diff options
author | sos <sos@FreeBSD.org> | 2003-01-27 09:04:29 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2003-01-27 09:04:29 +0000 |
commit | 6d3ace00e49004eacf93fadfa698d9aeb55ef142 (patch) | |
tree | 1e4653f12f5af9dbbd1526e68ccc6a080fed8931 | |
parent | e5f71e4b1ba2c5a960df3bbcdd88689ab8d59d51 (diff) | |
download | FreeBSD-src-6d3ace00e49004eacf93fadfa698d9aeb55ef142.zip FreeBSD-src-6d3ace00e49004eacf93fadfa698d9aeb55ef142.tar.gz |
Update the code that deals with disk enclosures:
Properly handle the newer Promise SuperSwap 1000 enclosures.
Print out what kind of enclosure was found in the probe.
Misc cleanups in the enclosure handling code.
Sponsored by: Advanis Inc.
-rw-r--r-- | sys/dev/ata/ata-all.c | 183 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 7 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 4 | ||||
-rw-r--r-- | sys/dev/ata/ata-raid.c | 10 |
4 files changed, 135 insertions, 69 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 83515ab..e9c020c 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -81,7 +81,8 @@ static void bswap(int8_t *, int); static void btrim(int8_t *, int); static void bpack(int8_t *, int8_t *, int); static void ata_change_mode(struct ata_device *, int); -static u_int8_t ata_drawersensor(struct ata_device *, int, u_int8_t, u_int8_t); +static u_int8_t ata_enclosure_sensor(struct ata_device *, int, u_int8_t, u_int8_t); +static int ata_enclosure_status(struct ata_device *, int *, int *, int *, int *); /* sysctl vars */ SYSCTL_NODE(_hw, OID_AUTO, ata, CTLFLAG_RD, 0, "ATA driver parameters"); @@ -202,7 +203,7 @@ ata_attach(device_t dev) if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY)) ch->devices &= ~ATA_ATAPI_MASTER; #ifdef DEV_ATADISK - if (ch->devices & ATA_ATA_MASTER) + if (ch->devices & ATA_ATA_MASTER) ad_attach(&ch->device[MASTER]); if (ch->devices & ATA_ATA_SLAVE) ad_attach(&ch->device[SLAVE]); @@ -398,49 +399,20 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) case ATAENCSTAT: { struct ata_device *atadev; - u_int8_t id1, id2, cnt, div; - int fan, temp; if (!device || !(ch = device_get_softc(device))) return ENXIO; - ch->lock_func(ch, ATA_LF_LOCK); - ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE); - if (iocmd->device == SLAVE) atadev = &ch->device[SLAVE]; else atadev = &ch->device[MASTER]; - ata_drawersensor(atadev, 1, 0x4e, 0); - id1 = ata_drawersensor(atadev, 0, 0x4f, 0); - ata_drawersensor(atadev, 1, 0x4e, 0x80); - id2 = ata_drawersensor(atadev, 0, 0x4f, 0); - if (id1 != 0xa3 || id2 != 0x5c) { - ATA_UNLOCK_CH(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); - return ENXIO; - } - - div = 1 << (((ata_drawersensor(atadev, 0, 0x5d, 0)&0x20)>>3) + - ((ata_drawersensor(atadev, 0, 0x47, 0)&0x30)>>4) + 1); - cnt = ata_drawersensor(atadev, 0, 0x28, 0); - if (cnt == 0xff) - fan = 0; - else - fan = 1350000 / cnt / div; - ata_drawersensor(atadev, 1, 0x4e, 0x01); - temp = (ata_drawersensor(atadev, 0, 0x50, 0) * 10) + - (ata_drawersensor(atadev, 0, 0x50, 0) & 0x80 ? 5 : 0); - - iocmd->u.enclosure.fan = fan; - iocmd->u.enclosure.temp = temp; - iocmd->u.enclosure.v05 = ata_drawersensor(atadev, 0, 0x23, 0) * 27; - iocmd->u.enclosure.v12 = ata_drawersensor(atadev, 0, 0x24, 0) * 61; - - ATA_UNLOCK_CH(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); - return 0; + return ata_enclosure_status(atadev, + &iocmd->u.enclosure.fan, + &iocmd->u.enclosure.temp, + &iocmd->u.enclosure.v05, + &iocmd->u.enclosure.v12); } #ifdef DEV_ATADISK @@ -1161,10 +1133,14 @@ ata_command(struct ata_device *atadev, u_int8_t command, } static void -ata_drawer_start(struct ata_device *atadev) +ata_enclosure_start(struct ata_device *atadev) { ATA_INB(atadev->channel->r_io, ATA_DRIVE); DELAY(1); + ATA_INB(atadev->channel->r_io, ATA_DRIVE); + DELAY(1); + ATA_INB(atadev->channel->r_io, ATA_CMD); + DELAY(1); ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); DELAY(1); ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); @@ -1178,14 +1154,14 @@ ata_drawer_start(struct ata_device *atadev) } static void -ata_drawer_end(struct ata_device *atadev) +ata_enclosure_end(struct ata_device *atadev) { ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); DELAY(1); } static void -ata_chip_start(struct ata_device *atadev) +ata_enclosure_chip_start(struct ata_device *atadev) { ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0b); ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0a); @@ -1194,7 +1170,7 @@ ata_chip_start(struct ata_device *atadev) } static void -ata_chip_end(struct ata_device *atadev) +ata_enclosure_chip_end(struct ata_device *atadev) { ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08); DELAY(64); @@ -1205,7 +1181,7 @@ ata_chip_end(struct ata_device *atadev) } static u_int8_t -ata_chip_rdbit(struct ata_device *atadev) +ata_enclosure_chip_rdbit(struct ata_device *atadev) { u_int8_t val; @@ -1219,7 +1195,7 @@ ata_chip_rdbit(struct ata_device *atadev) } static void -ata_chip_wrbit(struct ata_device *atadev, u_int8_t data) +ata_enclosure_chip_wrbit(struct ata_device *atadev, u_int8_t data) { ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08 | (data & 0x01)); DELAY(64); @@ -1228,50 +1204,133 @@ ata_chip_wrbit(struct ata_device *atadev, u_int8_t data) } static u_int8_t -ata_chip_rw(struct ata_device *atadev, int rw, u_int8_t val) +ata_enclosure_chip_rw(struct ata_device *atadev, int rw, u_int8_t val) { int i; if (rw) { for (i = 0; i < 8; i++) - ata_chip_wrbit(atadev, (val & (0x80 >> i)) ? 1 : 0); + ata_enclosure_chip_wrbit(atadev, (val & (0x80 >> i)) ? 1 : 0); } else { for (i = 0; i < 8; i++) - val = (val << 1) | ata_chip_rdbit(atadev); + val = (val << 1) | ata_enclosure_chip_rdbit(atadev); } - ata_chip_wrbit(atadev, 0); + ata_enclosure_chip_wrbit(atadev, 0); return val; } static u_int8_t -ata_drawersensor(struct ata_device *atadev, int rw, u_int8_t idx, u_int8_t data) +ata_enclosure_sensor(struct ata_device *atadev, + int rw, u_int8_t idx, u_int8_t data) { - ata_drawer_start(atadev); - ata_chip_start(atadev); - ata_chip_rw(atadev, 1, 0x5a); - ata_chip_rw(atadev, 1, idx); + ata_enclosure_start(atadev); + ata_enclosure_chip_start(atadev); + ata_enclosure_chip_rw(atadev, 1, 0x5a); + ata_enclosure_chip_rw(atadev, 1, idx); if (rw) { - ata_chip_rw(atadev, 1, data); + ata_enclosure_chip_rw(atadev, 1, data); } else { - ata_chip_end(atadev); - ata_chip_start(atadev); - ata_chip_rw(atadev, 1, 0x5b); - data = ata_chip_rw(atadev, 0, 0); + ata_enclosure_chip_end(atadev); + ata_enclosure_chip_start(atadev); + ata_enclosure_chip_rw(atadev, 1, 0x5b); + data = ata_enclosure_chip_rw(atadev, 0, 0); } - ata_chip_end(atadev); - ata_drawer_end(atadev); + ata_enclosure_chip_end(atadev); + ata_enclosure_end(atadev); return data; } +static int +ata_enclosure_status(struct ata_device *atadev, + int *fan, int *temp, int *v05, int *v12) +{ + u_int8_t id1, id2, cnt, div; + + if (atadev->flags & ATA_D_ENC_PRESENT) { + atadev->channel->lock_func(atadev->channel, ATA_LF_LOCK); + ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); + ata_enclosure_sensor(atadev, 1, 0x4e, 0); + id1 = ata_enclosure_sensor(atadev, 0, 0x4f, 0); + ata_enclosure_sensor(atadev, 1, 0x4e, 0x80); + id2 = ata_enclosure_sensor(atadev, 0, 0x4f, 0); + if (id1 != 0xa3 || id2 != 0x5c) + return ENXIO; + div = 1 << (((ata_enclosure_sensor(atadev, 0, 0x5d, 0) & 0x20) >> 3)+ + ((ata_enclosure_sensor(atadev, 0, 0x47, 0) & 0x30) >> 4)+1); + cnt = ata_enclosure_sensor(atadev, 0, 0x28, 0); + if (cnt == 0xff) + *fan = 0; + else + *fan = 1350000 / cnt / div; + ata_enclosure_sensor(atadev, 1, 0x4e, 0x01); + *temp = (ata_enclosure_sensor(atadev, 0, 0x50, 0) * 10) + + (ata_enclosure_sensor(atadev, 0, 0x50, 0) & 0x80 ? 5 : 0); + *v05 = ata_enclosure_sensor(atadev, 0, 0x23, 0) * 27; + *v12 = ata_enclosure_sensor(atadev, 0, 0x24, 0) * 61; + ATA_UNLOCK_CH(atadev->channel); + atadev->channel->lock_func(atadev->channel, ATA_LF_UNLOCK); + return 0; + } + return ENXIO; +} + void -ata_drawerleds(struct ata_device *atadev, u_int8_t color) +ata_enclosure_print(struct ata_device *atadev) { - ata_drawer_start(atadev); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, color); + u_int8_t id, st; + int fan, temp, v05, v12; + + atadev->channel->lock_func(atadev->channel, ATA_LF_LOCK); + ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); + ata_enclosure_start(atadev); + id = ATA_INB(atadev->channel->r_io, ATA_DRIVE); + DELAY(1); + st = ATA_INB(atadev->channel->r_io, ATA_COUNT); DELAY(1); - ata_drawer_end(atadev); + ata_enclosure_end(atadev); + ATA_UNLOCK_CH(atadev->channel); + atadev->channel->lock_func(atadev->channel, ATA_LF_UNLOCK); + + switch (id & 0x93) { + case 0x00: + ata_prtdev(atadev, "Universal enclosure"); + break; + case 0x01: + ata_prtdev(atadev, "FastSwap enclosure"); + break; + case 0x10: + case 0x11: + ata_prtdev(atadev, "SuperSwap enclosure"); + break; + default: + atadev->flags &= ~ATA_D_ENC_PRESENT; + return; + } + atadev->flags |= ATA_D_ENC_PRESENT; + + if (ata_enclosure_status(atadev, &fan, &temp, &v05, &v12)) + printf(" detected\n"); + else + printf(" [FAN:%drpm TEMP:%d.%01dC %d.%03dV %d.%03dV]\n", + fan, temp/10, temp%10, v05/1000, v05%1000, v12/1000, v12%1000); +} + +void +ata_enclosure_leds(struct ata_device *atadev, u_int8_t color) +{ + if (atadev->flags & ATA_D_ENC_PRESENT) { + u_int8_t reg; + + ata_enclosure_start(atadev); + reg = ATA_INB(atadev->channel->r_io, ATA_COUNT); + DELAY(1); + ATA_OUTB(atadev->channel->r_io, ATA_COUNT, + (color & ATA_LED_MASK) | (reg & ~ATA_LED_MASK)); + DELAY(1); + ata_enclosure_end(atadev); + } } static void diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 30352f0..323a99d 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -190,6 +190,7 @@ struct ata_device { #define ATA_D_USE_CHS 0x0001 #define ATA_D_DETACHING 0x0002 #define ATA_D_MEDIA_CHANGED 0x0004 +#define ATA_D_ENC_PRESENT 0x0008 int mode; /* transfermode */ int cmd; /* last cmd executed */ @@ -251,11 +252,12 @@ struct ata_channel { void *running; /* currently running request */ }; -/* disk bay/drawer related */ +/* disk bay/enclosure related */ #define ATA_LED_OFF 0x00 #define ATA_LED_RED 0x01 #define ATA_LED_GREEN 0x02 #define ATA_LED_ORANGE 0x03 +#define ATA_LED_MASK 0x03 /* externs */ extern devclass_t ata_devclass; @@ -271,7 +273,8 @@ void ata_reset(struct ata_channel *); int ata_reinit(struct ata_channel *); int ata_wait(struct ata_device *, u_int8_t); int ata_command(struct ata_device *, u_int8_t, u_int64_t, u_int16_t, u_int16_t, int); -void ata_drawerleds(struct ata_device *, u_int8_t); +void ata_enclosure_leds(struct ata_device *, u_int8_t); +void ata_enclosure_print(struct ata_device *); int ata_printf(struct ata_channel *, int, const char *, ...) __printflike(3, 4); int ata_prtdev(struct ata_device *, const char *, ...) __printflike(2, 3); void ata_set_name(struct ata_device *, char *, int); diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index b4fdbe8..af172f0 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -225,8 +225,10 @@ ad_attach(struct ata_device *atadev) if (ata_raiddisk_attach(adp)) adp->flags |= AD_F_RAID_SUBDISK; else { - if (atadev->driver) + if (atadev->driver) { ad_print(adp); + ata_enclosure_print(atadev); + } } } diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index 2c3fb19..62f5a9d 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -228,6 +228,8 @@ ar_attach_raid(struct ar_softc *rdp, int update) else printf(" %d FREE ", disk); ad_print(AD_SOFTC(rdp->disks[disk])); + printf(" "); + ata_enclosure_print(AD_SOFTC(rdp->disks[disk])->device); } else if (rdp->disks[disk].flags & AR_DF_ASSIGNED) printf(" %d DOWN\n", disk); @@ -396,7 +398,7 @@ ata_raid_delete(int array) for (disk = 0; disk < rdp->total_disks; disk++) { if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) { AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK; - ata_drawerleds(rdp->disks[disk].device, ATA_LED_GREEN); + ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN); rdp->disks[disk].flags = 0; } } @@ -768,9 +770,9 @@ ar_config_changed(struct ar_softc *rdp, int writeback) } if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) { if (rdp->disks[disk].flags & AR_DF_ONLINE) - ata_drawerleds(rdp->disks[disk].device, ATA_LED_GREEN); + ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN); else - ata_drawerleds(rdp->disks[disk].device, ATA_LED_RED); + ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_RED); } } if (writeback) { @@ -804,7 +806,7 @@ ar_rebuild(void *arg) #endif continue; } - ata_drawerleds(rdp->disks[disk].device, ATA_LED_ORANGE); + ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_ORANGE); count++; } } |