Created
August 2, 2013 07:46
-
-
Save Swind/6138165 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <inttypes.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <sys/ioctl.h> | |
#include <scsi/sg.h> /* take care: fetches glibc's /usr/include/scsi/sg.h */ | |
/* This is a simple program executing a SCSI INQUIRY command using the | |
sg_io_hdr interface of the SCSI generic (sg) driver. | |
* Copyright (C) 2001 D. Gilbert | |
* This program is free software. Version 1.01 (20020226) | |
*/ | |
#define INQ_REPLY_LEN 96 | |
#define INQ_CMD_CODE 0x12 | |
#define INQ_CMD_LEN 6 | |
int execute_scsi_command( | |
int fd, sg_io_hdr_t *io_hdr, | |
int cmd_size, uint8_t* cmd_buffer, | |
int out_size, uint8_t* out_buffer, | |
int sense_size, uint8_t* sense_buffer) | |
{ | |
//Prepare SCSI Command | |
memset(io_hdr, 0, sizeof(sg_io_hdr_t)); | |
io_hdr->interface_id = 'S'; //required | |
io_hdr->cmd_len = cmd_size; | |
io_hdr->mx_sb_len = sense_size; | |
/* | |
* SG_DXFER_NONE - SCSI Test Unit Ready command | |
* SG_DXFER_TO_DEV - SCSI WRITE command | |
* SG_DXFER_FROM_DEV - SCSI READ command | |
*/ | |
io_hdr->dxfer_direction = SG_DXFER_FROM_DEV; | |
io_hdr->dxfer_len = out_size; | |
io_hdr->dxferp = out_buffer; | |
io_hdr->cmdp = cmd_buffer; | |
io_hdr->sbp = sense_buffer; | |
io_hdr->timeout = 20000; // 20000 millisecs = 20 seconds | |
/* io_hdr.flags = 0; */ /* take defaults: indirect IO, etc */ | |
/* io_hdr.pack_id = 0; */ | |
/* io_hdr.usr_ptr = NULL; */ | |
if (ioctl(fd, SG_IO, io_hdr) < 0) { | |
perror("sg_simple0: Inquiry SG_IO ioctl error"); | |
return 1; | |
} | |
return 0; | |
} | |
int inquiry(char * device_path) | |
{ | |
int sg_fd, k; | |
unsigned char inqCmdBlk[INQ_CMD_LEN] = {INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0}; | |
/* This is a "standard" SCSI INQUIRY command. It is standard because the | |
* CMDDT and EVPD bits (in the second byte) are zero. All SCSI targets | |
* should respond promptly to a standard INQUIRY */ | |
unsigned char inqBuff[INQ_REPLY_LEN]; | |
unsigned char sense_buffer[32]; | |
if ((sg_fd = open(device_path, O_RDONLY)) < 0) { | |
/* Note that most SCSI commands require the O_RDWR flag to be set */ | |
perror("error opening given file name"); | |
return 1; | |
} | |
sg_io_hdr_t io_hdr; | |
execute_scsi_command( | |
sg_fd, &io_hdr, | |
INQ_CMD_LEN,inqCmdBlk, | |
INQ_REPLY_LEN,inqBuff , | |
32, sense_buffer | |
); | |
/* now for the error processing */ | |
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { | |
if (io_hdr.sb_len_wr > 0) { | |
printf("INQUIRY sense data: "); | |
for (k = 0; k < io_hdr.sb_len_wr; ++k) { | |
if ((k > 0) && (0 == (k % 10))) | |
printf("\n "); | |
printf("0x%02x ", sense_buffer[k]); | |
} | |
printf("\n"); | |
} | |
if (io_hdr.masked_status) | |
printf("INQUIRY SCSI status=0x%x\n", io_hdr.status); | |
if (io_hdr.host_status) | |
printf("INQUIRY host_status=0x%x\n", io_hdr.host_status); | |
if (io_hdr.driver_status) | |
printf("INQUIRY driver_status=0x%x\n", io_hdr.driver_status); | |
} | |
else { /* assume INQUIRY response is present */ | |
char * p = (char *)inqBuff; | |
printf("Some of the INQUIRY command's response:\n"); | |
printf(" %.8s %.16s %.4s\n", p + 8, p + 16, p + 32); | |
printf("INQUIRY duration=%u millisecs, resid=%d\n", | |
io_hdr.duration, io_hdr.resid); | |
} | |
close(sg_fd); | |
return 0; | |
} | |
int main(int argc, const char *argv[]) | |
{ | |
inquiry("/dev/sda"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment