NASD Programmer's Documentation
Drive operation calling convention

All NASD drive operations share a similar calling convention.

Calling

The first argument of all drive operation functions is a nasd_drive_handle_t bound to the drive which should perform the operation.

Those functions which contain request and/or result data take a nasd_key_t as their second argument, a pointer to the request argument structure as the third argument, and a pointer to the result structure as the fourth argument. Some operations, such as read and write, also operate on out-of-band buffers. These operations usually take the address of this buffer (or a list of buffers) as a separate argument, often between the argument and result structure pointers.

Some operations do not have request or result data. These take a pointer to a nasd_status_t in which they store the non-transport-specific status of the call.

All drive operation functions take a pointer to a nasd_rpc_status_t as their final argument. Additionally, all drive operations generate a nasd_result_t. The nasd_rpc_status_t is a result code generated by the transport layer. For all transport layers, a result of 0 is success, and a non-zero result indicates some sort of problem.

Interpreting results: two error codes

All drive operations have two result codes: a nasd_status_t and a nasd_rpc_status_t. The nasd_status_t is a specific status code generated either by the drive, or by some portion of the NASD API which implements the call to the drive. The nasd_rpc_status_t is generated only by the transport layer. If the nasd_rpc_status_t is non-zero, this indicates a transport failure of some nature. nasd_cl_error_string() can translate this error code into a human-readable error message. This has the signature:

char *
nasd_cl_error_string(
  nasd_drive_handle_t   handle,
  nasd_rpc_status_t     status,
  nasd_error_string_t   str)
The first argument should be the same drive handle passed to the operation which generated the error. The second argument is the nasd_rpc_status_t to translate. The third argument is a nasd_error_string_t, which is an array of characters, into which a translation of the error code will be written. This is also the value which is returned by nasd_cl_error_string(). This value is returned so that this function may be called as an argument to printf(), simplifying error reporting.

When the nasd_rpc_status_t is nonzero, the nasd_status_t may give some general indication of where or how the failure occurred, or it may simply indicate that the rpc transport mechanism observed a failure. If the nasd_rpc_status_t is zero, and the nasd_status_t is non-zero (non-NASD_SUCCESS), this indicates that the operation did not succeed, and will give some indication of how or why it failed. This failure may be generated by the local API which is responsible for generating the call, or it may be explicitly returned by the drive. If both values are zero, then the operation has succeeded. For more information on possible results of drive operations, and their meaning, see the section on drive operations.

Example

This code fragment illustrates a correct call to a drive operation function, and the associated error checking. In this case, the called function is nasd_cl_p_null(), which is a no-op. The drive receives this message, and responds by indicating NASD_SUCCESS. A trivial call, followed by a report of success or failure, might look something like:


nasd_rpc_status_t rpc_status;
nasd_error_string_t err_str;
nasd_status_t nasd_status;

nasd_cl_p_null_dr(drive_handle, &nasd_status, &rpc_status);
if (rpc_status || nasd_status) {
  printf("ERROR performing no-op, rpc_status 0x%x (%s) nasd_status 0x%x (%s)\n",
    rpc_status, nasd_cl_error_string(drive_handle, rpc_status, err_str),
    nasd_status, nasd_error_string(nasd_status));
  return(nasd_status ? nasd_status : NASD_FAIL);
}
else {
  printf("No-op succeeded\n");
}
return(NASD_SUCCESS);

<--- ---> ^<br>|<br>|
Drive handles Drive operations NASD Programmer's Documentation