int cfi_attach(device_t dev) { struct cfi_softc *sc; u_int blksz, blocks; u_int r, u; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_rid = 0; sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, RF_ACTIVE); if (sc->sc_res == NULL) return (ENXIO); sc->sc_tag = rman_get_bustag(sc->sc_res); sc->sc_handle = rman_get_bushandle(sc->sc_res); /* Get time-out values for erase and write. */ sc->sc_write_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_WRITE); sc->sc_erase_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_ERASE); sc->sc_write_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_WRITE); sc->sc_erase_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_ERASE); /* Get erase regions. */ sc->sc_regions = cfi_read_qry(sc, CFI_QRY_NREGIONS); sc->sc_region = malloc(sc->sc_regions * sizeof(struct cfi_region), M_TEMP, M_WAITOK | M_ZERO); for (r = 0; r < sc->sc_regions; r++) { blocks = cfi_read_qry(sc, CFI_QRY_REGION(r)) | (cfi_read_qry(sc, CFI_QRY_REGION(r) + 1) << 8); sc->sc_region[r].r_blocks = blocks + 1; blksz = cfi_read_qry(sc, CFI_QRY_REGION(r) + 2) | (cfi_read_qry(sc, CFI_QRY_REGION(r) + 3) << 8); sc->sc_region[r].r_blksz = (blksz == 0) ? 128 : blksz * 256; } /* Reset the device to a default state. */ cfi_write(sc, 0, CFI_BCS_CLEAR_STATUS); if (bootverbose) { device_printf(dev, "["); for (r = 0; r < sc->sc_regions; r++) { printf("%ux%s%s", sc->sc_region[r].r_blocks, cfi_fmtsize(sc->sc_region[r].r_blksz), (r == sc->sc_regions - 1) ? "]\n" : ","); } } u = device_get_unit(dev); sc->sc_nod = make_dev(&cfi_cdevsw, u, UID_ROOT, GID_WHEEL, 0600, "%s%u", cfi_driver_name, u); sc->sc_nod->si_drv1 = sc; device_add_child(dev, "cfid", -1); bus_generic_attach(dev); return (0); }
static int acpi_cpu_attach(device_t dev) { struct acpi_cpu_softc *sc = device_get_softc(dev); ACPI_HANDLE handle; device_t child; int cpu_id, cpu_features; struct acpi_softc *acpi_sc; handle = acpi_get_handle(dev); cpu_id = acpi_get_magic(dev); acpi_sc = acpi_device_get_parent_softc(dev); if (cpu_id == 0) { sysctl_ctx_init(&sc->glob_sysctl_ctx); sc->glob_sysctl_tree = SYSCTL_ADD_NODE(&sc->glob_sysctl_ctx, SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu", CTLFLAG_RD, 0, "node for CPU global settings"); if (sc->glob_sysctl_tree == NULL) return ENOMEM; } sysctl_ctx_init(&sc->pcpu_sysctl_ctx); sc->pcpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->pcpu_sysctl_ctx, SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0, "node for per-CPU settings"); if (sc->pcpu_sysctl_tree == NULL) { sysctl_ctx_free(&sc->glob_sysctl_ctx); return ENOMEM; } /* * Before calling any CPU methods, collect child driver feature hints * and notify ACPI of them. We support unified SMP power control * so advertise this ourselves. Note this is not the same as independent * SMP control where each CPU can have different settings. */ cpu_features = ACPI_PDC_MP_C1PXTX | ACPI_PDC_MP_C2C3; cpu_features |= acpi_cpu_md_features(); /* * CPU capabilities are specified as a buffer of 32-bit integers: * revision, count, and one or more capabilities. */ if (cpu_features) { ACPI_OBJECT_LIST arglist; uint32_t cap_set[3]; ACPI_OBJECT arg[4]; ACPI_STATUS status; /* UUID needed by _OSC evaluation */ static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53 }; arglist.Pointer = arg; arglist.Count = 4; arg[0].Type = ACPI_TYPE_BUFFER; arg[0].Buffer.Length = sizeof(cpu_oscuuid); arg[0].Buffer.Pointer = cpu_oscuuid; /* UUID */ arg[1].Type = ACPI_TYPE_INTEGER; arg[1].Integer.Value = 1; /* revision */ arg[2].Type = ACPI_TYPE_INTEGER; arg[2].Integer.Value = 2; /* # of capabilities integers */ arg[3].Type = ACPI_TYPE_BUFFER; arg[3].Buffer.Length = sizeof(cap_set[0]) * 2; /* capabilities buffer */ arg[3].Buffer.Pointer = (uint8_t *)cap_set; cap_set[0] = 0; cap_set[1] = cpu_features; status = AcpiEvaluateObject(handle, "_OSC", &arglist, NULL); if (!ACPI_SUCCESS(status)) { if (bootverbose) device_printf(dev, "_OSC failed, use _PDC\n"); arglist.Pointer = arg; arglist.Count = 1; arg[0].Type = ACPI_TYPE_BUFFER; arg[0].Buffer.Length = sizeof(cap_set); arg[0].Buffer.Pointer = (uint8_t *)cap_set; cap_set[0] = 1; /* revision */ cap_set[1] = 1; /* # of capabilities integers */ cap_set[2] = cpu_features; AcpiEvaluateObject(handle, "_PDC", &arglist, NULL); } } child = BUS_ADD_CHILD(dev, dev, 0, "cpu_cst", -1); if (child == NULL) return ENXIO; acpi_set_handle(child, handle); acpi_set_magic(child, cpu_id); sc->cpu_cst = child; child = BUS_ADD_CHILD(dev, dev, 0, "cpu_pst", -1); if (child == NULL) return ENXIO; acpi_set_handle(child, handle); acpi_set_magic(child, cpu_id); bus_generic_probe(dev); bus_generic_attach(dev); AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc); return 0; }
static int ismt_attach(device_t dev) { struct ismt_softc *sc = device_get_softc(dev); int err, num_vectors, val; sc->pcidev = dev; pci_enable_busmaster(dev); if ((sc->smbdev = device_add_child(dev, "smbus", -1)) == NULL) { device_printf(dev, "no smbus child found\n"); err = ENXIO; goto fail; } sc->mmio_rid = PCIR_BAR(0); sc->mmio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mmio_rid, RF_ACTIVE); if (sc->mmio_res == NULL) { device_printf(dev, "cannot allocate mmio region\n"); err = ENOMEM; goto fail; } sc->mmio_tag = rman_get_bustag(sc->mmio_res); sc->mmio_handle = rman_get_bushandle(sc->mmio_res); /* Attach "smbus" child */ if ((err = bus_generic_attach(dev)) != 0) { device_printf(dev, "failed to attach child: %d\n", err); err = ENXIO; goto fail; } bus_dma_tag_create(bus_get_dma_tag(dev), 4, PAGE_SIZE, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, DESC_SIZE, 1, DESC_SIZE, 0, NULL, NULL, &sc->desc_dma_tag); bus_dma_tag_create(bus_get_dma_tag(dev), 4, PAGE_SIZE, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, DMA_BUFFER_SIZE, 1, DMA_BUFFER_SIZE, 0, NULL, NULL, &sc->dma_buffer_dma_tag); bus_dmamap_create(sc->desc_dma_tag, 0, &sc->desc_dma_map); bus_dmamap_create(sc->dma_buffer_dma_tag, 0, &sc->dma_buffer_dma_map); bus_dmamem_alloc(sc->desc_dma_tag, (void **)&sc->desc, BUS_DMA_WAITOK, &sc->desc_dma_map); bus_dmamem_alloc(sc->dma_buffer_dma_tag, (void **)&sc->dma_buffer, BUS_DMA_WAITOK, &sc->dma_buffer_dma_map); bus_dmamap_load(sc->desc_dma_tag, sc->desc_dma_map, sc->desc, DESC_SIZE, ismt_single_map, &sc->desc_bus_addr, 0); bus_dmamap_load(sc->dma_buffer_dma_tag, sc->dma_buffer_dma_map, sc->dma_buffer, DMA_BUFFER_SIZE, ismt_single_map, &sc->dma_buffer_bus_addr, 0); bus_write_4(sc->mmio_res, ISMT_MSTR_MDBA, (sc->desc_bus_addr & 0xFFFFFFFFLL)); bus_write_4(sc->mmio_res, ISMT_MSTR_MDBA + 4, (sc->desc_bus_addr >> 32)); /* initialize the Master Control Register (MCTRL) */ bus_write_4(sc->mmio_res, ISMT_MSTR_MCTRL, ISMT_MCTRL_MEIE); /* initialize the Master Status Register (MSTS) */ bus_write_4(sc->mmio_res, ISMT_MSTR_MSTS, 0); /* initialize the Master Descriptor Size (MDS) */ val = bus_read_4(sc->mmio_res, ISMT_MSTR_MDS); val &= ~ISMT_MDS_MASK; val |= (ISMT_DESC_ENTRIES - 1); bus_write_4(sc->mmio_res, ISMT_MSTR_MDS, val); sc->using_msi = 1; if (pci_msi_count(dev) == 0) { sc->using_msi = 0; goto intx; } num_vectors = 1; if (pci_alloc_msi(dev, &num_vectors) != 0) { sc->using_msi = 0; goto intx; } sc->intr_rid = 1; sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->intr_rid, RF_ACTIVE); if (sc->intr_res == NULL) { sc->using_msi = 0; pci_release_msi(dev); } intx: if (sc->using_msi == 0) { sc->intr_rid = 0; sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->intr_rid, RF_SHAREABLE | RF_ACTIVE); if (sc->intr_res == NULL) { device_printf(dev, "cannot allocate irq\n"); err = ENXIO; goto fail; } } ISMT_DEBUG(dev, "using_msi = %d\n", sc->using_msi); err = bus_setup_intr(dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ismt_intr, sc, &sc->intr_handle); if (err != 0) { device_printf(dev, "cannot setup interrupt\n"); err = ENXIO; goto fail; } return (0); fail: ismt_detach(dev); return (err); }
static int bcm_spi_attach(device_t dev) { struct bcm_spi_softc *sc; device_t gpio; int i, rid; if (device_get_unit(dev) != 0) { device_printf(dev, "only one SPI controller supported\n"); return (ENXIO); } sc = device_get_softc(dev); sc->sc_dev = dev; /* Configure the GPIO pins to ALT0 function to enable SPI the pins. */ gpio = devclass_get_device(devclass_find("gpio"), 0); if (!gpio) { device_printf(dev, "cannot find gpio0\n"); return (ENXIO); } for (i = 0; i < nitems(bcm_spi_pins); i++) bcm_gpio_set_alternate(gpio, bcm_spi_pins[i], BCM_GPIO_ALT0); rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_mem_res) { device_printf(dev, "cannot allocate memory window\n"); return (ENXIO); } sc->sc_bst = rman_get_bustag(sc->sc_mem_res); sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (!sc->sc_irq_res) { bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "cannot allocate interrupt\n"); return (ENXIO); } /* Hook up our interrupt handler. */ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, bcm_spi_intr, sc, &sc->sc_intrhand)) { bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "cannot setup the interrupt handler\n"); return (ENXIO); } mtx_init(&sc->sc_mtx, "bcm_spi", NULL, MTX_DEF); /* Add sysctl nodes. */ bcm_spi_sysctl_init(sc); #ifdef BCM_SPI_DEBUG bcm_spi_printr(dev); #endif /* * Enable the SPI controller. Clear the rx and tx FIFO. * Defaults to SPI mode 0. */ BCM_SPI_WRITE(sc, SPI_CS, SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO); /* Set the SPI clock to 500Khz. */ BCM_SPI_WRITE(sc, SPI_CLK, SPI_CORE_CLK / 500000); #ifdef BCM_SPI_DEBUG bcm_spi_printr(dev); #endif device_add_child(dev, "spibus", -1); return (bus_generic_attach(dev)); }
/* * Scan Open Firmware child nodes, and attach these as children * of the macgpio bus */ static int macgpio_attach(device_t dev) { struct macgpio_softc *sc; struct macgpio_devinfo *dinfo; phandle_t root, child, iparent; device_t cdev; uint32_t irq; sc = device_get_softc(dev); root = sc->sc_node = ofw_bus_get_node(dev); sc->sc_gpios = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_gpios_rid, RF_ACTIVE); /* * Iterate through the sub-devices */ for (child = OF_child(root); child != 0; child = OF_peer(child)) { dinfo = malloc(sizeof(*dinfo), M_MACGPIO, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) != 0) { free(dinfo, M_MACGPIO); continue; } if (OF_getprop(child,"reg",&dinfo->gpio_num, sizeof(dinfo->gpio_num)) != sizeof(dinfo->gpio_num)) { /* * Some early GPIO controllers don't provide GPIO * numbers for GPIOs designed only to provide * interrupt resources. We should still allow these * to attach, but with caution. */ dinfo->gpio_num = -1; } resource_list_init(&dinfo->mdi_resources); if (OF_getprop(child, "interrupts", &irq, sizeof(irq)) == sizeof(irq)) { OF_searchprop(child, "interrupt-parent", &iparent, sizeof(iparent)); resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ, 0, MAP_IRQ(iparent, irq), MAP_IRQ(iparent, irq), 1); } /* Fix messed-up offsets */ if (dinfo->gpio_num > 0x50) dinfo->gpio_num -= 0x50; cdev = device_add_child(dev, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", dinfo->mdi_obdinfo.obd_name); ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo); free(dinfo, M_MACGPIO); continue; } device_set_ivars(cdev, dinfo); } return (bus_generic_attach(dev)); }
static int obio_attach(device_t dev) { struct obio_softc *sc = device_get_softc(dev); int rid; sc->oba_mem_rman.rm_type = RMAN_ARRAY; sc->oba_mem_rman.rm_descr = "OBIO memory"; if (rman_init(&sc->oba_mem_rman) != 0 || rman_manage_region(&sc->oba_mem_rman, OBIO_MEM_START, OBIO_MEM_END) != 0) panic("obio_attach: failed to set up I/O rman"); sc->oba_irq_rman.rm_type = RMAN_ARRAY; sc->oba_irq_rman.rm_descr = "OBIO IRQ"; if (rman_init(&sc->oba_irq_rman) != 0 || rman_manage_region(&sc->oba_irq_rman, 0, NIRQS-1) != 0) panic("obio_attach: failed to set up IRQ rman"); /* Hook up our interrupt handler. */ if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, RT305X_INTR, RT305X_INTR, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) { device_printf(dev, "unable to allocate IRQ resource\n"); return (ENXIO); } if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, obio_intr, NULL, sc, &sc->sc_ih))) { device_printf(dev, "WARNING: unable to register interrupt handler\n"); return (ENXIO); } /* Hook up our FAST interrupt handler. */ if ((sc->sc_fast_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, RT305X_FAST_INTR, RT305X_FAST_INTR, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) { device_printf(dev, "unable to allocate IRQ resource\n"); return (ENXIO); } if ((bus_setup_intr(dev, sc->sc_fast_irq, INTR_TYPE_MISC, obio_intr, NULL, sc, &sc->sc_fast_ih))) { device_printf(dev, "WARNING: unable to register interrupt handler\n"); return (ENXIO); } /* disable all interrupts */ rt305x_ic_set(IC_INT_DIS, IC_INT_MASK|IC_LINE_GLOBAL); bus_generic_probe(dev); obio_add_res_child(dev, "rt305x_sysctl", 0, SYSCTL_BASE, (SYSCTL_END - SYSCTL_BASE + 1), IC_SYSCTL); obio_add_res_child(dev, "rt305x_ic", 0, INTCTL_BASE, (INTCTL_END - INTCTL_BASE + 1), -1); #ifdef notyet obio_add_res_child(dev, "timer",0, TIMER_BASE, (TIMER_END - TIMER_BASE + 1), IC_TIMER0); obio_add_res_child(dev, "rt305x_memc", 0, MEMCTRL_BASE, (MEMCTRL_END - MEMCTRL_BASE + 1), -1); obio_add_res_child(dev, "pcm", 0, PCM_BASE, (PCM_END - PCM_BASE + 1), IC_PCM); #endif obio_add_res_child(dev, "uart", 0, UART_BASE, (UART_END - UART_BASE + 1), IC_UART); obio_add_res_child(dev, "gpio", 0, PIO_BASE, (PIO_END - PIO_BASE + 1), IC_PIO); #ifdef notyet obio_add_res_child(dev, "rt305x_dma", 0, GDMA_BASE, (GDMA_END - GDMA_BASE + 1), IC_DMA); obio_add_res_child(dev, "rt305x_nandc", 0, NANDFC_BASE, (NANDFC_END - NANDFC_BASE + 1), IC_NAND); obio_add_res_child(dev, "i2c", 0, I2C_BASE, (I2C_END - I2C_BASE + 1), -1); obio_add_res_child(dev, "i2s", 0, I2S_BASE, (I2S_END - I2S_BASE + 1), IC_I2S); #endif obio_add_res_child(dev, "spi", 0, SPI_BASE, (SPI_END - SPI_BASE + 1), -1); obio_add_res_child(dev, "uart", 1, UARTLITE_BASE, (UARTLITE_END - UARTLITE_BASE + 1), IC_UARTLITE); #if !defined(RT5350) && !defined(MT7620) obio_add_res_child(dev, "cfi", 0, FLASH_BASE, (FLASH_END - FLASH_BASE + 1), -1); obio_add_res_child(dev, "dwcotg", 0, USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE + 1), IC_OTG); #else obio_add_res_child(dev, "ehci", 0, USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE + 1), IC_OTG); obio_add_res_child(dev, "ohci", 0, USB_OHCI_BASE, (USB_OHCI_END - USB_OHCI_BASE + 1), IC_OTG); #endif obio_add_res_child(dev, "switch", 0, ETHSW_BASE, (ETHSW_END - ETHSW_BASE + 1), IC_ETHSW); bus_enumerate_hinted_children(dev); bus_generic_attach(dev); /* enable IC */ rt305x_ic_set(IC_INT_ENA, IC_LINE_GLOBAL); return (0); }
static int ofw_cpu_attach(device_t dev) { bus_generic_probe(dev); return (bus_generic_attach(dev)); }
static int thunder_pem_attach(device_t dev) { devclass_t pci_class; device_t parent; struct thunder_pem_softc *sc; int error; int rid; sc = device_get_softc(dev); sc->dev = dev; /* Allocate memory for resource */ pci_class = devclass_find("pci"); parent = device_get_parent(dev); if (device_get_devclass(parent) == pci_class) rid = PCIR_BAR(0); else rid = RID_PEM_SPACE; sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->reg == NULL) { device_printf(dev, "Failed to allocate resource\n"); return (ENXIO); } sc->reg_bst = rman_get_bustag(sc->reg); sc->reg_bsh = rman_get_bushandle(sc->reg); /* Map SLI, do it only once */ if (!sli0_s2m_regx_base) { bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC, SLIX_S2M_REGX_ACC_SIZE, 0, &sli0_s2m_regx_base); } if (!sli1_s2m_regx_base) { bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC + SLIX_S2M_REGX_ACC_SPACING, SLIX_S2M_REGX_ACC_SIZE, 0, &sli1_s2m_regx_base); } if ((sli0_s2m_regx_base == 0) || (sli1_s2m_regx_base == 0)) { device_printf(dev, "bus_space_map failed to map slix_s2m_regx_base\n"); goto fail; } /* Identify PEM */ if (thunder_pem_identify(dev) != 0) goto fail; /* Initialize rman and allocate regions */ sc->mem_rman.rm_type = RMAN_ARRAY; sc->mem_rman.rm_descr = "PEM PCIe Memory"; error = rman_init(&sc->mem_rman); if (error != 0) { device_printf(dev, "memory rman_init() failed. error = %d\n", error); goto fail; } sc->io_rman.rm_type = RMAN_ARRAY; sc->io_rman.rm_descr = "PEM PCIe IO"; error = rman_init(&sc->io_rman); if (error != 0) { device_printf(dev, "IO rman_init() failed. error = %d\n", error); goto fail_mem; } /* * We ignore the values that may have been provided in FDT * and configure ranges according to the below formula * for all types of devices. This is because some DTBs provided * by EFI do not have proper ranges property or don't have them * at all. */ /* Fill memory window */ sc->ranges[0].pci_base = PCI_MEMORY_BASE; sc->ranges[0].size = PCI_MEMORY_SIZE; sc->ranges[0].phys_base = sc->sli_window_base + SLI_PCI_OFFSET + sc->ranges[0].pci_base; rman_manage_region(&sc->mem_rman, sc->ranges[0].phys_base, sc->ranges[0].phys_base + sc->ranges[0].size - 1); /* Fill IO window */ sc->ranges[1].pci_base = PCI_IO_BASE; sc->ranges[1].size = PCI_IO_SIZE; sc->ranges[1].phys_base = sc->sli_window_base + SLI_PCI_OFFSET + sc->ranges[1].pci_base; rman_manage_region(&sc->io_rman, sc->ranges[1].phys_base, sc->ranges[1].phys_base + sc->ranges[1].size - 1); if (thunder_pem_init(sc)) { device_printf(dev, "Failure during PEM init\n"); goto fail_io; } device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); fail_io: rman_fini(&sc->io_rman); fail_mem: rman_fini(&sc->mem_rman); fail: bus_free_resource(dev, SYS_RES_MEMORY, sc->reg); return (ENXIO); }
static int zbpci_attach(device_t dev) { int n, rid, size; vm_offset_t va; struct resource *res; /* * Reserve the physical memory window used to map PCI I/O space. */ rid = 0; res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, PCI_IOSPACE_ADDR, PCI_IOSPACE_ADDR + PCI_IOSPACE_SIZE - 1, PCI_IOSPACE_SIZE, 0); if (res == NULL) panic("Cannot allocate resource for PCI I/O space mapping."); port_rman.rm_start = 0; port_rman.rm_end = PCI_IOSPACE_SIZE - 1; port_rman.rm_type = RMAN_ARRAY; port_rman.rm_descr = "PCI I/O ports"; if (rman_init(&port_rman) != 0 || rman_manage_region(&port_rman, 0, PCI_IOSPACE_SIZE - 1) != 0) panic("%s: port_rman", __func__); /* * Reserve the physical memory that is used to read/write to the * pci config space but don't activate it. We are using a page worth * of KVA as a window over this region. */ rid = 1; size = (PCI_BUSMAX + 1) * (PCI_SLOTMAX + 1) * (PCI_FUNCMAX + 1) * 256; res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, CFG_PADDR_BASE, CFG_PADDR_BASE + size - 1, size, 0); if (res == NULL) panic("Cannot allocate resource for config space accesses."); /* * Allocate the entire "match bit lanes" address space. */ #if _BYTE_ORDER == _BIG_ENDIAN rid = 2; res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, PCI_MATCH_BIT_LANES_START, PCI_MATCH_BIT_LANES_END, PCI_MATCH_BIT_LANES_SIZE, 0); if (res == NULL) panic("Cannot allocate resource for pci match bit lanes."); #endif /* _BYTE_ORDER ==_BIG_ENDIAN */ /* * Allocate KVA for accessing PCI config space. */ va = kva_alloc(PAGE_SIZE * mp_ncpus); if (va == 0) { device_printf(dev, "Cannot allocate virtual addresses for " "config space access.\n"); return (ENOMEM); } for (n = 0; n < mp_ncpus; ++n) zbpci_config_space[n].vaddr = va + n * PAGE_SIZE; /* * Sibyte has the PCI bus hierarchy rooted at bus 0 and HT-PCI * hierarchy rooted at bus 1. */ if (device_add_child(dev, "pci", 0) == NULL) panic("zbpci_attach: could not add pci bus 0.\n"); if (device_add_child(dev, "pci", 1) == NULL) panic("zbpci_attach: could not add pci bus 1.\n"); if (bootverbose) device_printf(dev, "attached.\n"); return (bus_generic_attach(dev)); }
static int mambobus_attach(device_t dev) { bus_generic_probe(dev); return (bus_generic_attach(dev)); }
static int sata_attach(device_t dev) { struct sata_softc *sc; int mem_id, irq_id, error, i; device_t ata_chan; uint32_t reg; sc = device_get_softc(dev); sc->sc_dev = dev; mem_id = 0; irq_id = 0; /* Allocate resources */ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_id, RF_ACTIVE); if (sc->sc_mem_res == NULL) { device_printf(dev, "could not allocate memory.\n"); return (ENOMEM); } sc->sc_mem_res_bustag = rman_get_bustag(sc->sc_mem_res); sc->sc_mem_res_bushdl = rman_get_bushandle(sc->sc_mem_res); KASSERT(sc->sc_mem_res_bustag && sc->sc_mem_res_bushdl, ("cannot get bus handle or tag.")); sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_id, RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(dev, "could not allocate IRQ.\n"); error = ENOMEM; goto err; } error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY, NULL, sata_intr, sc, &sc->sc_irq_cookiep); if (error != 0) { device_printf(dev, "could not setup interrupt.\n"); goto err; } /* Attach channels */ for (i = 0; i < SATA_CHAN_NUM; i++) { ata_chan = device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 0)); if (!ata_chan) { device_printf(dev, "cannot add channel %d.\n", i); error = ENOMEM; goto err; } } /* Disable interrupt coalescing */ reg = SATA_INL(sc, SATA_CR); for (i = 0; i < SATA_CHAN_NUM; i++) reg |= SATA_CR_COALDIS(i); /* Disable DMA byte swapping */ if (sc->sc_version == 2) reg |= SATA_CR_NODMABS | SATA_CR_NOEDMABS | SATA_CR_NOPRDPBS; SATA_OUTL(sc, SATA_CR, reg); /* Clear and mask all interrupts */ SATA_OUTL(sc, SATA_ICR, 0); SATA_OUTL(sc, SATA_MIMR, 0); return(bus_generic_attach(dev)); err: sata_detach(dev); return (error); }
static int lbc_attach(device_t dev) { struct lbc_softc *sc; struct lbc_devinfo *di; struct rman *rm; u_long offset, start, size; device_t cdev; phandle_t node, child; pcell_t *ranges, *rangesptr; int tuple_size, tuples; int par_addr_cells; int bank, error, i; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_mrid = 0; sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid, RF_ACTIVE); if (sc->sc_mres == NULL) return (ENXIO); sc->sc_bst = rman_get_bustag(sc->sc_mres); sc->sc_bsh = rman_get_bushandle(sc->sc_mres); for (bank = 0; bank < LBC_DEV_MAX; bank++) { bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0); } /* * Initialize configuration register: * - enable Local Bus * - set data buffer control signal function * - disable parity byte select * - set ECC parity type * - set bus monitor timing and timer prescale */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0); /* * Initialize clock ratio register: * - disable PLL bypass mode * - configure LCLK delay cycles for the assertion of LALE * - set system clock divider */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008); bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001); sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); if (sc->sc_ires != NULL) { error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc, &sc->sc_icookie); if (error) { device_printf(dev, "could not activate interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); sc->sc_ires = NULL; } } sc->sc_ltesr = ~0; rangesptr = NULL; rm = &sc->sc_rman; rm->rm_type = RMAN_ARRAY; rm->rm_descr = "Local Bus Space"; rm->rm_start = 0UL; rm->rm_end = ~0UL; error = rman_init(rm); if (error) goto fail; error = rman_manage_region(rm, rm->rm_start, rm->rm_end); if (error) { rman_fini(rm); goto fail; } /* * Process 'ranges' property. */ node = ofw_bus_get_node(dev); if ((fdt_addrsize_cells(node, &sc->sc_addr_cells, &sc->sc_size_cells)) != 0) { error = ENXIO; goto fail; } par_addr_cells = fdt_parent_addr_cells(node); if (par_addr_cells > 2) { device_printf(dev, "unsupported parent #addr-cells\n"); error = ERANGE; goto fail; } tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells + sc->sc_size_cells); tuples = OF_getprop_alloc(node, "ranges", tuple_size, (void **)&ranges); if (tuples < 0) { device_printf(dev, "could not retrieve 'ranges' property\n"); error = ENXIO; goto fail; } rangesptr = ranges; debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, " "tuple_size = %d, tuples = %d\n", par_addr_cells, sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples); start = 0; size = 0; for (i = 0; i < tuples; i++) { /* The first cell is the bank (chip select) number. */ bank = fdt_data_get((void *)ranges, 1); if (bank < 0 || bank > LBC_DEV_MAX) { device_printf(dev, "bank out of range: %d\n", bank); error = ERANGE; goto fail; } ranges += 1; /* * Remaining cells of the child address define offset into * this CS. */ offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1); ranges += sc->sc_addr_cells - 1; /* Parent bus start address of this bank. */ start = fdt_data_get((void *)ranges, par_addr_cells); ranges += par_addr_cells; size = fdt_data_get((void *)ranges, sc->sc_size_cells); ranges += sc->sc_size_cells; debugf("bank = %d, start = %lx, size = %lx\n", bank, start, size); sc->sc_banks[bank].addr = start + offset; sc->sc_banks[bank].size = size; /* * Attributes for the bank. * * XXX Note there are no DT bindings defined for them at the * moment, so we need to provide some defaults. */ sc->sc_banks[bank].width = 16; sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM; sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED; sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED; sc->sc_banks[bank].wp = 0; } /* * Initialize mem-mappings for the LBC banks (i.e. chip selects). */ error = lbc_banks_map(sc); if (error) goto fail; /* * Walk the localbus and add direct subordinates as our children. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) { free(di, M_LBC); device_printf(dev, "could not set up devinfo\n"); continue; } resource_list_init(&di->di_res); if (fdt_lbc_reg_decode(child, sc, di)) { device_printf(dev, "could not process 'reg' " "property\n"); ofw_bus_gen_destroy_devinfo(&di->di_ofw); free(di, M_LBC); continue; } fdt_lbc_fixup(child, sc, di); /* Add newbus device for this FDT node */ cdev = device_add_child(dev, NULL, -1); if (cdev == NULL) { device_printf(dev, "could not add child: %s\n", di->di_ofw.obd_name); resource_list_free(&di->di_res); ofw_bus_gen_destroy_devinfo(&di->di_ofw); free(di, M_LBC); continue; } debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name, (void *)child); device_set_ivars(cdev, di); } /* * Enable the LBC. */ lbc_banks_enable(sc); free(rangesptr, M_OFWPROP); return (bus_generic_attach(dev)); fail: free(rangesptr, M_OFWPROP); bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres); return (error); }
/* * PCI attach: scan Open Firmware child nodes, and attach these as children * of the macio bus */ static int macio_attach(device_t dev) { struct macio_softc *sc; struct macio_devinfo *dinfo; phandle_t root; phandle_t child; phandle_t subchild; device_t cdev; u_int reg[3]; int error, quirks; sc = device_get_softc(dev); root = sc->sc_node = ofw_bus_get_node(dev); /* * Locate the device node and it's base address */ if (OF_getprop(root, "assigned-addresses", reg, sizeof(reg)) < sizeof(reg)) { return (ENXIO); } sc->sc_base = reg[2]; sc->sc_size = MACIO_REG_SIZE; sc->sc_mem_rman.rm_type = RMAN_ARRAY; sc->sc_mem_rman.rm_descr = "MacIO Device Memory"; error = rman_init(&sc->sc_mem_rman); if (error) { device_printf(dev, "rman_init() failed. error = %d\n", error); return (error); } error = rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size); if (error) { device_printf(dev, "rman_manage_region() failed. error = %d\n", error); return (error); } /* * Iterate through the sub-devices */ for (child = OF_child(root); child != 0; child = OF_peer(child)) { dinfo = malloc(sizeof(*dinfo), M_MACIO, M_WAITOK | M_ZERO); if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) != 0) { free(dinfo, M_MACIO); continue; } quirks = macio_get_quirks(dinfo->mdi_obdinfo.obd_name); if ((quirks & MACIO_QUIRK_IGNORE) != 0) { ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo); free(dinfo, M_MACIO); continue; } resource_list_init(&dinfo->mdi_resources); dinfo->mdi_ninterrupts = 0; macio_add_intr(child, dinfo); if ((quirks & MACIO_QUIRK_USE_CHILD_REG) != 0) macio_add_reg(OF_child(child), dinfo); else macio_add_reg(child, dinfo); if ((quirks & MACIO_QUIRK_CHILD_HAS_INTR) != 0) for (subchild = OF_child(child); subchild != 0; subchild = OF_peer(subchild)) macio_add_intr(subchild, dinfo); cdev = device_add_child(dev, NULL, -1); if (cdev == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", dinfo->mdi_obdinfo.obd_name); resource_list_free(&dinfo->mdi_resources); ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo); free(dinfo, M_MACIO); continue; } device_set_ivars(cdev, dinfo); } return (bus_generic_attach(dev)); }
static int envctrl_attach(device_t dev) { struct pcf_softc *sc; int rv = ENXIO; sc = DEVTOSOFTC(dev); bzero(sc, sizeof(struct pcf_softc)); /* IO port is mandatory */ sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->rid_ioport, RF_ACTIVE); if (sc->res_ioport == 0) { device_printf(dev, "cannot reserve I/O port range\n"); goto error; } sc->bt_ioport = rman_get_bustag(sc->res_ioport); sc->bh_ioport = rman_get_bushandle(sc->res_ioport); sc->pcf_flags = device_get_flags(dev); if (!(sc->pcf_flags & IIC_POLLED)) { sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq, RF_ACTIVE); if (sc->res_irq == 0) { device_printf(dev, "can't reserve irq, polled mode.\n"); sc->pcf_flags |= IIC_POLLED; } } /* reset the chip */ pcf_rst_card(dev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->res_irq, INTR_TYPE_NET /* | INTR_ENTROPY */, pcf_intr, sc, &sc->intr_cookie); if (rv) { device_printf(dev, "could not setup IRQ\n"); goto error; } if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) device_printf(dev, "could not allocate iicbus instance\n"); /* probe and attach the iicbus */ bus_generic_attach(dev); return (0); error: if (sc->res_irq != 0) { bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); } if (sc->res_ioport != 0) { bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); } return (rv); }
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; }
static int apb_attach(device_t dev) { struct apb_softc *sc = device_get_softc(dev); #ifdef INTRNG intptr_t xref = pic_xref(dev); int miscirq; #else int rid = 0; #endif sc->apb_dev = dev; sc->apb_mem_rman.rm_type = RMAN_ARRAY; sc->apb_mem_rman.rm_descr = "APB memory window"; if(ar531x_soc >= AR531X_SOC_AR5315) { if (rman_init(&sc->apb_mem_rman) != 0 || rman_manage_region(&sc->apb_mem_rman, AR5315_APB_BASE, AR5315_APB_BASE + AR5315_APB_SIZE - 1) != 0) panic("apb_attach: failed to set up memory rman"); } else { if (rman_init(&sc->apb_mem_rman) != 0 || rman_manage_region(&sc->apb_mem_rman, AR5312_APB_BASE, AR5312_APB_BASE + AR5312_APB_SIZE - 1) != 0) panic("apb_attach: failed to set up memory rman"); } sc->apb_irq_rman.rm_type = RMAN_ARRAY; sc->apb_irq_rman.rm_descr = "APB IRQ"; if (rman_init(&sc->apb_irq_rman) != 0 || rman_manage_region(&sc->apb_irq_rman, APB_IRQ_BASE, APB_IRQ_END) != 0) panic("apb_attach: failed to set up IRQ rman"); #ifndef INTRNG if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { device_printf(dev, "unable to allocate IRQ resource\n"); return (ENXIO); } if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC, apb_filter, NULL, sc, &sc->sc_misc_ih))) { device_printf(dev, "WARNING: unable to register interrupt handler\n"); return (ENXIO); } #else /* Register the interrupts */ if (apb_pic_register_isrcs(sc) != 0) { device_printf(dev, "could not register PIC ISRCs\n"); return (ENXIO); } /* * Now, when everything is initialized, it's right time to * register interrupt controller to interrupt framefork. */ if (intr_pic_register(dev, xref) == NULL) { device_printf(dev, "could not register PIC\n"); return (ENXIO); } if(ar531x_soc >= AR531X_SOC_AR5315) { miscirq = AR5315_CPU_IRQ_MISC; } else { miscirq = AR5312_IRQ_MISC; } cpu_establish_hardintr("aric", apb_filter, NULL, sc, miscirq, INTR_TYPE_MISC, NULL); #endif /* mask all misc interrupt */ if(ar531x_soc >= AR531X_SOC_AR5315) { ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_MISC_INTMASK, 0); } else { ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTMASK, 0); } bus_generic_probe(dev); bus_enumerate_hinted_children(dev); bus_generic_attach(dev); return (0); }
static int at91_attach(device_t dev) { struct at91_softc *sc = device_get_softc(dev); const struct arm_devmap_entry *pdevmap; int i; arm_post_filter = at91_eoi; at91_softc = sc; sc->sc_st = &at91_bs_tag; sc->sc_sh = AT91_BASE; sc->sc_aic_sh = AT91_BASE + AT91_SYS_BASE; sc->dev = dev; sc->sc_irq_rman.rm_type = RMAN_ARRAY; sc->sc_irq_rman.rm_descr = "AT91 IRQs"; if (rman_init(&sc->sc_irq_rman) != 0 || rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0) panic("at91_attach: failed to set up IRQ rman"); sc->sc_mem_rman.rm_type = RMAN_ARRAY; sc->sc_mem_rman.rm_descr = "AT91 Memory"; if (rman_init(&sc->sc_mem_rman) != 0) panic("at91_attach: failed to set up memory rman"); for (pdevmap = at91_devmap; pdevmap->pd_va != 0; pdevmap++) { if (rman_manage_region(&sc->sc_mem_rman, pdevmap->pd_va, pdevmap->pd_va + pdevmap->pd_size - 1) != 0) panic("at91_attach: failed to set up memory rman"); } /* * Setup the interrupt table. */ if (soc_info.soc_data == NULL || soc_info.soc_data->soc_irq_prio == NULL) panic("Interrupt priority table missing\n"); for (i = 0; i < 32; i++) { bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + i * 4, i); /* Priority. */ bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, soc_info.soc_data->soc_irq_prio[i]); if (i < 8) bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 1); } bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); /* No debug. */ bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); /* Disable and clear all interrupts. */ bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); /* * Add this device's children... */ at91_cpu_add_builtin_children(dev, soc_info.soc_data->soc_children); soc_info.soc_data->soc_clock_init(); bus_generic_probe(dev); bus_generic_attach(dev); enable_interrupts(I32_bit | F32_bit); return (0); }
static int ofw_iicbus_attach(device_t dev) { struct iicbus_softc *sc = IICBUS_SOFTC(dev); struct ofw_iicbus_devinfo *dinfo; phandle_t child, node, root; pcell_t freq, paddr; device_t childdev; ssize_t compatlen; char compat[255]; char *curstr; u_int iic_addr_8bit = 0; sc->dev = dev; mtx_init(&sc->lock, "iicbus", NULL, MTX_DEF); /* * If there is a clock-frequency property for the device node, use it as * the starting value for the bus frequency. Then call the common * routine that handles the tunable/sysctl which allows the FDT value to * be overridden by the user. */ node = ofw_bus_get_node(dev); freq = 0; OF_getencprop(node, "clock-frequency", &freq, sizeof(freq)); iicbus_init_frequency(dev, freq); iicbus_reset(dev, IIC_FASTEST, 0, NULL); bus_generic_probe(dev); bus_enumerate_hinted_children(dev); /* * Check if we're running on a PowerMac, needed for the I2C * address below. */ root = OF_peer(0); compatlen = OF_getprop(root, "compatible", compat, sizeof(compat)); if (compatlen != -1) { for (curstr = compat; curstr < compat + compatlen; curstr += strlen(curstr) + 1) { if (strncmp(curstr, "MacRISC", 7) == 0) iic_addr_8bit = 1; } } /* * Attach those children represented in the device tree. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { /* * Try to get the I2C address first from the i2c-address * property, then try the reg property. It moves around * on different systems. */ if (OF_getencprop(child, "i2c-address", &paddr, sizeof(paddr)) == -1) if (OF_getencprop(child, "reg", &paddr, sizeof(paddr)) == -1) continue; /* * Now set up the I2C and OFW bus layer devinfo and add it * to the bus. */ dinfo = malloc(sizeof(struct ofw_iicbus_devinfo), M_DEVBUF, M_NOWAIT | M_ZERO); if (dinfo == NULL) continue; /* * FreeBSD drivers expect I2C addresses to be expressed as * 8-bit values. Apple OFW data contains 8-bit values, but * Linux FDT data contains 7-bit values, so shift them up to * 8-bit format. */ if (iic_addr_8bit) dinfo->opd_dinfo.addr = paddr; else dinfo->opd_dinfo.addr = paddr << 1; if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 0) { free(dinfo, M_DEVBUF); continue; } childdev = device_add_child(dev, NULL, -1); resource_list_init(&dinfo->opd_dinfo.rl); ofw_bus_intr_to_rl(childdev, child, &dinfo->opd_dinfo.rl, NULL); device_set_ivars(childdev, dinfo); } /* Register bus */ OF_device_register_xref(OF_xref_from_node(node), dev); return (bus_generic_attach(dev)); }
static int ad_attach(device_t dev) { struct ata_channel *ch = device_get_softc(device_get_parent(dev)); struct ata_device *atadev = device_get_softc(dev); struct disk_info info; struct ad_softc *adp; cdev_t cdev; u_int32_t lbasize; u_int64_t lbasize48; /* check that we have a virgin disk to attach */ if (device_get_ivars(dev)) return EEXIST; adp = kmalloc(sizeof(struct ad_softc), M_AD, M_INTWAIT | M_ZERO); device_set_ivars(dev, adp); if ((atadev->param.atavalid & ATA_FLAG_54_58) && atadev->param.current_heads && atadev->param.current_sectors) { adp->heads = atadev->param.current_heads; adp->sectors = atadev->param.current_sectors; adp->total_secs = (u_int32_t)atadev->param.current_size_1 | ((u_int32_t)atadev->param.current_size_2 << 16); } else { adp->heads = atadev->param.heads; adp->sectors = atadev->param.sectors; adp->total_secs = atadev->param.cylinders * adp->heads * adp->sectors; } lbasize = (u_int32_t)atadev->param.lba_size_1 | ((u_int32_t)atadev->param.lba_size_2 << 16); /* does this device need oldstyle CHS addressing */ if (!ad_version(atadev->param.version_major) || !lbasize) atadev->flags |= ATA_D_USE_CHS; /* use the 28bit LBA size if valid or bigger than the CHS mapping */ if (atadev->param.cylinders == 16383 || adp->total_secs < lbasize) adp->total_secs = lbasize; /* use the 48bit LBA size if valid */ lbasize48 = ((u_int64_t)atadev->param.lba_size48_1) | ((u_int64_t)atadev->param.lba_size48_2 << 16) | ((u_int64_t)atadev->param.lba_size48_3 << 32) | ((u_int64_t)atadev->param.lba_size48_4 << 48); if ((atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) && lbasize48 > ATA_MAX_28BIT_LBA) adp->total_secs = lbasize48; /* init device parameters */ ad_init(dev); /* create the disk device */ /* XXX TGEN Maybe use DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX. */ devstat_add_entry(&adp->stats, "ad", device_get_unit(dev), DEV_BSIZE, DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE, DEVSTAT_PRIORITY_DISK); cdev = disk_create(device_get_unit(dev), &adp->disk, &ad_ops); cdev->si_drv1 = dev; if (ch->dma) cdev->si_iosize_max = ch->dma->max_iosize; else cdev->si_iosize_max = DFLTPHYS; adp->cdev = cdev; bzero(&info, sizeof(info)); info.d_media_blksize = DEV_BSIZE; /* mandatory */ info.d_media_blocks = adp->total_secs; info.d_secpertrack = adp->sectors; /* optional */ info.d_nheads = adp->heads; info.d_ncylinders = adp->total_secs/(adp->heads*adp->sectors); info.d_secpercyl = adp->sectors * adp->heads; info.d_serialno = atadev->param.serial; device_add_child(dev, "subdisk", device_get_unit(dev)); bus_generic_attach(dev); /* announce we are here */ ad_describe(dev); disk_setdiskinfo(&adp->disk, &info); return 0; }
static int sbc_attach(device_t dev) { char *err = NULL; struct sbc_softc *scp; struct sndcard_func *func; u_int32_t logical_id = isa_get_logicalid(dev); int flags = device_get_flags(dev); int f, dh, dl, x, irq, i; if (!logical_id && (flags & DV_F_DUAL_DMA)) { bus_set_resource(dev, SYS_RES_DRQ, 1, flags & DV_F_DRQ_MASK, 1); } scp = device_get_softc(dev); bzero(scp, sizeof(*scp)); scp->dev = dev; sbc_lockinit(scp); err = "alloc_resource"; if (alloc_resource(scp)) goto bad; err = "sb_reset_dsp"; if (sb_reset_dsp(scp->io[0])) goto bad; err = "sb_identify_board"; scp->bd_ver = sb_identify_board(scp->io[0]) & 0x00000fff; if (scp->bd_ver == 0) goto bad; f = 0; if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) scp->bd_ver = 0x0499; switch ((scp->bd_ver & 0x0f00) >> 8) { case 1: /* old sound blaster has nothing... */ break; case 2: f |= BD_F_DUP_MIDI; if (scp->bd_ver > 0x200) f |= BD_F_MIX_CT1335; break; case 5: f |= BD_F_ESS; scp->bd_ver = 0x0301; case 3: f |= BD_F_DUP_MIDI | BD_F_MIX_CT1345; break; case 4: f |= BD_F_SB16 | BD_F_MIX_CT1745; if (scp->drq[0]) dl = rman_get_start(scp->drq[0]); else dl = -1; if (scp->drq[1]) dh = rman_get_start(scp->drq[1]); else dh = dl; if (!logical_id && (dh < dl)) { struct resource *r; r = scp->drq[0]; scp->drq[0] = scp->drq[1]; scp->drq[1] = r; dl = rman_get_start(scp->drq[0]); dh = rman_get_start(scp->drq[1]); } /* soft irq/dma configuration */ x = -1; irq = rman_get_start(scp->irq[0]); #ifdef PC98 /* SB16 in PC98 use different IRQ table */ if (irq == 3) x = 1; else if (irq == 5) x = 8; else if (irq == 10) x = 2; else if (irq == 12) x = 4; if (x == -1) { err = "bad irq (3/5/10/12 valid)"; goto bad; } else sb_setmixer(scp->io[0], IRQ_NR, x); /* SB16 in PC98 use different dma setting */ sb_setmixer(scp->io[0], DMA_NR, dh == 0 ? 1 : 2); #else if (irq == 5) x = 2; else if (irq == 7) x = 4; else if (irq == 9) x = 1; else if (irq == 10) x = 8; if (x == -1) { err = "bad irq (5/7/9/10 valid)"; goto bad; } else sb_setmixer(scp->io[0], IRQ_NR, x); sb_setmixer(scp->io[0], DMA_NR, (1 << dh) | (1 << dl)); #endif if (bootverbose) { device_printf(dev, "setting card to irq %d, drq %d", irq, dl); if (dl != dh) printf(", %d", dh); printf("\n"); } break; } switch (logical_id) { case 0x43008c0e: /* CTL0043 */ case 0x01200000: case 0x01000000: f |= BD_F_SB16X; break; } scp->bd_ver |= f << 16; err = "setup_intr"; for (i = 0; i < IRQ_MAX; i++) { scp->ihl[i].parent = scp; if (snd_setup_intr(dev, scp->irq[i], 0, sbc_intr, &scp->ihl[i], &scp->ih[i])) goto bad; } /* PCM Audio */ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); if (func == NULL) goto bad; func->func = SCF_PCM; scp->child_pcm = device_add_child(dev, "pcm", -1); device_set_ivars(scp->child_pcm, func); /* Midi Interface */ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); if (func == NULL) goto bad; func->func = SCF_MIDI; scp->child_midi1 = device_add_child(dev, "midi", -1); device_set_ivars(scp->child_midi1, func); /* OPL FM Synthesizer */ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO); if (func == NULL) goto bad; func->func = SCF_SYNTH; scp->child_midi2 = device_add_child(dev, "midi", -1); device_set_ivars(scp->child_midi2, func); /* probe/attach kids */ bus_generic_attach(dev); return (0); bad: if (err) device_printf(dev, "%s\n", err); release_resource(scp); return (ENXIO); }
static int bcm_bsc_attach(device_t dev) { struct bcm_bsc_softc *sc; unsigned long start; device_t gpio; int i, rid; sc = device_get_softc(dev); sc->sc_dev = dev; rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_mem_res) { device_printf(dev, "cannot allocate memory window\n"); return (ENXIO); } sc->sc_bst = rman_get_bustag(sc->sc_mem_res); sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); /* Check the unit we are attaching by its base address. */ start = rman_get_start(sc->sc_mem_res); for (i = 0; i < nitems(bcm_bsc_pins); i++) { if (bcm_bsc_pins[i].start == (start & BCM_BSC_BASE_MASK)) break; } if (i == nitems(bcm_bsc_pins)) { device_printf(dev, "only bsc0 and bsc1 are supported\n"); bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); return (ENXIO); } /* * Configure the GPIO pins to ALT0 function to enable BSC control * over the pins. */ gpio = devclass_get_device(devclass_find("gpio"), 0); if (!gpio) { device_printf(dev, "cannot find gpio0\n"); bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); return (ENXIO); } bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].sda, BCM_GPIO_ALT0); bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].scl, BCM_GPIO_ALT0); rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE); if (!sc->sc_irq_res) { bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "cannot allocate interrupt\n"); return (ENXIO); } /* Hook up our interrupt handler. */ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, bcm_bsc_intr, sc, &sc->sc_intrhand)) { bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); device_printf(dev, "cannot setup the interrupt handler\n"); return (ENXIO); } mtx_init(&sc->sc_mtx, "bcm_bsc", NULL, MTX_DEF); bcm_bsc_sysctl_init(sc); /* Enable the BSC controller. Flush the FIFO. */ BCM_BSC_LOCK(sc); bcm_bsc_reset(sc); BCM_BSC_UNLOCK(sc); sc->sc_iicbus = device_add_child(dev, "iicbus", -1); if (sc->sc_iicbus == NULL) { bcm_bsc_detach(dev); return (ENXIO); } return (bus_generic_attach(dev)); }
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); }
int iq80321_attach(device_t dev) { struct i80321_softc *sc = device_get_softc(dev); int b0u, b0l, b1u, b1l; vm_paddr_t memstart = 0; vm_size_t memsize = 0; int busno; /* * Fill in the space tag for the i80321's own devices, * and hand-craft the space handle for it (the device * was mapped during early bootstrap). */ i80321_bs_init(&i80321_bs_tag, sc); sc->sc_st = &i80321_bs_tag; sc->sc_sh = IQ80321_80321_VBASE; sc->dev = dev; sc->sc_is_host = 1; /* * Slice off a subregion for the Memory Controller -- we need it * here in order read the memory size. */ if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE, VERDE_MCU_SIZE, &sc->sc_mcu_sh)) panic("%s: unable to subregion MCU registers", device_get_name(dev)); if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE, VERDE_ATU_SIZE, &sc->sc_atu_sh)) panic("%s: unable to subregion ATU registers", device_get_name(dev)); /* * We have mapped the PCI I/O windows in the early * bootstrap phase. */ sc->sc_iow_vaddr = IQ80321_IOW_VBASE; /* * Check the configuration of the ATU to see if another BIOS * has configured us. If a PC BIOS didn't configure us, then: * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c. * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c. * If a BIOS has configured us, at least one of those should be * different. This is pretty fragile, but it's not clear what * would work better. */ b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0); b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4); b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8); b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc); #ifdef VERBOSE_INIT_ARM printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", b0l,b0u, b1l, b1u ); #endif #define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0 b0l &= PCI_MAPREG_MEM_ADDR_MASK; b0u &= PCI_MAPREG_MEM_ADDR_MASK; b1l &= PCI_MAPREG_MEM_ADDR_MASK; b1u &= PCI_MAPREG_MEM_ADDR_MASK; #ifdef VERBOSE_INIT_ARM printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", b0l,b0u, b1l, b1u ); #endif if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0)) sc->sc_is_host = 0; else sc->sc_is_host = 1; /* FIXME: i force it's */ #ifdef CPU_XSCALE_80219 sc->sc_is_host = 1; #endif i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize); /* * We set up the Inbound Windows as follows: * * 0 Access to i80321 PMMRs * * 1 Reserve space for private devices * * 2 RAM access * * 3 Unused. * * This chunk needs to be customized for each IOP321 application. */ #if 0 sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE; sc->sc_iwin[0].iwin_base_hi = 0; sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE; sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE; #endif if (sc->sc_is_host) { /* Map PCI:Local 1:1. */ sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE | PCI_MAPREG_MEM_PREFETCHABLE_MASK | PCI_MAPREG_MEM_TYPE_64BIT; sc->sc_iwin[1].iwin_base_hi = 0; } else { sc->sc_iwin[1].iwin_base_lo = 0; sc->sc_iwin[1].iwin_base_hi = 0; } sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE; sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE; if (sc->sc_is_host) { sc->sc_iwin[2].iwin_base_lo = memstart | PCI_MAPREG_MEM_PREFETCHABLE_MASK | PCI_MAPREG_MEM_TYPE_64BIT; sc->sc_iwin[2].iwin_base_hi = 0; } else { sc->sc_iwin[2].iwin_base_lo = 0; sc->sc_iwin[2].iwin_base_hi = 0; } sc->sc_iwin[2].iwin_xlate = memstart; sc->sc_iwin[2].iwin_size = memsize; if (sc->sc_is_host) { sc->sc_iwin[3].iwin_base_lo = 0 | PCI_MAPREG_MEM_PREFETCHABLE_MASK | PCI_MAPREG_MEM_TYPE_64BIT; } else { sc->sc_iwin[3].iwin_base_lo = 0; } sc->sc_iwin[3].iwin_base_hi = 0; sc->sc_iwin[3].iwin_xlate = 0; sc->sc_iwin[3].iwin_size = 0; #ifdef VERBOSE_INIT_ARM printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", sc->sc_iwin[1].iwin_base_hi, sc->sc_iwin[1].iwin_base_lo, sc->sc_iwin[1].iwin_xlate, sc->sc_iwin[1].iwin_size ); printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", sc->sc_iwin[2].iwin_base_hi, sc->sc_iwin[2].iwin_base_lo, sc->sc_iwin[2].iwin_xlate, sc->sc_iwin[2].iwin_size ); #endif /* * We set up the Outbound Windows as follows: * * 0 Access to private PCI space. * * 1 Unused. */ #define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) sc->sc_owin[0].owin_xlate_lo = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; /* * Set the Secondary Outbound I/O window to map * to PCI address 0 for all 64K of the I/O space. */ sc->sc_ioout_xlate = 0; i80321_attach(sc); i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate; i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); i80321_dr.dr_len = sc->sc_iwin[2].iwin_size; dma_range_init = 1; busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); busno = PCIXSR_BUSNO(busno); if (busno == 0xff) busno = 0; sc->sc_irq_rman.rm_type = RMAN_ARRAY; sc->sc_irq_rman.rm_descr = "i80321 IRQs"; if (rman_init(&sc->sc_irq_rman) != 0 || rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0) panic("i80321_attach: failed to set up IRQ rman"); device_add_child(dev, "obio", 0); device_add_child(dev, "itimer", 0); device_add_child(dev, "iopwdog", 0); #ifndef CPU_XSCALE_80219 device_add_child(dev, "iqseg", 0); #endif device_add_child(dev, "pcib", busno); device_add_child(dev, "i80321_dma", 0); device_add_child(dev, "i80321_dma", 1); #ifndef CPU_XSCALE_80219 device_add_child(dev, "i80321_aau", 0); #endif bus_generic_probe(dev); bus_generic_attach(dev); return (0); }
static int octe_attach(device_t dev) { struct ifnet *ifp; cvm_oct_private_t *priv; device_t child; unsigned qos; int error; priv = device_get_softc(dev); ifp = priv->ifp; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); if (priv->phy_id != -1) { if (priv->phy_device == NULL) { error = mii_attach(dev, &priv->miibus, ifp, octe_mii_medchange, octe_mii_medstat, BMSR_DEFCAPMASK, priv->phy_id, MII_OFFSET_ANY, 0); if (error != 0) device_printf(dev, "attaching PHYs failed\n"); } else { child = device_add_child(dev, priv->phy_device, -1); if (child == NULL) device_printf(dev, "missing phy %u device %s\n", priv->phy_id, priv->phy_device); } } if (priv->miibus == NULL) { ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat); ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO); } /* * XXX * We don't support programming the multicast filter right now, although it * ought to be easy enough. (Presumably it's just a matter of putting * multicast addresses in the CAM?) */ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI; ifp->if_init = octe_init; ifp->if_ioctl = octe_ioctl; priv->if_flags = ifp->if_flags; mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF); for (qos = 0; qos < 16; qos++) { mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF); IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH); } ether_ifattach(ifp, priv->mac); ifp->if_transmit = octe_transmit; ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; ifp->if_capenable = ifp->if_capabilities; ifp->if_hwassist = CSUM_TCP | CSUM_UDP; OCTE_TX_LOCK(priv); IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH); ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH; IFQ_SET_READY(&ifp->if_snd); OCTE_TX_UNLOCK(priv); return (bus_generic_attach(dev)); }
int fhc_attach(device_t dev) { struct fhc_devinfo *fdi; struct sbus_regs *reg; struct fhc_softc *sc; phandle_t child; phandle_t node; bus_addr_t size; bus_addr_t off; device_t cdev; uint32_t ctrl; char *name; int nreg; int i; sc = device_get_softc(dev); node = sc->sc_node; for (i = FHC_FANFAIL; i <= FHC_TOD; i++) { bus_space_write_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR, 0x0); bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR); } sc->sc_ign = sc->sc_board << 1; bus_space_write_4(sc->sc_bt[FHC_IGN], sc->sc_bh[FHC_IGN], 0x0, sc->sc_ign); sc->sc_ign = bus_space_read_4(sc->sc_bt[FHC_IGN], sc->sc_bh[FHC_IGN], 0x0); ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL], FHC_CTRL); if ((sc->sc_flags & FHC_CENTRAL) == 0) ctrl |= FHC_CTRL_IXIST; ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE); bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL], FHC_CTRL, ctrl); ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL], FHC_CTRL); sc->sc_nrange = OF_getprop_alloc(node, "ranges", sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges); if (sc->sc_nrange == -1) { device_printf(dev, "can't get ranges"); return (ENXIO); } for (child = OF_child(node); child != 0; child = OF_peer(child)) { if ((OF_getprop_alloc(child, "name", 1, (void **)&name)) == -1) continue; cdev = device_add_child(dev, NULL, -1); if (cdev != NULL) { fdi = malloc(sizeof(*fdi), M_DEVBUF, M_WAITOK | M_ZERO); fdi->fdi_name = name; fdi->fdi_node = child; OF_getprop_alloc(child, "device_type", 1, (void **)&fdi->fdi_type); resource_list_init(&fdi->fdi_rl); nreg = OF_getprop_alloc(child, "reg", sizeof(*reg), (void **)®); if (nreg != -1) { for (i = 0; i < nreg; i++) { off = reg[i].sbr_offset; size = reg[i].sbr_size; resource_list_add(&fdi->fdi_rl, SYS_RES_MEMORY, i, off, off + size, size); } free(reg, M_OFWPROP); } device_set_ivars(cdev, fdi); } else free(name, M_OFWPROP); } return (bus_generic_attach(dev)); }
static int chipc_attach(device_t dev) { struct chipc_softc *sc; int error; sc = device_get_softc(dev); sc->dev = dev; sc->quirks = bhnd_device_quirks(dev, chipc_devices, sizeof(chipc_devices[0])); sc->sprom_refcnt = 0; CHIPC_LOCK_INIT(sc); STAILQ_INIT(&sc->mem_regions); /* Set up resource management */ if ((error = chipc_init_rman(sc))) { device_printf(sc->dev, "failed to initialize chipc resource state: %d\n", error); goto failed; } /* Allocate the region containing the chipc register block */ if ((sc->core_region = chipc_find_region_by_rid(sc, 0)) == NULL) { error = ENXIO; goto failed; } error = chipc_retain_region(sc, sc->core_region, RF_ALLOCATED|RF_ACTIVE); if (error) { sc->core_region = NULL; goto failed; } /* Save a direct reference to our chipc registers */ sc->core = sc->core_region->cr_res; /* Fetch and parse capability register(s) */ if ((error = chipc_read_caps(sc, &sc->caps))) goto failed; if (bootverbose) chipc_print_caps(sc->dev, &sc->caps); /* Attach all supported child devices */ if ((error = chipc_add_children(sc))) goto failed; if ((error = bus_generic_attach(dev))) goto failed; return (0); failed: device_delete_children(sc->dev); if (sc->core_region != NULL) { chipc_release_region(sc, sc->core_region, RF_ALLOCATED|RF_ACTIVE); } chipc_free_rman(sc); CHIPC_LOCK_DESTROY(sc); return (error); }
static int viapm_pro_attach(device_t dev) { struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); u_int32_t l; mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF); if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &viapm->iorid, RF_ACTIVE))) { device_printf(dev, "could not allocate bus space\n"); goto error; } #ifdef notyet /* force irq 9 */ l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1); viapm->irqrid = 0; if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &viapm->irqrid, 9, 9, 1, RF_SHAREABLE | RF_ACTIVE))) { device_printf(dev, "could not allocate irq\n"); goto error; } if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC | INTR_MPSAFE, (driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) { device_printf(dev, "could not setup irq\n"); goto error; } #endif if (bootverbose) { l = pci_read_config(dev, VIAPM_PRO_REVID, 1); device_printf(dev, "SMBus revision code 0x%x\n", l); } viapm->smbus = device_add_child(dev, "smbus", -1); /* probe and attach the smbus */ bus_generic_attach(dev); /* disable slave function */ VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE); /* enable the SMBus controller function */ l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1); #ifdef notyet /* enable interrupts */ VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE); #endif #ifdef DEV_ISA /* If this device is a PCI-ISA bridge, then attach an ISA bus. */ if ((pci_get_class(dev) == PCIC_BRIDGE) && (pci_get_subclass(dev) == PCIS_BRIDGE_ISA)) isab_attach(dev); #endif return 0; error: if (viapm->iores) bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores); #ifdef notyet if (viapm->irqres) bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres); #endif mtx_destroy(&viapm->lock); return ENXIO; }
/* * SMBUS API FUNCTIONS * * Called from ig4iic_pci_attach/detach() */ int ig4iic_attach(ig4iic_softc_t *sc) { int error; uint32_t v; v = reg_read(sc, IG4_REG_COMP_TYPE); printf("type %08x\n", v); v = reg_read(sc, IG4_REG_COMP_PARAM1); printf("params %08x\n", v); v = reg_read(sc, IG4_REG_COMP_VER); printf("version %08x\n", v); if (v != IG4_COMP_VER) { error = ENXIO; goto done; } #if 1 v = reg_read(sc, IG4_REG_SS_SCL_HCNT); printf("SS_SCL_HCNT %08x\n", v); v = reg_read(sc, IG4_REG_SS_SCL_LCNT); printf("SS_SCL_LCNT %08x\n", v); v = reg_read(sc, IG4_REG_FS_SCL_HCNT); printf("FS_SCL_HCNT %08x\n", v); v = reg_read(sc, IG4_REG_FS_SCL_LCNT); printf("FS_SCL_LCNT %08x\n", v); v = reg_read(sc, IG4_REG_SDA_HOLD); printf("HOLD %08x\n", v); v = reg_read(sc, IG4_REG_SS_SCL_HCNT); reg_write(sc, IG4_REG_FS_SCL_HCNT, v); v = reg_read(sc, IG4_REG_SS_SCL_LCNT); reg_write(sc, IG4_REG_FS_SCL_LCNT, v); #endif /* * Program based on a 25000 Hz clock. This is a bit of a * hack (obviously). The defaults are 400 and 470 for standard * and 60 and 130 for fast. The defaults for standard fail * utterly (presumably cause an abort) because the clock time * is ~18.8ms by default. This brings it down to ~4ms (for now). */ reg_write(sc, IG4_REG_SS_SCL_HCNT, 100); reg_write(sc, IG4_REG_SS_SCL_LCNT, 125); reg_write(sc, IG4_REG_FS_SCL_HCNT, 100); reg_write(sc, IG4_REG_FS_SCL_LCNT, 125); /* * Use a threshold of 1 so we get interrupted on each character, * allowing us to use lksleep() in our poll code. Not perfect * but this is better than using DELAY() for receiving data. */ reg_write(sc, IG4_REG_RX_TL, 1); reg_write(sc, IG4_REG_CTL, IG4_CTL_MASTER | IG4_CTL_SLAVE_DISABLE | IG4_CTL_RESTARTEN | IG4_CTL_SPEED_STD); mtx_lock(&sc->mtx); sc->smb = device_add_child(sc->dev, "smbus", -1); if (sc->smb == NULL) { device_printf(sc->dev, "smbus driver not found\n"); error = ENXIO; goto done; } #if 0 /* * Don't do this, it blows up the PCI config */ reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT); reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT); #endif /* * Interrupt on STOP detect or receive character ready */ reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | IG4_INTR_RX_FULL); if (set_controller(sc, 0)) device_printf(sc->dev, "controller error during attach-1\n"); if (set_controller(sc, IG4_I2C_ENABLE)) device_printf(sc->dev, "controller error during attach-2\n"); mtx_unlock(&sc->mtx); error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ig4iic_intr, sc, &sc->intr_handle); if (error) { device_printf(sc->dev, "Unable to setup irq: error %d\n", error); goto done; } /* Attach us to the smbus */ error = bus_generic_attach(sc->dev); mtx_lock(&sc->mtx); if (error) { device_printf(sc->dev, "failed to attach child: error %d\n", error); goto done; } sc->generic_attached = 1; done: mtx_unlock(&sc->mtx); return error; }
static int smu_attach(device_t dev) { struct smu_softc *sc; phandle_t node, child; uint8_t data[12]; sc = device_get_softc(dev); mtx_init(&sc->sc_mtx, "smu", NULL, MTX_DEF); sc->sc_cur_cmd = NULL; sc->sc_doorbellirqid = -1; sc->sc_u3 = 0; if (OF_finddevice("/u3") != -1) sc->sc_u3 = 1; /* * Map the mailbox area. This should be determined from firmware, * but I have not found a simple way to do that. */ bus_dma_tag_create(NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, 0, NULL, NULL, &(sc->sc_dmatag)); sc->sc_bt = &bs_le_tag; bus_space_map(sc->sc_bt, SMU_MAILBOX, 4, 0, &sc->sc_mailbox); /* * Allocate the command buffer. This can be anywhere in the low 4 GB * of memory. */ bus_dmamem_alloc(sc->sc_dmatag, (void **)&sc->sc_cmd, BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->sc_cmd_dmamap); bus_dmamap_load(sc->sc_dmatag, sc->sc_cmd_dmamap, sc->sc_cmd, PAGE_SIZE, smu_phys_callback, sc, 0); STAILQ_INIT(&sc->sc_cmdq); /* * Set up handlers to change CPU voltage when CPU frequency is changed. */ EVENTHANDLER_REGISTER(cpufreq_pre_change, smu_cpufreq_pre_change, dev, EVENTHANDLER_PRI_ANY); EVENTHANDLER_REGISTER(cpufreq_post_change, smu_cpufreq_post_change, dev, EVENTHANDLER_PRI_ANY); node = ofw_bus_get_node(dev); /* Some SMUs have RPM and PWM controlled fans which do not sit * under the same node. So we have to attach them separately. */ smu_attach_fans(dev, node); /* * Now detect and attach the other child devices. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { char name[32]; memset(name, 0, sizeof(name)); OF_getprop(child, "name", name, sizeof(name)); if (strncmp(name, "sensors", 8) == 0) smu_attach_sensors(dev, child); if (strncmp(name, "smu-i2c-control", 15) == 0) smu_attach_i2c(dev, child); } /* Some SMUs have the I2C children directly under the bus. */ smu_attach_i2c(dev, node); /* * Collect calibration constants. */ smu_get_datablock(dev, SMU_CPUTEMP_CAL, data, sizeof(data)); sc->sc_cpu_diode_scale = (data[4] << 8) + data[5]; sc->sc_cpu_diode_offset = (data[6] << 8) + data[7]; smu_get_datablock(dev, SMU_CPUVOLT_CAL, data, sizeof(data)); sc->sc_cpu_volt_scale = (data[4] << 8) + data[5]; sc->sc_cpu_volt_offset = (data[6] << 8) + data[7]; sc->sc_cpu_curr_scale = (data[8] << 8) + data[9]; sc->sc_cpu_curr_offset = (data[10] << 8) + data[11]; smu_get_datablock(dev, SMU_SLOTPW_CAL, data, sizeof(data)); sc->sc_slots_pow_scale = (data[4] << 8) + data[5]; sc->sc_slots_pow_offset = (data[6] << 8) + data[7]; /* * Set up LED interface */ sc->sc_leddev = led_create(smu_set_sleepled, dev, "sleepled"); /* * Reset on power loss behavior */ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "server_mode", CTLTYPE_INT | CTLFLAG_RW, dev, 0, smu_server_mode, "I", "Enable reboot after power failure"); /* * Set up doorbell interrupt. */ sc->sc_doorbellirqid = 0; sc->sc_doorbellirq = bus_alloc_resource_any(smu_doorbell, SYS_RES_IRQ, &sc->sc_doorbellirqid, RF_ACTIVE); bus_setup_intr(smu_doorbell, sc->sc_doorbellirq, INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, dev, &sc->sc_doorbellirqcookie); powerpc_config_intr(rman_get_start(sc->sc_doorbellirq), INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); /* * Connect RTC interface. */ clock_register(dev, 1000); /* * Learn about shutdown events */ EVENTHANDLER_REGISTER(shutdown_final, smu_shutdown, dev, SHUTDOWN_PRI_LAST); return (bus_generic_attach(dev)); }
static int bhndb_pci_attach(device_t dev) { struct bhndb_pci_softc *sc; struct bhnd_chipid cid; struct bhnd_core_info *cores, hostb_core; bhnd_erom_class_t *erom_class; struct bhndb_pci_probe *probe; u_int ncores; int irq_rid; int error; sc = device_get_softc(dev); sc->dev = dev; sc->parent = device_get_parent(dev); sc->pci_devclass = bhndb_expected_pci_devclass(dev); sc->pci_quirks = 0; sc->set_regwin = NULL; BHNDB_PCI_LOCK_INIT(sc); probe = NULL; cores = NULL; /* Enable PCI bus mastering */ pci_enable_busmaster(sc->parent); /* Enable clocks (if required by this hardware) */ if ((error = bhndb_enable_pci_clocks(sc->dev))) goto cleanup; /* Identify the chip and enumerate the bridged cores */ error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass); if (error) goto cleanup; sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid, &probe->hostb_core); /* Select the appropriate register window handler */ if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) { sc->set_regwin = bhndb_pci_compat_setregwin; } else { sc->set_regwin = bhndb_pci_fast_setregwin; } /* * Fix up our PCI base address in the SPROM shadow, if necessary. * * This must be done prior to accessing any static register windows * that map the PCI core. */ if ((error = bhndb_pci_srsh_pi_war(sc, probe))) goto cleanup; /* Set up PCI interrupt handling */ if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) { /* MSI uses resource IDs starting at 1 */ irq_rid = 1; device_printf(dev, "Using MSI interrupts on %s\n", device_get_nameunit(sc->parent)); } else { sc->msi_count = 0; irq_rid = 0; device_printf(dev, "Using INTx interrupts on %s\n", device_get_nameunit(sc->parent)); } sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->isrc == NULL) { device_printf(sc->dev, "failed to allocate interrupt " "resource\n"); error = ENXIO; goto cleanup; } /* * Copy out the probe results and then free our probe state, releasing * its exclusive ownership of host bridge resources. * * This must be done prior to full configuration of the bridge via * bhndb_attach(). */ cid = probe->cid; erom_class = probe->erom_class; hostb_core = probe->hostb_core; error = bhndb_pci_probe_copy_core_table(probe, &cores, &ncores); if (error) { cores = NULL; goto cleanup; } bhndb_pci_probe_free(probe); probe = NULL; /* Perform bridge attach */ error = bhndb_attach(dev, &cid, cores, ncores, &hostb_core, erom_class); if (error) goto cleanup; /* Add any additional child devices */ if ((error = bhndb_pci_add_children(sc))) goto cleanup; /* Probe and attach our children */ if ((error = bus_generic_attach(dev))) goto cleanup; bhndb_pci_probe_free_core_table(cores); return (0); cleanup: device_delete_children(dev); if (sc->isrc != NULL) bhndb_free_intr_isrc(sc->isrc); if (sc->msi_count > 0) pci_release_msi(sc->parent); if (cores != NULL) bhndb_pci_probe_free_core_table(cores); if (probe != NULL) bhndb_pci_probe_free(probe); bhndb_disable_pci_clocks(sc->dev); pci_disable_busmaster(sc->parent); BHNDB_PCI_LOCK_DESTROY(sc); return (error); }