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

📄 depca.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 3 页
字号:
	printk(" starting at 0x%.5lx", mem_start);	/*	 ** Enable the shadow RAM.	*/	nicsr |= SHE;	outw(nicsr, DEPCA_NICSR); 	/*	** Calculate the ring size based on the available RAM	** found above. Allocate an equal number of buffers, each	** of size PKT_BUF_SZ (1544 bytes) to the Tx and Rx. Make sure	** that this ring size is <= RING_SIZE. The ring size must be	** a power of 2.	*/	j = ((0x10000 - offset) / PKT_BUF_SZ) >> 1;	for (i=0;j>1;i++) {	  j >>= 1;	}	/* Hold the ring size information here before the depca	** private structure is allocated. Need this for the memory	** space calculations.	*/	j = 1 << i;	/*	** Set up memory information in the device structure.	** Align the descriptor rings on an 8 byte (quadword) boundary.	**	**     depca_private area	**     rx ring descriptors	**     tx ring descriptors	**     rx buffers	**     tx buffers	**	*/	/* private area & initialise */	dev->priv = (void *)((mem_start + 0x07) & ~0x07);      	lp = (struct depca_private *)dev->priv;	memset(dev->priv, 0, sizeof(struct depca_private));	/* Tx & Rx descriptors (aligned to a quadword boundary) */	mem_start = ((((unsigned long)dev->priv + 		        sizeof(struct depca_private)) +			(unsigned long)0x07) & (unsigned long)~0x07);	lp->rx_ring = (struct depca_rx_head *)mem_start;	mem_start += (sizeof(struct depca_rx_head) * j);	lp->tx_ring = (struct depca_tx_head *)mem_start;	mem_start += (sizeof(struct depca_tx_head) * j);	lp->dma_buffs = mem_start & 0x00ffffff;	mem_start += (PKT_BUF_SZ * j);	/* (mem_start now points to the start of the Tx buffers) */	/* Initialise the data structures */	memset(lp->rx_ring, 0, sizeof(struct depca_rx_head)*j);	memset(lp->tx_ring, 0, sizeof(struct depca_tx_head)*j);	/* This should never happen. */	if ((int)(lp->rx_ring) & 0x07) {	  printk("\n **ERROR** DEPCA Rx and Tx descriptor rings not on a quadword boundary.\n");	  return -ENXIO;	}	/*	** Finish initialising the ring information.	*/	lp->ringSize = j;	if (lp->ringSize > RING_SIZE) lp->ringSize = RING_SIZE;	lp->rmask = lp->ringSize - 1;	/*	** calculate the real RLEN size for the descriptors. It is	** log2(ringSize).	*/	for (i=0, j = lp->ringSize; j>1; i++) {	  j >>= 1;	}	lp->rlen = (unsigned long)(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);	outw(nicsr, DEPCA_NICSR);	/* The DMA channel may be passed in on this parameter. */	dev->dma = 0;		/* 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) {	  autoirq_setup(0);	  /* Trigger an initialization just for the interrupt. */	  outw(INEA | INIT, DEPCA_DATA);	  	  dev->irq = autoirq_report(1);	  if (dev->irq) {	    printk(" and probed IRQ%d.\n", dev->irq);	  } else {	    printk(". Failed to detect IRQ line.\n");	    status = -EAGAIN;	  }	} else {	  printk(". Assigned IRQ%d.\n", dev->irq);	}      } else {	status = -ENXIO;      }      if (!status) {	if (depca_debug > 0) {	  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;#ifdef HAVE_MULTICAST	dev->set_multicast_list = &set_multicast_list;#endif	dev->mem_start = 0;		/* Fill in the generic field of the device structure. */	for (i = 0; i < DEV_NUMBUFFS; i++) {	  dev->buffs[i] = NULL;	}	dev->hard_header     = eth_header;	dev->add_arp	     = eth_add_arp;	dev->queue_xmit	     = dev_queue_xmit;	dev->rebuild_header  = eth_rebuild_header;	dev->type_trans	     = eth_type_trans;		dev->type	     = ARPHRD_ETHER;	dev->hard_header_len = ETH_HLEN;	dev->mtu	     = 1500; /* eth_mtu */	dev->addr_len	     = ETH_ALEN;	for (i = 0; i < dev->addr_len; i++) {	  dev->broadcast[i]=0xff;	}		/* New-style flags. */	dev->flags	     = IFF_BROADCAST;	dev->family	     = AF_INET;	dev->pa_addr	     = 0;	dev->pa_brdaddr	     = 0;	dev->pa_mask	     = 0;	dev->pa_alen	     = sizeof(unsigned long);      }    } else {      status = -ENXIO;    }    return status;}static intdepca_open(struct device *dev){    struct depca_private *lp = (struct depca_private *)dev->priv;    int i,nicsr,ioaddr = dev->base_addr;    if (request_irq(dev->irq, &depca_interrupt)) {        printk("depca_open(): Requested IRQ%d is busy\n",dev->irq);	return -EAGAIN;    }    irq2dev_map[dev->irq] = dev;    /*    ** Stop the DEPCA & get the board status information.      */    STOP_DEPCA;    nicsr = inw(DEPCA_NICSR);    /*     ** Re-initialize the DEPCA...     */    depca_init_ring(dev);                 /* initialize the descriptor rings */    LoadCSRs(dev);    if (depca_debug > 1){      printk("%s: depca open with irq %d\n",dev->name,dev->irq);      printk("Descriptor head addresses:\n");      printk("\t0x%8.8lx  0x%8.8lx\n",(long)lp->rx_ring,(long)lp->tx_ring);      printk("Descriptor addresses:\n");      for (i=0;i<lp->ringSize;i++){	printk("\t0x%8.8lx  0x%8.8lx\n",(long)&lp->rx_ring[i].base,	                                (long)&lp->tx_ring[i].base);      }      printk("Buffer addresses:\n");      for (i=0;i<lp->ringSize;i++){	printk("\t0x%8.8lx  0x%8.8lx\n",(long)lp->rx_ring[i].base,                                        (long)lp->tx_ring[i].base);      }      printk("Initialisation block at 0x%8.8lx\n",(long)&lp->init_block);      printk("\tmode: 0x%4.4x\n",lp->init_block.mode);      printk("\tphysical address: ");      for (i=0;i<6;i++){	printk("%2.2x:",(short)lp->init_block.phys_addr[i]);      }      printk("\n\tlogical address filter: 0x");      for (i=0;i<4;i++){	printk("%2.2x",(short)lp->init_block.filter[i]);      }      printk("\n\trx_ring at: 0x%8.8lx\n",(long)lp->init_block.rx_ring);      printk("\ttx_ring at: 0x%8.8lx\n",(long)lp->init_block.tx_ring);      printk("dma_buffs: 0x%8.8lx\n",(long)lp->dma_buffs);      printk("Ring size: %d\nMask: 0x%2.2x\nLog2(ringSize): 0x%8.8lx\n",                                          (short)lp->ringSize,                                           (char)lp->rmask,                                          (long)lp->rlen);      outw(CSR2,DEPCA_ADDR);      printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA));      outw(CSR1,DEPCA_ADDR);      printk("%4.4x\n",inw(DEPCA_DATA));      outw(CSR3,DEPCA_ADDR);      printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA));    }    /*    ** Enable DEPCA board interrupts    */    nicsr = ((nicsr & ~IM & ~LED)|SHE|IEN);    outw(nicsr, DEPCA_NICSR);    outw(CSR0,DEPCA_ADDR);    dev->tbusy = 0;                             dev->interrupt = 0;    dev->start = 1;    InitRestartDepca(dev);                /* ignore the return status */    if (depca_debug > 1){      printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA));      printk("nicsr: 0x%4.4x\n",inw(DEPCA_NICSR));    }    return 0;			          /* Always succeed */}/* Initialize the lance Rx and Tx descriptor rings. */static voiddepca_init_ring(struct device *dev){    struct depca_private *lp = (struct depca_private *)dev->priv;    unsigned long i;    lp->init_block.mode = DTX | DRX;	     /* Disable Rx and Tx. */    lp->cur_rx = lp->cur_tx = 0;    lp->dirty_rx = lp->dirty_tx = 0;    /* Initialize the base addresses and length of each buffer in the ring */    for (i = 0; i < lp->ringSize; i++) {	lp->rx_ring[i].base = (lp->dma_buffs + i*PKT_BUF_SZ) | R_OWN;	lp->rx_ring[i].buf_length = -PKT_BUF_SZ;	lp->tx_ring[i].base = (lp->dma_buffs + (i+lp->ringSize) * PKT_BUF_SZ) &	                                           (unsigned long)(0x00ffffff);    }    /* Set up the initialization block */    for (i = 0; i < ETH_ALEN; i++) {      lp->init_block.phys_addr[i] = dev->dev_addr[i];    }    for (i = 0; i < 4; i++) {      lp->init_block.filter[i] = 0x0000;    }    lp->init_block.rx_ring = (unsigned long)lp->rx_ring | lp->rlen;    lp->init_block.tx_ring = (unsigned long)lp->tx_ring | lp->rlen;    lp->init_block.mode = 0x0000;            /* Enable the Tx and Rx */ }/* ** Writes a socket buffer to TX descriptor ring and starts transmission */static intdepca_start_xmit(struct sk_buff *skb, struct device *dev){    struct depca_private *lp = (struct depca_private *)dev->priv;    int ioaddr = dev->base_addr;    int status = 0;    /* Transmitter timeout, serious problems. */    if (dev->tbusy) {      int tickssofar = jiffies - dev->trans_start;      if (tickssofar < 5) {	status = -1;      } else {	STOP_DEPCA;	printk("%s: transmit timed out, status %4.4x, resetting.\n",	       dev->name, inw(DEPCA_DATA));		depca_init_ring(dev);	LoadCSRs(dev);	InitRestartDepca(dev);	dev->tbusy=0;	dev->trans_start = jiffies;      }      return status;    }    if (skb == NULL) {	dev_tint(dev);	return 0;    }    /* Fill in the ethernet header. */    if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {	skb->dev = dev;	arp_queue (skb);	return 0;    }    skb->arp=1;    if (skb->len <= 0) {      return 0;    }    if (depca_debug > 3) {	outw(CSR0, DEPCA_ADDR);	printk("%s: depca_start_xmit() called, csr0 %4.4x.\n", dev->name,	       inw(DEPCA_DATA));    }    /* Block a timer-based transmit from overlapping.  This could better be       done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */    if (set_bit(0, (void*)&dev->tbusy) != 0)	printk("%s: Transmitter access conflict.\n", dev->name);    /*    ** The TX buffer, skb, has to be copied into the local network RAM    ** for the LANCE to access it. The skb may be at > 16MB for large     ** (memory) systems.    */    {				/* Fill in a Tx ring entry */      unsigned char *buf;      int entry = lp->cur_tx++;      int len;      long skbL = skb->len;      char *p = (char *) skb->data;      entry &= lp->rmask;  		    /* Ring around buffer number. */      buf = (unsigned char *)(lp->tx_ring[entry].base & 0x00ffffff);      /* Wait for a full ring to free up */      while (lp->tx_ring[entry].base < 0);      /*       ** Caution: the write order is important here... don't set up the      ** ownership rights until all the other information is in place.      */      len = ((skbL > PKT_SZ) ? PKT_SZ : skbL); /* skb too long */      if (len < ETH_ZLEN) len = ETH_ZLEN;      /* len too short */      skbL -= len;      lp->tx_ring[entry].length = -len;      /* Clears various error flags */      lp->tx_ring[entry].misc = 0x0000;      /* copy the data from the socket buffer to the net memory */      memcpy((unsigned char *)(buf), skb->data, len);      /* Hand over buffer ownership to the LANCE */      if (skbL <= 0) lp->tx_ring[entry].base |= (T_ENP);      lp->tx_ring[entry].base |= (T_OWN|T_STP);      /* Trigger an immediate send demand. */      outw(CSR0, DEPCA_ADDR);      outw(INEA | TDMD, DEPCA_DATA);      dev->trans_start = jiffies;      for (p += len; skbL > 0; p += len) {	/* Get new buffer pointer */	entry = lp->cur_tx++;	entry &= lp->rmask;  		    /* Ring around buffer number. */	buf = (unsigned char *)(lp->tx_ring[entry].base & 0x00ffffff);	/* Wait for a full ring to free up */	while (lp->tx_ring[entry].base < 0);	dev->tbusy=0;	/* Copy ethernet header to the new buffer */	memcpy((unsigned char *)buf, skb->data, PKT_HDR_LEN);	/* Determine length of data buffer */	len = ((skbL > DAT_SZ) ? DAT_SZ : skbL); /* skbL too long */	if (len < ETH_ZLEN) len = ETH_ZLEN;      /* len too short */	skbL -= len;	lp->tx_ring[entry].length = -len;	/* Clears various error flags */	lp->tx_ring[entry].misc = 0x0000;	/* copy the data from the socket buffer to the net memory */	memcpy((unsigned char *)(buf + PKT_HDR_LEN), (unsigned char *)p, len);	/* Hand over buffer ownership to the LANCE */	if (skbL <= 0) lp->tx_ring[entry].base |= T_ENP;	lp->tx_ring[entry].base |= T_OWN;      }      if (depca_debug > 4) {	unsigned char *pkt =	  (unsigned char *)(lp->tx_ring[entry].base & 0x00ffffff);	printk("%s: tx ring[%d], %#lx, sk_buf %#lx len %d.\n",	       dev->name, entry, (unsigned long) &lp->tx_ring[entry],	       lp->tx_ring[entry].base, -lp->tx_ring[entry].length);	printk("%s:  Tx %2.2x %2.2x %2.2x ... %2.2x  %2.2x %2.2x %2.2x...%2.2x len %2.2x %2.2x  %2.2x %2.2x.\n",	       dev->name, pkt[0], pkt[1], pkt[2], pkt[5], pkt[6],	       pkt[7], pkt[8], pkt[11], pkt[12], pkt[13],	       pkt[14], pkt[15]);      }            /* Check if the TX ring is full or not - 'tbusy' cleared if not full. */      if (lp->tx_ring[(entry+1) & lp->rmask].base >= 0) {	dev->tbusy=0;      }      if (skb->free) {	kfree_skb (skb, FREE_WRITE);      }    }    return 0;}/*** The DEPCA interrupt handler. */static void

⌨️ 快捷键说明

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