⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hmp4e.c.svn-base

📁 linux2.6.18下支持sd2.0的驱动程序源码,支持最大32G的SD卡
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
static int hmp4e_fasync(int fd, struct file *filp, int mode){    hmp4e_t *dev = (hmp4e_t *) filp->private_data;    PDEBUG("fasync called\n");    return fasync_helper(fd, filp, mode, &dev->async_queue);}#ifdef HMP4E_DEBUGstatic void dump_regs(unsigned long data);#endifstatic int hmp4e_release(struct inode *inode, struct file *filp){    hmp4e_t *dev = (hmp4e_t *) filp->private_data;    /* this is necessary if user process exited asynchronously */    disable_irq(dev->irq);#ifdef HMP4E_DEBUG    dump_regs((unsigned long) dev); /* dump the regs */#endif    ResetAsic(dev); /* reset hardware */    /* free the encoder IRQ */    free_irq(dev->irq, (void *) dev);    /* remove this filp from the asynchronusly notified filp's */    hmp4e_fasync(-1, filp, 0);    //MOD_DEC_USE_COUNT;    PDEBUG("dev closed\n");    return 0;}/* VFS methods */static struct file_operations hmp4e_fops = {    mmap:hmp4e_mmap,    open:hmp4e_open,    release:hmp4e_release,    ioctl:hmp4e_ioctl,    fasync:hmp4e_fasync,};int __init hmp4e_init(void){    int result;    /* if you want to test the module, you obviously need to "mknod". */    PDEBUG("module init\n");    printk("<1>hmp4e: base_port=0x%08lx irq=%i\n", base_porte, irqe);    hmp4e_data.iobaseaddr = base_porte;    hmp4e_data.iosize = ENC_IO_SIZE;    hmp4e_data.irq = irqe;    result = register_chrdev(hmp4e_major, "hmp4e", &hmp4e_fops);    if(result < 0)    {        printk(KERN_INFO "hmp4e: unable to get major %d\n", hmp4e_major);        goto err;    }    else if(result != 0)    /* this is for dynamic major */    {        hmp4e_major = result;    }    result = ReserveIO();    if(result < 0)    {        goto err;    }    ResetAsic(&hmp4e_data); /* reset hardware */    result = AllocMemory();    if(result < 0)    {        ReleaseIO();        goto err;    }    printk(KERN_INFO "hmp4e: module inserted. Major = %d\n", hmp4e_major);    //EXPORT_NO_SYMBOLS;    return 0;  err:    printk(KERN_INFO "hmp4e: module not inserted\n");    unregister_chrdev(hmp4e_major, "hmp4e");    return result;}void __exit hmp4e_cleanup(void){    unregister_chrdev(hmp4e_major, "hmp4e");    FreeMemory();    ReleaseIO();    printk(KERN_INFO "hmp4e: module removed\n");    return;}module_init(hmp4e_init);module_exit(hmp4e_cleanup);static int AllocMemory(void){    struct page *pg;    char *start_addr, *end_addr;    u32 order, size;    hmp4e_data.buffer = NULL;    hmp4e_data.buffsize = HMP4E_BUF_SIZE;    for(order = 0, size = PAGE_SIZE; size < hmp4e_data.buffsize;        order++, size <<= 1) ;    hmp4e_data.buffsize = size;    /* alloc memory */    start_addr = (char *) __get_free_pages(GFP_KERNEL, order);    if(!start_addr)    {        printk(KERN_INFO "hmp4e: failed to alloc memory\n");        return -ENOMEM;    }    else    {        memset(start_addr, 0, hmp4e_data.buffsize); /* clear the mem */        hmp4e_data.buffer = start_addr;    }    end_addr = start_addr + hmp4e_data.buffsize - 1;    PDEBUG("Alloc buffer 0x%08lx -- 0x%08lx\n", (long) start_addr,           (long) end_addr);    /* now we've got the kernel memory, but it can still be     * swapped out. We need to stop the VM system from removing our     * pages from main memory. To do this we just need to set the PG_reserved      * bit on each page, via mem_map_reserve() macro.     */    /* If we don't set the reserved bit, the user-space application sees      * all-zeroes pages. This is because remap_page_range() won't allow you to     * map non-reserved pages (check remap_pte_range()).     * The pte's will be cleared, resulting in a page faulting in a new zeroed      * page instead of the pages we are trying to mmap().      */    for(pg = virt_to_page(start_addr); pg <= virt_to_page(end_addr); pg++)    {        mem_map_reserve(pg);    }    return 0;}static void FreeMemory(void){    struct page *pg;    u32 size, order;    /* first unreserve */    for(pg = virt_to_page(hmp4e_data.buffer);        pg < virt_to_page(hmp4e_data.buffer + hmp4e_data.buffsize); pg++)    {        mem_map_unreserve(pg);    }    for(order = 0, size = PAGE_SIZE; size < hmp4e_data.buffsize;        order++, size <<= 1) ;    /* and now free */    free_pages((long) hmp4e_data.buffer, order);    PDEBUG("Free buffer 0x%08lx -- 0x%08lx\n", (long) hmp4e_data.buffer,           (long) (hmp4e_data.buffer + hmp4e_data.buffsize - 1));}static int ReserveIO(void){    long int hwid;    if(!request_mem_region(hmp4e_data.iobaseaddr, hmp4e_data.iosize, "hmp4e"))    {        printk(KERN_INFO "hmp4e: failed to reserve HW regs\n");        return -EBUSY;    }    hmp4e_data.hwregs =        (volatile u8 *) ioremap_nocache(hmp4e_data.iobaseaddr,                                        hmp4e_data.iosize);    if(hmp4e_data.hwregs == NULL)    {        printk(KERN_INFO "hmp4e: failed to ioremap HW regs\n");        ReleaseIO();        return -EBUSY;    }    hwid = readl(hmp4e_data.hwregs + 0x88);#if 1    /* check for correct HW */    if((hwid >> 20) != (ENC_HW_ID >> 20))    {        printk(KERN_INFO "hmp4e: HW not found at 0x%08lx\n",               hmp4e_data.iobaseaddr);#ifdef HMP4E_DEBUG        dump_regs((unsigned long) &hmp4e_data);#endif        ReleaseIO();        return -EBUSY;    }    else    {        printk(KERN_INFO               "hmp4e: Valid HW found at base 0x%08lx with ID# 0x%08lx\n",               hmp4e_data.iobaseaddr, hwid);    }#endif    return 0;}static void ReleaseIO(void){    if(hmp4e_data.hwregs)        iounmap((void *) hmp4e_data.hwregs);    release_mem_region(hmp4e_data.iobaseaddr, hmp4e_data.iosize);}static int MapBuffers(struct file *filp, struct vm_area_struct *vma){    unsigned long phys;    unsigned long start = (unsigned long) vma->vm_start;    unsigned long size = (unsigned long) (vma->vm_end - vma->vm_start);    /* if userspace tries to mmap beyond end of our buffer, fail */    if(size > hmp4e_data.buffsize){        return -EINVAL;	}    vma->vm_flags |= VM_RESERVED | VM_IO;    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);    /* Remember this won't work for vmalloc()d memory ! */    phys = virt_to_phys(hmp4e_data.buffer);    if(remap_pfn_range(vma, start, phys >> PAGE_SHIFT, size, vma->vm_page_prot))    {		printk("<1>HMP4E: MapBuffers -EAGAIN\n");        return -EAGAIN;    }    return 0;}static int MapHwRegs(struct file *filp, struct vm_area_struct *vma){    unsigned long phys;    unsigned long start = (unsigned long) vma->vm_start;    unsigned long size = (unsigned long) (vma->vm_end - vma->vm_start);    /* if userspace tries to mmap beyond end of our buffer, fail */    if(size > PAGE_SIZE)        return -EINVAL;    vma->vm_flags |= VM_RESERVED | VM_IO;    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);    phys = hmp4e_data.iobaseaddr;    if(remap_pfn_range(vma, start, phys >> PAGE_SHIFT, hmp4e_data.iosize, vma->vm_page_prot))    {        return -EAGAIN;    }    return 0;}int hmp4e_isr(int irq, void *dev_id, struct pt_regs *regs){    hmp4e_t *dev = (hmp4e_t *) dev_id;    u32 irq_status = readl(dev->hwregs + 0x10);    writel(irq_status & (~0x01), dev->hwregs + 0x10);   /* clear enc IRQ */    if(dev->async_queue)        kill_fasync(&dev->async_queue, SIGIO, POLL_IN);    PDEBUG("IRQ received!\n");	return IRQ_HANDLED;}void ResetAsic(hmp4e_t * dev){    int i;    writel(0, dev->hwregs + 0x10);    for(i = 0; i < dev->iosize; i += 4)    {        writel(0, dev->hwregs + i);    }}#ifdef HMP4E_DEBUGvoid dump_regs(unsigned long data){    hmp4e_t *dev = (hmp4e_t *) data;    int i;    PDEBUG("Reg Dump Start\n");    for(i = 0; i < dev->iosize; i += 4)    {        PDEBUG("\toffset %02X = %08X\n", i, readl(dev->hwregs + i));    }    PDEBUG("Reg Dump End\n");}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -