📄 arcnet.c
字号:
u_char daddr; short offset,length=skb->len+1; u_char proto=ARC_P_ETHER; lp->intx++; oldmask |= lp->intmask; lp->intmask=0; SETMASK; bad=arcnet_send_packet_bad(skb,dev); if (bad) { lp->intx--; lp->intmask=oldmask; SETMASK; return bad; } /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ lp->intmask=oldmask; SETMASK; if (length>XMTU) { BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n", length); BUGMSG(D_NORMAL,"transmit aborted.\n"); dev_kfree_skb(skb); lp->intx--; return 0; } BUGMSG(D_DURING,"starting tx sequence...\n"); /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */ if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF) daddr=0; else daddr=((struct ethhdr*)(skb->data))->h_dest[5]; /* load packet into shared memory */ offset=512-length; if (length>MTU) /* long/exception packet */ { if (length<MinTU) offset-=3; } else /* short packet */ { offset-=256; } BUGMSG(D_DURING," length=%Xh, offset=%Xh\n", length,offset); (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0, offset); dev_kfree_skb(skb); if (arcnet_go_tx(dev,1)) { /* inform upper layers */ arcnet_tx_done(lp->adev, lp); } dev->trans_start=jiffies; lp->intx--; /* make sure we didn't ignore a TX IRQ while we were in here */ lp->intmask |= TXFREEflag; SETMASK; return 0;}/* Packet receiver for ethernet-encap packets. */static voidarcnetE_rx(struct device *dev,u_char *arcsoft, int length,u_char saddr, u_char daddr){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; struct sk_buff *skb; BUGMSG(D_DURING,"it's an ethernet-encap packet (length=%d)\n", length); skb = alloc_skb(length, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); lp->stats.rx_dropped++; return; } skb_put(skb,length); skb->dev = dev; memcpy(skb->data,(u_char *)arcsoft+1,length-1); BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); lp->stats.rx_bytes += skb->len; skb->protocol=eth_type_trans(skb,dev); netif_rx(skb);}#endif /* CONFIG_ARCNET_ETH */#ifdef CONFIG_ARCNET_1051/**************************************************************************** * * * RFC1051 Support * * * ****************************************************************************//* Initialize the arc0s device. */static int arcnetS_init(struct device *dev){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; arcnet_setup(dev); /* And now fill particular fields with arcnet values */ dev->dev_addr[0]=lp->stationid; dev->hard_header_len=sizeof(struct S_ClientData); dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len + S_EXTRA_CLIENTDATA; dev->open=arcnetS_open_close; dev->stop=arcnetS_open_close; dev->hard_start_xmit=arcnetS_send_packet; dev->hard_header=arcnetS_header; dev->rebuild_header=arcnetS_rebuild_header; return 0;}/* Bring up/down the arc0s device - we don't actually have to do anything, * since our parent arc0 handles the card I/O itself. */static int arcnetS_open_close(struct device *dev){ return 0;}/* Called by the kernel in order to transmit an RFC1051-type packet. */static intarcnetS_send_packet(struct sk_buff *skb, struct device *dev){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; int bad,length; struct S_ClientData *hdr=(struct S_ClientData *)skb->data; lp->intx++; bad=arcnet_send_packet_bad(skb,dev); if (bad) { lp->intx--; return bad; } /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ length = 1 < skb->len ? skb->len : 1; BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx"); /* fits in one packet? */ if (length-S_EXTRA_CLIENTDATA<=XMTU) { (*lp->prepare_tx)(dev, skb->data+S_EXTRA_CLIENTDATA, sizeof(struct S_ClientData)-S_EXTRA_CLIENTDATA, skb->data+sizeof(struct S_ClientData), length-sizeof(struct S_ClientData), hdr->daddr,0,0); /* done right away */ dev_kfree_skb(skb); if (arcnet_go_tx(dev,1)) { /* inform upper layers */ arcnet_tx_done(lp->adev, lp); } } else /* too big for one - not accepted */ { BUGMSG(D_NORMAL,"packet too long (length=%d)\n", length); dev_kfree_skb(skb); lp->stats.tx_dropped++; arcnet_tx_done(lp->adev, lp); } dev->trans_start=jiffies; lp->intx--; /* make sure we didn't ignore a TX IRQ while we were in here */ lp->intmask |= TXFREEflag; SETMASK; return 0;}/* Packet receiver for RFC1051 packets; */static voidarcnetS_rx(struct device *dev,u_char *buf, int length,u_char saddr, u_char daddr){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; struct sk_buff *skb; struct S_ClientData *arcsoft,*soft; arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA); length+=S_EXTRA_CLIENTDATA; BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n", length); { /* was "if not split" in A protocol, S is never split */ skb = alloc_skb(length, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); lp->stats.rx_dropped++; return; } soft=(struct S_ClientData *)skb->data; skb_put(skb,length); memcpy((u_char *)soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA, (u_char *)arcsoft + sizeof(struct S_ClientData) -S_EXTRA_CLIENTDATA, length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA); soft->protocol_id=arcsoft->protocol_id; soft->daddr=daddr; soft->saddr=saddr; skb->dev = dev; /* is already lp->sdev */ BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); lp->stats.rx_bytes += skb->len; skb->protocol=arcnetS_type_trans(skb,dev); netif_rx(skb); }}/* Create the ARCnet ClientData header for an arbitrary protocol layer * * saddr=NULL means use device source address (always will anyway) * daddr=NULL means leave destination address (eg unresolved arp) */static int arcnetS_header(struct sk_buff *skb,struct device *dev, unsigned short type,void *daddr,void *saddr,unsigned len){ struct S_ClientData *head = (struct S_ClientData *) skb_push(skb,dev->hard_header_len); struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); /* set the protocol ID according to RFC1051 */ switch(type) { case ETH_P_IP: head->protocol_id=ARC_P_IP_RFC1051; BUGMSG(D_DURING,"S_header: IP_RFC1051 packet.\n"); break; case ETH_P_ARP: head->protocol_id=ARC_P_ARP_RFC1051; BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n"); break; default: BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n", type,type); lp->stats.tx_errors++; lp->stats.tx_aborted_errors++; return 0; } /* * Set the source hardware address. * * This is pretty pointless for most purposes, but it can help * in debugging. saddr is stored in the ClientData header and * removed before sending the packet (since ARCnet does not allow * us to change the source address in the actual packet sent) */ if(saddr) head->saddr=((u_char*)saddr)[0]; else head->saddr=((u_char*)(dev->dev_addr))[0]; /* supposedly if daddr is NULL, we should ignore it... */ if(daddr) { head->daddr=((u_char*)daddr)[0]; return dev->hard_header_len; } else head->daddr=0; /* better fill one in anyway */ return -dev->hard_header_len;}/* Rebuild the ARCnet ClientData header. This is called after an ARP * (or in future other address resolution) has completed on this * sk_buff. We now let ARP fill in the other fields. */static int arcnetS_rebuild_header(struct sk_buff *skb){ struct device *dev=skb->dev; struct S_ClientData *head = (struct S_ClientData *)skb->data; struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); /* * Only ARP and IP are currently supported */ if(head->protocol_id != ARC_P_IP_RFC1051) { BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n", head->protocol_id,head->protocol_id); lp->stats.tx_errors++; lp->stats.tx_aborted_errors++; head->daddr=0; /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/ return 0; } /* * Try to get ARP to resolve the header. */#ifdef CONFIG_INET return arp_find(&(head->daddr),skb)? 1 : 0;#else return 0;#endif}/* Determine a packet's protocol ID. * * With ARCnet we have to convert everything to Ethernet-style stuff. */unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev){ struct S_ClientData *head; struct arcnet_local *lp=(struct arcnet_local *) (dev->priv); /* Pull off the arcnet header. */ skb->mac.raw=skb->data; skb_pull(skb,dev->hard_header_len); head=(struct S_ClientData *)skb->mac.raw; if (head->daddr==0) skb->pkt_type=PACKET_BROADCAST; else if (dev->flags&IFF_PROMISC) { /* if we're not sending to ourselves :) */ if (head->daddr != dev->dev_addr[0]) skb->pkt_type=PACKET_OTHERHOST; } /* now return the protocol number */ switch (head->protocol_id) { case ARC_P_IP_RFC1051: return htons(ETH_P_IP); case ARC_P_ARP_RFC1051: return htons(ETH_P_ARP); case ARC_P_ATALK: return htons(ETH_P_ATALK); /* untested appletalk */ default: lp->stats.rx_errors++; lp->stats.rx_crc_errors++; return 0; } return htons(ETH_P_IP);}#endif /* CONFIG_ARCNET_1051 *//**************************************************************************** * * * Kernel Loadable Module Support * * * ****************************************************************************/#ifdef MODULEvoid cleanup_module(void){ printk("Generic arcnet support removed.\n");}void arcnet_use_count(int open){ if (open) MOD_INC_USE_COUNT; else MOD_DEC_USE_COUNT;}#elsevoid arcnet_use_count(int open){}struct device arcnet_devs[MAX_ARCNET_DEVS];int arcnet_num_devs=0;char arcnet_dev_names[MAX_ARCNET_DEVS][10];__initfunc(void arcnet_init(void)){ int c; init_module(); /* Don't register_netdev here. The chain hasn't been initialised. */#ifdef CONFIG_ARCNET_COM90xx if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS) { arcnet_devs[arcnet_num_devs].init=arc90xx_probe; arcnet_devs[arcnet_num_devs].name= (char *)&arcnet_dev_names[arcnet_num_devs]; arcnet_num_devs++; }#endif if (!arcnet_num_devs) { printk("Don't forget to load the chipset driver.\n"); return; } /* Link into the device chain */ /* Q: Should we put ourselves at the beginning or the end of the chain? */ /* Probably the end, because we're not so fast, but... */ for (c=0; c< (arcnet_num_devs-1); c++) arcnet_devs[c].next=&arcnet_devs[c+1]; arcnet_devs[c].next=dev_base; dev_base=&arcnet_devs[0]; /* Give names to those without them */ for (c=0; c< arcnet_num_devs; c++) if (!arcnet_dev_names[c][0]) arcnet_makename((char *)&arcnet_dev_names[c]);}#endif /* MODULE */#ifdef MODULEint init_module(void)#else__initfunc(static int init_module(void))#endif{#ifdef ALPHA_WARNING BUGLVL(D_EXTRA) { printk("arcnet: ***\n"); printk("arcnet: * Read arcnet.txt for important release notes!\n"); printk("arcnet: *\n"); printk("arcnet: * This is an ALPHA version! (Last stable release: v2.56) E-mail me if\n"); printk("arcnet: * you have any questions, comments, or bug reports.\n"); printk("arcnet: ***\n"); }#endif printk("%sAvailable protocols: ARCnet RFC1201"#ifdef CONFIG_ARCNET_ETH ", Ethernet-Encap"#endif#ifdef CONFIG_ARCNET_1051 ", ARCnet RFC1051"#endif#ifdef MODULE ".\nDon't forget to load the chipset driver"#endif ".\n",version); return 0;}void arcnet_makename(char *device){ struct device *dev; int arcnum; arcnum = 0; for (;;) { sprintf(device, "arc%d", arcnum); for (dev = dev_base; dev; dev=dev->next) if (dev->name != device && !strcmp(dev->name, device)) break; if (!dev) return; arcnum++; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -