/* * This is an example of using mrd_read_element_status to * find out much data a read Read Element Status command * needs. It will only work when the underlying device is * a SCSI device since it relies on behavior defined for * SCSI. It will make a best attempt to print out the * the SCSI header to see what other implementations * provide. * * Usage: * * mrd_res_size robot type start count */ #ifndef lint static char SccsId[] = "@(#)mrd_res_size.c 1.2 (mrd-example) 3/5/97" ; #endif #include #include #include #include #include /* * The SCSI specification says that a request size of 8 * bytes will have the underlying device only return a * header indicating the number of bytes needed for the * command. */ #define SCSI_RES_MIN (8) /* * Given a string, resembling one of the element types, * return the SCSI type code for it. */ struct { int code ; char *string ; } etypes[] = { TRANSPORT, "transport", SLOT, "slot", DRIVE, "drive", PORT, "port", } ; convert_type(char *etype) { register i ; /* * For each entry in the array. */ for(i = 0; i < sizeof(etypes)/sizeof(etypes[0]); i++) /* * Do a case insensitive comparison, allowing * abbreviations. Return as soon as a match is * found. Return -1 if one isn't found. */ #ifdef vms if( strncmp(etypes[i].string, etype, strlen(etype)) == 0 ) #else if( strncasecmp(etypes[i].string, etype, strlen(etype)) == 0 ) #endif return etypes[i].code ; return 0 ; } main(int argc, char *argv[]) { int status ; /* return status */ int type ; /* Element type */ int start ; /* First element */ int count ; /* Number of elements */ int bytes ; /* Bytes of data */ char *robot ; /* Robot to open */ robot_info_t robot_info ; /* Robot data */ dev_status_t dev_status ; /* Device status */ unsigned char data[SCSI_RES_MIN] ; /* minimum data */ char log_info[MRD_MAX_LOG_STRING+1] ; /* * Check that there are enough arguments. */ if( argc < 5 ) { printf("usage: %s robot type start count\n", argv[0]) ; exit(1) ; } else { robot = argv[1] ; type = convert_type(argv[2]) ; start = atoi(argv[3]) ; count = atoi(argv[4]) ; } /* * Initialize the channel field of the robot_info, so * mrd_startup(3mrd) will actually open the robot. */ robot_info.channel = BAD_CHANNEL ; status = mrd_startup(robot, &robot_info, log_info) ; if( status != MRD_STATUS_SUCCESS ) { printf("Startup failed: %s: %s.\n", mrd_strstatus(status), log_info[0] ? log_info : "none") ; exit(1) ; } switch( type ) { case SLOT: start += robot_info.slot_start ; break ; case PORT: start += robot_info.port_start ; break ; case TRANSPORT: start += robot_info.transport_start ; break ; case DRIVE: start += robot_info.device_start ; break ; } /* * Read Element Status commands rarely fail, they just * succeed, but return no data. Clear all the fields * so we'll have an easier time seeing if any data was * returned. */ memset((void *)data, 0, SCSI_RES_MIN) ; status = mrd_read_element_status(&robot_info, type, start, count, data, SCSI_RES_MIN, &dev_status) ; /* * But sometimes they do fail. */ if( status != MRD_STATUS_SUCCESS ) { printf("Read Element Status failed on %s: %s.\n", robot, mrd_strstatus(status)) ; exit(1) ; } /* * The SCSI header for element status data has two bytes * for the first element address... */ start = (data[RES_FIRST_MSB] << 8) | data[RES_FIRST_LSB] ; /* * Two bytes for the number of elements reports... */ count = (data[RES_COUNT_MSB] << 8) | data[RES_COUNT_LSB] ; /* * And three bytes for the amount of data needed. */ bytes = (data[RES_REPORT_MSB] << 16) | (data[RES_REPORT_ISB] << 8) | data[RES_REPORT_LSB] ; printf("First Element: %d, Count: %d, Bytes needed: %d\n", start, count, bytes) ; (void)mrd_shutdown(&robot_info) ; return 0 ; }