int gnttab_resume(device_t dev) { unsigned int max_nr_gframes, nr_gframes; nr_gframes = nr_grant_frames; max_nr_gframes = max_nr_grant_frames(); if (max_nr_gframes < nr_gframes) return (ENOSYS); if (!resume_frames) { KASSERT(dev != NULL, ("No resume frames and no device provided")); gnttab_pseudo_phys_res = xenmem_alloc(dev, &gnttab_pseudo_phys_res_id, PAGE_SIZE * max_nr_gframes); if (gnttab_pseudo_phys_res == NULL) panic("Unable to reserve physical memory for gnttab"); resume_frames = rman_get_start(gnttab_pseudo_phys_res); } return (gnttab_map(0, nr_gframes - 1)); }
static int nexus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { void *vaddr; vm_paddr_t paddr; vm_size_t psize; /* * If this is a memory resource, use pmap_mapdev to map it. */ if (type == SYS_RES_MEMORY) { paddr = rman_get_start(r); psize = rman_get_size(r); vaddr = pmap_mapdev(paddr, psize); rman_set_virtual(r, vaddr); rman_set_bustag(r, mips_bus_space_generic); rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr); } return (rman_activate_resource(r)); }
static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { int error; if ((rman_get_flags(res) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; /* We depend here on rman_activate_resource() being idempotent. */ error = rman_activate_resource(res); if (error) return (error); #ifdef INTRNG error = intr_setup_irq(child, res, filt, intr, arg, flags, cookiep); #else error = arm_setup_intr(device_get_nameunit(child), filt, intr, arg, rman_get_start(res), flags, cookiep); #endif return (error); }
static int nexus_activate_resource(device_t bus __unused, device_t child __unused, int type, int rid __unused, struct resource *r) { if (type == SYS_RES_MEMORY) { vm_offset_t start; void *p; start = (vm_offset_t) rman_get_start(r); if (bootverbose) printf("nexus mapdev: start %zx, len %ld\n", start, rman_get_size(r)); p = pmap_mapdev(start, (vm_size_t) rman_get_size(r)); if (p == NULL) return (ENOMEM); rman_set_virtual(r, p); rman_set_bustag(r, &bs_be_tag); rman_set_bushandle(r, (u_long)p); } return (rman_activate_resource(r)); }
static int nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { int error; if (r == NULL) panic("%s: NULL interrupt resource!", __func__); if ((rman_get_flags(r) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; /* We depend here on rman_activate_resource() being idempotent. */ error = rman_activate_resource(r); if (error) return (error); error = powerpc_setup_intr(device_get_nameunit(child), rman_get_start(r), filt, intr, arg, flags, cookiep); return (error); }
t_Error XX_FreeIntr(uintptr_t irq) { device_t dev; struct resource *r; r = (struct resource *)irq; dev = rman_get_device(r); irq = rman_get_start(r); /* Handle preallocated interrupts */ if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) { if (XX_IntrInfo[irq].handler == NULL) return (E_INVALID_STATE); XX_IntrInfo[irq].handler = NULL; XX_IntrInfo[irq].arg = NULL; return (E_OK); } return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie)); }
static int ndis_alloc_amem(struct ndis_softc *sc) { int error, rid = NDIS_AM_RID; sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); if (sc->ndis_res_am == NULL) { device_printf(sc->ndis_dev, "failed to allocate attribute memory\n"); return (ENXIO); } sc->ndis_rescnt++; resource_list_add(&sc->ndis_rl, SYS_RES_MEMORY, rid, rman_get_start(sc->ndis_res_am), rman_get_end(sc->ndis_res_am), rman_get_size(sc->ndis_res_am)); error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), sc->ndis_dev, rid, 0, NULL); if (error) { device_printf(sc->ndis_dev, "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error); return (error); } error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); if (error) { device_printf(sc->ndis_dev, "CARD_SET_RES_FLAGS() returned 0x%x\n", error); return (error); } sc->ndis_am_rid = rid; return (0); }
static int ata_isa_probe(device_t dev) { struct resource *io = NULL, *ctlio = NULL; u_long tmp; int rid; /* check isapnp ids */ if (ISA_PNP_PROBE(device_get_parent(dev), dev, ata_ids) == ENXIO) return ENXIO; /* allocate the io port range */ rid = ATA_IOADDR_RID; if (!(io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, ATA_IOSIZE, RF_ACTIVE))) return ENXIO; /* set the altport range */ if (bus_get_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, &tmp, &tmp)) { bus_set_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, rman_get_start(io) + ATA_CTLOFFSET, ATA_CTLIOSIZE); } /* allocate the altport range */ rid = ATA_CTLADDR_RID; if (!(ctlio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, ATA_CTLIOSIZE, RF_ACTIVE))) { bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); return ENXIO; } /* Release resources to reallocate on attach. */ bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlio); bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); return (ata_probe(dev)); }
static int simplebus_setup_intr(device_t bus, device_t child, struct resource *res, int flags, driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep) { struct simplebus_devinfo *di; enum intr_trigger trig; enum intr_polarity pol; int error, rid; if (device_get_parent(child) != bus) return (ECHILD); di = device_get_ivars(child); if (di == NULL) return (ENXIO); if (res == NULL) return (EINVAL); rid = rman_get_rid(res); if (rid >= DI_MAX_INTR_NUM) return (ENOENT); trig = di->di_intr_sl[rid].trig; pol = di->di_intr_sl[rid].pol; if (trig != INTR_TRIGGER_CONFORM || pol != INTR_POLARITY_CONFORM) { error = bus_generic_config_intr(bus, rman_get_start(res), trig, pol); if (error) return (error); } error = bus_generic_setup_intr(bus, child, res, flags, filter, ihand, arg, cookiep); return (error); }
static int obio_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_filter_t *filt, driver_intr_t *handler, void *arg, void **cookiep) { struct obio_softc *sc = device_get_softc(dev); struct intr_event *event; int irq, ip_bit, error, mask, mask_register; irq = rman_get_start(ires); if (irq >= NIRQS) panic("%s: bad irq %d", __func__, irq); event = sc->sc_eventstab[irq]; if (event == NULL) { error = intr_event_create(&event, (void *)irq, 0, irq, obio_mask_irq, obio_unmask_irq, NULL, NULL, "obio intr%d:", irq); sc->sc_eventstab[irq] = event; } intr_event_add_handler(event, device_get_nameunit(child), filt, handler, arg, intr_priority(flags), flags, cookiep); /* unmask IRQ */ mask_register = ICU_IRQ_MASK_REG(irq); ip_bit = ICU_IP_BIT(irq); mask = ICU_REG_READ(mask_register); ICU_REG_WRITE(mask_register, mask & ~ip_bit); return (0); }
/** * omap_activate_resource * * * */ static int omap_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { #if 0 struct omap3_softc *sc = device_get_softc(dev); const struct hwvtrans *vtrans; uint32_t start = rman_get_start(r); uint32_t size = rman_get_size(r); if (type == SYS_RES_MEMORY) { vtrans = omap3_gethwvtrans(start, size); if (vtrans == NULL) { /* NB: should not happen */ device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n", __func__, start, size); return (ENOENT); } rman_set_bustag(r, sc->sc_iot); rman_set_bushandle(r, vtrans->vbase + (start - vtrans->hwbase)); } #endif return (rman_activate_resource(r)); }
static int iobus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { struct iobus_softc *sc; void *p; sc = device_get_softc(bus); if (type == SYS_RES_IRQ) return (bus_activate_resource(bus, type, rid, res)); if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_addr, (vm_size_t)rman_get_size(res)); if (p == NULL) return (ENOMEM); rman_set_virtual(res, p); rman_set_bustag(res, &bs_le_tag); rman_set_bushandle(res, (u_long)p); } return (rman_activate_resource(res)); }
static int nexus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { int err; bus_addr_t paddr; bus_size_t psize; bus_space_handle_t vaddr; if ((err = rman_activate_resource(r)) != 0) return (err); /* * If this is a memory resource, map it into the kernel. */ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { paddr = (bus_addr_t)rman_get_start(r); psize = (bus_size_t)rman_get_size(r); err = bus_space_map(&memmap_bus, paddr, psize, 0, &vaddr); if (err != 0) { rman_deactivate_resource(r); return (err); } rman_set_bustag(r, &memmap_bus); rman_set_virtual(r, (void *)vaddr); rman_set_bushandle(r, vaddr); } else if (type == SYS_RES_IRQ) { err = intr_activate_irq(child, r); if (err != 0) { rman_deactivate_resource(r); return (err); } } return (0); }
static int pxa_smi_attach(device_t dev) { int error, i, dunit; const char *dname; struct pxa_smi_softc *sc; sc = (struct pxa_smi_softc *)device_get_softc(dev); error = bus_alloc_resources(dev, pxa_smi_spec, sc->ps_res); if (error) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } sc->ps_mem.rm_type = RMAN_ARRAY; sc->ps_mem.rm_descr = device_get_nameunit(dev); if (rman_init(&sc->ps_mem) != 0) panic("pxa_smi_attach: failed to init mem rman"); if (rman_manage_region(&sc->ps_mem, 0, PXA2X0_CS_SIZE * 6) != 0) panic("pxa_smi_attach: failed ot set up mem rman"); sc->ps_bst = base_tag; sc->ps_base = rman_get_start(sc->ps_res[0]); i = 0; while (resource_find_match(&i, &dname, &dunit, "at", device_get_nameunit(dev)) == 0) { pxa_smi_add_device(dev, dname, dunit); } bus_generic_probe(dev); bus_generic_attach(dev); return (0); }
static int nexus_setup_intr(device_t bus, device_t child, struct resource *res, int flags, driver_filter_t *ifilt, driver_intr_t *ihand, void *arg, void **cookiep) { int error; *cookiep = NULL; /* somebody tried to setup an irq that failed to allocate! */ if (res == NULL) return (EINVAL); if ((rman_get_flags(res) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; /* We depend on rman_activate_resource() being idempotent. */ error = rman_activate_resource(res); if (error) return (error); error = powerpc_setup_intr(device_get_nameunit(child), rman_get_start(res), ifilt, ihand, arg, flags, cookiep); return (error); }
int smc_probe(device_t dev) { int rid, type, error; uint16_t val; struct smc_softc *sc; struct resource *reg; sc = device_get_softc(dev); rid = 0; type = SYS_RES_IOPORT; error = 0; if (sc->smc_usemem) type = SYS_RES_MEMORY; reg = bus_alloc_resource(dev, type, &rid, 0, ~0, 16, RF_ACTIVE); if (reg == NULL) { if (bootverbose) device_printf(dev, "could not allocate I/O resource for probe\n"); return (ENXIO); } /* Check for the identification value in the BSR. */ val = bus_read_2(reg, BSR); if ((val & BSR_IDENTIFY_MASK) != BSR_IDENTIFY) { if (bootverbose) device_printf(dev, "identification value not in BSR\n"); error = ENXIO; goto done; } /* * Try switching banks and make sure we still get the identification * value. */ bus_write_2(reg, BSR, 0); val = bus_read_2(reg, BSR); if ((val & BSR_IDENTIFY_MASK) != BSR_IDENTIFY) { if (bootverbose) device_printf(dev, "identification value not in BSR after write\n"); error = ENXIO; goto done; } #if 0 /* Check the BAR. */ bus_write_2(reg, BSR, 1); val = bus_read_2(reg, BAR); val = BAR_ADDRESS(val); if (rman_get_start(reg) != val) { if (bootverbose) device_printf(dev, "BAR address %x does not match " "I/O resource address %lx\n", val, rman_get_start(reg)); error = ENXIO; goto done; } #endif /* Compare REV against known chip revisions. */ bus_write_2(reg, BSR, 3); val = bus_read_2(reg, REV); val = (val & REV_CHIP_MASK) >> REV_CHIP_SHIFT; if (smc_chip_ids[val] == NULL) { if (bootverbose) device_printf(dev, "Unknown chip revision: %d\n", val); error = ENXIO; goto done; } device_set_desc(dev, smc_chip_ids[val]); done: bus_release_resource(dev, type, rid, reg); return (error); }
/* * Attach all the sub-devices we can find */ static int aha_isa_attach(device_t dev) { struct aha_softc *aha = device_get_softc(dev); int error = ENOMEM; aha->dev = dev; aha->portrid = 0; aha->port = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &aha->portrid, AHA_NREGS, RF_ACTIVE); if (!aha->port) { device_printf(dev, "Unable to allocate I/O ports\n"); goto fail; } aha->irqrid = 0; aha->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &aha->irqrid, RF_ACTIVE); if (!aha->irq) { device_printf(dev, "Unable to allocate excluse use of irq\n"); goto fail; } aha->drqrid = 0; aha->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &aha->drqrid, RF_ACTIVE); if (!aha->drq) { device_printf(dev, "Unable to allocate drq\n"); goto fail; } #if 0 /* is the drq ever unset? */ if (dev->id_drq != -1) isa_dmacascade(dev->id_drq); #endif isa_dmacascade(rman_get_start(aha->drq)); /* Allocate our parent dmatag */ if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignemnt */ 1, /* boundary */ 0, /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, /* nsegments */ ~0, /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, /* flags */ 0, /* lockfunc */ NULL, /* lockarg */ NULL, &aha->parent_dmat) != 0) { device_printf(dev, "dma tag create failed.\n"); goto fail; } if (aha_init(aha)) { device_printf(dev, "init failed\n"); goto fail; } /* * The 1542A and B look the same. So we guess based on * the firmware revision. It appears that only rev 0 is on * the A cards. */ if (aha->boardid <= BOARD_1542 && aha->fw_major == 0) { device_printf(dev, "154xA may not work\n"); aha->ccb_sg_opcode = INITIATOR_SG_CCB; aha->ccb_ccb_opcode = INITIATOR_CCB; } error = aha_attach(aha); if (error) { device_printf(dev, "attach failed\n"); goto fail; } error = bus_setup_intr(dev, aha->irq, INTR_TYPE_CAM|INTR_ENTROPY| INTR_MPSAFE, NULL, aha_intr, aha, &aha->ih); if (error) { device_printf(dev, "Unable to register interrupt handler\n"); aha_detach(aha); goto fail; } return (0); fail: ; aha_free(aha); bus_free_resource(dev, SYS_RES_IOPORT, aha->port); bus_free_resource(dev, SYS_RES_IRQ, aha->irq); bus_free_resource(dev, SYS_RES_DRQ, aha->drq); return (error); }
/* * Check if the device can be found at the port given */ static int aha_isa_probe(device_t dev) { /* * find unit and check we have that many defined */ struct aha_softc *aha = device_get_softc(dev); int error; u_long port_start; int port_rid; int drq; int irq; config_data_t config_data; aha->dev = dev; /* Check isapnp ids */ if (ISA_PNP_PROBE(device_get_parent(dev), dev, aha_ids) == ENXIO) return (ENXIO); port_rid = 0; aha->port = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &port_rid, AHA_NREGS, RF_ACTIVE); if (aha->port == NULL) return (ENXIO); port_start = rman_get_start(aha->port); aha_alloc(aha); /* See if there is really a card present */ if (aha_probe(aha) || aha_fetch_adapter_info(aha)) { aha_free(aha); bus_release_resource(dev, SYS_RES_IOPORT, port_rid, aha->port); return (ENXIO); } /* * Determine our IRQ, and DMA settings and * export them to the configuration system. */ error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, (uint8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT); if (error != 0) { device_printf(dev, "Could not determine IRQ or DMA " "settings for adapter at %#jx. Failing probe\n", (uintmax_t)port_start); aha_free(aha); bus_release_resource(dev, SYS_RES_IOPORT, port_rid, aha->port); return (ENXIO); } bus_release_resource(dev, SYS_RES_IOPORT, port_rid, aha->port); aha->port = NULL; switch (config_data.dma_chan) { case DMA_CHAN_5: drq = 5; break; case DMA_CHAN_6: drq = 6; break; case DMA_CHAN_7: drq = 7; break; default: device_printf(dev, "Invalid DMA setting for adapter at %#jx.", (uintmax_t)port_start); return (ENXIO); } error = bus_set_resource(dev, SYS_RES_DRQ, 0, drq, 1); if (error) return error; irq = ffs(config_data.irq) + 8; error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); return (error); }
/*---------------------------------------------------------------------------* * attach for ISA PnP cards *---------------------------------------------------------------------------*/ static int isic_pnp_attach(device_t dev) { u_int32_t vend_id = isa_get_vendorid(dev); /* vendor id */ unsigned int unit = device_get_unit(dev); /* get unit */ const char *name = device_get_desc(dev); /* get description */ struct l1_softc *sc = 0; /* softc */ void *ih = 0; /* a dummy */ int ret; /* see if we are out of bounds */ if(unit >= ISIC_MAXUNIT) { printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n", unit, unit, name); return ENXIO; } /* get information structure for this unit */ sc = &l1_sc[unit]; /* get io_base */ if(!(sc->sc_resources.io_base[0] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[0], 0UL, ~0UL, 1, RF_ACTIVE ) )) { printf("isic_pnp_attach: Couldn't get my io_base.\n"); return ENXIO; } /* will not be used for pnp devices */ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); /* get irq, release io_base if we don't get it */ if(!(sc->sc_resources.irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_resources.irq_rid, 0UL, ~0UL, 1, RF_ACTIVE))) { printf("isic%d: Could not get irq.\n",unit); isic_detach_common(dev); return ENXIO; } /* not needed */ sc->sc_irq = rman_get_start(sc->sc_resources.irq); /* set flag so we know what this card is */ ret = ENXIO; switch(vend_id) { #if defined(TEL_S0_16_3_P) || defined(CRTX_S0_P) || defined(COMPAQ_M610) case VID_TEL163PNP: sc->sc_cardtyp = CARD_TYPEP_163P; ret = isic_attach_Cs0P(dev); break; case VID_CREATIXPP: sc->sc_cardtyp = CARD_TYPEP_CS0P; ret = isic_attach_Cs0P(dev); break; case VID_COMPAQ_M610: sc->sc_cardtyp = CARD_TYPEP_COMPAQ_M610; ret = isic_attach_Cs0P(dev); break; #endif #ifdef DYNALINK case VID_DYNALINK: sc->sc_cardtyp = CARD_TYPEP_DYNALINK; ret = isic_attach_Dyn(dev); break; #endif #ifdef SEDLBAUER case VID_SEDLBAUER: sc->sc_cardtyp = CARD_TYPEP_SWS; ret = isic_attach_sws(dev); break; #endif #ifdef DRN_NGO case VID_NICCYGO: sc->sc_cardtyp = CARD_TYPEP_DRNNGO; ret = isic_attach_drnngo(dev); break; #endif #ifdef ELSA_QS1ISA case VID_ELSAQS1P: sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA; ret = isic_attach_Eqs1pi(dev); break; #endif #ifdef ITKIX1 case VID_ITK0025: sc->sc_cardtyp = CARD_TYPEP_ITKIX1; ret = isic_attach_itkix1(dev); break; #endif #ifdef SIEMENS_ISURF2 case VID_SIESURF2: sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2; ret = isic_attach_siemens_isurf(dev); break; #endif #ifdef ASUSCOM_IPAC case VID_ASUSCOM_IPAC: sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC; ret = isic_attach_asi(dev); break; #endif #ifdef EICON_DIVA case VID_EICON_DIVA_20: sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; ret = isic_attach_diva(dev); break; case VID_EICON_DIVA_202: sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; ret = isic_attach_diva_ipac(dev); break; #endif default: printf("isic%d: Error, no driver for %s\n", unit, name); ret = ENXIO; break; } if(ret) { isic_detach_common(dev); return ENXIO; } if(isic_attach_common(dev)) { /* unset flag */ sc->sc_cardtyp = CARD_TYPEP_UNK; /* free irq here, it hasn't been attached yet */ bus_release_resource(dev,SYS_RES_IRQ,sc->sc_resources.irq_rid, sc->sc_resources.irq); sc->sc_resources.irq = 0; isic_detach_common(dev); return ENXIO; } else { /* setup intr routine */ bus_setup_intr(dev,sc->sc_resources.irq,INTR_TYPE_NET, (void(*)(void*))isicintr, sc,&ih); return 0; } }
static int pci_ioctl(struct dev_ioctl_args *ap) { device_t pcidev, brdev; void *confdata; const char *name; struct devlist *devlist_head; struct pci_conf_io *cio; struct pci_devinfo *dinfo; struct pci_io *io; struct pci_bar_io *bio; struct pci_match_conf *pattern_buf; struct resource_list_entry *rle; uint32_t value; size_t confsz, iolen, pbufsz; int error, ionum, i, num_patterns; #ifdef PRE7_COMPAT struct pci_conf_old conf_old; struct pci_io iodata; struct pci_io_old *io_old; struct pci_match_conf_old *pattern_buf_old; io_old = NULL; pattern_buf_old = NULL; if (!(ap->a_fflag & FWRITE) && ap->a_cmd != PCIOCGETBAR && ap->a_cmd != PCIOCGETCONF && ap->a_cmd != PCIOCGETCONF_OLD) return EPERM; #else if (!(ap->a_fflag & FWRITE) && ap->a_cmd != PCIOCGETBAR && ap->a_cmd != PCIOCGETCONF) return EPERM; #endif switch(ap->a_cmd) { #ifdef PRE7_COMPAT case PCIOCGETCONF_OLD: /* FALLTHROUGH */ #endif case PCIOCGETCONF: cio = (struct pci_conf_io *)ap->a_data; pattern_buf = NULL; num_patterns = 0; dinfo = NULL; cio->num_matches = 0; /* * If the user specified an offset into the device list, * but the list has changed since they last called this * ioctl, tell them that the list has changed. They will * have to get the list from the beginning. */ if ((cio->offset != 0) && (cio->generation != pci_generation)){ cio->status = PCI_GETCONF_LIST_CHANGED; error = 0; break; } /* * Check to see whether the user has asked for an offset * past the end of our list. */ if (cio->offset >= pci_numdevs) { cio->status = PCI_GETCONF_LAST_DEVICE; error = 0; break; } /* get the head of the device queue */ devlist_head = &pci_devq; /* * Determine how much room we have for pci_conf structures. * Round the user's buffer size down to the nearest * multiple of sizeof(struct pci_conf) in case the user * didn't specify a multiple of that size. */ #ifdef PRE7_COMPAT if (ap->a_cmd == PCIOCGETCONF_OLD) confsz = sizeof(struct pci_conf_old); else #endif confsz = sizeof(struct pci_conf); iolen = min(cio->match_buf_len - (cio->match_buf_len % confsz), pci_numdevs * confsz); /* * Since we know that iolen is a multiple of the size of * the pciconf union, it's okay to do this. */ ionum = iolen / confsz; /* * If this test is true, the user wants the pci_conf * structures returned to match the supplied entries. */ if ((cio->num_patterns > 0) && (cio->num_patterns < pci_numdevs) && (cio->pat_buf_len > 0)) { /* * pat_buf_len needs to be: * num_patterns * sizeof(struct pci_match_conf) * While it is certainly possible the user just * allocated a large buffer, but set the number of * matches correctly, it is far more likely that * their kernel doesn't match the userland utility * they're using. It's also possible that the user * forgot to initialize some variables. Yes, this * may be overly picky, but I hazard to guess that * it's far more likely to just catch folks that * updated their kernel but not their userland. */ #ifdef PRE7_COMPAT if (ap->a_cmd == PCIOCGETCONF_OLD) pbufsz = sizeof(struct pci_match_conf_old); else #endif pbufsz = sizeof(struct pci_match_conf); if (cio->num_patterns * pbufsz != cio->pat_buf_len) { /* The user made a mistake, return an error. */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; break; } /* * Allocate a buffer to hold the patterns. */ #ifdef PRE7_COMPAT if (ap->a_cmd == PCIOCGETCONF_OLD) { pattern_buf_old = kmalloc(cio->pat_buf_len, M_TEMP, M_WAITOK); error = copyin(cio->patterns, pattern_buf_old, cio->pat_buf_len); } else #endif { pattern_buf = kmalloc(cio->pat_buf_len, M_TEMP, M_WAITOK); error = copyin(cio->patterns, pattern_buf, cio->pat_buf_len); } if (error != 0) { error = EINVAL; goto getconfexit; } num_patterns = cio->num_patterns; } else if ((cio->num_patterns > 0) || (cio->pat_buf_len > 0)) { /* * The user made a mistake, spit out an error. */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; break; } /* * Go through the list of devices and copy out the devices * that match the user's criteria. */ for (cio->num_matches = 0, error = 0, i = 0, dinfo = STAILQ_FIRST(devlist_head); (dinfo != NULL) && (cio->num_matches < ionum) && (error == 0) && (i < pci_numdevs) && (dinfo != NULL); dinfo = STAILQ_NEXT(dinfo, pci_links), i++) { if (i < cio->offset) continue; /* Populate pd_name and pd_unit */ name = NULL; if (dinfo->cfg.dev) name = device_get_name(dinfo->cfg.dev); if (name) { strncpy(dinfo->conf.pd_name, name, sizeof(dinfo->conf.pd_name)); dinfo->conf.pd_name[PCI_MAXNAMELEN] = 0; dinfo->conf.pd_unit = device_get_unit(dinfo->cfg.dev); } else { dinfo->conf.pd_name[0] = '\0'; dinfo->conf.pd_unit = 0; } #ifdef PRE7_COMPAT if ((ap->a_cmd == PCIOCGETCONF_OLD && (pattern_buf_old == NULL || pci_conf_match_old(pattern_buf_old, num_patterns, &dinfo->conf) == 0)) || (ap->a_cmd == PCIOCGETCONF && (pattern_buf == NULL || pci_conf_match(pattern_buf, num_patterns, &dinfo->conf) == 0))) { #else if (pattern_buf == NULL || pci_conf_match(pattern_buf, num_patterns, &dinfo->conf) == 0) { #endif /* * If we've filled up the user's buffer, * break out at this point. Since we've * got a match here, we'll pick right back * up at the matching entry. We can also * tell the user that there are more matches * left. */ if (cio->num_matches >= ionum) break; #ifdef PRE7_COMPAT if (ap->a_cmd == PCIOCGETCONF_OLD) { conf_old.pc_sel.pc_bus = dinfo->conf.pc_sel.pc_bus; conf_old.pc_sel.pc_dev = dinfo->conf.pc_sel.pc_dev; conf_old.pc_sel.pc_func = dinfo->conf.pc_sel.pc_func; conf_old.pc_hdr = dinfo->conf.pc_hdr; conf_old.pc_subvendor = dinfo->conf.pc_subvendor; conf_old.pc_subdevice = dinfo->conf.pc_subdevice; conf_old.pc_vendor = dinfo->conf.pc_vendor; conf_old.pc_device = dinfo->conf.pc_device; conf_old.pc_class = dinfo->conf.pc_class; conf_old.pc_subclass = dinfo->conf.pc_subclass; conf_old.pc_progif = dinfo->conf.pc_progif; conf_old.pc_revid = dinfo->conf.pc_revid; strncpy(conf_old.pd_name, dinfo->conf.pd_name, sizeof(conf_old.pd_name)); conf_old.pd_name[PCI_MAXNAMELEN] = 0; conf_old.pd_unit = dinfo->conf.pd_unit; confdata = &conf_old; } else #endif confdata = &dinfo->conf; /* Only if we can copy it out do we count it. */ if (!(error = copyout(confdata, (caddr_t)cio->matches + confsz * cio->num_matches, confsz))) cio->num_matches++; } } /* * Set the pointer into the list, so if the user is getting * n records at a time, where n < pci_numdevs, */ cio->offset = i; /* * Set the generation, the user will need this if they make * another ioctl call with offset != 0. */ cio->generation = pci_generation; /* * If this is the last device, inform the user so he won't * bother asking for more devices. If dinfo isn't NULL, we * know that there are more matches in the list because of * the way the traversal is done. */ if (dinfo == NULL) cio->status = PCI_GETCONF_LAST_DEVICE; else cio->status = PCI_GETCONF_MORE_DEVS; getconfexit: if (pattern_buf != NULL) kfree(pattern_buf, M_TEMP); #ifdef PRE7_COMPAT if (pattern_buf_old != NULL) kfree(pattern_buf_old, M_TEMP); #endif break; #ifdef PRE7_COMPAT case PCIOCREAD_OLD: case PCIOCWRITE_OLD: io_old = (struct pci_io_old *)ap->a_data; iodata.pi_sel.pc_domain = 0; iodata.pi_sel.pc_bus = io_old->pi_sel.pc_bus; iodata.pi_sel.pc_dev = io_old->pi_sel.pc_dev; iodata.pi_sel.pc_func = io_old->pi_sel.pc_func; iodata.pi_reg = io_old->pi_reg; iodata.pi_width = io_old->pi_width; iodata.pi_data = io_old->pi_data; ap->a_data = (caddr_t)&iodata; /* FALLTHROUGH */ #endif case PCIOCREAD: case PCIOCWRITE: io = (struct pci_io *)ap->a_data; switch(io->pi_width) { case 4: case 2: case 1: /* Make sure register is in bounds and aligned. */ if (io->pi_reg < 0 || io->pi_reg + io->pi_width > PCI_REGMAX + 1 || io->pi_reg & (io->pi_width - 1)) { error = EINVAL; break; } /* * Assume that the user-level bus number is * in fact the physical PCI bus number. * Look up the grandparent, i.e. the bridge device, * so that we can issue configuration space cycles. */ pcidev = pci_find_dbsf(io->pi_sel.pc_domain, io->pi_sel.pc_bus, io->pi_sel.pc_dev, io->pi_sel.pc_func); if (pcidev) { brdev = device_get_parent( device_get_parent(pcidev)); #ifdef PRE7_COMPAT if (ap->a_cmd == PCIOCWRITE || ap->a_cmd == PCIOCWRITE_OLD) #else if (ap->a_cmd == PCIOCWRITE) #endif PCIB_WRITE_CONFIG(brdev, io->pi_sel.pc_bus, io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg, io->pi_data, io->pi_width); #ifdef PRE7_COMPAT else if (ap->a_cmd == PCIOCREAD_OLD) io_old->pi_data = PCIB_READ_CONFIG(brdev, io->pi_sel.pc_bus, io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg, io->pi_width); #endif else io->pi_data = PCIB_READ_CONFIG(brdev, io->pi_sel.pc_bus, io->pi_sel.pc_dev, io->pi_sel.pc_func, io->pi_reg, io->pi_width); error = 0; } else { #ifdef COMPAT_FREEBSD4 if (cmd == PCIOCREAD_OLD) { io_old->pi_data = -1; error = 0; } else #endif error = ENODEV; } break; default: error = EINVAL; break; } break; case PCIOCGETBAR: bio = (struct pci_bar_io *)ap->a_data; /* * Assume that the user-level bus number is * in fact the physical PCI bus number. */ pcidev = pci_find_dbsf(bio->pbi_sel.pc_domain, bio->pbi_sel.pc_bus, bio->pbi_sel.pc_dev, bio->pbi_sel.pc_func); if (pcidev == NULL) { error = ENODEV; break; } dinfo = device_get_ivars(pcidev); /* * Look for a resource list entry matching the requested BAR. * * XXX: This will not find BARs that are not initialized, but * maybe that is ok? */ rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, bio->pbi_reg); if (rle == NULL) rle = resource_list_find(&dinfo->resources, SYS_RES_IOPORT, bio->pbi_reg); if (rle == NULL || rle->res == NULL) { error = EINVAL; break; } /* * Ok, we have a resource for this BAR. Read the lower * 32 bits to get any flags. */ value = pci_read_config(pcidev, bio->pbi_reg, 4); if (PCI_BAR_MEM(value)) { if (rle->type != SYS_RES_MEMORY) { error = EINVAL; break; } value &= ~PCIM_BAR_MEM_BASE; } else { if (rle->type != SYS_RES_IOPORT) { error = EINVAL; break; } value &= ~PCIM_BAR_IO_BASE; } bio->pbi_base = rman_get_start(rle->res) | value; bio->pbi_length = rman_get_size(rle->res); /* * Check the command register to determine if this BAR * is enabled. */ value = pci_read_config(pcidev, PCIR_COMMAND, 2); if (rle->type == SYS_RES_MEMORY) bio->pbi_enabled = (value & PCIM_CMD_MEMEN) != 0; else bio->pbi_enabled = (value & PCIM_CMD_PORTEN) != 0; error = 0; break; default: error = ENOTTY; break; } return (error); } #define PCI_CDEV 78 struct dev_ops pcic_ops = { { "pci", PCI_CDEV, 0 }, .d_open = pci_open, .d_close = pci_close, .d_ioctl = pci_ioctl, };
static int cs4281_pci_attach(device_t dev) { struct sc_info *sc; struct ac97_info *codec = NULL; char status[SND_STATUSLEN]; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); sc->dev = dev; sc->type = pci_get_devid(dev); pci_enable_busmaster(dev); #if __FreeBSD_version > 500000 if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { /* Reset the power state. */ device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", pci_get_powerstate(dev)); pci_set_powerstate(dev, PCI_POWERSTATE_D0); } #else data = pci_read_config(dev, CS4281PCI_PMCS_OFFSET, 4); if (data & CS4281PCI_PMCS_PS_MASK) { /* Reset the power state. */ device_printf(dev, "chip is in D%d power mode " "-- setting to D0\n", data & CS4281PCI_PMCS_PS_MASK); pci_write_config(dev, CS4281PCI_PMCS_OFFSET, data & ~CS4281PCI_PMCS_PS_MASK, 4); } #endif sc->regid = PCIR_BAR(0); sc->regtype = SYS_RES_MEMORY; sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE); if (!sc->reg) { sc->regtype = SYS_RES_IOPORT; sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE); if (!sc->reg) { device_printf(dev, "unable to allocate register space\n"); goto bad; } } sc->st = rman_get_bustag(sc->reg); sc->sh = rman_get_bushandle(sc->reg); sc->memid = PCIR_BAR(1); sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->memid, 0, ~0, CS4281PCI_BA1_SIZE, RF_ACTIVE); if (sc->mem == NULL) { device_printf(dev, "unable to allocate fifo space\n"); goto bad; } sc->irqid = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, RF_ACTIVE | RF_SHAREABLE); if (!sc->irq) { device_printf(dev, "unable to allocate interrupt\n"); goto bad; } if (snd_setup_intr(dev, sc->irq, 0, cs4281_intr, sc, &sc->ih)) { device_printf(dev, "unable to setup interrupt\n"); goto bad; } sc->bufsz = pcm_getbuffersize(dev, 4096, CS4281_DEFAULT_BUFSZ, 65536); if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, &sc->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } /* power up */ cs4281_power(sc, 0); /* init chip */ if (cs4281_init(sc) == -1) { device_printf(dev, "unable to initialize the card\n"); goto bad; } /* create/init mixer */ codec = AC97_CREATE(dev, sc, cs4281_ac97); if (codec == NULL) goto bad; mixer_init(dev, ac97_getmixerclass(), codec); if (pcm_register(dev, sc, 1, 1)) goto bad; pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc); pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc); snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s", (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cs4281)); pcm_setstatus(dev, status); return 0; bad: if (codec) ac97_destroy(codec); if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); if (sc->mem) bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem); if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat); free(sc, M_DEVBUF); return ENXIO; }
int ata_command(struct ata_device *atadev, u_int8_t command, u_int64_t lba, u_int16_t count, u_int8_t feature, int flags) { int error = 0; #ifdef ATA_DEBUG ata_prtdev(atadev, "ata_command: addr=%04lx, cmd=%02x, " "lba=%lld, count=%d, feature=%d, flags=%02x\n", rman_get_start(atadev->channel->r_io), command, lba, count, feature, flags); #endif /* select device */ ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); /* disable interrupt from device */ if (atadev->channel->flags & ATA_QUEUED) ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT); /* ready to issue command ? */ if (ata_wait(atadev, 0) < 0) { ata_prtdev(atadev, "timeout sending command=%02x s=%02x e=%02x\n", command, atadev->channel->status, atadev->channel->error); return -1; } /* only use 48bit addressing if needed because of the overhead */ if ((lba >= 268435455 || count > 256) && atadev->param && atadev->param->support.address48) { ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, (feature>>8) & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, feature); ATA_OUTB(atadev->channel->r_io, ATA_COUNT, (count>>8) & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_COUNT, count & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, (lba>>24) & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, lba & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>32) & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>8) & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>40) & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>16) & 0xff); ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_LBA | atadev->unit); /* translate command into 48bit version */ switch (command) { case ATA_C_READ: command = ATA_C_READ48; break; case ATA_C_READ_MUL: command = ATA_C_READ_MUL48; break; case ATA_C_READ_DMA: command = ATA_C_READ_DMA48; break; case ATA_C_READ_DMA_QUEUED: command = ATA_C_READ_DMA_QUEUED48; break; case ATA_C_WRITE: command = ATA_C_WRITE48; break; case ATA_C_WRITE_MUL: command = ATA_C_WRITE_MUL48; break; case ATA_C_WRITE_DMA: command = ATA_C_WRITE_DMA48; break; case ATA_C_WRITE_DMA_QUEUED: command = ATA_C_WRITE_DMA_QUEUED48; break; case ATA_C_FLUSHCACHE: command = ATA_C_FLUSHCACHE48; break; default: ata_prtdev(atadev, "can't translate cmd to 48bit version\n"); return -1; } }
int ppc_probe(device_t dev) { #ifdef __i386__ static short next_bios_ppc = 0; #endif struct ppc_data *ppc; int error; u_long port; /* * Allocate the ppc_data structure. */ ppc = DEVTOSOFTC(dev); bzero(ppc, sizeof(struct ppc_data)); ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0; ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0; /* retrieve ISA parameters */ error = bus_get_resource(dev, SYS_RES_IOPORT, 0, &port, NULL); #ifdef __i386__ /* * If port not specified, use bios list. */ if (error) { if((next_bios_ppc < BIOS_MAX_PPC) && (*(BIOS_PORTS+next_bios_ppc) != 0) ) { port = *(BIOS_PORTS+next_bios_ppc++); if (bootverbose) device_printf(dev, "parallel port found at 0x%x\n", (int) port); } else { device_printf(dev, "parallel port not found.\n"); return ENXIO; } bus_set_resource(dev, SYS_RES_IOPORT, 0, port, IO_LPTSIZE_EXTENDED); } #endif #ifdef __alpha__ /* * There isn't a bios list on alpha. Put it in the usual place. */ if (error) { bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc, IO_LPTSIZE_NORMAL); } #endif /* IO port is mandatory */ /* Try "extended" IO port range...*/ ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &ppc->rid_ioport, 0, ~0, IO_LPTSIZE_EXTENDED, RF_ACTIVE); if (ppc->res_ioport != 0) { if (bootverbose) device_printf(dev, "using extended I/O port range\n"); } else { /* Failed? If so, then try the "normal" IO port range... */ ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &ppc->rid_ioport, 0, ~0, IO_LPTSIZE_NORMAL, RF_ACTIVE); if (ppc->res_ioport != 0) { if (bootverbose) device_printf(dev, "using normal I/O port range\n"); } else { device_printf(dev, "cannot reserve I/O port range\n"); goto error; } } ppc->ppc_base = rman_get_start(ppc->res_ioport); ppc->bsh = rman_get_bushandle(ppc->res_ioport); ppc->bst = rman_get_bustag(ppc->res_ioport); ppc->ppc_flags = device_get_flags(dev); if (!(ppc->ppc_flags & 0x20)) { ppc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ppc->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE); ppc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, &ppc->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE); } if (ppc->res_irq) ppc->ppc_irq = rman_get_start(ppc->res_irq); if (ppc->res_drq) ppc->ppc_dmachan = rman_get_start(ppc->res_drq); ppc->ppc_unit = device_get_unit(dev); ppc->ppc_model = GENERIC; ppc->ppc_mode = PPB_COMPATIBLE; ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4; ppc->ppc_type = PPC_TYPE_GENERIC; /* * Try to detect the chipset and its mode. */ if (ppc_detect(ppc, ppc->ppc_flags & 0xf)) goto error; return (0); error: if (ppc->res_irq != 0) { bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq, ppc->res_irq); } if (ppc->res_ioport != 0) { bus_deactivate_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport, ppc->res_ioport); bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport, ppc->res_ioport); } if (ppc->res_drq != 0) { bus_deactivate_resource(dev, SYS_RES_DRQ, ppc->rid_drq, ppc->res_drq); bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq, ppc->res_drq); } return (ENXIO); }
static int agp_nvidia_attach (device_t dev) { struct agp_nvidia_softc *sc = device_get_softc(dev); struct agp_gatt *gatt; u_int32_t apbase; u_int32_t aplimit; u_int32_t temp; int size; int i; int error; switch (pci_get_device(dev)) { case NVIDIA_DEVICEID_NFORCE: sc->wbc_mask = 0x00010000; break; case NVIDIA_DEVICEID_NFORCE2: sc->wbc_mask = 0x80000000; break; default: device_printf(dev, "Bad chip id\n"); return (ENODEV); } /* AGP Controller */ sc->dev = dev; /* Memory Controller 1 */ sc->mc1_dev = pci_find_bsf(pci_get_bus(dev), 0, 1); if (sc->mc1_dev == NULL) { device_printf(dev, "Unable to find NVIDIA Memory Controller 1.\n"); return (ENODEV); } /* Memory Controller 2 */ sc->mc2_dev = pci_find_bsf(pci_get_bus(dev), 0, 2); if (sc->mc2_dev == NULL) { device_printf(dev, "Unable to find NVIDIA Memory Controller 2.\n"); return (ENODEV); } /* AGP Host to PCI Bridge */ sc->bdev = pci_find_bsf(pci_get_bus(dev), 30, 0); if (sc->bdev == NULL) { device_printf(dev, "Unable to find NVIDIA AGP Host to PCI Bridge.\n"); return (ENODEV); } error = agp_generic_attach(dev); if (error) return (error); sc->initial_aperture = AGP_GET_APERTURE(dev); if (sc->initial_aperture == 0) { device_printf(dev, "bad initial aperture size, disabling\n"); return ENXIO; } for (;;) { gatt = agp_alloc_gatt(dev); if (gatt) break; /* * Probably contigmalloc failure. Try reducing the * aperture so that the gatt size reduces. */ if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) goto fail; } sc->gatt = gatt; apbase = rman_get_start(sc->agp.as_aperture); aplimit = apbase + AGP_GET_APERTURE(dev) - 1; pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APBASE, apbase, 4); pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APLIMIT, aplimit, 4); pci_write_config(sc->bdev, AGP_NVIDIA_3_APBASE, apbase, 4); pci_write_config(sc->bdev, AGP_NVIDIA_3_APLIMIT, aplimit, 4); error = nvidia_init_iorr(apbase, AGP_GET_APERTURE(dev)); if (error) { device_printf(dev, "Failed to setup IORRs\n"); goto fail; } /* directory size is 64k */ size = AGP_GET_APERTURE(dev) / 1024 / 1024; sc->num_dirs = size / 64; sc->num_active_entries = (size == 32) ? 16384 : ((size * 1024) / 4); sc->pg_offset = 0; if (sc->num_dirs == 0) { sc->num_dirs = 1; sc->num_active_entries /= (64 / size); sc->pg_offset = (apbase & (64 * 1024 * 1024 - 1) & ~(AGP_GET_APERTURE(dev) - 1)) / PAGE_SIZE; } /* (G)ATT Base Address */ for (i = 0; i < 8; i++) { pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_ATTBASE(i), (sc->gatt->ag_physical + (i % sc->num_dirs) * 64 * 1024) | 1, 4); } /* GTLB Control */ temp = pci_read_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, 4); pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, temp | 0x11, 4); /* GART Control */ temp = pci_read_config(sc->dev, AGP_NVIDIA_0_APSIZE, 4); pci_write_config(sc->dev, AGP_NVIDIA_0_APSIZE, temp | 0x100, 4); return (0); fail: agp_generic_detach(dev); return (ENOMEM); }
static struct resource * lbc_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct lbc_softc *sc; struct lbc_devinfo *di; struct resource_list_entry *rle; struct resource *res; struct rman *rm; int needactivate; /* We only support default allocations. */ if (start != 0ul || end != ~0ul) return (NULL); sc = device_get_softc(bus); if (type == SYS_RES_IRQ) return (bus_alloc_resource(bus, type, rid, start, end, count, flags)); /* * Request for the default allocation with a given rid: use resource * list stored in the local device info. */ if ((di = device_get_ivars(child)) == NULL) return (NULL); if (type == SYS_RES_IOPORT) type = SYS_RES_MEMORY; rid = &di->di_bank; rle = resource_list_find(&di->di_res, type, *rid); if (rle == NULL) { device_printf(bus, "no default resources for " "rid = %d, type = %d\n", *rid, type); return (NULL); } start = rle->start; count = rle->count; end = start + count - 1; sc = device_get_softc(bus); needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; rm = &sc->sc_rman; res = rman_reserve_resource(rm, start, end, count, flags, child); if (res == NULL) { device_printf(bus, "failed to reserve resource %#lx - %#lx " "(%#lx)\n", start, end, count); return (NULL); } rman_set_rid(res, *rid); rman_set_bustag(res, &bs_be_tag); rman_set_bushandle(res, rman_get_start(res)); if (needactivate) if (bus_activate_resource(child, type, *rid, res)) { device_printf(child, "resource activation failed\n"); rman_release_resource(res); return (NULL); } return (res); }
static int iir_pci_attach(device_t dev) { struct gdt_softc *gdt; struct resource *irq = NULL; int retries, rid, error = 0; void *ih; u_int8_t protocol; gdt = device_get_softc(dev); mtx_init(&gdt->sc_lock, "iir", NULL, MTX_DEF); /* map DPMEM */ rid = PCI_DPMEM; gdt->sc_dpmem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (gdt->sc_dpmem == NULL) { device_printf(dev, "can't allocate register resources\n"); error = ENOMEM; goto err; } /* get IRQ */ rid = 0; irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE); if (irq == NULL) { device_printf(dev, "can't find IRQ value\n"); error = ENOMEM; goto err; } gdt->sc_devnode = dev; gdt->sc_init_level = 0; gdt->sc_hanum = device_get_unit(dev); gdt->sc_bus = pci_get_bus(dev); gdt->sc_slot = pci_get_slot(dev); gdt->sc_vendor = pci_get_vendor(dev); gdt->sc_device = pci_get_device(dev); gdt->sc_subdevice = pci_get_subdevice(dev); gdt->sc_class = GDT_MPR; /* no FC ctr. if (gdt->sc_device >= GDT_PCI_PRODUCT_FC) gdt->sc_class |= GDT_FC; */ /* initialize RP controller */ /* check and reset interface area */ bus_write_4(gdt->sc_dpmem, GDT_MPR_IC, htole32(GDT_MPR_MAGIC)); if (bus_read_4(gdt->sc_dpmem, GDT_MPR_IC) != htole32(GDT_MPR_MAGIC)) { device_printf(dev, "cannot access DPMEM at 0x%lx (shadowed?)\n", rman_get_start(gdt->sc_dpmem)); error = ENXIO; goto err; } bus_set_region_4(gdt->sc_dpmem, GDT_I960_SZ, htole32(0), GDT_MPR_SZ >> 2); /* Disable everything */ bus_write_1(gdt->sc_dpmem, GDT_EDOOR_EN, bus_read_1(gdt->sc_dpmem, GDT_EDOOR_EN) | 4); bus_write_1(gdt->sc_dpmem, GDT_MPR_EDOOR, 0xff); bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0); bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_CMD_INDEX, 0); bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO, htole32(rman_get_start(gdt->sc_dpmem))); bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_CMD_INDX, 0xff); bus_write_1(gdt->sc_dpmem, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_read_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS) != 0xff) { if (--retries == 0) { device_printf(dev, "DEINIT failed\n"); error = ENXIO; goto err; } DELAY(1); } protocol = (uint8_t)le32toh(bus_read_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO)); bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0); if (protocol != GDT_PROTOCOL_VERSION) { device_printf(dev, "unsupported protocol %d\n", protocol); error = ENXIO; goto err; } /* special command to controller BIOS */ bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO, htole32(0)); bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), htole32(0)); bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), htole32(1)); bus_write_4(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), htole32(0)); bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_CMD_INDX, 0xfe); bus_write_1(gdt->sc_dpmem, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_read_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { if (--retries == 0) { device_printf(dev, "initialization error\n"); error = ENXIO; goto err; } DELAY(1); } bus_write_1(gdt->sc_dpmem, GDT_MPR_IC + GDT_S_STATUS, 0); gdt->sc_ic_all_size = GDT_MPR_SZ; gdt->sc_copy_cmd = gdt_mpr_copy_cmd; gdt->sc_get_status = gdt_mpr_get_status; gdt->sc_intr = gdt_mpr_intr; gdt->sc_release_event = gdt_mpr_release_event; gdt->sc_set_sema0 = gdt_mpr_set_sema0; gdt->sc_test_busy = gdt_mpr_test_busy; /* Allocate a dmatag representing the capabilities of this attachment */ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignemnt*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/BUS_SPACE_UNRESTRICTED, /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&gdt->sc_lock, &gdt->sc_parent_dmat) != 0) { error = ENXIO; goto err; } gdt->sc_init_level++; if (iir_init(gdt) != 0) { iir_free(gdt); error = ENXIO; goto err; } /* Register with the XPT */ iir_attach(gdt); /* associate interrupt handler */ if (bus_setup_intr(dev, irq, INTR_TYPE_CAM | INTR_MPSAFE, NULL, iir_intr, gdt, &ih )) { device_printf(dev, "Unable to register interrupt handler\n"); error = ENXIO; goto err; } gdt_pci_enable_intr(gdt); return (0); err: if (irq) bus_release_resource( dev, SYS_RES_IRQ, 0, irq ); if (gdt->sc_dpmem) bus_release_resource( dev, SYS_RES_MEMORY, rid, gdt->sc_dpmem ); mtx_destroy(&gdt->sc_lock); return (error); }
int puc_bfe_attach(device_t dev) { char buffer[64]; struct puc_bar *bar; struct puc_port *port; struct puc_softc *sc; struct rman *rm; intptr_t res; bus_addr_t ofs, start; bus_size_t size; bus_space_handle_t bsh; bus_space_tag_t bst; int error, idx; sc = device_get_softc(dev); for (idx = 0; idx < PUC_PCI_BARS; idx++) sc->sc_bar[idx].b_rid = -1; do { sc->sc_ioport.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_ioport); if (!error) { sc->sc_iomem.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_iomem); if (!error) { sc->sc_irq.rm_type = RMAN_ARRAY; error = rman_init(&sc->sc_irq); if (!error) break; rman_fini(&sc->sc_iomem); } rman_fini(&sc->sc_ioport); } return (error); } while (0); snprintf(buffer, sizeof(buffer), "%s I/O port mapping", device_get_nameunit(dev)); sc->sc_ioport.rm_descr = strdup(buffer, M_PUC); snprintf(buffer, sizeof(buffer), "%s I/O memory mapping", device_get_nameunit(dev)); sc->sc_iomem.rm_descr = strdup(buffer, M_PUC); snprintf(buffer, sizeof(buffer), "%s port numbers", device_get_nameunit(dev)); sc->sc_irq.rm_descr = strdup(buffer, M_PUC); error = puc_config(sc, PUC_CFG_GET_NPORTS, 0, &res); KASSERT(error == 0, ("%s %d", __func__, __LINE__)); sc->sc_nports = (int)res; sc->sc_port = malloc(sc->sc_nports * sizeof(struct puc_port), M_PUC, M_WAITOK|M_ZERO); error = rman_manage_region(&sc->sc_irq, 1, sc->sc_nports); if (error) goto fail; error = puc_config(sc, PUC_CFG_SETUP, 0, &res); if (error) goto fail; for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; port->p_nr = idx + 1; error = puc_config(sc, PUC_CFG_GET_TYPE, idx, &res); if (error) goto fail; port->p_type = res; error = puc_config(sc, PUC_CFG_GET_RID, idx, &res); if (error) goto fail; bar = puc_get_bar(sc, res); if (bar == NULL) { error = ENXIO; goto fail; } port->p_bar = bar; start = rman_get_start(bar->b_res); error = puc_config(sc, PUC_CFG_GET_OFS, idx, &res); if (error) goto fail; ofs = res; error = puc_config(sc, PUC_CFG_GET_LEN, idx, &res); if (error) goto fail; size = res; rm = (bar->b_type == SYS_RES_IOPORT) ? &sc->sc_ioport: &sc->sc_iomem; port->p_rres = rman_reserve_resource(rm, start + ofs, start + ofs + size - 1, size, 0, NULL); if (port->p_rres != NULL) { bsh = rman_get_bushandle(bar->b_res); bst = rman_get_bustag(bar->b_res); bus_space_subregion(bst, bsh, ofs, size, &bsh); rman_set_bushandle(port->p_rres, bsh); rman_set_bustag(port->p_rres, bst); } port->p_ires = rman_reserve_resource(&sc->sc_irq, port->p_nr, port->p_nr, 1, 0, NULL); if (port->p_ires == NULL) { error = ENXIO; goto fail; } error = puc_config(sc, PUC_CFG_GET_CLOCK, idx, &res); if (error) goto fail; port->p_rclk = res; port->p_dev = device_add_child(dev, NULL, -1); if (port->p_dev != NULL) device_set_ivars(port->p_dev, (void *)port); } error = puc_config(sc, PUC_CFG_GET_ILR, 0, &res); if (error) goto fail; sc->sc_ilr = res; if (bootverbose && sc->sc_ilr != 0) device_printf(dev, "using interrupt latch register\n"); sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE|RF_SHAREABLE); if (sc->sc_ires != NULL) { error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY, puc_intr, NULL, sc, &sc->sc_icookie); if (error) error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE, NULL, (driver_intr_t *)puc_intr, sc, &sc->sc_icookie); else sc->sc_fastintr = 1; if (error) { device_printf(dev, "could not activate interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); sc->sc_ires = NULL; } } if (sc->sc_ires == NULL) { /* XXX no interrupt resource. Force polled mode. */ sc->sc_polled = 1; } /* Probe and attach our children. */ for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; if (port->p_dev == NULL) continue; error = device_probe_and_attach(port->p_dev); if (error) { device_delete_child(dev, port->p_dev); port->p_dev = NULL; } } /* * If there are no serdev devices, then our interrupt handler * will do nothing. Tear it down. */ if (sc->sc_serdevs == 0UL) bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); return (0); fail: for (idx = 0; idx < sc->sc_nports; idx++) { port = &sc->sc_port[idx]; if (port->p_dev != NULL) device_delete_child(dev, port->p_dev); if (port->p_rres != NULL) rman_release_resource(port->p_rres); if (port->p_ires != NULL) rman_release_resource(port->p_ires); } for (idx = 0; idx < PUC_PCI_BARS; idx++) { bar = &sc->sc_bar[idx]; if (bar->b_res != NULL) bus_release_resource(sc->sc_dev, bar->b_type, bar->b_rid, bar->b_res); } rman_fini(&sc->sc_irq); free(__DECONST(void *, sc->sc_irq.rm_descr), M_PUC); rman_fini(&sc->sc_iomem); free(__DECONST(void *, sc->sc_iomem.rm_descr), M_PUC); rman_fini(&sc->sc_ioport); free(__DECONST(void *, sc->sc_ioport.rm_descr), M_PUC); free(sc->sc_port, M_PUC); return (error); }
static struct resource * cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start, int *rid) { struct resource *res; uint32_t space; space = *start & PCIM_CIS_ASI_MASK; switch (space) { case PCIM_CIS_ASI_CONFIG: DEVPRINTF((cbdev, "CIS in PCI config space\n")); /* CIS in PCI config space need no initialization */ return (CIS_CONFIG_SPACE); case PCIM_CIS_ASI_BAR0: case PCIM_CIS_ASI_BAR1: case PCIM_CIS_ASI_BAR2: case PCIM_CIS_ASI_BAR3: case PCIM_CIS_ASI_BAR4: case PCIM_CIS_ASI_BAR5: *rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0); DEVPRINTF((cbdev, "CIS in BAR %#x\n", *rid)); break; case PCIM_CIS_ASI_ROM: *rid = PCIR_BIOS; DEVPRINTF((cbdev, "CIS in option rom\n")); break; default: device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n", space); return (NULL); } /* allocate the memory space to read CIS */ res = bus_alloc_resource_any(child, SYS_RES_MEMORY, rid, rman_make_alignment_flags(4096) | RF_ACTIVE); if (res == NULL) { device_printf(cbdev, "Unable to allocate resource " "to read CIS.\n"); return (NULL); } DEVPRINTF((cbdev, "CIS Mapped to %#lx\n", rman_get_start(res))); /* Flip to the right ROM image if CIS is in ROM */ if (space == PCIM_CIS_ASI_ROM) { uint32_t imagesize; uint32_t imagebase = 0; uint32_t pcidata; uint16_t romsig; int romnum = 0; int imagenum; imagenum = (*start & PCIM_CIS_ROM_MASK) >> 28; for (romnum = 0;; romnum++) { romsig = bus_read_2(res, imagebase + CARDBUS_EXROM_SIGNATURE); if (romsig != 0xaa55) { device_printf(cbdev, "Bad header in rom %d: " "[%x] %04x\n", romnum, imagebase + CARDBUS_EXROM_SIGNATURE, romsig); cardbus_read_tuple_finish(cbdev, child, *rid, res); *rid = 0; return (NULL); } /* * If this was the Option ROM image that we were * looking for, then we are done. */ if (romnum == imagenum) break; /* Find out where the next Option ROM image is */ pcidata = imagebase + bus_read_2(res, imagebase + CARDBUS_EXROM_DATA_PTR); imagesize = bus_read_2(res, pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH); if (imagesize == 0) { /* * XXX some ROMs seem to have this as zero, * can we assume this means 1 block? */ device_printf(cbdev, "Warning, size of Option " "ROM image %d is 0 bytes, assuming 512 " "bytes.\n", romnum); imagesize = 1; } /* Image size is in 512 byte units */ imagesize <<= 9; if ((bus_read_1(res, pcidata + CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) { device_printf(cbdev, "Cannot find CIS in " "Option ROM\n"); cardbus_read_tuple_finish(cbdev, child, *rid, res); *rid = 0; return (NULL); } imagebase += imagesize; } *start = imagebase + (*start & PCIM_CIS_ADDR_MASK); } else {
/* * Probe and vendor-specific initialization routine for SIC boards */ int ed_probe_SIC(device_t dev, int port_rid, int flags) { struct ed_softc *sc = device_get_softc(dev); int error; int i; u_int memsize; u_long pmem; u_char sum; error = ed_alloc_port(dev, 0, ED_SIC_IO_PORTS); if (error) return (error); sc->asic_offset = ED_SIC_ASIC_OFFSET; sc->nic_offset = ED_SIC_NIC_OFFSET; memsize = 16384; /* XXX Needs to allow different msize */ error = ed_alloc_memory(dev, 0, memsize); if (error) return (error); sc->mem_start = 0; sc->mem_size = memsize; pmem = rman_get_start(sc->mem_res); error = ed_isa_mem_ok(dev, pmem, memsize); if (error) return (error); /* Reset card to force it into a known state. */ ed_asic_outb(sc, 0, 0x00); DELAY(100); /* * Here we check the card ROM, if the checksum passes, and the * type code and ethernet address check out, then we know we have * an SIC card. */ ed_asic_outb(sc, 0, 0x81); DELAY(100); sum = bus_space_read_1(sc->mem_bst, sc->mem_bsh, 6); for (i = 0; i < ETHER_ADDR_LEN; i++) sum ^= (sc->enaddr[i] = bus_space_read_1(sc->mem_bst, sc->mem_bsh, i)); #ifdef ED_DEBUG device_printf(dev, "ed_probe_sic: got address %6D\n", sc->enaddr, ":"); #endif if (sum != 0) return (ENXIO); if ((sc->enaddr[0] | sc->enaddr[1] | sc->enaddr[2]) == 0) return (ENXIO); sc->vendor = ED_VENDOR_SIC; sc->type_str = "SIC"; sc->isa16bit = 0; sc->cr_proto = 0; /* * SIC RAM page 0x0000-0x3fff(or 0x7fff) */ ed_asic_outb(sc, 0, 0x80); DELAY(100); error = ed_clear_memory(dev); if (error) return (error); sc->mem_shared = 1; sc->mem_end = sc->mem_start + sc->mem_size; /* * allocate one xmit buffer if < 16k, two buffers otherwise */ if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) sc->txb_cnt = 1; else sc->txb_cnt = 2; sc->tx_page_start = 0; sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt; sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE; sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; sc->sc_write_mbufs = ed_shmem_write_mbufs; return (0); }
static int ata_cbus_attach(device_t dev) { struct ata_cbus_controller *ctlr = device_get_softc(dev); device_t child; int rid, unit; /* allocate resources */ rid = ATA_IOADDR_RID; if (!(ctlr->io = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &rid, ATA_PC98_IOSIZE, RF_ACTIVE))) return ENOMEM; rid = ATA_PC98_CTLADDR_RID; if (!(ctlr->ctlio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, rman_get_start(ctlr->io) + ATA_PC98_CTLOFFSET, ~0, ATA_CTLIOSIZE, RF_ACTIVE))) { bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); return ENOMEM; } rid = ATA_PC98_BANKADDR_RID; if (!(ctlr->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, ATA_PC98_BANK, ~0, ATA_PC98_BANKIOSIZE, RF_ACTIVE))) { bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlr->ctlio); return ENOMEM; } rid = ATA_IRQ_RID; if (!(ctlr->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE))) { device_printf(dev, "unable to alloc interrupt\n"); bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlr->ctlio); bus_release_resource(dev, SYS_RES_IOPORT, ATA_PC98_BANKADDR_RID, ctlr->bankio); return ENXIO; } if ((bus_setup_intr(dev, ctlr->irq, ATA_INTR_FLAGS, NULL, ata_cbus_intr, ctlr, &ctlr->ih))) { device_printf(dev, "unable to setup interrupt\n"); bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, ctlr->ctlio); bus_release_resource(dev, SYS_RES_IOPORT, ATA_PC98_BANKADDR_RID, ctlr->bankio); bus_release_resource(dev, SYS_RES_IOPORT, ATA_IRQ_RID, ctlr->irq); return ENXIO; } /* Work around the lack of channel serialization in ATA_CAM. */ ctlr->channels = 1; device_printf(dev, "second channel ignored\n"); for (unit = 0; unit < ctlr->channels; unit++) { child = device_add_child(dev, "ata", unit); 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); }