📄 com90xx.c
字号:
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 void arc90xx_rx(struct device *dev, int recbuf){ struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int ioaddr = dev->base_addr; 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 void arc90xx_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, arc90xx_probe};int init_module(void){ struct device *dev = &thiscard; if (device) strcpy(dev->name, device); else arcnet_makename(dev->name); dev->base_addr = io; 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 defined(IO_MAPPED_BUFFERS) && !defined(COM20020) /* Set the thing back to MMAP mode, in case the old driver is loaded later */ outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);#endif } if (dev->irq) { free_irq(dev->irq, dev); } if (dev->base_addr) release_region(dev->base_addr, ARCNET_TOTAL_SIZE); unregister_netdev(dev); kfree(dev->priv); dev->priv = NULL; arcnet_use_count(0);}#else__initfunc(void com90xx_setup(char *str, int *ints)){ struct device *dev; if (arcnet_num_devs == MAX_ARCNET_DEVS) { printk("com90xx: Too many ARCnet devices registered (max %d).\n", MAX_ARCNET_DEVS); return; } if (!ints[0] && (!str || !*str)) { printk("com90xx: Disabled.\n"); com90xx_explicit++; return; } dev = &arcnet_devs[arcnet_num_devs]; dev->dev_addr[3] = 3; dev->init = arc90xx_probe; switch (ints[0]) { case 4: /* ERROR */ printk("com20020: Too many arguments.\n"); case 3: /* Mem address */ dev->mem_start = ints[3]; case 2: /* IRQ */ dev->irq = ints[2]; case 1: /* IO address */ dev->base_addr = 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 + -