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

📄 depca.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 3 页
字号:
depca_interrupt(int reg_ptr){    int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);    struct device *dev = (struct device *)(irq2dev_map[irq]);    struct depca_private *lp;    int csr0, ioaddr, nicsr;    if (dev == NULL) {	printk ("depca_interrupt(): irq %d for unknown device.\n", irq);	return;    } else {      lp = (struct depca_private *)dev->priv;      ioaddr = dev->base_addr;    }    if (dev->interrupt)	printk("%s: Re-entering the interrupt handler.\n", dev->name);    dev->interrupt = MASK_INTERRUPTS;    /* mask the DEPCA board interrupts and turn on the LED */    nicsr = inw(DEPCA_NICSR);    nicsr |= (IM|LED);    outw(nicsr, DEPCA_NICSR);    outw(CSR0, DEPCA_ADDR);    csr0 = inw(DEPCA_DATA);    /* Acknowledge all of the current interrupt sources ASAP. */    outw(csr0 & ~(INEA|TDMD|STOP|STRT|INIT), DEPCA_DATA);    if (depca_debug > 5)	printk("%s: interrupt  csr0=%#2.2x new csr=%#2.2x.\n",	       dev->name, csr0, inw(DEPCA_DATA));    if (csr0 & RINT)		/* Rx interrupt (packet arrived) */	depca_rx(dev);    if (csr0 & TINT) 	        /* Tx interrupt (packet sent) */        depca_tx(dev);    /* Clear the interrupts we've handled. */    outw(CSR0, DEPCA_ADDR);    outw(BABL|CERR|MISS|MERR|RINT|TINT|IDON|INEA, DEPCA_DATA);    if (depca_debug > 4) {      printk("%s: exiting interrupt, csr%d=%#4.4x.\n",	     dev->name, inw(DEPCA_ADDR),	     inw(DEPCA_DATA));    }    /* Unmask the DEPCA board interrupts and turn off the LED */    nicsr = (nicsr & ~IM & ~LED);    outw(nicsr, DEPCA_NICSR);    dev->interrupt = UNMASK_INTERRUPTS;    return;}static intdepca_rx(struct device *dev){    struct depca_private *lp = (struct depca_private *)dev->priv;    int entry = lp->cur_rx & lp->rmask;    /* If we own the next entry, it's a new packet. Send it up. */    for (; lp->rx_ring[entry].base >= 0; entry = (++lp->cur_rx) & lp->rmask) {	int status = lp->rx_ring[entry].base >> 16 ;	if (status & R_ERR) {	       /* There was an error. */	    lp->stats.rx_errors++;     /* Update the error stats. */	    if (status & R_FRAM) lp->stats.rx_frame_errors++;	    if (status & R_OFLO) lp->stats.rx_over_errors++;	    if (status & R_CRC)  lp->stats.rx_crc_errors++;	    if (status & R_BUFF) lp->stats.rx_fifo_errors++;	} else {	  /* Malloc up new buffer, compatible  with net-2e. */	    short pkt_len = lp->rx_ring[entry].msg_length;	    int sksize = sizeof(struct sk_buff) + pkt_len;	    struct sk_buff *skb;	    skb = alloc_skb(sksize, GFP_ATOMIC);	    if (skb == NULL) {		printk("%s: Memory squeeze, deferring packet.\n", dev->name);		lp->stats.rx_dropped++;	/* Really, deferred. */		break;	    }	    skb->mem_len = sksize;	    skb->mem_addr = skb;	    skb->len = pkt_len;	    skb->dev = dev;	    memcpy(skb->data,		   (unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff),		   pkt_len);	    /* 	    ** Notify the upper protocol layers that there is another 	    ** packet to handle	    */#ifdef HAVE_NETIF_RX	    netif_rx(skb);#else	    skb->lock = 0;	    if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {		kfree_skbmem(skb, sksize);		lp->stats.rx_dropped++;		break;	    }#endif	    lp->stats.rx_packets++;	}	/* turn over ownership of the current entry back to the LANCE */	lp->rx_ring[entry].base |= R_OWN;    }    /*     ** We should check that at least two ring entries are free.  If not,    ** we should free one and mark stats->rx_dropped++.     */    return 0;}/*** Buffer sent - check for buffer errors.*/static intdepca_tx(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  int dirty_tx = lp->dirty_tx & lp->rmask;  if (depca_debug > 5)    printk("%s: Cleaning tx ring, dirty %d clean %d.\n",	   dev->name, dirty_tx, (lp->cur_tx & lp->rmask));    /*   ** While the dirty entry is not the current one AND   ** the LANCE doesn't own it...   */  for (; dirty_tx!=(lp->cur_tx & lp->rmask) && lp->tx_ring[dirty_tx].base>0;                                       dirty_tx = ++lp->dirty_tx & lp->rmask) {    unsigned long *tmdp = (unsigned long *)(&lp->tx_ring[dirty_tx]);    int status = lp->tx_ring[dirty_tx].base >> 16;    if (status < 0) {                          /* Packet not yet sent! */      printk("interrupt for packet not yet sent!\n");      break;    }    if (status & T_ERR) { /* There was an major error, log it. */      int err_status = lp->tx_ring[dirty_tx].misc;      lp->stats.tx_errors++;      if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++;      if (err_status & TMD3_LCAR) lp->stats.tx_carrier_errors++;      if (err_status & TMD3_LCOL) lp->stats.tx_window_errors++;      if (err_status & TMD3_UFLO) lp->stats.tx_fifo_errors++;      /* We should re-init() after the FIFO error. */    } else if (status & (T_MORE | T_ONE)) {      lp->stats.collisions++;    } else {      lp->stats.tx_packets++;    }    if (depca_debug > 5)      printk("%s: Tx done entry %d, %4.4lx %4.4lx %4.4lx %4.4lx.\n",	     dev->name, dirty_tx,	     tmdp[0], tmdp[1], tmdp[2], tmdp[3]);  }  /*mark_bh(INET_BH);*/  return 0;}static intdepca_close(struct device *dev){    int 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);    free_irq(dev->irq);    irq2dev_map[dev->irq] = 0;    return 0;}static void LoadCSRs(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  int ioaddr = dev->base_addr;  outw(CSR1, DEPCA_ADDR);                /* initialisation block address LSW */  outw((unsigned short)(unsigned long)&lp->init_block, DEPCA_DATA);  outw(CSR2, DEPCA_ADDR);                /* initialisation block address MSW */  outw((unsigned short)((unsigned long)&lp->init_block >> 16), DEPCA_DATA);  outw(CSR3, DEPCA_ADDR);                /* ALE control */  outw(ACON, DEPCA_DATA);  outw(CSR0, DEPCA_ADDR);                /* point back to CSR0 */}static int InitRestartDepca(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  int ioaddr = dev->base_addr;  int i, status=0;  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 %#lx csr0 %4.4x.\n",	     dev->name, i, (long) &lp->init_block, inw(DEPCA_DATA));    }  } else {    status = -1;    printk("%s: DEPCA unopened after %d ticks, init block %#lx csr0 %4.4x.\n",	   dev->name, i, (long) &lp->init_block, inw(DEPCA_DATA));  }  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;}#ifdef HAVE_MULTICAST/*** Set or clear the multicast filter for this adaptor.** num_addrs == -1	Promiscuous mode, receive all packets** num_addrs == 0	Normal mode, clear multicast list** num_addrs > 0	Multicast mode, receive normal and MC packets, and do** 			best-effort filtering.*/static voidset_multicast_list(struct device *dev, int num_addrs, void *addrs){  short ioaddr = dev->base_addr;  struct depca_private *lp = (struct depca_private *)dev->priv;    /* We take the simple way out and always enable promiscuous mode. */  STOP_DEPCA;                       /* Temporarily stop the depca.  */  lp->init_block.mode = PROM;       /* Set promiscuous mode */  if (num_addrs >= 0) {    short multicast_table[4];    int i;    SetMulticastFilter(num_addrs, (char *)addrs, (char *)multicast_table);    /* We don't use the multicast table, but rely on upper-layer filtering. */    memset(multicast_table, (num_addrs==0) ? 0 : -1, sizeof(multicast_table));    for (i = 0; i < 4; i++) {      lp->init_block.filter[i] = multicast_table[i];    }    lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */  } else {    lp->init_block.mode |= PROM;    /* Set promiscuous mode */  }  outw(CSR0, DEPCA_ADDR);  outw(IDON|INEA|STRT, DEPCA_DATA); /* Resume normal operation. */}/*** Calculate the hash code and update the logical address filter** from a list of ethernet multicast addresses.** Derived from a 'C' program in the AMD data book:** "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)", ** Pub #17781, Rev. A, May 1993*/static void SetMulticastFilter(int num_addrs, char *addrs, char *multicast_table){  char j, ctrl, bit, octet, hashcode;  short int i;  long int CRC, poly = (long int) CRC_POLYNOMIAL;  for (i=0;i<num_addrs;i++) {                /* for each address in the list */    if (((char) *(addrs+ETH_ALEN*i) & 0x01) == 1) {/* is multicast address? */       CRC = (long int) 0xffffffff;           /* init CRC for each address */      for (octet=0;octet<ETH_ALEN;octet++) { /* for each address octet */	for(j=0;j<8;j++) {                   /* process each address bit */	  bit = (((char)* (addrs+ETH_ALEN*i+octet)) >> j) & 0x01;	  ctrl = ((CRC < 0) ? 1 : 0);        /* shift the control bit */	  CRC <<= 1;                         /* shift the CRC */	  if (bit ^ ctrl) {                  /* (bit) XOR (control bit) */	    CRC ^= poly;                     /* (CRC) XOR (polynomial) */	  }	}      }      hashcode = (CRC & 0x00000001);         /* hashcode is 6 LSb of CRC ... */      for (j=0;j<5;j++) {                    /* ... in reverse order. */	hashcode <<= 1;	CRC >>= 1;	hashcode |= (CRC & 0x00000001);      }                                            octet = hashcode >> 3;                  /* bit[3-5] -> octet in filter */                                              /* bit[0-2] -> bit in octet */      multicast_table[octet] |= (1 << (hashcode & 0x07));    }  }  return;}#endif  /* HAVE_MULTICAST *//*** Look for a particular board name in the on-board Remote Diagnostics** and Boot (RDB) ROM. This will also give us a clue to the network RAM** base address.*/static char *DepcaSignature(unsigned long mem_addr){  unsigned long i,j,k;  static char signatures[][DEPCA_NAME_LENGTH] = DEPCA_SIGNATURE;  static char thisName[DEPCA_NAME_LENGTH];  char tmpstr[17];  for (i=0;i<16;i++) {                  /* copy the first 16 bytes of ROM to */    tmpstr[i] = *(unsigned char *)(mem_addr+0xc000+i); /* a temporary string */  }  tmpstr[i]=(char)NULL;  strcpy(thisName,"");  for (i=0;*signatures[i]!=(char)NULL && *thisName==(char)NULL;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])) {      strcpy(thisName,signatures[i]);    }  }  return thisName;                    /* return the device name string */}/*** Look for a special sequence in the Ethernet station address PROM that** is common across all DEPCA products.*/static int DevicePresent(short ioaddr){  static short fp=1,sigLength=0;  static char devSig[] = PROBE_SEQUENCE;  char data;  int i, j, status = 0;  static char asc2hex(char value);/* ** Convert the ascii signature to a hex equivalent & pack in place */  if (fp) {                               /* only do this once!... */    for (i=0,j=0;devSig[i]!=(char)NULL && !status;i+=2,j++) {      if ((devSig[i]=asc2hex(devSig[i]))>=0) {	devSig[i]<<=4;	if((devSig[i+1]=asc2hex(devSig[i+1]))>=0){	  devSig[j]=devSig[i]+devSig[i+1];	} else {	  status= -1;	}      } else {	status= -1;      }    }    sigLength=j;    fp = 0;  }/* ** Search the Ethernet address ROM for the signature. Since the ROM address** counter can start at an arbitrary point, the search must include the entire** probe sequence length plus the length of the (signature - 1).** Stop the search IMMEDIATELY after the signature is found so that the** PROM address counter is correctly positioned at the start of the** ethernet address for later read out.*/  if (!status) {    for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {      data = inb(ioaddr);      if (devSig[j] == data) {    /* track signature */	j++;      } else {                    /* lost signature; begin search again */	j=0;      }    }    if (j!=sigLength) {      status = -ENODEV;           /* search failed */    }  }  return status;}static char asc2hex(char value){  value -= 0x30;                  /* normalise to 0..9 range */  if (value >= 0) {    if (value > 9) {              /* but may not be 10..15 */      value &= 0x1f;              /* make A..F & a..f be the same */      value -= 0x07;              /* normalise to 10..15 range */      if ((value < 0x0a) || (value > 0x0f)) { /* if outside range then... */	value = -1;               /* ...signal error */      }    }  } else {                        /* outside 0..9 range... */    value = -1;                   /* ...signal error */  }  return value;                   /* return hex char or error */}/* * Local variables: *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c depca.c" * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -