Even more Highpoint RAID support.

Fix the 80pin cable detection system.
This commit is contained in:
Søren Schmidt 2002-03-08 21:36:49 +00:00
parent a7a8a766e7
commit fefe430118
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=91914
5 changed files with 126 additions and 120 deletions

View File

@ -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;
}

View File

@ -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 @@ ata_dmainit(struct ata_channel *ch, int device,
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 @@ ata_dmainit(struct ata_channel *ch, int device,
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 @@ ata_dmainit(struct ata_channel *ch, int device,
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;
}

View File

@ -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 */

View File

@ -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,59 +686,16 @@ 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;
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_O_RAID01SRC:
if ((raid->magic_0 && raid->magic_0 != info->magic_0) ||
(raid->magic_1 && raid->magic_1 != info->magic_1))
continue;
raid->magic_0 = info->magic_0;
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;
break;
case HPT_O_RAID01DST:
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;
}
break;
case HPT_T_RAID1:
@ -747,6 +706,30 @@ ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp)
disk_number = (info->disk_number > 0);
break;
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;
raid->magic_0 = info->magic_0;
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;
}
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;
if (!(info->order & HPT_O_RAID1))
info->magic = 0; /* mark bad */
}
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) {

View File

@ -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;