📄 lanstreamer.c
字号:
{ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; __u8 *streamer_mmio = streamer_priv->streamer_mmio; unsigned long flags; char open_error[255]; int i, open_finished = 1; __u16 srb_word; __u16 srb_open; int rc; if (readw(streamer_mmio+BMCTL_SUM) & BMCTL_RX_ENABLED) { rc=streamer_reset(dev); } if (request_irq(dev->irq, &streamer_interrupt, SA_SHIRQ, "streamer", dev)) { return -EAGAIN; }#if STREAMER_DEBUG printk("BMCTL: %x\n", readw(streamer_mmio + BMCTL_SUM)); printk("pending ints: %x\n", readw(streamer_mmio + SISR));#endif writew(SISR_MI | SISR_SRB_REPLY, streamer_mmio + SISR_MASK); /* more ints later, doesn't stop arb cmd interrupt */ writew(LISR_LIE, streamer_mmio + LISR); /* more ints later */ /* adapter is closed, so SRB is pointed to by LAPWWO */ writew(readw(streamer_mmio + LAPWWO), streamer_mmio + LAPA);#if STREAMER_DEBUG printk("LAPWWO: %x, LAPA: %x\n", readw(streamer_mmio + LAPWWO), readw(streamer_mmio + LAPA)); printk("LAPE: %x\n", readw(streamer_mmio + LAPE)); printk("SISR Mask = %04x\n", readw(streamer_mmio + SISR_MASK));#endif do { int i; save_flags(flags); cli(); for (i = 0; i < SRB_COMMAND_SIZE; i += 2) { writew(0, streamer_mmio + LAPDINC); } writew(readw(streamer_mmio+LAPWWO),streamer_mmio+LAPA); writew(htons(SRB_OPEN_ADAPTER<<8),streamer_mmio+LAPDINC) ; /* open */ writew(htons(STREAMER_CLEAR_RET_CODE<<8),streamer_mmio+LAPDINC); writew(STREAMER_CLEAR_RET_CODE, streamer_mmio + LAPDINC); writew(readw(streamer_mmio + LAPWWO) + 8, streamer_mmio + LAPA);#if STREAMER_NETWORK_MONITOR /* If Network Monitor, instruct card to copy MAC frames through the ARB */ writew(htons(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON), streamer_mmio + LAPDINC); /* offset 8 word contains open options */#else writew(htons(OPEN_ADAPTER_ENABLE_FDX), streamer_mmio + LAPDINC); /* Offset 8 word contains Open.Options */#endif if (streamer_priv->streamer_laa[0]) { writew(readw(streamer_mmio + LAPWWO) + 12, streamer_mmio + LAPA); writew(htons((streamer_priv->streamer_laa[0] << 8) | streamer_priv->streamer_laa[1]),streamer_mmio+LAPDINC); writew(htons((streamer_priv->streamer_laa[2] << 8) | streamer_priv->streamer_laa[3]),streamer_mmio+LAPDINC); writew(htons((streamer_priv->streamer_laa[4] << 8) | streamer_priv->streamer_laa[5]),streamer_mmio+LAPDINC); memcpy(dev->dev_addr, streamer_priv->streamer_laa, dev->addr_len); } /* save off srb open offset */ srb_open = readw(streamer_mmio + LAPWWO);#if STREAMER_DEBUG writew(readw(streamer_mmio + LAPWWO), streamer_mmio + LAPA); printk("srb open request: \n"); for (i = 0; i < 16; i++) { printk("%x:", ntohs(readw(streamer_mmio + LAPDINC))); } printk("\n");#endif streamer_priv->srb_queued = 1; /* signal solo that SRB command has been issued */ writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM); while (streamer_priv->srb_queued) { interruptible_sleep_on_timeout(&streamer_priv->srb_wait, 5 * 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);#if STREAMER_DEBUG printk("SISR_MASK: %x\n", readw(streamer_mmio + SISR_MASK)); printk("srb open response:\n"); writew(srb_open, streamer_mmio + LAPA); for (i = 0; i < 10; i++) { printk("%x:", ntohs(readw(streamer_mmio + LAPDINC))); }#endif /* If we get the same return response as we set, the interrupt wasn't raised and the open * timed out. */ writew(srb_open + 2, streamer_mmio + LAPA); srb_word = ntohs(readw(streamer_mmio + LAPD)) & 0xFF; if (srb_word == STREAMER_CLEAR_RET_CODE) { printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name); return -EIO; } if (srb_word != 0) { if (srb_word == 0x07) { if (!streamer_priv->streamer_ring_speed && open_finished) { /* Autosense , first time around */ printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name); open_finished = 0; } else { __u16 error_code; writew(srb_open + 6, streamer_mmio + LAPA); error_code = ntohs(readw(streamer_mmio + LAPD)); strcpy(open_error, open_maj_error[(error_code & 0xf0) >> 4]); strcat(open_error, " - "); strcat(open_error, open_min_error[(error_code & 0x0f)]); if (!streamer_priv->streamer_ring_speed && ((error_code & 0x0f) == 0x0d)) { printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n", dev->name); printk(KERN_WARNING "%s: Please try again with a specified ring speed \n", dev->name); free_irq(dev->irq, dev); return -EIO; } printk(KERN_WARNING "%s: %s\n", dev->name, open_error); free_irq(dev->irq, dev); return -EIO; } /* if autosense && open_finished */ } else { printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name, srb_word); free_irq(dev->irq, dev); return -EIO; } } else open_finished = 1; } while (!(open_finished)); /* Will only loop if ring speed mismatch re-open attempted && autosense is on */ writew(srb_open + 18, streamer_mmio + LAPA); srb_word=ntohs(readw(streamer_mmio+LAPD)) >> 8; if (srb_word & (1 << 3)) if (streamer_priv->streamer_message_level) printk(KERN_INFO "%s: Opened in FDX Mode\n", dev->name); if (srb_word & 1) streamer_priv->streamer_ring_speed = 16; else streamer_priv->streamer_ring_speed = 4; if (streamer_priv->streamer_message_level) printk(KERN_INFO "%s: Opened in %d Mbps mode\n", dev->name, streamer_priv->streamer_ring_speed); writew(srb_open + 8, streamer_mmio + LAPA); streamer_priv->asb = ntohs(readw(streamer_mmio + LAPDINC)); streamer_priv->srb = ntohs(readw(streamer_mmio + LAPDINC)); streamer_priv->arb = ntohs(readw(streamer_mmio + LAPDINC)); readw(streamer_mmio + LAPDINC); /* offset 14 word is rsvd */ streamer_priv->trb = ntohs(readw(streamer_mmio + LAPDINC)); streamer_priv->streamer_receive_options = 0x00; streamer_priv->streamer_copy_all_options = 0; /* setup rx ring */ /* enable rx channel */ writew(~BMCTL_RX_DIS, streamer_mmio + BMCTL_RUM); /* setup rx descriptors */ streamer_priv->streamer_rx_ring= kmalloc( sizeof(struct streamer_rx_desc)* STREAMER_RX_RING_SIZE,GFP_KERNEL); if (!streamer_priv->streamer_rx_ring) { printk(KERN_WARNING "%s ALLOC of streamer rx ring FAILED!!\n",dev->name); return -EIO; } for (i = 0; i < STREAMER_RX_RING_SIZE; i++) { struct sk_buff *skb; skb = dev_alloc_skb(streamer_priv->pkt_buf_sz); if (skb == NULL) break; skb->dev = dev; streamer_priv->streamer_rx_ring[i].forward = virt_to_bus(&streamer_priv->streamer_rx_ring[i + 1]); streamer_priv->streamer_rx_ring[i].status = 0; streamer_priv->streamer_rx_ring[i].buffer = virt_to_bus(skb->data); streamer_priv->streamer_rx_ring[i].framelen_buflen = streamer_priv->pkt_buf_sz; streamer_priv->rx_ring_skb[i] = skb; } streamer_priv->streamer_rx_ring[STREAMER_RX_RING_SIZE - 1].forward = virt_to_bus(&streamer_priv->streamer_rx_ring[0]); if (i == 0) { printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n", dev->name); free_irq(dev->irq, dev); return -EIO; } streamer_priv->rx_ring_last_received = STREAMER_RX_RING_SIZE - 1; /* last processed rx status */ writel(virt_to_bus(&streamer_priv->streamer_rx_ring[0]), streamer_mmio + RXBDA); writel(virt_to_bus(&streamer_priv->streamer_rx_ring[STREAMER_RX_RING_SIZE - 1]), streamer_mmio + RXLBDA); /* set bus master interrupt event mask */ writew(MISR_RX_NOBUF | MISR_RX_EOF, streamer_mmio + MISR_MASK); /* setup tx ring */ streamer_priv->streamer_tx_ring=kmalloc(sizeof(struct streamer_tx_desc)* STREAMER_TX_RING_SIZE,GFP_KERNEL); if (!streamer_priv->streamer_tx_ring) { printk(KERN_WARNING "%s ALLOC of streamer_tx_ring FAILED\n",dev->name); return -EIO; } writew(~BMCTL_TX2_DIS, streamer_mmio + BMCTL_RUM); /* Enables TX channel 2 */ for (i = 0; i < STREAMER_TX_RING_SIZE; i++) { streamer_priv->streamer_tx_ring[i].forward = virt_to_bus(&streamer_priv->streamer_tx_ring[i + 1]); streamer_priv->streamer_tx_ring[i].status = 0; streamer_priv->streamer_tx_ring[i].bufcnt_framelen = 0; streamer_priv->streamer_tx_ring[i].buffer = 0; streamer_priv->streamer_tx_ring[i].buflen = 0; } streamer_priv->streamer_tx_ring[STREAMER_TX_RING_SIZE - 1].forward = virt_to_bus(&streamer_priv->streamer_tx_ring[0]);; streamer_priv->free_tx_ring_entries = STREAMER_TX_RING_SIZE; streamer_priv->tx_ring_free = 0; /* next entry in tx ring to use */ streamer_priv->tx_ring_last_status = STREAMER_TX_RING_SIZE - 1; /* set Busmaster interrupt event mask (handle receives on interrupt only */ writew(MISR_TX2_EOF | MISR_RX_NOBUF | MISR_RX_EOF, streamer_mmio + MISR_MASK); /* set system event interrupt mask */ writew(SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE, streamer_mmio + SISR_MASK_SUM);#if STREAMER_DEBUG printk("BMCTL: %x\n", readw(streamer_mmio + BMCTL_SUM)); printk("SISR MASK: %x\n", readw(streamer_mmio + SISR_MASK));#endif#if STREAMER_NETWORK_MONITOR writew(streamer_priv->streamer_addr_table_addr, streamer_mmio + LAPA); printk("%s: Node Address: %04x:%04x:%04x\n", dev->name, ntohs(readw(streamer_mmio + LAPDINC)), ntohs(readw(streamer_mmio + LAPDINC)), ntohs(readw(streamer_mmio + LAPDINC))); readw(streamer_mmio + LAPDINC); readw(streamer_mmio + LAPDINC); printk("%s: Functional Address: %04x:%04x\n", dev->name, ntohs(readw(streamer_mmio + LAPDINC)), ntohs(readw(streamer_mmio + LAPDINC))); writew(streamer_priv->streamer_parms_addr + 4, streamer_mmio + LAPA); printk("%s: NAUN Address: %04x:%04x:%04x\n", dev->name, ntohs(readw(streamer_mmio + LAPDINC)), ntohs(readw(streamer_mmio + LAPDINC)), ntohs(readw(streamer_mmio + LAPDINC)));#endif netif_start_queue(dev); MOD_INC_USE_COUNT; return 0;}/* * When we enter the rx routine we do not know how many frames have been * queued on the rx channel. Therefore we start at the next rx status * position and travel around the receive ring until we have completed * all the frames. * * This means that we may process the frame before we receive the end * of frame interrupt. This is why we always test the status instead * of blindly processing the next frame. * */static void streamer_rx(struct net_device *dev){ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; __u8 *streamer_mmio = streamer_priv->streamer_mmio; struct streamer_rx_desc *rx_desc; int rx_ring_last_received, length, frame_length, buffer_cnt = 0; struct sk_buff *skb, *skb2; /* setup the next rx descriptor to be received */ rx_desc = &streamer_priv->streamer_rx_ring[(streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1)]; rx_ring_last_received = streamer_priv->rx_ring_last_received; while (rx_desc->status & 0x01000000) { /* While processed descriptors are available */ if (rx_ring_last_received != streamer_priv->rx_ring_last_received) { printk(KERN_WARNING "RX Error 1 rx_ring_last_received not the same %x %x\n", rx_ring_last_received, streamer_priv->rx_ring_last_received); } streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1); rx_ring_last_received = streamer_priv->rx_ring_last_received; length = rx_desc->framelen_buflen & 0xffff; /* buffer length */ frame_length = (rx_desc->framelen_buflen >> 16) & 0xffff; if (rx_desc->status & 0x7E830000) { /* errors */ if (streamer_priv->streamer_message_level) { printk(KERN_WARNING "%s: Rx Error %x \n", dev->name, rx_desc->status); } } else { /* received without errors */ if (rx_desc->status & 0x80000000) { /* frame complete */ buffer_cnt = 1; skb = dev_alloc_skb(streamer_priv->pkt_buf_sz); } else { skb = dev_alloc_skb(frame_length); } if (skb == NULL) { printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n", dev->name); streamer_priv->streamer_stats.rx_dropped++; } else { /* we allocated an skb OK */ skb->dev = dev; if (buffer_cnt == 1) { skb2 = streamer_priv->rx_ring_skb[rx_ring_last_received];#if STREAMER_DEBUG_PACKETS { int i; printk("streamer_rx packet print: skb->data2 %p skb->head %p\n", skb2->data, skb2->head); for (i = 0; i < frame_length; i++) { printk("%x:", skb2->data[i]); if (((i + 1) % 16) == 0) printk("\n"); } printk("\n"); }#endif skb_put(skb2, length); skb2->protocol = tr_type_trans(skb2, dev); /* recycle this descriptor */ streamer_priv->streamer_rx_ring[rx_ring_last_received].status = 0; streamer_priv->streamer_rx_ring[rx_ring_last_received].framelen_buflen = streamer_priv->pkt_buf_sz; streamer_priv->streamer_rx_ring[rx_ring_last_received].buffer = virt_to_bus(skb->data); streamer_priv-> rx_ring_skb[rx_ring_last_received] = skb; /* place recycled descriptor back on the adapter */ writel(virt_to_bus(&streamer_priv->streamer_rx_ring[rx_ring_last_received]),streamer_mmio + RXLBDA); /* pass the received skb up to the protocol */ netif_rx(skb2); } else { do { /* Walk the buffers */ memcpy(skb_put(skb, length),bus_to_virt(rx_desc->buffer), length); /* copy this fragment */ streamer_priv->streamer_rx_ring[rx_ring_last_received].status = 0; streamer_priv->streamer_rx_ring[rx_ring_last_received].framelen_buflen = streamer_priv->pkt_buf_sz; /* give descriptor back to the adapter */ writel(virt_to_bus(&streamer_priv->streamer_rx_ring[rx_ring_last_received]), streamer_mmio + RXLBDA); if (rx_desc->status & 0x80000000) break; /* this descriptor completes the frame */ /* else get the next pending descriptor */ if (rx_ring_last_received!= streamer_priv->rx_ring_last_received) { printk("RX Error rx_ring_last_received not the same %x %x\n", rx_ring_last_received, streamer_priv->rx_ring_last_received); } rx_desc = &streamer_priv->streamer_rx_ring[(streamer_priv->rx_ring_last_received+1) & (STREAMER_RX_RING_SIZE-1)]; length = rx_desc->framelen_buflen & 0xffff; /* buffer length */ streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received+1) & (STREAMER_RX_RING_SIZE - 1); rx_ring_last_received = streamer_priv->rx_ring_last_received; } while (1); skb->protocol = tr_type_trans(skb, dev); /* send up to the protocol */ netif_rx(skb); } streamer_priv->streamer_stats.rx_packets++; streamer_priv->streamer_stats.rx_bytes += length; } /* if skb == null */ } /* end received without errors */ /* try the next one */ rx_desc = &streamer_priv->streamer_rx_ring[(rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1)]; } /* end for all completed rx descriptors */}static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = (struct net_device *) dev_id; struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; __u8 *streamer_mmio = streamer_priv->streamer_mmio; __u16 sisr; __u16 misr; __u16 sisrmask; sisrmask = SISR_MI; writew(~sisrmask, streamer_mmio + SISR_MASK_RUM); sisr = readw(streamer_mmio + SISR); writew(~sisr, streamer_mmio + SISR_RUM); misr = readw(streamer_mmio + MISR_RUM); writew(~misr, streamer_mmio + MISR_RUM); if (!sisr) { /* Interrupt isn't for us */ writew(~misr,streamer_mmio+MISR_RUM); return; } spin_lock(&streamer_priv->streamer_lock); if ((sisr & (SISR_SRB_REPLY | SISR_ADAPTER_CHECK | SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY)) || (misr & (MISR_TX2_EOF | MISR_RX_NOBUF | MISR_RX_EOF))) { if (sisr & SISR_SRB_REPLY) { if (streamer_priv->srb_queued == 1) { wake_up_interruptible(&streamer_priv->srb_wait); } else if (streamer_priv->srb_queued == 2) { streamer_srb_bh(dev); } streamer_priv->srb_queued = 0; } /* SISR_SRB_REPLY */ if (misr & MISR_TX2_EOF) { while (streamer_priv->streamer_tx_ring[(streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1)].status) { streamer_priv->tx_ring_last_status = (streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -