void hippi_setup(struct net_device *dev) { dev->set_multicast_list = NULL; dev->change_mtu = hippi_change_mtu; dev->hard_header = hippi_header; dev->rebuild_header = hippi_rebuild_header; dev->set_mac_address = hippi_mac_addr; dev->hard_header_parse = NULL; dev->hard_header_cache = NULL; dev->header_cache_update = NULL; dev->neigh_setup = hippi_neigh_setup_dev; /* * We don't support HIPPI `ARP' for the time being, and probably * never will unless someone else implements it. However we * still need a fake ARPHRD to make ifconfig and friends play ball. */ dev->type = ARPHRD_HIPPI; dev->hard_header_len = HIPPI_HLEN; dev->mtu = 65280; dev->addr_len = HIPPI_ALEN; dev->tx_queue_len = 25 /* 5 */; memset(dev->broadcast, 0xFF, HIPPI_ALEN); /* * HIPPI doesn't support broadcast+multicast and we only use * static ARP tables. ARP is disabled by hippi_neigh_setup_dev. */ dev->flags = 0; dev_init_buffers(dev); }
void ether_setup(struct net_device *dev) { /* Fill in the fields of the device structure with ethernet-generic values. This should be in a common file instead of per-driver. */ dev->change_mtu = eth_change_mtu; dev->hard_header = eth_header; dev->rebuild_header = eth_rebuild_header; dev->set_mac_address = eth_mac_addr; dev->hard_header_cache = eth_header_cache; dev->header_cache_update= eth_header_cache_update; dev->hard_header_parse = eth_header_parse; dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->mtu = 1500; /* eth_mtu */ dev->addr_len = ETH_ALEN; dev->tx_queue_len = 100; /* Ethernet wants good queues */ memset(dev->broadcast,0xFF, ETH_ALEN); /* New-style flags. */ dev->flags = IFF_BROADCAST|IFF_MULTICAST; dev_init_buffers(dev); }
void fddi_setup(struct net_device *dev) { /* * Fill in the fields of the device structure with FDDI-generic values. * This should be in a common file instead of per-driver. */ dev->change_mtu = fddi_change_mtu; dev->hard_header = fddi_header; dev->rebuild_header = fddi_rebuild_header; dev->type = ARPHRD_FDDI; dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */ dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */ dev->addr_len = FDDI_K_ALEN; dev->tx_queue_len = 100; /* Long queues on FDDI */ memset(dev->broadcast, 0xFF, FDDI_K_ALEN); /* New-style flags */ dev->flags = IFF_BROADCAST | IFF_MULTICAST; dev_init_buffers(dev); return; }
/* Initialize the rest of the LOOPBACK device. */ __initfunc(int loopback_init(struct device *dev)) { dev->mtu = LOOPBACK_MTU; dev->tbusy = 0; dev->hard_start_xmit = loopback_xmit; dev->hard_header = eth_header; dev->hard_header_cache = eth_header_cache; dev->header_cache_update= eth_header_cache_update; dev->hard_header_len = ETH_HLEN; /* 14 */ dev->addr_len = ETH_ALEN; /* 6 */ dev->tx_queue_len = 0; dev->type = ARPHRD_LOOPBACK; /* 0x0001 */ dev->rebuild_header = eth_rebuild_header; dev->open = loopback_open; dev->flags = IFF_LOOPBACK; dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; memset(dev->priv, 0, sizeof(struct net_device_stats)); dev->get_stats = get_stats; /* * Fill in the generic fields of the device structure. */ dev_init_buffers(dev); return(0); };
static int clip_init(struct net_device *dev) { DPRINTK("clip_init %s\n",dev->name); dev->hard_start_xmit = clip_start_xmit; /* sg_xmit ... */ dev->hard_header = NULL; dev->rebuild_header = NULL; dev->set_mac_address = NULL; dev->hard_header_parse = NULL; dev->hard_header_cache = NULL; dev->header_cache_update = NULL; dev->change_mtu = NULL; dev->do_ioctl = NULL; dev->get_stats = clip_get_stats; dev->type = ARPHRD_ATM; dev->hard_header_len = RFC1483LLC_LEN; dev->mtu = RFC1626_MTU; dev->addr_len = 0; dev->tx_queue_len = 100; /* "normal" queue (packets) */ /* When using a "real" qdisc, the qdisc determines the queue */ /* length. tx_queue_len is only used for the default case, */ /* without any more elaborate queuing. 100 is a reasonable */ /* compromise between decent burst-tolerance and protection */ /* against memory hogs. */ dev->flags = 0; dev_init_buffers(dev); /* is this ever supposed to be used ? */ return 0; }
int register_fcdev(struct net_device *dev) { dev_init_buffers(dev); if (dev->init && dev->init(dev) != 0) { unregister_fcdev(dev); return -EIO; } return 0; }
void setup_dummy_device (char *name, struct device **device) { error_t err; struct dummy_device *ddev; struct device *dev; ddev = calloc (1, sizeof (struct dummy_device)); if (!ddev) error (2, ENOMEM, "%s", name); ddev->next = dummy_dev; dummy_dev = ddev; *device = dev = &ddev->dev; dev->name = strdup (name); dev->priv = ddev; dev->get_stats = dummy_get_stats; dev->open = dummy_open; dev->stop = dummy_stop; dev->hard_start_xmit = dummy_xmit; dev->set_multicast_list = dummy_set_multi; /* These are the ones set by drivers/net/net_init.c::ether_setup. */ dev->hard_header = eth_header; dev->rebuild_header = eth_rebuild_header; dev->hard_header_cache = eth_header_cache; dev->header_cache_update = eth_header_cache_update; dev->hard_header_parse = eth_header_parse; /* We can't do these two (and we never try anyway). */ /* dev->change_mtu = eth_change_mtu; */ /* dev->set_mac_address = eth_mac_addr; */ /* Some more fields */ dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->addr_len = ETH_ALEN; memset (dev->broadcast, 0xff, ETH_ALEN); dev->flags = IFF_BROADCAST | IFF_MULTICAST; dev_init_buffers (dev); dev->mtu = 1500; dev->tx_queue_len = 0; dev->flags |= IFF_NOARP; dev->flags &= ~IFF_MULTICAST; /* That should be enough. */ /* This call adds the device to the `dev_base' chain, initializes its `ifindex' member (which matters!), and tells the protocol stacks about the device. */ err = - register_netdevice (dev); assert_perror (err); }
__initfunc(int shaper_probe(struct device *dev)) { /* * Set up the shaper. */ dev->priv = shaper_alloc(dev); if(dev->priv==NULL) return -ENOMEM; dev->open = shaper_open; dev->stop = shaper_close; dev->hard_start_xmit = shaper_start_xmit; dev->get_stats = shaper_get_stats; dev->set_multicast_list = NULL; /* * Intialise the packet queues */ dev_init_buffers(dev); /* * Handlers for when we attach to a device. */ dev->hard_header = shaper_header; dev->rebuild_header = shaper_rebuild_header; #if 0 dev->hard_header_cache = shaper_cache; dev->header_cache_update= shaper_cache_update; #endif dev->neigh_setup = shaper_neigh_setup_dev; dev->do_ioctl = shaper_ioctl; dev->hard_header_len = 0; dev->type = ARPHRD_ETHER; /* initially */ dev->set_mac_address = NULL; dev->mtu = 1500; dev->addr_len = 0; dev->tx_queue_len = 10; dev->flags = 0; /* * Shaper is ok */ return 0; }
int ipsec_mast_init(struct device *dev) { int i; KLIPS_PRINT(debug_mast, "klips_debug:ipsec_mast_init: " "allocating %lu bytes initialising device: %s\n", (unsigned long) sizeof(struct ipsecpriv), dev->name ? dev->name : "NULL"); /* Add our mast functions to the device */ dev->open = ipsec_mast_open; dev->stop = ipsec_mast_close; dev->hard_start_xmit = ipsec_mast_start_xmit; dev->get_stats = ipsec_mast_get_stats; dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); for(i = 0; i < sizeof(zeroes); i++) { ((__u8*)(zeroes))[i] = 0; } dev->set_multicast_list = NULL; dev->do_ioctl = ipsec_mast_ioctl; dev->hard_header = NULL; dev->rebuild_header = NULL; dev->set_mac_address = NULL; dev->header_cache_update= NULL; dev->neigh_setup = ipsec_mast_neigh_setup_dev; dev->hard_header_len = 0; dev->mtu = 0; dev->addr_len = 0; dev->type = ARPHRD_VOID; /* ARPHRD_MAST; */ /* ARPHRD_ETHER; */ dev->tx_queue_len = 10; /* Small queue */ memset((caddr_t)(dev->broadcast),0xFF, ETH_ALEN); /* what if this is not attached to ethernet? */ /* New-style flags. */ dev->flags = IFF_NOARP /* 0 */ /* Petr Novak */; dev_init_buffers(dev); /* We're done. Have I forgotten anything? */ return 0; }
void fc_setup(struct net_device *dev) { dev->hard_header = fc_header; dev->rebuild_header = fc_rebuild_header; dev->type = ARPHRD_IEEE802; dev->hard_header_len = FC_HLEN; dev->mtu = 2024; dev->addr_len = FC_ALEN; dev->tx_queue_len = 100; /* Long queues on fc */ memset(dev->broadcast,0xFF, FC_ALEN); /* New-style flags. */ dev->flags = IFF_BROADCAST; dev_init_buffers(dev); return; }
/* Initialize net device */ int tun_net_init(struct device *dev) { struct tun_struct *tun = (struct tun_struct *)dev->priv; DBG(KERN_INFO "%s: tun_net_init\n", tun->name); dev->open = tun_net_open; dev->hard_start_xmit = tun_net_xmit; dev->stop = tun_net_close; dev->get_stats = tun_net_stats; switch( tun->flags & TUN_TYPE_MASK ) { case TUN_TUN_DEV: /* Point-to-Point TUN Device */ dev->hard_header_len=0; dev->addr_len=0; dev->mtu = 1500; /* Type PPP seems most suitable */ dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; dev->tx_queue_len = 10; dev_init_buffers(dev); break; case TUN_TAP_DEV: /* Ethernet TAP Device */ dev->set_multicast_list = tun_net_mclist; /* Generate Ethernet address * Should be random enough */ *(unsigned short *)dev->dev_addr = htons(0x00FF); *(unsigned long *)(dev->dev_addr + sizeof(short)) = htonl( (long)((jiffies & 0x00ffffff)<<8) | (dev->base_addr+1) ); ether_setup(dev); break; } return 0; }
/* Initialize net device. */ int tun_net_init(struct net_device *dev) { struct tun_struct *tun = (struct tun_struct *)dev->priv; DBG(KERN_INFO "%s: tun_net_init\n", tun->name); SET_MODULE_OWNER(dev); dev->open = tun_net_open; dev->hard_start_xmit = tun_net_xmit; dev->stop = tun_net_close; dev->get_stats = tun_net_stats; switch (tun->flags & TUN_TYPE_MASK) { case TUN_TUN_DEV: /* Point-to-Point TUN Device */ dev->hard_header_len = 0; dev->addr_len = 0; dev->mtu = 1500; /* Type PPP seems most suitable */ dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; dev->tx_queue_len = 10; dev_init_buffers(dev); break; case TUN_TAP_DEV: /* Ethernet TAP Device */ dev->set_multicast_list = tun_net_mclist; /* Generate random Ethernet address. */ *(u16 *)dev->dev_addr = htons(0x00FF); get_random_bytes(dev->dev_addr + sizeof(u16), 4); ether_setup(dev); break; }; return 0; }
static void ipip_tunnel_init_gen(struct device *dev) { struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; dev->destructor = ipip_tunnel_destroy; dev->hard_start_xmit = ipip_tunnel_xmit; dev->get_stats = ipip_tunnel_get_stats; dev->do_ioctl = ipip_tunnel_ioctl; dev->change_mtu = ipip_tunnel_change_mtu; dev_init_buffers(dev); dev->type = ARPHRD_TUNNEL; dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); dev->mtu = 1500 - sizeof(struct iphdr); dev->flags = IFF_NOARP; dev->iflink = 0; dev->addr_len = 4; memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); memcpy(dev->broadcast, &t->parms.iph.daddr, 4); }
static int hdlc_init(struct device *dev) { hdlc_device *hdlc=dev_to_hdlc(dev); memset(&(hdlc->stats), 0, sizeof(struct net_device_stats)); dev->get_stats=hdlc_get_stats; dev->open=hdlc_open; dev->stop=hdlc_close; dev->do_ioctl=hdlc_ioctl; dev->change_mtu=hdlc_change_mtu; dev->mtu=HDLC_MAX_MTU; dev->type=ARPHRD_HDLC; dev->hard_header_len=16; dev->flags=IFF_POINTOPOINT | IFF_NOARP; dev_init_buffers(dev); return 0; }
void ltalk_setup(struct net_device *dev) { /* Fill in the fields of the device structure with localtalk-generic values. */ dev->change_mtu = ltalk_change_mtu; dev->hard_header = NULL; dev->rebuild_header = NULL; dev->set_mac_address = ltalk_mac_addr; dev->hard_header_cache = NULL; dev->header_cache_update= NULL; dev->type = ARPHRD_LOCALTLK; dev->hard_header_len = LTALK_HLEN; dev->mtu = LTALK_MTU; dev->addr_len = LTALK_ALEN; dev->tx_queue_len = 10; dev->broadcast[0] = 0xFF; dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP; dev_init_buffers(dev); }
/* * The init function (sometimes called probe). * It is invoked by register_netdev() * * NOTE: This is different from the init() function that can be called from * streams */ int ip2xinet_devinit(struct net_device *dev) { /* Assign other fields in dev, using ether_setup() and some hand assignments */ ether_setup(dev); #if !defined HAVE_KTYPE_STRUCT_NET_DEVICE_OPS dev->open = ip2xinet_devopen; dev->stop = ip2xinet_release; dev->set_config = ip2xinet_config; dev->hard_start_xmit = ip2xinet_tx; dev->do_ioctl = ip2xinet_ioctl; dev->get_stats = ip2xinet_stats; dev->change_mtu = ip2xinet_change_mtu; #endif #ifdef HAVE_KMEMB_STRUCT_NET_DEVICE_REBUILD_HEADER dev->rebuild_header = ip2xinet_rebuild_header; #endif #ifdef HAVE_KMEMB_STRUCT_NET_DEVICE_HARD_HEADER dev->hard_header = ip2xinet_hard_header; #endif dev->hard_header_len = ETH_HLEN; dev->flags |= IFF_NOARP; dev->type = ARPHRD_ETHER; dev->addr_len = 6; /* fake ethernet address */ dev->tx_queue_len = 10; /* dev->dev_addr is handled in the open() */ dev->flags &= ~IFF_BROADCAST; /* X25 doesn't broadcast */ dev->flags &= ~IFF_MULTICAST; /* X25 doesn't multicast */ #ifdef HAVE_KFUNC_DEV_INIT_BUFFERS dev_init_buffers(dev); #endif ip2xinet_status.ip2x_dlstate = UNLINKED; return 0; }
int register_hdlc_device(hdlc_device *hdlc) { int result; #ifndef MODULE if (!version_printed) { printk(KERN_INFO "%s\n", version); version_printed = 1; } #endif hdlc_to_dev(hdlc)->name = hdlc->name; hdlc_to_dev(hdlc)->init = hdlc_init; hdlc_to_dev(hdlc)->priv = &hdlc->syncppp_ptr; /* remove in 2.3 */ hdlc->syncppp_ptr = &hdlc->pppdev; hdlc->pppdev.dev=hdlc_to_dev(hdlc); hdlc->mode = MODE_NONE; hdlc->lmi.T391 = 10; /* polling verification timer */ hdlc->lmi.T392 = 15; /* link integrity verification polling timer */ hdlc->lmi.N391 = 6; /* full status polling counter */ hdlc->lmi.N392 = 3; /* error threshold */ hdlc->lmi.N393 = 4; /* monitored events count */ result=dev_alloc_name(hdlc_to_dev(hdlc), "hdlc%d"); if (result<0) return result; if (register_netdevice(hdlc_to_dev(hdlc))!=0) { hdlc_to_dev(hdlc)->name=NULL; /* non-NULL means registered */ return -EIO; } dev_init_buffers(hdlc_to_dev(hdlc)); MOD_INC_USE_COUNT; return 0; }
/* * Setup a new device. */ static int lapbeth_new_device(struct net_device *dev) { int k; unsigned char *buf; struct lapbethdev *lapbeth, *lapbeth2; if ((lapbeth = kmalloc(sizeof(struct lapbethdev), GFP_KERNEL)) == NULL) return -ENOMEM; memset(lapbeth, 0, sizeof(struct lapbethdev)); dev_hold(dev); lapbeth->ethdev = dev; lapbeth->ethname[sizeof(lapbeth->ethname)-1] = '\0'; strncpy(lapbeth->ethname, dev->name, sizeof(lapbeth->ethname)-1); dev = &lapbeth->axdev; buf = kmalloc(14, GFP_KERNEL); for (k = 0; k < MAXLAPBDEV; k++) { struct net_device *odev; sprintf(buf, "lapb%d", k); if ((odev = __dev_get_by_name(buf)) == NULL || lapbeth_check_devices(odev)) break; } if (k == MAXLAPBDEV) { dev_put(dev); kfree(lapbeth); return -ENODEV; } dev->priv = (void *)lapbeth; /* pointer back */ strcpy(dev->name, buf); dev->init = lapbeth_dev_init; if (register_netdev(dev) != 0) { dev_put(dev); kfree(lapbeth); return -EIO; } dev_init_buffers(dev); dev->hard_start_xmit = lapbeth_xmit; dev->open = lapbeth_open; dev->stop = lapbeth_close; dev->set_mac_address = lapbeth_set_mac_address; dev->get_stats = lapbeth_get_stats; dev->do_ioctl = lapbeth_ioctl; dev->flags = 0; dev->type = ARPHRD_X25; dev->hard_header_len = 3; dev->mtu = 1000; dev->addr_len = 0; cli(); if (lapbeth_devices == NULL) { lapbeth_devices = lapbeth; } else { for (lapbeth2 = lapbeth_devices; lapbeth2->next != NULL; lapbeth2 = lapbeth2->next); lapbeth2->next = lapbeth; } sti(); return 0; }
/*--------------------------------------------*/ int iucv_init(net_device *dev) { int rc; struct iucv_priv *privptr; #ifdef DEBUG printk( "iucv: iucv_init, device: %s\n",dev->name); #endif dev->open = iucv_open; dev->stop = iucv_release; dev->set_config = iucv_config; dev->hard_start_xmit = iucv_tx; dev->do_ioctl = iucv_ioctl; dev->get_stats = iucv_stats; dev->change_mtu = iucv_change_mtu; /* keep the default flags, just add NOARP */ dev->hard_header_len = 0; dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; dev->flags = IFF_NOARP|IFF_POINTOPOINT; dev->mtu = 4092; dev_init_buffers(dev); /* Then, allocate the priv field. This encloses the statistics */ /* and a few private fields.*/ dev->priv = kmalloc(sizeof(struct iucv_priv), GFP_KERNEL); if (dev->priv == NULL){ printk( "iucv: no memory for dev->priv.\n"); return -ENOMEM; } memset(dev->priv, 0, sizeof(struct iucv_priv)); privptr = (struct iucv_priv *)(dev->priv); privptr->send_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8); if (privptr->send_buffer == NULL) { printk(KERN_INFO "%s: could not get pages for send buffer\n", dev->name); return -ENOMEM; } memset(privptr->send_buffer, 0, 8*PAGE_SIZE); privptr->send_buffer_len=8*PAGE_SIZE; privptr->receive_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8); if (privptr->receive_buffer == NULL) { printk(KERN_INFO "%s: could not get pages for receive buffer\n", dev->name); return -ENOMEM; } memset(privptr->receive_buffer, 0, 8*PAGE_SIZE); privptr->receive_buffer_len=8*PAGE_SIZE; /* now use the private fields ... */ /* init pathid */ privptr->pathid = -1; /* init private userid from global userid */ memcpy(privptr->userid,iucv_userid[dev-iucv_devs],8); /* we can use only ONE buffer for external interrupt ! */ rc=iucv_declare_buffer(privptr->command_buffer, (DCLBFR_T *)iucv_ext_int_buffer); if (rc!=0 && rc!=19) /* ignore existing buffer */ { printk( "iucv:iucv_declare failed, rc: %X\n",rc); return -ENODEV; } rc = iucv_enable(privptr->command_buffer); if (rc!=0) { printk( "iucv:iucv_enable failed, rc: %x\n",rc); iucv_retrieve_buffer(privptr->command_buffer); return -ENODEV; } #ifdef DEBUG printk( "iucv: iucv_init endend OK for device %s.\n",dev->name); #endif return 0; }
static int hdlc_fr_pvc(hdlc_device *hdlc, int dlci) { pvc_device **pvc_p=&hdlc->first_pvc; pvc_device *pvc; int result, create=1; /* Create or delete PVC */ if(!capable(CAP_NET_ADMIN)) return -EPERM; if(dlci<0) { dlci=-dlci; create=0; } if(dlci<=0 || dlci>=1024) return -EINVAL; /* Only 10 bits for DLCI, DLCI=0 is reserved */ if(!mode_is(hdlc, MODE_FR)) return -EINVAL; /* Only meaningfull on FR */ while(*pvc_p) { if (netdev_dlci(&(*pvc_p)->netdev)==dlci) break; pvc_p=&(*pvc_p)->next; } if (create) { /* Create PVC */ if (*pvc_p!=NULL) return -EEXIST; *pvc_p=kmalloc(sizeof(pvc_device), GFP_KERNEL); pvc=*pvc_p; memset(pvc, 0, sizeof(pvc_device)); pvc->netdev.name=pvc->name; pvc->netdev.hard_start_xmit=pvc_xmit; pvc->netdev.get_stats=pvc_get_stats; pvc->netdev.open=pvc_open; pvc->netdev.stop=pvc_close; pvc->netdev.change_mtu=pvc_change_mtu; pvc->netdev.mtu=PVC_MAX_MTU; pvc->netdev.type=ARPHRD_DLCI; pvc->netdev.hard_header_len=16; pvc->netdev.hard_header=fr_hard_header; pvc->netdev.tx_queue_len=0; pvc->netdev.flags=IFF_POINTOPOINT; dev_init_buffers(&pvc->netdev); pvc->master=hdlc; *(u16*)pvc->netdev.dev_addr=htons(dlci); dlci_to_q922(pvc->netdev.broadcast, dlci); pvc->netdev.addr_len=2; /* 16 bits is enough */ pvc->netdev.irq=hdlc_to_dev(hdlc)->irq; result=dev_alloc_name(&pvc->netdev, "pvc%d"); if (result<0) { kfree(pvc); *pvc_p=NULL; return result; } if (register_netdevice(&pvc->netdev)!=0) { kfree(pvc); *pvc_p=NULL; return -EIO; } if (!mode_is(hdlc, MODE_SOFT) && hdlc->create_pvc) { result=hdlc->create_pvc(pvc); if (result) { unregister_netdevice(&pvc->netdev); kfree(pvc); *pvc_p=NULL; return result; } } hdlc->lmi.state |= LINK_STATE_CHANGED; hdlc->pvc_count++; return 0; } if (*pvc_p==NULL) /* Delete PVC */ return -ENOENT; pvc=*pvc_p; if (pvc->netdev.flags & IFF_UP) return -EBUSY; /* PVC in use */ if (!mode_is(hdlc, MODE_SOFT) && hdlc->destroy_pvc) hdlc->destroy_pvc(pvc); hdlc->lmi.state |= LINK_STATE_CHANGED; hdlc->pvc_count--; *pvc_p=pvc->next; unregister_netdevice(&pvc->netdev); kfree(pvc); return 0; }
void setup_ethernet_device (char *name, struct device **device) { struct net_status netstat; size_t count; int net_address[2]; error_t err; struct ether_device *edev; struct device *dev; edev = calloc (1, sizeof (struct ether_device)); if (!edev) error (2, ENOMEM, "%s", name); edev->next = ether_dev; ether_dev = edev; *device = dev = &edev->dev; dev->name = strdup (name); /* Functions. These ones are the true "hardware layer" in Linux. */ dev->open = 0; /* We set up before calling dev_open. */ dev->stop = ethernet_stop; dev->hard_start_xmit = ethernet_xmit; dev->get_stats = ethernet_get_stats; dev->set_multicast_list = ethernet_set_multi; /* These are the ones set by drivers/net/net_init.c::ether_setup. */ dev->hard_header = eth_header; dev->rebuild_header = eth_rebuild_header; dev->hard_header_cache = eth_header_cache; dev->header_cache_update = eth_header_cache_update; dev->hard_header_parse = eth_header_parse; /* We can't do these two (and we never try anyway). */ /* dev->change_mtu = eth_change_mtu; */ /* dev->set_mac_address = eth_mac_addr; */ /* Some more fields */ dev->priv = edev; /* For reverse lookup. */ dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->addr_len = ETH_ALEN; memset (dev->broadcast, 0xff, ETH_ALEN); dev->flags = IFF_BROADCAST | IFF_MULTICAST; /* FIXME: Receive all multicast to fix IPv6, until we implement ethernet_set_multi. */ dev->flags |= IFF_ALLMULTI; dev->change_flags = ethernet_change_flags; dev_init_buffers (dev); ethernet_open (dev); /* Fetch hardware information */ count = NET_STATUS_COUNT; err = device_get_status (edev->ether_port, NET_STATUS, (dev_status_t) &netstat, &count); if (err) error (2, err, "%s: Cannot get device status", name); dev->mtu = netstat.max_packet_size - dev->hard_header_len; assert (netstat.header_format == HDR_ETHERNET); assert (netstat.header_size == ETH_HLEN); assert (netstat.address_size == ETH_ALEN); count = 2; assert (count * sizeof (int) >= ETH_ALEN); err = device_get_status (edev->ether_port, NET_ADDRESS, net_address, &count); if (err) error (2, err, "%s: Cannot get hardware Ethernet address", name); net_address[0] = ntohl (net_address[0]); net_address[1] = ntohl (net_address[1]); memcpy (dev->dev_addr, net_address, ETH_ALEN); /* That should be enough. */ /* This call adds the device to the `dev_base' chain, initializes its `ifindex' member (which matters!), and tells the protocol stacks about the device. */ err = - register_netdevice (dev); assert_perror (err); }