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/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.