This example shows how the QTACTLDV (Control Device) API could be used to send a diagnostic command to a tape device.
/* Usage example 1 for QTACTLDV API */ /* */ /* */ #include <string.h> #include <stdio.h> #include <qtactldv.h> #include <qusec.h> /********************************************************************/ /* Typedef structure for QTACTLDV */ /********************************************************************/ typedef struct { /* QTACTLDV command data */ Qta_CTLD0100_t data; /* command data */ char cmd_str[6]; /* command string */ } cmd_struct; /********************************************************************/ /* Typedef structure for Error code */ /********************************************************************/ typedef struct { /* Error code structure */ Qus_EC_t Edata; /* Error code data */ /* CPF67C8 excp data */ char dev_nam[10]; /* Device name */ char reason_cd[3]; /* Reason code */ char resv1[3]; /* Reserved */ } EC_struct; /********************************************************************/ /* Constants */ /********************************************************************/ #define SNDRSNS "\x03\x00\x00\x00\x12\x00" /* Request sense */ /* command string */ #define SNDDIAG "\x1D\x04\x00\x00\x00\x00" /* Send diagnostic */ /* command string */ main(int argc,char *argv[]) { /********************************************************************/ /* */ /* START OF MAINLINE */ /* */ /********************************************************************/ /********************************************************************/ /* Variables for QTACTLDV */ /********************************************************************/ char device[10]; /* device name */ char send_buff[256]; /* send buffer */ int send_buff_len; /* length of send buffer */ char recv_buff[256]; /* receive buffer */ int recv_buff_len; /* length of recv buffer */ int cmd_data_len; /* length of command data */ int i; /* counter variable */ EC_struct EC; /* error code structure */ cmd_struct Cmd; /* struct for QTACTLDV */ memcpy(device,argv[1],10); /* copy device name */ /********************************************************************/ /* OPEN connection */ /********************************************************************/ send_buff_len = 0; /* no send buffer */ recv_buff_len = 0; /* no receive buffer */ cmd_data_len = 0; /* no command data */ EC.Edata.Bytes_Provided = 32; /* No exceptions */ QTACTLDV(device, /* device name */ FUNOPEN, /* requested function */ send_buff, /* send buffer */ send_buff_len, /* length of send buffer */ recv_buff, /* receive buffer */ recv_buff_len, /* length of receive buffer */ CTLD0100, /* command format */ &Cmd, /* command data */ cmd_data_len, /* length of command data */ &EC); /* Error Code */ if (EC.Edata.Bytes_Available>0) /* If there was an error */ { /* Handle the error */ } /********************************************************************/ /* Send Diagnostic command */ /********************************************************************/ send_buff_len = 0; /* no send buffer */ recv_buff_len = 0; /* no recv buffer */ cmd_data_len = sizeof(Cmd); /* size of command struct */ EC.Edata.Bytes_Provided = 32; /* No exceptions */ Cmd.data.Data_transfer_direction = XFRNONE; /* No data transfer */ Cmd.data.Requested_transfer_length = 0; /* 0 transfer length */ Cmd.data.Ignore_length_errors = RPTLERR; /* report length errs */ Cmd.data.Command_timeout = 600; /* 10 minute timeout */ Cmd.data.Type_of_command = CMDSCSI; /* SCSI command */ Cmd.data.Offset_to_command_string = 32; /* offset 32 */ Cmd.data.Length_of_command_string = 6; /* 6 byte command */ Cmd.data.Reserved1=0; /* reserved */ memcpy(&Cmd.cmd_str, SNDDIAG, 6); /* command string */ QTACTLDV(device, /* device name */ FUNCMD, /* requested function */ send_buff, /* send buffer */ send_buff_len, /* length of send buffer */ recv_buff, /* receive buffer */ recv_buff_len, /* length of receive buffer */ CTLD0100, /* command format */ &Cmd, /* command data */ cmd_data_len, /* length of command data */ &EC); /* Error code */ if (EC.Edata.Bytes_Available>0) /* If there was an error */ { /* See what message was returned */ if (strncmp(EC.Edata.Exception_Id,"CPF67C8",7)==0) /* Command failed msg */ { /****************************************************************/ /* Check the data returned with CPF67C8 */ /****************************************************************/ if (strncmp(EC.reason_cd,"\x02\xC0", 2) == 0) /* Device detected error */ { /* Check the SCSI completion status */ if (EC.reason_cd[2]=='\x02') /* Check condition status */ { /************************************************************/ /* Send Request Sense command */ /************************************************************/ send_buff_len = 0; /* no send buffer */ recv_buff_len = 18; /* length of recv buffer */ cmd_data_len = sizeof(Cmd); /* size of command struct */ Cmd.data.Data_transfer_direction = XFRRECV; /* receive */ Cmd.data.Requested_transfer_length = 18; /* 18 bytes */ Cmd.data.Ignore_length_errors = IGNLERR; /* ignore length errors */ Cmd.data.Command_timeout = 60; /* 60 sec timeout */ Cmd.data.Type_of_command = CMDSCSI; /* SCSI command */ Cmd.data.Offset_to_command_string = 32; /* offset 32 */ Cmd.data.Length_of_command_string = 6; /* 6 byte cmd */ Cmd.data.Reserved1=0; /* reserved */ memcpy(&Cmd.cmd_str, SNDRSNS, 6); /* command string */ EC.Edata.Bytes_Provided = 32; /* No exceptions */ QTACTLDV(device, /* device name */ FUNCMD, /* requested function */ send_buff, /* send buffer */ send_buff_len, /* length of send buffer */ recv_buff, /* receive buffer */ recv_buff_len, /* length of receive buffer */ CTLD0100, /* command format */ &Cmd, /* command data */ cmd_data_len, /* length of command data */ &EC); /* Error code */ if (EC.Edata.Bytes_Available>0) /* If there was an error */ { /* Handle error on request sense command */ } else { /* Parse the request sense data to determine what action */ /* to take. */ } } else if (EC.reason_cd[2]=='\x08') /* Busy status */ { /* Try the command again later */ } else /* Unexpected completion status */ { /* Send error message for unexpected completion status */ } } else if (strncmp(EC.reason_cd,"\x02\xC1\x00", 3) == 0) /* Selection timeout */ { /* Send message that device might be powered off */ } /* Add else if for the other reason codes here */ else { /* Send error message for unexpected reason code */ } } else { /* Handle other messages */ } } else { /* No error */ } /********************************************************************/ /* CLOSE connection */ /********************************************************************/ send_buff_len = 0; /* no send buffer */ recv_buff_len = 0; /* no receive buffer */ cmd_data_len = 0; /* no command data */ EC.Edata.Bytes_Provided = 32; /* No exceptions */ QTACTLDV(device, /* device name */ FUNCLOS, /* requested function */ send_buff, /* send buffer */ send_buff_len, /* length of send buffer */ recv_buff, /* receive buffer */ recv_buff_len, /* length of receive buffer */ CTLD0100, /* command format */ &Cmd, /* command data */ cmd_data_len, /* length of command data */ &EC.Edata); /* Error code */ if (EC.Edata.Bytes_Available>0) /* If there was an error */ { /* Handle the error */ } }
This example shows how the QTACTLDV (Control Device) API could be used to display the tape device firmware level.
/* Usage example 2 for QTACTLDV API */ /* */ /* */ #include // Control Device API #include // Error code header #include // String Header File #include // Standard I/O Header #include // Standard Library Header #include // Exception & cancel declares /*********************************************************************/ /* Type definitions */ /*********************************************************************/ // Define the command structure for sending commands using QTACTLDV API. typedef struct { // Command Structure Qta_CTLD0100_t hdr; // Header char cmd_str[6]; // Command String } ctldv_cmd_t; /**********************************************************************/ /* Entry point to program. */ /**********************************************************************/ int main (int argc, char *argv[]) { char device[10]; // Device name to get FM level int deviceLen; // Length of device name to cop char send_buff[1]; // Send buffer int send_buff_len; // Length of send buffer char recv_buff[50]; // Receive buffer int recv_buff_len; // Length of receive buffer ctldv_cmd_t ctldv_cmd; // Command variable int ctldv_cmd_len; // Length of command string char tempChar; // Used to conver ASCII to EBCD Qus_EC_t EC; // Error code for qtactldv char code[4]; // EBCDIC code level int i; // Iterator to move ASCII to EB EC.Bytes_Provided = 0; // Return errors to user memset(device, ' ', sizeof(device)); // Set to blanks deviceLen=strlen(argv[1]); if (deviceLen>10) deviceLen=10; memcpy(device, argv[1], deviceLen); // Copy up to 10 chars memset(code, ' ', sizeof(code)); // Clear code level /********************************************************************/ /* Open the pipe. */ /********************************************************************/ send_buff_len = 0; // No send buffer recv_buff_len = 0; // No receive buffer ctldv_cmd_len = 0; // No command #pragma exception_handler(PipeFailed, 0, 0, _C2_MH_ESCAPE, _CTLA_HANDLE) QTACTLDV(device, // Device name FUNOPEN, // Function requested send_buff, // Send buffer send_buff_len, // Send buffer length recv_buff, // Receive buffer recv_buff_len, // Receive buffer length CTLD0100, // Command structure &cldv_cmd, // Command data ctldv_cmd_len, // Command data length &EC); // Error structure #pragma disable_handler /********************************************************************/ /* Get the drive VPD */ /********************************************************************/ recv_buff_len = 16; // Receive buffer for VPD send_buff_len = 0; // No send buffer ctldv_cmd_len = 32 + 6; // Reserve command size ctldv_cmd.hdr.Command_timeout = 600; // 10 minute timeout ctldv_cmd.hdr.Type_of_command = 0; // SCSI Command ctldv_cmd.hdr.Offset_to_command_string = sizeof(ctldv_cmd.hdr); // Offset 32 ctldv_cmd.hdr.Length_of_command_string = 6; // 6 byte command ctldv_cmd.hdr.Reserved1 = 0; // Reserved ctldv_cmd.hdr.Data_transfer_direction=XFRRECV; // Receiving inquiry data ctldv_cmd.hdr.Requested_transfer_length=16; // Number of bytes to transfer ctldv_cmd.hdr.Ignore_length_errors = RPTLERR; // Report length errors memset(ctldv_cmd.cmd_str, 0x00, 6); // clear command ctldv_cmd.cmd_str[0] = 0x12; // set to Inquiry command ctldv_cmd.cmd_str[1] = 0x01; // set EVPD mode ctldv_cmd.cmd_str[2] = 0x03; // Set code page - VPD ctldv_cmd.cmd_str[4] = 0x10; // Allocation length #pragma exception_handler(PipeClose, 0, 0, _C2_MH_ESCAPE, _CTLA_HANDLE) QTACTLDV(device, // Device name FUNCMD, // Function requested send_buff, // Send buffer send_buff_len, // Send buffer length recv_buff, // Receive buffer recv_buff_len, // Receive buffer length CTLD0100, // Command structure &cldv_cmd, // Command data ctldv_cmd_len, // Command data length &EC); // Error structure #pragma disable_handler /********************************************************************/ /* Convert the level to EBSDIC */ /********************************************************************/ for (i = 0; (i < sizeof(code)); i++) { tempChar = recv_buff[12+i]; // Code offest in VPD data if (tempChar < 0x41) // is it a number? tempChar = tempChar - 0x30 + 0xF0; // ASCII to EBCDII 0-9 else { tempChar = tempChar & 0xDF; // Convert to ASCII uppercase if (tempChar < 0x4A) // is char < J ? tempChar = tempChar - 0x41 + 0xC1; // ASCII to EBCDII A-I else if (tempChar < 0x53) // is char < S tempChar = tempChar - 0x4A + 0xD1; // ASCII to EBCDII J-R else tempChar = tempChar - 0x53 + 0xE2; // ASCII to EBCDII S-Z } code[i] = tempChar; // Output the EBCDIC char } printf("The code level is: %s\n", code); /*********************************************************************/ /* Close the pipe. */ /*********************************************************************/ PipeClose: send_buff_len = 0; // No send buffer recv_buff_len = 0; // No receive buffer ctldv_cmd_len = 0; // No command #pragma exception_handler(PipeFailed, 0, 0, _C2_MH_ESCAPE, _CTLA_HANDLE) QTACTLDV(device, // Device name FUNCLOS, // Function requested send_buff, // Send buffer send_buff_len, // Send buffer length recv_buff, // Receive buffer recv_buff_len, // Receive buffer length CTLD0100, // Command structure &cldv_cmd, // Command data ctldv_cmd_len, // Command data length &EC); // Error structure #pragma disable_handler PipeFailed: return 0; // return to user }