2 * split in two parts for better support of different hardware
3 * by Joerg Dorchain (dorchain@mpi-sb.mpg.de)
5 * Amiga printer device by Michael Rausch (linux@uni-koblenz.de);
6 * Atari support added by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de);
9 * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
10 * Copyright (C) 1992,1993 by Michael K. Johnson
11 * - Thanks much to Gunter Windau for pointing out to me where the error
12 * checking ought to be.
13 * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
16 /* 01/17/95: Matthias Welwarsky (dg8y@rs11.hrz.th-darmstadt.de)
17 * lp_write(): rewritten from scratch
18 * lp_interrupt(): fixed cli()/sti()-bug
20 * 95/05/28: Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
21 * lp_write() fixed to make it work again.
22 * 95/08/18: Andreas Schwab
23 * lp_write_interrupt: fix race condition
25 * * CAUTION, please do check! *
27 * on 68000-based machines sti() must NEVER appear in interrupt driven
28 * code. The 68k-CPU has a priority-based interrupt scheme. while an interrupt
29 * with a certain priority is executed, all requests with lower or same
30 * priority get locked out. executing the sti()-macro allows ANY interrupt
31 * to be served. this really causes BIG trouble!
32 * to protect an interrupt driven routine against being interrupted
33 * (if absolutely needed!) one should use save_flags();cli()/restore_flags()!
37 #include <linux/config.h>
38 #include <linux/module.h>
39 #include <linux/errno.h>
40 #include <linux/kernel.h>
41 #include <linux/major.h>
42 #include <linux/sched.h>
43 #include <linux/string.h>
44 #include <linux/init.h>
47 #include <linux/kmod.h>
51 #ifdef CONFIG_MULTIFACE_III_LP
52 #include <linux/lp_mfc.h>
56 #include <linux/lp_m68k.h>
57 #include <linux/lp_intern.h>
58 #include <linux/malloc.h>
59 #include <linux/interrupt.h>
61 #include <asm/uaccess.h>
62 #include <asm/system.h>
66 * why bother around with the pio driver when the interrupt works;
67 * so, for "security" reasons only, it's configurable here.
68 * saves some bytes, at least ...
70 #define FORCE_POLLING 0
71 #define FORCE_INTERRUPT 1
73 * PREFER_INTERRUPT doesn't make much sense on m68k.
74 * it is preserved here in case of joining with the i386 driver
76 #define PREFER_INTERRUPT 2
79 #define WHICH_DRIVER FORCE_INTERRUPT
81 struct lp_struct
*lp_table
[MAX_LP
] = {NULL
,};
83 static int max_lp
; /* the real number of devices */
86 * All my debugging code assumes that you debug with only one printer at
94 #if WHICH_DRIVER != FORCE_INTERRUPT
96 static int lp_max_count
= 1;
99 static int lp_char_polled(char lpchar
, int dev
)
101 unsigned long count
= 0;
105 if (current
->need_resched
)
107 } while (lp_table
[dev
]->lp_is_busy(dev
) && count
< lp_table
[dev
]->chars
);
109 if (count
== lp_table
[dev
]->chars
) {
111 /* we timed out, and the character was /not/ printed */
114 if (count
> lp_max_count
) {
115 printk("lp success after %d counts.\n",count
);
116 lp_max_count
= count
;
119 lp_table
[dev
]->lp_out(lpchar
, dev
);
126 unsigned int lp_total_chars
= 0;
127 unsigned int lp_last_call
= 0;
131 #if WHICH_DRIVER != FORCE_POLLING
132 static __inline__
int lp_char_interrupt(char lpchar
, int dev
)
134 if (!lp_table
[dev
]->lp_is_busy(dev
)) {
135 lp_table
[dev
]->lp_out(lpchar
,dev
);
143 void lp_interrupt(int dev
)
145 if (dev
>= 0 && dev
< MAX_LP
&& lp_table
[dev
]->do_print
)
147 if (lp_table
[dev
]->copy_size
)
152 if (lp_char_interrupt(lp_table
[dev
]->lp_buffer
[lp_table
[dev
]->bytes_written
], dev
)) {
153 --lp_table
[dev
]->copy_size
;
154 ++lp_table
[dev
]->bytes_written
;
155 restore_flags(flags
);
159 lp_table
[dev
]->do_print
= 0;
160 restore_flags(flags
);
162 wake_up_interruptible(&lp_table
[dev
]->lp_wait_q
);
167 lp_table
[dev
]->do_print
= 0;
169 wake_up_interruptible(&lp_table
[dev
]->lp_wait_q
);
175 #if WHICH_DRIVER == FORCE_INTERRUPT
176 static ssize_t
lp_write(struct file
*file
, const char *buf
,
177 size_t count
, loff_t
*ppos
)
179 static ssize_t
lp_write_interrupt(struct file
*file
, const char *buf
,
180 size_t count
, loff_t
*ppos
)
183 struct inode
*inode
= file
->f_dentry
->d_inode
;
184 unsigned long total_bytes_written
= 0;
187 int dev
= MINOR(inode
->i_rdev
);
190 lp_table
[dev
]->do_print
= 0; /* disable lp_interrupt() */
191 lp_table
[dev
]->bytes_written
= 0; /* init buffer read-pointer */
193 lp_table
[dev
]->copy_size
= (count
<= LP_BUFFER_SIZE
? count
: LP_BUFFER_SIZE
);
194 if (copy_from_user(lp_table
[dev
]->lp_buffer
, buf
,
195 lp_table
[dev
]->copy_size
))
197 while (lp_table
[dev
]->copy_size
) {
199 cli(); /* no interrupts now */
200 lp_table
[dev
]->do_print
= 1; /* enable lp_interrupt() */
201 if (lp_char_interrupt(lp_table
[dev
]->lp_buffer
[lp_table
[dev
]->bytes_written
], dev
)) {
202 ++lp_table
[dev
]->bytes_written
;
203 --lp_table
[dev
]->copy_size
;
205 } else { /* something went wrong */
206 lp_table
[dev
]->do_print
= 0; /* disable lp_interrupt() */
207 lp_error
= 1; /* printer caused error */
211 /* something blocked printing, so we don't want to sleep too long,
212 in case we have to rekick the interrupt */
214 current
->timeout
= jiffies
+ LP_TIMEOUT_POLLED
;
216 current
->timeout
= jiffies
+ LP_TIMEOUT_INTERRUPT
;
219 interruptible_sleep_on(&lp_table
[dev
]->lp_wait_q
);
220 restore_flags(flags
);
222 /* we're up again and running. we first disable lp_interrupt(), then
223 check what happened meanwhile */
225 lp_table
[dev
]->do_print
= 0;
226 rc
= total_bytes_written
+ lp_table
[dev
]->bytes_written
;
228 if (signal_pending(current
)) {
235 /* an error has occurred, maybe in lp_interrupt().
236 figure out the type of error, exit on request or if nothing has
237 been printed at all. */
239 if (lp_table
[dev
]->lp_has_pout(dev
)) {
240 printk(KERN_NOTICE
"lp%d: paper-out\n",dev
);
241 if (!rc
) rc
= -ENOSPC
;
242 } else if (!lp_table
[dev
]->lp_is_online(dev
)) {
243 printk(KERN_NOTICE
"lp%d: off-line\n",dev
);
245 } else if (lp_table
[dev
]->lp_is_busy(dev
)) {
246 printk(KERN_NOTICE
"lp%d: on fire\n",dev
);
249 if (lp_table
[dev
]->flags
& LP_ABORT
)
252 /* check if our buffer was completely printed, if not, most likely
253 an unsolved error blocks the printer. As we can`t do anything
254 against, we start all over again. Else we set the read-pointer
255 of the buffer and count the printed characters */
257 if (!lp_table
[dev
]->copy_size
) {
258 total_bytes_written
+= lp_table
[dev
]->bytes_written
;
259 buf
+= lp_table
[dev
]->bytes_written
;
260 count
-= lp_table
[dev
]->bytes_written
;
264 return total_bytes_written
;
267 void (*lp_interrupt
)() = NULL
;
270 #if WHICH_DRIVER != FORCE_INTERRUPT
271 #if WHICH_DRIVER == FORCE_POLLING
272 static ssize_t
lp_write(struct file
*file
, const char *buf
,
273 size_t count
, loff_t
*ppos
)
275 static ssize_t
lp_write_polled(struct file
*file
, const char *buf
,
276 size_t count
, loff_t
*ppos
)
279 struct inode
*inode
= file
->f_dentry
->d_inode
;
281 int dev
= MINOR(inode
->i_rdev
);
284 if (jiffies
-lp_last_call
> lp_table
[dev
]->time
) {
288 lp_last_call
= jiffies
;
294 if (get_user(c
, temp
))
296 if (lp_char_polled(c
, dev
)) {
297 /* only update counting vars if character was printed */
302 } else { /* if printer timed out */
303 unsigned long timeout
= LP_TIMEOUT_POLLED
;
305 if (lp_table
[dev
]->lp_has_pout(dev
)) {
306 printk(KERN_NOTICE
"lp%d: out of paper\n",dev
);
307 if (lp_table
[dev
]->flags
& LP_ABORT
)
309 } else if (!lp_table
[dev
]->lp_is_online(dev
)) {
310 printk(KERN_NOTICE
"lp%d: off-line\n",dev
);
311 if (lp_table
[dev
]->flags
& LP_ABORT
)
314 /* not offline or out of paper. on fire? */
315 if (lp_table
[dev
]->lp_is_busy(dev
)) {
316 printk(KERN_NOTICE
"lp%d: on fire\n",dev
);
317 if (lp_table
[dev
]->flags
& LP_ABORT
)
321 timeout
= lp_table
[dev
]->time
;
323 /* check for signals before going to sleep */
324 if (error
== 0 && signal_pending(current
))
334 printk("lp sleeping at %d characters for %d jiffies\n",
335 lp_total_chars
, timeout
);
338 current
->state
= TASK_INTERRUPTIBLE
;
339 current
->timeout
= jiffies
+ timeout
;
347 unsigned int lp_irq
= 0;
349 #if WHICH_DRIVER == PREFER_INTERRUPT
350 static ssize_t
lp_write(struct file
*file
, const char *buf
, size_t count
,
354 return lp_write_interrupt(file
, buf
, count
, ppos
);
356 return lp_write_polled(file
, buf
, count
, ppos
);
360 static long long lp_lseek(struct file
* file
, long long offset
, int origin
)
365 static int lp_open(struct inode
*inode
, struct file
*file
)
367 int dev
= MINOR(inode
->i_rdev
);
377 if (!lp_table
[dev
]) {
380 sprintf(modname
, "char-major-%d-%d", LP_MAJOR
, dev
);
381 request_module(modname
);
386 if (!(lp_table
[dev
]->flags
& LP_EXIST
))
389 if (lp_table
[dev
]->flags
& LP_BUSY
)
392 lp_table
[dev
]->flags
|= LP_BUSY
;
394 ret
= lp_table
[dev
]->lp_open(dev
);
396 lp_table
[dev
]->flags
&= ~LP_BUSY
;
406 static int lp_release(struct inode
*inode
, struct file
*file
)
408 int dev
=MINOR(inode
->i_rdev
);
410 lp_table
[dev
]->flags
&= ~LP_BUSY
;
411 lp_table
[dev
]->lp_release(dev
);
417 static int lp_ioctl(struct inode
*inode
, struct file
*file
,
418 unsigned int cmd
, unsigned long arg
)
420 unsigned int minor
= MINOR(inode
->i_rdev
);
421 int retval
= -ENODEV
;
424 printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor
, cmd
, arg
);
428 if (!(lp_table
[minor
]->flags
& LP_EXIST
))
433 lp_table
[minor
]->time
= arg
;
436 lp_table
[minor
]->chars
= arg
;
440 lp_table
[minor
]->flags
|= LP_ABORT
;
442 lp_table
[minor
]->flags
&= ~LP_ABORT
;
445 lp_table
[minor
]->wait
= arg
;
453 if (lp_table
[minor
]->lp_ioctl
)
454 retval
= lp_table
[minor
]->lp_ioctl(minor
, cmd
, arg
);
461 static struct file_operations lp_fops
= {
465 NULL
, /* lp_readdir */
474 EXPORT_SYMBOL(lp_table
);
475 EXPORT_SYMBOL(lp_irq
);
476 EXPORT_SYMBOL(lp_interrupt
);
477 EXPORT_SYMBOL(register_parallel
);
478 EXPORT_SYMBOL(unregister_parallel
);
480 __initfunc(int lp_init(void))
482 extern char m68k_debug_device
[];
484 if (!strcmp( m68k_debug_device
, "par" ))
487 if (register_chrdev(LP_MAJOR
,"lp", &lp_fops
)) {
488 printk(KERN_ERR
"unable to get major %d for line printer\n", LP_MAJOR
);
492 #if WHICH_DRIVER == FORCE_POLLING
494 printk(KERN_INFO
"lp_init: lp using polling driver\n");
498 printk(KERN_INFO
"lp_init: lp using interrupt driver\n");
503 #ifdef CONFIG_MULTIFACE_III_LP
511 * Currently we do not accept any lp-parameters, but that may change.
513 __initfunc(void lp_setup(char *str
, int *ints
))
518 int init_module(void)
523 void cleanup_module(void)
525 unregister_chrdev(LP_MAJOR
, "lp");
530 * (un-)register for hardware drivers
531 * tab is an inititalised lp_struct, dev the desired minor
532 * if dev < 0, let the driver choose the first free minor
533 * if sucessful return the minor, else -1
535 int register_parallel(struct lp_struct
*tab
, int dev
)
539 while ((dev
< MAX_LP
) && (lp_table
[dev
] != NULL
))
544 if (lp_table
[dev
] != NULL
)
547 printk(KERN_INFO
"lp%d: %s at 0x%08lx\n", dev
, tab
->name
, (long)tab
->base
);
551 #ifdef CONFIG_MODULES
552 void unregister_parallel(int dev
)
554 if ((dev
< 0) || (dev
> MAX_LP
) || (lp_table
[dev
] == NULL
))
555 printk(KERN_ERR
"WARNING: unregister_parallel for non-existant device ignored!\n");
557 lp_table
[dev
] = NULL
;