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