summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2002-03-08 21:36:49 +0000
committersos <sos@FreeBSD.org>2002-03-08 21:36:49 +0000
commit259c8e6d5373d0e965569eecf645d36a8a89a100 (patch)
tree88a891cc6ed6a3dc54bae1b471a1ce056ab629ae /sys/dev/ata
parente81a222988987c911063a4420ec7ec6521da4836 (diff)
downloadFreeBSD-src-259c8e6d5373d0e965569eecf645d36a8a89a100.zip
FreeBSD-src-259c8e6d5373d0e965569eecf645d36a8a89a100.tar.gz
Even more Highpoint RAID support.
Fix the 80pin cable detection system.
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/ata-all.c2
-rw-r--r--sys/dev/ata/ata-dma.c93
-rw-r--r--sys/dev/ata/ata-pci.c15
-rw-r--r--sys/dev/ata/ata-raid.c105
-rw-r--r--sys/dev/ata/ata-raid.h13
5 files changed, 117 insertions, 111 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index cfe02f0..de10f7a 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -572,7 +572,7 @@ ata_intr(void *data)
case ATA_IDLE:
if (ch->flags & ATA_QUEUED) {
- ch->active = ATA_ACTIVE; /* XXX */
+ ch->active = ATA_ACTIVE;
if (ata_service(ch) == ATA_OP_CONTINUES)
return;
}
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index fbcbf70..f003049 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -47,6 +47,7 @@
static void cyrix_timing(struct ata_channel *, int, int);
static void promise_timing(struct ata_channel *, int, int);
static void hpt_timing(struct ata_channel *, int, int);
+static int hpt_cable80(struct ata_channel *);
/* misc defines */
#ifdef __alpha__
@@ -928,11 +929,10 @@ via_82c586:
case 0x00041103: /* HighPoint HPT366/368/370/372 controllers */
case 0x00051103: /* HighPoint HPT372 controllers */
case 0x00081103: /* HighPoint HPT374 controllers */
- if (!ATAPI_DEVICE(ch, device) && udmamode >= 6 &&
+ if (!ATAPI_DEVICE(ch, device) && udmamode >= 6 && hpt_cable80(ch) &&
((ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x05) ||
(ch->chiptype == 0x00051103 && pci_get_revid(parent) >= 0x01) ||
- (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07)) &&
- !(pci_read_config(parent, 0x5a, 1) & (ch->unit ? 0x01:0x02))) {
+ (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07))) {
error = ata_command(atadev, ATA_C_SETFEATURES, 0,
ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
@@ -944,11 +944,10 @@ via_82c586:
return;
}
}
- if (!ATAPI_DEVICE(ch, device) && udmamode >= 5 &&
+ if (!ATAPI_DEVICE(ch, device) && udmamode >= 5 && hpt_cable80(ch) &&
((ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x05) ||
(ch->chiptype == 0x00051103 && pci_get_revid(parent) >= 0x01) ||
- (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07)) &&
- !(pci_read_config(parent, 0x5a, 1) & (ch->unit ? 0x01:0x02))) {
+ (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07))) {
error = ata_command(atadev, ATA_C_SETFEATURES, 0,
ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
@@ -960,8 +959,7 @@ via_82c586:
return;
}
}
- if (!ATAPI_DEVICE(ch, device) && udmamode >= 4 &&
- !(pci_read_config(parent, 0x5a, 1) & (ch->unit ? 0x01:0x02))) {
+ if (!ATAPI_DEVICE(ch, device) && udmamode >= 4 && hpt_cable80(ch)) {
error = ata_command(atadev, ATA_C_SETFEATURES, 0,
ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
@@ -1217,6 +1215,7 @@ hpt_timing(struct ata_channel *ch, int devno, int mode)
{
device_t parent = device_get_parent(ch->dev);
u_int32_t timing;
+
if (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07) {
switch (mode) { /* HPT374 */
case ATA_PIO0: timing = 0x0ac1f48a; break;
@@ -1231,9 +1230,6 @@ hpt_timing(struct ata_channel *ch, int devno, int mode)
case ATA_UDMA6: timing = 0x12808242; break;
default: timing = 0x0d029d5e;
}
- pci_write_config(parent, 0x40 + (devno << 2) , timing, 4);
- pci_write_config(parent, 0x5b,
- (pci_read_config(parent, 0x5b, 1) & 0x01) | 0x20, 1);
}
else if ((ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x05) ||
(ch->chiptype == 0x00051103 && pci_get_revid(parent) >= 0x01)) {
@@ -1250,9 +1246,6 @@ hpt_timing(struct ata_channel *ch, int devno, int mode)
case ATA_UDMA6: timing = 0x1c81dc62; break;
default: timing = 0x0d029d5e;
}
- pci_write_config(parent, 0x40 + (devno << 2) , timing, 4);
- pci_write_config(parent, 0x5b,
- (pci_read_config(parent, 0x5b, 1) & 0x01) | 0x20, 1);
}
else if (ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x03) {
switch (mode) { /* HPT370 */
@@ -1268,50 +1261,70 @@ hpt_timing(struct ata_channel *ch, int devno, int mode)
default: timing = 0x06514e57;
}
pci_write_config(parent, 0x40 + (devno << 2) , timing, 4);
- pci_write_config(parent, 0x5b, 0x22, 1);
}
else { /* HPT36[68] */
switch (pci_read_config(parent, 0x41 + (devno << 2), 1)) {
case 0x85: /* 25Mhz */
switch (mode) {
- case ATA_PIO0: timing = 0xc0d08585; break;
- case ATA_PIO1: timing = 0xc0d08572; break;
- case ATA_PIO2: timing = 0xc0ca8542; break;
- case ATA_PIO3: timing = 0xc0ca8532; break;
- case ATA_PIO4: timing = 0xc0ca8521; break;
- case ATA_WDMA2: timing = 0xa0ca8521; break;
- case ATA_UDMA2: timing = 0x90cf8521; break;
- case ATA_UDMA4: timing = 0x90c98521; break;
+ case ATA_PIO0: timing = 0x40d08585; break;
+ case ATA_PIO1: timing = 0x40d08572; break;
+ case ATA_PIO2: timing = 0x40ca8542; break;
+ case ATA_PIO3: timing = 0x40ca8532; break;
+ case ATA_PIO4: timing = 0x40ca8521; break;
+ case ATA_WDMA2: timing = 0x20ca8521; break;
+ case ATA_UDMA2: timing = 0x10cf8521; break;
+ case ATA_UDMA4: timing = 0x10c98521; break;
default: timing = 0x01208585;
}
break;
default:
case 0xa7: /* 33MHz */
switch (mode) {
- case ATA_PIO0: timing = 0xc0d0a7aa; break;
- case ATA_PIO1: timing = 0xc0d0a7a3; break;
- case ATA_PIO2: timing = 0xc0d0a753; break;
- case ATA_PIO3: timing = 0xc0c8a742; break;
- case ATA_PIO4: timing = 0xc0c8a731; break;
- case ATA_WDMA2: timing = 0xa0c8a731; break;
- case ATA_UDMA2: timing = 0x90caa731; break;
- case ATA_UDMA4: timing = 0x90c9a731; break;
+ case ATA_PIO0: timing = 0x40d0a7aa; break;
+ case ATA_PIO1: timing = 0x40d0a7a3; break;
+ case ATA_PIO2: timing = 0x40d0a753; break;
+ case ATA_PIO3: timing = 0x40c8a742; break;
+ case ATA_PIO4: timing = 0x40c8a731; break;
+ case ATA_WDMA2: timing = 0x20c8a731; break;
+ case ATA_UDMA2: timing = 0x10caa731; break;
+ case ATA_UDMA4: timing = 0x10c9a731; break;
default: timing = 0x0120a7a7;
}
break;
case 0xd9: /* 40Mhz */
switch (mode) {
- case ATA_PIO0: timing = 0xc018d9d9; break;
- case ATA_PIO1: timing = 0xc010d9c7; break;
- case ATA_PIO2: timing = 0xc010d997; break;
- case ATA_PIO3: timing = 0xc010d974; break;
- case ATA_PIO4: timing = 0xc008d963; break;
- case ATA_WDMA2: timing = 0xa008d943; break;
- case ATA_UDMA2: timing = 0x900bd943; break;
- case ATA_UDMA4: timing = 0x900fd943; break;
+ case ATA_PIO0: timing = 0x4018d9d9; break;
+ case ATA_PIO1: timing = 0x4010d9c7; break;
+ case ATA_PIO2: timing = 0x4010d997; break;
+ case ATA_PIO3: timing = 0x4010d974; break;
+ case ATA_PIO4: timing = 0x4008d963; break;
+ case ATA_WDMA2: timing = 0x2008d943; break;
+ case ATA_UDMA2: timing = 0x100bd943; break;
+ case ATA_UDMA4: timing = 0x100fd943; break;
default: timing = 0x0120d9d9;
}
}
- pci_write_config(parent, 0x40 + (devno << 2), (timing & ~0x80000000),4);
}
+ pci_write_config(parent, 0x40 + (devno << 2) , timing, 4);
+}
+
+static int
+hpt_cable80(struct ata_channel *ch)
+{
+ device_t parent = device_get_parent(ch->dev);
+ u_int8_t reg, val, res;
+
+ if (ch->chiptype == 0x00081103 && pci_get_function(parent) == 1) {
+ reg = ch->unit ? 0x57 : 0x53;
+ val = pci_read_config(parent, reg, 1);
+ pci_write_config(parent, reg, val | 0x80, 1);
+ }
+ else {
+ reg = 0x5b;
+ val = pci_read_config(parent, reg, 1);
+ pci_write_config(parent, reg, val & 0xfe, 1);
+ }
+ res = pci_read_config(parent, 0x5a, 1) & (ch->unit ? 0x01 : 0x02);
+ pci_write_config(parent, reg, val, 1);
+ return !res;
}
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 60bd1c9..f39fc88 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -399,7 +399,16 @@ ata_pci_attach(device_t dev)
(pci_read_config(dev, 0x51, 1) & ~0x80), 1);
break;
}
- /* FALLTHROUGH */
+ /* turn off interrupt prediction */
+ pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1);
+ pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1);
+
+ /* turn on interrupts */
+ pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1);
+
+ /* set clocks etc */
+ pci_write_config(dev, 0x5b, 0x22, 1);
+ break;
case 0x00051103: /* HighPoint HPT372 */
case 0x00081103: /* HighPoint HPT374 */
@@ -409,6 +418,10 @@ ata_pci_attach(device_t dev)
/* turn on interrupts */
pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1);
+
+ /* set clocks etc */
+ pci_write_config(dev, 0x5b,
+ (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1);
break;
case 0x05711106: /* VIA 82C586, '596, '686 default setup */
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index 0f61f4f..a850c08 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -272,6 +272,7 @@ arstrategy(struct bio *bp)
biodone(bp);
return;
}
+
bp->bio_resid = bp->bio_bcount;
blkno = bp->bio_pblkno;
data = bp->bio_data;
@@ -622,6 +623,7 @@ ar_rebuild(struct ar_softc *rdp)
rdp->lock_end = rdp->lock_start + size;
wakeup(rdp);
}
+ rdp->lock_start = 0xffffffff;
free(buffer, M_AR);
for (disk = 0; disk < rdp->total_disks; disk++) {
if ((rdp->disks[disk].flags&(AR_DF_PRESENT|AR_DF_ONLINE|AR_DF_SPARE))==
@@ -684,31 +686,29 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
switch (info->type) {
case HPT_T_RAID0:
- case HPT_T_RAID01_RAID0:
- /* check the order byte to determine what this really is */
- switch (info->order) {
- case HPT_O_DOWN:
- if (raid->magic_0 && raid->magic_0 != info->magic_0)
- continue;
- raid->magic_0 = info->magic_0;
- raid->magic_1 = info->magic_1;
- raid->flags |= AR_F_RAID0;
- raid->interleave = 1 << info->stripe_shift;
- disk_number = info->disk_number;
+ if (info->order & (HPT_O_OK | HPT_O_RAID1))
+ goto highpoint_raid01;
+ if (raid->magic_0 && raid->magic_0 != info->magic_0)
+ continue;
+ raid->magic_0 = info->magic_0;
+ raid->flags |= AR_F_RAID0;
+ raid->interleave = 1 << info->stripe_shift;
+ disk_number = info->disk_number;
+ if (!(info->order & HPT_O_RAID0))
info->magic = 0; /* mark bad */
- break;
+ break;
- case HPT_O_RAID01DEGRADED:
- if (raid->magic_0 && raid->magic_0 != info->magic_0)
- continue;
- raid->magic_0 = info->magic_0;
- raid->magic_1 = info->magic_1;
- raid->flags |= AR_F_RAID0;
- raid->interleave = 1 << info->stripe_shift;
- disk_number = info->disk_number;
- break;
+ case HPT_T_RAID1:
+ if (raid->magic_0 && raid->magic_0 != info->magic_0)
+ continue;
+ raid->magic_0 = info->magic_0;
+ raid->flags |= AR_F_RAID1;
+ disk_number = (info->disk_number > 0);
+ break;
- case HPT_O_RAID01SRC:
+ case HPT_T_RAID01_RAID0:
+highpoint_raid01:
+ if (info->order & HPT_O_OK) {
if ((raid->magic_0 && raid->magic_0 != info->magic_0) ||
(raid->magic_1 && raid->magic_1 != info->magic_1))
continue;
@@ -717,36 +717,19 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
raid->flags |= (AR_F_RAID0 | AR_F_RAID1);
raid->interleave = 1 << info->stripe_shift;
disk_number = info->disk_number;
- break;
-
- case HPT_O_RAID01DST:
+ }
+ else {
if (raid->magic_1 && raid->magic_1 != info->magic_1)
continue;
raid->magic_1 = info->magic_1;
raid->flags |= (AR_F_RAID0 | AR_F_RAID1);
raid->interleave = 1 << info->stripe_shift;
disk_number = info->disk_number + info->array_width;
- break;
-
- case HPT_O_READY:
- if (raid->magic_0 && raid->magic_0 != info->magic_0)
- continue;
- raid->magic_0 = info->magic_0;
- raid->flags |= AR_F_RAID0;
- raid->interleave = 1 << info->stripe_shift;
- disk_number = info->disk_number;
- break;
+ if (!(info->order & HPT_O_RAID1))
+ info->magic = 0; /* mark bad */
}
break;
- case HPT_T_RAID1:
- if (raid->magic_0 && raid->magic_0 != info->magic_0)
- continue;
- raid->magic_0 = info->magic_0;
- raid->flags |= AR_F_RAID1;
- disk_number = (info->disk_number > 0);
- break;
-
case HPT_T_SPAN:
if (raid->magic_0 && raid->magic_0 != info->magic_0)
continue;
@@ -764,10 +747,10 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
raid->flags |= AR_F_HIGHPOINT_RAID;
raid->disks[disk_number].device = adp->device;
raid->disks[disk_number].flags = (AR_DF_PRESENT | AR_DF_ASSIGNED);
+ raid->lun = array;
if (info->magic == HPT_MAGIC_OK) {
raid->disks[disk_number].flags |= AR_DF_ONLINE;
raid->flags |= AR_F_READY;
- raid->lun = array;
raid->width = info->array_width;
raid->heads = 255;
raid->sectors = 63;
@@ -775,6 +758,7 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
raid->total_sectors = info->total_sectors;
raid->offset = HPT_LBA + 1;
raid->reserved = HPT_LBA + 1;
+ raid->lock_start = raid->lock_end = info->rebuild_lba;
raid->disks[disk_number].disk_sectors =
info->total_sectors / info->array_width;
}
@@ -801,7 +785,7 @@ ar_highpoint_write_conf(struct ar_softc *rdp)
int disk;
microtime(&timestamp);
- rdp->magic_0 = timestamp.tv_sec + 1;
+ rdp->magic_0 = timestamp.tv_sec + 2;
rdp->magic_1 = timestamp.tv_sec;
for (disk = 0; disk < rdp->total_disks; disk++) {
@@ -816,43 +800,40 @@ ar_highpoint_write_conf(struct ar_softc *rdp)
config->magic = HPT_MAGIC_OK;
if (rdp->disks[disk].flags & AR_DF_ASSIGNED) {
config->magic_0 = rdp->magic_0;
- config->magic_2 = HPT_MAGIC_2;
- strcpy(config->name_1, "FreeBSD ATARAID");
+ strcpy(config->name_1, "FreeBSD");
}
config->disk_number = disk;
switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) {
case AR_F_RAID0:
config->type = HPT_T_RAID0;
+ strcpy(config->name_2, "RAID 0");
if (rdp->disks[disk].flags & AR_DF_ONLINE)
- config->order = HPT_O_READY;
- else
- config->order = HPT_O_DOWN;
- strcpy(config->name_2, "RAID 0");
+ config->order = HPT_O_RAID0;
break;
case AR_F_RAID1:
config->type = HPT_T_RAID1;
- config->disk_number = (disk < rdp->width) ? disk : disk + 10;
strcpy(config->name_2, "RAID 1");
+ config->disk_number = (disk < rdp->width) ? disk : disk + 10;
break;
case AR_F_RAID0 | AR_F_RAID1:
- config->magic_1 = rdp->magic_1;
config->type = HPT_T_RAID01_RAID0;
- if (rdp->disks[disk].flags & AR_DF_ONLINE)
+ strcpy(config->name_2, "RAID 0+1");
+ if (rdp->disks[disk].flags & AR_DF_ONLINE) {
if (disk < rdp->width) {
- config->order = HPT_O_RAID01SRC;
+ config->order = (HPT_O_OK | HPT_O_RAID1);
config->magic_0 = rdp->magic_0 - 1;
- strcpy(config->name_2, "RAID 0+1 SRC");
}
else {
- config->order = HPT_O_RAID01DST;
+ config->order = HPT_O_RAID1;
config->disk_number -= rdp->width;
- strcpy(config->name_2, "RAID 0+1 DST");
}
- else
- config->order = HPT_O_DOWN;
+ }
+ else
+ config->magic_0 = rdp->magic_0 - 1;
+ config->magic_1 = rdp->magic_1;
break;
case AR_F_SPAN:
@@ -864,6 +845,7 @@ ar_highpoint_write_conf(struct ar_softc *rdp)
config->array_width = rdp->width;
config->stripe_shift = (rdp->width > 1) ? (ffs(rdp->interleave)-1) : 0;
config->total_sectors = rdp->total_sectors;
+ config->rebuild_lba = rdp->lock_start;
if ((rdp->disks[disk].flags & AR_DF_PRESENT) &&
rdp->disks[disk].device && rdp->disks[disk].device->driver &&
@@ -986,6 +968,7 @@ ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
raid->total_sectors = info->raid.total_sectors;
raid->offset = 0;
raid->reserved = 63;
+ raid->lock_start = raid->lock_end = info->raid.rebuild_lba;
/* convert disk flags to our internal types */
for (disk = 0; disk < info->raid.total_disks; disk++) {
@@ -1062,7 +1045,7 @@ ar_promise_write_conf(struct ar_softc *rdp)
/*config->raid.disk_offset*/
}
config->raid.magic_0 = config->magic_0;
- config->raid.rebuild_lba = 0xffffffff;
+ config->raid.rebuild_lba = rdp->lock_start;
config->raid.generation = rdp->generation;
if (rdp->flags & AR_F_READY) {
diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h
index 03a7e16..8de947e 100644
--- a/sys/dev/ata/ata-raid.h
+++ b/sys/dev/ata/ata-raid.h
@@ -82,7 +82,7 @@ struct ar_softc {
struct ar_buf {
struct bio bp; /* must be first element! */
- struct bio *org;
+ struct bio *org;
struct ar_buf *mirror;
int drive;
int flags;
@@ -100,11 +100,9 @@ struct highpoint_raid_conf {
u_int32_t magic_0;
u_int32_t magic_1;
u_int32_t order;
-#define HPT_O_DOWN 0x00
-#define HPT_O_RAID01DEGRADED 0x01
-#define HPT_O_RAID01DST 0x02
-#define HPT_O_RAID01SRC 0x03
-#define HPT_O_READY 0x04
+#define HPT_O_OK 0x01
+#define HPT_O_RAID1 0x02
+#define HPT_O_RAID0 0x04
u_int8_t array_width;
u_int8_t stripe_shift;
@@ -138,8 +136,7 @@ struct highpoint_raid_conf {
u_int32_t lba;
} errorlog[32];
int8_t filler2[16];
- u_int32_t magic_2;
-#define HPT_MAGIC_2 0x7fffffff
+ u_int32_t rebuild_lba;
u_int8_t dummy_1;
u_int8_t name_1[15];
u_int8_t dummy_2;
OpenPOWER on IntegriCloud