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

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