/* for debugging, print out all the data about the status of devices */ void wds_print(void) { int unit; int i; struct wds_req *r; struct wds *wp; for (unit = 0; unit < devclass_get_maxunit(wds_devclass); unit++) { wp = (struct wds *) devclass_get_device(wds_devclass, unit); if (wp == NULL) continue; printf("wds%d: want_wdsr=0x%x stat=0x%x irq=%s irqstat=0x%x\n", unit, wp->want_wdsr, inb(wp->addr + WDS_STAT) & 0xff, (inb(wp->addr + WDS_STAT) & WDS_IRQ) ? "ready" : "no", inb(wp->addr + WDS_IRQSTAT) & 0xff); for (i = 0; i < MAXSIMUL; i++) { r = &wp->dx->req[i]; if( wp->wdsr_free & (1 << r->id) ) { printf("req=%d flg=0x%x ombn=%d ombstat=%d " "mask=0x%x targ=%d lun=%d cmd=0x%x\n", i, r->flags, r->ombn, wp->dx->ombs[r->ombn].stat, r->mask, r->cmd.targ >> 5, r->cmd.targ & 7, r->cmd.scb[0]); } } }
int ata_pci_attach(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); u_int32_t cmd; int unit; /* do chipset specific setups only needed once */ ctlr->legacy = ata_legacy(dev); if (ctlr->legacy || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK) ctlr->channels = 2; else ctlr->channels = 1; ctlr->allocate = ata_pci_allocate; ctlr->dev = dev; /* if needed try to enable busmastering */ cmd = pci_read_config(dev, PCIR_COMMAND, 2); if (!(cmd & PCIM_CMD_BUSMASTEREN)) { pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2); cmd = pci_read_config(dev, PCIR_COMMAND, 2); } /* if busmastering mode "stuck" use it */ if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) { ctlr->r_type1 = SYS_RES_IOPORT; ctlr->r_rid1 = ATA_BMADDR_RID; ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1, RF_ACTIVE); /* Only set a dma init function if the device actually supports it. */ ctlr->dmainit = ata_pci_dmainit; } if (ctlr->chipinit(dev)) return ENXIO; /* attach all channels on this controller */ for (unit = 0; unit < ctlr->channels; unit++) { int freeunit = 2; if ((unit == 0 || unit == 1) && ctlr->legacy) { device_add_child(dev, "ata", unit); continue; } /* XXX TGEN devclass_find_free_unit() implementation */ if (ata_devclass) { while (freeunit < devclass_get_maxunit(ata_devclass) && devclass_get_device(ata_devclass, freeunit) != NULL) freeunit++; } device_add_child(dev, "ata", freeunit); } bus_generic_attach(dev); return 0; }
static void ata_boot_attach(void) { struct ata_channel *ch; int ctlr; get_mplock(); /* kick of probe and attach on all channels */ for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) { if ((ch = devclass_get_softc(ata_devclass, ctlr))) { ata_identify(ch->dev); } } rel_mplock(); }
sc_softc_t *sc_find_softc(struct video_adapter *adp, struct keyboard *kbd) { sc_softc_t *sc; int i; int units; sc = &main_softc; if ((adp == NULL || adp == sc->adp) && (kbd == NULL || kbd == sc->kbd)) return (sc); units = devclass_get_maxunit(sc_devclass); for (i = 0; i < units; ++i) { sc = device_get_softc(devclass_get_device(sc_devclass, i)); if (sc == NULL) continue; if ((adp == NULL || adp == sc->adp) && (kbd == NULL || kbd == sc->kbd)) return (sc); } return (NULL); }
static device_t find_masterdev(sc_p scp) { int i, units; devclass_t devclass; device_t dev; devclass = device_get_devclass(scp->dev); units = devclass_get_maxunit(devclass); dev = NULL; for (i = 0 ; i < units ; i++) { dev = devclass_get_device(devclass, i); if (isa_get_vendorid(dev) == isa_get_vendorid(scp->dev) && isa_get_logicalid(dev) == LOGICALID_PCM && isa_get_serial(dev) == isa_get_serial(scp->dev)) break; } if (i == units) return (NULL); return (dev); }
/* * The battery interface deals with devices and methods but userland * expects a logical unit number. Convert a logical unit to a device_t. */ static device_t acpi_battery_find_dev(u_int logical_unit) { int found_unit, i, maxunit; device_t dev; devclass_t batt_dc; dev = NULL; found_unit = 0; batt_dc = devclass_find("battery"); maxunit = devclass_get_maxunit(batt_dc); for (i = 0; i < maxunit; i++) { dev = devclass_get_device(batt_dc, i); if (dev == NULL) continue; if (logical_unit == found_unit) break; found_unit++; dev = NULL; } return (dev); }
static void ata_boot_attach(void) { struct ata_channel *ch; int ctlr; mtx_lock(&Giant); /* newbus suckage it needs Giant */ /* kick of probe and attach on all channels */ for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) { if ((ch = devclass_get_softc(ata_devclass, ctlr))) { ata_identify(ch->dev); } } /* release the hook that got us here, we are only needed once during boot */ if (ata_delayed_attach) { config_intrhook_disestablish(ata_delayed_attach); free(ata_delayed_attach, M_TEMP); ata_delayed_attach = NULL; } mtx_unlock(&Giant); /* newbus suckage dealt with, release Giant */ }
int sc_max_unit(void) { return (devclass_get_maxunit(sc_devclass)); }
static void ata_boot_attach(void) { struct ata_channel *ch; int ctlr, s; if (ata_delayed_attach) { config_intrhook_disestablish(ata_delayed_attach); free(ata_delayed_attach, M_TEMP); ata_delayed_attach = NULL; } s = splbio(); /* * run through all ata devices and look for real ATA & ATAPI devices * using the hints we found in the early probe, this avoids some of * the delays probing of non-exsistent devices can cause. */ for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { if (!(ch = devclass_get_softc(ata_devclass, ctlr))) continue; if (ch->devices & ATA_ATA_SLAVE) if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY)) ch->devices &= ~ATA_ATA_SLAVE; if (ch->devices & ATA_ATAPI_SLAVE) if (ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY)) ch->devices &= ~ATA_ATAPI_SLAVE; if (ch->devices & ATA_ATA_MASTER) if (ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY)) ch->devices &= ~ATA_ATA_MASTER; if (ch->devices & ATA_ATAPI_MASTER) if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY)) ch->devices &= ~ATA_ATAPI_MASTER; } #if NATADISK > 0 /* now we know whats there, do the real attach, first the ATA disks */ for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { if (!(ch = devclass_get_softc(ata_devclass, ctlr))) continue; if (ch->devices & ATA_ATA_MASTER) ad_attach(&ch->device[MASTER], 0); if (ch->devices & ATA_ATA_SLAVE) ad_attach(&ch->device[SLAVE], 0); } ata_raid_attach(); #endif #if DEV_ATAPIALL /* then the atapi devices */ for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { if (!(ch = devclass_get_softc(ata_devclass, ctlr))) continue; if (ch->devices & ATA_ATAPI_MASTER) atapi_attach(&ch->device[MASTER], 0); if (ch->devices & ATA_ATAPI_SLAVE) atapi_attach(&ch->device[SLAVE], 0); #if NATAPICAM > 0 atapi_cam_attach_bus(ch); #endif } #endif splx(s); }
static int atausb_attach(device_t dev) { struct atausb_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_device_handle udev; usb_device_request_t request; char devinfo[1024], *proto, *subclass; u_int8_t maxlun; int err, i; sc->dev = dev; usbd_devinfo(uaa->device, 0, devinfo); device_set_desc_copy(dev, devinfo); sc->bulkin = sc->bulkout = sc->bulkirq = -1; sc->bulkin_pipe = sc->bulkout_pipe= sc->bulkirq_pipe = NULL; sc->iface = uaa->iface; sc->ifaceno = uaa->ifaceno; sc->maxlun = 0; sc->timeout = 5000; sc->locked_ch = NULL; sc->restart_ch = NULL; spin_init(&sc->locked_mtx); id = usbd_get_interface_descriptor(sc->iface); switch (id->bInterfaceProtocol) { case UIPROTO_MASS_BBB: case UIPROTO_MASS_BBB_OLD: proto = "Bulk-Only"; break; case UIPROTO_MASS_CBI: proto = "CBI"; break; case UIPROTO_MASS_CBI_I: proto = "CBI with CCI"; break; default: proto = "Unknown"; } switch (id->bInterfaceSubClass) { case UISUBCLASS_RBC: subclass = "RBC"; break; case UISUBCLASS_QIC157: case UISUBCLASS_SFF8020I: case UISUBCLASS_SFF8070I: subclass = "ATAPI"; break; case UISUBCLASS_SCSI: subclass = "SCSI"; break; case UISUBCLASS_UFI: subclass = "UFI"; break; default: subclass = "Unknown"; } device_printf(dev, "using %s over %s\n", subclass, proto); if (strcmp(proto, "Bulk-Only") || (strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) return ENXIO; for (i = 0 ; i < id->bNumEndpoints ; i++) { if (!(ed = usbd_interface2endpoint_descriptor(sc->iface, i))) { device_printf(sc->dev, "could not read endpoint descriptor\n"); return ENXIO; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkin = ed->bEndpointAddress; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkout = ed->bEndpointAddress; } if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { sc->bulkirq = ed->bEndpointAddress; } } /* check whether we found at least the endpoints we need */ if (!sc->bulkin || !sc->bulkout) { device_printf(sc->dev, "needed endpoints not found (%d,%d)\n", sc->bulkin, sc->bulkout); atausb_detach(dev); return ENXIO; } /* open the pipes */ if (usbd_open_pipe(sc->iface, sc->bulkout, USBD_EXCLUSIVE_USE, &sc->bulkout_pipe)) { device_printf(sc->dev, "cannot open bulkout pipe (%d)\n", sc->bulkout); atausb_detach(dev); return ENXIO; } if (usbd_open_pipe(sc->iface, sc->bulkin, USBD_EXCLUSIVE_USE, &sc->bulkin_pipe)) { device_printf(sc->dev, "cannot open bulkin pipe (%d)\n", sc->bulkin); atausb_detach(dev); return ENXIO; } if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I) { if (usbd_open_pipe(sc->iface, sc->bulkirq, USBD_EXCLUSIVE_USE, &sc->bulkirq_pipe)) { device_printf(sc->dev, "cannot open bulkirq pipe (%d)\n", sc->bulkirq); atausb_detach(dev); return ENXIO; } } sc->state = ATAUSB_S_ATTACH; /* alloc needed number of transfer handles */ for (i = 0; i < ATAUSB_T_MAX; i++) { sc->transfer[i] = usbd_alloc_xfer(uaa->device); if (!sc->transfer[i]) { device_printf(sc->dev, "out of memory\n"); atausb_detach(dev); return ENXIO; } } /* driver is ready to process requests here */ sc->state = ATAUSB_S_IDLE; /* get number of devices so we can add matching channels */ usbd_interface2device_handle(sc->iface, &udev); request.bmRequestType = UT_READ_CLASS_INTERFACE; request.bRequest = 0xfe; /* GET_MAX_LUN; */ USETW(request.wValue, 0); USETW(request.wIndex, sc->ifaceno); USETW(request.wLength, sizeof(maxlun)); switch ((err = usbd_do_request(udev, &request, &maxlun))) { case USBD_NORMAL_COMPLETION: if (bootverbose) device_printf(sc->dev, "maxlun=%d\n", maxlun); sc->maxlun = maxlun; break; default: if (bootverbose) device_printf(sc->dev, "get maxlun not supported %s\n", usbd_errstr(err)); } /* ata channels are children to this USB control device */ for (i = 0; i <= sc->maxlun; i++) { /* XXX TGEN devclass_find_free_unit() implementation */ int freeunit = 2; while (freeunit < devclass_get_maxunit(ata_devclass) && devclass_get_device(ata_devclass, freeunit) != NULL) freeunit++; if (!device_add_child(sc->dev, "ata", freeunit)) { device_printf(sc->dev, "failed to attach ata child device\n"); atausb_detach(dev); return ENXIO; } } bus_generic_attach(sc->dev); return 0; }
/* * device related interfaces */ static int ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int32_t flag, struct thread *td) { device_t device, *children; struct ata_ioc_devices *devices = (struct ata_ioc_devices *)data; int *value = (int *)data; int i, nchildren, error = ENOTTY; switch (cmd) { case IOCATAGMAXCHANNEL: /* In case we have channel 0..n this will return n+1. */ *value = devclass_get_maxunit(ata_devclass); error = 0; break; case IOCATAREINIT: if (*value >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, *value))) return ENXIO; error = ata_reinit(device); break; case IOCATAATTACH: if (*value >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, *value))) return ENXIO; /* XXX SOS should enable channel HW on controller */ error = ata_attach(device); break; case IOCATADETACH: if (*value >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, *value))) return ENXIO; error = ata_detach(device); /* XXX SOS should disable channel HW on controller */ break; case IOCATADEVICES: if (devices->channel >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, devices->channel))) return ENXIO; bzero(devices->name[0], 32); bzero(&devices->params[0], sizeof(struct ata_params)); bzero(devices->name[1], 32); bzero(&devices->params[1], sizeof(struct ata_params)); if (!device_get_children(device, &children, &nchildren)) { for (i = 0; i < nchildren; i++) { if (children[i] && device_is_attached(children[i])) { struct ata_device *atadev = device_get_softc(children[i]); if (atadev->unit == ATA_MASTER) { strncpy(devices->name[0], device_get_nameunit(children[i]), 32); bcopy(&atadev->param, &devices->params[0], sizeof(struct ata_params)); } if (atadev->unit == ATA_SLAVE) { strncpy(devices->name[1], device_get_nameunit(children[i]), 32); bcopy(&atadev->param, &devices->params[1], sizeof(struct ata_params)); } } } free(children, M_TEMP); error = 0; } else error = ENODEV; break; default: if (ata_raid_ioctl_func) error = ata_raid_ioctl_func(cmd, data); } return error; }
/* Get info about one or all batteries. */ int acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo) { int batt_stat, devcount, dev_idx, error, i; int total_cap, total_min, valid_rate, valid_units; devclass_t batt_dc; device_t batt_dev; struct acpi_bst *bst; struct acpi_bif *bif; struct acpi_battinfo *bi; /* * Get the battery devclass and max unit for battery devices. If there * are none or error, return immediately. */ batt_dc = devclass_find("battery"); if (batt_dc == NULL) return (ENXIO); devcount = devclass_get_maxunit(batt_dc); if (devcount == 0) return (ENXIO); /* * Allocate storage for all _BST data, their derived battinfo data, * and the current battery's _BIF data. */ bst = kmalloc(devcount * sizeof(*bst), M_TEMP, M_WAITOK | M_ZERO); bi = kmalloc(devcount * sizeof(*bi), M_TEMP, M_WAITOK | M_ZERO); bif = kmalloc(sizeof(*bif), M_TEMP, M_WAITOK | M_ZERO); /* * Pass 1: for each battery that is present and valid, get its status, * calculate percent capacity remaining, and sum all the current * discharge rates. */ dev_idx = -1; batt_stat = valid_rate = valid_units = 0; for (i = 0; i < devcount; i++) { /* Default info for every battery is "not present". */ acpi_reset_battinfo(&bi[i]); /* * Find the device. Since devcount is in terms of max units, this * may be a sparse array so skip devices that aren't present. */ batt_dev = devclass_get_device(batt_dc, i); if (batt_dev == NULL) continue; /* If examining a specific battery and this is it, record its index. */ if (dev != NULL && dev == batt_dev) dev_idx = i; /* * Be sure we can get various info from the battery. Note that * acpi_BatteryIsPresent() is not enough because smart batteries only * return that the device is present. */ if (!acpi_BatteryIsPresent(batt_dev) || ACPI_BATT_GET_STATUS(batt_dev, &bst[i]) != 0 || ACPI_BATT_GET_INFO(batt_dev, bif) != 0) continue; /* If a battery is not installed, we sometimes get strange values. */ if (!acpi_battery_bst_valid(&bst[i]) || !acpi_battery_bif_valid(bif)) continue; /* * Record current state. If both charging and discharging are set, * ignore the charging flag. */ valid_units++; if ((bst[i].state & ACPI_BATT_STAT_DISCHARG) != 0) bst[i].state &= ~ACPI_BATT_STAT_CHARGING; batt_stat |= bst[i].state; bi[i].state = bst[i].state; /* * If the battery info is in terms of mA, convert to mW by * multiplying by the design voltage. If the design voltage * is 0 (due to some error reading the battery), skip this * conversion. */ if (bif->units == ACPI_BIF_UNITS_MA && bif->dvol != 0 && dev == NULL) { bst[i].rate = (bst[i].rate * bif->dvol) / 1000; bst[i].cap = (bst[i].cap * bif->dvol) / 1000; bif->lfcap = (bif->lfcap * bif->dvol) / 1000; } /* * The calculation above may set bif->lfcap to zero. This was * seen on a laptop with a broken battery. The result of the * division was rounded to zero. */ if (!acpi_battery_bif_valid(bif)) continue; /* Calculate percent capacity remaining. */ bi[i].cap = (100 * bst[i].cap) / bif->lfcap; /* * Some laptops report the "design-capacity" instead of the * "real-capacity" when the battery is fully charged. That breaks * the above arithmetic as it needs to be 100% maximum. */ if (bi[i].cap > 100) bi[i].cap = 100; /* * On systems with more than one battery, they may get used * sequentially, thus bst.rate may only signify the one currently * in use. For the remaining batteries, bst.rate will be zero, * which makes it impossible to calculate the total remaining time. * Therefore, we sum the bst.rate for batteries in the discharging * state and use the sum to calculate the total remaining time. */ if (bst[i].rate != ACPI_BATT_UNKNOWN && (bst[i].state & ACPI_BATT_STAT_DISCHARG) != 0) valid_rate += bst[i].rate; /* * Some DSDTs report a negative 16-bit value for the rate and/or * report 0 as 65536. */ if (acpi_quirks & ACPI_Q_BATT_RATE_ABS && bif->units == ACPI_BIF_UNITS_MA && bst[i].rate != ACPI_BATT_UNKNOWN && (int16_t)bst[i].rate < 0) bst[i].rate = abs((int16_t)bst[i].rate); } /* If the caller asked for a device but we didn't find it, error. */ if (dev != NULL && dev_idx == -1) { error = ENXIO; goto out; } /* Pass 2: calculate capacity and remaining time for all batteries. */ total_cap = total_min = 0; for (i = 0; i < devcount; i++) { /* * If any batteries are discharging, use the sum of the bst.rate * values. Otherwise, we are on AC power, and there is infinite * time remaining for this battery until we go offline. */ if (valid_rate > 0) bi[i].min = (60 * bst[i].cap) / valid_rate; else bi[i].min = 0; total_min += bi[i].min; /* If this battery is not present, don't use its capacity. */ if (bi[i].cap != -1) total_cap += bi[i].cap; } /* * Return total battery percent and time remaining. If there are * no valid batteries, report values as unknown. */ if (valid_units > 0) { if (dev == NULL) { battinfo->cap = total_cap / valid_units; battinfo->min = total_min; battinfo->state = batt_stat; battinfo->rate = valid_rate; } else { battinfo->cap = bi[dev_idx].cap; battinfo->min = bi[dev_idx].min; battinfo->state = bi[dev_idx].state; battinfo->rate = bst[dev_idx].rate; } /* * If the queried battery has no discharge rate or is charging, * report that we don't know the remaining time. */ if (valid_rate == 0 || (battinfo->state & ACPI_BATT_STAT_CHARGING)) battinfo->min = -1; } else acpi_reset_battinfo(battinfo); error = 0; out: if (bi) kfree(bi, M_TEMP); if (bif) kfree(bif, M_TEMP); if (bst) kfree(bst, M_TEMP); return (error); }