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  * Copyright (C) 1992 by Jim Weigand, Linus Torvalds, and Michael K. Johnson
   3  */
   4 
   5 #include <linux/lp.h>
   6 /* sched.h is included from lp.h */
   7 
   8 static int lp_reset(int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
   9 {
  10         int testvalue;
  11 
  12         /* reset value */
  13         outb(0, LP_C(minor));
  14         for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
  15                 ;
  16         outb(LP_PSELECP | LP_PINITP, LP_C(minor));
  17         return LP_S(minor);
  18 }
  19 
  20 static int lp_char(char lpchar, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  21 {
  22         int retval = 0;
  23         unsigned long count  = 0; 
  24 
  25         outb(lpchar, LP_B(minor));
  26         do {
  27                 retval = LP_S(minor);
  28                 count ++;
  29                 if (need_resched)
  30                         schedule();
  31         } while(!(retval & LP_PBUSY) && count < LP_TIME_CHAR);
  32 
  33         if (count == LP_TIME_CHAR) {
  34                 return 0;
  35                 /* we timed out, and the character was /not/ printed */
  36         }
  37         /* control port takes strobe high */
  38         outb(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
  39         /* take strobe low */
  40         outb(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
  41        /* get something meaningful for return value */
  42         return LP_S(minor);
  43 }
  44 
  45 static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47         int  retval;
  48         unsigned int minor = MINOR(inode->i_rdev);
  49         unsigned int each_cnt = 0, old_cnt = 0;
  50         char c, *temp = buf;
  51 
  52         temp = buf;
  53         while (count > 0) {
  54                 c = get_fs_byte(temp);
  55                 retval = lp_char(c, minor);
  56                 /* only update counting vars if character was printed */
  57                 if (retval) {
  58                         count--;
  59                         temp++;
  60                 }
  61 
  62                 if (!retval) { /* if printer timed out */
  63                         each_cnt = count - old_cnt;
  64                         old_cnt = count;
  65 
  66                         /* here we do calculations based on old count
  67                            and change the time that we will sleep.
  68                            For now this will be hard coded... */
  69 
  70                         /* check for signals before going to sleep */
  71                         if (current->signal & ~current->blocked) {
  72                                 return temp-buf?temp-buf:-ERESTARTSYS;
  73                         }
  74                         current->state = TASK_INTERRUPTIBLE;
  75                         current->timeout = jiffies + LP_TIME(minor);
  76                         schedule();
  77                         LP_COUNT(minor) = each_cnt;
  78 
  79                         /* the following is ugly, but should alert me if
  80                            something dreadful is going on. It will disappear
  81                            in the final versions of the driver. */
  82                         if (!(LP_S(minor) & LP_BUSY)) {
  83                                 current->state = TASK_INTERRUPTIBLE;
  84                                 current->timeout = jiffies + LP_TIMEOUT;
  85                                 schedule();
  86                                 if (!(LP_S(minor) & LP_BUSY))
  87                                         printk("lp%d timeout\n\r", minor);
  88                         }
  89                 } else {
  90                         if (retval & LP_POUTPA) {
  91                                 LP_F(minor) |= LP_NOPA;
  92                                 printk("lp%d out of paper\n\r", minor);
  93                                 return temp-buf?temp-buf:-ENOSPC;
  94                         } else
  95                                 LP_F(minor) &= ~LP_NOPA;
  96 
  97                         if (!(retval & LP_PSELECD)) {
  98                                 LP_F(minor) |= LP_SELEC;
  99                                 printk("lp%d off-line\n\r", minor);
 100                                 return temp-buf?temp-buf:-EFAULT;
 101                         } else
 102                                 LP_F(minor) &= ~LP_SELEC;
 103 
 104                         /* not offline or out of paper. on fire? */
 105                         if (!(retval & LP_PERRORP)) {
 106                                 LP_F(minor) |= LP_ERR;
 107                                 printk("lp%d on fire\n\r", minor);
 108                                 return temp-buf?temp-buf:-EIO;
 109                         } else
 110                                 LP_F(minor) &= ~LP_SELEC;
 111                 }
 112         }
 113         return temp-buf;
 114 }
 115 
 116 static int lp_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 117 {
 118         return -EINVAL;
 119 }
 120 
 121 static int lp_lseek(struct inode * inode, struct file * file, off_t offset, int origin)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         return -EINVAL;
 124 }
 125 
 126 static int lp_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128         unsigned int minor = MINOR(inode->i_rdev);
 129 
 130         if (minor >= LP_NO)
 131                 return -ENODEV;
 132         if ((LP_F(minor) & LP_EXIST) == 0)
 133                 return -ENODEV;
 134         if (LP_F(minor) & LP_BUSY)
 135                 return -EBUSY;
 136         LP_F(minor) |= LP_BUSY;
 137         return 0;
 138 }
 139 
 140 static void lp_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142         unsigned int minor = MINOR(inode->i_rdev);
 143 
 144         LP_F(minor) &= ~LP_BUSY;
 145 }
 146 
 147 static struct file_operations lp_fops = {
 148         lp_lseek,       /* why not null? */
 149         lp_read,        /* why not null? */
 150         lp_write,
 151         NULL,           /* lp_readdir */
 152         NULL,           /* lp_select */
 153         NULL,           /* lp_ioctl */
 154         NULL,           /* mmap */
 155         lp_open,
 156         lp_release
 157 };
 158 
 159 long lp_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         int offset = 0;
 162         unsigned int testvalue = 0;
 163         int count = 0;
 164 
 165         chrdev_fops[6] = &lp_fops;
 166         /* take on all known port values */
 167         for (offset = 0; offset < LP_NO; offset++) {
 168                 /* write to port & read back to check */
 169                 outb( LP_DUMMY, LP_B(offset));
 170                 for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
 171                         ;
 172                 testvalue = inb(LP_B(offset));
 173                 if (testvalue != 255) {
 174                         LP_F(offset) |= LP_EXIST;
 175                         lp_reset(offset);
 176                         printk("lp_init: lp%d exists (%d)\n", offset, testvalue);
 177                         count++;
 178                 }
 179         }
 180         if (count == 0)
 181                 printk("lp_init: no lp devices found\n");
 182         return kmem_start;
 183 }

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