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

📄 hp100.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	  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 );	      }	}      dev->trans_start = jiffies;      return -EAGAIN;    }	  /*   * we have to turn int's off before modifying this, otherwise   * a tx_pdl_cleanup could occur at the same time   */  save_flags( flags );  cli();  ringptr=lp->txrtail;  lp->txrtail=ringptr->next;	  /* Check whether packet has minimal packet size */  ok_flag = skb->len >= HP100_MIN_PACKET_SIZE;  i = ok_flag ? skb->len : HP100_MIN_PACKET_SIZE;					  ringptr->skb=skb;  ringptr->pdl[0]=((1<<16) | i);                /* PDH: 1 Fragment & length */  ringptr->pdl[1]=(u32)virt_to_bus(skb->data);  /* 1st Frag: Adr. of data */  if(lp->chip==HP100_CHIPID_SHASTA)    {      /* TODO:Could someone who has the EISA card please check if this works? */      ringptr->pdl[2]=i;    }  else /* Lassen */    {      /* In the PDL, don't use the padded size but the real packet size: */      ringptr->pdl[2]=skb->len;              /* 1st Frag: Length of frag */    }  /* Hand this PDL to the card. */  hp100_outl( ringptr->pdl_paddr, TX_PDA_L ); /* Low Prio. Queue */	  lp->txrcommit++;  restore_flags( flags );	  /* Update statistics */	  lp->stats.tx_packets++;#ifdef LINUX_2_1  lp->stats.tx_bytes += skb->len;#endif  dev->trans_start = jiffies;	  return 0;}/* clean_txring checks if packets have been sent by the card by reading * the TX_PDL register from the performance page and comparing it to the * number of commited packets. It then frees the skb's of the packets that * obviously have been sent to the network. * * Needs the PERFORMANCE page selected.  */static void hp100_clean_txring( struct device *dev ){  struct hp100_private *lp = (struct hp100_private *)dev->priv;  int    ioaddr = dev->base_addr;  int    donecount;#ifdef HP100_DEBUG_B  hp100_outw( 0x4211, TRACE );  printk("hp100: %s: clean txring\n", dev->name);#endif  /* How many PDLs have been transmitted? */  donecount=(lp->txrcommit)-hp100_inb(TX_PDL);#ifdef HP100_DEBUG  if(donecount>MAX_TX_PDL)    printk("hp100: %s: Warning: More PDLs transmitted than commited to card???\n",dev->name);#endif  for( ; 0!=donecount; donecount-- )    {#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 );		mdelay(1);	      }        }      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_add

⌨️ 快捷键说明

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