diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /drivers/char/lp_m68k.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'drivers/char/lp_m68k.c')
-rw-r--r-- | drivers/char/lp_m68k.c | 319 |
1 files changed, 187 insertions, 132 deletions
diff --git a/drivers/char/lp_m68k.c b/drivers/char/lp_m68k.c index 1c634041b..3cc9458bd 100644 --- a/drivers/char/lp_m68k.c +++ b/drivers/char/lp_m68k.c @@ -35,22 +35,22 @@ */ #include <linux/config.h> +#include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/sched.h> +#include <linux/string.h> #include <asm/irq.h> +#ifdef CONFIG_KERNELD +#include <linux/kerneld.h> +#endif #ifdef CONFIG_AMIGA -#include <asm/amigaints.h> #ifdef CONFIG_MULTIFACE_III_LP #include <linux/lp_mfc.h> #endif #endif -#ifdef CONFIG_ATARI -#include <asm/atarihw.h> -#include <asm/atariints.h> -#endif #include <linux/lp_m68k.h> #include <linux/lp_intern.h> @@ -68,13 +68,16 @@ */ #define FORCE_POLLING 0 #define FORCE_INTERRUPT 1 +/* + * PREFER_INTERRUPT doesn't make much sense on m68k. + * it is preserved here in case of joining with the i386 driver + * #define PREFER_INTERRUPT 2 + */ #define WHICH_DRIVER FORCE_INTERRUPT -#define MAX_LP 3 /* the maximum number of devices */ - -struct lp_struct lp_table[MAX_LP] = {{0,},}; +struct lp_struct *lp_table[MAX_LP] = {NULL,}; static int max_lp; /* the real number of devices */ @@ -100,9 +103,9 @@ static int lp_char_polled(char lpchar, int dev) count ++; if(need_resched) schedule(); - } while (lp_table[dev].lp_is_busy(dev) && count < lp_table[dev].chars); + } while (lp_table[dev]->lp_is_busy(dev) && count < lp_table[dev]->chars); - if (count == lp_table[dev].chars) { + if (count == lp_table[dev]->chars) { return 0; /* we timed out, and the character was /not/ printed */ } @@ -112,7 +115,7 @@ static int lp_char_polled(char lpchar, int dev) lp_max_count = count; } #endif - lp_table[dev].lp_out(lpchar, dev); + lp_table[dev]->lp_out(lpchar, dev); return 1; } #endif @@ -127,8 +130,8 @@ unsigned int lp_last_call = 0; #if WHICH_DRIVER != FORCE_POLLING static __inline__ int lp_char_interrupt(char lpchar, int dev) { - if (!lp_table[dev].lp_is_busy(dev)) { - lp_table[dev].lp_out(lpchar,dev); + if (!lp_table[dev]->lp_is_busy(dev)) { + lp_table[dev]->lp_out(lpchar,dev); return 1; } return 0; @@ -136,49 +139,44 @@ static __inline__ int lp_char_interrupt(char lpchar, int dev) static int lp_error; -static void lp_interrupt(int irq, struct pt_regs *fp, void *dummy) +void lp_interrupt(int dev) { - unsigned long flags; - int dev; - - for (dev = 0; dev < max_lp; dev++) { - if (lp_table[dev].lp_my_interrupt(dev) != 0) - if (lp_table[dev].do_print) - { - if (lp_table[dev].copy_size) - { - save_flags(flags); - cli(); - if (lp_char_interrupt(lp_table[dev].lp_buffer[lp_table[dev].bytes_written], dev)) { - --lp_table[dev].copy_size; - ++lp_table[dev].bytes_written; - restore_flags(flags); - } - else - { - lp_table[dev].do_print = 0; - restore_flags(flags); - lp_error = 1; - wake_up_interruptible(&lp_table[dev].lp_wait_q); - } - } - else - { - lp_table[dev].do_print = 0; - lp_error = 0; - wake_up_interruptible(&lp_table[dev].lp_wait_q); - } - - } + if (dev >= 0 && dev < MAX_LP && lp_table[dev]->do_print) + { + if (lp_table[dev]->copy_size) + { + unsigned long flags; + save_flags(flags); + cli(); + if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) { + --lp_table[dev]->copy_size; + ++lp_table[dev]->bytes_written; + restore_flags(flags); + } + else + { + lp_table[dev]->do_print = 0; + restore_flags(flags); + lp_error = 1; + wake_up_interruptible(&lp_table[dev]->lp_wait_q); + } + } + else + { + lp_table[dev]->do_print = 0; + lp_error = 0; + wake_up_interruptible(&lp_table[dev]->lp_wait_q); + } + } } #if WHICH_DRIVER == FORCE_INTERRUPT -static int lp_write(struct inode *inode, struct file *file, - const char *buf, int count) +static long lp_write(struct inode *inode, struct file *file, + const char *buf, unsigned long count) #else -static int lp_write_interrupt(struct inode *inode, struct file *file, - const char *buf, int count) +static long lp_write_interrupt(struct inode *inode, struct file *file, + const char *buf, unsigned long count) #endif { unsigned long total_bytes_written = 0; @@ -187,21 +185,21 @@ static int lp_write_interrupt(struct inode *inode, struct file *file, int dev = MINOR(inode->i_rdev); do { - lp_table[dev].do_print = 0; /* disable lp_interrupt() */ - lp_table[dev].bytes_written = 0; /* init buffer read-pointer */ + lp_table[dev]->do_print = 0; /* disable lp_interrupt() */ + lp_table[dev]->bytes_written = 0; /* init buffer read-pointer */ lp_error = 0; - lp_table[dev].copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE); - copy_from_user(lp_table[dev].lp_buffer, buf, lp_table[dev].copy_size); - while (lp_table[dev].copy_size) { + lp_table[dev]->copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE); + copy_from_user(lp_table[dev]->lp_buffer, buf, lp_table[dev]->copy_size); + while (lp_table[dev]->copy_size) { save_flags(flags); cli(); /* no interrupts now */ - lp_table[dev].do_print = 1; /* enable lp_interrupt() */ - if (lp_char_interrupt(lp_table[dev].lp_buffer[lp_table[dev].bytes_written], dev)) { - ++lp_table[dev].bytes_written; - --lp_table[dev].copy_size; + lp_table[dev]->do_print = 1; /* enable lp_interrupt() */ + if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) { + ++lp_table[dev]->bytes_written; + --lp_table[dev]->copy_size; lp_error = 0; } else { /* something went wrong */ - lp_table[dev].do_print = 0; /* disable lp_interrupt() */ + lp_table[dev]->do_print = 0; /* disable lp_interrupt() */ lp_error = 1; /* printer caused error */ } if (lp_error) { @@ -214,14 +212,14 @@ static int lp_write_interrupt(struct inode *inode, struct file *file, current->timeout = jiffies + LP_TIMEOUT_INTERRUPT; } - interruptible_sleep_on(&lp_table[dev].lp_wait_q); + interruptible_sleep_on(&lp_table[dev]->lp_wait_q); restore_flags(flags); /* we're up again and running. we first disable lp_interrupt(), then check what happened meanwhile */ - lp_table[dev].do_print = 0; - rc = total_bytes_written + lp_table[dev].bytes_written; + lp_table[dev]->do_print = 0; + rc = total_bytes_written + lp_table[dev]->bytes_written; if (current->signal & ~current->blocked) { if (rc) @@ -235,17 +233,17 @@ static int lp_write_interrupt(struct inode *inode, struct file *file, figure out the type of error, exit on request or if nothing has been printed at all. */ - if (lp_table[dev].lp_has_pout(dev)) { + if (lp_table[dev]->lp_has_pout(dev)) { printk(KERN_NOTICE "lp%d: paper-out\n",dev); if (!rc) rc = -ENOSPC; - } else if (!lp_table[dev].lp_is_online(dev)) { + } else if (!lp_table[dev]->lp_is_online(dev)) { printk(KERN_NOTICE "lp%d: off-line\n",dev); if (!rc) rc = -EIO; - } else if (lp_table[dev].lp_is_busy(dev)) { + } else if (lp_table[dev]->lp_is_busy(dev)) { printk(KERN_NOTICE "lp%d: on fire\n",dev); if (!rc) rc = -EIO; } - if (lp_table[dev].flags & LP_ABORT) + if (lp_table[dev]->flags & LP_ABORT) return rc; } /* check if our buffer was completely printed, if not, most likely @@ -253,31 +251,33 @@ static int lp_write_interrupt(struct inode *inode, struct file *file, against, we start all over again. Else we set the read-pointer of the buffer and count the printed characters */ - if (!lp_table[dev].copy_size) { - total_bytes_written += lp_table[dev].bytes_written; - buf += lp_table[dev].bytes_written; - count -= lp_table[dev].bytes_written; + if (!lp_table[dev]->copy_size) { + total_bytes_written += lp_table[dev]->bytes_written; + buf += lp_table[dev]->bytes_written; + count -= lp_table[dev]->bytes_written; } } } while (count > 0); return total_bytes_written; } +#else +void (*lp_interrupt)() = NULL; #endif #if WHICH_DRIVER != FORCE_INTERRUPT #if WHICH_DRIVER == FORCE_POLLING -static int lp_write(struct inode *inode, struct file *file, - const char *buf, int count) +static long lp_write(struct inode *inode, struct file *file, + const char *buf, unsigned long count) #else -static int lp_write_polled(struct inode *inode, struct file *file, - const char *buf, int count) +static long lp_write_polled(struct inode *inode, struct file *file, + const char *buf, unsigned long count) #endif { char *temp = buf; int dev = MINOR(inode->i_rdev); #ifdef LP_DEBUG - if (jiffies-lp_last_call > lp_table[dev].time) { + if (jiffies-lp_last_call > lp_table[dev]->time) { lp_total_chars = 0; lp_max_count = 1; } @@ -293,25 +293,25 @@ static int lp_write_polled(struct inode *inode, struct file *file, lp_total_chars++; #endif } else { /* if printer timed out */ - if (lp_table[dev].lp_has_pout(dev)) { + if (lp_table[dev]->lp_has_pout(dev)) { printk(KERN_NOTICE "lp%d: out of paper\n",dev); - if (lp_table[dev].flags & LP_ABORT) + if (lp_table[dev]->flags & LP_ABORT) return temp - buf ? temp-buf : -ENOSPC; current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + LP_TIMEOUT_POLLED; schedule(); - } else if (!lp_table[dev].lp_is_online(dev)) { + } else if (!lp_table[dev]->lp_is_online(dev)) { printk(KERN_NOTICE "lp%d: off-line\n",dev); - if (lp_table[dev].flags & LP_ABORT) + if (lp_table[dev]->flags & LP_ABORT) return temp - buf ? temp-buf : -EIO; current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + LP_TIMEOUT_POLLED; schedule(); } else /* not offline or out of paper. on fire? */ - if (lp_table[dev].lp_is_busy(dev)) { + if (lp_table[dev]->lp_is_busy(dev)) { printk(KERN_NOTICE "lp%d: on fire\n",dev); - if (lp_table[dev].flags & LP_ABORT) + if (lp_table[dev]->flags & LP_ABORT) return temp - buf ? temp-buf : -EFAULT; current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + LP_TIMEOUT_POLLED; @@ -327,11 +327,11 @@ static int lp_write_polled(struct inode *inode, struct file *file, } #ifdef LP_DEBUG printk("lp sleeping at %d characters for %d jiffies\n", - lp_total_chars, lp_table[dev].time); + lp_total_chars, lp_table[dev]->time); lp_total_chars = 0; #endif current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + lp_table[dev].time; + current->timeout = jiffies + lp_table[dev]->time; schedule(); } } @@ -339,11 +339,11 @@ static int lp_write_polled(struct inode *inode, struct file *file, } #endif -static unsigned int lp_irq = 0; +unsigned int lp_irq = 0; #if WHICH_DRIVER == PREFER_INTERRUPT -static int lp_write(struct inode *inode, struct file *file, - const char *buf, int count) +static long lp_write(struct inode *inode, struct file *file, + const char *buf, unsigned long count) { if (lp_irq) return lp_write_interrupt(inode, file, buf, count); @@ -352,8 +352,8 @@ static int lp_write(struct inode *inode, struct file *file, } #endif -static int lp_lseek(struct inode *inode, struct file *file, - off_t offset, int origin) +static long long lp_lseek(struct inode * inode, struct file * file, + long long offset, int origin) { return -ESPIPE; } @@ -361,22 +361,45 @@ static int lp_lseek(struct inode *inode, struct file *file, static int lp_open(struct inode *inode, struct file *file) { int dev = MINOR(inode->i_rdev); + int ret; - if (dev >= max_lp) + if (dev >= MAX_LP) return -ENODEV; - if (!(lp_table[dev].flags & LP_EXIST)) +#ifdef CONFIG_KERNELD + if (!lp_table[dev]) { + char modname[30]; + + sprintf(modname, "char-major-%d-%d", LP_MAJOR, dev); + request_module(modname); + } +#endif + if (!lp_table[dev]) + return -ENODEV; + if (!(lp_table[dev]->flags & LP_EXIST)) return -ENODEV; - if (lp_table[dev].flags & LP_BUSY) + if (lp_table[dev]->flags & LP_BUSY) return -EBUSY; - lp_table[dev].flags |= LP_BUSY; + lp_table[dev]->flags |= LP_BUSY; - return 0; + ret = lp_table[dev]->lp_open(dev); + if (ret != 0) { + lp_table[dev]->flags &= ~LP_BUSY; + } + else { + MOD_INC_USE_COUNT; + } + return ret; } -static void lp_release(struct inode *inode, struct file *file) +static int lp_release(struct inode *inode, struct file *file) { - lp_table[MINOR(inode->i_rdev)].flags &= ~LP_BUSY; + int dev =MINOR(inode->i_rdev); + + lp_table[dev]->flags &= ~LP_BUSY; + lp_table[dev]->lp_release(dev); + MOD_DEC_USE_COUNT; + return 0; } @@ -391,30 +414,33 @@ static int lp_ioctl(struct inode *inode, struct file *file, #endif if (minor >= max_lp) return -ENODEV; - if (!(lp_table[minor].flags & LP_EXIST)) + if (!(lp_table[minor]->flags & LP_EXIST)) return -ENODEV; switch (cmd) { case LPTIME: - lp_table[minor].time = arg; + lp_table[minor]->time = arg; break; case LPCHAR: - lp_table[minor].chars = arg; + lp_table[minor]->chars = arg; break; case LPABORT: if (arg) - lp_table[minor].flags |= LP_ABORT; + lp_table[minor]->flags |= LP_ABORT; else - lp_table[minor].flags &= ~LP_ABORT; + lp_table[minor]->flags &= ~LP_ABORT; break; case LPWAIT: - lp_table[minor].wait = arg; + lp_table[minor]->wait = arg; break; case LPSETIRQ: case LPGETIRQ: retval = lp_irq; break; default: - retval = -EINVAL; + if (lp_table[minor]->lp_ioctl) + retval = lp_table[minor]->lp_ioctl(minor, cmd, arg); + else + retval = -EINVAL; } return retval; } @@ -425,13 +451,19 @@ static struct file_operations lp_fops = { NULL, /* lp_read */ lp_write, NULL, /* lp_readdir */ - NULL, /* lp_select */ + NULL, /* lp_poll */ lp_ioctl, NULL, /* lp_mmap */ lp_open, lp_release }; +EXPORT_SYMBOL(lp_table); +EXPORT_SYMBOL(lp_irq); +EXPORT_SYMBOL(lp_interrupt); +EXPORT_SYMBOL(lp_init); +EXPORT_SYMBOL(register_parallel); +EXPORT_SYMBOL(unregister_parallel); int lp_init(void) { @@ -441,8 +473,8 @@ int lp_init(void) return -EBUSY; if (register_chrdev(LP_MAJOR,"lp", &lp_fops)) { - printk("unable to get major %d for line printer\n", LP_MAJOR); - return -EBUSY; + printk(KERN_ERR "unable to get major %d for line printer\n", LP_MAJOR); + return -ENXIO; } #if WHICH_DRIVER == FORCE_POLLING @@ -450,35 +482,14 @@ int lp_init(void) printk(KERN_INFO "lp_init: lp using polling driver\n"); #else -#ifdef CONFIG_AMIGA - if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) - lp_irq = add_isr(IRQ_AMIGA_CIAA_FLG, lp_interrupt, 0, - NULL, "printer"); -#endif -#ifdef CONFIG_ATARI - if (MACH_IS_ATARI) - lp_irq = add_isr(IRQ_MFP_BUSY, lp_interrupt, IRQ_TYPE_SLOW, - NULL, "printer"); + lp_irq = 1; + printk(KERN_INFO "lp_init: lp using interrupt driver\n"); #endif - if (lp_irq) - printk(KERN_INFO "lp_init: lp using interrupt\n"); - else - -#if WHICH_DRIVER == PREFER_INTERRUPT - printk(KERN_INFO "lp_init: lp using polling driver\n"); -#else - printk(KERN_WARNING "lp_init: can't get interrupt, and polling driver not configured\n"); -#endif -#endif - - max_lp = 0; - max_lp += lp_internal_init(lp_table, max_lp, MAX_LP, WHICH_DRIVER); +#ifndef MODULE + lp_internal_init(); #ifdef CONFIG_MULTIFACE_III_LP - max_lp += lp_mfc_init(lp_table, max_lp, MAX_LP, WHICH_DRIVER); -#if WHICH_DRIVER != FORCE_POLLING - add_isr(IRQ_AMIGA_PORTS, lp_interrupt, 0, NULL, - "Multiface III printer"); + lp_mfc_init(); #endif #endif return 0; @@ -490,3 +501,47 @@ int lp_init(void) void lp_setup(char *str, int *ints) { } + +#ifdef MODULE +int init_module(void) +{ +return lp_init(); +} + +void cleanup_module(void) +{ +unregister_chrdev(LP_MAJOR, "lp"); +} +#endif + +/* + * (un-)register for hardware drivers + * tab is an inititalised lp_struct, dev the desired minor + * if dev < 0, let the driver choose the first free minor + * if sucessful return the minor, else -1 + */ +int register_parallel(struct lp_struct *tab, int dev) +{ +if (dev < 0) { + dev = 0; + while ((dev < MAX_LP) && (lp_table[dev] != NULL)) + dev++; +} +if (dev > MAX_LP) + return -1; +if (lp_table[dev] != NULL) + return -1; +lp_table[dev] = tab; +printk(KERN_INFO "lp%d: %s at 0x%08lx\n", dev, tab->name, (long)tab->base); +return dev; +} + +#ifdef CONFIG_MODULES +void unregister_parallel(int dev) +{ +if ((dev < 0) || (dev > MAX_LP) || (lp_table[dev] == NULL)) + printk(KERN_ERR "WARNING: unregister_parallel for non-existant device ignored!\n"); +else + lp_table[dev] = NULL; +} +#endif |