ei_receive()函数


static void ei_receive(struct device *dev)
{
    int e8390_base = dev->base_addr;
    struct ei_device *ei_local = (struct ei_device *) dev->priv;
    int rxing_page, this_frame, next_frame, current_offset;
    int rx_pkt_count = 0;
    struct e8390_pkt_hdr rx_frame;
    int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
   
    while (++rx_pkt_count < 10) {
  int pkt_len;
 
  /* Get the rx page (incoming packet pointer). */
  outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
  rxing_page = inb_p(e8390_base + EN1_CURPAG);
  outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
 
  /* Remove one frame from the ring.  Boundary is always a page behind. */
  this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
  if (this_frame >= ei_local->stop_page)
   this_frame = ei_local->rx_start_page;
 
  /* Someday we'll omit the previous, iff we never get this message.
     (There is at least one clone claimed to have a problem.)  */
  if (ei_debug > 0  &&  this_frame != ei_local->current_page)
   printk("%s: mismatched read page pointers %2x vs %2x. ",
       dev->name, this_frame, ei_local->current_page);
 
  if (this_frame == rxing_page) /* Read all the frames? */
   break;    /* Done for now */
 
  current_offset = this_frame << 8;
  ei_block_input(dev, sizeof(rx_frame), (char *)&rx_frame,
        current_offset);
 
  pkt_len = rx_frame.count - sizeof(rx_frame);
 
  next_frame = this_frame + 1 + ((pkt_len+4)>>8);
 
  /* Check for bogosity warned by 3c503 book: the status byte is never
     written.  This happened a lot during testing! This code should be
     cleaned up someday. */
  if (rx_frame.next != next_frame
   && rx_frame.next != next_frame + 1
   && rx_frame.next != next_frame - num_rx_pages
   && rx_frame.next != next_frame + 1 - num_rx_pages) {
   ei_local->current_page = rxing_page;
   outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
   ei_local->stat.rx_errors++;
   continue;
  }

  if (pkt_len < 60  ||  pkt_len > 1518) {
   if (ei_debug)
    printk("%s: bogus packet size: %d, status=%#2x nxpg=%#2x. ",
        dev->name, rx_frame.count, rx_frame.status,
        rx_frame.next);
   ei_local->stat.rx_errors++;
  } else if ((rx_frame.status & 0x0F) == ENRSR_RXOK) {
   struct sk_buff *skb;
  
   skb = alloc_skb(pkt_len, GFP_ATOMIC);
   if (skb == NULL) {
    if (ei_debug > 1)
     printk("%s: Couldn't allocate a sk_buff of size %d. ",
         dev->name, pkt_len);
    ei_local->stat.rx_dropped++;
    break;
   } else {
    skb->len = pkt_len;
    skb->dev = dev;
   
    ei_block_input(dev, pkt_len, (char *) skb->data,
          current_offset + sizeof(rx_frame));
    netif_rx(skb);
    ei_local->stat.rx_packets++;
   }
  } else {
   int errs = rx_frame.status;
   if (ei_debug)
    printk("%s: bogus packet: status=%#2x nxpg=%#2x size=%d ",
        dev->name, rx_frame.status, rx_frame.next,
        rx_frame.count);
   if (errs & ENRSR_FO)
    ei_local->stat.rx_fifo_errors++;
  }
  next_frame = rx_frame.next;
 
  /* This _should_ never happen: it's here for avoiding bad clones. */
  if (next_frame >= ei_local->stop_page) {
   printk("%s: next frame inconsistency, %#2x ", dev->name,
       next_frame);
   next_frame = ei_local->rx_start_page;
  }
  ei_local->current_page = next_frame;
  outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
    }
    /* If any worth-while packets have been received, dev_rint()
       has done a mark_bh(NET_BH) for us and will work on them
       when we get to the bottom-half routine. */

 /* Record the maximum Rx packet queue. */
 if (rx_pkt_count > high_water_mark)
  high_water_mark = rx_pkt_count;

    /* Bug alert!  Reset ENISR_OVER to avoid spurious overruns! */
    outb_p(ENISR_RX+ENISR_RX_ERR+ENISR_OVER, e8390_base+EN0_ISR);
    return;
}

  本文转自:http://blog.csdn.net/yming0221/article/details/7492423