📄 sh7722gfx.c
字号:
wake_up_all( &wait_next ); } else { shared->num_idle++; QDUMP( " '-> Idle." ); BEM_PE_CACHE = 1; shared->hw_running = 0; wake_up_all( &wait_next ); wake_up_all( &wait_idle ); } shared->num_done++; } return IRQ_HANDLED;}#ifdef SH7722GFX_IRQ_POLLERstatic intsh7722_tdg_irq_poller( void *arg ){ daemonize( "%s", __FUNCTION__ ); sigfillset( ¤t->blocked ); while (!stop_poller) { set_current_state( TASK_UNINTERRUPTIBLE ); schedule_timeout( 1 ); sh7722_tdg_irq( TDG_IRQ, (void*) arg ); } stop_poller = 0; return 0;}#endif/**********************************************************************************************************************/static intsh7722gfx_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ){ SH7722Register reg; switch (cmd) { case SH7722GFX_IOCTL_RESET: return sh7722_reset( shared ); case SH7722GFX_IOCTL_WAIT_IDLE: return sh7722_wait_idle( shared ); case SH7722GFX_IOCTL_WAIT_NEXT: return sh7722_wait_next( shared ); case SH7722GFX_IOCTL_SETREG32: if (copy_from_user( ®, arg, sizeof(SH7722Register) )) return -EFAULT; /* BEU, LCDC, VOU, JPEG */ if (reg.address < 0xFE930000 || reg.address > 0xFEA102D0) return -EACCES; *(volatile __u32 *) reg.address = reg.value; return 0; case SH7722GFX_IOCTL_GETREG32: if (copy_from_user( ®, arg, sizeof(SH7722Register) )) return -EFAULT; /* BEU, LCDC, VOU, JPEG */ if (reg.address < 0xFE930000 || reg.address > 0xFEA102D0) return -EACCES; reg.value = *(volatile __u32 *) reg.address; if (copy_to_user( arg, ®, sizeof(SH7722Register) )) return -EFAULT; return 0; } return -ENOSYS;}static intsh7722gfx_mmap( struct file *file, struct vm_area_struct *vma ){ unsigned int size; /* Just allow mapping at offset 0. */ if (vma->vm_pgoff) return -EINVAL; /* Check size of requested mapping. */ size = vma->vm_end - vma->vm_start; if (size != PAGE_ALIGN(sizeof(SH7722GfxSharedArea))) return -EINVAL; /* Set reserved and I/O flag for the area. */ vma->vm_flags |= VM_RESERVED | VM_IO; /* Select uncached access. */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9) return remap_pfn_range( vma, vma->vm_start, virt_to_phys((void*)shared) >> PAGE_SHIFT, size, vma->vm_page_prot );#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) return remap_page_range( vma, vma->vm_start, virt_to_phys((void*)shared), size, vma->vm_page_prot );#else return io_remap_page_range( vma->vm_start, virt_to_phys((void*)shared), size, vma->vm_page_prot );#endif}/**********************************************************************************************************************/static struct file_operations sh7722gfx_fops = { ioctl: sh7722gfx_ioctl, mmap: sh7722gfx_mmap};static struct miscdevice sh7722gfx_miscdev = { minor: 196, // 7*7*2*2 name: "sh7722gfx", fops: &sh7722gfx_fops};/**********************************************************************************************************************/static int __initsh7722gfx_module_init( void ){#ifndef SHARED_AREA_PHYS int i;#endif int ret; /* Register the SH7722 graphics device. */ ret = misc_register( &sh7722gfx_miscdev ); if (ret < 0) { printk( KERN_ERR "%s: misc_register() for minor %d failed! (error %d)\n", __FUNCTION__, sh7722gfx_miscdev.minor, ret ); return ret; } /* Allocate and initialize the shared area. */#ifdef SHARED_AREA_PHYS#if SHARED_AREA_SIZE < PAGE_ALIGN(sizeof(SH7722GfxSharedArea))#error SHARED_AREA_SIZE < PAGE_ALIGN(sizeof(SH7722GfxSharedArea))!#endif shared = ioremap( SHARED_AREA_PHYS, PAGE_ALIGN(sizeof(SH7722GfxSharedArea)) );#else shared_order = get_order(sizeof(SH7722GfxSharedArea)); shared_page = alloc_pages( GFP_DMA | GFP_KERNEL, shared_order ); shared = ioremap( virt_to_phys( page_address(shared_page) ), PAGE_ALIGN(sizeof(SH7722GfxSharedArea)) ); for (i=0; i<1<<shared_order; i++) SetPageReserved( shared_page + i );#endif printk( KERN_INFO "sh7722gfx: shared area (order %d) at %p [%lx] using %d bytes\n", shared_order, shared, virt_to_phys(shared), sizeof(SH7722GfxSharedArea) ); /* Register the BEU interrupt handler. */ ret = request_irq( BEU_IRQ, sh7722_beu_irq, IRQF_DISABLED, "BEU", (void*) shared ); if (ret) { printk( KERN_ERR "%s: request_irq() for interrupt %d failed! (error %d)\n", __FUNCTION__, BEU_IRQ, ret ); goto error_beu; }#ifdef SH7722GFX_IRQ_POLLER kernel_thread( sh7722_tdg_irq_poller, (void*) shared, CLONE_KERNEL );#else /* Register the TDG interrupt handler. */ ret = request_irq( TDG_IRQ, sh7722_tdg_irq, IRQF_DISABLED, "TDG", (void*) shared ); if (ret) { printk( KERN_ERR "%s: request_irq() for interrupt %d failed! (error %d)\n", __FUNCTION__, TDG_IRQ, ret ); goto error_tdg; }#endif sh7722_reset( shared ); return 0;#ifndef SH7722GFX_IRQ_POLLERerror_tdg: free_irq( BEU_IRQ, (void*) shared );#endiferror_beu:#ifndef SHARED_AREA_PHYS for (i=0; i<1<<shared_order; i++) ClearPageReserved( shared_page + i ); __free_pages( shared_page, shared_order );#endif misc_deregister( &sh7722gfx_miscdev ); return ret;}module_init( sh7722gfx_module_init );/**********************************************************************************************************************/static void __exitsh7722gfx_module_exit( void ){#ifndef SHARED_AREA_PHYS int i;#endif#ifdef SH7722GFX_IRQ_POLLER stop_poller = 1; while (stop_poller) { set_current_state( TASK_UNINTERRUPTIBLE ); schedule_timeout( 1 ); }#else free_irq( TDG_IRQ, (void*) shared );#endif free_irq( BEU_IRQ, (void*) shared ); misc_deregister( &sh7722gfx_miscdev );#ifndef SHARED_AREA_PHYS for (i=0; i<1<<shared_order; i++) ClearPageReserved( shared_page + i ); __free_pages( shared_page, shared_order );#endif}module_exit( sh7722gfx_module_exit );/**********************************************************************************************************************/MODULE_AUTHOR( "Denis Oliver Kropp <dok@directfb.org>" );MODULE_LICENSE( "GPL v2" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -