📄 lanstreamer.c
字号:
writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM); while (streamer_priv->srb_queued) { interruptible_sleep_on_timeout(&streamer_priv->srb_wait, jiffies + 60 * HZ); if (signal_pending(current)) { printk(KERN_WARNING "%s: SRB timed out.\n", dev->name); printk(KERN_WARNING "SISR=%x MISR=%x LISR=%x\n", readw(streamer_mmio + SISR), readw(streamer_mmio + MISR_RUM), readw(streamer_mmio + LISR)); streamer_priv->srb_queued = 0; break; } } restore_flags(flags); streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1); for (i = 0; i < STREAMER_RX_RING_SIZE; i++) { if (streamer_priv->rx_ring_skb[streamer_priv->rx_ring_last_received]) { dev_kfree_skb(streamer_priv->rx_ring_skb[streamer_priv->rx_ring_last_received]); } streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1); } /* reset tx/rx fifo's and busmaster logic */ /* TBD. Add graceful way to reset the LLC channel without doing a soft reset. writel(readl(streamer_mmio+BCTL)|(3<<13),streamer_mmio+BCTL); udelay(1); writel(readl(streamer_mmio+BCTL)&~(3<<13),streamer_mmio+BCTL); */#if STREAMER_DEBUG writew(streamer_priv->srb, streamer_mmio + LAPA); printk("srb): "); for (i = 0; i < 2; i++) { printk("%x ", ntohs(readw(streamer_mmio + LAPDINC))); } printk("\n");#endif free_irq(dev->irq, dev); return 0;}static void streamer_set_rx_mode(struct net_device *dev){ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; __u8 *streamer_mmio = streamer_priv->streamer_mmio; __u8 options = 0; struct dev_mc_list *dmi; unsigned char dev_mc_address[5]; int i; writel(streamer_priv->srb, streamer_mmio + LAPA); options = streamer_priv->streamer_copy_all_options; if (dev->flags & IFF_PROMISC) options |= (3 << 5); /* All LLC and MAC frames, all through the main rx channel */ else options &= ~(3 << 5); /* Only issue the srb if there is a change in options */ if ((options ^ streamer_priv->streamer_copy_all_options)) { /* Now to issue the srb command to alter the copy.all.options */ writew(htons(SRB_MODIFY_RECEIVE_OPTIONS << 8), streamer_mmio+LAPDINC); writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC); writew(htons((streamer_priv->streamer_receive_options << 8) | options),streamer_mmio+LAPDINC); writew(htons(0x4a41),streamer_mmio+LAPDINC); writew(htons(0x4d45),streamer_mmio+LAPDINC); writew(htons(0x5320),streamer_mmio+LAPDINC); writew(0x2020, streamer_mmio + LAPDINC); streamer_priv->srb_queued = 2; /* Can't sleep, use srb_bh */ writel(LISR_SRB_CMD, streamer_mmio + LISR_SUM); streamer_priv->streamer_copy_all_options = options; return; } /* Set the functional addresses we need for multicast */ writel(streamer_priv->srb,streamer_mmio+LAPA); dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; dev_mc_address[2] |= dmi->dmi_addr[4] ; dev_mc_address[3] |= dmi->dmi_addr[5] ; } writew(htons(SRB_SET_FUNC_ADDRESS << 8),streamer_mmio+LAPDINC); writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC); writew(0,streamer_mmio+LAPDINC); writew(htons( (dev_mc_address[0] << 8) | dev_mc_address[1]),streamer_mmio+LAPDINC); writew(htons( (dev_mc_address[2] << 8) | dev_mc_address[3]),streamer_mmio+LAPDINC); streamer_priv->srb_queued = 2 ; writel(LISR_SRB_CMD,streamer_mmio+LISR_SUM);}static void streamer_srb_bh(struct net_device *dev){ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; __u8 *streamer_mmio = streamer_priv->streamer_mmio; __u16 srb_word; writew(streamer_priv->srb, streamer_mmio + LAPA); srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; switch (srb_word) { /* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous) * At some point we should do something if we get an error, such as * resetting the IFF_PROMISC flag in dev */ case SRB_MODIFY_RECEIVE_OPTIONS: srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; switch (srb_word) { case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command\n", dev->name); break; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name); break; default: if (streamer_priv->streamer_message_level) printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n", dev->name, streamer_priv->streamer_copy_all_options, streamer_priv->streamer_receive_options); break; } /* switch srb[2] */ break; /* SRB_SET_GROUP_ADDRESS - Multicast group setting */ case SRB_SET_GROUP_ADDRESS: srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; switch (srb_word) { case 0x00: break; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name); break; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name); break; case 0x3c: printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n", dev->name); break; case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */ printk(KERN_WARNING "%s: Group address registers full\n", dev->name); break; case 0x55: printk(KERN_INFO "%s: Group Address already set.\n", dev->name); break; default: break; } /* switch srb[2] */ break; /* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list */ case SRB_RESET_GROUP_ADDRESS: srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; switch (srb_word) { case 0x00: break; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name); break; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name); break; case 0x39: /* Must deal with this if individual multicast addresses used */ printk(KERN_INFO "%s: Group address not found \n", dev->name); break; default: break; } /* switch srb[2] */ break; /* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode */ case SRB_SET_FUNC_ADDRESS: srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; switch (srb_word) { case 0x00: if (streamer_priv->streamer_message_level) printk(KERN_INFO "%s: Functional Address Mask Set \n", dev->name); break; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name); break; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name); break; default: break; } /* switch srb[2] */ break; /* SRB_READ_LOG - Read and reset the adapter error counters */ case SRB_READ_LOG: srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; switch (srb_word) { case 0x00: { int i; if (streamer_priv->streamer_message_level) printk(KERN_INFO "%s: Read Log command complete\n", dev->name); printk("Read Log statistics: "); writew(streamer_priv->srb + 6, streamer_mmio + LAPA); for (i = 0; i < 5; i++) { printk("%x:", ntohs(readw(streamer_mmio + LAPDINC))); } printk("\n"); } break; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name); break; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name); break; } /* switch srb[2] */ break; /* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */ case SRB_READ_SR_COUNTERS: srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; switch (srb_word) { case 0x00: if (streamer_priv->streamer_message_level) printk(KERN_INFO "%s: Read Source Routing Counters issued\n", dev->name); break; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name); break; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name); break; default: break; } /* switch srb[2] */ break; default: printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n", dev->name); break; } /* switch srb[0] */}static struct net_device_stats *streamer_get_stats(struct net_device *dev){ struct streamer_private *streamer_priv; streamer_priv = (struct streamer_private *) dev->priv; return (struct net_device_stats *) &streamer_priv->streamer_stats;}static int streamer_set_mac_address(struct net_device *dev, void *addr){ struct sockaddr *saddr = addr; struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; if (netif_running(dev)) { printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name); return -EIO; } memcpy(streamer_priv->streamer_laa, saddr->sa_data, dev->addr_len); if (streamer_priv->streamer_message_level) { printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n", dev->name, streamer_priv->streamer_laa[0], streamer_priv->streamer_laa[1], streamer_priv->streamer_laa[2], streamer_priv->streamer_laa[3], streamer_priv->streamer_laa[4], streamer_priv->streamer_laa[5]); } return 0;}static void streamer_arb_cmd(struct net_device *dev){ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; __u8 *streamer_mmio = streamer_priv->streamer_mmio; __u8 header_len; __u16 frame_len, buffer_len; struct sk_buff *mac_frame; __u8 frame_data[256]; __u16 buff_off; __u16 lan_status = 0, lan_status_diff; /* Initialize to stop compiler warning */ __u8 fdx_prot_error; __u16 next_ptr; __u16 arb_word;#if STREAMER_NETWORK_MONITOR struct trh_hdr *mac_hdr;#endif writew(streamer_priv->arb, streamer_mmio + LAPA); arb_word=ntohs(readw(streamer_mmio+LAPD)) >> 8; if (arb_word == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */ writew(streamer_priv->arb + 6, streamer_mmio + LAPA); streamer_priv->mac_rx_buffer = buff_off = ntohs(readw(streamer_mmio + LAPDINC)); header_len=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; /* 802.5 Token-Ring Header Length */ frame_len = ntohs(readw(streamer_mmio + LAPDINC));#if STREAMER_DEBUG { int i; __u16 next; __u8 status; __u16 len; writew(ntohs(buff_off), streamer_mmio + LAPA); /*setup window to frame data */ next = htons(readw(streamer_mmio + LAPDINC)); status = ntohs(readw(streamer_mmio + LAPDINC)) & 0xff; len = ntohs(readw(streamer_mmio + LAPDINC)); /* print out 1st 14 bytes of frame data */ for (i = 0; i < 7; i++) { printk("Loc %d = %04x\n", i, ntohs(readw (streamer_mmio + LAPDINC))); } printk("next %04x, fs %02x, len %04x \n", next, status, len); }#endif if (!(mac_frame = dev_alloc_skb(frame_len))) { printk(KERN_WARNING "%s: Memory squeeze, dropping frame.\n", dev->name); goto drop_frame; } /* Walk the buffer chain, creating the frame */ do { int i; __u16 rx_word;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -