summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2003-01-27 09:04:29 +0000
committersos <sos@FreeBSD.org>2003-01-27 09:04:29 +0000
commit6d3ace00e49004eacf93fadfa698d9aeb55ef142 (patch)
tree1e4653f12f5af9dbbd1526e68ccc6a080fed8931
parente5f71e4b1ba2c5a960df3bbcdd88689ab8d59d51 (diff)
downloadFreeBSD-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.c183
-rw-r--r--sys/dev/ata/ata-all.h7
-rw-r--r--sys/dev/ata/ata-disk.c4
-rw-r--r--sys/dev/ata/ata-raid.c10
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++;
}
}
OpenPOWER on IntegriCloud