📄 arc-rimi.c
字号:
if (lp->lasttrans_dest != 0) { BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", status,lp->lasttrans_dest); lp->stats.tx_errors++; lp->stats.tx_carrier_errors++; } else { BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", status, lp->lasttrans_dest); } } /* send packet if there is one */ arcnet_go_tx(dev,0); didsomething++; if (lp->intx) { BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n", ARCSTATUS,lp->intx); lp->in_txhandler--; continue; } if (!lp->outgoing.skb) { BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n"); /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); lp->in_txhandler--; continue; } /* if more than one segment, and not all segments * are done, then continue xmit. */ if (out->segnum<out->numsegs) arcnetA_continue_tx(dev); arcnet_go_tx(dev,0); /* if segnum==numsegs, the transmission is finished; * free the skb. */ if (out->segnum>=out->numsegs) { /* transmit completed */ out->segnum++; if (out->skb) { lp->stats.tx_bytes += out->skb->len; dev_kfree_skb(out->skb); } out->skb=NULL; /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); } didsomething++; lp->in_txhandler--; } else if (lp->txready && !lp->sending && !lp->intx) { BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n", status); arcnet_go_tx(dev,0); didsomething++; }#ifdef DETECT_RECONFIGS if (status & (lp->intmask) & RECONflag) { ACOMMAND(CFLAGScmd|CONFIGclear); lp->stats.tx_carrier_errors++;#ifdef SHOW_RECONFIGS BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n", status);#endif /* SHOW_RECONFIGS */#ifdef RECON_THRESHOLD /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || jiffies-lp->last_recon > HZ*10) { if (lp->network_down) BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n"); lp->first_recon=lp->last_recon=jiffies; lp->num_recons=lp->network_down=0; BUGMSG(D_DURING,"recon: clearing counters.\n"); } else /* add to current RECON counter */ { lp->last_recon=jiffies; lp->num_recons++; BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n", lp->num_recons, (lp->last_recon-lp->first_recon)/HZ, lp->network_down); /* if network is marked up; * and first_recon and last_recon are 60+ sec * apart; * and the average no. of recons counted is * > RECON_THRESHOLD/min; * then print a warning message. */ if (!lp->network_down && (lp->last_recon-lp->first_recon)<=HZ*60 && lp->num_recons >= RECON_THRESHOLD) { lp->network_down=1; BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n"); } else if (!lp->network_down && lp->last_recon-lp->first_recon > HZ*60) { /* reset counters if we've gone for * over a minute. */ lp->first_recon=lp->last_recon; lp->num_recons=1; } } } else if (lp->network_down && jiffies-lp->last_recon > HZ*10) { if (lp->network_down) BUGMSG(D_NORMAL,"cabling restored?\n"); lp->first_recon=lp->last_recon=0; lp->num_recons=lp->network_down=0; BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");#endif }#endif /* DETECT_RECONFIGS */ } while (--boguscount && didsomething); BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n", ARCSTATUS,boguscount); BUGMSG(D_DURING,"\n"); SETMASK; /* put back interrupt mask */}/* A packet has arrived; grab it from the buffers and pass it to the generic * arcnet_rx routing to deal with it. */static voidarcrimi_rx(struct device *dev,int recbuf){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; int ioaddr=dev->mem_start+0x800; union ArcPacket *arcpacket= (union ArcPacket *)phys_to_virt(dev->mem_start+recbuf*512); u_char *arcsoft; short length,offset; u_char daddr,saddr; lp->stats.rx_packets++; saddr=arcpacket->hardheader.source; /* if source is 0, it's a "used" packet! */ if (saddr==0) { BUGMSG(D_NORMAL,"discarding old packet. (status=%Xh)\n", ARCSTATUS); lp->stats.rx_errors++; return; } /* Set source address to zero to mark it as old */ arcpacket->hardheader.source=0; daddr=arcpacket->hardheader.destination; if (arcpacket->hardheader.offset1) /* Normal Packet */ { offset=arcpacket->hardheader.offset1; arcsoft=&arcpacket->raw[offset]; length=256-offset; } else /* ExtendedPacket or ExceptionPacket */ { offset=arcpacket->hardheader.offset2; arcsoft=&arcpacket->raw[offset]; length=512-offset; } arcnet_rx(lp, arcsoft, length, saddr, daddr); BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");#ifndef SLOW_XMIT_COPY /* clean out the page to make debugging make more sense :) */ BUGLVL(D_DURING) memset((void *)arcpacket->raw,0x42,512);#endif}/* Given an skb, copy a packet into the ARCnet buffers for later transmission * by arcnet_go_tx. */static voidarcrimi_prepare_tx(struct device *dev,u_char *hdr,int hdrlen, char *data,int length,int daddr,int exceptA, int offset){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; union ArcPacket *arcpacket = (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));#ifdef SLOW_XMIT_COPY char *iptr,*iend,*optr;#endif lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */ length+=hdrlen; BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n", hdr,length,data);#ifndef SLOW_XMIT_COPY /* clean out the page to make debugging make more sense :) */ BUGLVL(D_DURING) memset_io(dev->mem_start+lp->txbuf*512,0x42,512);#endif arcpacket->hardheader.destination=daddr; /* load packet into shared memory */ if (length<=MTU) /* Normal (256-byte) Packet */ arcpacket->hardheader.offset1=offset=offset?offset:256-length; else if (length>=MinTU || offset) /* Extended (512-byte) Packet */ { arcpacket->hardheader.offset1=0; arcpacket->hardheader.offset2=offset=offset?offset:512-length; } else if (exceptA) /* RFC1201 Exception Packet */ { arcpacket->hardheader.offset1=0; arcpacket->hardheader.offset2=offset=512-length-4; /* exception-specific stuff - these four bytes * make the packet long enough to fit in a 512-byte * frame. */ arcpacket->raw[offset+0]=hdr[0]; arcpacket->raw[offset+1]=0xFF; /* FF flag */ arcpacket->raw[offset+2]=0xFF; /* FF padding */ arcpacket->raw[offset+3]=0xFF; /* FF padding */ offset+=4; } else /* "other" Exception packet */ { /* RFC1051 - set 4 trailing bytes to 0 */ memset(&arcpacket->raw[508],0,4); /* now round up to MinTU */ arcpacket->hardheader.offset1=0; arcpacket->hardheader.offset2=offset=512-MinTU; } /* copy the packet into ARCnet shmem * - the first bytes of ClientData header are skipped */ memcpy((u_char*)arcpacket+offset, (u_char*)hdr,hdrlen);#ifdef SLOW_XMIT_COPY for (iptr=data,iend=iptr+length-hdrlen,optr=(char *)arcpacket+offset+hdrlen; iptr<iend; iptr++,optr++) { *optr=*iptr; /*udelay(5);*/ }#else memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen);#endif BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n", daddr,length); BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx"); lp->lastload_dest=daddr; lp->txready=lp->txbuf; /* packet is ready for sending */}/**************************************************************************** * * * Kernel Loadable Module Support * * * ****************************************************************************/#ifdef MODULEstatic char devicename[9] = "";static struct device thiscard = { devicename, /* device name is inserted by linux/drivers/net/net_init.c */ 0, 0, 0, 0, 0, 0, /* I/O address, IRQ */ 0, 0, 0, NULL, arcrimi_probe};int init_module(void){ struct device *dev=&thiscard; if (device) strcpy(dev->name,device); else arcnet_makename(dev->name); if (node && node != 0xff) dev->dev_addr[0]=node; dev->irq=irq; if (dev->irq==2) dev->irq=9; if (shmem) { dev->mem_start=shmem; dev->mem_end=thiscard.mem_start+512*4-1; dev->rmem_start=thiscard.mem_start+512*0; dev->rmem_end=thiscard.mem_start+512*2-1; } if (register_netdev(dev) != 0) return -EIO; arcnet_use_count(1); return 0;}void cleanup_module(void){ struct device *dev=&thiscard; int ioaddr=dev->mem_start; if (dev->start) (*dev->stop)(dev); /* Flush TX and disable RX */ if (ioaddr) { AINTMASK(0); /* disable IRQ's */ ACOMMAND(NOTXcmd); /* stop transmit */ ACOMMAND(NORXcmd); /* disable receive */ } if (dev->irq) { free_irq(dev->irq,dev); } unregister_netdev(dev); kfree(dev->priv); dev->priv = NULL; arcnet_use_count(0);}#else__initfunc(void arcrimi_setup (char *str, int *ints)){ struct device *dev; if (arcnet_num_devs == MAX_ARCNET_DEVS) { printk("ARCnet RIM I: Too many ARCnet devices registered (max %d).\n", MAX_ARCNET_DEVS); return; } dev=&arcnet_devs[arcnet_num_devs]; if (ints[0] < 3) { printk("ARCnet RIM I: You must give address, IRQ and node ID.\n"); return; } dev->init=arcrimi_probe; switch(ints[0]) { case 4: /* ERROR */ printk("ARCnet RIM I: Too many arguments.\n"); case 3: /* Node ID */ dev->dev_addr[0]=(u_char)ints[3]; case 2: /* IRQ */ dev->irq=ints[2]; case 1: /* Mem address */ dev->mem_start=ints[1]; } dev->name = (char *)&arcnet_dev_names[arcnet_num_devs]; if (str) strncpy(dev->name, str, 9); arcnet_num_devs++;}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -