OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [drivers/] [char/] [lp.c] - Blame information for rev 1622

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
3
 * Copyright (C) 1992,1993 by Michael K. Johnson
4
 * - Thanks much to Gunter Windau for pointing out to me where the error
5
 *   checking ought to be.
6
 * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
7
 * Copyright (C) 1994 by Alan Cox (Modularised it)
8
 * LPCAREFUL, LPABORT, LPGETSTATUS added by Chris Metcalf, metcalf@lcs.mit.edu
9
 * Statistics and support for slow printers by Rob Janssen, rob@knoware.nl
10
 * "lp=" command line parameters added by Grant Guenther, grant@torque.net
11
 */
12
 
13
#include <linux/module.h>
14
 
15
#include <linux/errno.h>
16
#include <linux/kernel.h>
17
#include <linux/major.h>
18
#include <linux/sched.h>
19
#include <linux/lp.h>
20
#include <linux/malloc.h>
21
#include <linux/ioport.h>
22
#include <linux/fcntl.h>
23
#include <linux/delay.h>
24
 
25
#include <asm/io.h>
26
#include <asm/segment.h>
27
#include <asm/system.h>
28
 
29
#define NO_IRQ (-1)
30
 
31
/* the BIOS manuals say there can be up to 4 lpt devices
32
 * but I have not seen a board where the 4th address is listed
33
 * if you have different hardware change the table below
34
 * please let me know if you have different equipment
35
 * if you have more than 3 printers, remember to increase LP_NO
36
 */
37
struct lp_struct lp_table[] = {
38
        { 0x3bc, NO_IRQ, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
39
        { 0x378, NO_IRQ, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
40
        { 0x278, NO_IRQ, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
41
};
42
#define LP_NO 3
43
 
44
/* Test if printer is ready (and optionally has no error conditions) */
45
#define LP_READY(minor, status) \
46
  ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : (status & LP_PBUSY))
47
#define LP_CAREFUL_READY(minor, status) \
48
  ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : 1)
49
#define _LP_CAREFUL_READY(status) \
50
   (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
51
      (LP_PBUSY|LP_PSELECD|LP_PERRORP)
52
 
53
/*
54
 * All my debugging code assumes that you debug with only one printer at
55
 * a time. RWWH
56
 * Debug info moved into stats area, so this is no longer true (Rob Janssen)
57
 */
58
 
59
#undef LP_DEBUG
60
 
61
static int lp_reset(int minor)
62
{
63
        outb_p(LP_PSELECP, LP_C(minor));
64
        udelay(LP_DELAY);
65
        outb_p(LP_PSELECP | LP_PINITP, LP_C(minor));
66
        return LP_S(minor);
67
}
68
 
69
static inline int lp_char_polled(char lpchar, int minor)
70
{
71
        int status, wait = 0;
72
        unsigned long count  = 0;
73
        struct lp_stats *stats;
74
 
75
        do {
76
                status = LP_S(minor);
77
                count ++;
78
                if(need_resched)
79
                        schedule();
80
        } while(!LP_READY(minor,status) && count < LP_CHAR(minor));
81
 
82
        if (count == LP_CHAR(minor)) {
83
                return 0;
84
                /* we timed out, and the character was /not/ printed */
85
        }
86
        outb_p(lpchar, LP_B(minor));
87
        stats = &LP_STAT(minor);
88
        stats->chars++;
89
        /* must wait before taking strobe high, and after taking strobe
90
           low, according spec.  Some printers need it, others don't. */
91
        while(wait != LP_WAIT(minor)) wait++;
92
        /* control port takes strobe high */
93
        outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
94
        /* Wait until NBUSY line goes high */
95
        count = 0;
96
        do {
97
                status = LP_S(minor);
98
                count++;
99
                if (need_resched)
100
                        schedule();
101
        } while (LP_READY(minor, status) && (count<LP_CHAR(minor)));
102
        /* take strobe low */
103
        outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
104
        /* update waittime statistics */
105
        if (count > stats->maxwait) {
106
#ifdef LP_DEBUG
107
            printk(KERN_DEBUG "lp%d success after %d counts.\n",minor,count);
108
#endif
109
            stats->maxwait = count;
110
        }
111
        count *= 256;
112
        wait = (count > stats->meanwait)? count - stats->meanwait :
113
                                          stats->meanwait - count;
114
        stats->meanwait = (255*stats->meanwait + count + 128) / 256;
115
        stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
116
 
117
        return 1;
118
}
119
 
120
static inline int lp_char_interrupt(char lpchar, int minor)
121
{
122
        int wait;
123
        unsigned long count = 0;
124
        unsigned char status;
125
        struct lp_stats *stats;
126
 
127
        do {
128
            if(need_resched)
129
                schedule();
130
            if ((status = LP_S(minor)) & LP_PBUSY) {
131
                if (!LP_CAREFUL_READY(minor, status))
132
                        return 0;
133
                outb_p(lpchar, LP_B(minor));
134
                stats = &LP_STAT(minor);
135
                stats->chars++;
136
                /* must wait before taking strobe high, and after taking strobe
137
                   low, according spec.  Some printers need it, others don't. */
138
                wait = 0;
139
                while(wait != LP_WAIT(minor)) wait++;
140
                /* control port takes strobe high */
141
                outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
142
                while(wait) wait--;
143
                /* take strobe low */
144
                outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
145
                /* update waittime statistics */
146
                if (count) {
147
                    if (count > stats->maxwait)
148
                        stats->maxwait = count;
149
                    count *= 256;
150
                    wait = (count > stats->meanwait)? count - stats->meanwait :
151
                                                      stats->meanwait - count;
152
                    stats->meanwait = (255*stats->meanwait + count + 128) / 256;
153
                    stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
154
                }
155
                return 1;
156
            }
157
        } while (count++ < LP_CHAR(minor));
158
 
159
        return 0;
160
}
161
 
162
static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
163
{
164
        struct lp_struct *lp = &lp_table[0];
165
 
166
        while (irq != lp->irq) {
167
                if (++lp >= &lp_table[LP_NO])
168
                        return;
169
        }
170
 
171
        wake_up(&lp->lp_wait_q);
172
}
173
 
174
static inline int lp_write_interrupt(unsigned int minor, const char * buf, int count)
175
{
176
        unsigned long copy_size;
177
        unsigned long total_bytes_written = 0;
178
        unsigned long bytes_written;
179
        struct lp_struct *lp = &lp_table[minor];
180
        unsigned char status;
181
 
182
        do {
183
                bytes_written = 0;
184
                copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
185
                memcpy_fromfs(lp->lp_buffer, buf, copy_size);
186
 
187
                while (copy_size) {
188
                        if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {
189
                                --copy_size;
190
                                ++bytes_written;
191
                                lp_table[minor].runchars++;
192
                        } else {
193
                                int rc = total_bytes_written + bytes_written;
194
                                if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
195
                                         LP_STAT(minor).maxrun = lp_table[minor].runchars;
196
                                status = LP_S(minor);
197
                                if ((status & LP_POUTPA)) {
198
                                        printk(KERN_INFO "lp%d out of paper\n", minor);
199
                                        if (LP_F(minor) & LP_ABORT)
200
                                                return rc?rc:-ENOSPC;
201
                                } else if (!(status & LP_PSELECD)) {
202
                                        printk(KERN_INFO "lp%d off-line\n", minor);
203
                                        if (LP_F(minor) & LP_ABORT)
204
                                                return rc?rc:-EIO;
205
                                } else if (!(status & LP_PERRORP)) {
206
                                        printk(KERN_ERR "lp%d printer error\n", minor);
207
                                        if (LP_F(minor) & LP_ABORT)
208
                                                return rc?rc:-EIO;
209
                                }
210
                                LP_STAT(minor).sleeps++;
211
                                cli();
212
                                outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
213
                                status = LP_S(minor);
214
                                if ((!(status & LP_PACK) || (status & LP_PBUSY))
215
                                  && LP_CAREFUL_READY(minor, status)) {
216
                                        outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
217
                                        sti();
218
                                        continue;
219
                                }
220
                                lp_table[minor].runchars=0;
221
                                current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
222
                                interruptible_sleep_on(&lp->lp_wait_q);
223
                                outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
224
                                sti();
225
                                if (current->signal & ~current->blocked) {
226
                                        if (total_bytes_written + bytes_written)
227
                                                return total_bytes_written + bytes_written;
228
                                        else
229
                                                return -EINTR;
230
                                }
231
                        }
232
                }
233
 
234
                total_bytes_written += bytes_written;
235
                buf += bytes_written;
236
                count -= bytes_written;
237
 
238
        } while (count > 0);
239
 
240
        return total_bytes_written;
241
}
242
 
243
static inline int lp_write_polled(unsigned int minor, const char * buf, int count)
244
{
245
        int  retval,status;
246
        char c;
247
        const char *temp;
248
 
249
        temp = buf;
250
        while (count > 0) {
251
                c = get_user(temp);
252
                retval = lp_char_polled(c, minor);
253
                /* only update counting vars if character was printed */
254
                if (retval) {
255
                        count--; temp++;
256
                        lp_table[minor].runchars++;
257
                } else { /* if printer timed out */
258
                        if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
259
                                 LP_STAT(minor).maxrun = lp_table[minor].runchars;
260
                        status = LP_S(minor);
261
 
262
                        if (status & LP_POUTPA) {
263
                                printk(KERN_INFO "lp%d out of paper\n", minor);
264
                                if(LP_F(minor) & LP_ABORT)
265
                                        return temp-buf?temp-buf:-ENOSPC;
266
                                current->state = TASK_INTERRUPTIBLE;
267
                                current->timeout = jiffies + LP_TIMEOUT_POLLED;
268
                                schedule();
269
                        } else
270
                        if (!(status & LP_PSELECD)) {
271
                                printk(KERN_INFO "lp%d off-line\n", minor);
272
                                if(LP_F(minor) & LP_ABORT)
273
                                        return temp-buf?temp-buf:-EIO;
274
                                current->state = TASK_INTERRUPTIBLE;
275
                                current->timeout = jiffies + LP_TIMEOUT_POLLED;
276
                                schedule();
277
                        } else
278
                        /* not offline or out of paper. on fire? */
279
                        if (!(status & LP_PERRORP)) {
280
                                printk(KERN_ERR "lp%d reported invalid error status (on fire, eh?)\n", minor);
281
                                if(LP_F(minor) & LP_ABORT)
282
                                        return temp-buf?temp-buf:-EIO;
283
                                current->state = TASK_INTERRUPTIBLE;
284
                                current->timeout = jiffies + LP_TIMEOUT_POLLED;
285
                                schedule();
286
                        }
287
 
288
                        /* check for signals before going to sleep */
289
                        if (current->signal & ~current->blocked) {
290
                                if (temp != buf)
291
                                        return temp-buf;
292
                                else
293
                                        return -EINTR;
294
                        }
295
                        LP_STAT(minor).sleeps++;
296
#ifdef LP_DEBUG
297
                        printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n",
298
                                minor,lp_table[minor].runchars, LP_TIME(minor));
299
#endif
300
                        lp_table[minor].runchars=0;
301
                        current->state = TASK_INTERRUPTIBLE;
302
                        current->timeout = jiffies + LP_TIME(minor);
303
                        schedule();
304
                }
305
        }
306
        return temp-buf;
307
}
308
 
309
static int lp_write(struct inode * inode, struct file * file, const char * buf, int count)
310
{
311
        unsigned int minor = MINOR(inode->i_rdev);
312
 
313
        if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
314
                lp_table[minor].runchars = 0;
315
        lp_table[minor].lastcall = jiffies;
316
 
317
        if (LP_IRQ(minor) != NO_IRQ)
318
                return lp_write_interrupt(minor, buf, count);
319
        else
320
                return lp_write_polled(minor, buf, count);
321
}
322
 
323
static int lp_lseek(struct inode * inode, struct file * file,
324
                    off_t offset, int origin)
325
{
326
        return -ESPIPE;
327
}
328
 
329
static int lp_open(struct inode * inode, struct file * file)
330
{
331
        unsigned int minor = MINOR(inode->i_rdev);
332
        int ret;
333
        unsigned int irq;
334
 
335
        if (minor >= LP_NO)
336
                return -ENXIO;
337
        if ((LP_F(minor) & LP_EXIST) == 0)
338
                return -ENXIO;
339
        if (LP_F(minor) & LP_BUSY)
340
                return -EBUSY;
341
 
342
        MOD_INC_USE_COUNT;
343
 
344
        /* If ABORTOPEN is set and the printer is offline or out of paper,
345
           we may still want to open it to perform ioctl()s.  Therefore we
346
           have commandeered O_NONBLOCK, even though it is being used in
347
           a non-standard manner.  This is strictly a Linux hack, and
348
           should most likely only ever be used by the tunelp application. */
349
        if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
350
                int status = LP_S(minor);
351
                if (status & LP_POUTPA) {
352
                        printk(KERN_INFO "lp%d out of paper\n", minor);
353
                        MOD_DEC_USE_COUNT;
354
                        return -ENOSPC;
355
                } else if (!(status & LP_PSELECD)) {
356
                        printk(KERN_INFO "lp%d off-line\n", minor);
357
                        MOD_DEC_USE_COUNT;
358
                        return -EIO;
359
                } else if (!(status & LP_PERRORP)) {
360
                        printk(KERN_ERR "lp%d printer error\n", minor);
361
                        MOD_DEC_USE_COUNT;
362
                        return -EIO;
363
                }
364
        }
365
 
366
        if ((irq = LP_IRQ(minor)) != NO_IRQ) {
367
                lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
368
                if (!lp_table[minor].lp_buffer) {
369
                        MOD_DEC_USE_COUNT;
370
                        return -ENOMEM;
371
                }
372
 
373
                ret = request_irq(irq, lp_interrupt, SA_INTERRUPT, "printer", NULL);
374
                if (ret) {
375
                        kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
376
                        lp_table[minor].lp_buffer = NULL;
377
                        printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret);
378
                        MOD_DEC_USE_COUNT;
379
                        return ret;
380
                }
381
        }
382
 
383
        LP_F(minor) |= LP_BUSY;
384
        return 0;
385
}
386
 
387
static void lp_release(struct inode * inode, struct file * file)
388
{
389
        unsigned int minor = MINOR(inode->i_rdev);
390
        unsigned int irq;
391
 
392
        if ((irq = LP_IRQ(minor)) != NO_IRQ) {
393
                free_irq(irq, NULL);
394
                kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
395
                lp_table[minor].lp_buffer = NULL;
396
        }
397
 
398
        LP_F(minor) &= ~LP_BUSY;
399
        MOD_DEC_USE_COUNT;
400
}
401
 
402
 
403
static int lp_ioctl(struct inode *inode, struct file *file,
404
                    unsigned int cmd, unsigned long arg)
405
{
406
        unsigned int minor = MINOR(inode->i_rdev);
407
        int retval = 0;
408
 
409
#ifdef LP_DEBUG
410
        printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
411
#endif
412
        if (minor >= LP_NO)
413
                return -ENODEV;
414
        if ((LP_F(minor) & LP_EXIST) == 0)
415
                return -ENODEV;
416
        switch ( cmd ) {
417
                case LPTIME:
418
                        LP_TIME(minor) = arg * HZ/100;
419
                        break;
420
                case LPCHAR:
421
                        LP_CHAR(minor) = arg;
422
                        break;
423
                case LPABORT:
424
                        if (arg)
425
                                LP_F(minor) |= LP_ABORT;
426
                        else
427
                                LP_F(minor) &= ~LP_ABORT;
428
                        break;
429
                case LPABORTOPEN:
430
                        if (arg)
431
                                LP_F(minor) |= LP_ABORTOPEN;
432
                        else
433
                                LP_F(minor) &= ~LP_ABORTOPEN;
434
                        break;
435
                case LPCAREFUL:
436
                        if (arg)
437
                                LP_F(minor) |= LP_CAREFUL;
438
                        else
439
                                LP_F(minor) &= ~LP_CAREFUL;
440
                        break;
441
                case LPWAIT:
442
                        LP_WAIT(minor) = arg;
443
                        break;
444
                case LPSETIRQ: {
445
                        int oldirq;
446
                        int newirq = arg;
447
                        struct lp_struct *lp = &lp_table[minor];
448
 
449
                        if (!suser())
450
                                return -EPERM;
451
 
452
                        oldirq = LP_IRQ(minor);
453
 
454
                        /* Allocate buffer now if we are going to need it */
455
                        if (oldirq == NO_IRQ && newirq != NO_IRQ) {
456
                                lp->lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
457
                                if (!lp->lp_buffer)
458
                                        return -ENOMEM;
459
                        }
460
 
461
                        if (oldirq != NO_IRQ) {
462
                                free_irq(oldirq, NULL);
463
                        }
464
                        if (newirq != NO_IRQ) {
465
                                /* Install new irq */
466
                                if ((retval = request_irq(newirq, lp_interrupt, SA_INTERRUPT, "printer", NULL))) {
467
                                        if (oldirq != NO_IRQ) {
468
                                                /* restore old irq */
469
                                                request_irq(oldirq, lp_interrupt, SA_INTERRUPT, "printer", NULL);
470
                                        } else {
471
                                                /* We don't need the buffer */
472
                                                kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
473
                                                lp->lp_buffer = NULL;
474
                                        }
475
                                        return retval;
476
                                }
477
                        }
478
                        if (oldirq != NO_IRQ && newirq == NO_IRQ) {
479
                                /* We don't need the buffer */
480
                                kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
481
                                lp->lp_buffer = NULL;
482
                        }
483
                        LP_IRQ(minor) = newirq;
484
                        lp_reset(minor);
485
                        break;
486
                }
487
                case LPGETIRQ:
488
                        retval = verify_area(VERIFY_WRITE, (void *) arg,
489
                            sizeof(int));
490
                        if (retval)
491
                                return retval;
492
                        memcpy_tofs((int *) arg, &LP_IRQ(minor), sizeof(int));
493
                        break;
494
                case LPGETSTATUS:
495
                        retval = verify_area(VERIFY_WRITE, (void *) arg,
496
                            sizeof(int));
497
                        if (retval)
498
                                return retval;
499
                        else {
500
                                int status = LP_S(minor);
501
                                memcpy_tofs((int *) arg, &status, sizeof(int));
502
                        }
503
                        break;
504
                case LPRESET:
505
                        lp_reset(minor);
506
                        break;
507
                case LPGETSTATS:
508
                        retval = verify_area(VERIFY_WRITE, (void *) arg,
509
                            sizeof(struct lp_stats));
510
                        if (retval)
511
                                return retval;
512
                        else {
513
                                memcpy_tofs((int *) arg, &LP_STAT(minor), sizeof(struct lp_stats));
514
                                if (suser())
515
                                        memset(&LP_STAT(minor), 0, sizeof(struct lp_stats));
516
                        }
517
                        break;
518
                case LPGETFLAGS:
519
                        retval = verify_area(VERIFY_WRITE, (void *) arg,
520
                            sizeof(int));
521
                        if (retval)
522
                                return retval;
523
                        else {
524
                                int status = LP_F(minor);
525
                                memcpy_tofs((int *) arg, &status, sizeof(int));
526
                        }
527
                        break;
528
                default:
529
                        retval = -EINVAL;
530
        }
531
        return retval;
532
}
533
 
534
 
535
static struct file_operations lp_fops = {
536
        lp_lseek,
537
        NULL,           /* lp_read */
538
        lp_write,
539
        NULL,           /* lp_readdir */
540
        NULL,           /* lp_select */
541
        lp_ioctl,
542
        NULL,           /* lp_mmap */
543
        lp_open,
544
        lp_release
545
};
546
 
547
static int lp_probe(int offset)
548
{
549
        int base, size;
550
        unsigned int testvalue;
551
 
552
        base = LP_B(offset);
553
        if (base == 0)
554
                return -1;              /* de-configured by command line */
555
        if (LP_IRQ(offset) != NO_IRQ && LP_IRQ(offset) > 15)
556
                return -1;              /* bogus interrupt value */
557
        size = (base == 0x3bc)? 3 : 8;
558
        if (check_region(base, size) < 0)
559
                return -1;
560
        /* write to port & read back to check */
561
        outb_p(LP_DUMMY, base);
562
        udelay(LP_DELAY);
563
        testvalue = inb_p(base);
564
        if (testvalue == LP_DUMMY) {
565
                LP_F(offset) |= LP_EXIST;
566
                lp_reset(offset);
567
                printk(KERN_INFO "lp%d at 0x%04x, ", offset, base);
568
                request_region(base, size, "lp");
569
                if (LP_IRQ(offset) != NO_IRQ)
570
                        printk("(irq = %d)\n", LP_IRQ(offset));
571
                else
572
                        printk("(polling)\n");
573
                return 1;
574
        } else
575
                return 0;
576
}
577
 
578
/* Command line parameters:
579
 
580
   When the lp driver is built in to the kernel, you may use the
581
   LILO/LOADLIN command line to set the port addresses and interrupts
582
   that the driver will use.
583
 
584
   Syntax:      lp=port0[,irq0[,port1[,irq1[,port2[,irq2]]]]]
585
 
586
   For example:   lp=0x378,0   or   lp=0x278,5,0x378,7
587
 
588
   Note that if this feature is used, you must specify *all* the ports
589
   you want considered, there are no defaults.  You can disable a
590
   built-in driver with lp=0 .
591
 
592
*/
593
 
594
void    lp_setup(char *str, int *ints)
595
 
596
{
597
        LP_B(0)   = ((ints[0] > 0) ? ints[1] : 0 );
598
        LP_IRQ(0) = ((ints[0] > 1) ? ints[2] : NO_IRQ );
599
        LP_B(1)   = ((ints[0] > 2) ? ints[3] : 0 );
600
        LP_IRQ(1) = ((ints[0] > 3) ? ints[4] : NO_IRQ );
601
        LP_B(2)   = ((ints[0] > 4) ? ints[5] : 0 );
602
        LP_IRQ(2) = ((ints[0] > 5) ? ints[6] : NO_IRQ );
603
}
604
 
605
#ifdef MODULE
606
static int io[] = {0, 0, 0};
607
static int irq[] = {NO_IRQ, NO_IRQ, NO_IRQ};
608
 
609
#define lp_init init_module
610
#endif
611
 
612
int lp_init(void)
613
{
614
        int offset = 0;
615
        int count = 0;
616
#ifdef MODULE
617
        int failed = 0;
618
#endif
619
 
620
        if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
621
                printk("lp: unable to get major %d\n", LP_MAJOR);
622
                return -EIO;
623
        }
624
#ifdef MODULE
625
        /* When user feeds parameters, use them */
626
        for (offset=0; offset < LP_NO; offset++) {
627
                int specified=0;
628
 
629
                if (io[offset] != 0) {
630
                        LP_B(offset) = io[offset];
631
                        specified++;
632
                }
633
                if (irq[offset] != NO_IRQ) {
634
                        LP_IRQ(offset) = irq[offset];
635
                        specified++;
636
                }
637
                if (specified) {
638
                        if (lp_probe(offset) <= 0) {
639
                                printk(KERN_INFO "lp%d: Not found\n", offset);
640
                                failed++;
641
                        } else
642
                                count++;
643
                }
644
        }
645
        /* Successful specified devices increase count
646
         * Unsuccessful specified devices increase failed
647
         */
648
        if (count)
649
                return 0;
650
        if (failed) {
651
                printk(KERN_INFO "lp: No override devices found.\n");
652
                unregister_chrdev(LP_MAJOR,"lp");
653
                return -EIO;
654
        }
655
        /* Only get here if there were no specified devices. To continue
656
         * would be silly since the above code has scribbled all over the
657
         * probe list.
658
         */
659
#endif
660
        /* take on all known port values */
661
        for (offset = 0; offset < LP_NO; offset++) {
662
                int ret = lp_probe(offset);
663
                if (ret < 0)
664
                        continue;
665
                count += ret;
666
        }
667
        if (count == 0)
668
                printk("lp: Driver configured but no interfaces found.\n");
669
 
670
        return 0;
671
}
672
 
673
#ifdef MODULE
674
void cleanup_module(void)
675
{
676
        int offset;
677
 
678
        unregister_chrdev(LP_MAJOR,"lp");
679
        for (offset = 0; offset < LP_NO; offset++) {
680
                int base, size;
681
                base = LP_B(offset);
682
                size = (base == 0x3bc)? 3 : 8;
683
                if (LP_F(offset) & LP_EXIST)
684
                        release_region(LP_B(offset),size);
685
        }
686
}
687
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.