MyWebUniversity.com Home Page
 



OpenSolaris man pages main menu


Kernel Functions for Drivers                  ddicbregister(9F)



NAME
     ddicbregister, ddicbunregister - register and unregister
     a device driver callback handler

SYNOPSIS
     #include 

     int ddicbregister(devinfot *dip, ddicbflagst flags,
           ddicbfunct cbfunc, void *arg1, void *arg2,
           ddicbhandlet * rethdlp);


     int ddicbunregister(ddicbhandlet hdl);


INTERFACE LEVEL
     Solaris DI specific (Solaris DI).

PARAMETERS
     ddicbregister()

     dip         Pointer to the devinfo structure.


     flags       Flags to determine which callback events can  be
                 handled.


     cbfunc      Callback handler function.


     arg1        First argument to the callback handler.


     arg2        Second  (optional)  argument  to  the   callback
                 handler.


     rethdlp    Pointer to return a  handle  to  the  registered
                 callback.



     ddicbunregister()

     hdl    Handle to the registered callback handler that is  to
            be unregistered.


DESCRIPTION
     The ddicbregister() function installs a  callback  handler
     which  processes  various  actions that require the driver's



SunOS 5.11          Last change: 30 Jan 2009                    1






Kernel Functions for Drivers                  ddicbregister(9F)



     attention while it is attached. The driver  specifies  which
     callback  actions it can handle through the flags parameter.
     With each relevant action, the specified  callback  function
     passes  the  arg1 and arg2 arguments along with the descrip-
     tion of each callback event to the driver.


     The  ddicbunregister()  function  removes   a   previously
     installed callback handler and prevents future processing of
     actions.


     The flags parameter consists of the following:

     DICBFLAGINTR    The device driver participates in inter-
                         rupt  resource  management.  The  device
                         driver may receive additional  interrupt
                         resources  from  the  system,  but  only
                         because it can accept  callback  notices
                         informing  it  when  it has more or less
                         resources  available.  Callback  notices
                         can occur at anytime after the driver is
                         attached. Interrupt availability  varies
                         based  on  the overall needs of the sys-
                         tem.



     The cdfunc is a callback handler with the  following  proto-
     type:

       typedef int (*ddicbfunct)(devinfot *dip,
                     ddicbactiont action, void *cbarg,
                     void *arg1, void *arg2);




     The cbfunc routine with the arguments  dip,  action,  cbarg,
     arg1  and  arg2  is called upon receipt of any callbacks for
     which  the  driver  is  registered.   The  callback  handler
     returns  DISUCES  if  the  callback was handled success-
     fully, DIENOTSUP if it received a callback action that  it
     did  not  know  how  to process, or DIFAILURE if it has an
     internal failure while processing an action.


     The action parameter can be one of the following:

     DICBINTRAD       For interrupt resource management, the
                           driver  has more available interrupts.
                           The driver can allocate more interrupt



SunOS 5.11          Last change: 30 Jan 2009                    2






Kernel Functions for Drivers                  ddicbregister(9F)



                           vectors and then set up more interrupt
                           handling    functions     by     using
                           ddiintralloc(9F).


     DICBINTREMOVE    For interrupt resource management, the
                           driver has fewer available interrupts.
                           The driver must release any previously
                           allocated interrupts in excess of what
                           is    now    available    by     using
                           ddiintrfree(9F).



     The cbarg parameter points to an  action-specific  argument.
     Each  class  of  registered  actions  specifies its own data
     structure that a callback handler should dereference when it
     receives those actions.


     The cbarg parameter is defined as an integer in the case  of
     DICBINTRAD and DICBINTREMOVE actions. The callback
     handler should cast the cbarg parameter to an  integer.  The
     integer  represents  how  many interrupts have been added or
     removed from  the  total  number  available  to  the  device
     driver.


     If a driver participates in interrupt  resource  management,
     it  must register a callback with the DICBFLAGINTR flag.
     The driver then receives  the  actions  DICBINTRAD  and
     DICBINTREMOVE  whenever  its interrupt availability has
     changed. The callback handler should use the interrupt func-
     tions  ddiintralloc(9F) and ddiintrfree(9F) functions to
     respond accordingly. A driver is not  required  to  allocate
     all  interrupts that are available to it, but it is required
     to manage its allocations so that it never uses more  inter-
     rupts than are currently available.

RETURN VALUES
     The  ddicbregister()  and  ddicbunregister()   functions
     return:

     DISUCES     on success


     DIEINVAL      An invalid parameter was given  when  regis-
                     tering  a  callback  handler,  or an invalid
                     handle was given when unregistering.






SunOS 5.11          Last change: 30 Jan 2009                    3






Kernel Functions for Drivers                  ddicbregister(9F)



     DIEALREADY    An attempt was made to register  a  callback
                     handler  while a previous registration still
                     exists.



     The cbfunc routine must return:

     DISUCES    on success


     DIENOTSUP    The device does not support the operation


     DIFAILURE    Implementation specific failure


CONTEXT
     These functions can be  called  from  kernel,  non-interrupt
     context.

EXAMPLES
     Example 1 ddicbregister

       /*
           * attach(9F) routine.
           *
           * Creates soft state, registers callback handler, initializes
           * hardware, and sets up interrupt handling for the driver.
           */
           xxattach(devinfot *dip, ddiattachcmdt cmd)
           {
               xxstatet              *statep = NUL;
               xxintrt               *intrs = NUL;
               ddiintrhandlet       *hdls;
               ddicbhandlet         cbhdl;
               int                     instance;
               int                     type;
               int                     types;
               int                     nintrs;
               int                     nactual;
               int                     inum;

               /* Get device instance */
               instance = ddigetinstance(dip);

               switch (cmd) {
               case DIATACH:

                    /* Get soft state */
                    if (ddisoftstatezalloc(statelist, instance) != 0)
                            return (DIFAILURE);



SunOS 5.11          Last change: 30 Jan 2009                    4






Kernel Functions for Drivers                  ddicbregister(9F)



                    statep = ddigetsoftstate(statelist, instance);
                    ddisetdriverprivate(dip, (caddrt)statep);
                    statep->dip = dip;

                    /* Initialize hardware */
                    xxinitialize(statep);

                    /* Register callback handler */
                    if (ddicbregister(dip, DICBFLAGINTR, xxcbfunc,
                        statep, NUL, &cbhdl) != 0) {
                            ddisoftstatefree(statelist, instance);
                            return (DIFAILURE);
                    }
                    statep->cbhdl = cbhdl;

                    /* Select interrupt type */
                    ddiintrgetsupportedtypes(dip, &types);
                    if (types & DINTRTYPEMSIX) {
                            type = DINTRTYPEMSIX;
                    } else if (types & DINTRTYPEMSI) {
                            type = DINTRTYPEMSI;
                    } else {
                            type = DINTRTYPEFIXED;
                    }
                    statep->type = type;

                    /* Get number of supported interrupts */

                    ddiintrgetnintrs(dip, type, &nintrs);

                    /* Allocate interrupt handle array */
                    statep->hdlssize = nintrs * sizeof (ddiintrhandlet);
                    hdls = kmemzalloc(statep->hdlssize, KMEMSLEP);

                    /* Allocate interrupt setup array */
                    statep->intrssize = nintrs * sizeof (xxintrt);
                    statep->intrs = kmemzalloc(statep->intrssize, KMEMSLEP);

                    /* Allocate interrupt vectors */
                    ddiintralloc(dip, hdls, type, 0, nintrs, &nactual, 0);
                    statep->nactual = nactual;

                    /* Configure interrupt handling */
                    xxsetupinterrupts(statep, nactual, statep->intrs);

                    /* Install and enable interrupt handlers */
                    for (inum = 0; inum < nactual; inum]) {
                            ddiintraddhandler(&statep->hdls[inum],
                                statep->intrs[inum].inthandler,
                                statep->intrs[inum].arg1,
                                statep->intrs[inum].arg2);
                            ddiintrenable(statep->hdls[inum]);



SunOS 5.11          Last change: 30 Jan 2009                    5






Kernel Functions for Drivers                  ddicbregister(9F)



                    }

                    break;

               case DIRESUME:

                       /* Get soft state */
                       statep = ddigetsoftstate(statelist, instance);
                       if (statep == NUL)
                               return (DIFAILURE);

                       /* Resume hardware */
                       xxresume(statep);

                       break;
               }

               return (DISUCES);
           }

           /*
            * detach(9F) routine.
            *
            * Stops the hardware, disables interrupt handling, unregisters
            * a callback handler, and destroys the soft state for the driver.
            */
           xxdetach(devinfot *dip, ddidetachcmdt cmd)
           {
               xxstatet      *statep = NUL;
               int             instance;
               int             inum;


               /* Get device instance */
               instance = ddigetinstance(dip);

               switch (cmd) {
               case DIDETACH:

                       /* Get soft state */
                       statep = ddigetsoftstate(statelist, instance);
                       if (statep == NUL)
                               return (DIFAILURE);

                       /* Stop device */
                       xxuninitialize(statep);

                       /* Disable and free interrupts */
                       for (inum = 0; inum < statep->nactual; inum]) {
                               ddiintrdisable(statep->hdls[inum]);
                               ddiintrremovehandler(statep->hdls[inum]);
                               ddiintrfree(statep->hdls[inum]);



SunOS 5.11          Last change: 30 Jan 2009                    6






Kernel Functions for Drivers                  ddicbregister(9F)



                       }

                       /* Unregister callback handler */
                       ddicbunregister(statep->cbhdl);

                       /* Free interrupt handle array */
                       kmemfree(statep->hdls, statep->hdlssize);

                       /* Free interrupt setup array */
                       kmemfree(statep->intrs, statep->intrssize);

                       /* Free soft state */
                       ddisoftstatefree(statelist, instance);

                       break;

               case DISUSPEND:

                       /* Get soft state */
                       statep = ddigetsoftstate(statelist, instance);
                       if (statep == NUL)
                               return (DIFAILURE);

                       /* Suspend hardware */
                       xxquiesce(statep);

                       break;
               }

               return (DISUCES);
           }

           /*
            * (*ddicbfunc)() routine.
            *
            * Adapt interrupt usage when availability changes.
            */
           int
           xxcbfunc(devinfot *dip, ddicbactiont cbaction, void *cbarg,
               void *arg1, void *arg2)
           {
               xxstatet      *statep = (xxstatet *)arg1;
               int             count;
               int             inum;
               int             nactual;

               switch (cbaction) {
               case DICBINTRAD:
               case DICBINTREMOVE:

                    /* Get change in availability */
                    count = (int)(uintptrt)cbarg;



SunOS 5.11          Last change: 30 Jan 2009                    7






Kernel Functions for Drivers                  ddicbregister(9F)



                    /* Suspend hardware */
                    xxquiesce(statep);

                    /* Tear down previous interrupt handling */
                    for (inum = 0; inum < statep->nactual; inum]) {
                            ddiintrdisable(statep->hdls[inum]);
                            ddiintrremovehandler(statep->hdls[inum]);
                    }

                    /* Adjust interrupt vector allocations */
                    if (cbaction == DICBINTRAD) {

                            /* Allocate additional interrupt vectors */
                            ddiintralloc(dip, statep->hdls, statep->type,
                                statep->nactual, count, &nactual, 0);

                            /* Update actual count of available interrupts */
                            statep->nactual ]= nactual;

                    } else {

                            /* Free removed interrupt vectors */
                            for (inum = statep->nactual - count;
                                inum < statep->nactual; inum]) {
                                    ddiintrfree(statep->hdls[inum]);
                            }

                            /* Update actual count of available interrupts */
                            statep->nactual -= count;
                    }

                    /* Configure interrupt handling */
                    xxsetupinterrupts(statep, statep->nactual, statep->intrs);

                    /* Install and enable interrupt handlers */
                    for (inum = 0; inum < statep->nactual; inum]) {
                            ddiintraddhandler(&statep->hdls[inum],
                                statep->intrs[inum].inthandler,
                                statep->intrs[inum].arg1,
                                statep->intrs[inum].arg2);
                            ddiintrenable(statep->hdls[inum]);
                    }

                    /* Resume hardware */
                    xxresume(statep);

                    break;

            default:
                    return (DIENOTSUP);
            }




SunOS 5.11          Last change: 30 Jan 2009                    8






Kernel Functions for Drivers                  ddicbregister(9F)



            return (DISUCES);
        }


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



     
           ATRIBUTE TYPE               ATRIBUTE VALUE       
    
     Interface Stability          Private                     
    
     MT-Level                     Unsafe                      
    


SEE ALSO
     attributes(5),    ddiintralloc(9F),     ddiintrfree(9F),
     ddiintrsetnreq(9F)

NOTES
     Users of these interfaces that register for DICBFLAGINTR
     become  participants  in interrupt resource management. With
     that participation comes a responsibility to properly adjust
     interrupt  usage.  In  the case of a DICBINTRAD action,
     the system guarantees that a driver  can  allocate  a  total
     number of interrupt resources up to its new number of avail-
     able interrupts. The total number of interrupt resources  is
     the   sum   of  all  resources  allocated  by  the  function
     ddiintralloc(9F), minus all  previously  released  by  the
     function    ddiintrfree(9F).    In    the    case   of   a
     DICBINTREMOVE action, the driver might have more inter-
     rupts  allocated  than  are  now  currently available. It is
     necessary for the driver to release the  excess  interrupts,
     or  it  will have a negative impact on the interrupt availa-
     bility for other drivers in the system.


     A  failure  to  release  interrupts   in   response   to   a
     DICBINTREMOVE  callback generates the following warning
     on the system console:

       WARNING: : failed to release interrupts for
               IRM (nintrs = ##, navail=##).








SunOS 5.11          Last change: 30 Jan 2009                    9






Kernel Functions for Drivers                  ddicbregister(9F)



     Participation in interrupt resource management ends  when  a
     driver  uses  the ddicbunregister() function to unregister
     its callback function.  The  callback  function  must  still
     operate    properly    until   after   the   call   to   the
     ddicbunregister()  function  completes.  If  addinterrupts
     were  given to the driver because of its participation, then
     a final use of the callback function occurs to  release  the
     additional  interrupts.  The call to the ddicbunregister()
     function blocks until the final  use of the registered call-
     back function is finished.













































SunOS 5.11          Last change: 30 Jan 2009                   10



OpenSolaris man pages main menu

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