| #include <unistd.h> |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <sys/ioctl.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include "sg_include.h" |
| |
| /* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") |
| device driver. |
| * Copyright (C) 1999-2002 D. Gilbert |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2, or (at your option) |
| * any later version. |
| |
| This program send either device, bus or host resets to device, |
| or bus or host associated with the given sg device. |
| |
| */ |
| |
| #define ME "sg_reset: " |
| |
| static char * version_str = "0.54 20050517"; |
| |
| #ifndef SG_SCSI_RESET |
| #define SG_SCSI_RESET 0x2284 |
| #endif |
| |
| #ifndef SG_SCSI_RESET_NOTHING |
| #define SG_SCSI_RESET_NOTHING 0 |
| #define SG_SCSI_RESET_DEVICE 1 |
| #define SG_SCSI_RESET_BUS 2 |
| #define SG_SCSI_RESET_HOST 3 |
| #endif |
| |
| |
| |
| int main(int argc, char * argv[]) |
| { |
| int sg_fd, res, k; |
| int do_device_reset = 0; |
| int do_bus_reset = 0; |
| int do_host_reset = 0; |
| char * file_name = 0; |
| |
| for (k = 1; k < argc; ++k) { |
| if (0 == strcmp("-d", argv[k])) |
| do_device_reset = 1; |
| else if (0 == strcmp("-b", argv[k])) |
| do_bus_reset = 1; |
| else if (0 == strcmp("-h", argv[k])) |
| do_host_reset = 1; |
| else if (0 == strcmp("-V", argv[k])) { |
| fprintf(stderr, "Version string: %s\n", version_str); |
| exit(0); |
| } else if (*argv[k] == '-') { |
| printf("Unrecognized switch: %s\n", argv[k]); |
| file_name = 0; |
| break; |
| } else |
| file_name = argv[k]; |
| } |
| if (0 == file_name) { |
| printf( |
| "Usage: 'sg_reset [-b] [-d] [-h] [-V] <scsi_device>'\n"); |
| printf(" where: -b attempt a SCSI bus reset\n"); |
| printf(" -d attempt a SCSI device reset\n"); |
| printf(" -h attempt a host adapter reset\n"); |
| printf(" -V print version string then exit"); |
| printf(" {if no switch given then check if reset underway}\n"); |
| printf("To reset use '-d' first, then '-b' then '-h'\n"); |
| return 1; |
| } |
| |
| sg_fd = open(file_name, O_RDWR | O_NONBLOCK); |
| if (sg_fd < 0) { |
| fprintf(stderr, ME "open error: %s: ", file_name); |
| perror(""); |
| return 1; |
| } |
| |
| k = SG_SCSI_RESET_NOTHING; |
| if (do_device_reset) { |
| printf(ME "starting device reset\n"); |
| k = SG_SCSI_RESET_DEVICE; |
| } |
| else if (do_bus_reset) { |
| printf(ME "starting bus reset\n"); |
| k = SG_SCSI_RESET_BUS; |
| } |
| else if (do_host_reset) { |
| printf(ME "starting host reset\n"); |
| k = SG_SCSI_RESET_HOST; |
| } |
| |
| res = ioctl(sg_fd, SG_SCSI_RESET, &k); |
| if (res < 0) { |
| if (EBUSY == errno) |
| printf(ME "BUSY, may be resetting now\n"); |
| else if (EIO == errno) |
| printf(ME "requested type of reset may not be available\n"); |
| else if (EACCES == errno) |
| printf(ME "reset requires CAP_SYS_ADMIN (root) " |
| "permission\n"); |
| else if (EINVAL == errno) |
| printf(ME "SG_SCSI_RESET not supported\n"); |
| else if (EIO == errno) |
| printf(ME "scsi_reset_provider() call failed\n"); |
| else |
| perror(ME "SG_SCSI_RESET failed"); |
| return 1; |
| } |
| if (SG_SCSI_RESET_NOTHING == k) |
| printf(ME "did nothing, device is normal mode\n"); |
| else if (SG_SCSI_RESET_DEVICE == k) |
| printf(ME "completed device reset\n"); |
| else if (SG_SCSI_RESET_BUS == k) |
| printf(ME "completed bus reset\n"); |
| else if (SG_SCSI_RESET_HOST == k) |
| printf(ME "completed host reset\n"); |
| |
| if (close(sg_fd) < 0) { |
| perror(ME "close error"); |
| return 1; |
| } |
| return 0; |
| } |