home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / char / lp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  15.4 KB  |  619 lines

  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.  */
  10.  
  11. #ifdef MODULE
  12. #include <linux/module.h>
  13. #include <linux/version.h>
  14. #else
  15. #define MOD_INC_USE_COUNT
  16. #define MOD_DEC_USE_COUNT
  17. #endif
  18.  
  19. #include <linux/errno.h>
  20. #include <linux/kernel.h>
  21. #include <linux/major.h>
  22. #include <linux/sched.h>
  23. #include <linux/lp.h>
  24. #include <linux/malloc.h>
  25. #include <linux/ioport.h>
  26. #include <linux/fcntl.h>
  27.  
  28. #include <asm/io.h>
  29. #include <asm/segment.h>
  30. #include <asm/system.h>
  31.  
  32. /* the BIOS manuals say there can be up to 4 lpt devices
  33.  * but I have not seen a board where the 4th address is listed
  34.  * if you have different hardware change the table below 
  35.  * please let me know if you have different equipment
  36.  * if you have more than 3 printers, remember to increase LP_NO
  37.  */
  38. struct lp_struct lp_table[] = {
  39.     { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
  40.     { 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
  41.     { 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
  42. }; 
  43. #define LP_NO 3
  44.  
  45. /* Test if printer is ready (and optionally has no error conditions) */
  46. #define LP_READY(minor, status) \
  47.   ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : (status & LP_PBUSY))
  48. #define LP_CAREFUL_READY(minor, status) \
  49.   ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : 1)
  50. #define _LP_CAREFUL_READY(status) \
  51.    (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
  52.       (LP_PBUSY|LP_PSELECD|LP_PERRORP) 
  53.  
  54. /* Allow old versions of tunelp to continue to work */
  55. #define OLD_LPCHAR   0x0001
  56. #define OLD_LPTIME   0x0002
  57. #define OLD_LPABORT  0x0004
  58. #define OLD_LPSETIRQ 0x0005
  59. #define OLD_LPGETIRQ 0x0006
  60. #define OLD_LPWAIT   0x0008
  61. #define OLD_IOCTL_MAX 8
  62.  
  63. /* 
  64.  * All my debugging code assumes that you debug with only one printer at
  65.  * a time. RWWH
  66.  */
  67.  
  68. #undef LP_DEBUG
  69.  
  70. static int lp_reset(int minor)
  71. {
  72.     int testvalue;
  73.     unsigned char command;
  74.  
  75.     command = LP_PSELECP | LP_PINITP;
  76.  
  77.     /* reset value */
  78.     outb_p(0, LP_C(minor));
  79.     for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
  80.         ;
  81.     outb_p(command, LP_C(minor));
  82.     return LP_S(minor);
  83. }
  84.  
  85. #ifdef LP_DEBUG
  86. static int lp_max_count = 1;
  87. #endif
  88.  
  89. static int lp_char_polled(char lpchar, int minor)
  90. {
  91.     int status = 0, wait = 0;
  92.     unsigned long count  = 0; 
  93.  
  94.     do {
  95.         status = LP_S(minor);
  96.         count ++;
  97.         if(need_resched)
  98.             schedule();
  99.     } while(!LP_READY(minor,status) && count < LP_CHAR(minor));
  100.  
  101.     if (count == LP_CHAR(minor)) {
  102.         return 0;
  103.         /* we timed out, and the character was /not/ printed */
  104.     }
  105. #ifdef LP_DEBUG
  106.     if (count > lp_max_count) {
  107.         printk("lp success after %d counts.\n",count);
  108.         lp_max_count=count;
  109.     }
  110. #endif
  111.     outb_p(lpchar, LP_B(minor));
  112.     /* must wait before taking strobe high, and after taking strobe
  113.        low, according spec.  Some printers need it, others don't. */
  114.     while(wait != LP_WAIT(minor)) wait++;
  115.         /* control port takes strobe high */
  116.     outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
  117.     while(wait) wait--;
  118.         /* take strobe low */
  119.     outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
  120.  
  121.     return 1;
  122. }
  123.  
  124. static int lp_char_interrupt(char lpchar, int minor)
  125. {
  126.     int wait = 0;
  127.     unsigned char status;
  128.  
  129.  
  130.     if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
  131.     || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
  132.     || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) {
  133.  
  134.         if (!LP_CAREFUL_READY(minor, status))
  135.             return 0;
  136.         outb_p(lpchar, LP_B(minor));
  137.         /* must wait before taking strobe high, and after taking strobe
  138.            low, according spec.  Some printers need it, others don't. */
  139.         while(wait != LP_WAIT(minor)) wait++;
  140.         /* control port takes strobe high */
  141.         outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
  142.         while(wait) wait--;
  143.         /* take strobe low */
  144.         outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
  145.         return 1;
  146.     }
  147.  
  148.     return 0;
  149. }
  150.  
  151. #ifdef LP_DEBUG
  152.     unsigned int lp_total_chars = 0;
  153.     unsigned int lp_last_call = 0;
  154. #endif
  155.  
  156. static void lp_interrupt(int irq, struct pt_regs *regs)
  157. {
  158.     struct lp_struct *lp = &lp_table[0];
  159.     struct lp_struct *lp_end = &lp_table[LP_NO];
  160.  
  161.     while (irq != lp->irq) {
  162.         if (++lp >= lp_end)
  163.             return;
  164.     }
  165.  
  166.     wake_up(&lp->lp_wait_q);
  167. }
  168.  
  169. static int lp_write_interrupt(struct inode * inode, struct file * file, char * buf, int count)
  170. {
  171.     unsigned int minor = MINOR(inode->i_rdev);
  172.     unsigned long copy_size;
  173.     unsigned long total_bytes_written = 0;
  174.     unsigned long bytes_written;
  175.     struct lp_struct *lp = &lp_table[minor];
  176.     unsigned char status;
  177.  
  178.     do {
  179.         bytes_written = 0;
  180.         copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
  181.         memcpy_fromfs(lp->lp_buffer, buf, copy_size);
  182.  
  183.         while (copy_size) {
  184.             if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {
  185.                 --copy_size;
  186.                 ++bytes_written;
  187.             } else {
  188.                 int rc = total_bytes_written + bytes_written;
  189.                 status = LP_S(minor);
  190.                 if ((status & LP_POUTPA)) {
  191.                     printk(KERN_INFO "lp%d out of paper\n", minor);
  192.                     if (LP_F(minor) & LP_ABORT)
  193.                         return rc?rc:-ENOSPC;
  194.                 } else if (!(status & LP_PSELECD)) {
  195.                     printk(KERN_INFO "lp%d off-line\n", minor);
  196.                     if (LP_F(minor) & LP_ABORT)
  197.                         return rc?rc:-EIO;
  198.                 } else if (!(status & LP_PERRORP)) {
  199.                     printk(KERN_ERR "lp%d printer error\n", minor);
  200.                     if (LP_F(minor) & LP_ABORT)
  201.                         return rc?rc:-EIO;
  202.                 }
  203.                 cli();
  204.                 outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
  205.                 status = LP_S(minor);
  206.                 if ((!(status & LP_PACK) || (status & LP_PBUSY))
  207.                   && LP_CAREFUL_READY(minor, status)) {
  208.                     outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
  209.                     sti();
  210.                     continue;
  211.                 }
  212.                 current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
  213.                 interruptible_sleep_on(&lp->lp_wait_q);
  214.                 outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
  215.                 sti();
  216.                 if (current->signal & ~current->blocked) {
  217.                     if (total_bytes_written + bytes_written)
  218.                         return total_bytes_written + bytes_written;
  219.                     else
  220.                         return -EINTR;
  221.                 }
  222.             }
  223.         }
  224.  
  225.         total_bytes_written += bytes_written;
  226.         buf += bytes_written;
  227.         count -= bytes_written;
  228.  
  229.     } while (count > 0);
  230.  
  231.     return total_bytes_written;
  232. }
  233.  
  234. static int lp_write_polled(struct inode * inode, struct file * file,
  235.                char * buf, int count)
  236. {
  237.     int  retval;
  238.     unsigned int minor = MINOR(inode->i_rdev);
  239.     char c, *temp = buf;
  240.  
  241. #ifdef LP_DEBUG
  242.     if (jiffies-lp_last_call > LP_TIME(minor)) {
  243.         lp_total_chars = 0;
  244.         lp_max_count = 1;
  245.     }
  246.     lp_last_call = jiffies;
  247. #endif
  248.  
  249.     temp = buf;
  250.     while (count > 0) {
  251.         c = get_fs_byte(temp);
  252.         retval = lp_char_polled(c, minor);
  253.         /* only update counting vars if character was printed */
  254.         if (retval) { count--; temp++;
  255. #ifdef LP_DEBUG
  256.             lp_total_chars++;
  257. #endif
  258.         }
  259.         if (!retval) { /* if printer timed out */
  260.             int status = LP_S(minor);
  261.  
  262.             if (status & LP_POUTPA) {
  263.                 printk(KERN_INFO "lp%d out of paper\n", minor);
  264.                 if(LP_F(minor) & LP_ABORT)
  265.                     return temp-buf?temp-buf:-ENOSPC;
  266.                 current->state = TASK_INTERRUPTIBLE;
  267.                 current->timeout = jiffies + LP_TIMEOUT_POLLED;
  268.                 schedule();
  269.             } else
  270.             if (!(status & LP_PSELECD)) {
  271.                 printk(KERN_INFO "lp%d off-line\n", minor);
  272.                 if(LP_F(minor) & LP_ABORT)
  273.                     return temp-buf?temp-buf:-EIO;
  274.                 current->state = TASK_INTERRUPTIBLE;
  275.                 current->timeout = jiffies + LP_TIMEOUT_POLLED;
  276.                 schedule();
  277.             } else
  278.                     /* not offline or out of paper. on fire? */
  279.             if (!(status & LP_PERRORP)) {
  280.                 printk(KERN_ERR "lp%d reported invalid error status (on fire, eh?)\n", minor);
  281.                 if(LP_F(minor) & LP_ABORT)
  282.                     return temp-buf?temp-buf:-EIO;
  283.                 current->state = TASK_INTERRUPTIBLE;
  284.                 current->timeout = jiffies + LP_TIMEOUT_POLLED;
  285.                 schedule();
  286.             }
  287.  
  288.             /* check for signals before going to sleep */
  289.             if (current->signal & ~current->blocked) {
  290.                 if (temp != buf)
  291.                     return temp-buf;
  292.                 else
  293.                     return -EINTR;
  294.             }
  295. #ifdef LP_DEBUG
  296.             printk("lp sleeping at %d characters for %d jiffies\n",
  297.                 lp_total_chars, LP_TIME(minor));
  298.             lp_total_chars=0;
  299. #endif
  300.             current->state = TASK_INTERRUPTIBLE;
  301.             current->timeout = jiffies + LP_TIME(minor);
  302.             schedule();
  303.         }
  304.     }
  305.     return temp-buf;
  306. }
  307.  
  308. static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
  309. {
  310.     if (LP_IRQ(MINOR(inode->i_rdev)))
  311.         return lp_write_interrupt(inode, file, buf, count);
  312.     else
  313.         return lp_write_polled(inode, file, buf, count);
  314. }
  315.  
  316. static int lp_lseek(struct inode * inode, struct file * file,
  317.             off_t offset, int origin)
  318. {
  319.     return -ESPIPE;
  320. }
  321.  
  322. static int lp_open(struct inode * inode, struct file * file)
  323. {
  324.     unsigned int minor = MINOR(inode->i_rdev);
  325.     int ret;
  326.     unsigned int irq;
  327.  
  328.     if (minor >= LP_NO)
  329.         return -ENODEV;
  330.     if ((LP_F(minor) & LP_EXIST) == 0)
  331.         return -ENODEV;
  332.     if (LP_F(minor) & LP_BUSY)
  333.         return -EBUSY;
  334.  
  335.     MOD_INC_USE_COUNT;
  336.  
  337.     /* If ABORTOPEN is set and the printer is offline or out of paper,
  338.        we may still want to open it to perform ioctl()s.  Therefore we
  339.        have commandeered O_NONBLOCK, even though it is being used in
  340.        a non-standard manner.  This is strictly a Linux hack, and
  341.        should most likely only ever be used by the tunelp application. */
  342.         if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
  343.         int status = LP_S(minor);
  344.         if (status & LP_POUTPA) {
  345.             printk(KERN_INFO "lp%d out of paper\n", minor);
  346.             MOD_DEC_USE_COUNT;
  347.             return -ENOSPC;
  348.         } else if (!(status & LP_PSELECD)) {
  349.             printk(KERN_INFO "lp%d off-line\n", minor);
  350.             MOD_DEC_USE_COUNT;
  351.             return -EIO;
  352.         } else if (!(status & LP_PERRORP)) {
  353.             printk(KERN_ERR "lp%d printer error\n", minor);
  354.             MOD_DEC_USE_COUNT;
  355.             return -EIO;
  356.         }
  357.     }
  358.  
  359.     if ((irq = LP_IRQ(minor))) {
  360.         lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
  361.         if (!lp_table[minor].lp_buffer) {
  362.             MOD_DEC_USE_COUNT;
  363.             return -ENOMEM;
  364.         }
  365.  
  366.         ret = request_irq(irq, lp_interrupt, SA_INTERRUPT, "printer");
  367.         if (ret) {
  368.             kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
  369.             lp_table[minor].lp_buffer = NULL;
  370.             printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret);
  371.             MOD_DEC_USE_COUNT;
  372.             return ret;
  373.         }
  374.     }
  375.  
  376.     LP_F(minor) |= LP_BUSY;
  377.     return 0;
  378. }
  379.  
  380. static void lp_release(struct inode * inode, struct file * file)
  381. {
  382.     unsigned int minor = MINOR(inode->i_rdev);
  383.     unsigned int irq;
  384.  
  385.     if ((irq = LP_IRQ(minor))) {
  386.         free_irq(irq);
  387.         kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
  388.         lp_table[minor].lp_buffer = NULL;
  389.     }
  390.  
  391.     LP_F(minor) &= ~LP_BUSY;
  392.     MOD_DEC_USE_COUNT;
  393. }
  394.  
  395.  
  396. static int lp_ioctl(struct inode *inode, struct file *file,
  397.             unsigned int cmd, unsigned long arg)
  398. {
  399.     unsigned int minor = MINOR(inode->i_rdev);
  400.     int retval = 0;
  401.  
  402. #ifdef LP_DEBUG
  403.     printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
  404. #endif
  405.     if (minor >= LP_NO)
  406.         return -ENODEV;
  407.     if ((LP_F(minor) & LP_EXIST) == 0)
  408.         return -ENODEV;
  409.     if (cmd <= OLD_IOCTL_MAX)
  410.         printk(KERN_NOTICE "lp%d: warning: obsolete ioctl %#x (perhaps you need a new tunelp)\n",
  411.             minor, cmd);
  412.     switch ( cmd ) {
  413.         case OLD_LPTIME:
  414.         case LPTIME:
  415.             LP_TIME(minor) = arg;
  416.             break;
  417.         case OLD_LPCHAR:
  418.         case LPCHAR:
  419.             LP_CHAR(minor) = arg;
  420.             break;
  421.         case OLD_LPABORT:
  422.         case LPABORT:
  423.             if (arg)
  424.                 LP_F(minor) |= LP_ABORT;
  425.             else
  426.                 LP_F(minor) &= ~LP_ABORT;
  427.             break;
  428.         case LPABORTOPEN:
  429.             if (arg)
  430.                 LP_F(minor) |= LP_ABORTOPEN;
  431.             else
  432.                 LP_F(minor) &= ~LP_ABORTOPEN;
  433.             break;
  434.         case LPCAREFUL:
  435.             if (arg)
  436.                 LP_F(minor) |= LP_CAREFUL;
  437.             else
  438.                 LP_F(minor) &= ~LP_CAREFUL;
  439.             break;
  440.         case OLD_LPWAIT:
  441.         case LPWAIT:
  442.             LP_WAIT(minor) = arg;
  443.             break;
  444.         case OLD_LPSETIRQ:
  445.         case LPSETIRQ: {
  446.             int oldirq;
  447.             int newirq = arg;
  448.             struct lp_struct *lp = &lp_table[minor];
  449.  
  450.             if (!suser())
  451.                 return -EPERM;
  452.  
  453.             oldirq = LP_IRQ(minor);
  454.  
  455.             /* Allocate buffer now if we are going to need it */
  456.             if (!oldirq && newirq) {
  457.                 lp->lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
  458.                 if (!lp->lp_buffer)
  459.                     return -ENOMEM;
  460.             }
  461.  
  462.             if (oldirq) {
  463.                 free_irq(oldirq);
  464.             }
  465.             if (newirq) {
  466.                 /* Install new irq */
  467.                 if ((retval = request_irq(newirq, lp_interrupt, SA_INTERRUPT, "printer"))) {
  468.                     if (oldirq) {
  469.                         /* restore old irq */
  470.                         request_irq(oldirq, lp_interrupt, SA_INTERRUPT, "printer");
  471.                     } else {
  472.                         /* We don't need the buffer */
  473.                         kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
  474.                         lp->lp_buffer = NULL;
  475.                     }
  476.                     return retval;
  477.                 }
  478.             }
  479.             if (oldirq && !newirq) {
  480.                 /* We don't need the buffer */
  481.                 kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
  482.                 lp->lp_buffer = NULL;
  483.             }
  484.             LP_IRQ(minor) = newirq;
  485.             lp_reset(minor);
  486.             break;
  487.         }
  488.         case OLD_LPGETIRQ:
  489.             retval = LP_IRQ(minor);
  490.             break;
  491.         case LPGETIRQ:
  492.             retval = verify_area(VERIFY_WRITE, (void *) arg,
  493.                 sizeof(int));
  494.                 if (retval)
  495.                     return retval;
  496.             memcpy_tofs((int *) arg, &LP_IRQ(minor), sizeof(int));
  497.             break;
  498.         case LPGETSTATUS:
  499.             retval = verify_area(VERIFY_WRITE, (void *) arg,
  500.                 sizeof(int));
  501.                 if (retval)
  502.                     return retval;
  503.             else {
  504.                 int status = LP_S(minor);
  505.                 memcpy_tofs((int *) arg, &status, sizeof(int));
  506.             }
  507.             break;
  508.         case LPRESET:
  509.             lp_reset(minor);
  510.             break;
  511.         default:
  512.             retval = -EINVAL;
  513.     }
  514.     return retval;
  515. }
  516.  
  517.  
  518. static struct file_operations lp_fops = {
  519.     lp_lseek,
  520.     NULL,        /* lp_read */
  521.     lp_write,
  522.     NULL,        /* lp_readdir */
  523.     NULL,        /* lp_select */
  524.     lp_ioctl,
  525.     NULL,        /* lp_mmap */
  526.     lp_open,
  527.     lp_release
  528. };
  529.  
  530. #ifndef MODULE
  531.  
  532. long lp_init(long kmem_start)
  533. {
  534.     int offset = 0;
  535.     unsigned int testvalue = 0;
  536.     int count = 0;
  537.  
  538.     if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
  539.         printk("unable to get major %d for line printer\n", LP_MAJOR);
  540.         return kmem_start;
  541.     }
  542.     /* take on all known port values */
  543.     for (offset = 0; offset < LP_NO; offset++) {
  544.         if (check_region(LP_B(offset), 3))
  545.             continue;
  546.         /* write to port & read back to check */
  547.         outb_p( LP_DUMMY, LP_B(offset));
  548.         for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
  549.             ;
  550.         testvalue = inb_p(LP_B(offset));
  551.         if (testvalue == LP_DUMMY) {
  552.             LP_F(offset) |= LP_EXIST;
  553.             lp_reset(offset);
  554.             printk("lp%d at 0x%04x, ", offset,LP_B(offset));
  555.             request_region(LP_B(offset), 3, "lp");
  556.             if (LP_IRQ(offset))
  557.                 printk("using IRQ%d\n", LP_IRQ(offset));
  558.             else
  559.                 printk("using polling driver\n");
  560.             count++;
  561.         }
  562.     }
  563.     if (count == 0)
  564.         printk("lp_init: no lp devices found\n");
  565.     return kmem_start;
  566. }
  567.  
  568. #else
  569.  
  570. char kernel_version[]= UTS_RELEASE;
  571.  
  572. int init_module(void)
  573. {
  574.     int offset = 0;
  575.     unsigned int testvalue = 0;
  576.     int count = 0;
  577.  
  578.     if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
  579.         printk("unable to get major %d for line printer\n", LP_MAJOR);
  580.         return -EIO;
  581.     }
  582.     /* take on all known port values */
  583.     for (offset = 0; offset < LP_NO; offset++) {
  584.         /* write to port & read back to check */
  585.         outb_p( LP_DUMMY, LP_B(offset));
  586.         for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
  587.             ;
  588.         testvalue = inb_p(LP_B(offset));
  589.         if (testvalue == LP_DUMMY) {
  590.             LP_F(offset) |= LP_EXIST;
  591.             lp_reset(offset);
  592.             printk("lp%d at 0x%04x, ", offset,LP_B(offset));
  593.             request_region(LP_B(offset),3,"lp");
  594.             if (LP_IRQ(offset))
  595.                 printk("using IRQ%d\n", LP_IRQ(offset));
  596.             else
  597.                 printk("using polling driver\n");
  598.             count++;
  599.         }
  600.     }
  601.     if (count == 0)
  602.         printk("lp_init: no lp devices found\n");
  603.     return 0;
  604. }
  605.  
  606. void cleanup_module(void)
  607. {
  608.         int offset;
  609.     if(MOD_IN_USE)
  610.                printk("lp: busy - remove delayed\n");
  611.         else
  612.                unregister_chrdev(LP_MAJOR,"lp");
  613.            for (offset = 0; offset < LP_NO; offset++) 
  614.             if(LP_F(offset) && LP_EXIST) 
  615.                  release_region(LP_B(offset),3);
  616. }
  617.  
  618. #endif
  619.