/* tprobe-enhanced.c - generic SCSI device probe for AIX * * Extends the original tprobe to: * - Support any SCSI device type (disk, cdrom, etc.) * - Provide more detailed output * - Include device type detection * - Better error handling and logging * * Usage: tprobe-enhanced [-d device] [-v] * -d device SCSI device to probe (default: /dev/rmt0) * -v Verbose output */ #include #include #include #include #include #include #include #include #include #define DEVTYPE_DISK 0x00 #define DEVTYPE_TAPE 0x01 #define DEVTYPE_CDROM 0x05 static int fd; static unsigned char buf[65536]; static int verbose = 0; static char *devtype_name(int type) { switch (type) { case DEVTYPE_DISK: return "Direct-access disk"; case DEVTYPE_TAPE: return "Sequential-access"; case DEVTYPE_CDROM: return "CD-ROM"; default: return "Unknown"; } } static void hex(unsigned char *p, int n) { int i; for (i = 0; i < n; i++) printf("%02x%s", p[i], (i % 16 == 15) ? "\n " : " "); printf("\n"); } static int cmd(char *name, unsigned char *cdb, int clen, int dlen, int rd) { struct sc_iocmd c; int rc; memset(&c, 0, sizeof c); memset(buf, 0, dlen ? dlen : 1); c.data_length = dlen; c.buffer = (char *)buf; c.timeout_value = 120; c.flags = dlen ? (rd ? B_READ : B_WRITE) : 0; c.command_length = clen; memcpy(c.scsi_cdb, cdb, clen); rc = ioctl(fd, STIOCMD, &c); if (verbose || rc != 0) { printf("%-20s: rc=%d errno=%d valid=%d bus=0x%02x adapter=0x%02x\n", name, rc, rc ? errno : 0, c.status_validity, c.scsi_bus_status, c.adapter_status); } return rc; } static void sense(void) { unsigned char cdb[6] = {0x03, 0, 0, 0, 32, 0}; if (cmd("REQUEST SENSE", cdb, 6, 32, 1) == 0) { printf(" Sense key=0x%x ASC=0x%02x ASCQ=0x%02x filemark=%d eom=%d ili=%d\n", buf[2] & 0x0f, buf[12], buf[13], !!(buf[2] & 0x80), !!(buf[2] & 0x40), !!(buf[2] & 0x20)); } } int main(int argc, char **argv) { unsigned char tur[6] = {0x00, 0, 0, 0, 0, 0}; unsigned char inq[6] = {0x12, 0, 0, 0, 96, 0}; unsigned char msn[6] = {0x1a, 0, 0x00, 0, 255, 0}; char *dev = "/dev/rmt0"; int i, devtype; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-d") == 0 && i+1 < argc) { dev = argv[++i]; } else if (strcmp(argv[i], "-v") == 0) { verbose = 1; } } printf("=== SCSI Device Probe: %s ===\n\n", dev); fd = openx(dev, O_RDONLY, 0, SC_DIAGNOSTIC); if (fd < 0) { perror("openx"); return 1; } printf("Device opened in diagnostic mode\n\n"); if (cmd("TEST UNIT READY", tur, 6, 0, 0) != 0) { sense(); printf("Device not ready\n\n"); } else { printf("Device is ready\n\n"); } if (cmd("INQUIRY", inq, 6, 96, 1) == 0) { devtype = buf[0] & 0x1f; printf("Device Type: %s\n", devtype_name(devtype)); printf("Vendor: %.8s\n", buf + 8); printf("Product: %.16s\n", buf + 16); printf("Revision: %.4s\n\n", buf + 32); } else { sense(); } if (cmd("MODE SENSE", msn, 6, 255, 1) == 0) { printf("Medium Info:\n"); printf(" Length: %d\n", buf[0]); printf(" Type: 0x%02x\n", buf[1]); if (buf[3] >= 8) { printf(" Density: 0x%02x\n", buf[4]); printf(" Blocks: %d\n", (buf[5] << 16) | (buf[6] << 8) | buf[7]); printf(" Block len: %d\n\n", (buf[9] << 16) | (buf[10] << 8) | buf[11]); } } close(fd); return 0; }