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

📄 ewrk3.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
		shmem_length = SHMEM_64K;	      } else if ((mem_start >= 0x14) && (mem_start <= 0x1f)) {		mem_start *= SHMEM_32K;		shmem_length = SHMEM_32K;	      } else if ((mem_start >= 0x40) && (mem_start <= 0xff)) {		mem_start = mem_start * SHMEM_2K + 0x80000;		shmem_length = SHMEM_2K;	      } else {		status = -ENXIO;	      }	    }	  	    /*	    ** See the top of this source code for comments about	    ** uncommenting this line.	    *//*	    FORCE_2K_MODE;*/	    if (!status) {	      if (hard_strapped) {		printk("      is hard strapped.\n");	      } else if (mem_start) {		printk("      has a %dk RAM window", (int)(shmem_length >> 10));		printk(" at 0x%.5lx", mem_start);	      } else {		printk("      is in I/O only mode");	      }	    	      /* private area & initialise */	      dev->priv = (void *) kmalloc(sizeof(struct ewrk3_private), 					                           GFP_KERNEL);	      if (dev->priv == NULL) {		return -ENOMEM;	      }	      lp = (struct ewrk3_private *)dev->priv;	      memset(dev->priv, 0, sizeof(struct ewrk3_private));	      lp->shmem_base = mem_start;	      lp->shmem_length = shmem_length;	      lp->lemac = lemac;	      lp->hard_strapped = hard_strapped;	      lp->mPage = 64;	      if (cmr & CMR_DRAM) lp->mPage <<= 1 ;/* 2 DRAMS on module */ 	      sprintf(lp->adapter_name,"%s (%s)", name, dev->name);	      request_region(iobase, EWRK3_TOTAL_SIZE, lp->adapter_name);	      lp->irq_mask = ICR_TNEM|ICR_TXDM|ICR_RNEM|ICR_RXDM;	      	      if (!hard_strapped) {		/*		** Enable EWRK3 board interrupts for autoprobing		*/		icr |= ICR_IE;	                   /* Enable interrupts */		outb(icr, EWRK3_ICR);	    		/* 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) {#ifndef MODULE		  u_char irqnum;	      		  autoirq_setup(0);		  /* 		  ** Trigger a TNE interrupt.		  */		  icr |=ICR_TNEM;		  outb(1,EWRK3_TDQ);          /* Write to the TX done queue */		  outb(icr, EWRK3_ICR);       /* Unmask the TXD interrupt */	      		  irqnum = irq[((icr & IRQ_SEL) >> 4)];	      		  dev->irq = autoirq_report(1);		  if ((dev->irq) && (irqnum == dev->irq)) {		    printk(" and uses IRQ%d.\n", dev->irq);		  } else {		    if (!dev->irq) {		      printk(" and failed to detect IRQ line.\n");		    } else if ((irqnum == 1) && (lemac == LeMAC2)) {		      printk(" and an illegal IRQ line detected.\n");		    } else {		      printk(", but incorrect IRQ line detected.\n");		    }		    status = -ENXIO;		  }				  DISABLE_IRQs;                 /* Mask all interrupts */#endif /* MODULE */		} else {		  printk(" and requires IRQ%d.\n", dev->irq);		}	      }	      if (status) release_region(iobase, EWRK3_TOTAL_SIZE);	    } else {	      status = -ENXIO;	    }	  }	}      } else {	status = -ENXIO;      }    }    if (!status) {      if (ewrk3_debug > 1) {	printk(version);      }            /* The EWRK3-specific entries in the device structure. */      dev->open = &ewrk3_open;      dev->hard_start_xmit = &ewrk3_queue_pkt;      dev->stop = &ewrk3_close;      dev->get_stats = &ewrk3_get_stats;      dev->set_multicast_list = &set_multicast_list;      dev->do_ioctl = &ewrk3_ioctl;      dev->mem_start = 0;	      /* Fill in the generic field of the device structure. */      ether_setup(dev);    }  } else {    status = -ENXIO;  }  return status;}static intewrk3_open(struct device *dev){  struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;  u_long iobase = dev->base_addr;  int i, status = 0;  u_char icr, csr;  /*  ** Stop the TX and RX...  */  STOP_EWRK3;  if (!lp->hard_strapped) {    irq2dev_map[dev->irq] = dev;                   /* For latched interrupts */    if (request_irq(dev->irq, (void *)ewrk3_interrupt, 0, "ewrk3", NULL)) {      printk("ewrk3_open(): Requested IRQ%d is busy\n",dev->irq);      status = -EAGAIN;    } else {      /*       ** Re-initialize the EWRK3...       */      ewrk3_init(dev);      if (ewrk3_debug > 1){	printk("%s: ewrk3 open with irq %d\n",dev->name,dev->irq);	printk("  physical address: ");	for (i=0;i<5;i++){	  printk("%2.2x:",(u_char)dev->dev_addr[i]);	}	printk("%2.2x\n",(u_char)dev->dev_addr[i]);	if (lp->shmem_length == 0) {	  printk("  no shared memory, I/O only mode\n");	} else {	  printk("  start of shared memory: 0x%08lx\n",lp->shmem_base);	  printk("  window length: 0x%04lx\n",lp->shmem_length);	}	printk("  # of DRAMS: %d\n",((inb(EWRK3_CMR) & 0x02) ? 2 : 1));	printk("  csr:  0x%02x\n", inb(EWRK3_CSR));	printk("  cr:   0x%02x\n", inb(EWRK3_CR));	printk("  icr:  0x%02x\n", inb(EWRK3_ICR));	printk("  cmr:  0x%02x\n", inb(EWRK3_CMR));	printk("  fmqc: 0x%02x\n", inb(EWRK3_FMQC));      }      dev->tbusy = 0;                               dev->start = 1;      dev->interrupt = UNMASK_INTERRUPTS;      /*      ** Unmask EWRK3 board interrupts      */      icr = inb(EWRK3_ICR);      ENABLE_IRQs;    }  } else {    dev->start = 0;    dev->tbusy = 1;    printk("%s: ewrk3 available for hard strapped set up only.\n", dev->name);    printk("      Run the 'ewrk3setup' utility or remove the hard straps.\n");  }  MOD_INC_USE_COUNT;  return status;}/*** Initialize the EtherWORKS 3 operating conditions*/static voidewrk3_init(struct device *dev){  struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;  u_char csr, page;  u_long iobase = dev->base_addr;    /*   ** Enable any multicasts   */  set_multicast_list(dev);  /*  ** Clean out any remaining entries in all the queues here  */  while (inb(EWRK3_TQ));  while (inb(EWRK3_TDQ));  while (inb(EWRK3_RQ));  while (inb(EWRK3_FMQ));  /*  ** Write a clean free memory queue  */  for (page=1;page<lp->mPage;page++) {      /* Write the free page numbers */    outb(page, EWRK3_FMQ);                  /* to the Free Memory Queue */  }  lp->lock = 0;                             /* Ensure there are no locks */  START_EWRK3;                              /* Enable the TX and/or RX */}/* ** Writes a socket buffer to the free page queue*/static intewrk3_queue_pkt(struct sk_buff *skb, struct device *dev){  struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;  u_long iobase = dev->base_addr;  int status = 0;  u_char icr, csr;  /* Transmitter timeout, serious problems. */  if (dev->tbusy || lp->lock) {    int tickssofar = jiffies - dev->trans_start;    if (tickssofar < QUEUE_PKT_TIMEOUT) {      status = -1;    } else if (!lp->hard_strapped) {      printk("%s: transmit timed/locked out, status %04x, resetting.\n",	                                           dev->name, inb(EWRK3_CSR));	      /*      ** Mask all board interrupts      */      DISABLE_IRQs;      /*      ** Stop the TX and RX...      */      STOP_EWRK3;      ewrk3_init(dev);      /*      ** Unmask EWRK3 board interrupts      */      ENABLE_IRQs;      dev->tbusy=0;      dev->trans_start = jiffies;      dev_kfree_skb(skb, FREE_WRITE);    }  } else if (skb == NULL) {    dev_tint(dev);  } else if (skb->len > 0) {    /*     ** 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);    DISABLE_IRQs;                      /* So that the page # remains correct */        /*     ** Get a free page from the FMQ when resources are available    */    if (inb(EWRK3_FMQC) > 0) {      u_long buf = 0;      u_char page;      if ((page = inb(EWRK3_FMQ)) < lp->mPage) {	/*	** Set up shared memory window and pointer into the window	*/	while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */	if (lp->shmem_length == IO_ONLY) {	  outb(page, EWRK3_IOPR);	} else if (lp->shmem_length == SHMEM_2K) {	  buf = lp->shmem_base;	  outb(page, EWRK3_MPR);	} else if (lp->shmem_length == SHMEM_32K) {	  buf = ((((short)page << 11) & 0x7800) + lp->shmem_base);	  outb((page >> 4), EWRK3_MPR);	} else if (lp->shmem_length == SHMEM_64K) {	  buf = ((((short)page << 11) & 0xf800) + lp->shmem_base);	  outb((page >> 5), EWRK3_MPR);	} else {	  status = -1;	  printk("%s: Oops - your private data area is hosed!\n",dev->name);	}	if (!status) {          /* 	  ** Set up the buffer control structures and copy the data from	  ** the socket buffer to the shared memory .	  */	  if (lp->shmem_length == IO_ONLY) {	    int i;	    u_char *p = skb->data;	    	    outb((char)(TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA);	    outb((char)(skb->len & 0xff), EWRK3_DATA);	    outb((char)((skb->len >> 8) & 0xff), EWRK3_DATA);	    outb((char)0x04, EWRK3_DATA);	    for (i=0; i<skb->len; i++) {	      outb(*p++, EWRK3_DATA);	    }	    outb(page, EWRK3_TQ);                      /* Start sending pkt */	  } else {	    writeb((char)(TCR_QMODE|TCR_PAD|TCR_IFC), (char *)buf);/* ctrl byte*/	    buf+=1;	    writeb((char)(skb->len & 0xff), (char *)buf);/* length (16 bit xfer)*/	    buf+=1;	    if (lp->txc) {	      writeb((char)(((skb->len >> 8) & 0xff) | XCT), (char *)buf);	      buf+=1;	      writeb(0x04, (char *)buf);               /* index byte */	      buf+=1;	      writeb(0x00, (char *)(buf + skb->len));  /* Write the XCT flag */	      memcpy_toio(buf, skb->data, PRELOAD);/* Write PRELOAD bytes*/	      outb(page, EWRK3_TQ);                    /* Start sending pkt */	      memcpy_toio(buf+PRELOAD, skb->data+PRELOAD, skb->len-PRELOAD);	      writeb(0xff, (char *)(buf + skb->len));  /* Write the XCT flag */	    } else {	      writeb((char)((skb->len >> 8) & 0xff), (char *)buf);	      buf+=1;	      writeb(0x04, (char *)buf);               /* index byte */	      buf+=1;	      memcpy_toio((char *)buf, skb->data, skb->len);/* Write data bytes */	      outb(page, EWRK3_TQ);                    /* Start sending pkt */	    }	  }	  dev->trans_start = jiffies;	  dev_kfree_skb (skb, FREE_WRITE);        } else {              /* return unused page to the free memory queue */	  outb(page, EWRK3_FMQ);	}	lp->lock = 0;         /* unlock the page register */      } else {	printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",	                                                 (u_char) page);      }    } else {      printk("ewrk3_queue_pkt(): No free resources...\n");      printk("ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n",inb(EWRK3_CSR),inb(EWRK3_ICR),inb(EWRK3_FMQC));    }        /* Check for free resources: clear 'tbusy' if there are some */    if (inb(EWRK3_FMQC) > 0) {      dev->tbusy = 0;    }    ENABLE_IRQs;  }  return status;}/*** The EWRK3 interrupt handler. */static voidewrk3_interrupt(int irq, void *dev_id, struct pt_regs * regs){    struct device *dev = (struct device *)(irq2dev_map[irq]);    struct ewrk3_private *lp;    u_long iobase;    u_char icr, cr, csr;    if (dev == NULL) {	printk ("ewrk3_interrupt(): irq %d for unknown device.\n", irq);    } else {      lp = (struct ewrk3_private *)dev->priv;      iobase = dev->base_addr;      if (dev->interrupt)	printk("%s: Re-entering the interrupt handler.\n", dev->name);      dev->interrupt = MASK_INTERRUPTS;      /* get the interrupt information */      csr = inb(EWRK3_CSR);      /*       ** Mask the EWRK3 board interrupts and turn on the LED       */      DISABLE_IRQs;      cr = inb(EWRK3_CR);      cr |= CR_LED;      outb(cr, EWRK3_CR);      if (csr & CSR_RNE)	  /* Rx interrupt (packet[s] arrived) */	ewrk3_rx(dev);      if (csr & CSR_TNE)          /* Tx interrupt (packet sent) */        ewrk3_tx(dev);      /*      ** Now deal with the TX/RX disable flags. These are set when there      ** are no more resources. If resources free up then enable these      ** interrupts, otherwise mask them - failure to do this will result      ** in the system hanging in an interrupt loop.      */      if (inb(EWRK3_FMQC)) {      /* any resources available? */	lp->irq_mask |= ICR_TXDM|ICR_RXDM;/* enable the interrupt source */	csr &= ~(CSR_TXD|CSR_RXD);/* ensure restart of a stalled TX or RX */	outb(csr, EWRK3_CSR);	dev->tbusy = 0;           /* clear TX busy flag */	mark_bh(NET_BH);      } else {	lp->irq_mask &= ~(ICR_TXDM|ICR_RXDM);/* disable the interrupt source */      }      /* Unmask the EWRK3 board interrupts and turn off the LED */      cr &= ~CR_LED;      outb(cr, EWRK3_CR);      dev->interrupt = UNMASK_INTERRUPTS;      ENABLE_IRQs;    }    return;}static intewrk3_rx(struct device *dev){  struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;  u_long iobase = dev->base_addr;  int i, status = 0;  u_char page, tmpPage = 0, tmpLock = 0;  u_long buf = 0;  while (inb(EWRK3_RQC) && !status) {        /* Whilst there's incoming data */    if ((page = inb(EWRK3_RQ)) < lp->mPage) {/* Get next entry's buffer page */      /*      ** Preempt any process using the current page register. Check for      ** an existing lock to reduce time taken in I/O transactions.      */      if ((tmpLock = set_bit(0, (void *)&lp->lock)) == 1) {   /* Assert lock */	if (lp->shmem_length == IO_ONLY) {              /* Get existing page */	  tmpPage = inb(EWRK3_IOPR);	} else {	  tmpPage = inb(EWRK3_MPR);	}      }

⌨️ 快捷键说明

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