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

📄 kllad.c

📁 1. 8623L平台
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		break;	case DIRECT_IOCTL_GBUS_GET_LOCKED_AREA:		{			struct gbus_lock_area param;			unsigned long i;			 			if (cfu(&param, (char *)arg, sizeof(param)) != 0)				return -EFAULT;			rc = 0;			i = get_locked_area(&param);		/* 	printk("get_locked area %p %d %d %d\n", param.byte_address, param.offset, param.size, i); */			if (i==DIRECT_REGION_COUNT) 				rc = -EINVAL;			if (ctu((char *) arg, &param, sizeof(param)) != 0) 				return -EFAULT;					}		break;	case DIRECT_IOCTL_GBUS_GET_SYSTEM_PAGE_COUNT:		{						struct gbus_region_count param;			unsigned long  region_index, system_page_count;						if (cfu(&param, (char *)arg, sizeof(param)) != 0)				return -EFAULT;			rc = 0;			region_index=param.region_index;			if (region_index >= DIRECT_REGION_COUNT) { 				return  -EINVAL;			}			system_page_count=R.region_info[region_index].region_count;		/* 			printk("get_system_page_count: region=%i, count=%i\n", region_index, system_page_count); */			param.region_count=system_page_count;			if (ctu((char *) arg, &param, sizeof(param)) != 0) 				return -EFAULT;					}		break;#endif // EM86XX_CHIP 			default:		rc = -EINVAL;	}done:	return rc;}#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)#define DIRECT_MMAP_MASK          0xff000000#define DIRECT_MMAP_DMAPOOL       0x02000000#define DIRECT_MMAP_REGION        0x03000000#define DIRECT_MMAP_DMAPOOL_SHIFT 12#define DIRECT_MMAP_REGION_SHIFT  12#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)struct page *kdmapool_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type);#elsestruct page *kdmapool_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int unused);#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)static struct page *direct_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)#elsestatic struct page *direct_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int type)#endif{	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;	struct page *page = NULL;	if ((offset & DIRECT_MMAP_MASK) == DIRECT_MMAP_DMAPOOL) 		page = kdmapool_vma_nopage(vma, addr, type);#if 0	/* this is only true if the region mapped is under kernel control */	else if ((offset & DIRECT_MMAP_MASK) == DIRECT_MMAP_REGION) {		unsigned long region_index, base, vaddr;		region_index = (offset - DIRECT_MMAP_REGION) >> DIRECT_MMAP_REGION_SHIFT;		base = XLAT_G2P(R.region_info[region_index].direct_map);		offset = (addr - vma->vm_start); /* absolute offset */		vaddr = (base + offset) & PAGE_MASK;		page = virt_to_page(vaddr);	}#endif	if (page)		get_page(page);	return page;}static struct vm_operations_struct direct_vm_ops = {	.nopage = direct_vma_nopage};static int minor_mmap(struct file *filp, struct vm_area_struct *vma){	int rc = 0;	unsigned long offset;	unsigned long dmapool_id, region_index;		offset = vma->vm_pgoff << PAGE_SHIFT; 	/*  printk("mmap at offset 0x%x\n", offset);   */	switch (offset & DIRECT_MMAP_MASK) {	case DIRECT_MMAP_DMAPOOL:		dmapool_id = (offset - DIRECT_MMAP_DMAPOOL) >> DIRECT_MMAP_DMAPOOL_SHIFT;		rc = kdmapool_mmap((struct llad *) NULL, (struct kc_vm_area_struct *)vma, dmapool_id, vma->vm_start, 				   vma->vm_end-vma->vm_start,(struct kc_pgprot_t *)&(vma->vm_page_prot));		break;	case DIRECT_MMAP_REGION:  	/* 	printk("mmaping region: %p 0x%08lx\n", vma->vm_start, vma->vm_end-vma->vm_start);   */		region_index = (offset - DIRECT_MMAP_REGION) >> DIRECT_MMAP_REGION_SHIFT;		/* because we run on MIPS */		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);		/* from linux-2.6.10 remap_page_range is replaced by remap_pfn_range */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)		rc = remap_page_range(vma->vm_start,				      XLAT_G2P(R.region_info[region_index].direct_map),				      vma->vm_end - vma->vm_start,				      vma->vm_page_prot);#else		rc = remap_pfn_range(vma,				     vma->vm_start,				     XLAT_G2P(R.region_info[region_index].direct_map) >> PAGE_SHIFT,				     vma->vm_end - vma->vm_start,				     vma->vm_page_prot);#endif // LINUX_VERSION_CODE		if (rc) {			printk("failed to mmap region\n");			return -EAGAIN;		} 		break;	default:		printk("Unknown offset\n");		rc = -EINVAL;		break;	}	if (rc >= 0) {		vma->vm_ops = &direct_vm_ops;		vma->vm_flags |= VM_RESERVED;	}	return rc;}#endif // EM86XX_CHIPstatic int minor_open(struct inode *i_node, struct file *filp){	int i;	spin_lock(&open_lock);	// find direct_id in the table	for (i=0;i<MAX_OPENERS;i++) if (R.openers[i].direct_id==CURRENT_DIRECT_ID) break; 	if (i==MAX_OPENERS) {		// find empty entry		for (i=0;i<MAX_OPENERS;i++) if (R.openers[i].direct_id==0) break;		if (i==MAX_OPENERS) {			printk("minor_open: too many openers (increase MAX_OPENERS)\n");			spin_unlock(&open_lock);			return -EINVAL;		}					R.openers[i].direct_id=CURRENT_DIRECT_ID;		//printk("minor_open: #%d new mum_id %d\n", i,R.openers[i].direct_id);	}	R.openers[i].open_count ++;	R.total_open_count ++;	spin_unlock(&open_lock);	return 0;}static int minor_release(struct inode *i_node, struct file *filp){	int i;	spin_lock(&open_lock);	// find direct_id in the table	for (i=0;i<MAX_OPENERS;i++) if (R.openers[i].direct_id==CURRENT_DIRECT_ID) break;	if (i>=MAX_OPENERS) {		printk("minor_release: too many openers (increase MAX_OPENERS)\n");		spin_unlock_bh(&open_lock);		return -EINVAL;	}	R.openers[i].open_count --;	if (R.openers[i].open_count == 0) {		/* close openned dmapools */		int j=0;				while (R.openers[i].dmapool_usage_mask) {			if (test_and_clear_bit(j, (void *)&(R.openers[i].dmapool_usage_mask))) {				kdmapool_close((struct llad *) NULL, j);			}			j++;		}		R.openers[i].direct_id = 0;	}			R.total_open_count --;	spin_unlock(&open_lock);	return 0;}static struct file_operations direct_fops = {	// this replaces MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT pain	owner: THIS_MODULE,		ioctl:minor_ioctl, #if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2) 	mmap:minor_mmap,#endif // EM86XX_CHIP	open:minor_open, 	release:minor_release, };#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)#define IRQ_FLAGS_INTERRUPT (SA_INTERRUPT)#define IRQ_FLAGS_SHIRQ (SA_INTERRUPT | SA_SHIRQ)#else#define IRQ_FLAGS_INTERRUPT (IRQF_DISABLED)#define IRQ_FLAGS_SHIRQ (IRQF_DISABLED | IRQF_SHARED)#endifint llad_init(void){  	int res,i;	init_waitqueue_head(&(R.irq_queue));		sema_init(&gbus_buf_sem, 1);	spin_lock_init(&open_lock);	R.total_open_count = 0;		for (i=0 ; i<MAX_OPENERS ; i++) {		R.openers[i].direct_id = 0;		R.openers[i].open_count = 0;		R.openers[i].dmapool_usage_mask = 0;	}	#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)	for (res=0 ; res<DIRECT_REGION_COUNT ; res++) {		R.region_info[res].direct_map =0; 		R.region_info[res].region_count=0;		R.region_info[res].map_refcount=0;		R.region_info[res].area_offset=0;		R.region_info[res].area_size=0;		R.region_info[res].area_byte_address=0;	}#endif // EM86XX_CHIP#if (EM86XX_CHIP<EM86XX_CHIPID_TANGO2) && defined WITH_IRQHANDLER_BOOTLOADER	{		/*		  when linux boots, it has overwritten irq and undef; in case		  of bootirq we put it back.		*/				RMuint32 val, table;				table = gbus_read_uint32(pGBus, JUMPTABLE_ADDRESS);		val = gbus_read_uint32(pGBus, IRQHANDLER_ENTRY);		overload_IRQHandler(pGBus, val, table);				val = gbus_read_uint32(pGBus, UNDEFHANDLER_ENTRY);		overload_UNDEFHandler(pGBus, val, table);	}#else	/* 	   when not using irqhandler from bootloader, clear all events/interrupts 	   before enabling the SOFTINT.	*/	gbus_write_uint32(pGBus, HOST_INTERRUPT_STATUS, 0);	gbus_write_uint32(pGBus, REG_BASE_cpu_block + CPU_irq_softclr, ~SOFTIRQMASK_VALID);		/* We need to initialize the UCLINUX_LLAD_IRQHANDLER_HANDSHAKE parmater to 0 since we are           going to register an IRQ that cannot be handled by the emhwlib IRQ handler yet since           the emhwlib will be loaded only later. */	gbus_write_uint32(pGBus, UCLINUX_LLAD_IRQHANDLER_HANDSHAKE, 0);#endif		res = kdmapool_init((struct llad *) NULL);	if (res < 0) 		return res;	if ((res = request_irq(IRQ_SOFTINT, tophalf, IRQ_FLAGS_SHIRQ, DIRECT_DEVICE_NAME, &R)) != 0)		goto free_irq_softint;	if ((res = request_irq(IRQ_MBUS_W1, dummy_isr, IRQ_FLAGS_INTERRUPT, "mbus_w1", &R)) != 0)		goto free_irq_mbus_w1;	if ((res = request_irq(IRQ_GRAPHICACCEL, dummy_isr, IRQ_FLAGS_INTERRUPT, "gfx", &R)) != 0)		goto free_irq_graphicaccel;	if ((res = request_irq(IRQ_MBUS_R1, dummy_isr, IRQ_FLAGS_INTERRUPT, "mbus_r1", &R)) != 0)		goto free_irq_mbus_r1;	if ((res = request_irq(IRQ_TIMER1, dummy_isr, IRQ_FLAGS_INTERRUPT, "timer1", &R)) != 0)		goto free_irq_timer1;#if (EM86XX_CHIP == EM86XX_CHIPID_TANGOLIGHT) || (EM86XX_CHIP == EM86XX_CHIPID_MAMBOLIGHT) || (EM86XX_CHIP == EM86XX_CHIPID_MAMBO)	if ((res = request_irq(IRQ_RTC, dummy_isr, IRQ_FLAGS_INTERRUPT, "rtc", &R)) != 0)		goto free_irq_rtc;#endif#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)	if ((res = request_irq(IRQ_VSYNC0, tango2_vsync_intr, IRQ_FLAGS_INTERRUPT, "vsync0", &R)) != 0)		goto free_irq_vsync0;	if ((res = request_irq(IRQ_VSYNC1, tango2_vsync_intr, IRQ_FLAGS_INTERRUPT, "vsync1", &R)) != 0)		goto free_irq_vsync1;	if ((res = request_irq(IRQ_VSYNC2, tango2_vsync_intr, IRQ_FLAGS_INTERRUPT, "vsync2", &R)) != 0)		goto free_irq_vsync2;	if ((res = request_irq(IRQ_VSYNC3, tango2_vsync_intr, IRQ_FLAGS_INTERRUPT, "vsync3", &R)) != 0)		goto free_irq_vsync3;#endif	res = register_chrdev(major, DIRECT_DEVICE_NAME, &direct_fops);	if (res < 0) {		printk("Cannot register module major=%d for %s\n", major, DIRECT_DEVICE_NAME);#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)free_irq_vsync3:		free_irq(IRQ_VSYNC3, &R);free_irq_vsync2:		free_irq(IRQ_VSYNC2, &R);free_irq_vsync1:		free_irq(IRQ_VSYNC1, &R);free_irq_vsync0:		free_irq(IRQ_VSYNC0, &R);#endif#if (EM86XX_CHIP == EM86XX_CHIPID_TANGOLIGHT) || (EM86XX_CHIP == EM86XX_CHIPID_MAMBOLIGHT) || (EM86XX_CHIP == EM86XX_CHIPID_MAMBO)free_irq_rtc:		free_irq(IRQ_RTC, &R);#endiffree_irq_timer1:		free_irq(IRQ_TIMER1, &R);free_irq_mbus_r1:		free_irq(IRQ_MBUS_R1, &R);free_irq_graphicaccel:		free_irq(IRQ_GRAPHICACCEL, &R);free_irq_mbus_w1:		free_irq(IRQ_MBUS_W1, &R);free_irq_softint:		free_irq(IRQ_SOFTINT, &R);		return res;	}	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) 	/* does nothing if CONFIG_DEVFS_FS is undefined */	R.devfs_handle = devfs_register(NULL, DIRECT_DEVICE_NAME, DEVFS_FL_AUTO_DEVNUM, major, 0,				      S_IFCHR | S_IRUGO | S_IWUGO,				      &direct_fops, NULL);		if (R.devfs_handle == NULL) {		printk("devfs module not registered\n");	}#endif#ifdef WITH_PROC#ifdef WITH_MONITORING        /* Add /proc/driver/mum/ entries */      	add_driver_proc_entry();       	add_driver_proc_files();#endif#endif		return res;}void llad_exit(void){#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)	/* does nothing if CONFIG_DEVFS_FS is undefined */	if (R.devfs_handle != NULL)		devfs_unregister(R.devfs_handle);#endif	unregister_chrdev(major, DIRECT_DEVICE_NAME);	free_irq(IRQ_SOFTINT, &R);	free_irq(IRQ_MBUS_W1, &R);	free_irq(IRQ_GRAPHICACCEL, &R);#if (EM86XX_CHIP == EM86XX_CHIPID_TANGOLIGHT) || (EM86XX_CHIP == EM86XX_CHIPID_MAMBOLIGHT) || (EM86XX_CHIP == EM86XX_CHIPID_MAMBO)	free_irq(IRQ_RTC, &R);#endif	free_irq(IRQ_MBUS_R1, &R);	free_irq(IRQ_TIMER1, &R);#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)	free_irq(IRQ_VSYNC3, &R);	free_irq(IRQ_VSYNC2, &R);	free_irq(IRQ_VSYNC1, &R);	free_irq(IRQ_VSYNC0, &R);#endif	kdmapool_deinit((struct llad *) NULL);#ifdef WITH_PROC#ifdef WITH_MONITORING        /* Add /proc/driver/mum/ entries */      	rm_driver_proc_entry();       	rm_driver_proc_files();#endif#endif	#if (EM86XX_CHIP<EM86XX_CHIPID_TANGO2) && defined WITH_IRQHANDLER_BOOTLOADER	restore_IRQHandler(pGBus);	restore_UNDEFHandler(pGBus);#endif}module_init(llad_init);module_exit(llad_exit);

⌨️ 快捷键说明

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