ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / char / lp_old98.c
1 /*
2  *      linux/drivers/char/lp_old98.c
3  *
4  * printer port driver for ancient PC-9800s with no bidirectional port support
5  *
6  * Copyright (C)  1998,99  Kousuke Takai <tak@kmc.kyoto-u.ac.jp>,
7  *                         Kyoto University Microcomputer Club
8  *
9  * This driver is based on and has compatibility with `lp.c',
10  * generic PC printer port driver.
11  */
12
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/config.h>
16 #include <linux/errno.h>
17 #include <linux/kernel.h>
18 #include <linux/major.h>
19 #include <linux/sched.h>
20 #include <linux/slab.h>
21 #include <linux/spinlock.h>
22 #include <linux/ioport.h>
23 #include <linux/fcntl.h>
24 #include <linux/delay.h>
25 #include <linux/console.h>
26 #include <linux/fs.h>
27
28 #include <asm/io.h>
29 #include <asm/uaccess.h>
30 #include <asm/system.h>
31
32 #include <linux/lp.h>
33
34 /*
35  *  I/O port numbers
36  */
37 #define LP_PORT_DATA    0x40
38 #define LP_PORT_STATUS  (LP_PORT_DATA + 2)
39 #define LP_PORT_STROBE  (LP_PORT_DATA + 4)
40 #define LP_PORT_CONTROL (LP_PORT_DATA + 6)
41
42 #define LP_PORT_H98MODE 0x0448
43 #define LP_PORT_EXTMODE 0x0149
44
45 /*
46  *  bit mask for I/O
47  */
48 #define LP_MASK_nBUSY   (1 << 2)
49 #define LP_MASK_nSTROBE (1 << 7)
50
51 #define LP_CONTROL_ASSERT_STROBE        (0x0e)
52 #define LP_CONTROL_NEGATE_STROBE        (0x0f)
53
54 /*
55  *  Acceptable maximum value for non-privileged user for LPCHARS ioctl.
56  */
57 #define LP_CHARS_NOPRIV_MAX     65535
58
59 #define DC1     '\x11'
60 #define DC3     '\x13'
61
62 /* PC-9800s have at least and at most one old-style printer port. */
63 static struct lp_struct lp = {
64         .flags  = LP_EXIST | LP_ABORTOPEN,
65         .chars  = LP_INIT_CHAR,
66         .time   = LP_INIT_TIME,
67         .wait   = LP_INIT_WAIT,
68 };
69
70 static  int     dc1_check;
71 static spinlock_t lp_old98_lock = SPIN_LOCK_UNLOCKED;
72
73
74 #undef LP_OLD98_DEBUG
75
76 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
77 static struct console lp_old98_console;         /* defined later */
78 static short saved_console_flags;
79 #endif
80
81 static DECLARE_WAIT_QUEUE_HEAD (lp_old98_waitq);
82
83 static void lp_old98_timer_function(unsigned long data)
84 {
85         if (inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
86                 wake_up_interruptible(&lp_old98_waitq);
87         else {
88                 struct timer_list *t = (struct timer_list *) data;
89
90                 t->expires = jiffies + 1;
91                 add_timer(t);
92         }
93 }
94
95 static inline int lp_old98_wait_ready(void)
96 {
97         struct timer_list timer;
98
99         init_timer(&timer);
100         timer.function = lp_old98_timer_function;
101         timer.expires = jiffies + 1;
102         timer.data = (unsigned long)&timer;
103         add_timer(&timer);
104         interruptible_sleep_on(&lp_old98_waitq);
105         del_timer(&timer);
106         return signal_pending(current);
107 }
108
109 static inline int lp_old98_char(char lpchar)
110 {
111         unsigned long count = 0;
112 #ifdef LP_STATS
113         int tmp;
114 #endif
115
116         while (!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY)) {
117                 count++;
118                 if (count >= lp.chars)
119                         return 0;
120         }
121
122         outb(lpchar, LP_PORT_DATA);
123
124 #ifdef LP_STATS
125         /*
126          *  Update lp statsistics here (and between next two outb()'s).
127          *  Time to compute it is part of storobe delay.
128          */
129         if (count > lp.stats.maxwait) {
130 #ifdef LP_OLD98_DEBUG
131                 printk(KERN_DEBUG "lp_old98: success after %d counts.\n",
132                        count);
133 #endif
134                 lp.stats.maxwait = count;
135         }
136         count *= 256;
137         tmp = count - lp.stats.meanwait;
138         if (tmp < 0)
139                 tmp = -tmp;
140 #endif
141         ndelay(lp.wait);
142     
143         /* negate PSTB# (activate strobe)       */
144         outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
145
146 #ifdef LP_STATS
147         lp.stats.meanwait = (255 * lp.stats.meanwait + count + 128) / 256;
148         lp.stats.mdev = (127 * lp.stats.mdev + tmp + 64) / 128;
149         lp.stats.chars ++;
150 #endif
151
152         ndelay(lp.wait);
153
154         /* assert PSTB# (deactivate strobe)     */
155         outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
156
157         return 1;
158 }
159
160 static ssize_t lp_old98_write(struct file * file,
161                               const char * buf, size_t count,
162                               loff_t *dummy)
163 {
164         unsigned long total_bytes_written = 0;
165
166         if (!access_ok(VERIFY_READ, buf, count))
167                 return -EFAULT;
168
169 #ifdef LP_STATS
170         if (jiffies - lp.lastcall > lp.time)
171                 lp.runchars = 0;
172         lp.lastcall = jiffies;
173 #endif
174
175         do {
176                 unsigned long bytes_written = 0;
177                 unsigned long copy_size
178                         = (count < LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
179
180                 if (__copy_from_user(lp.lp_buffer, buf, copy_size))
181                         return -EFAULT;
182
183                 while (bytes_written < copy_size) {
184                         if (lp_old98_char(lp.lp_buffer[bytes_written]))
185                                 bytes_written ++;
186                         else {
187 #ifdef LP_STATS
188                                 int rc = lp.runchars + bytes_written;
189
190                                 if (rc > lp.stats.maxrun)
191                                         lp.stats.maxrun = rc;
192
193                                 lp.stats.sleeps ++;
194 #endif
195 #ifdef LP_OLD98_DEBUG
196                                 printk(KERN_DEBUG
197                                        "lp_old98: sleeping at %d characters"
198                                        " for %d jiffies\n",
199                                        lp.runchars, lp.time);
200                                 lp.runchars = 0;
201 #endif
202                                 if (lp_old98_wait_ready())
203                                         return ((total_bytes_written
204                                                  + bytes_written)
205                                                 ? : -EINTR);
206                         }
207                 }
208                 total_bytes_written += bytes_written;
209                 buf += bytes_written;
210 #ifdef LP_STATS
211                 lp.runchars += bytes_written;
212 #endif
213                 count -= bytes_written;
214         } while (count > 0);
215
216         return total_bytes_written;
217 }
218
219 static int lp_old98_open(struct inode * inode, struct file * file)
220 {
221         if (iminor(inode) != 0)
222                 return -ENXIO;
223
224         if (lp.flags & LP_BUSY)
225                 return -EBUSY;
226
227         if (dc1_check && (lp.flags & LP_ABORTOPEN)
228             && !(file->f_flags & O_NONBLOCK)) {
229                 /*
230                  *  Check whether printer is on-line.
231                  *  PC-9800's old style port have only BUSY# as status input,
232                  *  so that it is impossible to distinguish that the printer is
233                  *  ready and that the printer is off-line or not connected
234                  *  (in both case BUSY# is in the same state). So:
235                  *
236                  *    (1) output DC1 (0x11) to printer port and do strobe.
237                  *    (2) watch BUSY# line for a while. If BUSY# is pulled
238                  *        down, the printer will be ready. Otherwise,
239                  *        it will be off-line (or not connected, or power-off,
240                  *         ...).
241                  *
242                  *  The source of this procedure:
243                  *      Terumasa KODAKA, Kazufumi SHIMIZU, Yu HAYAMI:
244                  *              `PC-9801 Super Technique', Ascii, 1992.
245                  */
246                 int count;
247                 unsigned long flags;
248
249                 /* interrupts while check is fairly bad */
250                 spin_lock_irqsave(&lp_old98_lock, flags);
251
252                 if (!lp_old98_char(DC1)) {
253                         spin_unlock_irqrestore(&lp_old98_lock, flags);
254                         return -EBUSY;
255                 }
256                 count = (unsigned int)dc1_check > 10000 ? 10000 : dc1_check;
257                 while (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) {
258                         if (--count == 0) {
259                                 spin_unlock_irqrestore(&lp_old98_lock, flags);
260                                 return -ENODEV;
261                         }
262                 }
263                 spin_unlock_irqrestore(&lp_old98_lock, flags);
264         }
265
266         if ((lp.lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)) == NULL)
267                 return -ENOMEM;
268
269         lp.flags |= LP_BUSY;
270
271 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
272         saved_console_flags = lp_old98_console.flags;
273         lp_old98_console.flags &= ~CON_ENABLED;
274 #endif
275         return 0;
276 }
277
278 static int lp_old98_release(struct inode * inode, struct file * file)
279 {
280         kfree(lp.lp_buffer);
281         lp.lp_buffer = NULL;
282         lp.flags &= ~LP_BUSY;
283 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
284         lp_old98_console.flags = saved_console_flags;
285 #endif
286         return 0;
287 }
288
289 static int lp_old98_init_device(void)
290 {
291         unsigned char data;
292
293         if ((data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10)) {
294                 printk(KERN_INFO
295                        "lp_old98: shutting down extended parallel port mode...\n");
296                 outb(data & ~0x10, LP_PORT_EXTMODE);
297         }
298 #ifdef  PC98_HW_H98
299         if ((pc98_hw_flags & PC98_HW_H98)
300             && ((data = inb(LP_PORT_H98MODE)) & 0x01)) {
301                 printk(KERN_INFO
302                        "lp_old98: shutting down H98 full centronics mode...\n");
303                 outb(data & ~0x01, LP_PORT_H98MODE);
304         }
305 #endif
306         return 0;
307 }
308
309 static int lp_old98_ioctl(struct inode *inode, struct file *file,
310                           unsigned int command, unsigned long arg)
311 {
312         int retval = 0;
313
314         switch (command) {
315         case LPTIME:
316                 lp.time = arg * HZ/100;
317                 break;
318         case LPCHAR:
319                 lp.chars = arg;
320                 break;
321         case LPABORT:
322                 if (arg)
323                         lp.flags |= LP_ABORT;
324                 else
325                         lp.flags &= ~LP_ABORT;
326                 break;
327         case LPABORTOPEN:
328                 if (arg)
329                         lp.flags |= LP_ABORTOPEN;
330                 else
331                         lp.flags &= ~LP_ABORTOPEN;
332                 break;
333         case LPCAREFUL:
334                 /* do nothing */
335                 break;
336         case LPWAIT:
337                 lp.wait = arg;
338                 break;
339         case LPGETIRQ:
340                 retval = put_user(0, (int *)arg);
341                 break;
342         case LPGETSTATUS:
343                 /*
344                  * convert PC-9800's status to IBM PC's one, so that tunelp(8)
345                  * works in the same way on this driver.
346                  */
347                 retval = put_user((inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
348                                         ? (LP_PBUSY | LP_PERRORP) : LP_PERRORP,
349                                         (int *)arg);
350                 break;
351         case LPRESET:
352                 retval = lp_old98_init_device();
353                 break;
354 #ifdef LP_STATS
355         case LPGETSTATS:
356                 if (copy_to_user((struct lp_stats *)arg, &lp.stats,
357                                  sizeof(struct lp_stats)))
358                         retval = -EFAULT;
359                 else if (suser())
360                         memset(&lp.stats, 0, sizeof(struct lp_stats));
361                 break;
362 #endif
363         case LPGETFLAGS:
364                 retval = put_user(lp.flags, (int *)arg);
365                 break;
366         case LPSETIRQ: 
367         default:
368                 retval = -EINVAL;
369         }
370         return retval;
371 }
372
373 static struct file_operations lp_old98_fops = {
374         .owner          = THIS_MODULE,
375         .write          = lp_old98_write,
376         .ioctl          = lp_old98_ioctl,
377         .open           = lp_old98_open,
378         .release        = lp_old98_release,
379 };
380
381 /*
382  *  Support for console on lp_old98
383  */
384 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
385
386 static inline void io_delay(void)
387 {
388         unsigned char dummy;    /* actually not output */
389
390         asm volatile ("out%B0 %0,%1" : "=a"(dummy) : "N"(0x5f));
391 }
392
393 static void lp_old98_console_write(struct console *console,
394                                     const char *s, unsigned int count)
395 {
396         int i;
397         static unsigned int timeout_run = 0;
398
399         while (count) {
400                 /* wait approx 1.2 seconds */
401                 for (i = 2000000; !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
402                                                                 io_delay())
403                         if (!--i) {
404                                 if (++timeout_run >= 10)
405                                         /* disable forever... */
406                                         console->flags &= ~CON_ENABLED;
407                                 return;
408                         }
409
410                 timeout_run = 0;
411
412                 if (*s == '\n') {
413                         outb('\r', LP_PORT_DATA);
414                         io_delay();
415                         io_delay();
416                         outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
417                         io_delay();
418                         io_delay();
419                         outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
420                         io_delay();
421                         io_delay();
422                         for (i = 1000000;
423                                         !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
424                                         io_delay())
425                                 if (!--i)
426                                         return;
427                 }
428
429                 outb(*s++, LP_PORT_DATA);
430                 io_delay();
431                 io_delay();
432                 outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
433                 io_delay();
434                 io_delay();
435                 outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
436                 io_delay();
437                 io_delay();
438
439                 --count;
440         }
441 }
442
443 static struct console lp_old98_console = {
444         .name   = "lp_old98",
445         .write  = lp_old98_console_write,
446         .flags  = CON_PRINTBUFFER,
447         .index  = -1,
448 };
449
450 #endif  /* console on lp_old98 */
451
452 static int __init lp_old98_init(void)
453 {
454         char *errmsg = "I/O ports already occupied, giving up.";
455
456 #ifdef  PC98_HW_H98
457         if (pc98_hw_flags & PC98_HW_H98)
458             if (!request_region(LP_PORT_H98MODE, 1, "lp_old98")
459                 goto err1;
460 #endif
461         if (!request_region(LP_PORT_DATA,   1, "lp_old98"))
462                 goto err2;
463         if (!request_region(LP_PORT_STATUS, 1, "lp_old98"))
464                 goto err3;
465         if (!request_region(LP_PORT_STROBE, 1, "lp_old98"))
466                 goto err4;
467         if (!request_region(LP_PORT_EXTMODE, 1, "lp_old98"))
468                 goto err5;
469         if (!register_chrdev(LP_MAJOR, "lp", &lp_old98_fops)) {
470 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
471                 register_console(&lp_old98_console);
472                 printk(KERN_INFO "lp_old98: console ready\n");
473 #endif
474                 /*
475                  * rest are not needed by this driver,
476                  * but for locking out other printer drivers...
477                  */
478                 lp_old98_init_device();
479                 return 0;
480         } else
481                 errmsg = "unable to register device";
482
483         release_region(LP_PORT_EXTMODE, 1);
484 err5:
485         release_region(LP_PORT_STROBE, 1);
486 err4:
487         release_region(LP_PORT_STATUS, 1);
488 err3:
489         release_region(LP_PORT_DATA, 1);
490 err2:
491 #ifdef  PC98_HW_H98
492         if (pc98_hw_flags & PC98_HW_H98)
493             release_region(LP_PORT_H98MODE, 1);
494
495 err1:
496 #endif
497         printk(KERN_ERR "lp_old98: %s\n", errmsg);
498         return -EBUSY;
499 }
500
501 static void __exit lp_old98_exit(void)
502 {
503 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
504         unregister_console(&lp_old98_console);
505 #endif
506         unregister_chrdev(LP_MAJOR, "lp");
507
508         release_region(LP_PORT_DATA,   1);
509         release_region(LP_PORT_STATUS, 1);
510         release_region(LP_PORT_STROBE, 1);
511 #ifdef  PC98_HW_H98
512         if (pc98_hw_flags & PC98_HW_H98)
513                 release_region(LP_PORT_H98MODE, 1);
514 #endif
515         release_region(LP_PORT_EXTMODE, 1);
516 }
517
518 #ifndef MODULE
519 static int __init lp_old98_setup(char *str)
520 {
521         int ints[4];
522
523         str = get_options(str, ARRAY_SIZE(ints), ints);
524         if (ints[0] > 0)
525                 dc1_check = ints[1];
526         return 1;
527 }
528 __setup("lp_old98_dc1_check=", lp_old98_setup);
529 #endif
530
531 MODULE_PARM(dc1_check, "i");
532 MODULE_AUTHOR("Kousuke Takai <tak@kmc.kyoto-u.ac.jp>");
533 MODULE_DESCRIPTION("PC-9800 old printer port driver");
534 MODULE_LICENSE("GPL");
535
536 module_init(lp_old98_init);
537 module_exit(lp_old98_exit);