?? arlan-main.c
字號:
} priv->in_bytes += pkt_len; priv->in_bytes10 += pkt_len; if (conf->measure_rate < 1) conf->measure_rate = 1; if (time_after(jiffies, priv->in_time + conf->measure_rate * HZ)) { conf->in_speed = priv->in_bytes / conf->measure_rate; priv->in_bytes = 0; priv->in_time = jiffies; } if (time_after(jiffies, priv->in_time10 + conf->measure_rate * 10*HZ)) { conf->in_speed10 = priv->in_bytes10 / (10 * conf->measure_rate); priv->in_bytes10 = 0; priv->in_time10 = jiffies; } DEBUGSHM(1, "arlan rcv pkt rxStatus= %d ", arlan->rxStatus, u_char); switch (rxStatus) { case 1: case 2: case 3: { /* Malloc up new buffer. */ struct sk_buff *skb; DEBUGSHM(50, "arlan recv pkt offs=%d\n", arlan->rxOffset, u_short); DEBUGSHM(1, "arlan rxFrmType = %d \n", arlan->rxFrmType, u_char); DEBUGSHM(1, KERN_INFO "arlan rx scrambled = %d \n", arlan->scrambled, u_char); /* here we do multicast filtering to avoid slow 8-bit memcopy */#ifdef ARLAN_MULTICAST if (!(dev->flags & IFF_ALLMULTI) && !(dev->flags & IFF_PROMISC) && dev->mc_list) { char hw_dst_addr[6]; struct dev_mc_list *dmi = dev->mc_list; int i; memcpy_fromio(hw_dst_addr, arlan->ultimateDestAddress, 6); if (hw_dst_addr[0] == 0x01) { if (mdebug) if (hw_dst_addr[1] == 0x00) printk(KERN_ERR "%s mcast 0x0100 \n", dev->name); else if (hw_dst_addr[1] == 0x40) printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name); while (dmi) { if (dmi->dmi_addrlen == 6) { if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP) printk(KERN_ERR "%s mcl %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]); for (i = 0; i < 6; i++) if (dmi->dmi_addr[i] != hw_dst_addr[i]) break; if (i == 6) break; } else printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name); dmi = dmi->next; } /* we reach here if multicast filtering is on and packet * is multicast and not for receive */ goto end_of_interrupt; } }#endif // ARLAN_MULTICAST /* multicast filtering ends here */ pkt_len += ARLAN_FAKE_HDR_LEN; skb = dev_alloc_skb(pkt_len + 4); if (skb == NULL) { printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name); priv->stats.rx_dropped++; break; } skb_reserve(skb, 2); skb->dev = dev; skbtmp = skb_put(skb, pkt_len); memcpy_fromio(skbtmp + ARLAN_FAKE_HDR_LEN, ((char *) arlan) + rxOffset, pkt_len - ARLAN_FAKE_HDR_LEN); memcpy_fromio(skbtmp, arlan->ultimateDestAddress, 6); memcpy_fromio(skbtmp + 6, arlan->rxSrc, 6); WRITESHMB(arlan->rxStatus, 0x00); arlan_command(dev, ARLAN_COMMAND_RX); IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) { char immedDestAddress[6]; char immedSrcAddress[6]; memcpy_fromio(immedDestAddress, arlan->immedDestAddress, 6); memcpy_fromio(immedSrcAddress, arlan->immedSrcAddress, 6); printk(KERN_WARNING "%s t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x imd %2x:%2x:%2x:%2x:%2x:%2x ims %2x:%2x:%2x:%2x:%2x:%2x\n", dev->name, (unsigned char) skbtmp[0], (unsigned char) skbtmp[1], (unsigned char) skbtmp[2], (unsigned char) skbtmp[3], (unsigned char) skbtmp[4], (unsigned char) skbtmp[5], (unsigned char) skbtmp[6], (unsigned char) skbtmp[7], (unsigned char) skbtmp[8], (unsigned char) skbtmp[9], (unsigned char) skbtmp[10], (unsigned char) skbtmp[11], immedDestAddress[0], immedDestAddress[1], immedDestAddress[2], immedDestAddress[3], immedDestAddress[4], immedDestAddress[5], immedSrcAddress[0], immedSrcAddress[1], immedSrcAddress[2], immedSrcAddress[3], immedSrcAddress[4], immedSrcAddress[5]); } skb->protocol = eth_type_trans(skb, dev); IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) if (skb->protocol != 0x608 && skb->protocol != 0x8) { for (i = 0; i <= 22; i++) printk("%02x:", (u_char) skbtmp[i + 12]); printk(KERN_ERR "\n"); printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol); } netif_rx(skb); dev->last_rx = jiffies; priv->stats.rx_packets++; priv->stats.rx_bytes += pkt_len; } break; default: printk(KERN_ERR "arlan intr: received unknown status\n"); priv->stats.rx_crc_errors++; break; } ARLAN_DEBUG_EXIT("arlan_rx_interrupt");}static void arlan_process_interrupt(struct net_device *dev){ struct arlan_private *priv = dev->priv; volatile struct arlan_shmem *arlan = priv->card; u_char rxStatus = READSHMB(arlan->rxStatus); u_char txStatus = READSHMB(arlan->txStatus); u_short rxOffset = READSHMS(arlan->rxOffset); u_short pkt_len = READSHMS(arlan->rxLength); int interrupt_count = 0; ARLAN_DEBUG_ENTRY("arlan_process_interrupt"); if (test_and_set_bit(0, (void *) &priv->interrupt_processing_active)) { if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) printk(KERN_ERR "interrupt chain reentering \n"); goto end_int_process; } while ((rxStatus || txStatus || priv->interrupt_ack_requested) && (interrupt_count < 5)) { if (rxStatus) priv->last_rx_int_ack_time = jiffies; arlan_command(dev, ARLAN_COMMAND_INT_ACK); arlan_command(dev, ARLAN_COMMAND_INT_ENABLE); IFDEBUG(ARLAN_DEBUG_INTERRUPT) printk(KERN_ERR "%s: got IRQ rx %x tx %x comm %x rxOff %x rxLen %x \n", dev->name, rxStatus, txStatus, READSHMB(arlan->commandByte), rxOffset, pkt_len); if (rxStatus == 0 && txStatus == 0) { if (priv->irq_test_done) { if (!registrationBad(dev)) IFDEBUG(ARLAN_DEBUG_INTERRUPT) printk(KERN_ERR "%s unknown interrupt(nop? regLost ?) reason tx %d rx %d ", dev->name, txStatus, rxStatus); } else { IFDEBUG(ARLAN_DEBUG_INTERRUPT) printk(KERN_INFO "%s irq $%d test OK \n", dev->name, dev->irq); } priv->interrupt_ack_requested = 0; goto ends; } if (txStatus != 0) { WRITESHMB(arlan->txStatus, 0x00); arlan_tx_done_interrupt(dev, txStatus); goto ends; } if (rxStatus == 1 || rxStatus == 2) { /* a packet waiting */ arlan_rx_interrupt(dev, rxStatus, rxOffset, pkt_len); goto ends; } if (rxStatus > 2 && rxStatus < 0xff) { WRITESHMB(arlan->rxStatus, 0x00); printk(KERN_ERR "%s unknown rxStatus reason tx %d rx %d ", dev->name, txStatus, rxStatus); goto ends; } if (rxStatus == 0xff) { WRITESHMB(arlan->rxStatus, 0x00); arlan_command(dev, ARLAN_COMMAND_RX); if (registrationBad(dev)) netif_device_detach(dev); if (!registrationBad(dev)) { priv->registrationLastSeen = jiffies; if (!netif_queue_stopped(dev) && !priv->under_reset && !priv->under_config) netif_wake_queue (dev); } goto ends; }ends: arlan_command_process(dev); rxStatus = READSHMB(arlan->rxStatus); txStatus = READSHMB(arlan->txStatus); rxOffset = READSHMS(arlan->rxOffset); pkt_len = READSHMS(arlan->rxLength); priv->irq_test_done = 1; interrupt_count++; } priv->interrupt_processing_active = 0;end_int_process: arlan_command_process(dev); ARLAN_DEBUG_EXIT("arlan_process_interrupt"); return;}static irqreturn_t arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = dev_id; struct arlan_private *priv = dev->priv; volatile struct arlan_shmem *arlan = priv->card; u_char rxStatus = READSHMB(arlan->rxStatus); u_char txStatus = READSHMB(arlan->txStatus); ARLAN_DEBUG_ENTRY("arlan_interrupt"); if (!rxStatus && !txStatus) priv->interrupt_ack_requested++; arlan_process_interrupt(dev); priv->irq_test_done = 1; ARLAN_DEBUG_EXIT("arlan_interrupt"); return IRQ_HANDLED;}static int arlan_close(struct net_device *dev){ struct arlan_private *priv = dev->priv; ARLAN_DEBUG_ENTRY("arlan_close"); del_timer_sync(&priv->timer); arlan_command(dev, ARLAN_COMMAND_POWERDOWN); IFDEBUG(ARLAN_DEBUG_STARTUP) printk(KERN_NOTICE "%s: Closing device\n", dev->name); netif_stop_queue(dev); free_irq(dev->irq, dev); ARLAN_DEBUG_EXIT("arlan_close"); return 0;}#ifdef ARLAN_DEBUGGINGstatic long alignLong(volatile u_char * ptr){ long ret; memcpy_fromio(&ret, (void *) ptr, 4); return ret;}#endif/* * Get the current statistics. * This may be called with the card open or closed. */static struct net_device_stats *arlan_statistics(struct net_device *dev){ struct arlan_private *priv = dev->priv; volatile struct arlan_shmem *arlan = priv->card; ARLAN_DEBUG_ENTRY("arlan_statistics"); /* Update the statistics from the device registers. */ READSHM(priv->stats.collisions, arlan->numReTransmissions, u_int); READSHM(priv->stats.rx_crc_errors, arlan->numCRCErrors, u_int); READSHM(priv->stats.rx_dropped, arlan->numFramesDiscarded, u_int); READSHM(priv->stats.rx_fifo_errors, arlan->numRXBufferOverflows, u_int); READSHM(priv->stats.rx_frame_errors, arlan->numReceiveFramesLost, u_int); READSHM(priv->stats.rx_over_errors, arlan->numRXOverruns, u_int); READSHM(priv->stats.rx_packets, arlan->numDatagramsReceived, u_int); READSHM(priv->stats.tx_aborted_errors, arlan->numAbortErrors, u_int); READSHM(priv->stats.tx_carrier_errors, arlan->numStatusTimeouts, u_int); READSHM(priv->stats.tx_dropped, arlan->numDatagramsDiscarded, u_int); READSHM(priv->stats.tx_fifo_errors, arlan->numTXUnderruns, u_int); READSHM(priv->stats.tx_packets, arlan->numDatagramsTransmitted, u_int); READSHM(priv->stats.tx_window_errors, arlan->numHoldOffs, u_int); ARLAN_DEBUG_EXIT("arlan_statistics"); return &priv->stats;}static void arlan_set_multicast(struct net_device *dev){ struct arlan_private *priv = dev->priv; volatile struct arlan_shmem *arlan = priv->card; struct arlan_conf_stru *conf = priv->Conf; int board_conf_needed = 0; ARLAN_DEBUG_ENTRY("arlan_set_multicast"); if (dev->flags & IFF_PROMISC) { unsigned char recMode; READSHM(recMode, arlan->receiveMode, u_char); conf->receiveMode = (ARLAN_RCV_PROMISC | ARLAN_RCV_CONTROL); if (conf->receiveMode != recMode) board_conf_needed = 1; } else { /* turn off promiscuous mode */ unsigned char recMode; READSHM(recMode, arlan->receiveMode, u_char); conf->receiveMode = ARLAN_RCV_CLEAN | ARLAN_RCV_CONTROL; if (conf->receiveMode != recMode) board_conf_needed = 1; } if (board_conf_needed) arlan_command(dev, ARLAN_COMMAND_CONF); ARLAN_DEBUG_EXIT("arlan_set_multicast");}struct net_device * __init arlan_probe(int unit){ struct net_device *dev; int err; int m; ARLAN_DEBUG_ENTRY("arlan_probe"); if (arlans_found == MAX_ARLANS) return ERR_PTR(-ENODEV); /* * Reserve space for local data and a copy of the shared memory * that is used by the /proc interface. */ dev = alloc_etherdev(sizeof(struct arlan_private) + sizeof(struct arlan_shmem)); if (!dev) return ERR_PTR(-ENOMEM); SET_MODULE_OWNER(dev); if (unit >= 0) { sprintf(dev->name, "eth%d", unit); netdev_boot_setup_check(dev); if (dev->mem_start) { if (arlan_probe_here(dev, dev->mem_start) == 0) goto found; goto not_found; } } for (m = (int)phys_to_virt(lastFoundAt) + ARLAN_SHMEM_SIZE; m <= (int)phys_to_virt(0xDE000); m += ARLAN_SHMEM_SIZE) { if (arlan_probe_here(dev, m) == 0) { lastFoundAt = (int)virt_to_phys((void*)m); goto found; } } if (lastFoundAt == 0xbe000) printk(KERN_ERR "arlan: No Arlan devices found \n"); not_found: free_netdev(dev); return ERR_PTR(-ENODEV); found: err = arlan_setup_device(dev, arlans_found); if (err) dev = ERR_PTR(err); else if (!arlans_found++) printk(KERN_INFO "Arlan driver %s\n", arlan_version); return dev;}#ifdef MODULEint init_module(void){ int i = 0; ARLAN_DEBUG_ENTRY("init_module"); if (channelSet != channelSetUNKNOWN || channelNumber != channelNumberUNKNOWN || systemId != systemIdUNKNOWN) return -EINVAL; for (i = 0; i < MAX_ARLANS; i++) { struct net_device *dev = arlan_probe(i); if (IS_ERR(dev)) return PTR_ERR(dev); } init_arlan_proc(); printk(KERN_INFO "Arlan driver %s\n", arlan_version); ARLAN_DEBUG_EXIT("init_module"); return 0;}void cleanup_module(void){ int i = 0; struct net_device *dev; ARLAN_DEBUG_ENTRY("cleanup_module"); IFDEBUG(ARLAN_DEBUG_SHUTDOWN) printk(KERN_INFO "arlan: unloading module\n"); cleanup_arlan_proc(); for (i = 0; i < MAX_ARLANS; i++) { dev = arlan_device[i]; if (dev) { arlan_command(dev, ARLAN_COMMAND_POWERDOWN ); unregister_netdev(dev); release_mem_region(virt_to_phys((void *) dev->mem_start), ARLAN_SHMEM_SIZE); free_netdev(dev); arlan_device[i] = NULL; } } ARLAN_DEBUG_EXIT("cleanup_module");}#endifMODULE_LICENSE("GPL");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -