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

📄 galil_1800.c

📁 galil1800 linux驱动程序演示
💻 C
📖 第 1 页 / 共 2 页
字号:
    read_unlock(&dev->siglock);    spin_lock_irqsave(&dev->irqlock, flags);    if (sz < dev->irqstack_sz)    	for (i=0; i<dev->irqstack_sz-sz; ++i)            dev->irqstack[i] = dev->irqstack[i+sz];    dev->irqstack_sz -= sz;    spin_unlock_irqrestore(&dev->irqlock, flags);    }static int galil_1800_del_from_siglist(struct galil_1800_state *dev,                                        struct task_struct *task){    struct list_head *list;    struct list_head *head = &dev->siglist;    struct galil_1800_siglist_t *elem;    unsigned long flags;    write_lock_irqsave(&dev->siglock, flags);    list_for_each(list, head) {        elem = list_entry(list, struct galil_1800_siglist_t, list);         if (elem->owner == task)            break;    }    if (list == head) {        write_unlock_irqrestore(&dev->siglock, flags);        return -ESRCH;    }    if (task->pid != elem->owner->pid) {    	printk(KERN_WARNING PFX "bad PID (%d) in the signaling process list\n",                	elem->owner->pid);        return -EFAULT;    }        list_del(list);    write_unlock_irqrestore(&dev->siglock, flags);    kfree(elem);    printk(KERN_INFO PFX "deregistered PID %d for device #%d\n",            task->pid, dev->index);    return 0;}static int galil_1800_add_to_siglist(struct galil_1800_state *dev,                                      char * userbuf, struct task_struct *task){    struct list_head *list;    struct list_head *head = &dev->siglist;    struct galil_1800_siglist_t *elem;    unsigned long flags;        if (!userbuf)        return -EINVAL;    write_lock_irqsave(&dev->siglock, flags);        list_for_each(list, head)        if (list_entry(list,struct galil_1800_siglist_t,list)->owner==task) {             write_unlock_irqrestore(&dev->siglock, flags);            printk(KERN_INFO PFX "PID %d already registered for device #%d\n",                    task->pid, dev->index);            return -EINVAL;        }            elem = kmalloc(sizeof(struct galil_1800_siglist_t), GFP_ATOMIC);    if (!elem) {         printk(KERN_ERR PFX "cannot allocate memory\n");        return -ENOMEM;       }    elem->owner = task;    elem->pid = task->pid;    elem->ubuf = userbuf;    list_add(&elem->list, head);    write_unlock_irqrestore(&dev->siglock, flags);    printk(KERN_INFO PFX "registered PID %d for device #%d\n",            task->pid, dev->index);    return 0;}static ssize_t galil_1800_read(struct file * filp, char * buf, size_t size,                                 loff_t *poff){    struct galil_1800_state *dev =             (struct galil_1800_state *) filp->private_data;    char _buf[GALIL_1800_READ_FIFO_SIZE], *p = _buf;    ssize_t count;    ssize_t request = (size < GALIL_1800_READ_FIFO_SIZE ?                                    size : GALIL_1800_READ_FIFO_SIZE);    int rc;        for (count = 0; count < request && galil_1800_may_read(dev); ++count)               *p++ = inb(GALIL_1800_READ_REG(dev));    if (!count)        return 0;    rc = copy_to_user(buf, _buf, count);    return (rc > 0 ? -EFAULT : count);}static ssize_t galil_1800_write(struct file * filp, const char * buf,                                 size_t size, loff_t *poff){    struct galil_1800_state *dev =             (struct galil_1800_state *) filp->private_data;    char _buf[GALIL_1800_WRITE_FIFO_SIZE], *p = _buf;    ssize_t count;    ssize_t request = (size < GALIL_1800_WRITE_FIFO_SIZE ?                                    size : GALIL_1800_WRITE_FIFO_SIZE);    int rc, written = 0;    if (!request)        return 0;        if (!buf)      	return -EINVAL;        rc = copy_from_user(_buf, buf, request);    if (rc)        return -EFAULT;        rc = request;    if (galil_1800_may_write(dev) == 2) {                /* write in burst mode */                if (rc > GALIL_1800_WRITE_FIFO_SIZE / 2) {            request = GALIL_1800_WRITE_FIFO_SIZE / 2;            rc -= GALIL_1800_WRITE_FIFO_SIZE / 2;        } else {            request = rc;            rc = 0;        }                    for (count = 0; count < request; ++count, ++p)            outb_p(*p, GALIL_1800_WRITE_REG(dev));        written = request;    }          for (count = 0; count < rc && galil_1800_may_write(dev); ++count, p++)        outb(*p, GALIL_1800_WRITE_REG(dev));    return count+written;}static int galil_1800_open(struct inode * inode, struct file * file){    int minor = MINOR(inode->i_rdev);    DECLARE_WAITQUEUE(wait, current);    struct list_head *list;    struct galil_1800_state *s;    read_lock(&galil_1800_devs_lock);    list_for_each(list, &galil_1800_devs) {        s = list_entry(list, struct galil_1800_state, devs);        if (!((s->index ^ minor) & ~0xf))            break;    }    read_unlock(&galil_1800_devs_lock);    if (list == &galil_1800_devs)        return -ENODEV;            file->private_data = s;        /* wait for device to become free */    down(&s->open_sem);    while (s->open_mode & file->f_mode) {        if (file->f_flags & O_NONBLOCK) {            up(&s->open_sem);            return -EBUSY;        }        add_wait_queue(&s->open_wait, &wait);        __set_current_state(TASK_INTERRUPTIBLE);        up(&s->open_sem);        schedule();        remove_wait_queue(&s->open_wait, &wait);        set_current_state(TASK_RUNNING);        if (signal_pending(current))            return -ERESTARTSYS;        down(&s->open_sem);    }    s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);    	if (++s->opens == 1) {	    galil_1800_clear_FIFO(s, 0);    	galil_1800_enable_IRQ(s);    }    up(&s->open_sem);        return 0;}static int galil_1800_release(struct inode * inode, struct file * file){    struct galil_1800_state *s =     	(struct galil_1800_state *) file->private_data;    down(&s->open_sem);    if (!--s->opens) {	    galil_1800_disable_IRQ(s);    	galil_1800_clear_FIFO(s, 0);    }        galil_1800_del_from_siglist(s, current);    s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);    up(&s->open_sem);        wake_up(&s->open_wait);    return 0;}static int galil_1800_ioctl(struct inode *inode, struct file *file,                             unsigned int cmd, unsigned long arg){    struct galil_1800_state *dev =         (struct galil_1800_state *) file->private_data;    switch (cmd) {          case GALIL_CLEAR_FIFO:            galil_1800_clear_FIFO(dev, arg);            return 0;                    case GALIL_MAY_READ:            return galil_1800_may_read(dev);                    case GALIL_MAY_WRITE:            return galil_1800_may_write(dev);                    case GALIL_GET_SERIAL_NUMBER:            {#define SN_BUF_SIZE 256                char buf[SN_BUF_SIZE];                int rc = galil_1800_get_serial_number(dev, buf);                return (rc < 0 ?                           rc : copy_to_user((void *)arg, buf, strlen(buf)) ?                              -EFAULT : 0);#undef SN_BUF_SIZE            }        case GALIL_SIGNAL_INTERRUPTS:            if ((char *) arg == NULL)                return galil_1800_del_from_siglist(dev, current);            else                return galil_1800_add_to_siglist(dev, (char *) arg, current);            break;        case  GALIL_GET_IRQ_STACK:           {               int rc =  copy_to_user((void *) arg, dev->irqstack,                                GALIL_1800_IRQ_STACK_SZ*sizeof(dev->irqstack[0]));                if (!rc)                       return -EFAULT;                rc = dev->irqstack_sz;                dev->irqstack_sz = 0;                return rc;           }           break;        case GALIL_READ_2ND_FIFO:            {                char buf[GALIL_1800_READ_FIFO2_SIZE];                int n = galil_1800_read_FIFO2(dev, buf,                                               GALIL_1800_READ_FIFO2_SIZE);                if (!n)                    return 0;                return (copy_to_user((void *)arg, buf, n) ? -EFAULT : n);            }			break;                }    return -EINVAL;}/* module/hotplug stuff */static int __devinit galil_1800_probe(struct pci_dev *pcidev,                                       const struct pci_device_id *devid){    struct galil_1800_state *s;        if (pcidev->irq == 0)         return -1;    if (!(s = kmalloc(sizeof(struct galil_1800_state), GFP_KERNEL))) {        printk(KERN_ERR PFX "alloc of galil_1800_state struct failed\n");        return -1;    }    memset(s, 0, sizeof(struct galil_1800_state));        init_waitqueue_head(&s->open_wait);    init_MUTEX(&s->open_sem);    spin_lock_init(&s->hwlock);    spin_lock_init(&s->irqlock);    rwlock_init(&s->siglock);    INIT_LIST_HEAD(&s->siglist);    tasklet_init(&s->tlet, galil_1800_send_signals, (unsigned long) s);    s->index = devindex;    s->dev = pcidev;    s->io = pci_resource_start(pcidev, 2);    s->ctrl_reg = s->io + 4;    s->irq_reg = s->io + 8;    s->chan2_reg = s->io + 12;    s->irq = pcidev->irq;    s->irqstack_sz = 0;    	s->opens = 0;        if (!request_region(s->io, pci_resource_len(pcidev,2),                GALIL_1800_MODULE_NAME)) {        printk(KERN_ERR PFX "io ports %#lx->%#lx in use\n",               s->io, s->io + pci_resource_len(pcidev,2)-1);        goto err_region;    }    if (request_irq(s->irq, galil_1800_interrupt, SA_SHIRQ,            GALIL_1800_MODULE_NAME, s)) {        printk(KERN_ERR PFX "irq %u in use\n", s->irq);        goto err_irq;    }    printk(KERN_INFO PFX "device #%d, base I/O: 0x%lx, IRQ: %d\n",              s->index, s->io, s->irq);                if (pci_enable_device(pcidev))        goto err_pci;         pci_set_drvdata(pcidev, s);    /* pcidev->dma_mask = 0xffffffff; */    /* put it into driver list */    write_lock(&galil_1800_devs_lock);         list_add_tail(&s->devs, &galil_1800_devs);    write_unlock(&galil_1800_devs_lock);        devindex++;    return 0; err_pci:    printk(KERN_ERR PFX "cannot enable PCI device\n");    free_irq(s->irq, s); err_irq:    release_region(s->io, pci_resource_len(pcidev,2)); err_region:    kfree(s);    return -1;}static void __devexit galil_1800_remove(struct pci_dev *dev){    struct galil_1800_state *s = pci_get_drvdata(dev);    if (!s)        return;    write_lock(&galil_1800_devs_lock);    list_del(&s->devs);    write_unlock(&galil_1800_devs_lock);        synchronize_irq();    free_irq(s->irq, s);    release_region(s->io, pci_resource_len(dev,2));    kfree(s);    pci_set_drvdata(dev, NULL);  }static struct __devinitdata pci_device_id galil_1800_idtable[] = {    {  vendor: PLX_PCI_VENDOR_ID,        device: PLX_PCI_DEVICE_ID,        subvendor: GALIL_SUB_VENDOR,        subdevice: GALIL_SUB_DEVICE_1800,        class: 0,       class_mask: 0,        driver_data: 0 },    { 0,  }};static struct pci_driver galil_1800_driver  = {    name: GALIL_1800_MODULE_NAME,    id_table: galil_1800_idtable,    probe: galil_1800_probe,    remove: __devexit_p(galil_1800_remove),    save_state: NULL,    suspend: NULL,    resume: NULL,    enable_wake: NULL};static struct file_operations galil_1800_fops = {  read:    galil_1800_read,  write:   galil_1800_write,  ioctl:   galil_1800_ioctl,  open:    galil_1800_open,  release: galil_1800_release};static int __init galil_1800_init(void){    int rc, maj;    rc = pci_module_init(&galil_1800_driver);    if (rc == -ENODEV) {        printk(KERN_INFO PFX "no Galil 1800 device was found\n");        return rc;    }    if (rc) {        printk(KERN_ERR PFX "cannot register the device driver\n");        return rc;    }        maj = (major != -1 ? major : 0);    rc = register_chrdev(maj, GALIL_1800_MODULE_NAME, &galil_1800_fops);    if (rc < 0) {        printk(KERN_ERR PFX "cannot register the device files\n");        pci_unregister_driver(&galil_1800_driver);        return 1;    }    major = (rc == 0 ? maj : rc);    SET_MODULE_OWNER(&galil_1800_fops);    printk(KERN_INFO PFX "module loaded\n");    return 0;}static void __exit galil_1800_cleanup(void){    unregister_chrdev(major, GALIL_1800_MODULE_NAME);    pci_unregister_driver(&galil_1800_driver);    printk(KERN_INFO PFX "module unloaded\n");        }/* __setup("galil_1800=", galil_1800_setup); */module_init(galil_1800_init);module_exit(galil_1800_cleanup);MODULE_AUTHOR("Shell Technologies s.r.l. (M. Cesati)");MODULE_DESCRIPTION("Galil 1800 Motion Controller Driver");MODULE_LICENSE("GPL");MODULE_PARM(major,"i");MODULE_PARM_DESC(major, "Major number of the device file");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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