1/* Hey EMACS -*- linux-c -*- 2 * 3 * tipar - low level driver for handling a parallel link cable designed 4 * for Texas Instruments graphing calculators (http://lpg.ticalc.org). 5 * A part of the TiLP project. 6 * 7 * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org> 8 * under the terms of the GNU General Public License. 9 * 10 * Various fixes & clean-up from the Linux Kernel Mailing List 11 * (Alan Cox, Richard B. Johnson, Christoph Hellwig). 12 */ 13 14/* This driver should, in theory, work with any parallel port that has an 15 * appropriate low-level driver; all I/O is done through the parport 16 * abstraction layer. 17 * 18 * If this driver is built into the kernel, you can configure it using the 19 * kernel command-line. For example: 20 * 21 * tipar=timeout,delay (set timeout and delay) 22 * 23 * If the driver is loaded as a module, similar functionality is available 24 * using module parameters. The equivalent of the above commands would be: 25 * 26 * # insmod tipar timeout=15 delay=10 27 */ 28 29/* COMPATIBILITY WITH OLD KERNELS 30 * 31 * Usually, parallel cables were bound to ports at 32 * particular I/O addresses, as follows: 33 * 34 * tipar0 0x378 35 * tipar1 0x278 36 * tipar2 0x3bc 37 * 38 * 39 * This driver, by default, binds tipar devices according to parport and 40 * the minor number. 41 * 42 */ 43#undef DEBUG /* change to #define to get debugging 44 * output - for pr_debug() */ 45#include <linux/module.h> 46#include <linux/types.h> 47#include <linux/errno.h> 48#include <linux/kernel.h> 49#include <linux/sched.h> 50#include <linux/delay.h> 51#include <linux/fcntl.h> 52#include <linux/fs.h> 53#include <linux/init.h> 54#include <asm/uaccess.h> 55#include <linux/ioport.h> 56#include <asm/io.h> 57#include <linux/bitops.h> 58#include <linux/parport.h> /* Our code depend on parport */ 59#include <linux/device.h> 60 61/* 62 * TI definitions 63 */ 64#include <linux/ticable.h> 65 66/* 67 * Version Information 68 */ 69#define DRIVER_VERSION "1.19" 70#define DRIVER_AUTHOR "Romain Lievin <roms@lpg.ticalc.org>" 71#define DRIVER_DESC "Device driver for TI/PC parallel link cables" 72#define DRIVER_LICENSE "GPL" 73 74#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) 75 76/* ----- global variables --------------------------------------------- */ 77 78struct tipar_struct { 79 struct pardevice *dev; /* Parport device entry */ 80}; 81 82#define PP_NO 3 83static struct tipar_struct table[PP_NO]; 84 85static int delay = IO_DELAY; /* inter-bit delay in microseconds */ 86static int timeout = TIMAXTIME; /* timeout in tenth of seconds */ 87 88static unsigned int tp_count; /* tipar count */ 89static unsigned long opened; /* opened devices */ 90 91static struct class *tipar_class; 92 93/* --- macros for parport access -------------------------------------- */ 94 95#define r_dtr(x) (parport_read_data(table[(x)].dev->port)) 96#define r_str(x) (parport_read_status(table[(x)].dev->port)) 97#define w_ctr(x,y) (parport_write_control(table[(x)].dev->port, (y))) 98#define w_dtr(x,y) (parport_write_data(table[(x)].dev->port, (y))) 99 100/* --- setting states on the D-bus with the right timing: ------------- */ 101 102static inline void 103outbyte(int value, int minor) 104{ 105 w_dtr(minor, value); 106} 107 108static inline int 109inbyte(int minor) 110{ 111 return (r_str(minor)); 112} 113 114static inline void 115init_ti_parallel(int minor) 116{ 117 outbyte(3, minor); 118} 119 120/* ----- global defines ----------------------------------------------- */ 121 122#define START(x) { x = jiffies + (HZ * timeout) / 10; } 123#define WAIT(x) { \ 124 if (time_before((x), jiffies)) return -1; \ 125 if (need_resched()) schedule(); } 126 127/* ----- D-bus bit-banging functions ---------------------------------- */ 128 129/* D-bus protocol (45kbit/s max): 130 1 0 0 131 _______ ______|______ __________|________ __________ 132Red : ________ | ____ | ____ 133 _ ____________|________ ______|__________ _____ 134White: ________ | ______ | _______ 135*/ 136 137/* Try to transmit a byte on the specified port (-1 if error). */ 138static int 139put_ti_parallel(int minor, unsigned char data) 140{ 141 unsigned int bit; 142 unsigned long max; 143 144 for (bit = 0; bit < 8; bit++) { 145 if (data & 1) { 146 outbyte(2, minor); 147 START(max); 148 do { 149 WAIT(max); 150 } while (inbyte(minor) & 0x10); 151 152 outbyte(3, minor); 153 START(max); 154 do { 155 WAIT(max); 156 } while (!(inbyte(minor) & 0x10)); 157 } else { 158 outbyte(1, minor); 159 START(max); 160 do { 161 WAIT(max); 162 } while (inbyte(minor) & 0x20); 163 164 outbyte(3, minor); 165 START(max); 166 do { 167 WAIT(max); 168 } while (!(inbyte(minor) & 0x20)); 169 } 170 171 data >>= 1; 172 udelay(delay); 173 174 if (need_resched()) 175 schedule(); 176 } 177 178 return 0; 179} 180 181/* Receive a byte on the specified port or -1 if error. */ 182static int 183get_ti_parallel(int minor) 184{ 185 unsigned int bit; 186 unsigned char v, data = 0; 187 unsigned long max; 188 189 for (bit = 0; bit < 8; bit++) { 190 START(max); 191 do { 192 WAIT(max); 193 } while ((v = inbyte(minor) & 0x30) == 0x30); 194 195 if (v == 0x10) { 196 data = (data >> 1) | 0x80; 197 outbyte(1, minor); 198 START(max); 199 do { 200 WAIT(max); 201 } while (!(inbyte(minor) & 0x20)); 202 outbyte(3, minor); 203 } else { 204 data = data >> 1; 205 outbyte(2, minor); 206 START(max); 207 do { 208 WAIT(max); 209 } while (!(inbyte(minor) & 0x10)); 210 outbyte(3, minor); 211 } 212 213 udelay(delay); 214 if (need_resched()) 215 schedule(); 216 } 217 218 return (int) data; 219} 220 221/* Try to detect a parallel link cable on the specified port */ 222static int 223probe_ti_parallel(int minor) 224{ 225 int i; 226 int seq[] = { 0x00, 0x20, 0x10, 0x30 }; 227 int data; 228 229 for (i = 3; i >= 0; i--) { 230 outbyte(3, minor); 231 outbyte(i, minor); 232 udelay(delay); 233 data = inbyte(minor) & 0x30; 234 pr_debug("tipar: Probing -> %i: 0x%02x 0x%02x\n", i, 235 data, seq[i]); 236 if (data != seq[i]) { 237 outbyte(3, minor); 238 return -1; 239 } 240 } 241 242 outbyte(3, minor); 243 return 0; 244} 245 246/* ----- kernel module functions--------------------------------------- */ 247 248static int 249tipar_open(struct inode *inode, struct file *file) 250{ 251 unsigned int minor = iminor(inode) - TIPAR_MINOR; 252 253 if (tp_count == 0 || minor > tp_count - 1) 254 return -ENXIO; 255 256 if (test_and_set_bit(minor, &opened)) 257 return -EBUSY; 258 259 if (!table[minor].dev) { 260 printk(KERN_ERR "%s: NULL device for minor %u\n", 261 __FUNCTION__, minor); 262 return -ENXIO; 263 } 264 parport_claim_or_block(table[minor].dev); 265 init_ti_parallel(minor); 266 parport_release(table[minor].dev); 267 268 return nonseekable_open(inode, file); 269} 270 271static int 272tipar_close(struct inode *inode, struct file *file) 273{ 274 unsigned int minor = iminor(inode) - TIPAR_MINOR; 275 276 if (minor > tp_count - 1) 277 return -ENXIO; 278 279 clear_bit(minor, &opened); 280 281 return 0; 282} 283 284static ssize_t 285tipar_write (struct file *file, const char __user *buf, size_t count, 286 loff_t * ppos) 287{ 288 unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; 289 ssize_t n; 290 291 parport_claim_or_block(table[minor].dev); 292 293 for (n = 0; n < count; n++) { 294 unsigned char b; 295 296 if (get_user(b, buf + n)) { 297 n = -EFAULT; 298 goto out; 299 } 300 301 if (put_ti_parallel(minor, b) == -1) { 302 init_ti_parallel(minor); 303 n = -ETIMEDOUT; 304 goto out; 305 } 306 } 307 out: 308 parport_release(table[minor].dev); 309 return n; 310} 311 312static ssize_t 313tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) 314{ 315 int b = 0; 316 unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; 317 ssize_t retval = 0; 318 ssize_t n = 0; 319 320 if (count == 0) 321 return 0; 322 323 parport_claim_or_block(table[minor].dev); 324 325 while (n < count) { 326 b = get_ti_parallel(minor); 327 if (b == -1) { 328 init_ti_parallel(minor); 329 retval = -ETIMEDOUT; 330 goto out; 331 } else { 332 if (put_user(b, buf + n)) { 333 retval = -EFAULT; 334 break; 335 } else 336 retval = ++n; 337 } 338 339 /* Non-blocking mode : try again ! */ 340 if (file->f_flags & O_NONBLOCK) { 341 retval = -EAGAIN; 342 goto out; 343 } 344 345 /* Signal pending, try again ! */ 346 if (signal_pending(current)) { 347 retval = -ERESTARTSYS; 348 goto out; 349 } 350 351 if (need_resched()) 352 schedule(); 353 } 354 355 out: 356 parport_release(table[minor].dev); 357 return retval; 358} 359 360static int 361tipar_ioctl(struct inode *inode, struct file *file, 362 unsigned int cmd, unsigned long arg) 363{ 364 int retval = 0; 365 366 switch (cmd) { 367 case IOCTL_TIPAR_DELAY: 368 delay = (int)arg; //get_user(delay, &arg); 369 break; 370 case IOCTL_TIPAR_TIMEOUT: 371 if (arg != 0) 372 timeout = (int)arg; 373 else 374 retval = -EINVAL; 375 break; 376 default: 377 retval = -ENOTTY; 378 break; 379 } 380 381 return retval; 382} 383 384/* ----- kernel module registering ------------------------------------ */ 385 386static const struct file_operations tipar_fops = { 387 .owner = THIS_MODULE, 388 .llseek = no_llseek, 389 .read = tipar_read, 390 .write = tipar_write, 391 .ioctl = tipar_ioctl, 392 .open = tipar_open, 393 .release = tipar_close, 394}; 395 396/* --- initialisation code ------------------------------------- */ 397 398#ifndef MODULE 399/* You must set these - there is no sane way to probe for this cable. 400 * You can use 'tipar=timeout,delay' to set these now. */ 401static int __init 402tipar_setup(char *str) 403{ 404 int ints[3]; 405 406 str = get_options(str, ARRAY_SIZE(ints), ints); 407 408 if (ints[0] > 0) { 409 if (ints[1] != 0) 410 timeout = ints[1]; 411 else 412 printk(KERN_WARNING "tipar: bad timeout value (0), " 413 "using default value instead"); 414 if (ints[0] > 1) { 415 delay = ints[2]; 416 } 417 } 418 419 return 1; 420} 421#endif 422 423/* 424 * Register our module into parport. 425 * Pass also 2 callbacks functions to parport: a pre-emptive function and an 426 * interrupt handler function (unused). 427 * Display a message such "tipar0: using parport0 (polling)". 428 */ 429static int 430tipar_register(int nr, struct parport *port) 431{ 432 int err = 0; 433 434 /* Register our module into parport */ 435 table[nr].dev = parport_register_device(port, "tipar", 436 NULL, NULL, NULL, 0, 437 (void *) &table[nr]); 438 439 if (table[nr].dev == NULL) { 440 err = 1; 441 goto out; 442 } 443 444 class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR, 445 TIPAR_MINOR + nr), port->dev, "par%d", nr); 446 447 /* Display informations */ 448 pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq == 449 PARPORT_IRQ_NONE) ? "polling" : "interrupt-driven"); 450 451 if (probe_ti_parallel(nr) != -1) 452 pr_info("tipar%d: link cable found\n", nr); 453 else 454 pr_info("tipar%d: link cable not found\n", nr); 455 456 err = 0; 457 458out: 459 return err; 460} 461 462static void 463tipar_attach(struct parport *port) 464{ 465 if (tp_count == PP_NO) { 466 pr_info("tipar: ignoring parallel port (max. %d)\n", PP_NO); 467 return; 468 } 469 470 if (!tipar_register(tp_count, port)) 471 tp_count++; 472} 473 474static void 475tipar_detach(struct parport *port) 476{ 477 /* Nothing to do */ 478} 479 480static struct parport_driver tipar_driver = { 481 .name = "tipar", 482 .attach = tipar_attach, 483 .detach = tipar_detach, 484}; 485 486static int __init 487tipar_init_module(void) 488{ 489 int err = 0; 490 491 pr_info("tipar: parallel link cable driver, version %s\n", 492 DRIVER_VERSION); 493 494 if (register_chrdev(TIPAR_MAJOR, "tipar", &tipar_fops)) { 495 printk(KERN_ERR "tipar: unable to get major %d\n", TIPAR_MAJOR); 496 err = -EIO; 497 goto out; 498 } 499 500 tipar_class = class_create(THIS_MODULE, "ticables"); 501 if (IS_ERR(tipar_class)) { 502 err = PTR_ERR(tipar_class); 503 goto out_chrdev; 504 } 505 if (parport_register_driver(&tipar_driver)) { 506 printk(KERN_ERR "tipar: unable to register with parport\n"); 507 err = -EIO; 508 goto out_class; 509 } 510 511 err = 0; 512 goto out; 513 514out_class: 515 class_destroy(tipar_class); 516 517out_chrdev: 518 unregister_chrdev(TIPAR_MAJOR, "tipar"); 519out: 520 return err; 521} 522 523static void __exit 524tipar_cleanup_module(void) 525{ 526 unsigned int i; 527 528 /* Unregistering module */ 529 parport_unregister_driver(&tipar_driver); 530 531 unregister_chrdev(TIPAR_MAJOR, "tipar"); 532 533 for (i = 0; i < PP_NO; i++) { 534 if (table[i].dev == NULL) 535 continue; 536 parport_unregister_device(table[i].dev); 537 class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i)); 538 } 539 class_destroy(tipar_class); 540 541 pr_info("tipar: module unloaded\n"); 542} 543 544/* --------------------------------------------------------------------- */ 545 546__setup("tipar=", tipar_setup); 547module_init(tipar_init_module); 548module_exit(tipar_cleanup_module); 549 550MODULE_AUTHOR(DRIVER_AUTHOR); 551MODULE_DESCRIPTION(DRIVER_DESC); 552MODULE_LICENSE(DRIVER_LICENSE); 553 554module_param(timeout, int, 0); 555MODULE_PARM_DESC(timeout, "Timeout (default=1.5 seconds)"); 556module_param(delay, int, 0); 557MODULE_PARM_DESC(delay, "Inter-bit delay (default=10 microseconds)"); 558