phantom.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  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. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/device.h>
  16. #include <linux/pci.h>
  17. #include <linux/fs.h>
  18. #include <linux/poll.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/cdev.h>
  21. #include <linux/phantom.h>
  22. #include <asm/atomic.h>
  23. #include <asm/io.h>
  24. #define PHANTOM_VERSION "n0.9.5"
  25. #define PHANTOM_MAX_MINORS 8
  26. #define PHN_IRQCTL 0x4c /* irq control in caddr space */
  27. #define PHB_RUNNING 1
  28. static struct class *phantom_class;
  29. static int phantom_major;
  30. struct phantom_device {
  31. unsigned int opened;
  32. void __iomem *caddr;
  33. u32 __iomem *iaddr;
  34. u32 __iomem *oaddr;
  35. unsigned long status;
  36. atomic_t counter;
  37. wait_queue_head_t wait;
  38. struct cdev cdev;
  39. struct mutex open_lock;
  40. spinlock_t ioctl_lock;
  41. };
  42. static unsigned char phantom_devices[PHANTOM_MAX_MINORS];
  43. static int phantom_status(struct phantom_device *dev, unsigned long newstat)
  44. {
  45. pr_debug("phantom_status %lx %lx\n", dev->status, newstat);
  46. if (!(dev->status & PHB_RUNNING) && (newstat & PHB_RUNNING)) {
  47. atomic_set(&dev->counter, 0);
  48. iowrite32(PHN_CTL_IRQ, dev->iaddr + PHN_CONTROL);
  49. iowrite32(0x43, dev->caddr + PHN_IRQCTL);
  50. ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
  51. } else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING)) {
  52. iowrite32(0, dev->caddr + PHN_IRQCTL);
  53. ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
  54. }
  55. dev->status = newstat;
  56. return 0;
  57. }
  58. /*
  59. * File ops
  60. */
  61. static long phantom_ioctl(struct file *file, unsigned int cmd,
  62. unsigned long arg)
  63. {
  64. struct phantom_device *dev = file->private_data;
  65. struct phm_regs rs;
  66. struct phm_reg r;
  67. void __user *argp = (void __user *)arg;
  68. unsigned int i;
  69. if (_IOC_TYPE(cmd) != PH_IOC_MAGIC ||
  70. _IOC_NR(cmd) > PH_IOC_MAXNR)
  71. return -ENOTTY;
  72. switch (cmd) {
  73. case PHN_SET_REG:
  74. if (copy_from_user(&r, argp, sizeof(r)))
  75. return -EFAULT;
  76. if (r.reg > 7)
  77. return -EINVAL;
  78. spin_lock(&dev->ioctl_lock);
  79. if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) &&
  80. phantom_status(dev, dev->status | PHB_RUNNING)){
  81. spin_unlock(&dev->ioctl_lock);
  82. return -ENODEV;
  83. }
  84. pr_debug("phantom: writing %x to %u\n", r.value, r.reg);
  85. iowrite32(r.value, dev->iaddr + r.reg);
  86. ioread32(dev->iaddr); /* PCI posting */
  87. if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ))
  88. phantom_status(dev, dev->status & ~PHB_RUNNING);
  89. spin_unlock(&dev->ioctl_lock);
  90. break;
  91. case PHN_SET_REGS:
  92. if (copy_from_user(&rs, argp, sizeof(rs)))
  93. return -EFAULT;
  94. pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask);
  95. spin_lock(&dev->ioctl_lock);
  96. for (i = 0; i < min(rs.count, 8U); i++)
  97. if ((1 << i) & rs.mask)
  98. iowrite32(rs.values[i], dev->oaddr + i);
  99. ioread32(dev->iaddr); /* PCI posting */
  100. spin_unlock(&dev->ioctl_lock);
  101. break;
  102. case PHN_GET_REG:
  103. if (copy_from_user(&r, argp, sizeof(r)))
  104. return -EFAULT;
  105. if (r.reg > 7)
  106. return -EINVAL;
  107. r.value = ioread32(dev->iaddr + r.reg);
  108. if (copy_to_user(argp, &r, sizeof(r)))
  109. return -EFAULT;
  110. break;
  111. case PHN_GET_REGS:
  112. if (copy_from_user(&rs, argp, sizeof(rs)))
  113. return -EFAULT;
  114. pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask);
  115. spin_lock(&dev->ioctl_lock);
  116. for (i = 0; i < min(rs.count, 8U); i++)
  117. if ((1 << i) & rs.mask)
  118. rs.values[i] = ioread32(dev->iaddr + i);
  119. spin_unlock(&dev->ioctl_lock);
  120. if (copy_to_user(argp, &rs, sizeof(rs)))
  121. return -EFAULT;
  122. break;
  123. default:
  124. return -ENOTTY;
  125. }
  126. return 0;
  127. }
  128. static int phantom_open(struct inode *inode, struct file *file)
  129. {
  130. struct phantom_device *dev = container_of(inode->i_cdev,
  131. struct phantom_device, cdev);
  132. nonseekable_open(inode, file);
  133. if (mutex_lock_interruptible(&dev->open_lock))
  134. return -ERESTARTSYS;
  135. if (dev->opened) {
  136. mutex_unlock(&dev->open_lock);
  137. return -EINVAL;
  138. }
  139. file->private_data = dev;
  140. dev->opened++;
  141. mutex_unlock(&dev->open_lock);
  142. return 0;
  143. }
  144. static int phantom_release(struct inode *inode, struct file *file)
  145. {
  146. struct phantom_device *dev = file->private_data;
  147. mutex_lock(&dev->open_lock);
  148. dev->opened = 0;
  149. phantom_status(dev, dev->status & ~PHB_RUNNING);
  150. mutex_unlock(&dev->open_lock);
  151. return 0;
  152. }
  153. static unsigned int phantom_poll(struct file *file, poll_table *wait)
  154. {
  155. struct phantom_device *dev = file->private_data;
  156. unsigned int mask = 0;
  157. pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter));
  158. poll_wait(file, &dev->wait, wait);
  159. if (atomic_read(&dev->counter)) {
  160. mask = POLLIN | POLLRDNORM;
  161. atomic_dec(&dev->counter);
  162. } else if ((dev->status & PHB_RUNNING) == 0)
  163. mask = POLLIN | POLLRDNORM | POLLERR;
  164. pr_debug("phantom_poll end: %x/%d\n", mask, atomic_read(&dev->counter));
  165. return mask;
  166. }
  167. static struct file_operations phantom_file_ops = {
  168. .open = phantom_open,
  169. .release = phantom_release,
  170. .unlocked_ioctl = phantom_ioctl,
  171. .poll = phantom_poll,
  172. };
  173. static irqreturn_t phantom_isr(int irq, void *data)
  174. {
  175. struct phantom_device *dev = data;
  176. if (!(ioread32(dev->iaddr + PHN_CONTROL) & PHN_CTL_IRQ))
  177. return IRQ_NONE;
  178. iowrite32(0, dev->iaddr);
  179. iowrite32(0xc0, dev->iaddr);
  180. ioread32(dev->iaddr); /* PCI posting */
  181. atomic_inc(&dev->counter);
  182. wake_up_interruptible(&dev->wait);
  183. return IRQ_HANDLED;
  184. }
  185. /*
  186. * Init and deinit driver
  187. */
  188. static unsigned int __devinit phantom_get_free(void)
  189. {
  190. unsigned int i;
  191. for (i = 0; i < PHANTOM_MAX_MINORS; i++)
  192. if (phantom_devices[i] == 0)
  193. break;
  194. return i;
  195. }
  196. static int __devinit phantom_probe(struct pci_dev *pdev,
  197. const struct pci_device_id *pci_id)
  198. {
  199. struct phantom_device *pht;
  200. unsigned int minor;
  201. int retval;
  202. retval = pci_enable_device(pdev);
  203. if (retval)
  204. goto err;
  205. minor = phantom_get_free();
  206. if (minor == PHANTOM_MAX_MINORS) {
  207. dev_err(&pdev->dev, "too many devices found!\n");
  208. retval = -EIO;
  209. goto err_dis;
  210. }
  211. phantom_devices[minor] = 1;
  212. retval = pci_request_regions(pdev, "phantom");
  213. if (retval)
  214. goto err_null;
  215. retval = -ENOMEM;
  216. pht = kzalloc(sizeof(*pht), GFP_KERNEL);
  217. if (pht == NULL) {
  218. dev_err(&pdev->dev, "unable to allocate device\n");
  219. goto err_reg;
  220. }
  221. pht->caddr = pci_iomap(pdev, 0, 0);
  222. if (pht->caddr == NULL) {
  223. dev_err(&pdev->dev, "can't remap conf space\n");
  224. goto err_fr;
  225. }
  226. pht->iaddr = pci_iomap(pdev, 2, 0);
  227. if (pht->iaddr == NULL) {
  228. dev_err(&pdev->dev, "can't remap input space\n");
  229. goto err_unmc;
  230. }
  231. pht->oaddr = pci_iomap(pdev, 3, 0);
  232. if (pht->oaddr == NULL) {
  233. dev_err(&pdev->dev, "can't remap output space\n");
  234. goto err_unmi;
  235. }
  236. mutex_init(&pht->open_lock);
  237. spin_lock_init(&pht->ioctl_lock);
  238. init_waitqueue_head(&pht->wait);
  239. cdev_init(&pht->cdev, &phantom_file_ops);
  240. pht->cdev.owner = THIS_MODULE;
  241. iowrite32(0, pht->caddr + PHN_IRQCTL);
  242. ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
  243. retval = request_irq(pdev->irq, phantom_isr,
  244. IRQF_SHARED | IRQF_DISABLED, "phantom", pht);
  245. if (retval) {
  246. dev_err(&pdev->dev, "can't establish ISR\n");
  247. goto err_unmo;
  248. }
  249. retval = cdev_add(&pht->cdev, MKDEV(phantom_major, minor), 1);
  250. if (retval) {
  251. dev_err(&pdev->dev, "chardev registration failed\n");
  252. goto err_irq;
  253. }
  254. if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major,
  255. minor), "phantom%u", minor)))
  256. dev_err(&pdev->dev, "can't create device\n");
  257. pci_set_drvdata(pdev, pht);
  258. return 0;
  259. err_irq:
  260. free_irq(pdev->irq, pht);
  261. err_unmo:
  262. pci_iounmap(pdev, pht->oaddr);
  263. err_unmi:
  264. pci_iounmap(pdev, pht->iaddr);
  265. err_unmc:
  266. pci_iounmap(pdev, pht->caddr);
  267. err_fr:
  268. kfree(pht);
  269. err_reg:
  270. pci_release_regions(pdev);
  271. err_null:
  272. phantom_devices[minor] = 0;
  273. err_dis:
  274. pci_disable_device(pdev);
  275. err:
  276. return retval;
  277. }
  278. static void __devexit phantom_remove(struct pci_dev *pdev)
  279. {
  280. struct phantom_device *pht = pci_get_drvdata(pdev);
  281. unsigned int minor = MINOR(pht->cdev.dev);
  282. device_destroy(phantom_class, MKDEV(phantom_major, minor));
  283. cdev_del(&pht->cdev);
  284. iowrite32(0, pht->caddr + PHN_IRQCTL);
  285. ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
  286. free_irq(pdev->irq, pht);
  287. pci_iounmap(pdev, pht->oaddr);
  288. pci_iounmap(pdev, pht->iaddr);
  289. pci_iounmap(pdev, pht->caddr);
  290. kfree(pht);
  291. pci_release_regions(pdev);
  292. phantom_devices[minor] = 0;
  293. pci_disable_device(pdev);
  294. }
  295. #ifdef CONFIG_PM
  296. static int phantom_suspend(struct pci_dev *pdev, pm_message_t state)
  297. {
  298. struct phantom_device *dev = pci_get_drvdata(pdev);
  299. iowrite32(0, dev->caddr + PHN_IRQCTL);
  300. ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
  301. return 0;
  302. }
  303. static int phantom_resume(struct pci_dev *pdev)
  304. {
  305. struct phantom_device *dev = pci_get_drvdata(pdev);
  306. iowrite32(0, dev->caddr + PHN_IRQCTL);
  307. return 0;
  308. }
  309. #else
  310. #define phantom_suspend NULL
  311. #define phantom_resume NULL
  312. #endif
  313. static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
  314. { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050),
  315. .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
  316. { 0, }
  317. };
  318. MODULE_DEVICE_TABLE(pci, phantom_pci_tbl);
  319. static struct pci_driver phantom_pci_driver = {
  320. .name = "phantom",
  321. .id_table = phantom_pci_tbl,
  322. .probe = phantom_probe,
  323. .remove = __devexit_p(phantom_remove),
  324. .suspend = phantom_suspend,
  325. .resume = phantom_resume
  326. };
  327. static ssize_t phantom_show_version(struct class *cls, char *buf)
  328. {
  329. return sprintf(buf, PHANTOM_VERSION "\n");
  330. }
  331. static CLASS_ATTR(version, 0444, phantom_show_version, NULL);
  332. static int __init phantom_init(void)
  333. {
  334. int retval;
  335. dev_t dev;
  336. phantom_class = class_create(THIS_MODULE, "phantom");
  337. if (IS_ERR(phantom_class)) {
  338. retval = PTR_ERR(phantom_class);
  339. printk(KERN_ERR "phantom: can't register phantom class\n");
  340. goto err;
  341. }
  342. retval = class_create_file(phantom_class, &class_attr_version);
  343. if (retval) {
  344. printk(KERN_ERR "phantom: can't create sysfs version file\n");
  345. goto err_class;
  346. }
  347. retval = alloc_chrdev_region(&dev, 0, PHANTOM_MAX_MINORS, "phantom");
  348. if (retval) {
  349. printk(KERN_ERR "phantom: can't register character device\n");
  350. goto err_attr;
  351. }
  352. phantom_major = MAJOR(dev);
  353. retval = pci_register_driver(&phantom_pci_driver);
  354. if (retval) {
  355. printk(KERN_ERR "phantom: can't register pci driver\n");
  356. goto err_unchr;
  357. }
  358. printk(KERN_INFO "Phantom Linux Driver, version " PHANTOM_VERSION ", "
  359. "init OK\n");
  360. return 0;
  361. err_unchr:
  362. unregister_chrdev_region(dev, PHANTOM_MAX_MINORS);
  363. err_attr:
  364. class_remove_file(phantom_class, &class_attr_version);
  365. err_class:
  366. class_destroy(phantom_class);
  367. err:
  368. return retval;
  369. }
  370. static void __exit phantom_exit(void)
  371. {
  372. pci_unregister_driver(&phantom_pci_driver);
  373. unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS);
  374. class_remove_file(phantom_class, &class_attr_version);
  375. class_destroy(phantom_class);
  376. pr_debug("phantom: module successfully removed\n");
  377. }
  378. module_init(phantom_init);
  379. module_exit(phantom_exit);
  380. MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>");
  381. MODULE_DESCRIPTION("Sensable Phantom driver");
  382. MODULE_LICENSE("GPL");
  383. MODULE_VERSION(PHANTOM_VERSION);