pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode

The pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode() function writes any number of locations in the hardware and sleeps until a desired number of interrupts occur or a timeout occurs. The timeout occurs if any of the expected interrupts does not occur within the timeout time for that interrupt.

The pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode() function provides a thread-safe way to kick off a hardware operation and guarantees that all (up to four) expected pdiag_dd_interrupt_notify() service calls by the adapter SLIH are not missed by this routine. A pdiagex internal locking mechanism prevents interrupts from being missed. The user SLIH will not be called until this routine first releases the lock.

The pdiag_dd_watch_for_interrupt() legacy routine does not handle the hardware kick-off operation. With the legacy function, the hardware interrupt may have already occurred before the user application calls the legacy watch function.

Syntax


#include <sys/pdiagex_dds.h>
int32 pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode
( handle, kick_vec_parm_p, 
	num_kick_records, num_intrpts_expected, flag_found_p, timeout_sec );
pdiag_info_handle_t  handle; 
kick_io_t*kick_vec_parm_p;
uint32 num_kick_records;
uint32 num_intrpts_expected;
uint32 *flag_found_p;
uint32 timeout_sec;

Description

The pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode() function performs the following operations:

  • Copies in the caller-provided table of hardware write operations required to kick off the hardware. This table is an array of kick_io_t structures. Each element in the array describes a hardware location that must be written to start the hardware operation. The calling application can pass an array of any size to this routine. The kick_io_t structure is described in the pdiagex_dds.h header file. The size of the array is passed in using the parameter num_kick_records.
  • Acquires the pdiagex intr_lock lock.
  • Clears the flag_word variable.
  • Kicks off the hardware by writing the addresses, size, and data value or values that were just copied in.
  • For each of the interrupts that the user expects (passed in using the num_intrpts_expected parameter), this function does an e_sleep_thread() system call to process each pdiag_dd_interrupt_notify() function that the SLIH generates. The pdiagex intr_lock lock is released only during the e_sleep_thread() system call. A timeout value for each sleep is passed in using the timeout_sec parameter. The flag_word variable that the SLIH created is saved for each time the routine is awakened.
  • Releases the pdiagex intr_lock lock.
  • The values of flag_word variable saved after each sleep are copied out to the user's array of type uint32 variables pointed to by the flag_found_p parameter to this routine. The array should be of type uint32[4].

If the SLIH calls pdiag_dd_interrupt_notify() function, then the e_sleep_thread() system call no longer blocks. Once the SLIH calls pdiag_dd_interrupt_notify() function, the kernel guarantees that the e_sleep_thread() system call will be first to reacquire the intr_lock lock. This means that the SLIH will not be reentered until this routine releases the lock, either starting another e_sleep_thread(), or at exit of this routine. The pdiagex and kernel locks only permit the user SLIH to be called once each time this routine does this e_sleep_thread() system call.

To be awakened from the sleep state and get interrupt condition information, this routine is highly dependent on the interaction of the application's interrupt handler. This interaction is maintained by using the handle.flag_word, handle.sleep_word, and handle.sleep_flag variables. The handle.flag_word bit format is determined by the user's application. It must be of type uint32.

The application's interrupt handler should update the handle.flag_word each time it receives an interrupt. The application's interrupt handler should also test the handle.sleep_flag each time it receives an interrupt to determine if the pdiag_dd_watch_for_interrupt() routine is sleeping. If handle.sleep_flag is TRUE, the application's interrupt handler should wake the pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode() routine using the pdiag_dd_interrupt_notify() service with handle.sleep_word as the sleep word.

Execution Environment

The pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode() function can be called from the process environment.

Parameters

Parameter Description
handle Points to pdiag_info_handle_t structure, which is returned from pdiag_open().
kick_vec_param_p Pointer to a user space array of kick_io_t records. These records are used to describe the hardware write or writes required to initiate an operation that should result in an interrupt caused by the hardware. The kick_io_t is defined in the /usr/include/sys/pdiagex_dds.h header file. It has four uint32 entries that specify the address, data, data type, and whether the register is in I/O space or memory-mapped space.
num_kick_records The number of write operations needed to kick off the hardware. This value specifies the number of kick_io_t records that need to be copied from the calling application at the kick_vec_param_p user address.
num_intrpts_expected Specifies the number of interrupt notifications that are expected from the SLIH. This must be in the range of 1 to PDIAGEX_MAX_WATCH_INTRPTS interrupts.
flag_found_p Pointer to a user space array of PDIAGEX_MAX_WATCH_INTRPTS elements of uint32 type. The routine copies out the values of the flag_word as set by the user's SLIH, after each sleep.
timeout_sec Number of seconds to wait for the interrupt condition before timing out. This value is for each of the num_intrpts_expected. This must always be a non-zero value.

Return Value

The pdiag_dd_kick_hdw_and_watch_for_interrupts_safe_mode() function returns one of the following values:

Return Value Description
0 The operation was successful.
x80000023 The e_sleep_thread timed out. If any interrupts occurred, the SLIH did not call pdiag_dd_interrupt_notify().
0x80000024 One interrupt notification was received, but the e_sleep_thread timed out the second time. If another interrupt occurred, the SLIH did not call pdiag_dd_interrupt_notify().
0x80000025 Two interrupt notifications were received, but the e_sleep_thread timed out the third time. If another interrupt occurred, the SLIH did not call pdiag_dd_interrupt_notify().
0x80000026 Three interrupt notifications were received, but the e_sleep_thread timed out the fourth time. If another interrupt occurred, the SLIH did not call pdiag_dd_interrupt_notify().
0xFFFFFFFF The e_sleep_thread failed for reason other than a timeout.
0x80000000 Specified handle has been closed or was not generated by the pdiag_open() call.
0x80000027 num_intrpts_expected was out of range. It must be 1, 2, 3, or 4.
0x80000028 The hardware write to kick off the adapter operation failed.