diff options
author | sos <sos@FreeBSD.org> | 2006-01-25 23:07:42 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2006-01-25 23:07:42 +0000 |
commit | 0d5c93667ae5e094af6756634ecc40011f97c886 (patch) | |
tree | c5615b22498f07ad26231976a35fcccf9be2d568 | |
parent | 64e71c497436b5aad818fb2f87388dbdaa556ec1 (diff) | |
download | FreeBSD-src-0d5c93667ae5e094af6756634ecc40011f97c886.zip FreeBSD-src-0d5c93667ae5e094af6756634ecc40011f97c886.tar.gz |
Add support for the JMicron JMB360 SATAII controller.
Thanks to JMicron for providing needed info.
HW donated by: Ralf Folkerts
-rw-r--r-- | sys/dev/ata/ata-chipset.c | 135 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.c | 4 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.h | 4 |
3 files changed, 119 insertions, 24 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index 2f0e11f..acc5bb3 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -99,6 +99,7 @@ static int ata_intel_31244_command(struct ata_request *request); static void ata_intel_31244_reset(device_t dev); static int ata_ite_chipinit(device_t dev); static void ata_ite_setmode(device_t dev, int mode); +static int ata_jmicron_chipinit(device_t dev); static int ata_marvell_chipinit(device_t dev); static int ata_marvell_allocate(device_t dev); static int ata_marvell_status(device_t dev); @@ -236,7 +237,9 @@ ata_sata_phy_enable(struct ata_channel *ch) } ata_udelay(5000); for (loop = 0; loop < 10; loop++) { - ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE); + ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE | + ATA_SC_IPM_DIS_PARTIAL | + ATA_SC_IPM_DIS_SLUMBER); ata_udelay(100); if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0) { ata_sata_connect(ch); @@ -448,28 +451,29 @@ ata_ahci_status(device_t dev) struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); struct ata_connect_task *tp; - u_int32_t action, status, error, issued; + u_int32_t action, istatus, sstatus, error, issued; int offset = (ch->unit << 7); int tag = 0; - action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS) & (1 << ch->unit); - - if (action) { - error = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SERR + offset); - status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset); + if ((action = ATA_INL(ctlr->r_res2, ATA_AHCI_IS)) & (1 << ch->unit)) { + istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset); issued = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset); + sstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SSTS + offset); + error = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SERR + offset); + + /* clear interrupt(s) */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action); + ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus); ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_SERR + offset, error); - ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, status); /* do we have cold connect surprise */ - if (status & ATA_AHCI_P_IX_CPD) { - printf("ata_ahci_intr status=%08x error=%08x issued=%08x\n", - status, error, issued); + if (istatus & ATA_AHCI_P_IX_CPD) { + printf("ata_ahci_intr status=%08x sstatus=%08x error=%08x\n", + istatus, sstatus, error); } /* check for and handle connect events */ - if (((status & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) == - ATA_AHCI_P_IX_PC) && + if ((istatus & ATA_AHCI_P_IX_PC) && (tp = (struct ata_connect_task *) malloc(sizeof(struct ata_connect_task), M_ATA, M_NOWAIT | M_ZERO))) { @@ -483,8 +487,9 @@ ata_ahci_status(device_t dev) } /* check for and handle disconnect events */ - if (((status & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) == - ATA_AHCI_P_IX_PRC) && + else if ((istatus & ATA_AHCI_P_IX_PRC) && + !((sstatus & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 || + (sstatus & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) && (tp = (struct ata_connect_task *) malloc(sizeof(struct ata_connect_task), M_ATA, M_NOWAIT | M_ZERO))) { @@ -497,9 +502,6 @@ ata_ahci_status(device_t dev) taskqueue_enqueue(taskqueue_thread, &tp->task); } - /* clear interrupt */ - ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action); - /* do we have any device action ? */ if (!(issued & (1 << tag))) return 1; @@ -902,11 +904,13 @@ ata_ali_chipinit(device_t dev) switch (ctlr->chip->cfg2) { case ALISATA: - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); ctlr->channels = ctlr->chip->cfg1; ctlr->allocate = ata_ali_sata_allocate; ctlr->setmode = ata_sata_setmode; + + /* enable PCI interrupt */ + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); break; case ALINEW: @@ -2040,6 +2044,84 @@ ata_ite_setmode(device_t dev, int mode) /* + * JMicron chipset support functions + */ +int +ata_jmicron_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_JMB360, 0, 0, 0, ATA_SA300, "JMB360" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "JMicron %s %s controller", + idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_jmicron_chipinit; + return 0; +} + +static int +ata_jmicron_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_setup_interrupt(dev)) + return ENXIO; + + 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))) + return ENXIO; + + + /* enable AHCI mode */ + pci_write_config(dev, 0x41, 0xa1, 1); + + /* reset AHCI controller */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, + ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_HR); + DELAY(1000000); + if (ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) { + bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); + device_printf(dev, "AHCI controller reset failure\n"); + return ENXIO; + } + + /* enable AHCI mode */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, + ATA_INL(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; + + ctlr->allocate = ata_ahci_allocate; + ctlr->reset = ata_ahci_reset; + ctlr->dmainit = ata_ahci_dmainit; + ctlr->setmode = ata_sata_setmode; + + /* clear interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, ATA_INL(ctlr->r_res2, ATA_AHCI_IS)); + + /* enable AHCI interrupts */ + ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, + ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) | ATA_AHCI_GHC_IE); + + /* enable PCI interrupt */ + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); + return 0; +} + + +/* * Marvell chipset support functions */ #define ATA_MV_HOST_BASE(ch) \ @@ -2128,6 +2210,7 @@ ata_marvell_chipinit(device_t dev) ATA_OUTL(ctlr->r_res1, 0x01d64, 0x000000ff/*HC0*/ | 0x0001fe00/*HC1*/ | /*(1<<19) | (1<<20) | (1<<21) |*/(1<<22) | (1<<24) | (0x7f << 25)); + /* enable PCI interrupt */ pci_write_config(dev, PCIR_COMMAND, pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2); return 0; @@ -4282,10 +4365,12 @@ ata_sis_chipinit(device_t dev) ctlr->r_rid2 = PCIR_BAR(5); if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, &ctlr->r_rid2, RF_ACTIVE))) { - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); ctlr->allocate = ata_sis_allocate; ctlr->reset = ata_sis_reset; + + /* enable PCI interrupt */ + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); } ctlr->setmode = ata_sata_setmode; return 0; @@ -4471,10 +4556,12 @@ ata_via_chipinit(device_t dev) ctlr->r_rid2 = PCIR_BAR(5); if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, &ctlr->r_rid2, RF_ACTIVE))) { - pci_write_config(dev, PCIR_COMMAND, - pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); ctlr->allocate = ata_via_allocate; ctlr->reset = ata_via_reset; + + /* enable PCI interrupt */ + pci_write_config(dev, PCIR_COMMAND, + pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); } ctlr->setmode = ata_sata_setmode; return 0; diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 896094d..6551459 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -113,6 +113,10 @@ ata_pci_probe(device_t dev) if (!ata_ite_ident(dev)) return ATA_PROBE_OK; break; + case ATA_JMICRON_ID: + if (!ata_jmicron_ident(dev)) + return ATA_PROBE_OK; + break; case ATA_MARVELL_ID: if (!ata_marvell_ident(dev)) return ATA_PROBE_OK; diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index 59bf0f8..ff193e7 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -159,6 +159,9 @@ struct ata_connect_task { #define ATA_IT8211F 0x82111283 #define ATA_IT8212F 0x82121283 +#define ATA_JMICRON_ID 0x197b +#define ATA_JMB360 0x2360197b + #define ATA_MARVELL_ID 0x11ab #define ATA_M88SX5040 0x504011ab #define ATA_M88SX5041 0x504111ab @@ -411,6 +414,7 @@ int ata_cypress_ident(device_t); int ata_highpoint_ident(device_t); int ata_intel_ident(device_t); int ata_ite_ident(device_t); +int ata_jmicron_ident(device_t); int ata_marvell_ident(device_t); int ata_national_ident(device_t); int ata_nvidia_ident(device_t); |