static int mlx_pci_attach(device_t dev) { struct mlx_softc *sc; struct mlx_ident *m; int error; debug_called(1); pci_enable_busmaster(dev); sc = device_get_softc(dev); sc->mlx_dev = dev; /* * Work out what sort of adapter this is (we need to know this in order * to map the appropriate interface resources). */ m = mlx_pci_match(dev); if (m == NULL) /* shouldn't happen */ return(ENXIO); sc->mlx_iftype = m->iftype; mtx_init(&sc->mlx_io_lock, "mlx I/O", NULL, MTX_DEF); sx_init(&sc->mlx_config_lock, "mlx config"); callout_init_mtx(&sc->mlx_timeout, &sc->mlx_io_lock, 0); /* * Allocate the PCI register window. */ /* type 2/3 adapters have an I/O region we don't prefer at base 0 */ switch(sc->mlx_iftype) { case MLX_IFTYPE_2: case MLX_IFTYPE_3: sc->mlx_mem_type = SYS_RES_MEMORY; sc->mlx_mem_rid = MLX_CFG_BASE1; sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type, &sc->mlx_mem_rid, RF_ACTIVE); if (sc->mlx_mem == NULL) { sc->mlx_mem_type = SYS_RES_IOPORT; sc->mlx_mem_rid = MLX_CFG_BASE0; sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type, &sc->mlx_mem_rid, RF_ACTIVE); } break; case MLX_IFTYPE_4: case MLX_IFTYPE_5: sc->mlx_mem_type = SYS_RES_MEMORY; sc->mlx_mem_rid = MLX_CFG_BASE0; sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type, &sc->mlx_mem_rid, RF_ACTIVE); break; } if (sc->mlx_mem == NULL) { device_printf(sc->mlx_dev, "couldn't allocate mailbox window\n"); mlx_free(sc); return(ENXIO); } /* * Allocate the parent bus DMA tag appropriate for PCI. */ error = bus_dma_tag_create(bus_get_dma_tag(dev), /* PCI parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ BUS_SPACE_UNRESTRICTED, /* nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->mlx_parent_dmat); if (error != 0) { device_printf(dev, "can't allocate parent DMA tag\n"); mlx_free(sc); return(ENOMEM); } /* * Do bus-independant initialisation. */ error = mlx_attach(sc); if (error != 0) { mlx_free(sc); return(error); } /* * Start the controller. */ mlx_startup(sc); return(0); }
static int ida_eisa_attach(device_t dev) { struct ida_softc *ida; struct ida_board *board; int error; int rid; ida = device_get_softc(dev); ida->dev = dev; board = ida_eisa_match(eisa_get_id(dev)); ida->cmd = *board->accessor; ida->flags = board->flags; mtx_init(&ida->lock, "ida", NULL, MTX_DEF); callout_init_mtx(&ida->ch, &ida->lock, 0); ida->regs_res_type = SYS_RES_IOPORT; ida->regs_res_id = 0; ida->regs = bus_alloc_resource_any(dev, ida->regs_res_type, &ida->regs_res_id, RF_ACTIVE); if (ida->regs == NULL) { device_printf(dev, "can't allocate register resources\n"); return (ENOMEM); } error = bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignment */ 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, /* maxsegsize */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ BUS_DMA_ALLOCNOW, /* lockfunc */ NULL, /* lockarg */ NULL, &ida->parent_dmat); if (error != 0) { device_printf(dev, "can't allocate DMA tag\n"); ida_free(ida); return (ENOMEM); } rid = 0; ida->irq_res_type = SYS_RES_IRQ; ida->irq = bus_alloc_resource_any(dev, ida->irq_res_type, &rid, RF_ACTIVE | RF_SHAREABLE); if (ida->irq == NULL) { ida_free(ida); return (ENOMEM); } error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, ida_intr, ida, &ida->ih); if (error) { device_printf(dev, "can't setup interrupt\n"); ida_free(ida); return (ENOMEM); } error = ida_setup(ida); if (error) { ida_free(ida); return (error); } return (0); }
static int ath_ahb_attach(device_t dev) { struct ath_ahb_softc *psc = device_get_softc(dev); struct ath_softc *sc = &psc->sc_sc; int error = ENXIO; int rid; long eepromaddr; uint8_t *p; sc->sc_dev = dev; rid = 0; psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (psc->sc_sr == NULL) { device_printf(dev, "cannot map register space\n"); goto bad; } if (resource_long_value(device_get_name(dev), device_get_unit(dev), "eepromaddr", &eepromaddr) != 0) { device_printf(dev, "cannot fetch 'eepromaddr' from hints\n"); goto bad0; } rid = 0; device_printf(sc->sc_dev, "eeprom @ %p\n", (void *) eepromaddr); psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr, (uintptr_t) eepromaddr + (uintptr_t) ((ATH_EEPROM_DATA_SIZE * 2) - 1), 0, RF_ACTIVE); if (psc->sc_eeprom == NULL) { device_printf(dev, "cannot map eeprom space\n"); goto bad0; } /* XXX uintptr_t is a bandaid for ia64; to be fixed */ sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr); sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); /* * Mark device invalid so any interrupts (shared or otherwise) * that arrive before the HAL is setup are discarded. */ sc->sc_invalid = 1; /* Copy the EEPROM data out */ sc->sc_eepromdata = malloc(ATH_EEPROM_DATA_SIZE * 2, M_TEMP, M_NOWAIT | M_ZERO); if (sc->sc_eepromdata == NULL) { device_printf(dev, "cannot allocate memory for eeprom data\n"); goto bad1; } device_printf(sc->sc_dev, "eeprom data @ %p\n", (void *) rman_get_bushandle(psc->sc_eeprom)); /* XXX why doesn't this work? -adrian */ #if 0 bus_space_read_multi_1( rman_get_bustag(psc->sc_eeprom), rman_get_bushandle(psc->sc_eeprom), 0, (u_int8_t *) sc->sc_eepromdata, ATH_EEPROM_DATA_SIZE * 2); #endif p = (void *) rman_get_bushandle(psc->sc_eeprom); memcpy(sc->sc_eepromdata, p, ATH_EEPROM_DATA_SIZE * 2); /* * Arrange interrupt line. */ rid = 0; psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE); if (psc->sc_irq == NULL) { device_printf(dev, "could not map interrupt\n"); goto bad1; } if (bus_setup_intr(dev, psc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ath_intr, sc, &psc->sc_ih)) { device_printf(dev, "could not establish interrupt\n"); goto bad2; } /* * Setup DMA descriptor area. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ 0x3ffff, /* maxsize XXX */ ATH_MAX_SCATTER, /* nsegments */ 0x3ffff, /* maxsegsize XXX */ BUS_DMA_ALLOCNOW, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->sc_dmat)) { device_printf(dev, "cannot allocate DMA tag\n"); goto bad3; } ATH_LOCK_INIT(sc); error = ath_attach(AR9130_DEVID, sc); if (error == 0) /* success */ return 0; ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); bad2: bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); bad1: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); bad0: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); bad: /* XXX?! */ if (sc->sc_eepromdata) free(sc->sc_eepromdata, M_TEMP); return (error); }
static int dpt_pci_attach (device_t dev) { dpt_softc_t * dpt; int error = 0; dpt = device_get_softc(dev); dpt->dev = dev; dpt_alloc(dev); #ifdef DPT_ALLOW_MMIO dpt->io_rid = DPT_PCI_MEMADDR; dpt->io_type = SYS_RES_MEMORY; dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, &dpt->io_rid, RF_ACTIVE); #endif if (dpt->io_res == NULL) { dpt->io_rid = DPT_PCI_IOADDR; dpt->io_type = SYS_RES_IOPORT; dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, &dpt->io_rid, RF_ACTIVE); } if (dpt->io_res == NULL) { device_printf(dev, "can't allocate register resources\n"); error = ENOMEM; goto bad; } dpt->io_offset = 0x10; dpt->irq_rid = 0; dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid, RF_ACTIVE | RF_SHAREABLE); if (dpt->irq_res == NULL) { device_printf(dev, "No irq?!\n"); error = ENOMEM; goto bad; } /* Ensure busmastering is enabled */ pci_enable_busmaster(dev); if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) { #ifdef DPT_DEBUG_WARN device_printf(dev, "Mapped as an IDE controller. " "Disabling SCSI setup\n"); #endif error = ENXIO; goto bad; } /* Allocate a dmatag representing the capabilities of this attachment */ if (bus_dma_tag_create( /* PCI 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 */ ~0, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ NULL, /* lockarg */ NULL, &dpt->parent_dmat) != 0) { error = ENXIO; goto bad; } if (dpt_init(dpt) != 0) { error = ENXIO; goto bad; } /* Register with the XPT */ dpt_attach(dpt); if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) { device_printf(dev, "Unable to register interrupt handler\n"); error = ENXIO; goto bad; } return (error); bad: dpt_release_resources(dev); dpt_free(dpt); return (error); }
static int fm801_pci_attach(device_t dev) { struct ac97_info *codec = 0; struct fm801_info *fm801; int i; int mapped = 0; char status[SND_STATUSLEN]; fm801 = malloc(sizeof(*fm801), M_DEVBUF, M_WAITOK | M_ZERO); fm801->type = pci_get_devid(dev); pci_enable_busmaster(dev); for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) { fm801->regid = PCIR_BAR(i); fm801->regtype = SYS_RES_MEMORY; fm801->reg = bus_alloc_resource_any(dev, fm801->regtype, &fm801->regid, RF_ACTIVE); if(!fm801->reg) { fm801->regtype = SYS_RES_IOPORT; fm801->reg = bus_alloc_resource_any(dev, fm801->regtype, &fm801->regid, RF_ACTIVE); } if(fm801->reg) { fm801->st = rman_get_bustag(fm801->reg); fm801->sh = rman_get_bushandle(fm801->reg); mapped++; } } if (mapped == 0) { device_printf(dev, "unable to map register space\n"); goto oops; } fm801->bufsz = pcm_getbuffersize(dev, 4096, FM801_DEFAULT_BUFSZ, 65536); fm801_init(fm801); codec = AC97_CREATE(dev, fm801, fm801_ac97); if (codec == NULL) goto oops; if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto oops; fm801->irqid = 0; fm801->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fm801->irqid, RF_ACTIVE | RF_SHAREABLE); if (!fm801->irq || snd_setup_intr(dev, fm801->irq, 0, fm801_intr, fm801, &fm801->ih)) { device_printf(dev, "unable to map interrupt\n"); goto oops; } 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*/fm801->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, &fm801->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto oops; } snprintf(status, 64, "at %s 0x%jx irq %jd %s", (fm801->regtype == SYS_RES_IOPORT)? "io" : "memory", rman_get_start(fm801->reg), rman_get_start(fm801->irq),PCM_KLDSTRING(snd_fm801)); #define FM801_MAXPLAYCH 1 if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops; pcm_addchan(dev, PCMDIR_PLAY, &fm801ch_class, fm801); pcm_addchan(dev, PCMDIR_REC, &fm801ch_class, fm801); pcm_setstatus(dev, status); fm801->radio = device_add_child(dev, "radio", -1); bus_generic_attach(dev); return 0; oops: if (codec) ac97_destroy(codec); if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih); if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq); if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat); free(fm801, M_DEVBUF); return ENXIO; }
/* * Attach all the sub-devices we can find */ static int aha_isa_attach(device_t dev) { struct aha_softc *aha = device_get_softc(dev); bus_dma_filter_t *filter; void *filter_arg; bus_addr_t lowaddr; void *ih; int error = ENOMEM; int aha_free_needed = 0; aha->dev = dev; aha->portrid = 0; aha->port = bus_alloc_resource(dev, SYS_RES_IOPORT, &aha->portrid, 0, ~0, 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 */ filter = NULL; filter_arg = NULL; lowaddr = BUS_SPACE_MAXADDR_24BIT; if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignemnt */ 1, /* boundary */ 0, /* lowaddr */ lowaddr, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ filter, /* filterarg */ filter_arg, /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, /* nsegments */ ~0, /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &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; } aha_free_needed++; 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, NULL, aha_intr, aha, &ih); if (error) { device_printf(dev, "Unable to register interrupt handler\n"); goto fail; } return (0); fail: ; 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); if (aha_free_needed) aha_free(aha); return (error); }
static int dma_setup(struct dwmmc_softc *sc) { int error; int nidx; int idx; /* * Set up TX descriptor ring, descriptors, and dma maps. */ error = bus_dma_tag_create( bus_get_dma_tag(sc->dev), /* Parent tag. */ 4096, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ DESC_SIZE, 1, /* maxsize, nsegments */ DESC_SIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->desc_tag); if (error != 0) { device_printf(sc->dev, "could not create ring DMA tag.\n"); return (1); } error = bus_dmamem_alloc(sc->desc_tag, (void**)&sc->desc_ring, BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->desc_map); if (error != 0) { device_printf(sc->dev, "could not allocate descriptor ring.\n"); return (1); } error = bus_dmamap_load(sc->desc_tag, sc->desc_map, sc->desc_ring, DESC_SIZE, dwmmc_get1paddr, &sc->desc_ring_paddr, 0); if (error != 0) { device_printf(sc->dev, "could not load descriptor ring map.\n"); return (1); } for (idx = 0; idx < sc->desc_count; idx++) { sc->desc_ring[idx].des0 = DES0_CH; sc->desc_ring[idx].des1 = 0; nidx = (idx + 1) % sc->desc_count; sc->desc_ring[idx].des3 = sc->desc_ring_paddr + \ (nidx * sizeof(struct idmac_desc)); } error = bus_dma_tag_create( bus_get_dma_tag(sc->dev), /* Parent tag. */ 4096, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->desc_count * MMC_SECTOR_SIZE, /* maxsize */ sc->desc_count, /* nsegments */ MMC_SECTOR_SIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->buf_tag); if (error != 0) { device_printf(sc->dev, "could not create ring DMA tag.\n"); return (1); } error = bus_dmamap_create(sc->buf_tag, 0, &sc->buf_map); if (error != 0) { device_printf(sc->dev, "could not create TX buffer DMA map.\n"); return (1); } return (0); }
static int bcm2835_cpufreq_attach(device_t dev) { struct bcm2835_cpufreq_softc *sc; struct sysctl_oid *oid; int err; /* set self dev */ sc = device_get_softc(dev); sc->dev = dev; /* initial values */ sc->arm_max_freq = -1; sc->arm_min_freq = -1; sc->core_max_freq = -1; sc->core_min_freq = -1; sc->sdram_max_freq = -1; sc->sdram_min_freq = -1; sc->max_voltage_core = 0; sc->min_voltage_core = 0; /* create VC mbox buffer */ sc->dma_size = PAGE_SIZE; err = bus_dma_tag_create( bus_get_dma_tag(sc->dev), PAGE_SIZE, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->dma_size, 1, /* maxsize, nsegments */ sc->dma_size, 0, /* maxsegsize, flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->dma_tag); if (err) { device_printf(dev, "can't create DMA tag\n"); return (ENXIO); } err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->dma_buf, 0, &sc->dma_map); if (err) { bus_dma_tag_destroy(sc->dma_tag); device_printf(dev, "can't allocate dmamem\n"); return (ENXIO); } err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->dma_buf, sc->dma_size, bcm2835_cpufreq_cb, &sc->dma_phys, 0); if (err) { bus_dmamem_free(sc->dma_tag, sc->dma_buf, sc->dma_map); bus_dma_tag_destroy(sc->dma_tag); device_printf(dev, "can't load DMA map\n"); return (ENXIO); } /* OK, ready to use VC buffer */ /* setup sysctl at first device */ if (device_get_unit(dev) == 0) { sysctl_ctx_init(&bcm2835_sysctl_ctx); /* create node for hw.cpufreq */ oid = SYSCTL_ADD_NODE(&bcm2835_sysctl_ctx, SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "cpufreq", CTLFLAG_RD, NULL, ""); /* Frequency (Hz) */ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "arm_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_arm_freq, "IU", "ARM frequency (Hz)"); SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "core_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_core_freq, "IU", "Core frequency (Hz)"); SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "sdram_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_sdram_freq, "IU", "SDRAM frequency (Hz)"); /* Turbo state */ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "turbo", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_turbo, "IU", "Disables dynamic clocking"); /* Voltage (offset from 1.2V in units of 0.025V) */ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "voltage_core", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_voltage_core, "I", "ARM/GPU core voltage" "(offset from 1.2V in units of 0.025V)"); SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "voltage_sdram", CTLTYPE_INT | CTLFLAG_WR, sc, 0, sysctl_bcm2835_cpufreq_voltage_sdram, "I", "SDRAM voltage (offset from 1.2V in units of 0.025V)"); /* Voltage individual SDRAM */ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "voltage_sdram_c", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_voltage_sdram_c, "I", "SDRAM controller voltage" "(offset from 1.2V in units of 0.025V)"); SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "voltage_sdram_i", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_voltage_sdram_i, "I", "SDRAM I/O voltage (offset from 1.2V in units of 0.025V)"); SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "voltage_sdram_p", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bcm2835_cpufreq_voltage_sdram_p, "I", "SDRAM phy voltage (offset from 1.2V in units of 0.025V)"); /* Temperature */ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0, sysctl_bcm2835_cpufreq_temperature, "I", "SoC temperature (thousandths of a degree C)"); } /* ARM->VC lock */ sema_init(&vc_sema, 1, "vcsema"); /* register callback for using mbox when interrupts are enabled */ sc->init_hook.ich_func = bcm2835_cpufreq_init; sc->init_hook.ich_arg = sc; if (config_intrhook_establish(&sc->init_hook) != 0) { bus_dmamap_unload(sc->dma_tag, sc->dma_map); bus_dmamem_free(sc->dma_tag, sc->dma_buf, sc->dma_map); bus_dma_tag_destroy(sc->dma_tag); device_printf(dev, "config_intrhook_establish failed\n"); return (ENOMEM); } /* this device is controlled by cpufreq(4) */ cpufreq_register(dev); return (0); }
static int ahbattach(device_t dev) { /* * find unit and check we have that many defined */ struct ahb_softc *ahb; struct ecb* next_ecb; struct resource *io = 0; struct resource *irq = 0; int rid; void *ih; rid = 0; io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (!io) { device_printf(dev, "No I/O space?!\n"); return ENOMEM; } if ((ahb = ahballoc(dev, io)) == NULL) { goto error_exit2; } if (ahbreset(ahb) != 0) goto error_exit; rid = 0; irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (!irq) { device_printf(dev, "Can't allocate interrupt\n"); goto error_exit; } /* * Create our DMA tags. These tags define the kinds of device * accessible memory allocations and memory mappings we will * need to perform during normal operation. */ /* DMA tag for mapping buffers into device visible space. */ if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignment */ 1, /* boundary */ 0, /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ MAXBSIZE, /* nsegments */ AHB_NSEG, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ BUS_DMA_ALLOCNOW, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &ahb->buffer_dmat) != 0) goto error_exit; ahb->init_level++; /* DMA tag for our ccb structures and ha inquiry data */ if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignment */ 1, /* boundary */ 0, /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ (AHB_NECB * sizeof(struct ecb)) + sizeof(*ahb->ha_inq_data), /* nsegments */ 1, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &ahb->ecb_dmat) != 0) goto error_exit; ahb->init_level++; /* Allocation for our ccbs */ if (bus_dmamem_alloc(ahb->ecb_dmat, (void **)&ahb->ecb_array, BUS_DMA_NOWAIT, &ahb->ecb_dmamap) != 0) goto error_exit; ahb->ha_inq_data = (struct ha_inquiry_data *)&ahb->ecb_array[AHB_NECB]; ahb->init_level++; /* And permanently map them */ bus_dmamap_load(ahb->ecb_dmat, ahb->ecb_dmamap, ahb->ecb_array, AHB_NSEG * sizeof(struct ecb), ahbmapecbs, ahb, /*flags*/0); ahb->init_level++; /* Allocate the buffer dmamaps for each of our ECBs */ bzero(ahb->ecb_array, (AHB_NECB * sizeof(struct ecb)) + sizeof(*ahb->ha_inq_data)); next_ecb = ahb->ecb_array; while (ahb->num_ecbs < AHB_NECB) { u_int32_t ecb_paddr; if (bus_dmamap_create(ahb->buffer_dmat, /*flags*/0, &next_ecb->dmamap)) break; ecb_paddr = ahbecbvtop(ahb, next_ecb); next_ecb->hecb.status_ptr = ahbstatuspaddr(ecb_paddr); next_ecb->hecb.sense_ptr = ahbsensepaddr(ecb_paddr); ahb->num_ecbs++; ahbecbfree(ahb, next_ecb); next_ecb++; } if (ahb->num_ecbs == 0) goto error_exit; ahb->init_level++; /* * Now that we know we own the resources we need, register * our bus with the XPT. */ if (ahbxptattach(ahb)) goto error_exit; /* Enable our interrupt */ if (bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, NULL, ahbintr, ahb, &ih) != 0) goto error_exit; return (0); error_exit: /* * The board's IRQ line will not be left enabled * if we can't intialize correctly, so its safe * to release the irq. */ ahbfree(ahb); error_exit2: if (io) bus_release_resource(dev, SYS_RES_IOPORT, 0, io); if (irq) bus_release_resource(dev, SYS_RES_IRQ, 0, irq); return (-1); }
static int hdspe_alloc_resources(struct sc_info *sc) { /* Allocate resource. */ sc->csid = PCIR_BAR(0); sc->cs = bus_alloc_resource(sc->dev, SYS_RES_MEMORY, &sc->csid, 0, ~0, 1, RF_ACTIVE); if (!sc->cs) { device_printf(sc->dev, "Unable to map SYS_RES_MEMORY.\n"); return (ENXIO); } sc->cst = rman_get_bustag(sc->cs); sc->csh = rman_get_bushandle(sc->cs); /* Allocate interrupt resource. */ sc->irqid = 0; sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); if (!sc->irq || bus_setup_intr(sc->dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV, NULL, hdspe_intr, sc, &sc->ih)) { device_printf(sc->dev, "Unable to alloc interrupt resource.\n"); return (ENXIO); } /* Allocate DMA resources. */ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev), /*alignment*/4, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/2 * HDSPE_DMASEGSIZE, /*nsegments*/2, /*maxsegsz*/HDSPE_DMASEGSIZE, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, /*dmatag*/&sc->dmat) != 0) { device_printf(sc->dev, "Unable to create dma tag.\n"); return (ENXIO); } sc->bufsize = HDSPE_DMASEGSIZE; /* pbuf (play buffer). */ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap)) { device_printf(sc->dev, "Can't alloc pbuf.\n"); return (ENXIO); } if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->bufsize, hdspe_dmapsetmap, sc, 0)) { device_printf(sc->dev, "Can't load pbuf.\n"); return (ENXIO); } /* rbuf (rec buffer). */ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap)) { device_printf(sc->dev, "Can't alloc rbuf.\n"); return (ENXIO); } if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->bufsize, hdspe_dmapsetmap, sc, 0)) { device_printf(sc->dev, "Can't load rbuf.\n"); return (ENXIO); } bzero(sc->pbuf, sc->bufsize); bzero(sc->rbuf, sc->bufsize); return (0); }
static int sbus_attach(device_t dev) { struct sbus_softc *sc; struct sbus_devinfo *sdi; struct sbus_icarg *sica; struct sbus_ranges *range; struct resource *res; struct resource_list *rl; device_t cdev; bus_addr_t intrclr, intrmap, phys; bus_size_t size; u_long vec; phandle_t child, node; uint32_t prop; int i, j; sc = device_get_softc(dev); sc->sc_dev = dev; node = ofw_bus_get_node(dev); i = 0; sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, RF_ACTIVE); if (sc->sc_sysio_res == NULL) panic("%s: cannot allocate device memory", __func__); if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1) panic("%s: cannot get IGN", __func__); sc->sc_ign = INTIGN(prop); sc->sc_cbustag = sbus_alloc_bustag(sc); /* * Record clock frequency for synchronous SCSI. * IS THIS THE CORRECT DEFAULT?? */ if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1) prop = 25000000; sc->sc_clockfreq = prop; prop /= 1000; device_printf(dev, "clock %d.%03d MHz\n", prop / 1000, prop % 1000); /* * Collect address translations from the OBP. */ if ((sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range)) == -1) { panic("%s: error getting ranges property", __func__); } sc->sc_rd = (struct sbus_rd *)malloc(sizeof(*sc->sc_rd) * sc->sc_nrange, M_DEVBUF, M_NOWAIT); if (sc->sc_rd == NULL) panic("%s: cannot allocate rmans", __func__); /* * Preallocate all space that the SBus bridge decodes, so that nothing * else gets in the way; set up rmans etc. */ rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); for (i = 0; i < sc->sc_nrange; i++) { phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32); size = range[i].size; sc->sc_rd[i].rd_slot = range[i].cspace; sc->sc_rd[i].rd_coffset = range[i].coffset; sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size; j = resource_list_add_next(rl, SYS_RES_MEMORY, phys, phys + size - 1, size); if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j, RF_ACTIVE)) == NULL) panic("%s: cannot allocate decoded range", __func__); sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res); sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY; sc->sc_rd[i].rd_rman.rm_descr = "SBus Device Memory"; if (rman_init(&sc->sc_rd[i].rd_rman) != 0 || rman_manage_region(&sc->sc_rd[i].rd_rman, 0, size) != 0) panic("%s: failed to set up memory rman", __func__); sc->sc_rd[i].rd_poffset = phys; sc->sc_rd[i].rd_pend = phys + size; sc->sc_rd[i].rd_res = res; } free(range, M_OFWPROP); /* * Get the SBus burst transfer size if burst transfers are supported. */ if (OF_getprop(node, "up-burst-sizes", &sc->sc_burst, sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0) sc->sc_burst = (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF; /* initalise the IOMMU */ /* punch in our copies */ sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS); sc->sc_is.is_bustag = rman_get_bustag(sc->sc_sysio_res); sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_sysio_res); sc->sc_is.is_iommu = SBR_IOMMU; sc->sc_is.is_dtag = SBR_IOMMU_TLB_TAG_DIAG; sc->sc_is.is_ddram = SBR_IOMMU_TLB_DATA_DIAG; sc->sc_is.is_dqueue = SBR_IOMMU_QUEUE_DIAG; sc->sc_is.is_dva = SBR_IOMMU_SVADIAG; sc->sc_is.is_dtcmp = 0; sc->sc_is.is_sb[0] = SBR_STRBUF; sc->sc_is.is_sb[1] = 0; /* * Note: the SBus IOMMU ignores the high bits of an address, so a NULL * DMA pointer will be translated by the first page of the IOTSB. * To detect bugs we'll allocate and ignore the first entry. */ iommu_init(device_get_nameunit(dev), &sc->sc_is, 3, -1, 1); /* Create the DMA tag. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0) panic("%s: bus_dma_tag_create failed", __func__); /* Customize the tag. */ sc->sc_cdmatag->dt_cookie = &sc->sc_is; sc->sc_cdmatag->dt_mt = &iommu_dma_methods; /* * Hunt through all the interrupt mapping regs and register our * interrupt controller for the corresponding interrupt vectors. * We do this early in order to be able to catch stray interrupts. */ for (i = 0; i <= SBUS_MAX_INO; i++) { if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0) continue; sica = malloc(sizeof(*sica), M_DEVBUF, M_NOWAIT); if (sica == NULL) panic("%s: could not allocate interrupt controller " "argument", __func__); sica->sica_sc = sc; sica->sica_map = intrmap; sica->sica_clr = intrclr; #ifdef SBUS_DEBUG device_printf(dev, "intr map (INO %d, %s) %#lx: %#lx, clr: %#lx\n", i, (i & INTMAP_OBIO_MASK) == 0 ? "SBus slot" : "OBIO", (u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap), (u_long)intrclr); #endif j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i), &sbus_ic, sica); if (j != 0) device_printf(dev, "could not register interrupt " "controller for INO %d (%d)\n", i, j); } /* Enable the over-temperature and power-fail interrupts. */ i = 4; sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE); if (sc->sc_ot_ires == NULL || INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign || INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec || intr_vectors[vec].iv_ic != &sbus_ic || bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_FAST, NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0) panic("%s: failed to set up temperature interrupt", __func__); i = 3; sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE); if (sc->sc_pf_ires == NULL || INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign || INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec || intr_vectors[vec].iv_ic != &sbus_ic || bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_FAST, NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0) panic("%s: failed to set up power fail interrupt", __func__); /* Initialize the counter-timer. */ sparc64_counter_init(device_get_nameunit(dev), rman_get_bustag(sc->sc_sysio_res), rman_get_bushandle(sc->sc_sysio_res), SBR_TC0); /* * Loop through ROM children, fixing any relative addresses * and then configuring each device. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { if ((sdi = sbus_setup_dinfo(dev, sc, child)) == NULL) continue; /* * For devices where there are variants that are actually * split into two SBus devices (as opposed to the first * half of the device being a SBus device and the second * half hanging off of the first one) like 'auxio' and * 'SUNW,fdtwo' or 'dma' and 'esp' probe the SBus device * which is a prerequisite to the driver attaching to the * second one with a lower order. Saves us from dealing * with different probe orders in the respective device * drivers which generally is more hackish. */ cdev = device_add_child_ordered(dev, (OF_child(child) == 0 && sbus_inlist(sdi->sdi_obdinfo.obd_name, sbus_order_first)) ? SBUS_ORDER_FIRST : SBUS_ORDER_NORMAL, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child_ordered failed\n", sdi->sdi_obdinfo.obd_name); sbus_destroy_dinfo(sdi); continue; } device_set_ivars(cdev, sdi); } return (bus_generic_attach(dev)); }
static int ath_ahb_attach(device_t dev) { struct ath_ahb_softc *psc = device_get_softc(dev); struct ath_softc *sc = &psc->sc_sc; int error = ENXIO; int rid; long eepromaddr; int eepromsize; uint8_t *p; int device_id, vendor_id; sc->sc_dev = dev; rid = 0; psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (psc->sc_sr == NULL) { device_printf(dev, "cannot map register space\n"); goto bad; } if (resource_long_value(device_get_name(dev), device_get_unit(dev), "eepromaddr", &eepromaddr) != 0) { device_printf(dev, "cannot fetch 'eepromaddr' from hints\n"); goto bad0; } /* * The default EEPROM size is 2048 * 16 bit words. * Later EEPROM/OTP/flash regions may be quite a bit bigger. */ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "eepromsize", &eepromsize) != 0) { eepromsize = ATH_EEPROM_DATA_SIZE * 2; } rid = 0; device_printf(sc->sc_dev, "eeprom @ %p (%d bytes)\n", (void *) eepromaddr, eepromsize); /* * XXX this assumes that the parent device is the nexus * and will just pass through requests for all of memory. * * Later on, when this has to attach off of the actual * AHB, this won't work. * * Ideally this would be done in machdep code in mips/atheros/ * and it'd expose the EEPROM via the firmware interface, * so the ath/ath_ahb drivers can be loaded as modules * after boot-time. */ psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr, (uintptr_t) eepromaddr + (uintptr_t) (eepromsize - 1), 0, RF_ACTIVE); if (psc->sc_eeprom == NULL) { device_printf(dev, "cannot map eeprom space\n"); goto bad0; } sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr); sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); /* * Mark device invalid so any interrupts (shared or otherwise) * that arrive before the HAL is setup are discarded. */ sc->sc_invalid = 1; /* Copy the EEPROM data out */ sc->sc_eepromdata = malloc(eepromsize, M_TEMP, M_NOWAIT | M_ZERO); if (sc->sc_eepromdata == NULL) { device_printf(dev, "cannot allocate memory for eeprom data\n"); goto bad1; } device_printf(sc->sc_dev, "eeprom data @ %p\n", (void *) rman_get_bushandle(psc->sc_eeprom)); /* XXX why doesn't this work? -adrian */ #if 0 bus_space_read_multi_1( rman_get_bustag(psc->sc_eeprom), rman_get_bushandle(psc->sc_eeprom), 0, (u_int8_t *) sc->sc_eepromdata, eepromsize); #endif p = (void *) rman_get_bushandle(psc->sc_eeprom); memcpy(sc->sc_eepromdata, p, eepromsize); /* * Arrange interrupt line. */ rid = 0; psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE); if (psc->sc_irq == NULL) { device_printf(dev, "could not map interrupt\n"); goto bad1; } if (bus_setup_intr(dev, psc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ath_ahb_intr, sc, &psc->sc_ih)) { device_printf(dev, "could not establish interrupt\n"); goto bad2; } /* * Setup DMA descriptor area. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ 0x3ffff, /* maxsize XXX */ ATH_MAX_SCATTER, /* nsegments */ 0x3ffff, /* maxsegsize XXX */ BUS_DMA_ALLOCNOW, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->sc_dmat)) { device_printf(dev, "cannot allocate DMA tag\n"); goto bad3; } /* * Check if a device/vendor ID is provided in hints. */ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "vendor_id", &vendor_id) != 0) { vendor_id = VENDOR_ATHEROS; } if (resource_int_value(device_get_name(dev), device_get_unit(dev), "device_id", &device_id) != 0) { device_id = AR9130_DEVID; } ATH_LOCK_INIT(sc); ATH_PCU_LOCK_INIT(sc); ATH_RX_LOCK_INIT(sc); ATH_TX_LOCK_INIT(sc); ATH_TX_IC_LOCK_INIT(sc); ATH_TXSTATUS_LOCK_INIT(sc); error = ath_attach(device_id, sc); if (error == 0) /* success */ return 0; ATH_TXSTATUS_LOCK_DESTROY(sc); ATH_RX_LOCK_DESTROY(sc); ATH_TX_LOCK_DESTROY(sc); ATH_TX_IC_LOCK_DESTROY(sc); ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); bad2: bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); bad1: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); bad0: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); bad: /* XXX?! */ if (sc->sc_eepromdata) free(sc->sc_eepromdata, M_TEMP); return (error); }
static int adv_isa_probe(device_t dev) { int port_index; int max_port_index; u_long iobase, iocount, irq; int user_iobase = 0; int rid = 0; void *ih; struct resource *iores, *irqres; /* * We don't know of any PnP ID's for these cards. */ if (isa_get_logicalid(dev) != 0) return (ENXIO); /* * Default to scanning all possible device locations. */ port_index = 0; max_port_index = MAX_ISA_IOPORT_INDEX; if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, &iocount) == 0) { user_iobase = 1; for (;port_index <= max_port_index; port_index++) if (iobase <= adv_isa_ioports[port_index]) break; if ((port_index > max_port_index) || (iobase != adv_isa_ioports[port_index])) { if (bootverbose) device_printf(dev, "Invalid baseport of 0x%lx specified. " "Nearest valid baseport is 0x%x. Failing " "probe.\n", iobase, (port_index <= max_port_index) ? adv_isa_ioports[port_index] : adv_isa_ioports[max_port_index]); return ENXIO; } max_port_index = port_index; } /* Perform the actual probing */ adv_set_isapnp_wait_for_key(); for (;port_index <= max_port_index; port_index++) { u_int16_t port_addr = adv_isa_ioports[port_index]; bus_size_t maxsegsz; bus_size_t maxsize; bus_addr_t lowaddr; int error; struct adv_softc *adv; if (port_addr == 0) /* Already been attached */ continue; if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port_addr, 1)) continue; /* XXX what is the real portsize? */ iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (iores == NULL) continue; if (adv_find_signature(iores) == 0) { bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); continue; } /* * Got one. Now allocate our softc * and see if we can initialize the card. */ adv = adv_alloc(dev, iores, 0); if (adv == NULL) { bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); break; } /* * Stop the chip. */ ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); ADV_OUTW(adv, ADV_CHIP_STATUS, 0); /* * Determine the chip version. */ adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL) && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) { adv->type = ADV_VL; maxsegsz = ADV_VL_MAX_DMA_COUNT; maxsize = BUS_SPACE_MAXSIZE_32BIT; lowaddr = ADV_VL_MAX_DMA_ADDR; bus_delete_resource(dev, SYS_RES_DRQ, 0); } else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA) && (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) { if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) { adv->type = ADV_ISAPNP; ADV_OUTB(adv, ADV_REG_IFC, ADV_IFC_INIT_DEFAULT); } else { adv->type = ADV_ISA; } maxsegsz = ADV_ISA_MAX_DMA_COUNT; maxsize = BUS_SPACE_MAXSIZE_24BIT; lowaddr = ADV_ISA_MAX_DMA_ADDR; adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED; adv->isa_dma_channel = adv_get_isa_dma_channel(adv); bus_set_resource(dev, SYS_RES_DRQ, 0, adv->isa_dma_channel, 1); } else { panic("advisaprobe: Unknown card revision\n"); } /* * Allocate a parent dmatag for all tags created * by the MI portions of the advansys driver */ error = bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignemnt */ 1, /* boundary */ 0, /* lowaddr */ lowaddr, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ maxsize, /* nsegments */ ~0, /* maxsegsz */ maxsegsz, /* flags */ 0, /* lockfunc */ NULL, /* lockarg */ NULL, &adv->parent_dmat); if (error != 0) { device_printf(dev, "Could not allocate DMA tag - error %d\n", error); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); break; } adv->init_level += 2; if (overrun_buf == NULL) { /* Need to allocate our overrun buffer */ if (bus_dma_tag_create( /* parent */ adv->parent_dmat, /* alignment */ 8, /* boundary */ 0, /* lowaddr */ ADV_ISA_MAX_DMA_ADDR, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ ADV_OVERRUN_BSIZE, /* nsegments */ 1, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ NULL, /* lockarg */ NULL, &overrun_dmat) != 0) { adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); break; } if (bus_dmamem_alloc(overrun_dmat, (void **)&overrun_buf, BUS_DMA_NOWAIT, &overrun_dmamap) != 0) { bus_dma_tag_destroy(overrun_dmat); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); break; } /* And permanently map it in */ bus_dmamap_load(overrun_dmat, overrun_dmamap, overrun_buf, ADV_OVERRUN_BSIZE, adv_map, &overrun_physbase, /*flags*/0); } adv->overrun_physbase = overrun_physbase; if (adv_init(adv) != 0) { bus_dmamap_unload(overrun_dmat, overrun_dmamap); bus_dmamem_free(overrun_dmat, overrun_buf, overrun_dmamap); bus_dma_tag_destroy(overrun_dmat); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); break; } switch (adv->type) { case ADV_ISAPNP: if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG) { adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN; adv->fix_asyn_xfer = ~0; } /* Fall Through */ case ADV_ISA: adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT; adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR; adv_set_isa_dma_settings(adv); break; case ADV_VL: adv->max_dma_count = ADV_VL_MAX_DMA_COUNT; adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR; break; default: panic("advisaprobe: Invalid card type\n"); } /* Determine our IRQ */ if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL)) bus_set_resource(dev, SYS_RES_IRQ, 0, adv_get_chip_irq(adv), 1); else adv_set_chip_irq(adv, irq); irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (irqres == NULL || bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY| INTR_MPSAFE, NULL, adv_intr, adv, &ih) != 0) { if (irqres != NULL) bus_release_resource(dev, SYS_RES_IRQ, rid, irqres); bus_dmamap_unload(overrun_dmat, overrun_dmamap); bus_dmamem_free(overrun_dmat, overrun_buf, overrun_dmamap); bus_dma_tag_destroy(overrun_dmat); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); break; } /* Mark as probed */ adv_isa_ioports[port_index] = 0; return 0; } if (user_iobase) bus_set_resource(dev, SYS_RES_IOPORT, 0, iobase, iocount); else bus_delete_resource(dev, SYS_RES_IOPORT, 0); return ENXIO; }
int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller) { int error; device_t device = controller->isci->device; uint32_t max_segment_size = isci_io_request_get_max_io_size(); uint32_t status = 0; struct ISCI_MEMORY *uncached_controller_memory = &controller->uncached_controller_memory; struct ISCI_MEMORY *cached_controller_memory = &controller->cached_controller_memory; struct ISCI_MEMORY *request_memory = &controller->request_memory; POINTER_UINT virtual_address; bus_addr_t physical_address; controller->mdl = sci_controller_get_memory_descriptor_list_handle( controller->scif_controller_handle); uncached_controller_memory->size = sci_mdl_decorator_get_memory_size( controller->mdl, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS); error = isci_allocate_dma_buffer(device, uncached_controller_memory); if (error != 0) return (error); sci_mdl_decorator_assign_memory( controller->mdl, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS, uncached_controller_memory->virtual_address, uncached_controller_memory->physical_address); cached_controller_memory->size = sci_mdl_decorator_get_memory_size( controller->mdl, SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS ); error = isci_allocate_dma_buffer(device, cached_controller_memory); if (error != 0) return (error); sci_mdl_decorator_assign_memory(controller->mdl, SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS, cached_controller_memory->virtual_address, cached_controller_memory->physical_address); request_memory->size = controller->queue_depth * isci_io_request_get_object_size(); error = isci_allocate_dma_buffer(device, request_memory); if (error != 0) return (error); /* For STP PIO testing, we want to ensure we can force multiple SGLs * since this has been a problem area in SCIL. This tunable parameter * will allow us to force DMA segments to a smaller size, ensuring * that even if a physically contiguous buffer is attached to this * I/O, the DMA subsystem will pass us multiple segments in our DMA * load callback. */ TUNABLE_INT_FETCH("hw.isci.max_segment_size", &max_segment_size); /* Create DMA tag for our I/O requests. Then we can create DMA maps based off * of this tag and store them in each of our ISCI_IO_REQUEST objects. This * will enable better performance than creating the DMA maps every time we get * an I/O. */ status = bus_dma_tag_create(bus_get_dma_tag(device), 0x1, 0x0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, isci_io_request_get_max_io_size(), SCI_MAX_SCATTER_GATHER_ELEMENTS, max_segment_size, 0, NULL, NULL, &controller->buffer_dma_tag); sci_pool_initialize(controller->request_pool); virtual_address = request_memory->virtual_address; physical_address = request_memory->physical_address; for (int i = 0; i < controller->queue_depth; i++) { struct ISCI_REQUEST *request = (struct ISCI_REQUEST *)virtual_address; isci_request_construct(request, controller->scif_controller_handle, controller->buffer_dma_tag, physical_address); sci_pool_put(controller->request_pool, request); virtual_address += isci_request_get_object_size(); physical_address += isci_request_get_object_size(); } uint32_t remote_device_size = sizeof(struct ISCI_REMOTE_DEVICE) + scif_remote_device_get_object_size(); controller->remote_device_memory = (uint8_t *) malloc( remote_device_size * SCI_MAX_REMOTE_DEVICES, M_ISCI, M_NOWAIT | M_ZERO); sci_pool_initialize(controller->remote_device_pool); uint8_t *remote_device_memory_ptr = controller->remote_device_memory; for (int i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) { struct ISCI_REMOTE_DEVICE *remote_device = (struct ISCI_REMOTE_DEVICE *)remote_device_memory_ptr; controller->remote_device[i] = NULL; remote_device->index = i; remote_device->is_resetting = FALSE; remote_device->frozen_lun_mask = 0; sci_fast_list_element_init(remote_device, &remote_device->pending_device_reset_element); TAILQ_INIT(&remote_device->queued_ccbs); remote_device->release_queued_ccb = FALSE; remote_device->queued_ccb_in_progress = NULL; /* * For the first SCI_MAX_DOMAINS device objects, do not put * them in the pool, rather assign them to each domain. This * ensures that any device attached directly to port "i" will * always get CAM target id "i". */ if (i < SCI_MAX_DOMAINS) controller->domain[i].da_remote_device = remote_device; else sci_pool_put(controller->remote_device_pool, remote_device); remote_device_memory_ptr += remote_device_size; } return (0); }
static int iir_pci_attach(device_t dev) { struct gdt_softc *gdt; struct resource *io = NULL, *irq = NULL; int retries, rid, error = 0; void *ih; u_int8_t protocol; /* map DPMEM */ rid = PCI_DPMEM; io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (io == 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 = device_get_softc(dev); gdt->sc_devnode = dev; gdt->sc_init_level = 0; gdt->sc_dpmemt = rman_get_bustag(io); gdt->sc_dpmemh = rman_get_bushandle(io); gdt->sc_dpmembase = rman_get_start(io); 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_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC, htole32(GDT_MPR_MAGIC)); if (bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC) != htole32(GDT_MPR_MAGIC)) { printf("cannot access DPMEM at 0x%jx (shadowed?)\n", (uintmax_t)gdt->sc_dpmembase); error = ENXIO; goto err; } bus_space_set_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_I960_SZ, htole32(0), GDT_MPR_SZ >> 2); /* Disable everything */ bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN, bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN) | 4); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_CMD_INDEX, 0); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO, htole32(gdt->sc_dpmembase)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 0xff); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS) != 0xff) { if (--retries == 0) { printf("DEINIT failed\n"); error = ENXIO; goto err; } DELAY(1); } protocol = (uint8_t)le32toh(bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS, 0); if (protocol != GDT_PROTOCOL_VERSION) { printf("unsupported protocol %d\n", protocol); error = ENXIO; goto err; } /* special commnd to controller BIOS */ bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO, htole32(0)); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), htole32(0)); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t), htole32(1)); bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t), htole32(0)); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX, 0xfe); bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1); DELAY(20); retries = GDT_RETRIES; while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS) != 0xfe) { if (--retries == 0) { printf("initialization error\n"); error = ENXIO; goto err; } DELAY(1); } bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 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*/GDT_MAXSG, /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant, &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, 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 (io) bus_release_resource( dev, SYS_RES_MEMORY, rid, io ); */ return (error); }
static int malo_pci_attach(device_t dev) { int error = ENXIO, i, msic, reg; struct malo_pci_softc *psc = device_get_softc(dev); struct malo_softc *sc = &psc->malo_sc; sc->malo_dev = dev; pci_enable_busmaster(dev); /* * Setup memory-mapping of PCI registers. */ psc->malo_mem_spec = malo_res_spec_mem; error = bus_alloc_resources(dev, psc->malo_mem_spec, psc->malo_res_mem); if (error) { device_printf(dev, "couldn't allocate memory resources\n"); return (ENXIO); } /* * Arrange and allocate interrupt line. */ sc->malo_invalid = 1; if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) { msic = pci_msi_count(dev); if (bootverbose) device_printf(dev, "MSI count : %d\n", msic); } else msic = 0; psc->malo_irq_spec = malo_res_spec_legacy; if (msic == MALO_MSI_MESSAGES && msi_disable == 0) { if (pci_alloc_msi(dev, &msic) == 0) { if (msic == MALO_MSI_MESSAGES) { device_printf(dev, "Using %d MSI messages\n", msic); psc->malo_irq_spec = malo_res_spec_msi; psc->malo_msi = 1; } else pci_release_msi(dev); } } error = bus_alloc_resources(dev, psc->malo_irq_spec, psc->malo_res_irq); if (error) { device_printf(dev, "couldn't allocate IRQ resources\n"); goto bad; } if (psc->malo_msi == 0) error = bus_setup_intr(dev, psc->malo_res_irq[0], INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc, &psc->malo_intrhand[0]); else { for (i = 0; i < MALO_MSI_MESSAGES; i++) { error = bus_setup_intr(dev, psc->malo_res_irq[i], INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc, &psc->malo_intrhand[i]); if (error != 0) break; } } /* * Setup DMA descriptor area. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE, /* maxsize */ 0, /* nsegments */ BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->malo_dmat)) { device_printf(dev, "cannot allocate DMA tag\n"); goto bad1; } sc->malo_io0t = rman_get_bustag(psc->malo_res_mem[0]); sc->malo_io0h = rman_get_bushandle(psc->malo_res_mem[0]); sc->malo_io1t = rman_get_bustag(psc->malo_res_mem[1]); sc->malo_io1h = rman_get_bushandle(psc->malo_res_mem[1]); error = malo_attach(pci_get_device(dev), sc); if (error != 0) goto bad2; return (error); bad2: bus_dma_tag_destroy(sc->malo_dmat); bad1: if (psc->malo_msi == 0) bus_teardown_intr(dev, psc->malo_res_irq[0], psc->malo_intrhand[0]); else { for (i = 0; i < MALO_MSI_MESSAGES; i++) bus_teardown_intr(dev, psc->malo_res_irq[i], psc->malo_intrhand[i]); } bus_release_resources(dev, psc->malo_irq_spec, psc->malo_res_irq); bad: if (psc->malo_msi != 0) pci_release_msi(dev); bus_release_resources(dev, psc->malo_mem_spec, psc->malo_res_mem); return (error); }
static int dma_attach(device_t dev) { struct dma_softc *dsc; struct lsi64854_softc *lsc; struct dma_devinfo *ddi; device_t cdev; const char *name; char *cabletype; uint32_t csr; phandle_t child, node; int error, i; dsc = device_get_softc(dev); lsc = &dsc->sc_lsi64854; name = ofw_bus_get_name(dev); node = ofw_bus_get_node(dev); dsc->sc_ign = sbus_get_ign(dev); dsc->sc_slot = sbus_get_slot(dev); i = 0; lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, RF_ACTIVE); if (lsc->sc_res == NULL) { device_printf(dev, "cannot allocate resources\n"); return (ENXIO); } if (strcmp(name, "espdma") == 0 || strcmp(name, "dma") == 0) lsc->sc_channel = L64854_CHANNEL_SCSI; else if (strcmp(name, "ledma") == 0) { /* * Check to see which cable type is currently active and * set the appropriate bit in the ledma csr so that it * gets used. If we didn't netboot, the PROM won't have * the "cable-selection" property; default to TP and then * the user can change it via a "media" option to ifconfig. */ csr = L64854_GCSR(lsc); if ((OF_getprop_alloc(node, "cable-selection", 1, (void **)&cabletype)) == -1) { /* assume TP if nothing there */ csr |= E_TP_AUI; } else { if (strcmp(cabletype, "aui") == 0) csr &= ~E_TP_AUI; else csr |= E_TP_AUI; free(cabletype, M_OFWPROP); } L64854_SCSR(lsc, csr); DELAY(20000); /* manual says we need a 20ms delay */ lsc->sc_channel = L64854_CHANNEL_ENET; } else { device_printf(dev, "unsupported DMA channel\n"); error = ENXIO; goto fail_lres; } error = bus_dma_tag_create( bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE, /* maxsize */ BUS_SPACE_UNRESTRICTED, /* nsegments */ BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* no locking */ &lsc->sc_parent_dmat); if (error != 0) { device_printf(dev, "cannot allocate parent DMA tag\n"); goto fail_lres; } i = sbus_get_burstsz(dev); lsc->sc_burst = (i & SBUS_BURST_32) ? 32 : (i & SBUS_BURST_16) ? 16 : 0; lsc->sc_dev = dev; /* Attach children. */ i = 0; for (child = OF_child(node); child != 0; child = OF_peer(child)) { if ((ddi = dma_setup_dinfo(dev, dsc, child)) == NULL) continue; if (i != 0) { device_printf(dev, "<%s>: only one child per DMA channel supported\n", ddi->ddi_obdinfo.obd_name); dma_destroy_dinfo(ddi); continue; } if ((cdev = device_add_child(dev, NULL, -1)) == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", ddi->ddi_obdinfo.obd_name); dma_destroy_dinfo(ddi); continue; } device_set_ivars(cdev, ddi); i++; } return (bus_generic_attach(dev)); fail_lres: bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res), lsc->sc_res); return (error); }
static int kr_dma_alloc(struct kr_softc *sc) { struct kr_dmamap_arg ctx; struct kr_txdesc *txd; struct kr_rxdesc *rxd; int error, i; /* Create parent DMA tag. */ error = bus_dma_tag_create( bus_get_dma_tag(sc->kr_dev), /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 0, /* nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->kr_cdata.kr_parent_tag); if (error != 0) { device_printf(sc->kr_dev, "failed to create parent DMA tag\n"); goto fail; } /* Create tag for Tx ring. */ error = bus_dma_tag_create( sc->kr_cdata.kr_parent_tag, /* parent */ KR_RING_ALIGN, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ KR_TX_RING_SIZE, /* maxsize */ 1, /* nsegments */ KR_TX_RING_SIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->kr_cdata.kr_tx_ring_tag); if (error != 0) { device_printf(sc->kr_dev, "failed to create Tx ring DMA tag\n"); goto fail; } /* Create tag for Rx ring. */ error = bus_dma_tag_create( sc->kr_cdata.kr_parent_tag, /* parent */ KR_RING_ALIGN, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ KR_RX_RING_SIZE, /* maxsize */ 1, /* nsegments */ KR_RX_RING_SIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->kr_cdata.kr_rx_ring_tag); if (error != 0) { device_printf(sc->kr_dev, "failed to create Rx ring DMA tag\n"); goto fail; } /* Create tag for Tx buffers. */ error = bus_dma_tag_create( sc->kr_cdata.kr_parent_tag, /* parent */ sizeof(uint32_t), 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MCLBYTES * KR_MAXFRAGS, /* maxsize */ KR_MAXFRAGS, /* nsegments */ MCLBYTES, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->kr_cdata.kr_tx_tag); if (error != 0) { device_printf(sc->kr_dev, "failed to create Tx DMA tag\n"); goto fail; } /* Create tag for Rx buffers. */ error = bus_dma_tag_create( sc->kr_cdata.kr_parent_tag, /* parent */ KR_RX_ALIGN, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MCLBYTES, /* maxsize */ 1, /* nsegments */ MCLBYTES, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->kr_cdata.kr_rx_tag); if (error != 0) { device_printf(sc->kr_dev, "failed to create Rx DMA tag\n"); goto fail; } /* Allocate DMA'able memory and load the DMA map for Tx ring. */ error = bus_dmamem_alloc(sc->kr_cdata.kr_tx_ring_tag, (void **)&sc->kr_rdata.kr_tx_ring, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->kr_cdata.kr_tx_ring_map); if (error != 0) { device_printf(sc->kr_dev, "failed to allocate DMA'able memory for Tx ring\n"); goto fail; } ctx.kr_busaddr = 0; error = bus_dmamap_load(sc->kr_cdata.kr_tx_ring_tag, sc->kr_cdata.kr_tx_ring_map, sc->kr_rdata.kr_tx_ring, KR_TX_RING_SIZE, kr_dmamap_cb, &ctx, 0); if (error != 0 || ctx.kr_busaddr == 0) { device_printf(sc->kr_dev, "failed to load DMA'able memory for Tx ring\n"); goto fail; } sc->kr_rdata.kr_tx_ring_paddr = ctx.kr_busaddr; /* Allocate DMA'able memory and load the DMA map for Rx ring. */ error = bus_dmamem_alloc(sc->kr_cdata.kr_rx_ring_tag, (void **)&sc->kr_rdata.kr_rx_ring, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->kr_cdata.kr_rx_ring_map); if (error != 0) { device_printf(sc->kr_dev, "failed to allocate DMA'able memory for Rx ring\n"); goto fail; } ctx.kr_busaddr = 0; error = bus_dmamap_load(sc->kr_cdata.kr_rx_ring_tag, sc->kr_cdata.kr_rx_ring_map, sc->kr_rdata.kr_rx_ring, KR_RX_RING_SIZE, kr_dmamap_cb, &ctx, 0); if (error != 0 || ctx.kr_busaddr == 0) { device_printf(sc->kr_dev, "failed to load DMA'able memory for Rx ring\n"); goto fail; } sc->kr_rdata.kr_rx_ring_paddr = ctx.kr_busaddr; /* Create DMA maps for Tx buffers. */ for (i = 0; i < KR_TX_RING_CNT; i++) { txd = &sc->kr_cdata.kr_txdesc[i]; txd->tx_m = NULL; txd->tx_dmamap = NULL; error = bus_dmamap_create(sc->kr_cdata.kr_tx_tag, 0, &txd->tx_dmamap); if (error != 0) { device_printf(sc->kr_dev, "failed to create Tx dmamap\n"); goto fail; } } /* Create DMA maps for Rx buffers. */ if ((error = bus_dmamap_create(sc->kr_cdata.kr_rx_tag, 0, &sc->kr_cdata.kr_rx_sparemap)) != 0) { device_printf(sc->kr_dev, "failed to create spare Rx dmamap\n"); goto fail; } for (i = 0; i < KR_RX_RING_CNT; i++) { rxd = &sc->kr_cdata.kr_rxdesc[i]; rxd->rx_m = NULL; rxd->rx_dmamap = NULL; error = bus_dmamap_create(sc->kr_cdata.kr_rx_tag, 0, &rxd->rx_dmamap); if (error != 0) { device_printf(sc->kr_dev, "failed to create Rx dmamap\n"); goto fail; } } fail: return (error); }
static int adv_pci_attach(device_t dev) { struct adv_softc *adv; u_int32_t id; u_int32_t command; int error, rid, irqrid; void *ih; struct resource *iores, *irqres; /* * Determine the chip version. */ id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4); command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); /* * These cards do not allow memory mapped accesses, so we must * ensure that I/O accesses are available or we won't be able * to talk to them. */ if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) { command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN; pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); } /* * Early chips can't handle non-zero latency timer settings. */ if (id == PCI_DEVICE_ID_ADVANSYS_1200A || id == PCI_DEVICE_ID_ADVANSYS_1200B) { pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1); } rid = PCI_BASEADR0; iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (iores == NULL) return ENXIO; if (adv_find_signature(rman_get_bustag(iores), rman_get_bushandle(iores)) == 0) { bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores)); if (adv == NULL) { bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } /* Allocate a dmatag for our transfer DMA maps */ error = bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), /* alignment */ 1, /* boundary */ 0, /* lowaddr */ ADV_PCI_MAX_DMA_ADDR, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, /* nsegments */ ~0, /* maxsegsz */ ADV_PCI_MAX_DMA_COUNT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &adv->parent_dmat); if (error != 0) { printf("%s: Could not allocate DMA tag - error %d\n", adv_name(adv), error); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv->init_level++; if (overrun_buf == NULL) { /* Need to allocate our overrun buffer */ if (bus_dma_tag_create( /* parent */ adv->parent_dmat, /* alignment */ 8, /* boundary */ 0, /* lowaddr */ ADV_PCI_MAX_DMA_ADDR, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ ADV_OVERRUN_BSIZE, /* nsegments */ 1, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ busdma_lock_mutex, /* lockarg */ &Giant, &overrun_dmat) != 0) { bus_dma_tag_destroy(adv->parent_dmat); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } if (bus_dmamem_alloc(overrun_dmat, &overrun_buf, BUS_DMA_NOWAIT, &overrun_dmamap) != 0) { bus_dma_tag_destroy(overrun_dmat); bus_dma_tag_destroy(adv->parent_dmat); adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } /* And permanently map it in */ bus_dmamap_load(overrun_dmat, overrun_dmamap, overrun_buf, ADV_OVERRUN_BSIZE, adv_map, &overrun_physbase, /*flags*/0); } adv->overrun_physbase = overrun_physbase; /* * Stop the chip. */ ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); ADV_OUTW(adv, ADV_CHIP_STATUS, 0); adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); adv->type = ADV_PCI; /* * Setup active negation and signal filtering. */ { u_int8_t extra_cfg; if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150) adv->type |= ADV_ULTRA; if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050) extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER; else extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE; ADV_OUTB(adv, ADV_REG_IFC, extra_cfg); } if (adv_init(adv) != 0) { adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT; adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR; #if defined(CC_DISABLE_PCI_PARITY_INT) && CC_DISABLE_PCI_PARITY_INT { u_int16_t config_msw; config_msw = ADV_INW(adv, ADV_CONFIG_MSW); config_msw &= 0xFFC0; ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); } #endif if (id == PCI_DEVICE_ID_ADVANSYS_1200A || id == PCI_DEVICE_ID_ADVANSYS_1200B) { adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB; adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN; adv->fix_asyn_xfer = ~0; } irqrid = 0; irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid, RF_SHAREABLE | RF_ACTIVE); if (irqres == NULL || bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, NULL, adv_intr, adv, &ih)) { adv_free(adv); bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); return ENXIO; } adv_attach(adv); return 0; }
static int fwohci_pci_attach(device_t self) { fwohci_softc_t *sc = device_get_softc(self); int err; int rid; #if 0 if (bootverbose) firewire_debug = bootverbose; #endif mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF); fwohci_pci_init(self); rid = PCI_CBMEM; sc->bsr = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->bsr) { device_printf(self, "Could not map memory\n"); return ENXIO; } sc->bst = rman_get_bustag(sc->bsr); sc->bsh = rman_get_bushandle(sc->bsr); rid = 0; sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->irq_res == NULL) { device_printf(self, "Could not allocate irq\n"); fwohci_pci_detach(self); return ENXIO; } err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, NULL, (driver_intr_t *) fwohci_intr, sc, &sc->ih); if (err) { device_printf(self, "Could not setup irq, %d\n", err); fwohci_pci_detach(self); return ENXIO; } err = bus_dma_tag_create( /*parent*/bus_get_dma_tag(self), /*alignment*/1, /*boundary*/0, #if BOUNCE_BUFFER_TEST /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, #else /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, #endif /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/0x100000, /*nsegments*/0x20, /*maxsegsz*/0x8000, /*flags*/BUS_DMA_ALLOCNOW, /*lockfunc*/busdma_lock_mutex, /*lockarg*/FW_GMTX(&sc->fc), &sc->fc.dmat); if (err != 0) { printf("fwohci_pci_attach: Could not allocate DMA tag " "- error %d\n", err); return (ENOMEM); } err = fwohci_init(sc, self); if (err) { device_printf(self, "fwohci_init failed with err=%d\n", err); fwohci_pci_detach(self); return EIO; } /* probe and attach a child device(firewire) */ bus_generic_probe(self); bus_generic_attach(self); return 0; }
static int ath_pci_attach(device_t dev) { struct ath_pci_softc *psc = device_get_softc(dev); struct ath_softc *sc = &psc->sc_sc; int error = ENXIO; int rid; #ifdef ATH_EEPROM_FIRMWARE const struct firmware *fw = NULL; const char *buf; #endif sc->sc_dev = dev; /* * Enable bus mastering. */ pci_enable_busmaster(dev); /* * Setup other PCI bus configuration parameters. */ ath_pci_setup(dev); /* * Setup memory-mapping of PCI registers. */ rid = BS_BAR; psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (psc->sc_sr == NULL) { device_printf(dev, "cannot map register space\n"); goto bad; } /* XXX uintptr_t is a bandaid for ia64; to be fixed */ sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr); sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); /* * Mark device invalid so any interrupts (shared or otherwise) * that arrive before the HAL is setup are discarded. */ sc->sc_invalid = 1; /* * Arrange interrupt line. */ rid = 0; psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE); if (psc->sc_irq == NULL) { device_printf(dev, "could not map interrupt\n"); goto bad1; } if (bus_setup_intr(dev, psc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ath_intr, sc, &psc->sc_ih)) { device_printf(dev, "could not establish interrupt\n"); goto bad2; } /* * Setup DMA descriptor area. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ 0x3ffff, /* maxsize XXX */ ATH_MAX_SCATTER, /* nsegments */ 0x3ffff, /* maxsegsize XXX */ BUS_DMA_ALLOCNOW, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->sc_dmat)) { device_printf(dev, "cannot allocate DMA tag\n"); goto bad3; } #ifdef ATH_EEPROM_FIRMWARE /* * If there's an EEPROM firmware image, load that in. */ if (resource_string_value(device_get_name(dev), device_get_unit(dev), "eeprom_firmware", &buf) == 0) { if (bootverbose) device_printf(dev, "%s: looking up firmware @ '%s'\n", __func__, buf); fw = firmware_get(buf); if (fw == NULL) { device_printf(dev, "%s: couldn't find firmware\n", __func__); goto bad3; } device_printf(dev, "%s: EEPROM firmware @ %p\n", __func__, fw->data); sc->sc_eepromdata = malloc(fw->datasize, M_TEMP, M_WAITOK | M_ZERO); if (! sc->sc_eepromdata) { device_printf(dev, "%s: can't malloc eepromdata\n", __func__); goto bad3; } memcpy(sc->sc_eepromdata, fw->data, fw->datasize); firmware_put(fw, 0); } #endif /* ATH_EEPROM_FIRMWARE */ ATH_LOCK_INIT(sc); ATH_PCU_LOCK_INIT(sc); ATH_RX_LOCK_INIT(sc); ATH_TX_LOCK_INIT(sc); ATH_TX_IC_LOCK_INIT(sc); ATH_TXSTATUS_LOCK_INIT(sc); error = ath_attach(pci_get_device(dev), sc); if (error == 0) /* success */ return 0; ATH_TXSTATUS_LOCK_DESTROY(sc); ATH_PCU_LOCK_DESTROY(sc); ATH_RX_LOCK_DESTROY(sc); ATH_TX_IC_LOCK_DESTROY(sc); ATH_TX_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); bad2: bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); bad1: bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, psc->sc_sr); bad: return (error); }
static int amr_pci_attach(device_t dev) { struct amr_softc *sc; struct amr_ident *id; int rid, rtype, error; debug_called(1); /* * Initialise softc. */ sc = device_get_softc(dev); bzero(sc, sizeof(*sc)); sc->amr_dev = dev; /* assume failure is 'not configured' */ error = ENXIO; /* * Determine board type. */ if ((id = amr_find_ident(dev)) == NULL) return (ENXIO); if (id->flags & AMR_ID_QUARTZ) { sc->amr_type |= AMR_TYPE_QUARTZ; } if ((amr_force_sg32 == 0) && (id->flags & AMR_ID_DO_SG64) && (sizeof(vm_paddr_t) > 4)) { device_printf(dev, "Using 64-bit DMA\n"); sc->amr_type |= AMR_TYPE_SG64; } /* force the busmaster enable bit on */ pci_enable_busmaster(dev); /* * Allocate the PCI register window. */ rid = PCIR_BAR(0); rtype = AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT; sc->amr_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); if (sc->amr_reg == NULL) { device_printf(sc->amr_dev, "can't allocate register window\n"); goto out; } sc->amr_btag = rman_get_bustag(sc->amr_reg); sc->amr_bhandle = rman_get_bushandle(sc->amr_reg); /* * Allocate and connect our interrupt. */ rid = 0; sc->amr_irq = bus_alloc_resource_any(sc->amr_dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->amr_irq == NULL) { device_printf(sc->amr_dev, "can't allocate interrupt\n"); goto out; } if (bus_setup_intr(sc->amr_dev, sc->amr_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, amr_pci_intr, sc, &sc->amr_intr)) { device_printf(sc->amr_dev, "can't set up interrupt\n"); goto out; } debug(2, "interrupt attached"); /* assume failure is 'out of memory' */ error = ENOMEM; /* * Allocate the parent bus DMA tag appropriate for PCI. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* PCI parent */ 1, 0, /* alignment,boundary */ AMR_IS_SG64(sc) ? BUS_SPACE_MAXADDR : BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->amr_parent_dmat)) { device_printf(dev, "can't allocate parent DMA tag\n"); goto out; } /* * Create DMA tag for mapping buffers into controller-addressable space. */ if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 1, 0, /* alignment,boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */ MAXBSIZE, /* maxsegsize */ 0, /* flags */ busdma_lock_mutex, /* lockfunc */ &sc->amr_list_lock, /* lockarg */ &sc->amr_buffer_dmat)) { device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n"); goto out; } if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 1, 0, /* alignment,boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */ MAXBSIZE, /* maxsegsize */ 0, /* flags */ busdma_lock_mutex, /* lockfunc */ &sc->amr_list_lock, /* lockarg */ &sc->amr_buffer64_dmat)) { device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n"); goto out; } debug(2, "dma tag done"); /* * Allocate and set up mailbox in a bus-visible fashion. */ mtx_init(&sc->amr_list_lock, "AMR List Lock", NULL, MTX_DEF); mtx_init(&sc->amr_hw_lock, "AMR HW Lock", NULL, MTX_DEF); if ((error = amr_setup_mbox(sc)) != 0) goto out; debug(2, "mailbox setup"); /* * Build the scatter/gather buffers. */ if ((error = amr_sglist_map(sc)) != 0) goto out; debug(2, "s/g list mapped"); if ((error = amr_ccb_map(sc)) != 0) goto out; debug(2, "ccb mapped"); /* * Do bus-independant initialisation, bring controller online. */ error = amr_attach(sc); out: if (error) amr_pci_free(sc); return(error); }
/* * Function name: tw_osli_alloc_mem * Description: Allocates memory needed both by CL and OSL. * * Input: sc -- OSL internal controller context * Output: None * Return value: 0 -- success * non-zero-- failure */ static TW_INT32 tw_osli_alloc_mem(struct twa_softc *sc) { struct tw_osli_req_context *req; TW_UINT32 max_sg_elements; TW_UINT32 non_dma_mem_size; TW_UINT32 dma_mem_size; TW_INT32 error; TW_INT32 i; tw_osli_dbg_dprintf(3, sc, "entered"); sc->flags |= (sizeof(bus_addr_t) == 8) ? TW_CL_64BIT_ADDRESSES : 0; sc->flags |= (sizeof(bus_size_t) == 8) ? TW_CL_64BIT_SG_LENGTH : 0; max_sg_elements = (sizeof(bus_addr_t) == 8) ? TW_CL_MAX_64BIT_SG_ELEMENTS : TW_CL_MAX_32BIT_SG_ELEMENTS; if ((error = tw_cl_get_mem_requirements(&sc->ctlr_handle, sc->flags, sc->device_id, TW_OSLI_MAX_NUM_REQUESTS, TW_OSLI_MAX_NUM_AENS, &(sc->alignment), &(sc->sg_size_factor), &non_dma_mem_size, &dma_mem_size ))) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2008, "Can't get Common Layer's memory requirements", error); return(error); } if ((sc->non_dma_mem = malloc(non_dma_mem_size, TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2009, "Can't allocate non-dma memory", ENOMEM); return(ENOMEM); } /* Create the parent dma tag. */ if (bus_dma_tag_create(bus_get_dma_tag(sc->bus_dev), /* parent */ sc->alignment, /* alignment */ 0, /* boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ TW_CL_MAX_IO_SIZE, /* maxsize */ max_sg_elements, /* nsegments */ TW_CL_MAX_IO_SIZE, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockfuncarg */ &sc->parent_tag /* tag */)) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x200A, "Can't allocate parent DMA tag", ENOMEM); return(ENOMEM); } /* Create a dma tag for Common Layer's DMA'able memory (dma_mem). */ if (bus_dma_tag_create(sc->parent_tag, /* parent */ sc->alignment, /* alignment */ 0, /* boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ dma_mem_size, /* maxsize */ 1, /* nsegments */ BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockfuncarg */ &sc->cmd_tag /* tag */)) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x200B, "Can't allocate DMA tag for Common Layer's " "DMA'able memory", ENOMEM); return(ENOMEM); } if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem, BUS_DMA_NOWAIT, &sc->cmd_map)) { /* Try a second time. */ if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem, BUS_DMA_NOWAIT, &sc->cmd_map)) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x200C, "Can't allocate DMA'able memory for the" "Common Layer", ENOMEM); return(ENOMEM); } } bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem, dma_mem_size, twa_map_load_callback, &sc->dma_mem_phys, 0); /* * Create a dma tag for data buffers; size will be the maximum * possible I/O size (128kB). */ if (bus_dma_tag_create(sc->parent_tag, /* parent */ sc->alignment, /* alignment */ 0, /* boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ TW_CL_MAX_IO_SIZE, /* maxsize */ max_sg_elements, /* nsegments */ TW_CL_MAX_IO_SIZE, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ twa_busdma_lock, /* lockfunc */ sc->io_lock, /* lockfuncarg */ &sc->dma_tag /* tag */)) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x200F, "Can't allocate DMA tag for data buffers", ENOMEM); return(ENOMEM); } /* * Create a dma tag for ioctl data buffers; size will be the maximum * possible I/O size (128kB). */ if (bus_dma_tag_create(sc->parent_tag, /* parent */ sc->alignment, /* alignment */ 0, /* boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ TW_CL_MAX_IO_SIZE, /* maxsize */ max_sg_elements, /* nsegments */ TW_CL_MAX_IO_SIZE, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ twa_busdma_lock, /* lockfunc */ sc->io_lock, /* lockfuncarg */ &sc->ioctl_tag /* tag */)) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2010, "Can't allocate DMA tag for ioctl data buffers", ENOMEM); return(ENOMEM); } /* Create just one map for all ioctl request data buffers. */ if (bus_dmamap_create(sc->ioctl_tag, 0, &sc->ioctl_map)) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2011, "Can't create ioctl map", ENOMEM); return(ENOMEM); } /* Initialize request queues. */ tw_osli_req_q_init(sc, TW_OSLI_FREE_Q); tw_osli_req_q_init(sc, TW_OSLI_BUSY_Q); if ((sc->req_ctx_buf = (struct tw_osli_req_context *) malloc((sizeof(struct tw_osli_req_context) * TW_OSLI_MAX_NUM_REQUESTS), TW_OSLI_MALLOC_CLASS, M_WAITOK)) == NULL) { tw_osli_printf(sc, "error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2012, "Failed to allocate request packets", ENOMEM); return(ENOMEM); } bzero(sc->req_ctx_buf, sizeof(struct tw_osli_req_context) * TW_OSLI_MAX_NUM_REQUESTS); for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) { req = &(sc->req_ctx_buf[i]); req->ctlr = sc; if (bus_dmamap_create(sc->dma_tag, 0, &req->dma_map)) { tw_osli_printf(sc, "request # = %d, error = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 0x2013, "Can't create dma map", i, ENOMEM); return(ENOMEM); } /* Initialize the ioctl wakeup/ timeout mutex */ req->ioctl_wake_timeout_lock = &(req->ioctl_wake_timeout_lock_handle); mtx_init(req->ioctl_wake_timeout_lock, "tw_ioctl_wake_timeout_lock", NULL, MTX_DEF); /* Insert request into the free queue. */ tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); } return(0); }
/******************************************************************************** * Allocate resources, initialise the controller. */ static int twe_attach(device_t dev) { struct twe_softc *sc; struct sysctl_oid *sysctl_tree; int rid, error; debug_called(4); /* * Initialise the softc structure. */ sc = device_get_softc(dev); sc->twe_dev = dev; mtx_init(&sc->twe_io_lock, "twe I/O", NULL, MTX_DEF); sx_init(&sc->twe_config_lock, "twe config"); /* * XXX: This sysctl tree must stay at hw.tweX rather than using * the device_get_sysctl_tree() created by new-bus because * existing 3rd party binary tools such as tw_cli and 3dm2 use the * existence of this sysctl node to discover controllers. */ sysctl_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0, ""); if (sysctl_tree == NULL) { twe_printf(sc, "cannot add sysctl tree node\n"); return (ENXIO); } SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "driver_version", CTLFLAG_RD, TWE_DRIVER_VERSION_STRING, 0, "TWE driver version"); /* * Force the busmaster enable bit on, in case the BIOS forgot. */ pci_enable_busmaster(dev); /* * Allocate the PCI register window. */ rid = TWE_IO_CONFIG_REG; if ((sc->twe_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE)) == NULL) { twe_printf(sc, "can't allocate register window\n"); twe_free(sc); return(ENXIO); } /* * Allocate the parent bus DMA tag appropriate for PCI. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* PCI parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXBSIZE, TWE_MAX_SGL_LENGTH, /* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->twe_parent_dmat)) { twe_printf(sc, "can't allocate parent DMA tag\n"); twe_free(sc); return(ENOMEM); } /* * Allocate and connect our interrupt. */ rid = 0; if ((sc->twe_irq = bus_alloc_resource_any(sc->twe_dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { twe_printf(sc, "can't allocate interrupt\n"); twe_free(sc); return(ENXIO); } if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, twe_pci_intr, sc, &sc->twe_intr)) { twe_printf(sc, "can't set up interrupt\n"); twe_free(sc); return(ENXIO); } /* * Create DMA tag for mapping command's into controller-addressable space. */ if (bus_dma_tag_create(sc->twe_parent_dmat, /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sizeof(TWE_Command) * TWE_Q_LENGTH, 1, /* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->twe_cmd_dmat)) { twe_printf(sc, "can't allocate data buffer DMA tag\n"); twe_free(sc); return(ENOMEM); } /* * Allocate memory and make it available for DMA. */ if (bus_dmamem_alloc(sc->twe_cmd_dmat, (void **)&sc->twe_cmd, BUS_DMA_NOWAIT, &sc->twe_cmdmap)) { twe_printf(sc, "can't allocate command memory\n"); return(ENOMEM); } bus_dmamap_load(sc->twe_cmd_dmat, sc->twe_cmdmap, sc->twe_cmd, sizeof(TWE_Command) * TWE_Q_LENGTH, twe_setup_request_dmamap, sc, 0); bzero(sc->twe_cmd, sizeof(TWE_Command) * TWE_Q_LENGTH); /* * Create DMA tag for mapping objects into controller-addressable space. */ if (bus_dma_tag_create(sc->twe_parent_dmat, /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXBSIZE, TWE_MAX_SGL_LENGTH,/* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ busdma_lock_mutex, /* lockfunc */ &sc->twe_io_lock, /* lockarg */ &sc->twe_buffer_dmat)) { twe_printf(sc, "can't allocate data buffer DMA tag\n"); twe_free(sc); return(ENOMEM); } /* * Create DMA tag for mapping objects into controller-addressable space. */ if (bus_dma_tag_create(sc->twe_parent_dmat, /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXBSIZE, 1, /* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->twe_immediate_dmat)) { twe_printf(sc, "can't allocate data buffer DMA tag\n"); twe_free(sc); return(ENOMEM); } /* * Allocate memory for requests which cannot sleep or support continuation. */ if (bus_dmamem_alloc(sc->twe_immediate_dmat, (void **)&sc->twe_immediate, BUS_DMA_NOWAIT, &sc->twe_immediate_map)) { twe_printf(sc, "can't allocate memory for immediate requests\n"); return(ENOMEM); } /* * Initialise the controller and driver core. */ if ((error = twe_setup(sc))) { twe_free(sc); return(error); } /* * Print some information about the controller and configuration. */ twe_describe_controller(sc); /* * Create the control device. */ sc->twe_dev_t = make_dev(&twe_cdevsw, device_get_unit(sc->twe_dev), UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "twe%d", device_get_unit(sc->twe_dev)); sc->twe_dev_t->si_drv1 = sc; /* * Schedule ourselves to bring the controller up once interrupts are available. * This isn't strictly necessary, since we disable interrupts while probing the * controller, but it is more in keeping with common practice for other disk * devices. */ sc->twe_ich.ich_func = twe_intrhook; sc->twe_ich.ich_arg = sc; if (config_intrhook_establish(&sc->twe_ich) != 0) { twe_printf(sc, "can't establish configuration hook\n"); twe_free(sc); return(ENXIO); } return(0); }
static int tws_init(struct tws_softc *sc) { u_int32_t max_sg_elements; u_int32_t dma_mem_size; int error; u_int32_t reg; sc->seq_id = 0; if ( tws_queue_depth > TWS_MAX_REQS ) tws_queue_depth = TWS_MAX_REQS; if (tws_queue_depth < TWS_RESERVED_REQS+1) tws_queue_depth = TWS_RESERVED_REQS+1; sc->is64bit = (sizeof(bus_addr_t) == 8) ? true : false; max_sg_elements = (sc->is64bit && !tws_use_32bit_sgls) ? TWS_MAX_64BIT_SG_ELEMENTS : TWS_MAX_32BIT_SG_ELEMENTS; dma_mem_size = (sizeof(struct tws_command_packet) * tws_queue_depth) + (TWS_SECTOR_SIZE) ; if ( bus_dma_tag_create(bus_get_dma_tag(sc->tws_dev), /* PCI parent */ TWS_ALIGNMENT, /* alignment */ 0, /* boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE, /* maxsize */ max_sg_elements, /* numsegs */ BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockfuncarg */ &sc->parent_tag /* tag */ )) { TWS_TRACE_DEBUG(sc, "DMA parent tag Create fail", max_sg_elements, sc->is64bit); return(ENOMEM); } /* In bound message frame requires 16byte alignment. * Outbound MF's can live with 4byte alignment - for now just * use 16 for both. */ if ( bus_dma_tag_create(sc->parent_tag, /* parent */ TWS_IN_MF_ALIGNMENT, /* alignment */ 0, /* boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ dma_mem_size, /* maxsize */ 1, /* numsegs */ BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockfuncarg */ &sc->cmd_tag /* tag */ )) { TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit); return(ENOMEM); } if (bus_dmamem_alloc(sc->cmd_tag, &sc->dma_mem, BUS_DMA_NOWAIT, &sc->cmd_map)) { TWS_TRACE_DEBUG(sc, "DMA mem alloc fail", max_sg_elements, sc->is64bit); return(ENOMEM); } /* if bus_dmamem_alloc succeeds then bus_dmamap_load will succeed */ sc->dma_mem_phys=0; error = bus_dmamap_load(sc->cmd_tag, sc->cmd_map, sc->dma_mem, dma_mem_size, tws_dmamap_cmds_load_cbfn, &sc->dma_mem_phys, 0); /* * Create a dma tag for data buffers; size will be the maximum * possible I/O size (128kB). */ if (bus_dma_tag_create(sc->parent_tag, /* parent */ TWS_ALIGNMENT, /* alignment */ 0, /* boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ TWS_MAX_IO_SIZE, /* maxsize */ max_sg_elements, /* nsegments */ TWS_MAX_IO_SIZE, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ busdma_lock_mutex, /* lockfunc */ &sc->io_lock, /* lockfuncarg */ &sc->data_tag /* tag */)) { TWS_TRACE_DEBUG(sc, "DMA cmd tag Create fail", max_sg_elements, sc->is64bit); return(ENOMEM); } sc->reqs = malloc(sizeof(struct tws_request) * tws_queue_depth, M_TWS, M_WAITOK | M_ZERO); if ( sc->reqs == NULL ) { TWS_TRACE_DEBUG(sc, "malloc failed", 0, sc->is64bit); return(ENOMEM); } sc->sense_bufs = malloc(sizeof(struct tws_sense) * tws_queue_depth, M_TWS, M_WAITOK | M_ZERO); if ( sc->sense_bufs == NULL ) { TWS_TRACE_DEBUG(sc, "sense malloc failed", 0, sc->is64bit); return(ENOMEM); } sc->scan_ccb = malloc(sizeof(union ccb), M_TWS, M_WAITOK | M_ZERO); if ( sc->scan_ccb == NULL ) { TWS_TRACE_DEBUG(sc, "ccb malloc failed", 0, sc->is64bit); return(ENOMEM); } if (bus_dmamem_alloc(sc->data_tag, (void **)&sc->ioctl_data_mem, (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &sc->ioctl_data_map)) { device_printf(sc->tws_dev, "Cannot allocate ioctl data mem\n"); return(ENOMEM); } if ( !tws_ctlr_ready(sc) ) if( !tws_ctlr_reset(sc) ) return(FAILURE); bzero(&sc->stats, sizeof(struct tws_stats)); tws_init_qs(sc); tws_turn_off_interrupts(sc); /* * enable pull mode by setting bit1 . * setting bit0 to 1 will enable interrupt coalesing * will revisit. */ #ifdef TWS_PULL_MODE_ENABLE reg = tws_read_reg(sc, TWS_I2O0_CTL, 4); TWS_TRACE_DEBUG(sc, "i20 ctl", reg, TWS_I2O0_CTL); tws_write_reg(sc, TWS_I2O0_CTL, reg | TWS_BIT1, 4); #endif TWS_TRACE_DEBUG(sc, "dma_mem_phys", sc->dma_mem_phys, TWS_I2O0_CTL); if ( tws_init_reqs(sc, dma_mem_size) == FAILURE ) return(FAILURE); if ( tws_init_aen_q(sc) == FAILURE ) return(FAILURE); return(SUCCESS); }
static int via_attach(device_t dev) { struct via_info *via = 0; char status[SND_STATUSLEN]; u_int32_t data, cnt; via = malloc(sizeof(*via), M_DEVBUF, M_WAITOK | M_ZERO); via->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_via82c686 softc"); pci_enable_busmaster(dev); /* Wake up and reset AC97 if necessary */ data = pci_read_config(dev, VIA_AC97STATUS, 1); if ((data & VIA_AC97STATUS_RDY) == 0) { /* Cold reset per ac97r2.3 spec (page 95) */ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Assert low */ DELAY(100); /* Wait T_rst_low */ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_NRST, 1); /* Assert high */ DELAY(5); /* Wait T_rst2clk */ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Assert low */ } else { /* Warm reset */ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Force no sync */ DELAY(100); pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_SYNC, 1); /* Sync */ DELAY(5); /* Wait T_sync_high */ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Force no sync */ DELAY(5); /* Wait T_sync2clk */ } /* Power everything up */ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1); /* Wait for codec to become ready (largest reported delay here 310ms) */ for (cnt = 0; cnt < 2000; cnt++) { data = pci_read_config(dev, VIA_AC97STATUS, 1); if (data & VIA_AC97STATUS_RDY) break; DELAY(5000); } via->regid = PCIR_BAR(0); via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid, RF_ACTIVE); if (!via->reg) { device_printf(dev, "cannot allocate bus resource."); goto bad; } via->st = rman_get_bustag(via->reg); via->sh = rman_get_bushandle(via->reg); via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536); via->irqid = 0; via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid, RF_ACTIVE | RF_SHAREABLE); if (!via->irq || snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) { device_printf(dev, "unable to map interrupt\n"); goto bad; } via_wr(via, VIA_PLAY_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); via_wr(via, VIA_RECORD_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); via->codec = AC97_CREATE(dev, via, via_ac97); if (!via->codec) goto bad; if (mixer_init(dev, ac97_getmixerclass(), via->codec)) goto bad; via->codec_caps = ac97_getextcaps(via->codec); ac97_setextmode(via->codec, via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); /* DMA tag for buffers */ 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*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL, &via->parent_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } /* * DMA tag for SGD table. The 686 uses scatter/gather DMA and * requires a list in memory of work to do. We need only 16 bytes * for this list, and it is wasteful to allocate 16K. */ 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*/NSEGS * sizeof(struct via_dma_op), /*nsegments*/1, /*maxsegz*/0x3ffff, /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL, &via->sgd_dmat) != 0) { device_printf(dev, "unable to create dma tag\n"); goto bad; } if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, BUS_DMA_NOWAIT, &via->sgd_dmamap) != 0) goto bad; if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table, NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0) != 0) goto bad; snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s", rman_get_start(via->reg), rman_get_start(via->irq), PCM_KLDSTRING(snd_via82c686)); /* Register */ if (pcm_register(dev, via, 1, 1)) goto bad; pcm_addchan(dev, PCMDIR_PLAY, &viachan_class, via); pcm_addchan(dev, PCMDIR_REC, &viachan_class, via); pcm_setstatus(dev, status); return 0; bad: if (via->codec) ac97_destroy(via->codec); if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap); if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap); if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); if (via->lock) snd_mtxfree(via->lock); if (via) free(via, M_DEVBUF); return ENXIO; }
static int mpt_dma_mem_alloc(struct mpt_softc *mpt) { size_t len; struct mpt_map_info mi; /* Check if we alreay have allocated the reply memory */ if (mpt->reply_phys != 0) { return 0; } len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt); mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); if (mpt->request_pool == NULL) { mpt_prt(mpt, "cannot allocate request pool\n"); return (1); } /* * Create a parent dma tag for this device. * * Align at byte boundaries, * Limit to 32-bit addressing for request/reply queues. */ if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev), /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/BUS_SPACE_UNRESTRICTED, /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, &mpt->parent_dmat) != 0) { mpt_prt(mpt, "cannot create parent dma tag\n"); return (1); } /* Create a child tag for reply buffers */ if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0, &mpt->reply_dmat) != 0) { mpt_prt(mpt, "cannot create a dma tag for replies\n"); return (1); } /* Allocate some DMA accessible memory for replies */ if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply, BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) { mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n", (u_long) (2 * PAGE_SIZE)); return (1); } mi.mpt = mpt; mi.error = 0; /* Load and lock it into "bus space" */ bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply, 2 * PAGE_SIZE, mpt_map_rquest, &mi, 0); if (mi.error) { mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n", mi.error); return (1); } mpt->reply_phys = mi.phys; return (0); }
static int ahc_pci_attach(device_t dev) { struct ahc_pci_identity *entry; struct ahc_softc *ahc; char *name; int error; entry = ahc_find_pci_device(dev); if (entry == NULL) return (ENXIO); /* * Allocate a softc for this card and * set it up for attachment by our * common detect routine. */ name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (ENOMEM); strcpy(name, device_get_nameunit(dev)); ahc = ahc_alloc(dev, name); if (ahc == NULL) return (ENOMEM); ahc_set_unit(ahc, device_get_unit(dev)); /* * Should we bother disabling 39Bit addressing * based on installed memory? */ if (sizeof(bus_addr_t) > 4) ahc->flags |= AHC_39BIT_ADDRESSING; /* Allocate a dmatag for our SCB DMA maps */ error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), /*alignment*/1, /*boundary*/0, (ahc->flags & AHC_39BIT_ADDRESSING) ? 0x7FFFFFFFFFLL : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/AHC_NSEG, /*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*flags*/0, &ahc->parent_dmat); if (error != 0) { printf("ahc_pci_attach: Could not allocate DMA tag " "- error %d\n", error); ahc_free(ahc); return (ENOMEM); } ahc->dev_softc = dev; error = ahc_pci_config(ahc, entry); if (error != 0) { ahc_free(ahc); return (error); } ahc_attach(ahc); return (0); }
static int dpt_isa_attach (device_t dev) { dpt_softc_t * dpt; int error = 0; dpt = device_get_softc(dev); dpt->dev = dev; dpt_alloc(dev); dpt->io_rid = 0; dpt->io_type = SYS_RES_IOPORT; dpt->irq_rid = 0; error = dpt_alloc_resources(dev); if (error) { goto bad; } dpt->drq_rid = 0; dpt->drq_res = bus_alloc_resource_any(dev, SYS_RES_DRQ, &dpt->drq_rid, RF_ACTIVE); if (!dpt->drq_res) { device_printf(dev, "No DRQ!\n"); error = ENOMEM; goto bad; } isa_dma_acquire(rman_get_start(dpt->drq_res)); isa_dmacascade(rman_get_start(dpt->drq_res)); /* 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 */ ~0, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, /* lockfunc */ NULL, /* lockarg */ NULL, &dpt->parent_dmat) != 0) { error = ENXIO; goto bad; } if (dpt_init(dpt) != 0) { error = ENXIO; goto bad; } /* Register with the XPT */ dpt_attach(dpt); if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) { device_printf(dev, "Unable to register interrupt handler\n"); error = ENXIO; goto bad; } return (error); bad: if (dpt->drq_res) { isa_dma_release(rman_get_start(dpt->drq_res)); } dpt_release_resources(dev); if (dpt) dpt_free(dpt); return (error); }
static int ahc_isa_attach(device_t dev) { struct aic7770_identity *entry; bus_space_tag_t tag; bus_space_handle_t bsh; struct resource *regs; struct ahc_softc *ahc; char *name; int zero; int error; zero = 0; regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &zero, RF_ACTIVE); if (regs == NULL) return (ENOMEM); tag = rman_get_bustag(regs); bsh = rman_get_bushandle(regs); entry = ahc_isa_find_device(tag, bsh); bus_release_resource(dev, SYS_RES_IOPORT, zero, regs); if (entry == NULL) return (ENODEV); /* * Allocate a softc for this card and * set it up for attachment by our * common detect routine. */ name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); if (name == NULL) return (ENOMEM); strcpy(name, device_get_nameunit(dev)); ahc = ahc_alloc(dev, name); if (ahc == NULL) return (ENOMEM); ahc_set_unit(ahc, device_get_unit(dev)); /* Allocate a dmatag for our SCB DMA maps */ error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, /*nsegments*/AHC_NSEG, /*maxsegsz*/AHC_MAXTRANSFER_SIZE, /*flags*/0, &ahc->parent_dmat); if (error != 0) { printf("ahc_isa_attach: Could not allocate DMA tag " "- error %d\n", error); ahc_free(ahc); return (ENOMEM); } ahc->dev_softc = dev; error = aic7770_config(ahc, entry, /*unused ioport arg*/0); if (error != 0) { ahc_free(ahc); return (error); } ahc_attach(ahc); return (0); }