diff options
-rw-r--r-- | sys/alpha/include/md_var.h | 7 | ||||
-rw-r--r-- | sys/alpha/pci/pcibus.c | 37 | ||||
-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 | ||||
-rw-r--r-- | sys/kern/subr_disk.c | 5 | ||||
-rw-r--r-- | sys/powerpc/include/md_var.h | 7 |
17 files changed, 1106 insertions, 612 deletions
diff --git a/sys/alpha/include/md_var.h b/sys/alpha/include/md_var.h index 42d40f3..bdcba94 100644 --- a/sys/alpha/include/md_var.h +++ b/sys/alpha/include/md_var.h @@ -57,7 +57,12 @@ int fill_fpregs __P((struct proc *, struct fpreg *)); int set_fpregs __P((struct proc *, struct fpreg *)); void alpha_register_pci_scsi __P((int bus, int slot, struct cam_sim *sim)); #ifdef _SYS_BUS_H_ -int alpha_platform_setup_ide_intr(int chan, driver_intr_t *fn, void *arg); +struct resource *alpha_platform_alloc_ide_intr(int chan); +int alpha_platform_release_ide_intr(int chan, struct resource *res); +int alpha_platform_setup_ide_intr(struct resource *res, + driver_intr_t *fn, void *arg, + void **cookiep); +int alpha_platform_teardown_ide_intr(struct resource *res, void *cookie); #endif void alpha_platform_assign_pciintr(struct pcicfg *cfg); diff --git a/sys/alpha/pci/pcibus.c b/sys/alpha/pci/pcibus.c index b668c82..a137558 100644 --- a/sys/alpha/pci/pcibus.c +++ b/sys/alpha/pci/pcibus.c @@ -140,22 +140,31 @@ alpha_platform_assign_pciintr(pcicfgregs *cfg) platform.pci_intr_map((void *)cfg); } +struct resource * +alpha_platform_alloc_ide_intr(int chan) +{ + int irqs[2] = { 14, 15 }; + return isa_alloc_intr(0, 0, irqs[chan]); +} + int -alpha_platform_setup_ide_intr(int chan, driver_intr_t *fn, void *arg) +alpha_platform_release_ide_intr(int chan, struct resource *res) { - if (platform.pci_setup_ide_intr) - return platform.pci_setup_ide_intr(chan, fn, arg); - else { - int irqs[2] = { 14, 15 }; - void *junk; - struct resource *res; - res = isa_alloc_intr(0, 0, irqs[chan]); - if (res) - return isa_setup_intr(0, 0, res, INTR_TYPE_BIO, - fn, arg, &junk); - else - return ENOMEM; - } + return isa_release_intr(0, 0, res); +} + +int +alpha_platform_setup_ide_intr(struct resource *res, + driver_intr_t *fn, void *arg, + void **cookiep) +{ + return isa_setup_intr(0, 0, res, INTR_TYPE_BIO, fn, arg, cookiep); +} + +int +alpha_platform_teardown_ide_intr(struct resource *res, void *cookie) +{ + return isa_teardown_intr(0, 0, res, cookie); } static struct rman irq_rman, port_rman, mem_rman; 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 */ }; diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index fa5eff9..cf1b3cc 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -88,12 +88,15 @@ disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) void disk_invalidate (struct disk *disk) { - dsgone(&disk->d_slice); + if (disk->d_slice) + dsgone(&disk->d_slice); } void disk_destroy(dev_t dev) { + dev->si_disk = NULL; + destroy_dev(dev); return; } diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h index 42d40f3..bdcba94 100644 --- a/sys/powerpc/include/md_var.h +++ b/sys/powerpc/include/md_var.h @@ -57,7 +57,12 @@ int fill_fpregs __P((struct proc *, struct fpreg *)); int set_fpregs __P((struct proc *, struct fpreg *)); void alpha_register_pci_scsi __P((int bus, int slot, struct cam_sim *sim)); #ifdef _SYS_BUS_H_ -int alpha_platform_setup_ide_intr(int chan, driver_intr_t *fn, void *arg); +struct resource *alpha_platform_alloc_ide_intr(int chan); +int alpha_platform_release_ide_intr(int chan, struct resource *res); +int alpha_platform_setup_ide_intr(struct resource *res, + driver_intr_t *fn, void *arg, + void **cookiep); +int alpha_platform_teardown_ide_intr(struct resource *res, void *cookie); #endif void alpha_platform_assign_pciintr(struct pcicfg *cfg); |