int netif_news_open(struct romdev *pd) { struct iodesc *io; /* find a free socket */ io = &sdesc; if (io->io_netif) { #ifdef DEBUG printf("netif_open: device busy\n"); #endif errno = ENFILE; return -1; } memset(io, 0, sizeof(*io)); io->io_netif = pd; /* Put our ethernet address in io->myea */ prom_getether(pd, io->myea); return 0; }
/* * Called back during autoconfiguration for each device found */ void device_register(device_t dev, void *aux) { device_t busdev = device_parent(dev); int ofnode = 0; /* * We don't know the type of 'aux' - it depends on the * bus this device attaches to. We are only interested in * certain bus types, this only is used to find the boot * device. */ if (busdev == NULL) { /* * Ignore mainbus0 itself, it certainly is not a boot * device. */ } else if (device_is_a(busdev, "mainbus")) { struct mainbus_attach_args *ma = aux; ofnode = ma->ma_node; } else if (device_is_a(busdev, "pci")) { struct pci_attach_args *pa = aux; ofnode = PCITAG_NODE(pa->pa_tag); } else if (device_is_a(busdev, "sbus") || device_is_a(busdev, "dma") || device_is_a(busdev, "ledma")) { struct sbus_attach_args *sa = aux; ofnode = sa->sa_node; } else if (device_is_a(busdev, "ebus")) { struct ebus_attach_args *ea = aux; ofnode = ea->ea_node; } else if (device_is_a(busdev, "iic")) { struct i2c_attach_args *ia = aux; if (ia->ia_name == NULL) /* indirect config */ return; ofnode = (int)ia->ia_cookie; } else if (device_is_a(dev, "sd") || device_is_a(dev, "cd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; int off = 0; /* * There are two "cd" attachments: * atapibus -> atabus -> controller * scsibus -> controller * We want the node of the controller. */ if (device_is_a(busdev, "atapibus")) { busdev = device_parent(busdev); /* * if the atapibus is connected to the secondary * channel of the atabus, we need an offset of 2 * to match OF's idea of the target number. * (i.e. on U5/U10 "cdrom" and "disk2" have the * same target encoding, though different names) */ if (periph->periph_channel->chan_channel == 1) off = 2; } ofnode = device_ofnode(device_parent(busdev)); dev_path_drive_match(dev, ofnode, periph->periph_target + off, 0, periph->periph_lun); return; } else if (device_is_a(dev, "wd")) { struct ata_device *adev = aux; ofnode = device_ofnode(device_parent(busdev)); dev_path_drive_match(dev, ofnode, adev->adev_channel*2+ adev->adev_drv_data->drive, 0, 0); return; } if (busdev == NULL) return; if (ofnode != 0) { uint8_t eaddr[ETHER_ADDR_LEN]; char tmpstr[32]; char tmpstr2[32]; int node; uint32_t id = 0; uint64_t nwwn = 0, pwwn = 0; prop_dictionary_t dict; prop_data_t blob; prop_number_t pwwnd = NULL, nwwnd = NULL; prop_number_t idd = NULL; device_setofnode(dev, ofnode); dev_path_exact_match(dev, ofnode); if (OF_getprop(ofnode, "name", tmpstr, sizeof(tmpstr)) <= 0) tmpstr[0] = 0; if (OF_getprop(ofnode, "device_type", tmpstr2, sizeof(tmpstr2)) <= 0) tmpstr2[0] = 0; /* * If this is a network interface, note the * mac address. */ if (strcmp(tmpstr, "network") == 0 || strcmp(tmpstr, "ethernet") == 0 || strcmp(tmpstr2, "network") == 0 || strcmp(tmpstr2, "ethernet") == 0 || OF_getprop(ofnode, "mac-address", &eaddr, sizeof(eaddr)) >= ETHER_ADDR_LEN || OF_getprop(ofnode, "local-mac-address", &eaddr, sizeof(eaddr)) >= ETHER_ADDR_LEN) { dict = device_properties(dev); /* * Is it a network interface with FCode? */ if (strcmp(tmpstr, "network") == 0 || strcmp(tmpstr2, "network") == 0) { prop_dictionary_set_bool(dict, "without-seeprom", true); prom_getether(ofnode, eaddr); } else { if (!prom_get_node_ether(ofnode, eaddr)) goto noether; } blob = prop_data_create_data(eaddr, ETHER_ADDR_LEN); prop_dictionary_set(dict, "mac-address", blob); prop_object_release(blob); of_to_dataprop(dict, ofnode, "shared-pins", "shared-pins"); } noether: /* is this a FC node? */ if (strcmp(tmpstr, "scsi-fcp") == 0) { dict = device_properties(dev); if (OF_getprop(ofnode, "port-wwn", &pwwn, sizeof(pwwn)) == sizeof(pwwn)) { pwwnd = prop_number_create_unsigned_integer(pwwn); prop_dictionary_set(dict, "port-wwn", pwwnd); prop_object_release(pwwnd); } if (OF_getprop(ofnode, "node-wwn", &nwwn, sizeof(nwwn)) == sizeof(nwwn)) { nwwnd = prop_number_create_unsigned_integer(nwwn); prop_dictionary_set(dict, "node-wwn", nwwnd); prop_object_release(nwwnd); } } /* is this an spi device? look for scsi-initiator-id */ if (strcmp(tmpstr2, "scsi") == 0 || strcmp(tmpstr2, "scsi-2") == 0) { dict = device_properties(dev); for (node = ofnode; node != 0; node = OF_parent(node)) { if (OF_getprop(node, "scsi-initiator-id", &id, sizeof(id)) <= 0) continue; idd = prop_number_create_unsigned_integer(id); prop_dictionary_set(dict, "scsi-initiator-id", idd); prop_object_release(idd); break; } } } /* * Check for I2C busses and add data for their direct configuration. */ if (device_is_a(dev, "iic")) { int busnode = device_ofnode(busdev); if (busnode) { prop_dictionary_t props = device_properties(busdev); prop_object_t cfg = prop_dictionary_get(props, "i2c-child-devices"); if (!cfg) { int node; const char *name; /* * pmu's i2c devices are under the "i2c" node, * so find it out. */ name = prom_getpropstring(busnode, "name"); if (strcmp(name, "pmu") == 0) { for (node = OF_child(busnode); node != 0; node = OF_peer(node)) { name = prom_getpropstring(node, "name"); if (strcmp(name, "i2c") == 0) { busnode = node; break; } } } of_enter_i2c_devs(props, busnode, sizeof(cell_t)); } } /* * Add SPARCle spdmem devices (0x50 and 0x51) that the * firmware does not know about. */ if (!strcmp(machine_model, "TAD,SPARCLE")) { prop_dictionary_t props = device_properties(busdev); prop_array_t cfg = prop_array_create(); int i; DPRINTF(ACDB_PROBE, ("\nAdding spdmem for SPARCle ")); for (i = 0x50; i <= 0x51; i++) { prop_dictionary_t spd = prop_dictionary_create(); prop_dictionary_set_cstring(spd, "name", "dimm-spd"); prop_dictionary_set_uint32(spd, "addr", i); prop_dictionary_set_uint64(spd, "cookie", 0); prop_array_add(cfg, spd); prop_object_release(spd); } prop_dictionary_set(props, "i2c-child-devices", cfg); prop_object_release(cfg); } } /* set properties for PCI framebuffers */ if (device_is_a(busdev, "pci")) { /* see if this is going to be console */ struct pci_attach_args *pa = aux; prop_dictionary_t dict; int sub; int console = 0; dict = device_properties(dev); /* we only care about display devices from here on */ if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) return; console = (ofnode == console_node); if (!console) { /* * see if any child matches since OF attaches * nodes for each head and /chosen/stdout * points to the head rather than the device * itself in this case */ sub = OF_child(ofnode); while ((sub != 0) && (sub != console_node)) { sub = OF_peer(sub); } if (sub == console_node) { console = true; } } copyprops(busdev, ofnode, dict, console); if (console) { uint64_t cmap_cb; prop_dictionary_set_uint32(dict, "instance_handle", console_instance); gfb_cb.gcc_cookie = (void *)(intptr_t)console_instance; gfb_cb.gcc_set_mapreg = of_set_palette; cmap_cb = (uint64_t)(uintptr_t)&gfb_cb; prop_dictionary_set_uint64(dict, "cmap_callback", cmap_cb); } #ifdef notyet else { int width; /* * the idea is to 'open' display devices with no useful * properties, in the hope that the firmware will * properly initialize them and we can run things like * genfb on them */ if (OF_getprop(node, "width", &width, sizeof(width)) != 4) { instance = OF_open(name); #endif } } /* * Called back after autoconfiguration of a device is done */ void device_register_post_config(device_t dev, void *aux) { if (booted_device == NULL && device_is_a(dev, "sd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; uint64_t wwn = 0; int ofnode; /* * If this is a FC-AL drive it will have * aquired its WWN device property by now, * so we can properly match it. */ if (prop_dictionary_get_uint64(device_properties(dev), "port-wwn", &wwn)) { /* * Different to what we do in device_register, * we do not pass the "controller" ofnode, * because FC-AL devices attach below a "fp" node, * E.g.: /pci/SUNW,qlc@4/fp@0,0/disk * and we need the parent of "disk" here. */ ofnode = device_ofnode( device_parent(device_parent(dev))); for (ofnode = OF_child(ofnode); ofnode != 0 && booted_device == NULL; ofnode = OF_peer(ofnode)) { dev_path_drive_match(dev, ofnode, periph->periph_target, wwn, periph->periph_lun); } } } } static void copyprops(device_t busdev, int node, prop_dictionary_t dict, int is_console) { device_t cntrlr; prop_dictionary_t psycho; paddr_t fbpa, mem_base = 0; uint32_t temp, fboffset; uint32_t fbaddr = 0; int options; char output_device[256]; char *pos; cntrlr = device_parent(busdev); if (cntrlr != NULL) { psycho = device_properties(cntrlr); prop_dictionary_get_uint64(psycho, "mem_base", &mem_base); } if (is_console) prop_dictionary_set_bool(dict, "is_console", 1); of_to_uint32_prop(dict, node, "width", "width"); of_to_uint32_prop(dict, node, "height", "height"); of_to_uint32_prop(dict, node, "linebytes", "linebytes"); if (!of_to_uint32_prop(dict, node, "depth", "depth") && /* Some cards have an extra space in the property name */ !of_to_uint32_prop(dict, node, "depth ", "depth")) { /* * XXX we should check linebytes vs. width but those * FBs that don't have a depth property ( /chaos/control... ) * won't have linebytes either */ prop_dictionary_set_uint32(dict, "depth", 8); } OF_getprop(node, "address", &fbaddr, sizeof(fbaddr)); if (fbaddr != 0) { pmap_extract(pmap_kernel(), fbaddr, &fbpa); #ifdef DEBUG printf("membase: %lx fbpa: %lx\n", (unsigned long)mem_base, (unsigned long)fbpa); #endif if (mem_base == 0) { /* XXX this is guesswork */ fboffset = (uint32_t)(fbpa & 0xffffffff); } fboffset = (uint32_t)(fbpa - mem_base); prop_dictionary_set_uint32(dict, "address", fboffset); } if (!of_to_dataprop(dict, node, "EDID", "EDID")) of_to_dataprop(dict, node, "edid", "EDID"); temp = 0; if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) { OF_getprop(OF_parent(node), "ATY,RefCLK", &temp, sizeof(temp)); } if (temp != 0) prop_dictionary_set_uint32(dict, "refclk", temp / 10); /* * finally, let's see if there's a video mode specified in * output-device and pass it on so drivers like radeonfb * can do their thing */ if (!is_console) return; options = OF_finddevice("/options"); if ((options == 0) || (options == -1)) return; if (OF_getprop(options, "output-device", output_device, 256) == 0) return; /* find the mode string if there is one */ pos = strstr(output_device, ":r"); if (pos == NULL) return; prop_dictionary_set_cstring(dict, "videomode", pos + 2); } static void of_set_palette(void *cookie, int index, int r, int g, int b) { int ih = (int)((intptr_t)cookie); OF_call_method_1("color!", ih, 4, r, g, b, index); }
void beattach(device_t parent, device_t self, void *aux) { struct sbus_attach_args *sa = aux; struct qec_softc *qec = device_private(parent); struct be_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_ethercom.ec_if; struct mii_data *mii = &sc->sc_mii; struct mii_softc *child; int node = sa->sa_node; bus_dma_tag_t dmatag = sa->sa_dmatag; bus_dma_segment_t seg; bus_size_t size; int instance; int rseg, error; uint32_t v; sc->sc_dev = self; if (sa->sa_nreg < 3) { printf(": only %d register sets\n", sa->sa_nreg); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base), (bus_size_t)sa->sa_reg[0].oa_size, 0, &sc->sc_cr) != 0) { printf(": cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base), (bus_size_t)sa->sa_reg[1].oa_size, 0, &sc->sc_br) != 0) { printf(": cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base), (bus_size_t)sa->sa_reg[2].oa_size, 0, &sc->sc_tr) != 0) { printf(": cannot map registers\n"); return; } sc->sc_bustag = sa->sa_bustag; sc->sc_qec = qec; sc->sc_qr = qec->sc_regs; sc->sc_rev = prom_getpropint(node, "board-version", -1); printf(": rev %x,", sc->sc_rev); callout_init(&sc->sc_tick_ch, 0); sc->sc_channel = prom_getpropint(node, "channel#", -1); if (sc->sc_channel == -1) sc->sc_channel = 0; sc->sc_burst = prom_getpropint(node, "burst-sizes", -1); if (sc->sc_burst == -1) sc->sc_burst = qec->sc_burst; /* Clamp at parent's burst sizes */ sc->sc_burst &= qec->sc_burst; /* Establish interrupt handler */ if (sa->sa_nintr) (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, beintr, sc); prom_getether(node, sc->sc_enaddr); printf(" address %s\n", ether_sprintf(sc->sc_enaddr)); /* * Allocate descriptor ring and buffers. */ /* for now, allocate as many bufs as there are ring descriptors */ sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE; sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE; size = QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + sc->sc_rb.rb_ntbuf * BE_PKT_BUF_SZ + sc->sc_rb.rb_nrbuf * BE_PKT_BUF_SZ; /* Get a DMA handle */ if ((error = bus_dmamap_create(dmatag, size, 1, size, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { aprint_error_dev(self, "DMA map create error %d\n", error); return; } /* Allocate DMA buffer */ if ((error = bus_dmamem_alloc(sa->sa_dmatag, size, 0, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer alloc error %d\n", error); return; } /* Map DMA memory in CPU addressable space */ if ((error = bus_dmamem_map(sa->sa_dmatag, &seg, rseg, size, &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error_dev(self, "DMA buffer map error %d\n", error); bus_dmamem_free(sa->sa_dmatag, &seg, rseg); return; } /* Load the buffer */ if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap, sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer map load error %d\n", error); bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size); bus_dmamem_free(dmatag, &seg, rseg); return; } sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr; /* * Initialize our media structures and MII info. */ mii->mii_ifp = ifp; mii->mii_readreg = be_mii_readreg; mii->mii_writereg = be_mii_writereg; mii->mii_statchg = be_mii_statchg; ifmedia_init(&mii->mii_media, 0, be_ifmedia_upd, be_ifmedia_sts); /* * Initialize transceiver and determine which PHY connection to use. */ be_mii_sync(sc); v = bus_space_read_4(sc->sc_bustag, sc->sc_tr, BE_TRI_MGMTPAL); instance = 0; if ((v & MGMT_PAL_EXT_MDIO) != 0) { mii_attach(self, mii, 0xffffffff, BE_PHY_EXTERNAL, MII_OFFSET_ANY, 0); child = LIST_FIRST(&mii->mii_phys); if (child == NULL) { /* No PHY attached */ ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, instance), 0, NULL); ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, instance)); } else { /* * Note: we support just one PHY on the external * MII connector. */ #ifdef DIAGNOSTIC if (LIST_NEXT(child, mii_list) != NULL) { aprint_error_dev(self, "spurious MII device %s attached\n", device_xname(child->mii_dev)); } #endif if (child->mii_phy != BE_PHY_EXTERNAL || child->mii_inst > 0) { aprint_error_dev(self, "cannot accommodate MII device %s" " at phy %d, instance %d\n", device_xname(child->mii_dev), child->mii_phy, child->mii_inst); } else { sc->sc_phys[instance] = child->mii_phy; } /* * XXX - we can really do the following ONLY if the * phy indeed has the auto negotiation capability!! */ ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance)); /* Mark our current media setting */ be_pal_gate(sc, BE_PHY_EXTERNAL); instance++; } } if ((v & MGMT_PAL_INT_MDIO) != 0) { /* * The be internal phy looks vaguely like MII hardware, * but not enough to be able to use the MII device * layer. Hence, we have to take care of media selection * ourselves. */ sc->sc_mii_inst = instance; sc->sc_phys[instance] = BE_PHY_INTERNAL; /* Use `ifm_data' to store BMCR bits */ ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, instance), 0, NULL); ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, instance), BMCR_S100, NULL); ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance), 0, NULL); printf("on-board transceiver at %s: 10baseT, 100baseTX, auto\n", device_xname(self)); be_mii_reset(sc, BE_PHY_INTERNAL); /* Only set default medium here if there's no external PHY */ if (instance == 0) { be_pal_gate(sc, BE_PHY_INTERNAL); ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance)); } else be_mii_writereg(self, BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO); } memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = bestart; ifp->if_ioctl = beioctl; ifp->if_watchdog = bewatchdog; ifp->if_init = beinit; ifp->if_stop = bestop; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); /* claim 802.1q capability */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); }
void leattach_ledma(device_t parent, device_t self, void *aux) { struct le_softc *lesc = device_private(self); struct lance_softc *sc = &lesc->sc_am7990.lsc; struct lsi64854_softc *lsi = device_private(parent); struct sbus_attach_args *sa = aux; bus_dma_tag_t dmatag = sa->sa_dmatag; bus_dma_segment_t seg; int rseg, error; sc->sc_dev = self; lesc->sc_bustag = sa->sa_bustag; /* Establish link to `ledma' device */ lesc->sc_dma = lsi; lesc->sc_dma->sc_client = lesc; /* Map device registers */ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &lesc->sc_reg) != 0) { aprint_error(": cannot map registers\n"); return; } /* Allocate buffer memory */ sc->sc_memsize = MEMSIZE; /* Get a DMA handle */ if ((error = bus_dmamap_create(dmatag, MEMSIZE, 1, MEMSIZE, LEDMA_BOUNDARY, BUS_DMA_NOWAIT, &lesc->sc_dmamap)) != 0) { aprint_error(": DMA map create error %d\n", error); return; } /* Allocate DMA buffer */ if ((error = bus_dmamem_alloc(dmatag, MEMSIZE, 0, LEDMA_BOUNDARY, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { aprint_error(": DMA buffer alloc error %d\n",error); return; } /* Map DMA buffer into kernel space */ if ((error = bus_dmamem_map(dmatag, &seg, rseg, MEMSIZE, (void **)&sc->sc_mem, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error(": DMA buffer map error %d\n", error); bus_dmamem_free(dmatag, &seg, rseg); return; } /* Load DMA buffer */ if ((error = bus_dmamap_load(dmatag, lesc->sc_dmamap, sc->sc_mem, MEMSIZE, NULL, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error(": DMA buffer map load error %d\n", error); bus_dmamem_free(dmatag, &seg, rseg); bus_dmamem_unmap(dmatag, sc->sc_mem, MEMSIZE); return; } lesc->sc_laddr = lesc->sc_dmamap->dm_segs[0].ds_addr; sc->sc_addr = lesc->sc_laddr & 0xffffff; sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; /* Assume SBus is grandparent */ lesc->sc_sd.sd_reset = (void *)lance_reset; sbus_establish(&lesc->sc_sd, parent); sc->sc_mediachange = lemediachange; sc->sc_mediastatus = lemediastatus; sc->sc_supmedia = lemedia; sc->sc_nsupmedia = NLEMEDIA; sc->sc_defaultmedia = IFM_ETHER|IFM_AUTO; prom_getether(sa->sa_node, sc->sc_enaddr); sc->sc_copytodesc = lance_copytobuf_contig; sc->sc_copyfromdesc = lance_copyfrombuf_contig; sc->sc_copytobuf = lance_copytobuf_contig; sc->sc_copyfrombuf = lance_copyfrombuf_contig; sc->sc_zerobuf = lance_zerobuf_contig; sc->sc_rdcsr = lerdcsr; sc->sc_wrcsr = lewrcsr; sc->sc_hwinit = lehwinit; sc->sc_nocarrier = lenocarrier; sc->sc_hwreset = lehwreset; /* Establish interrupt handler */ if (sa->sa_nintr != 0) (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, am7990_intr, sc); am7990_config(&lesc->sc_am7990); /* now initialize DMA */ lehwreset(sc); }
void qeattach(device_t parent, device_t self, void *aux) { struct sbus_attach_args *sa = aux; struct qec_softc *qec = device_private(parent); struct qe_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_ethercom.ec_if; int node = sa->sa_node; bus_dma_tag_t dmatag = sa->sa_dmatag; bus_dma_segment_t seg; bus_size_t size; int rseg, error; sc->sc_dev = self; if (sa->sa_nreg < 2) { printf("%s: only %d register sets\n", device_xname(self), sa->sa_nreg); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR( sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base), (bus_size_t)sa->sa_reg[0].oa_size, 0, &sc->sc_cr) != 0) { aprint_error_dev(self, "cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR( sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base), (bus_size_t)sa->sa_reg[1].oa_size, 0, &sc->sc_mr) != 0) { aprint_error_dev(self, "cannot map registers\n"); return; } sc->sc_rev = prom_getpropint(node, "mace-version", -1); printf(" rev %x", sc->sc_rev); sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; sc->sc_qec = qec; sc->sc_qr = qec->sc_regs; sc->sc_channel = prom_getpropint(node, "channel#", -1); sc->sc_burst = qec->sc_burst; qestop(sc); /* Note: no interrupt level passed */ (void)bus_intr_establish(sa->sa_bustag, 0, IPL_NET, qeintr, sc); prom_getether(node, sc->sc_enaddr); /* * Allocate descriptor ring and buffers. */ /* for now, allocate as many bufs as there are ring descriptors */ sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE; sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE; size = QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + sc->sc_rb.rb_ntbuf * QE_PKT_BUF_SZ + sc->sc_rb.rb_nrbuf * QE_PKT_BUF_SZ; /* Get a DMA handle */ if ((error = bus_dmamap_create(dmatag, size, 1, size, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { aprint_error_dev(self, "DMA map create error %d\n", error); return; } /* Allocate DMA buffer */ if ((error = bus_dmamem_alloc(dmatag, size, 0, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer alloc error %d\n", error); return; } /* Map DMA buffer in CPU addressable space */ if ((error = bus_dmamem_map(dmatag, &seg, rseg, size, &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error_dev(self, "DMA buffer map error %d\n", error); bus_dmamem_free(dmatag, &seg, rseg); return; } /* Load the buffer */ if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap, sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer map load error %d\n", error); bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size); bus_dmamem_free(dmatag, &seg, rseg); return; } sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr; /* Initialize media properties */ ifmedia_init(&sc->sc_ifmedia, 0, qe_ifmedia_upd, qe_ifmedia_sts); ifmedia_add(&sc->sc_ifmedia, IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,0), 0, NULL); ifmedia_add(&sc->sc_ifmedia, IFM_MAKEWORD(IFM_ETHER,IFM_10_5,0,0), 0, NULL); ifmedia_add(&sc->sc_ifmedia, IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,0), 0, NULL); ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO); memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = qestart; ifp->if_ioctl = qeioctl; ifp->if_watchdog = qewatchdog; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); printf(" address %s\n", ether_sprintf(sc->sc_enaddr)); }