2 * linux/drivers/char/lp_old98.c
4 * printer port driver for ancient PC-9800s with no bidirectional port support
6 * Copyright (C) 1998,99 Kousuke Takai <tak@kmc.kyoto-u.ac.jp>,
7 * Kyoto University Microcomputer Club
9 * This driver is based on and has compatibility with `lp.c',
10 * generic PC printer port driver.
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>
29 #include <asm/uaccess.h>
30 #include <asm/system.h>
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)
42 #define LP_PORT_H98MODE 0x0448
43 #define LP_PORT_EXTMODE 0x0149
48 #define LP_MASK_nBUSY (1 << 2)
49 #define LP_MASK_nSTROBE (1 << 7)
51 #define LP_CONTROL_ASSERT_STROBE (0x0e)
52 #define LP_CONTROL_NEGATE_STROBE (0x0f)
55 * Acceptable maximum value for non-privileged user for LPCHARS ioctl.
57 #define LP_CHARS_NOPRIV_MAX 65535
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,
71 static spinlock_t lp_old98_lock = SPIN_LOCK_UNLOCKED;
76 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
77 static struct console lp_old98_console; /* defined later */
78 static short saved_console_flags;
81 static DECLARE_WAIT_QUEUE_HEAD (lp_old98_waitq);
83 static void lp_old98_timer_function(unsigned long data)
85 if (inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
86 wake_up_interruptible(&lp_old98_waitq);
88 struct timer_list *t = (struct timer_list *) data;
90 t->expires = jiffies + 1;
95 static inline int lp_old98_wait_ready(void)
97 struct timer_list timer;
100 timer.function = lp_old98_timer_function;
101 timer.expires = jiffies + 1;
102 timer.data = (unsigned long)&timer;
104 interruptible_sleep_on(&lp_old98_waitq);
106 return signal_pending(current);
109 static inline int lp_old98_char(char lpchar)
111 unsigned long count = 0;
116 while (!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY)) {
118 if (count >= lp.chars)
122 outb(lpchar, LP_PORT_DATA);
126 * Update lp statsistics here (and between next two outb()'s).
127 * Time to compute it is part of storobe delay.
129 if (count > lp.stats.maxwait) {
130 #ifdef LP_OLD98_DEBUG
131 printk(KERN_DEBUG "lp_old98: success after %d counts.\n",
134 lp.stats.maxwait = count;
137 tmp = count - lp.stats.meanwait;
143 /* negate PSTB# (activate strobe) */
144 outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
147 lp.stats.meanwait = (255 * lp.stats.meanwait + count + 128) / 256;
148 lp.stats.mdev = (127 * lp.stats.mdev + tmp + 64) / 128;
154 /* assert PSTB# (deactivate strobe) */
155 outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
160 static ssize_t lp_old98_write(struct file * file,
161 const char * buf, size_t count,
164 unsigned long total_bytes_written = 0;
166 if (!access_ok(VERIFY_READ, buf, count))
170 if (jiffies - lp.lastcall > lp.time)
172 lp.lastcall = jiffies;
176 unsigned long bytes_written = 0;
177 unsigned long copy_size
178 = (count < LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
180 if (__copy_from_user(lp.lp_buffer, buf, copy_size))
183 while (bytes_written < copy_size) {
184 if (lp_old98_char(lp.lp_buffer[bytes_written]))
188 int rc = lp.runchars + bytes_written;
190 if (rc > lp.stats.maxrun)
191 lp.stats.maxrun = rc;
195 #ifdef LP_OLD98_DEBUG
197 "lp_old98: sleeping at %d characters"
199 lp.runchars, lp.time);
202 if (lp_old98_wait_ready())
203 return ((total_bytes_written
208 total_bytes_written += bytes_written;
209 buf += bytes_written;
211 lp.runchars += bytes_written;
213 count -= bytes_written;
216 return total_bytes_written;
219 static int lp_old98_open(struct inode * inode, struct file * file)
221 if (iminor(inode) != 0)
224 if (lp.flags & LP_BUSY)
227 if (dc1_check && (lp.flags & LP_ABORTOPEN)
228 && !(file->f_flags & O_NONBLOCK)) {
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:
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,
242 * The source of this procedure:
243 * Terumasa KODAKA, Kazufumi SHIMIZU, Yu HAYAMI:
244 * `PC-9801 Super Technique', Ascii, 1992.
249 /* interrupts while check is fairly bad */
250 spin_lock_irqsave(&lp_old98_lock, flags);
252 if (!lp_old98_char(DC1)) {
253 spin_unlock_irqrestore(&lp_old98_lock, flags);
256 count = (unsigned int)dc1_check > 10000 ? 10000 : dc1_check;
257 while (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) {
259 spin_unlock_irqrestore(&lp_old98_lock, flags);
263 spin_unlock_irqrestore(&lp_old98_lock, flags);
266 if ((lp.lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)) == NULL)
271 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
272 saved_console_flags = lp_old98_console.flags;
273 lp_old98_console.flags &= ~CON_ENABLED;
278 static int lp_old98_release(struct inode * inode, struct file * file)
282 lp.flags &= ~LP_BUSY;
283 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
284 lp_old98_console.flags = saved_console_flags;
289 static int lp_old98_init_device(void)
293 if ((data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10)) {
295 "lp_old98: shutting down extended parallel port mode...\n");
296 outb(data & ~0x10, LP_PORT_EXTMODE);
299 if ((pc98_hw_flags & PC98_HW_H98)
300 && ((data = inb(LP_PORT_H98MODE)) & 0x01)) {
302 "lp_old98: shutting down H98 full centronics mode...\n");
303 outb(data & ~0x01, LP_PORT_H98MODE);
309 static int lp_old98_ioctl(struct inode *inode, struct file *file,
310 unsigned int command, unsigned long arg)
316 lp.time = arg * HZ/100;
323 lp.flags |= LP_ABORT;
325 lp.flags &= ~LP_ABORT;
329 lp.flags |= LP_ABORTOPEN;
331 lp.flags &= ~LP_ABORTOPEN;
340 retval = put_user(0, (int *)arg);
344 * convert PC-9800's status to IBM PC's one, so that tunelp(8)
345 * works in the same way on this driver.
347 retval = put_user((inb(LP_PORT_STATUS) & LP_MASK_nBUSY)
348 ? (LP_PBUSY | LP_PERRORP) : LP_PERRORP,
352 retval = lp_old98_init_device();
356 if (copy_to_user((struct lp_stats *)arg, &lp.stats,
357 sizeof(struct lp_stats)))
360 memset(&lp.stats, 0, sizeof(struct lp_stats));
364 retval = put_user(lp.flags, (int *)arg);
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,
382 * Support for console on lp_old98
384 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
386 static inline void io_delay(void)
388 unsigned char dummy; /* actually not output */
390 asm volatile ("out%B0 %0,%1" : "=a"(dummy) : "N"(0x5f));
393 static void lp_old98_console_write(struct console *console,
394 const char *s, unsigned int count)
397 static unsigned int timeout_run = 0;
400 /* wait approx 1.2 seconds */
401 for (i = 2000000; !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
404 if (++timeout_run >= 10)
405 /* disable forever... */
406 console->flags &= ~CON_ENABLED;
413 outb('\r', LP_PORT_DATA);
416 outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
419 outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
423 !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY);
429 outb(*s++, LP_PORT_DATA);
432 outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL);
435 outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL);
443 static struct console lp_old98_console = {
445 .write = lp_old98_console_write,
446 .flags = CON_PRINTBUFFER,
450 #endif /* console on lp_old98 */
452 static int __init lp_old98_init(void)
454 char *errmsg = "I/O ports already occupied, giving up.";
457 if (pc98_hw_flags & PC98_HW_H98)
458 if (!request_region(LP_PORT_H98MODE, 1, "lp_old98")
461 if (!request_region(LP_PORT_DATA, 1, "lp_old98"))
463 if (!request_region(LP_PORT_STATUS, 1, "lp_old98"))
465 if (!request_region(LP_PORT_STROBE, 1, "lp_old98"))
467 if (!request_region(LP_PORT_EXTMODE, 1, "lp_old98"))
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");
475 * rest are not needed by this driver,
476 * but for locking out other printer drivers...
478 lp_old98_init_device();
481 errmsg = "unable to register device";
483 release_region(LP_PORT_EXTMODE, 1);
485 release_region(LP_PORT_STROBE, 1);
487 release_region(LP_PORT_STATUS, 1);
489 release_region(LP_PORT_DATA, 1);
492 if (pc98_hw_flags & PC98_HW_H98)
493 release_region(LP_PORT_H98MODE, 1);
497 printk(KERN_ERR "lp_old98: %s\n", errmsg);
501 static void __exit lp_old98_exit(void)
503 #ifdef CONFIG_PC9800_OLDLP_CONSOLE
504 unregister_console(&lp_old98_console);
506 unregister_chrdev(LP_MAJOR, "lp");
508 release_region(LP_PORT_DATA, 1);
509 release_region(LP_PORT_STATUS, 1);
510 release_region(LP_PORT_STROBE, 1);
512 if (pc98_hw_flags & PC98_HW_H98)
513 release_region(LP_PORT_H98MODE, 1);
515 release_region(LP_PORT_EXTMODE, 1);
519 static int __init lp_old98_setup(char *str)
523 str = get_options(str, ARRAY_SIZE(ints), ints);
528 __setup("lp_old98_dc1_check=", lp_old98_setup);
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");
536 module_init(lp_old98_init);
537 module_exit(lp_old98_exit);