Linux SCSI Device Inquiry: How to Use sg_ll_inquiry() to Check Supported Pages

Introduction

In the Linux environment, SCSI devices play a crucial role in storage and data management. Understanding how to interact with these devices can be beneficial for system administrators and developers. One common task is querying SCSI devices to retrieve information about their capabilities and supported features. In this article, we will explore how to make an inquiry call to a SCSI device using the sg_ll_inquiry() function, specifically targeting page code 00 to check which other pages are supported.

Understanding SCSI and sg_ll_inquiry()

Before diving into the details, it’s essential to have a basic understanding of SCSI (Small Computer System Interface) and the sg_ll_inquiry() function. SCSI is a standard interface protocol used for communication between computers and peripheral devices, such as hard drives, tape drives, and scanners. The sg_ll_inquiry() function is part of the SCSI Generic (sg) driver in Linux, which allows users to send SCSI commands directly to devices.

Prerequisites

Before proceeding, ensure that the libsgutils library is installed on your Linux system. If not, you can install it using your package manager (e.g., apt for Debian/Ubuntu, yum for CentOS/Fedora).

Steps to Make an Inquiry Call

  • Open the SCSI Device: Begin by opening the SCSI device using the sg_cmds_open_device() function, which takes the device path (/dev/sgX) and a flag indicating read/write access.
  • Prepare the Inquiry Command: Create an inquiry command buffer (inquiry_cmd) with the SCSI INQUIRY opcode (0x12) and other necessary parameters. For page code 00, the inquiry command is typically {0x12, 0, 0, 0, 0, 0}.
  • Send the Inquiry Command: Use the SG_IO ioctl to send the inquiry command to the device. Prepare an sg_io_hdr_t structure (io_hdr) to hold the command and response data.
  • Check Command Status: After sending the command, check the status of the operation. If the command was successful, proceed to parse the response data.
  • Parse the Inquiry Response: The response data contains information about the device, including supported pages. For page code 00, check the first byte of the response buffer (inquiry_buff) for a value of 0x00. Other non-zero bytes at different offsets indicate supported pages.

Code Example

#include <stdio.h>
#include <stdlib.h>
#include <scsi/sg.h>

int main() {
    int fd;
    sg_io_hdr_t io_hdr;
    unsigned char inquiry_cmd[] = {SCSI_INQUIRY, 0, 0, 0, 0, 0};
    unsigned char inquiry_buff[96]; // Buffer to hold inquiry data

    fd = sg_cmds_open_device("/dev/sg0", 0 /* read/write */);
    if (fd < 0) {
        perror("Error opening device");
        exit(EXIT_FAILURE);
    }

    memset(&io_hdr, 0, sizeof(io_hdr));
    io_hdr.interface_id = 'S';
    io_hdr.cmdp = inquiry_cmd;
    io_hdr.cmd_len = sizeof(inquiry_cmd);
    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
    io_hdr.dxfer_len = sizeof(inquiry_buff);
    io_hdr.dxferp = inquiry_buff;
    io_hdr.mx_sb_len = 32;
    io_hdr.timeout = 5000; // 5 seconds

    if (ioctl(fd, SG_IO, &io_hdr) < 0) {
        perror("Error sending SCSI command");
        exit(EXIT_FAILURE);
    }

    // Check if inquiry command succeeded
    if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
        fprintf(stderr, "SCSI command failed\n");
        exit(EXIT_FAILURE);
    }

    // Parse inquiry data to find supported pages
    // For page code 00, the first byte of inquiry_buff will be 0x00
    // Other pages supported will be indicated by non-zero bytes at other offsets

    close(fd);
    return 0;
}

Conclusion

In conclusion, querying SCSI devices on Linux using sg_ll_inquiry() can provide valuable insights into their capabilities. By following the steps outlined in this article, you can effectively make an inquiry call to a SCSI device, specifically targeting page code 00 to check which other pages are supported. This knowledge can be useful for troubleshooting, performance tuning, and ensuring compatibility with different SCSI devices.

References