static int settunnel(prop_dictionary_t env, prop_dictionary_t oenv) { const struct paddr_prefix *srcpfx, *dstpfx; struct if_laddrreq req; prop_data_t srcdata, dstdata; srcdata = (prop_data_t)prop_dictionary_get(env, "tunsrc"); dstdata = (prop_data_t)prop_dictionary_get(env, "tundst"); if (srcdata == NULL || dstdata == NULL) { warnx("%s.%d", __func__, __LINE__); errno = ENOENT; return -1; } srcpfx = prop_data_data_nocopy(srcdata); dstpfx = prop_data_data_nocopy(dstdata); if (srcpfx->pfx_addr.sa_family != dstpfx->pfx_addr.sa_family) errx(EXIT_FAILURE, "source and destination address families do not match"); memset(&req, 0, sizeof(req)); memcpy(&req.addr, &srcpfx->pfx_addr, MIN(sizeof(req.addr), srcpfx->pfx_addr.sa_len)); memcpy(&req.dstaddr, &dstpfx->pfx_addr, MIN(sizeof(req.dstaddr), dstpfx->pfx_addr.sa_len)); #ifdef INET6 if (req.addr.ss_family == AF_INET6) { struct sockaddr_in6 *s6, *d; s6 = (struct sockaddr_in6 *)&req.addr; d = (struct sockaddr_in6 *)&req.dstaddr; if (s6->sin6_scope_id != d->sin6_scope_id) { errx(EXIT_FAILURE, "scope mismatch"); /* NOTREACHED */ } if (IN6_IS_ADDR_MULTICAST(&d->sin6_addr) || IN6_IS_ADDR_MULTICAST(&s6->sin6_addr)) errx(EXIT_FAILURE, "tunnel src/dst is multicast"); /* embed scopeid */ if (s6->sin6_scope_id && IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) { *(u_int16_t *)&s6->sin6_addr.s6_addr[2] = htons(s6->sin6_scope_id); } if (d->sin6_scope_id && IN6_IS_ADDR_LINKLOCAL(&d->sin6_addr)) { *(u_int16_t *)&d->sin6_addr.s6_addr[2] = htons(d->sin6_scope_id); } } #endif /* INET6 */ if (direct_ioctl(env, SIOCSLIFPHYADDR, &req) == -1) warn("SIOCSLIFPHYADDR"); return 0; }
/* * return appropriate mode for HID descriptor */ const char * hid_mode(prop_data_t desc) { report_desc_t r; hid_data_t d; struct hid_item h; const char *mode; hid_init(NULL); mode = BTDEVauth; /* default */ r = hid_use_report_desc(prop_data_data_nocopy(desc), prop_data_size(desc)); if (r == NULL) err(EXIT_FAILURE, "hid_use_report_desc"); d = hid_start_parse(r, ~0, -1); while (hid_get_item(d, &h) > 0) { if (h.kind == hid_collection && HID_PAGE(h.usage) == HUP_GENERIC_DESKTOP && HID_USAGE(h.usage) == HUG_KEYBOARD) mode = BTDEVencrypt; } hid_end_parse(d); hid_dispose_report_desc(r); return mode; }
static int __noinline npf_mk_ncode(prop_object_t obj, void **code, size_t *csize, prop_dictionary_t errdict) { const void *ncptr; int nc_err, errat; size_t nc_size; void *nc; /* * Allocate, copy and validate n-code. XXX: Inefficient. */ ncptr = prop_data_data_nocopy(obj); nc_size = prop_data_size(obj); if (ncptr == NULL || nc_size > NPF_NCODE_LIMIT) { NPF_ERR_DEBUG(errdict); return ERANGE; } nc = npf_ncode_alloc(nc_size); if (nc == NULL) { NPF_ERR_DEBUG(errdict); return ENOMEM; } memcpy(nc, ncptr, nc_size); nc_err = npf_ncode_validate(nc, nc_size, &errat); if (nc_err) { npf_ncode_free(nc, nc_size); prop_dictionary_set_int32(errdict, "ncode-error", nc_err); prop_dictionary_set_int32(errdict, "ncode-errat", errat); return EINVAL; } *code = nc; *csize = nc_size; return 0; }
static void epe_attach(device_t parent, device_t self, void *aux) { struct epe_softc *sc = device_private(self); struct epsoc_attach_args *sa; prop_data_t enaddr; aprint_normal("\n"); sa = aux; sc->sc_dev = self; sc->sc_iot = sa->sa_iot; sc->sc_intr = sa->sa_intr; sc->sc_dmat = sa->sa_dmat; if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh)) panic("%s: Cannot map registers", device_xname(self)); /* Fetch the Ethernet address from property if set. */ enaddr = prop_dictionary_get(device_properties(self), "mac-address"); if (enaddr != NULL) { KASSERT(prop_object_type(enaddr) == PROP_TYPE_DATA); KASSERT(prop_data_size(enaddr) == ETHER_ADDR_LEN); memcpy(sc->sc_enaddr, prop_data_data_nocopy(enaddr), ETHER_ADDR_LEN); bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPE_AFP, 0); bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, EPE_IndAd, sc->sc_enaddr, ETHER_ADDR_LEN); } ep93xx_intr_establish(sc->sc_intr, IPL_NET, epe_intr, sc); epe_init(sc); }
static int __noinline npf_mk_table_entries(npf_table_t *t, prop_array_t entries) { prop_object_iterator_t eit; prop_dictionary_t ent; int error = 0; if (prop_object_type(entries) != PROP_TYPE_ARRAY) { return EINVAL; } eit = prop_array_iterator(entries); while ((ent = prop_object_iterator_next(eit)) != NULL) { const npf_addr_t *addr; npf_netmask_t mask; int alen; /* Get address and mask. Add a table entry. */ prop_object_t obj = prop_dictionary_get(ent, "addr"); addr = (const npf_addr_t *)prop_data_data_nocopy(obj); prop_dictionary_get_uint8(ent, "mask", &mask); alen = prop_data_size(obj); error = npf_table_insert(t, alen, addr, mask); if (error) break; } prop_object_iterator_release(eit); return error; }
static int __noinline npf_mk_code(prop_object_t obj, int type, void **code, size_t *csize, prop_dictionary_t errdict) { const void *cptr; size_t clen; void *bc; if (type != NPF_CODE_BPF) { return ENOTSUP; } cptr = prop_data_data_nocopy(obj); if (cptr == NULL || (clen = prop_data_size(obj)) == 0) { NPF_ERR_DEBUG(errdict); return EINVAL; } if (!npf_bpf_validate(cptr, clen)) { NPF_ERR_DEBUG(errdict); return EINVAL; } bc = kmem_alloc(clen, KM_SLEEP); memcpy(bc, cptr, clen); *code = bc; *csize = clen; return 0; }
const void * npf_rule_getinfo(nl_rule_t *rl, size_t *len) { prop_dictionary_t rldict = rl->nrl_dict; prop_object_t obj = prop_dictionary_get(rldict, "info"); *len = prop_data_size(obj); return prop_data_data_nocopy(obj); }
void npf_nat_getmap(nl_nat_t *nt, npf_addr_t *addr, size_t *alen, in_port_t *port) { prop_dictionary_t rldict = nt->nrl_dict; prop_object_t obj = prop_dictionary_get(rldict, "translation-ip"); *alen = prop_data_size(obj); memcpy(addr, prop_data_data_nocopy(obj), *alen); *port = 0; prop_dictionary_get_uint16(rldict, "translation-port", port); }
static void emac_attach(device_t parent, device_t self, void *aux) { struct emac_softc *sc = device_private(self); struct at91bus_attach_args *sa = aux; prop_data_t enaddr; uint32_t u; printf("\n"); sc->sc_dev = self; sc->sc_iot = sa->sa_iot; sc->sc_pid = sa->sa_pid; sc->sc_dmat = sa->sa_dmat; if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh)) panic("%s: Cannot map registers", device_xname(self)); /* enable peripheral clock */ at91_peripheral_clock(sc->sc_pid, 1); /* configure emac: */ EMAC_WRITE(ETH_CTL, 0); // disable everything EMAC_WRITE(ETH_IDR, -1); // disable interrupts EMAC_WRITE(ETH_RBQP, 0); // clear receive EMAC_WRITE(ETH_CFG, ETH_CFG_CLK_32 | ETH_CFG_SPD | ETH_CFG_FD | ETH_CFG_BIG); EMAC_WRITE(ETH_TCR, 0); // send nothing //(void)EMAC_READ(ETH_ISR); u = EMAC_READ(ETH_TSR); EMAC_WRITE(ETH_TSR, (u & (ETH_TSR_UND | ETH_TSR_COMP | ETH_TSR_BNQ | ETH_TSR_IDLE | ETH_TSR_RLE | ETH_TSR_COL|ETH_TSR_OVR))); u = EMAC_READ(ETH_RSR); EMAC_WRITE(ETH_RSR, (u & (ETH_RSR_OVR|ETH_RSR_REC|ETH_RSR_BNA))); /* Fetch the Ethernet address from property if set. */ enaddr = prop_dictionary_get(device_properties(self), "mac-addr"); if (enaddr != NULL) { KASSERT(prop_object_type(enaddr) == PROP_TYPE_DATA); KASSERT(prop_data_size(enaddr) == ETHER_ADDR_LEN); memcpy(sc->sc_enaddr, prop_data_data_nocopy(enaddr), ETHER_ADDR_LEN); } else { static const uint8_t hardcoded[ETHER_ADDR_LEN] = { 0x00, 0x0d, 0x10, 0x81, 0x0c, 0x94 }; memcpy(sc->sc_enaddr, hardcoded, ETHER_ADDR_LEN); } at91_intr_establish(sc->sc_pid, IPL_NET, INTR_HIGH_LEVEL, emac_intr, sc); emac_init(sc); }
ssize_t getargstr(prop_dictionary_t env, const char *key, char *buf, size_t buflen) { prop_data_t data; size_t datalen; data = (prop_data_t)prop_dictionary_get(env, key); if (data == NULL) { errno = ENOENT; return -1; } datalen = prop_data_size(data); if (datalen >= buflen) { errno = ENAMETOOLONG; return -1; } memset(buf, 0, buflen); memcpy(buf, prop_data_data_nocopy(data), datalen); return datalen; }
int wsdisplayio_get_edid(device_t dev, struct wsdisplayio_edid_info *d) { prop_data_t edid_data; int edid_size; edid_data = prop_dictionary_get(device_properties(dev), "EDID"); if (edid_data != NULL) { edid_size = prop_data_size(edid_data); /* less than 128 bytes is bogus */ if (edid_size < 128) return ENODEV; d->data_size = edid_size; if (d->buffer_size < edid_size) return EAGAIN; return copyout(prop_data_data_nocopy(edid_data), d->edid_data, edid_size); } return ENODEV; }
/* ARGSUSED */ static void smsh_axi_attach(device_t parent, device_t self, void *aux) { struct lan9118_softc *sc = device_private(self); struct axi_attach_args *aa = aux; prop_dictionary_t dict = device_properties(self); void *ih; sc->sc_dev = self; /* * Prefer the Ethernet address in device properties. */ prop_data_t ea = prop_dictionary_get(dict, "mac-address"); if (ea != NULL) { KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); memcpy(sc->sc_enaddr, prop_data_data_nocopy(ea), ETHER_ADDR_LEN); sc->sc_flags |= LAN9118_FLAGS_NO_EEPROM; } /* Map i/o space. */ if (bus_space_map(aa->aa_iot, aa->aa_addr, LAN9118_IOSIZE, 0, &sc->sc_ioh)) panic("smsh_axi_attach: can't map i/o space"); sc->sc_iot = aa->aa_iot; if (lan9118_attach(sc) != 0) { bus_space_unmap(sc->sc_iot, sc->sc_ioh, LAN9118_IOSIZE); return; } /* Establish the interrupt handler. */ ih = intr_establish(aa->aa_irq, IPL_NET, IST_LEVEL, lan9118_intr, sc); if (ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt handler\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, LAN9118_IOSIZE); return; } }
int setcarp_passwd(prop_dictionary_t env, prop_dictionary_t oenv) { struct carpreq carpr; prop_data_t data; data = (prop_data_t)prop_dictionary_get(env, "pass"); if (data == NULL) { errno = ENOENT; return -1; } carp_get(env, &carpr); memset(carpr.carpr_key, 0, sizeof(carpr.carpr_key)); /* XXX Should hash the password into the key here, perhaps? */ strlcpy((char *)carpr.carpr_key, prop_data_data_nocopy(data), MIN(CARP_KEY_LEN, prop_data_size(data))); carp_set(env, &carpr); return 0; }
static int bthub_print(void *aux, const char *pnp) { prop_dictionary_t dict = aux; prop_object_t obj; const bdaddr_t *raddr; if (pnp != NULL) { obj = prop_dictionary_get(dict, BTDEVtype); aprint_normal("%s: %s '%s',", pnp, BTDEVtype, prop_string_cstring_nocopy(obj)); } obj = prop_dictionary_get(dict, BTDEVraddr); raddr = prop_data_data_nocopy(obj); aprint_verbose(" %s %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", BTDEVraddr, raddr->b[5], raddr->b[4], raddr->b[3], raddr->b[2], raddr->b[1], raddr->b[0]); return UNCONF; }
static int bthub_pioctl(dev_t devno, unsigned long cmd, prop_dictionary_t dict, int flag, struct lwp *l) { prop_data_t laddr, raddr; prop_string_t service; prop_dictionary_t prop; prop_object_t obj; device_t dev, self; deviter_t di; int unit; /* validate local address */ laddr = prop_dictionary_get(dict, BTDEVladdr); if (prop_data_size(laddr) != sizeof(bdaddr_t)) return EINVAL; /* locate the relevant bthub */ for (unit = 0 ; ; unit++) { if (unit == bthub_cd.cd_ndevs) return ENXIO; self = device_lookup(&bthub_cd, unit); if (self == NULL) continue; prop = device_properties(self); obj = prop_dictionary_get(prop, BTDEVladdr); if (prop_data_equals(laddr, obj)) break; } /* validate remote address */ raddr = prop_dictionary_get(dict, BTDEVraddr); if (prop_data_size(raddr) != sizeof(bdaddr_t) || bdaddr_any(prop_data_data_nocopy(raddr))) return EINVAL; /* validate service name */ service = prop_dictionary_get(dict, BTDEVservice); if (prop_object_type(service) != PROP_TYPE_STRING) return EINVAL; /* locate matching child device, if any */ deviter_init(&di, 0); while ((dev = deviter_next(&di)) != NULL) { if (device_parent(dev) != self) continue; prop = device_properties(dev); obj = prop_dictionary_get(prop, BTDEVraddr); if (!prop_object_equals(raddr, obj)) continue; obj = prop_dictionary_get(prop, BTDEVservice); if (!prop_object_equals(service, obj)) continue; break; } deviter_release(&di); switch (cmd) { case BTDEV_ATTACH: /* attach BTDEV */ if (dev != NULL) return EADDRINUSE; dev = config_found(self, dict, bthub_print); if (dev == NULL) return ENXIO; prop = device_properties(dev); prop_dictionary_set(prop, BTDEVladdr, laddr); prop_dictionary_set(prop, BTDEVraddr, raddr); prop_dictionary_set(prop, BTDEVservice, service); break; case BTDEV_DETACH: /* detach BTDEV */ if (dev == NULL) return ENXIO; config_detach(dev, DETACH_FORCE); break; } return 0; }
/* * ae_attach: * * Attach an ae interface to the system. */ void ae_attach(device_t parent, device_t self, void *aux) { const uint8_t *enaddr; prop_data_t ea; struct ae_softc *sc = device_private(self); struct arbus_attach_args *aa = aux; struct ifnet *ifp = &sc->sc_ethercom.ec_if; int i, error; sc->sc_dev = self; callout_init(&sc->sc_tick_callout, 0); printf(": Atheros AR531X 10/100 Ethernet\n"); /* * Try to get MAC address. */ ea = prop_dictionary_get(device_properties(sc->sc_dev), "mac-address"); if (ea == NULL) { printf("%s: unable to get mac-addr property\n", device_xname(sc->sc_dev)); return; } KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); enaddr = prop_data_data_nocopy(ea); /* Announce ourselves. */ printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev), ether_sprintf(enaddr)); sc->sc_cirq = aa->aa_cirq; sc->sc_mirq = aa->aa_mirq; sc->sc_st = aa->aa_bst; sc->sc_dmat = aa->aa_dmat; SIMPLEQ_INIT(&sc->sc_txfreeq); SIMPLEQ_INIT(&sc->sc_txdirtyq); /* * Map registers. */ sc->sc_size = aa->aa_size; if ((error = bus_space_map(sc->sc_st, aa->aa_addr, sc->sc_size, 0, &sc->sc_sh)) != 0) { printf("%s: unable to map registers, error = %d\n", device_xname(sc->sc_dev), error); goto fail_0; } /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct ae_control_data), PAGE_SIZE, 0, &sc->sc_cdseg, 1, &sc->sc_cdnseg, 0)) != 0) { printf("%s: unable to allocate control data, error = %d\n", device_xname(sc->sc_dev), error); goto fail_1; } if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg, sizeof(struct ae_control_data), (void **)&sc->sc_control_data, BUS_DMA_COHERENT)) != 0) { printf("%s: unable to map control data, error = %d\n", device_xname(sc->sc_dev), error); goto fail_2; } if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct ae_control_data), 1, sizeof(struct ae_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { printf("%s: unable to create control data DMA map, " "error = %d\n", device_xname(sc->sc_dev), error); goto fail_3; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct ae_control_data), NULL, 0)) != 0) { printf("%s: unable to load control data DMA map, error = %d\n", device_xname(sc->sc_dev), error); goto fail_4; } /* * Create the transmit buffer DMA maps. */ for (i = 0; i < AE_TXQUEUELEN; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, AE_NTXSEGS, MCLBYTES, 0, 0, &sc->sc_txsoft[i].txs_dmamap)) != 0) { printf("%s: unable to create tx DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); goto fail_5; } } /* * Create the receive buffer DMA maps. */ for (i = 0; i < AE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { printf("%s: unable to create rx DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); goto fail_6; } sc->sc_rxsoft[i].rxs_mbuf = NULL; } /* * Reset the chip to a known state. */ ae_reset(sc); /* * From this point forward, the attachment cannot fail. A failure * before this point releases all resources that may have been * allocated. */ sc->sc_flags |= AE_ATTACHED; /* * Initialize our media structures. This may probe the MII, if * present. */ sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = ae_mii_readreg; sc->sc_mii.mii_writereg = ae_mii_writereg; sc->sc_mii.mii_statchg = ae_mii_statchg; sc->sc_ethercom.ec_mii = &sc->sc_mii; ifmedia_init(&sc->sc_mii.mii_media, 0, ether_mediachange, ether_mediastatus); mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); sc->sc_tick = ae_mii_tick; strcpy(ifp->if_xname, device_xname(sc->sc_dev)); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; sc->sc_if_flags = ifp->if_flags; ifp->if_ioctl = ae_ioctl; ifp->if_start = ae_start; ifp->if_watchdog = ae_watchdog; ifp->if_init = ae_init; ifp->if_stop = ae_stop; IFQ_SET_READY(&ifp->if_snd); /* * We can support 802.1Q VLAN-sized frames. */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; /* * Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, ae_ifflags_cb); rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev), RND_TYPE_NET, RND_FLAG_DEFAULT); /* * Make sure the interface is shutdown during reboot. */ sc->sc_sdhook = shutdownhook_establish(ae_shutdown, sc); if (sc->sc_sdhook == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", device_xname(sc->sc_dev)); /* * Add a suspend hook to make sure we come back up after a * resume. */ sc->sc_powerhook = powerhook_establish(device_xname(sc->sc_dev), ae_power, sc); if (sc->sc_powerhook == NULL) printf("%s: WARNING: unable to establish power hook\n", device_xname(sc->sc_dev)); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: for (i = 0; i < AE_NRXDESC; i++) { if (sc->sc_rxsoft[i].rxs_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxsoft[i].rxs_dmamap); } fail_5: for (i = 0; i < AE_TXQUEUELEN; i++) { if (sc->sc_txsoft[i].txs_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_txsoft[i].txs_dmamap); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); fail_4: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); fail_3: bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, sizeof(struct ae_control_data)); fail_2: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg); fail_1: bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_size); fail_0: return; }
static int __noinline npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t tbldict; int error = 0; /* Tables - array. */ if (prop_object_type(tables) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } it = prop_array_iterator(tables); while ((tbldict = prop_object_iterator_next(it)) != NULL) { prop_dictionary_t ent; prop_object_iterator_t eit; prop_array_t entries; npf_table_t *t; u_int tid; int type; /* Table - dictionary. */ if (prop_object_type(tbldict) != PROP_TYPE_DICTIONARY) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } /* Table ID and type. */ prop_dictionary_get_uint32(tbldict, "id", &tid); prop_dictionary_get_int32(tbldict, "type", &type); /* Validate them, check for duplicate IDs. */ error = npf_table_check(tblset, tid, type); if (error) break; /* Create and insert the table. */ t = npf_table_create(tid, type, 1024); /* XXX */ if (t == NULL) { NPF_ERR_DEBUG(errdict); error = ENOMEM; break; } error = npf_tableset_insert(tblset, t); KASSERT(error == 0); /* Entries. */ entries = prop_dictionary_get(tbldict, "entries"); if (prop_object_type(entries) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } eit = prop_array_iterator(entries); while ((ent = prop_object_iterator_next(eit)) != NULL) { const npf_addr_t *addr; npf_netmask_t mask; int alen; /* Get address and mask. Add a table entry. */ prop_object_t obj = prop_dictionary_get(ent, "addr"); addr = (const npf_addr_t *)prop_data_data_nocopy(obj); prop_dictionary_get_uint8(ent, "mask", &mask); alen = prop_data_size(obj); error = npf_table_insert(tblset, tid, alen, addr, mask); if (error) break; } prop_object_iterator_release(eit); if (error) break; } prop_object_iterator_release(it); /* * Note: in a case of error, caller will free the tableset. */ return error; }
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); }
static void tlp_pci_attach(device_t parent, device_t self, void *aux) { struct tulip_pci_softc *psc = device_private(self); struct tulip_softc *sc = &psc->sc_tulip; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; int ioh_valid, memh_valid, i, j; const struct tulip_pci_product *tpp; prop_data_t ea; uint8_t enaddr[ETHER_ADDR_LEN]; uint32_t val = 0; pcireg_t reg; int error; bus_size_t iosize = 0, memsize = 0; sc->sc_dev = self; sc->sc_devno = pa->pa_device; psc->sc_pc = pa->pa_pc; psc->sc_pcitag = pa->pa_tag; LIST_INIT(&psc->sc_intrslaves); tpp = tlp_pci_lookup(pa); if (tpp == NULL) { printf("\n"); panic("tlp_pci_attach: impossible"); } sc->sc_chip = tpp->tpp_chip; /* * By default, Tulip registers are 8 bytes long (4 bytes * followed by a 4 byte pad). */ sc->sc_regshift = 3; /* * No power management hooks. * XXX Maybe we should add some! */ sc->sc_flags |= TULIPF_ENABLED; /* * Get revision info, and set some chip-specific variables. */ sc->sc_rev = PCI_REVISION(pa->pa_class); switch (sc->sc_chip) { case TULIP_CHIP_21140: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_21140A; break; case TULIP_CHIP_21142: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_21143; break; case TULIP_CHIP_82C168: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_82C169; break; case TULIP_CHIP_MX98713: if (sc->sc_rev >= 0x10) sc->sc_chip = TULIP_CHIP_MX98713A; break; case TULIP_CHIP_MX98715: if (sc->sc_rev >= 0x20) sc->sc_chip = TULIP_CHIP_MX98715A; if (sc->sc_rev >= 0x25) sc->sc_chip = TULIP_CHIP_MX98715AEC_X; if (sc->sc_rev >= 0x30) sc->sc_chip = TULIP_CHIP_MX98725; break; case TULIP_CHIP_WB89C840F: sc->sc_regshift = 2; break; case TULIP_CHIP_AN985: /* * The AN983 and AN985 are very similar, and are * differentiated by a "signature" register that * is like, but not identical, to a PCI ID register. */ reg = pci_conf_read(pc, pa->pa_tag, 0x80); switch (reg) { case 0x09811317: sc->sc_chip = TULIP_CHIP_AN985; break; case 0x09851317: sc->sc_chip = TULIP_CHIP_AN983; break; default: /* Unknown -- use default. */ break; } break; case TULIP_CHIP_AX88140: if (sc->sc_rev >= 0x10) sc->sc_chip = TULIP_CHIP_AX88141; break; case TULIP_CHIP_DM9102: if (sc->sc_rev >= 0x30) sc->sc_chip = TULIP_CHIP_DM9102A; break; default: /* Nothing. */ break; } aprint_normal(": %s Ethernet, pass %d.%d\n", tlp_chip_name(sc->sc_chip), (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf); switch (sc->sc_chip) { case TULIP_CHIP_21040: if (sc->sc_rev < 0x20) { aprint_normal_dev(self, "21040 must be at least pass 2.0\n"); return; } break; case TULIP_CHIP_21140: if (sc->sc_rev < 0x11) { aprint_normal_dev(self, "21140 must be at least pass 1.1\n"); return; } break; default: /* Nothing. */ break; } /* * Check to see if the device is in power-save mode, and * being it out if necessary. */ switch (sc->sc_chip) { case TULIP_CHIP_21140: case TULIP_CHIP_21140A: case TULIP_CHIP_21142: case TULIP_CHIP_21143: case TULIP_CHIP_MX98713A: case TULIP_CHIP_MX98715: case TULIP_CHIP_MX98715A: case TULIP_CHIP_MX98715AEC_X: case TULIP_CHIP_MX98725: case TULIP_CHIP_DM9102: case TULIP_CHIP_DM9102A: case TULIP_CHIP_AX88140: case TULIP_CHIP_AX88141: case TULIP_CHIP_RS7112: /* * Clear the "sleep mode" bit in the CFDA register. */ reg = pci_conf_read(pc, pa->pa_tag, TULIP_PCI_CFDA); if (reg & (CFDA_SLEEP|CFDA_SNOOZE)) pci_conf_write(pc, pa->pa_tag, TULIP_PCI_CFDA, reg & ~(CFDA_SLEEP|CFDA_SNOOZE)); break; default: /* Nothing. */ break; } /* power up chip */ if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, NULL)) && error != EOPNOTSUPP) { aprint_error_dev(self, "cannot activate %d\n", error); return; } /* * Map the device. */ ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, &iosize) == 0); memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, &memsize) == 0); if (memh_valid) { sc->sc_st = memt; sc->sc_sh = memh; psc->sc_mapsize = memsize; if (ioh_valid) { bus_space_unmap(iot, ioh, iosize); ioh_valid = 0; } } else if (ioh_valid) { sc->sc_st = iot; sc->sc_sh = ioh; psc->sc_mapsize = iosize; if (memh_valid) { bus_space_unmap(memt, memh, memsize); memh_valid = 0; } } else { aprint_error_dev(self, "unable to map device registers\n"); goto fail; } sc->sc_dmat = pa->pa_dmat; /* * Make sure bus mastering is enabled. */ pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE); /* * Get the cacheline size. */ sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag, PCI_BHLC_REG)); /* * Get PCI data moving command info. */ if (pa->pa_flags & PCI_FLAGS_MRL_OKAY) sc->sc_flags |= TULIPF_MRL; if (pa->pa_flags & PCI_FLAGS_MRM_OKAY) sc->sc_flags |= TULIPF_MRM; if (pa->pa_flags & PCI_FLAGS_MWI_OKAY) sc->sc_flags |= TULIPF_MWI; /* * Read the contents of the Ethernet Address ROM/SROM. */ switch (sc->sc_chip) { case TULIP_CHIP_21040: sc->sc_srom_addrbits = 6; sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT); TULIP_WRITE(sc, CSR_MIIROM, MIIROM_SROMCS); for (i = 0; i < TULIP_ROM_SIZE(6); i++) { for (j = 0; j < 10000; j++) { val = TULIP_READ(sc, CSR_MIIROM); if ((val & MIIROM_DN) == 0) break; } sc->sc_srom[i] = val & MIIROM_DATA; } break; case TULIP_CHIP_82C168: case TULIP_CHIP_82C169: { sc->sc_srom_addrbits = 2; sc->sc_srom = malloc(TULIP_ROM_SIZE(2), M_DEVBUF, M_NOWAIT); /* * The Lite-On PNIC stores the Ethernet address in * the first 3 words of the EEPROM. EEPROM access * is not like the other Tulip chips. */ for (i = 0; i < 6; i += 2) { TULIP_WRITE(sc, CSR_PNIC_SROMCTL, PNIC_SROMCTL_READ | (i >> 1)); for (j = 0; j < 500; j++) { delay(2); val = TULIP_READ(sc, CSR_MIIROM); if ((val & PNIC_MIIROM_BUSY) == 0) break; } if (val & PNIC_MIIROM_BUSY) { aprint_error_dev(self, "EEPROM timed out\n"); goto fail; } val &= PNIC_MIIROM_DATA; sc->sc_srom[i] = val >> 8; sc->sc_srom[i + 1] = val & 0xff; } break; } default: /* * XXX This isn't quite the right way to do this; we should * XXX be attempting to fetch the mac-addr property in the * XXX bus-agnostic part of the driver independently. But * XXX that requires a larger change in the SROM handling * XXX logic, and for now we can at least remove a machine- * XXX dependent wart from the PCI front-end. */ ea = prop_dictionary_get(device_properties(self), "mac-address"); if (ea != NULL) { extern int tlp_srom_debug; KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); memcpy(enaddr, prop_data_data_nocopy(ea), ETHER_ADDR_LEN); sc->sc_srom_addrbits = 6; sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT|M_ZERO); memcpy(sc->sc_srom, enaddr, sizeof(enaddr)); if (tlp_srom_debug) { aprint_normal("SROM CONTENTS:"); for (i = 0; i < TULIP_ROM_SIZE(6); i++) { if ((i % 8) == 0) aprint_normal("\n\t"); aprint_normal("0x%02x ", sc->sc_srom[i]); } aprint_normal("\n"); } break; } /* Check for a slaved ROM on a multi-port board. */ tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDROM, TULIP_PCI_SLAVEROM); if (psc->sc_flags & TULIP_PCI_SLAVEROM) { sc->sc_srom_addrbits = psc->sc_master->sc_tulip.sc_srom_addrbits; sc->sc_srom = psc->sc_master->sc_tulip.sc_srom; enaddr[5] += sc->sc_devno - psc->sc_master->sc_tulip.sc_devno; } else if (tlp_read_srom(sc) == 0) goto cant_cope; break; } /* * Deal with chip/board quirks. This includes setting up * the mediasw, and extracting the Ethernet address from * the rombuf. */ switch (sc->sc_chip) { case TULIP_CHIP_21040: /* * Parse the Ethernet Address ROM. */ if (tlp_parse_old_srom(sc, enaddr) == 0) goto cant_cope; /* * All 21040 boards start out with the same * media switch. */ sc->sc_mediasw = &tlp_21040_mediasw; /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21040_quirks); break; case TULIP_CHIP_21041: /* Check for new format SROM. */ if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { /* * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ if (tlp_parse_old_srom(sc, enaddr) == 0) goto cant_cope; } /* * All 21041 boards use the same media switch; they all * work basically the same! Yippee! */ sc->sc_mediasw = &tlp_21041_mediasw; /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21041_quirks); break; case TULIP_CHIP_21140: case TULIP_CHIP_21140A: /* Check for new format SROM. */ if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { /* * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ if (tlp_parse_old_srom(sc, enaddr) == 0) goto cant_cope; } else { /* * We start out with the 2114x ISV media switch. * When we search for quirks, we may change to * a different switch. */ sc->sc_mediasw = &tlp_2114x_isv_mediasw; } /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21140_quirks); /* * Bail out now if we can't deal with this board. */ if (sc->sc_mediasw == NULL) goto cant_cope; break; case TULIP_CHIP_21142: case TULIP_CHIP_21143: /* Check for new format SROM. */ if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { /* * Not an ISV SROM; try the old DEC Ethernet Address * ROM format. */ if (tlp_parse_old_srom(sc, enaddr) == 0) { /* * One last try: just copy the address * from offset 20 and try to look * up quirks. */ memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); } } else { /* * We start out with the 2114x ISV media switch. * When we search for quirks, we may change to * a different switch. */ sc->sc_mediasw = &tlp_2114x_isv_mediasw; } /* * Deal with any quirks this board might have. */ tlp_pci_get_quirks(psc, enaddr, tlp_pci_21142_quirks); /* * Bail out now if we can't deal with this board. */ if (sc->sc_mediasw == NULL) goto cant_cope; break; case TULIP_CHIP_82C168: case TULIP_CHIP_82C169: /* * Lite-On PNIC's Ethernet address is the first 6 * bytes of its EEPROM. */ memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); /* * Lite-On PNICs always use the same mediasw; we * select MII vs. internal NWAY automatically. */ sc->sc_mediasw = &tlp_pnic_mediasw; break; case TULIP_CHIP_MX98713: /* * The Macronix MX98713 has an MII and GPIO, but no * internal Nway block. This chip is basically a * perfect 21140A clone, with the exception of the * a magic register frobbing in order to make the * interface function. */ if (tlp_isv_srom_enaddr(sc, enaddr)) { sc->sc_mediasw = &tlp_2114x_isv_mediasw; break; } /* FALLTHROUGH */ case TULIP_CHIP_82C115: /* * Yippee! The Lite-On 82C115 is a clone of * the MX98725 (the data sheet even says `MXIC' * on it)! Imagine that, a clone of a clone. * * The differences are really minimal: * * - Wake-On-LAN support * - 128-bit multicast hash table, rather than * the standard 512-bit hash table */ /* FALLTHROUGH */ case TULIP_CHIP_MX98713A: case TULIP_CHIP_MX98715A: case TULIP_CHIP_MX98715AEC_X: case TULIP_CHIP_MX98725: /* * The MX98713A has an MII as well as an internal Nway block, * but no GPIO. The MX98715 and MX98725 have an internal * Nway block only. * * The internal Nway block, unlike the Lite-On PNIC's, does * just that - performs Nway. Once autonegotiation completes, * we must program the GPR media information into the chip. * * The byte offset of the Ethernet address is stored at * offset 0x70. */ memcpy(enaddr, &sc->sc_srom[sc->sc_srom[0x70]], ETHER_ADDR_LEN); sc->sc_mediasw = &tlp_pmac_mediasw; break; case TULIP_CHIP_WB89C840F: /* * Winbond 89C840F's Ethernet address is the first * 6 bytes of its EEPROM. */ memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); /* * Winbond 89C840F has an MII attached to the SIO. */ sc->sc_mediasw = &tlp_sio_mii_mediasw; break; case TULIP_CHIP_AL981: /* * The ADMtek AL981's Ethernet address is located * at offset 8 of its EEPROM. */ memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); /* * ADMtek AL981 has a built-in PHY accessed through * special registers. */ sc->sc_mediasw = &tlp_al981_mediasw; break; case TULIP_CHIP_AN983: case TULIP_CHIP_AN985: /* * The ADMtek AN985's Ethernet address is located * at offset 8 of its EEPROM. */ memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); /* * The ADMtek AN985 can be configured in Single-Chip * mode or MAC-only mode. Single-Chip uses the built-in * PHY, MAC-only has an external PHY (usually HomePNA). * The selection is based on an EEPROM setting, and both * PHYs are accessed via MII attached to SIO. * * The AN985 "ghosts" the internal PHY onto all * MII addresses, so we have to use a media init * routine that limits the search. * XXX How does this work with MAC-only mode? */ sc->sc_mediasw = &tlp_an985_mediasw; break; case TULIP_CHIP_DM9102: case TULIP_CHIP_DM9102A: /* * Some boards with the Davicom chip have an ISV * SROM (mostly DM9102A boards -- trying to describe * the HomePNA PHY, probably) although the data in * them is generally wrong. Check for ISV format * and grab the Ethernet address that way, and if * that fails, fall back on grabbing it from an * observed offset of 20 (which is where it would * be in an ISV SROM anyhow, tho ISV can cope with * multi-port boards). */ if (!tlp_isv_srom_enaddr(sc, enaddr)) { prop_data_t eaddrprop; eaddrprop = prop_dictionary_get( device_properties(self), "mac-address"); if (eaddrprop != NULL && prop_data_size(eaddrprop) == ETHER_ADDR_LEN) memcpy(enaddr, prop_data_data_nocopy(eaddrprop), ETHER_ADDR_LEN); else memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); } /* * Davicom chips all have an internal MII interface * and a built-in PHY. DM9102A also has a an external * MII interface, usually with a HomePNA PHY attached * to it. */ sc->sc_mediasw = &tlp_dm9102_mediasw; break; case TULIP_CHIP_AX88140: case TULIP_CHIP_AX88141: /* * ASIX AX88140/AX88141 Ethernet Address is located at offset * 20 of the SROM. */ memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); /* * ASIX AX88140A/AX88141 chip can have a built-in PHY or * an external MII interface. */ sc->sc_mediasw = &tlp_asix_mediasw; break; case TULIP_CHIP_RS7112: /* * RS7112 Ethernet Address is located of offset 0x19a * of the SROM */ memcpy(enaddr, &sc->sc_srom[0x19a], ETHER_ADDR_LEN); /* RS7112 chip has a PHY at MII address 1 */ sc->sc_mediasw = &tlp_rs7112_mediasw; break; default: cant_cope: aprint_error_dev(self, "sorry, unable to handle your board\n"); goto fail; } /* * Handle shared interrupts. */ if (psc->sc_flags & TULIP_PCI_SHAREDINTR) { if (psc->sc_master) psc->sc_flags |= TULIP_PCI_SLAVEINTR; else { tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDINTR, TULIP_PCI_SLAVEINTR); if (psc->sc_master == NULL) psc->sc_master = psc; } LIST_INSERT_HEAD(&psc->sc_master->sc_intrslaves, psc, sc_intrq); } if (psc->sc_flags & TULIP_PCI_SLAVEINTR) { aprint_normal_dev(self, "sharing interrupt with %s\n", device_xname(psc->sc_master->sc_tulip.sc_dev)); } else { /* * Map and establish our interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "unable to map interrupt\n"); goto fail; } intrstr = pci_intr_string(pc, ih); psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, (psc->sc_flags & TULIP_PCI_SHAREDINTR) ? tlp_pci_shared_intr : tlp_intr, sc); if (psc->sc_ih == NULL) { aprint_error_dev(self, "unable to establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); goto fail; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); } /* * Finish off the attach. */ error = tlp_attach(sc, enaddr); if (error) goto fail; return; fail: if (psc->sc_ih != NULL) { pci_intr_disestablish(psc->sc_pc, psc->sc_ih); psc->sc_ih = NULL; } if (ioh_valid) bus_space_unmap(iot, ioh, iosize); if (memh_valid) bus_space_unmap(memt, memh, memsize); psc->sc_mapsize = 0; return; }
/* * npfctl_rule: add or remove dynamic rules in the specified ruleset. */ int npfctl_rule(u_long cmd, void *data) { struct plistref *pref = data; prop_dictionary_t npf_rule, retdict = NULL; npf_ruleset_t *rlset; npf_rule_t *rl = NULL; const char *ruleset_name; uint32_t rcmd = 0; int error; error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_rule); if (error) { return error; } prop_dictionary_get_uint32(npf_rule, "command", &rcmd); if (!prop_dictionary_get_cstring_nocopy(npf_rule, "ruleset-name", &ruleset_name)) { error = EINVAL; goto out; } if (rcmd == NPF_CMD_RULE_ADD) { retdict = prop_dictionary_create(); if (npf_mk_singlerule(npf_rule, NULL, &rl, retdict) != 0) { error = EINVAL; goto out; } } npf_config_enter(); rlset = npf_config_ruleset(); switch (rcmd) { case NPF_CMD_RULE_ADD: { if ((error = npf_ruleset_add(rlset, ruleset_name, rl)) == 0) { /* Success. */ uint64_t id = npf_rule_getid(rl); prop_dictionary_set_uint64(retdict, "id", id); rl = NULL; } break; } case NPF_CMD_RULE_REMOVE: { uint64_t id; if (!prop_dictionary_get_uint64(npf_rule, "id", &id)) { error = EINVAL; break; } error = npf_ruleset_remove(rlset, ruleset_name, id); break; } case NPF_CMD_RULE_REMKEY: { prop_object_t obj = prop_dictionary_get(npf_rule, "key"); const void *key = prop_data_data_nocopy(obj); size_t len = prop_data_size(obj); if (len == 0 || len > NPF_RULE_MAXKEYLEN) { error = EINVAL; break; } error = npf_ruleset_remkey(rlset, ruleset_name, key, len); break; } case NPF_CMD_RULE_LIST: { retdict = npf_ruleset_list(rlset, ruleset_name); if (!retdict) { error = ESRCH; } break; } case NPF_CMD_RULE_FLUSH: { error = npf_ruleset_flush(rlset, ruleset_name); break; } default: error = EINVAL; break; } /* Destroy any removed rules. */ if (!error && rcmd != NPF_CMD_RULE_ADD && rcmd != NPF_CMD_RULE_LIST) { npf_config_sync(); npf_ruleset_gc(rlset); } npf_config_exit(); if (rl) { KASSERT(error); npf_rule_free(rl); } out: if (retdict) { prop_object_release(npf_rule); prop_dictionary_copyout_ioctl(pref, cmd, retdict); prop_object_release(retdict); } return error; }
void smsc_attach(device_t parent, device_t self, void *aux) { struct smsc_softc *sc = device_private(self); struct usb_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; char *devinfop; struct mii_data *mii; struct ifnet *ifp; int err, s, i; uint32_t mac_h, mac_l; sc->sc_dev = self; sc->sc_udev = dev; aprint_naive("\n"); aprint_normal("\n"); devinfop = usbd_devinfo_alloc(sc->sc_udev, 0); aprint_normal_dev(self, "%s\n", devinfop); usbd_devinfo_free(devinfop); err = usbd_set_config_no(dev, SMSC_CONFIG_INDEX, 1); if (err) { aprint_error_dev(self, "failed to set configuration" ", err=%s\n", usbd_errstr(err)); return; } /* Setup the endpoints for the SMSC LAN95xx device(s) */ usb_init_task(&sc->sc_tick_task, smsc_tick_task, sc, 0); usb_init_task(&sc->sc_stop_task, (void (*)(void *))smsc_stop, sc, 0); mutex_init(&sc->sc_mii_lock, MUTEX_DEFAULT, IPL_NONE); err = usbd_device2interface_handle(dev, SMSC_IFACE_IDX, &sc->sc_iface); if (err) { aprint_error_dev(self, "getting interface handle failed\n"); return; } id = usbd_get_interface_descriptor(sc->sc_iface); if (sc->sc_udev->speed >= USB_SPEED_HIGH) sc->sc_bufsz = SMSC_MAX_BUFSZ; else sc->sc_bufsz = SMSC_MIN_BUFSZ; /* Find endpoints. */ for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (!ed) { aprint_error_dev(self, "couldn't get ep %d\n", i); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->sc_ed[SMSC_ENDPT_RX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->sc_ed[SMSC_ENDPT_TX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { sc->sc_ed[SMSC_ENDPT_INTR] = ed->bEndpointAddress; } } s = splnet(); ifp = &sc->sc_ec.ec_if; ifp->if_softc = sc; strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = smsc_init; ifp->if_ioctl = smsc_ioctl; ifp->if_start = smsc_start; ifp->if_stop = smsc_stop; #ifdef notyet /* * We can do TCPv4, and UDPv4 checksums in hardware. */ ifp->if_capabilities |= /*IFCAP_CSUM_TCPv4_Tx |*/ IFCAP_CSUM_TCPv4_Rx | /*IFCAP_CSUM_UDPv4_Tx |*/ IFCAP_CSUM_UDPv4_Rx; #endif sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU; /* Setup some of the basics */ sc->sc_phyno = 1; /* * Attempt to get the mac address, if an EEPROM is not attached this * will just return FF:FF:FF:FF:FF:FF, so in such cases we invent a MAC * address based on urandom. */ memset(sc->sc_enaddr, 0xff, ETHER_ADDR_LEN); prop_dictionary_t dict = device_properties(self); prop_data_t eaprop = prop_dictionary_get(dict, "mac-address"); if (eaprop != NULL) { KASSERT(prop_object_type(eaprop) == PROP_TYPE_DATA); KASSERT(prop_data_size(eaprop) == ETHER_ADDR_LEN); memcpy(sc->sc_enaddr, prop_data_data_nocopy(eaprop), ETHER_ADDR_LEN); } else /* Check if there is already a MAC address in the register */ if ((smsc_read_reg(sc, SMSC_MAC_ADDRL, &mac_l) == 0) && (smsc_read_reg(sc, SMSC_MAC_ADDRH, &mac_h) == 0)) { sc->sc_enaddr[5] = (uint8_t)((mac_h >> 8) & 0xff); sc->sc_enaddr[4] = (uint8_t)((mac_h) & 0xff); sc->sc_enaddr[3] = (uint8_t)((mac_l >> 24) & 0xff); sc->sc_enaddr[2] = (uint8_t)((mac_l >> 16) & 0xff); sc->sc_enaddr[1] = (uint8_t)((mac_l >> 8) & 0xff); sc->sc_enaddr[0] = (uint8_t)((mac_l) & 0xff); }
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 void admsw_attach(device_t parent, device_t self, void *aux) { uint8_t enaddr[ETHER_ADDR_LEN]; struct admsw_softc *sc = device_private(self); struct obio_attach_args *aa = aux; struct ifnet *ifp; bus_dma_segment_t seg; int error, i, rseg; prop_data_t pd; printf(": ADM5120 Switch Engine, %d ports\n", SW_DEVS); sc->sc_dev = self; sc->sc_dmat = aa->oba_dt; sc->sc_st = aa->oba_st; pd = prop_dictionary_get(device_properties(self), "mac-address"); if (pd == NULL) { enaddr[0] = 0x02; enaddr[1] = 0xaa; enaddr[2] = 0xbb; enaddr[3] = 0xcc; enaddr[4] = 0xdd; enaddr[5] = 0xee; } else memcpy(enaddr, prop_data_data_nocopy(pd), sizeof(enaddr)); memcpy(sc->sc_enaddr, enaddr, sizeof(sc->sc_enaddr)); printf("%s: base Ethernet address %s\n", device_xname(sc->sc_dev), ether_sprintf(enaddr)); /* Map the device. */ if (bus_space_map(sc->sc_st, aa->oba_addr, 512, 0, &sc->sc_ioh) != 0) { printf("%s: unable to map device\n", device_xname(sc->sc_dev)); return; } /* Hook up the interrupt handler. */ sc->sc_ih = adm5120_intr_establish(aa->oba_irq, INTR_IRQ, admsw_intr, sc); if (sc->sc_ih == NULL) { printf("%s: unable to register interrupt handler\n", device_xname(sc->sc_dev)); return; } /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct admsw_control_data), PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) { printf("%s: unable to allocate control data, error = %d\n", device_xname(sc->sc_dev), error); return; } if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(struct admsw_control_data), (void *)&sc->sc_control_data, 0)) != 0) { printf("%s: unable to map control data, error = %d\n", device_xname(sc->sc_dev), error); return; } if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct admsw_control_data), 1, sizeof(struct admsw_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { printf("%s: unable to create control data DMA map, " "error = %d\n", device_xname(sc->sc_dev), error); return; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct admsw_control_data), NULL, 0)) != 0) { printf("%s: unable to load control data DMA map, error = %d\n", device_xname(sc->sc_dev), error); return; } /* * Create the transmit buffer DMA maps. */ for (i = 0; i < ADMSW_NTXHDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 2, MCLBYTES, 0, 0, &sc->sc_txhsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create txh DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_txhsoft[i].ds_mbuf = NULL; } for (i = 0; i < ADMSW_NTXLDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 2, MCLBYTES, 0, 0, &sc->sc_txlsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create txl DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_txlsoft[i].ds_mbuf = NULL; } /* * Create the receive buffer DMA maps. */ for (i = 0; i < ADMSW_NRXHDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxhsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create rxh DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_rxhsoft[i].ds_mbuf = NULL; } for (i = 0; i < ADMSW_NRXLDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxlsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create rxl DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_rxlsoft[i].ds_mbuf = NULL; } admsw_init_bufs(sc); admsw_reset(sc); for (i = 0; i < SW_DEVS; i++) { ifmedia_init(&sc->sc_ifmedia[i], 0, admsw_mediachange, admsw_mediastatus); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_10_T, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_100_TX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO); ifp = &sc->sc_ethercom[i].ec_if; strcpy(ifp->if_xname, device_xname(sc->sc_dev)); ifp->if_xname[5] += i; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = admsw_ioctl; ifp->if_start = admsw_start; ifp->if_watchdog = admsw_watchdog; ifp->if_init = admsw_init; ifp->if_stop = admsw_stop; ifp->if_capabilities |= IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx; IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, IFQ_MAXLEN)); IFQ_SET_READY(&ifp->if_snd); /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, enaddr); enaddr[5]++; } #ifdef ADMSW_EVENT_COUNTERS evcnt_attach_dynamic(&sc->sc_ev_txstall, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "txstall"); evcnt_attach_dynamic(&sc->sc_ev_rxstall, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "rxstall"); evcnt_attach_dynamic(&sc->sc_ev_txintr, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "txintr"); evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "rxintr"); #if 1 evcnt_attach_dynamic(&sc->sc_ev_rxsync, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "rxsync"); #endif #endif admwdog_attach(sc); /* Make sure the interface is shutdown during reboot. */ sc->sc_sdhook = shutdownhook_establish(admsw_shutdown, sc); if (sc->sc_sdhook == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", device_xname(sc->sc_dev)); /* leave interrupts and cpu port disabled */ return; }