Imported Upstream version 1.3.11
[debian/mtx] / tapeinfo.c
index 820004ed66a84aab1ce35b80a49d04452f32eea1..bd80b3b78490e77a6edef3db1c9903e1cb0812ed 100644 (file)
@@ -1,8 +1,8 @@
 /* Copyright 2000 Enhanced Software Technologies Inc.
  *   Released under terms of the GNU General Public License as
  * required by the license on 'mtxl.c'.
- * $Date: 2001/06/19 21:51:32 $
- * $Revision: 1.2 $
+ * $Date: 2007-03-24 18:14:01 -0700 (Sat, 24 Mar 2007) $
+ * $Revision: 166 $
  */
 
 /*#define DEBUG_PARTITION */
 #include "mtx.h"
 #include "mtxl.h"
 
-char  *argv0;
+char   *argv0;
 
-void usage(void) {
-  FatalError("Usage: tapeinfo -f <generic-device>\n");
+void usage(void)
+{
+       FatalError("Usage: tapeinfo -f <generic-device>\n");
 }
 
 /* A table for printing out the peripheral device type as ASCII. */ 
-static char *PeripheralDeviceType[32] = {
-  "Disk Drive",
-  "Tape Drive",
-  "Printer",
-  "Processor",
-  "Write-once",
-  "CD-ROM",
-  "Scanner",
-  "Optical",
-  "Medium Changer",
-  "Communications",
-  "ASC IT8",
-  "ASC IT8",
-  "RAID Array",
-  "Enclosure Services",
-  "OCR/W",
-  "Bridging Expander", /* 0x10 */
-  "Reserved",  /* 0x11 */
-  "Reserved", /* 0x12 */
-  "Reserved",  /* 0x13 */
-  "Reserved",  /* 0x14 */
-  "Reserved",  /* 0x15 */
-  "Reserved",  /* 0x16 */
-  "Reserved",  /* 0x17 */
-  "Reserved",  /* 0x18 */
-  "Reserved",  /* 0x19 */
-  "Reserved",  /* 0x1a */
-  "Reserved",  /* 0x1b */
-  "Reserved",  /* 0x1c */
-  "Reserved",  /* 0x1d */
-  "Reserved",  /* 0x1e */
-  "Unknown"    /* 0x1f */
+static char *PeripheralDeviceType[32] =
+{
+       "Disk Drive",
+       "Tape Drive",
+       "Printer",
+       "Processor",
+       "Write-once",
+       "CD-ROM",
+       "Scanner",
+       "Optical",
+       "Medium Changer",
+       "Communications",
+       "ASC IT8",
+       "ASC IT8",
+       "RAID Array",
+       "Enclosure Services",
+       "OCR/W",
+       "Bridging Expander",    /* 0x10 */
+       "Reserved",                             /* 0x11 */
+       "Reserved",                             /* 0x12 */
+       "Reserved",                             /* 0x13 */
+       "Reserved",                             /* 0x14 */
+       "Reserved",                             /* 0x15 */
+       "Reserved",                             /* 0x16 */
+       "Reserved",                             /* 0x17 */
+       "Reserved",                             /* 0x18 */
+       "Reserved",                             /* 0x19 */
+       "Reserved",                             /* 0x1a */
+       "Reserved",                             /* 0x1b */
+       "Reserved",                             /* 0x1c */
+       "Reserved",                             /* 0x1d */
+       "Reserved",                             /* 0x1e */
+       "Unknown"                               /* 0x1f */
 };
 
 
@@ -99,34 +101,43 @@ static char *PeripheralDeviceType[32] = {
 
 static void ReportInquiry(DEVICE_TYPE MediumChangerFD)
 {
-  RequestSense_T RequestSense;
-  Inquiry_T *Inquiry;
-  int i;
-
-  Inquiry = RequestInquiry(MediumChangerFD,&RequestSense);
-  if (Inquiry == NULL) 
-    {
-      PrintRequestSense(&RequestSense);
-      FatalError("INQUIRY Command Failed\n");
-    }
-  
-  printf("Product Type: %s\n",PeripheralDeviceType[Inquiry->PeripheralDeviceType]);
-  printf("Vendor ID: '");
-  for (i = 0; i < sizeof(Inquiry->VendorIdentification); i++)
-    printf("%c", Inquiry->VendorIdentification[i]);
-  printf("'\nProduct ID: '");
-  for (i = 0; i < sizeof(Inquiry->ProductIdentification); i++)
-    printf("%c", Inquiry->ProductIdentification[i]);
-  printf("'\nRevision: '");
-  for (i = 0; i < sizeof(Inquiry->ProductRevisionLevel); i++)
-    printf("%c", Inquiry->ProductRevisionLevel[i]);
-  printf("'\n");\
-  if (Inquiry->MChngr) {  /* check the attached-media-changer bit... */
-    printf("Attached Changer: Yes\n");
-  } else {
-    printf("Attached Changer: No\n");
-  }
-  free(Inquiry);  /* well, we're about to exit, but ... */
+       RequestSense_T RequestSense;
+       Inquiry_T *Inquiry;
+       int i;
+
+       Inquiry = RequestInquiry(MediumChangerFD, &RequestSense);
+       if (Inquiry == NULL)
+       {
+               PrintRequestSense(&RequestSense);
+               FatalError("INQUIRY Command Failed\n");
+       }
+
+       printf("Product Type: %s\n", PeripheralDeviceType[Inquiry->PeripheralDeviceType]);
+
+       printf("Vendor ID: '");
+       for (i = 0; i < sizeof(Inquiry->VendorIdentification); i++)
+               printf("%c", Inquiry->VendorIdentification[i]);
+
+       printf("'\nProduct ID: '");
+       for (i = 0; i < sizeof(Inquiry->ProductIdentification); i++)
+               printf("%c", Inquiry->ProductIdentification[i]);
+
+       printf("'\nRevision: '");
+       for (i = 0; i < sizeof(Inquiry->ProductRevisionLevel); i++)
+               printf("%c", Inquiry->ProductRevisionLevel[i]);
+       printf("'\n");
+
+       if (Inquiry->MChngr)
+       {
+               /* check the attached-media-changer bit... */
+               printf("Attached Changer API: Yes\n");
+       }
+       else
+       {
+               printf("Attached Changer API: No\n");
+       }
+
+       free(Inquiry);          /* well, we're about to exit, but ... */
 }
 
 
@@ -136,321 +147,505 @@ static void ReportInquiry(DEVICE_TYPE MediumChangerFD)
 #define TAPEALERT_SIZE 2048  /* max size of tapealert buffer. */ 
 #define MAX_TAPE_ALERT 0x41
 
-static char *tapealert_messages[]= {
-  "Undefined", /* 0 */
-  "         Read: Having problems reading (slowing down)", /* 1 */
-  "        Write: Having problems writing (losing capacity)", /* 2 */
-  "   Hard Error: Uncorrectable read/write error", /* 3 */
-  "        Media: Media Performance Degraded, Data Is At Risk", /* 4 */
-  " Read Failure: Tape faulty or tape drive broken", /* 5 */
-  "Write Failure: Tape faulty or tape drive broken", /* 6 */
-  "   Media Life: The tape has reached the end of its useful life", /* 7 */
-  "Not Data Grade:Replace cartridge with one  containing data grade tape",/*8*/
-  "Write Protect: Attempted to write to a write-protected cartridge",/*9 */
-  "   No Removal: Cannot unload, initiator is preventing media removal", /*a*/
-  "Cleaning Media:Cannot back up or restore to a cleaning cartridge", /* b */
-  "   Bad Format: The loaded tape contains data in an unsupported format", /*c */
-  " Snapped Tape: The data cartridge contains a broken tape", /* d */
-  "Undefined", /* e */
-  "Undefined", /* f */
-  "Undefined", /* 10 */
-  "Undefined", /* 11 */
-  "Undefined", /* 12 */
-  "Undefined", /* 13 */
-  "    Clean Now: The tape drive neads cleaning NOW", /* 0x14 */
-  "Clean Periodic:The tape drive needs to be cleaned at next opportunity", /* 0x15 */
-  "Cleaning Media:Cannot clean because cleaning cartridge used up, insert new cleaning cartridge to clean the drive", /* 0x16 */
-  "Undefined", /* 0x17 */
-  "Undefined", /* 0x18 */
-  "Undefined", /* 0x19 */
-  "Undefined", /* 0x1a */
-  "Undefined", /* 0x1b */
-  "Undefined", /* 0x1c */
-  "Undefined", /* 0x1d */
-  "   Hardware A: Tape drive has a problem not read/write related", /* 0x1e */
-  "   Hardware B: Tape drive has a problem not read/write related", /* 0x1f */
-  "    Interface: Problem with SCSI interface between tape drive and initiator", /* 0x20 */
-  "  Eject Media: The current operation has failed. Eject and reload media", /* 0x21 */
-  "Download Fail: Attempt to download new firmware failed", /* 0x22 */
-  "Undefined", /* 0x23 */
-  "Undefined", /* 0x24 */
-  "Undefined", /* 0x25 */
-  "Undefined", /* 0x26 */
-  "Undefined", /* 0x27 */
-  "Loader Hardware A: Changer having problems communicating with tape drive", /* 0x28   40 */
-  "Loader Stray Tape: Stray tape left in drive from prior error", /* 0x29 41 */
-  "Loader Hardware B: Autoloader mechanism has a fault", /* 0x2a 42 */
-  "  Loader Door: Loader door is open, please close it", /* 0x2b 43 */
-  "Undefined", /* 0x2c */
-  "Undefined", /* 0x2d */
-  "Undefined", /* 0x2e */
-  "Undefined", /* 0x2f */
-  "Undefined", /* 0x30 */
-  "Undefined", /* 0x31 */
-  "Undefined", /* 0x32 */
-  "Undefined", /* 0x33 */
-  "Undefined", /* 0x34 */
-  "Undefined", /* 0x35 */
-  "Undefined", /* 0x36 */
-  "Undefined", /* 0x37 */
-  "Undefined", /* 0x38 */
-  "Undefined", /* 0x39 */
-  "Undefined", /* 0x3a */
-  "Undefined", /* 0x3b */
-  "Undefined", /* 0x3c */
-  "Undefined", /* 0x3d */
-  "Undefined", /* 0x3e */
-  "Undefined", /* 0x3f */
-  "Undefined" /* 0x40 */
+static char *tapealert_messages[] =
+{
+       "Undefined", /* 0 */
+       "         Read: Having problems reading (slowing down)", /* 1 */
+       "        Write: Having problems writing (losing capacity)", /* 2 */
+       "   Hard Error: Uncorrectable read/write error", /* 3 */
+       "        Media: Media Performance Degraded, Data Is At Risk", /* 4 */
+       " Read Failure: Tape faulty or tape drive broken", /* 5 */
+       "Write Failure: Tape faulty or tape drive broken", /* 6 */
+       "   Media Life: The tape has reached the end of its useful life", /* 7 */
+       "Not Data Grade:Replace cartridge with one  containing data grade tape",/*8*/
+       "Write Protect: Attempted to write to a write-protected cartridge",/*9 */
+       "   No Removal: Cannot unload, initiator is preventing media removal", /*a*/
+       "Cleaning Media:Cannot back up or restore to a cleaning cartridge", /* b */
+       "   Bad Format: The loaded tape contains data in an unsupported format", /*c */
+       " Snapped Tape: The data cartridge contains a broken tape", /* d */
+       "Undefined", /* e */
+       "Undefined", /* f */
+       "Undefined", /* 10 */
+       "Undefined", /* 11 */
+       "Undefined", /* 12 */
+       "Undefined", /* 13 */
+       "    Clean Now: The tape drive neads cleaning NOW", /* 0x14 */
+       "Clean Periodic:The tape drive needs to be cleaned at next opportunity", /* 0x15 */
+       "Cleaning Media:Cannot clean because cleaning cartridge used up, insert new cleaning cartridge to clean the drive", /* 0x16 */
+       "Undefined", /* 0x17 */
+       "Undefined", /* 0x18 */
+       "Undefined", /* 0x19 */
+       "Undefined", /* 0x1a */
+       "Undefined", /* 0x1b */
+       "Undefined", /* 0x1c */
+       "Undefined", /* 0x1d */
+       "   Hardware A: Tape drive has a problem not read/write related", /* 0x1e */
+       "   Hardware B: Tape drive has a problem not read/write related", /* 0x1f */
+       "    Interface: Problem with SCSI interface between tape drive and initiator", /* 0x20 */
+       "  Eject Media: The current operation has failed. Eject and reload media", /* 0x21 */
+       "Download Fail: Attempt to download new firmware failed", /* 0x22 */
+       "Undefined", /* 0x23 */
+       "Undefined", /* 0x24 */
+       "Undefined", /* 0x25 */
+       "Undefined", /* 0x26 */
+       "Undefined", /* 0x27 */
+       "Loader Hardware A: Changer having problems communicating with tape drive", /* 0x28   40 */
+       "Loader Stray Tape: Stray tape left in drive from prior error", /* 0x29 41 */
+       "Loader Hardware B: Autoloader mechanism has a fault", /* 0x2a 42 */
+       "  Loader Door: Loader door is open, please close it", /* 0x2b 43 */
+       "Undefined", /* 0x2c */
+       "Undefined", /* 0x2d */
+       "Undefined", /* 0x2e */
+       "Undefined", /* 0x2f */
+       "Undefined", /* 0x30 */
+       "Undefined", /* 0x31 */
+       "Undefined", /* 0x32 */
+       "Undefined", /* 0x33 */
+       "Undefined", /* 0x34 */
+       "Undefined", /* 0x35 */
+       "Undefined", /* 0x36 */
+       "Undefined", /* 0x37 */
+       "Undefined", /* 0x38 */
+       "Undefined", /* 0x39 */
+       "Undefined", /* 0x3a */
+       "Undefined", /* 0x3b */
+       "Undefined", /* 0x3c */
+       "Undefined", /* 0x3d */
+       "Undefined", /* 0x3e */
+       "Undefined", /* 0x3f */
+       "Undefined" /* 0x40 */
 };
 
+typedef struct TapeCapacityStruct
+{
+       unsigned int partition0_remaining;
+       unsigned int partition1_remaining;
+       unsigned int partition0_size;
+       unsigned int partition1_size;
+}      TapeCapacity;
+
+#if defined(DEBUG)
+/* DEBUG */
+static void dump_data(unsigned char *data, int len)
+{
+       if (len != 0)
+       {
+               fprintf(stderr,"DATA:");
+               PrintHex(1, data, len);
+       }
+       else
+       {
+               fprintf(stderr, "**NO DATA**\n");
+       }
+}
+#endif
+
 
-struct tapealert_struct {
-  int length;
-  unsigned char *data;
+/* Request the tape capacity page defined by some DAT autoloaders. */
+
+static TapeCapacity *RequestTapeCapacity(DEVICE_TYPE fd, RequestSense_T *sense)
+{
+       CDB_T CDB;
+       TapeCapacity *result;
+       int result_len;
+
+       unsigned char buffer[TAPEALERT_SIZE]; /* Overkill, but ... */
+
+       slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
+
+       /* now to create the CDB block: */
+       CDB[0] = 0x4d;   /* Log Sense */
+       CDB[1] = 0;   
+       CDB[2] = 0x31;   /* Tape Capacity Page. */
+       CDB[3] = 0;
+       CDB[4] = 0;
+       CDB[5] = 0;
+       CDB[6] = 0;
+       CDB[7] = TAPEALERT_SIZE >> 8 & 0xff;    /* hi byte, allocation size */
+       CDB[8] = TAPEALERT_SIZE & 0xff;                 /* lo byte, allocation size */
+       CDB[9] = 0;                                                             /* reserved */ 
+
+       if (SCSI_ExecuteCommand(fd, Input, &CDB, 10, buffer, TAPEALERT_SIZE, sense) != 0)
+       {
+               /*    fprintf(stderr,"RequestTapeCapacity: Command failed: Log Sense\n"); */
+               return NULL;
+       }
+
+       /* dump_data(buffer,64); */
+
+       /* okay, we have stuff in the result buffer: the first 4 bytes are a header:
+       * byte 0 should be 0x31, byte 1 == 0, bytes 2,3 tell how long the
+       * log page is. 
+       */
+       if ((buffer[0]&0x3f) != 0x31)
+       {
+               /*    fprintf(stderr,"RequestTapeCapacity: Invalid header for page (not 0x31).\n"); */
+               return NULL;
+       }
+
+       result_len = ((int)buffer[2] << 8) + buffer[3];
+
+       if (result_len != 32)
+       {
+               /*   fprintf(stderr,"RequestTapeCapacity: Page was %d bytes long, not 32 bytes\n",result_len); */
+               return NULL; /* This Is Not The Page You're Looking For */
+       }
+
+       result = xmalloc(sizeof(TapeCapacity));
+
+       /* okay, now allocate data and move the buffer over there: */
+
+               /*      0  1  2  3  4  5  6  7  8  9
+       DATA:   31 00 00 20 00 01 4c 04 01 3a
+                       10 11 12 13 14 15 16 17 18 19
+       DATA:   81 0c 00 02 4c 04 00 00 00 00
+                       20 21 22 23 24 25 26 27 28 29
+       DATA:   00 03 4c 04 01 3f 4b 1f 00 04
+                       30 31 32 33 34 35
+       DATA:   4c 04 00 00 00 00 00 00 00 00
+       DATA:   00 00 00 00 00 00 00 00 00 00
+       DATA:   00 00 00 00 00 00 00 00 00 00
+       DATA:   00 00 00 00
+       */
+
+       result->partition0_remaining =
+               ((unsigned int)buffer[8]  << 24) +
+               ((unsigned int)buffer[9]  << 16) +
+               ((unsigned int)buffer[10] <<  8) + 
+               buffer[11];
+
+       result->partition1_remaining =
+               ((unsigned int)buffer[16] << 24) +
+               ((unsigned int)buffer[17] << 16) +
+               ((unsigned int)buffer[18] <<  8) +
+               buffer[19];
+
+       result->partition0_size =
+               ((unsigned int)buffer[24] << 24) +
+               ((unsigned int)buffer[25] << 16) +
+               ((unsigned int)buffer[26] <<  8) +
+               buffer[27];
+
+       result->partition1_size =
+               ((unsigned int)buffer[32] << 24) +
+               ((unsigned int)buffer[33] << 16) +
+               ((unsigned int)buffer[34] <<  8) +
+               buffer[35]; 
+
+       return result;
+}
+
+
+
+struct tapealert_struct
+{
+       int length;
+       unsigned char *data;
 };
-  
-  
-static struct tapealert_struct *RequestTapeAlert(DEVICE_TYPE fd, RequestSense_T *sense) {
-  CDB_T CDB;
-  
-  struct tapealert_struct *result;
-  int i,tapealert_len,result_idx;
-  
-  unsigned char buffer[TAPEALERT_SIZE];
-  unsigned char *walkptr;
-
-  slow_bzero(buffer,TAPEALERT_SIZE); /*zero it... */
-
-  /* now to create the CDB block: */
-  CDB[0]=0x4d;   /* Log Sense */
-  CDB[1]=0;   
-  CDB[2]=0x2e;   /* Tape Alert Page. */
-  CDB[3]=0;
-  CDB[4]=0;
-  CDB[5]=0;
-  CDB[6]=0;
-  CDB[7]=TAPEALERT_SIZE>>8 & 0xff;  /* hi byte, allocation size */
-  CDB[8]=TAPEALERT_SIZE & 0xff;     /* lo byte, allocation size */
-  CDB[9]=0;  /* reserved */ 
-
-  if (SCSI_ExecuteCommand(fd,Input,&CDB,10,buffer,TAPEALERT_SIZE,sense)!=0){
-    return NULL;
-  }
-
-  result=xmalloc(sizeof(struct tapealert_struct));
-
-  /* okay, we have stuff in the result buffer: the first 4 bytes are a header:
-   * byte 0 should be 0x2e, byte 1 == 0, bytes 2,3 tell how long the
-   * tapealert page is. 
-   */
-  if ((buffer[0]&0x3f) != 0x2e) {
-    result->data=NULL;
-    result->length=0;
-    return result;
-  }
-
-  tapealert_len=(((int)buffer[2])<<8) + buffer[3];
-  
-
-  if (!tapealert_len) {
-    result->length=0;
-    result->data=NULL;
-    return result;
-  }
-
-  /* okay, now allocate data and move the buffer over there: */
-  result->length=MAX_TAPE_ALERT;
-  result->data=xzmalloc(MAX_TAPE_ALERT); /* alloc & zero. */
-  
-  walkptr=&buffer[4];
-  i=0;
-  while (i<tapealert_len) {
-    
-
-    result_idx=(((int)walkptr[0])<<8) + walkptr[1]; /* the parameter #. */
-    if (result_idx > 0 && result_idx < MAX_TAPE_ALERT) {
-      if (walkptr[4]) {
-       result->data[result_idx]=1; 
-      } else {
-       result->data[result_idx]=0;
-      }
+
+static struct tapealert_struct *RequestTapeAlert(DEVICE_TYPE fd, RequestSense_T *sense)
+{
+       CDB_T CDB;
+
+       struct tapealert_struct *result;
+       int i, tapealert_len, result_idx;
+
+       unsigned char buffer[TAPEALERT_SIZE];
+       unsigned char *walkptr;
+
+       slow_bzero((char *)buffer, TAPEALERT_SIZE); /*zero it... */
+
+       /* now to create the CDB block: */
+       CDB[0] = 0x4d;  /* Log Sense */
+       CDB[1] = 0;
+       CDB[2] = 0x2e;  /* Tape Alert Page. */
+       CDB[3] = 0;
+       CDB[4] = 0;
+       CDB[5] = 0;
+       CDB[6] = 0;
+       CDB[7] = TAPEALERT_SIZE >> 8 & 0xff;    /* hi byte, allocation size */
+       CDB[8] = TAPEALERT_SIZE & 0xff;                 /* lo byte, allocation size */
+       CDB[9] = 0;                                                             /* reserved */
+
+       if (SCSI_ExecuteCommand(fd,Input,&CDB,10,buffer,TAPEALERT_SIZE,sense)!=0)
+       {
+               return NULL;
+       }
+
+       result = xmalloc(sizeof(struct tapealert_struct));
+
+       /* okay, we have stuff in the result buffer: the first 4 bytes are a header:
+        * byte 0 should be 0x2e, byte 1 == 0, bytes 2,3 tell how long the
+        * tapealert page is. 
+        */
+       if ((buffer[0]&0x3f) != 0x2e)
+       {
+               result->data = NULL;
+               result->length = 0;
+               return result;
+       }
+
+       tapealert_len = ((int)buffer[2] << 8) + buffer[3];
+
+       if (!tapealert_len)
+       {
+               result->length = 0;
+               result->data = NULL;
+               return result;
+       }
+
+       /* okay, now allocate data and move the buffer over there: */
+       result->length = MAX_TAPE_ALERT;
+       result->data = xzmalloc(MAX_TAPE_ALERT); /* alloc & zero. */
+
+       walkptr = &buffer[4];
+       i = 0;
+
+       while (i < tapealert_len)
+       {
+               result_idx=(((int)walkptr[0])<<8) + walkptr[1]; /* the parameter #. */
+               if (result_idx > 0 && result_idx < MAX_TAPE_ALERT)
+               {
+                       if (walkptr[4])
+                       {
+                               result->data[result_idx] = 1; 
+                       }
+                       else
+                       {
+                               result->data[result_idx] = 0;
+                       }
 #ifdef DEBUGOLD1
-      fprintf(stderr,"Alert[0x%x]=%d\n",result_idx,result->data[result_idx]);
-      fflush(stderr);
+                       fprintf(stderr,"Alert[0x%x]=%d\n",result_idx,result->data[result_idx]);
+                       fflush(stderr);
 #endif
-    } else {
-      FatalError("Invalid tapealert page: %d\n",result_idx);
-    }
-    i=i+4+walkptr[3]; /* length byte! */
-    walkptr=walkptr+4+walkptr[3]; /* next! */
-  }
-  return result;
+               }
+               else
+               {
+                       FatalError("Invalid tapealert page: %d\n",result_idx);
+               }
+
+               i = i + 4 + walkptr[3]; /* length byte! */
+               walkptr = walkptr + 4 + walkptr[3]; /* next! */
+       }
+       return result;
 }
 
-static void ReportTapeAlert(DEVICE_TYPE fd) {
-  /* we actually ignore a bad sense reading, like might happen if the 
-   * tape drive does not support the tapealert page. 
-   */
-  
-  RequestSense_T RequestSense;
-  
-  struct tapealert_struct *result;
-  int i;
-
-  result=RequestTapeAlert(fd,&RequestSense);
-  if (!result) return; /* sorry. Don't print sense here. */
-  if (!result->length) return; /* sorry, no alerts valid. */
-  
-  for (i=0;i<result->length;i++) {
-    if (result->data[i]) {
-      printf("TapeAlert[%d]:%s.\n",i,tapealert_messages[i]);
-    }
-  }
-  free(result->data);
-  free(result);
-  return;
-}
+static void ReportTapeCapacity(DEVICE_TYPE fd)
+{
+       /* we actually ignore a bad sense reading, like might happen if the 
+        * tape drive does not support the tape capacity page. 
+        */
 
-static unsigned char
-*mode_sense(DEVICE_TYPE fd, int pagenum, int alloc_len,  RequestSense_T *RequestSense) {
-  CDB_T CDB;
-
-  unsigned char *input_buffer; /*the input buffer -- has junk prepended to
-                               * actual sense page. 
-                               */
-  unsigned char *tmp;
-  unsigned char *retval;  /* the return value. */
-  int i,pagelen;
-
-  if (alloc_len > 255) {
-    FatalError("mode_sense(6) can only read up to 255 characters!\n");
-  }
-
-  input_buffer=(unsigned char *)xzmalloc(256); /* overdo it, eh? */
-
-  /* clear the sense buffer: */
-  slow_bzero((char *)RequestSense,sizeof(RequestSense_T));
-  
-
-  /* returns an array of bytes in the page, or, if not possible, NULL. */
-  CDB[0]=0x1a; /* Mode Sense(6) */
-  CDB[1]=0; 
-  CDB[2]=pagenum; /* the page to read. */
-  CDB[3]=0;
-  CDB[4]=255; /* allocation length. This does max of 256 bytes! */
-  CDB[5]=0;
-  
-  if (SCSI_ExecuteCommand(fd,Input,&CDB,6,
-                         input_buffer,255,RequestSense) != 0) {
-#ifdef DEBUG_MODE_SENSE
-    fprintf(stderr,"Could not execute mode sense...\n");
-    fflush(stderr);
-#endif
-    return NULL; /* sorry, couldn't do it. */
-  }
-
-  /* Oh hell, write protect is the only thing I have: always print
-   * it if our mode page was 0x0fh, before skipping past buffer: 
-   * if the media is *NOT* write protected, just skip, sigh. 
-   *
-   * Oh poops, the blocksize is reported in the block descriptor header
-<   * too. Again, just print if our mode page was 0x0f...
-   */
-  if (pagenum == 0x0f) {
-    int blocklen;
-    if (input_buffer[2] & 0x80) {
-      printf("WriteProtect: yes\n");
-    }
-    if (input_buffer[2] & 0x70) {
-      printf("BufferedMode: yes\n");
-    }
-    if (input_buffer[1] ) {
-      printf("Medium Type: 0x%x\n", input_buffer[1]);
-    } else {
-      printf("Medium Type: Not Loaded\n");
-    }
-    printf("Density Code: 0x%x\n", input_buffer[4]);
-    /* Put out the block size: */
-    blocklen=((int)input_buffer[9]<<16)+
-      ((int)input_buffer[10]<<8)+
-      input_buffer[11];
-    printf("BlockSize: %d\n", blocklen);
-    /* This doesn't seem to do anything useful on my Tandberg so I
-     * am taking it out -- elg
-     */ 
-    /* Put out the # Blocks */
-    /* blocklen=((int)input_buffer[5]<<16)+ */
-    /*      ((int)input_buffer[6]<<8)+ */
-    /*      input_buffer[7]; */
-    /* printf("Num Blocks:  %d\n", blocklen); */
-  }
-  /* First skip past any header.... */
-  tmp=input_buffer+4+input_buffer[3];
-  /* now find out real length of page... */
-  pagelen=tmp[1]+2;
-  retval=xmalloc(pagelen);
-  /* and copy our data to the new page. */
-  for (i=0;i<pagelen;i++) {
-    retval[i]=tmp[i];
-  }
-  /* okay, free our input buffer: */
-  free(input_buffer);
-  return retval;
+       RequestSense_T RequestSense;
+
+       TapeCapacity *result;
+
+       result=RequestTapeCapacity(fd,&RequestSense);
+
+       if (!result)
+               return;
+
+       printf("Partition 0 Remaining Kbytes: %d\n", result->partition0_remaining);
+       printf("Partition 0 Size in Kbytes: %d\n", result->partition0_size);
+
+       if (result->partition1_size)
+       {
+               printf("Partition 1 Remaining Kbytes: %d\n", result->partition1_remaining);
+               printf("Partition 1 Size in Kbytes: %d\n", result->partition1_size);
+       }
+
+       free(result);
 }
 
 
 
+static void ReportTapeAlert(DEVICE_TYPE fd)
+{
+       /* we actually ignore a bad sense reading, like might happen if the 
+        * tape drive does not support the tapealert page. 
+        */
 
+       RequestSense_T RequestSense;
 
-#define DCE_MASK 0x80
-#define DCC_MASK 0x40
-#define DDE_MASK 0x80
+       struct tapealert_struct *result;
+       int i;
+
+       result=RequestTapeAlert(fd,&RequestSense);
+
+       if (!result)
+               return; /* sorry. Don't print sense here. */
+
+       if (!result->length)
+               return; /* sorry, no alerts valid. */
+
+       for (i = 0; i < result->length; i++)
+       {
+               if (result->data[i])
+               {
+                       printf("TapeAlert[%d]: %s.\n", i, tapealert_messages[i]);
+               }
+       }
+
+       free(result->data);
+       free(result);
+}
 
-static void ReportCompressionPage(DEVICE_TYPE fd) {
-  /* actually ignore a bad sense reading, like might happen if the tape
-   * drive does not support the mode sense compression page. 
-   */
+static unsigned char
+*mode_sense(DEVICE_TYPE fd, char pagenum, int alloc_len,  RequestSense_T *RequestSense)
+{
+       CDB_T CDB;
 
-  RequestSense_T RequestSense;
+       unsigned char *input_buffer;
+       unsigned char *tmp;
+       unsigned char *retval;
+       int i, pagelen;
 
-  unsigned char *compression_page;
+       if (alloc_len > 255)
+       {
+               FatalError("mode_sense(6) can only read up to 255 characters!\n");
+       }
 
+       input_buffer = (unsigned char *)xzmalloc(256); /* overdo it, eh? */
 
-  compression_page=mode_sense(fd,0x0f,16,&RequestSense);
+       /* clear the sense buffer: */
+       slow_bzero((char *)RequestSense, sizeof(RequestSense_T));
 
-  if (!compression_page) {
-    return;  /* sorry! */
-  }
+       /* returns an array of bytes in the page, or, if not possible, NULL. */
+       CDB[0] = 0x1a; /* Mode Sense(6) */
+       CDB[1] = 0; 
+       CDB[2] = pagenum; /* the page to read. */
+       CDB[3] = 0;
+       CDB[4] = 255; /* allocation length. This does max of 256 bytes! */
+       CDB[5] = 0;
 
-  /* Okay, we now have the compression page. Now print stuff from it: */
-  printf("DataCompEnabled: %s\n", (compression_page[2]&DCE_MASK)? "yes" : "no");
-  printf("DataCompCapable: %s\n", (compression_page[2]&DCC_MASK)? "yes" : "no");
-  printf("DataDeCompEnabled: %s\n", (compression_page[3]&DDE_MASK)? "yes" : "no");
-  printf("CompType: 0x%x\n",
-        (compression_page[4]<<24)+(compression_page[5]<<16)+(compression_page[6]<<8)+compression_page[7]);
-  printf("DeCompType: 0x%x\n",
-       (compression_page[8]<<24)+ (compression_page[9]<<16)+(compression_page[10]<<8)+compression_page[11]);
-  free(compression_page);
-  return;
+       if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, input_buffer, 255, RequestSense) != 0)
+       {
+#ifdef DEBUG_MODE_SENSE
+               fprintf(stderr,"Could not execute mode sense...\n");
+               fflush(stderr);
+#endif
+               return NULL; /* sorry, couldn't do it. */
+       }
+
+       /* Oh hell, write protect is the only thing I have: always print
+        * it if our mode page was 0x0fh, before skipping past buffer: 
+        * if the media is *NOT* write protected, just skip, sigh. 
+        *
+        * Oh poops, the blocksize is reported in the block descriptor header
+        * <   * too. Again, just print if our mode page was 0x0f...
+        */
+       if (pagenum == 0x0f)
+       {
+               int blocklen;
+
+               if (input_buffer[2] & 0x80)
+               {
+                       printf("WriteProtect: yes\n");
+               }
+
+               if (input_buffer[2] & 0x70)
+               {
+                       printf("BufferedMode: yes\n");
+               }
+
+               if (input_buffer[1] )
+               {
+                       printf("Medium Type: 0x%x\n", input_buffer[1]);
+               }
+               else
+               {
+                       printf("Medium Type: Not Loaded\n");
+               }
+
+               printf("Density Code: 0x%x\n", input_buffer[4]);
+               /* Put out the block size: */
+
+               blocklen =      ((int)input_buffer[9]  << 16)+
+                                       ((int)input_buffer[10] <<  8)+
+                                       input_buffer[11];
+
+               printf("BlockSize: %d\n", blocklen);
+       }
+
+       /* First skip past any header.... */
+       tmp = input_buffer + 4 + input_buffer[3];
+
+       /* now find out real length of page... */
+       pagelen = tmp[1] + 2;
+       retval = xmalloc(pagelen);
+
+       /* and copy our data to the new page. */
+       for (i=0;i<pagelen;i++)
+       {
+               retval[i]=tmp[i];
+       }
+
+       /* okay, free our input buffer: */
+       free(input_buffer);
+       return retval;
 }
-  
+
+
+#define DCE_MASK 0x80
+#define DCC_MASK 0x40
+#define DDE_MASK 0x80
+
+static void ReportCompressionPage(DEVICE_TYPE fd)
+{
+       /* actually ignore a bad sense reading, like might happen if the tape
+       * drive does not support the mode sense compression page. 
+       */
+
+       RequestSense_T RequestSense;
+
+       unsigned char *compression_page;
+
+       compression_page=mode_sense(fd,0x0f,16,&RequestSense);
+
+       if (!compression_page)
+       {
+               return;  /* sorry! */
+       }
+
+       /* Okay, we now have the compression page. Now print stuff from it: */
+       printf("DataCompEnabled: %s\n", (compression_page[2] & DCE_MASK)? "yes" : "no");
+       printf("DataCompCapable: %s\n", (compression_page[2] & DCC_MASK)? "yes" : "no");
+       printf("DataDeCompEnabled: %s\n", (compression_page[3] & DDE_MASK)? "yes" : "no");
+       printf("CompType: 0x%x\n",
+               (compression_page[4] << 24) +
+               (compression_page[5] << 16) +
+               (compression_page[6] <<  8) +
+                compression_page[7]);
+
+       printf("DeCompType: 0x%x\n",
+               (compression_page[8]  << 24) +
+               (compression_page[9]  << 16) +
+               (compression_page[10] <<  8) +
+                compression_page[11]);
+
+       free(compression_page);
+}
+
 /* Now for the device configuration mode page: */
 
-static void ReportConfigPage(DEVICE_TYPE fd) {
-  RequestSense_T RequestSense;
-  unsigned char *config_page;
-  
-  config_page=mode_sense(fd,0x10,16,&RequestSense);
-  if (!config_page) return;
-
-  /* Now to print the stuff: */
-  printf("ActivePartition: %d\n",config_page[3]);
-  /* The following does NOT work accurately on any tape drive I know of... */
-  /*  printf("DevConfigComp: %s\n", config_page[14] ? "yes" : "no"); */
-  printf("EarlyWarningSize: %d\n",
-        (config_page[11]<<16)+(config_page[12]<<8)+config_page[13]);
-  return;
+static void ReportConfigPage(DEVICE_TYPE fd)
+{
+       RequestSense_T RequestSense;
+       unsigned char *config_page;
+
+       config_page = mode_sense(fd, 0x10, 16, &RequestSense);
+       if (!config_page)
+               return;
+
+       /* Now to print the stuff: */
+       printf("ActivePartition: %d\n", config_page[3]);
+
+       /* The following does NOT work accurately on any tape drive I know of... */
+       /*  printf("DevConfigComp: %s\n", config_page[14] ? "yes" : "no"); */
+       printf("EarlyWarningSize: %d\n",
+               (config_page[11] << 16) +
+               (config_page[12] <<  8) +
+                config_page[13]);
 }
 
 /* ***************************************
@@ -467,156 +662,163 @@ static void ReportConfigPage(DEVICE_TYPE fd) {
  *
  ********************************************/
 
-static void ReportPartitionPage(DEVICE_TYPE fd) {
-  RequestSense_T RequestSense;
-  unsigned char *partition_page;
+static void ReportPartitionPage(DEVICE_TYPE fd)
+{
+       RequestSense_T RequestSense;
+       unsigned char *partition_page;
+
+       int num_parts,max_parts;
+       int i;
 
-  int num_parts,max_parts;
-  int i;
+       partition_page=mode_sense(fd,0x11,255,&RequestSense);
+       if (!partition_page)
+               return;
 
-  partition_page=mode_sense(fd,0x11,255,&RequestSense);
-  if (!partition_page) return;
+       /* Okay, now we have either old format or new format: */
+       num_parts = partition_page[3];
+       max_parts = partition_page[2];
 
-  /* Okay, now we have either old format or new format: */
-  num_parts=partition_page[3];
-  max_parts=partition_page[2];
+       printf("NumPartitions: %d\n", num_parts);
+       printf("MaxPartitions: %d\n", max_parts);
 
-  printf("NumPartitions:%d\n",num_parts);
-  printf("MaxPartitions:%d\n",max_parts);
-  if (!num_parts) {  /* if no additional partitions, then ... */ 
-    free(partition_page);
-    return;
-  }
-  
-  /* we know we have at least one partition if we got here. Check the
-   * page size field. If it is 8 or below, then we are the old format....
-   */
+       if (!num_parts)
+       {
+               /* if no additional partitions, then ... */ 
+               free(partition_page);
+               return;
+       }
+
+       /* we know we have at least one partition if we got here. Check the
+        * page size field. If it is 8 or below, then we are the old format....
+        */
 
 #ifdef DEBUG_PARTITION
-  fprintf(stderr,"partition_page[1]=%d\n",partition_page[1]);
-  fflush(stderr);
+       fprintf(stderr,"partition_page[1]=%d\n",partition_page[1]);
+       fflush(stderr);
 #endif
-  if (partition_page[1]==8) {
-    /* old-style! */
-    printf("Partition1:%d\n",(partition_page[8]<<8)+partition_page[9]);
-  } else {
-    /* new-style! */
-    for (i=0;i<=max_parts;i++) {
-#ifdef DEBUG_PARTITION    
-      fprintf(stderr,"partition%d:[%d]%d [%d]%d\n",i,8+i*2,
-             partition_page[8+i*2]<<8, 9+i*2,partition_page[9+i*2]);
-      fflush(stderr);
+       if (partition_page[1]==8)
+       {
+               /* old-style! */
+               printf("Partition1: %d\n",(partition_page[8]<<8)+partition_page[9]);
+       }
+       else
+       {
+               /* new-style! */
+               for (i=0;i<=max_parts;i++)
+               {
+#ifdef DEBUG_PARTITION
+                       fprintf(stderr,"partition%d:[%d]%d [%d]%d\n", i, 8 + i * 2,
+                       partition_page[8+i*2]<<8, 9+i*2,partition_page[9 + i * 2]);
+                       fflush(stderr);
 #endif
-      printf("Partition%d:%d\n",i,
-            (partition_page[8+i*2]<<8)+partition_page[9+i*2]);
-    }
-  }
-  free(partition_page);
-  return;
+                       printf("Partition%d: %d\n", i,
+                                       (partition_page[8 + i * 2] << 8) + partition_page[9 + i * 2]);
+               }
+       }
+       free(partition_page);
 }
 
-static void ReportSerialNumber(DEVICE_TYPE fd) {
-  /* actually ignore a bad sense reading, like might happen if the
-     tape drive does not support the inquiry page 0x80. 
-  */
+static void ReportSerialNumber(DEVICE_TYPE fd)
+{
+       /*      Actually ignore a bad sense reading, like might happen if the
+               tape drive does not support the inquiry page 0x80. 
+       */
+
+       RequestSense_T sense;
+       CDB_T CDB;
 
-  RequestSense_T sense;
-  CDB_T CDB;
 #define WILD_SER_SIZE 30
-  unsigned char buffer[WILD_SER_SIZE]; /* just wildly overestimate serial# length! */
-
-  int i,lim;
-  char *bufptr; 
-  
-  CDB[0]=0x12;  /* INQUIRY */
-  CDB[1]= 1;     /* EVPD = 1 */
-  CDB[2]=0x80;   /* The serial # page, hopefully. */
-  CDB[3]=0  ; /* reserved */
-  CDB[4]=WILD_SER_SIZE;
-  CDB[5]=0;
-
-  if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,
-                         &buffer, sizeof(buffer), &sense) != 0)  {
-    /* PrintRequestSense(&sense); */ /* zap debugging output :-) */
-    /* printf("No Serial Number: None\n"); */
-    return; 
-  }
-  
-  /* okay, we have something in our buffer. Byte 3 should be the length of
-     the sernum field, and bytes 4 onward are the serial #. */
-  
-  lim=(int)buffer[3];
-  bufptr= &(buffer[4]);
-  
-  printf("SerialNumber: '");
-  for (i=0;i<lim;i++) {
-    putchar(*bufptr++);
-  }
-  printf("'\n");
-  return ; /* done! */
+unsigned char buffer[WILD_SER_SIZE]; /* just wildly overestimate serial# length! */
+
+       int i, lim;
+       char *bufptr; 
+
+       CDB[0] = 0x12;                  /* INQUIRY */
+       CDB[1] = 1;                             /* EVPD = 1 */
+       CDB[2] = 0x80;                  /* The serial # page, hopefully. */
+       CDB[3] = 0;                             /* reserved */
+       CDB[4] = WILD_SER_SIZE;
+       CDB[5] = 0;
+
+       if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, &buffer, sizeof(buffer), &sense) != 0)
+       {
+               /* PrintRequestSense(&sense); */ /* zap debugging output :-) */
+               /* printf("No Serial Number: None\n"); */
+               return; 
+       }
+
+       /* okay, we have something in our buffer. Byte 3 should be the length of
+       the sernum field, and bytes 4 onward are the serial #. */
+
+       lim = (int)buffer[3];
+       bufptr = (char *)&(buffer[4]);
+
+       printf("SerialNumber: '");
+       for (i=0;i<lim;i++)
+       {
+               putchar(*bufptr++);
+       }
+       printf("'\n");
 }
-    
 
 /*  Read Block Limits! */
 
-void ReportBlockLimits(DEVICE_TYPE fd) {
-  RequestSense_T sense;
-  CDB_T CDB;
-  unsigned char buffer[6];
-
-
-  CDB[0]=0x05;  /* READ_BLOCK_LIMITS */
-  CDB[1]=0;
-  CDB[2]=0;
-  CDB[3]=0;  /* 1-5 all unused. */
-  CDB[4]=0;
-  CDB[5]=0; 
-
-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
-  if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,6,&sense)!=0){
-    return;
-  }
-  
-  /* okay, but if we did get a result, print it: */
-  printf("MinBlock:%d\n",
-        (buffer[4]<<8)+buffer[5]);
-  printf("MaxBlock:%d\n",
-        (buffer[1]<<16)+(buffer[2]<<8)+buffer[3]);
-
-  return;
+void ReportBlockLimits(DEVICE_TYPE fd)
+{
+       RequestSense_T sense;
+       CDB_T CDB;
+       unsigned char buffer[6];
+
+       CDB[0] = 0x05;  /* READ_BLOCK_LIMITS */
+       CDB[1] = 0;
+       CDB[2] = 0;
+       CDB[3] = 0;             /* 1-5 all unused. */
+       CDB[4] = 0;
+       CDB[5] = 0; 
+
+       slow_bzero((char *)&sense,sizeof(RequestSense_T));
+       if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, buffer, 6, &sense) != 0)
+       {
+               return;
+       }
+
+       /* okay, but if we did get a result, print it: */
+       printf("MinBlock: %d\n", (buffer[4] << 8) + buffer[5]);
+       printf("MaxBlock: %d\n", (buffer[1] << 16) + (buffer[2]<<8) + buffer[3]);
 }
-  
+
 /* Do a READ_POSITION. This may not be always valid, but (shrug). */
-void ReadPosition(DEVICE_TYPE fd) {
-  RequestSense_T sense;
-  CDB_T CDB;
-  unsigned char buffer[20];
-  unsigned int position;
-
-
-  CDB[0]=0x34;  /* READ_POSITION */
-  CDB[1]=0;
-  CDB[2]=0;
-  CDB[3]=0;  /* 1-9 all unused. */
-  CDB[4]=0;
-  CDB[5]=0; 
-  CDB[6]=0;
-  CDB[7]=0;
-  CDB[8]=0;
-  CDB[9]=0;
-
-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
-
-  /* set the timeout: */
-  SCSI_Set_Timeout(2); /* set timeout to 2 seconds! */
-
-  /* if we don't get a result (e.g. we issue this to a disk drive), punt. */
-  if (SCSI_ExecuteCommand(fd,Input,&CDB,10,buffer,20,&sense)!=0){
-    return;
-  }
-  
-  SCSI_Default_Timeout(); /* reset it to 5 minutes, sigh! */
-  /* okay, but if we did get a result, print it: */
+void ReadPosition(DEVICE_TYPE fd)
+{
+       RequestSense_T sense;
+       CDB_T CDB;
+       unsigned char buffer[20];
+       unsigned int position;
+
+       CDB[0] = 0x34;          /* READ_POSITION */
+       CDB[1] = 0;
+       CDB[2] = 0;
+       CDB[3] = 0;                     /* 1-9 all unused. */
+       CDB[4] = 0;
+       CDB[5] = 0;
+       CDB[6] = 0;
+       CDB[7] = 0;
+       CDB[8] = 0;
+       CDB[9] = 0;
+
+       slow_bzero((char *)&sense, sizeof(RequestSense_T));
+
+       SCSI_Set_Timeout(2); /* set timeout to 2 seconds! */
+
+       /* if we don't get a result (e.g. we issue this to a disk drive), punt. */
+       if (SCSI_ExecuteCommand(fd, Input, &CDB, 10, buffer, 20, &sense) != 0)
+       {
+               return;
+       }
+
+       SCSI_Default_Timeout(); /* reset it to 5 minutes, sigh! */
+       /* okay, but if we did get a result, print it: */
+
 #define RBL_BOP 0x80
 #define RBL_EOP 0x40
 #define RBL_BCU 0x20
@@ -625,73 +827,81 @@ void ReadPosition(DEVICE_TYPE fd) {
 #define RBL_BPU 0x04
 #define RBL_PERR 0x02
 
-  /* If we have BOP, go ahead and print that. */
-  if (buffer[0]&RBL_BOP) {
-    printf("BOP: yes\n");
-  }
-  /* if we have valid data, print it: */
-  if (buffer[0]&RBL_BPU) {
-    printf("Block Position: -1");
-  } else {
-    
-    position= (unsigned int) (((unsigned int)buffer[4]<<24) +
-                             ((unsigned int)buffer[5]<<16) + 
-                             ((unsigned int)buffer[6]<<8) + buffer[7]);
-    printf("Block Position: %d\n",position);
-  }
-  return;
+       /* If we have BOP, go ahead and print that. */
+       if (buffer[0]&RBL_BOP)
+       {
+               printf("BOP: yes\n");
+       }
+
+       /* if we have valid data, print it: */
+       if (buffer[0]&RBL_BPU)
+       {
+               printf("Block Position: -1");
+       }
+       else
+       {
+               position = (unsigned int)(((unsigned int)buffer[4] << 24) +
+                                                                 ((unsigned int)buffer[5] << 16) +
+                                                                 ((unsigned int)buffer[6] <<  8) +
+                                                                       buffer[7]);
+
+               printf("Block Position: %d\n",position);
+       }
 }
 
 /* Test unit ready: This will tell us whether the tape drive
  * is currently ready to read or write.
  */
 
-int TestUnitReady(DEVICE_TYPE fd) {
-  RequestSense_T sense;
-  CDB_T CDB;
-  unsigned char buffer[6];
-
-
-  CDB[0]=0x00;  /* TEST_UNIT_READY */
-  CDB[1]=0;
-  CDB[2]=0;
-  CDB[3]=0;  /* 1-5 all unused. */
-  CDB[4]=0;
-  CDB[5]=0; 
-
-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
-  if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){
-    printf("Ready: no\n");
-    return 0;
-  }
-  
-  printf("Ready: yes\n");
-  return 1;
+int TestUnitReady(DEVICE_TYPE fd)
+{
+       RequestSense_T sense;
+       CDB_T CDB;
+       unsigned char buffer[6];
+
+       CDB[0] = 0x00;          /* TEST_UNIT_READY */
+       CDB[1] = 0;
+       CDB[2] = 0;
+       CDB[3] = 0;                     /* 1-5 all unused. */
+       CDB[4] = 0;
+       CDB[5] = 0;
+
+       slow_bzero((char *)&sense,sizeof(RequestSense_T));
+       if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0)
+       {
+               printf("Ready: no\n");
+               return 0;
+       }
+
+       printf("Ready: yes\n");
+       return 1;
 }
 
 /* We write a filemarks of 0 before going to grab position, in order
  * to insure that data in the buffer is not a problem. 
  */
 
-int WriteFileMarks(DEVICE_TYPE fd,int count) {
-  RequestSense_T sense;
-  CDB_T CDB;
-  unsigned char buffer[6];
-
-
-  CDB[0]=0x10;  /* WRITE_FILE_MARKS */
-  CDB[1]=0;
-  CDB[2]=(count >> 16) & 0xff;
-  CDB[3]=(count >>8) & 0xff;
-  CDB[4]=count & 0xff;
-  CDB[5]=0; 
-
-  /* we really don't care if this command works or not, sigh.  */
-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
-  if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){
-    return 1;
-  }
-  return 0;
+int WriteFileMarks(DEVICE_TYPE fd,int count)
+{
+       RequestSense_T sense;
+       CDB_T CDB;
+       unsigned char buffer[6];
+
+       CDB[0] = 0x10;  /* WRITE_FILE_MARKS */
+       CDB[1] = 0;
+       CDB[2] = (unsigned char)(count >> 16);
+       CDB[3] = (unsigned char)(count >> 8);
+       CDB[4] = (unsigned char)count;
+       CDB[5] = 0; 
+
+       /* we really don't care if this command works or not, sigh.  */
+       slow_bzero((char *)&sense, sizeof(RequestSense_T));
+       if (SCSI_ExecuteCommand(fd, Input, &CDB, 6, buffer, 0, &sense) != 0)
+       {
+               return 1;
+       }
+
+       return 0;
 }
 
 
@@ -702,52 +912,57 @@ int WriteFileMarks(DEVICE_TYPE fd,int count) {
  */
 #ifdef HAVE_GET_ID_LUN
 
-static void ReportIDLun(DEVICE_TYPE fd) {
-  scsi_id_t *scsi_id;
+static void ReportIDLun(DEVICE_TYPE fd)
+{
+       scsi_id_t *scsi_id;
 
-  scsi_id=SCSI_GetIDLun(fd);
-  printf("SCSI ID: %d\nSCSI LUN: %d\n",scsi_id->id,scsi_id->lun);
+       scsi_id = SCSI_GetIDLun(fd);
+       printf("SCSI ID: %d\nSCSI LUN: %d\n", scsi_id->id, scsi_id->lun);
 }
 
 #endif
 
 /* we only have one argument: "-f <device>". */
-int main(int argc, char **argv) {
-  DEVICE_TYPE fd;
-  char *filename;
-
-  argv0=argv[0];
-  
-  if (argc != 3) {
-    fprintf(stderr,"argc=%d",argc);
-    usage();
-  }
-
-  if (strcmp(argv[1],"-f")!=0) {
-    usage();
-  }
-  filename=argv[2];
-  
-  fd=SCSI_OpenDevice(filename);
-  
-  /* Now to call the various routines: */
-  ReportInquiry(fd);
-  ReportSerialNumber(fd);
-  ReportTapeAlert(fd);
-  /* ReportConfigPage(fd);  */
-  /* ReportPartitionPage(fd); */
-  ReportBlockLimits(fd); 
-#ifdef HAVE_GET_ID_LUN
-  ReportIDLun(fd);
-#endif
+int main(int argc, char **argv)
+{
+       DEVICE_TYPE fd;
+       char *filename;
+
+       argv0=argv[0];
+
+       if (argc != 3)
+       {
+               fprintf(stderr,"argc=%d",argc);
+               usage();
+       }
 
-  /* okay, we should only report position if the unit is ready :-(. */
-  if (TestUnitReady(fd)) {
-    ReportCompressionPage(fd); 
-    ReadPosition(fd); 
-  }
+       if (strcmp(argv[1],"-f")!=0)
+       {
+               usage();
+       }
+       filename=argv[2];
 
+       fd=SCSI_OpenDevice(filename);
+
+       /* Now to call the various routines: */
+       ReportInquiry(fd);
+       ReportSerialNumber(fd);
+       ReportTapeAlert(fd);
+       ReportBlockLimits(fd); 
+
+#ifdef HAVE_GET_ID_LUN
+       ReportIDLun(fd);
+#endif
 
-  exit(0);
+       /* okay, we should only report position if the unit is ready :-(. */
+       if (TestUnitReady(fd))
+       {
+               ReportCompressionPage(fd); 
+               ReadPosition(fd); 
+               ReportTapeCapacity(fd);         /* only if we have it */
+               ReportConfigPage(fd);           /* only valid if unit is ready. */
+               ReportPartitionPage(fd); 
+       }
+
+       exit(0);
 }
-