diff options
author | sos <sos@FreeBSD.org> | 2000-02-18 20:57:33 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2000-02-18 20:57:33 +0000 |
commit | 6feaaed878ea54ff19a32fb1fa9e961f31156bf9 (patch) | |
tree | df6b1c424ce11d10280d0e2830b96a3eb27b5673 /sys/dev/ata | |
parent | eeff6080d3810c5a858215f55e4a05d7a095f464 (diff) | |
download | FreeBSD-src-6feaaed878ea54ff19a32fb1fa9e961f31156bf9.zip FreeBSD-src-6feaaed878ea54ff19a32fb1fa9e961f31156bf9.tar.gz |
Update the ata driver to take more advantage of newbus, this
was needed to make attach/detach of devices work, which is
needed for the PCCARD support.
(PCCARD support is still not working though, more to come on that)
Support the CMD646 chip which is used on many alphas, sadly only
in WDMA2 mode, as the silicon is broken beyond belief for UDMA modes.
Lots of cosmetic fixes here and there.
Sorry for the size of this megapatchfromhell but it was not
possible otherwise...
newbus patches based on work from: dfr (Doug Rabson)
Diffstat (limited to 'sys/dev/ata')
-rw-r--r-- | sys/dev/ata/ata-all.c | 1225 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 46 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 75 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.h | 2 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 87 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 48 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.h | 5 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 102 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.h | 1 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 32 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.h | 1 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.c | 37 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.h | 1 |
13 files changed, 1067 insertions, 595 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 3a497e5..e5f120e 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -29,8 +29,8 @@ */ #include "ata.h" -#include "apm.h" #include "isa.h" +#include "card.h" #include "pci.h" #include "atadisk.h" #include "atapicd.h" @@ -65,34 +65,37 @@ #include <machine/smp.h> #include <i386/isa/intr_machdep.h> #endif -#if NAPM > 0 -#include <machine/apm_bios.h> +#ifdef __alpha__ +#include <machine/md_var.h> #endif #include <dev/ata/ata-all.h> #include <dev/ata/ata-disk.h> #include <dev/ata/atapi-all.h> /* misc defines */ -#if SMP == 0 -#define isa_apic_irq(x) x -#endif -#define IOMASK 0xfffffffc +#define IOMASK 0xfffffffc +#define ATA_IOADDR_RID 0 +#define ATA_ALTIOADDR_RID 1 +#define ATA_BMADDR_RID 2 /* prototypes */ -static int32_t ata_probe(int32_t, int32_t, int32_t, device_t, int32_t *); -static void ata_attach(void *); +static int ata_probe(device_t); +static int ata_attach(device_t); +static int ata_detach(device_t); +static int ata_resume(device_t); +static void ata_boot_attach(void); +static void ata_intr(void *); static int32_t ata_getparam(struct ata_softc *, int32_t, u_int8_t); -static void ataintr(void *); static int8_t *active2str(int32_t); static void bswap(int8_t *, int32_t); static void btrim(int8_t *, int32_t); static void bpack(int8_t *, int8_t *, int32_t); /* local vars */ -static int32_t atanlun = 2; -static struct intr_config_hook *ata_attach_hook = NULL; static devclass_t ata_devclass; -struct ata_softc *atadevices[MAXATA]; +static devclass_t ata_pci_devclass; +static struct intr_config_hook *ata_delayed_attach = NULL; +static char ata_conf[256]; MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer"); #if NISA > 0 @@ -105,91 +108,134 @@ static struct isa_pnp_id ata_ids[] = { }; static int -ata_isaprobe(device_t dev) +ata_isa_probe(device_t dev) { + struct ata_softc *scp = device_get_softc(dev); struct resource *port; int rid; - int32_t ctlr, res; - int32_t lun; + u_long tmp; - /* Check isapnp ids */ + /* check isapnp ids */ if (ISA_PNP_PROBE(device_get_parent(dev), dev, ata_ids) == ENXIO) return ENXIO; - /* Allocate the port range */ - rid = 0; - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + /* allocate the port range */ + rid = ATA_IOADDR_RID; + port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_IOSIZE, RF_ACTIVE); if (!port) return ENOMEM; - /* check if allready in use by a PCI device */ - for (ctlr = 0; ctlr < atanlun; ctlr++) { - if (atadevices[ctlr] && atadevices[ctlr]->ioaddr==rman_get_start(port)){ - printf("ata-isa%d: already registered as ata%d\n", - device_get_unit(dev), ctlr); - bus_release_resource(dev, SYS_RES_IOPORT, 0, port); - return ENXIO; - } + /* 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, + ATA_ALTIOSIZE); } + bus_release_resource(dev, SYS_RES_IOPORT, 0, port); + scp->unit = device_get_unit(dev); + scp->flags |= ATA_USE_16BIT; + return ata_probe(dev); +} - lun = 0; - res = ata_probe(rman_get_start(port), rman_get_start(port) + ATA_ALTPORT, - 0, dev, &lun); +static device_method_t ata_isa_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, ata_isa_probe), + DEVMETHOD(device_attach, ata_attach), + DEVMETHOD(device_resume, ata_resume), + { 0, 0 } +}; - bus_release_resource(dev, SYS_RES_IOPORT, 0, port); +static driver_t ata_isa_driver = { + "ata", + ata_isa_methods, + sizeof(struct ata_softc), +}; - if (res) { - isa_set_portsize(dev, res); - *(int *)device_get_softc(dev) = lun; - atadevices[lun]->flags |= ATA_USE_16BIT; - return 0; - } - return ENXIO; -} +DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0); +#endif +#if NCARD > 0 static int -ata_isaattach(device_t dev) +ata_pccard_probe(device_t dev) { + struct ata_softc *scp = device_get_softc(dev); struct resource *port; - struct resource *irq; - void *ih; int rid; + u_long tmp; - /* Allocate the port range and interrupt */ - rid = 0; - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + /* allocate the port range */ + rid = ATA_IOADDR_RID; + port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_IOSIZE, RF_ACTIVE); if (!port) - return (ENOMEM); + return ENOMEM; - rid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE); - if (!irq) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, 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); } - return bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, - atadevices[*(int *)device_get_softc(dev)], &ih); + bus_release_resource(dev, SYS_RES_IOPORT, 0, port); + scp->unit = device_get_unit(dev); + scp->flags |= ATA_USE_16BIT; + return ata_probe(dev); } -static device_method_t ata_isa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ata_isaprobe), - DEVMETHOD(device_attach, ata_isaattach), +static device_method_t ata_pccard_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, ata_pccard_probe), + DEVMETHOD(device_attach, ata_attach), + DEVMETHOD(device_detach, ata_detach), + DEVMETHOD(device_resume, ata_resume), { 0, 0 } }; -static driver_t ata_isa_driver = { +static driver_t ata_pccard_driver = { "ata", - ata_isa_methods, - sizeof(int), + ata_pccard_methods, + sizeof(struct ata_softc), }; -DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0); +DRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, 0, 0); #endif #if NPCI > 0 +struct ata_pci_softc { + struct resource *bmio; + struct resource bmio_1; + struct resource bmio_2; + struct resource *irq; + int32_t irqcnt; +}; + +static int32_t +ata_find_dev(device_t dev, int32_t type) +{ + device_t *children, child; + int nchildren, i; + + if (device_get_children(device_get_parent(dev), &children, &nchildren)) + return 0; + + for (i = 0; i < nchildren; i++) { + child = children[i]; + + /* check that it's on the same silicon and the device we want */ + if (pci_get_slot(dev) == pci_get_slot(child) && + pci_get_vendor(child) == (type & 0xffff) && + pci_get_device(child) == ((type & 0xffff0000) >> 16)) { + free(children, M_TEMP); + return 1; + } + } + free(children, M_TEMP); + return 0; +} + static const char * -ata_pcimatch(device_t dev) +ata_pci_match(device_t dev) { if (pci_get_class(dev) != PCIC_STORAGE) return NULL; @@ -204,54 +250,61 @@ ata_pcimatch(device_t dev) case 0x71118086: case 0x71998086: - return "Intel PIIX4 ATA-33 controller"; + return "Intel PIIX4 ATA33 controller"; case 0x24118086: - return "Intel ICH ATA-66 controller"; + return "Intel ICH ATA66 controller"; case 0x24218086: - return "Intel ICH0 ATA-33 controller"; + return "Intel ICH0 ATA33 controller"; case 0x522910b9: - return "AcerLabs Aladdin ATA-33 controller"; + return "AcerLabs Aladdin ATA33 controller"; - case 0x05711106: /* 82c586 & 82c686 */ + case 0x05711106: if (ata_find_dev(dev, 0x05861106)) - return "VIA 82C586 ATA-33 controller"; + return "VIA 82C586 ATA33 controller"; if (ata_find_dev(dev, 0x05961106)) - return "VIA 82C596 ATA-33 controller"; + return "VIA 82C596 ATA33 controller"; if (ata_find_dev(dev, 0x06861106)) - return "VIA 82C686 ATA-66 controller"; + return "VIA 82C686 ATA66 controller"; return "VIA Apollo ATA controller"; case 0x55131039: - return "SiS 5591 ATA-33 controller"; + return "SiS 5591 ATA33 controller"; + + case 0x06461095: + return "CMD 646 ATA controller"; case 0x74091022: - return "AMD 756 ATA-66 controller"; + return "AMD 756 ATA66 controller"; case 0x4d33105a: - return "Promise ATA-33 controller"; + return "Promise ATA33 controller"; case 0x4d38105a: - return "Promise ATA-66 controller"; + return "Promise ATA66 controller"; case 0x00041103: - return "HighPoint HPT366 ATA-66 controller"; + return "HighPoint HPT366 ATA66 controller"; /* unsupported but known chipsets, generic DMA only */ - case 0x06401095: - return "CMD 640 ATA controller (generic mode)"; + case 0x10001042: + case 0x10011042: + return "RZ 100? ATA controller !WARNING! buggy chip data loss possible"; - case 0x06461095: - return "CMD 646 ATA controller (generic mode)"; + case 0x06401095: + return "CMD 640 ATA controller !WARNING! buggy chip data loss possible"; case 0xc6931080: - return "Cypress 82C693 ATA controller (generic mode)"; + 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)"; + /* unknown chipsets, try generic DMA if it seems possible */ default: if (pci_get_class(dev) == PCIC_STORAGE && (pci_get_subclass(dev) == PCIS_STORAGE_IDE)) @@ -261,9 +314,9 @@ ata_pcimatch(device_t dev) } static int -ata_pciprobe(device_t dev) +ata_pci_probe(device_t dev) { - const char *desc = ata_pcimatch(dev); + const char *desc = ata_pci_match(dev); if (desc) { device_set_desc(dev, desc); @@ -274,17 +327,31 @@ ata_pciprobe(device_t dev) } static int -ata_pciattach(device_t dev) +ata_pci_add_child(device_t dev, int unit) { - int unit = device_get_unit(dev); - struct ata_softc *scp; - u_int32_t type; + 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; + + device_set_ivars(child, (void *)(uintptr_t) unit); + return 0; +} + +static int +ata_pci_attach(device_t dev) +{ + struct ata_pci_softc *sc = device_get_softc(dev); u_int8_t class, subclass; - u_int32_t cmd; - int32_t iobase_1, iobase_2, altiobase_1, altiobase_2; - int32_t bmaddr_1 = 0, bmaddr_2 = 0, irq1, irq2; - struct resource *irq = NULL; - int32_t lun; + u_int32_t type, cmd; + int rid; /* set up vendor-specific stuff */ type = pci_get_devid(dev); @@ -292,62 +359,32 @@ ata_pciattach(device_t dev) subclass = pci_get_subclass(dev); cmd = pci_read_config(dev, PCIR_COMMAND, 4); -#ifdef ATA_DEBUG - printf("ata-pci%d: type=%08x class=%02x subclass=%02x cmd=%08x if=%02x\n", - unit, type, class, subclass, cmd, pci_get_progif(dev)); -#endif - - if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { - iobase_1 = IO_WD1; - altiobase_1 = iobase_1 + ATA_ALTPORT; - irq1 = 14; - } - else { - iobase_1 = pci_read_config(dev, 0x10, 4) & IOMASK; - altiobase_1 = pci_read_config(dev, 0x14, 4) & IOMASK; - irq1 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff; - /* this is needed for old non-std systems */ - if (iobase_1 == IO_WD1 && irq1 == 0x00) - irq1 = 14; - } - - if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { - iobase_2 = IO_WD2; - altiobase_2 = iobase_2 + ATA_ALTPORT; - irq2 = 15; - } - else { - iobase_2 = pci_read_config(dev, 0x18, 4) & IOMASK; - altiobase_2 = pci_read_config(dev, 0x1c, 4) & IOMASK; - irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff; - /* this is needed for old non-std systems */ - if (iobase_2 == IO_WD2 && irq2 == 0x00) - irq2 = 15; - } - /* is this controller busmaster DMA capable ? */ if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { /* is busmastering support turned on ? */ if ((cmd & (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) == (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) { + /* is there a valid port range to connect to ? */ - if ((bmaddr_1 = pci_read_config(dev, 0x20, 4) & IOMASK)) - bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1; - else - printf("ata-pci%d: Busmastering DMA not configured\n", unit); + rid = 0x20; + sc->bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->bmio) + device_printf(dev, "Busmastering DMA not configured\n"); } else - printf("ata-pci%d: Busmastering DMA not enabled\n", unit); + device_printf(dev, "Busmastering DMA not enabled\n"); } else { if (type == 0x4d33105a || type == 0x4d38105a || type == 0x00041103) { /* Promise and HPT366 controllers support busmastering DMA */ - bmaddr_1 = pci_read_config(dev, 0x20, 4) & IOMASK; - bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1; + rid = 0x20; + sc->bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); } else /* we dont know this controller, no busmastering DMA */ - printf("ata-pci%d: Busmastering DMA not supported\n", unit); + device_printf(dev, "Busmastering DMA not supported\n"); } /* do extra chipset specific setups */ @@ -356,12 +393,15 @@ ata_pciattach(device_t dev) pci_write_config(dev, 0x53, (pci_read_config(dev, 0x53, 1) & ~0x01) | 0x02, 1); break; + case 0x4d38105a: /* Promise 66's need their clock changed */ - outb(bmaddr_1 + 0x11, inb(bmaddr_1 + 0x11) | 0x0a); + outb(rman_get_start(sc->bmio) + 0x11, + inb(rman_get_start(sc->bmio) + 0x11) | 0x0a); /* FALLTHROUGH */ case 0x4d33105a: /* Promise's need burst mode to be turned on */ - outb(bmaddr_1 + 0x1f, inb(bmaddr_1 + 0x1f) | 0x01); + outb(rman_get_start(sc->bmio) + 0x1f, + inb(rman_get_start(sc->bmio) + 0x1f) | 0x01); break; case 0x00041103: /* HPT366 turn of fast interrupt prediction */ @@ -388,159 +428,339 @@ ata_pciattach(device_t dev) pci_write_config(dev, 0x60, DEV_BSIZE, 2); pci_write_config(dev, 0x68, DEV_BSIZE, 2); - /* set the chiptype to the hostchip ID, makes life easier */ - if (ata_find_dev(dev, 0x05861106)) - type = 0x05861106; - if (ata_find_dev(dev, 0x05961106)) - type = 0x05961106; + /* prepare for ATA-66 on the 82C686 */ if (ata_find_dev(dev, 0x06861106)) { - type = 0x06861106; - /* prepare for ATA-66 on the 82C686 */ pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 4) | 0x070f070f, 4); } break; } - - /* now probe the addresse found for "real" ATA/ATAPI hardware */ - lun = 0; - if (iobase_1 && ata_probe(iobase_1, altiobase_1, bmaddr_1, dev, &lun)) { - int rid; - void *ih; - - scp = atadevices[lun]; - scp->chiptype = type; - rid = 0; - if (iobase_1 == IO_WD1) { -#ifdef __alpha__ - alpha_platform_setup_ide_intr(0, ataintr, scp); -#else - bus_set_resource(dev, SYS_RES_IRQ, rid, irq1, 1); - if (!(irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE))) - printf("ata_pciattach: Unable to alloc interrupt\n"); -#endif - } else { - if (!(irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE))) - printf("ata_pciattach: Unable to alloc interrupt\n"); + + ata_pci_add_child(dev, 0); + + if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV || + pci_read_config(dev, 0x18, 4) & IOMASK) + ata_pci_add_child(dev, 1); + + return bus_generic_attach(dev); +} + +static int +ata_pci_print_child(device_t dev, device_t child) +{ + struct ata_softc *scp = device_get_softc(child); + int unit = (uintptr_t) device_get_ivars(child); + int retval = 0; + + retval += bus_print_child_header(dev, child); + retval += printf(": at 0x%x", scp->ioaddr); + + if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) + retval += printf(" irq %d", 14 + unit); + + retval += bus_print_child_footer(dev, child); + + return retval; +} + +static struct resource * +ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct ata_pci_softc *sc = device_get_softc(dev); + int masterdev = pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV; + int unit = (int)device_get_ivars(child); + int myrid; + + if (type == SYS_RES_IOPORT) { + switch (*rid) { + case ATA_IOADDR_RID: + if (masterdev) { + myrid = 0; + start = (unit == 0 ? IO_WD1 : IO_WD2); + end = start + ATA_IOSIZE - 1; + count = ATA_IOSIZE; + } + else + myrid = 0x10 + 8 * unit; + break; + + case ATA_ALTIOADDR_RID: + if (masterdev) { + myrid = 0; + start = (unit == 0 ? IO_WD1 : IO_WD2) + ATA_ALTPORT; + end = start + ATA_ALTIOSIZE - 1; + count = ATA_ALTIOSIZE; + } + else + myrid = 0x14 + 8 * unit; + break; + + case ATA_BMADDR_RID: + /* the busmaster resource is shared between the two channels */ + if (sc->bmio) { + if (unit == 0) { + sc->bmio_1 = *sc->bmio; + sc->bmio_1.r_end = sc->bmio->r_start + ATA_BM_OFFSET1; + return &sc->bmio_1; + } else { + sc->bmio_2 = *sc->bmio; + sc->bmio_2.r_start = sc->bmio->r_start + ATA_BM_OFFSET1; + sc->bmio_2.r_end = sc->bmio_2.r_start + ATA_BM_OFFSET1; + return &sc->bmio_2; + } + } + break; + + default: + return 0; } - if (irq) - bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih); - printf("ata%d at 0x%04x irq %d on ata-pci%d\n", - lun, iobase_1, isa_apic_irq(irq1), unit); + + if (masterdev) + /* make the parent just pass through the allocation. */ + return BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + SYS_RES_IOPORT, &myrid, + start, end, count, flags); + else + /* we are using the parent resource directly. */ + return BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + SYS_RES_IOPORT, &myrid, + start, end, count, flags); } - lun = 1; - if (iobase_2 && ata_probe(iobase_2, altiobase_2, bmaddr_2, dev, &lun)) { - int rid; - void *ih; - - scp = atadevices[lun]; - scp->chiptype = type; - if (iobase_2 == IO_WD2) { -#ifdef __alpha__ - alpha_platform_setup_ide_intr(1, ataintr, scp); + + if (type == SYS_RES_IRQ) { + if (*rid != 0) + return 0; + + if (masterdev) { +#ifdef __i386__ + int irq = (unit == 0 ? 14 : 15); + + return BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + SYS_RES_IRQ, rid, + irq, irq, 1, flags & ~RF_SHAREABLE); #else - rid = 1; - bus_set_resource(dev, SYS_RES_IRQ, rid, irq2, 1); - if (!(irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE))) - printf("ata_pciattach: Unable to alloc interrupt\n"); + return alpha_platform_alloc_ide_intr(unit); #endif } else { - rid = 0; - if (irq1 != irq2 || irq == NULL) { - if (!(irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE))) - printf("ata_pciattach: Unable to alloc interrupt\n"); - } + /* primary and secondary channels share the same interrupt */ + sc->irqcnt++; + if (!sc->irq) + sc->irq = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + SYS_RES_IRQ, rid, 0, ~0, 1, flags); + return sc->irq; } - if (irq) - bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih); - printf("ata%d at 0x%04x irq %d on ata-pci%d\n", - lun, iobase_2, isa_apic_irq(irq2), unit); } return 0; } -int32_t -ata_find_dev(device_t dev, int32_t type) +static int +ata_pci_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) { - device_t *children, child; - int nchildren, i; + struct ata_pci_softc *sc = device_get_softc(dev); + int unit = (uintptr_t) device_get_ivars(child); + int masterdev = pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV; + int myrid = 0; + + if (type == SYS_RES_IOPORT) { + switch (rid) { + case ATA_IOADDR_RID: + if (masterdev) + myrid = 0; + else + myrid = 0x10 + 8 * unit; + break; - if (device_get_children(device_get_parent(dev), &children, &nchildren)) - return 0; + case ATA_ALTIOADDR_RID: + if (masterdev) + myrid = 0; + else + myrid = 0x14 + 8 * unit; + break; - for (i = 0; i < nchildren; i++) { - child = children[i]; + case ATA_BMADDR_RID: + return 0; - /* check that it's on the same silicon and the device we want */ - if (pci_get_slot(dev) == pci_get_slot(child) && - pci_get_vendor(child) == (type & 0xffff) && - pci_get_device(child) == ((type & 0xffff0000)>>16)) { - free(children, M_TEMP); - return 1; + default: + return ENOENT; } + + if (masterdev) + /* make the parent just pass through the allocation. */ + return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, + SYS_RES_IOPORT, myrid, r); + else + /* we are using the parent resource directly. */ + return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, + SYS_RES_IOPORT, myrid, r); } - free(children, M_TEMP); - return 0; + if (type == SYS_RES_IRQ) { + if (rid != 0) + return ENOENT; + + if (masterdev) { +#ifdef __i386__ + return BUS_RELEASE_RESOURCE(device_get_parent(dev), + child, SYS_RES_IRQ, rid, r); +#else + return alpha_platform_release_ide_intr(unit, r); +#endif + } + else { + if (--sc->irqcnt) + return 0; + + return BUS_RELEASE_RESOURCE(device_get_parent(dev), + dev, SYS_RES_IRQ, rid, r); + } + } + return EINVAL; +} + +static int +ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, + int flags, driver_intr_t *intr, void *arg, + void **cookiep) +{ + if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { +#ifdef __i386__ + return BUS_SETUP_INTR(device_get_parent(dev), child, irq, + flags, intr, arg, cookiep); +#else + return alpha_platform_setup_ide_intr(irq, intr, arg, cookiep); +#endif + } + else + return BUS_SETUP_INTR(device_get_parent(dev), dev, irq, + flags, intr, arg, cookiep); +} + +static int +ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) +{ + if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { +#ifdef __i386__ + return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie); +#else + return alpha_platform_teardown_ide_intr(irq, cookie); +#endif + } + else + return BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie); } static device_method_t ata_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ata_pciprobe), - DEVMETHOD(device_attach, ata_pciattach), + /* device interface */ + DEVMETHOD(device_probe, ata_pci_probe), + DEVMETHOD(device_attach, ata_pci_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* bus methods */ + DEVMETHOD(bus_print_child, ata_pci_print_child), + DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), + DEVMETHOD(bus_release_resource, ata_pci_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), + DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), { 0, 0 } }; static driver_t ata_pci_driver = { - "ata-pci", + "atapci", ata_pci_methods, - sizeof(int), + sizeof(struct ata_pci_softc), }; -DRIVER_MODULE(ata, pci, ata_pci_driver, ata_devclass, 0, 0); -#endif +DRIVER_MODULE(atapci, pci, ata_pci_driver, ata_devclass, 0, 0); -static int32_t -ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr, - device_t dev, int32_t *unit) +static int +ata_pcisub_probe(device_t dev) { - struct ata_softc *scp; - int32_t lun, mask = 0; - u_int8_t status0, status1; + struct ata_softc *scp = device_get_softc(dev); + + /* kids of pci ata chipsets has their physical unit number in ivars */ + scp->unit = (uintptr_t) device_get_ivars(dev); + + /* set the chiptype to the hostchip ID, makes life easier */ + if (ata_find_dev(device_get_parent(dev), 0x05861106)) + scp->chiptype = 0x05861106; + else if (ata_find_dev(device_get_parent(dev), 0x05961106)) + scp->chiptype = 0x05961106; + else if (ata_find_dev(device_get_parent(dev), 0x06861106)) + scp->chiptype = 0x06861106; + else + scp->chiptype = pci_get_devid(device_get_parent(dev)); + return ata_probe(dev); +} - if (atanlun > MAXATA) { - printf("ata: unit out of range(%d)\n", atanlun); - return 0; - } +static device_method_t ata_pcisub_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, ata_pcisub_probe), + DEVMETHOD(device_attach, ata_attach), + DEVMETHOD(device_detach, ata_detach), + DEVMETHOD(device_resume, ata_resume), + { 0, 0 } +}; - /* check if this is located at one of the std addresses */ - if (ioaddr == IO_WD1) - lun = 0; - else if (ioaddr == IO_WD2) - lun = 1; - else - lun = atanlun++; +static driver_t ata_pcisub_driver = { + "ata", + ata_pcisub_methods, + sizeof(struct ata_softc), +}; - if ((scp = atadevices[lun])) { - ata_printf(scp, -1, "unit already attached\n"); - return 0; - } - scp = malloc(sizeof(struct ata_softc), M_ATA, M_NOWAIT); - if (scp == NULL) { - ata_printf(scp, -1, "failed to allocate driver storage\n"); - return 0; - } - bzero(scp, sizeof(struct ata_softc)); +DRIVER_MODULE(ata, atapci, ata_pcisub_driver, ata_pci_devclass, 0, 0); +#endif + +static int +ata_probe(device_t dev) +{ + struct ata_softc *scp = device_get_softc(dev); + struct resource *io = 0; + struct resource *altio = 0; + struct resource *bmio = 0; + int rid; + int32_t ioaddr, altioaddr, bmaddr; + int32_t mask = 0; + u_int8_t status0, status1; + + if (!scp || scp->flags & ATA_ATTACHED) + return ENXIO; + /* initialize the softc basics */ + scp->active = ATA_IDLE; + scp->dev = dev; + scp->devices = 0; + + rid = ATA_IOADDR_RID; + io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 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_BMADDR_RID; + bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + bmaddr = bmio ? rman_get_start(bmio) : 0; + + /* store the IO resources for eventual later release */ + scp->r_io = io; + scp->r_altio = altio; + scp->r_bmio = bmio; + + /* store the physical IO addresse for easy access */ scp->ioaddr = ioaddr; scp->altioaddr = altioaddr; scp->bmaddr = bmaddr; - scp->lun = lun; - scp->unit = *unit; - scp->active = ATA_IDLE; if (bootverbose) ata_printf(scp, -1, "iobase=0x%04x altiobase=0x%04x bmaddr=0x%04x\n", @@ -553,26 +773,23 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr, outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); DELAY(1); status1 = inb(scp->ioaddr + ATA_STATUS); - if ((status0 & 0xf8) != 0xf8) + if ((status0 & 0xf8) != 0xf8 && status0 != 0xa5) mask |= 0x01; - if ((status1 & 0xf8) != 0xf8) + if ((status1 & 0xf8) != 0xf8 && status1 != 0xa5) mask |= 0x02; if (bootverbose) ata_printf(scp, -1, "mask=%02x status0=%02x status1=%02x\n", mask, status0, status1); - if (!mask) { - free(scp, M_DEVBUF); - return 0; - } + if (!mask) + goto failure; + ata_reset(scp, &mask); - if (!mask) { - free(scp, M_DEVBUF); - return 0; - } + if (!mask) + goto failure; + /* - * OK, we have at least one device on the chain, - * check for ATAPI signatures, if none check if its - * a good old ATA device. + * OK, we have at least one device on the chain, check for ATAPI + * signatures, if none check if its a good old ATA device. */ outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER)); DELAY(1); @@ -609,92 +826,122 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr, if (bootverbose) ata_printf(scp, -1, "devices = 0x%x\n", scp->devices); if (!scp->devices) { - free(scp, M_DEVBUF); - return 0; + goto failure; } TAILQ_INIT(&scp->ata_queue); TAILQ_INIT(&scp->atapi_queue); - *unit = scp->lun; - scp->dev = dev; - atadevices[scp->lun] = scp; - - /* register callback for when interrupts are enabled */ - if (!ata_attach_hook) { - if (!(ata_attach_hook = (struct intr_config_hook *) - malloc(sizeof(struct intr_config_hook), - M_TEMP, M_NOWAIT))) { - ata_printf(scp, -1, "ERROR malloc attach_hook failed\n"); - return 0; - } - bzero(ata_attach_hook, sizeof(struct intr_config_hook)); - - ata_attach_hook->ich_func = ata_attach; - if (config_intrhook_establish(ata_attach_hook) != 0) { - ata_printf(scp, -1, "config_intrhook_establish failed\n"); - free(ata_attach_hook, M_TEMP); - } - } -#if NAPM > 0 - scp->resume_hook.ah_fun = (void *)ata_reinit; - scp->resume_hook.ah_arg = scp; - scp->resume_hook.ah_name = "ATA driver"; - scp->resume_hook.ah_order = APM_MID_ORDER; - apm_hook_establish(APM_HOOK_RESUME, &scp->resume_hook); -#endif - return ATA_IOSIZE; + return 0; + +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); + if (bmio) + bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, bmio); + if (bootverbose) + ata_printf(scp, -1, "probe allocation failed\n"); + return ENXIO; } -void -ata_attach(void *dummy) +static int +ata_attach(device_t dev) { - int32_t ctlr; + struct ata_softc *scp = device_get_softc(dev); + int rid = 0; + void *ih; + + if (!scp || scp->flags & ATA_ATTACHED) + return ENXIO; + + scp->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (!scp->r_irq) { + 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); /* - * run through atadevices[] and look for real ATA & ATAPI devices - * using the hints we found in the early probe to avoid probing - * of non-exsistent devices and thereby long delays + * do not attach devices if we are in early boot, this is done later + * when interrupts are enabled by a hook into the boot process. + * otherwise attach what the probe has found in scp->devices. */ - for (ctlr=0; ctlr<MAXATA; ctlr++) { - if (!atadevices[ctlr]) continue; - if (atadevices[ctlr]->devices & ATA_ATA_SLAVE) - if (ata_getparam(atadevices[ctlr], ATA_SLAVE, ATA_C_ATA_IDENTIFY)) - atadevices[ctlr]->devices &= ~ATA_ATA_SLAVE; - if (atadevices[ctlr]->devices & ATA_ATAPI_SLAVE) - if (ata_getparam(atadevices[ctlr], ATA_SLAVE, ATA_C_ATAPI_IDENTIFY)) - atadevices[ctlr]->devices &= ~ATA_ATAPI_SLAVE; - if (atadevices[ctlr]->devices & ATA_ATA_MASTER) - if (ata_getparam(atadevices[ctlr], ATA_MASTER, ATA_C_ATA_IDENTIFY)) - atadevices[ctlr]->devices &= ~ATA_ATA_MASTER; - if (atadevices[ctlr]->devices & ATA_ATAPI_MASTER) - if (ata_getparam(atadevices[ctlr], ATA_MASTER,ATA_C_ATAPI_IDENTIFY)) - atadevices[ctlr]->devices &= ~ATA_ATAPI_MASTER; + if (!ata_delayed_attach) { + if (scp->devices & ATA_ATA_SLAVE) + if (ata_getparam(scp, ATA_SLAVE, ATA_C_ATA_IDENTIFY)) + scp->devices &= ~ATA_ATA_SLAVE; + if (scp->devices & ATA_ATAPI_SLAVE) + if (ata_getparam(scp, ATA_SLAVE, ATA_C_ATAPI_IDENTIFY)) + scp->devices &= ~ATA_ATAPI_SLAVE; + if (scp->devices & ATA_ATA_MASTER) + if (ata_getparam(scp, ATA_MASTER, ATA_C_ATA_IDENTIFY)) + scp->devices &= ~ATA_ATA_MASTER; + if (scp->devices & ATA_ATAPI_MASTER) + if (ata_getparam(scp, ATA_MASTER,ATA_C_ATAPI_IDENTIFY)) + scp->devices &= ~ATA_ATAPI_MASTER; +#if NATADISK > 0 + if (scp->devices & ATA_ATA_MASTER) + ad_attach(scp, ATA_MASTER); + if (scp->devices & ATA_ATA_SLAVE) + ad_attach(scp, ATA_SLAVE); +#endif +#if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0 + if (scp->devices & ATA_ATAPI_MASTER) + atapi_attach(scp, ATA_MASTER); + if (scp->devices & ATA_ATAPI_SLAVE) + atapi_attach(scp, ATA_SLAVE); +#endif } + scp->flags |= ATA_ATTACHED; + return 0; +} + +static int +ata_detach(device_t dev) +{ + struct ata_softc *scp = device_get_softc(dev); + + if (!scp || !(scp->flags & ATA_ATTACHED)) + return ENXIO; #if NATADISK > 0 - /* now we know whats there, do the real attach, first the ATA disks */ - for (ctlr=0; ctlr<MAXATA; ctlr++) { - if (!atadevices[ctlr]) continue; - if (atadevices[ctlr]->devices & ATA_ATA_MASTER) - ad_attach(atadevices[ctlr], ATA_MASTER); - if (atadevices[ctlr]->devices & ATA_ATA_SLAVE) - ad_attach(atadevices[ctlr], ATA_SLAVE); - } + if (scp->devices & ATA_ATA_MASTER) + ad_detach(scp, ATA_MASTER); + if (scp->devices & ATA_ATA_SLAVE) + ad_detach(scp, ATA_SLAVE); #endif #if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0 - /* then the atapi devices */ - for (ctlr=0; ctlr<MAXATA; ctlr++) { - if (!atadevices[ctlr]) continue; - if (atadevices[ctlr]->devices & ATA_ATAPI_MASTER) - atapi_attach(atadevices[ctlr], ATA_MASTER); - if (atadevices[ctlr]->devices & ATA_ATAPI_SLAVE) - atapi_attach(atadevices[ctlr], ATA_SLAVE); - } + if (scp->devices & ATA_ATAPI_MASTER) + atapi_detach(scp, ATA_MASTER); + if (scp->devices & ATA_ATAPI_SLAVE) + atapi_detach(scp, ATA_SLAVE); #endif - if (ata_attach_hook) { - config_intrhook_disestablish(ata_attach_hook); - free(ata_attach_hook, M_ATA); - ata_attach_hook = NULL; + if (scp->dev_param[ATA_DEV(ATA_MASTER)]) { + free(scp->dev_param[ATA_DEV(ATA_MASTER)], M_ATA); + scp->dev_param[ATA_DEV(ATA_MASTER)] = NULL; } + if (scp->dev_param[ATA_DEV(ATA_SLAVE)]) { + free(scp->dev_param[ATA_DEV(ATA_SLAVE)], M_ATA); + scp->dev_param[ATA_DEV(ATA_SLAVE)] = NULL; + } + scp->mode[ATA_DEV(ATA_MASTER)] = ATA_PIO; + scp->mode[ATA_DEV(ATA_SLAVE)] = ATA_PIO; + 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); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, scp->r_io); + scp->flags &= ~ATA_ATTACHED; + return 0; +} + +static int +ata_resume(device_t dev) +{ + struct ata_softc *scp = device_get_softc(dev); + + ata_reinit(scp); + return 0; } static int32_t @@ -708,7 +955,7 @@ ata_getparam(struct ata_softc *scp, int32_t device, u_int8_t command) outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device); DELAY(1); - /* enable interrupts */ + /* enable interrupt */ outb(scp->altioaddr, ATA_A_4BIT); DELAY(1); @@ -719,7 +966,7 @@ ata_getparam(struct ata_softc *scp, int32_t device, u_int8_t command) return -1; } if (retry++ > 4) { - ata_printf(scp, device, "drive wont come ready after identify\n"); + ata_printf(scp, device, "identify retries exceeded\n"); return -1; } } while (ata_wait(scp, device, @@ -729,7 +976,7 @@ ata_getparam(struct ata_softc *scp, int32_t device, u_int8_t command) insw(scp->ioaddr + ATA_DATA, buffer, sizeof(buffer)/sizeof(int16_t)); ata_parm = malloc(sizeof(struct ata_params), M_ATA, M_NOWAIT); if (!ata_parm) { - ata_printf(scp, device, "malloc for ata_param failed\n"); + ata_printf(scp, device, "malloc for identify data failed\n"); return -1; } bcopy(buffer, ata_parm, sizeof(struct ata_params)); @@ -746,15 +993,72 @@ ata_getparam(struct ata_softc *scp, int32_t device, u_int8_t command) return 0; } +static void +ata_boot_attach(void) +{ + struct ata_softc *scp; + int32_t ctlr; + + /* + * run through all ata devices and look for real ATA & ATAPI devices + * using the hints we found in the early probe, this avoids some of + * the delays probing of non-exsistent devices can cause. + */ + for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { + if (!(scp = devclass_get_softc(ata_devclass, ctlr))) + continue; + if (scp->devices & ATA_ATA_SLAVE) + if (ata_getparam(scp, ATA_SLAVE, ATA_C_ATA_IDENTIFY)) + scp->devices &= ~ATA_ATA_SLAVE; + if (scp->devices & ATA_ATAPI_SLAVE) + if (ata_getparam(scp, ATA_SLAVE, ATA_C_ATAPI_IDENTIFY)) + scp->devices &= ~ATA_ATAPI_SLAVE; + if (scp->devices & ATA_ATA_MASTER) + if (ata_getparam(scp, ATA_MASTER, ATA_C_ATA_IDENTIFY)) + scp->devices &= ~ATA_ATA_MASTER; + if (scp->devices & ATA_ATAPI_MASTER) + if (ata_getparam(scp, ATA_MASTER,ATA_C_ATAPI_IDENTIFY)) + scp->devices &= ~ATA_ATAPI_MASTER; + } + +#if NATADISK > 0 + /* now we know whats there, do the real attach, first the ATA disks */ + for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { + if (!(scp = devclass_get_softc(ata_devclass, ctlr))) + continue; + if (scp->devices & ATA_ATA_MASTER) + ad_attach(scp, ATA_MASTER); + if (scp->devices & ATA_ATA_SLAVE) + ad_attach(scp, ATA_SLAVE); + } +#endif +#if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0 + /* then the atapi devices */ + for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { + if (!(scp = devclass_get_softc(ata_devclass, ctlr))) + continue; + if (scp->devices & ATA_ATAPI_MASTER) + atapi_attach(scp, ATA_MASTER); + if (scp->devices & ATA_ATAPI_SLAVE) + atapi_attach(scp, ATA_SLAVE); + } +#endif + if (ata_delayed_attach) { + config_intrhook_disestablish(ata_delayed_attach); + free(ata_delayed_attach, M_ATA); + ata_delayed_attach = NULL; + } +} + static void -ataintr(void *data) +ata_intr(void *data) { struct ata_softc *scp = (struct ata_softc *)data; u_int8_t dmastat; /* * since we might share the IRQ with another device, and in some - * case with our twin channel, we only want to process interrupts + * cases with our twin channel, we only want to process interrupts * that we know this channel generated. */ switch (scp->chiptype) { @@ -767,9 +1071,13 @@ ataintr(void *data) case 0x4d33105a: /* Promise 33's */ case 0x4d38105a: /* Promise 66's */ - if (!(inl((pci_read_config(scp->dev, 0x20, 4) & IOMASK) + 0x1c) & + { + struct ata_pci_softc *sc=device_get_softc(device_get_parent(scp->dev)); + + if (!(inl(rman_get_start(sc->bmio) + 0x1c) & ((scp->unit) ? 0x00004000 : 0x00000400))) return; + } /* FALLTHROUGH */ #endif default: @@ -904,7 +1212,7 @@ void ata_reset(struct ata_softc *scp, int32_t *mask) { int32_t timeout; - int8_t status0, status1; + u_int8_t status0 = 0, status1 = 0; /* reset channel */ outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER); @@ -954,29 +1262,31 @@ ata_reinit(struct ata_softc *scp) scp->active = ATA_REINITING; scp->running = NULL; - ata_printf(scp, -1, "resetting devices .. "); if (scp->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) mask |= 0x01; if (scp->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) mask |= 0x02; - omask = mask; - ata_reset(scp, &mask); - if (omask != mask) - printf(" device dissapeared! %d ", omask & ~mask); + if (mask) { + omask = mask; + ata_printf(scp, -1, "resetting devices .. "); + ata_reset(scp, &mask); + if (omask != mask) + printf(" device dissapeared! %d ", omask & ~mask); #if NATADISK > 0 - if (scp->devices & (ATA_ATA_MASTER) && scp->dev_softc[0]) - ad_reinit((struct ad_softc *)scp->dev_softc[0]); - if (scp->devices & (ATA_ATA_SLAVE) && scp->dev_softc[1]) - ad_reinit((struct ad_softc *)scp->dev_softc[1]); + if (scp->devices & (ATA_ATA_MASTER) && scp->dev_softc[0]) + ad_reinit((struct ad_softc *)scp->dev_softc[0]); + if (scp->devices & (ATA_ATA_SLAVE) && scp->dev_softc[1]) + ad_reinit((struct ad_softc *)scp->dev_softc[1]); #endif #if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0 - if (scp->devices & (ATA_ATAPI_MASTER) && scp->dev_softc[0]) - atapi_reinit((struct atapi_softc *)scp->dev_softc[0]); - if (scp->devices & (ATA_ATAPI_SLAVE) && scp->dev_softc[1]) - atapi_reinit((struct atapi_softc *)scp->dev_softc[1]); + if (scp->devices & (ATA_ATAPI_MASTER) && scp->dev_softc[0]) + atapi_reinit((struct atapi_softc *)scp->dev_softc[0]); + if (scp->devices & (ATA_ATAPI_SLAVE) && scp->dev_softc[1]) + atapi_reinit((struct atapi_softc *)scp->dev_softc[1]); #endif - printf("done\n"); + printf("done\n"); + } scp->active = ATA_IDLE; ata_start(scp); return 0; @@ -1103,6 +1413,38 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command, return 0; } +int +ata_printf(struct ata_softc *scp, int32_t device, const char * fmt, ...) +{ + va_list ap; + int ret; + + if (device == -1) + ret = printf("ata%d: ", device_get_unit(scp->dev)); + else + ret = printf("ata%d-%s: ", device_get_unit(scp->dev), + (device == ATA_MASTER) ? "master" : "slave"); + va_start(ap, fmt); + ret += vprintf(fmt, ap); + va_end(ap); + return ret; +} + +int +ata_get_lun(u_int32_t *map) +{ + int lun = ffs(~*map) - 1; + + *map |= (1 << lun); + return lun; +} + +void +ata_free_lun(u_int32_t *map, int lun) +{ + *map &= ~(1 << lun); +} + int8_t * ata_mode2str(int32_t mode) { @@ -1134,6 +1476,54 @@ ata_pio2mode(int32_t pio) } } +int +ata_pmode(struct ata_params *ap) +{ + if (ap->atavalid & ATA_FLAG_64_70) { + if (ap->apiomodes & 2) + return 4; + if (ap->apiomodes & 1) + return 3; + } + if (ap->opiomode == 2) + return 2; + if (ap->opiomode == 1) + return 1; + if (ap->opiomode == 0) + return 0; + return -1; +} + +int +ata_wmode(struct ata_params *ap) +{ + if (ap->wdmamodes & 4) + return 2; + if (ap->wdmamodes & 2) + return 1; + if (ap->wdmamodes & 1) + return 0; + return -1; +} + +int +ata_umode(struct ata_params *ap) +{ + if (ap->atavalid & ATA_FLAG_88) { + if (ap->udmamodes & 0x10) + return (ap->cblid ? 4 : 2); + if (ap->udmamodes & 0x08) + return (ap->cblid ? 3 : 2); + if (ap->udmamodes & 0x04) + return 2; + if (ap->udmamodes & 0x02) + return 1; + if (ap->udmamodes & 0x01) + return 0; + } + return -1; +} + static int8_t * active2str(int32_t active) { @@ -1162,60 +1552,25 @@ active2str(int32_t active) } } -int32_t -ata_pmode(struct ata_params *ap) -{ - if (ap->atavalid & ATA_FLAG_64_70) { - if (ap->apiomodes & 2) return 4; - if (ap->apiomodes & 1) return 3; - } - if (ap->opiomode == 2) return 2; - if (ap->opiomode == 1) return 1; - if (ap->opiomode == 0) return 0; - return -1; -} - -int32_t -ata_wmode(struct ata_params *ap) -{ - if (ap->wdmamodes & 4) return 2; - if (ap->wdmamodes & 2) return 1; - if (ap->wdmamodes & 1) return 0; - return -1; -} - -int32_t -ata_umode(struct ata_params *ap) -{ - if (ap->atavalid & ATA_FLAG_88) { - if (ap->udmamodes & 0x10) return (ap->cblid ? 4 : 2); - if (ap->udmamodes & 0x08) return (ap->cblid ? 3 : 2); - if (ap->udmamodes & 0x04) return 2; - if (ap->udmamodes & 0x02) return 1; - if (ap->udmamodes & 0x01) return 0; - } - return -1; -} - static void bswap(int8_t *buf, int32_t len) { - u_int16_t *p = (u_int16_t*)(buf + len); + u_int16_t *ptr = (u_int16_t*)(buf + len); - while (--p >= (u_int16_t*)buf) - *p = ntohs(*p); + while (--ptr >= (u_int16_t*)buf) + *ptr = ntohs(*ptr); } static void btrim(int8_t *buf, int32_t len) { - int8_t *p; + int8_t *ptr; - for (p = buf; p < buf+len; ++p) - if (!*p) - *p = ' '; - for (p = buf + len - 1; p >= buf && *p == ' '; --p) - *p = 0; + for (ptr = buf; ptr < buf+len; ++ptr) + if (!*ptr) + *ptr = ' '; + for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr) + *ptr = 0; } static void @@ -1241,25 +1596,6 @@ bpack(int8_t *src, int8_t *dst, int32_t len) dst[j] = 0x00; } -int32_t -ata_printf(struct ata_softc *scp, int32_t device, const char * fmt, ...) -{ - va_list ap; - int ret; - - if (device == -1) - ret = printf("ata%d: ", scp->lun); - else - ret = printf("ata%d-%s: ", scp->lun, - (device == ATA_MASTER) ? "master" : "slave"); - va_start(ap, fmt); - ret += vprintf(fmt, ap); - va_end(ap); - return ret; -} - -static char ata_conf[1024]; - static void ata_change_mode(struct ata_softc *scp, int32_t device, int32_t mode) { @@ -1279,17 +1615,22 @@ ata_change_mode(struct ata_softc *scp, int32_t device, int32_t mode) static int sysctl_hw_ata SYSCTL_HANDLER_ARGS { - int error, i; + struct ata_softc *scp; + int ctlr, error, i; /* readout internal state */ bzero(ata_conf, sizeof(ata_conf)); - for (i = 0; i < (atanlun << 1); i++) { - if (!atadevices[i >> 1] || !atadevices[ i >> 1]->dev_softc[i & 1]) - strcat(ata_conf, "---,"); - else if (atadevices[i >> 1]->mode[i & 1] >= ATA_DMA) - strcat(ata_conf, "dma,"); - else - strcat(ata_conf, "pio,"); + for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { + if (!(scp = devclass_get_softc(ata_devclass, ctlr))) + continue; + for (i = 0; i < 2; i++) { + if (!scp->dev_softc[i]) + strcat(ata_conf, "---,"); + else if (scp->mode[i] >= ATA_DMA) + strcat(ata_conf, "dma,"); + else + strcat(ata_conf, "pio,"); + } } error = sysctl_handle_string(oidp, ata_conf, sizeof(ata_conf), req); if (error == 0 && req->newptr != NULL) { @@ -1299,28 +1640,44 @@ sysctl_hw_ata SYSCTL_HANDLER_ARGS i = 0; while (*ptr) { if (!strncmp(ptr, "pio", 3) || !strncmp(ptr, "PIO", 3)) { - if (atadevices[i >> 1] && - atadevices[i >> 1]->dev_softc[i & 1] && - atadevices[i >>1 ]->mode[i & 1] >= ATA_DMA) - ata_change_mode(atadevices[i >> 1], - (i & 1) ? ATA_SLAVE : ATA_MASTER, ATA_PIO); + if ((scp = devclass_get_softc(ata_devclass, i >> 1)) && + scp->dev_softc[i & 1] && scp->mode[i & 1] >= ATA_DMA) + ata_change_mode(scp, (i & 1)?ATA_SLAVE:ATA_MASTER, ATA_PIO); } else if (!strncmp(ptr, "dma", 3) || !strncmp(ptr, "DMA", 3)) { - if (atadevices[i >> 1] && - atadevices[i >> 1]->dev_softc[i & 1] && - atadevices[i >> 1]->mode[i & 1] < ATA_DMA) - ata_change_mode(atadevices[i >> 1], - (i & 1) ? ATA_SLAVE : ATA_MASTER, ATA_DMA); + if ((scp = devclass_get_softc(ata_devclass, i >> 1)) && + scp->dev_softc[i & 1] && scp->mode[i & 1] < ATA_DMA) + ata_change_mode(scp, (i & 1)?ATA_SLAVE:ATA_MASTER, ATA_DMA); } else if (strncmp(ptr, "---", 3)) break; ptr+=3; - if (*ptr++ != ',' || ++i > (atanlun << 1)) + if (*ptr++ != ',' || + ++i > (devclass_get_maxunit(ata_devclass) << 1)) break; } } return error; } - SYSCTL_PROC(_hw, OID_AUTO, atamodes, CTLTYPE_STRING | CTLFLAG_RW, 0, sizeof(ata_conf), sysctl_hw_ata, "A", ""); + +static void +ata_init(void) +{ + /* register boot attach to be run when interrupts are enabled */ + if (!(ata_delayed_attach = (struct intr_config_hook *) + malloc(sizeof(struct intr_config_hook), + M_TEMP, M_NOWAIT))) { + printf("ata: malloc of delayed attach hook failed\n"); + return; + } + bzero(ata_delayed_attach, sizeof(struct intr_config_hook)); + + ata_delayed_attach->ich_func = (void*)ata_boot_attach; + if (config_intrhook_establish(ata_delayed_attach) != 0) { + printf("ata: config_intrhook_establish failed\n"); + free(ata_delayed_attach, M_TEMP); + } +} +SYSINIT(atadev, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_init, NULL) diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 009827e..317926f 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -86,11 +86,14 @@ #define ATA_S_READY 0x40 /* drive ready */ #define ATA_S_BUSY 0x80 /* busy */ -#define ATA_ALTPORT 0x206 /* alternate Status register */ +#define ATA_ALTPORT 0x206 /* alternate status register */ +#define ATA_ALTPORT_PCCARD 0x8 /* ditto on PCCARD devices */ #define ATA_A_IDS 0x02 /* disable interrupts */ #define ATA_A_RESET 0x04 /* RESET controller */ #define ATA_A_4BIT 0x08 /* 4 head bits */ +#define ATA_ALTIOSIZE 0x01 + /* misc defines */ #define ATA_MASTER 0x00 #define ATA_SLAVE 0x10 @@ -121,6 +124,8 @@ #define ATA_BMDTP_PORT 0x04 +#define ATA_BMIOSIZE 0x20 + /* structure for holding DMA address data */ struct ata_dmaentry { u_int32_t base; @@ -249,12 +254,15 @@ struct ata_params { /* structure describing an ATA device */ struct ata_softc { - int32_t unit; /* unit on this controller */ - int32_t lun; /* logical unit # */ struct device *dev; /* device handle */ - int32_t ioaddr; /* port addr */ - int32_t altioaddr; /* alternate port addr */ - int32_t bmaddr; /* bus master DMA port */ + int32_t unit; /* unit on this controller */ + struct resource *r_io; /* io addr resource handle */ + struct resource *r_altio; /* altio addr resource handle */ + struct resource *r_bmio; /* bmio addr resource handle */ + struct resource *r_irq; /* interrupt of this channel */ + int32_t ioaddr; /* physical port addr */ + int32_t altioaddr; /* physical alt port addr */ + int32_t bmaddr; /* physical bus master port */ int32_t chiptype; /* pciid of controller chip */ struct ata_params *dev_param[2]; /* ptr to devices params */ void *dev_softc[2]; /* ptr to devices softc's */ @@ -275,6 +283,7 @@ struct ata_softc { #define ATA_DMA_ACTIVE 0x01 #define ATA_ATAPI_DMA_RO 0x02 #define ATA_USE_16BIT 0x04 +#define ATA_ATTACHED 0x08 int32_t devices; /* what is present */ #define ATA_ATA_MASTER 0x01 @@ -297,15 +306,10 @@ struct ata_softc { TAILQ_HEAD(, ad_request) ata_queue; /* head of ATA queue */ TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */ void *running; /* currently running request */ -#if NAPM > 0 - struct apmhook resume_hook; /* hook for apm */ -#endif - }; -/* array to hold all ata softc's */ -extern struct ata_softc *atadevices[]; -#define MAXATA 16 +/* To convert unit numbers to devices */ +extern devclass_t ata_devclass; /* public prototypes */ void ata_start(struct ata_softc *); @@ -313,15 +317,17 @@ void ata_reset(struct ata_softc *, int32_t *); int32_t ata_reinit(struct ata_softc *); int32_t ata_wait(struct ata_softc *, int32_t, u_int8_t); int32_t ata_command(struct ata_softc *, int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int32_t); +int ata_printf(struct ata_softc *, int32_t, const char *, ...) __printflike(3, 4); +int ata_get_lun(u_int32_t *); +void ata_free_lun(u_int32_t *, int); +int8_t *ata_mode2str(int32_t); +int8_t ata_pio2mode(int32_t); +int ata_pmode(struct ata_params *); +int ata_wmode(struct ata_params *); +int ata_umode(struct ata_params *); + void ata_dmainit(struct ata_softc *, int32_t, int32_t, int32_t, int32_t); int32_t ata_dmasetup(struct ata_softc *, int32_t, int8_t *, int32_t, int32_t); void ata_dmastart(struct ata_softc *); int32_t ata_dmastatus(struct ata_softc *); int32_t ata_dmadone(struct ata_softc *); -int32_t ata_pmode(struct ata_params *); -int32_t ata_wmode(struct ata_params *); -int32_t ata_umode(struct ata_params *); -int8_t *ata_mode2str(int32_t); -int8_t ata_pio2mode(int32_t); -int32_t ata_find_dev(device_t, int32_t); -int32_t ata_printf(struct ata_softc *, int32_t, const char *, ...) __printflike(3, 4); diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 0629442..301fe6b 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -48,16 +48,13 @@ #include <vm/vm_object.h> #include <machine/clock.h> #include <machine/md_var.h> -#if NAPM > 0 -#include <machine/apm_bios.h> -#endif #include <dev/ata/ata-all.h> #include <dev/ata/ata-disk.h> +/* device structures */ static d_open_t adopen; static d_strategy_t adstrategy; static d_dump_t addump; - static struct cdevsw ad_cdevsw = { /* open */ adopen, /* close */ nullclose, @@ -99,6 +96,7 @@ static void ad_timeout(struct ad_request *); static int32_t ad_version(u_int16_t); /* internal vars */ +static u_int32_t adp_lun_map = 0; MALLOC_DEFINE(M_AD, "AD driver", "ATA disk driver"); /* defines */ @@ -109,22 +107,23 @@ void ad_attach(struct ata_softc *scp, int32_t device) { struct ad_softc *adp; - static int32_t adnlun = 0; - dev_t dev1; + dev_t dev; int32_t secsperint; -#ifdef ATA_STATIC_ID - adnlun = (scp->lun << 1) + ATA_DEV(device); -#endif + if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT))) { - printf("ad%d: failed to allocate driver storage\n", adnlun); + ata_printf(scp, device, "failed to allocate driver storage\n"); return; } bzero(adp, sizeof(struct ad_softc)); scp->dev_softc[ATA_DEV(device)] = adp; adp->controller = scp; adp->unit = device; - adp->lun = adnlun++; +#ifdef ATA_STATIC_ID + adp->lun = (device_get_unit(scp->dev) << 1) + ATA_DEV(device); +#else + adp->lun = ata_get_lun(&adp_lun_map); +#endif adp->heads = AD_PARAM->heads; adp->sectors = AD_PARAM->sectors; adp->total_secs = AD_PARAM->cylinders * adp->heads * adp->sectors; @@ -162,7 +161,7 @@ ad_attach(struct ata_softc *scp, int32_t device) if (bootverbose) { printf("ad%d: <%.40s/%.8s> ATA-%d disk at ata%d as %s\n", adp->lun, AD_PARAM->model, AD_PARAM->revision, - ad_version(AD_PARAM->versmajor), scp->lun, + ad_version(AD_PARAM->versmajor), device_get_unit(scp->dev), (adp->unit == ATA_MASTER) ? "master" : "slave"); printf("ad%d: %luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n", @@ -184,7 +183,7 @@ ad_attach(struct ata_softc *scp, int32_t device) printf("ad%d: %luMB <%.40s> [%d/%d/%d] at ata%d-%s using %s\n", adp->lun, adp->total_secs / ((1024L * 1024L) / DEV_BSIZE), AD_PARAM->model, adp->total_secs / (adp->heads * adp->sectors), - adp->heads, adp->sectors, scp->lun, + adp->heads, adp->sectors, device_get_unit(scp->dev), (adp->unit == ATA_MASTER) ? "master" : "slave", ata_mode2str(adp->controller->mode[ATA_DEV(adp->unit)])); @@ -193,18 +192,34 @@ ad_attach(struct ata_softc *scp, int32_t device) DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE, DEVSTAT_PRIORITY_DISK); - dev1 = disk_create(adp->lun, &adp->disk, 0, &ad_cdevsw, &addisk_cdevsw); - dev1->si_drv1 = adp; - dev1->si_iosize_max = 256 * DEV_BSIZE; + dev = disk_create(adp->lun, &adp->disk, 0, &ad_cdevsw, &addisk_cdevsw); + dev->si_drv1 = adp; + dev->si_iosize_max = 256 * DEV_BSIZE; + adp->dev1 = dev; - dev1 = disk_create(adp->lun, &adp->disk, 0, &fakewd_cdevsw, + dev = disk_create(adp->lun, &adp->disk, 0, &fakewd_cdevsw, &fakewddisk_cdevsw); - dev1->si_drv1 = adp; - dev1->si_iosize_max = 256 * DEV_BSIZE; + dev->si_drv1 = adp; + dev->si_iosize_max = 256 * DEV_BSIZE; + adp->dev2 = dev; bufq_init(&adp->queue); } +void +ad_detach(struct ata_softc *scp, int32_t device) +{ + struct ad_softc *adp = scp->dev_softc[ATA_DEV(device)]; + + disk_invalidate(&adp->disk); + disk_destroy(adp->dev1); + disk_destroy(adp->dev2); + devstat_remove_entry(&adp->stats); + ata_free_lun(&adp_lun_map, adp->lun); + free(adp, M_AD); + scp->dev_softc[ATA_DEV(device)] = NULL; +} + static int adopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { @@ -300,7 +315,7 @@ addump(dev_t dev) } if (ata_wait(adp->controller, adp->unit, ATA_S_READY | ATA_S_DSC) < 0) - printf("addump: timeout waiting for final ready\n"); + printf("ad%d: timeout waiting for final ready\n", adp->lun); return 0; } @@ -315,7 +330,7 @@ ad_start(struct ad_softc *adp) return; if (!(request = malloc(sizeof(struct ad_request), M_AD, M_NOWAIT))) { - printf("ad_start: out of memory\n"); + printf("ad%d: out of memory in start\n", adp->lun); return; } @@ -365,7 +380,8 @@ ad_transfer(struct ad_request *request) count = howmany(request->bytecount, DEV_BSIZE); if (count > 256) { count = 256; - printf("ad%d: count=%d not supported\n", adp->lun, count); + printf("ad%d: count %d size transfers not supported\n", + adp->lun, count); } if (adp->flags & AD_F_LBA_ENABLED) { @@ -406,7 +422,7 @@ ad_transfer(struct ad_request *request) if (ata_command(adp->controller, adp->unit, cmd, cylinder, head, sector, count, 0, ATA_IMMEDIATE)) { - printf("ad%d: wouldn't take transfer command\n", adp->lun); + printf("ad%d: error executing command\n", adp->lun); return; } @@ -452,7 +468,7 @@ ad_interrupt(struct ad_request *request) /* get drive status */ if (ata_wait(adp->controller, adp->unit, 0) < 0) - printf("ad_interrupt: timeout waiting for status"); + printf("ad%d: timeout waiting for status", adp->lun); /* do we have a corrected soft error ? */ if (adp->controller->status & ATA_S_CORR) @@ -499,7 +515,7 @@ oops: /* if we arrived here with forced PIO mode, DMA doesn't work right */ if (request->flags & AR_F_FORCE_PIO) - printf("ad%d: DMA problem, fallback to PIO mode\n", adp->lun); + printf("ad%d: DMA problem fallback to PIO mode\n", adp->lun); /* if this was a PIO read operation, get the data */ if (!(request->flags & AR_F_DMA_USED) && @@ -508,11 +524,11 @@ oops: /* ready to receive data? */ if ((adp->controller->status & (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) != (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) - printf("ad_interrupt: read interrupt arrived early"); + printf("ad%d: read interrupt arrived early", adp->lun); if (ata_wait(adp->controller, adp->unit, (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) != 0) { - printf("ad_interrupt: read error detected late"); + printf("ad%d: read error detected late", adp->lun); goto oops; } @@ -574,13 +590,14 @@ ad_timeout(struct ad_request *request) int32_t s = splbio(); adp->controller->running = NULL; - printf("ad%d: ad_timeout: lost disk contact - resetting\n", adp->lun); + printf("ad%d: %s command timeout - resetting\n", + adp->lun, (request->flags & AR_F_READ) ? "READ" : "WRITE"); if (request->flags & AR_F_DMA_USED) { ata_dmadone(adp->controller); if (request->retries == AD_MAX_RETRIES) { ata_dmainit(adp->controller, adp->unit, ata_pmode(AD_PARAM), -1,-1); - printf("ad%d: ad_timeout: trying fallback to PIO mode\n", adp->lun); + printf("ad%d: trying fallback to PIO mode\n", adp->lun); request->retries = 0; } } diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h index eadfeb12..47f9f78 100644 --- a/sys/dev/ata/ata-disk.h +++ b/sys/dev/ata/ata-disk.h @@ -47,6 +47,7 @@ struct ad_softc { struct buf_queue_head queue; /* head of request queue */ struct devstat stats; /* devstat entry */ struct disk disk; /* disklabel/slice stuff */ + dev_t dev1, dev2; /* device place holder */ }; struct ad_request { @@ -70,6 +71,7 @@ struct ad_request { }; void ad_attach(struct ata_softc *, int32_t); +void ad_detach(struct ata_softc *, int32_t); void ad_transfer(struct ad_request *); int32_t ad_interrupt(struct ad_request *); void ad_reinit(struct ad_softc *); diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 1751648..5463b05 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -29,7 +29,6 @@ */ #include "pci.h" -#include "apm.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> @@ -42,9 +41,6 @@ #if NPCI > 0 #include <pci/pcivar.h> #endif -#if NAPM > 0 -#include <machine/apm_bios.h> -#endif #include <dev/ata/ata-all.h> #include <dev/ata/ata-disk.h> @@ -64,6 +60,7 @@ void ata_dmainit(struct ata_softc *scp, int32_t device, int32_t apiomode, int32_t wdmamode, int32_t udmamode) { + device_t parent = device_get_parent(scp->dev); int32_t devno = (scp->unit << 1) + ATA_DEV(device); int32_t error; @@ -116,8 +113,8 @@ ata_dmainit(struct ata_softc *scp, int32_t device, if (!error) { mask48 = (1 << devno) + (3 << (16 + (devno << 2))); new48 = (1 << devno) + (2 << (16 + (devno << 2))); - pci_write_config(scp->dev, 0x48, - (pci_read_config(scp->dev, 0x48, 4) & + pci_write_config(parent, 0x48, + (pci_read_config(parent, 0x48, 4) & ~mask48) | new48, 4); scp->mode[ATA_DEV(device)] = ATA_UDMA2; return; @@ -130,9 +127,9 @@ ata_dmainit(struct ata_softc *scp, int32_t device, int32_t mask40, new40, mask44, new44; /* if SITRE not set doit for both channels */ - if (!((pci_read_config(scp->dev, 0x40, 4)>>(scp->unit<<8))&0x4000)){ - new40 = pci_read_config(scp->dev, 0x40, 4); - new44 = pci_read_config(scp->dev, 0x44, 4); + if (!((pci_read_config(parent, 0x40, 4)>>(scp->unit<<8))&0x4000)){ + new40 = pci_read_config(parent, 0x40, 4); + new44 = pci_read_config(parent, 0x44, 4); if (!(new40 & 0x00004000)) { new44 &= ~0x0000000f; new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8); @@ -142,8 +139,8 @@ ata_dmainit(struct ata_softc *scp, int32_t device, new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20); } new40 |= 0x40004000; - pci_write_config(scp->dev, 0x40, new40, 4); - pci_write_config(scp->dev, 0x44, new44, 4); + pci_write_config(parent, 0x40, new40, 4); + pci_write_config(parent, 0x44, new44, 4); } error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); @@ -172,11 +169,11 @@ ata_dmainit(struct ata_softc *scp, int32_t device, mask44 <<= 4; new44 <<= 4; } - pci_write_config(scp->dev, 0x40, - (pci_read_config(scp->dev, 0x40, 4) & ~mask40)| + pci_write_config(parent, 0x40, + (pci_read_config(parent, 0x40, 4) & ~mask40)| new40, 4); - pci_write_config(scp->dev, 0x44, - (pci_read_config(scp->dev, 0x44, 4) & ~mask44)| + pci_write_config(parent, 0x44, + (pci_read_config(parent, 0x44, 4) & ~mask44)| new44, 4); scp->mode[ATA_DEV(device)] = ATA_WDMA2; return; @@ -189,7 +186,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, if (wdmamode >= 2 && apiomode >= 4) { int32_t word40; - word40 = pci_read_config(scp->dev, 0x40, 4); + word40 = pci_read_config(parent, 0x40, 4); word40 >>= scp->unit * 16; /* Check for timing config usable for DMA on controller */ @@ -218,7 +215,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, break; } if (udmamode >= 2) { - int32_t word54 = pci_read_config(scp->dev, 0x54, 4); + int32_t word54 = pci_read_config(parent, 0x54, 4); error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); @@ -229,9 +226,9 @@ ata_dmainit(struct ata_softc *scp, int32_t device, if (!error) { word54 |= 0x5555; word54 |= (0x0a << (16 + (scp->unit << 3) + (device << 2))); - pci_write_config(scp->dev, 0x54, word54, 4); - pci_write_config(scp->dev, 0x53, - pci_read_config(scp->dev, 0x53, 1) | 0x03, 1); + pci_write_config(parent, 0x54, word54, 4); + pci_write_config(parent, 0x53, + pci_read_config(parent, 0x53, 1) | 0x03, 1); scp->flags |= ATA_ATAPI_DMA_RO; scp->mode[ATA_DEV(device)] = ATA_UDMA2; return; @@ -245,8 +242,8 @@ ata_dmainit(struct ata_softc *scp, int32_t device, "%s setting up WDMA2 mode on Aladdin chip\n", (error) ? "failed" : "success"); if (!error) { - pci_write_config(scp->dev, 0x53, - pci_read_config(scp->dev, 0x53, 1) | 0x03, 1); + pci_write_config(parent, 0x53, + pci_read_config(parent, 0x53, 1) | 0x03, 1); scp->flags |= ATA_ATAPI_DMA_RO; scp->mode[ATA_DEV(device)] = ATA_WDMA2; return; @@ -264,7 +261,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, "%s setting up UDMA4 mode on VIA chip\n", (error) ? "failed" : "success"); if (!error) { - pci_write_config(scp->dev, 0x53 - devno, 0xe8, 1); + pci_write_config(parent, 0x53 - devno, 0xe8, 1); scp->mode[ATA_DEV(device)] = ATA_UDMA4; return; } @@ -277,7 +274,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, "%s setting up UDMA2 mode on VIA chip\n", (error) ? "failed" : "success"); if (!error) { - pci_write_config(scp->dev, 0x53 - devno, 0xea, 1); + pci_write_config(parent, 0x53 - devno, 0xea, 1); scp->mode[ATA_DEV(device)] = ATA_UDMA2; return; } @@ -293,7 +290,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, "%s setting up UDMA4 mode on AMD chip\n", (error) ? "failed" : "success"); if (!error) { - pci_write_config(scp->dev, 0x53 - devno, 0xc3, 1); + pci_write_config(parent, 0x53 - devno, 0xc3, 1); scp->mode[ATA_DEV(device)] = ATA_UDMA4; return; } @@ -315,7 +312,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, (error) ? "failed" : "success", (scp->chiptype == 0x74091022) ? "AMD" : "VIA"); if (!error) { - pci_write_config(scp->dev, 0x53 - devno, 0xc0, 1); + pci_write_config(parent, 0x53 - devno, 0xc0, 1); scp->mode[ATA_DEV(device)] = ATA_UDMA2; return; } @@ -332,8 +329,8 @@ via_generic: (error) ? "failed" : "success", (scp->chiptype == 0x74091022) ? "AMD" : "VIA"); if (!error) { - pci_write_config(scp->dev, 0x53 - devno, 0x82, 1); - pci_write_config(scp->dev, 0x4b - devno, 0x31, 1); + pci_write_config(parent, 0x53 - devno, 0x82, 1); + pci_write_config(parent, 0x4b - devno, 0x31, 1); scp->mode[ATA_DEV(device)] = ATA_WDMA2; return; } @@ -350,7 +347,7 @@ via_generic: "%s setting up UDMA2 mode on SiS chip\n", (error) ? "failed" : "success"); if (!error) { - pci_write_config(scp->dev, 0x40 + (devno << 1), 0xa301, 2); + pci_write_config(parent, 0x40 + (devno << 1), 0xa301, 2); scp->mode[ATA_DEV(device)] = ATA_UDMA2; return; } @@ -363,7 +360,26 @@ via_generic: "%s setting up WDMA2 mode on SiS chip\n", (error) ? "failed" : "success"); if (!error) { - pci_write_config(scp->dev, 0x40 + (devno << 1), 0x0301, 2); + pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); + scp->mode[ATA_DEV(device)] = ATA_WDMA2; + return; + } + } + /* we could set PIO mode timings, but we assume the BIOS did that */ + break; + + case 0x06461095: /* CMD 646 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 CMD646 chip\n", + error ? "failed" : "success"); + if (!error) { + int32_t offset = (devno < 3) ? (devno << 1) : 7; + + pci_write_config(parent, 0x54 + offset, 0x3f, 1); scp->mode[ATA_DEV(device)] = ATA_WDMA2; return; } @@ -379,7 +395,7 @@ via_generic: break; if (udmamode >=4 && scp->chiptype == 0x4d38105a && - !(pci_read_config(scp->dev, 0x50, 2)&(scp->unit ? 1<<11 : 1<<10))) { + !(pci_read_config(parent, 0x50, 2)&(scp->unit ? 1<<11 : 1<<10))) { error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); if (bootverbose) @@ -436,7 +452,7 @@ via_generic: (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) break; - if (udmamode >=4 && !(pci_read_config(scp->dev, 0x5a, 1) & 0x2)) { + if (udmamode >=4 && !(pci_read_config(parent, 0x5a, 1) & 0x2)) { error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); if (bootverbose) @@ -648,15 +664,16 @@ promise_timing(struct ata_softc *scp, int32_t devno, int32_t mode) } break; } - pci_write_config(scp->dev, 0x60 + (devno << 2), timing, 4); + pci_write_config(device_get_parent(scp->dev), 0x60 + (devno<<2), timing, 4); } static void hpt366_timing(struct ata_softc *scp, int32_t devno, int32_t mode) { + device_t parent = device_get_parent(scp->dev); u_int32_t timing; - switch (pci_read_config(scp->dev, 0x41 + (devno << 2), 1)) { + switch (pci_read_config(parent, 0x41 + (devno << 2), 1)) { case 0x85: /* 25Mhz */ switch (mode) { case ATA_PIO0: timing = 0xc0d08585; break; @@ -697,7 +714,7 @@ hpt366_timing(struct ata_softc *scp, int32_t devno, int32_t mode) default: timing = 0x0120d9d9; } } - pci_write_config(scp->dev, 0x40 + (devno << 2) , (timing & ~0x80000000), 4); + pci_write_config(parent, 0x40 + (devno << 2) , (timing & ~0x80000000), 4); } #else /* NPCI > 0 */ diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index b31290a..8f1e67a 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -28,7 +28,6 @@ * $FreeBSD$ */ -#include "apm.h" #include "atapicd.h" #include "atapist.h" #include "atapifd.h" @@ -41,9 +40,6 @@ #include <sys/bus.h> #include <sys/malloc.h> #include <machine/clock.h> -#if NAPM > 0 -#include <machine/apm_bios.h> -#endif #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> @@ -59,6 +55,9 @@ static int8_t *atapi_skey2str(u_int8_t); int32_t acdattach(struct atapi_softc *); int32_t afdattach(struct atapi_softc *); int32_t astattach(struct atapi_softc *); +void acddetach(struct atapi_softc *); +void afddetach(struct atapi_softc *); +void astdetach(struct atapi_softc *); /* internal vars */ MALLOC_DEFINE(M_ATAPI, "ATAPI generic", "ATAPI driver generic layer"); @@ -73,7 +72,7 @@ atapi_attach(struct ata_softc *scp, int32_t device) struct atapi_softc *atp; if (!(atp = malloc(sizeof(struct atapi_softc), M_ATAPI, M_NOWAIT))) { - printf("atapi: failed to allocate driver storage\n"); + ata_printf(scp, device, "failed to allocate driver storage\n"); return; } bzero(atp, sizeof(struct atapi_softc)); @@ -131,10 +130,38 @@ notfound: scp->dev_softc[ATA_DEV(device)] = atp; } +void +atapi_detach(struct ata_softc *scp, int32_t device) +{ + struct atapi_softc *atp = scp->dev_softc[ATA_DEV(device)]; + + switch (ATP_PARAM->device_type) { +#if NATAPICD > 0 + case ATAPI_TYPE_CDROM: + acddetach(atp); + break; +#endif +#if NATAPIFD > 0 + case ATAPI_TYPE_DIRECT: + afddetach(atp); + break; +#endif +#if NATAPIST > 0 + case ATAPI_TYPE_TAPE: + astdetach(atp); + break; +#endif + default: + return; + } + free(atp, M_ATAPI); + scp->dev_softc[ATA_DEV(device)] = NULL; +} + int32_t atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, int32_t count, int32_t flags, int32_t timeout, - atapi_callback_t callback, void *driver, struct buf *bp) + atapi_callback_t callback, void *unused, struct buf *bp) { struct atapi_request *request; int32_t error, s; @@ -153,7 +180,6 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, if (callback) { request->callback = callback; request->bp = bp; - request->driver = driver; } s = splbio(); @@ -273,7 +299,7 @@ atapi_interrupt(struct atapi_request *request) if (reason == ATAPI_P_CMDOUT) { if (!(atp->controller->status & ATA_S_DRQ)) { request->result = inb(atp->controller->ioaddr + ATA_ERROR); - printf("%s: command interrupt, but no DRQ\n", atp->devname); + printf("%s: command interrupt without DRQ\n", atp->devname); goto op_finished; } outsw(atp->controller->ioaddr + ATA_DATA, request->ccb, @@ -469,7 +495,6 @@ atapi_read(struct atapi_request *request, int32_t length) if (request->bytecount < length) { printf("%s: read data overrun %d/%d\n", request->device->devname, length, request->bytecount); - for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t)) inw(request->device->controller->ioaddr + ATA_DATA); } @@ -498,7 +523,6 @@ atapi_write(struct atapi_request *request, int32_t length) if (request->bytecount < length) { printf("%s: write data underrun %d/%d\n", request->device->devname, length, request->bytecount); - for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t)) outw(request->device->controller->ioaddr + ATA_DATA, 0); } @@ -513,7 +537,7 @@ atapi_timeout(struct atapi_request *request) int32_t s = splbio(); atp->controller->running = NULL; - printf("%s: atapi_timeout: cmd=%s - resetting\n", + printf("%s: %s command timeout - resetting\n", atp->devname, atapi_cmd2str(request->ccb[0])); if (request->flags & ATAPI_F_DMA_USED) @@ -597,7 +621,7 @@ atapi_cmd2str(u_int8_t cmd) case 0xbe: return ("READ_CD"); default: { static int8_t buffer[16]; - sprintf(buffer, "Unknown CMD (0x%02x)", cmd); + sprintf(buffer, "unknown CMD (0x%02x)", cmd); return buffer; } } diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h index 26cf7ad..ca7a55f 100644 --- a/sys/dev/ata/atapi-all.h +++ b/sys/dev/ata/atapi-all.h @@ -134,8 +134,9 @@ struct atapi_reqsense { }; struct atapi_softc { - struct ata_softc *controller; /* ptr to parent ctrl */ + struct ata_softc *controller; /* ptr to controller softc */ int32_t unit; /* ATA_MASTER or ATA_SLAVE */ + void *driver; /* ptr to subdriver softc */ int8_t *devname; /* this devices name */ int8_t cmd; /* last cmd executed */ u_int32_t flags; /* drive flags */ @@ -149,7 +150,6 @@ typedef int32_t atapi_callback_t(struct atapi_request *); struct atapi_request { struct atapi_softc *device; /* ptr to parent device */ - void *driver; /* ptr to calling driver */ u_int8_t ccb[16]; /* command control block */ int32_t ccbsize; /* size of ccb (12 | 16) */ u_int32_t bytecount; /* bytes to transfer */ @@ -169,6 +169,7 @@ struct atapi_request { }; void atapi_attach(struct ata_softc *, int32_t); +void atapi_detach(struct ata_softc *, int32_t); void atapi_transfer(struct atapi_request *); int32_t atapi_interrupt(struct atapi_request *); int32_t atapi_queue_cmd(struct atapi_softc *, int8_t [], void *, int32_t, int32_t, int32_t, atapi_callback_t, void *, struct buf *); diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index dbacde7..f35f964 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -28,7 +28,6 @@ * $FreeBSD$ */ -#include "apm.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -44,18 +43,15 @@ #include <sys/fcntl.h> #include <sys/conf.h> #include <sys/stat.h> -#if NAPM > 0 -#include <machine/apm_bios.h> -#endif #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> #include <dev/ata/atapi-cd.h> +/* device structures */ static d_open_t acdopen; static d_close_t acdclose; static d_ioctl_t acdioctl; static d_strategy_t acdstrategy; - static struct cdevsw acd_cdevsw = { /* open */ acdopen, /* close */ acdclose, @@ -75,7 +71,8 @@ static struct cdevsw acd_cdevsw = { /* prototypes */ int32_t acdattach(struct atapi_softc *); -static struct acd_softc *acd_init_lun(struct atapi_softc *, int32_t, struct devstat *); +void acddetach(struct atapi_softc *); +static struct acd_softc *acd_init_lun(struct atapi_softc *, struct devstat *); static void acd_describe(struct acd_softc *); static void lba2msf(int32_t, u_int8_t *, u_int8_t *, u_int8_t *); static int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t); @@ -101,6 +98,7 @@ static int32_t acd_mode_select(struct acd_softc *, void *, int32_t); static int32_t acd_set_speed(struct acd_softc *cdp, int32_t); /* internal vars */ +static u_int32_t acd_lun_map = 0; MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers"); int @@ -109,14 +107,14 @@ acdattach(struct atapi_softc *atp) struct acd_softc *cdp; struct changer *chp; int32_t count, error = 0; - static int32_t acd_cdev_done = 0, acdnlun = 0; + static int32_t acd_cdev_done = 0; if (!acd_cdev_done) { cdevsw_add(&acd_cdevsw); acd_cdev_done++; } - if ((cdp = acd_init_lun(atp, acdnlun, NULL)) == NULL) { + if ((cdp = acd_init_lun(atp, NULL)) == NULL) { printf("acd: out of memory\n"); return -1; } @@ -162,7 +160,7 @@ acdattach(struct atapi_softc *atp) chp->table_length = htons(chp->table_length); for (count = 0; count < chp->slots; count++) { if (count > 0) { - tmpcdp = acd_init_lun(atp, acdnlun, cdp->stats); + tmpcdp = acd_init_lun(atp, cdp->stats); if (!tmpcdp) { printf("acd: out of memory\n"); return -1; @@ -171,9 +169,8 @@ acdattach(struct atapi_softc *atp) tmpcdp->slot = count; tmpcdp->changer_info = chp; if (bootverbose) - printf("acd%d: changer slot %d %s\n", acdnlun, count, + printf("acd%d: changer slot %d %s\n", tmpcdp->lun, count, (chp->slot[count].present ? "CD present" : "empty")); - acdnlun++; } sprintf(string, "acd%d-", cdp->lun); devstat_add_entry(cdp->stats, string, tmpcdp->lun, DEV_BSIZE, @@ -187,51 +184,73 @@ acdattach(struct atapi_softc *atp) DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, DEVSTAT_PRIORITY_CD); - acdnlun++; } acd_describe(cdp); return 0; } +void +acddetach(struct atapi_softc *atp) +{ + struct acd_softc *cdp = atp->driver; + + destroy_dev(cdp->dev1); + destroy_dev(cdp->dev2); + if (cdp->changer_info) { + /* should free all cdp's here, not possible yet SOS XXX */ + free(cdp->changer_info, M_ACD); + } + devstat_remove_entry(cdp->stats); + free(cdp->stats, M_ACD); + free(cdp->atp->devname, M_ACD); + ata_free_lun(&acd_lun_map, cdp->lun); + free(cdp, M_ACD); +} + static struct acd_softc * -acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats) +acd_init_lun(struct atapi_softc *atp, struct devstat *stats) { - struct acd_softc *acd; + struct acd_softc *cdp; dev_t dev; - if (!(acd = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT))) + if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT))) return NULL; - bzero(acd, sizeof(struct acd_softc)); - bufq_init(&acd->buf_queue); - acd->atp = atp; - acd->lun = lun; - acd->flags &= ~(F_WRITTEN|F_DISK_OPEN|F_TRACK_OPEN); - acd->block_size = 2048; - acd->slot = -1; - acd->changer_info = NULL; - acd->atp->flags |= ATAPI_F_MEDIA_CHANGED; + bzero(cdp, sizeof(struct acd_softc)); + bufq_init(&cdp->buf_queue); + cdp->atp = atp; + cdp->lun = ata_get_lun(&acd_lun_map); + cdp->flags &= ~(F_WRITTEN|F_DISK_OPEN|F_TRACK_OPEN); + cdp->block_size = 2048; + cdp->slot = -1; + cdp->changer_info = NULL; if (stats == NULL) { - if (!(acd->stats = malloc(sizeof(struct devstat), M_ACD, M_NOWAIT))) { - free(acd, M_ACD); + if (!(cdp->stats = malloc(sizeof(struct devstat), M_ACD, M_NOWAIT))) { + free(cdp, M_ACD); return NULL; } - bzero(acd->stats, sizeof(struct devstat)); + bzero(cdp->stats, sizeof(struct devstat)); } else - acd->stats = stats; - dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0), - UID_ROOT, GID_OPERATOR, 0644, "acd%da", lun); - dev->si_drv1 = acd; + cdp->stats = stats; + + cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + cdp->atp->driver = cdp; + + dev = make_dev(&acd_cdevsw, dkmakeminor(cdp->lun, 0, 0), + UID_ROOT, GID_OPERATOR, 0644, "acd%da", cdp->lun); + dev->si_drv1 = cdp; dev->si_iosize_max = 252 * DEV_BSIZE; dev->si_bsize_phys = 2048; /* XXX SOS */ - dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART), - UID_ROOT, GID_OPERATOR, 0644, "acd%dc", lun); - dev->si_drv1 = acd; + cdp->dev1 = dev; + dev = make_dev(&acd_cdevsw, dkmakeminor(cdp->lun, 0, RAW_PART), + UID_ROOT, GID_OPERATOR, 0644, "acd%dc", cdp->lun); + dev->si_drv1 = cdp; dev->si_iosize_max = 252 * DEV_BSIZE; dev->si_bsize_phys = 2048; /* XXX SOS */ - if ((acd->atp->devname = malloc(8, M_ACD, M_NOWAIT))) - sprintf(acd->atp->devname, "acd%d", acd->lun); - return acd; + cdp->dev2 = dev; + if ((cdp->atp->devname = malloc(8, M_ACD, M_NOWAIT))) + sprintf(cdp->atp->devname, "acd%d", cdp->lun); + return cdp; } static void @@ -249,7 +268,7 @@ acd_describe(struct acd_softc *cdp) (cdp->cap.write_cdrw) ? "CD-RW" : (cdp->cap.write_cdr) ? "CD-R" : (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM", - cdp->atp->controller->lun, + device_get_unit(cdp->atp->controller->dev), (cdp->atp->unit == ATA_MASTER) ? "master" : "slave"); printf("acd%d:", cdp->lun); @@ -415,7 +434,7 @@ acd_describe(struct acd_softc *cdp) (cdp->cap.write_cdr) ? "CD-R" : (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM", changer, ATA_PARAM(cdp->atp->controller, cdp->atp->unit)->model, - cdp->atp->controller->lun, + device_get_unit(cdp->atp->controller->dev), (cdp->atp->unit == ATA_MASTER) ? "master" : "slave", ata_mode2str(cdp->atp->controller->mode[ATA_DEV(cdp->atp->unit)]) ); @@ -1062,7 +1081,6 @@ acd_start(struct acd_softc *cdp) } acd_select_slot(cdp); - if (!(bp->b_flags & B_READ) && (!(cdp->flags & F_DISK_OPEN) || !(cdp->flags & F_TRACK_OPEN))) { printf("acd%d: sequence error (no open)\n", cdp->lun); @@ -1084,7 +1102,7 @@ acd_start(struct acd_softc *cdp) ccb[0] = ATAPI_READ_BIG; else { ccb[0] = ATAPI_READ_CD; - ccb[9] = 0x10; + ccb[9] = 0xf8; } } else @@ -1108,7 +1126,7 @@ static int32_t acd_done(struct atapi_request *request) { struct buf *bp = request->bp; - struct acd_softc *cdp = request->driver; + struct acd_softc *cdp = request->device->driver; if (request->error) { bp->b_error = request->error; diff --git a/sys/dev/ata/atapi-cd.h b/sys/dev/ata/atapi-cd.h index 6345ded..2fb760c 100644 --- a/sys/dev/ata/atapi-cd.h +++ b/sys/dev/ata/atapi-cd.h @@ -341,4 +341,5 @@ struct acd_softc { int32_t slot; /* this lun's slot number */ u_int32_t block_size; /* blocksize currently used */ struct devstat *stats; /* devstat entry */ + dev_t dev1, dev2; /* device place holders */ }; diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index df30c26..3423f5b 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -28,7 +28,6 @@ * $FreeBSD$ */ -#include "apm.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -40,18 +39,15 @@ #include <sys/disk.h> #include <sys/devicestat.h> #include <sys/cdio.h> -#if NAPM > 0 -#include <machine/apm_bios.h> -#endif #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> #include <dev/ata/atapi-fd.h> +/* device structures */ static d_open_t afdopen; static d_close_t afdclose; static d_ioctl_t afdioctl; static d_strategy_t afdstrategy; - static struct cdevsw afd_cdevsw = { /* open */ afdopen, /* close */ afdclose, @@ -72,6 +68,7 @@ static struct cdevsw afddisk_cdevsw; /* prototypes */ int32_t afdattach(struct atapi_softc *); +void afddetach(struct atapi_softc *); static int32_t afd_sense(struct afd_softc *); static void afd_describe(struct afd_softc *); static void afd_start(struct afd_softc *); @@ -82,6 +79,7 @@ static int32_t afd_start_stop(struct afd_softc *, int32_t); static int32_t afd_prevent_allow(struct afd_softc *, int32_t); /* internal vars */ +static u_int32_t afd_lun_map = 0; MALLOC_DEFINE(M_AFD, "AFD driver", "ATAPI floppy driver buffers"); int32_t @@ -89,7 +87,6 @@ afdattach(struct atapi_softc *atp) { struct afd_softc *fdp; dev_t dev; - static int32_t afdnlun = 0; fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT); if (!fdp) { @@ -99,8 +96,9 @@ afdattach(struct atapi_softc *atp) bzero(fdp, sizeof(struct afd_softc)); bufq_init(&fdp->buf_queue); fdp->atp = atp; - fdp->lun = afdnlun++; + fdp->lun = ata_get_lun(&afd_lun_map); fdp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + fdp->atp->driver = fdp; if (afd_sense(fdp)) { free(fdp, M_AFD); @@ -118,12 +116,26 @@ afdattach(struct atapi_softc *atp) dev = disk_create(fdp->lun, &fdp->disk, 0, &afd_cdevsw, &afddisk_cdevsw); dev->si_drv1 = fdp; dev->si_iosize_max = 252 * DEV_BSIZE; + fdp->dev = dev; if ((fdp->atp->devname = malloc(8, M_AFD, M_NOWAIT))) sprintf(fdp->atp->devname, "afd%d", fdp->lun); afd_describe(fdp); return 0; } +void +afddetach(struct atapi_softc *atp) +{ + struct afd_softc *fdp = atp->driver; + + disk_invalidate(&fdp->disk); + disk_destroy(fdp->dev); + devstat_remove_entry(&fdp->stats); + free(fdp->atp->devname, M_AFD); + ata_free_lun(&afd_lun_map, fdp->lun); + free(fdp, M_AFD); +} + static int32_t afd_sense(struct afd_softc *fdp) { @@ -160,7 +172,7 @@ afd_describe(struct afd_softc *fdp) printf("afd%d: <%.40s/%.8s> rewriteable drive at ata%d as %s\n", fdp->lun, ATA_PARAM(fdp->atp->controller, fdp->atp->unit)->model, ATA_PARAM(fdp->atp->controller, fdp->atp->unit)->revision, - fdp->atp->controller->lun, + device_get_unit(fdp->atp->controller->dev), (fdp->atp->unit == ATA_MASTER) ? "master" : "slave"); printf("afd%d: %luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n", fdp->lun, @@ -200,7 +212,7 @@ afd_describe(struct afd_softc *fdp) ((1024L * 1024L) / fdp->cap.sector_size), ATA_PARAM(fdp->atp->controller, fdp->atp->unit)->model, fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors, - fdp->atp->controller->lun, + device_get_unit(fdp->atp->controller->dev), (fdp->atp->unit == ATA_MASTER) ? "master" : "slave", ata_mode2str(fdp->atp->controller->mode[ATA_DEV(fdp->atp->unit)]) ); @@ -364,7 +376,7 @@ static int32_t afd_done(struct atapi_request *request) { struct buf *bp = request->bp; - struct afd_softc *fdp = request->driver; + struct afd_softc *fdp = request->device->driver; if (request->error || (bp->b_flags & B_ERROR)) { bp->b_error = request->error; diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h index f2c77f0..b141625 100644 --- a/sys/dev/ata/atapi-fd.h +++ b/sys/dev/ata/atapi-fd.h @@ -79,5 +79,6 @@ struct afd_softc { struct afd_cappage cap; /* capabilities page info */ struct disk disk; /* virtual drives */ struct devstat stats; + dev_t dev; /* device place holder */ }; diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index 71c69ca..9d41648 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -28,7 +28,6 @@ * $FreeBSD$ */ -#include "apm.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -39,18 +38,15 @@ #include <sys/mtio.h> #include <sys/disklabel.h> #include <sys/devicestat.h> -#if NAPM > 0 -#include <machine/apm_bios.h> -#endif #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> #include <dev/ata/atapi-tape.h> +/* device structures */ static d_open_t astopen; static d_close_t astclose; static d_ioctl_t astioctl; static d_strategy_t aststrategy; - static struct cdevsw ast_cdevsw = { /* open */ astopen, /* close */ astclose, @@ -70,6 +66,7 @@ static struct cdevsw ast_cdevsw = { /* prototypes */ int32_t astattach(struct atapi_softc *); +void astdetach(struct atapi_softc *); static int32_t ast_sense(struct ast_softc *); static void ast_describe(struct ast_softc *); static void ast_start(struct ast_softc *); @@ -86,6 +83,7 @@ static int32_t ast_rewind(struct ast_softc *); static int32_t ast_erase(struct ast_softc *); /* internal vars */ +static u_int32_t ast_lun_map = 0; static u_int64_t ast_total = 0; MALLOC_DEFINE(M_AST, "AST driver", "ATAPI tape driver buffers"); @@ -95,7 +93,7 @@ astattach(struct atapi_softc *atp) struct ast_softc *stp; struct ast_readposition position; dev_t dev; - static int32_t ast_cdev_done = 0, astnlun = 0; + static int32_t ast_cdev_done = 0; if (!ast_cdev_done) { cdevsw_add(&ast_cdevsw); @@ -109,12 +107,14 @@ astattach(struct atapi_softc *atp) bzero(stp, sizeof(struct ast_softc)); bufq_init(&stp->buf_queue); stp->atp = atp; - stp->lun = astnlun++; - stp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + stp->lun = ata_get_lun(&ast_lun_map); if (ast_sense(stp)) { free(stp, M_AST); return -1; } + stp->atp->flags |= ATAPI_F_MEDIA_CHANGED; + stp->atp->driver = stp; + if (!strcmp(ATA_PARAM(stp->atp->controller, stp->atp->unit)->model, "OnStream DI-30")) { struct ast_transferpage transfer; @@ -139,16 +139,31 @@ astattach(struct atapi_softc *atp) UID_ROOT, GID_OPERATOR, 0640, "ast%d", stp->lun); dev->si_drv1 = stp; dev->si_iosize_max = 252 * DEV_BSIZE; + stp->dev1 = dev; dev = make_dev(&ast_cdevsw, dkmakeminor(stp->lun, 0, 1), UID_ROOT, GID_OPERATOR, 0640, "nast%d", stp->lun); dev->si_drv1 = stp; dev->si_iosize_max = 252 * DEV_BSIZE; + stp->dev2 = dev; if ((stp->atp->devname = malloc(8, M_AST, M_NOWAIT))) sprintf(stp->atp->devname, "ast%d", stp->lun); ast_describe(stp); return 0; } +void +astdetach(struct atapi_softc *atp) +{ + struct ast_softc *stp = atp->driver; + + destroy_dev(stp->dev1); + destroy_dev(stp->dev2); + devstat_remove_entry(&stp->stats); + free(stp->atp->devname, M_AST); + ata_free_lun(&ast_lun_map, stp->lun); + free(stp, M_AST); +} + static int32_t ast_sense(struct ast_softc *stp) { @@ -184,7 +199,7 @@ ast_describe(struct ast_softc *stp) printf("ast%d: <%.40s/%.8s> tape drive at ata%d as %s\n", stp->lun, ATA_PARAM(stp->atp->controller, stp->atp->unit)->model, ATA_PARAM(stp->atp->controller, stp->atp->unit)->revision, - stp->atp->controller->lun, + device_get_unit(stp->atp->controller->dev), (stp->atp->unit == ATA_MASTER) ? "master" : "slave"); printf("ast%d: ", stp->lun); printf("%dKB/s, ", stp->cap.max_speed); @@ -225,7 +240,7 @@ ast_describe(struct ast_softc *stp) else { printf("ast%d: TAPE <%.40s> at ata%d-%s using %s\n", stp->lun, ATA_PARAM(stp->atp->controller, stp->atp->unit)->model, - stp->atp->controller->lun, + device_get_unit(stp->atp->controller->dev), (stp->atp->unit == ATA_MASTER) ? "master" : "slave", ata_mode2str(stp->atp->controller->mode[ATA_DEV(stp->atp->unit)]) ); @@ -482,7 +497,7 @@ static int32_t ast_done(struct atapi_request *request) { struct buf *bp = request->bp; - struct ast_softc *stp = request->driver; + struct ast_softc *stp = request->device->driver; if (request->error) { bp->b_error = request->error; diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h index 98719bf..bccd665 100644 --- a/sys/dev/ata/atapi-tape.h +++ b/sys/dev/ata/atapi-tape.h @@ -158,4 +158,5 @@ struct ast_softc { struct atapi_params *param; /* drive parameters table */ struct ast_cappage cap; /* capabilities page info */ struct devstat stats; /* devstat entry */ + dev_t dev1, dev2; /* device place holders */ }; |