Import 2.1.118
[davej-history.git] / drivers / char / lp_m68k.c
blobdc0300751dcbecf246fbd56dd1a61fab6e91cb2a
1 /*
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);
7 * based upon work from
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>
45 #include <asm/irq.h>
46 #ifdef CONFIG_KMOD
47 #include <linux/kmod.h>
48 #endif
50 #ifdef CONFIG_AMIGA
51 #ifdef CONFIG_MULTIFACE_III_LP
52 #include <linux/lp_mfc.h>
53 #endif
54 #endif
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 */
85 /*
86 * All my debugging code assumes that you debug with only one printer at
87 * a time. RWWH
90 #define LP_DEBUG
91 #undef LP_DEBUG
94 #if WHICH_DRIVER != FORCE_INTERRUPT
95 #ifdef LP_DEBUG
96 static int lp_max_count = 1;
97 #endif
99 static int lp_char_polled(char lpchar, int dev)
101 unsigned long count = 0;
103 do {
104 count ++;
105 if (current->need_resched)
106 schedule();
107 } while (lp_table[dev]->lp_is_busy(dev) && count < lp_table[dev]->chars);
109 if (count == lp_table[dev]->chars) {
110 return 0;
111 /* we timed out, and the character was /not/ printed */
113 #ifdef LP_DEBUG
114 if (count > lp_max_count) {
115 printk("lp success after %d counts.\n",count);
116 lp_max_count = count;
118 #endif
119 lp_table[dev]->lp_out(lpchar, dev);
120 return 1;
122 #endif
125 #ifdef LP_DEBUG
126 unsigned int lp_total_chars = 0;
127 unsigned int lp_last_call = 0;
128 #endif
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);
136 return 1;
138 return 0;
141 static int lp_error;
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)
149 unsigned long flags;
150 save_flags(flags);
151 cli();
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);
157 else
159 lp_table[dev]->do_print = 0;
160 restore_flags(flags);
161 lp_error = 1;
162 wake_up_interruptible(&lp_table[dev]->lp_wait_q);
165 else
167 lp_table[dev]->do_print = 0;
168 lp_error = 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)
178 #else
179 static ssize_t lp_write_interrupt(struct file *file, const char *buf,
180 size_t count, loff_t *ppos)
181 #endif
183 struct inode *inode = file->f_dentry->d_inode;
184 unsigned long total_bytes_written = 0;
185 unsigned int flags;
186 int rc;
187 int dev = MINOR(inode->i_rdev);
189 do {
190 lp_table[dev]->do_print = 0; /* disable lp_interrupt() */
191 lp_table[dev]->bytes_written = 0; /* init buffer read-pointer */
192 lp_error = 0;
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))
196 return -EFAULT;
197 while (lp_table[dev]->copy_size) {
198 save_flags(flags);
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;
204 lp_error = 0;
205 } else { /* something went wrong */
206 lp_table[dev]->do_print = 0; /* disable lp_interrupt() */
207 lp_error = 1; /* printer caused error */
209 if (lp_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;
215 } else {
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)) {
229 if (rc == 0)
230 rc = -EINTR;
231 return rc;
233 if (lp_error) {
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);
244 if (!rc) rc = -EIO;
245 } else if (lp_table[dev]->lp_is_busy(dev)) {
246 printk(KERN_NOTICE "lp%d: on fire\n",dev);
247 if (!rc) rc = -EIO;
249 if (lp_table[dev]->flags & LP_ABORT)
250 return rc;
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;
263 } while (count > 0);
264 return total_bytes_written;
266 #else
267 void (*lp_interrupt)() = NULL;
268 #endif
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)
274 #else
275 static ssize_t lp_write_polled(struct file *file, const char *buf,
276 size_t count, loff_t *ppos)
277 #endif
279 struct inode *inode = file->f_dentry->d_inode;
280 char *temp = buf;
281 int dev = MINOR(inode->i_rdev);
283 #ifdef LP_DEBUG
284 if (jiffies-lp_last_call > lp_table[dev]->time) {
285 lp_total_chars = 0;
286 lp_max_count = 1;
288 lp_last_call = jiffies;
289 #endif
291 temp = buf;
292 while (count > 0) {
293 int c;
294 if (get_user(c, temp))
295 return -EFAULT;
296 if (lp_char_polled(c, dev)) {
297 /* only update counting vars if character was printed */
298 count--; temp++;
299 #ifdef LP_DEBUG
300 lp_total_chars++;
301 #endif
302 } else { /* if printer timed out */
303 unsigned long timeout = LP_TIMEOUT_POLLED;
304 int error = 0;
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)
308 error = -ENOSPC;
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)
312 error = -EIO;
313 } else
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)
318 error = -EIO;
320 else
321 timeout = lp_table[dev]->time;
323 /* check for signals before going to sleep */
324 if (error == 0 && signal_pending(current))
325 error = -EINTR;
326 if (error) {
327 if (temp != buf)
328 return temp-buf;
329 else
330 return error;
333 #ifdef LP_DEBUG
334 printk("lp sleeping at %d characters for %d jiffies\n",
335 lp_total_chars, timeout);
336 lp_total_chars = 0;
337 #endif
338 current->state = TASK_INTERRUPTIBLE;
339 current->timeout = jiffies + timeout;
340 schedule();
343 return temp - buf;
345 #endif
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,
351 loff_t *ppos)
353 if (lp_irq)
354 return lp_write_interrupt(file, buf, count, ppos);
355 else
356 return lp_write_polled(file, buf, count, ppos);
358 #endif
360 static long long lp_lseek(struct file * file, long long offset, int origin)
362 return -ESPIPE;
365 static int lp_open(struct inode *inode, struct file *file)
367 int dev = MINOR(inode->i_rdev);
368 int ret;
370 MOD_INC_USE_COUNT;
372 ret = -ENODEV;
373 if (dev >= MAX_LP)
374 goto out_err;
376 #ifdef CONFIG_KMOD
377 if (!lp_table[dev]) {
378 char modname[30];
380 sprintf(modname, "char-major-%d-%d", LP_MAJOR, dev);
381 request_module(modname);
383 #endif
384 if (!lp_table[dev])
385 goto out_err;
386 if (!(lp_table[dev]->flags & LP_EXIST))
387 goto out_err;
388 ret = -EBUSY;
389 if (lp_table[dev]->flags & LP_BUSY)
390 goto out_err;
392 lp_table[dev]->flags |= LP_BUSY;
394 ret = lp_table[dev]->lp_open(dev);
395 if (ret != 0) {
396 lp_table[dev]->flags &= ~LP_BUSY;
397 goto out_err;
399 return ret;
401 out_err:
402 MOD_DEC_USE_COUNT;
403 return ret;
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);
412 MOD_DEC_USE_COUNT;
413 return 0;
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;
423 #ifdef LP_DEBUG
424 printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
425 #endif
426 if (minor >= max_lp)
427 goto out;
428 if (!(lp_table[minor]->flags & LP_EXIST))
429 goto out;
430 retval = 0;
431 switch (cmd) {
432 case LPTIME:
433 lp_table[minor]->time = arg;
434 break;
435 case LPCHAR:
436 lp_table[minor]->chars = arg;
437 break;
438 case LPABORT:
439 if (arg)
440 lp_table[minor]->flags |= LP_ABORT;
441 else
442 lp_table[minor]->flags &= ~LP_ABORT;
443 break;
444 case LPWAIT:
445 lp_table[minor]->wait = arg;
446 break;
447 case LPSETIRQ:
448 case LPGETIRQ:
449 retval = lp_irq;
450 break;
451 default:
452 retval = -EINVAL;
453 if (lp_table[minor]->lp_ioctl)
454 retval = lp_table[minor]->lp_ioctl(minor, cmd, arg);
456 out:
457 return retval;
461 static struct file_operations lp_fops = {
462 lp_lseek,
463 NULL, /* lp_read */
464 lp_write,
465 NULL, /* lp_readdir */
466 NULL, /* lp_poll */
467 lp_ioctl,
468 NULL, /* lp_mmap */
469 lp_open,
470 NULL, /* flush */
471 lp_release
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" ))
485 return -EBUSY;
487 if (register_chrdev(LP_MAJOR,"lp", &lp_fops)) {
488 printk(KERN_ERR "unable to get major %d for line printer\n", LP_MAJOR);
489 return -ENXIO;
492 #if WHICH_DRIVER == FORCE_POLLING
493 lp_irq = 0;
494 printk(KERN_INFO "lp_init: lp using polling driver\n");
495 #else
497 lp_irq = 1;
498 printk(KERN_INFO "lp_init: lp using interrupt driver\n");
499 #endif
501 #ifndef MODULE
502 lp_internal_init();
503 #ifdef CONFIG_MULTIFACE_III_LP
504 lp_mfc_init();
505 #endif
506 #endif
507 return 0;
511 * Currently we do not accept any lp-parameters, but that may change.
513 __initfunc(void lp_setup(char *str, int *ints))
517 #ifdef MODULE
518 int init_module(void)
520 return lp_init();
523 void cleanup_module(void)
525 unregister_chrdev(LP_MAJOR, "lp");
527 #endif
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)
537 if (dev < 0) {
538 dev = 0;
539 while ((dev < MAX_LP) && (lp_table[dev] != NULL))
540 dev++;
542 if (dev > MAX_LP)
543 return -1;
544 if (lp_table[dev] != NULL)
545 return -1;
546 lp_table[dev] = tab;
547 printk(KERN_INFO "lp%d: %s at 0x%08lx\n", dev, tab->name, (long)tab->base);
548 return dev;
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");
556 else
557 lp_table[dev] = NULL;
559 #endif