]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/patches/mtx.patch
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / win32 / patches / mtx.patch
1 Index: README.win32
2 ===================================================================
3 --- /dev/null   Sat Jul 29 14:54:52 2006
4 +++ README.win32        Sat Jul 29 14:46:45 2006
5 @@ -0,0 +1,22 @@
6 +CHANGES FROM UNIX
7 +=================
8 +
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>.
11 +
12 +On Linux the tape drive is referenced using /dev/nst<N>, on Windows you use
13 +Tape<N>.
14 +
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.
18 +
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:
21 +
22 +       <port>:<bus>:<target>:<lun>
23 +       
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
28 Index: scsi_win32.c
29 ===================================================================
30 --- /dev/null   Sat Jul 29 14:55:00 2006
31 +++ scsi_win32.c        Sat Jul 29 14:54:08 2006
32 @@ -0,0 +1,353 @@
33 +/* Copyright 2006 Robert Nelson <robertn@the-nelsons.org>
34 +
35 +$Date: 2006-07-30 06:32:36 -0700 (Sun, 30 Jul 2006) $
36 +$Revision: 3200 $
37 +
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.
41 +
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.
46 +
47 +*/
48 +
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
51 + * behaviour.
52 + */
53 +
54 +#include <stdio.h>
55 +#include <windows.h>
56 +
57 +#ifdef _MSC_VER
58 +#include <ntddscsi.h>
59 +#else
60 +#include <ddk/ntddscsi.h>
61 +#endif
62 +
63 +#ifndef HZ
64 +#define HZ 1000
65 +#endif
66 +
67 +/* These are copied out of BRU 16.1, with all the boolean masks changed
68 + * to our bitmasks.
69 +*/
70 +#define S_NO_SENSE(s) ((s)->SenseKey == 0x0)
71 +#define S_RECOVERED_ERROR(s) ((s)->SenseKey == 0x1)
72 +
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)
79 +
80 +#define DEFAULT_TIMEOUT 3 * 60  /* 3 minutes here */
81 +
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.
85 + */
86 +
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)
92 +
93 +#define STILL_A_VALID_READ(s) (HIT_FILEMARK(s) || SHORT_READ(s) || HIT_EOD(s) || HIT_EOP(s) || HIT_EOM(s))
94 +
95 +#define SCSI_DEFAULT_TIMEOUT  60    /* 1 minute */
96 +#define SCSI_MAX_TIMEOUT      108   /* 1 minute 48 seconds */
97 +
98 +typedef        struct  _HANDLE_ENTRY {
99 +  HANDLE  hDevice;
100 +  UCHAR   PortId;
101 +  UCHAR   PathId;
102 +  UCHAR   TargetId;
103 +  UCHAR   Lun;
104 +} HANDLE_ENTRY, *PHANDLE_ENTRY;
105 +
106 +PHANDLE_ENTRY HandleTable = NULL;
107 +int           nEntries = 0;
108 +
109 +DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
110 +{
111 +  int   DeviceIndex;
112 +  TCHAR szDevicePath[256];
113 +
114 +  int   nColons = 0;
115 +  int   index;
116 +
117 +  int   port, path, target, lun;
118 +
119 +  for (DeviceIndex = 0; DeviceIndex < nEntries; DeviceIndex++)
120 +  {
121 +    if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
122 +      break;
123 +  }
124 +
125 +  if (DeviceIndex >= nEntries)
126 +  {
127 +    PHANDLE_ENTRY pNewTable;
128 +
129 +    nEntries += 4;
130 +
131 +    if (HandleTable == NULL)
132 +    {
133 +      pNewTable = (PHANDLE_ENTRY)malloc(nEntries * sizeof(HANDLE_ENTRY));
134 +    }
135 +    else
136 +    {
137 +      pNewTable = (PHANDLE_ENTRY)realloc(HandleTable, nEntries * sizeof(HANDLE_ENTRY));
138 +    }
139 +
140 +    if (pNewTable == NULL)
141 +    {
142 +      FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
143 +    }
144 +
145 +    HandleTable = pNewTable;
146 +  }
147 +
148 +  for (index = 0; DeviceName[index] != '\0'; index++)
149 +  {
150 +    if (DeviceName[index] == ':')
151 +      nColons++;
152 +    else if (DeviceName[index] < '0' || DeviceName[index] > '9')
153 +      break;
154 +  }
155 +
156 +  if (DeviceName[index] == '\0' && nColons == 3 && 
157 +      sscanf(DeviceName, "%d:%d:%d:%d", &port, &path, &target, &lun) == 4) {
158 +
159 +    HandleTable[DeviceIndex].PortId = (UCHAR)port;
160 +    HandleTable[DeviceIndex].PathId = (UCHAR)path;
161 +    HandleTable[DeviceIndex].TargetId = (UCHAR)target;
162 +    HandleTable[DeviceIndex].Lun = (UCHAR)lun;
163 +
164 +    sprintf(szDevicePath, "\\\\.\\scsi%d:", port);
165 +  }
166 +  else 
167 +  {
168 +    int nPrefixLength = 0;
169 +
170 +    if (DeviceName[0] != '\\') {
171 +      memcpy(szDevicePath, "\\\\.\\", 4 * sizeof(TCHAR));
172 +      nPrefixLength = 4;
173 +    }
174 +
175 +    HandleTable[DeviceIndex].PortId = 0;
176 +    HandleTable[DeviceIndex].PathId = 0;
177 +    HandleTable[DeviceIndex].TargetId = 0;
178 +    HandleTable[DeviceIndex].Lun = 0;
179 +
180 +    strncpy( &szDevicePath[nPrefixLength], 
181 +              DeviceName, 
182 +              sizeof(szDevicePath) / sizeof(TCHAR) - nPrefixLength - 1);
183 +    
184 +    szDevicePath[sizeof(szDevicePath) / sizeof(TCHAR) - 1] = '\0';
185 +  }
186 +
187 +  HandleTable[DeviceIndex].hDevice = CreateFile(szDevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
188 +
189 +  if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
190 +  {
191 +    DWORD dwError = GetLastError();
192 +
193 +#if DEBUG
194 +    LPSTR lpszMessage;
195 +
196 +    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
197 +    fputs(lpszMessage, stderr);
198 +#endif
199 +
200 +    switch (dwError) {
201 +    case ERROR_FILE_NOT_FOUND:
202 +    case ERROR_PATH_NOT_FOUND:
203 +      errno = ENOENT;
204 +      break;
205 +
206 +    case ERROR_TOO_MANY_OPEN_FILES:
207 +      errno =  EMFILE;
208 +      break;
209 +
210 +    default:
211 +    case ERROR_ACCESS_DENIED:
212 +    case ERROR_SHARING_VIOLATION:
213 +    case ERROR_LOCK_VIOLATION:
214 +    case ERROR_INVALID_NAME:
215 +      errno = EACCES;
216 +      break;
217 +
218 +    case ERROR_FILE_EXISTS:
219 +      errno = EEXIST;
220 +      break;
221 +
222 +    case ERROR_INVALID_PARAMETER:
223 +      errno = EINVAL;
224 +      break;
225 +    }
226 +
227 +    FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
228 +  }
229 +
230 +  return DeviceIndex;
231 +}
232 +
233 +static int scsi_timeout = SCSI_DEFAULT_TIMEOUT;
234 +
235 +void SCSI_Set_Timeout(int secs)
236 +{
237 +  if (secs > SCSI_MAX_TIMEOUT) {
238 +    secs = SCSI_MAX_TIMEOUT;
239 +  }
240 +  scsi_timeout = secs * HZ;
241 +}
242
243 +void SCSI_Default_Timeout(void)
244 +{
245 +  scsi_timeout = SCSI_DEFAULT_TIMEOUT * HZ;
246 +}
247 +
248 +void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
249 +{
250 +  if (DeviceFD < nEntries)
251 +  {
252 +    CloseHandle(HandleTable[DeviceFD].hDevice);
253 +    HandleTable[DeviceFD].hDevice = INVALID_HANDLE_VALUE;
254 +  }
255 +  else
256 +  {
257 +    errno = EBADF;
258 +    FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
259 +  }
260 +}
261 +
262 +
263 +/* Added by Eric Green <eric@estinc.com> to deal with burping
264 + * Seagate autoloader (hopefully!). 
265 + */
266 +/* Get the SCSI ID and LUN... */
267 +scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd) {
268 +  scsi_id_t *          retval;
269 +
270 +  SCSI_ADDRESS         ScsiAddress;
271 +  BOOL                 bResult;
272 +  DWORD                dwBytesReturned;
273 +
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;
278 +
279 +#ifdef DEBUG
280 +    fprintf(stderr,"SCSI:ID=%d LUN=%d\n", retval->id, retval->lun);
281 +#endif
282 +    return retval;
283 +  } else {
284 +    errno = EBADF;
285 +    FatalError("cannot close SCSI device - %m\n");
286 +  }
287 +
288 +  memset(&ScsiAddress, 0, sizeof(ScsiAddress));
289 +
290 +  ScsiAddress.Length = sizeof(ScsiAddress);
291 +
292 +  bResult = DeviceIoControl(HandleTable[fd].hDevice, 
293 +                            IOCTL_SCSI_GET_ADDRESS, 
294 +                            &ScsiAddress, sizeof(ScsiAddress), 
295 +                            &ScsiAddress, sizeof(ScsiAddress), 
296 +                            &dwBytesReturned, 
297 +                            NULL);
298 +   
299 +  if (!bResult) {
300 +    return NULL;
301 +  }
302 +
303 +  retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
304 +  retval->id = ScsiAddress.TargetId;
305 +  retval->lun = ScsiAddress.Lun;
306 +
307 +#ifdef DEBUG
308 +  fprintf(stderr,"SCSI:ID=%d LUN=%d\n",retval->id,retval->lun);
309 +#endif
310 +  return retval;
311 +}
312 +  
313 +int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
314 +                        Direction_T Direction,
315 +                        CDB_T *CDB,
316 +                        int CDB_Length,
317 +                        void *DataBuffer,
318 +                        int DataBufferLength,
319 +                        RequestSense_T *RequestSense)
320 +{
321 +  PSCSI_PASS_THROUGH_DIRECT ScsiPassThrough;
322 +
323 +  const DWORD dwBufferSize = sizeof(SCSI_PASS_THROUGH_DIRECT) + sizeof(RequestSense_T);
324 +  BOOL        bResult;
325 +  DWORD       dwBytesReturned;
326 +
327 +  if (DeviceFD >= nEntries || HandleTable[DeviceFD].hDevice == INVALID_HANDLE_VALUE)
328 +  {
329 +    errno = EBADF;
330 +    return -1;
331 +  }
332 +
333 +  ScsiPassThrough = (PSCSI_PASS_THROUGH_DIRECT)malloc(dwBufferSize);
334 +
335 +  memset(ScsiPassThrough, 0, dwBufferSize);
336 +
337 +  ScsiPassThrough->Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
338 +
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);
349 +
350 +  memcpy(ScsiPassThrough->Cdb, CDB, CDB_Length);
351 +  dwBytesReturned = 0;
352 +
353 +  bResult = DeviceIoControl(HandleTable[DeviceFD].hDevice, 
354 +                            IOCTL_SCSI_PASS_THROUGH_DIRECT, 
355 +                            ScsiPassThrough, sizeof(SCSI_PASS_THROUGH_DIRECT), 
356 +                            ScsiPassThrough, dwBufferSize, 
357 +                            &dwBytesReturned, 
358 +                            NULL);
359 +  if (bResult) {
360 +    if (ScsiPassThrough->ScsiStatus != 0) {
361 +      memcpy(RequestSense, &ScsiPassThrough[1], sizeof(RequestSense_T));
362 +#if DEBUG
363 +      fprintf(stderr, "Command failed - ScsiStatus = %d\n", ScsiPassThrough->ScsiStatus);
364 +      PrintRequestSense(RequestSense);
365 +#endif
366 +      bResult = false;
367 +    }
368 +  }
369 +  else
370 +  {
371 +#if DEBUG
372 +    DWORD   dwError = GetLastError();
373 +    LPSTR   lpszMessage;
374 +
375 +    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
376 +    fputs(lpszMessage, stderr);
377 +#endif
378 +
379 +    memset(RequestSense, 0, sizeof(RequestSense_T));
380 +  }
381 +
382 +  free(ScsiPassThrough);
383 +
384 +  return bResult ? 0 : -1;
385 +}
386 Index: tapeinfo.c
387 ===================================================================
388 --- tapeinfo.c  (revision 139)
389 +++ tapeinfo.c  (revision 147)
390 @@ -211,25 +211,18 @@
391    unsigned int partition1_size;
392  } TapeCapacity;
393  
394 +#if defined(DEBUG)
395  /* DEBUG */
396  static void dump_data(unsigned char *data, int len) {
397 -  int i;
398    if (!len) {
399      fprintf(stderr,"**NO DATA**\n");
400      return;
401    }
402  
403 -  for (i=0;i<len;i++) {
404 -    if ((i % 10) == 0) {
405 -      if (i) {
406 -       fprintf(stderr,"\n");
407 -      }
408 -      fprintf(stderr,"DATA:");
409 -    }
410 -    fprintf(stderr,"%02x ",(unsigned int)*data++);
411 -  }
412 -  fprintf(stderr,"\n");
413 +  fprintf(stderr,"DATA:");
414 +  PrintHex(1, data, len);
415  }
416 +#endif
417  
418  
419  
420 @@ -243,7 +236,7 @@
421    
422    unsigned char buffer[TAPEALERT_SIZE]; /* Overkill, but ... */
423  
424 -  slow_bzero(buffer,TAPEALERT_SIZE); /*zero it... */
425 +  slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
426  
427    /* now to create the CDB block: */
428    CDB[0]=0x4d;   /* Log Sense */
429 @@ -325,7 +318,7 @@
430    unsigned char buffer[TAPEALERT_SIZE];
431    unsigned char *walkptr;
432  
433 -  slow_bzero(buffer,TAPEALERT_SIZE); /*zero it... */
434 +  slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
435  
436    /* now to create the CDB block: */
437    CDB[0]=0x4d;   /* Log Sense */
438 @@ -676,7 +669,7 @@
439       the sernum field, and bytes 4 onward are the serial #. */
440    
441    lim=(int)buffer[3];
442 -  bufptr= &(buffer[4]);
443 +  bufptr=(char *)&(buffer[4]);
444    
445    printf("SerialNumber: '");
446    for (i=0;i<lim;i++) {
447 @@ -702,7 +695,7 @@
448    CDB[4]=0;
449    CDB[5]=0; 
450  
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){
454      return;
455    }
456 @@ -735,7 +728,7 @@
457    CDB[8]=0;
458    CDB[9]=0;
459  
460 -  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
461 +  slow_bzero((char *)&sense,sizeof(RequestSense_T));
462  
463    /* set the timeout: */
464    SCSI_Set_Timeout(2); /* set timeout to 2 seconds! */
465 @@ -789,7 +782,7 @@
466    CDB[4]=0;
467    CDB[5]=0; 
468  
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");
473      return 0;
474 @@ -817,7 +810,7 @@
475    CDB[5]=0; 
476  
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){
481      return 1;
482    }
483 Index: mtx.c
484 ===================================================================
485 --- mtx.c       (revision 139)
486 +++ mtx.c       (revision 147)
487 @@ -623,7 +623,7 @@
488                "illegal <drive-number> argument '%d' to 'unload' command\n",
489                arg2);
490    }
491 -  if (ElementStatus->DataTransferElementFull[arg2] < 0 ) {
492 +  if (!ElementStatus->DataTransferElementFull[arg2]) {
493      FatalError("Data Transfer Element %d is Empty\n", arg2);
494    }    
495    /* Now see if something already lives where  we wanna go... */
496 @@ -715,7 +715,7 @@
497      }
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"); 
503      }
504    }
505 @@ -813,9 +813,6 @@
506  
507    argv0=argv[0];
508  
509 -   
510 -
511 -
512    parse_args();  /* also executes them as it sees them, sigh. */
513  
514  #ifndef VMS
515 Index: scsitape.c
516 ===================================================================
517 --- scsitape.c  (revision 139)
518 +++ scsitape.c  (revision 147)
519 @@ -41,11 +41,26 @@
520  #include "mtx.h"
521  #include "mtxl.h"
522  
523 +#if HAVE_UNISTD_H
524  #include <unistd.h>
525 +#endif
526 +
527 +#if HAVE_SYS_TYPES_H
528  #include <sys/types.h>
529 +#endif
530 +
531 +#if HAVE_SYS_IOCTL_H
532  #include <sys/ioctl.h>
533 +#endif
534 +
535 +#if HAVE_SYS_MTIO_H
536  #include <sys/mtio.h> /* will try issuing some ioctls for Solaris, sigh. */
537 +#endif
538  
539 +#ifdef _MSC_VER
540 +#include <io.h>
541 +#endif
542 +
543  void Usage(void) {
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");
545  }
546 @@ -54,7 +69,7 @@
547  static int arg[4];  /* the argument for the command, sigh. */
548  
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;
553  
554  
555 @@ -96,43 +111,7 @@
556  
557  char *argv0;
558  
559 -/* A table for printing out the peripheral device type as ASCII. */ 
560 -static char *PeripheralDeviceType[32] = {
561 -  "Disk Drive",
562 -  "Tape Drive",
563 -  "Printer",
564 -  "Processor",
565 -  "Write-once",
566 -  "CD-ROM",
567 -  "Scanner",
568 -  "Optical",
569 -  "Medium Changer",
570 -  "Communications",
571 -  "ASC IT8",
572 -  "ASC IT8",
573 -  "RAID Array",
574 -  "Enclosure Services",
575 -  "OCR/W",
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 */
592 -};
593  
594 -
595 -
596  /* open_device() -- set the 'fh' variable.... */
597  void open_device(void) {
598  
599 @@ -301,7 +280,7 @@
600    CDB[5]=0; 
601  
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);
607      return 1;
608 @@ -324,7 +303,7 @@
609    CDB[5]=0; 
610  
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);
616      return 1;
617 @@ -349,7 +328,7 @@
618    CDB[5]=0; 
619  
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);
625      return 1;
626 @@ -392,7 +371,7 @@
627    CDB[5]=0; 
628  
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);
634      return 1;
635 @@ -422,7 +401,7 @@
636    CDB[9]=0; 
637  
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);
643      return 1;
644 @@ -462,7 +441,7 @@
645  static int S_setblk(void) {
646    RequestSense_T sense;
647    CDB_T CDB;
648 -  unsigned char buffer[12];
649 +  char buffer[12];
650    unsigned int count = (unsigned int) arg1;
651  
652    
653 @@ -473,7 +452,7 @@
654    CDB[4]=12; /* length of data */
655    CDB[5]=0;
656  
657 -  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
658 +  slow_bzero((char *)&sense,sizeof(RequestSense_T));
659    slow_bzero(buffer,12);
660  
661    /* Now to set the mode page header: */
662 @@ -679,9 +658,9 @@
663  
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. */
668    int buffersize;
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 */
674 @@ -755,9 +734,9 @@
675  
676  
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 */
680    int buffersize;
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. */
686 Index: mtx.h
687 ===================================================================
688 --- mtx.h       (revision 139)
689 +++ mtx.h       (working copy)
690 @@ -18,7 +18,11 @@
691  #include "[.vms]defs.h"
692  #else /* all the Unix stuff:  */
693  
694 +#ifdef _MSC_VER
695 +#include "msvc/config.h"  /* all the autoconf stuff. */
696 +#else
697  #include "config.h"  /* all the autoconf stuff. */
698 +#endif
699  
700  /* all the general Unix includes: */
701  
702 @@ -59,7 +63,7 @@
703  #  include <sys/ioctl.h>
704  #endif
705  
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: */
709  #if HAVE_SCSI_SG_H
710  #  include <scsi/scsi.h>
711 @@ -69,6 +73,27 @@
712  #  define HAVE_GET_ID_LUN 1  /* signal that we have it... */
713  #endif
714  
715 +/* Windows Native programs built using MinGW */
716 +#if HAVE_DDK_NTDDSCSI_H
717 +#  include <windows.h>
718 +#  include <ddk/ntddscsi.h>
719 +#  undef DEVICE_TYPE
720 +
721 +typedef int DEVICE_TYPE;
722 +#  define HAVE_GET_ID_LUN 1  /* signal that we have it... */
723 +#endif
724 +
725 +/* Windows Native programs built using Microsoft Visual C */
726 +#ifdef _MSC_VER
727 +#  include <windows.h>
728 +#  include <winioctl.h>
729 +#  include <ntddscsi.h>
730 +#  undef DEVICE_TYPE
731 +
732 +typedef int DEVICE_TYPE;
733 +#  define HAVE_GET_ID_LUN 1  /* signal that we have it... */
734 +#endif
735 +
736  /* The 'cam' interface, like FreeBSD: */
737  #if HAVE_CAMLIB_H
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. */
741  } SCSI_Flags_T;
742  
743 +#ifdef _MSC_VER
744 +typedef unsigned char boolean;
745 +
746 +#define false   0
747 +#define true    1
748 +
749 +
750 +typedef unsigned char Direction_T;
751 +
752 +#define Input   0
753 +#define Output  1
754 +#else
755  typedef enum { false, true } boolean;
756  
757  
758  typedef enum { Input, Output } Direction_T;
759 +#endif
760  
761  
762  typedef unsigned char CDB_T[12];
763 @@ -354,6 +392,15 @@
764  } ElementModeSense_T;
765  
766  
767 +#ifdef _MSC_VER
768 +typedef char ElementTypeCode_T;
769 +
770 +#define AllElementTypes                0
771 +#define MediumTransportElement  1
772 +#define StorageElement         2
773 +#define ImportExportElement     3
774 +#define DataTransferElement     4
775 +#else
776  typedef enum ElementTypeCode
777  {
778    AllElementTypes =            0,
779 @@ -363,6 +410,7 @@
780    DataTransferElement =                4
781  }
782  ElementTypeCode_T;
783 +#endif
784  
785  
786  typedef struct ElementStatusDataHeader
787 Index: nsmhack.c
788 ===================================================================
789 --- nsmhack.c   (revision 139)
790 +++ nsmhack.c   (revision 147)
791 @@ -33,13 +33,13 @@
792  
793  #include "mtxl.h"  /* get the SCSI routines out of the main file */
794  
795 -/*****************************************************************
796 +/****************************************************************/
797  /* Variables:  */
798  /****************************************************************/   
799  
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;
805  char *argv0;
806  int arg[4]; /* arguments for the command. */
807  #define arg1 (arg[0])  /* for backward compatibility, sigh */
808 @@ -74,7 +74,7 @@
809  /* open_device() -- set the 'fh' variable.... */
810  void open_device(void) {
811  
812 -  if (MediumChangerFD) {
813 +  if (MediumChangerFD != -1) {
814      SCSI_CloseDevice("Unknown",MediumChangerFD);  /* close it, sigh...  new device now! */
815    }
816  
817 @@ -101,7 +101,7 @@
818    /* if the device is not already open, then open it from the 
819     * environment.
820     */
821 -  if (!MediumChangerFD) {
822 +  if (MediumChangerFD == -1) {
823      /* try to get it from STAPE or TAPE environment variable... */
824      device=getenv("STAPE");
825      if (device==NULL) {
826 @@ -302,7 +302,7 @@
827  }
828  
829  static int S_tongue_in(void) {
830 -
831 +  return 0;
832  }
833  
834  /* okay, stick our tongue out. We need a slot ID to grab a caddy from. */
835 @@ -326,6 +326,7 @@
836    }
837    
838    /* Okay, we have element status, so now let's assume that */
839 +  return 0;
840  }
841  
842  /* See parse_args for the scoop. parse_args does all. */
843 Index: mtxl.h
844 ===================================================================
845 --- mtxl.h      (revision 139)
846 +++ mtxl.h      (revision 147)
847 @@ -27,6 +27,9 @@
848  
849  #include "mtx.h"
850  
851 +#undef min
852 +#undef max
853 +
854  void FatalError(char *ErrorMessage, ...);
855  void *xmalloc(size_t Size);
856  void *xzmalloc(size_t Size);
857 Index: config.h
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
861 @@ -1,3 +1,4 @@
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
866 @@ -10,10 +11,10 @@
867  #define CONFIG_H 1
868  
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
881 @@ -23,10 +24,12 @@
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
894  
895  #define WORDS_BIGENDIAN 0
896  
897 Index: mtxl.c
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
901 @@ -53,6 +53,11 @@
902  #  include "scsi_linux.c"
903  #endif
904  
905 +/* the IOCTL_SCSI_PASSTHROUGH interface is used on Windows. */
906 +#if HAVE_DDK_NTDDSCSI_H || defined(_MSC_VER)
907 +#  include "scsi_win32.c"
908 +#endif
909 +
910  /* The 'uscsi' interface is used on Solaris. */
911  #if HAVE_SYS_SCSI_IMPL_USCSI_H
912  #  include "scsi_sun.c"
913 @@ -78,6 +83,7 @@
914  #include "[.vms]scsi.c"
915  #endif
916  
917 +void PrintHex(int Indent, unsigned char *Buffer, int Length);
918  extern char *argv0; /* something to let us do good error messages. */
919  
920  /* create a global RequestSenseT value. */
921 @@ -104,6 +110,9 @@
922    if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,
923                           Inquiry, sizeof(Inquiry_T), RequestSense) != 0)
924      {
925 +#ifdef DEBUG
926 +      fprintf(stderr, "SCSI Inquiry Command failed\n");
927 +#endif
928        free(Inquiry);
929        return NULL;  /* sorry! */
930      }
931 @@ -111,36 +120,27 @@
932  }
933  
934  
935 +#if defined(DEBUG_NSM) || defined(DEBUG_EXCHANGE)
936  /* DEBUG */
937  static void dump_cdb(unsigned char *CDB, int len) {
938 -  int i;
939    fprintf(stderr,"CDB:");
940 -  for (i=0;i<len;i++) {
941 -    fprintf(stderr,"%02x ",CDB[i]);
942 -  }
943 -  fprintf(stderr,"\n");
944 +  PrintHex(1, CDB, len);
945  }
946 +#endif
947  
948  
949 +#if defined(DEBUG_NSM) || defined(DEBUG_ADIC)
950  /* DEBUG */
951  static void dump_data(unsigned char *data, int len) {
952 -  int i;
953    if (!len) {
954      fprintf(stderr,"**NO DATA**\n");
955      return;
956    }
957  
958 -  for (i=0;i<len;i++) {
959 -    if ((i % 10) == 0) {
960 -      if (i) {
961 -       fprintf(stderr,"\n");
962 -      }
963 -      fprintf(stderr,"DATA:");
964 -    }
965 -    fprintf(stderr,"%02x ",(unsigned int)*data++);
966 -  }
967 -  fprintf(stderr,"\n");
968 +  fprintf(stderr,"DATA:");
969 +  PrintHex(1, data, len);
970  }
971 +#endif
972  
973  
974  int BigEndian16(unsigned char *BigEndianData)
975 @@ -255,7 +255,7 @@
976  
977  
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. 
981   */
982  
983  int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command, 
984 @@ -346,6 +346,10 @@
985    SCSI_Set_Timeout(30*60); /* 30 minutes, sigh! */
986    
987    if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,NULL,0,&scsi_error_sense) != 0) {
988 +#ifdef DEBUG
989 +    PrintRequestSense(&scsi_error_sense);
990 +    fprintf(stderr, "Initialize Element Status (0x07) failed\n");
991 +#endif
992      return -1;  /* could not do! */
993    }
994    return 0; /* did do! */
995 @@ -364,6 +368,10 @@
996    CDB[1]=CDB[2]=CDB[3]=CDB[4]=CDB[5]=0;
997    
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");
1002 +#endif
1003      return -1;  /* could not do! */
1004    }
1005    return 0; /* did do! */
1006 @@ -396,7 +404,8 @@
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");
1013      fflush(stderr);
1014  #endif
1015      return NULL; /* sorry, couldn't do it. */
1016 @@ -405,18 +414,7 @@
1017    /* Could do it, now build return value: */
1018  
1019  #ifdef DEBUG_MODE_SENSE
1020 -  {
1021 -    int i;
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]);
1028 -       */
1029 -    }
1030 -    fflush(stderr);
1031 -  }
1032 +  PrintHex(0, input_buffer, 30);
1033  #endif
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 @@
1037  
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);
1049    fflush(stderr);
1050  #endif
1051  
1052 @@ -620,19 +618,16 @@
1053    CDB[11] = 0;                 /* Control */
1054  
1055  #ifdef DEBUG_BARCODE
1056 -  {
1057 -    int i;
1058 -    fprintf(stderr,"CDB= ");
1059 -    for (i=0;i<12;i++) {
1060 -      fprintf(stderr,"%x ",CDB[i]);
1061 -    }
1062 -    fprintf(stderr,"\n");
1063 -    fflush(stderr);
1064 -  }
1065 +  fprintf(stderr,"CDB:\n");
1066 +  PrintHex(2, CDB, 12);
1067  #endif
1068  
1069    if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,
1070                           DataBuffer,NumBytes, RequestSense) != 0){
1071 +
1072 +#ifdef DEBUG
1073 +    fprintf(stderr, "Read Element Status (0x%02X) failed\n", CDB[0]);
1074 +#endif
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! */
1080  
1081  #ifdef DEBUG_BARCODE
1082 -      {
1083 -       int i;
1084 -       fprintf(stderr,"CDB= ");
1085 -       for (i=0;i<12;i++) {
1086 -         fprintf(stderr,"%x ",CDB[i]);
1087 -       }
1088 -       fprintf(stderr,"\n");
1089 -       fflush(stderr);
1090 -      }
1091 +      fprintf(stderr,"CDB:\n");
1092 +      PrintHex(2, CDB, 12);
1093  #endif
1094        
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 :-(. */
1100 -  {
1101 -    int i;
1102 -    fprintf(stderr,"Data:");
1103 -    for (i=0;i<40;i++) {
1104 -      fprintf(stderr,"%02x ",DataBuffer[i]);
1105 -    }
1106 -    fprintf(stderr,"\n");
1107 -  }
1108 +  fprintf(stderr,"Data:\n");
1109 +  PrintHex(2, DataBuffer, 40);
1110  #endif  
1111    return DataBuffer; /* we succeeded! */
1112  }
1113 @@ -703,7 +685,7 @@
1114                                         ) {
1115  
1116    unsigned char *DataBuffer; /* size of data... */
1117 -  unsigned int real_numbytes;
1118 +  int real_numbytes;
1119  
1120    
1121    DataBuffer=SendElementStatusRequestActual(MediumChangerFD,
1122 @@ -950,34 +932,42 @@
1123                 BigEndian16(TransportElementDescriptor
1124                             ->SourceStorageElementAddress);
1125  
1126 -             if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer) {
1127 -               FatalError("Too many Data Transfer Elements Reported\n");
1128 -             }
1129 -             if (ElementStatusPage->VolBits & E2_PVOLTAG) {
1130 -               copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
1131 -                            ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);
1132 -             } else {
1133 -               ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1134 -             }
1135 -             if (ElementStatusPage->VolBits & E2_AVOLTAG) {
1136 -               copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
1137 -                            ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);
1138 -             } else {
1139 -               ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1140 -             }
1141 -             ElementStatus->DataTransferElementCount++;
1142 -             /* 0 actually is a usable element address */
1143 -             /* if (DataTransferElementAddress == 0) */
1144 -             /*        FatalError( */
1145 -             /*  "illegal Data Transfer Element Address %d reported\n", */
1146 -             /* DataTransferElementAddress); */
1147 -             break;
1148 -           default:
1149 -             FatalError("illegal Element Type Code %d reported\n",
1150 -                        ElementStatusPage->ElementTypeCode);
1151 -           }
1152 -       }
1153 +#if DEBUG
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]);
1159 +#endif
1160 +        if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer) {
1161 +          FatalError("Too many Data Transfer Elements Reported\n");
1162 +        }
1163 +        if (ElementStatusPage->VolBits & E2_PVOLTAG) {
1164 +          copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
1165 +                       ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);
1166 +        } else {
1167 +          ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1168 +        }
1169 +        if (ElementStatusPage->VolBits & E2_AVOLTAG) {
1170 +          copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
1171 +                       ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);
1172 +        } else {
1173 +          ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
1174 +        }
1175 +        ElementStatus->DataTransferElementCount++;
1176 +
1177 +        /* 0 actually is a usable element address */
1178 +        /* if (DataTransferElementAddress == 0) */
1179 +        /*     FatalError( */
1180 +        /*  "illegal Data Transfer Element Address %d reported\n", */
1181 +        /* DataTransferElementAddress); */
1182 +        break;
1183 +      default:
1184 +        FatalError("illegal Element Type Code %d reported\n",
1185 +          ElementStatusPage->ElementTypeCode);
1186 +      }
1187      }
1188 +  }
1189  }
1190  
1191  /********************* Real ReadElementStatus ********************* */
1192 @@ -1008,7 +998,6 @@
1193    int *EmptyStorageElementAddress; /* [MAX_STORAGE_ELEMENTS]; */
1194    
1195    int empty_idx=0;
1196 -  int invalid_sources=0;
1197    boolean is_attached = false;
1198    int i,j;
1199    
1200 @@ -1049,7 +1038,7 @@
1201    
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;
1206    }
1207    
1208    /* Okay, now to send some requests for the various types of stuff: */
1209 @@ -1076,6 +1065,9 @@
1210  #endif
1211      /* darn. Free up stuff and return. */
1212      /****FIXME**** do a free on element data! */
1213 +#ifdef DEBUG_MODE_SENSE
1214 +      PrintRequestSense(RequestSense);
1215 +#endif
1216      FreeElementData(ElementStatus);
1217      return NULL; 
1218    } 
1219 @@ -1107,6 +1099,9 @@
1220  #endif
1221        /* darn. Free up stuff and return. */
1222        /****FIXME**** do a free on element data! */
1223 +#ifdef DEBUG_MODE_SENSE
1224 +      PrintRequestSense(RequestSense);
1225 +#endif
1226        FreeElementData(ElementStatus);
1227        return NULL; 
1228      } 
1229 @@ -1138,6 +1133,9 @@
1230  #endif
1231      /* darn. Free up stuff and return. */
1232      /****FIXME**** do a free on element data! */
1233 +#ifdef DEBUG_MODE_SENSE
1234 +    PrintRequestSense(RequestSense);
1235 +#endif
1236      FreeElementData(ElementStatus);
1237      return NULL; 
1238    } 
1239 @@ -1172,6 +1170,9 @@
1240  #endif
1241         /* darn. Free up stuff and return. */
1242         /****FIXME**** do a free on element data! */
1243 +#ifdef DEBUG_MODE_SENSE
1244 +      PrintRequestSense(RequestSense);
1245 +#endif
1246         FreeElementData(ElementStatus);
1247         return NULL; 
1248       } 
1249 @@ -1223,34 +1224,24 @@
1250     * is obviously defective: 
1251     */
1252    /* pass one: */
1253 -  invalid_sources=0; /* no invalid sources yet! */
1254    for (i=0;i<ElementStatus->DataTransferElementCount;i++) {
1255      int elnum;
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 ... */
1261        if (elnum >= 0) {
1262 -         /* Now to translate the elnum: */
1263 -        for (j=0; j<ElementStatus->StorageElementCount; j++) {
1264 -            if (elnum == ElementStatus->StorageElementAddress[j]) {
1265 -                translated_elnum=j; 
1266 -            }
1267 -        }
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! */
1272 -       } else {
1273 -          /* properly set the source... */
1274 -       ElementStatus->DataTransferElementSourceStorageElementNumber[i]=
1275 -               translated_elnum;
1276 -       }
1277 -                
1278 -      } else {
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;
1289 +            }
1290 +          }
1291 +        }
1292        }
1293      }
1294    }
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 :-(. 
1298     */ 
1299 -  if (invalid_sources) {
1300 -    empty_idx=0;
1301 -    for (i=0;i<ElementStatus->DataTransferElementCount;i++) {
1302 -      if (ElementStatus->DataTransferElementFull[i]) {
1303 +  empty_idx=0;
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",
1309 -            i,
1310 -            ElementStatus->DataTransferElementSourceStorageElementNumber[i],
1311 -             EmptyStorageElementAddress[empty_idx],
1312 -             empty_idx);
1313 +      fprintf(stderr,"for drive %d, changing to %d (empty slot #%d)\n",
1314 +              i,
1315 +              EmptyStorageElementAddress[empty_idx],
1316 +              empty_idx);
1317  #endif
1318                
1319         ElementStatus->DataTransferElementSourceStorageElementNumber[i]=
1320           EmptyStorageElementAddress[empty_idx++];
1321 -      }
1322      }
1323    }
1324  
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 */
1339    
1340    if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12,
1341 -                         NULL, 0, RequestSense) != 0) {
1342 +                          NULL, 0, RequestSense) != 0) {
1343 +
1344 +#ifdef DEBUG
1345 +    fprintf(stderr, "Move Medium (0x%02X) failed\n", CDB[0]);
1346 +#endif
1347      return RequestSense;
1348    }
1349    free(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? */
1361    CDB[10]=0;
1362 @@ -1418,12 +1411,53 @@
1363  
1364    if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 6,
1365                           NULL, 0, RequestSense) != 0) {
1366 +#ifdef DEBUG
1367 +    fprintf(stderr, "Erase (0x19) failed\n");
1368 +#endif
1369      return RequestSense;
1370    }
1371    free(RequestSense);
1372    return NULL;  /* Success! */
1373  }  
1374  
1375 +static char Spaces[] = "                                                            ";
1376 +
1377 +void PrintHex(int Indent, unsigned char *Buffer, int Length)
1378 +{
1379 +  int  idxBuffer;
1380 +  int  idxAscii;
1381 +  int  PadLength;
1382 +  char cAscii;
1383 +
1384 +  for (idxBuffer = 0; idxBuffer < Length; idxBuffer++) {
1385 +    if ((idxBuffer % 16) == 0) {
1386 +      if (idxBuffer > 0) {
1387 +        fputc('\'', stderr);
1388 +
1389 +        for (idxAscii = idxBuffer - 16; idxAscii < idxBuffer; idxAscii++) {
1390 +          cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x7F ? Buffer[idxAscii] : '.';
1391 +          fputc(cAscii, stderr);
1392 +        }
1393 +        fputs("'\n", stderr);
1394 +      }
1395 +      fprintf(stderr, "%.*s%04X: ", Indent, Spaces, idxBuffer);
1396 +    }
1397 +    fprintf(stderr, "%02X ", (unsigned char)Buffer[idxBuffer]);
1398 +  }
1399 +
1400 +  PadLength = 16 - (Length % 16);
1401 +
1402 +  if (PadLength > 0) {
1403 +    fprintf(stderr, "%.*s'", 3 * PadLength, Spaces);
1404 +
1405 +    for (idxAscii = idxBuffer - (16 - PadLength); idxAscii < idxBuffer; idxAscii++) {
1406 +      cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x80 ? Buffer[idxAscii] : '.';
1407 +      fputc(cAscii, stderr);
1408 +    }
1409 +    fputs("'\n", stderr);
1410 +  }
1411 +  fflush(stderr);
1412 +}
1413  
1414  #ifdef LONG_PRINT_REQUEST_SENSE
1415  
1416 @@ -1488,12 +1522,9 @@
1417  #else
1418  void PrintRequestSense(RequestSense_T *RequestSense)
1419  {
1420 -  int i;
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));
1429  }
1430  
1431  #endif
1432 Index: Makefile
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
1436 @@ -11,26 +11,28 @@
1437  # Version # for 'make dist'...
1438  VERSION=1.3.9
1439  
1440 -BINS = mtx tapeinfo loaderinfo scsitape nsmhack
1441 +BINS = mtx.exe tapeinfo.exe loaderinfo.exe scsitape.exe nsmhack.exe
1442 +DBGS := $(BINS:%.exe=%.dbg)
1443  
1444 -TARGET = @TARGET@
1445 -CPU    = @CPU@
1446 -CC     = @CC@
1447 -INSTALL        = @INSTALL@
1448 -
1449 -CFLAGS         = @CFLAGS@
1450 -CPPFLAGS       = @CPPFLAGS@ -DVERSION="\"$(VERSION)\""
1451 -LDFLAGS                = @LDFLAGS@
1452 -LIBS           = @LIBS@
1453 +TARGET = mingw
1454 +CPU    = 386
1455 +CC     = mingw32-gcc
1456 +INSTALL        = install -c
1457 +
1458 +CFLAGS         = -g -O2
1459 +CPPFLAGS       =  -DVERSION="\"$(VERSION)\""
1460 +LDFLAGS                = 
1461 +LIBS           = 
1462 +USE_OBJCOPY    = yes
1463  
1464  INSTALL_DOC = $(INSTALL) -m 644
1465  INSTALL_BIN = $(INSTALL) -m 755
1466  INSTALL_DIR = $(INSTALL) -m 755 -d
1467  
1468 -prefix         = @prefix@
1469 -exec_prefix    = @exec_prefix@
1470 -sbindir                = @sbindir@
1471 -mandir         = @mandir@
1472 +prefix         = dummy
1473 +exec_prefix    = ${prefix}
1474 +sbindir        = ${exec_prefix}/bin
1475 +mandir         = ${prefix}/man
1476  
1477  #
1478  # Linux on x86...
1479 @@ -40,6 +42,11 @@
1480  CPPFLAGS       += -I/usr/src/linux/include -DLONG_PRINT_REQUEST_SENSE=1
1481  endif
1482  
1483 +ifeq ($(TARGET),mingw)
1484 +CFLAGS += -Wall
1485 +CPPFLAGS       += -DLONG_PRINT_REQUEST_SENSE=1
1486 +endif
1487 +
1488  #
1489  # FreeBSD on x86...
1490  #
1491 @@ -82,12 +89,22 @@
1492  See vms/000readme for information.
1493  endif
1494  
1495 +%.dbg : %.exe
1496 +ifeq ($(USE_OBJCOPY),yes)
1497 +       mingw32-objcopy --only-keep-debug $< $@
1498 +       mingw32-objcopy --strip-debug $<
1499 +       mingw32-objcopy --add-gnu-debuglink=$@ $<
1500 +else
1501 +       strip $< -o $@
1502 +endif
1503 +
1504  all:   $(BINS)
1505  
1506 -install: $(BINS)
1507 +dbgs: $(DBGS)
1508 +
1509 +install: $(BINS) $(DBGS)
1510         $(INSTALL_DIR) $(sbindir)
1511         for file in $(BINS); do \
1512 -       strip "$$file" ;        \
1513         $(INSTALL_BIN) "$$file" $(sbindir) ; \
1514         done    
1515         $(INSTALL_DIR) $(mandir) $(mandir)/man1
1516 @@ -98,7 +115,9 @@
1517  clean:
1518         rm -f *.o *~
1519         rm -f $(BINS)
1520 -       rm -f mam2debug mam2debug2
1521 +       rm -f $(DBGS)
1522 +       rm -f mam2debug.exe mam2debug2.exe
1523 +       rm -rf autom4te.cache
1524  
1525  distclean: clean
1526         rm -f Makefile config.log config.cache config.status
1527 @@ -106,27 +125,26 @@
1528  dist: distclean
1529         ./makedist $(VERSION)   
1530  
1531 -loaderinfo: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
1532 -       $(CC) $(LDFLAGS) -o loaderinfo loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
1533 -
1534 +loaderinfo.exe: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
1535 +       $(CC) $(LDFLAGS) -o $@ loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
1536  
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)
1541  
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)
1546  
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)
1551  
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)
1556  
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)
1561  
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)
1566  
1567  scsitape.o: scsitape.c mtx.h mtxl.h
1568  
1569 @@ -140,6 +158,6 @@
1570  
1571  mtx.o: mtx.c mtx.h mtxl.h
1572  
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
1575  
1576  nsmhack.o: nsmhack.c mtxl.h mtx.h