The HyperNews Linux KHG Discussion Pages

Question: using XX_select() for device without interrupts

Forum: Device Driver Basics
Keywords: select interrupts polling sleeping
Date: Thu, 25 Jul 1996 14:59:48 GMT
From: Elwood Downey <ecdowney@noao.edu>

Hello;

I have need for a select() entry point in my driver but my
device is not using interrupts so I'm not sure how to have
the os call my select() to let me poll the device. I think I must use a timer,
with select_wait(), so the system will call my select() until my device becomes
active. The trouble is I can not seem to get the timer work. The entire system
hangs _solid_ whenever it gets activated.

Below is my select() code. I use wake_up_interruptible() as the function the
timer will call in the future to just make this process runnable again, in lieu
of calling it from an interrupt service routine. A few specific questions:

1) my driver permits several processes to have the device open at once. Am I
   correct in assuming that if this general approach works I will need a 
   separate timer_list and wait_queue for each open process instance?

2) In no examples do I ever see the wait_queue pointer ever _set_ to point at
   an actual wait_queue instance. Is this correct?
   

Any comments would be greatly appreciated. Rememeber, the only real goal here
is some way to get the os to call us occasionally to let us poll the device,
but the device is not using interrupts.

Thank you in advance;

Elwood Downey

static int
pc39_select (struct inode *inode, struct file *file, int sel_type,
select_table *wait)
{
        static struct timer_list pc39_tl;
        static struct wait_queue *pc39_wq;

        switch (sel_type) {
        case SEL_EX:
            return (0); /* never any exceptions */
        case SEL_IN:
            if (IBF())
                return (1);
            break;
        case SEL_OUT:
            if (TBE())
                return (1);
            break;
        }

        /* nothing ready -- set timer to try again later if necessary */
        if (wait) {
            init_timer (&pc39_tl);
            pc39_tl.expires = PC39_SELTO;
            pc39_tl.function = (void(*)(unsigned long))wake_up_interruptible;
            pc39_tl.data = (unsigned long) &pc39_wq;
            add_timer (&pc39_tl);
            select_wait (&pc39_wq, wait);
        }
        return (0);
}