/* * Setting LED interface for inside kernel. * Argumnt `led' is 3-bit LED state (led=0-7/ON=1/OFF=0). */ void obs266_led_set(int led) { device_t dv; deviter_t di; /* * Sarching "obsled" devices from device tree. * Do you have something better idea? */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_is_a(dv, "obsles")) { struct obsled_softc *sc = device_private(dv); sc->sc_led_state = (led & (1 << device_unit(dv))) >> device_unit(dv); obsled_set_state(sc); } } deviter_release(&di); }
static void findroot(void) { device_t dv; deviter_t di; if (booted_device) return; if ((booted_device == NULL) && netboot == 0) { for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_class(dv) == DV_DISK && device_is_a(dv, "wd")) booted_device = dv; } deviter_release(&di); } /* * XXX Match up MBR boot specification with BSD disklabel for root? */ booted_partition = 0; }
/* * XXX Ugly bit of code. But, this is the only safe time that the * match between BIOS disks and native disks can be done. */ static void matchbiosdisks(void) { struct btinfo_biosgeom *big; struct bi_biosgeom_entry *be; device_t dv; deviter_t di; int i, ck, error, m, n; struct vnode *tv; char mbr[DEV_BSIZE]; int dklist_size; int numbig; if (x86_ndisks) return; big = lookup_bootinfo(BTINFO_BIOSGEOM); numbig = big ? big->num : 0; /* First, count all native disks. */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (is_valid_disk(dv)) x86_ndisks++; } deviter_release(&di); dklist_size = sizeof(struct disklist) + (x86_ndisks - 1) * sizeof(struct nativedisk_info); /* XXX M_TEMP is wrong */ x86_alldisks = malloc(dklist_size, M_TEMP, M_NOWAIT | M_ZERO); if (x86_alldisks == NULL) return; x86_alldisks->dl_nnativedisks = x86_ndisks; x86_alldisks->dl_nbiosdisks = numbig; for (i = 0; i < numbig; i++) { x86_alldisks->dl_biosdisks[i].bi_dev = big->disk[i].dev; x86_alldisks->dl_biosdisks[i].bi_sec = big->disk[i].sec; x86_alldisks->dl_biosdisks[i].bi_head = big->disk[i].head; x86_alldisks->dl_biosdisks[i].bi_cyl = big->disk[i].cyl; x86_alldisks->dl_biosdisks[i].bi_lbasecs = big->disk[i].totsec; x86_alldisks->dl_biosdisks[i].bi_flags = big->disk[i].flags; DPRINTF(("%s: disk %x: flags %x", __func__, big->disk[i].dev, big->disk[i].flags)); #ifdef BIOSDISK_EXTINFO_V3 DPRINTF((", interface %x, device %llx", big->disk[i].interface_path, big->disk[i].device_path)); #endif DPRINTF(("\n")); } /* XXX Code duplication from findroot(). */ n = -1; for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (!is_valid_disk(dv)) continue; DPRINTF(("%s: trying to match (%s) %s: ", __func__, device_xname(dv), device_cfdata(dv)->cf_name)); n++; snprintf(x86_alldisks->dl_nativedisks[n].ni_devname, sizeof(x86_alldisks->dl_nativedisks[n].ni_devname), "%s", device_xname(dv)); if ((tv = opendisk(dv)) == NULL) { DPRINTF(("cannot open\n")); continue; } error = vn_rdwr(UIO_READ, tv, mbr, DEV_BSIZE, 0, UIO_SYSSPACE, 0, NOCRED, NULL, NULL); VOP_CLOSE(tv, FREAD, NOCRED); vput(tv); if (error) { DPRINTF(("MBR read failure %d\n", error)); continue; } for (ck = i = 0; i < DEV_BSIZE; i++) ck += mbr[i]; for (m = i = 0; i < numbig; i++) { be = &big->disk[i]; if (be->flags & BI_GEOM_INVALID) continue; DPRINTF(("matched with %d dev ck %x bios ck %x\n", i, ck, be->cksum)); if (be->cksum == ck && memcmp(&mbr[MBR_PART_OFFSET], be->mbrparts, MBR_PART_COUNT * sizeof(struct mbr_partition)) == 0) { DPRINTF(("%s: matched BIOS disk %x with %s\n", __func__, be->dev, device_xname(dv))); x86_alldisks->dl_nativedisks[n]. ni_biosmatches[m++] = i; } } x86_alldisks->dl_nativedisks[n].ni_nmatches = m; } deviter_release(&di); }
/* * Attempt to find the device from which we were booted. If we can do so, * and not instructed not to do so, change rootdev to correspond to the * load device. */ static void findroot(void) { struct btinfo_rootdevice *biv; struct btinfo_bootdisk *bid; struct btinfo_bootwedge *biw; struct btinfo_biosgeom *big; device_t dv; deviter_t di; if (booted_device) return; if (lookup_bootinfo(BTINFO_NETIF) != NULL) { /* * We got netboot interface information, but device_register() * failed to match it to a configured device. Boot disk * information cannot be present at the same time, so give * up. */ printf("%s: netboot interface not found.\n", __func__); return; } if ((biv = lookup_bootinfo(BTINFO_ROOTDEVICE)) != NULL) { for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { cfdata_t cd; size_t len; if (device_class(dv) != DV_DISK) continue; cd = device_cfdata(dv); len = strlen(cd->cf_name); if (strncmp(cd->cf_name, biv->devname, len) == 0 && biv->devname[len] - '0' == device_unit(dv)) { booted_device = dv; booted_partition = biv->devname[len + 1] - 'a'; booted_nblks = 0; break; } } DPRINTF(("%s: BTINFO_ROOTDEVICE %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); deviter_release(&di); if (dv != NULL) return; } bid = lookup_bootinfo(BTINFO_BOOTDISK); biw = lookup_bootinfo(BTINFO_BOOTWEDGE); if (biw != NULL) { /* * Scan all disk devices for ones that match the passed data. * Don't break if one is found, to get possible multiple * matches - for problem tracking. Use the first match anyway * because lower devices numbers are more likely to be the * boot device. */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (is_valid_disk(dv)) { /* * Don't trust BIOS device numbers, try * to match the information passed by the * boot loader instead. */ if ((biw->biosdev & 0x80) == 0 || match_bootwedge(dv, biw) == 0) continue; goto bootwedge_found; } continue; bootwedge_found: if (booted_device) { dmatch(__func__, dv); continue; } booted_device = dv; booted_partition = bid != NULL ? bid->partition : 0; booted_nblks = biw->nblks; booted_startblk = biw->startblk; } deviter_release(&di); DPRINTF(("%s: BTINFO_BOOTWEDGE %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); if (booted_nblks) return; } if (bid != NULL) { /* * Scan all disk devices for ones that match the passed data. * Don't break if one is found, to get possible multiple * matches - for problem tracking. Use the first match anyway * because lower device numbers are more likely to be the * boot device. */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_is_a(dv, "fd") && device_class(dv) == DV_DISK) { /* * Assume the configured unit number matches * the BIOS device number. (This is the old * behavior.) Needs some ideas how to handle * the BIOS's "swap floppy drive" options. */ /* XXX device_unit() abuse */ if ((bid->biosdev & 0x80) != 0 || device_unit(dv) != bid->biosdev) continue; goto bootdisk_found; } if (is_valid_disk(dv)) { /* * Don't trust BIOS device numbers, try * to match the information passed by the * boot loader instead. */ if ((bid->biosdev & 0x80) == 0 || match_bootdisk(dv, bid) == 0) continue; goto bootdisk_found; } continue; bootdisk_found: if (booted_device) { dmatch(__func__, dv); continue; } booted_device = dv; booted_partition = bid->partition; booted_nblks = 0; } deviter_release(&di); DPRINTF(("%s: BTINFO_BOOTDISK %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); if (booted_device) return; /* * No booted device found; check CD-ROM boot at last. * * Our bootloader assumes CD-ROM boot if biosdev is larger * or equal than the number of hard drives recognized by the * BIOS. The number of drives can be found in BTINFO_BIOSGEOM * here. For example, if we have wd0, wd1, and cd0: * * big->num = 2 (for wd0 and wd1) * bid->biosdev = 0x80 (wd0) * bid->biosdev = 0x81 (wd1) * bid->biosdev = 0x82 (cd0) * * See src/sys/arch/i386/stand/boot/devopen.c and * src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c . */ if ((big = lookup_bootinfo(BTINFO_BIOSGEOM)) != NULL && bid->biosdev >= 0x80 + big->num) { /* * XXX * There is no proper way to detect which unit is * recognized as a bootable CD-ROM drive by the BIOS. * Assume the first unit is the one. */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_class(dv) == DV_DISK && device_is_a(dv, "cd")) { booted_device = dv; booted_partition = 0; booted_nblks = 0; break; } } deviter_release(&di); DPRINTF(("%s: BTINFO_BIOSGEOM %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); } } }
static void thinkpad_attach(device_t parent, device_t self, void *opaque) { thinkpad_softc_t *sc = device_private(self); struct acpi_attach_args *aa = (struct acpi_attach_args *)opaque; struct sysmon_pswitch *psw; device_t curdev; deviter_t di; ACPI_STATUS rv; ACPI_INTEGER val; int i; sc->sc_dev = self; sc->sc_powhdl = NULL; sc->sc_cmoshdl = NULL; sc->sc_node = aa->aa_node; sc->sc_display_state = THINKPAD_DISPLAY_LCD; aprint_naive("\n"); aprint_normal("\n"); sc->sc_ecdev = NULL; for (curdev = deviter_first(&di, DEVITER_F_ROOT_FIRST); curdev != NULL; curdev = deviter_next(&di)) if (device_is_a(curdev, "acpiecdt") || device_is_a(curdev, "acpiec")) { sc->sc_ecdev = curdev; break; } deviter_release(&di); if (sc->sc_ecdev) aprint_debug_dev(self, "using EC at %s\n", device_xname(sc->sc_ecdev)); /* Get the supported event mask */ rv = acpi_eval_integer(sc->sc_node->ad_handle, "MHKA", &val); if (ACPI_FAILURE(rv)) { aprint_error_dev(self, "couldn't evaluate MHKA: %s\n", AcpiFormatException(rv)); goto fail; } /* Enable all supported events */ rv = thinkpad_mask_init(sc, val); if (ACPI_FAILURE(rv)) { aprint_error_dev(self, "couldn't set event mask: %s\n", AcpiFormatException(rv)); goto fail; } (void)acpi_register_notify(sc->sc_node, thinkpad_notify_handler); /* * Obtain a handle for CMOS commands. This is used by T61. */ (void)AcpiGetHandle(NULL, "\\UCMS", &sc->sc_cmoshdl); /* * Obtain a handle to the power resource available on many models. * Since pmf(9) is not yet integrated with the ACPI power resource * code, this must be turned on manually upon resume. Otherwise the * system may, for instance, resume from S3 with usb(4) powered down. */ (void)AcpiGetHandle(NULL, "\\_SB.PCI0.LPC.EC.PUBS", &sc->sc_powhdl); /* Register power switches with sysmon */ psw = sc->sc_smpsw; sc->sc_smpsw_valid = true; psw[TP_PSW_SLEEP].smpsw_name = device_xname(self); psw[TP_PSW_SLEEP].smpsw_type = PSWITCH_TYPE_SLEEP; #if notyet psw[TP_PSW_HIBERNATE].smpsw_name = device_xname(self); mpsw[TP_PSW_HIBERNATE].smpsw_type = PSWITCH_TYPE_HIBERNATE; #endif for (i = TP_PSW_DISPLAY_CYCLE; i < TP_PSW_LAST; i++) sc->sc_smpsw[i].smpsw_type = PSWITCH_TYPE_HOTKEY; psw[TP_PSW_DISPLAY_CYCLE].smpsw_name = PSWITCH_HK_DISPLAY_CYCLE; psw[TP_PSW_LOCK_SCREEN].smpsw_name = PSWITCH_HK_LOCK_SCREEN; psw[TP_PSW_BATTERY_INFO].smpsw_name = PSWITCH_HK_BATTERY_INFO; psw[TP_PSW_EJECT_BUTTON].smpsw_name = PSWITCH_HK_EJECT_BUTTON; psw[TP_PSW_ZOOM_BUTTON].smpsw_name = PSWITCH_HK_ZOOM_BUTTON; psw[TP_PSW_VENDOR_BUTTON].smpsw_name = PSWITCH_HK_VENDOR_BUTTON; #ifndef THINKPAD_NORMAL_HOTKEYS psw[TP_PSW_FNF1_BUTTON].smpsw_name = PSWITCH_HK_FNF1_BUTTON; psw[TP_PSW_WIRELESS_BUTTON].smpsw_name = PSWITCH_HK_WIRELESS_BUTTON; psw[TP_PSW_WWAN_BUTTON].smpsw_name = PSWITCH_HK_WWAN_BUTTON; psw[TP_PSW_POINTER_BUTTON].smpsw_name = PSWITCH_HK_POINTER_BUTTON; psw[TP_PSW_FNF10_BUTTON].smpsw_name = PSWITCH_HK_FNF10_BUTTON; psw[TP_PSW_FNF11_BUTTON].smpsw_name = PSWITCH_HK_FNF11_BUTTON; psw[TP_PSW_BRIGHTNESS_UP].smpsw_name = PSWITCH_HK_BRIGHTNESS_UP; psw[TP_PSW_BRIGHTNESS_DOWN].smpsw_name = PSWITCH_HK_BRIGHTNESS_DOWN; psw[TP_PSW_THINKLIGHT].smpsw_name = PSWITCH_HK_THINKLIGHT; psw[TP_PSW_VOLUME_UP].smpsw_name = PSWITCH_HK_VOLUME_UP; psw[TP_PSW_VOLUME_DOWN].smpsw_name = PSWITCH_HK_VOLUME_DOWN; psw[TP_PSW_VOLUME_MUTE].smpsw_name = PSWITCH_HK_VOLUME_MUTE; #endif /* THINKPAD_NORMAL_HOTKEYS */ for (i = 0; i < TP_PSW_LAST; i++) { /* not supported yet */ if (i == TP_PSW_HIBERNATE) continue; if (sysmon_pswitch_register(&sc->sc_smpsw[i]) != 0) { aprint_error_dev(self, "couldn't register with sysmon\n"); sc->sc_smpsw_valid = false; break; } } /* Register temperature and fan sensors with envsys */ thinkpad_sensors_init(sc); fail: if (!pmf_device_register(self, NULL, thinkpad_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP, thinkpad_brightness_up, true)) aprint_error_dev(self, "couldn't register event handler\n"); if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN, thinkpad_brightness_down, true)) aprint_error_dev(self, "couldn't register event handler\n"); }