📄 depca.c
字号:
(*(s16 *)&buf[4] == -1)) { lp->pktStats.broadcast++; } else { lp->pktStats.multicast++; } } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) && (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) && (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { lp->pktStats.unicast++; } lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ if (lp->pktStats.bins[0] == 0) { /* Reset counters */ memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); } } else { printk("%s: Memory squeeze, deferring packet.\n", dev->name); lp->stats.rx_dropped++; /* Really, deferred. */ break; } } /* Change buffer ownership for this last frame, back to the adapter */ for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) { writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base); } writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); } /* ** Update entry information */ lp->rx_new = (++lp->rx_new) & lp->rxRingMask; } return 0;}/*** Buffer sent - check for buffer errors.*/static intdepca_tx(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; int entry; s32 status; u_long ioaddr = dev->base_addr; for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { status = readl(&lp->tx_ring[entry].base) >> 16 ; if (status < 0) { /* Packet not yet sent! */ break; } else if (status & T_ERR) { /* An error occurred. */ status = readl(&lp->tx_ring[entry].misc); lp->stats.tx_errors++; if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; if (status & TMD3_LCOL) lp->stats.tx_window_errors++; if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++; if (status & (TMD3_BUFF | TMD3_UFLO)) { /* Trigger an immediate send demand. */ outw(CSR0, DEPCA_ADDR); outw(INEA | TDMD, DEPCA_DATA); } } else if (status & (T_MORE | T_ONE)) { lp->stats.collisions++; } else { lp->stats.tx_packets++; } /* Update all the pointers */ lp->tx_old = (++lp->tx_old) & lp->txRingMask; } return 0;}static intdepca_close(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; s16 nicsr; u_long ioaddr = dev->base_addr; dev->start = 0; dev->tbusy = 1; outw(CSR0, DEPCA_ADDR); if (depca_debug > 1) { printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA)); } /* ** We stop the DEPCA here -- it occasionally polls ** memory if we don't. */ outw(STOP, DEPCA_DATA); /* ** Give back the ROM in case the user wants to go to DOS */ if (lp->adapter != DEPCA) { nicsr = inb(DEPCA_NICSR); nicsr &= ~SHE; outb(nicsr, DEPCA_NICSR); } /* ** Free the associated irq */ free_irq(dev->irq, NULL); irq2dev_map[dev->irq] = NULL; MOD_DEC_USE_COUNT; return 0;}static void LoadCSRs(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ outw((u16)(lp->sh_mem & LA_MASK), DEPCA_DATA); outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ outw((u16)((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA); outw(CSR3, DEPCA_ADDR); /* ALE control */ outw(ACON, DEPCA_DATA); outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ return;}static int InitRestartDepca(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; int i, status=0; /* Copy the shadow init_block to shared memory */ memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ outw(INIT, DEPCA_DATA); /* initialize DEPCA */ /* wait for lance to complete initialisation */ for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); if (i!=100) { /* clear IDON by writing a "1", enable interrupts and start lance */ outw(IDON | INEA | STRT, DEPCA_DATA); if (depca_debug > 2) { printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); } } else { printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); status = -1; } return status;}static struct enet_statistics *depca_get_stats(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; /* Null body since there is no framing error counter */ return &lp->stats;}/*** Set or clear the multicast filter for this adaptor.*/static voidset_multicast_list(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; if (irq2dev_map[dev->irq] != NULL) { while(dev->tbusy); /* Stop ring access */ set_bit(0, (void*)&dev->tbusy); while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ STOP_DEPCA; /* Temporarily stop the depca. */ depca_init_ring(dev); /* Initialize the descriptor rings */ if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ lp->init_block.mode |= PROM; } else { SetMulticastFilter(dev); lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ } LoadCSRs(dev); /* Reload CSR3 */ InitRestartDepca(dev); /* Resume normal operation. */ dev->tbusy = 0; /* Unlock the TX ring */ }}/*** Calculate the hash code and update the logical address filter** from a list of ethernet multicast addresses.** Big endian crc one liner is mine, all mine, ha ha ha ha!** LANCE calculates its hash codes big endian.*/static void SetMulticastFilter(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; struct dev_mc_list *dmi=dev->mc_list; char *addrs; int i, j, bit, byte; u16 hashcode; s32 crc, poly = CRC_POLYNOMIAL_BE; if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ for (i=0; i<(HASH_TABLE_LEN>>3); i++) { lp->init_block.mcast_table[i] = (char)0xff; } } else { for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */ lp->init_block.mcast_table[i]=0; } /* Add multicast addresses */ for (i=0;i<dev->mc_count;i++) { /* for each address in the list */ addrs=dmi->dmi_addr; dmi=dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = 0xffffffff; /* init CRC for each address */ for (byte=0;byte<ETH_ALEN;byte++) {/* for each address byte */ /* process each address bit */ for (bit = *addrs++,j=0;j<8;j++, bit>>=1) { crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0); } } hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ for (j=0;j<5;j++) { /* ... in reverse order. */ hashcode = (hashcode << 1) | ((crc>>=1) & 1); } byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ lp->init_block.mcast_table[byte] |= bit; } } } return;}/*** ISA bus I/O device probe*/static void isa_probe(struct device *dev, u_long ioaddr){ int i = num_depcas, maxSlots; s32 ports[] = DEPCA_IO_PORTS; if (!ioaddr && autoprobed) return ; /* Been here before ! */ if (ioaddr > 0x400) return; /* EISA Address */ if (i >= MAX_NUM_DEPCAS) return; /* Too many ISA adapters */ if (ioaddr == 0) { /* Autoprobing */ maxSlots = MAX_NUM_DEPCAS; } else { /* Probe a specific location */ ports[i] = ioaddr; maxSlots = i + 1; } for (; (i<maxSlots) && (dev!=NULL) && ports[i]; i++) { if (DevicePresent(ports[i]) == 0) { if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { if ((dev = alloc_device(dev, ports[i])) != NULL) { if (depca_hw_init(dev, ports[i]) == 0) { num_depcas++; } num_eth++; } } else if (autoprobed) { printk("%s: region already allocated at 0x%04x.\n", dev->name,ports[i]); } } } return;}/*** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually** the motherboard. Upto 15 EISA devices are supported.*/static void eisa_probe(struct device *dev, u_long ioaddr){ int i, maxSlots; u_long iobase; char name[DEPCA_STRLEN]; if (!ioaddr && autoprobed) return ; /* Been here before ! */ if ((ioaddr < 0x400) && (ioaddr > 0)) return; /* ISA Address */ if (ioaddr == 0) { /* Autoprobing */ iobase = EISA_SLOT_INC; /* Get the first slot address */ i = 1; maxSlots = MAX_EISA_SLOTS; } else { /* Probe a specific location */ iobase = ioaddr; i = (ioaddr >> 12); maxSlots = i + 1; } if ((iobase & 0x0fff) == 0) iobase += DEPCA_EISA_IO_PORTS; for (; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) { if (EISA_signature(name, EISA_ID)) { if (DevicePresent(iobase) == 0) { if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { if ((dev = alloc_device(dev, iobase)) != NULL) { if (depca_hw_init(dev, iobase) == 0) { num_depcas++; } num_eth++; } } else if (autoprobed) { printk("%s: region already allocated at 0x%04lx.\n",dev->name,iobase); } } } } return;}/*** Search the entire 'eth' device list for a fixed probe. If a match isn't** found then check for an autoprobe or unused device location. If they** are not available then insert a new device structure at the end of** the current list.*/static struct device *alloc_device(struct device *dev, u_long iobase){ struct device *adev = NULL; int fixed = 0, new_dev = 0; num_eth = depca_dev_index(dev->name); if (loading_module) return dev; while (1) { if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr==0)) && !adev) { adev=dev; } else if ((dev->priv == NULL) && (dev->base_addr==iobase)) { fixed = 1; } else { if (dev->next == NULL) { new_dev = 1; } else if (strncmp(dev->next->name, "eth", 3) != 0) { new_dev = 1; } } if ((dev->next == NULL) || new_dev || fixed) break; dev = dev->next; num_eth++; } if (adev && !fixed) { dev = adev; num_eth = depca_dev_index(dev->name); new_dev = 0; } if (((dev->next == NULL) && ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || new_dev) { num_eth++; /* New device */ dev = insert_device(dev, iobase, depca_probe); } return dev;}/*** If at end of eth device list and can't use current entry, malloc** one up. If memory could not be allocated, print an error message.*/static struct device *insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)){ struct device *new; new = (struct device *)kmalloc(sizeof(struct device)+8, GFP_KERNEL); if (new == NULL) { printk("eth%d: Device not initialised, insufficient memory\n",num_eth); return NULL; } else { new->next = dev->next; dev->next = new; dev = dev->next; /* point to the new device */ dev->name = (char *)(dev + 1); if (num_eth > 9999) { sprintf(dev->name,"eth????");/* New device name */ } else { sprintf(dev->name,"eth%d", num_eth);/* New device name */ } dev->base_addr = iobase; /* assign the io address */ dev->init = init; /* initialisation routine */ } return dev;}static intdepca_dev_index(char *s){ int i=0, j=0; for (;*s; s++) { if (isdigit(*s)) { j=1; i = (i * 10) + (*s - '0'); } else if (j) break; } return i;}/*** Look for a particular board name in the on-board Remote Diagnostics** and Boot (readb) ROM. This will also give us a clue to the network RAM** base address.*/static void DepcaSignature(char *name, u_long paddr){ u_int i,j,k; const char *signatures[] = DEPCA_SIGNATURE; char tmpstr[16]; /* Copy the first 16 bytes of ROM */ for (i=0;i<16;i++) { tmpstr[i] = readb(paddr+0xc000+i); } /* Check if PROM contains a valid string */ for (i=0;*signatures[i]!='\0';i++) { for (j=0,k=0;j<16 && k<strlen(signatures[i]);j++) { if (signatures[i][k] == tmpstr[j]) { /* track signature */ k++; } else { /* lost signature; begin search again */ k=0; } } if (k == strlen(signatures[i])) break; } /* Check if name string is valid, provided there's no PROM */ if (*name && (i == unknown)) { for (i=0;*signatures[i]!='\0';i++) { if (strcmp(name,signatures[i]) == 0) break; } } /* Update search results */ strcpy(name,signatures[i]); adapter = i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -