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

📄 hmp4d.c.svn-base

📁 linux2.6.18下支持sd2.0的驱动程序源码,支持最大32G的SD卡
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
    /* if you want to test the module, you obviously need to "mknod". */    PDEBUG("module init\n");	if(use_hmp4d == 0) return -ENODEV;    printk(KERN_INFO "hmp4d: base_port=0x%08lx irq=%i\n", base_port, irq);    hmp4d_data.iobaseaddr = base_port;    hmp4d_data.iosize = DEC_IO_SIZE;    hmp4d_data.irq = irq;#ifdef IRQTEST1    result = request_irq(irq, hmp4d_isr,                         SA_SHIRQ, "hmp4d", (void *) &hmp4d_data);    if(result == -EINVAL)    {        printk(KERN_ERR "hmp4d: Bad irq number or handler\n");        return result;    }    else if(result == -EBUSY)    {        printk(KERN_ERR "hmp4d: IRQ %d busy, change your config\n", irq);        return result;    }#endif    result = register_chrdev(hmp4d_major, "hmp4d", &hmp4d_fops);    if(result < 0)    {        printk(KERN_INFO "hmp4d: unable to get major %d\n", hmp4d_major);        goto err;    }    else if(result != 0)    /* this is for dynamic major */    {        hmp4d_major = result;    }    result = ReserveIO();    if(result < 0)    {        goto err;    }    ResetAsic(&hmp4d_data);    result = AllocMemory();    if(result < 0)    {        ReleaseIO();        goto err;    }    printk(KERN_INFO "hmp4d: module inserted. Major = %d\n", hmp4d_major);    //EXPORT_NO_SYMBOLS;    return 0;  err:    printk(KERN_INFO "hmp4d: module not inserted. Major = %d\n", hmp4d_major);    unregister_chrdev(hmp4d_major, "hmp4d");    return result;}void __exit hmp4d_cleanup(void){    unregister_chrdev(hmp4d_major, "hmp4d");    FreeMemory();#ifdef IRQTEST1    free_irq(irq, (void *) &hmp4d_data);#endif    ReleaseIO();    printk(KERN_INFO "hmp4d: module removed\n");    return;}//arch_initcall(hmp4d_init);module_init(hmp4d_init);module_exit(hmp4d_cleanup);static int AllocMemory(void){#if !CONS_ALLOC    struct page *pg;    char *start_addr, *end_addr;    u32 order, size;    hmp4d_data.buffer = NULL;#endif    hmp4d_data.buffsize = HMP4D_BUF_SIZE;#if !CONS_ALLOC    for(order = 0, size = PAGE_SIZE; size < hmp4d_data.buffsize;        order++, size <<= 1) ;    hmp4d_data.buffsize = size;    /* alloc memory */    start_addr = (char *) __get_free_pages(GFP_KERNEL, order);    if(!start_addr)    {        printk(KERN_INFO "hmp4d: failed to alloc memory\n");        return -ENOMEM;    }    else    {        memset(start_addr, 0, hmp4d_data.buffsize); /* clear the mem */        strcpy(start_addr, "Mapping test, data written from kernel!");        hmp4d_data.buffer = start_addr;    }    end_addr = start_addr + hmp4d_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);    }#else	hmp4d_data.buffsize = (HMP4D_BUF_SIZE + PAGE_SIZE - 1) & 		~(PAGE_SIZE - 1);        hmp4d_data.buffer = consistent_alloc(GFP_DMA | GFP_KERNEL, 		hmp4d_data.buffsize, (dma_addr_t *)&hmp4d_phys);	if (!hmp4d_data.buffer)	{printk("alloc %d failed\n", hmp4d_data.buffsize);		return -ENOMEM;	}	else	{		memset(hmp4d_data.buffer, 0, hmp4d_data.buffsize);		strcpy(hmp4d_data.buffer, 			"Mapping test, data written from kernel!");	}#endif    return 0;}static void FreeMemory(void){#if !CONS_ALLOC    struct page *pg;    u32 size, order;    /* first unreserve */    for(pg = virt_to_page(hmp4d_data.buffer);        pg < virt_to_page(hmp4d_data.buffer + hmp4d_data.buffsize); pg++)    {        mem_map_unreserve(pg);    }    for(order = 0, size = PAGE_SIZE; size < hmp4d_data.buffsize;        order++, size <<= 1) ;    /* and now free */    free_pages((long) hmp4d_data.buffer, order);    PDEBUG("Free buffer 0x%08lx -- 0x%08lx\n", (long) hmp4d_data.buffer,           (long) (hmp4d_data.buffer + hmp4d_data.buffsize - 1));#else	consistent_free(hmp4d_data.buffer, hmp4d_data.buffsize, hmp4d_phys);#endif}static int ReserveIO(void){	long int hwid;	    if(!request_mem_region(hmp4d_data.iobaseaddr, hmp4d_data.iosize, "hmp4d"))    {        printk(KERN_INFO "hmp4d: failed to reserve IO memory\n");        return -EBUSY;    }    hmp4d_data.hwregs =        (u8 *) ioremap_nocache(hmp4d_data.iobaseaddr, (size_t)hmp4d_data.iosize);    if(hmp4d_data.hwregs == NULL)    {        printk(KERN_INFO "hmp4d: failed to ioremap IO memory\n");        ReleaseIO();        return -EBUSY;    }#if 1    	hwid = readl(hmp4d_data.hwregs + 0x54); 	if((hwid >> 16) != DEC_HW_ID)    {        printk(KERN_INFO "hmp4d: HW not found at 0x%08lx\n",               hmp4d_data.iobaseaddr);                       printk(KERN_INFO "hmp4d: HW not found at 0x%08x\n",               (u32)&hmp4d_data.hwregs);        #ifdef HMP4D_DEBUG              		dump_regs((unsigned long) &hmp4d_data);        #endif		       	                		            ReleaseIO();        return -EBUSY;    }    else    {	    printk(KERN_INFO "hmp4d: Success: HW found at 0x%08lx\n",        hmp4d_data.iobaseaddr);        printk(KERN_INFO "hmp4d: Value of ID REG 0x%08lx\n",        hwid);          	}    #endif    return 0;}static void ReleaseIO(void){    if(hmp4d_data.hwregs)        iounmap((u32 *)hmp4d_data.hwregs);    release_mem_region(hmp4d_data.iobaseaddr, hmp4d_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 > hmp4d_data.buffsize)        return -EINVAL;    vma->vm_flags |= VM_RESERVED;    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);    /* Remember this won't work for vmalloc()d memory ! */#if !CONS_ALLOC    phys = virt_to_phys(hmp4d_data.buffer);#else	phys = hmp4d_phys;#endif    printk("<1>hmp4d1:remap_page_range,%x,%x,%x\n",start, phys , size);    if(remap_pfn_range(vma, start, phys >> PAGE_SHIFT, size, vma->vm_page_prot))//    if(remap_page_range(vma, start, phys, 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 NON_PAGE_ALIGNED	int	ofs;	ofs  = hmp4d_data.iobaseaddr & (PAGE_SIZE - 1);#endif    /* 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);    /* Remember this won't work for vmalloc()d memory ! */    phys = hmp4d_data.iobaseaddr;#if NON_PAGE_ALIGNED    printk("<1>hmp4d2:remap_page_range,%x,%x,%x\n",start, phys -ofs, hmp4d_data.iosize+ofs);if(remap_pfn_range(vma, start, (phys - ofs) >> PAGE_SHIFT, hmp4d_data.iosize + ofs, //	if(remap_page_range(vma, start, (phys - ofs) , hmp4d_data.iosize + ofs, 		vma->vm_page_prot))#else    printk("<1>hmp4d3:remap_page_range,%x,%x,%x\n",start, phys -ofs, hmp4d_data.iosize+ofs);   if(remap_pfn_range(vma, start, phys >> PAGE_SHIFT, hmp4d_data.iosize, vma->vm_page_prot))//    if(remap_page_range(vma, start, phys, hmp4d_data.iosize, vma->vm_page_prot))#endif    {        return -EAGAIN;    }    return 0;}int hmp4d_isr(int irq, void *dev_id, struct pt_regs *regs){    hmp4d_t *dev = (hmp4d_t *) dev_id;    /* Clear the HW Interrupt Register immediately! */    u32 irq_status = readl(dev->hwregs);    writel(irq_status & (~0x02), dev->hwregs);    PDEBUG("DecIRQ");    if(dev->async_queue)        kill_fasync(&dev->async_queue, SIGIO, POLL_IN);                   if(dev->async_queue)        kill_fasync(&dev->async_queue, SIGIO, POLL_IN);    return IRQ_HANDLED;}void ResetAsic(hmp4d_t * dev){    #if 1        int i;    writel(0, dev->hwregs);    for(i = 0; i < dev->iosize; i += 4)    {        writel(0, dev->hwregs + i);    }        #else			u32 tmp;    tmp = readl(dev->hwregs);    tmp = tmp | 0x20;    writel(tmp, dev->hwregs);   /* enable dec CLK */    writel(tmp & (~0x01), dev->hwregs); /* disable dec */    writel(0x20, dev->hwregs);  /* clear reg 1 */    writel(0, dev->hwregs); /* disable dec CLK */	#endif}#ifdef HMP4D_DEBUGvoid dump_regs(unsigned long data){    hmp4d_t *dev = (hmp4d_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 + -