root/drivers/char/lp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lp_reset
  2. lp_char_polled
  3. lp_char_interrupt
  4. lp_interrupt
  5. lp_write_interrupt
  6. lp_write_polled
  7. lp_write
  8. lp_lseek
  9. lp_open
  10. lp_release
  11. lp_ioctl
  12. lp_probe
  13. lp_init
  14. cleanup_module

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

/* [previous][next][first][last][top][bottom][index][help] */