Update the ICH7 support so it deals better with chips without AHCI.
Update Intel MatrixRAID support to be able to pick up RAID0+1 (RAID10) and RAID5 arrays without panic'ing. This has the side effect of now also supporting multiple volumes on MatrixRAID's now I have the metadata better understood.. HW sponsored by: Mullet Scandinavia AB
This commit is contained in:
parent
4ea655e4bb
commit
ddaf769709
@ -211,7 +211,6 @@ ata_generic_setmode(device_t dev, int mode)
|
||||
static void
|
||||
ata_sata_setmode(device_t dev, int mode)
|
||||
{
|
||||
struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev));
|
||||
struct ata_device *atadev = device_get_softc(dev);
|
||||
|
||||
/*
|
||||
@ -224,7 +223,8 @@ ata_sata_setmode(device_t dev, int mode)
|
||||
atadev->param.satacapabilities != 0xffff) {
|
||||
if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
|
||||
ata_limit_mode(dev, mode, ATA_UDMA6)))
|
||||
atadev->mode = ctlr->chip->max_dma;
|
||||
/* XXX SOS we should query SATA STATUS for the speed */
|
||||
atadev->mode = ATA_SA150;
|
||||
}
|
||||
else {
|
||||
mode = ata_limit_mode(dev, mode, ATA_UDMA5);
|
||||
@ -1545,36 +1545,36 @@ ata_intel_ident(device_t dev)
|
||||
struct ata_pci_controller *ctlr = device_get_softc(dev);
|
||||
struct ata_chip_id *idx;
|
||||
static struct ata_chip_id ids[] =
|
||||
{{ ATA_I82371FB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX" },
|
||||
{ ATA_I82371SB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX3" },
|
||||
{ ATA_I82371AB, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
|
||||
{ ATA_I82443MX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
|
||||
{ ATA_I82451NX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
|
||||
{ ATA_I82801AB, 0, 0, 0x00, ATA_UDMA2, "Intel ICH0" },
|
||||
{ ATA_I82801AA, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" },
|
||||
{ ATA_I82372FB, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" },
|
||||
{ ATA_I82801BA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" },
|
||||
{ ATA_I82801BA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" },
|
||||
{ ATA_I82801CA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" },
|
||||
{ ATA_I82801CA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" },
|
||||
{ ATA_I82801DB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH4" },
|
||||
{ ATA_I82801DB_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH4" },
|
||||
{ ATA_I82801EB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH5" },
|
||||
{ ATA_I82801EB_S1, 0, 0, 0x00, ATA_SA150, "Intel ICH5" },
|
||||
{ ATA_I82801EB_R1, 0, 0, 0x00, ATA_SA150, "Intel ICH5" },
|
||||
{ ATA_I6300ESB, 0, 0, 0x00, ATA_UDMA5, "Intel 6300ESB" },
|
||||
{ ATA_I6300ESB_S1, 0, 0, 0x00, ATA_SA150, "Intel 6300ESB" },
|
||||
{ ATA_I6300ESB_R1, 0, 0, 0x00, ATA_SA150, "Intel 6300ESB" },
|
||||
{ ATA_I82801FB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH6" },
|
||||
{ ATA_I82801FB_S1, 0, 0, 0x00, ATA_SA150, "Intel ICH6" },
|
||||
{ ATA_I82801FB_R1, 0, 0, 0x00, ATA_SA150, "Intel ICH6" },
|
||||
{ ATA_I82801FB_M, 0, 0, 0x00, ATA_SA150, "Intel ICH6" },
|
||||
{ ATA_I82801GB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH7" },
|
||||
{ ATA_I82801GB_S1, 0, 0, 0x00, ATA_SA150, "Intel ICH7" },
|
||||
{ ATA_I82801GB_R1, 0, 0, 0x00, ATA_SA150, "Intel ICH7" },
|
||||
{ ATA_I82801GB_M, 0, 0, 0x00, ATA_SA150, "Intel ICH7" },
|
||||
{ ATA_I82801GB_AH, 0, 0, 0x00, ATA_SA150, "Intel ICH7" },
|
||||
{ ATA_I31244, 0, 0, 0x00, ATA_SA150, "Intel 31244" },
|
||||
{{ ATA_I82371FB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX" },
|
||||
{ ATA_I82371SB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX3" },
|
||||
{ ATA_I82371AB, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
|
||||
{ ATA_I82443MX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
|
||||
{ ATA_I82451NX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
|
||||
{ ATA_I82801AB, 0, 0, 0x00, ATA_UDMA2, "Intel ICH0" },
|
||||
{ ATA_I82801AA, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" },
|
||||
{ ATA_I82372FB, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" },
|
||||
{ ATA_I82801BA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" },
|
||||
{ ATA_I82801BA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" },
|
||||
{ ATA_I82801CA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" },
|
||||
{ ATA_I82801CA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" },
|
||||
{ ATA_I82801DB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH4" },
|
||||
{ ATA_I82801DB_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH4" },
|
||||
{ ATA_I82801EB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH5" },
|
||||
{ ATA_I82801EB_S1, 0, 0, 0x00, ATA_SA150, "Intel ICH5" },
|
||||
{ ATA_I82801EB_R1, 0, 0, 0x00, ATA_SA150, "Intel ICH5" },
|
||||
{ ATA_I6300ESB, 0, 0, 0x00, ATA_UDMA5, "Intel 6300ESB" },
|
||||
{ ATA_I6300ESB_S1, 0, 0, 0x00, ATA_SA150, "Intel 6300ESB" },
|
||||
{ ATA_I6300ESB_R1, 0, 0, 0x00, ATA_SA150, "Intel 6300ESB" },
|
||||
{ ATA_I82801FB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH6" },
|
||||
{ ATA_I82801FB_S1, 0, AHCI, 0x00, ATA_SA150, "Intel ICH6" },
|
||||
{ ATA_I82801FB_R1, 0, AHCI, 0x00, ATA_SA150, "Intel ICH6" },
|
||||
{ ATA_I82801FB_M, 0, AHCI, 0x00, ATA_SA150, "Intel ICH6" },
|
||||
{ ATA_I82801GB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH7" },
|
||||
{ ATA_I82801GB_S1, 0, AHCI, 0x00, ATA_SA300, "Intel ICH7" },
|
||||
{ ATA_I82801GB_R1, 0, AHCI, 0x00, ATA_SA300, "Intel ICH7" },
|
||||
{ ATA_I82801GB_M, 0, AHCI, 0x00, ATA_SA300, "Intel ICH7" },
|
||||
{ ATA_I82801GB_AH, 0, AHCI, 0x00, ATA_SA300, "Intel ICH7" },
|
||||
{ ATA_I31244, 0, 0, 0x00, ATA_SA150, "Intel 31244" },
|
||||
{ 0, 0, 0, 0, 0, 0}};
|
||||
char buffer[64];
|
||||
|
||||
@ -1642,40 +1642,54 @@ ata_intel_chipinit(device_t dev)
|
||||
|
||||
/* SATA parts can be either compat or AHCI */
|
||||
else {
|
||||
/* if we have BAR(5) as a memory resource we should use AHCI mode */
|
||||
ctlr->r_type2 = SYS_RES_MEMORY;
|
||||
ctlr->r_rid2 = PCIR_BAR(5);
|
||||
if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
|
||||
&ctlr->r_rid2, RF_ACTIVE))) {
|
||||
if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) ||
|
||||
bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
|
||||
ata_ahci_intr, ctlr, &ctlr->handle)) {
|
||||
device_printf(dev, "unable to setup interrupt\n");
|
||||
return ENXIO;
|
||||
/* force all ports active "the legacy way" */
|
||||
pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f,2);
|
||||
|
||||
ctlr->reset = ata_intel_reset;
|
||||
|
||||
/* if we have AHCI capability and BAR(5) as a memory resource */
|
||||
if (ctlr->chip->cfg1 == AHCI) {
|
||||
ctlr->r_type2 = SYS_RES_MEMORY;
|
||||
ctlr->r_rid2 = PCIR_BAR(5);
|
||||
if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
|
||||
&ctlr->r_rid2,
|
||||
RF_ACTIVE))) {
|
||||
/* is AHCI or RAID mode enabled in BIOS ? */
|
||||
if (pci_read_config(dev, 0x90, 1) & 0xc0) {
|
||||
if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) ||
|
||||
bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
|
||||
ata_ahci_intr, ctlr, &ctlr->handle)) {
|
||||
device_printf(dev, "unable to setup interrupt\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
/* enable AHCI mode */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
|
||||
|
||||
/* get the number of HW channels */
|
||||
ctlr->channels = (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) &
|
||||
ATA_AHCI_NPMASK) + 1;
|
||||
|
||||
/* enable AHCI interrupts */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
|
||||
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) |
|
||||
ATA_AHCI_GHC_IE);
|
||||
ctlr->reset = ata_ahci_reset;
|
||||
ctlr->dmainit = ata_ahci_dmainit;
|
||||
ctlr->allocate = ata_ahci_allocate;
|
||||
}
|
||||
#if 0
|
||||
else {
|
||||
/* enable SATA registers in compat mode */
|
||||
pci_write_config(dev, 0x94,
|
||||
pci_read_config(dev, 0x94, 4) | 1 << 9, 4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* force all ports active "the legacy way" */
|
||||
pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f,2);
|
||||
|
||||
/* enable AHCI mode */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_AE);
|
||||
|
||||
/* get the number of HW channels */
|
||||
ctlr->channels = (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) &
|
||||
ATA_AHCI_NPMASK) + 1;
|
||||
|
||||
/* enable AHCI interrupts */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
|
||||
ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE);
|
||||
|
||||
ctlr->reset = ata_ahci_reset;
|
||||
ctlr->dmainit = ata_ahci_dmainit;
|
||||
ctlr->allocate = ata_ahci_allocate;
|
||||
}
|
||||
else {
|
||||
ctlr->reset = ata_intel_reset;
|
||||
}
|
||||
ctlr->setmode = ata_sata_setmode;
|
||||
|
||||
/* enable PCI interrupt */
|
||||
pci_write_config(dev, PCIR_COMMAND,
|
||||
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
|
||||
}
|
||||
@ -1845,10 +1859,8 @@ ata_intel_reset(device_t dev)
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
int mask, timeout;
|
||||
|
||||
/* ICH6 has 4 SATA ports as master/slave on 2 channels so deal with pairs */
|
||||
if (ctlr->chip->chipid == ATA_I82801FB_S1 ||
|
||||
ctlr->chip->chipid == ATA_I82801FB_R1 ||
|
||||
ctlr->chip->chipid == ATA_I82801FB_M) {
|
||||
/* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
|
||||
if (ctlr->chip->cfg1) {
|
||||
mask = (0x0005 << ch->unit);
|
||||
}
|
||||
else {
|
||||
@ -1857,7 +1869,7 @@ ata_intel_reset(device_t dev)
|
||||
mask = 0x0003;
|
||||
else {
|
||||
mask = (0x0001 << ch->unit);
|
||||
/* XXX SOS should be in intel_allocate when we grow it */
|
||||
/* XXX SOS should be in intel_allocate if we grow it */
|
||||
ch->flags |= ATA_NO_SLAVE;
|
||||
}
|
||||
}
|
||||
@ -2177,8 +2189,8 @@ ata_nvidia_ident(device_t dev)
|
||||
{ ATA_NFORCE3_MCP_S1, 0, 0, NV4OFF, ATA_SA150, "nVidia nForce3 MCP" },
|
||||
{ ATA_NFORCE3_MCP_S2, 0, 0, NV4OFF, ATA_SA150, "nVidia nForce3 MCP" },
|
||||
{ ATA_NFORCE4, 0, AMDNVIDIA, NVIDIA, ATA_UDMA6, "nVidia nForce4" },
|
||||
{ ATA_NFORCE4_S1, 0, 0, NV4OFF, ATA_SA150, "nVidia nForce4" },
|
||||
{ ATA_NFORCE4_S2, 0, 0, NV4OFF, ATA_SA150, "nVidia nForce4" },
|
||||
{ ATA_NFORCE4_S1, 0, 0, NV4OFF, ATA_SA300, "nVidia nForce4" },
|
||||
{ ATA_NFORCE4_S2, 0, 0, NV4OFF, ATA_SA300, "nVidia nForce4" },
|
||||
{ 0, 0, 0, 0, 0, 0}};
|
||||
char buffer[64];
|
||||
|
||||
|
@ -307,6 +307,7 @@ struct ata_connect_task {
|
||||
#define ATA_VIA6421 0x32491106
|
||||
|
||||
/* chipset setup related defines */
|
||||
#define AHCI 1
|
||||
#define ATPOLD 1
|
||||
|
||||
#define ALIOLD 0x01
|
||||
|
@ -1830,20 +1830,25 @@ ata_raid_intel_read_meta(device_t dev, struct ar_softc **raidp)
|
||||
struct ata_raid_subdisk *ars = device_get_softc(dev);
|
||||
device_t parent = device_get_parent(dev);
|
||||
struct intel_raid_conf *meta;
|
||||
struct intel_raid_mapping *map;
|
||||
struct ar_softc *raid = NULL;
|
||||
u_int32_t checksum, *ptr;
|
||||
int array, count, disk, retval = 0;
|
||||
int array, count, disk, volume = 1, retval = 0;
|
||||
char *tmp;
|
||||
|
||||
if (!(meta = (struct intel_raid_conf *)
|
||||
malloc(1024, M_AR, M_NOWAIT | M_ZERO)))
|
||||
malloc(1536, M_AR, M_NOWAIT | M_ZERO)))
|
||||
return ENOMEM;
|
||||
|
||||
if (ata_raid_rw(parent, INTEL_LBA(parent),
|
||||
meta, 1024, ATA_R_READ)) {
|
||||
if (ata_raid_rw(parent, INTEL_LBA(parent), meta, 1024, ATA_R_READ)) {
|
||||
if (testing || bootverbose)
|
||||
device_printf(parent, "Intel read metadata failed\n");
|
||||
goto intel_out;
|
||||
}
|
||||
tmp = (char *)meta;
|
||||
bcopy(tmp, tmp+1024, 512);
|
||||
bcopy(tmp+512, tmp, 1024);
|
||||
bzero(tmp+1024, 512);
|
||||
|
||||
/* check if this is a Intel RAID struct */
|
||||
if (strncmp(meta->intel_id, INTEL_MAGIC, strlen(INTEL_MAGIC))) {
|
||||
@ -1851,23 +1856,23 @@ ata_raid_intel_read_meta(device_t dev, struct ar_softc **raidp)
|
||||
device_printf(parent, "Intel check1 failed\n");
|
||||
goto intel_out;
|
||||
}
|
||||
|
||||
for (checksum = 0, ptr = (u_int32_t *)meta, count = 0;
|
||||
count < (meta->config_size / sizeof(u_int32_t)); count++) {
|
||||
checksum += *ptr++;
|
||||
}
|
||||
|
||||
/* XXX SOS needs to be fixed */
|
||||
device_printf(parent, "Intel calc=%08x meta=%08x\n", checksum, meta->checksum);
|
||||
|
||||
checksum -= meta->checksum;
|
||||
if (checksum != meta->checksum) {
|
||||
if (testing || bootverbose)
|
||||
device_printf(parent, "Intel check2 failed\n");
|
||||
//goto intel_out;
|
||||
goto intel_out;
|
||||
}
|
||||
|
||||
if (testing || bootverbose)
|
||||
ata_raid_intel_print_meta(meta);
|
||||
|
||||
map = (struct intel_raid_mapping *)&meta->disk[meta->total_disks];
|
||||
|
||||
/* now convert Intel metadata into our generic form */
|
||||
for (array = 0; array < MAX_ARRAYS; array++) {
|
||||
if (!raidp[array]) {
|
||||
@ -1889,13 +1894,9 @@ device_printf(parent, "Intel calc=%08x meta=%08x\n", checksum, meta->checksum);
|
||||
|
||||
/*
|
||||
* update our knowledge about the array config based on generation
|
||||
* we only grap the first volume description (yet) since the
|
||||
* BIOS'n I have access to puts crap into the following ones
|
||||
* NOTE: there can be multiple volumes on a disk set
|
||||
*/
|
||||
if (!meta->generation || meta->generation > raid->generation) {
|
||||
struct intel_raid_mapping *map =
|
||||
(struct intel_raid_mapping *)&meta->disk[meta->total_disks];
|
||||
|
||||
switch (map->type) {
|
||||
case INTEL_T_RAID0:
|
||||
raid->type = AR_T_RAID0;
|
||||
@ -1903,10 +1904,18 @@ device_printf(parent, "Intel calc=%08x meta=%08x\n", checksum, meta->checksum);
|
||||
break;
|
||||
|
||||
case INTEL_T_RAID1:
|
||||
raid->type = AR_T_RAID1;
|
||||
if (map->total_disks == 4)
|
||||
raid->type = AR_T_RAID01;
|
||||
else
|
||||
raid->type = AR_T_RAID1;
|
||||
raid->width = map->total_disks / 2;
|
||||
break;
|
||||
|
||||
case INTEL_T_RAID5:
|
||||
raid->type = AR_T_RAID5;
|
||||
raid->width = map->total_disks;
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(parent, "Intel unknown RAID type 0x%02x\n",
|
||||
map->type);
|
||||
@ -1976,8 +1985,15 @@ device_printf(parent, "Intel calc=%08x meta=%08x\n", checksum, meta->checksum);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retval)
|
||||
if (retval) {
|
||||
if (volume < meta->total_volumes) {
|
||||
map = (struct intel_raid_mapping *)
|
||||
&map->disk_idx[map->total_disks];
|
||||
volume++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
intel_out:
|
||||
@ -3724,6 +3740,7 @@ ata_raid_intel_type(int type)
|
||||
switch (type) {
|
||||
case INTEL_T_RAID0: return "RAID0";
|
||||
case INTEL_T_RAID1: return "RAID1";
|
||||
case INTEL_T_RAID5: return "RAID5";
|
||||
default: sprintf(buffer, "UNKNOWN 0x%02x", type);
|
||||
return buffer;
|
||||
}
|
||||
@ -3767,7 +3784,7 @@ ata_raid_intel_print_meta(struct intel_raid_conf *meta)
|
||||
for (i = 0; i < map->total_disks; i++ ) {
|
||||
printf(" disk %d at disk_idx 0x%08x\n", i, map->disk_idx[i]);
|
||||
}
|
||||
map = (struct intel_raid_mapping *)&map->disk_idx[i];
|
||||
map = (struct intel_raid_mapping *)&map->disk_idx[map->total_disks];
|
||||
}
|
||||
printf("=================================================\n");
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ struct hptv3_raid_conf {
|
||||
|
||||
/* Intel MatrixRAID Metadata */
|
||||
#define INTEL_LBA(dev) \
|
||||
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 2)
|
||||
(((struct ad_softc *)device_get_ivars(dev))->total_secs - 3)
|
||||
|
||||
struct intel_raid_conf {
|
||||
u_int8_t intel_id[24];
|
||||
@ -332,6 +332,7 @@ struct intel_raid_mapping {
|
||||
u_int8_t type;
|
||||
#define INTEL_T_RAID0 0x00
|
||||
#define INTEL_T_RAID1 0x01
|
||||
#define INTEL_T_RAID5 0x05
|
||||
|
||||
u_int8_t total_disks;
|
||||
u_int8_t dummy_2[3];
|
||||
|
Loading…
Reference in New Issue
Block a user