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

📄 hp100.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef HP100_DEBUG_BM      printk("hp100: %s: Free skb: data @0x%.8x txrcommit=0x%x TXPDL=0x%x, done=0x%x\n",             dev->name,	     (u_int) lp->txrhead->skb->data,	     lp->txrcommit,	     hp100_inb(TX_PDL),	     donecount);#endif#ifdef LINUX_2_1      dev_kfree_skb( lp->txrhead->skb );#else      dev_kfree_skb( lp->txrhead->skb, FREE_WRITE );#endif      lp->txrhead->skb=(void *)NULL;      lp->txrhead=lp->txrhead->next;      lp->txrcommit--;    }}/* tx function for slave modes */static int hp100_start_xmit( struct sk_buff *skb, struct device *dev ){  int i, ok_flag;  int ioaddr = dev->base_addr;  u_short val;  struct hp100_private *lp = (struct hp100_private *)dev->priv;#ifdef HP100_DEBUG_B  hp100_outw( 0x4212, TRACE );  printk("hp100: %s: start_xmit\n", dev->name);#endif  if ( skb==NULL )    {#ifndef LINUX_2_1      dev_tint( dev );#endif      return 0;    }	  if ( skb->len <= 0 ) return 0;	  if ( lp->lan_type < 0 ) /* no LAN type detected yet? */    {      hp100_stop_interface( dev );      if ( ( lp->lan_type = hp100_sense_lan( dev ) ) < 0 )        {          printk( "hp100: %s: no connection found - check wire\n", dev->name );          hp100_start_interface( dev );  /* 10Mb/s RX packets maybe handled */          return -EIO;        }      if ( lp->lan_type == HP100_LAN_100 )        lp->hub_status = hp100_login_to_vg_hub( dev, FALSE ); /* relogin */      hp100_start_interface( dev );    }  /* If there is not enough free memory on the card... */  i=hp100_inl(TX_MEM_FREE)&0x7fffffff;  if ( !(((i/2)-539)>(skb->len+16) && (hp100_inb(TX_PKT_CNT)<255)) )    {#ifdef HP100_DEBUG      printk( "hp100: %s: start_xmit: tx free mem = 0x%x\n", dev->name, i );#endif      /* not waited long enough since last failed tx try? */      if ( jiffies - dev->trans_start < HZ ) 	{#ifdef HP100_DEBUG	  printk("hp100: %s: trans_start timing problem\n", dev->name);#endif	  return -EAGAIN;	}      if ( lp->lan_type == HP100_LAN_100 && lp->hub_status < 0 )	/* we have a 100Mb/s adapter but it isn't connected to hub */        {          printk( "hp100: %s: login to 100Mb/s hub retry\n", dev->name );          hp100_stop_interface( dev );          lp->hub_status = hp100_login_to_vg_hub( dev, FALSE );          hp100_start_interface( dev );        }      else        {          hp100_ints_off();          i = hp100_sense_lan( dev );          hp100_ints_on();          if ( i == HP100_LAN_ERR )            printk( "hp100: %s: link down detected\n", dev->name );	  else	    if ( lp->lan_type != i ) /* cable change! */	      {		/* it's very hard - all network setting must be changed!!! */		printk( "hp100: %s: cable change 10Mb/s <-> 100Mb/s detected\n", dev->name );		lp->lan_type = i;		hp100_stop_interface( dev );		if ( lp->lan_type == HP100_LAN_100 )		  lp->hub_status = hp100_login_to_vg_hub( dev, FALSE );		hp100_start_interface( dev );	      }	    else	      {		printk( "hp100: %s: interface reset\n", dev->name );		hp100_stop_interface( dev );		if ( lp->lan_type == HP100_LAN_100 )		  lp->hub_status = hp100_login_to_vg_hub( dev, FALSE );		hp100_start_interface( dev );		udelay(1000);	      }        }      dev->trans_start = jiffies;      return -EAGAIN;    }  for ( i=0; i<6000 && ( hp100_inb( OPTION_MSW ) & HP100_TX_CMD ); i++ )    {#ifdef HP100_DEBUG_TX      printk( "hp100: %s: start_xmit: busy\n", dev->name );#endif    }	  hp100_ints_off();  val = hp100_inw( IRQ_STATUS );  /* Ack / clear the interrupt TX_COMPLETE interrupt - this interrupt is set   * when the current packet being transmitted on the wire is completed. */  hp100_outw( HP100_TX_COMPLETE, IRQ_STATUS ); #ifdef HP100_DEBUG_TX  printk("hp100: %s: start_xmit: irq_status=0x%.4x, irqmask=0x%.4x, len=%d\n",dev->name,val,hp100_inw(IRQ_MASK),(int)skb->len );#endif  ok_flag = skb->len >= HP100_MIN_PACKET_SIZE;  i = ok_flag ? skb->len : HP100_MIN_PACKET_SIZE;  hp100_outw( i, DATA32 );       /* tell card the total packet length */  hp100_outw( i, FRAGMENT_LEN ); /* and first/only fragment length    */	  if ( lp->mode==2 ) /* memory mapped */    {      if ( lp->mem_ptr_virt ) /* high pci memory was remapped */	{	  /* Note: The J2585B needs alignment to 32bits here!  */	  memcpy( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 );	  if ( !ok_flag )	    memset( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len );	}      else	{	  /* Note: The J2585B needs alignment to 32bits here!  */	  memcpy_toio( lp->mem_ptr_phys, skb->data, (skb->len + 3) & ~3 );	  if ( !ok_flag )	    memset_io( lp->mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb->len );	}    }  else /* programmed i/o */    {      outsl( ioaddr + HP100_REG_DATA32, skb->data, ( skb->len + 3 ) >> 2 );      if ( !ok_flag )	for ( i = ( skb->len + 3 ) & ~3; i < HP100_MIN_PACKET_SIZE; i += 4 )	  hp100_outl( 0, DATA32 );    }	  hp100_outb( HP100_TX_CMD | HP100_SET_LB, OPTION_MSW ); /* send packet */	  lp->stats.tx_packets++;#ifdef LINUX_2_1  lp->stats.tx_bytes += skb->len;#endif  dev->trans_start=jiffies;  hp100_ints_on();	#ifdef LINUX_2_1  dev_kfree_skb( skb );#else  dev_kfree_skb( skb, FREE_WRITE );#endif	#ifdef HP100_DEBUG_TX  printk( "hp100: %s: start_xmit: end\n", dev->name );#endif	  return 0;}/* * Receive Function (Non-Busmaster mode) * Called when an "Receive Packet" interrupt occurs, i.e. the receive  * packet counter is non-zero. * For non-busmaster, this function does the whole work of transfering * the packet to the host memory and then up to higher layers via skb * and netif_rx.  */static void hp100_rx( struct device *dev ){  int packets, pkt_len;  int ioaddr = dev->base_addr;  struct hp100_private *lp = (struct hp100_private *)dev->priv;  u_int header;  struct sk_buff *skb;#ifdef DEBUG_B  hp100_outw( 0x4213, TRACE );  printk("hp100: %s: rx\n", dev->name);#endif  /* First get indication of received lan packet */  /* RX_PKT_CND indicates the number of packets which have been fully */  /* received onto the card but have not been fully transfered of the card */  packets = hp100_inb( RX_PKT_CNT );#ifdef HP100_DEBUG_RX  if ( packets > 1 )    printk( "hp100: %s: rx: waiting packets = %d\n", dev->name,packets );#endif  while ( packets-- > 0 )    {      /* If ADV_NXT_PKT is still set, we have to wait until the card has */      /* really advanced to the next packet. */      for (pkt_len=0; pkt_len<6000 &&(hp100_inb(OPTION_MSW)&HP100_ADV_NXT_PKT);	   pkt_len++ )        {#ifdef HP100_DEBUG_RX          printk( "hp100: %s: rx: busy, remaining packets = %d\n", dev->name, packets );#endif            }      /* First we get the header, which contains information about the */      /* actual length of the received packet. */      if( lp->mode==2 ) /* memory mapped mode */        {          if ( lp->mem_ptr_virt )    /* if memory was remapped */            header = *(__u32 *)lp->mem_ptr_virt;          else            header = readl( lp->mem_ptr_phys );        }      else /* programmed i/o */        header = hp100_inl( DATA32 );            pkt_len = ((header & HP100_PKT_LEN_MASK) + 3) & ~3;#ifdef HP100_DEBUG_RX      printk( "hp100: %s: rx: new packet - length=%d, errors=0x%x, dest=0x%x\n",      	      dev->name,              header & HP100_PKT_LEN_MASK, (header>>16)&0xfff8,              (header>>16)&7);#endif          /* Now we allocate the skb and transfer the data into it. */        skb = dev_alloc_skb( pkt_len );      if ( skb == NULL ) /* Not enough memory->drop packet */	{#ifdef HP100_DEBUG	  printk( "hp100: %s: rx: couldn't allocate a sk_buff of size %d\n", dev->name, pkt_len );#endif	  lp->stats.rx_dropped++;	}      else /* skb successfully allocated */	{	  u_char *ptr;      	  skb->dev = dev;      	  /* ptr to start of the sk_buff data area */	  ptr = (u_char *)skb_put( skb, pkt_len );      	  /* Now transfer the data from the card into that area */	  if ( lp->mode==2 )            {              if ( lp->mem_ptr_virt )                memcpy( ptr, lp->mem_ptr_virt, pkt_len );              /* Note alignment to 32bit transfers */              else                memcpy_fromio( ptr, lp->mem_ptr_phys, pkt_len );            }	  else /* io mapped */	    insl( ioaddr + HP100_REG_DATA32, ptr, pkt_len >> 2 );      	  skb->protocol = eth_type_trans( skb, dev );	  netif_rx( skb );	  lp->stats.rx_packets++;#ifdef LINUX_2_1	  lp->stats.rx_bytes += skb->len;#endif      #ifdef HP100_DEBUG_RX	  printk( "hp100: %s: rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",	  	  dev->name,		  ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ], ptr[ 4 ], ptr[ 5 ],		  ptr[ 6 ], ptr[ 7 ], ptr[ 8 ], ptr[ 9 ], ptr[ 10 ], ptr[ 11 ] );#endif	}        /* Indicate the card that we have got the packet */      hp100_outb( HP100_ADV_NXT_PKT | HP100_SET_LB, OPTION_MSW );      switch ( header & 0x00070000 ) {      case (HP100_MULTI_ADDR_HASH<<16):      case (HP100_MULTI_ADDR_NO_HASH<<16):	lp->stats.multicast++; break;      }    } /* end of while(there are packets) loop */#ifdef HP100_DEBUG_RX  printk( "hp100_rx: %s: end\n", dev->name );#endif}/*  * Receive Function for Busmaster Mode */static void hp100_rx_bm( struct device *dev ){  int ioaddr = dev->base_addr;  struct hp100_private *lp = (struct hp100_private *)dev->priv;  hp100_ring_t *ptr;  u_int header;  int pkt_len;#ifdef HP100_DEBUG_B  hp100_outw( 0x4214, TRACE );  printk("hp100: %s: rx_bm\n", dev->name);#endif#ifdef HP100_DEBUG  if(0==lp->rxrcommit)    {      printk("hp100: %s: rx_bm called although no PDLs were committed to adapter?\n", dev->name);       return;    }  else    /* RX_PKT_CNT states how many PDLs are currently formatted and available to      * the cards BM engine */    if( (hp100_inw(RX_PKT_CNT)&0x00ff) >= lp->rxrcommit)      {	printk("hp100: %s: More packets received than commited? RX_PKT_CNT=0x%x, commit=0x%x\n", dev->name, hp100_inw(RX_PKT_CNT)&0x00ff, lp->rxrcommit);	return;      }#endif  while( (lp->rxrcommit > hp100_inb(RX_PDL)) )    {      /*       * The packet was received into the pdl pointed to by lp->rxrhead (       * the oldest pdl in the ring        */						      /* First we get the header, which contains information about the */      /* actual length of the received packet. */            ptr=lp->rxrhead;            header = *(ptr->pdl-1);      pkt_len = (header & HP100_PKT_LEN_MASK);#ifdef HP100_DEBUG_BM      printk( "hp100: %s: rx_bm: header@0x%x=0x%x length=%d, errors=0x%x, dest=0x%x\n",      	      dev->name,              (u_int) (ptr->pdl-1),(u_int) header,              pkt_len,               (header>>16)&0xfff8,              (header>>16)&7);      printk( "hp100: %s: RX_PDL_COUNT:0x%x TX_PDL_COUNT:0x%x, RX_PKT_CNT=0x%x PDH=0x%x, Data@0x%x len=0x%x\n",      	      dev->name,	      hp100_inb( RX_PDL ),	      hp100_inb( TX_PDL ),	      hp100_inb( RX_PKT_CNT ),	      (u_int) *(ptr->pdl),	      (u_int) *(ptr->pdl+3),	      (u_int) *(ptr->pdl+4));#endif            if( (pkt_len>=MIN_ETHER_SIZE) &&          (pkt_len<=MAX_ETHER_SIZE) )          {	  if(ptr->skb==NULL)	    {	      printk("hp100: %s: rx_bm: skb null\n", dev->name);	      /* can happen if we only allocated room for the pdh due to memory shortage. */	      lp->stats.rx_dropped++;	    }	  else	    {	      skb_trim( ptr->skb, pkt_len );     /* Shorten it */	      ptr->skb->protocol = eth_type_trans( ptr->skb, dev );															      netif_rx( ptr->skb );              /* Up and away... */	      lp->stats.rx_packets++;#ifdef LINUX_2_1	      lp->stats.rx_bytes += ptr->skb->len;#endif	    }          switch ( header & 0x00070000 ) {          case (HP100_MULTI_ADDR_HASH<<16):          case (HP100_MULTI_ADDR_NO_HASH<<16):            lp->stats.multicast++; break;          }        }      else        {#ifdef HP100_DEBUG          printk("hp100: %s: rx_bm: Received bad packet (length=%d)\n",dev->name,pkt_len);#endif	  if(ptr->skb!=NULL)#ifdef LINUX_2_1	    dev_kfree_skb( ptr->skb );#else	    dev_kfree_skb( ptr->skb, FREE_READ );					#endif          lp->stats.rx_errors++;        }						      lp->rxrhead=lp->rxrhead->next;      /* Allocate a new rx PDL (so lp->rxrcommit stays the same) */      if (0 == hp100_build_rx_pdl( lp->rxrtail, dev ))        {	  /* No space for skb, header can still be received. */#ifdef HP100_DEBUG          printk("hp100: %s: rx_bm: No space for new PDL.\n", dev->name);#

⌨️ 快捷键说明

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