MyWebUniversity.com Home Page
 



OpenSolaris man pages main menu


Kernel Functions for Drivers                 ddiaddsoftintr(9F)



NAME
     ddiaddsoftintr,                ddigetsoftiblockcookie,
     ddiremovesoftintr,  dditriggersoftintr - software inter-
     rupt handling routines

SYNOPSIS
     #include 
     #include 
     #include 
     #include 



     int ddigetsoftiblockcookie(devinfot *dip,
     int preference, ddiiblockcookiet *iblockcookiep);


     int ddiaddsoftintr(devinfot *dip, int preference, ddisoftintrt *idp,
          ddiiblockcookiet *iblockcookiep, ddiidevicecookiet *
          idevicecookiep,
          uintt(*inthandler) (caddrt inthandlerarg), caddrt
          inthandlerarg);


     void ddiremovesoftintr(ddisoftintrt id);


     void dditriggersoftintr(ddisoftintrt id);


INTERFACE LEVEL
     Solaris DI specific (Solaris  DI).  These  interfaces  are
     obsolete.  Use  the  new  interrupt interfaces referenced in
     Intro(9F). Refer to Writing Device Drivers for more informa-
     tion.

PARAMETERS
     ddigetsoftiblockcookie()

     dip               Pointer to a devinfo structure.


     preference        The type of soft interrupt to retrieve the
                       cookie for.


     iblockcookiep    Pointer to a location to store the  inter-
                       rupt block cookie.







SunOS 5.11          Last change: 19 Oct 2005                    1






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



     ddiaddsoftintr()

     dip                Pointer to devinfo structure.


     preference         A hint value describing the type of  soft
                        interrupt to generate.


     idp                Pointer to a  soft  interrupt  identifier
                        where  a returned soft interrupt identif-
                        ier is stored.


     iblockcookiep     Optional pointer to  an  interrupt  block
                        cookie  where  a returned interrupt block
                        cookie is stored.


     idevicecookiep    Optional pointer to an  interrupt  device
                        cookie  where a returned interrupt device
                        cookie is stored (not used).


     inthandler        Pointer to interrupt handler.


     inthandlerarg    Argument for interrupt handler.



     ddiremovesoftintr()

     id    The identifier specifying which soft interrupt handler
           to remove.



     dditriggersoftintr()

     id    The identifier  specifying  which  soft  interrupt  to
           trigger  and  which  soft  interrupt  handler  will be
           called.


DESCRIPTION
     For ddigetsoftiblockcookie():


     ddigetsoftiblockcookie() retrieves the  interrupt  block
     cookie  associated  with a particular soft interrupt prefer-
     ence  level.  This   routine   should   be   called   before



SunOS 5.11          Last change: 19 Oct 2005                    2






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



     ddiaddsoftintr()  to  retrieve  the interrupt block cookie
     needed to initialize locks ( mutex(9F), rwlock(9F)) used  by
     the  software interrupt routine. preference determines which
     type of soft interrupt to retrieve the cookie for. The  pos-
     sible values for preference are:

     DISOFTINTLOW     Low priority soft interrupt.


     DISOFTINTMED     Medium priority soft interrupt.


     DISOFTINTHIGH    High priority soft interrupt.



     On a successful return, iblockcookiep contains  information
     needed  for  initializing  locks  associated  with this soft
     interrupt (see mutexinit(9F) and rwinit(9F)).  The  driver
     can  then  initialize mutexes acquired by the interrupt rou-
     tine before calling ddiaddsoftintr() which prevents a pos-
     sible  race  condition  where  the  driver's  soft interrupt
     handler is called immediately after the  driver  has  called
     ddiaddsoftintr() but before the driver has initialized the
     mutexes. This can happen when a soft interrupt  for  a  dif-
     ferent  device  occurs  on  the same soft interrupt priority
     level. If the soft  interrupt  routine  acquires  the  mutex
     before  it  has  been  initialized,  undefined  behavior may
     result.


     For ddiaddsoftintr():


     ddiaddsoftintr() adds a soft interrupt to the system.  The
     user  specified  hint  preference identifies three suggested
     levels for the system to attempt to allocate the soft inter-
     rupt  priority  at.  The  value for preference should be the
     same  as  that   used   in   the   corresponding   call   to
     ddigetsoftiblockcookie().  Refer  to  the description of
     ddigetsoftiblockcookie() above.


     The value returned in the location pointed at by idp is  the
     soft interrupt identifier. This value is used in later calls
     to ddiremovesoftintr() and dditriggersoftintr() to iden-
     tify the soft interrupt and the soft interrupt handler.


     The  value  returned  in  the   location   pointed   at   by
     iblockcookiep  is  an interrupt block cookie which contains
     information used for initializing  mutexes  associated  with



SunOS 5.11          Last change: 19 Oct 2005                    3






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



     this  soft  interrupt  (see mutexinit(9F) and rwinit(9F)).
     Note that the interrupt block cookie  is  normally  obtained
     using  ddigetsoftiblockcookie() to avoid the race condi-
     tions  described  above  (refer  to   the   description   of
     ddigetsoftiblockcookie()   above).   For   this  reason,
     iblockcookiep is no longer useful  and  should  be  set  to
     NUL.


     idevicecookiep is not used and should be set to NUL.


     The routine inthandler, with its argument  inthandlerarg,
     is  called  upon  receipt  of a software interrupt. Software
     interrupt handlers must not assume that they have work to do
     when they run, since (like hardware interrupt handlers) they
     may run because a soft interrupt  occurred  for  some  other
     reason.  For  example,  another  driver may have triggered a
     soft interrupt at the same level. For  this  reason,  before
     triggering  the  soft interrupt, the driver must indicate to
     its soft interrupt handler that it should do work.  This  is
     usually  done  by setting a flag in the state structure. The
     routine inthandler  checks  this  flag,  reachable  through
     inthandlerarg,  to determine if it should claim the inter-
     rupt and do its work.


     The interrupt handler must return  DINTRCLAIMED  if  the
     interrupt was claimed, DINTRUNCLAIMED otherwise.


     If successful, ddiaddsoftintr() will  return  DISUCES;
     if the interrupt information cannot be found, it will return
     DIFAILURE.


     For ddiremovesoftintr():


     ddiremovesoftintr() removes a soft interrupt from the sys-
     tem.  The  soft  interrupt identifier id, which was returned
     from a call to  ddiaddsoftintr(),  is  used  to  determine
     which  soft  interrupt  and  which soft interrupt handler to
     remove. Drivers must  remove  any  soft  interrupt  handlers
     before allowing the system to unload the driver.


     For dditriggersoftintr():


     dditriggersoftintr() triggers a soft interrupt.  The  soft
     interrupt  identifier  id  is  used  to determine which soft



SunOS 5.11          Last change: 19 Oct 2005                    4






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



     interrupt to  trigger.  This  function  is  used  by  device
     drivers when they wish to trigger a soft interrupt which has
     been set up using ddiaddsoftintr().

RETURN VALUES
     ddiaddsoftintr() and ddigetsoftiblockcookie() return:

     DISUCES    on success


     DIFAILURE    on failure


CONTEXT
     These functions can be called from user or  kernel  context.
     dditriggersoftintr()  may be called from high-level inter-
     rupt context as well.

EXAMPLES
     Example 1 device using high-level interrupts


     In the following example, the device uses high-level  inter-
     rupts. High-level interrupts are those that interrupt at the
     level of the scheduler and above. High level interrupts must
     be  handled  without  using  system services that manipulate
     thread or process states, because these interrupts  are  not
     blocked  by the scheduler. In addition, high level interrupt
     handlers must take care to do a minimum of work because they
     are not preemptable. See ddiintrhilevel(9F).



     In the example, the high-level interrupt  routine  minimally
     services  the  device,  and enqueues the data for later pro-
     cessing by the soft interrupt handler. If the soft interrupt
     handler  is  not currently running, the high-level interrupt
     routine triggers a soft  interrupt  so  the  soft  interrupt
     handler  can process the data. Once running, the soft inter-
     rupt handler processes all the enqueued data before  return-
     ing.



     The state structure contains  two  mutexes.  The  high-level
     mutex  is used to protect data shared between the high-level
     interrupt handler and the soft interrupt handler.  The  low-
     level  mutex  is used to protect the rest of the driver from
     the soft interrupt handler.


       struct xxstate {



SunOS 5.11          Last change: 19 Oct 2005                    5






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



             ...
             ddisoftintrt             id;
                ddiiblockcookiet     highiblockcookie;
                kmutext                      highmutex;
                ddiiblockcookiet     lowiblockcookie;
                kmutext                      lowmutex;
                int                              softintrunning;
             ...
       };
       struct xxstate *xsp;
       static uintt xxsoftintr(caddrt);
       static uintt xxhighintr(caddrt);
       ...


     Example 2 sample attach() routine


     The following code fragment  would  usually  appear  in  the
     driver's attach(9E) routine. ddiaddintr(9F) is used to add
     the high-level interrupt handler and  ddiaddsoftintr()  is
     used to add the low-level interrupt routine.


       static uintt
       xxattach(devinfot *dip, ddiattachcmdt cmd)
       {
                struct xxstate *xsp;
                ...
             /* get high-level iblock cookie */
                if (ddigetiblockcookie(dip, inumber,
                       &xsp->highiblockcookie) != DISUCES)  {
                             /* clean up */
                             return (DIFAILURE); /* fail attach */
                }

                /* initialize high-level mutex */
                mutexinit(&xsp->highmutex, "xx high mutex", MUTEXDRIVER,
                      (void *)xsp->highiblockcookie);

                /* add high-level routine - xxhighintr() */
                if (ddiaddintr(dip, inumber, NUL, NUL,
                       xxhighintr, (caddrt) xsp) != DISUCES)  {
                             /* cleanup */
                             return (DIFAILURE); /* fail attach */
                }

                /* get soft iblock cookie */
                if (ddigetsoftiblockcookie(dip, DISOFTINTMED,
                       &xsp->lowiblockcookie) != DISUCES)  {
                             /* clean up */
                             return (DIFAILURE); /* fail attach */



SunOS 5.11          Last change: 19 Oct 2005                    6






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



                }

                /* initialize low-level mutex */
                mutexinit(&xsp->lowmutex, "xx low mutex", MUTEXDRIVER,
                       (void *)xsp->lowiblockcookie);

                /* add low level routine - xxsoftintr() */
                if ( ddiaddsoftintr(dip, DISOFTINTMED, &xsp->id,
                       NUL, NUL, xxsoftintr, (caddrt) xsp) != DISUCES) {
                             /* cleanup */
                             return (DIFAILURE);  /* fail attach */
                }

                ...
       }


     Example 3 High-level interrupt routine


     The next code fragment represents the  high-level  interrupt
     routine. The high-level interrupt routine minimally services
     the device, and enqueues the data for  later  processing  by
     the soft interrupt routine. If the soft interrupt routine is
     not already running,  dditriggersoftintr()  is  called  to
     start the routine. The soft interrupt routine will run until
     there is no more data on the queue.


       static uintt
       xxhighintr(caddrt arg)
       {
             struct xxstate *xsp = (struct xxstate *) arg;
                int needsoftint;
                ...
                mutexenter(&xsp->highmutex);
                /*
                * Verify this device generated the interrupt
                * and disable the device interrupt.
                * Enqueue data for xxsoftintr() processing.
                */

                /* is xxsoftintr() already running ? */
                if (xsp->softintrunning)
                       needsoftint = 0;
                 else
                       needsoftint = 1;
                 mutexexit(&xsp->highmutex);

                 /* read-only access to xsp->id, no mutex needed */
                 if (needsoftint)
                       dditriggersoftintr(xsp->id);



SunOS 5.11          Last change: 19 Oct 2005                    7






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



                 ...
                 return (DINTRCLAIMED);
       }

       static uintt
       xxsoftintr(caddrt arg)
       {
             struct xxstate *xsp = (struct xxstate *) arg;
             ...
                mutexenter(&xsp->lowmutex);
             mutexenter(&xsp->highmutex);

             /* verify there is work to do */
             if (work queue empty  xsp->softintrunning )  {
                       mutexexit(&xsp->highmutex);
                       mutexexit(&xsp->lowmutex);
                       return (DINTRUNCLAIMED);
             }

             xsp->softintrunning = 1;

                while ( data on queue )  {
                       ASERT(mutexowned(&xsp->highmutex));

                       /* de-queue data */

                       mutexexit(&xsp->highmutex);

                       /* Process data on queue */

                       mutexenter(&xsp->highmutex);
                 }

                 xsp->softintrunning = 0;
                 mutexexit(&xsp->highmutex);
                 mutexexit(&xsp->lowmutex);

                 return (DINTRCLAIMED);
       }


ATRIBUTES
     See attributes(5) for descriptions of the  following  attri-
     butes:











SunOS 5.11          Last change: 19 Oct 2005                    8






Kernel Functions for Drivers                 ddiaddsoftintr(9F)



     
           ATRIBUTE TYPE               ATRIBUTE VALUE       
    
     Interface Stability          Obsolete                    
    


SEE ALSO
     ddiaddintr(9F),  ddiinpanic(9F),   ddiintrhilevel(9F),
     ddiremoveintr(9F), Intro(9F), mutexinit(9F)


     Writing Device Drivers

NOTES
     ddiaddsoftintr() may not be used to add the same  software
     interrupt  handler  more  than  once. This is true even if a
     different value is used for inthandlerarg in each  of  the
     calls to ddiaddsoftintr(). Instead, the argument passed to
     the interrupt handler should indicate  what  service(s)  the
     interrupt  handler should perform. For example, the argument
     could be a pointer to the  device's  soft  state  structure,
     which could contain a 'whichservice' field that the handler
     examines. The driver must set this field to the  appropriate
     value before calling dditriggersoftintr().






























SunOS 5.11          Last change: 19 Oct 2005                    9



OpenSolaris man pages main menu

Contact us      |       About us      |       Term of use      |       Copyright © 2000-2010 MyWebUniversity.com ™