Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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.