Misc: phantom, add comment about openhaptics
[safe/jmp/linux-2.6] / drivers / misc / phantom.c
1 /*
2  *  Copyright (C) 2005-2007 Jiri Slaby <jirislaby@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  You need an userspace library to cooperate with this driver. It (and other
10  *  info) may be obtained here:
11  *  http://www.fi.muni.cz/~xslaby/phantom.html
12  *  or alternatively, you might use OpenHaptics provided by Sensable.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/device.h>
18 #include <linux/pci.h>
19 #include <linux/fs.h>
20 #include <linux/poll.h>
21 #include <linux/interrupt.h>
22 #include <linux/cdev.h>
23 #include <linux/phantom.h>
24
25 #include <asm/atomic.h>
26 #include <asm/io.h>
27
28 #define PHANTOM_VERSION         "n0.9.5"
29
30 #define PHANTOM_MAX_MINORS      8
31
32 #define PHN_IRQCTL              0x4c    /* irq control in caddr space */
33
34 #define PHB_RUNNING             1
35
36 static struct class *phantom_class;
37 static int phantom_major;
38
39 struct phantom_device {
40         unsigned int opened;
41         void __iomem *caddr;
42         u32 __iomem *iaddr;
43         u32 __iomem *oaddr;
44         unsigned long status;
45         atomic_t counter;
46
47         wait_queue_head_t wait;
48         struct cdev cdev;
49
50         struct mutex open_lock;
51         spinlock_t ioctl_lock;
52 };
53
54 static unsigned char phantom_devices[PHANTOM_MAX_MINORS];
55
56 static int phantom_status(struct phantom_device *dev, unsigned long newstat)
57 {
58         pr_debug("phantom_status %lx %lx\n", dev->status, newstat);
59
60         if (!(dev->status & PHB_RUNNING) && (newstat & PHB_RUNNING)) {
61                 atomic_set(&dev->counter, 0);
62                 iowrite32(PHN_CTL_IRQ, dev->iaddr + PHN_CONTROL);
63                 iowrite32(0x43, dev->caddr + PHN_IRQCTL);
64                 ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
65         } else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING)) {
66                 iowrite32(0, dev->caddr + PHN_IRQCTL);
67                 ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
68         }
69
70         dev->status = newstat;
71
72         return 0;
73 }
74
75 /*
76  * File ops
77  */
78
79 static long phantom_ioctl(struct file *file, unsigned int cmd,
80                 unsigned long arg)
81 {
82         struct phantom_device *dev = file->private_data;
83         struct phm_regs rs;
84         struct phm_reg r;
85         void __user *argp = (void __user *)arg;
86         unsigned int i;
87
88         if (_IOC_TYPE(cmd) != PH_IOC_MAGIC ||
89                         _IOC_NR(cmd) > PH_IOC_MAXNR)
90                 return -ENOTTY;
91
92         switch (cmd) {
93         case PHN_SET_REG:
94                 if (copy_from_user(&r, argp, sizeof(r)))
95                         return -EFAULT;
96
97                 if (r.reg > 7)
98                         return -EINVAL;
99
100                 spin_lock(&dev->ioctl_lock);
101                 if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) &&
102                                 phantom_status(dev, dev->status | PHB_RUNNING)){
103                         spin_unlock(&dev->ioctl_lock);
104                         return -ENODEV;
105                 }
106
107                 pr_debug("phantom: writing %x to %u\n", r.value, r.reg);
108                 iowrite32(r.value, dev->iaddr + r.reg);
109                 ioread32(dev->iaddr); /* PCI posting */
110
111                 if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ))
112                         phantom_status(dev, dev->status & ~PHB_RUNNING);
113                 spin_unlock(&dev->ioctl_lock);
114                 break;
115         case PHN_SET_REGS:
116                 if (copy_from_user(&rs, argp, sizeof(rs)))
117                         return -EFAULT;
118
119                 pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask);
120                 spin_lock(&dev->ioctl_lock);
121                 for (i = 0; i < min(rs.count, 8U); i++)
122                         if ((1 << i) & rs.mask)
123                                 iowrite32(rs.values[i], dev->oaddr + i);
124                 ioread32(dev->iaddr); /* PCI posting */
125                 spin_unlock(&dev->ioctl_lock);
126                 break;
127         case PHN_GET_REG:
128                 if (copy_from_user(&r, argp, sizeof(r)))
129                         return -EFAULT;
130
131                 if (r.reg > 7)
132                         return -EINVAL;
133
134                 r.value = ioread32(dev->iaddr + r.reg);
135
136                 if (copy_to_user(argp, &r, sizeof(r)))
137                         return -EFAULT;
138                 break;
139         case PHN_GET_REGS:
140                 if (copy_from_user(&rs, argp, sizeof(rs)))
141                         return -EFAULT;
142
143                 pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask);
144                 spin_lock(&dev->ioctl_lock);
145                 for (i = 0; i < min(rs.count, 8U); i++)
146                         if ((1 << i) & rs.mask)
147                                 rs.values[i] = ioread32(dev->iaddr + i);
148                 spin_unlock(&dev->ioctl_lock);
149
150                 if (copy_to_user(argp, &rs, sizeof(rs)))
151                         return -EFAULT;
152                 break;
153         default:
154                 return -ENOTTY;
155         }
156
157         return 0;
158 }
159
160 static int phantom_open(struct inode *inode, struct file *file)
161 {
162         struct phantom_device *dev = container_of(inode->i_cdev,
163                         struct phantom_device, cdev);
164
165         nonseekable_open(inode, file);
166
167         if (mutex_lock_interruptible(&dev->open_lock))
168                 return -ERESTARTSYS;
169
170         if (dev->opened) {
171                 mutex_unlock(&dev->open_lock);
172                 return -EINVAL;
173         }
174
175         file->private_data = dev;
176
177         dev->opened++;
178         mutex_unlock(&dev->open_lock);
179
180         return 0;
181 }
182
183 static int phantom_release(struct inode *inode, struct file *file)
184 {
185         struct phantom_device *dev = file->private_data;
186
187         mutex_lock(&dev->open_lock);
188
189         dev->opened = 0;
190         phantom_status(dev, dev->status & ~PHB_RUNNING);
191
192         mutex_unlock(&dev->open_lock);
193
194         return 0;
195 }
196
197 static unsigned int phantom_poll(struct file *file, poll_table *wait)
198 {
199         struct phantom_device *dev = file->private_data;
200         unsigned int mask = 0;
201
202         pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter));
203         poll_wait(file, &dev->wait, wait);
204         if (atomic_read(&dev->counter)) {
205                 mask = POLLIN | POLLRDNORM;
206                 atomic_dec(&dev->counter);
207         } else if ((dev->status & PHB_RUNNING) == 0)
208                 mask = POLLIN | POLLRDNORM | POLLERR;
209         pr_debug("phantom_poll end: %x/%d\n", mask, atomic_read(&dev->counter));
210
211         return mask;
212 }
213
214 static struct file_operations phantom_file_ops = {
215         .open = phantom_open,
216         .release = phantom_release,
217         .unlocked_ioctl = phantom_ioctl,
218         .poll = phantom_poll,
219 };
220
221 static irqreturn_t phantom_isr(int irq, void *data)
222 {
223         struct phantom_device *dev = data;
224
225         if (!(ioread32(dev->iaddr + PHN_CONTROL) & PHN_CTL_IRQ))
226                 return IRQ_NONE;
227
228         iowrite32(0, dev->iaddr);
229         iowrite32(0xc0, dev->iaddr);
230         ioread32(dev->iaddr); /* PCI posting */
231
232         atomic_inc(&dev->counter);
233         wake_up_interruptible(&dev->wait);
234
235         return IRQ_HANDLED;
236 }
237
238 /*
239  * Init and deinit driver
240  */
241
242 static unsigned int __devinit phantom_get_free(void)
243 {
244         unsigned int i;
245
246         for (i = 0; i < PHANTOM_MAX_MINORS; i++)
247                 if (phantom_devices[i] == 0)
248                         break;
249
250         return i;
251 }
252
253 static int __devinit phantom_probe(struct pci_dev *pdev,
254         const struct pci_device_id *pci_id)
255 {
256         struct phantom_device *pht;
257         unsigned int minor;
258         int retval;
259
260         retval = pci_enable_device(pdev);
261         if (retval)
262                 goto err;
263
264         minor = phantom_get_free();
265         if (minor == PHANTOM_MAX_MINORS) {
266                 dev_err(&pdev->dev, "too many devices found!\n");
267                 retval = -EIO;
268                 goto err_dis;
269         }
270
271         phantom_devices[minor] = 1;
272
273         retval = pci_request_regions(pdev, "phantom");
274         if (retval)
275                 goto err_null;
276
277         retval = -ENOMEM;
278         pht = kzalloc(sizeof(*pht), GFP_KERNEL);
279         if (pht == NULL) {
280                 dev_err(&pdev->dev, "unable to allocate device\n");
281                 goto err_reg;
282         }
283
284         pht->caddr = pci_iomap(pdev, 0, 0);
285         if (pht->caddr == NULL) {
286                 dev_err(&pdev->dev, "can't remap conf space\n");
287                 goto err_fr;
288         }
289         pht->iaddr = pci_iomap(pdev, 2, 0);
290         if (pht->iaddr == NULL) {
291                 dev_err(&pdev->dev, "can't remap input space\n");
292                 goto err_unmc;
293         }
294         pht->oaddr = pci_iomap(pdev, 3, 0);
295         if (pht->oaddr == NULL) {
296                 dev_err(&pdev->dev, "can't remap output space\n");
297                 goto err_unmi;
298         }
299
300         mutex_init(&pht->open_lock);
301         spin_lock_init(&pht->ioctl_lock);
302         init_waitqueue_head(&pht->wait);
303         cdev_init(&pht->cdev, &phantom_file_ops);
304         pht->cdev.owner = THIS_MODULE;
305
306         iowrite32(0, pht->caddr + PHN_IRQCTL);
307         ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
308         retval = request_irq(pdev->irq, phantom_isr,
309                         IRQF_SHARED | IRQF_DISABLED, "phantom", pht);
310         if (retval) {
311                 dev_err(&pdev->dev, "can't establish ISR\n");
312                 goto err_unmo;
313         }
314
315         retval = cdev_add(&pht->cdev, MKDEV(phantom_major, minor), 1);
316         if (retval) {
317                 dev_err(&pdev->dev, "chardev registration failed\n");
318                 goto err_irq;
319         }
320
321         if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major,
322                         minor), "phantom%u", minor)))
323                 dev_err(&pdev->dev, "can't create device\n");
324
325         pci_set_drvdata(pdev, pht);
326
327         return 0;
328 err_irq:
329         free_irq(pdev->irq, pht);
330 err_unmo:
331         pci_iounmap(pdev, pht->oaddr);
332 err_unmi:
333         pci_iounmap(pdev, pht->iaddr);
334 err_unmc:
335         pci_iounmap(pdev, pht->caddr);
336 err_fr:
337         kfree(pht);
338 err_reg:
339         pci_release_regions(pdev);
340 err_null:
341         phantom_devices[minor] = 0;
342 err_dis:
343         pci_disable_device(pdev);
344 err:
345         return retval;
346 }
347
348 static void __devexit phantom_remove(struct pci_dev *pdev)
349 {
350         struct phantom_device *pht = pci_get_drvdata(pdev);
351         unsigned int minor = MINOR(pht->cdev.dev);
352
353         device_destroy(phantom_class, MKDEV(phantom_major, minor));
354
355         cdev_del(&pht->cdev);
356
357         iowrite32(0, pht->caddr + PHN_IRQCTL);
358         ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
359         free_irq(pdev->irq, pht);
360
361         pci_iounmap(pdev, pht->oaddr);
362         pci_iounmap(pdev, pht->iaddr);
363         pci_iounmap(pdev, pht->caddr);
364
365         kfree(pht);
366
367         pci_release_regions(pdev);
368
369         phantom_devices[minor] = 0;
370
371         pci_disable_device(pdev);
372 }
373
374 #ifdef CONFIG_PM
375 static int phantom_suspend(struct pci_dev *pdev, pm_message_t state)
376 {
377         struct phantom_device *dev = pci_get_drvdata(pdev);
378
379         iowrite32(0, dev->caddr + PHN_IRQCTL);
380         ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
381
382         synchronize_irq(pdev->irq);
383
384         return 0;
385 }
386
387 static int phantom_resume(struct pci_dev *pdev)
388 {
389         struct phantom_device *dev = pci_get_drvdata(pdev);
390
391         iowrite32(0, dev->caddr + PHN_IRQCTL);
392
393         return 0;
394 }
395 #else
396 #define phantom_suspend NULL
397 #define phantom_resume  NULL
398 #endif
399
400 static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
401         { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050),
402                 .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
403         { 0, }
404 };
405 MODULE_DEVICE_TABLE(pci, phantom_pci_tbl);
406
407 static struct pci_driver phantom_pci_driver = {
408         .name = "phantom",
409         .id_table = phantom_pci_tbl,
410         .probe = phantom_probe,
411         .remove = __devexit_p(phantom_remove),
412         .suspend = phantom_suspend,
413         .resume = phantom_resume
414 };
415
416 static ssize_t phantom_show_version(struct class *cls, char *buf)
417 {
418         return sprintf(buf, PHANTOM_VERSION "\n");
419 }
420
421 static CLASS_ATTR(version, 0444, phantom_show_version, NULL);
422
423 static int __init phantom_init(void)
424 {
425         int retval;
426         dev_t dev;
427
428         phantom_class = class_create(THIS_MODULE, "phantom");
429         if (IS_ERR(phantom_class)) {
430                 retval = PTR_ERR(phantom_class);
431                 printk(KERN_ERR "phantom: can't register phantom class\n");
432                 goto err;
433         }
434         retval = class_create_file(phantom_class, &class_attr_version);
435         if (retval) {
436                 printk(KERN_ERR "phantom: can't create sysfs version file\n");
437                 goto err_class;
438         }
439
440         retval = alloc_chrdev_region(&dev, 0, PHANTOM_MAX_MINORS, "phantom");
441         if (retval) {
442                 printk(KERN_ERR "phantom: can't register character device\n");
443                 goto err_attr;
444         }
445         phantom_major = MAJOR(dev);
446
447         retval = pci_register_driver(&phantom_pci_driver);
448         if (retval) {
449                 printk(KERN_ERR "phantom: can't register pci driver\n");
450                 goto err_unchr;
451         }
452
453         printk(KERN_INFO "Phantom Linux Driver, version " PHANTOM_VERSION ", "
454                         "init OK\n");
455
456         return 0;
457 err_unchr:
458         unregister_chrdev_region(dev, PHANTOM_MAX_MINORS);
459 err_attr:
460         class_remove_file(phantom_class, &class_attr_version);
461 err_class:
462         class_destroy(phantom_class);
463 err:
464         return retval;
465 }
466
467 static void __exit phantom_exit(void)
468 {
469         pci_unregister_driver(&phantom_pci_driver);
470
471         unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS);
472
473         class_remove_file(phantom_class, &class_attr_version);
474         class_destroy(phantom_class);
475
476         pr_debug("phantom: module successfully removed\n");
477 }
478
479 module_init(phantom_init);
480 module_exit(phantom_exit);
481
482 MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>");
483 MODULE_DESCRIPTION("Sensable Phantom driver");
484 MODULE_LICENSE("GPL");
485 MODULE_VERSION(PHANTOM_VERSION);