Import 2.1.36
[davej-history.git] / drivers / char / lp.c
blob7fd2f9b35a9bc16036bbce9f2977e2a2a2e5dfc9
1 /*
2 * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
3 * Copyright (C) 1992,1993 by Michael K. Johnson
4 * - Thanks much to Gunter Windau for pointing out to me where the error
5 * checking ought to be.
6 * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
7 * Copyright (C) 1994 by Alan Cox (Modularised it)
8 * LPCAREFUL, LPABORT, LPGETSTATUS added by Chris Metcalf, metcalf@lcs.mit.edu
9 * Statistics and support for slow printers by Rob Janssen, rob@knoware.nl
10 * "lp=" command line parameters added by Grant Guenther, grant@torque.net
11 * lp_read (Status readback) support added by Carsten Gross,
12 * carsten@sol.wohnheim.uni-ulm.de
15 #include <linux/module.h>
17 #include <linux/config.h>
18 #include <linux/errno.h>
19 #include <linux/kernel.h>
20 #include <linux/major.h>
21 #include <linux/sched.h>
22 #include <linux/malloc.h>
23 #include <linux/ioport.h>
24 #include <linux/fcntl.h>
25 #include <linux/delay.h>
26 #include <linux/init.h>
28 #include <asm/io.h>
29 #include <asm/uaccess.h>
30 #include <asm/system.h>
31 #include <linux/parport.h>
32 #include <linux/lp.h>
34 /* the BIOS manuals say there can be up to 4 lpt devices
35 * but I have not seen a board where the 4th address is listed
36 * if you have different hardware change the table below
37 * please let me know if you have different equipment
38 * if you have more than 3 printers, remember to increase LP_NO
40 struct lp_struct lp_table[] =
42 {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0,
43 {0}},
44 {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0,
45 {0}},
46 {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0,
47 {0}}
49 #define LP_NO 3
51 /* Device name */
52 static char *dev_name = "lp";
54 /* Test if printer is ready (and optionally has no error conditions) */
55 #define LP_READY(minor, status) \
56 ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : (status & LP_PBUSY))
57 #define LP_CAREFUL_READY(minor, status) \
58 ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : 1)
59 #define _LP_CAREFUL_READY(status) \
60 (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
61 (LP_PBUSY|LP_PSELECD|LP_PERRORP)
63 #undef LP_DEBUG
64 #undef LP_READ_DEBUG
66 static int lp_reset(int minor)
68 w_ctr(minor, LP_PSELECP);
69 udelay(LP_DELAY);
70 w_ctr(minor, LP_PSELECP | LP_PINITP);
71 return r_str(minor);
74 static inline int lp_char_polled(char lpchar, int minor)
76 int status, wait = 0;
77 unsigned long count = 0;
78 struct lp_stats *stats;
80 do {
81 status = r_str(minor);
82 count++;
83 if (need_resched)
84 schedule();
85 } while (!LP_READY(minor, status) && count < LP_CHAR(minor));
87 if (count == LP_CHAR(minor)) {
88 return 0;
89 /* we timed out, and the character was /not/ printed */
91 w_dtr(minor, lpchar);
92 stats = &LP_STAT(minor);
93 stats->chars++;
94 /* must wait before taking strobe high, and after taking strobe
95 low, according spec. Some printers need it, others don't. */
96 while (wait != LP_WAIT(minor))
97 wait++;
98 /* control port takes strobe high */
99 w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
100 while (wait)
101 wait--;
102 /* take strobe low */
103 w_ctr(minor, LP_PSELECP | LP_PINITP);
104 /* update waittime statistics */
105 if (count > stats->maxwait) {
106 #ifdef LP_DEBUG
107 printk(KERN_DEBUG "lp%d success after %d counts.\n", minor, count);
108 #endif
109 stats->maxwait = count;
111 count *= 256;
112 wait = (count > stats->meanwait) ? count - stats->meanwait :
113 stats->meanwait - count;
114 stats->meanwait = (255 * stats->meanwait + count + 128) / 256;
115 stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
117 return 1;
120 static inline int lp_char_interrupt(char lpchar, int minor)
122 int wait;
123 unsigned long count = 0;
124 unsigned char status;
125 struct lp_stats *stats;
127 do {
128 if(need_resched)
129 schedule();
130 if ((status = r_str(minor)) & LP_PBUSY) {
131 if (!LP_CAREFUL_READY(minor, status))
132 return 0;
133 w_dtr(minor, lpchar);
134 stats = &LP_STAT(minor);
135 stats->chars++;
136 /* must wait before taking strobe high, and after taking strobe
137 low, according spec. Some printers need it, others don't. */
138 wait = 0;
139 while (wait != LP_WAIT(minor))
140 wait++;
141 /* control port takes strobe high */
142 w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
143 while (wait)
144 wait--;
145 /* take strobe low */
146 w_ctr(minor, LP_PSELECP | LP_PINITP);
147 /* update waittime statistics */
148 if (count) {
149 if (count > stats->maxwait)
150 stats->maxwait = count;
151 count *= 256;
152 wait = (count > stats->meanwait) ? count - stats->meanwait :
153 stats->meanwait - count;
154 stats->meanwait = (255 * stats->meanwait + count + 128) / 256;
155 stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
157 return 1;
159 } while (count++ < LP_CHAR(minor));
161 return 0;
164 static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
166 struct parport *pb = (struct parport *) dev_id;
167 struct ppd *pd = pb->cad;
168 struct lp_struct *lp_dev = (struct lp_struct *) pd->private;
170 if (lp_dev->lp_wait_q)
171 wake_up(&lp_dev->lp_wait_q);
174 static inline int lp_write_interrupt(unsigned int minor, const char *buf, int count)
176 unsigned long copy_size;
177 unsigned long total_bytes_written = 0;
178 unsigned long bytes_written;
179 struct lp_struct *lp = &lp_table[minor];
180 unsigned char status;
182 if (minor >= LP_NO)
183 return -ENXIO;
184 if (lp_table[minor].dev == NULL)
185 return -ENXIO;
187 do {
188 bytes_written = 0;
189 copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
190 copy_from_user(lp->lp_buffer, buf, copy_size);
192 while (copy_size) {
193 if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {
194 --copy_size;
195 ++bytes_written;
196 lp_table[minor].runchars++;
197 } else {
198 int rc = total_bytes_written + bytes_written;
199 if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
200 LP_STAT(minor).maxrun = lp_table[minor].runchars;
201 status = r_str(minor);
202 if ((status & LP_POUTPA)) {
203 printk(KERN_INFO "lp%d out of paper\n", minor);
204 if (LP_F(minor) & LP_ABORT)
205 return rc ? rc : -ENOSPC;
206 } else if (!(status & LP_PSELECD)) {
207 printk(KERN_INFO "lp%d off-line\n", minor);
208 if (LP_F(minor) & LP_ABORT)
209 return rc ? rc : -EIO;
210 } else if (!(status & LP_PERRORP)) {
211 printk(KERN_ERR "lp%d printer error\n", minor);
212 if (LP_F(minor) & LP_ABORT)
213 return rc ? rc : -EIO;
215 LP_STAT(minor).sleeps++;
216 cli();
217 w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
218 status = r_str(minor);
219 if ((!(status & LP_PACK) || (status & LP_PBUSY))
220 && LP_CAREFUL_READY(minor, status)) {
221 w_ctr(minor, LP_PSELECP | LP_PINITP);
222 sti();
223 continue;
225 lp_table[minor].runchars = 0;
226 current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
227 interruptible_sleep_on(&lp->lp_wait_q);
228 w_ctr(minor, LP_PSELECP | LP_PINITP);
229 sti();
230 if (current->signal & ~current->blocked) {
231 if (total_bytes_written + bytes_written)
232 return total_bytes_written + bytes_written;
233 else
234 return -EINTR;
239 total_bytes_written += bytes_written;
240 buf += bytes_written;
241 count -= bytes_written;
243 } while (count > 0);
245 return total_bytes_written;
248 static inline int lp_write_polled(unsigned int minor, const char *buf, int count)
250 int retval, status;
251 char c;
252 const char *temp;
254 temp = buf;
255 while (count > 0) {
256 get_user(c, temp);
257 retval = lp_char_polled(c, minor);
258 /* only update counting vars if character was printed */
259 if (retval) {
260 count--; temp++;
261 lp_table[minor].runchars++;
262 } else { /* if printer timed out */
263 if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
264 LP_STAT(minor).maxrun = lp_table[minor].runchars;
265 status = r_str(minor);
267 if (status & LP_POUTPA) {
268 printk(KERN_INFO "lp%d out of paper\n", minor);
269 if(LP_F(minor) & LP_ABORT)
270 return temp-buf?temp-buf:-ENOSPC;
271 current->state = TASK_INTERRUPTIBLE;
272 current->timeout = jiffies + LP_TIMEOUT_POLLED;
273 schedule();
274 } else
275 if (!(status & LP_PSELECD)) {
276 printk(KERN_INFO "lp%d off-line\n", minor);
277 if(LP_F(minor) & LP_ABORT)
278 return temp-buf?temp-buf:-EIO;
279 current->state = TASK_INTERRUPTIBLE;
280 current->timeout = jiffies + LP_TIMEOUT_POLLED;
281 schedule();
282 } else
283 /* not offline or out of paper. on fire? */
284 if (!(status & LP_PERRORP)) {
285 printk(KERN_ERR "lp%d on fire\n", minor);
286 if(LP_F(minor) & LP_ABORT)
287 return temp-buf?temp-buf:-EIO;
288 current->state = TASK_INTERRUPTIBLE;
289 current->timeout = jiffies + LP_TIMEOUT_POLLED;
290 schedule();
293 /* check for signals before going to sleep */
294 if (current->signal & ~current->blocked) {
295 if (temp != buf)
296 return temp-buf;
297 else
298 return -EINTR;
300 LP_STAT(minor).sleeps++;
301 #ifdef LP_DEBUG
302 printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n",
303 minor,lp_table[minor].runchars, LP_TIME(minor));
304 #endif
305 lp_table[minor].runchars=0;
306 current->state = TASK_INTERRUPTIBLE;
307 current->timeout = jiffies + LP_TIME(minor);
308 schedule();
311 return temp-buf;
314 static long lp_write(struct inode * inode, struct file * file,
315 const char * buf, unsigned long count)
317 unsigned int minor = MINOR(inode->i_rdev);
318 int retv;
320 if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
321 lp_table[minor].runchars = 0;
323 lp_table[minor].lastcall = jiffies;
325 /* Claim Parport or sleep until it becomes available
326 * (see lp_wakeup() for details)
328 if (parport_claim(lp_table[minor].dev)) {
329 sleep_on(&lp_table[minor].lp_wait_q);
330 lp_table[minor].lp_wait_q = NULL;
332 if (LP_IRQ(minor) > 0)
333 retv = lp_write_interrupt(minor, buf, count);
334 else
335 retv = lp_write_polled(minor, buf, count);
337 parport_release(lp_table[minor].dev);
338 return retv;
341 static long long lp_lseek(struct inode * inode, struct file * file,
342 long long offset, int origin)
344 return -ESPIPE;
347 #ifdef CONFIG_PRINTER_READBACK
349 static int lp_read_nibble(int minor)
351 unsigned char i;
352 i=r_str(minor)>>3;
353 i&=~8;
354 if ( ( i & 0x10) == 0) i|=8;
355 return(i & 0x0f);
358 static void lp_select_in_high(int minor) {
359 w_ctr(minor, (r_ctr(minor) | 8));
362 /* Status readback confirming to ieee1284 */
363 static long lp_read(struct inode * inode, struct file * file,
364 char * buf, unsigned long count)
366 unsigned char z=0, Byte=0, status;
367 char *temp;
368 int retval;
369 unsigned int counter=0;
370 unsigned int i;
371 unsigned int minor=MINOR(inode->i_rdev);
373 /* Claim Parport or sleep until it becomes available
374 * (see lp_wakeup() for details)
376 if (parport_claim(lp_table[minor].dev)) {
377 sleep_on(&lp_table[minor].lp_wait_q);
378 lp_table[minor].lp_wait_q = NULL;
381 temp=buf;
382 #ifdef LP_READ_DEBUG
383 printk(KERN_INFO "lp%d: read mode\n", minor);
384 #endif
386 retval = verify_area(VERIFY_WRITE, buf, count);
387 if (retval)
388 return retval;
389 if (parport_ieee1284_nibble_mode_ok(lp_table[minor].dev->port, 0)==0) {
390 #ifdef LP_READ_DEBUG
391 printk(KERN_INFO "lp%d: rejected IEEE1284 negotiation.\n",
392 minor);
393 #endif
394 lp_select_in_high(minor);
395 parport_release(lp_table[minor].dev);
396 return temp-buf; /* End of file */
398 for (i=0; i<=(count*2); i++) {
399 w_ctr(minor, r_ctr(minor) | 2); /* AutoFeed high */
400 do {
401 status=(r_str(minor) & 0x40);
402 udelay(50);
403 counter++;
404 if (need_resched)
405 schedule();
406 } while ( (status == 0x40) && (counter < 20) );
407 if ( counter == 20 ) { /* Timeout */
408 #ifdef LP_READ_DEBUG
409 printk(KERN_DEBUG "lp_read: (Autofeed high) timeout\n");
410 #endif
411 w_ctr(minor, r_ctr(minor) & ~2);
412 lp_select_in_high(minor);
413 parport_release(lp_table[minor].dev);
414 return temp-buf; /* end the read at timeout */
416 counter=0;
417 z=lp_read_nibble(minor);
418 w_ctr(minor, r_ctr(minor) & ~2); /* AutoFeed low */
419 do {
420 status=(r_str(minor) & 0x40);
421 udelay(20);
422 counter++;
423 if (need_resched)
424 schedule();
425 } while ( (status == 0) && (counter < 20) );
426 if (counter == 20) { /* Timeout */
427 #ifdef LP_READ_DEBUG
428 printk(KERN_DEBUG "lp_read: (Autofeed low) timeout\n");
429 #endif
430 if (current->signal & ~current->blocked) {
431 lp_select_in_high(minor);
432 parport_release(lp_table[minor].dev);
433 if (temp !=buf)
434 return temp-buf;
435 else
436 return -EINTR;
438 current->state=TASK_INTERRUPTIBLE;
439 current->timeout=jiffies + LP_TIME(minor);
440 schedule();
442 counter=0;
443 if (( i & 1) != 0) {
444 Byte= (Byte | z<<4);
445 put_user(Byte, temp);
446 temp++;
447 } else Byte=z;
449 lp_select_in_high(minor);
450 parport_release(lp_table[minor].dev);
451 return temp-buf;
454 #endif
456 static int lp_open(struct inode * inode, struct file * file)
458 unsigned int minor = MINOR(inode->i_rdev);
460 if (minor >= LP_NO)
461 return -ENXIO;
462 if ((LP_F(minor) & LP_EXIST) == 0)
463 return -ENXIO;
464 if (LP_F(minor) & LP_BUSY)
465 return -EBUSY;
467 MOD_INC_USE_COUNT;
469 /* If ABORTOPEN is set and the printer is offline or out of paper,
470 we may still want to open it to perform ioctl()s. Therefore we
471 have commandeered O_NONBLOCK, even though it is being used in
472 a non-standard manner. This is strictly a Linux hack, and
473 should most likely only ever be used by the tunelp application. */
474 if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
475 int status = r_str(minor);
476 if (status & LP_POUTPA) {
477 printk(KERN_INFO "lp%d out of paper\n", minor);
478 MOD_DEC_USE_COUNT;
479 return -ENOSPC;
480 } else if (!(status & LP_PSELECD)) {
481 printk(KERN_INFO "lp%d off-line\n", minor);
482 MOD_DEC_USE_COUNT;
483 return -EIO;
484 } else if (!(status & LP_PERRORP)) {
485 printk(KERN_ERR "lp%d printer error\n", minor);
486 MOD_DEC_USE_COUNT;
487 return -EIO;
490 if (LP_IRQ(minor) > 0) {
491 lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
492 if (!lp_table[minor].lp_buffer) {
493 MOD_DEC_USE_COUNT;
494 return -ENOMEM;
497 LP_F(minor) |= LP_BUSY;
498 return 0;
501 static int lp_release(struct inode * inode, struct file * file)
503 unsigned int minor = MINOR(inode->i_rdev);
504 unsigned int irq;
506 if ((irq = LP_IRQ(minor))) {
507 kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
508 lp_table[minor].lp_buffer = NULL;
510 LP_F(minor) &= ~LP_BUSY;
511 MOD_DEC_USE_COUNT;
512 return 0;
516 static int lp_ioctl(struct inode *inode, struct file *file,
517 unsigned int cmd, unsigned long arg)
519 unsigned int minor = MINOR(inode->i_rdev);
520 int retval = 0;
522 #ifdef LP_DEBUG
523 printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
524 #endif
525 if (minor >= LP_NO)
526 return -ENODEV;
527 if ((LP_F(minor) & LP_EXIST) == 0)
528 return -ENODEV;
529 switch ( cmd ) {
530 case LPTIME:
531 LP_TIME(minor) = arg * HZ/100;
532 break;
533 case LPCHAR:
534 LP_CHAR(minor) = arg;
535 break;
536 case LPABORT:
537 if (arg)
538 LP_F(minor) |= LP_ABORT;
539 else
540 LP_F(minor) &= ~LP_ABORT;
541 break;
542 case LPABORTOPEN:
543 if (arg)
544 LP_F(minor) |= LP_ABORTOPEN;
545 else
546 LP_F(minor) &= ~LP_ABORTOPEN;
547 break;
548 case LPCAREFUL:
549 if (arg)
550 LP_F(minor) |= LP_CAREFUL;
551 else
552 LP_F(minor) &= ~LP_CAREFUL;
553 break;
554 case LPWAIT:
555 LP_WAIT(minor) = arg;
556 break;
557 case LPSETIRQ:
558 return -EINVAL;
559 break;
560 case LPGETIRQ:
561 retval = verify_area(VERIFY_WRITE, (void *) arg,
562 sizeof(int));
563 if (retval)
564 return retval;
565 copy_to_user((int *) arg, &LP_IRQ(minor), sizeof(int));
566 break;
567 case LPGETSTATUS:
568 retval = verify_area(VERIFY_WRITE, (void *) arg,
569 sizeof(int));
570 if (retval)
571 return retval;
572 else {
573 int status = r_str(minor);
574 copy_to_user((int *) arg, &status, sizeof(int));
576 break;
577 case LPRESET:
578 lp_reset(minor);
579 break;
580 case LPGETSTATS:
581 retval = verify_area(VERIFY_WRITE, (void *) arg,
582 sizeof(struct lp_stats));
583 if (retval)
584 return retval;
585 else {
586 copy_to_user((int *) arg, &LP_STAT(minor), sizeof(struct lp_stats));
587 if (suser())
588 memset(&LP_STAT(minor), 0, sizeof(struct lp_stats));
590 break;
591 case LPGETFLAGS:
592 retval = verify_area(VERIFY_WRITE, (void *) arg,
593 sizeof(int));
594 if (retval)
595 return retval;
596 else {
597 int status = LP_F(minor);
598 copy_to_user((int *) arg, &status, sizeof(int));
600 break;
601 default:
602 retval = -EINVAL;
604 return retval;
608 static struct file_operations lp_fops = {
609 lp_lseek,
610 #ifdef CONFIG_PRINTER_READBACK
611 lp_read,
612 #else
613 NULL,
614 #endif
615 lp_write,
616 NULL, /* lp_readdir */
617 NULL, /* lp_poll */
618 lp_ioctl,
619 NULL, /* lp_mmap */
620 lp_open,
621 lp_release
624 static int parport[LP_NO] = { -1, };
626 #ifdef MODULE
627 #define lp_init init_module
628 MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "i");
630 #else
632 static int parport_ptr = 0;
634 void lp_setup(char *str, int *ints)
636 /* Ugh. */
637 if (!strncmp(str, "parport", 7)) {
638 int n = simple_strtoul(str+7, NULL, 10);
639 if (parport_ptr < LP_NO)
640 parport[parport_ptr++] = n;
641 else
642 printk(KERN_INFO "lp: too many ports, %s ignored.\n",
643 str);
644 } else if (!strcmp(str, "auto")) {
645 parport[0] = -3;
646 } else {
647 if (ints[0] == 0 || ints[1] == 0) {
648 /* disable driver on "parport=" or "parport=0" */
649 parport[0] = -2;
650 } else {
651 printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
656 #endif
658 int lp_wakeup(void *ref)
660 struct lp_struct *lp_dev = (struct lp_struct *) ref;
662 if (!lp_dev->lp_wait_q)
663 return 1; /* Wake up whom? */
665 /* Claim the Parport */
666 if (parport_claim(lp_dev->dev))
667 return 1; /* Shouldn't happen */
669 wake_up(&lp_dev->lp_wait_q);
670 return 0;
673 static int inline lp_searchfor(int list[], int a)
675 int i;
676 for (i = 0; i < LP_NO && list[i] != -1; i++) {
677 if (list[i] == a) return 1;
679 return 0;
682 __initfunc(int lp_init(void))
684 int count = 0;
685 struct parport *pb;
687 if (register_chrdev(LP_MAJOR, "lp", &lp_fops)) {
688 printk("lp: unable to get major %d\n", LP_MAJOR);
689 return -EIO;
692 if (parport[0] == -2) return 0;
694 pb = parport_enumerate();
696 while (pb) {
697 /* We only understand PC-style ports. */
698 if (pb->modes & PARPORT_MODE_SPP) {
699 if (parport[0] == -1 || lp_searchfor(parport, count) ||
700 (parport[0] == -3 &&
701 pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
702 lp_table[count].dev =
703 parport_register_device(pb, dev_name, NULL,
704 lp_wakeup,
705 lp_interrupt, PARPORT_DEV_TRAN,
706 (void *) &lp_table[count]);
707 lp_table[count].flags |= LP_EXIST;
708 printk(KERN_INFO "lp%d: using %s at 0x%x, ",
709 count, pb->name, pb->base);
710 if (pb->irq == -1)
711 printk("polling.\n");
712 else
713 printk("irq %d.\n", pb->irq);
715 if (++count == LP_NO)
716 break;
718 pb = pb->next;
721 /* Successful specified devices increase count
722 * Unsuccessful specified devices increase failed
724 if (count)
725 return 0;
727 printk(KERN_INFO "lp: driver loaded but no devices found\n");
728 return 1;
731 #ifdef MODULE
732 void cleanup_module(void)
734 int offset;
736 unregister_chrdev(LP_MAJOR, "lp");
737 for (offset = 0; offset < LP_NO; offset++) {
738 if (lp_table[offset].dev == NULL)
739 continue;
740 parport_unregister_device(lp_table[offset].dev);
743 #endif