From e3989d3ebf0821b15bb0f0cc89b381ecc4f63dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Schmidt?= Date: Thu, 16 Feb 2006 17:09:24 +0000 Subject: [PATCH] Add support for the JMicron JMB363 dual SATA + single PATA controller. Documentation and HW kindly provided by JMicron. --- sys/dev/ata/ata-chipset.c | 136 ++++++++++++++++++++++++++++---------- sys/dev/ata/ata-pci.c | 5 +- sys/dev/ata/ata-pci.h | 2 + 3 files changed, 104 insertions(+), 39 deletions(-) diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index 2936534a1dc6..db123d9a2fea 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -100,6 +100,10 @@ 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_jmicron_allocate(device_t dev); +static void ata_jmicron_reset(device_t dev); +static void ata_jmicron_dmainit(device_t dev); +static void ata_jmicron_setmode(device_t dev, int mode); static int ata_marvell_chipinit(device_t dev); static int ata_marvell_allocate(device_t dev); static int ata_marvell_status(device_t dev); @@ -2065,6 +2069,7 @@ ata_jmicron_ident(device_t dev) struct ata_chip_id *idx; static struct ata_chip_id ids[] = {{ ATA_JMB360, 0, 0, 0, ATA_SA300, "JMB360" }, + { ATA_JMB363, 0, 1, 0, ATA_SA300, "JMB363" }, { 0, 0, 0, 0, 0, 0}}; char buffer[64]; @@ -2087,51 +2092,112 @@ ata_jmicron_chipinit(device_t dev) if (ata_setup_interrupt(dev)) return ENXIO; + /* set controller configuration to a setup we support */ + pci_write_config(dev, 0x40, 0x80c0a131, 4); + + ctlr->allocate = ata_jmicron_allocate; + ctlr->reset = ata_jmicron_reset; + ctlr->dmainit = ata_jmicron_dmainit; + ctlr->setmode = ata_jmicron_setmode; + 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; + if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, + &ctlr->r_rid2, RF_ACTIVE))) { + /* 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); - /* enable AHCI mode */ - pci_write_config(dev, 0x41, 0xa1, 1); + /* get the number of HW channels */ + ctlr->channels = + (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_NPMASK) + 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; + /* 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); } - /* 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); + /* add in PATA channel(s) */ + ctlr->channels += ctlr->chip->cfg1; return 0; } +static int +ata_jmicron_allocate(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + int error; + + if (ch->unit >= 2) { + ch->unit -= 2; + error = ata_pci_allocate(dev); + ch->unit += 2; + } + else + error = ata_ahci_allocate(dev); + return error; +} + +static void +ata_jmicron_reset(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + + if (ch->unit >= 2) + ata_generic_reset(dev); + else + ata_ahci_reset(dev); +} + +static void +ata_jmicron_dmainit(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + + if (ch->unit >= 2) + ata_pci_dmainit(dev); + else + ata_ahci_dmainit(dev); +} + +static void +ata_jmicron_setmode(device_t dev, int mode) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(dev)); + + if (ch->unit >= 2) { + struct ata_device *atadev = device_get_softc(dev); + + /* check for 80pin cable present */ + if (pci_read_config(dev, 0x40, 1) & 0x08) + mode = ata_limit_mode(dev, mode, ATA_UDMA2); + else + mode = ata_limit_mode(dev, mode, ATA_UDMA6); + + if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) + atadev->mode = mode; + } + else + ata_sata_setmode(dev, mode); +} + /* * Marvell chipset support functions diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 9f4623b8cd40..38d3c068542f 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -59,9 +59,6 @@ static MALLOC_DEFINE(M_ATAPCI, "ata_pci", "ATA driver PCI"); #define IOMASK 0xfffffffc #define ATA_PROBE_OK -10 -/* prototypes */ -static void ata_pci_dmainit(device_t); - int ata_legacy(device_t dev) { @@ -505,7 +502,7 @@ ata_pci_dmareset(device_t dev) ch->dma->unload(dev); } -static void +void ata_pci_dmainit(device_t dev) { struct ata_channel *ch = device_get_softc(dev); diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index ff193e7f7c15..106962360f31 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -161,6 +161,7 @@ struct ata_connect_task { #define ATA_JMICRON_ID 0x197b #define ATA_JMB360 0x2360197b +#define ATA_JMB363 0x2363197b #define ATA_MARVELL_ID 0x11ab #define ATA_M88SX5040 0x504011ab @@ -401,6 +402,7 @@ int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int f int ata_pci_allocate(device_t dev); void ata_pci_hw(device_t dev); int ata_pci_status(device_t dev); +void ata_pci_dmainit(device_t); /* global prototypes ata-chipset.c */