From: GWDVMS::MOELLER [moeller@gwdvms.dnet.gwdg.de] Sent: Thursday, April 13, 2000 6:02 AM To: Info-VAX@Mvb.Saic.Com Subject: RE: Spin down hard disk on idle VMS system Markus Ruggiero writes (a while ago): >[...] Most of the time this box is just idling. Is there some > software around that allows the OS to spin down the hard disks after > some time of inactivity? [...] I've played with the C program below, mostly on VAX (V5.5-2), and found that VMS wouldn't object to finding a MOUNTed disk spun down (instead it would ask for spin-up and *not* increment the error count). It's not pretty (it's sort of excerpts from an old version of CDWRITE), though it might well serve as a starting point. Wolfgang J. Moeller, Tel. +49 551 2011516 or -510, moeller@gwdvms.dnet.gwdg.de GWDG, D-37077 Goettingen, F.R.Germany | Disclaimer: No claim intended! http://www.gwdg.de/~moeller/ ---- ----- $! ................... Cut between dotted lines and save. ................... $!........................................................................... $! VAX/VMS archive file created by VMS_SHARE V06.10 7-FEB-1989. $! $! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from $! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au). $! $! To unpack, simply save, concatinate all parts into one file and $! execute (@) that file. $! $! This archive was created by user MOELLER $! on 13-APR-2000 11:52:09.93. $! $! It contains the following 1 file: $! SCSI-STOP.C $! $!============================================================================ $ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL ) $ VERSION = F$GETSYI( "VERSION" ) $ if f$getsyi("cpu").gt.127 then goto version_ok $ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK $ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", - "VMS_SHARE V06.10 7-FEB-1989 requires VMS V4.4 or higher." $ EXIT 44 ! SS$_ABORT $VERSION_OK: $ GOTO START $! $UNPACK_FILE: $ WRITE SYS$OUTPUT "Creating ''FILE_IS'" $ DEFINE/USER_MODE SYS$OUTPUT NL: $ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION - VMS_SHARE_DUMMY.DUMMY b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) ) ; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE , b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors := 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN & "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION ( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail & LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP ; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK ( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 ) ; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF ; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT ) ; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip := MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip <> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET ) ; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part ) ); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF ; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE ; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1 ; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF ; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors := i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT ( "The following line could not be unpacked properly:" ); SPLIT_LINE ; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL ( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH ( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1 ); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP ; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION ( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO ( "The following !UL errors were detected while unpacking !AS", i_errors , s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" ) ; ENDIF; EXIT; $ DELETE VMS_SHARE_DUMMY.DUMMY;* $ CHECKSUM 'FILE_IS $ WRITE SYS$OUTPUT " CHECKSUM ", - F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." ) $ RETURN $! $START: $ FILE_IS = "SCSI-STOP.C" $ CHECKSUM_IS = 1864267845 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* X * argument: disk to be spun down X * V **************************************************************************** X** X */ X X#include X#include X#include X#include X X#include X#include X#include X X X/* macro definitions */ X X#define GK_EFN 0`009`009/* Event flag number */ X X#define SCSI_DATA_LENGTH 0xFF`009/* Length of inquiry buffer */ X X X/* SCSI command opcodes */ X X#define TEST_UNIT_READY`009`0090x00 X#define REZERO_UNIT`009`0090x01 X#define READ_10`009`009`0090x28 X#define INQUIRY`009`009`0090x12 X#define START_STOP`009`0090x1b X#define ALLOW_MEDIUM_REMOVAL`0090x1e X#define READ_CAPACITY`009`0090x25 X X X/* Generic SCSI command descriptor */ X Xstruct SCSI$DESC `123 X`009unsigned int`009SCSI$L_OPCODE;`009`009/* SCSI Operation Code */ X`009unsigned int`009SCSI$L_FLAGS;`009`009/* SCSI Flags Bit Map */ X`009char *`009`009SCSI$A_CMD_ADDR;`009/* ->SCSI command buffer */ X`009unsigned int`009SCSI$L_CMD_LEN;`009`009/* SCSI command length, bytes */ X`009char *`009`009SCSI$A_DATA_ADDR;`009/* ->SCSI data buffer */ X`009unsigned int`009SCSI$L_DATA_LEN;`009/* SCSI data length, bytes */ X`009unsigned int`009SCSI$L_PAD_LEN;`009`009/* SCSI pad length, bytes */ V`009unsigned int`009SCSI$L_PH_CH_TMOUT;`009/* SCSI phase change timeout, sec X */ V`009unsigned int`009SCSI$L_DISCON_TMOUT;`009/* SCSI disconnect timeout, sec * X/ X`009unsigned int`009SCSI$L_RES_1;`009`009/* Reserved */ X`009unsigned int`009SCSI$L_RES_2;`009`009/* Reserved */ X`009unsigned int`009SCSI$L_RES_3;`009`009/* Reserved */ X`009unsigned int`009SCSI$L_RES_4;`009`009/* Reserved */ X`009unsigned int`009SCSI$L_RES_5;`009`009/* Reserved */ X`009unsigned int`009SCSI$L_RES_6;`009`009/* Reserved */ X`125; X X/* SCSI Input/Output Status Block */ X X#ifdef __ALPHA X#pragma member_alignment save X#pragma nomember_alignment X#endif X Xstruct SCSI$IOSB `123 X`009unsigned short int SCSI$W_VMS_STAT;`009/* VMS status code */ X`009unsigned long int SCSI$L_IOSB_TFR_CNT; /* Actual #bytes transferred */ X`009char`009`009 SCSI$B_IOSB_FILL_1; X`009unsigned char`009 SCSI$B_IOSB_STS;`009/* SCSI device status */ X`125; X X#ifdef __ALPHA X#pragma member_alignment restore X#endif X X X/* SCSI status codes and flag field constants */ X X#define SCSI$K_GOOD_STATUS`0090 X#define SCSI$K_WRITE`009`0090X0`009/* direction of transfer=write */ X#define SCSI$K_READ`009`0090X1`009/* direction of transfer=read */ X#define SCSI$K_FL_ENAB_DIS`0090X2`009/* enable disconnects */ X#define SCSI$K_FL_ENAB_SYNC`0090X4`009/* enable sync */ X X/* end of SCSI definitions */ X X/* data declarations */ X Xstatic char X`009scsi_status, X`009scsi_command_6[6],`032 X`009scsi_command_10[10], X`009scsi_data[SCSI_DATA_LENGTH]; X Xstatic unsigned short int X`009gk_chan,`032 X`009transfer_length; X Xstatic int X`009i,`032 X`009status; X Xstatic struct dsc$descriptor_s gk_device_desc = `123`032 X`0090-0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0-0 `125; X Xstatic struct SCSI$IOSB gk_iosb ; X Xstatic struct SCSI$DESC gk_desc; X X/*****/ X X Xlong lib$wait(); Xvoid lib$stop(); X X/*****/ X Xvoid scsiprbytes(s, cp, n) X`009`009char`009*s; X`009register unsigned char`009*cp; X`009register int`009n; X`123 X`009printf(s); X`009while (--n >= 0) X`009`009printf(" %02.2X", *cp++); X`009printf("\n"); X`125 X X Xvoid inquire(void) `123 X X`009scsi_command_6[0] = INQUIRY; X`009scsi_command_6[1] = 0; X`009scsi_command_6[2] = 0; X`009scsi_command_6[3] = 0; X`009scsi_command_6[4] = SCSI_DATA_LENGTH; X`009scsi_command_6[5] = 0; X X`009gk_desc.SCSI$L_FLAGS = SCSI$K_FL_ENAB_SYNC `124 X`009`009`009`009SCSI$K_READ `124 X`009`009`009`009SCSI$K_FL_ENAB_DIS;`009/* SCSI Flags Bit Map */ V`009gk_desc.SCSI$A_CMD_ADDR = &scsi_command_6[0];`009/* ->SCSI command buffer X */ X`009gk_desc.SCSI$L_CMD_LEN = 6;`009`009/* SCSI command length, bytes */ X`009gk_desc.SCSI$A_DATA_ADDR = &scsi_data[0];`009/* ->SCSI data buffer */ V`009gk_desc.SCSI$L_DATA_LEN = SCSI_DATA_LENGTH;`009/* SCSI data length, bytes X */ V`009gk_desc.SCSI$L_PH_CH_TMOUT = 0xff;`009/* SCSI phase change timeout, sec * X/ X`009gk_desc.SCSI$L_DISCON_TMOUT = 0xff;`009/* SCSI disconnect timeout, sec */ X X X/* Issue the QIO to send the inquiry command and receive the inquiry data */ X X`009status = sys$qiow ( GK_EFN, gk_chan, IO$_DIAGNOSE, &gk_iosb, 0, 0,`032 X`009`009`009&gk_desc, sizeof(gk_desc), 0, 0, 0, 0); X X`009if (!(status & 1)) lib$stop(status); X X`009if (!(gk_iosb.SCSI$W_VMS_STAT & 1)) X`009`009lib$stop(gk_iosb.SCSI$W_VMS_STAT); X X/* Yes, was SCSI Status OK from QIO? */ X X`009if (gk_iosb.SCSI$B_IOSB_STS != SCSI$K_GOOD_STATUS) `123 X`009`009printf ("Bad SCSI status returned: %02.2x\n", X`009`009`009gk_iosb.SCSI$B_IOSB_STS); X`009`009abort(); X`009`125 X X/* The command succeeded. Display the SCSI data returned from the target */ X X`009transfer_length = gk_iosb.SCSI$L_IOSB_TFR_CNT; X`009printf ("SCSI inquiry data returned %u bytes of data: \n", X`009`009transfer_length); X X`009for (i = 0; i < 8; i++) printf(" %02.2X",scsi_data[i] & 0xFF); X`009printf("\n"); X`009for (i = 8; i < transfer_length; i++) `123 X`009`009if (isprint (scsi_data[i])) X`009`009`009printf ("%c", scsi_data[i]); X`009`009else X`009`009`009printf ("."); X`009`125 X`009printf ("\n"); X`125 X X Xvoid test_unit_ready(void) `123 X`009scsi_command_6[0] = TEST_UNIT_READY; X`009scsi_command_6[1] = 0; X`009scsi_command_6[2] = 0; X`009scsi_command_6[3] = 0; X`009scsi_command_6[4] = 0; X`009scsi_command_6[5] = 0; X X`009gk_desc.SCSI$L_FLAGS = SCSI$K_FL_ENAB_SYNC `124 X`009`009`009`009SCSI$K_READ `124 X`009`009`009`009SCSI$K_FL_ENAB_DIS;`009/* SCSI Flags Bit Map */ V`009gk_desc.SCSI$A_CMD_ADDR = &scsi_command_6[0];`009/* ->SCSI command buffer X */ X`009gk_desc.SCSI$L_CMD_LEN = 6;`009`009/* SCSI command length, bytes */ X`009gk_desc.SCSI$A_DATA_ADDR = &scsi_data[0];`009/* ->SCSI data buffer */ X`009gk_desc.SCSI$L_DATA_LEN = 0;`009`009/* SCSI data length, bytes */ V`009gk_desc.SCSI$L_PH_CH_TMOUT = 0xff;`009/* SCSI phase change timeout, sec * X/ X`009gk_desc.SCSI$L_DISCON_TMOUT = 0xff;`009/* SCSI disconnect timeout, sec */ X X X`009do `123 X`009`009status = sys$qiow ( GK_EFN, gk_chan, IO$_DIAGNOSE, X`009`009`009`009&gk_iosb, 0, 0,`032 X`009`009`009`009&gk_desc, sizeof(gk_desc), 0, 0, 0, 0); X X/* Check the various returned status values */ X X`009`009if (!(status & 1)) lib$stop (status); X X`009`009if (!(gk_iosb.SCSI$W_VMS_STAT & 1)) X`009`009`009lib$stop (gk_iosb.SCSI$W_VMS_STAT); X X`009`125 while (gk_iosb.SCSI$B_IOSB_STS != 0); X`125 X X Xvoid start_unit(int load) `123 X X`009scsi_command_6[0] = START_STOP; X`009scsi_command_6[1] = 1; X`009scsi_command_6[2] = 0; X`009scsi_command_6[3] = 0; X`009scsi_command_6[4] = 1 `124 ((!!load) << 1); X`009scsi_command_6[5] = 0; X X`009gk_desc.SCSI$L_FLAGS = SCSI$K_FL_ENAB_SYNC `124 X`009`009`009`009SCSI$K_READ `124 X`009`009`009`009SCSI$K_FL_ENAB_DIS;`009/* SCSI Flags Bit Map */ V`009gk_desc.SCSI$A_CMD_ADDR = &scsi_command_6[0];`009/* ->SCSI command buffer X */ X`009gk_desc.SCSI$L_CMD_LEN = 6;`009`009/* SCSI command length, bytes */ X`009gk_desc.SCSI$A_DATA_ADDR = &scsi_data[0];`009/* ->SCSI data buffer */ X`009gk_desc.SCSI$L_DATA_LEN = 0;`009`009/* SCSI data length, bytes */ V`009gk_desc.SCSI$L_PH_CH_TMOUT = 0xff;`009/* SCSI phase change timeout, sec * X/ X`009gk_desc.SCSI$L_DISCON_TMOUT = 0xff;`009/* SCSI disconnect timeout, sec */ X X X`009status = sys$qiow ( GK_EFN, gk_chan, IO$_DIAGNOSE, &gk_iosb, 0, 0,`032 X`009`009`009&gk_desc, sizeof(gk_desc), 0, 0, 0, 0); X X`009if (!(status & 1)) lib$stop (status); X X`009if (!(gk_iosb.SCSI$W_VMS_STAT & 1)) X`009`009lib$stop (gk_iosb.SCSI$W_VMS_STAT); X X`009status = gk_iosb.SCSI$B_IOSB_STS; X`125 X Xvoid stop_unit(int eject) `123 X`009scsi_command_6[0] = START_STOP; X`009scsi_command_6[1] = 1; X`009scsi_command_6[2] = 0; X`009scsi_command_6[3] = 0; X`009scsi_command_6[4] = (!!eject) << 1; X`009scsi_command_6[5] = 0; X X`009gk_desc.SCSI$L_FLAGS = SCSI$K_FL_ENAB_SYNC `124 X`009`009`009`009SCSI$K_READ `124 X`009`009`009`009SCSI$K_FL_ENAB_DIS;`009/* SCSI Flags Bit Map */ V`009gk_desc.SCSI$A_CMD_ADDR = &scsi_command_6[0];`009/* ->SCSI command buffer X */ X`009gk_desc.SCSI$L_CMD_LEN = 6;`009`009/* SCSI command length, bytes */ X`009gk_desc.SCSI$A_DATA_ADDR = &scsi_data[0];`009/* ->SCSI data buffer */ X`009gk_desc.SCSI$L_DATA_LEN = 0;`009`009/* SCSI data length, bytes */ V`009gk_desc.SCSI$L_PH_CH_TMOUT = 0xff;`009/* SCSI phase change timeout, sec * X/ X`009gk_desc.SCSI$L_DISCON_TMOUT = 0xff;`009/* SCSI disconnect timeout, sec */ X X X`009status = sys$qiow ( GK_EFN, gk_chan, IO$_DIAGNOSE, &gk_iosb, 0, 0,`032 X`009`009`009&gk_desc, sizeof(gk_desc), 0, 0, 0, 0); X X/* Check the various returned status values */ X X`009if (!(status & 1)) lib$stop (status); X X`009if (!(gk_iosb.SCSI$W_VMS_STAT & 1)) X`009`009lib$stop (gk_iosb.SCSI$W_VMS_STAT); X X`009status = gk_iosb.SCSI$B_IOSB_STS; X`125 X X/*****/ X X Xmain (int argc, char **argv ) `123 X X`009gk_desc.SCSI$L_OPCODE = 1;`009/* SCSI Operation Code */ X`009gk_desc.SCSI$L_PAD_LEN = 0;`009/* SCSI pad length, bytes */ X`009gk_desc.SCSI$L_RES_1 = 0;`009/* Reserved */ X`009gk_desc.SCSI$L_RES_2 = 0;`009/* Reserved */ X`009gk_desc.SCSI$L_RES_3 = 0;`009/* Reserved */ X`009gk_desc.SCSI$L_RES_4 = 0;`009/* Reserved */ X`009gk_desc.SCSI$L_RES_5 = 0;`009/* Reserved */ X`009gk_desc.SCSI$L_RES_6 = 0;`009/* Reserved */ X X X/* Assign the device channel */ X X`009gk_device_desc.dsc$a_pointer = argv[1]; X`009gk_device_desc.dsc$w_length = strlen(argv[1]); X`032 X`009status = sys$assign ( &gk_device_desc, &gk_chan, 0, 0); X`009if (!(status & 1)) `123 X`009`009printf ("Unable to assign channel to %s\n", argv[1]); X`009`009sys$exit (status); X`009`125 X X/* do something */ X X`009inquire(); X X`009start_unit(0); X`009test_unit_ready(); X X`009stop_unit(0); X`125 $ GOSUB UNPACK_FILE $ EXIT Wolfgang J. Moeller, Tel. +49 551 2011516 or -510, moeller@gwdvms.dnet.gwdg.de GWDG, D-37077 Goettingen, F.R.Germany | Disclaimer: No claim intended! http://www.gwdg.de/~moeller/ ---- -----