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

📄 depca.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
static intdepca_hw_init(struct device *dev, u_long ioaddr){  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 ((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;	  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:	      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;  irq2dev_map[dev->irq] = dev;  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, NULL)) {    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 */  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];  }  lp->init_block.mode = 0x0000;            /* Enable the Tx and Rx */  return;}/* ** 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;  u_long ioaddr = dev->base_addr;  int status = 0;  /* Transmitter timeout, serious problems. */  if (dev->tbusy) {    int tickssofar = jiffies - dev->trans_start;    if (tickssofar < 1*HZ) {      status = -1;    } else {      printk("%s: transmit timed out, status %04x, resetting.\n",	     dev->name, inw(DEPCA_DATA));	      STOP_DEPCA;      depca_init_ring(dev);      LoadCSRs(dev);      dev->interrupt = UNMASK_INTERRUPTS;      dev->start = 1;      dev->tbusy=0;      dev->trans_start = jiffies;      InitRestartDepca(dev);      dev_kfree_skb(skb, FREE_WRITE);    }    return status;  } else if (skb == NULL) {    dev_tint(dev);  } else if (skb->len > 0) {    /* Enforce 1 process per h/w access */    if (set_bit(0, (void*)&dev->tbusy) != 0) {      printk("%s: Transmitter access conflict.\n", dev->name);      status = -1;    } else {      if (TX_BUFFS_AVAIL) {                    /* Fill in a Tx ring entry */	status = load_packet(dev, skb);	if (!status) {	  /* Trigger an immediate send demand. */	  outw(CSR0, DEPCA_ADDR);	  outw(INEA | TDMD, DEPCA_DATA);	  	  dev->trans_start = jiffies;	  dev_kfree_skb(skb, FREE_WRITE);	}	if (TX_BUFFS_AVAIL) {	  dev->tbusy=0;	}        } else {	status = -1;      }    }  }    return status;}/*** The DEPCA interrupt handler. */static voiddepca_interrupt(int irq, void *dev_id, struct pt_regs * regs){  struct device *dev = (struct device *)(irq2dev_map[irq]);  struct depca_private *lp;  s16 csr0, nicsr;  u_long ioaddr;  if (dev == NULL) {    printk ("depca_interrupt(): irq %d for unknown device.\n", irq);  } 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 = inb(DEPCA_NICSR);    nicsr |= (IM|LED);    outb(nicsr, DEPCA_NICSR);    outw(CSR0, DEPCA_ADDR);    csr0 = inw(DEPCA_DATA);    /* Acknowledge all of the current interrupt sources ASAP. */    outw(csr0 & INTE, DEPCA_DATA);    if (csr0 & RINT)		       /* Rx interrupt (packet arrived) */      depca_rx(dev);    if (csr0 & TINT) 	               /* Tx interrupt (packet sent) */      depca_tx(dev);    if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */      dev->tbusy = 0;                  /* clear TX busy flag */      mark_bh(NET_BH);    }    /* Unmask the DEPCA board interrupts and turn off the LED */    nicsr = (nicsr & ~IM & ~LED);    outb(nicsr, DEPCA_NICSR);    dev->interrupt = UNMASK_INTERRUPTS;  }  return;}static intdepca_rx(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  int i, entry;  s32 status;  for (entry=lp->rx_new;        !(readl(&lp->rx_ring[entry].base) & R_OWN);       entry=lp->rx_new){    status = readl(&lp->rx_ring[entry].base) >> 16 ;    if (status & R_STP) {                      /* Remember start of frame */      lp->rx_old = entry;    }    if (status & R_ENP) {                      /* Valid frame status */      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 {		short len, pkt_len = readw(&lp->rx_ring[entry].msg_length);	struct sk_buff *skb;	skb = dev_alloc_skb(pkt_len+2);	if (skb != NULL) {	  unsigned char *buf;	  skb_reserve(skb,2);               /* 16 byte align the IP header */	  buf = skb_put(skb,pkt_len);	  skb->dev = dev;	  if (entry < lp->rx_old) {         /* Wrapped buffer */	    len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ;	    memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len);	    memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len-len);	  } else {                          /* Linear buffer */	    memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len);	  }	  /* 	  ** Notify the upper protocol layers that there is another 	  ** packet to handle	  */	  skb->protocol=eth_type_trans(skb,dev);	  netif_rx(skb); 	  /*	  ** Update stats	  */	  lp->stats.rx_packets++;	  for (i=1; i<DEPCA_PKT_STAT_SZ-1; i++) {	    if (pkt_len < (i*DEPCA_PKT_BIN_SZ)) {	      lp->pktStats.bins[i]++;	      i = DEPCA_PKT_STAT_SZ;	    }	  }	  if (buf[0] & 0x01) {              /* Multicast/Broadcast */	    if ((*(s16 *)&buf[0] == -1) &&		(*(s16 *)&buf[2] == -1) &&

⌨️ 快捷键说明

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