Your message dated Mon, 26 Apr 1999 14:48:58 +0200 with message-id <[EMAIL PROTECTED]> and subject line Closing has caused the attached bug report to be marked as done.
This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what I'm talking about this indicates a serious mail system misconfiguration somewhere. Please contact me immediately.) Ian Jackson (administrator, Debian bugs database) Received: (at submit) by bugs.debian.org; 4 Apr 1998 23:15:31 +0000 Received: (qmail 10668 invoked from network); 4 Apr 1998 23:15:31 -0000 Received: from mail.cs.utexas.edu ([EMAIL PROTECTED]) by debian.novare.net with SMTP; 4 Apr 1998 23:15:31 -0000 Received: from nevermore.csres.utexas.edu (dial-73-9.ots.utexas.edu [128.83.254.73]) by mail.cs.utexas.edu (8.8.5/8.8.5) with ESMTP id RAA18084 for <[EMAIL PROTECTED]>; Sat, 4 Apr 1998 17:15:16 -0600 (CST) Received: from rlb by nevermore.csres.utexas.edu with local (Exim 1.891 #1) id 0yLc9a-00031J-00 (Debian); Sat, 4 Apr 1998 17:15:14 -0600 To: [EMAIL PROTECTED] Subject: hwtools: scsi-spin -- an additional program for hwtools... From: Rob Browning <[EMAIL PROTECTED]> Date: 04 Apr 1998 17:15:14 -0600 Message-ID: <[EMAIL PROTECTED]> Lines: 250 X-Mailer: Gnus v5.6.2/Emacs 20.2 Package: hwtools Version: 0.3-4 Severity: wishlist Here's a small program I wrote called scsi-spin that lets you spin up and down scsi drives. I thought you might consider it for inclusion in the debian hwtools package, and perhaps from there into the upstream source somewhere. Thanks... This command is particularly useful if you've got noisy (or hot) drives in a machine that you rarely need to access. This is *not* the same as the kernel patch that's floating around that will automatically spin down the drive after some time. scsi-spin is completely manual, and spinning down a drive that's in use, especially the one containing the scsi-spin binary, it probably a *really* bad idea. You can build it with GNU make, and this command: make CC=g++ CFLAGS="-g -Wall -O2 -I/usr/src/linux/include" scsi-spin It doesn't really need g++, but I just wanted the extra type checking... And here's the source: /* File: scsi-spin.c A simple program to manually spin up and down a scsi device. Copyright 1998 Rob Browning <[EMAIL PROTECTED]> This source is covered by the terms the GNU Public License. Some of the original code came from The Linux SCSI programming HOWTO Heiko Ei<DF>feldt [EMAIL PROTECTED] v1.5, 7 May 1996 */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <getopt.h> #include <string.h> #include <fcntl.h> #include <errno.h> #include <scsi/sg.h> #include <scsi/scsi.h> #include <linux/major.h> #include <sys/sysmacros.h> #include <sys/stat.h> static const int SCSI_CMD_SIZE = 18; static const unsigned int scsi_off = sizeof(struct sg_header); static unsigned char cmd[scsi_off + SCSI_CMD_SIZE]; /* SCSI command buffer */ /* process a complete SCSI cmd. Use the generic SCSI interface. */ static int handle_SCSI_cmd(const int fd, const unsigned cmd_len, /* command length */ const unsigned in_size, /* input data size */ const unsigned char *i_buff, /* input buffer */ unsigned out_size, /* output data size */ unsigned char *o_buff /* output buffer */ ) { int status = 0; struct sg_header *sg_hd; /* safety checks */ if (!cmd_len) return -1; /* need a cmd_len != 0 */ if (!i_buff) return -1; /* need an input buffer != NULL */ #ifdef SG_BIG_BUFF if (scsi_off + cmd_len + in_size > SG_BIG_BUFF) return -1; if (scsi_off + out_size > SG_BIG_BUFF) return -1; #else if (scsi_off + cmd_len + in_size > 4096) return -1; if (scsi_off + out_size > 4096) return -1; #endif if (!o_buff) out_size = 0; /* no output buffer, no output size */ /* generic SCSI device header construction */ sg_hd = (struct sg_header *) i_buff; sg_hd->reply_len = scsi_off + out_size; sg_hd->twelve_byte = cmd_len == 12; sg_hd->result = 0; #if 0 sg_hd->pack_len = scsi_off + cmd_len + in_size; /* not necessary */ sg_hd->pack_id; /* not used */ sg_hd->other_flags; /* not used */ #endif /* send command */ status = write( fd, i_buff, scsi_off + cmd_len + in_size ); if ( status < 0 || status != scsi_off + cmd_len + in_size || sg_hd->result ) { /* some error happened */ fprintf( stderr, "write(generic) result = 0x%x cmd = 0x%x\n", sg_hd->result, i_buff[scsi_off] ); perror(""); return status; } if(!o_buff) o_buff = (char *) i_buff; /* buffer pointer check */ /* retrieve result */ status = read( fd, o_buff, scsi_off + out_size); if ( status < 0 || status != scsi_off + out_size || sg_hd->result ) { /* some error happened */ fprintf( stderr, "read(generic) status = 0x%x, result = 0x%x, " "cmd = 0x%x\n", status, sg_hd->result, o_buff[scsi_off] ); fprintf( stderr, "read(generic) sense " "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", sg_hd->sense_buffer[0], sg_hd->sense_buffer[1], sg_hd->sense_buffer[2], sg_hd->sense_buffer[3], sg_hd->sense_buffer[4], sg_hd->sense_buffer[5], sg_hd->sense_buffer[6], sg_hd->sense_buffer[7], sg_hd->sense_buffer[8], sg_hd->sense_buffer[9], sg_hd->sense_buffer[10], sg_hd->sense_buffer[11], sg_hd->sense_buffer[12], sg_hd->sense_buffer[13], sg_hd->sense_buffer[14], sg_hd->sense_buffer[15]); if (status < 0) perror(""); } /* Look if we got what we expected to get */ if (status == scsi_off + out_size) status = 0; /* got them all */ return status; /* 0 means no error */ } #define START_STOP_CMDLEN 6 static void scsi_spin(const int fd, const char desired_state) { unsigned char cmdblk [ START_STOP_CMDLEN ] = { START_STOP, /* command */ 0, /* lun(3 bits)/reserved(4 bits)/immed(1 bit) */ 0, /* reserved */ 0, /* reserved */ desired_state ? 1 : 0, /* reserved(6)/LoEj(1)/Start(1)*/ 0 };/* reserved/flag/link */ memcpy(cmd + scsi_off, cmdblk, sizeof(cmdblk)); /* * +------------------+ * | struct sg_header | <- cmd * +------------------+ * | copy of cmdblk | <- cmd + scsi_off * +------------------+ */ if (handle_SCSI_cmd(fd, sizeof(cmdblk), 0, cmd, 0, NULL )) { fprintf( stderr, "Inquiry failed\n" ); exit(2); } } static void usage() { static char usage_string[] = "usage: scsi-spin ( --up | --down ) device\n" "--up spin up device.\n" "--up spin down device.\n"; fputs(usage_string, stderr); } int main(int argc, char *argv[]) { int result = 0; int fd; int opt_up = 0; int opt_down = 0; struct option cmd_line_opts[] = { {"up", 0, &opt_up, 1}, {"down", 0, &opt_down, 1}, {0, 0, 0, 0}, }; char c; while((c = getopt_long(argc, argv, "", cmd_line_opts, NULL)) != EOF) { if(c == ':') { usage(); exit(1); } if(c == '?') { usage(); exit(1); } } if(opt_up && opt_down) { fputs("scsi-spin: specified both --up and --down. " "Is this some kind of test?\n", stderr); usage(); exit(1); } if(!(opt_up || opt_down)) { fputs("scsi-spin: must specify --up or --down.\n", stderr); usage(); exit(1); } if(optind != (argc - 1)) { usage(); exit(1); } fd = open(argv[optind], O_RDWR); if (fd < 0) { fprintf(stderr, "Failure opening %s\n", argv[optind]); exit(1); } { struct stat devstat; if(stat(argv[optind], &devstat) == -1) { fprintf(stderr, "stat on %s failed.\n", argv[optind]); close(fd); exit(1); } if(!S_ISCHR(devstat.st_rdev) || major(devstat.st_rdev) != SCSI_GENERIC_MAJOR) { fprintf(stderr, "%s is not a generic SCSI device.\n", argv[optind]); close(fd); exit(1); } } if(opt_up) scsi_spin(fd, 1); else scsi_spin(fd, 0); close(fd); return result; } -- Rob Browning <[EMAIL PROTECTED]> PGP fingerprint = E8 0E 0D 04 F5 21 A0 94 53 2B 97 F5 D6 4E 39 30