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_controller *controller = device_get_softc(dev); int unit = ((struct ata_channel *)device_get_softc(child))->unit; struct resource *res = NULL; int myrid; if (type == SYS_RES_IOPORT) { switch (*rid) { case ATA_IOADDR_RID: if (ata_legacy(dev)) { start = (unit ? ATA_SECONDARY : ATA_PRIMARY); count = ATA_IOSIZE; end = start + count - 1; } myrid = PCIR_BAR(0) + (unit << 3); res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, SYS_RES_IOPORT, &myrid, start, end, count, flags); break; case ATA_CTLADDR_RID: if (ata_legacy(dev)) { start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET; count = ATA_CTLIOSIZE; end = start + count - 1; } myrid = PCIR_BAR(1) + (unit << 3); res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, SYS_RES_IOPORT, &myrid, start, end, count, flags); break; } } if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) { if (ata_legacy(dev)) { int irq = (unit == 0 ? 14 : 15); res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, SYS_RES_IRQ, rid, irq, irq, 1, flags); } else res = controller->r_irq; } return res; }
int ata_pci_attach(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); u_int32_t cmd; int unit; /* do chipset specific setups only needed once */ if (ata_legacy(dev) || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK) ctlr->channels = 2; else ctlr->channels = 1; ctlr->allocate = ata_pci_allocate; ctlr->dmainit = ata_pci_dmainit; ctlr->dev = dev; /* if needed try to enable busmastering */ cmd = pci_read_config(dev, PCIR_COMMAND, 2); if (!(cmd & PCIM_CMD_BUSMASTEREN)) { pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2); cmd = pci_read_config(dev, PCIR_COMMAND, 2); } /* if busmastering mode "stuck" use it */ if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) { ctlr->r_type1 = SYS_RES_IOPORT; ctlr->r_rid1 = ATA_BMADDR_RID; ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1, RF_ACTIVE); } if (ctlr->chipinit(dev)) return ENXIO; /* attach all channels on this controller */ for (unit = 0; unit < ctlr->channels; unit++) { if ((unit == 0 || unit == 1) && ata_legacy(dev)) { device_add_child(dev, "ata", unit); continue; } device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 2)); } bus_generic_attach(dev); return 0; }
int ata_pci_attach(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); device_t child; u_int32_t cmd; int unit; /* do chipset specific setups only needed once */ ctlr->legacy = ata_legacy(dev); if (ctlr->legacy || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK) ctlr->channels = 2; else ctlr->channels = 1; ctlr->ichannels = -1; ctlr->ch_attach = ata_pci_ch_attach; ctlr->ch_detach = ata_pci_ch_detach; ctlr->dev = dev; /* if needed try to enable busmastering */ cmd = pci_read_config(dev, PCIR_COMMAND, 2); if (!(cmd & PCIM_CMD_BUSMASTEREN)) { pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2); cmd = pci_read_config(dev, PCIR_COMMAND, 2); } /* if busmastering mode "stuck" use it */ if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) { ctlr->r_type1 = SYS_RES_IOPORT; ctlr->r_rid1 = ATA_BMADDR_RID; ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1, RF_ACTIVE); } if (ctlr->chipinit(dev)) return ENXIO; /* attach all channels on this controller */ for (unit = 0; unit < ctlr->channels; unit++) { if ((ctlr->ichannels & (1 << unit)) == 0) continue; child = device_add_child(dev, "ata", ((unit == 0 || unit == 1) && ctlr->legacy) ? unit : devclass_find_free_unit(ata_devclass, 2)); if (child == NULL) device_printf(dev, "failed to add ata child device\n"); else device_set_ivars(child, (void *)(intptr_t)unit); } bus_generic_attach(dev); return 0; }
int ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) { if (ata_legacy(dev)) { return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie); } else { struct ata_pci_controller *controller = device_get_softc(dev); int unit = ((struct ata_channel *)device_get_softc(child))->unit; controller->interrupt[unit].function = NULL; controller->interrupt[unit].argument = NULL; return 0; } }
static int imx_ata_attach(device_t dev) { struct ata_pci_controller *ctrl; device_t child; int unit; ctrl = device_get_softc(dev); /* do chipset specific setups only needed once */ ctrl->legacy = ata_legacy(dev); ctrl->channels = 1; ctrl->ichannels = -1; ctrl->ch_attach = ata_pci_ch_attach; ctrl->ch_detach = ata_pci_ch_detach; ctrl->dev = dev; ctrl->r_type1 = SYS_RES_MEMORY; ctrl->r_rid1 = 0; ctrl->r_res1 = bus_alloc_resource_any(dev, ctrl->r_type1, &ctrl->r_rid1, RF_ACTIVE); if (ata_setup_interrupt(dev, imx_ata_intr)) { device_printf(dev, "failed to setup interrupt\n"); return ENXIO; } ctrl->channels = 1; ctrl->ch_attach = imx_ata_ch_attach; ctrl->setmode = imx_ata_setmode; /* attach all channels on this controller */ unit = 0; child = device_add_child(dev, "ata", ((unit == 0) && ctrl->legacy) ? unit : devclass_find_free_unit(ata_devclass, 2)); if (child == NULL) device_printf(dev, "failed to add ata child device\n"); else device_set_ivars(child, (void *)(intptr_t)unit); bus_generic_attach(dev); return 0; }
int ata_pci_status(device_t dev) { struct ata_channel *ch = device_get_softc(dev); if ((dumping || !ata_legacy(device_get_parent(dev))) && ch->dma && ((ch->flags & ATA_ALWAYS_DMASTAT) || (ch->dma->flags & ATA_DMA_ACTIVE))) { int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; if ((bmstat & ATA_BMSTAT_INTERRUPT) == 0) return 0; ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR); DELAY(1); } if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) { DELAY(100); if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) return 0; } return 1; }
int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *function, void *argument, void **cookiep) { if (ata_legacy(dev)) { return BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags, filter, function, argument, cookiep); } else { struct ata_pci_controller *controller = device_get_softc(dev); int unit = ((struct ata_channel *)device_get_softc(child))->unit; if (filter != NULL) { printf("ata-pci.c: we cannot use a filter here\n"); return (EINVAL); } controller->interrupt[unit].function = function; controller->interrupt[unit].argument = argument; *cookiep = controller; return 0; } }
int ata_pci_allocate(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); struct resource *io = NULL, *ctlio = NULL; int i, rid; rid = ATA_IOADDR_RID; if (!(io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE))) return ENXIO; rid = ATA_CTLADDR_RID; if (!(ctlio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,RF_ACTIVE))){ bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); return ENXIO; } for (i = ATA_DATA; i <= ATA_COMMAND; i ++) { ch->r_io[i].res = io; ch->r_io[i].offset = i; } ch->r_io[ATA_CONTROL].res = ctlio; ch->r_io[ATA_CONTROL].offset = ata_legacy(device_get_parent(dev)) ? 0 : 2; ch->r_io[ATA_IDX_ADDR].res = io; ata_default_registers(dev); if (ctlr->r_res1) { for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) { ch->r_io[i].res = ctlr->r_res1; ch->r_io[i].offset = (i - ATA_BMCMD_PORT) + (ch->unit*ATA_BMIOSIZE); } } ata_pci_hw(dev); return 0; }
int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { int unit = ((struct ata_channel *)device_get_softc(child))->unit; if (type == SYS_RES_IOPORT) { switch (rid) { case ATA_IOADDR_RID: return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, SYS_RES_IOPORT, PCIR_BAR(0) + (unit << 3), r); break; case ATA_CTLADDR_RID: return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, SYS_RES_IOPORT, PCIR_BAR(1) + (unit << 3), r); break; default: return ENOENT; } } if (type == SYS_RES_IRQ) { if (rid != ATA_IRQ_RID) return ENOENT; if (ata_legacy(dev)) { return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, SYS_RES_IRQ, rid, r); } else return 0; } return EINVAL; }