📄 hp100.c
字号:
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 } spin_lock_irqsave(&lp->lock, flags); 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_toio(lp->mem_ptr_virt, skb->data, (skb->len + 3) & ~3); if (!ok_flag) memset_io(lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len); } else { /* Note: The J2585B needs alignment to 32bits here! */ isa_memcpy_toio(lp->mem_ptr_phys, skb->data, (skb->len + 3) & ~3); if (!ok_flag) isa_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++; lp->stats.tx_bytes += skb->len; dev->trans_start = jiffies; hp100_ints_on(); spin_unlock_irqrestore(&lp->lock, flags); dev_kfree_skb_any(skb);#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 net_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 transferred 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 = readl(lp->mem_ptr_virt); else header = isa_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_fromio(ptr, lp->mem_ptr_virt,pkt_len); /* Note alignment to 32bit transfers */ else isa_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);#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 netif_rx(skb); dev->last_rx = jiffies; lp->stats.rx_packets++; lp->stats.rx_bytes += pkt_len; } /* 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 net_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... */ dev->last_rx = jiffies; lp->stats.rx_packets++; lp->stats.rx_bytes += pkt_len; } 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) dev_kfree_skb_any(ptr->skb); 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);#endif return; } else { /* successfully allocated new PDL - put it in ringlist at tail. */ hp100_outl((u32) lp->rxrtail->pdl_paddr, RX_PDA); lp->rxrtail = lp->rxrtail->next; } }}/* * statistics */static hp100_stats_t *hp100_get_stats(struct net_device *dev){ unsigned long flags; int ioaddr = dev->base_addr; struct hp100_private *lp = (struct hp100_private *) dev->priv;#ifdef HP100_DEBUG_B hp100_outw(0x4215, TRACE);#endif spin_lock_irqsave(&lp->lock, flags); hp100_ints_off(); /* Useful ? Jean II */ hp100_update_stats(dev); hp100_ints_on(); spin_unlock_irqrestore(&lp->lock, flags); return &(lp->stats);}static void hp100_update_stats(struct net_device *dev){ int ioaddr = dev->base_addr; u_short val; struct hp100_private *lp = (struct hp100_private *) dev->priv;#ifdef HP100_DEBUG_B hp100_outw(0x4216, TRACE); printk("hp100: %s: update-stats\n", dev->name);#endif /* Note: Statistics counters clear when read. */ hp100_page(MAC_CTRL); val = hp100_inw(DROPPED) & 0x0fff; lp->stats.rx_errors += val; lp->stats.rx_over_errors += val; val = hp100_inb(CRC); lp->stats.rx_errors += val; lp->stats.rx_crc_errors += val; val = hp100_inb(ABORT); lp->stats.tx_errors += val; lp->stats.tx_aborted_errors += val; hp100_page(PERFORMANCE);}static void hp100_misc_interrupt(struct net_device *dev){ struct hp100_private *lp = (struct hp100_private *) dev->priv;#ifdef HP100_DEBUG_B hp100_outw(0x4216, TRACE); printk("hp100: %s: misc_interrupt\n", dev->name);#endif /* Note: Statistics counters clear when read. */ lp->stats.rx_errors++; lp->stats.tx_errors++;}static void hp100_clear_stats(struct hp100_private *lp, int ioaddr){ unsigned long flags;#ifdef HP100_DEBUG_B hp100_outw(0x4217, TRACE); printk("hp100: %s: clear_stats\n", dev->name);#endif spin_lock_irqsave(&lp->lock, flags); hp100_page(MAC_CTRL); /* get all statistics bytes */ hp100_inw(DROPPED); hp100_inb(CRC); hp100_inb(ABORT); hp100_page(PERFORMANCE); spin_unlock_irqrestore(&lp->lock, flags);}/* * multicast setup *//* * Set or clear the multicast filter for this adapter. */static void hp100_set_multicast_list(struct net_device *dev){ unsigned long flags; int ioaddr = dev->base_addr; struct hp100_private *lp = (struct hp100_private *) dev->priv;#ifdef HP100_DEBUG_B hp100_outw(0x4218, TRACE); printk("hp100: %s: set_mc_list\n", dev->name);#endif spin_lock_irqsave(&lp->lock, flags); hp100_ints_off(); hp100_page(MAC_CTRL); hp100_andb(~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1); /* stop rx/tx */ if (dev->flags & IFF_PROMISC) { lp->mac2_mode = HP100_MAC2MODE6; /* promiscuous mode = get all good */ lp->mac1_mode = HP100_MAC1MODE6; /* packets on the net */ memset(&lp->hash_bytes, 0xff, 8); } else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) { lp->mac2_mode = HP100_MAC2MODE5; /* multicast mode = get packets for */ lp->mac1_mode = HP100_MAC1MODE5; /* me, broadcasts and all multicasts */#ifdef HP100_MULTICAST_FILTER /* doesn't work!!! */ if (dev->flags & IFF_ALLMULTI) { /* set hash filter to receive all multicast packets */ memset(&lp->hash_bytes, 0xff, 8); } else { int i, j, idx; u_char *addrs; struct dev_mc_list *dmi; memset(&lp->hash_bytes, 0x00, 8);#ifdef HP100_DEBUG printk("hp100: %s: computing hash filter - mc_count = %i\n", dev->name, dev->mc_count);#endif for (i = 0, dmi = dev->mc_list; i < dev->mc_count; i++, dmi = dmi->next) { addrs = dmi->dmi_addr; if ((*addrs & 0x01) == 0x01) { /* multicast address? */#ifdef HP100_DEBUG printk("hp100: %s: multicast = %02x:%02x:%02x:%02x:%02x:%02x, ", dev->name, addrs[0], addrs[1], addr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -