📄 depca.c
字号:
** 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 device *dev);static int depca_start_xmit(struct sk_buff *skb, struct device *dev);static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int depca_close(struct device *dev);static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd);static struct net_device_stats *depca_get_stats(struct device *dev);static void set_multicast_list(struct device *dev);/*** Private functions*/static int depca_hw_init(struct device *dev, u_long ioaddr, int mca_slot);static void depca_init_ring(struct device *dev);static int depca_rx(struct device *dev);static int depca_tx(struct device *dev);static void LoadCSRs(struct device *dev);static int InitRestartDepca(struct device *dev);static void DepcaSignature(char *name, u_long paddr);static int DevicePresent(u_long ioaddr);static int get_hw_addr(struct device *dev);static int EISA_signature(char *name, s32 eisa_id);static void SetMulticastFilter(struct device *dev);static void isa_probe(struct device *dev, u_long iobase);static void eisa_probe(struct device *dev, u_long iobase);#ifdef CONFIG_MCA static void mca_probe(struct device *dev, u_long iobase);#endifstatic struct device *alloc_device(struct device *dev, u_long iobase);static int depca_dev_index(char *s);static struct device *insert_device(struct device *dev, u_long iobase, int (*init)(struct device *));static int load_packet(struct device *dev, struct sk_buff *skb);static void depca_dbg_open(struct 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 = 0, loading_module = 0;#endif /* MODULE */static char name[DEPCA_STRLEN];static int num_depcas = 0, num_eth = 0;static int mem=0; /* 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)__initfunc(intdepca_probe(struct 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;}__initfunc(static intdepca_hw_init(struct 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) { 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) { /* found a DEPCA device */ 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) { /* 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 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; sprintf(lp->adapter_name,"%s (%s)", name, dev->name); request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name); /* Initialisation Block */ lp->sh_mem = mem_start; mem_start += sizeof(struct depca_init); /* Tx & Rx descriptors (aligned to a quadword boundary) */ mem_start = (mem_start + ALIGN) & ~ALIGN; lp->rx_ring = (struct depca_rx_desc *)mem_start; mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); lp->tx_ring = (struct depca_tx_desc *)mem_start; mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); lp->bus_offset = mem_start & 0x00ff0000; mem_start &= LA_MASK; /* LANCE re-mapped start address */ lp->dma_buffs = mem_start; /* 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) release_region(ioaddr, DEPCA_TOTAL_SIZE); } else { printk(",\n requests %dkB RAM: only %dkB is available!\n", (mem_len>>10), netRAM); status = -ENXIO; } } else { printk(" which has an Ethernet PROM CRC error.\n"); status = -ENXIO; } } else { status = -ENXIO; } 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->mem_start = 0; /* Fill in the generic field of the device structure. */ ether_setup(dev); } else { /* Incorrectly initialised hardware */ if (dev->priv) { kfree_s(dev->priv, sizeof(struct depca_private)); dev->priv = NULL; } } } else { status = -ENXIO; } return status;}static intdepca_open(struct 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 (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); dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; 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 device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_int i; u_long p; /* Lock out other processes whilst setting up the hardware */ test_and_set_bit(0, (void *)&dev->tbusy); lp->rx_new = lp->tx_new = 0; lp->rx_old = lp->tx_old = 0; /* Initialize the base addresses and length of each buffer in the ring */ for (i = 0; i <= lp->rxRingMask; i++) { writel((p=lp->dma_buffs+i*RX_BUFF_SZ) | R_OWN, &lp->rx_ring[i].base); writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); lp->rx_memcpy[i]=(char *)(p+lp->bus_offset); } for (i = 0; i <= lp->txRingMask; i++) { writel((p=lp->dma_buffs+(i+lp->txRingMask+1)*TX_BUFF_SZ) & 0x00ffffff, &lp->tx_ring[i].base); lp->tx_memcpy[i]=(char *)(p+lp->bus_offset); } /* Set up the initialization block */ lp->init_block.rx_ring = ((u32)((u_long)lp->rx_ring)&LA_MASK) | lp->rx_rlen; lp->init_block.tx_ring = ((u32)((u_long)lp->tx_ring)&LA_MASK) | lp->tx_rlen; SetMulticastFilter(dev); for (i = 0; i < ETH_ALEN; i++) { lp->init_block.phys_addr[i] = dev->dev_addr[i]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -