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