📄 rtd-dm7520.c
字号:
} if (!(dm7520_table[card_idx].lasmap[LCFG] && dm7520_table[card_idx].lasmap[LAS0] && dm7520_table[card_idx].lasmap[LAS1] && dm7520_table[card_idx].irq )) // unsuccessful { printk(KERN_INFO "dm7520%d: Something is unsuccessful.\n",card_idx); for (i=0;i<=LCFG;i++) { if (dm7520_table[card_idx].lasmap[i]) iounmap((void*)dm7520_table[i].lasmap[i]); } if (dm7520_table[i].irq) { free_irq(dm7520_table[i].irq,&dm7520_table[i]); } continue; } else { dm7520_table[card_idx].present=1; } ret=dm7520_register_procfile(card_idx); dm7520_table[card_idx].fifosize=dm7520_probefifosize(card_idx); printk(KERN_INFO "dm7520%d: FIFO size %d.\n",card_idx, dm7520_table[card_idx].fifosize); /* Here we have to fiddle with the delay for the interruptible_sleep_on_timeout functions, because the FIFO size determines the max value we can wait otherwise the FIFO fills up. This is a quick hack. */ if (dm7520_table[card_idx].fifosize==1024) { dm7520_table[card_idx].jiffie_r=READ_TIMEOUT_SHORT; dm7520_table[card_idx].jiffie_w=WRITE_TIMEOUT_SHORT; } else { dm7520_table[card_idx].jiffie_r=READ_TIMEOUT_LONG; dm7520_table[card_idx].jiffie_w=WRITE_TIMEOUT_LONG; } epld_version=GETMEM32(card_idx,LAS0,0)&0xFF; if ((epld_version&0xF0)>>4 == 0x0F) { VPRINTK(KERN_INFO "dm7520%d: pre-v8 EPLD.\n",card_idx); } else { VPRINTK(KERN_INFO "dm7520%d: EPLD version %08X.\n",card_idx,epld_version>>4); } dm7520_table[card_idx].flags&=~DM7520_FLAGS_BMCAP; pci_read_config_word(pdev, PCI_COMMAND, &pci_command); new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; if (pci_command != new_command) { printk(KERN_INFO "dm7520%d: Busmastering not enabled on this device.\n", card_idx); pci_write_config_word(pdev, PCI_COMMAND, new_command); } else { if (epld_version&0x01) { dm7520_table[card_idx].flags|=DM7520_FLAGS_BMCAP; DMABUF(card_idx,0)=kmalloc(DMASIZE(card_idx),GFP_KERNEL); DMABUF(card_idx,1)=kmalloc(DMASIZE(card_idx),GFP_KERNEL);
DMATEMPBUF(card_idx,0)=kmalloc(DMATEMPSIZE,GFP_KERNEL);
DMATEMPBUF(card_idx,1)=kmalloc(DMATEMPSIZE,GFP_KERNEL);
CONTROLBUF(card_idx) = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!DMABUF(card_idx,0) && !DMABUF(card_idx,1)) { printk(KERN_INFO "dm7520%d: Unable to get DMA buffer.\n", card_idx); dm7520_table[card_idx].flags&=~DM7520_FLAGS_BMCAP; } else {
if (DMATEMPBUF(card_idx,0)) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) for (page=virt_to_page(DMATEMPBUF(card_idx,0));
page<(virt_to_page(DMATEMPBUF(card_idx,0)+DMATEMPSIZE));
page++){
mem_map_reserve(page); }
#else for (i=MAP_NR(DMATEMPBUF(card_idx,0));
i<MAP_NR((DMATEMPBUF(card_idx,0)+DMATEMPSIZE));
i++){
mem_map_reserve(i); } #endif // printk("<1> dmatempbuf0=%ld\n",(long)DMATEMPBUF(card_idx,0)); } else printk(KERN_INFO "Could not allocate memory for DMATEMPBUF(card_idx,0)\n"); if (DMATEMPBUF(card_idx,1)) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) for (page=virt_to_page(DMATEMPBUF(card_idx,1));
page<(virt_to_page(DMATEMPBUF(card_idx,1)+DMATEMPSIZE));
page++){
mem_map_reserve(page);
}
#else for (i=MAP_NR(DMATEMPBUF(card_idx,1));
i<MAP_NR((DMATEMPBUF(card_idx,1)+DMATEMPSIZE));
i++){
mem_map_reserve(i);
}
#endif // printk("<1> dmatempbuf1=%ld\n",(long)DMATEMPBUF(card_idx,1)); } else printk(KERN_INFO "Could not allocate memory for DMATEMPBUF(card_idx,1)\n"); if (CONTROLBUF(card_idx)){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) page=virt_to_page(CONTROLBUF(card_idx));
mem_map_reserve(page); #else i=MAP_NR(CONTROLBUF(card_idx));
mem_map_reserve(i); #endif } else printk(KERN_INFO "Could not allocate memory for CONTROLBUF\n"); } } else { dm7520_table[card_idx].dmasetup[0].dmabuf=NULL; dm7520_table[card_idx].dmasetup[1].dmabuf=NULL; } } pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < 32) { VPRINTK("dm7520%d: PCI latency timer Changed to %d.\n",card_idx,32); pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); } card_idx++; }
return card_idx;}/************************************************************************/ int init_module(){ int ret; memset(dm7520_table,0,MAXDM7520*sizeof(dm7520_table[0])); printk(KERN_INFO "%s> \n", DRIVER_NAME); printk( KERN_INFO "%s> Initializing module (version %s).\n", DRIVER_NAME, DRIVER_RELEASE ); printk(KERN_INFO "%s> %s\n", DRIVER_NAME, DRIVER_DESCRIPTION); printk(KERN_INFO "%s> %s\n", DRIVER_NAME, DRIVER_COPYRIGHT); ret=finddevices(); if (0==ret) { printk(KERN_INFO "dm7520: No devices found.\n"); return(-ENODEV); } /* * Register the character device, requesting dynamic major number allocation */ dm7520_major = register_chrdev(0, DEVICE_NAME, &dm7520_fops); if (dm7520_major < 0) { printk( KERN_INFO "%s> Dynamic character device registration failed with errno %d\n", DRIVER_NAME, -dm7520_major ); return dm7520_major; } printk( KERN_INFO "%s> Driver registered using character major number %d\n", DRIVER_NAME, dm7520_major ); SET_MODULE_OWNER(&dm7520_fops); return 0;}voidcleanup_module(void) { int ret; int i; struct page *page; for (i = 0; i < MAXDM7520; i++) { if (dm7520_table[i].present) { disable_PLX_it(i); reset_card(i); if (dm7520_table[i].dmasetup[0].dmainuse) { dm7520_table[i].dmasetup[0].dmainuse = 0; abort_dma0(i); disable_dma(i, 0); } if (dm7520_table[i].dmasetup[1].dmainuse) { dm7520_table[i].dmasetup[1].dmainuse = 0; abort_dma1(i); disable_dma(i, 1); } dm7520_unregister_procfile(i); if (DMABUF(i, 0)) { kfree(DMABUF(i, 0)); } if (DMABUF(i, 1)) { kfree(DMABUF(i, 1)); } if (DMATEMPBUF(i, 0)) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) for ( page = virt_to_page(DMATEMPBUF(i, 0)); page < (virt_to_page(DMATEMPBUF(i, 0) + DMATEMPSIZE)); page++ ) { mem_map_unreserve(page); }#endif kfree(DMATEMPBUF(i, 0)); } if (DMATEMPBUF(i, 1)) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) for ( page = virt_to_page(DMATEMPBUF(i, 1)); page < (virt_to_page(DMATEMPBUF(i, 1) + DMATEMPSIZE)); page++ ) { mem_map_unreserve(page); }#endif kfree(DMATEMPBUF(i, 1)); } if (CONTROLBUF(i)) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) page = virt_to_page(CONTROLBUF(i)); mem_map_unreserve(page);#endif kfree(CONTROLBUF(i)); } iounmap((void*) dm7520_table[i].lasmap[LAS0]); iounmap((void*) dm7520_table[i].lasmap[LAS1]); iounmap((void*) dm7520_table[i].lasmap[LCFG]); free_irq(dm7520_table[i].irq, &dm7520_table[i]); } } ret = unregister_chrdev(dm7520_major, DEVICE_NAME); if (ret < 0) printk("DM7520: Error in unregister_chrdev: %d\n", ret);} /*=============================================================================What follows is source code for DM7520 /proc file entry support. This wasbrought in from procfs.c. =============================================================================*/#ifndef DEBUGstatic char *rwchan_names[] = {"A/D", "HDIN", "D/A1", "D/A2"};#endifstatic ssize_tdm7520_proc_output( char *buf, char **start, off_t offset, int len, int *eof, void *data) { int minor; DM7520_STAT *devptr = (DM7520_STAT *) data;#ifdef DEBUG uint32_t p_itcsr, p_d0s, p_d1s, p_d0m, p_d1m;#endif minor = devptr - &(dm7520_table[0]); len = 0;#ifdef DEBUG dm7520_getregs(minor, &p_itcsr, &p_d0m, &p_d1m, &p_d0s, &p_d1s); len = sprintf( buf, "IRQ: %d, LAS0 %p, LAS1 %p, LCFG %p, Busmaster: %s, opened: %d, " "errorcode: %d, IT: %08X\n", dm7520_table[minor].irq, dm7520_table[minor].lasmap[LAS0], dm7520_table[minor].lasmap[LAS1], dm7520_table[minor].lasmap[LCFG], (dm7520_table[minor].flags & DM7520_FLAGS_BMCAP) ? "yes" : "no", dm7520_table[minor].opened, dm7520_table[minor].errcode, p_itcsr );#else len = sprintf( buf, "IRQ: %d, Busmaster: %s, opened: %d, errorcode: %d,\n used by %s, " "used by %s.\n", dm7520_table[minor].irq, (dm7520_table[minor].flags & DM7520_FLAGS_BMCAP) ? "yes" : "no", dm7520_table[minor].opened, dm7520_table[minor].errcode, dm7520_table[minor].dmasetup[0].dmainuse ? rwchan_names[(int) dm7520_table[minor].dmasetup[0].usedby] : "-", dm7520_table[minor].dmasetup[1].dmainuse ? rwchan_names[(int) dm7520_table[minor].dmasetup[1].usedby] : "-" );#endif //DEBUG *eof = 1; return len;}static ssize_tdm7520_proc_input( struct file *file, const char *buf, size_t length, loff_t *offset) { return -EACCES;}static intdm7520_proc_permission(struct inode *inode, int op) { if (op == MAY_READ) { return 0; } return -EACCES;}intdm7520_proc_open(struct inode *inode, struct file *file) { dm7520_incuse(); return 0;}intdm7520_proc_close(struct inode *inode, struct file *file) { dm7520_decuse(); return 0;}intdm7520_register_procfile(int minor) { struct proc_dir_entry *pfile;#ifdef DEBUG printk(KERN_INFO "registering /proc/%s\n", dm7520_table[minor].devname);#endif pfile = create_proc_entry( dm7520_table[minor].devname, (S_IFREG | S_IRUGO | S_IWUSR), &proc_root ); if (pfile) { pfile->read_proc = dm7520_proc_output; pfile->data = &(dm7520_table[minor]); dm7520_table[minor].procfile = pfile; return 1; } else { dm7520_table[minor].procfile = NULL; } return 0;}voiddm7520_unregister_procfile(int minor) { remove_proc_entry(dm7520_table[minor].devname, &proc_root);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -