1 /*
2 * A version of the "short" driver which drives a parallel printer directly,
3 * with a lot of simplifying assumptions.
4 *
5 * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
6 * Copyright (C) 2001 O'Reilly & Associates
7 *
8 * The source code in this file can be freely used, adapted,
9 * and redistributed in source or binary form, so long as an
10 * acknowledgment appears in derived source files. The citation
11 * should list that the code comes from the book "Linux Device
12 * Drivers" by Alessandro Rubini and Jonathan Corbet, published
13 * by O'Reilly & Associates. No warranty is attached;
14 * we cannot take responsibility for errors or fitness for use.
15 *
16 * $Id: shortprint.c,v 1.4 2004/09/26 08:01:04 gregkh Exp $
17 */
18 #include <linux/config.h>
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21
22 #include <linux/sched.h>
23 #include <linux/kernel.h> /* printk() */
24 #include <linux/fs.h> /* everything... */
25 #include <linux/errno.h> /* error codes */
26 #include <linux/delay.h> /* udelay */
27 #include <linux/slab.h>
28 #include <linux/ioport.h>
29 #include <linux/interrupt.h>
30 #include <linux/workqueue.h>
31 #include <linux/timer.h>
32 #include <linux/poll.h>
33
34 #include <asm/io.h>
35 #include <asm/semaphore.h>
36 #include <asm/atomic.h>
37
38 #include "shortprint.h"
39
40 #define SHORTP_NR_PORTS 3
41
42 /*
43 * all of the parameters have no "shortp_" prefix, to save typing when
44 * specifying them at load time
45 */
46 static int major = 0; /* dynamic by default */
47 module_param(major, int, 0);
48
49 /* default is the first printer port on PC's. "shortp_base" is there too
50 because it's what we want to use in the code */
51 static unsigned long base = 0x378;
52 unsigned long shortp_base = 0;
53 module_param(base, long, 0);
54
55 /* The interrupt line is undefined by default. "shortp_irq" is as above */
56 static int irq = -1;
57 static int shortp_irq = -1;
58 module_param(irq, int, 0);
59
60 /* Microsecond delay around strobe. */
61 static int delay = 0;
62 static int shortp_delay;
63 module_param(delay, int, 0);
64
65 MODULE_AUTHOR ("Jonathan Corbet");
66 MODULE_LICENSE("Dual BSD/GPL");
67
68 /*
69 * Forwards.
70 */
71 static void shortp_cleanup(void);
72 static void shortp_timeout(unsigned long unused);
73
74 /*
75 * Input is managed through a simple circular buffer which, among other things,
76 * is allowed to overrun if the reader isn't fast enough. That makes life simple
77 * on the "read" interrupt side, where we don't want to block.
78 */
79 static unsigned long shortp_in_buffer = 0;
80 static unsigned long volatile shortp_in_head;
81 static volatile unsigned long shortp_in_tail;
82 DECLARE_WAIT_QUEUE_HEAD(shortp_in_queue);
83 static struct timeval shortp_tv; /* When the interrupt happened. */
84
85 /*
86 * Atomicly increment an index into shortp_in_buffer
87 */
88 static inline void shortp_incr_bp(volatile unsigned long *index, int delta)
89 {
90 unsigned long new = *index + delta;
91 barrier (); /* Don't optimize these two together */
92 *index = (new >= (shortp_in_buffer + PAGE_SIZE)) ? shortp_in_buffer : new;
93 }
94
95
96 /*
97 * On the write side we have to be more careful, since we don't want to drop
98 * data. The semaphore is used to serialize write-side access to the buffer;
99 * there is only one consumer, so read-side access is unregulated. The
100 * wait queue will be awakened when space becomes available in the buffer.
101 */
102 static unsigned char *shortp_out_buffer = NULL;
103 static volatile unsigned char *shortp_out_head, *shortp_out_tail;
104 static struct semaphore shortp_out_sem;
105 static DECLARE_WAIT_QUEUE_HEAD(shortp_out_queue);
106
107 /*
108 * Feeding the output queue to the device is handled by way of a
109 * workqueue.
110 */
111 static void shortp_do_work(void *);
112 static DECLARE_WORK(shortp_work, shortp_do_work, NULL);
113 static struct workqueue_struct *shortp_workqueue;
114
115 /*
116 * Available space in the output buffer; should be called with the semaphore
117 * held. Returns contiguous space, so caller need not worry about wraps.
118 */
119 static inline int shortp_out_space(void)
120 {
121 if (shortp_out_head >= shortp_out_tail) {
122 int space = PAGE_SIZE - (shortp_out_head - shortp_out_buffer);
123 return (shortp_out_tail == shortp_out_buffer) ? space - 1 : space;
124 } else
125 return (shortp_out_tail - shortp_out_head) - 1;
126 }
127
128 static inline void shortp_incr_out_bp(volatile unsigned char **bp, int incr)
129 {
130 unsigned char *new = (unsigned char *) *bp + incr;
131 if (new >= (shortp_out_buffer + PAGE_SIZE))
132 new -= PAGE_SIZE;
133 *bp = new;
134 }
135
136 /*
137 * The output "process" is controlled by a spin lock; decisions on
138 * shortp_output_active or manipulation of shortp_out_tail require
139 * that this lock be held.
140 */
141 static spinlock_t shortp_out_lock;
142 volatile static int shortp_output_active;
143 DECLARE_WAIT_QUEUE_HEAD(shortp_empty_queue); /* waked when queue empties */
144
145 /*
146 * When output is active, the timer is too, in case we miss interrupts. Hold
147 * shortp_out_lock if you mess with the timer.
148 */
149 static struct timer_list shortp_timer;
150 #define TIMEOUT 5*HZ /* Wait a long time */
151
152
153 /*
154 * Open the device.
155 */
156 static int shortp_open(struct inode *inode, struct file *filp)
157 {
158 return 0;
159 }
160
161
162 static int shortp_release(struct inode *inode, struct file *filp)
163 {
164 /* Wait for any pending output to complete */
165 wait_event_interruptible(shortp_empty_queue, shortp_output_active==0);
166
167 return 0;
168 }
169
170
171
172 static unsigned int shortp_poll(struct file *filp, poll_table *wait)
173 {
174 return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
175 }
176
177
178
179 /*
180 * The read routine, which doesn't return data from the device; instead, it
181 * returns timing information just like the "short" device.
182 */
183 static ssize_t shortp_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
184 {
185 int count0;
186 DEFINE_WAIT(wait);
187
188 while (shortp_in_head == shortp_in_tail) {
189 prepare_to_wait(&shortp_in_queue, &wait, TASK_INTERRUPTIBLE);
190 if (shortp_in_head == shortp_in_tail)
191 schedule();
192 finish_wait(&shortp_in_queue, &wait);
193 if (signal_pending (current)) /* a signal arrived */
194 return -ERESTARTSYS; /* tell the fs layer to handle it */
195 }
196
197 /* count0 is the number of readable data bytes */
198 count0 = shortp_in_head - shortp_in_tail;
199 if (count0 < 0) /* wrapped */
200 count0 = shortp_in_buffer + PAGE_SIZE - shortp_in_tail;
201 if (count0 < count)
202 count = count0;
203
204 if (copy_to_user(buf, (char *)shortp_in_tail, count))
205 return -EFAULT;
206 shortp_incr_bp(&shortp_in_tail, count);
207 return count;
208 }
209
210
211 /*
212 * Wait for the printer to be ready; this can sleep.
213 */
214 static void shortp_wait(void)
215 {
216 if ((inb(shortp_base + SP_STATUS) & SP_SR_BUSY) == 0) {
217 printk(KERN_INFO "shortprint: waiting for printer busy\n");
218 printk(KERN_INFO "Status is 0x%x\n", inb(shortp_base + SP_STATUS));
219 while ((inb(shortp_base + SP_STATUS) & SP_SR_BUSY) == 0) {
220 set_current_state(TASK_INTERRUPTIBLE);
221 schedule_timeout(10*HZ);
222 }
223 }
224 }
225
226
227 /*
228 * Write the next character from the buffer. There should *be* a next
229 * character... The spinlock should be held when this routine is called.
230 */
231 static void shortp_do_write(void)
232 {
233 unsigned char cr = inb(shortp_base + SP_CONTROL);
234
235 /* Something happened; reset the timer */
236 mod_timer(&shortp_timer, jiffies + TIMEOUT);
237
238 /* Strobe a byte out to the device */
239 outb_p(*shortp_out_tail, shortp_base+SP_DATA);
240 shortp_incr_out_bp(&shortp_out_tail, 1);
241 if (shortp_delay)
242 udelay(shortp_delay);
243 outb_p(cr | SP_CR_STROBE, shortp_base+SP_CONTROL);
244 if (shortp_delay)
245 udelay(shortp_delay);
246 outb_p(cr & ~SP_CR_STROBE, shortp_base+SP_CONTROL);
247 }
248
249
250 /*
251 * Start output; call under lock.
252 */
253 static void shortp_start_output(void)
254 {
255 if (shortp_output_active) /* Should never happen */
256 return;
257
258 /* Set up our 'missed interrupt' timer */
259 shortp_output_active = 1;
260 shortp_timer.expires = jiffies + TIMEOUT;
261 add_timer(&shortp_timer);
262
263 /* And get the process going. */
264 queue_work(shortp_workqueue, &shortp_work);
265 }
266
267
268 /*
269 * Write to the device.
270 */
271 static ssize_t shortp_write(struct file *filp, const char __user *buf, size_t count,
272 loff_t *f_pos)
273 {
274 int space, written = 0;
275 unsigned long flags;
276 /*
277 * Take and hold the semaphore for the entire duration of the operation. The
278 * consumer side ignores it, and it will keep other data from interleaving
279 * with ours.
280 */
281 if (down_interruptible(&shortp_out_sem))
282 return -ERESTARTSYS;
283 /*
284 * Out with the data.
285 */
286 while (written < count) {
287 /* Hang out until some buffer space is available. */
288 space = shortp_out_space();
289 if (space <= 0) {
290 if (wait_event_interruptible(shortp_out_queue,
291 (space = shortp_out_space()) > 0))
292 goto out;
293 }
294
295 /* Move data into the buffer. */
296 if ((space + written) > count)
297 space = count - written;
298 if (copy_from_user((char *) shortp_out_head, buf, space)) {
299 up(&shortp_out_sem);
300 return -EFAULT;
301 }
302 shortp_incr_out_bp(&shortp_out_head, space);
303 buf += space;
304 written += space;
305
306 /* If no output is active, make it active. */
307 spin_lock_irqsave(&shortp_out_lock, flags);
308 if (! shortp_output_active)
309 shortp_start_output();
310 spin_unlock_irqrestore(&shortp_out_lock, flags);
311 }
312
313 out:
314 *f_pos += written;
315 up(&shortp_out_sem);
316 return written;
317 }
318
319
320 /*
321 * The bottom-half handler.
322 */
323
324
325 static void shortp_do_work(void *unused)
326 {
327 int written;
328 unsigned long flags;
329
330 /* Wait until the device is ready */
331 shortp_wait();
332
333 spin_lock_irqsave(&shortp_out_lock, flags);
334
335 /* Have we written everything? */
336 if (shortp_out_head == shortp_out_tail) { /* empty */
337 shortp_output_active = 0;
338 wake_up_interruptible(&shortp_empty_queue);
339 del_timer(&shortp_timer);
340 }
341 /* Nope, write another byte */
342 else
343 shortp_do_write();
344
345 /* If somebody's waiting, maybe wake them up. */
346 if (((PAGE_SIZE + shortp_out_tail - shortp_out_head) % PAGE_SIZE) > SP_MIN_SPACE) {
347 wake_up_interruptible(&shortp_out_queue);
348 }
349 spin_unlock_irqrestore(&shortp_out_lock, flags);
350
351 /* Handle the "read" side operation */
352 written = sprintf((char *)shortp_in_head, "%08u.%06u\n",
353 (int)(shortp_tv.tv_sec % 100000000),
354 (int)(shortp_tv.tv_usec));
355 shortp_incr_bp(&shortp_in_head, written);
356 wake_up_interruptible(&shortp_in_queue); /* awake any reading process */
357 }
358
359
360 /*
361 * The top-half interrupt handler.
362 */
363 static irqreturn_t shortp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
364 {
365 if (! shortp_output_active)
366 return IRQ_NONE;
367
368 /* Remember the time, and farm off the rest to the workqueue function */
369 do_gettimeofday(&shortp_tv);
370 queue_work(shortp_workqueue, &shortp_work);
371 return IRQ_HANDLED;
372 }
373
374 /*
375 * Interrupt timeouts. Just because we got a timeout doesn't mean that
376 * things have gone wrong, however; printers can spend an awful long time
377 * just thinking about things.
378 */
379 static void shortp_timeout(unsigned long unused)
380 {
381 unsigned long flags;
382 unsigned char status;
383
384 if (! shortp_output_active)
385 return;
386 spin_lock_irqsave(&shortp_out_lock, flags);
387 status = inb(shortp_base + SP_STATUS);
388
389 /* If the printer is still busy we just reset the timer */
390 if ((status & SP_SR_BUSY) == 0 || (status & SP_SR_ACK)) {
391 shortp_timer.expires = jiffies + TIMEOUT;
392 add_timer(&shortp_timer);
393 spin_unlock_irqrestore(&shortp_out_lock, flags);
394 return;
395 }
396
397 /* Otherwise we must have dropped an interrupt. */
398 spin_unlock_irqrestore(&shortp_out_lock, flags);
399 shortp_interrupt(shortp_irq, NULL, NULL);
400 }
401
402
403
404
405
406 static struct file_operations shortp_fops = {
407 .read = shortp_read,
408 .write = shortp_write,
409 .open = shortp_open,
410 .release = shortp_release,
411 .poll = shortp_poll,
412 .owner = THIS_MODULE
413 };
414
415
416
417
418 /*
419 * Module initialization
420 */
421
422 static int shortp_init(void)
423 {
424 int result;
425
426 /*
427 * first, sort out the base/shortp_base ambiguity: we'd better
428 * use shortp_base in the code, for clarity, but allow setting
429 * just "base" at load time. Same for "irq".
430 */
431 shortp_base = base;
432 shortp_irq = irq;
433 shortp_delay = delay;
434
435 /* Get our needed resources. */
436 if (! request_region(shortp_base, SHORTP_NR_PORTS, "shortprint")) {
437 printk(KERN_INFO "shortprint: can't get I/O port address 0x%lx\n",
438 shortp_base);
439 return -ENODEV;
440 }
441
442 /* Register the device */
443 result = register_chrdev(major, "shortprint", &shortp_fops);
444 if (result < 0) {
445 printk(KERN_INFO "shortp: can't get major number\n");
446 release_region(shortp_base, SHORTP_NR_PORTS);
447 return result;
448 }
449 if (major == 0)
450 major = result; /* dynamic */
451
452 /* Initialize the input buffer. */
453 shortp_in_buffer = __get_free_pages(GFP_KERNEL, 0); /* never fails */
454 shortp_in_head = shortp_in_tail = shortp_in_buffer;
455
456 /* And the output buffer. */
457 shortp_out_buffer = (unsigned char *) __get_free_pages(GFP_KERNEL, 0);
458 shortp_out_head = shortp_out_tail = shortp_out_buffer;
459 sema_init(&shortp_out_sem, 1);
460
461 /* And the output info */
462 shortp_output_active = 0;
463 spin_lock_init(&shortp_out_lock);
464 init_timer(&shortp_timer);
465 shortp_timer.function = shortp_timeout;
466 shortp_timer.data = 0;
467
468 /* Set up our workqueue. */
469 shortp_workqueue = create_singlethread_workqueue("shortprint");
470
471 /* If no IRQ was explicitly requested, pick a default */
472 if (shortp_irq < 0)
473 switch(shortp_base) {
474 case 0x378: shortp_irq = 7; break;
475 case 0x278: shortp_irq = 2; break;
476 case 0x3bc: shortp_irq = 5; break;
477 }
478
479 /* Request the IRQ */
480 result = request_irq(shortp_irq, shortp_interrupt, 0, "shortprint", NULL);
481 if (result) {
482 printk(KERN_INFO "shortprint: can't get assigned irq %i\n",
483 shortp_irq);
484 shortp_irq = -1;
485 shortp_cleanup ();
486 return result;
487 }
488
489 /* Initialize the control register, turning on interrupts. */
490 outb(SP_CR_IRQ | SP_CR_SELECT | SP_CR_INIT, shortp_base + SP_CONTROL);
491
492 return 0;
493 }
494
495 static void shortp_cleanup(void)
496 {
497 /* Return the IRQ if we have one */
498 if (shortp_irq >= 0) {
499 outb(0x0, shortp_base + SP_CONTROL); /* disable the interrupt */
500 free_irq(shortp_irq, NULL);
501 }
502
503 /* All done with the device */
504 unregister_chrdev(major, "shortprint");
505 release_region(shortp_base,SHORTP_NR_PORTS);
506
507 /* Don't leave any timers floating around. Note that any active output
508 is effectively stopped by turning off the interrupt */
509 if (shortp_output_active)
510 del_timer_sync (&shortp_timer);
511 flush_workqueue(shortp_workqueue);
512 destroy_workqueue(shortp_workqueue);
513
514 if (shortp_in_buffer)
515 free_page(shortp_in_buffer);
516 if (shortp_out_buffer)
517 free_page((unsigned long) shortp_out_buffer);
518 }
519
520 module_init(shortp_init);
521 module_exit(shortp_cleanup);
522
|
This page was automatically generated by the
LXR engine.
|