/* * Get the firmware package handle from a device_t. * Assuming we have previously stored it in the device properties * dictionary. */ static int device_ofnode(device_t dev) { prop_dictionary_t props; prop_object_t obj; if (dev == NULL) return 0; props = device_properties(dev); if (props == NULL) return 0; obj = prop_dictionary_get(props, OFNODEKEY); if (obj == NULL) return 0; return prop_number_integer_value(obj); }
int32_t udev_device_get_minor(struct udev_device *udev_device) { prop_number_t pn; int32_t minor; if (udev_device->dict == NULL) return 0; pn = prop_dictionary_get(udev_device->dict, "minor"); if (pn == NULL) return 0; minor = (int32_t)prop_number_integer_value(pn); return minor; }
static void cpuattach(struct device *parent, struct device *self, void *aux) { struct cputab *cp = models; u_int pvr; u_int processor_freq; prop_number_t freq; freq = prop_dictionary_get(board_properties, "processor-frequency"); KASSERT(freq != NULL); processor_freq = (unsigned int) prop_number_integer_value(freq); cpufound++; ncpus++; pvr = mfpvr(); while (cp->name) { if ((pvr & cp->mask) == cp->version) break; cp++; } if (cp->name) strcpy(cpu_model, cp->name); else sprintf(cpu_model, "Version 0x%x", pvr); printf(": %dMHz %s (PVR 0x%x)\n", processor_freq / 1000 / 1000, cp->name ? cp->name : "unknown model", pvr); cpu_probe_cache(); /* We would crash later on anyway so just make the reason obvious */ if (curcpu()->ci_ci.icache_size == 0 && curcpu()->ci_ci.dcache_size == 0) panic("%s could not detect cache size", device_xname(self)); printf("%s: Instruction cache size %d line size %d\n", device_xname(self), curcpu()->ci_ci.icache_size, curcpu()->ci_ci.icache_line_size); printf("%s: Data cache size %d line size %d\n", device_xname(self), curcpu()->ci_ci.dcache_size, curcpu()->ci_ci.dcache_line_size); }
int prep_pci_bus_maxdevs(pci_chipset_tag_t pc, int busno) { struct genppc_pci_chipset_businfo *pbi; prop_object_t busmax; pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi); while (busno--) pbi = SIMPLEQ_NEXT(pbi, next); if (pbi == NULL) return 32; busmax = prop_dictionary_get(pbi->pbi_properties, "prep-pcibus-maxdevices"); if (busmax == NULL) return 32; else return prop_number_integer_value(busmax); return 32; }
void com_arbus_attach(device_t parent, device_t self, void *aux) { struct com_arbus_softc *arsc = device_private(self); struct com_softc *sc = &arsc->sc_com; struct arbus_attach_args *aa = aux; prop_number_t prop; bus_space_handle_t ioh; sc->sc_dev = self; prop = prop_dictionary_get(device_properties(sc->sc_dev), "frequency"); if (prop == NULL) { aprint_error(": unable to get frequency property\n"); return; } KASSERT(prop_object_type(prop) == PROP_TYPE_NUMBER); sc->sc_frequency = (int)prop_number_integer_value(prop); if (!com_is_console(aa->aa_bst, aa->aa_addr, &ioh) && bus_space_map(aa->aa_bst, aa->aa_addr, aa->aa_size, 0, &ioh) != 0) { aprint_error(": can't map registers\n"); return; } COM_INIT_REGS(sc->sc_regs, aa->aa_bst, ioh, aa->aa_addr); sc->sc_regs.cr_nports = aa->aa_size; com_arbus_initmap(&sc->sc_regs); com_attach_subr(sc); arbus_intr_establish(aa->aa_cirq, aa->aa_mirq, comintr, sc); }
static void wdog_attach(device_t parent, device_t self, void *aux) { struct wdog_softc * const sc = device_private(self); unsigned int processor_freq; prop_number_t freq; freq = prop_dictionary_get(board_properties, "processor-frequency"); KASSERT(freq != NULL); processor_freq = (unsigned int) prop_number_integer_value(freq); sc->sc_wdog_period = (2LL << 29) / processor_freq; aprint_normal(": %d second period\n", sc->sc_wdog_period); sc->sc_dev = self; sc->sc_smw.smw_name = device_xname(self); sc->sc_smw.smw_cookie = sc; sc->sc_smw.smw_setmode = wdog_setmode; sc->sc_smw.smw_tickle = wdog_tickle; sc->sc_smw.smw_period = sc->sc_wdog_period; if (sysmon_wdog_register(&sc->sc_smw) != 0) aprint_error_dev(self, "unable to register with sysmon\n"); }
/* * Reads the CPU temperature from /sys/class/thermal/thermal_zone%d/temp (or * the user provided path) and returns the temperature in degree celcius. * */ void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const char *path, const char *format, int max_threshold) { char *outwalk = buffer; #ifdef THERMAL_ZONE const char *walk; bool colorful_output = false; char *thermal_zone; if (path == NULL) asprintf(&thermal_zone, THERMAL_ZONE, zone); else { static glob_t globbuf; if (glob(path, GLOB_NOCHECK | GLOB_TILDE, NULL, &globbuf) < 0) die("glob() failed\n"); if (globbuf.gl_pathc == 0) { /* No glob matches, the specified path does not contain a wildcard. */ asprintf(&thermal_zone, path, zone); } else { /* glob matched, we take the first match and ignore the others */ asprintf(&thermal_zone, "%s", globbuf.gl_pathv[0]); } globfree(&globbuf); } INSTANCE(thermal_zone); for (walk = format; *walk != '\0'; walk++) { if (*walk != '%') { *(outwalk++) = *walk; continue; } if (BEGINS_WITH(walk + 1, "degrees")) { #if defined(LINUX) static char buf[16]; long int temp; if (!slurp(thermal_zone, buf, sizeof(buf))) goto error; temp = strtol(buf, NULL, 10); if (temp == LONG_MIN || temp == LONG_MAX || temp <= 0) *(outwalk++) = '?'; else { if ((temp / 1000) >= max_threshold) { START_COLOR("color_bad"); colorful_output = true; } outwalk += sprintf(outwalk, "%ld", (temp / 1000)); if (colorful_output) { END_COLOR; colorful_output = false; } } #elif defined(__DragonFly__) struct sensor th_sensor; size_t th_sensorlen; th_sensorlen = sizeof(th_sensor); if (sysctlbyname(thermal_zone, &th_sensor, &th_sensorlen, NULL, 0) == -1) { perror("sysctlbyname"); goto error; } if (MUKTOC(th_sensor.value) >= max_threshold) { START_COLOR("color_bad"); colorful_output = true; } outwalk += sprintf(outwalk, "%.2f", MUKTOC(th_sensor.value)); if (colorful_output) { END_COLOR; colorful_output = false; } #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) int sysctl_rslt; size_t sysctl_size = sizeof(sysctl_rslt); if (sysctlbyname(thermal_zone, &sysctl_rslt, &sysctl_size, NULL, 0)) goto error; if (TZ_AVG(sysctl_rslt) >= max_threshold) { START_COLOR("color_bad"); colorful_output = true; } outwalk += sprintf(outwalk, "%d.%d", TZ_KELVTOC(sysctl_rslt)); if (colorful_output) { END_COLOR; colorful_output = false; } #elif defined(__OpenBSD__) struct sensordev sensordev; struct sensor sensor; size_t sdlen, slen; int dev, numt, mib[5] = {CTL_HW, HW_SENSORS, 0, 0, 0}; sdlen = sizeof(sensordev); slen = sizeof(sensor); for (dev = 0;; dev++) { mib[2] = dev; if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) { if (errno == ENXIO) continue; if (errno == ENOENT) break; goto error; } /* 'path' is the node within the full path (defaults to acpitz0). */ if (BEGINS_WITH(sensordev.xname, thermal_zone)) { mib[3] = SENSOR_TEMP; /* Limit to temo0, but should retrieve from a full path... */ for (numt = 0; numt < 1 /*sensordev.maxnumt[SENSOR_TEMP]*/; numt++) { mib[4] = numt; if (sysctl(mib, 5, &sensor, &slen, NULL, 0) == -1) { if (errno != ENOENT) { warn("sysctl"); continue; } } if ((int)MUKTOC(sensor.value) >= max_threshold) { START_COLOR("color_bad"); colorful_output = true; } outwalk += sprintf(outwalk, "%.2f", MUKTOC(sensor.value)); if (colorful_output) { END_COLOR; colorful_output = false; } } } } #elif defined(__NetBSD__) int fd, rval; bool err = false; prop_dictionary_t dict; prop_array_t array; prop_object_iterator_t iter; prop_object_iterator_t iter2; prop_object_t obj, obj2, obj3; fd = open("/dev/sysmon", O_RDONLY); if (fd == -1) goto error; rval = prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &dict); if (rval == -1) { err = true; goto error_netbsd1; } /* No drivers registered? */ if (prop_dictionary_count(dict) == 0) { err = true; goto error_netbsd2; } iter = prop_dictionary_iterator(dict); if (iter == NULL) { err = true; goto error_netbsd2; } /* iterate over the dictionary returned by the kernel */ while ((obj = prop_object_iterator_next(iter)) != NULL) { /* skip this dict if it's not what we're looking for */ if ((strlen(prop_dictionary_keysym_cstring_nocopy(obj)) != strlen(thermal_zone)) || (strncmp(thermal_zone, prop_dictionary_keysym_cstring_nocopy(obj), strlen(thermal_zone)) != 0)) continue; array = prop_dictionary_get_keysym(dict, obj); if (prop_object_type(array) != PROP_TYPE_ARRAY) { err = true; goto error_netbsd3; } iter2 = prop_array_iterator(array); if (!iter2) { err = true; goto error_netbsd3; } /* iterate over array of dicts specific to target sensor */ while ((obj2 = prop_object_iterator_next(iter2)) != NULL) { obj3 = prop_dictionary_get(obj2, "cur-value"); float temp = MUKTOC(prop_number_integer_value(obj3)); if ((int)temp >= max_threshold) { START_COLOR("color_bad"); colorful_output = true; } outwalk += sprintf(outwalk, "%.2f", temp); if (colorful_output) { END_COLOR; colorful_output = false; } break; } prop_object_iterator_release(iter2); } error_netbsd3: prop_object_iterator_release(iter); error_netbsd2: prop_object_release(dict); error_netbsd1: close(fd); if (err) goto error; #endif walk += strlen("degrees"); } } free(thermal_zone); OUTPUT_FULL_TEXT(buffer); return; error: free(thermal_zone); #endif OUTPUT_FULL_TEXT("can't read temp"); (void)fputs("i3status: Cannot read temperature. Verify that you have a thermal zone in /sys/class/thermal or disable the cpu_temperature module in your i3status config.\n", stderr); }
int prep_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct genppc_pci_chipset_businfo *pbi; prop_dictionary_t dict, devsub; prop_object_t pinsub; prop_number_t pbus; int busno, bus, pin, line, swiz, dev, origdev, i; char key[20]; pin = pa->pa_intrpin; line = pa->pa_intrline; bus = busno = pa->pa_bus; swiz = pa->pa_intrswiz; origdev = dev = pa->pa_device; i = 0; pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi); while (busno--) pbi = SIMPLEQ_NEXT(pbi, next); KASSERT(pbi != NULL); dict = prop_dictionary_get(pbi->pbi_properties, "prep-pci-intrmap"); if (dict != NULL) i = prop_dictionary_count(dict); if (dict == NULL || i == 0) { /* We have a non-PReP bus. now it gets hard */ pbus = prop_dictionary_get(pbi->pbi_properties, "prep-pcibus-parent"); if (pbus == NULL) goto bad; busno = prop_number_integer_value(pbus); pbus = prop_dictionary_get(pbi->pbi_properties, "prep-pcibus-rawdevnum"); dev = prop_number_integer_value(pbus); /* now that we know the parent bus, we need to find it's pbi */ pbi = SIMPLEQ_FIRST(&genppc_pct->pc_pbi); while (busno--) pbi = SIMPLEQ_NEXT(pbi, next); KASSERT(pbi != NULL); /* swizzle the pin */ pin = ((pin + origdev - 1) & 3) + 1; /* now we have the pbi, ask for dict again */ dict = prop_dictionary_get(pbi->pbi_properties, "prep-pci-intrmap"); if (dict == NULL) goto bad; } /* No IRQ used. */ if (pin == 0) goto bad; if (pin > 4) { aprint_error("pci_intr_map: bad interrupt pin %d\n", pin); goto bad; } sprintf(key, "devfunc-%d", dev); devsub = prop_dictionary_get(dict, key); if (devsub == NULL) goto bad; sprintf(key, "pin-%c", 'A' + (pin-1)); pinsub = prop_dictionary_get(devsub, key); if (pinsub == NULL) goto bad; line = prop_number_integer_value(pinsub); /* * Section 6.2.4, `Miscellaneous Functions', says that 255 means * `unknown' or `no connection' on a PC. We assume that a device with * `no connection' either doesn't have an interrupt (in which case the * pin number should be 0, and would have been noticed above), or * wasn't configured by the BIOS (in which case we punt, since there's * no real way we can know how the interrupt lines are mapped in the * hardware). * * XXX * Since IRQ 0 is only used by the clock, and we can't actually be sure * that the BIOS did its job, we also recognize that as meaning that * the BIOS has not configured the device. */ if (line == 0 || line == 255) { aprint_error("pci_intr_map: no mapping for pin %c\n", '@' + pin); goto bad; } else { if (line >= ICU_LEN) { aprint_error("pci_intr_map: bad interrupt line %d\n", line); goto bad; } if (line == IRQ_SLAVE) { aprint_verbose("pci_intr_map: changed line 2 to line 9\n"); line = 9; } } *ihp = line; return 0; bad: *ihp = -1; return 1; }
static void bthidev_attach(device_t parent, device_t self, void *aux) { struct bthidev_softc *sc = device_private(self); prop_dictionary_t dict = aux; prop_object_t obj; device_t dev; struct bthidev_attach_args bha; struct bthidev *hidev; struct hid_data *d; struct hid_item h; const void *desc; int locs[BTHIDBUSCF_NLOCS]; int maxid, rep, dlen; /* * Init softc */ sc->sc_dev = self; LIST_INIT(&sc->sc_list); callout_init(&sc->sc_reconnect, 0); callout_setfunc(&sc->sc_reconnect, bthidev_timeout, sc); sc->sc_state = BTHID_CLOSED; sc->sc_flags = BTHID_CONNECTING; sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL; sc->sc_intpsm = L2CAP_PSM_HID_INTR; sockopt_init(&sc->sc_mode, BTPROTO_L2CAP, SO_L2CAP_LM, 0); /* * extract config from proplist */ obj = prop_dictionary_get(dict, BTDEVladdr); bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj)); obj = prop_dictionary_get(dict, BTDEVraddr); bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj)); obj = prop_dictionary_get(dict, BTDEVmode); if (prop_object_type(obj) == PROP_TYPE_STRING) { if (prop_string_equals_cstring(obj, BTDEVauth)) sockopt_setint(&sc->sc_mode, L2CAP_LM_AUTH); else if (prop_string_equals_cstring(obj, BTDEVencrypt)) sockopt_setint(&sc->sc_mode, L2CAP_LM_ENCRYPT); else if (prop_string_equals_cstring(obj, BTDEVsecure)) sockopt_setint(&sc->sc_mode, L2CAP_LM_SECURE); else { aprint_error(" unknown %s\n", BTDEVmode); return; } aprint_verbose(" %s %s", BTDEVmode, prop_string_cstring_nocopy(obj)); } obj = prop_dictionary_get(dict, BTHIDEVcontrolpsm); if (prop_object_type(obj) == PROP_TYPE_NUMBER) { sc->sc_ctlpsm = prop_number_integer_value(obj); if (L2CAP_PSM_INVALID(sc->sc_ctlpsm)) { aprint_error(" invalid %s\n", BTHIDEVcontrolpsm); return; } } obj = prop_dictionary_get(dict, BTHIDEVinterruptpsm); if (prop_object_type(obj) == PROP_TYPE_NUMBER) { sc->sc_intpsm = prop_number_integer_value(obj); if (L2CAP_PSM_INVALID(sc->sc_intpsm)) { aprint_error(" invalid %s\n", BTHIDEVinterruptpsm); return; } } obj = prop_dictionary_get(dict, BTHIDEVdescriptor); if (prop_object_type(obj) == PROP_TYPE_DATA) { dlen = prop_data_size(obj); desc = prop_data_data_nocopy(obj); } else { aprint_error(" no %s\n", BTHIDEVdescriptor); return; } obj = prop_dictionary_get(dict, BTHIDEVreconnect); if (prop_object_type(obj) == PROP_TYPE_BOOL && !prop_bool_true(obj)) sc->sc_flags |= BTHID_RECONNECT; /* * Parse the descriptor and attach child devices, one per report. */ maxid = -1; h.report_ID = 0; d = hid_start_parse(desc, dlen, hid_none); while (hid_get_item(d, &h)) { if (h.report_ID > maxid) maxid = h.report_ID; } hid_end_parse(d); if (maxid < 0) { aprint_error(" no reports found\n"); return; } aprint_normal("\n"); for (rep = 0 ; rep <= maxid ; rep++) { if (hid_report_size(desc, dlen, hid_feature, rep) == 0 && hid_report_size(desc, dlen, hid_input, rep) == 0 && hid_report_size(desc, dlen, hid_output, rep) == 0) continue; bha.ba_desc = desc; bha.ba_dlen = dlen; bha.ba_input = bthidev_null; bha.ba_feature = bthidev_null; bha.ba_output = bthidev_output; bha.ba_id = rep; locs[BTHIDBUSCF_REPORTID] = rep; dev = config_found_sm_loc(self, "bthidbus", locs, &bha, bthidev_print, config_stdsubmatch); if (dev != NULL) { hidev = device_private(dev); hidev->sc_dev = dev; hidev->sc_parent = self; hidev->sc_id = rep; hidev->sc_input = bha.ba_input; hidev->sc_feature = bha.ba_feature; LIST_INSERT_HEAD(&sc->sc_list, hidev, sc_next); } } /* * start bluetooth connections */ mutex_enter(bt_lock); if ((sc->sc_flags & BTHID_RECONNECT) == 0) bthidev_listen(sc); if (sc->sc_flags & BTHID_CONNECTING) bthidev_connect(sc); mutex_exit(bt_lock); }
static int swsensor_init(void *arg) { int error, val = 0; const char *key, *str; prop_dictionary_t pd = (prop_dictionary_t)arg; prop_object_t po, obj; prop_object_iterator_t iter; prop_type_t type; const struct sme_descr_entry *descr; swsensor_sme = sysmon_envsys_create(); if (swsensor_sme == NULL) return ENOTTY; swsensor_sme->sme_name = "swsensor"; swsensor_sme->sme_cookie = &swsensor_edata; swsensor_sme->sme_refresh = swsensor_refresh; swsensor_sme->sme_set_limits = NULL; swsensor_sme->sme_get_limits = NULL; /* Set defaults in case no prop dictionary given */ swsensor_edata.units = ENVSYS_INTEGER; swsensor_edata.flags = 0; sw_sensor_mode = 0; sw_sensor_value = 0; sw_sensor_limit = 0; /* Iterate over the provided dictionary, if any */ if (pd != NULL) { iter = prop_dictionary_iterator(pd); if (iter == NULL) return ENOMEM; while ((obj = prop_object_iterator_next(iter)) != NULL) { key = prop_dictionary_keysym_cstring_nocopy(obj); po = prop_dictionary_get_keysym(pd, obj); type = prop_object_type(po); if (type == PROP_TYPE_NUMBER) val = prop_number_integer_value(po); /* Sensor type/units */ if (strcmp(key, "type") == 0) { if (type == PROP_TYPE_NUMBER) { descr = sme_find_table_entry( SME_DESC_UNITS, val); if (descr == NULL) return EINVAL; swsensor_edata.units = descr->type; continue; } if (type != PROP_TYPE_STRING) return EINVAL; str = prop_string_cstring_nocopy(po); descr = sme_find_table_desc(SME_DESC_UNITS, str); if (descr == NULL) return EINVAL; swsensor_edata.units = descr->type; continue; } /* Sensor flags */ if (strcmp(key, "flags") == 0) { if (type != PROP_TYPE_NUMBER) return EINVAL; swsensor_edata.flags = val; continue; } /* Sensor limit behavior * 0 - simple sensor, no hw limits * 1 - simple sensor, hw provides initial limit * 2 - complex sensor, hw provides settable * limits and does its own limit checking */ if (strcmp(key, "mode") == 0) { if (type != PROP_TYPE_NUMBER) return EINVAL; sw_sensor_mode = val; if (sw_sensor_mode > 2) sw_sensor_mode = 2; else if (sw_sensor_mode < 0) sw_sensor_mode = 0; continue; } /* Grab any limit that might be specified */ if (strcmp(key, "limit") == 0) { if (type != PROP_TYPE_NUMBER) return EINVAL; sw_sensor_limit = val; continue; } /* Grab the initial value */ if (strcmp(key, "value") == 0) { if (type != PROP_TYPE_NUMBER) return EINVAL; sw_sensor_value = val; continue; } /* Grab value_min and value_max */ if (strcmp(key, "value_min") == 0) { if (type != PROP_TYPE_NUMBER) return EINVAL; swsensor_edata.value_min = val; swsensor_edata.flags |= ENVSYS_FVALID_MIN; continue; } if (strcmp(key, "value_max") == 0) { if (type != PROP_TYPE_NUMBER) return EINVAL; swsensor_edata.value_max = val; swsensor_edata.flags |= ENVSYS_FVALID_MAX; continue; } /* See if sensor reports percentages vs raw values */ if (strcmp(key, "percentage") == 0) { if (type != PROP_TYPE_BOOL) return EINVAL; if (prop_bool_true(po)) swsensor_edata.flags |= ENVSYS_FPERCENT; continue; } /* Unrecognized dicttionary object */ #ifdef DEBUG printf("%s: unknown attribute %s\n", __func__, key); #endif return EINVAL; } /* while */ prop_object_iterator_release(iter); } /* Initialize limit processing */ if (sw_sensor_mode >= 1) swsensor_sme->sme_get_limits = swsensor_get_limits; if (sw_sensor_mode == 2) swsensor_sme->sme_set_limits = swsensor_set_limits; if (sw_sensor_mode != 0) { swsensor_edata.flags |= ENVSYS_FMONLIMITS; swsensor_get_limits(swsensor_sme, &swsensor_edata, &sw_sensor_deflims, &sw_sensor_defprops); } strlcpy(swsensor_edata.desc, "sensor", ENVSYS_DESCLEN); /* Wait for refresh to validate the sensor value */ swsensor_edata.state = ENVSYS_SINVALID; sw_sensor_state = ENVSYS_SVALID; error = sysmon_envsys_sensor_attach(swsensor_sme, &swsensor_edata); if (error != 0) { aprint_error("sysmon_envsys_sensor_attach failed: %d\n", error); return error; } error = sysmon_envsys_register(swsensor_sme); if (error != 0) { aprint_error("sysmon_envsys_register failed: %d\n", error); return error; } sysctl_swsensor_setup(); aprint_normal("swsensor: initialized\n"); return 0; }
static void btsco_attach(device_t parent, device_t self, void *aux) { struct btsco_softc *sc = device_private(self); prop_dictionary_t dict = aux; prop_object_t obj; /* * Init softc */ sc->sc_vgs = 200; sc->sc_vgm = 200; sc->sc_state = BTSCO_CLOSED; sc->sc_name = device_xname(self); cv_init(&sc->sc_connect, "connect"); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE); /* * copy in our configuration info */ obj = prop_dictionary_get(dict, BTDEVladdr); bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj)); obj = prop_dictionary_get(dict, BTDEVraddr); bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj)); obj = prop_dictionary_get(dict, BTDEVservice); if (prop_string_equals_cstring(obj, "HF")) { sc->sc_flags |= BTSCO_LISTEN; aprint_verbose(" listen mode"); } obj = prop_dictionary_get(dict, BTSCOchannel); if (prop_object_type(obj) != PROP_TYPE_NUMBER || prop_number_integer_value(obj) < RFCOMM_CHANNEL_MIN || prop_number_integer_value(obj) > RFCOMM_CHANNEL_MAX) { aprint_error(" invalid %s", BTSCOchannel); return; } sc->sc_channel = prop_number_integer_value(obj); aprint_verbose(" channel %d", sc->sc_channel); aprint_normal("\n"); DPRINTF("sc=%p\n", sc); /* * set up transmit interrupt */ sc->sc_intr = softint_establish(SOFTINT_NET, btsco_intr, sc); if (sc->sc_intr == NULL) { aprint_error_dev(self, "softint_establish failed\n"); return; } /* * attach audio device */ sc->sc_audio = audio_attach_mi(&btsco_if, sc, self); if (sc->sc_audio == NULL) { aprint_error_dev(self, "audio_attach_mi failed\n"); return; } pmf_device_register(self, NULL, NULL); }
int main(int argc, char **argv) { int c, mode; char *attr = 0; extern char *optarg; extern int optind; int fd, res; size_t children; struct devpmargs paa = {.devname = "", .flags = 0}; struct devlistargs laa = {.l_devname = "", .l_childname = NULL, .l_children = 0}; struct devdetachargs daa; struct devrescanargs raa; int *locs, i; prop_dictionary_t command_dict, args_dict, results_dict, data_dict; prop_string_t string; prop_number_t number; char *xml; mode = 0; while ((c = getopt(argc, argv, OPTS)) != -1) { switch (c) { case 'Q': case 'R': case 'S': case 'd': case 'l': case 'p': case 'r': mode = c; break; case 'a': attr = optarg; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc < 1 || mode == 0) usage(); fd = open(DRVCTLDEV, OPEN_MODE(mode), 0); if (fd < 0) err(2, "open %s", DRVCTLDEV); switch (mode) { case 'Q': paa.flags = DEVPM_F_SUBTREE; /*FALLTHROUGH*/ case 'R': strlcpy(paa.devname, argv[0], sizeof(paa.devname)); if (ioctl(fd, DRVRESUMEDEV, &paa) == -1) err(3, "DRVRESUMEDEV"); break; case 'S': strlcpy(paa.devname, argv[0], sizeof(paa.devname)); if (ioctl(fd, DRVSUSPENDDEV, &paa) == -1) err(3, "DRVSUSPENDDEV"); break; case 'd': strlcpy(daa.devname, argv[0], sizeof(daa.devname)); if (ioctl(fd, DRVDETACHDEV, &daa) == -1) err(3, "DRVDETACHDEV"); break; case 'l': strlcpy(laa.l_devname, argv[0], sizeof(laa.l_devname)); if (ioctl(fd, DRVLISTDEV, &laa) == -1) err(3, "DRVLISTDEV"); children = laa.l_children; laa.l_childname = malloc(children * sizeof(laa.l_childname[0])); if (laa.l_childname == NULL) err(5, "DRVLISTDEV"); if (ioctl(fd, DRVLISTDEV, &laa) == -1) err(3, "DRVLISTDEV"); if (laa.l_children > children) err(6, "DRVLISTDEV: number of children grew"); for (i = 0; i < laa.l_children; i++) printf("%s %s\n", laa.l_devname, laa.l_childname[i]); break; case 'r': memset(&raa, 0, sizeof(raa)); strlcpy(raa.busname, argv[0], sizeof(raa.busname)); if (attr) strlcpy(raa.ifattr, attr, sizeof(raa.ifattr)); if (argc > 1) { locs = malloc((argc - 1) * sizeof(int)); if (!locs) err(5, "malloc int[%d]", argc - 1); for (i = 0; i < argc - 1; i++) locs[i] = atoi(argv[i + 1]); raa.numlocators = argc - 1; raa.locators = locs; } if (ioctl(fd, DRVRESCANBUS, &raa) == -1) err(3, "DRVRESCANBUS"); break; case 'p': command_dict = prop_dictionary_create(); args_dict = prop_dictionary_create(); string = prop_string_create_cstring_nocopy("get-properties"); prop_dictionary_set(command_dict, "drvctl-command", string); prop_object_release(string); string = prop_string_create_cstring(argv[0]); prop_dictionary_set(args_dict, "device-name", string); prop_object_release(string); prop_dictionary_set(command_dict, "drvctl-arguments", args_dict); prop_object_release(args_dict); res = prop_dictionary_sendrecv_ioctl(command_dict, fd, DRVCTLCOMMAND, &results_dict); prop_object_release(command_dict); if (res) errx(3, "DRVCTLCOMMAND: %s", strerror(res)); number = prop_dictionary_get(results_dict, "drvctl-error"); if (prop_number_integer_value(number) != 0) { errx(3, "get-properties: %s", strerror((int)prop_number_integer_value(number))); } data_dict = prop_dictionary_get(results_dict, "drvctl-result-data"); if (data_dict == NULL) { errx(3, "get-properties: failed to return result data"); } xml = prop_dictionary_externalize(data_dict); prop_object_release(results_dict); printf("Properties for device `%s':\n%s", argv[0], xml); free(xml); break; default: errx(4, "unknown command"); } return (0); }
static bool slurp_battery_info(struct battery_info *batt_info, yajl_gen json_gen, char *buffer, int number, const char *path, const char *format_down) { char *outwalk = buffer; #if defined(LINUX) char buf[1024]; memset(buf, 0, 1024); const char *walk, *last; bool watt_as_unit = false; int voltage = -1; char batpath[512]; sprintf(batpath, path, number); INSTANCE(batpath); if (!slurp(batpath, buf, sizeof(buf))) { OUTPUT_FULL_TEXT(format_down); return false; } for (walk = buf, last = buf; (walk - buf) < 1024; walk++) { if (*walk == '\n') { last = walk + 1; continue; } if (*walk != '=') continue; if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_NOW=")) { watt_as_unit = true; batt_info->remaining = atoi(walk + 1); batt_info->percentage_remaining = -1; } else if (BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_NOW=")) { watt_as_unit = false; batt_info->remaining = atoi(walk + 1); batt_info->percentage_remaining = -1; } else if (BEGINS_WITH(last, "POWER_SUPPLY_CAPACITY=") && batt_info->remaining == -1) { batt_info->percentage_remaining = atoi(walk + 1); } else if (BEGINS_WITH(last, "POWER_SUPPLY_CURRENT_NOW=")) batt_info->present_rate = abs(atoi(walk + 1)); else if (BEGINS_WITH(last, "POWER_SUPPLY_VOLTAGE_NOW=")) voltage = abs(atoi(walk + 1)); /* on some systems POWER_SUPPLY_POWER_NOW does not exist, but actually * it is the same as POWER_SUPPLY_CURRENT_NOW but with μWh as * unit instead of μAh. We will calculate it as we need it * later. */ else if (BEGINS_WITH(last, "POWER_SUPPLY_POWER_NOW=")) batt_info->present_rate = abs(atoi(walk + 1)); else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Charging")) batt_info->status = CS_CHARGING; else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Full")) batt_info->status = CS_FULL; else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=Discharging")) batt_info->status = CS_DISCHARGING; else if (BEGINS_WITH(last, "POWER_SUPPLY_STATUS=")) batt_info->status = CS_UNKNOWN; else if (BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL_DESIGN=") || BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL_DESIGN=")) batt_info->full_design = atoi(walk + 1); else if (BEGINS_WITH(last, "POWER_SUPPLY_ENERGY_FULL=") || BEGINS_WITH(last, "POWER_SUPPLY_CHARGE_FULL=")) batt_info->full_last = atoi(walk + 1); } /* the difference between POWER_SUPPLY_ENERGY_NOW and * POWER_SUPPLY_CHARGE_NOW is the unit of measurement. The energy is * given in mWh, the charge in mAh. So calculate every value given in * ampere to watt */ if (!watt_as_unit && voltage >= 0) { if (batt_info->present_rate > 0) { batt_info->present_rate = (((float)voltage / 1000.0) * ((float)batt_info->present_rate / 1000.0)); } if (batt_info->remaining > 0) { batt_info->remaining = (((float)voltage / 1000.0) * ((float)batt_info->remaining / 1000.0)); } if (batt_info->full_design > 0) { batt_info->full_design = (((float)voltage / 1000.0) * ((float)batt_info->full_design / 1000.0)); } if (batt_info->full_last > 0) { batt_info->full_last = (((float)voltage / 1000.0) * ((float)batt_info->full_last / 1000.0)); } } #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) int state; int sysctl_rslt; size_t sysctl_size = sizeof(sysctl_rslt); if (sysctlbyname(BATT_LIFE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) { OUTPUT_FULL_TEXT(format_down); return false; } batt_info->percentage_remaining = sysctl_rslt; if (sysctlbyname(BATT_TIME, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) { OUTPUT_FULL_TEXT(format_down); return false; } batt_info->seconds_remaining = sysctl_rslt * 60; if (sysctlbyname(BATT_STATE, &sysctl_rslt, &sysctl_size, NULL, 0) != 0) { OUTPUT_FULL_TEXT(format_down); return false; } state = sysctl_rslt; if (state == 0 && batt_info->percentage_remaining == 100) batt_info->status = CS_FULL; else if ((state & ACPI_BATT_STAT_CHARGING) && batt_info->percentage_remaining < 100) batt_info->status = CS_CHARGING; else batt_info->status = CS_DISCHARGING; #elif defined(__OpenBSD__) /* * We're using apm(4) here, which is the interface to acpi(4) on amd64/i386 and * the generic interface on macppc/sparc64/zaurus, instead of using sysctl(3) and * probing acpi(4) devices. */ struct apm_power_info apm_info; int apm_fd; apm_fd = open("/dev/apm", O_RDONLY); if (apm_fd < 0) { OUTPUT_FULL_TEXT("can't open /dev/apm"); return false; } if (ioctl(apm_fd, APM_IOC_GETPOWER, &apm_info) < 0) OUTPUT_FULL_TEXT("can't read power info"); close(apm_fd); /* Don't bother to go further if there's no battery present. */ if ((apm_info.battery_state == APM_BATTERY_ABSENT) || (apm_info.battery_state == APM_BATT_UNKNOWN)) { OUTPUT_FULL_TEXT(format_down); return false; } switch (apm_info.ac_state) { case APM_AC_OFF: batt_info->status = CS_DISCHARGING; break; case APM_AC_ON: batt_info->status = CS_CHARGING; break; default: /* If we don't know what's going on, just assume we're discharging. */ batt_info->status = CS_DISCHARGING; break; } batt_info->percentage_remaining = apm_info.battery_life; /* Can't give a meaningful value for remaining minutes if we're charging. */ if (batt_info->status != CS_CHARGING) { batt_info->seconds_remaining = apm_info.minutes_left * 60; } #elif defined(__NetBSD__) /* * Using envsys(4) via sysmon(4). */ int fd, rval; bool is_found = false; char sensor_desc[16]; prop_dictionary_t dict; prop_array_t array; prop_object_iterator_t iter; prop_object_iterator_t iter2; prop_object_t obj, obj2, obj3, obj4, obj5; if (number >= 0) (void)snprintf(sensor_desc, sizeof(sensor_desc), "acpibat%d", number); fd = open("/dev/sysmon", O_RDONLY); if (fd < 0) { OUTPUT_FULL_TEXT("can't open /dev/sysmon"); return false; } rval = prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &dict); if (rval == -1) { close(fd); return false; } if (prop_dictionary_count(dict) == 0) { prop_object_release(dict); close(fd); return false; } iter = prop_dictionary_iterator(dict); if (iter == NULL) { prop_object_release(dict); close(fd); } /* iterate over the dictionary returned by the kernel */ while ((obj = prop_object_iterator_next(iter)) != NULL) { /* skip this dict if it's not what we're looking for */ if (number < 0) { /* we want all batteries */ if (!BEGINS_WITH(prop_dictionary_keysym_cstring_nocopy(obj), "acpibat")) continue; } else { /* we want a specific battery */ if (strcmp(sensor_desc, prop_dictionary_keysym_cstring_nocopy(obj)) != 0) continue; } is_found = true; array = prop_dictionary_get_keysym(dict, obj); if (prop_object_type(array) != PROP_TYPE_ARRAY) { prop_object_iterator_release(iter); prop_object_release(dict); close(fd); return false; } iter2 = prop_array_iterator(array); if (!iter2) { prop_object_iterator_release(iter); prop_object_release(dict); close(fd); return false; } struct battery_info batt_buf = { .full_design = 0, .full_last = 0, .remaining = 0, .present_rate = 0, .status = CS_UNKNOWN, }; int voltage = -1; bool watt_as_unit = false; /* iterate over array of dicts specific to target battery */ while ((obj2 = prop_object_iterator_next(iter2)) != NULL) { obj3 = prop_dictionary_get(obj2, "description"); if (obj3 == NULL) continue; if (strcmp("charging", prop_string_cstring_nocopy(obj3)) == 0) { obj3 = prop_dictionary_get(obj2, "cur-value"); if (prop_number_integer_value(obj3)) batt_buf.status = CS_CHARGING; else batt_buf.status = CS_DISCHARGING; } else if (strcmp("charge", prop_string_cstring_nocopy(obj3)) == 0) { obj3 = prop_dictionary_get(obj2, "cur-value"); obj4 = prop_dictionary_get(obj2, "max-value"); obj5 = prop_dictionary_get(obj2, "type"); batt_buf.remaining = prop_number_integer_value(obj3); batt_buf.full_design = prop_number_integer_value(obj4); if (strcmp("Ampere hour", prop_string_cstring_nocopy(obj5)) == 0) watt_as_unit = false; else watt_as_unit = true; } else if (strcmp("discharge rate", prop_string_cstring_nocopy(obj3)) == 0) { obj3 = prop_dictionary_get(obj2, "cur-value"); batt_buf.present_rate = prop_number_integer_value(obj3); } else if (strcmp("charge rate", prop_string_cstring_nocopy(obj3)) == 0) { obj3 = prop_dictionary_get(obj2, "cur-value"); batt_info->present_rate = prop_number_integer_value(obj3); } else if (strcmp("last full cap", prop_string_cstring_nocopy(obj3)) == 0) { obj3 = prop_dictionary_get(obj2, "cur-value"); batt_buf.full_last = prop_number_integer_value(obj3); } else if (strcmp("voltage", prop_string_cstring_nocopy(obj3)) == 0) { obj3 = prop_dictionary_get(obj2, "cur-value"); voltage = prop_number_integer_value(obj3); } } prop_object_iterator_release(iter2); if (!watt_as_unit && voltage != -1) { batt_buf.present_rate = (((float)voltage / 1000.0) * ((float)batt_buf.present_rate / 1000.0)); batt_buf.remaining = (((float)voltage / 1000.0) * ((float)batt_buf.remaining / 1000.0)); batt_buf.full_design = (((float)voltage / 1000.0) * ((float)batt_buf.full_design / 1000.0)); batt_buf.full_last = (((float)voltage / 1000.0) * ((float)batt_buf.full_last / 1000.0)); } if (batt_buf.remaining == batt_buf.full_design) batt_buf.status = CS_FULL; add_battery_info(batt_info, &batt_buf); } prop_object_iterator_release(iter); prop_object_release(dict); close(fd); if (!is_found) { OUTPUT_FULL_TEXT(format_down); return false; } batt_info->present_rate = abs(batt_info->present_rate); #endif return true; } /* * Populate batt_info with aggregate information about all batteries. * Returns false on error, and an error message will have been written. */ static bool slurp_all_batteries(struct battery_info *batt_info, yajl_gen json_gen, char *buffer, const char *path, const char *format_down) { #if defined(LINUX) char *outwalk = buffer; bool is_found = false; char *placeholder; char *globpath = sstrdup(path); if ((placeholder = strstr(path, "%d")) != NULL) { char *globplaceholder = globpath + (placeholder - path); *globplaceholder = '*'; strcpy(globplaceholder + 1, placeholder + 2); } if (!strcmp(globpath, path)) { OUTPUT_FULL_TEXT("no '%d' in battery path"); return false; } glob_t globbuf; if (glob(globpath, 0, NULL, &globbuf) == 0) { for (size_t i = 0; i < globbuf.gl_pathc; i++) { /* Probe to see if there is such a battery. */ struct battery_info batt_buf = { .full_design = 0, .full_last = 0, .remaining = 0, .present_rate = 0, .status = CS_UNKNOWN, }; if (!slurp_battery_info(&batt_buf, json_gen, buffer, i, globbuf.gl_pathv[i], format_down)) return false; is_found = true; add_battery_info(batt_info, &batt_buf); } } globfree(&globbuf); free(globpath); if (!is_found) { OUTPUT_FULL_TEXT(format_down); return false; } batt_info->present_rate = abs(batt_info->present_rate); #else /* FreeBSD and OpenBSD only report aggregates. NetBSD always * iterates through all batteries, so it's more efficient to * aggregate in slurp_battery_info. */ return slurp_battery_info(batt_info, json_gen, buffer, -1, path, format_down); #endif return true; } void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char *path, const char *format, const char *format_down, const char *status_chr, const char *status_bat, const char *status_unk, const char *status_full, int low_threshold, char *threshold_type, bool last_full_capacity, bool integer_battery_capacity, bool hide_seconds) { const char *walk; char *outwalk = buffer; struct battery_info batt_info = { .full_design = -1, .full_last = -1, .remaining = -1, .present_rate = -1, .seconds_remaining = -1, .percentage_remaining = -1, .status = CS_UNKNOWN, }; bool colorful_output = false; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__OpenBSD__) /* These OSes report battery stats in whole percent. */ integer_battery_capacity = true; #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__OpenBSD__) /* These OSes report battery time in minutes. */ hide_seconds = true; #endif if (number < 0) { if (!slurp_all_batteries(&batt_info, json_gen, buffer, path, format_down)) return; } else { if (!slurp_battery_info(&batt_info, json_gen, buffer, number, path, format_down)) return; } // *Choose* a measure of the 'full' battery. It is whichever is better of // the battery's (hardware-given) design capacity (batt_info.full_design) // and the battery's last known good charge (batt_info.full_last). // We prefer the design capacity, but use the last capacity if we don't have it, // or if we are asked to (last_full_capacity == true); but similarly we use // the design capacity if we don't have the last capacity. // If we don't have either then both full_design and full_last <= 0, // which implies full <= 0, which bails out on the following line. int full = batt_info.full_design; if (full <= 0 || (last_full_capacity && batt_info.full_last > 0)) { full = batt_info.full_last; } if (full <= 0 && batt_info.remaining < 0 && batt_info.percentage_remaining < 0) { /* We have no physical measurements and no estimates. Nothing * much we can report, then. */ OUTPUT_FULL_TEXT(format_down); return; } if (batt_info.percentage_remaining < 0) { batt_info.percentage_remaining = (((float)batt_info.remaining / (float)full) * 100); /* Some batteries report POWER_SUPPLY_CHARGE_NOW=<full_design> when fully * charged, even though that’s plainly wrong. For people who chose to see * the percentage calculated based on the last full capacity, we clamp the * value to 100%, as that makes more sense. * See http://bugs.debian.org/785398 */ if (last_full_capacity && batt_info.percentage_remaining > 100) { batt_info.percentage_remaining = 100; } } if (batt_info.seconds_remaining < 0 && batt_info.present_rate > 0 && batt_info.status != CS_FULL) { if (batt_info.status == CS_CHARGING) batt_info.seconds_remaining = 3600.0 * (full - batt_info.remaining) / batt_info.present_rate; else if (batt_info.status == CS_DISCHARGING) batt_info.seconds_remaining = 3600.0 * batt_info.remaining / batt_info.present_rate; else batt_info.seconds_remaining = 0; } if (batt_info.status == CS_DISCHARGING && low_threshold > 0) { if (batt_info.percentage_remaining >= 0 && strcasecmp(threshold_type, "percentage") == 0 && batt_info.percentage_remaining < low_threshold) { START_COLOR("color_bad"); colorful_output = true; } else if (batt_info.seconds_remaining >= 0 && strcasecmp(threshold_type, "time") == 0 && batt_info.seconds_remaining < 60 * low_threshold) { START_COLOR("color_bad"); colorful_output = true; } } #define EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT() \ do { \ if (outwalk == prevoutwalk) { \ if (outwalk > buffer && isspace((int)outwalk[-1])) \ outwalk--; \ else if (isspace((int)*(walk + 1))) \ walk++; \ } \ } while (0) for (walk = format; *walk != '\0'; walk++) { char *prevoutwalk = outwalk; if (*walk != '%') { *(outwalk++) = *walk; continue; } if (BEGINS_WITH(walk + 1, "status")) { const char *statusstr; switch (batt_info.status) { case CS_CHARGING: statusstr = status_chr; break; case CS_DISCHARGING: statusstr = status_bat; break; case CS_FULL: statusstr = status_full; break; default: statusstr = status_unk; } outwalk += sprintf(outwalk, "%s", statusstr); walk += strlen("status"); } else if (BEGINS_WITH(walk + 1, "percentage")) { if (integer_battery_capacity) { outwalk += sprintf(outwalk, "%.00f%s", batt_info.percentage_remaining, pct_mark); } else { outwalk += sprintf(outwalk, "%.02f%s", batt_info.percentage_remaining, pct_mark); } walk += strlen("percentage"); } else if (BEGINS_WITH(walk + 1, "remaining")) { if (batt_info.seconds_remaining >= 0) { int seconds, hours, minutes; hours = batt_info.seconds_remaining / 3600; seconds = batt_info.seconds_remaining - (hours * 3600); minutes = seconds / 60; seconds -= (minutes * 60); if (hide_seconds) outwalk += sprintf(outwalk, "%02d:%02d", max(hours, 0), max(minutes, 0)); else outwalk += sprintf(outwalk, "%02d:%02d:%02d", max(hours, 0), max(minutes, 0), max(seconds, 0)); } walk += strlen("remaining"); EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT(); } else if (BEGINS_WITH(walk + 1, "emptytime")) { if (batt_info.seconds_remaining >= 0) { time_t empty_time = time(NULL) + batt_info.seconds_remaining; set_timezone(NULL); /* Use local time. */ struct tm *empty_tm = localtime(&empty_time); if (hide_seconds) outwalk += sprintf(outwalk, "%02d:%02d", max(empty_tm->tm_hour, 0), max(empty_tm->tm_min, 0)); else outwalk += sprintf(outwalk, "%02d:%02d:%02d", max(empty_tm->tm_hour, 0), max(empty_tm->tm_min, 0), max(empty_tm->tm_sec, 0)); } walk += strlen("emptytime"); EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT(); } else if (BEGINS_WITH(walk + 1, "consumption")) { if (batt_info.present_rate >= 0) outwalk += sprintf(outwalk, "%1.2fW", batt_info.present_rate / 1e6); walk += strlen("consumption"); EAT_SPACE_FROM_OUTPUT_IF_NO_OUTPUT(); } } if (colorful_output) END_COLOR; OUTPUT_FULL_TEXT(buffer); }
/* ARGSUSED */ static void bcmemmc_attach(device_t parent, device_t self, void *aux) { struct bcmemmc_softc *sc = device_private(self); prop_dictionary_t dict = device_properties(self); struct amba_attach_args *aaa = aux; prop_number_t frequency; int error; sc->sc.sc_dev = self; sc->sc.sc_dmat = aaa->aaa_dmat; sc->sc.sc_flags = 0; sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS; sc->sc.sc_flags |= SDHC_FLAG_HOSTCAPS; sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT; sc->sc.sc_caps = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP | (SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT); sc->sc.sc_caps2 = SDHC_SDR50_SUPP; sc->sc.sc_host = sc->sc_hosts; sc->sc.sc_clkbase = 50000; /* Default to 50MHz */ sc->sc_iot = aaa->aaa_iot; /* Fetch the EMMC clock frequency from property if set. */ frequency = prop_dictionary_get(dict, "frequency"); if (frequency != NULL) { sc->sc.sc_clkbase = prop_number_integer_value(frequency) / 1000; } error = bus_space_map(sc->sc_iot, aaa->aaa_addr, aaa->aaa_size, 0, &sc->sc_ioh); if (error) { aprint_error_dev(self, "can't map registers for %s: %d\n", aaa->aaa_name, error); return; } sc->sc_ios = aaa->aaa_size; sc->sc_physaddr = aaa->aaa_addr; aprint_naive(": SDHC controller\n"); aprint_normal(": SDHC controller\n"); sc->sc_ih = intr_establish(aaa->aaa_intr, IPL_SDMMC, IST_LEVEL, sdhc_intr, &sc->sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "failed to establish interrupt %d\n", aaa->aaa_intr); goto fail; } aprint_normal_dev(self, "interrupting on intr %d\n", aaa->aaa_intr); #if NBCMDMAC > 0 sc->sc_dmac = bcm_dmac_alloc(BCM_DMAC_TYPE_NORMAL, IPL_SDMMC, bcmemmc_dma_done, sc); if (sc->sc_dmac == NULL) goto done; sc->sc.sc_flags |= SDHC_FLAG_USE_DMA; sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA; sc->sc.sc_caps |= SDHC_DMA_SUPPORT; sc->sc.sc_vendor_transfer_data_dma = bcmemmc_xfer_data_dma; sc->sc_state = EMMC_DMA_STATE_IDLE; cv_init(&sc->sc_cv, "bcmemmcdma"); int rseg; error = bus_dmamem_alloc(sc->sc.sc_dmat, PAGE_SIZE, PAGE_SIZE, PAGE_SIZE, sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK); if (error) { aprint_error_dev(self, "dmamem_alloc failed (%d)\n", error); goto fail; } error = bus_dmamem_map(sc->sc.sc_dmat, sc->sc_segs, rseg, PAGE_SIZE, (void **)&sc->sc_cblk, BUS_DMA_WAITOK); if (error) { aprint_error_dev(self, "dmamem_map failed (%d)\n", error); goto fail; } KASSERT(sc->sc_cblk != NULL); memset(sc->sc_cblk, 0, PAGE_SIZE); error = bus_dmamap_create(sc->sc.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0, BUS_DMA_WAITOK, &sc->sc_dmamap); if (error) { aprint_error_dev(self, "dmamap_create failed (%d)\n", error); goto fail; } error = bus_dmamap_load(sc->sc.sc_dmat, sc->sc_dmamap, sc->sc_cblk, PAGE_SIZE, NULL, BUS_DMA_WAITOK|BUS_DMA_WRITE); if (error) { aprint_error_dev(self, "dmamap_load failed (%d)\n", error); goto fail; } done: #endif config_interrupts(self, bcmemmc_attach_i); return; fail: /* XXX add bus_dma failure cleanup */ if (sc->sc_ih) { intr_disestablish(sc->sc_ih); sc->sc_ih = NULL; } bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); }
void udev_read_event(int fd) { struct pdev_array_entry *pae; prop_dictionary_t dict, evdict, devdict; prop_number_t pn; prop_string_t ps; prop_object_t po; prop_array_t pa; char *xml; int n, idx, evtype; size_t sz; sz = 4096 * 1024; xml = malloc(sz); /* 4 MB */ again: if ((n = read(fd, xml, sz)) <= 0) { if (errno == ENOMEM) { sz <<= 2; if ((xml = realloc(xml, sz)) == NULL) { syslog(LOG_ERR, "could not realloc xml memory"); return; } goto again; } free(xml); return; } dict = prop_dictionary_internalize(xml); free(xml); if (dict == NULL) { syslog(LOG_ERR, "internalization of xml failed"); return; } pn = prop_dictionary_get(dict, "evtype"); if (pn == NULL) { syslog(LOG_ERR, "read_event: no key evtype"); goto out; } evtype = prop_number_integer_value(pn); evdict = prop_dictionary_get(dict, "evdict"); if (evdict == NULL) { syslog(LOG_ERR, "read_event: no key evdict"); goto out; } switch (evtype) { case UDEV_EVENT_ATTACH: monitor_queue_event(dict); pae = pdev_array_entry_get_last(); pa = prop_array_copy(pae->pdev_array); pdev_array_entry_unref(pae); if (pa == NULL) goto out; prop_array_add(pa, evdict); pdev_array_entry_insert(pa); break; case UDEV_EVENT_DETACH: monitor_queue_event(dict); if ((devdict = find_dev_dict(-1, evdict, &idx)) == NULL) goto out; pae = pdev_array_entry_get_last(); pa = prop_array_copy(pae->pdev_array); pdev_array_entry_unref(pae); if (pa == NULL) goto out; prop_array_remove(pa, idx); pdev_array_entry_insert(pa); break; case UDEV_EV_KEY_UPDATE: if ((devdict = find_dev_dict(-1, evdict, NULL)) == NULL) goto out; if ((ps = prop_dictionary_get(evdict, "key")) == NULL) goto out; if ((po = prop_dictionary_get(evdict, "value")) == NULL) goto out; /* prop_object_retain(po); */ /* not necessary afaik */ prop_dictionary_set(devdict, prop_string_cstring_nocopy(ps), po); break; case UDEV_EV_KEY_REMOVE: if ((devdict = find_dev_dict(-1, evdict, NULL)) == NULL) goto out; if ((ps = prop_dictionary_get(evdict, "key")) == NULL) goto out; prop_dictionary_remove(devdict, prop_string_cstring_nocopy(ps)); break; default: syslog(LOG_ERR, "read_event: unknown evtype %d", evtype); } out: prop_object_release(dict); return; }