The HyperNews Linux KHG Discussion Pages

## 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);
    }