📄 hp100.c
字号:
#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 + -