1 /*
2  * lirc_parallel.c
3  *
4  * lirc_parallel - device driver for infra-red signal receiving and
5  *                 transmitting unit built by the author
6  *
7  * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24 
25 /*** Includes ***/
26 
27 #include <linux/module.h>
28 #include <linux/sched.h>
29 #include <linux/errno.h>
30 #include <linux/signal.h>
31 #include <linux/fs.h>
32 #include <linux/kernel.h>
33 #include <linux/ioport.h>
34 #include <linux/time.h>
35 #include <linux/mm.h>
36 #include <linux/delay.h>
37 
38 #include <linux/io.h>
39 #include <linux/irq.h>
40 #include <linux/uaccess.h>
41 #include <asm/div64.h>
42 
43 #include <linux/poll.h>
44 #include <linux/parport.h>
45 #include <linux/platform_device.h>
46 
47 #include <media/lirc.h>
48 #include <media/lirc_dev.h>
49 
50 #include "lirc_parallel.h"
51 
52 #define LIRC_DRIVER_NAME "lirc_parallel"
53 
54 #ifndef LIRC_IRQ
55 #define LIRC_IRQ 7
56 #endif
57 #ifndef LIRC_PORT
58 #define LIRC_PORT 0x378
59 #endif
60 #ifndef LIRC_TIMER
61 #define LIRC_TIMER 65536
62 #endif
63 
64 /*** Global Variables ***/
65 
66 static bool debug;
67 static bool check_pselecd;
68 
69 unsigned int irq = LIRC_IRQ;
70 unsigned int io = LIRC_PORT;
71 #ifdef LIRC_TIMER
72 unsigned int timer;
73 unsigned int default_timer = LIRC_TIMER;
74 #endif
75 
76 #define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */
77 
78 static int rbuf[RBUF_SIZE];
79 
80 DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
81 
82 unsigned int rptr;
83 unsigned int wptr;
84 unsigned int lost_irqs;
85 int is_open;
86 
87 struct parport *pport;
88 struct pardevice *ppdevice;
89 int is_claimed;
90 
91 unsigned int tx_mask = 1;
92 
93 /*** Internal Functions ***/
94 
in(int offset)95 static unsigned int in(int offset)
96 {
97 	switch (offset) {
98 	case LIRC_LP_BASE:
99 		return parport_read_data(pport);
100 	case LIRC_LP_STATUS:
101 		return parport_read_status(pport);
102 	case LIRC_LP_CONTROL:
103 		return parport_read_control(pport);
104 	}
105 	return 0; /* make compiler happy */
106 }
107 
out(int offset,int value)108 static void out(int offset, int value)
109 {
110 	switch (offset) {
111 	case LIRC_LP_BASE:
112 		parport_write_data(pport, value);
113 		break;
114 	case LIRC_LP_CONTROL:
115 		parport_write_control(pport, value);
116 		break;
117 	case LIRC_LP_STATUS:
118 		printk(KERN_INFO "%s: attempt to write to status register\n",
119 		       LIRC_DRIVER_NAME);
120 		break;
121 	}
122 }
123 
lirc_get_timer(void)124 static unsigned int lirc_get_timer(void)
125 {
126 	return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT;
127 }
128 
lirc_get_signal(void)129 static unsigned int lirc_get_signal(void)
130 {
131 	return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT;
132 }
133 
lirc_on(void)134 static void lirc_on(void)
135 {
136 	out(LIRC_PORT_DATA, tx_mask);
137 }
138 
lirc_off(void)139 static void lirc_off(void)
140 {
141 	out(LIRC_PORT_DATA, 0);
142 }
143 
init_lirc_timer(void)144 static unsigned int init_lirc_timer(void)
145 {
146 	struct timeval tv, now;
147 	unsigned int level, newlevel, timeelapsed, newtimer;
148 	int count = 0;
149 
150 	do_gettimeofday(&tv);
151 	tv.tv_sec++;                     /* wait max. 1 sec. */
152 	level = lirc_get_timer();
153 	do {
154 		newlevel = lirc_get_timer();
155 		if (level == 0 && newlevel != 0)
156 			count++;
157 		level = newlevel;
158 		do_gettimeofday(&now);
159 	} while (count < 1000 && (now.tv_sec < tv.tv_sec
160 			     || (now.tv_sec == tv.tv_sec
161 				 && now.tv_usec < tv.tv_usec)));
162 
163 	timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000
164 		     + (now.tv_usec - tv.tv_usec));
165 	if (count >= 1000 && timeelapsed > 0) {
166 		if (default_timer == 0) {
167 			/* autodetect timer */
168 			newtimer = (1000000*count)/timeelapsed;
169 			printk(KERN_INFO "%s: %u Hz timer detected\n",
170 			       LIRC_DRIVER_NAME, newtimer);
171 			return newtimer;
172 		}  else {
173 			newtimer = (1000000*count)/timeelapsed;
174 			if (abs(newtimer - default_timer) > default_timer/10) {
175 				/* bad timer */
176 				printk(KERN_NOTICE "%s: bad timer: %u Hz\n",
177 				       LIRC_DRIVER_NAME, newtimer);
178 				printk(KERN_NOTICE "%s: using default timer: "
179 				       "%u Hz\n",
180 				       LIRC_DRIVER_NAME, default_timer);
181 				return default_timer;
182 			} else {
183 				printk(KERN_INFO "%s: %u Hz timer detected\n",
184 				       LIRC_DRIVER_NAME, newtimer);
185 				return newtimer; /* use detected value */
186 			}
187 		}
188 	} else {
189 		printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME);
190 		return 0;
191 	}
192 }
193 
lirc_claim(void)194 static int lirc_claim(void)
195 {
196 	if (parport_claim(ppdevice) != 0) {
197 		printk(KERN_WARNING "%s: could not claim port\n",
198 		       LIRC_DRIVER_NAME);
199 		printk(KERN_WARNING "%s: waiting for port becoming available"
200 		       "\n", LIRC_DRIVER_NAME);
201 		if (parport_claim_or_block(ppdevice) < 0) {
202 			printk(KERN_NOTICE "%s: could not claim port, giving"
203 			       " up\n", LIRC_DRIVER_NAME);
204 			return 0;
205 		}
206 	}
207 	out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
208 	is_claimed = 1;
209 	return 1;
210 }
211 
212 /*** interrupt handler ***/
213 
rbuf_write(int signal)214 static void rbuf_write(int signal)
215 {
216 	unsigned int nwptr;
217 
218 	nwptr = (wptr + 1) & (RBUF_SIZE - 1);
219 	if (nwptr == rptr) {
220 		/* no new signals will be accepted */
221 		lost_irqs++;
222 		printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME);
223 		return;
224 	}
225 	rbuf[wptr] = signal;
226 	wptr = nwptr;
227 }
228 
irq_handler(void * blah)229 static void irq_handler(void *blah)
230 {
231 	struct timeval tv;
232 	static struct timeval lasttv;
233 	static int init;
234 	long signal;
235 	int data;
236 	unsigned int level, newlevel;
237 	unsigned int timeout;
238 
239 	if (!is_open)
240 		return;
241 
242 	if (!is_claimed)
243 		return;
244 
245 #if 0
246 	/* disable interrupt */
247 	  disable_irq(irq);
248 	  out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN));
249 #endif
250 	if (check_pselecd && (in(1) & LP_PSELECD))
251 		return;
252 
253 #ifdef LIRC_TIMER
254 	if (init) {
255 		do_gettimeofday(&tv);
256 
257 		signal = tv.tv_sec - lasttv.tv_sec;
258 		if (signal > 15)
259 			/* really long time */
260 			data = PULSE_MASK;
261 		else
262 			data = (int) (signal*1000000 +
263 					 tv.tv_usec - lasttv.tv_usec +
264 					 LIRC_SFH506_DELAY);
265 
266 		rbuf_write(data); /* space */
267 	} else {
268 		if (timer == 0) {
269 			/*
270 			 * wake up; we'll lose this signal, but it will be
271 			 * garbage if the device is turned on anyway
272 			 */
273 			timer = init_lirc_timer();
274 			/* enable_irq(irq); */
275 			return;
276 		}
277 		init = 1;
278 	}
279 
280 	timeout = timer/10;	/* timeout after 1/10 sec. */
281 	signal = 1;
282 	level = lirc_get_timer();
283 	do {
284 		newlevel = lirc_get_timer();
285 		if (level == 0 && newlevel != 0)
286 			signal++;
287 		level = newlevel;
288 
289 		/* giving up */
290 		if (signal > timeout
291 		    || (check_pselecd && (in(1) & LP_PSELECD))) {
292 			signal = 0;
293 			printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME);
294 			break;
295 		}
296 	} while (lirc_get_signal());
297 
298 	if (signal != 0) {
299 		/* adjust value to usecs */
300 		__u64 helper;
301 
302 		helper = ((__u64) signal)*1000000;
303 		do_div(helper, timer);
304 		signal = (long) helper;
305 
306 		if (signal > LIRC_SFH506_DELAY)
307 			data = signal - LIRC_SFH506_DELAY;
308 		else
309 			data = 1;
310 		rbuf_write(PULSE_BIT|data); /* pulse */
311 	}
312 	do_gettimeofday(&lasttv);
313 #else
314 	/* add your code here */
315 #endif
316 
317 	wake_up_interruptible(&lirc_wait);
318 
319 	/* enable interrupt */
320 	/*
321 	  enable_irq(irq);
322 	  out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN);
323 	*/
324 }
325 
326 /*** file operations ***/
327 
lirc_lseek(struct file * filep,loff_t offset,int orig)328 static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
329 {
330 	return -ESPIPE;
331 }
332 
lirc_read(struct file * filep,char * buf,size_t n,loff_t * ppos)333 static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos)
334 {
335 	int result = 0;
336 	int count = 0;
337 	DECLARE_WAITQUEUE(wait, current);
338 
339 	if (n % sizeof(int))
340 		return -EINVAL;
341 
342 	add_wait_queue(&lirc_wait, &wait);
343 	set_current_state(TASK_INTERRUPTIBLE);
344 	while (count < n) {
345 		if (rptr != wptr) {
346 			if (copy_to_user(buf+count, (char *) &rbuf[rptr],
347 					 sizeof(int))) {
348 				result = -EFAULT;
349 				break;
350 			}
351 			rptr = (rptr + 1) & (RBUF_SIZE - 1);
352 			count += sizeof(int);
353 		} else {
354 			if (filep->f_flags & O_NONBLOCK) {
355 				result = -EAGAIN;
356 				break;
357 			}
358 			if (signal_pending(current)) {
359 				result = -ERESTARTSYS;
360 				break;
361 			}
362 			schedule();
363 			set_current_state(TASK_INTERRUPTIBLE);
364 		}
365 	}
366 	remove_wait_queue(&lirc_wait, &wait);
367 	set_current_state(TASK_RUNNING);
368 	return count ? count : result;
369 }
370 
lirc_write(struct file * filep,const char * buf,size_t n,loff_t * ppos)371 static ssize_t lirc_write(struct file *filep, const char *buf, size_t n,
372 			  loff_t *ppos)
373 {
374 	int count;
375 	unsigned int i;
376 	unsigned int level, newlevel;
377 	unsigned long flags;
378 	int counttimer;
379 	int *wbuf;
380 	ssize_t ret;
381 
382 	if (!is_claimed)
383 		return -EBUSY;
384 
385 	count = n / sizeof(int);
386 
387 	if (n % sizeof(int) || count % 2 == 0)
388 		return -EINVAL;
389 
390 	wbuf = memdup_user(buf, n);
391 	if (IS_ERR(wbuf))
392 		return PTR_ERR(wbuf);
393 
394 #ifdef LIRC_TIMER
395 	if (timer == 0) {
396 		/* try again if device is ready */
397 		timer = init_lirc_timer();
398 		if (timer == 0) {
399 			ret = -EIO;
400 			goto out;
401 		}
402 	}
403 
404 	/* adjust values from usecs */
405 	for (i = 0; i < count; i++) {
406 		__u64 helper;
407 
408 		helper = ((__u64) wbuf[i])*timer;
409 		do_div(helper, 1000000);
410 		wbuf[i] = (int) helper;
411 	}
412 
413 	local_irq_save(flags);
414 	i = 0;
415 	while (i < count) {
416 		level = lirc_get_timer();
417 		counttimer = 0;
418 		lirc_on();
419 		do {
420 			newlevel = lirc_get_timer();
421 			if (level == 0 && newlevel != 0)
422 				counttimer++;
423 			level = newlevel;
424 			if (check_pselecd && (in(1) & LP_PSELECD)) {
425 				lirc_off();
426 				local_irq_restore(flags);
427 				ret = -EIO;
428 				goto out;
429 			}
430 		} while (counttimer < wbuf[i]);
431 		i++;
432 
433 		lirc_off();
434 		if (i == count)
435 			break;
436 		counttimer = 0;
437 		do {
438 			newlevel = lirc_get_timer();
439 			if (level == 0 && newlevel != 0)
440 				counttimer++;
441 			level = newlevel;
442 			if (check_pselecd && (in(1) & LP_PSELECD)) {
443 				local_irq_restore(flags);
444 				ret = -EIO;
445 				goto out;
446 			}
447 		} while (counttimer < wbuf[i]);
448 		i++;
449 	}
450 	local_irq_restore(flags);
451 #else
452 	/* place code that handles write without external timer here */
453 #endif
454 	ret = n;
455 out:
456 	kfree(wbuf);
457 
458 	return ret;
459 }
460 
lirc_poll(struct file * file,poll_table * wait)461 static unsigned int lirc_poll(struct file *file, poll_table *wait)
462 {
463 	poll_wait(file, &lirc_wait, wait);
464 	if (rptr != wptr)
465 		return POLLIN | POLLRDNORM;
466 	return 0;
467 }
468 
lirc_ioctl(struct file * filep,unsigned int cmd,unsigned long arg)469 static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
470 {
471 	int result;
472 	__u32 features = LIRC_CAN_SET_TRANSMITTER_MASK |
473 			 LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
474 	__u32 mode;
475 	__u32 value;
476 
477 	switch (cmd) {
478 	case LIRC_GET_FEATURES:
479 		result = put_user(features, (__u32 *) arg);
480 		if (result)
481 			return result;
482 		break;
483 	case LIRC_GET_SEND_MODE:
484 		result = put_user(LIRC_MODE_PULSE, (__u32 *) arg);
485 		if (result)
486 			return result;
487 		break;
488 	case LIRC_GET_REC_MODE:
489 		result = put_user(LIRC_MODE_MODE2, (__u32 *) arg);
490 		if (result)
491 			return result;
492 		break;
493 	case LIRC_SET_SEND_MODE:
494 		result = get_user(mode, (__u32 *) arg);
495 		if (result)
496 			return result;
497 		if (mode != LIRC_MODE_PULSE)
498 			return -EINVAL;
499 		break;
500 	case LIRC_SET_REC_MODE:
501 		result = get_user(mode, (__u32 *) arg);
502 		if (result)
503 			return result;
504 		if (mode != LIRC_MODE_MODE2)
505 			return -ENOSYS;
506 		break;
507 	case LIRC_SET_TRANSMITTER_MASK:
508 		result = get_user(value, (__u32 *) arg);
509 		if (result)
510 			return result;
511 		if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value)
512 			return LIRC_PARALLEL_MAX_TRANSMITTERS;
513 		tx_mask = value;
514 		break;
515 	default:
516 		return -ENOIOCTLCMD;
517 	}
518 	return 0;
519 }
520 
lirc_open(struct inode * node,struct file * filep)521 static int lirc_open(struct inode *node, struct file *filep)
522 {
523 	if (is_open || !lirc_claim())
524 		return -EBUSY;
525 
526 	parport_enable_irq(pport);
527 
528 	/* init read ptr */
529 	rptr = 0;
530 	wptr = 0;
531 	lost_irqs = 0;
532 
533 	is_open = 1;
534 	return 0;
535 }
536 
lirc_close(struct inode * node,struct file * filep)537 static int lirc_close(struct inode *node, struct file *filep)
538 {
539 	if (is_claimed) {
540 		is_claimed = 0;
541 		parport_release(ppdevice);
542 	}
543 	is_open = 0;
544 	return 0;
545 }
546 
547 static const struct file_operations lirc_fops = {
548 	.owner		= THIS_MODULE,
549 	.llseek		= lirc_lseek,
550 	.read		= lirc_read,
551 	.write		= lirc_write,
552 	.poll		= lirc_poll,
553 	.unlocked_ioctl	= lirc_ioctl,
554 #ifdef CONFIG_COMPAT
555 	.compat_ioctl	= lirc_ioctl,
556 #endif
557 	.open		= lirc_open,
558 	.release	= lirc_close
559 };
560 
set_use_inc(void * data)561 static int set_use_inc(void *data)
562 {
563 	return 0;
564 }
565 
set_use_dec(void * data)566 static void set_use_dec(void *data)
567 {
568 }
569 
570 static struct lirc_driver driver = {
571 	.name		= LIRC_DRIVER_NAME,
572 	.minor		= -1,
573 	.code_length	= 1,
574 	.sample_rate	= 0,
575 	.data		= NULL,
576 	.add_to_buf	= NULL,
577 	.set_use_inc	= set_use_inc,
578 	.set_use_dec	= set_use_dec,
579 	.fops		= &lirc_fops,
580 	.dev		= NULL,
581 	.owner		= THIS_MODULE,
582 };
583 
584 static struct platform_device *lirc_parallel_dev;
585 
lirc_parallel_probe(struct platform_device * dev)586 static int __devinit lirc_parallel_probe(struct platform_device *dev)
587 {
588 	return 0;
589 }
590 
lirc_parallel_remove(struct platform_device * dev)591 static int __devexit lirc_parallel_remove(struct platform_device *dev)
592 {
593 	return 0;
594 }
595 
lirc_parallel_suspend(struct platform_device * dev,pm_message_t state)596 static int lirc_parallel_suspend(struct platform_device *dev,
597 					pm_message_t state)
598 {
599 	return 0;
600 }
601 
lirc_parallel_resume(struct platform_device * dev)602 static int lirc_parallel_resume(struct platform_device *dev)
603 {
604 	return 0;
605 }
606 
607 static struct platform_driver lirc_parallel_driver = {
608 	.probe	= lirc_parallel_probe,
609 	.remove	= __devexit_p(lirc_parallel_remove),
610 	.suspend	= lirc_parallel_suspend,
611 	.resume	= lirc_parallel_resume,
612 	.driver	= {
613 		.name	= LIRC_DRIVER_NAME,
614 		.owner	= THIS_MODULE,
615 	},
616 };
617 
pf(void * handle)618 static int pf(void *handle)
619 {
620 	parport_disable_irq(pport);
621 	is_claimed = 0;
622 	return 0;
623 }
624 
kf(void * handle)625 static void kf(void *handle)
626 {
627 	if (!is_open)
628 		return;
629 	if (!lirc_claim())
630 		return;
631 	parport_enable_irq(pport);
632 	lirc_off();
633 	/* this is a bit annoying when you actually print...*/
634 	/*
635 	printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
636 	*/
637 }
638 
639 /*** module initialization and cleanup ***/
640 
lirc_parallel_init(void)641 static int __init lirc_parallel_init(void)
642 {
643 	int result;
644 
645 	result = platform_driver_register(&lirc_parallel_driver);
646 	if (result) {
647 		printk(KERN_NOTICE "platform_driver_register"
648 					" returned %d\n", result);
649 		return result;
650 	}
651 
652 	lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
653 	if (!lirc_parallel_dev) {
654 		result = -ENOMEM;
655 		goto exit_driver_unregister;
656 	}
657 
658 	result = platform_device_add(lirc_parallel_dev);
659 	if (result)
660 		goto exit_device_put;
661 
662 	pport = parport_find_base(io);
663 	if (pport == NULL) {
664 		printk(KERN_NOTICE "%s: no port at %x found\n",
665 		       LIRC_DRIVER_NAME, io);
666 		result = -ENXIO;
667 		goto exit_device_put;
668 	}
669 	ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
670 					   pf, kf, irq_handler, 0, NULL);
671 	parport_put_port(pport);
672 	if (ppdevice == NULL) {
673 		printk(KERN_NOTICE "%s: parport_register_device() failed\n",
674 		       LIRC_DRIVER_NAME);
675 		result = -ENXIO;
676 		goto exit_device_put;
677 	}
678 	if (parport_claim(ppdevice) != 0)
679 		goto skip_init;
680 	is_claimed = 1;
681 	out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
682 
683 #ifdef LIRC_TIMER
684 	if (debug)
685 		out(LIRC_PORT_DATA, tx_mask);
686 
687 	timer = init_lirc_timer();
688 
689 #if 0	/* continue even if device is offline */
690 	if (timer == 0) {
691 		is_claimed = 0;
692 		parport_release(pport);
693 		parport_unregister_device(ppdevice);
694 		result = -EIO;
695 		goto exit_device_put;
696 	}
697 
698 #endif
699 	if (debug)
700 		out(LIRC_PORT_DATA, 0);
701 #endif
702 
703 	is_claimed = 0;
704 	parport_release(ppdevice);
705  skip_init:
706 	driver.dev = &lirc_parallel_dev->dev;
707 	driver.minor = lirc_register_driver(&driver);
708 	if (driver.minor < 0) {
709 		printk(KERN_NOTICE "%s: register_chrdev() failed\n",
710 		       LIRC_DRIVER_NAME);
711 		parport_unregister_device(ppdevice);
712 		result = -EIO;
713 		goto exit_device_put;
714 	}
715 	printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n",
716 	       LIRC_DRIVER_NAME, io, irq);
717 	return 0;
718 
719 exit_device_put:
720 	platform_device_put(lirc_parallel_dev);
721 exit_driver_unregister:
722 	platform_driver_unregister(&lirc_parallel_driver);
723 	return result;
724 }
725 
lirc_parallel_exit(void)726 static void __exit lirc_parallel_exit(void)
727 {
728 	parport_unregister_device(ppdevice);
729 	lirc_unregister_driver(driver.minor);
730 
731 	platform_device_unregister(lirc_parallel_dev);
732 	platform_driver_unregister(&lirc_parallel_driver);
733 }
734 
735 module_init(lirc_parallel_init);
736 module_exit(lirc_parallel_exit);
737 
738 MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
739 MODULE_AUTHOR("Christoph Bartelmus");
740 MODULE_LICENSE("GPL");
741 
742 module_param(io, int, S_IRUGO);
743 MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
744 
745 module_param(irq, int, S_IRUGO);
746 MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
747 
748 module_param(tx_mask, int, S_IRUGO);
749 MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)");
750 
751 module_param(debug, bool, S_IRUGO | S_IWUSR);
752 MODULE_PARM_DESC(debug, "Enable debugging messages");
753 
754 module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
755 MODULE_PARM_DESC(check_pselecd, "Check for printer (default: 0)");
756