2 ===================================================================
3 --- /dev/null Sat Jul 29 14:54:52 2006
4 +++ README.win32 Sat Jul 29 14:46:45 2006
9 +The only difference is in the naming of devices. On Linux the changer is
10 +accessed using /dev/sg<N>, on Windows you use Changer<N>.
12 +On Linux the tape drive is referenced using /dev/nst<N>, on Windows you use
15 +There is one exception in the case where there isn't a driver loaded for the
16 +device. This is usually only the case on Windows 2000 or if the Windows XP or
17 +Windows Server 2003 system supplied driver has been disabled.
19 +In the case where there is no driver loaded you can access the device directly
20 +through the SCSI driver using the following notation:
22 + <port>:<bus>:<target>:<lun>
24 + Port is the adapter number
25 + Bus is the SCSI bus number relative to the adapter
26 + Target is the SCSI device's target ID
27 + LUN is the SCSI device's logical unit number
29 ===================================================================
30 --- /dev/null Sat Jul 29 14:55:00 2006
31 +++ scsi_win32.c Sat Jul 29 14:54:08 2006
33 +/* Copyright 2006 Robert Nelson <robertn@the-nelsons.org>
38 + This program is free software; you may redistribute and/or modify it under
39 + the terms of the GNU General Public License Version 2 as published by the
40 + Free Software Foundation.
42 + This program is distributed in the hope that it will be useful, but
43 + WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
44 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45 + for complete details.
49 +/* These are the SCSI commands for Microsoft Windows. This is derived from
50 + * the file scsi_linux.c substituting Windows specific emulation of the Linux
58 +#include <ntddscsi.h>
60 +#include <ddk/ntddscsi.h>
67 +/* These are copied out of BRU 16.1, with all the boolean masks changed
70 +#define S_NO_SENSE(s) ((s)->SenseKey == 0x0)
71 +#define S_RECOVERED_ERROR(s) ((s)->SenseKey == 0x1)
73 +#define S_NOT_READY(s) ((s)->SenseKey == 0x2)
74 +#define S_MEDIUM_ERROR(s) ((s)->SenseKey == 0x3)
75 +#define S_HARDWARE_ERROR(s) ((s)->SenseKey == 0x4)
76 +#define S_UNIT_ATTENTION(s) ((s)->SenseKey == 0x6)
77 +#define S_BLANK_CHECK(s) ((s)->SenseKey == 0x8)
78 +#define S_VOLUME_OVERFLOW(s) ((s)->SenseKey == 0xd)
80 +#define DEFAULT_TIMEOUT 3 * 60 /* 3 minutes here */
82 +/* Sigh, the T-10 SSC spec says all of the following is needed to
83 + * detect a short read while in variable block mode, and that even
84 + * though we got a BLANK_CHECK or MEDIUM_ERROR, it's still a valid read.
87 +#define HIT_FILEMARK(s) (S_NO_SENSE((s)) && (s)->Filemark && (s)->Valid)
88 +#define SHORT_READ(s) (S_NO_SENSE((s)) && (s)->ILI && (s)->Valid && (s)->AdditionalSenseCode==0 && (s)->AdditionalSenseCodeQualifier==0)
89 +#define HIT_EOD(s) (S_BLANK_CHECK((s)) && (s)->Valid)
90 +#define HIT_EOP(s) (S_MEDIUM_ERROR((s)) && (s)->EOM && (s)->Valid)
91 +#define HIT_EOM(s) ((s)->EOM && (s)->Valid)
93 +#define STILL_A_VALID_READ(s) (HIT_FILEMARK(s) || SHORT_READ(s) || HIT_EOD(s) || HIT_EOP(s) || HIT_EOM(s))
95 +#define SCSI_DEFAULT_TIMEOUT 60 /* 1 minute */
96 +#define SCSI_MAX_TIMEOUT 108 /* 1 minute 48 seconds */
98 +typedef struct _HANDLE_ENTRY {
104 +} HANDLE_ENTRY, *PHANDLE_ENTRY;
106 +PHANDLE_ENTRY HandleTable = NULL;
109 +DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
112 + TCHAR szDevicePath[256];
117 + int port, path, target, lun;
119 + for (DeviceIndex = 0; DeviceIndex < nEntries; DeviceIndex++)
121 + if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
125 + if (DeviceIndex >= nEntries)
127 + PHANDLE_ENTRY pNewTable;
131 + if (HandleTable == NULL)
133 + pNewTable = (PHANDLE_ENTRY)malloc(nEntries * sizeof(HANDLE_ENTRY));
137 + pNewTable = (PHANDLE_ENTRY)realloc(HandleTable, nEntries * sizeof(HANDLE_ENTRY));
140 + if (pNewTable == NULL)
142 + FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
145 + HandleTable = pNewTable;
148 + for (index = 0; DeviceName[index] != '\0'; index++)
150 + if (DeviceName[index] == ':')
152 + else if (DeviceName[index] < '0' || DeviceName[index] > '9')
156 + if (DeviceName[index] == '\0' && nColons == 3 &&
157 + sscanf(DeviceName, "%d:%d:%d:%d", &port, &path, &target, &lun) == 4) {
159 + HandleTable[DeviceIndex].PortId = (UCHAR)port;
160 + HandleTable[DeviceIndex].PathId = (UCHAR)path;
161 + HandleTable[DeviceIndex].TargetId = (UCHAR)target;
162 + HandleTable[DeviceIndex].Lun = (UCHAR)lun;
164 + sprintf(szDevicePath, "\\\\.\\scsi%d:", port);
168 + int nPrefixLength = 0;
170 + if (DeviceName[0] != '\\') {
171 + memcpy(szDevicePath, "\\\\.\\", 4 * sizeof(TCHAR));
175 + HandleTable[DeviceIndex].PortId = 0;
176 + HandleTable[DeviceIndex].PathId = 0;
177 + HandleTable[DeviceIndex].TargetId = 0;
178 + HandleTable[DeviceIndex].Lun = 0;
180 + strncpy( &szDevicePath[nPrefixLength],
182 + sizeof(szDevicePath) / sizeof(TCHAR) - nPrefixLength - 1);
184 + szDevicePath[sizeof(szDevicePath) / sizeof(TCHAR) - 1] = '\0';
187 + HandleTable[DeviceIndex].hDevice = CreateFile(szDevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
189 + if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
191 + DWORD dwError = GetLastError();
196 + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
197 + fputs(lpszMessage, stderr);
201 + case ERROR_FILE_NOT_FOUND:
202 + case ERROR_PATH_NOT_FOUND:
206 + case ERROR_TOO_MANY_OPEN_FILES:
211 + case ERROR_ACCESS_DENIED:
212 + case ERROR_SHARING_VIOLATION:
213 + case ERROR_LOCK_VIOLATION:
214 + case ERROR_INVALID_NAME:
218 + case ERROR_FILE_EXISTS:
222 + case ERROR_INVALID_PARAMETER:
227 + FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
230 + return DeviceIndex;
233 +static int scsi_timeout = SCSI_DEFAULT_TIMEOUT;
235 +void SCSI_Set_Timeout(int secs)
237 + if (secs > SCSI_MAX_TIMEOUT) {
238 + secs = SCSI_MAX_TIMEOUT;
240 + scsi_timeout = secs * HZ;
243 +void SCSI_Default_Timeout(void)
245 + scsi_timeout = SCSI_DEFAULT_TIMEOUT * HZ;
248 +void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
250 + if (DeviceFD < nEntries)
252 + CloseHandle(HandleTable[DeviceFD].hDevice);
253 + HandleTable[DeviceFD].hDevice = INVALID_HANDLE_VALUE;
258 + FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
263 +/* Added by Eric Green <eric@estinc.com> to deal with burping
264 + * Seagate autoloader (hopefully!).
266 +/* Get the SCSI ID and LUN... */
267 +scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd) {
268 + scsi_id_t * retval;
270 + SCSI_ADDRESS ScsiAddress;
272 + DWORD dwBytesReturned;
274 + if (fd < nEntries) {
275 + retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
276 + retval->id = HandleTable[fd].TargetId;
277 + retval->lun = HandleTable[fd].Lun;
280 + fprintf(stderr,"SCSI:ID=%d LUN=%d\n", retval->id, retval->lun);
285 + FatalError("cannot close SCSI device - %m\n");
288 + memset(&ScsiAddress, 0, sizeof(ScsiAddress));
290 + ScsiAddress.Length = sizeof(ScsiAddress);
292 + bResult = DeviceIoControl(HandleTable[fd].hDevice,
293 + IOCTL_SCSI_GET_ADDRESS,
294 + &ScsiAddress, sizeof(ScsiAddress),
295 + &ScsiAddress, sizeof(ScsiAddress),
303 + retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
304 + retval->id = ScsiAddress.TargetId;
305 + retval->lun = ScsiAddress.Lun;
308 + fprintf(stderr,"SCSI:ID=%d LUN=%d\n",retval->id,retval->lun);
313 +int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
314 + Direction_T Direction,
318 + int DataBufferLength,
319 + RequestSense_T *RequestSense)
321 + PSCSI_PASS_THROUGH_DIRECT ScsiPassThrough;
323 + const DWORD dwBufferSize = sizeof(SCSI_PASS_THROUGH_DIRECT) + sizeof(RequestSense_T);
325 + DWORD dwBytesReturned;
327 + if (DeviceFD >= nEntries || HandleTable[DeviceFD].hDevice == INVALID_HANDLE_VALUE)
333 + ScsiPassThrough = (PSCSI_PASS_THROUGH_DIRECT)malloc(dwBufferSize);
335 + memset(ScsiPassThrough, 0, dwBufferSize);
337 + ScsiPassThrough->Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
339 + ScsiPassThrough->PathId = HandleTable[DeviceFD].PathId;
340 + ScsiPassThrough->TargetId = HandleTable[DeviceFD].TargetId;
341 + ScsiPassThrough->Lun = HandleTable[DeviceFD].Lun;
342 + ScsiPassThrough->CdbLength = (UCHAR)CDB_Length;
343 + ScsiPassThrough->SenseInfoLength = sizeof(RequestSense_T);
344 + ScsiPassThrough->DataIn = Direction == Input;
345 + ScsiPassThrough->DataTransferLength = DataBufferLength;
346 + ScsiPassThrough->TimeOutValue = scsi_timeout;
347 + ScsiPassThrough->DataBuffer = DataBuffer;
348 + ScsiPassThrough->SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);
350 + memcpy(ScsiPassThrough->Cdb, CDB, CDB_Length);
351 + dwBytesReturned = 0;
353 + bResult = DeviceIoControl(HandleTable[DeviceFD].hDevice,
354 + IOCTL_SCSI_PASS_THROUGH_DIRECT,
355 + ScsiPassThrough, sizeof(SCSI_PASS_THROUGH_DIRECT),
356 + ScsiPassThrough, dwBufferSize,
360 + if (ScsiPassThrough->ScsiStatus != 0) {
361 + memcpy(RequestSense, &ScsiPassThrough[1], sizeof(RequestSense_T));
363 + fprintf(stderr, "Command failed - ScsiStatus = %d\n", ScsiPassThrough->ScsiStatus);
364 + PrintRequestSense(RequestSense);
372 + DWORD dwError = GetLastError();
375 + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
376 + fputs(lpszMessage, stderr);
379 + memset(RequestSense, 0, sizeof(RequestSense_T));
382 + free(ScsiPassThrough);
384 + return bResult ? 0 : -1;
387 ===================================================================
388 --- tapeinfo.c (revision 139)
389 +++ tapeinfo.c (revision 147)
390 @@ -211,25 +211,18 @@
391 unsigned int partition1_size;
396 static void dump_data(unsigned char *data, int len) {
399 fprintf(stderr,"**NO DATA**\n");
403 - for (i=0;i<len;i++) {
404 - if ((i % 10) == 0) {
406 - fprintf(stderr,"\n");
408 - fprintf(stderr,"DATA:");
410 - fprintf(stderr,"%02x ",(unsigned int)*data++);
412 - fprintf(stderr,"\n");
413 + fprintf(stderr,"DATA:");
414 + PrintHex(1, data, len);
422 unsigned char buffer[TAPEALERT_SIZE]; /* Overkill, but ... */
424 - slow_bzero(buffer,TAPEALERT_SIZE); /*zero it... */
425 + slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
427 /* now to create the CDB block: */
428 CDB[0]=0x4d; /* Log Sense */
430 unsigned char buffer[TAPEALERT_SIZE];
431 unsigned char *walkptr;
433 - slow_bzero(buffer,TAPEALERT_SIZE); /*zero it... */
434 + slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
436 /* now to create the CDB block: */
437 CDB[0]=0x4d; /* Log Sense */
439 the sernum field, and bytes 4 onward are the serial #. */
442 - bufptr= &(buffer[4]);
443 + bufptr=(char *)&(buffer[4]);
445 printf("SerialNumber: '");
446 for (i=0;i<lim;i++) {
451 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
452 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
453 if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,6,&sense)!=0){
460 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
461 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
463 /* set the timeout: */
464 SCSI_Set_Timeout(2); /* set timeout to 2 seconds! */
469 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
470 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
471 if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){
472 printf("Ready: no\n");
477 /* we really don't care if this command works or not, sigh. */
478 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
479 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
480 if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){
484 ===================================================================
485 --- mtx.c (revision 139)
486 +++ mtx.c (revision 147)
488 "illegal <drive-number> argument '%d' to 'unload' command\n",
491 - if (ElementStatus->DataTransferElementFull[arg2] < 0 ) {
492 + if (!ElementStatus->DataTransferElementFull[arg2]) {
493 FatalError("Data Transfer Element %d is Empty\n", arg2);
495 /* Now see if something already lives where we wanna go... */
498 ElementStatus = ReadElementStatus(MediumChangerFD,&RequestSense,inquiry_info,&SCSI_Flags);
499 if (!ElementStatus) {
500 - PrintRequestSense(&RequestSense);
501 + PrintRequestSense(&RequestSense);
502 FatalError("READ ELEMENT STATUS Command Failed\n");
512 parse_args(); /* also executes them as it sees them, sigh. */
516 ===================================================================
517 --- scsitape.c (revision 139)
518 +++ scsitape.c (revision 147)
527 +#if HAVE_SYS_TYPES_H
528 #include <sys/types.h>
531 +#if HAVE_SYS_IOCTL_H
532 #include <sys/ioctl.h>
536 #include <sys/mtio.h> /* will try issuing some ioctls for Solaris, sigh. */
544 FatalError("Usage: scsitape -f <generic-device> <command> where <command> is:\n setblk <n> | fsf <n> | bsf <n> | eod | rewind | eject | mark <n> |\n seek <n> | read [<blksize> [<numblocks]] | write [<blocksize>] \n");
547 static int arg[4]; /* the argument for the command, sigh. */
549 /* the device handle we're operating upon, sigh. */
550 -static unsigned char *device; /* the text of the device thingy. */
551 +static char *device; /* the text of the device thingy. */
552 static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) 0;
559 -/* A table for printing out the peripheral device type as ASCII. */
560 -static char *PeripheralDeviceType[32] = {
574 - "Enclosure Services",
576 - "Bridging Expander", /* 0x10 */
577 - "Reserved", /* 0x11 */
578 - "Reserved", /* 0x12 */
579 - "Reserved", /* 0x13 */
580 - "Reserved", /* 0x14 */
581 - "Reserved", /* 0x15 */
582 - "Reserved", /* 0x16 */
583 - "Reserved", /* 0x17 */
584 - "Reserved", /* 0x18 */
585 - "Reserved", /* 0x19 */
586 - "Reserved", /* 0x1a */
587 - "Reserved", /* 0x1b */
588 - "Reserved", /* 0x1c */
589 - "Reserved", /* 0x1d */
590 - "Reserved", /* 0x1e */
591 - "Unknown" /* 0x1f */
596 /* open_device() -- set the 'fh' variable.... */
597 void open_device(void) {
602 /* we really don't care if this command works or not, sigh. */
603 - slow_bzero((unsigned char *)&RequestSense,sizeof(RequestSense_T));
604 + slow_bzero((char *)&RequestSense,sizeof(RequestSense_T));
605 if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&RequestSense)!=0){
606 PrintRequestSense(&RequestSense);
611 /* we really don't care if this command works or not, sigh. */
612 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
613 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
614 if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&sense)!=0){
615 PrintRequestSense(&sense);
620 /* we really don't care if this command works or not, sigh. */
621 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
622 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
623 if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&sense)!=0){
624 PrintRequestSense(&sense);
629 /* we really don't care if this command works or not, sigh. */
630 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
631 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
632 if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&sense)!=0){
633 PrintRequestSense(&sense);
638 /* we really don't care if this command works or not, sigh. */
639 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
640 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
641 if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,10,buffer,0,&sense)!=0){
642 PrintRequestSense(&sense);
645 static int S_setblk(void) {
646 RequestSense_T sense;
648 - unsigned char buffer[12];
650 unsigned int count = (unsigned int) arg1;
654 CDB[4]=12; /* length of data */
657 - slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
658 + slow_bzero((char *)&sense,sizeof(RequestSense_T));
659 slow_bzero(buffer,12);
661 /* Now to set the mode page header: */
664 /* S_write is not implemented yet! */
665 static int S_write(void) {
666 - unsigned char *buffer; /* the buffer we're gonna read/write out of. */
667 + char *buffer; /* the buffer we're gonna read/write out of. */
669 - int len; /* the length of the data in the buffer */
670 + unsigned int len; /* the length of the data in the buffer */
671 int blocksize=arg[0];
672 int numblocks=arg[1];
673 int varsize=0; /* variable size block flag */
677 static int S_read(void) {
678 - unsigned char *buffer; /* the buffer we're going to be reading out of */
679 + char *buffer; /* the buffer we're going to be reading out of */
681 - int len; /* the length of the data in the buffer */
682 + unsigned int len; /* the length of the data in the buffer */
683 int blocksize=arg[0];
684 int numblocks=arg[1];
685 int varsize=0; /* variable size block flag. */
687 ===================================================================
688 --- mtx.h (revision 139)
689 +++ mtx.h (working copy)
691 #include "[.vms]defs.h"
692 #else /* all the Unix stuff: */
695 +#include "msvc/config.h" /* all the autoconf stuff. */
697 #include "config.h" /* all the autoconf stuff. */
700 /* all the general Unix includes: */
703 # include <sys/ioctl.h>
706 -/* Now greately modified to use GNU Autoconf stuff: */
707 +/* Now greatly modified to use GNU Autoconf stuff: */
708 /* If we use the 'sg' interface, like Linux, do this: */
710 # include <scsi/scsi.h>
712 # define HAVE_GET_ID_LUN 1 /* signal that we have it... */
715 +/* Windows Native programs built using MinGW */
716 +#if HAVE_DDK_NTDDSCSI_H
717 +# include <windows.h>
718 +# include <ddk/ntddscsi.h>
721 +typedef int DEVICE_TYPE;
722 +# define HAVE_GET_ID_LUN 1 /* signal that we have it... */
725 +/* Windows Native programs built using Microsoft Visual C */
727 +# include <windows.h>
728 +# include <winioctl.h>
729 +# include <ntddscsi.h>
732 +typedef int DEVICE_TYPE;
733 +# define HAVE_GET_ID_LUN 1 /* signal that we have it... */
736 /* The 'cam' interface, like FreeBSD: */
738 # include <camlib.h> /* easy (?) access to the CAM user library. */
739 @@ -176,10 +201,23 @@
740 unsigned char invert2; /* used for EXCHANGE command, sigh. */
744 +typedef unsigned char boolean;
750 +typedef unsigned char Direction_T;
755 typedef enum { false, true } boolean;
758 typedef enum { Input, Output } Direction_T;
762 typedef unsigned char CDB_T[12];
764 } ElementModeSense_T;
768 +typedef char ElementTypeCode_T;
770 +#define AllElementTypes 0
771 +#define MediumTransportElement 1
772 +#define StorageElement 2
773 +#define ImportExportElement 3
774 +#define DataTransferElement 4
776 typedef enum ElementTypeCode
780 DataTransferElement = 4
786 typedef struct ElementStatusDataHeader
788 ===================================================================
789 --- nsmhack.c (revision 139)
790 +++ nsmhack.c (revision 147)
793 #include "mtxl.h" /* get the SCSI routines out of the main file */
795 -/*****************************************************************
796 +/****************************************************************/
798 /****************************************************************/
800 /* the device handle we're operating upon, sigh. */
801 -static unsigned char *device; /* the text of the device thingy. */
802 -static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) 0;
803 +static char *device; /* the text of the device thingy. */
804 +static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) -1;
806 int arg[4]; /* arguments for the command. */
807 #define arg1 (arg[0]) /* for backward compatibility, sigh */
809 /* open_device() -- set the 'fh' variable.... */
810 void open_device(void) {
812 - if (MediumChangerFD) {
813 + if (MediumChangerFD != -1) {
814 SCSI_CloseDevice("Unknown",MediumChangerFD); /* close it, sigh... new device now! */
818 /* if the device is not already open, then open it from the
821 - if (!MediumChangerFD) {
822 + if (MediumChangerFD == -1) {
823 /* try to get it from STAPE or TAPE environment variable... */
824 device=getenv("STAPE");
829 static int S_tongue_in(void) {
834 /* okay, stick our tongue out. We need a slot ID to grab a caddy from. */
838 /* Okay, we have element status, so now let's assume that */
842 /* See parse_args for the scoop. parse_args does all. */
844 ===================================================================
845 --- mtxl.h (revision 139)
846 +++ mtxl.h (revision 147)
854 void FatalError(char *ErrorMessage, ...);
855 void *xmalloc(size_t Size);
856 void *xzmalloc(size_t Size);
858 ===================================================================
859 --- ../release/mtx-1.3.9/config.h.in 2003-09-29 19:43:20.000000000 -0700
860 +++ config.h 2006-07-30 00:42:37.000000000 -0700
862 +/* config.h. Generated by configure. */
863 /* Copyright 2001 Enhanced Software Technologies Inc.
864 * Released under GNU General Public License V2 or Above
865 * See http://www.gnu.org for more information about the terms of
869 /* autoconf changes these. */
870 -#define HAVE_STRING_H 0
871 -#define HAVE_UNISTD_H 0
872 -#define HAVE_STDLIB_H 0
873 -#define HAVE_STDARG_H 0
874 +#define HAVE_STRING_H 1
875 +#define HAVE_UNISTD_H 1
876 +#define HAVE_STDLIB_H 1
877 +#define HAVE_STDARG_H 1
878 #define HAVE_SCSI_SCSI_H 0
879 #define HAVE_SCSI_SCSI_IOCTL_H 0
880 #define HAVE_SCSI_SG_H 0
882 #define HAVE_SYS_SCSI_CTL_H 0
883 #define HAVE_DSLIB_H 0
884 #define HAVE_DU_DEFS_H 0
885 -#define HAVE_SYS_STAT_H 0
886 -#define HAVE_SYS_TYPES_H 0
887 -#define HAVE_FCNTL_H 0
888 +#define HAVE_SYS_STAT_H 1
889 +#define HAVE_SYS_TYPES_H 1
890 +#define HAVE_FCNTL_H 1
891 #define HAVE_SYS_IOCTL_H 0
892 +#define HAVE_SYS_MTIO_H 0
893 +#define HAVE_DDK_NTDDSCSI_H 1
895 #define WORDS_BIGENDIAN 0
898 ===================================================================
899 --- ../release/mtx-1.3.9/mtxl.c 2003-10-02 23:03:20.000000000 -0700
900 +++ mtxl.c 2006-07-30 00:49:31.000000000 -0700
902 # include "scsi_linux.c"
905 +/* the IOCTL_SCSI_PASSTHROUGH interface is used on Windows. */
906 +#if HAVE_DDK_NTDDSCSI_H || defined(_MSC_VER)
907 +# include "scsi_win32.c"
910 /* The 'uscsi' interface is used on Solaris. */
911 #if HAVE_SYS_SCSI_IMPL_USCSI_H
912 # include "scsi_sun.c"
914 #include "[.vms]scsi.c"
917 +void PrintHex(int Indent, unsigned char *Buffer, int Length);
918 extern char *argv0; /* something to let us do good error messages. */
920 /* create a global RequestSenseT value. */
922 if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,
923 Inquiry, sizeof(Inquiry_T), RequestSense) != 0)
926 + fprintf(stderr, "SCSI Inquiry Command failed\n");
929 return NULL; /* sorry! */
931 @@ -111,36 +120,27 @@
935 +#if defined(DEBUG_NSM) || defined(DEBUG_EXCHANGE)
937 static void dump_cdb(unsigned char *CDB, int len) {
939 fprintf(stderr,"CDB:");
940 - for (i=0;i<len;i++) {
941 - fprintf(stderr,"%02x ",CDB[i]);
943 - fprintf(stderr,"\n");
944 + PrintHex(1, CDB, len);
949 +#if defined(DEBUG_NSM) || defined(DEBUG_ADIC)
951 static void dump_data(unsigned char *data, int len) {
954 fprintf(stderr,"**NO DATA**\n");
958 - for (i=0;i<len;i++) {
959 - if ((i % 10) == 0) {
961 - fprintf(stderr,"\n");
963 - fprintf(stderr,"DATA:");
965 - fprintf(stderr,"%02x ",(unsigned int)*data++);
967 - fprintf(stderr,"\n");
968 + fprintf(stderr,"DATA:");
969 + PrintHex(1, data, len);
974 int BigEndian16(unsigned char *BigEndianData)
978 /* Okay, this is a hack for the NSM modular jukebox series, which
979 - * uses the "SEND DIAGNOSTIC" command do to shit.
980 + * uses the "SEND DIAGNOSTIC" command to do shit.
983 int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command,
985 SCSI_Set_Timeout(30*60); /* 30 minutes, sigh! */
987 if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,NULL,0,&scsi_error_sense) != 0) {
989 + PrintRequestSense(&scsi_error_sense);
990 + fprintf(stderr, "Initialize Element Status (0x07) failed\n");
992 return -1; /* could not do! */
994 return 0; /* did do! */
996 CDB[1]=CDB[2]=CDB[3]=CDB[4]=CDB[5]=0;
998 if (SCSI_ExecuteCommand(fd,Input,&CDB,6,NULL,0,&scsi_error_sense) != 0) {
999 +#ifdef DEBUG_MODE_SENSE
1000 + PrintRequestSense(&scsi_error_sense);
1001 + fprintf(stderr, "Eject (0x1B) failed\n");
1003 return -1; /* could not do! */
1005 return 0; /* did do! */
1007 if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,
1008 &input_buffer,sizeof(input_buffer),&scsi_error_sense) != 0) {
1009 #ifdef DEBUG_MODE_SENSE
1010 - fprintf(stderr,"Could not execute mode sense...\n");
1011 + PrintRequestSense(&scsi_error_sense);
1012 + fprintf(stderr,"Mode sense (0x1A) for Page 0x1D failed\n");
1015 return NULL; /* sorry, couldn't do it. */
1016 @@ -405,18 +414,7 @@
1017 /* Could do it, now build return value: */
1019 #ifdef DEBUG_MODE_SENSE
1022 - for (i=0;i<30;i+=3) {
1023 - fprintf(stderr,"ib[%d]=%d ib[%d]=%d ib[%d]=%d\n",
1024 - i,input_buffer[i],i+1,input_buffer[i+1],
1025 - i+2,input_buffer[i+2]);
1026 - /* fprintf(stderr,"input_buffer[0]=%d input_buffer[3]=%d\n",
1027 - * input_buffer[0], input_buffer[3]);
1032 + PrintHex(0, input_buffer, 30);
1034 /* first, skip past: mode data header, and block descriptor header if any */
1035 sense_page=(ElementModeSensePage_T *)(input_buffer+4+input_buffer[3]);
1036 @@ -444,11 +442,11 @@
1038 #ifdef DEBUG_MODE_SENSE
1039 fprintf(stderr,"rawNumStorage= %d %d rawNumImportExport= %d %d\n",
1040 - sense_page->NumStorageHi,sense_page->NumStorageLo,
1041 - sense_page->NumImportExportHi, sense_page->NumImportExportLo);
1042 + sense_page->NumStorageHi,sense_page->NumStorageLo,
1043 + sense_page->NumImportExportHi, sense_page->NumImportExportLo);
1044 fprintf(stderr,"rawNumTransport=%d %d rawNumDataTransfer=%d %d\n",
1045 - sense_page->NumMediumTransportHi,sense_page->NumMediumTransportLo,
1046 - sense_page->NumDataTransferHi,sense_page->NumDataTransferLo);
1047 + sense_page->NumMediumTransportHi,sense_page->NumMediumTransportLo,
1048 + sense_page->NumDataTransferHi,sense_page->NumDataTransferLo);
1052 @@ -620,19 +618,16 @@
1053 CDB[11] = 0; /* Control */
1055 #ifdef DEBUG_BARCODE
1058 - fprintf(stderr,"CDB= ");
1059 - for (i=0;i<12;i++) {
1060 - fprintf(stderr,"%x ",CDB[i]);
1062 - fprintf(stderr,"\n");
1065 + fprintf(stderr,"CDB:\n");
1066 + PrintHex(2, CDB, 12);
1069 if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,
1070 DataBuffer,NumBytes, RequestSense) != 0){
1073 + fprintf(stderr, "Read Element Status (0x%02X) failed\n", CDB[0]);
1075 /* okay, first see if we have sense key of 'illegal request',
1076 additional sense code of '24', additional sense qualfier of
1077 '0', and field in error of '4'. This means that we issued a request
1078 @@ -654,15 +649,8 @@
1079 CDB[1] &= ~0x10; /* clear bar code flag! */
1081 #ifdef DEBUG_BARCODE
1084 - fprintf(stderr,"CDB= ");
1085 - for (i=0;i<12;i++) {
1086 - fprintf(stderr,"%x ",CDB[i]);
1088 - fprintf(stderr,"\n");
1091 + fprintf(stderr,"CDB:\n");
1092 + PrintHex(2, CDB, 12);
1095 if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,
1096 @@ -679,14 +667,8 @@
1097 #ifdef DEBUG_BARCODE
1098 /* print a bunch of extra debug data :-(. */
1099 PrintRequestSense(RequestSense); /* see what it sez :-(. */
1102 - fprintf(stderr,"Data:");
1103 - for (i=0;i<40;i++) {
1104 - fprintf(stderr,"%02x ",DataBuffer[i]);
1106 - fprintf(stderr,"\n");
1108 + fprintf(stderr,"Data:\n");
1109 + PrintHex(2, DataBuffer, 40);
1111 return DataBuffer; /* we succeeded! */
1116 unsigned char *DataBuffer; /* size of data... */
1117 - unsigned int real_numbytes;
1118 + int real_numbytes;
1121 DataBuffer=SendElementStatusRequestActual(MediumChangerFD,
1122 @@ -950,34 +932,42 @@
1123 BigEndian16(TransportElementDescriptor
1124 ->SourceStorageElementAddress);
1126 - if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer) {
1127 - FatalError("Too many Data Transfer Elements Reported\n");
1129 - if (ElementStatusPage->VolBits & E2_PVOLTAG) {
1130 - copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
1131 - ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);
1133 - ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1135 - if (ElementStatusPage->VolBits & E2_AVOLTAG) {
1136 - copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
1137 - ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);
1139 - ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1141 - ElementStatus->DataTransferElementCount++;
1142 - /* 0 actually is a usable element address */
1143 - /* if (DataTransferElementAddress == 0) */
1145 - /* "illegal Data Transfer Element Address %d reported\n", */
1146 - /* DataTransferElementAddress); */
1149 - FatalError("illegal Element Type Code %d reported\n",
1150 - ElementStatusPage->ElementTypeCode);
1154 + fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n",
1155 + ElementStatus->DataTransferElementCount,
1156 + ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount],
1157 + ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount],
1158 + ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount]);
1160 + if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer) {
1161 + FatalError("Too many Data Transfer Elements Reported\n");
1163 + if (ElementStatusPage->VolBits & E2_PVOLTAG) {
1164 + copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
1165 + ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);
1167 + ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1169 + if (ElementStatusPage->VolBits & E2_AVOLTAG) {
1170 + copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
1171 + ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);
1173 + ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1175 + ElementStatus->DataTransferElementCount++;
1177 + /* 0 actually is a usable element address */
1178 + /* if (DataTransferElementAddress == 0) */
1180 + /* "illegal Data Transfer Element Address %d reported\n", */
1181 + /* DataTransferElementAddress); */
1184 + FatalError("illegal Element Type Code %d reported\n",
1185 + ElementStatusPage->ElementTypeCode);
1191 /********************* Real ReadElementStatus ********************* */
1192 @@ -1008,7 +998,6 @@
1193 int *EmptyStorageElementAddress; /* [MAX_STORAGE_ELEMENTS]; */
1196 - int invalid_sources=0;
1197 boolean is_attached = false;
1200 @@ -1049,7 +1038,7 @@
1202 EmptyStorageElementAddress=(int *)xzmalloc((mode_sense->NumStorage+1)*sizeof(int));
1203 for (i=0;i<mode_sense->NumStorage;i++) {
1204 - EmptyStorageElementAddress[i]=-1;
1205 + EmptyStorageElementAddress[i] = -1;
1208 /* Okay, now to send some requests for the various types of stuff: */
1209 @@ -1076,6 +1065,9 @@
1211 /* darn. Free up stuff and return. */
1212 /****FIXME**** do a free on element data! */
1213 +#ifdef DEBUG_MODE_SENSE
1214 + PrintRequestSense(RequestSense);
1216 FreeElementData(ElementStatus);
1219 @@ -1107,6 +1099,9 @@
1221 /* darn. Free up stuff and return. */
1222 /****FIXME**** do a free on element data! */
1223 +#ifdef DEBUG_MODE_SENSE
1224 + PrintRequestSense(RequestSense);
1226 FreeElementData(ElementStatus);
1229 @@ -1138,6 +1133,9 @@
1231 /* darn. Free up stuff and return. */
1232 /****FIXME**** do a free on element data! */
1233 +#ifdef DEBUG_MODE_SENSE
1234 + PrintRequestSense(RequestSense);
1236 FreeElementData(ElementStatus);
1239 @@ -1172,6 +1170,9 @@
1241 /* darn. Free up stuff and return. */
1242 /****FIXME**** do a free on element data! */
1243 +#ifdef DEBUG_MODE_SENSE
1244 + PrintRequestSense(RequestSense);
1246 FreeElementData(ElementStatus);
1249 @@ -1223,34 +1224,24 @@
1250 * is obviously defective:
1253 - invalid_sources=0; /* no invalid sources yet! */
1254 for (i=0;i<ElementStatus->DataTransferElementCount;i++) {
1256 - int translated_elnum = -1;
1257 /* if we have an element, then ... */
1258 if (ElementStatus->DataTransferElementFull[i]) {
1259 elnum=ElementStatus->DataTransferElementSourceStorageElementNumber[i];
1260 /* if we have an element number, then ... */
1262 - /* Now to translate the elnum: */
1263 - for (j=0; j<ElementStatus->StorageElementCount; j++) {
1264 - if (elnum == ElementStatus->StorageElementAddress[j]) {
1265 - translated_elnum=j;
1268 - /* now see if the element # is already occupied: */
1269 - if (ElementStatus->StorageElementFull[translated_elnum]) {
1270 - invalid_sources=1;
1271 - break; /* break out of the loop! */
1273 - /* properly set the source... */
1274 - ElementStatus->DataTransferElementSourceStorageElementNumber[i]=
1279 - /* if element # was not >=0, then we had an invalid source anyhow! */
1280 - invalid_sources=1;
1281 + /* Now to translate the elnum: */
1282 + ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
1283 + for (j=0; j<ElementStatus->StorageElementCount; j++) {
1284 + if (elnum == ElementStatus->StorageElementAddress[j]) {
1285 + /* now see if the element # is already occupied:*/
1286 + if (!ElementStatus->StorageElementFull[j]) {
1287 + /* properly set the source... */
1288 + ElementStatus->DataTransferElementSourceStorageElementNumber[i]= j;
1295 @@ -1267,21 +1258,19 @@
1296 * by the user interface. This is an invalid value, but more useful for us
1297 * to have than just crapping out here :-(.
1299 - if (invalid_sources) {
1301 - for (i=0;i<ElementStatus->DataTransferElementCount;i++) {
1302 - if (ElementStatus->DataTransferElementFull[i]) {
1304 + for (i = 0; i < ElementStatus->DataTransferElementCount; i++) {
1305 + if (ElementStatus->DataTransferElementFull[i] &&
1306 + ElementStatus->DataTransferElementSourceStorageElementNumber[i] < 0) {
1307 #ifdef DEBUG_TAPELIST
1308 - fprintf(stderr,"for drive %d, changing source %d to %d (empty slot #%d)\n",
1310 - ElementStatus->DataTransferElementSourceStorageElementNumber[i],
1311 - EmptyStorageElementAddress[empty_idx],
1313 + fprintf(stderr,"for drive %d, changing to %d (empty slot #%d)\n",
1315 + EmptyStorageElementAddress[empty_idx],
1319 ElementStatus->DataTransferElementSourceStorageElementNumber[i]=
1320 EmptyStorageElementAddress[empty_idx++];
1325 @@ -1337,9 +1326,9 @@
1326 CDB[2] = (ElementStatus->TransportElementAddress >> 8) & 0xFF; /* Transport Element Address MSB */
1327 CDB[3] = (ElementStatus->TransportElementAddress) & 0xff; /* Transport Element Address LSB */
1328 CDB[4] = (SourceAddress >> 8) & 0xFF; /* Source Address MSB */
1329 - CDB[5] = SourceAddress & 0xFF; /* Source Address MSB */
1330 + CDB[5] = SourceAddress & 0xFF; /* Source Address LSB */
1331 CDB[6] = (DestinationAddress >> 8) & 0xFF; /* Destination Address MSB */
1332 - CDB[7] = DestinationAddress & 0xFF; /* Destination Address MSB */
1333 + CDB[7] = DestinationAddress & 0xFF; /* Destination Address LSB */
1334 CDB[8] = 0; /* Reserved */
1335 CDB[9] = 0; /* Reserved */
1336 if (flags->invert) {
1337 @@ -1351,7 +1340,11 @@
1338 CDB[11] = 0 | (flags->eepos <<6); /* Control */
1340 if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12,
1341 - NULL, 0, RequestSense) != 0) {
1342 + NULL, 0, RequestSense) != 0) {
1345 + fprintf(stderr, "Move Medium (0x%02X) failed\n", CDB[0]);
1347 return RequestSense;
1350 @@ -1372,9 +1365,9 @@
1351 CDB[2] = (ElementStatus->TransportElementAddress >> 8) & 0xFF; /* Transport Element Address MSB */
1352 CDB[3] = (ElementStatus->TransportElementAddress) & 0xff; /* Transport Element Address LSB */
1353 CDB[4] = (SourceAddress >> 8) & 0xFF; /* Source Address MSB */
1354 - CDB[5] = SourceAddress & 0xFF; /* Source Address MSB */
1355 + CDB[5] = SourceAddress & 0xFF; /* Source Address LSB */
1356 CDB[6] = (DestinationAddress >> 8) & 0xFF; /* Destination Address MSB */
1357 - CDB[7] = DestinationAddress & 0xFF; /* Destination Address MSB */
1358 + CDB[7] = DestinationAddress & 0xFF; /* Destination Address LSB */
1359 CDB[8] = (Dest2Address>>8) & 0xFF; /* move destination back to source? */
1360 CDB[9] = Dest2Address & 0xFF; /* move destination back to source? */
1362 @@ -1418,12 +1411,53 @@
1364 if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 6,
1365 NULL, 0, RequestSense) != 0) {
1367 + fprintf(stderr, "Erase (0x19) failed\n");
1369 return RequestSense;
1372 return NULL; /* Success! */
1375 +static char Spaces[] = " ";
1377 +void PrintHex(int Indent, unsigned char *Buffer, int Length)
1384 + for (idxBuffer = 0; idxBuffer < Length; idxBuffer++) {
1385 + if ((idxBuffer % 16) == 0) {
1386 + if (idxBuffer > 0) {
1387 + fputc('\'', stderr);
1389 + for (idxAscii = idxBuffer - 16; idxAscii < idxBuffer; idxAscii++) {
1390 + cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x7F ? Buffer[idxAscii] : '.';
1391 + fputc(cAscii, stderr);
1393 + fputs("'\n", stderr);
1395 + fprintf(stderr, "%.*s%04X: ", Indent, Spaces, idxBuffer);
1397 + fprintf(stderr, "%02X ", (unsigned char)Buffer[idxBuffer]);
1400 + PadLength = 16 - (Length % 16);
1402 + if (PadLength > 0) {
1403 + fprintf(stderr, "%.*s'", 3 * PadLength, Spaces);
1405 + for (idxAscii = idxBuffer - (16 - PadLength); idxAscii < idxBuffer; idxAscii++) {
1406 + cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x80 ? Buffer[idxAscii] : '.';
1407 + fputc(cAscii, stderr);
1409 + fputs("'\n", stderr);
1414 #ifdef LONG_PRINT_REQUEST_SENSE
1416 @@ -1488,12 +1522,9 @@
1418 void PrintRequestSense(RequestSense_T *RequestSense)
1421 - fprintf(stderr, "mtx: Request Sense: %02X",
1422 - ((unsigned char *) RequestSense)[0]);
1423 - for (i = 1; i < sizeof(RequestSense_T); i++)
1424 - fprintf(stderr, " %02X", ((unsigned char *) RequestSense)[i]);
1425 - fprintf(stderr, "\n");
1426 + fprintf(stderr, "mtx: Request Sense: %02X\n",
1427 + ((unsigned char *) RequestSense)[0]);
1428 + PrintHex(2, (char *)RequestSense, sizeof(RequestSense_T));
1433 ===================================================================
1434 --- ../release/mtx-1.3.9/Makefile.in 2006-02-20 13:42:10.000000000 -0800
1435 +++ Makefile 2006-07-30 01:22:00.000000000 -0700
1437 # Version # for 'make dist'...
1440 -BINS = mtx tapeinfo loaderinfo scsitape nsmhack
1441 +BINS = mtx.exe tapeinfo.exe loaderinfo.exe scsitape.exe nsmhack.exe
1442 +DBGS := $(BINS:%.exe=%.dbg)
1447 -INSTALL = @INSTALL@
1450 -CPPFLAGS = @CPPFLAGS@ -DVERSION="\"$(VERSION)\""
1451 -LDFLAGS = @LDFLAGS@
1456 +INSTALL = install -c
1459 +CPPFLAGS = -DVERSION="\"$(VERSION)\""
1464 INSTALL_DOC = $(INSTALL) -m 644
1465 INSTALL_BIN = $(INSTALL) -m 755
1466 INSTALL_DIR = $(INSTALL) -m 755 -d
1469 -exec_prefix = @exec_prefix@
1470 -sbindir = @sbindir@
1473 +exec_prefix = ${prefix}
1474 +sbindir = ${exec_prefix}/bin
1475 +mandir = ${prefix}/man
1480 CPPFLAGS += -I/usr/src/linux/include -DLONG_PRINT_REQUEST_SENSE=1
1483 +ifeq ($(TARGET),mingw)
1485 +CPPFLAGS += -DLONG_PRINT_REQUEST_SENSE=1
1492 See vms/000readme for information.
1496 +ifeq ($(USE_OBJCOPY),yes)
1497 + mingw32-objcopy --only-keep-debug $< $@
1498 + mingw32-objcopy --strip-debug $<
1499 + mingw32-objcopy --add-gnu-debuglink=$@ $<
1509 +install: $(BINS) $(DBGS)
1510 $(INSTALL_DIR) $(sbindir)
1511 for file in $(BINS); do \
1512 - strip "$$file" ; \
1513 $(INSTALL_BIN) "$$file" $(sbindir) ; \
1515 $(INSTALL_DIR) $(mandir) $(mandir)/man1
1520 - rm -f mam2debug mam2debug2
1522 + rm -f mam2debug.exe mam2debug2.exe
1523 + rm -rf autom4te.cache
1526 rm -f Makefile config.log config.cache config.status
1527 @@ -106,27 +125,26 @@
1529 ./makedist $(VERSION)
1531 -loaderinfo: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
1532 - $(CC) $(LDFLAGS) -o loaderinfo loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
1534 +loaderinfo.exe: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
1535 + $(CC) $(LDFLAGS) -o $@ loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
1537 -nsmhack: nsmhack.o mtxl.o $(EXTRA)
1538 - $(CC) $(LDFLAGS) -o nsmhack nsmhack.o mtxl.o $(EXTRA) $(LIBS)
1539 +nsmhack.exe: nsmhack.o mtxl.o $(EXTRA)
1540 + $(CC) $(LDFLAGS) -o $@ nsmhack.o mtxl.o $(EXTRA) $(LIBS)
1542 -mtx: mtx.o mtxl.o mtxl.h mtx.h $(EXTRA)
1543 - $(CC) $(LDFLAGS) -o mtx mtx.o mtxl.o $(EXTRA) $(LIBS)
1544 +mtx.exe: mtx.o mtxl.o mtxl.h mtx.h $(EXTRA)
1545 + $(CC) $(LDFLAGS) -o $@ mtx.o mtxl.o $(EXTRA) $(LIBS)
1547 -mam2debug: mtxl.o mam2debug.o mtx.h $(EXTRA)
1548 - $(CC) $(LDFLAGS) -o mam2debug mtxl.o mam2debug.o $(EXTRA) $(LIBS)
1549 +mam2debug.exe: mtxl.o mam2debug.o mtx.h $(EXTRA)
1550 + $(CC) $(LDFLAGS) -o $@ mtxl.o mam2debug.o $(EXTRA) $(LIBS)
1552 -tapeinfo: tapeinfo.o mtxl.o mtx.h mtxl.h $(EXTRA)
1553 - $(CC) $(LDFLAGS) -o tapeinfo tapeinfo.o mtxl.o $(EXTRA) $(LIBS)
1554 +tapeinfo.exe: tapeinfo.o mtxl.o mtx.h mtxl.h $(EXTRA)
1555 + $(CC) $(LDFLAGS) -o $@ tapeinfo.o mtxl.o $(EXTRA) $(LIBS)
1557 -mam2debug2: mtxl.o mam2debug2.o mtx.h $(EXTRA)
1558 - $(CC) $(LDFLAGS) -o mam2debug2 mtxl.o mam2debug2.o $(EXTRA) $(LIBS)
1559 +mam2debug2.exe: mtxl.o mam2debug2.o mtx.h $(EXTRA)
1560 + $(CC) $(LDFLAGS) -o $@ mtxl.o mam2debug2.o $(EXTRA) $(LIBS)
1562 -scsitape: scsitape.o mtxl.o mtxl.h mtx.h $(EXTRA)
1563 - $(CC) $(LDFLAGS) -o scsitape scsitape.o mtxl.o $(EXTRA) $(LIBS)
1564 +scsitape.exe: scsitape.o mtxl.o mtxl.h mtx.h $(EXTRA)
1565 + $(CC) $(LDFLAGS) -o $@ scsitape.o mtxl.o $(EXTRA) $(LIBS)
1567 scsitape.o: scsitape.c mtx.h mtxl.h
1571 mtx.o: mtx.c mtx.h mtxl.h
1573 -mtxl.o: mtxl.c mtx.h mtxl.h scsi_linux.c
1574 +mtxl.o: mtxl.c mtx.h mtxl.h scsi_linux.c scsi_win32.c
1576 nsmhack.o: nsmhack.c mtxl.h mtx.h