📄 sk_mca.c
字号:
InitDscrs(dev); /* next RX descriptor to be read is the first one. Since the LANCE will start from the beginning after initialization, we have to reset out pointers too. */ priv->nextrx = 0; /* no TX descriptors active */ priv->nexttxput = priv->nexttxdone = priv->txbusy = 0; /* set up the LANCE bus control register - constant for SKnet boards */ SetLANCE(dev, LANCE_CSR3, CSR3_BSWAP_OFF | CSR3_ALE_LOW | CSR3_BCON_HOLD); /* write address of initialization block into LANCE */ SetLANCE(dev, LANCE_CSR1, RAM_INITBASE & 0xffff); SetLANCE(dev, LANCE_CSR2, (RAM_INITBASE >> 16) & 0xff); /* we don't get ready until the LANCE has read the init block */#if (LINUX_VERSION_CODE >= 0x02032a) netif_stop_queue(dev);#else dev->tbusy = 1;#endif /* let LANCE read the initialization block. LANCE is ready when we receive the corresponding interrupt. */ SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_INIT);}/* stop the LANCE so we can reinitialize it */static void StopLANCE(struct SKMCA_NETDEV *dev){ /* can't take frames any more */#if (LINUX_VERSION_CODE >= 0x02032a) netif_stop_queue(dev);#else dev->tbusy = 1;#endif /* disable interrupts, stop it */ SetLANCE(dev, LANCE_CSR0, CSR0_STOP);}/* initialize card and LANCE for proper operation */static void InitBoard(struct SKMCA_NETDEV *dev){ LANCE_InitBlock block; /* Lay out the shared RAM - first we create the init block for the LANCE. We do not overwrite it later because we need it again when we switch promiscous mode on/off. */ block.Mode = 0; if (dev->flags & IFF_PROMISC) block.Mode |= LANCE_INIT_PROM; memcpy(block.PAdr, dev->dev_addr, 6); memset(block.LAdrF, 0, sizeof(block.LAdrF)); block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29); block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29); SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block)); /* initialize LANCE. Implicitly sets up other structures in RAM. */ InitLANCE(dev);}/* deinitialize card and LANCE */static void DeinitBoard(struct SKMCA_NETDEV *dev){ /* stop LANCE */ StopLANCE(dev); /* reset board */ ResetBoard(dev);}/* probe for device's irq */static int ProbeIRQ(struct SKMCA_NETDEV *dev){ unsigned long imaskval, njiffies, irq; u16 csr0val; /* enable all interrupts */ imaskval = probe_irq_on(); /* initialize the board. Wait for interrupt 'Initialization done'. */ ResetBoard(dev); InitBoard(dev); njiffies = jiffies + 100; do { csr0val = GetLANCE(dev, LANCE_CSR0); } while (((csr0val & CSR0_IDON) == 0) && (jiffies != njiffies)); /* turn of interrupts again */ irq = probe_irq_off(imaskval); /* if we found something, ack the interrupt */ if (irq) SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_IDON); /* back to idle state */ DeinitBoard(dev); return irq;}/* ------------------------------------------------------------------------ * interrupt handler(s) * ------------------------------------------------------------------------ *//* LANCE has read initialization block -> start it */static u16 irqstart_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){ /* now we're ready to transmit */#if (LINUX_VERSION_CODE >= 0x02032a) netif_wake_queue(dev);#else dev->tbusy = 0;#endif /* reset IDON bit, start LANCE */ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT); return GetLANCE(dev, LANCE_CSR0);}/* did we loose blocks due to a FIFO overrun ? */static u16 irqmiss_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){ skmca_priv *priv = (skmca_priv *) dev->priv; /* update statistics */ priv->stat.rx_fifo_errors++; /* reset MISS bit */ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_MISS); return GetLANCE(dev, LANCE_CSR0);}/* receive interrupt */static u16 irqrx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){ skmca_priv *priv = (skmca_priv *) dev->priv; LANCE_RxDescr descr; unsigned int descraddr; /* run through queue until we reach a descriptor we do not own */ descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr)); while (1) { /* read descriptor */ SKMCA_FROMIO(&descr, dev->mem_start + descraddr, sizeof(LANCE_RxDescr)); /* if we reach a descriptor we do not own, we're done */ if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0) break;#ifdef DEBUG PrTime(); printk("Receive packet on descr %d len %d\n", priv->nextrx, descr.Len);#endif /* erroneous packet ? */ if ((descr.Flags & RXDSCR_FLAGS_ERR) != 0) { priv->stat.rx_errors++; if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0) priv->stat.rx_crc_errors++; else if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0) priv->stat.rx_frame_errors++; else if ((descr.Flags & RXDSCR_FLAGS_OFLO) != 0) priv->stat.rx_fifo_errors++; } /* good packet ? */ else { struct sk_buff *skb; skb = dev_alloc_skb(descr.Len + 2); if (skb == NULL) priv->stat.rx_dropped++; else { SKMCA_FROMIO(skb_put(skb, descr.Len), dev->mem_start + descr.LowAddr, descr.Len); skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; priv->stat.rx_packets++;#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */ priv->stat.rx_bytes += descr.Len;#endif netif_rx(skb); } } /* give descriptor back to LANCE */ descr.Len = 0; descr.Flags |= RXDSCR_FLAGS_OWN; /* update descriptor in shared RAM */ SKMCA_TOIO(dev->mem_start + descraddr, &descr, sizeof(LANCE_RxDescr)); /* go to next descriptor */ priv->nextrx++; descraddr += sizeof(LANCE_RxDescr); if (priv->nextrx >= RXCOUNT) { priv->nextrx = 0; descraddr = RAM_RXBASE; } } /* reset RINT bit */ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_RINT); return GetLANCE(dev, LANCE_CSR0);}/* transmit interrupt */static u16 irqtx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0){ skmca_priv *priv = (skmca_priv *) dev->priv; LANCE_TxDescr descr; unsigned int descraddr; /* check descriptors at most until no busy one is left */ descraddr = RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr)); while (priv->txbusy > 0) { /* read descriptor */ SKMCA_FROMIO(&descr, dev->mem_start + descraddr, sizeof(LANCE_TxDescr)); /* if the LANCE still owns this one, we've worked out all sent packets */ if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0) break;#ifdef DEBUG PrTime(); printk("Send packet done on descr %d\n", priv->nexttxdone);#endif /* update statistics */ if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) { priv->stat.tx_packets++;#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */ priv->stat.tx_bytes++;#endif } else { priv->stat.tx_errors++; if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) { priv->stat.tx_fifo_errors++; InitLANCE(dev); } else if ((descr.Status & TXDSCR_STATUS_LCOL) != 0) priv->stat.tx_window_errors++; else if ((descr.Status & TXDSCR_STATUS_LCAR) != 0) priv->stat.tx_carrier_errors++; else if ((descr.Status & TXDSCR_STATUS_RTRY) != 0) priv->stat.tx_aborted_errors++; } /* go to next descriptor */ priv->nexttxdone++; descraddr += sizeof(LANCE_TxDescr); if (priv->nexttxdone >= TXCOUNT) { priv->nexttxdone = 0; descraddr = RAM_TXBASE; } priv->txbusy--; } /* reset TX interrupt bit */ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_TINT); oldcsr0 = GetLANCE(dev, LANCE_CSR0); /* at least one descriptor is freed. Therefore we can accept a new one */ /* inform upper layers we're in business again */#if (LINUX_VERSION_CODE >= 0x02032a) netif_wake_queue(dev);#else dev->tbusy = 0; mark_bh(NET_BH);#endif return oldcsr0;}/* general interrupt entry */static void irq_handler(int irq, void *device, struct pt_regs *regs){ struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) device; u16 csr0val; /* read CSR0 to get interrupt cause */ csr0val = GetLANCE(dev, LANCE_CSR0); /* in case we're not meant... */ if ((csr0val & CSR0_INTR) == 0) return;#if (LINUX_VERSION_CODE >= 0x02032a)#if 0 set_bit(LINK_STATE_RXSEM, &dev->state);#endif#else dev->interrupt = 1;#endif /* loop through the interrupt bits until everything is clear */ do { if ((csr0val & CSR0_IDON) != 0) csr0val = irqstart_handler(dev, csr0val); if ((csr0val & CSR0_RINT) != 0) csr0val = irqrx_handler(dev, csr0val); if ((csr0val & CSR0_MISS) != 0) csr0val = irqmiss_handler(dev, csr0val); if ((csr0val & CSR0_TINT) != 0) csr0val = irqtx_handler(dev, csr0val); if ((csr0val & CSR0_MERR) != 0) { SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_MERR); csr0val = GetLANCE(dev, LANCE_CSR0); } if ((csr0val & CSR0_BABL) != 0) { SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_BABL); csr0val = GetLANCE(dev, LANCE_CSR0); } } while ((csr0val & CSR0_INTR) != 0);#if (LINUX_VERSION_CODE >= 0x02032a)#if 0 clear_bit(LINK_STATE_RXSEM, &dev->state);#endif#else dev->interrupt = 0;#endif}/* ------------------------------------------------------------------------ * driver methods * ------------------------------------------------------------------------ *//* MCA info */static int skmca_getinfo(char *buf, int slot, void *d){ int len = 0, i; struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) d; skmca_priv *priv; /* can't say anything about an uninitialized device... */ if (dev == NULL) return len; if (dev->priv == NULL) return len; priv = (skmca_priv *) dev->priv; /* print info */ len += sprintf(buf + len, "IRQ: %d\n", priv->realirq); len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start, dev->mem_end - 1); len += sprintf(buf + len, "Transceiver: %s\n", MediaNames[priv->medium]); len += sprintf(buf + len, "Device: %s\n", dev->name); len += sprintf(buf + len, "MAC address:"); for (i = 0; i < 6; i++) len += sprintf(buf + len, " %02x", dev->dev_addr[i]); buf[len++] = '\n'; buf[len] = 0; return len;}/* open driver. Means also initialization and start of LANCE */static int skmca_open(struct SKMCA_NETDEV *dev){ int result; skmca_priv *priv = (skmca_priv *) dev->priv; /* register resources - only necessary for IRQ */ result = request_irq(priv->realirq, irq_handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "sk_mca", dev); if (result != 0) { printk("%s: failed to register irq %d\n", dev->name, dev->irq); return result;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -