⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 depca.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
		(*(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 + -