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_readdir
  7. 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         if (minor >= LP_NO)
  57                 return -ENODEV;
  58         if ((LP_F(minor) & LP_EXIST) == 0)
  59                 return -ENODEV;
  60         LP_T(minor) = current->pid;
  61         LP_F(minor) |= LP_BUSY;
  62         LP_R(minor) = count;
  63         temp = buf;
  64         while (count > 0) {
  65                 c = get_fs_byte(temp++);
  66                 retval = lp_char(c, minor);
  67                 count--;
  68                 if (retval & LP_POUTPA) {
  69                         LP_F(minor) |= LP_NOPA;
  70                         return temp-buf?temp-buf:-ENOSPC;
  71                 } else
  72                         LP_F(minor) &= ~LP_NOPA;
  73 
  74                 if (!(retval & LP_PSELECD)) {
  75                         LP_F(minor) &= ~LP_SELEC;
  76                         return temp-buf?temp-buf:-EFAULT;
  77                 } else
  78                         LP_F(minor) &= ~LP_SELEC;
  79 
  80     /* not offline or out of paper. on fire? */
  81                 if (!(retval & LP_PERRORP)) {
  82                         LP_F(minor) |= LP_ERR;
  83                         return temp-buf?temp-buf:-EIO;
  84                 } else
  85                         LP_F(minor) &= ~LP_SELEC;
  86         }
  87         return temp-buf;
  88 }
  89 
  90 static int lp_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         return -EINVAL;
  93 }
  94 
  95 static int lp_lseek(struct inode * inode, struct file * file, off_t offset, int origin)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         return -EINVAL;
  98 }
  99 
 100 static int lp_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         return -ENOTDIR;
 103 }
 104 
 105 static struct file_operations lp_fops = {
 106         lp_lseek,
 107         lp_read,
 108         lp_write,
 109         lp_readdir,
 110         NULL,           /* lp_close */
 111         NULL,           /* lp_select */
 112         NULL            /* lp_ioctl */
 113 };
 114 
 115 void lp_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         int offset = 0;
 118         unsigned int testvalue = 0;
 119         int count = 0;
 120 
 121         chrdev_fops[6] = &lp_fops;
 122         /* take on all known port values */
 123         for (offset = 0; offset < LP_NO; offset++) {
 124                 /* write to port & read back to check */
 125                 outb( LP_DUMMY, LP_B(offset));
 126                 for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
 127                         ;
 128                 testvalue = inb(LP_B(offset));
 129                 if (testvalue != 255) {
 130                         LP_F(offset) |= LP_EXIST;
 131                         lp_reset(offset);
 132                         printk("lp_init: lp%d exists (%d)\n", offset, testvalue);
 133                         count++;
 134                 }
 135         }
 136         if (count == 0)
 137                 printk("lp_init: no lp devices found\n");
 138 }

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