root/kernel/chr_drv/lp.c

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

DEFINITIONS

This source file includes following definitions.
  1. lp_reset
  2. lp_char
  3. lp_write
  4. lp_read
  5. lp_lseek
  6. lp_open
  7. lp_release
  8. lp_init

   1 /*
   2  $Header: /usr/src/linux/kernel/chr_drv/lp.c,v 1.9 1992/01/06 16:11:19
   3   james_r_wiegand Exp james_r_wiegand $
   4 */
   5 
   6 /*
   7  * Edited by Linus - cleaner interface etc. Still not using interrupts, so
   8  * it eats more resources than necessary, but it was easy to code this way...
   9  */
  10 
  11 #include <linux/sched.h>
  12 #include <linux/lp.h>
  13 
  14 static int lp_reset(int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  15 {
  16         int testvalue;
  17 
  18         /* reset value */
  19         outb(0, LP_B(minor)+2);
  20         for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
  21                 ;
  22         outb(LP_PSELECP | LP_PINITP, LP_B(minor)+2);
  23         return LP_S(minor);
  24 }
  25 
  26 static int lp_char(char lpchar, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  27 {
  28         int retval = 0;
  29         unsigned long count  = 0; 
  30 
  31         outb(lpchar, LP_B(minor));
  32         do {
  33                 retval = LP_S(minor);
  34                 schedule(); 
  35                 count ++;
  36         } while(!(retval & LP_PBUSY) && count < LP_TIMEOUT);
  37         if (count == LP_TIMEOUT) {
  38                 printk("lp%d timeout\n\r", minor);
  39                 return 0;
  40         }
  41   /* control port pr_table[0]+2 take strobe high */
  42         outb(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_B( minor ) + 2 ));
  43   /* take strobe low */
  44         outb(( LP_PSELECP | LP_PINITP ), ( LP_B( minor ) + 2 ));
  45   /* get something meaningful for return value */
  46         return LP_S(minor);
  47 }
  48 
  49 static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51         int  retval;
  52         unsigned int minor = MINOR(inode->i_rdev);
  53         char c, *temp = buf;
  54 
  55         temp = buf;
  56         while (count > 0) {
  57                 c = get_fs_byte(temp++);
  58                 retval = lp_char(c, minor);
  59                 count--;
  60                 if (retval & LP_POUTPA) {
  61                         LP_F(minor) |= LP_NOPA;
  62                         return temp-buf?temp-buf:-ENOSPC;
  63                 } else
  64                         LP_F(minor) &= ~LP_NOPA;
  65 
  66                 if (!(retval & LP_PSELECD)) {
  67                         LP_F(minor) &= ~LP_SELEC;
  68                         return temp-buf?temp-buf:-EFAULT;
  69                 } else
  70                         LP_F(minor) &= ~LP_SELEC;
  71 
  72     /* not offline or out of paper. on fire? */
  73                 if (!(retval & LP_PERRORP)) {
  74                         LP_F(minor) |= LP_ERR;
  75                         return temp-buf?temp-buf:-EIO;
  76                 } else
  77                         LP_F(minor) &= ~LP_SELEC;
  78         }
  79         return temp-buf;
  80 }
  81 
  82 static int lp_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84         return -EINVAL;
  85 }
  86 
  87 static int lp_lseek(struct inode * inode, struct file * file, off_t offset, int origin)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89         return -EINVAL;
  90 }
  91 
  92 static int lp_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         unsigned int minor = MINOR(inode->i_rdev);
  95 
  96         if (minor >= LP_NO)
  97                 return -ENODEV;
  98         if ((LP_F(minor) & LP_EXIST) == 0)
  99                 return -ENODEV;
 100         if (LP_F(minor) & LP_BUSY)
 101                 return -EBUSY;
 102         LP_F(minor) |= LP_BUSY;
 103         return 0;
 104 }
 105 
 106 static void lp_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         unsigned int minor = MINOR(inode->i_rdev);
 109 
 110         LP_F(minor) &= ~LP_BUSY;
 111 }
 112 
 113 static struct file_operations lp_fops = {
 114         lp_lseek,
 115         lp_read,
 116         lp_write,
 117         NULL,           /* lp_readdir */
 118         NULL,           /* lp_select */
 119         NULL,           /* lp_ioctl */
 120         lp_open,
 121         lp_release
 122 };
 123 
 124 long lp_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         int offset = 0;
 127         unsigned int testvalue = 0;
 128         int count = 0;
 129 
 130         chrdev_fops[6] = &lp_fops;
 131         /* take on all known port values */
 132         for (offset = 0; offset < LP_NO; offset++) {
 133                 /* write to port & read back to check */
 134                 outb( LP_DUMMY, LP_B(offset));
 135                 for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
 136                         ;
 137                 testvalue = inb(LP_B(offset));
 138                 if (testvalue != 255) {
 139                         LP_F(offset) |= LP_EXIST;
 140                         lp_reset(offset);
 141                         printk("lp_init: lp%d exists (%d)\n", offset, testvalue);
 142                         count++;
 143                 }
 144         }
 145         if (count == 0)
 146                 printk("lp_init: no lp devices found\n");
 147         return kmem_start;
 148 }

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