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.
This commit is contained in:
sos 2000-02-25 09:48:23 +00:00
parent 823a6c05b0
commit 627ad02e66
3 changed files with 74 additions and 39 deletions

View File

@ -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 @@ ata_probe(device_t dev)
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;

View File

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

View File

@ -413,6 +413,23 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
/* 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 */