📄 farsync.c
字号:
{ sppp_detach ( dev ); MOD_DEC_USE_COUNT; return err; } break; case FST_MONITOR: case FST_RAW: break; default: dbg ( DBG_OPEN,"open: Unknown proto %d\n", port->proto ); break; } fst_openport ( port ); netif_wake_queue ( dev ); return 0;}static intfst_close ( struct net_device *dev ){ struct fst_port_info *port; port = dev->priv; netif_stop_queue ( dev ); switch ( port->proto ) { case FST_HDLC: case FST_PPP: sppp_close ( dev ); sppp_detach ( dev ); break; case FST_MONITOR: case FST_RAW: break; default: dbg ( DBG_OPEN,"close: Unknown proto %d\n", port->proto ); break; } fst_closeport ( port ); MOD_DEC_USE_COUNT; return 0;}static voidfst_tx_timeout ( struct net_device *dev ){ struct fst_port_info *port; dbg ( DBG_INTR | DBG_TX,"tx_timeout\n"); port = dev->priv; port->stats.tx_errors++; port->stats.tx_aborted_errors++; if ( port->txcnt > 0 ) fst_issue_cmd ( port, ABORTTX ); dev->trans_start = jiffies; netif_wake_queue ( dev );}static intfst_start_xmit ( struct sk_buff *skb, struct net_device *dev ){ struct fst_card_info *card; struct fst_port_info *port; unsigned char dmabits; unsigned long flags; int pi; int txp; port = dev->priv; card = port->card; /* Drop packet if in monitor (rx only) mode */ if ( port->proto == FST_MONITOR ) { dev_kfree_skb ( skb ); return 0; } /* Drop packet with error if we don't have carrier */ if ( ! netif_carrier_ok ( dev )) { dev_kfree_skb ( skb ); port->stats.tx_errors++; port->stats.tx_carrier_errors++; return 0; } /* Drop it if it's too big! MTU failure ? */ if ( skb->len > LEN_TX_BUFFER ) { dbg ( DBG_TX,"Packet too large %d vs %d\n", skb->len, LEN_TX_BUFFER ); dev_kfree_skb ( skb ); port->stats.tx_errors++; return 0; } /* Check we have a buffer */ pi = port->index; spin_lock_irqsave ( &card->card_lock, flags ); txp = port->txpos; dmabits = FST_RDB ( card, txDescrRing[pi][txp].bits ); if ( dmabits & DMA_OWN ) { spin_unlock_irqrestore ( &card->card_lock, flags ); dbg ( DBG_TX,"Out of Tx buffers\n"); dev_kfree_skb ( skb ); port->stats.tx_errors++; return 0; } if ( ++port->txpos >= NUM_TX_BUFFER ) port->txpos = 0; if ( ++port->txcnt >= NUM_TX_BUFFER ) netif_stop_queue ( dev ); /* Release the card lock before we copy the data as we now have * exclusive access to the buffer. */ spin_unlock_irqrestore ( &card->card_lock, flags ); /* Enqueue the packet */ memcpy_toio ( card->mem + BUF_OFFSET ( txBuffer[pi][txp][0]), skb->data, skb->len ); FST_WRW ( card, txDescrRing[pi][txp].bcnt, cnv_bcnt ( skb->len )); FST_WRB ( card, txDescrRing[pi][txp].bits, DMA_OWN | TX_STP | TX_ENP ); port->stats.tx_packets++; port->stats.tx_bytes += skb->len; dev_kfree_skb ( skb ); dev->trans_start = jiffies; return 0;}static struct net_device_stats *fst_get_stats ( struct net_device *dev ){ struct fst_port_info *port; if (( port = dev->priv ) != NULL ) return &port->stats; else return NULL;}/* * Card setup having checked hardware resources. * Should be pretty bizarre if we get an error here (kernel memory * exhaustion is one possibility). If we do see a problem we report it * via a printk and leave the corresponding interface and all that follow * disabled. */static char *type_strings[] __devinitdata = { "no hardware", /* Should never be seen */ "FarSync T2P", "FarSync T4P"};static void __devinitfst_init_card ( struct fst_card_info *card ){ int i; int err; struct net_device *dev; /* We're working on a number of ports based on the card ID. If the * firmware detects something different later (should never happen) * we'll have to revise it in some way then. */ for ( i = 0 ; i < card->nports ; i++ ) { card->ports[i].if_ptr = &card->ports[i].pppdev; card->ports[i].card = card; card->ports[i].index = i; card->ports[i].proto = FST_HDLC; card->ports[i].run = 0; dev = kmalloc ( sizeof ( struct net_device ), GFP_KERNEL ); if ( dev == NULL ) { printk_err ("Cannot allocate net_device for port %d\n", i ); /* No point going any further */ card->nports = i; break; } memset ( dev, 0, sizeof ( struct net_device )); card->ports[i].dev = dev; if ( dev_alloc_name ( dev, FST_NDEV_NAME "%d") < 0 ) { printk_err ("Cannot allocate i/f name for port %d\n", i ); kfree ( dev ); card->nports = i; break; } /* Fill in remainder of the net device info */ /* Since this is a PCI setup this is purely * informational. Give them the buffer addresses * and basic card I/O. */ dev->mem_start = card->phys_mem + BUF_OFFSET ( txBuffer[i][0][0]); dev->mem_end = card->phys_mem + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]); dev->rmem_start = card->phys_mem + BUF_OFFSET ( rxBuffer[i][0][0]); dev->rmem_end = card->phys_mem + BUF_OFFSET ( rxBuffer[i][NUM_RX_BUFFER][0]); dev->base_addr = card->pci_conf; dev->irq = card->irq; dev->get_stats = fst_get_stats; dev->mtu = FST_DEF_MTU; dev->change_mtu = fst_change_mtu; dev->priv = &card->ports[i]; dev->tx_queue_len = FST_TX_QUEUE_LEN; dev->type = ARPHRD_MYTYPE; dev->addr_len = 0; dev->open = fst_open; dev->stop = fst_close; dev->hard_start_xmit = fst_start_xmit; dev->do_ioctl = fst_ioctl; dev->watchdog_timeo = FST_TX_TIMEOUT; dev->tx_timeout = fst_tx_timeout; dev->flags = IFF_POINTOPOINT|IFF_NOARP; if (( err = register_netdev ( dev )) < 0 ) { printk_err ("Cannot register %s (errno %d)\n", dev->name, -err ); kfree ( dev ); card->nports = i; break; } } spin_lock_init ( &card->card_lock ); printk ( KERN_INFO "%s-%s: %s IRQ%d, %d ports\n", card->ports[0].dev->name, card->ports[card->nports-1].dev->name, type_strings[card->type], card->irq, card->nports );}/* * Initialise card when detected. * Returns 0 to indicate success, or errno otherwise. */static int __devinitfst_add_one ( struct pci_dev *pdev, const struct pci_device_id *ent ){ static int firsttime_done = 0; struct fst_card_info *card; int err = 0; if ( ! firsttime_done ) { printk ( KERN_INFO "FarSync X21 driver " FST_USER_VERSION " (c) 2001 FarSite Communications Ltd.\n"); firsttime_done = 1; } /* Allocate driver private data */ card = kmalloc ( sizeof ( struct fst_card_info ), GFP_KERNEL); if (card == NULL) { printk_err ("FarSync card found but insufficient memory for" " driver storage\n"); return -ENOMEM; } memset ( card, 0, sizeof ( struct fst_card_info )); /* Record info we need*/ card->irq = pdev->irq; card->pci_conf = pci_resource_start ( pdev, 1 ); card->phys_mem = pci_resource_start ( pdev, 2 ); card->phys_ctlmem = pci_resource_start ( pdev, 3 ); card->type = ent->driver_data; card->nports = ( ent->driver_data == FST_TYPE_T2P ) ? 2 : 4; card->state = FST_UNINIT; dbg ( DBG_PCI,"type %d nports %d irq %d\n", card->type, card->nports, card->irq ); dbg ( DBG_PCI,"conf %04x mem %08x ctlmem %08x\n", card->pci_conf, card->phys_mem, card->phys_ctlmem ); /* Check we can get access to the memory and I/O regions */ if ( ! request_region ( card->pci_conf, 0x80,"PLX config regs")) { printk_err ("Unable to get config I/O @ 0x%04X\n", card->pci_conf ); err = -ENODEV; goto error_free_card; } if ( ! request_mem_region ( card->phys_mem, FST_MEMSIZE,"Shared RAM")) { printk_err ("Unable to get main memory @ 0x%08X\n", card->phys_mem ); err = -ENODEV; goto error_release_io; } if ( ! request_mem_region ( card->phys_ctlmem, 0x10,"Control memory")) { printk_err ("Unable to get control memory @ 0x%08X\n", card->phys_ctlmem ); err = -ENODEV; goto error_release_mem; } /* Try to enable the device */ if (( err = pci_enable_device ( pdev )) != 0 ) { printk_err ("Failed to enable card. Err %d\n", -err ); goto error_release_ctlmem; } /* Get virtual addresses of memory regions */ if (( card->mem = ioremap ( card->phys_mem, FST_MEMSIZE )) == NULL ) { printk_err ("Physical memory remap failed\n"); err = -ENODEV; goto error_release_ctlmem; } if (( card->ctlmem = ioremap ( card->phys_ctlmem, 0x10 )) == NULL ) { printk_err ("Control memory remap failed\n"); err = -ENODEV; goto error_unmap_mem; } dbg ( DBG_PCI,"kernel mem %p, ctlmem %p\n", card->mem, card->ctlmem); /* Reset the card's processor */ fst_cpureset ( card ); card->state = FST_RESET; /* Register the interrupt handler */ if ( request_irq ( card->irq, fst_intr, SA_SHIRQ, FST_DEV_NAME, card )) { printk_err ("Unable to register interrupt %d\n", card->irq ); err = -ENODEV; goto error_unmap_ctlmem; } /* Record driver data for later use */ pci_set_drvdata(pdev, card); /* Remainder of card setup */ fst_init_card ( card ); return 0; /* Success */ /* Failure. Release resources */error_unmap_ctlmem: iounmap ( card->ctlmem );error_unmap_mem: iounmap ( card->mem );error_release_ctlmem: release_mem_region ( card->phys_ctlmem, 0x10 );error_release_mem: release_mem_region ( card->phys_mem, FST_MEMSIZE );error_release_io: release_region ( card->pci_conf, 0x80 );error_free_card: kfree ( card ); return err;}/* * Cleanup and close down a card */static void __devexitfst_remove_one ( struct pci_dev *pdev ){ struct fst_card_info *card; int i; card = pci_get_drvdata(pdev); for ( i = 0 ; i < card->nports ; i++ ) { unregister_netdev ( card->ports[i].dev ); kfree ( card->ports[i].dev ); } fst_disable_intr ( card ); free_irq ( card->irq, card ); iounmap ( card->ctlmem ); iounmap ( card->mem ); release_mem_region ( card->phys_ctlmem, 0x10 ); release_mem_region ( card->phys_mem, FST_MEMSIZE ); release_region ( card->pci_conf, 0x80 ); kfree ( card );}static struct pci_driver fst_driver = { name: FST_NAME, id_table: fst_pci_dev_id, probe: fst_add_one, remove: __devexit_p(fst_remove_one), suspend: NULL, resume: NULL,};static int __initfst_init(void){ return pci_module_init ( &fst_driver );}static void __exitfst_cleanup_module(void){ pci_unregister_driver ( &fst_driver );}module_init ( fst_init );module_exit ( fst_cleanup_module );MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -