MyWebUniversity.com Home Page
 



OpenSolaris man pages main menu


Kernel Functions for Drivers        ldievregistercallbacks(9F)



NAME
     ldievregistercallbacks - add  a  notify  and/or  finalize
     callback

SYNOPSIS
     #include 

     int ldievgetcookie(ldihandlet lh, ldievcookiet *cookie,
           ldievcallbackt *callb, void *arg, ldievcallbackidt *id);


INTERFACE LEVEL
     Solaris DI specific (Solaris DI)

PARAMETERS
     ldihandlet lh

         A layered handle representing the device for  which  the
         event notification was requested.


     ldievcookiet *cookie

         An opaque event cookie for the event type returned by  a
         previous call to ldievgetcookie(9F).


     ldievcallbackt *callb

         A data  structure  which  currently  has  the  following
         members:

           struct ldievcallback {
                   uintt  cbvers;
                   int     (*cbnotify)(ldihandlet,
                                        ldievcookiet cookie,
                                        void *arg, void *evdata);
                   void    (*cbfinalize)(ldihandlet,
                                          ldievcookiet cookie,
                                          int ldiresult,
                                          void *arg,
                                          void *evdata);
            } ldievcallbackt;

         where

         cbvers    Version of callback vector. Must  be  set  to
                    LDIEVCBVERS by the caller.

                    The arguments passed into the callbacks  when
                    they are invoked, include:




SunOS 5.11          Last change: 21 Aug 2007                    1






Kernel Functions for Drivers        ldievregistercallbacks(9F)



                    int ldiresult

                        The actual result  of  the  state  change
                        operation/event  passed to finalize call-
                        back: LDIEVSUCES:  The  state  change
                        succeeded   LDIEVFAILURE:   The   state
                        change failed.


                    void *evdata

                        Event specific data.




     void *arg

         A pointer to opaque caller private data.


     ldievcallbackidt *id

         Unique  system  wide   registration   id   returned   by
         ldievregistercallbacks(9F)  upon successful registra-
         tion.


DESCRIPTION
     The  ldievregistercallbacks()  interface  allows  layered
     drivers  to  register notify and finalize callbacks for cer-
     tain   events.   These   events   are    listed    in    the
     ldievgetcookie(9F)  man  page.  The  notify  callback  is
     invoked only for events that can be blocked, just before the
     event occurs. The notify event is not called for events ser-
     viced by the NDI event  service framework since such  events
     are  by definition asynchronous. Only  the finalize callback
     is invoked  for  such  events.  Layered  drivers  that  have
     registered  notify  callbacks for that event have the oppor-
     tunity of blocking such events.  The  finalize  callback  is
     invoked  once the final disposition of the state of a device
     (specifically a device minor node) is known. The callback is
     invoked  with  this  result,  either  LDIEVSUCES  (state
     change succeeded) or LDIEVFAILURE (state  change  failed).
     This allows layered driver consumers to finalize any changes
     they made in response to a previous "notify" callback.


     For example, a  layered  driver's  notify  callback  may  be
     invoked  in  response to a LDIEVOFLINE event. The layered
     driver may reconfigure itself to stop using the  device  and
     permit  the change to go forward. Once that happens, the I/O



SunOS 5.11          Last change: 21 Aug 2007                    2






Kernel Functions for Drivers        ldievregistercallbacks(9F)



     framework attempts to actually take the device offline. This
     offline  attempt  can have two possible outcomes: success or
     failure. In  the  former  case,  the  finalize  callback  is
     invoked  with  the ldiresult argument set to LDIEVSUCES
     and the layered driver knows that the device has been  taken
     offline.  In  the  latter case, finalize is invoked with the
     ldiresult set to  LDIEVFAILURE  and  the  layered  driver
     knows  that  the  state  change failed. In this case, it may
     choose to reconfigure  itself  to  start  using  the  device
     again.


     Finalize callbacks can be registered for all events  includ-
     ing events that cannot be blocked.


     A layered driver can also  propagate  these  events  up  the
     software  stack by using interfaces offered by the LDI event
     framework. The layered driver  may  use  ldievnotify()  to
     propagate  notify events occurring on minors it imports onto
     minors it exports. Similarly, it may  use  ldievfinalize()
     to  propagate  finalize  events.  Both  ldievnotify()  and
     ldievfinalize() propagate events to  device  contracts  as
     well as LDI callbacks  registered against the exported minor
     nodes.


     The LDI event framework has  the  following  guarantees  and
     requirements with respect to these callbacks:

         1.   The notify() callback is invoked  before  an  event
              (represented  by the event cookie) occurs on a dev-
              ice (represented by the layered driver handle)  and
              is  invoked only for events that can be blocked. If
              the callback returns LDIEVFAILURE, the  event  is
              blocked.  If  the  callback returns LDIEVSUCES,
              the event is allowed to proceed. If any other value
              is  returned,  it  is an error. An error message is
              logged and the event is blocked. An example  of  an
              event  that  can  be  blocked  and for which notify
              callbacks may  be  invoked  is  the  offline  event
              LDIEVOFLINE.

         2.   The finalize callback is  invoked  for  all  events
              (including events that cannot be blocked) after the
              event has  occurred.  It  is  invoked  with  either
              LDIEVSUCES  indicating  that the event success-
              fully happened or  LDIEVFAILURE  indicating  that
              the  event  did  not  occur.  The finalize callback
              returns no values. Good  examples  of  events  that
              cannot   be   blocked   are   the   degrade   event
              (LDIEVDEGRADE) and events  serviced  by  the  NDI



SunOS 5.11          Last change: 21 Aug 2007                    3






Kernel Functions for Drivers        ldievregistercallbacks(9F)



              event service framework.

         3.   Layered drivers may register one or both  of  these
              callbacks (that is, only for a notify event or only
              for a finalize event or for both) against  any  LDI
              handle  that  they  may  possess.  If a finalize or
              notify  event  is   not   being   registered,   the
              corresponding   pointer  in  the  ldievcallbackt
              structure must be set to NUL. It is  an  error  to
              attempt  a  registration with both callbacks set to
              NUL.

         4.   A notify and/or finalize callback is  invoked  only
              if  the corresponding LDI handle is open. If an LDI
              handle against which the callbacks  are  registered
              is  closed,  the  corresponding finalize and notify
              callbacks is not invoked as it is assumed that  the
              layered  driver is no longer interested in the dev-
              ice. See number 5 below for the exception  to  this
              rule.

         5.   A layered driver that closes  it's  LDI  handle  in
              it's  notify  routine  receives  the  corresponding
              finalize callback after  the  event  has  occurred.
              Because  the LDI handle has been closed, the final-
              ize callback is invoked with a NUL LDI handle.  It
              is  the  responsibility  of  the  layered driver to
              maintain state in it's private "arg"  parameter  so
              that  it can reopen the device (if desired) in it's
              finalize callback.

              One example where  this  may  happen  is  with  the
              LDIEVOFLINE  event.  A  layered  driver's notify
              callback may be invoked for an offline  event.  The
              layered  driver  may  choose to allow this event to
              proceed. In that case, since it has a layered  open
              of the device, it must close the LDI handle so that
              the offline event can succeed (an offline of a dev-
              ice  does  not  succeed if there is any open of the
              device, layered or otherwise).  Since  the  layered
              driver has closed the LDI handle in the notify rou-
              tine, it's finalize callback (if  any)  is  invoked
              with a NUL LDI handle. It is the responsibility of
              the layered driver to maintain state (such  as  the
              device path or devid) in it's private "arg" parame-
              ter, so that in the finalize routine, it can  do  a
              layered  open  of  the device if the device offline
              failed.

              This is the only exception where the finalize call-
              back  is invoked if the LDI handle has been closed.
              In all other cases  if  the  LDI  handle  has  been



SunOS 5.11          Last change: 21 Aug 2007                    4






Kernel Functions for Drivers        ldievregistercallbacks(9F)



              closed, no corresponding callbacks is invoked.

         6.   In  order  for  the  offline   event   to   succeed
              (LDIEVOFLINE), it is imperative that there be no
              opens (including LDI handles) to the device.  If  a
              layered  driver's notify callback is invoked for an
              offline event and the driver intends to  allow  the
              offline  to  proceed,  the  driver  must  close the
              corresponding LDI handle.

         7.   The notify and finalize callbacks are not automati-
              cally  unregistered  even  if the corresponding LDI
              handle has been closed. It is the responsibility of
              the  layered  driver  to unregister these callbacks
              when they are not required. It may do so using  the
              ldievremovecallbacks(9F)   interface.   The  LDI
              framework may panic if the entity  registering  the
              callback (such as a dip, devt or module) no longer
              exists on the system and  the  corresponding  call-
              backs have not been unregistered.

         8.   The LDI event framework guarantees that if  a  lay-
              ered  driver  receives  a  notify  event,  it  also
              receives a finalize event  except  if  the  layered
              consumer  itself  blocked  the  event  (that is, it
              returned LDIEVFAILURE from it's notify  callback.
              In  this  case,  the  layered driver knows that the
              event has been blocked and therefore does not  need
              the finalize callback.

         9.   If a layered driver  propagates  notify  events  on
              minors  it  imports  to  minors it exports, it must
              first propagate these events up the software  stack
              via  ldievenotify()  in  it's notify callback. It
              must do so before attempting to check if it  blocks
              the  event.  This  is  required,  because a layered
              driver cannot release the device  if  consumers  up
              the   stack   are   still   using  the  device.  If
              ldievnotify() returns LDIEVFAILURE,  the  call-
              back  must  immediately  return LDIEVFAILURE from
              it's notify callback. If  ldievnotify()   returns
              LDIEVSUCES,  then the state change is permissi-
              ble as far as consumers higher up in  the  software
              stack  are  concerned. The layered driver must then
              determine if it can permit the state change. If the
              state  change  is to be allowed, the layered driver
              must return LDIEVSUCES. If the  layered  driver
              determines that the state change should not be per-
              mitted, it must invoke ldievfinalize()  on minors
              it  exports  with  a  result  of LDIEVFAILURE (to
              inform consumers up  the  stack)  and  then  return
              LDIEVFAILURE from it's notify callback.



SunOS 5.11          Last change: 21 Aug 2007                    5






Kernel Functions for Drivers        ldievregistercallbacks(9F)



         10.  The LDI event framework generates  finalize  events
              at  the earliest point where a failure is detected.
              If the failure is detected in the  framework  (such
              as  in ldievnotify()) the framework generates the
              finalize events. In the event  that  a  failure  is
              first detected in a layered driver (that is, in the
              notify callback of a layered  driver)  the  layered
              driver must use ldievfinalize()  to send finalize
              events up the software stack . See the examples for
              code snippets describing this scenario.

         11.  The finalize callback must first reconfigure itself
              before  attempting  to  propagate  the event up the
              software stack via ldievfinalize(9F). This is  so
              that  the minors it exports are available and ready
              for use before the finalize event is propagated  up
              the software stack.

         12.  It may so happen that the event propagated  up  the
              software  stack  is  not  the same as the event for
              which a layered driver's  notify/finalize  callback
              is   invoked.   For  example,  a  layered  driver's
              callback(s) may be invoked for  an  offline  event,
              but  the  driver  may  choose to only propagate the
              degraded event to its consumers (since it may  have
              a  mirror/copy  of the data on the device.) In that
              case, the layered driver must generate a  different
              event  cookie  (that  is,  one corresponding to the
              degraded event via ldievgetcookie(9F))  and  use
              that  cookie  in  its  propagation  calls (that is,
              ldievnotify(9F) and ldievfinalize(9F)).


     Once the registration of the callback(s) is  successful,  an
     opaque  ldievcallbackidt structure is returned which may
     be used to unregister the callback(s) later.

RETURN VALUES
     The return values for this function are:

     LDIEVSUCES

         Callback(s) added successfully.


     LDIEVFAILURE

         Failed to add callback(s).


CONTEXT




SunOS 5.11          Last change: 21 Aug 2007                    6






Kernel Functions for Drivers        ldievregistercallbacks(9F)



     This function can be called from user  and  kernel  contexts
     only.

EXAMPLES
     Example 1 Registration and Callbacks for the OFLINE Event


     The      following      example      shows      how      the
     ldievregistercallbacks() function performs a registration
     and callback for the offline event:


       static int
       eventregister(void)
       {
               ldihandlet lh;
               ldievcallbackt callb;
               ldievcookiet offcookie;

               if (ldievgetcookie(lh, LDIEVOFLINE, &offcookie)
                   == LDIEVFAILURE)
                       goto fail;


               callb.cbvers = LDIEVCBVERS;
               callb.cbnotify = offnotify;
               callb.cbfinalize = offfinalize;

               if (ldievregistercallbacks(lh, offcookie, &callb, arg, &id)
                   != LDIEVSUCES)
                       goto fail;
       }

       static void
       eventunregister(ldievcallbackidt id)
       {
               ldievremovecallbacks(id);
       }

       static int
       offnotify(ldihandlet lh, ldievcookiet offcookie, void *arg,
           void *evdata)
       {

               ASERT(strcmp(ldievgettype(offcookie), LDIEVOFLINE) == 0);

               /* Map imported minors to exported minor */
               widgetmap(lh, &minor, &spectype);

               /*
                * Call ldievnotify() to propagate events to our consumers.
                * This *must* happen before we check if offline should be blocked



SunOS 5.11          Last change: 21 Aug 2007                    7






Kernel Functions for Drivers        ldievregistercallbacks(9F)



                */
               if (ldievnotify(dip, minor, spectype, offcookie, evdata)
                   != LDIEVSUCES)
                       return (LDIEVFAILURE);

               /*
                * Next, check if we can allow the offline
                */
               if (widgetcheck(lh) == WIDGETSUCES) {
                       widgetsavepath(arg, lh);
                       widgetreconfigure(lh, RELEASE);
                       ldiclose(lh);
                       return (LDIEVSUCES)
               }

               /*
                * We cannot permit the offline. The first layer that detects
                * failure i.e. us, must generate finalize events for our
                  consumers
                */
               ldievfinalize(dip, minor, spectype, LDIEVFAILURE, offcookie,
                   evdata);

               return (LDIEVFAILURE);
       }

       /*
       /*
        * The finalize callback will only be called if we returned LDIEVSUCES
        * in our notify callback. ldiresult passed in may be SUCES or FAILURE
        */
       static void
       offfinalize(ldihandlet NULlh, ldievcookiet offcookie,
           int ldiresult, void *arg, void *evdata)
       {
               ldihandlet lh;

               ASERT(strcmp(ldievgettype(offcookie), LDIEVOFLINE) == 0);

               path = widgetgetpath(arg);

               widgetmapbypath(path, &minor, &spectype);

               if (ldiresult == LDIEVSUCES) {
                       ldievfinalize(dip, minor, spectype, LDIEVSUCES,
                           offcookie, evdata);
                       return;
               }

               /* The offline failed. Reopen the device */
               ldiopenbyname(path, &lh);
               widgetreconfigure(lh, REACQUIRE);



SunOS 5.11          Last change: 21 Aug 2007                    8






Kernel Functions for Drivers        ldievregistercallbacks(9F)



               ldievfinalize(dip, minor, spectype, LDIEVFAILURE, offcookie,
                   evdata);
       }


     Example 2 Registration and Callbacks for the DEGRADE Event


     The      following      example      shows      how      the
     ldievregistercallbacks() function performs a registration
     and callback for the degrade event:


       static int
       eventregister(void)
       {
               ldihandlet lh;
               ldievcallbackt callb;
               ldievcookiet dgrdcookie;

               if (ldievgetcookie(lh, LDIEVDEGRADE, &dgrdcookie)
                   == LDIEVFAILURE)
                       goto fail;

               /* no notify callbacks allowed for degrade events */
               callb.cbvers = LDIEVCBVERS;
               callb.cbnotify = NUL; /* NUL, notify cannot be used for
                                          DEGRADE */
               callb.cbfinalize = dgrdfinalize;

               if (ldievregistercallbacks(lh, dgrdcookie, &callb, arg, &id)
                   != LDIEVSUCES)
                       goto fail;
       }

       static void
       eventunregister(ldievcallbackidt id)
       {
               ldievremovecallbacks(id);
       }

       /*
        * For degrade events. ldiresult will always be LDIEVSUCES
        */
       static void
       dgrdfinalize(ldihandlet lh, ldievcookiet offcookie,
           int ldiresult, void *arg, void *evdata)
       {
               ASERT(ldiresult == LDIEVSUCES);
               ASERT(strcmp(ldievgettype(offcookie), LDIEVDEGRADE) == 0);

               widgetmap(lh, &minor, &spectype);



SunOS 5.11          Last change: 21 Aug 2007                    9






Kernel Functions for Drivers        ldievregistercallbacks(9F)



               widgetreconfigure(lh, RELEASE);

               ldievfinalize(dip, minor, spectype, LDIEVSUCES, d
                   grdcookie, evdata);
       }


SEE ALSO
     ldievfinalize(9F),                  ldievgetcookie(9F),
     ldievnotify(9F), ldievremovecallbacks(9F)













































SunOS 5.11          Last change: 21 Aug 2007                   10



OpenSolaris man pages main menu

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