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_lseek
  5. lp_open
  6. lp_release
  7. lp_ioctl
  8. lp_init

   1 /* Copyright (C) 1992 by Jim Weigand, Linus Torvalds, and Michael K. Johnson
   2 */
   3 
   4 #include <linux/lp.h>
   5 /* sched.h is included from lp.h */
   6 
   7 /* 
   8  * All my debugging code assumes that you debug with only one printer at
   9  * a time. RWWH
  10  */
  11 
  12 #undef LP_DEBUG
  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_C(minor));
  20         for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
  21                 ;
  22         outb(LP_PSELECP | LP_PINITP, LP_C(minor));
  23         return LP_S(minor);
  24 }
  25 
  26 #ifdef LP_DEBUG
  27 static int lp_max_count = 1;
  28 #endif
  29 
  30 static int lp_char(char lpchar, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32         int retval = 0, wait = 0;
  33         unsigned long count  = 0; 
  34 
  35         outb(lpchar, LP_B(minor));
  36         do {
  37                 retval = LP_S(minor);
  38                 count ++;
  39                 if(need_resched)
  40                         schedule();
  41         } while(!(retval & LP_PBUSY) && count < LP_CHAR(minor));
  42 
  43         if (count == LP_CHAR(minor)) {
  44                 return 0;
  45                 /* we timed out, and the character was /not/ printed */
  46         }
  47 #ifdef LP_DEBUG
  48         if (count > lp_max_count) {
  49                 printk("lp success after %d counts.\n",count);
  50                 lp_max_count=count;
  51         }
  52 #endif
  53         /* must wait before taking strobe high, and after taking strobe
  54            low, according spec.  Some printers need it, others don't. */
  55         while(wait != LP_WAIT(minor)) wait++;
  56         /* control port takes strobe high */
  57         outb(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
  58         while(wait) wait--;
  59         /* take strobe low */
  60         outb(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
  61        /* get something meaningful for return value */
  62         return LP_S(minor);
  63 }
  64 
  65 #ifdef LP_DEBUG
  66         unsigned int lp_total_chars = 0;
  67         unsigned int lp_last_call = 0;
  68 #endif
  69 
  70 static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         int  retval;
  73         unsigned int minor = MINOR(inode->i_rdev);
  74         char c, *temp = buf;
  75 
  76 #ifdef LP_DEBUG
  77         if (jiffies-lp_last_call > LP_TIME(minor)) {
  78                 lp_total_chars = 0;
  79                 lp_max_count = 1;
  80         }
  81         lp_last_call = jiffies;
  82 #endif
  83 
  84         temp = buf;
  85         while (count > 0) {
  86                 c = get_fs_byte(temp);
  87                 retval = lp_char(c, minor);
  88                 /* only update counting vars if character was printed */
  89                 if (retval) { count--; temp++;
  90 #ifdef LP_DEBUG
  91                         lp_total_chars++;
  92 #endif
  93                 }
  94                 if (!retval) { /* if printer timed out */
  95                         /* check for signals before going to sleep */
  96                         if (current->signal & ~current->blocked) {
  97                                 if (count > 0) return -EINTR;
  98                         }
  99 #ifdef LP_DEBUG
 100                         printk("lp sleeping at %d characters for %d jiffies\n",
 101                                 lp_total_chars, LP_TIME(minor));
 102                         lp_total_chars=0;
 103 #endif
 104                         current->state = TASK_INTERRUPTIBLE;
 105                         current->timeout = jiffies + LP_TIME(minor);
 106                         schedule();
 107 
 108                         /* If nothing is getting to the printer
 109                            for a considerable length of time,
 110                            someone oughtta know.  */
 111                         if (!(LP_S(minor) & LP_BUSY)) {
 112                                 current->state = TASK_INTERRUPTIBLE;
 113                                 current->timeout = jiffies + LP_TIMEOUT;
 114                                 schedule();
 115                                 if (!(LP_S(minor) & LP_BUSY))
 116                                         printk("lp%d timeout\n", minor);
 117                         }
 118                 } else {
 119                         if (retval & LP_POUTPA) {
 120                                 printk("lp%d out of paper\n", minor);
 121                                 if(LP_F(minor) && LP_ABORT)
 122                                         return temp-buf?temp-buf:-ENOSPC;
 123                                 current->state = TASK_INTERRUPTIBLE;
 124                                 current->timeout = jiffies + LP_TIMEOUT;
 125                                 schedule();
 126                         } else
 127 
 128                         if (!(retval & LP_PSELECD)) {
 129                                 printk("lp%d off-line\n", minor);
 130                                 if(LP_F(minor) && LP_ABORT)
 131                                         return temp-buf?temp-buf:-EIO;
 132                                 current->state = TASK_INTERRUPTIBLE;
 133                                 current->timeout = jiffies + LP_TIMEOUT;
 134                                 schedule();
 135                         } else
 136 
 137                         /* not offline or out of paper. on fire? */
 138                         if (!(retval & LP_PERRORP)) {
 139                                 printk("lp%d on fire\n", minor);
 140                                 if(LP_F(minor) && LP_ABORT)
 141                                         return temp-buf?temp-buf:-EFAULT;
 142                                 current->state = TASK_INTERRUPTIBLE;
 143                                 current->timeout = jiffies + LP_TIMEOUT;
 144                                 schedule();
 145                         }
 146                 }
 147         }
 148         return temp-buf;
 149 }
 150 
 151 
 152 static int lp_lseek(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 153                     off_t offset, int origin)
 154 {
 155         return -EINVAL;
 156 }
 157 
 158 static int lp_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160         unsigned int minor = MINOR(inode->i_rdev);
 161 
 162         if (minor >= LP_NO)
 163                 return -ENODEV;
 164         if ((LP_F(minor) & LP_EXIST) == 0)
 165                 return -ENODEV;
 166         if (LP_F(minor) & LP_BUSY)
 167                 return -EBUSY;
 168         LP_F(minor) |= LP_BUSY;
 169         return 0;
 170 }
 171 
 172 static void lp_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         unsigned int minor = MINOR(inode->i_rdev);
 175 
 176         LP_F(minor) &= ~LP_BUSY;
 177 }
 178 
 179 
 180 static int lp_ioctl(struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 181                     unsigned int cmd, unsigned int arg)
 182 {
 183         unsigned int minor = MINOR(inode->i_rdev);
 184 
 185 #ifdef LP_DEBUG
 186         printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
 187 #endif
 188         if (minor >= LP_NO)
 189                 return -ENODEV;
 190         if ((LP_F(minor) & LP_EXIST) == 0)
 191                 return -ENODEV;
 192         switch ( cmd ) {
 193                 case LPTIME:
 194                         LP_TIME(minor) = arg;
 195                         break;
 196                 case LPCHAR:
 197                         LP_CHAR(minor) = arg;
 198                         break;
 199                 case LPABORT:
 200                         if(arg)
 201                                 LP_F(minor) |= LP_ABORT;
 202                         else    LP_F(minor) &= ~LP_ABORT;
 203                         break;
 204                 case LPWAIT:
 205                         LP_WAIT(minor) = arg;
 206                         break;
 207                 default: arg = -EINVAL;
 208         }
 209         return arg;
 210 }
 211 
 212 
 213 static struct file_operations lp_fops = {
 214         lp_lseek,
 215         NULL,           /* lp_read */
 216         lp_write,
 217         NULL,           /* lp_readdir */
 218         NULL,           /* lp_select */
 219         lp_ioctl,
 220         NULL,           /* lp_mmap */
 221         lp_open,
 222         lp_release
 223 };
 224 
 225 long lp_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 226 {
 227         int offset = 0;
 228         unsigned int testvalue = 0;
 229         int count = 0;
 230 
 231         chrdev_fops[6] = &lp_fops;
 232         /* take on all known port values */
 233         for (offset = 0; offset < LP_NO; offset++) {
 234                 /* write to port & read back to check */
 235                 outb( LP_DUMMY, LP_B(offset));
 236                 for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
 237                         ;
 238                 testvalue = inb(LP_B(offset));
 239                 if (testvalue != 255) {
 240                         LP_F(offset) |= LP_EXIST;
 241                         lp_reset(offset);
 242                         printk("lp_init: lp%d exists (%d)\n", offset, testvalue);
 243                         count++;
 244                 }
 245         }
 246         if (count == 0)
 247                 printk("lp_init: no lp devices found\n");
 248         return kmem_start;
 249 }

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