📄 depca.c
字号:
} pktStats; int txRingMask; /* TX ring mask */ int rxRingMask; /* RX ring mask */ s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */};/*** The transmit ring full condition is described by the tx_old and tx_new** pointers by:** tx_old = tx_new Empty ring** tx_old = tx_new+1 Full ring** tx_old+txRingMask = tx_new Full ring (wrapped condition)*/#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ lp->tx_old+lp->txRingMask-lp->tx_new:\ lp->tx_old -lp->tx_new-1)/*** Public Functions*/static int depca_open(struct net_device *dev);static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev);static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int depca_close(struct net_device *dev);static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static void depca_tx_timeout (struct net_device *dev);static struct net_device_stats *depca_get_stats(struct net_device *dev);static void set_multicast_list(struct net_device *dev);/*** Private functions*/static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot);static void depca_init_ring(struct net_device *dev);static int depca_rx(struct net_device *dev);static int depca_tx(struct net_device *dev);static void LoadCSRs(struct net_device *dev);static int InitRestartDepca(struct net_device *dev);static void DepcaSignature(char *name, u_long paddr);static int DevicePresent(u_long ioaddr);static int get_hw_addr(struct net_device *dev);static int EISA_signature(char *name, s32 eisa_id);static void SetMulticastFilter(struct net_device *dev);static void isa_probe(struct net_device *dev, u_long iobase);static void eisa_probe(struct net_device *dev, u_long iobase);#ifdef CONFIG_MCA static void mca_probe(struct net_device *dev, u_long iobase);#endifstatic struct net_device *alloc_device(struct net_device *dev, u_long iobase);static int depca_dev_index(char *s);static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *));static int load_packet(struct net_device *dev, struct sk_buff *skb);static void depca_dbg_open(struct net_device *dev);#ifdef MODULEint init_module(void);void cleanup_module(void);static int autoprobed = 1, loading_module = 1;# elsestatic u_char de1xx_irq[] __initdata = {2,3,4,5,7,9,0};static u_char de2xx_irq[] __initdata = {5,9,10,11,15,0};static u_char de422_irq[] __initdata = {5,9,10,11,0};static u_char *depca_irq;static int autoprobed, loading_module;#endif /* MODULE */static char name[DEPCA_STRLEN];static int num_depcas, num_eth;static int mem; /* For loadable module assignment use insmod mem=0x????? .... */static char *adapter_name = '\0'; /* If no PROM when loadable module use insmod adapter_name=DE??? ... *//*** Miscellaneous defines...*/#define STOP_DEPCA \ outw(CSR0, DEPCA_ADDR);\ outw(STOP, DEPCA_DATA)int __init depca_probe(struct net_device *dev){ int tmp = num_depcas, status = -ENODEV; u_long iobase = dev->base_addr; if ((iobase == 0) && loading_module){ printk("Autoprobing is not supported when loading a module based driver.\n"); status = -EIO; } else {#ifdef CONFIG_MCA mca_probe(dev, iobase);#endif isa_probe(dev, iobase); eisa_probe(dev, iobase); if ((tmp == num_depcas) && (iobase != 0) && loading_module) { printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase); } /* ** Walk the device list to check that at least one device ** initialised OK */ for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next); if (dev->priv) status = 0; if (iobase == 0) autoprobed = 1; } return status;}static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot){ struct depca_private *lp; int i, j, offset, netRAM, mem_len, status=0; s16 nicsr; u_long mem_start=0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; STOP_DEPCA; nicsr = inb(DEPCA_NICSR); nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM); outb(nicsr, DEPCA_NICSR); if (inw(DEPCA_DATA) != STOP) { return -ENXIO; } do { strcpy(name, (adapter_name ? adapter_name : "")); mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]); DepcaSignature(name, mem_start); } while (!mem && mem_base[mem_chkd] && (adapter == unknown)); if ((adapter == unknown) || !mem_start) { /* DEPCA device not found */ return -ENXIO; } dev->base_addr = ioaddr; if (mca_slot != -1) { printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot); } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int)((ioaddr>>12)&0x0f)); } else { /* ISA port address */ printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); } printk(", h/w address "); status = get_hw_addr(dev); for (i=0; i<ETH_ALEN - 1; i++) { /* get the ethernet address */ printk("%2.2x:", dev->dev_addr[i]); } printk("%2.2x", dev->dev_addr[i]); if (status != 0) { printk(" which has an Ethernet PROM CRC error.\n"); return -ENXIO; } /* Set up the maximum amount of network RAM(kB) */ netRAM = ((adapter != DEPCA) ? 64 : 48); if ((nicsr & _128KB) && (adapter == de422)) netRAM = 128; offset = 0x0000; /* Shared Memory Base Address */ if (nicsr & BUF) { offset = 0x8000; /* 32kbyte RAM offset*/ nicsr &= ~BS; /* DEPCA RAM in top 32k */ netRAM -= 32; } mem_start += offset; /* (E)ISA start address */ if ((mem_len = (NUM_RX_DESC*(sizeof(struct depca_rx_desc)+RX_BUFF_SZ) + NUM_TX_DESC*(sizeof(struct depca_tx_desc)+TX_BUFF_SZ) + sizeof(struct depca_init))) > (netRAM<<10)) { printk(",\n requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM); return -ENXIO; } printk(",\n has %dkB RAM at 0x%.5lx", netRAM, mem_start); /* Enable the shadow RAM. */ if (adapter != DEPCA) { nicsr |= SHE; outb(nicsr, DEPCA_NICSR); } /* Define the device private memory */ dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; lp = (struct depca_private *)dev->priv; memset((char *)dev->priv, 0, sizeof(struct depca_private)); lp->adapter = adapter; lp->mca_slot = mca_slot; lp->lock = SPIN_LOCK_UNLOCKED; sprintf(lp->adapter_name,"%s (%s)", name, dev->name); if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) { printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", DEPCA_TOTAL_SIZE, ioaddr); return -EBUSY; } /* Initialisation Block */ lp->sh_mem = ioremap(mem_start, mem_len); if (lp->sh_mem == NULL) { printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n"); return -EIO; } lp->device_ram_start = mem_start & LA_MASK; offset = 0; offset += sizeof(struct depca_init); /* Tx & Rx descriptors (aligned to a quadword boundary) */ offset = (offset + ALIGN) & ~ALIGN; lp->rx_ring = (struct depca_rx_desc *)(lp->sh_mem + offset); lp->rx_ring_offset = offset; offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); lp->tx_ring = (struct depca_tx_desc *)(lp->sh_mem + offset); lp->tx_ring_offset = offset; offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); lp->buffs_offset = offset; /* Finish initialising the ring information. */ lp->rxRingMask = NUM_RX_DESC - 1; lp->txRingMask = NUM_TX_DESC - 1; /* Calculate Tx/Rx RLEN size for the descriptors. */ for (i=0, j = lp->rxRingMask; j>0; i++) { j >>= 1; } lp->rx_rlen = (s32)(i << 29); for (i=0, j = lp->txRingMask; j>0; i++) { j >>= 1; } lp->tx_rlen = (s32)(i << 29); /* Load the initialisation block */ depca_init_ring(dev); /* Initialise the control and status registers */ LoadCSRs(dev); /* Enable DEPCA board interrupts for autoprobing */ nicsr = ((nicsr & ~IM)|IEN); outb(nicsr, DEPCA_NICSR); /* To auto-IRQ we enable the initialization-done and DMA err, interrupts. For now we will always get a DMA error. */ if (dev->irq < 2) {#ifndef MODULE unsigned char irqnum; autoirq_setup(0); /* Assign the correct irq list */ switch (lp->adapter) { case DEPCA: case de100: case de101: depca_irq = de1xx_irq; break; case de200: case de201: case de202: case de210: case de212: depca_irq = de2xx_irq; break; case de422: depca_irq = de422_irq; break; } /* Trigger an initialization just for the interrupt. */ outw(INEA | INIT, DEPCA_DATA); irqnum = autoirq_report(1); if (!irqnum) { printk(" and failed to detect IRQ line.\n"); status = -ENXIO; } else { for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) { if (irqnum == depca_irq[i]) { dev->irq = irqnum; printk(" and uses IRQ%d.\n", dev->irq); } } if (!dev->irq) { printk(" but incorrect IRQ line detected.\n"); status = -ENXIO; } }#endif /* MODULE */ } else { printk(" and assigned IRQ%d.\n", dev->irq); } if (!status) { if (depca_debug > 1) { printk(version); } /* The DEPCA-specific entries in the device structure. */ dev->open = &depca_open; dev->hard_start_xmit = &depca_start_xmit; dev->stop = &depca_close; dev->get_stats = &depca_get_stats; dev->set_multicast_list = &set_multicast_list; dev->do_ioctl = &depca_ioctl; dev->tx_timeout = depca_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->mem_start = 0; /* Fill in the generic field of the device structure. */ ether_setup(dev); } else { /* Incorrectly initialised hardware */ release_region(ioaddr, DEPCA_TOTAL_SIZE); if (dev->priv) { kfree(dev->priv); dev->priv = NULL; } } return status;}static intdepca_open(struct net_device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; s16 nicsr; int status = 0; STOP_DEPCA; nicsr = inb(DEPCA_NICSR); /* Make sure the shadow RAM is enabled */ if (lp->adapter != DEPCA) { nicsr |= SHE; outb(nicsr, DEPCA_NICSR); } /* Re-initialize the DEPCA... */ depca_init_ring(dev); LoadCSRs(dev); depca_dbg_open(dev); if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); status = -EAGAIN; } else { /* Enable DEPCA board interrupts and turn off LED */ nicsr = ((nicsr & ~IM & ~LED)|IEN); outb(nicsr, DEPCA_NICSR); outw(CSR0,DEPCA_ADDR); netif_start_queue(dev); status = InitRestartDepca(dev); if (depca_debug > 1){ printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); } } MOD_INC_USE_COUNT; return status;}/* Initialize the lance Rx and Tx descriptor rings. */static voiddepca_init_ring(struct net_device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_int i; u_long offset; /* Lock out other processes whilst setting up the hardware */ netif_stop_queue(dev); lp->rx_new = lp->tx_new = 0; lp->rx_old = lp->tx_old = 0; /* Initialize the base address and length of each buffer in the ring */ for (i = 0; i <= lp->rxRingMask; i++) { offset = lp->buffs_offset + i*RX_BUFF_SZ; writel((lp->device_ram_start + offset) | R_OWN,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -