?? arlan-main.c
字號:
conf->tx_delay_ms = tx_delay_ms; conf->ReTransmitPacketMaxSize = 200; conf->waitReTransmitPacketMaxSize = 200; conf->txAckTimeoutMs = 900; conf->fastReTransCount = 3; ARLAN_DEBUG_EXIT("arlan_read_card_configuration"); return 0;}static int lastFoundAt = 0xbe000;/* * This is the real probe routine. Linux has a history of friendly device * probes on the ISA bus. A good device probes avoids doing writes, and * verifies that the correct device exists and functions. */#define ARLAN_SHMEM_SIZE 0x2000static int __init arlan_check_fingerprint(unsigned long memaddr){ static const char probeText[] = "TELESYSTEM SLW INC. ARLAN \0"; volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr; unsigned long paddr = virt_to_phys((void *) memaddr); char tempBuf[49]; ARLAN_DEBUG_ENTRY("arlan_check_fingerprint"); if (!request_mem_region(paddr, ARLAN_SHMEM_SIZE, "arlan")) { // printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",paddr); return -ENODEV; } memcpy_fromio(tempBuf, arlan->textRegion, 29); tempBuf[30] = 0; /* check for card at this address */ if (0 != strncmp(tempBuf, probeText, 29)){ release_mem_region(paddr, ARLAN_SHMEM_SIZE); return -ENODEV; }// printk(KERN_INFO "arlan found at 0x%x \n",memaddr); ARLAN_DEBUG_EXIT("arlan_check_fingerprint"); return 0;}static int arlan_change_mtu(struct net_device *dev, int new_mtu){ struct arlan_private *priv = dev->priv; struct arlan_conf_stru *conf = priv->Conf; ARLAN_DEBUG_ENTRY("arlan_change_mtu"); if (new_mtu > 2032) return -EINVAL; dev->mtu = new_mtu; if (new_mtu < 256) new_mtu = 256; /* cards book suggests 1600 */ conf->maxDatagramSize = new_mtu; conf->maxFrameSize = new_mtu + 48; arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF); printk(KERN_NOTICE "%s mtu changed to %d \n", dev->name, new_mtu); ARLAN_DEBUG_EXIT("arlan_change_mtu"); return 0;}static int arlan_mac_addr(struct net_device *dev, void *p){ struct sockaddr *addr = p; ARLAN_DEBUG_ENTRY("arlan_mac_addr"); return -EINVAL; if (!netif_running(dev)) return -EBUSY; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); ARLAN_DEBUG_EXIT("arlan_mac_addr"); return 0;}static int __init arlan_setup_device(struct net_device *dev, int num){ struct arlan_private *ap = dev->priv; int err; ARLAN_DEBUG_ENTRY("arlan_setup_device"); ap->conf = (struct arlan_shmem *)(ap+1); dev->tx_queue_len = tx_queue_len; dev->open = arlan_open; dev->stop = arlan_close; dev->hard_start_xmit = arlan_tx; dev->get_stats = arlan_statistics; dev->set_multicast_list = arlan_set_multicast; dev->change_mtu = arlan_change_mtu; dev->set_mac_address = arlan_mac_addr; dev->tx_timeout = arlan_tx_timeout; dev->watchdog_timeo = 3*HZ; ap->irq_test_done = 0; ap->Conf = &arlan_conf[num]; ap->Conf->pre_Command_Wait = 40; ap->Conf->rx_tweak1 = 30; ap->Conf->rx_tweak2 = 0; err = register_netdev(dev); if (err) { release_mem_region(virt_to_phys((void *) dev->mem_start), ARLAN_SHMEM_SIZE); free_netdev(dev); return err; } arlan_device[num] = dev; ARLAN_DEBUG_EXIT("arlan_setup_device"); return 0;}static int __init arlan_probe_here(struct net_device *dev, unsigned long memaddr){ struct arlan_private *ap = dev->priv; ARLAN_DEBUG_ENTRY("arlan_probe_here"); if (arlan_check_fingerprint(memaddr)) return -ENODEV; printk(KERN_NOTICE "%s: Arlan found at %x, \n ", dev->name, (int) virt_to_phys((void*)memaddr)); ap->card = (void *) memaddr; dev->mem_start = memaddr; dev->mem_end = memaddr + ARLAN_SHMEM_SIZE-1; if (dev->irq < 2) { READSHM(dev->irq, ap->card->irqLevel, u_char); } else if (dev->irq == 2) dev->irq = 9; arlan_read_card_configuration(dev); ARLAN_DEBUG_EXIT("arlan_probe_here"); return 0;}static int arlan_open(struct net_device *dev){ struct arlan_private *priv = dev->priv; volatile struct arlan_shmem *arlan = priv->card; int ret = 0; ARLAN_DEBUG_ENTRY("arlan_open"); ret = request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev); if (ret) { printk(KERN_ERR "%s: unable to get IRQ %d .\n", dev->name, dev->irq); return ret; } priv->bad = 0; priv->lastReset = 0; priv->reset = 0; memcpy_fromio(dev->dev_addr, arlan->lanCardNodeId, 6); memset(dev->broadcast, 0xff, 6); dev->tx_queue_len = tx_queue_len; priv->interrupt_processing_active = 0; spin_lock_init(&priv->lock); netif_start_queue (dev); priv->registrationLostCount = 0; priv->registrationLastSeen = jiffies; priv->txLast = 0; priv->tx_command_given = 0; priv->rx_command_given = 0; priv->reRegisterExp = 1; priv->tx_last_sent = jiffies - 1; priv->tx_last_cleared = jiffies; priv->Conf->writeEEPROM = 0; priv->Conf->registrationInterrupts = 1; init_timer(&priv->timer); priv->timer.expires = jiffies + HZ / 10; priv->timer.data = (unsigned long) dev; priv->timer.function = &arlan_registration_timer; /* timer handler */ arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW); mdelay(200); add_timer(&priv->timer); ARLAN_DEBUG_EXIT("arlan_open"); return 0;}static void arlan_tx_timeout (struct net_device *dev){ printk(KERN_ERR "%s: arlan transmit timed out, kernel decided\n", dev->name); /* Try to restart the adaptor. */ arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); // dev->trans_start = jiffies; // netif_start_queue (dev);}static int arlan_tx(struct sk_buff *skb, struct net_device *dev){ short length; unsigned char *buf; ARLAN_DEBUG_ENTRY("arlan_tx"); length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; buf = skb->data; if (length + 0x12 > 0x800) { printk(KERN_ERR "TX RING overflow \n"); netif_stop_queue (dev); } if (arlan_hw_tx(dev, buf, length) == -1) goto bad_end; dev->trans_start = jiffies; dev_kfree_skb(skb); arlan_process_interrupt(dev); ARLAN_DEBUG_EXIT("arlan_tx"); return 0;bad_end: arlan_process_interrupt(dev); netif_stop_queue (dev); ARLAN_DEBUG_EXIT("arlan_tx"); return 1;}static inline int DoNotReTransmitCrap(struct net_device *dev){ struct arlan_private *priv = dev->priv; if (TXLAST(dev).length < priv->Conf->ReTransmitPacketMaxSize) return 1; return 0;}static inline int DoNotWaitReTransmitCrap(struct net_device *dev){ struct arlan_private *priv = dev->priv; if (TXLAST(dev).length < priv->Conf->waitReTransmitPacketMaxSize) return 1; return 0;}static inline void arlan_queue_retransmit(struct net_device *dev){ struct arlan_private *priv = dev->priv; ARLAN_DEBUG_ENTRY("arlan_queue_retransmit"); if (DoNotWaitReTransmitCrap(dev)) { arlan_drop_tx(dev); } else priv->ReTransmitRequested++; ARLAN_DEBUG_EXIT("arlan_queue_retransmit");}static inline void RetryOrFail(struct net_device *dev){ struct arlan_private *priv = dev->priv; ARLAN_DEBUG_ENTRY("RetryOrFail"); if (priv->retransmissions > priv->Conf->retries || DoNotReTransmitCrap(dev)) { arlan_drop_tx(dev); } else if (priv->bad <= priv->Conf->fastReTransCount) { arlan_retransmit_now(dev); } else arlan_queue_retransmit(dev); ARLAN_DEBUG_EXIT("RetryOrFail");}static void arlan_tx_done_interrupt(struct net_device *dev, int status){ struct arlan_private *priv = dev->priv; ARLAN_DEBUG_ENTRY("arlan_tx_done_interrupt"); priv->tx_last_cleared = jiffies; priv->tx_command_given = 0; switch (status) { case 1: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit OK\n"); priv->stats.tx_packets++; priv->bad = 0; priv->reset = 0; priv->retransmissions = 0; if (priv->Conf->tx_delay_ms) { priv->tx_done_delayed = jiffies + (priv->Conf->tx_delay_ms * HZ) / 1000 + 1; } else { TXLAST(dev).offset = 0; if (priv->txLast) priv->txLast = 0; else if (TXTAIL(dev).offset) priv->txLast = 1; if (TXLAST(dev).offset) { arlan_retransmit_now(dev); dev->trans_start = jiffies; } if (!TXHEAD(dev).offset || !TXTAIL(dev).offset) { netif_wake_queue (dev); } } } break; case 2: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit timed out\n"); priv->bad += 1; //arlan_queue_retransmit(dev); RetryOrFail(dev); } break; case 3: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit max retries\n"); priv->bad += 1; priv->reset = 0; //arlan_queue_retransmit(dev); RetryOrFail(dev); } break; case 4: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit aborted\n"); priv->bad += 1; arlan_queue_retransmit(dev); //RetryOrFail(dev); } break; case 5: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit not registered\n"); priv->bad += 1; //debug=101; arlan_queue_retransmit(dev); } break; case 6: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit destination full\n"); priv->bad += 1; priv->reset = 0; //arlan_drop_tx(dev); arlan_queue_retransmit(dev); } break; case 7: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit unknown ack\n"); priv->bad += 1; priv->reset = 0; arlan_queue_retransmit(dev); } break; case 8: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit dest mail box full\n"); priv->bad += 1; priv->reset = 0; //arlan_drop_tx(dev); arlan_queue_retransmit(dev); } break; case 9: { IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("arlan intr: transmit root dest not reg.\n"); priv->bad += 1; priv->reset = 1; //arlan_drop_tx(dev); arlan_queue_retransmit(dev); } break; default: { printk(KERN_ERR "arlan intr: transmit status unknown\n"); priv->bad += 1; priv->reset = 1; arlan_drop_tx(dev); } } ARLAN_DEBUG_EXIT("arlan_tx_done_interrupt");}static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len){ char *skbtmp; int i = 0; struct arlan_private *priv = dev->priv; volatile struct arlan_shmem *arlan = priv->card; struct arlan_conf_stru *conf = priv->Conf; ARLAN_DEBUG_ENTRY("arlan_rx_interrupt"); // by spec, not WRITESHMB(arlan->rxStatus,0x00); // prohibited here arlan_command(dev, ARLAN_COMMAND_RX); if (pkt_len < 10 || pkt_len > 2048) { printk(KERN_WARNING "%s: got too short or long packet, len %d \n", dev->name, pkt_len); return; } if (rxOffset + pkt_len > 0x2000) { printk("%s: got too long packet, len %d offset %x\n", dev->name, pkt_len, rxOffset); return;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -