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.8" 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 #define PHB_NOT_OH 2 36 37 static struct class *phantom_class; 38 static int phantom_major; 39 40 struct phantom_device { 41 unsigned int opened; 42 void __iomem *caddr; 43 u32 __iomem *iaddr; 44 u32 __iomem *oaddr; 45 unsigned long status; 46 atomic_t counter; 47 48 wait_queue_head_t wait; 49 struct cdev cdev; 50 51 struct mutex open_lock; 52 spinlock_t regs_lock; 53 54 /* used in NOT_OH mode */ 55 struct phm_regs oregs; 56 u32 ctl_reg; 57 }; 58 59 static unsigned char phantom_devices[PHANTOM_MAX_MINORS]; 60 61 static int phantom_status(struct phantom_device *dev, unsigned long newstat) 62 { 63 pr_debug("phantom_status %lx %lx\n", dev->status, newstat); 64 65 if (!(dev->status & PHB_RUNNING) && (newstat & PHB_RUNNING)) { 66 atomic_set(&dev->counter, 0); 67 iowrite32(PHN_CTL_IRQ, dev->iaddr + PHN_CONTROL); 68 iowrite32(0x43, dev->caddr + PHN_IRQCTL); 69 ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */ 70 } else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING)) { 71 iowrite32(0, dev->caddr + PHN_IRQCTL); 72 ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */ 73 } 74 75 dev->status = newstat; 76 77 return 0; 78 } 79 80 /* 81 * File ops 82 */ 83 84 static long phantom_ioctl(struct file *file, unsigned int cmd, 85 unsigned long arg) 86 { 87 struct phantom_device *dev = file->private_data; 88 struct phm_regs rs; 89 struct phm_reg r; 90 void __user *argp = (void __user *)arg; 91 unsigned long flags; 92 unsigned int i; 93 94 if (_IOC_TYPE(cmd) != PH_IOC_MAGIC || 95 _IOC_NR(cmd) > PH_IOC_MAXNR) 96 return -ENOTTY; 97 98 switch (cmd) { 99 case PHN_SET_REG: 100 if (copy_from_user(&r, argp, sizeof(r))) 101 return -EFAULT; 102 103 if (r.reg > 7) 104 return -EINVAL; 105 106 spin_lock_irqsave(&dev->regs_lock, flags); 107 if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) && 108 phantom_status(dev, dev->status | PHB_RUNNING)){ 109 spin_unlock_irqrestore(&dev->regs_lock, flags); 110 return -ENODEV; 111 } 112 113 pr_debug("phantom: writing %x to %u\n", r.value, r.reg); 114 115 /* preserve amp bit (don't allow to change it when in NOT_OH) */ 116 if (r.reg == PHN_CONTROL && (dev->status & PHB_NOT_OH)) { 117 r.value &= ~PHN_CTL_AMP; 118 r.value |= dev->ctl_reg & PHN_CTL_AMP; 119 dev->ctl_reg = r.value; 120 } 121 122 iowrite32(r.value, dev->iaddr + r.reg); 123 ioread32(dev->iaddr); /* PCI posting */ 124 125 if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ)) 126 phantom_status(dev, dev->status & ~PHB_RUNNING); 127 spin_unlock_irqrestore(&dev->regs_lock, flags); 128 break; 129 case PHN_SET_REGS: 130 if (copy_from_user(&rs, argp, sizeof(rs))) 131 return -EFAULT; 132 133 pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask); 134 spin_lock_irqsave(&dev->regs_lock, flags); 135 if (dev->status & PHB_NOT_OH) 136 memcpy(&dev->oregs, &rs, sizeof(rs)); 137 else { 138 u32 m = min(rs.count, 8U); 139 for (i = 0; i < m; i++) 140 if (rs.mask & BIT(i)) 141 iowrite32(rs.values[i], dev->oaddr + i); 142 ioread32(dev->iaddr); /* PCI posting */ 143 } 144 spin_unlock_irqrestore(&dev->regs_lock, flags); 145 break; 146 case PHN_GET_REG: 147 if (copy_from_user(&r, argp, sizeof(r))) 148 return -EFAULT; 149 150 if (r.reg > 7) 151 return -EINVAL; 152 153 r.value = ioread32(dev->iaddr + r.reg); 154 155 if (copy_to_user(argp, &r, sizeof(r))) 156 return -EFAULT; 157 break; 158 case PHN_GET_REGS: { 159 u32 m; 160 161 if (copy_from_user(&rs, argp, sizeof(rs))) 162 return -EFAULT; 163 164 m = min(rs.count, 8U); 165 166 pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask); 167 spin_lock_irqsave(&dev->regs_lock, flags); 168 for (i = 0; i < m; i++) 169 if (rs.mask & BIT(i)) 170 rs.values[i] = ioread32(dev->iaddr + i); 171 spin_unlock_irqrestore(&dev->regs_lock, flags); 172 173 if (copy_to_user(argp, &rs, sizeof(rs))) 174 return -EFAULT; 175 break; 176 } case PHN_NOT_OH: 177 spin_lock_irqsave(&dev->regs_lock, flags); 178 if (dev->status & PHB_RUNNING) { 179 printk(KERN_ERR "phantom: you need to set NOT_OH " 180 "before you start the device!\n"); 181 spin_unlock_irqrestore(&dev->regs_lock, flags); 182 return -EINVAL; 183 } 184 dev->status |= PHB_NOT_OH; 185 spin_unlock_irqrestore(&dev->regs_lock, flags); 186 break; 187 default: 188 return -ENOTTY; 189 } 190 191 return 0; 192 } 193 194 static int phantom_open(struct inode *inode, struct file *file) 195 { 196 struct phantom_device *dev = container_of(inode->i_cdev, 197 struct phantom_device, cdev); 198 199 nonseekable_open(inode, file); 200 201 if (mutex_lock_interruptible(&dev->open_lock)) 202 return -ERESTARTSYS; 203 204 if (dev->opened) { 205 mutex_unlock(&dev->open_lock); 206 return -EINVAL; 207 } 208 209 WARN_ON(dev->status & PHB_NOT_OH); 210 211 file->private_data = dev; 212 213 atomic_set(&dev->counter, 0); 214 dev->opened++; 215 mutex_unlock(&dev->open_lock); 216 217 return 0; 218 } 219 220 static int phantom_release(struct inode *inode, struct file *file) 221 { 222 struct phantom_device *dev = file->private_data; 223 224 mutex_lock(&dev->open_lock); 225 226 dev->opened = 0; 227 phantom_status(dev, dev->status & ~PHB_RUNNING); 228 dev->status &= ~PHB_NOT_OH; 229 230 mutex_unlock(&dev->open_lock); 231 232 return 0; 233 } 234 235 static unsigned int phantom_poll(struct file *file, poll_table *wait) 236 { 237 struct phantom_device *dev = file->private_data; 238 unsigned int mask = 0; 239 240 pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter)); 241 poll_wait(file, &dev->wait, wait); 242 if (atomic_read(&dev->counter)) { 243 mask = POLLIN | POLLRDNORM; 244 atomic_dec(&dev->counter); 245 } else if ((dev->status & PHB_RUNNING) == 0) 246 mask = POLLIN | POLLRDNORM | POLLERR; 247 pr_debug("phantom_poll end: %x/%d\n", mask, atomic_read(&dev->counter)); 248 249 return mask; 250 } 251 252 static struct file_operations phantom_file_ops = { 253 .open = phantom_open, 254 .release = phantom_release, 255 .unlocked_ioctl = phantom_ioctl, 256 .poll = phantom_poll, 257 }; 258 259 static irqreturn_t phantom_isr(int irq, void *data) 260 { 261 struct phantom_device *dev = data; 262 unsigned int i; 263 u32 ctl; 264 265 spin_lock(&dev->regs_lock); 266 ctl = ioread32(dev->iaddr + PHN_CONTROL); 267 if (!(ctl & PHN_CTL_IRQ)) { 268 spin_unlock(&dev->regs_lock); 269 return IRQ_NONE; 270 } 271 272 iowrite32(0, dev->iaddr); 273 iowrite32(0xc0, dev->iaddr); 274 275 if (dev->status & PHB_NOT_OH) { 276 struct phm_regs *r = &dev->oregs; 277 u32 m = min(r->count, 8U); 278 279 for (i = 0; i < m; i++) 280 if (r->mask & BIT(i)) 281 iowrite32(r->values[i], dev->oaddr + i); 282 283 dev->ctl_reg ^= PHN_CTL_AMP; 284 iowrite32(dev->ctl_reg, dev->iaddr + PHN_CONTROL); 285 } 286 spin_unlock(&dev->regs_lock); 287 288 ioread32(dev->iaddr); /* PCI posting */ 289 290 atomic_inc(&dev->counter); 291 wake_up_interruptible(&dev->wait); 292 293 return IRQ_HANDLED; 294 } 295 296 /* 297 * Init and deinit driver 298 */ 299 300 static unsigned int __devinit phantom_get_free(void) 301 { 302 unsigned int i; 303 304 for (i = 0; i < PHANTOM_MAX_MINORS; i++) 305 if (phantom_devices[i] == 0) 306 break; 307 308 return i; 309 } 310 311 static int __devinit phantom_probe(struct pci_dev *pdev, 312 const struct pci_device_id *pci_id) 313 { 314 struct phantom_device *pht; 315 unsigned int minor; 316 int retval; 317 318 retval = pci_enable_device(pdev); 319 if (retval) 320 goto err; 321 322 minor = phantom_get_free(); 323 if (minor == PHANTOM_MAX_MINORS) { 324 dev_err(&pdev->dev, "too many devices found!\n"); 325 retval = -EIO; 326 goto err_dis; 327 } 328 329 phantom_devices[minor] = 1; 330 331 retval = pci_request_regions(pdev, "phantom"); 332 if (retval) 333 goto err_null; 334 335 retval = -ENOMEM; 336 pht = kzalloc(sizeof(*pht), GFP_KERNEL); 337 if (pht == NULL) { 338 dev_err(&pdev->dev, "unable to allocate device\n"); 339 goto err_reg; 340 } 341 342 pht->caddr = pci_iomap(pdev, 0, 0); 343 if (pht->caddr == NULL) { 344 dev_err(&pdev->dev, "can't remap conf space\n"); 345 goto err_fr; 346 } 347 pht->iaddr = pci_iomap(pdev, 2, 0); 348 if (pht->iaddr == NULL) { 349 dev_err(&pdev->dev, "can't remap input space\n"); 350 goto err_unmc; 351 } 352 pht->oaddr = pci_iomap(pdev, 3, 0); 353 if (pht->oaddr == NULL) { 354 dev_err(&pdev->dev, "can't remap output space\n"); 355 goto err_unmi; 356 } 357 358 mutex_init(&pht->open_lock); 359 spin_lock_init(&pht->regs_lock); 360 init_waitqueue_head(&pht->wait); 361 cdev_init(&pht->cdev, &phantom_file_ops); 362 pht->cdev.owner = THIS_MODULE; 363 364 iowrite32(0, pht->caddr + PHN_IRQCTL); 365 ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */ 366 retval = request_irq(pdev->irq, phantom_isr, 367 IRQF_SHARED | IRQF_DISABLED, "phantom", pht); 368 if (retval) { 369 dev_err(&pdev->dev, "can't establish ISR\n"); 370 goto err_unmo; 371 } 372 373 retval = cdev_add(&pht->cdev, MKDEV(phantom_major, minor), 1); 374 if (retval) { 375 dev_err(&pdev->dev, "chardev registration failed\n"); 376 goto err_irq; 377 } 378 379 if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major, 380 minor), "phantom%u", minor))) 381 dev_err(&pdev->dev, "can't create device\n"); 382 383 pci_set_drvdata(pdev, pht); 384 385 return 0; 386 err_irq: 387 free_irq(pdev->irq, pht); 388 err_unmo: 389 pci_iounmap(pdev, pht->oaddr); 390 err_unmi: 391 pci_iounmap(pdev, pht->iaddr); 392 err_unmc: 393 pci_iounmap(pdev, pht->caddr); 394 err_fr: 395 kfree(pht); 396 err_reg: 397 pci_release_regions(pdev); 398 err_null: 399 phantom_devices[minor] = 0; 400 err_dis: 401 pci_disable_device(pdev); 402 err: 403 return retval; 404 } 405 406 static void __devexit phantom_remove(struct pci_dev *pdev) 407 { 408 struct phantom_device *pht = pci_get_drvdata(pdev); 409 unsigned int minor = MINOR(pht->cdev.dev); 410 411 device_destroy(phantom_class, MKDEV(phantom_major, minor)); 412 413 cdev_del(&pht->cdev); 414 415 iowrite32(0, pht->caddr + PHN_IRQCTL); 416 ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */ 417 free_irq(pdev->irq, pht); 418 419 pci_iounmap(pdev, pht->oaddr); 420 pci_iounmap(pdev, pht->iaddr); 421 pci_iounmap(pdev, pht->caddr); 422 423 kfree(pht); 424 425 pci_release_regions(pdev); 426 427 phantom_devices[minor] = 0; 428 429 pci_disable_device(pdev); 430 } 431 432 #ifdef CONFIG_PM 433 static int phantom_suspend(struct pci_dev *pdev, pm_message_t state) 434 { 435 struct phantom_device *dev = pci_get_drvdata(pdev); 436 437 iowrite32(0, dev->caddr + PHN_IRQCTL); 438 ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */ 439 440 synchronize_irq(pdev->irq); 441 442 return 0; 443 } 444 445 static int phantom_resume(struct pci_dev *pdev) 446 { 447 struct phantom_device *dev = pci_get_drvdata(pdev); 448 449 iowrite32(0, dev->caddr + PHN_IRQCTL); 450 451 return 0; 452 } 453 #else 454 #define phantom_suspend NULL 455 #define phantom_resume NULL 456 #endif 457 458 static struct pci_device_id phantom_pci_tbl[] __devinitdata = { 459 { .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050, 460 .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050, 461 .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 }, 462 { 0, } 463 }; 464 MODULE_DEVICE_TABLE(pci, phantom_pci_tbl); 465 466 static struct pci_driver phantom_pci_driver = { 467 .name = "phantom", 468 .id_table = phantom_pci_tbl, 469 .probe = phantom_probe, 470 .remove = __devexit_p(phantom_remove), 471 .suspend = phantom_suspend, 472 .resume = phantom_resume 473 }; 474 475 static ssize_t phantom_show_version(struct class *cls, char *buf) 476 { 477 return sprintf(buf, PHANTOM_VERSION "\n"); 478 } 479 480 static CLASS_ATTR(version, 0444, phantom_show_version, NULL); 481 482 static int __init phantom_init(void) 483 { 484 int retval; 485 dev_t dev; 486 487 phantom_class = class_create(THIS_MODULE, "phantom"); 488 if (IS_ERR(phantom_class)) { 489 retval = PTR_ERR(phantom_class); 490 printk(KERN_ERR "phantom: can't register phantom class\n"); 491 goto err; 492 } 493 retval = class_create_file(phantom_class, &class_attr_version); 494 if (retval) { 495 printk(KERN_ERR "phantom: can't create sysfs version file\n"); 496 goto err_class; 497 } 498 499 retval = alloc_chrdev_region(&dev, 0, PHANTOM_MAX_MINORS, "phantom"); 500 if (retval) { 501 printk(KERN_ERR "phantom: can't register character device\n"); 502 goto err_attr; 503 } 504 phantom_major = MAJOR(dev); 505 506 retval = pci_register_driver(&phantom_pci_driver); 507 if (retval) { 508 printk(KERN_ERR "phantom: can't register pci driver\n"); 509 goto err_unchr; 510 } 511 512 printk(KERN_INFO "Phantom Linux Driver, version " PHANTOM_VERSION ", " 513 "init OK\n"); 514 515 return 0; 516 err_unchr: 517 unregister_chrdev_region(dev, PHANTOM_MAX_MINORS); 518 err_attr: 519 class_remove_file(phantom_class, &class_attr_version); 520 err_class: 521 class_destroy(phantom_class); 522 err: 523 return retval; 524 } 525 526 static void __exit phantom_exit(void) 527 { 528 pci_unregister_driver(&phantom_pci_driver); 529 530 unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS); 531 532 class_remove_file(phantom_class, &class_attr_version); 533 class_destroy(phantom_class); 534 535 pr_debug("phantom: module successfully removed\n"); 536 } 537 538 module_init(phantom_init); 539 module_exit(phantom_exit); 540 541 MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>"); 542 MODULE_DESCRIPTION("Sensable Phantom driver"); 543 MODULE_LICENSE("GPL"); 544 MODULE_VERSION(PHANTOM_VERSION); 545