dhahelper.c

来自「linux下的MPEG1」· C语言 代码 · 共 1,240 行 · 第 1/3 页

C
1,240
字号
	if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	nitems = mem.length / PAGE_SIZE;	if(mem.length % PAGE_SIZE) nitems++;	addr = mem.virtaddr;	for(i=0;i<nitems;i++)	{	    unsigned long result;	    result = uvirt_to_pa((unsigned long)addr);	    if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))	    {		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy to userspace\n");		return -EFAULT;	    }	    addr += PAGE_SIZE;	}	return 0;}static int dhahelper_virt_to_bus(dhahelper_vmi_t *arg){	dhahelper_vmi_t mem;	unsigned long i,nitems;	char *addr;	if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	nitems = mem.length / PAGE_SIZE;	if(mem.length % PAGE_SIZE) nitems++;	addr = mem.virtaddr;	for(i=0;i<nitems;i++)	{	    unsigned long result;	    result = uvirt_to_bus((unsigned long)addr);	    if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))	    {		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy to userspace\n");		return -EFAULT;	    }	    addr += PAGE_SIZE;	}	return 0;}static int dhahelper_alloc_pa(dhahelper_mem_t *arg){	dhahelper_mem_t mem;	if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	mem.addr = rvmalloc(mem.length);	if (copy_to_user(arg, &mem, sizeof(dhahelper_mem_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy to userspace\n");		return -EFAULT;	}	return 0;}static int dhahelper_free_pa(dhahelper_mem_t *arg){	dhahelper_mem_t mem;	if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	rvfree(mem.addr,mem.length);	return 0;}static int dhahelper_lock_mem(dhahelper_mem_t *arg){	dhahelper_mem_t mem;	int retval;	unsigned long i,nitems,addr;	if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	nitems = mem.length / PAGE_SIZE;	if(mem.length % PAGE_SIZE) nitems++;	addr = (unsigned long)mem.addr;	for(i=0;i<nitems;i++)	{	    retval = pag_lock((unsigned long)addr);	    if(retval)	    {		unsigned long j;		addr = (unsigned long)mem.addr;		for(j=0;j<i;j++)		{		    pag_unlock(addr);		    addr +=  PAGE_SIZE;		}		return retval;	    }	    addr += PAGE_SIZE;	}	return 0;}static int dhahelper_unlock_mem(dhahelper_mem_t *arg){	dhahelper_mem_t mem;	int retval;	unsigned long i,nitems,addr;	if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	nitems = mem.length / PAGE_SIZE;	if(mem.length % PAGE_SIZE) nitems++;	addr = (unsigned long)mem.addr;	for(i=0;i<nitems;i++)	{	    retval = pag_unlock((unsigned long)addr);	    if(retval) return retval;	    addr += PAGE_SIZE;	}	return 0;}static struct dha_irq {    spinlock_t lock;    unsigned long flags;    int handled;    int rcvd;    volatile u32 *ack_addr;    u32 ack_data;    struct pci_dev *dev;    wait_queue_head_t wait;    unsigned long count;} dha_irqs[256];static irqreturn_t dhahelper_irq_handler(int irq, void *dev_id,					 struct pt_regs *regs){    spin_lock_irqsave(&dha_irqs[irq].lock, dha_irqs[irq].flags);    if(dha_irqs[irq].handled){	dha_irqs[irq].rcvd = 1;	dha_irqs[irq].count++;	if(dha_irqs[irq].ack_addr){	    *dha_irqs[irq].ack_addr = dha_irqs[irq].ack_data;	    mb();	}	wake_up_interruptible(&dha_irqs[irq].wait);    }    spin_unlock_irqrestore(&dha_irqs[irq].lock, dha_irqs[irq].flags);    irqreturn(0);}static int dhahelper_install_irq(dhahelper_irq_t *arg){    dhahelper_irq_t my_irq;    struct pci_dev *pci;    long rlen;    int retval;    long ack_addr;    int irqn;    if (copy_from_user(&my_irq, arg, sizeof(dhahelper_irq_t)))    {	if (dhahelper_verbosity > 0)	    printk(KERN_ERR "dhahelper: failed copy from userspace\n");	return -EFAULT;    }    if(!(pci = pci_find_slot(my_irq.bus, PCI_DEVFN(my_irq.dev, my_irq.func))))	return -EINVAL;    rlen = pci_resource_len(pci, my_irq.ack_region);    if(my_irq.ack_offset > rlen - 4)	return -EINVAL;    irqn = pci->irq;    spin_lock_irqsave(&dha_irqs[irqn].lock,		      dha_irqs[irqn].flags);    if(dha_irqs[irqn].handled){	retval = -EBUSY;	goto fail;    }    if(my_irq.ack_region >= 0){	ack_addr = pci_resource_start(pci, my_irq.ack_region);	ack_addr += my_irq.ack_offset;#ifdef CONFIG_ALPHA	ack_addr += ((struct pci_controller *) pci->sysdata)->dense_mem_base;#endif	/* FIXME:  Other architectures */	dha_irqs[irqn].ack_addr = phys_to_virt(ack_addr);	dha_irqs[irqn].ack_data = my_irq.ack_data;    } else {	dha_irqs[irqn].ack_addr = 0;    }    dha_irqs[irqn].lock = SPIN_LOCK_UNLOCKED;    dha_irqs[irqn].flags = 0;    dha_irqs[irqn].rcvd = 0;    dha_irqs[irqn].dev = pci;    init_waitqueue_head(&dha_irqs[irqn].wait);    dha_irqs[irqn].count = 0;    retval = request_irq(irqn, dhahelper_irq_handler,			 SA_SHIRQ, "dhahelper", pci);    if(retval < 0)	goto fail;    copy_to_user(&arg->num, &irqn, sizeof(irqn));    dha_irqs[irqn].handled = 1;out:    spin_unlock_irqrestore(&dha_irqs[irqn].lock,			   dha_irqs[irqn].flags);    return retval;fail:    if(retval == -EINVAL){	printk("dhahelper: bad irq number or handler\n");    } else if(retval == -EBUSY){	printk("dhahelper: IRQ %u busy\n", irqn);    } else {	printk("dhahelper: Could not install irq handler...\n");    }    printk("dhahelper: Perhaps you need to let your BIOS assign an IRQ to your video card\n");    goto out;}static int dhahelper_free_irq(dhahelper_irq_t *arg){	dhahelper_irq_t irq;	struct pci_dev *pci;	int irqn;	if (copy_from_user(&irq, arg, sizeof(dhahelper_irq_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	pci = pci_find_slot(irq.bus, PCI_DEVFN(irq.dev, irq.func));	if(!pci)	    return -EINVAL;	irqn = pci->irq;	spin_lock_irqsave(&dha_irqs[irqn].lock, dha_irqs[irqn].flags);	if(dha_irqs[irqn].handled) {		free_irq(irqn, pci);		dha_irqs[irqn].handled = 0;		printk("IRQ %i: %li\n", irqn, dha_irqs[irqn].count);	}	spin_unlock_irqrestore(&dha_irqs[irqn].lock, dha_irqs[irqn].flags);	return 0;}static int dhahelper_ack_irq(dhahelper_irq_t *arg){	dhahelper_irq_t irq;	int retval = 0;	DECLARE_WAITQUEUE(wait, current);	if (copy_from_user(&irq, arg, sizeof(dhahelper_irq_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	if(irq.num > 255) return -EINVAL;	if(!dha_irqs[irq.num].handled) return -ESRCH;	add_wait_queue(&dha_irqs[irq.num].wait, &wait);	set_current_state(TASK_INTERRUPTIBLE);	for(;;){		int r;		spin_lock_irqsave(&dha_irqs[irq.num].lock,				  dha_irqs[irq.num].flags);		r = dha_irqs[irq.num].rcvd;		spin_unlock_irqrestore(&dha_irqs[irq.num].lock,				       dha_irqs[irq.num].flags);		if(r){			dha_irqs[irq.num].rcvd = 0;			break;		}		if(signal_pending(current)){			retval = -ERESTARTSYS;			break;		}		schedule();	}	set_current_state(TASK_RUNNING);	remove_wait_queue(&dha_irqs[irq.num].wait, &wait);		return retval;}static int dhahelper_cpu_flush(dhahelper_cpu_flush_t *arg){	dhahelper_cpu_flush_t my_l2;	if (copy_from_user(&my_l2, arg, sizeof(dhahelper_cpu_flush_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}#if defined(__i386__)	/* WBINVD writes all modified cache lines back to main memory */	if(boot_cpu_data.x86 > 3) { __asm __volatile("wbinvd":::"memory"); }#else	/* FIXME!!!*/	mb(); /* declared in "asm/system.h" */#endif	return 0;}static struct pci_dev *pdev = NULL;static int dhahelper_pci_find(dhahelper_pci_device_t *arg){	dhahelper_pci_device_t this_dev;	pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev);	if(pdev)	{	    this_dev.bus = pdev->bus->number;	    this_dev.card = PCI_SLOT(pdev->devfn);	    this_dev.func = PCI_FUNC(pdev->devfn);	    this_dev.vendor = pdev->vendor;	    this_dev.device = pdev->device;	    this_dev.base0 = pci_resource_start (pdev, 0);	    this_dev.base1 = pci_resource_start (pdev, 1);	    this_dev.base2 = pci_resource_start (pdev, 2);	    pci_read_config_dword(pdev, pdev->rom_base_reg, (u32*)&this_dev.baserom);	    this_dev.base3 = pci_resource_start (pdev, 3);	    this_dev.base4 = pci_resource_start (pdev, 4);	    this_dev.base5 = pci_resource_start (pdev, 5);	    pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &this_dev.irq);	    pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &this_dev.ipin);	    pci_read_config_byte(pdev, PCI_MIN_GNT, &this_dev.gnt);	    pci_read_config_byte(pdev, PCI_MAX_LAT, &this_dev.lat);	}	else memset(&this_dev,0,sizeof(dhahelper_pci_device_t));	if (copy_to_user(arg, &this_dev, sizeof(dhahelper_pci_device_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy to userspace\n");		return -EFAULT;	}	return pdev?0:-ENODATA;}static int dhahelper_pci_config(dhahelper_pci_config_t *arg){    dhahelper_pci_config_t op;    struct pci_dev *pdev;	if (copy_from_user(&op, arg, sizeof(dhahelper_pci_config_t)))	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: failed copy from userspace\n");		return -EFAULT;	}	pdev = pci_find_slot(op.bus,PCI_DEVFN(op.dev,op.func));	if(!pdev)	{		if (dhahelper_verbosity > 0)		    printk(KERN_ERR "dhahelper: can't identify device\n");		return -EFAULT;	}	switch(op.operation)	{	    case PCI_OP_READ:		switch(op.size)		{		    case 1:			pci_read_config_byte(pdev,op.cmd,(u8*)&op.ret);			break;		    case 2:			pci_read_config_word(pdev,op.cmd,(u16*)&op.ret);			break;		    case 4:			pci_read_config_dword(pdev,op.cmd,(u32*)&op.ret);			break;		    default:			if (dhahelper_verbosity > 0)			    printk(KERN_ERR "dhahelper: wrong size of pci operation: %u \n",op.size);			return -EFAULT;		}	    case PCI_OP_WRITE:		switch(op.size)		{		    case 1:

⌨️ 快捷键说明

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