static int hv_kvp_probe(device_t dev) { int rtn_value = ENXIO; const char *p = vmbus_get_type(dev); /** * Note: GUID codes below are predefined by the host hypervisor * (Hyper-V and Azure)interface and required for correct operation. */ /* KVP (Key Value Pair) Service */ const char kvp_guid[16] = {0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6}; #ifdef DEBUG printf("hv_kvp_probe: called\n"); #endif if (!memcmp(p, &kvp_guid, sizeof(hv_guid))) { device_set_softc(dev, NULL); #ifdef DEBUG printf("hv_kvp_probe: memcmp matched\n"); #endif rtn_value = 0; } #ifdef DEBUG else printf("hv_kvp_probe: memcmp not matched\n"); #endif return rtn_value; }
/*------------------------------------------------------------------------* * usb_bus_detach * * This function is used to detach the device tree from the root. *------------------------------------------------------------------------*/ void usb_bus_detach(struct usb_proc_msg *pm) { struct usb_bus *bus; struct usb_device *udev; device_t dev; bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; dev = bus->bdev; /* clear the softc */ device_set_softc(dev, NULL); USB_BUS_UNLOCK(bus); /* detach children first */ mtx_lock(&Giant); bus_generic_detach(dev); mtx_unlock(&Giant); /* * Free USB device and all subdevices, if any. */ usb_free_device(udev, 0); USB_BUS_LOCK(bus); /* clear bdev variable last */ bus->bdev = NULL; }
static void pcib_mbus_add_child(driver_t *driver, device_t parent, struct pcib_mbus_softc *sc) { device_t child; int error; /* Configure CPU decoding windows */ error = decode_win_cpu_set(sc->sc_info->op_io_win_target, sc->sc_info->op_io_win_attr, sc->sc_info->op_io_base, sc->sc_info->op_io_size, -1); if (error < 0) { device_printf(parent, "Could not set up CPU decode " "window for PCI IO\n"); return; } error = decode_win_cpu_set(sc->sc_info->op_mem_win_target, sc->sc_info->op_mem_win_attr, sc->sc_info->op_mem_base, sc->sc_info->op_mem_size, -1); if (error < 0) { device_printf(parent, "Could not set up CPU decode " "windows for PCI MEM\n"); return; } /* Create driver instance */ child = BUS_ADD_CHILD(parent, 0, driver->name, -1); bus_set_resource(child, SYS_RES_MEMORY, 0, sc->sc_info->op_base, sc->sc_info->op_size); device_set_softc(child, sc); }
/* * misc support functions */ static device_t ata_add_child(device_t parent, struct ata_device *atadev, int unit) { device_t child; if ((child = device_add_child(parent, NULL, unit))) { device_set_softc(child, atadev); device_quiet(child); atadev->dev = child; atadev->max_iosize = DEV_BSIZE; atadev->mode = ATA_PIO_MAX; } return child; }
static int hv_util_probe(device_t dev) { int i; int rtn_value = ENXIO; for (i = 0; i < HV_MAX_UTIL_SERVICES; i++) { const char *p = vmbus_get_type(dev); if (service_table[i].enabled && !memcmp(p, &service_table[i].guid, sizeof(hv_guid))) { device_set_softc(dev, (void *) (&service_table[i])); rtn_value = 0; } } return rtn_value; }
int pst_add_raid(struct iop_softc *sc, struct i2o_lct_entry *lct) { struct pst_softc *psc; device_t child = device_add_child(sc->dev, "pst", -1); if (!child) return ENOMEM; if (!(psc = malloc(sizeof(struct pst_softc), M_PSTRAID, M_NOWAIT | M_ZERO))) { device_delete_child(sc->dev, child); return ENOMEM; } psc->iop = sc; psc->lct = lct; device_set_softc(child, psc); return bus_generic_attach(sc->dev); }
/* * read_partition_table - given a device @dev, create one subdevice per partition * found in that device. * * This function will read a partition table from the canonical location of the * device pointed by @dev. For each partition found, a new device will be * created. The newly created device will have most of its data copied from * @dev, except for its name, offset and size. */ void read_partition_table(struct device *dev) { struct buf *bp; unsigned long offset; int index; bread(dev, 0, &bp); sched_lock(); for (offset = 0x1be, index = 0; offset < 0x1fe; offset += 0x10, index++) { struct partition_table_entry *entry; char dev_name[MAXDEVNAME]; struct device *new_dev; entry = bp->b_data + offset; if (entry->system_id == 0) { continue; } if (entry->starting_sector == 0) { continue; } snprintf(dev_name, MAXDEVNAME, "%s.%d", dev->name, index); new_dev = device_create(dev->driver, dev_name, dev->flags); free(new_dev->private_data); new_dev->offset = (off_t)entry->rela_sector << 9; new_dev->size = (off_t)entry->total_sectors << 9; new_dev->max_io_size = dev->max_io_size; new_dev->private_data = dev->private_data; device_set_softc(new_dev, device_get_softc(dev)); } sched_unlock(); brelse(bp); }
/*------------------------------------------------------------------------* * usb_bus_attach * * This function attaches USB in context of the explore thread. *------------------------------------------------------------------------*/ static void usb_bus_attach(struct usb_proc_msg *pm) { struct usb_bus *bus; struct usb_device *child; device_t dev; usb_error_t err; enum usb_dev_speed speed; bus = ((struct usb_bus_msg *)pm)->bus; dev = bus->bdev; DPRINTF("\n"); switch (bus->usbrev) { case USB_REV_1_0: speed = USB_SPEED_FULL; device_printf(bus->bdev, "12Mbps Full Speed USB v1.0\n"); break; case USB_REV_1_1: speed = USB_SPEED_FULL; device_printf(bus->bdev, "12Mbps Full Speed USB v1.1\n"); break; case USB_REV_2_0: speed = USB_SPEED_HIGH; device_printf(bus->bdev, "480Mbps High Speed USB v2.0\n"); break; case USB_REV_2_5: speed = USB_SPEED_VARIABLE; device_printf(bus->bdev, "480Mbps Wireless USB v2.5\n"); break; case USB_REV_3_0: speed = USB_SPEED_SUPER; device_printf(bus->bdev, "4.8Gbps Super Speed USB v3.0\n"); break; default: device_printf(bus->bdev, "Unsupported USB revision\n"); usb_root_mount_rel(bus); return; } USB_BUS_UNLOCK(bus); /* default power_mask value */ bus->hw_power_state = USB_HW_POWER_CONTROL | USB_HW_POWER_BULK | USB_HW_POWER_INTERRUPT | USB_HW_POWER_ISOC | USB_HW_POWER_NON_ROOT_HUB; /* make sure power is set at least once */ if (bus->methods->set_hw_power != NULL) { (bus->methods->set_hw_power) (bus); } /* Allocate the Root USB device */ child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1, speed, USB_MODE_HOST); if (child) { err = usb_probe_and_attach(child, USB_IFACE_INDEX_ANY); if (!err) { if ((bus->devices[USB_ROOT_HUB_ADDR] == NULL) || (bus->devices[USB_ROOT_HUB_ADDR]->hub == NULL)) { err = USB_ERR_NO_ROOT_HUB; } } } else { err = USB_ERR_NOMEM; } USB_BUS_LOCK(bus); if (err) { device_printf(bus->bdev, "Root HUB problem, error=%s\n", usbd_errstr(err)); usb_root_mount_rel(bus); } /* set softc - we are ready */ device_set_softc(dev, bus); /* start watchdog */ usb_power_wdog(bus); }
int scc_bfe_attach(device_t dev, u_int ipc) { struct resource_list_entry *rle; struct scc_chan *ch; struct scc_class *cl; struct scc_mode *m; struct scc_softc *sc, *sc0; const char *sep; bus_space_handle_t bh; u_long base, size, start, sz; int c, error, mode, sysdev; /* * The sc_class field defines the type of SCC we're going to work * with and thus the size of the softc. Replace the generic softc * with one that matches the SCC now that we're certain we handle * the device. */ sc0 = device_get_softc(dev); cl = sc0->sc_class; if (cl->size > sizeof(*sc)) { sc = malloc(cl->size, M_SCC, M_WAITOK|M_ZERO); bcopy(sc0, sc, sizeof(*sc)); device_set_softc(dev, sc); } else sc = sc0; size = abs(cl->cl_range) << sc->sc_bas.regshft; mtx_init(&sc->sc_hwmtx, "scc_hwmtx", NULL, MTX_SPIN); /* * Re-allocate. We expect that the softc contains the information * collected by scc_bfe_probe() intact. */ sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid, 0, ~0, cl->cl_channels * size, RF_ACTIVE); if (sc->sc_rres == NULL) return (ENXIO); sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); /* * Allocate interrupt resources. There may be a different interrupt * per channel. We allocate them all... */ sc->sc_chan = malloc(sizeof(struct scc_chan) * cl->cl_channels, M_SCC, M_WAITOK | M_ZERO); for (c = 0; c < cl->cl_channels; c++) { ch = &sc->sc_chan[c]; /* * XXX temporary hack. If we have more than 1 interrupt * per channel, allocate the first for the channel. At * this time only the macio bus front-end has more than * 1 interrupt per channel and we don't use the 2nd and * 3rd, because we don't support DMA yet. */ ch->ch_irid = c * ipc; ch->ch_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &ch->ch_irid, RF_ACTIVE | RF_SHAREABLE); if (ipc == 0) break; } /* * Create the control structures for our children. Probe devices * and query them to see if we can reset the hardware. */ sysdev = 0; base = rman_get_start(sc->sc_rres); sz = (size != 0) ? size : rman_get_size(sc->sc_rres); start = base + ((cl->cl_range < 0) ? size * (cl->cl_channels - 1) : 0); for (c = 0; c < cl->cl_channels; c++) { ch = &sc->sc_chan[c]; resource_list_init(&ch->ch_rlist); ch->ch_nr = c + 1; if (!SCC_ENABLED(sc, ch)) goto next; ch->ch_enabled = 1; resource_list_add(&ch->ch_rlist, sc->sc_rtype, 0, start, start + sz - 1, sz); rle = resource_list_find(&ch->ch_rlist, sc->sc_rtype, 0); rle->res = &ch->ch_rres; bus_space_subregion(rman_get_bustag(sc->sc_rres), rman_get_bushandle(sc->sc_rres), start - base, sz, &bh); rman_set_bushandle(rle->res, bh); rman_set_bustag(rle->res, rman_get_bustag(sc->sc_rres)); resource_list_add(&ch->ch_rlist, SYS_RES_IRQ, 0, c, c, 1); rle = resource_list_find(&ch->ch_rlist, SYS_RES_IRQ, 0); rle->res = (ch->ch_ires != NULL) ? ch->ch_ires : sc->sc_chan[0].ch_ires; for (mode = 0; mode < SCC_NMODES; mode++) { m = &ch->ch_mode[mode]; m->m_chan = ch; m->m_mode = 1U << mode; if ((cl->cl_modes & m->m_mode) == 0 || ch->ch_sysdev) continue; m->m_dev = device_add_child(dev, NULL, -1); device_set_ivars(m->m_dev, (void *)m); error = device_probe_child(dev, m->m_dev); if (!error) { m->m_probed = 1; m->m_sysdev = SERDEV_SYSDEV(m->m_dev) ? 1 : 0; ch->ch_sysdev |= m->m_sysdev; } } next: start += (cl->cl_range < 0) ? -size : size; sysdev |= ch->ch_sysdev; } /* * Have the hardware driver initialize the hardware. Tell it * whether or not a hardware reset should be performed. */ if (bootverbose) { device_printf(dev, "%sresetting hardware\n", (sysdev) ? "not " : ""); } error = SCC_ATTACH(sc, !sysdev); if (error) goto fail; /* * Setup our interrupt handler. Make it FAST under the assumption * that our children's are fast as well. We make it MPSAFE as soon * as a child sets up a MPSAFE interrupt handler. * Of course, if we can't setup a fast handler, we make it MPSAFE * right away. */ for (c = 0; c < cl->cl_channels; c++) { ch = &sc->sc_chan[c]; if (ch->ch_ires == NULL) continue; error = bus_setup_intr(dev, ch->ch_ires, INTR_TYPE_TTY, scc_bfe_intr, NULL, sc, &ch->ch_icookie); if (error) { error = bus_setup_intr(dev, ch->ch_ires, INTR_TYPE_TTY | INTR_MPSAFE, NULL, (driver_intr_t *)scc_bfe_intr, sc, &ch->ch_icookie); } else sc->sc_fastintr = 1; if (error) { device_printf(dev, "could not activate interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid, ch->ch_ires); ch->ch_ires = NULL; } } sc->sc_polled = 1; for (c = 0; c < cl->cl_channels; c++) { if (sc->sc_chan[0].ch_ires != NULL) sc->sc_polled = 0; } /* * Attach all child devices that were probed successfully. */ for (c = 0; c < cl->cl_channels; c++) { ch = &sc->sc_chan[c]; for (mode = 0; mode < SCC_NMODES; mode++) { m = &ch->ch_mode[mode]; if (!m->m_probed) continue; error = device_attach(m->m_dev); if (error) continue; m->m_attached = 1; } } if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) { sep = ""; device_print_prettyname(dev); if (sc->sc_fastintr) { printf("%sfast interrupt", sep); sep = ", "; } if (sc->sc_polled) { printf("%spolled mode", sep); sep = ", "; } printf("\n"); } return (0); fail: for (c = 0; c < cl->cl_channels; c++) { ch = &sc->sc_chan[c]; if (ch->ch_ires == NULL) continue; bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid, ch->ch_ires); } bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); return (error); }
static int atkbdc_ebus_attach(device_t dev) { atkbdc_softc_t *sc; atkbdc_device_t *adi; device_t cdev; phandle_t child; u_long count, intr, start; int children, error, rid, unit; char *cname, *dname; unit = device_get_unit(dev); sc = *(atkbdc_softc_t **)device_get_softc(dev); if (sc == NULL) { /* * We have to maintain two copies of the kbdc_softc struct, * as the low-level console needs to have access to the * keyboard controller before kbdc is probed and attached. * kbdc_soft[] contains the default entry for that purpose. * See atkbdc.c. XXX */ sc = atkbdc_get_softc(unit); if (sc == NULL) return (ENOMEM); device_set_softc(dev, sc); } rid = 0; if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) { device_printf(dev, "cannot determine command/data port resource\n"); return (ENXIO); } sc->retry = 5000; sc->port0 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start, 1, RF_ACTIVE); if (sc->port0 == NULL) { device_printf(dev, "cannot allocate command/data port resource\n"); return (ENXIO); } rid = 1; if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) { device_printf(dev, "cannot determine status port resource\n"); error = ENXIO; goto fail_port0; } start += KBD_STATUS_PORT; sc->port1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start, 1, RF_ACTIVE); if (sc->port1 == NULL) { device_printf(dev, "cannot allocate status port resource\n"); error = ENXIO; goto fail_port0; } error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1); if (error != 0) { device_printf(dev, "atkbdc_attach_unit failed\n"); goto fail_port1; } /* Attach children. */ children = 0; for (child = OF_child(ofw_bus_get_node(dev)); child != 0; child = OF_peer(child)) { if ((OF_getprop_alloc(child, "name", 1, (void **)&cname)) == -1) continue; if (children >= 2) { device_printf(dev, "<%s>: only two children per 8042 supported\n", cname); free(cname, M_OFWPROP); continue; } adi = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV, M_NOWAIT | M_ZERO); if (adi == NULL) { device_printf(dev, "<%s>: malloc failed\n", cname); free(cname, M_OFWPROP); continue; } if (strcmp(cname, "kb_ps2") == 0) { adi->rid = KBDC_RID_KBD; dname = ATKBD_DRIVER_NAME; } else if (strcmp(cname, "kdmouse") == 0) { adi->rid = KBDC_RID_AUX; dname = PSM_DRIVER_NAME; } else { device_printf(dev, "<%s>: unknown device\n", cname); free(adi, M_ATKBDDEV); free(cname, M_OFWPROP); continue; } intr = bus_get_resource_start(dev, SYS_RES_IRQ, adi->rid); if (intr == 0) { device_printf(dev, "<%s>: cannot determine interrupt resource\n", cname); free(adi, M_ATKBDDEV); free(cname, M_OFWPROP); continue; } resource_list_init(&adi->resources); resource_list_add(&adi->resources, SYS_RES_IRQ, adi->rid, intr, intr, 1); if ((cdev = device_add_child(dev, dname, -1)) == NULL) { device_printf(dev, "<%s>: device_add_child failed\n", cname); resource_list_free(&adi->resources); free(adi, M_ATKBDDEV); free(cname, M_OFWPROP); continue; } device_set_ivars(cdev, adi); children++; } error = bus_generic_attach(dev); if (error != 0) { device_printf(dev, "bus_generic_attach failed\n"); goto fail_port1; } return (0); fail_port1: bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->port1); fail_port0: bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->port0); return (error); }