diff options
author | sos <sos@FreeBSD.org> | 2000-02-25 09:48:23 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2000-02-25 09:48:23 +0000 |
commit | bc6c7f473064c95d7f3ce9e88ef33d38e2d8009d (patch) | |
tree | 3bfb040ee9f8c8174423daa33f87231396ed6bfe /sys | |
parent | 9f02798cbfe015ae668d1b66d84cd72f96f7b332 (diff) | |
download | FreeBSD-src-bc6c7f473064c95d7f3ce9e88ef33d38e2d8009d.zip FreeBSD-src-bc6c7f473064c95d7f3ce9e88ef33d38e2d8009d.tar.gz |
Add (partial) support for the Cypress ATA controller.
Call intr_teardown on detach.
Always add non masterdevice from unit 2 upwards.
Update to the pccard code, at least some cards are now working,
more testing to follow.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ata/ata-all.c | 95 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 1 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 17 |
3 files changed, 74 insertions, 39 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index e5f120e..7bf5a4a 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -75,7 +75,7 @@ /* misc defines */ #define IOMASK 0xfffffffc #define ATA_IOADDR_RID 0 -#define ATA_ALTIOADDR_RID 1 +#define ATA_ALTADDR_RID 1 #define ATA_BMADDR_RID 2 /* prototypes */ @@ -161,21 +161,23 @@ ata_pccard_probe(device_t dev) { struct ata_softc *scp = device_get_softc(dev); struct resource *port; - int rid; - u_long tmp; + int rid, len; /* allocate the port range */ rid = ATA_IOADDR_RID; - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_IOSIZE, RF_ACTIVE); + len = bus_get_resource_count(dev, SYS_RES_IOPORT, rid); + port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, len, RF_ACTIVE); if (!port) return ENOMEM; - /* alloctate the altport range */ - if (bus_get_resource(dev, SYS_RES_IOPORT, 1, &tmp, &tmp)) { - bus_set_resource(dev, SYS_RES_IOPORT, 1, - rman_get_start(port) + ATA_ALTPORT_PCCARD, - ATA_ALTIOSIZE); + /* + * if we got more than the default ATA_IOSIZE ports, this is likely + * a pccard system where the altio ports are located just after the + * normal io ports, so no need to allocate them. + */ + if (len <= ATA_IOSIZE) { + bus_set_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, + rman_get_start(port) + ATA_ALTPORT, ATA_ALTIOSIZE); } bus_release_resource(dev, SYS_RES_IOPORT, 0, port); scp->unit = device_get_unit(dev); @@ -188,7 +190,6 @@ static device_method_t ata_pccard_methods[] = { DEVMETHOD(device_probe, ata_pccard_probe), DEVMETHOD(device_attach, ata_attach), DEVMETHOD(device_detach, ata_detach), - DEVMETHOD(device_resume, ata_resume), { 0, 0 } }; @@ -276,6 +277,11 @@ ata_pci_match(device_t dev) case 0x06461095: return "CMD 646 ATA controller"; + case 0xc6931080: + if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) + return "Cypress 82C693 ATA controller"; + break; + case 0x74091022: return "AMD 756 ATA66 controller"; @@ -296,11 +302,6 @@ ata_pci_match(device_t dev) case 0x06401095: return "CMD 640 ATA controller !WARNING! buggy chip data loss possible"; - case 0xc6931080: - if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) - return "Cypress 82C693 ATA controller (generic mode)"; - break; - case 0x01021078: return "Cyrix 5530 ATA controller (generic mode)"; @@ -330,17 +331,16 @@ static int ata_pci_add_child(device_t dev, int unit) { device_t child; - int lun; /* check if this is located at one of the std addresses */ - if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) - lun = unit; - else - lun = -1; - - if (!(child = device_add_child(dev, "ata", lun))) - return ENOMEM; - + if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { + if (!(child = device_add_child(dev, "ata", unit))) + return ENOMEM; + } + else { + if (!(child = device_add_child(dev, "ata", 2))) + return ENOMEM; + } device_set_ivars(child, (void *)(uintptr_t) unit); return 0; } @@ -436,6 +436,16 @@ ata_pci_attach(device_t dev) break; } + /* + * the Cypress chip is a mess, it contains two ATA functions, but + * both channels are visible on the first one. + * simply ignore the second function for now, as the right + * solution (ignoring the second channel on the first function) + * doesn't work with the crappy ATA interrupt setup on the alpha. + */ + if (pci_get_devid(dev) == 0xc6931080 && pci_get_function(dev) > 1) + return 0; + ata_pci_add_child(dev, 0); if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV || @@ -485,7 +495,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, myrid = 0x10 + 8 * unit; break; - case ATA_ALTIOADDR_RID: + case ATA_ALTADDR_RID: if (masterdev) { myrid = 0; start = (unit == 0 ? IO_WD1 : IO_WD2) + ATA_ALTPORT; @@ -572,7 +582,7 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid, myrid = 0x10 + 8 * unit; break; - case ATA_ALTIOADDR_RID: + case ATA_ALTADDR_RID: if (masterdev) myrid = 0; else @@ -737,16 +747,19 @@ ata_probe(device_t dev) scp->devices = 0; rid = ATA_IOADDR_RID; - io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_IOSIZE, RF_ACTIVE); if (!io) goto failure; ioaddr = rman_get_start(io); - rid = ATA_ALTIOADDR_RID; - altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); - if (!altio) - goto failure; - altioaddr = rman_get_start(altio); + rid = ATA_ALTADDR_RID; + altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_ALTIOSIZE, RF_ACTIVE); + if (altio) + altioaddr = rman_get_start(altio); + else + altioaddr = ioaddr + ATA_IOSIZE; rid = ATA_BMADDR_RID; bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); @@ -836,7 +849,7 @@ failure: if (io) bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); if (altio) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTIOADDR_RID, altio); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, altio); if (bmio) bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, bmio); if (bootverbose) @@ -848,8 +861,7 @@ static int ata_attach(device_t dev) { struct ata_softc *scp = device_get_softc(dev); - int rid = 0; - void *ih; + int error, rid = 0; if (!scp || scp->flags & ATA_ATTACHED) return ENXIO; @@ -860,7 +872,9 @@ ata_attach(device_t dev) ata_printf(scp, -1, "unable to allocate interrupt\n"); return ENXIO; } - bus_setup_intr(dev, scp->r_irq, INTR_TYPE_BIO, ata_intr, scp, &ih); + if ((error = bus_setup_intr(dev, scp->r_irq, INTR_TYPE_BIO, ata_intr, + scp, &scp->ih))) + return error; /* * do not attach devices if we are in early boot, this is done later @@ -927,9 +941,12 @@ ata_detach(device_t dev) } scp->mode[ATA_DEV(ATA_MASTER)] = ATA_PIO; scp->mode[ATA_DEV(ATA_SLAVE)] = ATA_PIO; + bus_teardown_intr(dev, scp->r_irq, scp->ih); bus_release_resource(dev, SYS_RES_IRQ, 0, scp->r_irq); - bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, scp->r_bmio); - bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTIOADDR_RID, scp->r_altio); + if (scp->r_bmio) + bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, scp->r_bmio); + if (scp->r_altio) + bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID,scp->r_altio); bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, scp->r_io); scp->flags &= ~ATA_ATTACHED; return 0; diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 317926f..fcac26e 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -260,6 +260,7 @@ struct ata_softc { struct resource *r_altio; /* altio addr resource handle */ struct resource *r_bmio; /* bmio addr resource handle */ struct resource *r_irq; /* interrupt of this channel */ + void *ih; /* interrupt handle */ int32_t ioaddr; /* physical port addr */ int32_t altioaddr; /* physical alt port addr */ int32_t bmaddr; /* physical bus master port */ diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 1dfadcd..11a9458 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -413,6 +413,23 @@ via_generic: /* we could set PIO mode timings, but we assume the BIOS did that */ break; + case 0xc6931080: /* Cypress 82c693 ATA controller */ + if (wdmamode >= 2 && apiomode >= 4) { + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_printf(scp, device, + "%s setting up WDMA2 mode on Cypress chip\n", + error ? "failed" : "success"); + if (!error) { + pci_write_config(scp->dev, scp->unit ? 0x4e : 0x4c, 0x2020, 2); + scp->mode[ATA_DEV(device)] = ATA_WDMA2; + return; + } + } + /* we could set PIO mode timings, but we assume the BIOS did that */ + break; + case 0x4d33105a: /* Promise Ultra33 / FastTrak33 controllers */ case 0x4d38105a: /* Promise Ultra66 / FastTrak66 controllers */ /* the Promise can only do DMA on ATA disks not on ATAPI devices */ |