📄 farsync.c
字号:
fst_issue_cmd ( port, STARTPORT ); port->run = 1; signals = FST_RDL ( port->card, v24DebouncedSts[port->index]); if ( signals & (( port->hwif == X21 ) ? IPSTS_INDICATE : IPSTS_DCD )) netif_carrier_on ( port_to_dev ( port )); else netif_carrier_off ( port_to_dev ( port )); }}static voidfst_closeport ( struct fst_port_info *port ){ if ( port->card->state == FST_RUNNING ) { if ( port->run ) { port->run = 0; fst_op_lower ( port, OPSTS_RTS | OPSTS_DTR ); fst_issue_cmd ( port, STOPPORT ); } else { dbg ( DBG_OPEN,"close: port not running\n"); } }}static intfst_open ( struct net_device *dev ){ int err; err = hdlc_open ( dev_to_hdlc ( dev )); if ( err ) return err; MOD_INC_USE_COUNT; fst_openport ( dev_to_port ( dev )); netif_wake_queue ( dev ); return 0;}static intfst_close ( struct net_device *dev ){ netif_stop_queue ( dev ); fst_closeport ( dev_to_port ( dev )); hdlc_close ( dev_to_hdlc ( dev )); MOD_DEC_USE_COUNT; return 0;}static intfst_attach ( hdlc_device *hdlc, unsigned short encoding, unsigned short parity ){ /* Setting currently fixed in FarSync card so we check and forget */ if ( encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT ) return -EINVAL; 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_to_port ( dev ); port->hdlc.stats.tx_errors++; port->hdlc.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_to_port ( dev ); card = port->card; /* Drop packet with error if we don't have carrier */ if ( ! netif_carrier_ok ( dev )) { dev_kfree_skb ( skb ); port->hdlc.stats.tx_errors++; port->hdlc.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->hdlc.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->hdlc.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->hdlc.stats.tx_packets++; port->hdlc.stats.tx_bytes += skb->len; dev_kfree_skb ( skb ); dev->trans_start = jiffies; return 0;}/* * 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].card = card; card->ports[i].index = i; card->ports[i].run = 0; dev = hdlc_to_dev ( &card->ports[i].hdlc ); /* Fill in 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->tx_queue_len = FST_TX_QUEUE_LEN; dev->open = fst_open; dev->stop = fst_close; dev->do_ioctl = fst_ioctl; dev->watchdog_timeo = FST_TX_TIMEOUT; dev->tx_timeout = fst_tx_timeout; card->ports[i].hdlc.attach = fst_attach; card->ports[i].hdlc.xmit = fst_start_xmit; if (( err = register_hdlc_device ( &card->ports[i].hdlc )) < 0 ) { printk_err ("Cannot register HDLC device for port %d" " (errno %d)\n", i, -err ); card->nports = i; break; } } spin_lock_init ( &card->card_lock ); printk ( KERN_INFO "%s-%s: %s IRQ%d, %d ports\n", hdlc_to_dev(&card->ports[0].hdlc)->name, hdlc_to_dev(&card->ports[card->nports-1].hdlc)->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_hdlc_device ( &card->ports[i].hdlc ); } 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -