static void ue_attach_post_task(struct usb_proc_msg *_task) { struct usb_ether_cfg_task *task = (struct usb_ether_cfg_task *)_task; struct usb_ether *ue = task->ue; struct ifnet *ifp; int error; char num[14]; /* sufficient for 32 bits */ /* first call driver's post attach routine */ ue->ue_methods->ue_attach_post(ue); UE_UNLOCK(ue); ue->ue_unit = alloc_unr(ueunit); usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0); sysctl_ctx_init(&ue->ue_sysctl_ctx); ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(ue->ue_dev, "could not allocate ifnet\n"); goto error; } ifp->if_softc = ue; if_initname(ifp, "ue", ue->ue_unit); ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; if (ue->ue_methods->ue_ioctl != NULL) ifp->if_ioctl = ue->ue_methods->ue_ioctl; else ifp->if_ioctl = uether_ioctl; ifp->if_start = ue_start; ifp->if_init = ue_init; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; IFQ_SET_READY(&ifp->if_snd); ue->ue_ifp = ifp; if (ue->ue_methods->ue_mii_upd != NULL && ue->ue_methods->ue_mii_sts != NULL) { mtx_lock(&Giant); /* device_xxx() depends on this */ error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus, ue_ifmedia_upd, ue->ue_methods->ue_mii_sts); mtx_unlock(&Giant); if (error) { device_printf(ue->ue_dev, "MII without any PHY\n"); goto error; } } if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev)); ether_ifattach(ifp, ue->ue_eaddr); snprintf(num, sizeof(num), "%u", ue->ue_unit); ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx, &SYSCTL_NODE_CHILDREN(_net, ue), OID_AUTO, num, CTLFLAG_RD, NULL, ""); SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx, SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO, "%parent", CTLFLAG_RD, ue, 0, ue_sysctl_parent, "A", "parent device"); UE_LOCK(ue); return; error: free_unr(ueunit, ue->ue_unit); if (ue->ue_ifp != NULL) { if_free(ue->ue_ifp); ue->ue_ifp = NULL; } UE_LOCK(ue); return; }
static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data) { int *priv = priv_data; int try = (*priv & 0x1); *priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10; if (p_dev->config_index == 0) return -EINVAL; if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32) return -EINVAL; if (try) p_dev->io_lines = 16; return try_io_port(p_dev); } static hw_info_t *pcnet_try_config(struct pcmcia_device *link, int *has_shmem, int try) { struct net_device *dev = link->priv; hw_info_t *local_hw_info; pcnet_dev_t *info = PRIV(dev); int priv = try; int ret; ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); if (ret) { dev_warn(&link->dev, "no useable port range found\n"); return NULL; } *has_shmem = (priv & 0x10); if (!link->irq) return NULL; if (resource_size(link->resource[1]) == 8) link->config_flags |= CONF_ENABLE_SPKR; if ((link->manf_id == MANFID_IBM) && (link->card_id == PRODID_IBM_HOME_AND_AWAY)) link->config_index |= 0x10; ret = pcmcia_enable_device(link); if (ret) return NULL; dev->irq = link->irq; dev->base_addr = link->resource[0]->start; if (info->flags & HAS_MISC_REG) { if ((if_port == 1) || (if_port == 2)) dev->if_port = if_port; else dev_notice(&link->dev, "invalid if_port requested\n"); } else dev->if_port = 0; if ((link->config_base == 0x03c0) && (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { dev_info(&link->dev, "this is an AX88190 card - use axnet_cs instead.\n"); return NULL; } local_hw_info = get_hwinfo(link); if (!local_hw_info) local_hw_info = get_prom(link); if (!local_hw_info) local_hw_info = get_dl10019(link); if (!local_hw_info) local_hw_info = get_ax88190(link); if (!local_hw_info) local_hw_info = get_hwired(link); return local_hw_info; } static int pcnet_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; pcnet_dev_t *info = PRIV(dev); int start_pg, stop_pg, cm_offset; int has_shmem = 0; hw_info_t *local_hw_info; dev_dbg(&link->dev, "pcnet_config\n"); local_hw_info = pcnet_try_config(link, &has_shmem, 0); if (!local_hw_info) { /* check whether forcing io_lines to 16 helps... */ pcmcia_disable_device(link); local_hw_info = pcnet_try_config(link, &has_shmem, 1); if (local_hw_info == NULL) { dev_notice(&link->dev, "unable to read hardware net" " address for io base %#3lx\n", dev->base_addr); goto failed; } } info->flags = local_hw_info->flags; /* Check for user overrides */ info->flags |= (delay_output) ? DELAY_OUTPUT : 0; if ((link->manf_id == MANFID_SOCKET) && ((link->card_id == PRODID_SOCKET_LPE) || (link->card_id == PRODID_SOCKET_LPE_CF) || (link->card_id == PRODID_SOCKET_EIO))) info->flags &= ~USE_BIG_BUF; if (!use_big_buf) info->flags &= ~USE_BIG_BUF; if (info->flags & USE_BIG_BUF) { start_pg = SOCKET_START_PG; stop_pg = SOCKET_STOP_PG; cm_offset = 0x10000; } else { start_pg = PCNET_START_PG; stop_pg = PCNET_STOP_PG; cm_offset = 0; } /* has_shmem is ignored if use_shmem != -1 */ if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) || (setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0)) setup_dma_config(link, start_pg, stop_pg); ei_status.name = "NE2000"; ei_status.word16 = 1; ei_status.reset_8390 = pcnet_reset_8390; if (info->flags & (IS_DL10019|IS_DL10022)) mii_phy_probe(dev); SET_NETDEV_DEV(dev, &link->dev); if (register_netdev(dev) != 0) { pr_notice("register_netdev() failed\n"); goto failed; } if (info->flags & (IS_DL10019|IS_DL10022)) { u_char id = inb(dev->base_addr + 0x1a); netdev_info(dev, "NE2000 (DL100%d rev %02x): ", (info->flags & IS_DL10022) ? 22 : 19, id); if (info->pna_phy) pr_cont("PNA, "); } else { netdev_info(dev, "NE2000 Compatible: "); } pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq); if (info->flags & USE_SHMEM) pr_cont(" mem %#5lx,", dev->mem_start); if (info->flags & HAS_MISC_REG) pr_cont(" %s xcvr,", if_names[dev->if_port]); pr_cont(" hw_addr %pM\n", dev->dev_addr); return 0; failed: pcnet_release(link); return -ENODEV; } /* pcnet_config */ static void pcnet_release(struct pcmcia_device *link) { pcnet_dev_t *info = PRIV(link->priv); dev_dbg(&link->dev, "pcnet_release\n"); if (info->flags & USE_SHMEM) iounmap(info->base); pcmcia_disable_device(link); }
static int pegasus_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct net_device *net; pegasus_t *pegasus; int dev_index = id - pegasus_ids; int res = -ENOMEM; usb_get_dev(dev); if (!(pegasus = kmalloc(sizeof (struct pegasus), GFP_KERNEL))) { err("out of memory allocating device structure"); goto out; } memset(pegasus, 0, sizeof (struct pegasus)); pegasus->dev_index = dev_index; init_waitqueue_head(&pegasus->ctrl_wait); if (!alloc_urbs(pegasus)) goto out1; net = alloc_etherdev(0); if (!net) goto out2; tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); pegasus->usb = dev; pegasus->net = net; SET_MODULE_OWNER(net); net->priv = pegasus; net->open = pegasus_open; net->stop = pegasus_close; net->watchdog_timeo = PEGASUS_TX_TIMEOUT; net->tx_timeout = pegasus_tx_timeout; net->do_ioctl = pegasus_ioctl; net->hard_start_xmit = pegasus_start_xmit; net->set_multicast_list = pegasus_set_multicast; net->get_stats = pegasus_netdev_stats; net->mtu = PEGASUS_MTU; pegasus->mii.dev = net; pegasus->mii.mdio_read = mdio_read; pegasus->mii.mdio_write = mdio_write; pegasus->mii.phy_id_mask = 0x1f; pegasus->mii.reg_num_mask = 0x1f; spin_lock_init(&pegasus->rx_pool_lock); pegasus->features = usb_dev_id[dev_index].private; get_interrupt_interval(pegasus); if (reset_mac(pegasus)) { err("can't reset MAC"); res = -EIO; goto out3; } set_ethernet_addr(pegasus); fill_skb_pool(pegasus); if (pegasus->features & PEGASUS_II) { info("setup Pegasus II specific registers"); setup_pegasus_II(pegasus); } pegasus->phy = mii_phy_probe(pegasus); if (pegasus->phy == 0xff) { warn("can't locate MII phy, using default"); pegasus->phy = 1; } usb_set_intfdata(intf, pegasus); SET_NETDEV_DEV(net, &intf->dev); res = register_netdev(net); if (res) goto out4; printk("%s: %s\n", net->name, usb_dev_id[dev_index].name); return 0; out4: usb_set_intfdata(intf, NULL); free_skb_pool(pegasus); out3: free_netdev(net); out2: free_all_urbs(pegasus); out1: kfree(pegasus); out: usb_put_dev(dev); return res; }
static void ue_attach_post_task(struct usb_proc_msg *_task) { struct usb_ether_cfg_task *task = (struct usb_ether_cfg_task *)_task; struct usb_ether *ue = task->ue; struct ifnet *ifp = uether_getifp(ue); int error; char num[14]; /* sufficient for 32 bits */ /* first call driver's post attach routine */ ue->ue_methods->ue_attach_post(ue); UE_UNLOCK(ue); KKASSERT(!lockowned(ue->ue_lock)); ue->ue_unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(ue), 0); usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_lock, 0); sysctl_ctx_init(&ue->ue_sysctl_ctx); KKASSERT(!lockowned(ue->ue_lock)); error = 0; ifp->if_softc = ue; if_initname(ifp, "ue", ue->ue_unit); if (ue->ue_methods->ue_attach_post_sub != NULL) { error = ue->ue_methods->ue_attach_post_sub(ue); KKASSERT(!lockowned(ue->ue_lock)); } else { ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; if (ue->ue_methods->ue_ioctl != NULL) ifp->if_ioctl = ue->ue_methods->ue_ioctl; else ifp->if_ioctl = uether_ioctl; ifp->if_start = ue_start; ifp->if_init = ue_init; ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); ifq_set_ready(&ifp->if_snd); if (ue->ue_methods->ue_mii_upd != NULL && ue->ue_methods->ue_mii_sts != NULL) { error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus, ue_ifmedia_upd, ue->ue_methods->ue_mii_sts); } } if (error) { device_printf(ue->ue_dev, "attaching PHYs failed\n"); goto fail; } if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev)); ether_ifattach(ifp, ue->ue_eaddr, NULL); /* Tell upper layer we support VLAN oversized frames. */ if (ifp->if_capabilities & IFCAP_VLAN_MTU) ifp->if_hdrlen = sizeof(struct ether_vlan_header); ksnprintf(num, sizeof(num), "%u", ue->ue_unit); ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx, &SYSCTL_NODE_CHILDREN(_net, ue), OID_AUTO, num, CTLFLAG_RD, NULL, ""); SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx, SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO, "%parent", CTLTYPE_STRING | CTLFLAG_RD, ue, 0, ue_sysctl_parent, "A", "parent device"); KKASSERT(!lockowned(ue->ue_lock)); UE_LOCK(ue); return; fail: devfs_clone_bitmap_put(&DEVFS_CLONE_BITMAP(ue), ue->ue_unit); UE_LOCK(ue); return; }