📄 wct4xxp.c
字号:
inirq = 1; /* Make sure it's really for us */ status = t4_pci_in(wc, WC_INTR); t4_pci_out(wc, WC_INTR, 0); /* Ignore if it's not for us */ if (!status)#ifdef LINUX26 return IRQ_NONE;#else return;#endif if (!wc->spansstarted) { printk("Not prepped yet!\n");#ifdef LINUX26 return IRQ_NONE;#else return;#endif } wc->intcount++;#if 0 if (wc->intcount < 20) printk("Got interrupt, status = %08x\n", status);#endif if (status & 0x3) { t4_receiveprep(wc, status); t4_transmitprep(wc, status); } #if 0 if ((wc->intcount < 10) || !(wc->intcount % 1000)) { status2 = t4_framer_in(wc, 0, 0x6f); printk("Status2: %04x\n", status2); for (x = 0;x<4;x++) { status2 = t4_framer_in(wc, x, 0x4c); printk("FRS0/%d: %04x\n", x, status2); } }#endif spin_lock_irqsave(&wc->reglock, flags); __handle_leds(wc); __t4_do_counters(wc); x = wc->intcount & 15 /* 63 */; switch(x) { case 0: case 1: case 2: case 3: __t4_check_sigbits(wc, x); break; case 4: case 5: case 6: case 7: __t4_check_alarms(wc, x - 4); break; } if (wc->checktiming > 0) __t4_set_timing_source_auto(wc); spin_unlock_irqrestore(&wc->reglock, flags);#ifdef LINUX26 return IRQ_RETVAL(1);#endif }static int t4_reset_dma(struct t4 *wc){ /* Turn off DMA and such */ wc->dmactrl = 0x0; t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); t4_pci_out(wc, WC_COUNT, 0); t4_pci_out(wc, WC_RDADDR, 0); t4_pci_out(wc, WC_WRADDR, 0); t4_pci_out(wc, WC_INTR, 0); /* Turn it all back on */ t4_pci_out(wc, WC_RDADDR, wc->readdma); t4_pci_out(wc, WC_WRADDR, wc->writedma); t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); t4_pci_out(wc, WC_INTR, 0); wc->dmactrl = 0xc0000003 | (1 << 29); if (noburst) wc->dmactrl |= (1 << 26); t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); return 0;}static int t4_hardware_init(struct t4 *wc){ int x; unsigned int version; unsigned int falcver; version = t4_pci_in(wc, WC_VERSION); printk("TE410P version %08x\n", version); /* Make sure DMA engine is not running and interrupts are acknowledged */ wc->dmactrl = 0x0; t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); /* Reset Framer and friends */ t4_pci_out(wc, WC_LEDS, 0x00000000); /* Set DMA addresses */ t4_pci_out(wc, WC_RDADDR, wc->readdma); t4_pci_out(wc, WC_WRADDR, wc->writedma); /* Setup counters, interrupt flags */ t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); /* Reset pending interrupts */ t4_pci_out(wc, WC_INTR, 0x00000000); /* Read T1/E1 status */ if (t1e1override > -1) wc->t1e1 = t1e1override; else wc->t1e1 = ((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8; wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28; /* Setup LEDS, take out of reset */ t4_pci_out(wc, WC_LEDS, 0x000000ff); t4_activate(wc); t4_framer_out(wc, 0, 0x4a, 0xaa); falcver = t4_framer_in(wc, 0 ,0x4a); printk("FALC version: %08x, Board ID: %02x\n", falcver, wc->order); for (x=0;x< 11;x++) printk("Reg %d: 0x%08x\n", x, t4_pci_in(wc, x)); return 0;}static int __devinit t4_launch(struct t4 *wc){ int x; unsigned long flags; if (wc->spans[0].flags & ZT_FLAG_REGISTERED) return 0; printk("TE410P: Launching card: %d\n", wc->order); /* Setup serial parameters and system interface */ for (x=0;x<4;x++) t4_serial_setup(wc, x); if (zt_register(&wc->spans[0], 0)) { printk(KERN_ERR "Unable to register span %s\n", wc->spans[0].name); return -1; } if (zt_register(&wc->spans[1], 0)) { printk(KERN_ERR "Unable to register span %s\n", wc->spans[1].name); zt_unregister(&wc->spans[0]); return -1; } if (zt_register(&wc->spans[2], 0)) { printk(KERN_ERR "Unable to register span %s\n", wc->spans[2].name); zt_unregister(&wc->spans[0]); zt_unregister(&wc->spans[1]); return -1; } if (zt_register(&wc->spans[3], 0)) { printk(KERN_ERR "Unable to register span %s\n", wc->spans[3].name); zt_unregister(&wc->spans[0]); zt_unregister(&wc->spans[1]); zt_unregister(&wc->spans[2]); return -1; } wc->checktiming = 1; spin_lock_irqsave(&wc->reglock, flags); __t4_set_timing_source(wc,4); spin_unlock_irqrestore(&wc->reglock, flags);#ifdef ENABLE_TASKLETS tasklet_init(&wc->t4_tlet, t4_tasklet, (unsigned long)wc);#endif return 0;}static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){ int res; struct t4 *wc; int x,f;#if 0 int y; unsigned int *canary;#endif if (pci_enable_device(pdev)) { res = -EIO; } else { wc = kmalloc(sizeof(struct t4), GFP_KERNEL); if (wc) { memset(wc, 0x0, sizeof(struct t4)); spin_lock_init(&wc->reglock); wc->variety = (char *)(ent->driver_data); wc->memaddr = pci_resource_start(pdev, 0); wc->memlen = pci_resource_len(pdev, 0); wc->membase = ioremap(wc->memaddr, wc->memlen); /* This rids of the Double missed interrupt message after loading */ wc->last0 = 1;#if 0 if (!request_mem_region(wc->memaddr, wc->memlen, wc->variety)) printk("wct4: Unable to request memory region :(, using anyway...\n");#endif if (pci_request_regions(pdev, wc->variety)) printk("wct4xxp: Unable to request regions\n"); printk("Found TE410P at base address %08lx, remapped to %p\n", wc->memaddr, wc->membase); wc->dev = pdev; wc->writechunk = /* 32 channels, Double-buffer, Read/Write, 4 spans */ (unsigned int *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 32 * 2 * 2 * 4, &wc->writedma); if (!wc->writechunk) { printk("wct1xxp: Unable to allocate DMA-able memory\n"); return -ENOMEM; } /* Read is after the whole write piece (in words) */ wc->readchunk = wc->writechunk + ZT_CHUNKSIZE * 32 * 2; /* Same thing but in bytes... */ wc->readdma = wc->writedma + ZT_CHUNKSIZE * 32 * 2 * 4; /* Initialize Write/Buffers to all blank data */ memset((void *)wc->writechunk,0xff,ZT_MAX_CHUNKSIZE * 2 * 32 * 4); memset((void *)wc->readchunk,0xff,ZT_MAX_CHUNKSIZE * 2 * 32 * 4);#if 0 memset((void *)wc->readchunk,0xff,ZT_MAX_CHUNKSIZE * 2 * 32 * 4); /* Initialize canary */ canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 * 4 - 4); *canary = (CANARY << 16) | (0xffff);#endif /* Enable bus mastering */ pci_set_master(pdev); /* Keep track of which device we are */ pci_set_drvdata(pdev, wc); /* Initialize hardware */ t4_hardware_init(wc); for(x = 0; x < MAX_T4_CARDS; x++) { if (!cards[x]) break; } if (x >= MAX_T4_CARDS) { printk("No cards[] slot available!!\n"); return -ENOMEM; } wc->num = x; cards[x] = wc; if (request_irq(pdev->irq, t4_interrupt, SA_INTERRUPT | SA_SHIRQ, "t4xxp", wc)) { printk("t4xxp: Unable to request IRQ %d\n", pdev->irq); kfree(wc); return -EIO; } for (x=0;x<4;x++) { if (wc->t1e1 & (1 << x)) { wc->spantype[x] = TYPE_E1; wc->chans[x] = kmalloc(sizeof(struct zt_chan) * 31,GFP_KERNEL); memset(wc->chans[x],0,sizeof(struct zt_chan) * 31); } else { wc->spantype[x] = TYPE_T1; wc->chans[x] = kmalloc(sizeof(struct zt_chan) * 24,GFP_KERNEL); memset(wc->chans[x],0,sizeof(struct zt_chan) * 24); } if (!wc->chans[x]) return -ENOMEM; } init_spans(wc); /* Launch cards as appropriate */ x = 0; for(;;) { /* Find a card to activate */ f = 0; for (x=0;cards[x];x++) { if (cards[x]->order <= highestorder) { t4_launch(cards[x]); if (cards[x]->order == highestorder) f = 1; } } /* If we found at least one, increment the highest order and search again, otherwise stop */ if (f) highestorder++; else break; } printk("Found a Wildcard: %s\n", wc->variety); res = 0; } else res = -ENOMEM; } return res;}static int t4_hardware_stop(struct t4 *wc){ /* Turn off DMA, leave interrupts enabled */ wc->dmactrl = 0x0000000; t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); /* Turn on only the read interrupts, not the write */ t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); t4_pci_out(wc, WC_INTR, 0x00000000); current->state = TASK_UNINTERRUPTIBLE; schedule_timeout((25 * HZ) / 1000); /* Turn off counter, address, etc */ t4_pci_out(wc, WC_COUNT, 0x000000); t4_pci_out(wc, WC_RDADDR, 0x0000000); t4_pci_out(wc, WC_WRADDR, 0x0000000); t4_pci_out(wc, WC_GPIO, 0x0000000); t4_pci_out(wc, WC_LEDS, 0x00000000); printk("\nStopped TE410P, Turned off DMA\n"); return 0;}static void __devexit t4_remove_one(struct pci_dev *pdev){ struct t4 *wc = pci_get_drvdata(pdev); if (wc) { /* Stop hardware */ t4_hardware_stop(wc); /* Unregister spans */ if (wc->spans[0].flags & ZT_FLAG_REGISTERED) zt_unregister(&wc->spans[0]); if (wc->spans[1].flags & ZT_FLAG_REGISTERED) zt_unregister(&wc->spans[1]); if (wc->spans[2].flags & ZT_FLAG_REGISTERED) zt_unregister(&wc->spans[2]); if (wc->spans[3].flags & ZT_FLAG_REGISTERED) zt_unregister(&wc->spans[3]);#if 0 /* Stop any DMA */ __t1xxp_stop_dma(wc); /* In case hardware is still there */ __t1xxp_disable_interrupts(wc); t1xxp_stop_stuff(wc);#endif if (wc->membase) iounmap((void *)wc->membase); pci_release_regions(pdev); #if 0 if (wc->memaddr) release_mem_region(wc->memaddr, wc->memlen);#endif /* Immediately free resources */ pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma);#if 1 free_irq(pdev->irq, wc);#endif cards[wc->num] = NULL; pci_set_drvdata(pdev, NULL); }}static struct pci_device_id t4_pci_tbl[] __devinitdata ={ { 0x10ee, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Wildcard TE410P-Xilinx" }, { 0, }};static struct pci_driver t4_driver = { name: "t4xxp", probe: t4_init_one,#ifdef LINUX26 remove: __devexit_p(t4_remove_one),#else remove: t4_remove_one,#endif suspend: NULL, resume: NULL, id_table: t4_pci_tbl,};static int __init t4_init(void){ int res; res = pci_module_init(&t4_driver); if (res) return -ENODEV; return 0;}static void __exit t4_cleanup(void){ pci_unregister_driver(&t4_driver);}MODULE_AUTHOR("Mark Spencer");MODULE_DESCRIPTION("TE410P PCI Driver");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif#ifdef LINUX26module_param(debug, int, 0600);module_param(loopback, int, 0600);module_param(noburst, int, 0600);module_param(timingcable, int, 0600);module_param(t1e1override, int, 0600);module_param(alarmdebounce, int, 0600);#elseMODULE_PARM(debug, "i");MODULE_PARM(loopback, "i");MODULE_PARM(noburst, "i");MODULE_PARM(timingcable, "i");MODULE_PARM(t1e1override, "i");MODULE_PARM(alarmdebounce, "i");#endifMODULE_DEVICE_TABLE(pci, t4_pci_tbl);module_init(t4_init);module_exit(t4_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -