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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [char/] [lp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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