Kai Makisara wrote:
> The "current" st.c driver is what is in 2.3.99-pre1 (it seems that you

Okay, I'll take a look at that. 

> describe (and some other, too). These changes were initiated by
> Michael Schaefer and it seems that we have done parallel work. If you have

That's okay. My goal at the moment is learning SCSI tape control. Most of my
"patch" is to add debugging output to see what's happening (e.g., dumping out
CDB, mode sense, and medium partition page contents). 

> The new version is based on the principle that the length of the mode page
> read from the drive is used also for writing it back to the drive.

The problem is that this does not work with the Seagate DDS-4 drives, and
probably not with other Seagate DDS[234] type drives. I quote from the Seagate
DDS-4 technical documentation:

"If no additional partition is to be defined or if going from a dual-partition
format to a single-partition format, the Page Length field must be set to 6,
which indicates that 6 parameter bytes follow the page length byte. If an
additional partition is to be defined (dual-partition), this field is set to
8."

If there is not a second partition, a length of 6 is reported by the mode
sense. Feeding a length of 6 back into the mode select in order to create the
partition obviously isn't going to work. The Seagate reports an error. 

Similarly, when there is a second partition, and you want to zap it, the
Seagate has reported a Page Length of 8. Trying to feed that back into the
Seagate results in the Seagate reporting an error. (Yes, my initial effort
tried that -- anything other than 6 causes the Seagate to barf). 

I assume that you're doing something a little more sophisticated than just
feeding the length back, if your code still works with DDS drives. As soon as
the 2.3.99pre1 kernel finishes coming down, I'll take a look. 

Whoops. Just took a look. Don't see any way that what you have will work with
the Seagate. But I'll try it and see what happens. 

*****POSSIBILITY: from mode sense page 11h: 
  page length==6 && additional partitions defined ==0: page_format=OLD_DDS
  page length==8 && additional partitions defined ==1: page_format=OLD_DDS
  otherwise:
    page_format=SCSI3
*****
 
If the page format is OLD_DDS, you stuff a 6 into the page_length field to zap
partitions, and an 8 if you are creating/redefining the second partition.
Otherwise you do not touch it.

Similarly, if OLD_DDS, you stuff the length into Partition Size Descriptor 0.
Otherwise
you stuff 0xffff into Partition Size Descriptor 0, and stuff the size of the
new partition 1 into Partition Size Descriptor 1.  

I was not aware of the SDT-7000 using the new-style commands. Do you happen to
know off-hand whether the SDT-7000 reports a length greater than six for a
medium partition page mode sense where there is no second partition?
Unfortunately I do not have access to an SDT-7000 for testing purposes. Sony
does not appear to have any SCSI-level documentation for the drive on their
web site either. 

> proper settings in the other fields this seems to work with all of the
> drives that the previous one has worked plus many others. The new method
> is also compatible with SCSI-3 and Mammoth, SLR, and VXA documentation. I
> have not seen any AIT documents.

I verified this morning that your approach (the 0xffff for the first
partition, the size for the second partition) will work with the SLR/MLR. I
will have to re-validate later today whether that works with the Exabyte
Mammoth. I suspect it will. Yep, it works. We have an AIT drive somewhere
around here, I'll see whether that works too. The Seagate AIT document isn't
clear on that, but it should. But I fed the VXA the old-style DAT parameters
and successfully partitioned the tape, so I'm not sure whether the new method
will work with the VXA. I don't have it hooked to my machine at the moment
because it dumbs my SCSI bus down to plain SCSI-2 (I'm usually running LVD),
but I will do so later today, after I finish compiling a 2.3.99pre1 kernel. (I
can't really test this with 2.2 because I've already patched st.c to detect
that only 1 partition can be created and default to the old-style format if
so). 

> Basically the st.c driver has a very long time understood more than two
> partitions (up to the ST_NBR_PARTITIONS which defaults to 4). It is only
> MTMKPART that is limited to two partitions.

In reality, what it does is what I need. But it never hurts to think about the
future.

BTW, attached is a patch for the 2.2.14 driver that incorporates the changes
that I discussed above. I have verified that this works with both the Seagate
DDS-4 (old-style DAT partition page) and the Exabyte Mammoth (SCSI-3 style
partition page). Discard my old patch because it definitely will NOT work with
the AIT, and won't work with the SLR-50 either, as well as reversing the order
of the partitions for the Exabyte. I have not yet had the chance to check the
Excrix VXA or SLR-50 with these, and the only AIT drive around is in the
machine of someone who has seniority over me :-}. These patches won't apply to
the 2.3.99 driver because you've overhauled/simplified the thing so much, I'll
go after the 2.3.99 driver as soon as I can get it compiled and running here
on my system. 

Oh -- I apologize in advance for the quantity of debugging output code in this
patch. Without the debugging output lines, it's maybe a dozen lines of changed
code. But I had to figure out what was going wrong before I could fix it :-}. 

-- 
Eric Lee Green                         [EMAIL PROTECTED]
Software Engineer                      Visit our Web page:
Enhanced Software Technologies, Inc.   http://www.estinc.com/
(602) 470-1115 voice                   (602) 470-1116 fax
--- linux/drivers/scsi/st.c.orig        Sat May 22 14:51:26 1999
+++ linux/drivers/scsi/st.c     Thu Mar 16 11:16:05 2000
@@ -34,7 +34,7 @@
 
 /* The driver prints some debugging information on the console if DEBUG
    is defined and non-zero. */
-#define DEBUG 0
+#define DEBUG 1
 
 /* The message level for the debug messages is currently set to KERN_NOTICE
    so that people can easily see the messages. Later when the debugging messages
@@ -2513,6 +2513,12 @@
       return (-EIO);
 
     memset (scmd, 0, 10);
+#if DEBUG
+    if (debugging) {
+      printk(ST_DEB_MSG "st%d: scsi_level=%d (SCSI_2=%d)\n",dev,
+            (STp->device)->scsi_level,SCSI_2);
+    }
+#endif
     if ((STp->device)->scsi_level < SCSI_2) {
       scmd[0] = QFA_REQUEST_BLOCK;
       scmd[4] = 3;
@@ -2522,6 +2528,15 @@
       if (!logical && !STp->scsi2_logical)
        scmd[1] = 1;
     }
+#if DEBUG
+    if (debugging) {
+      int i;
+      for (i=0;i<10;i++) {
+       printk(ST_DEB_MSG "st%d: get_location: cmd[%d]=0x%x\n",
+              dev,i,scmd[i]);
+      }
+    }
+#endif
     SCpnt = st_do_scsi(NULL, STp, scmd, 20, STp->timeout, MAX_READY_RETRIES, TRUE);
     if (!SCpnt)
       return (-EBUSY);
@@ -2763,59 +2778,168 @@
 #endif
     }
 
+#if DEBUG
+    if (debugging)
+      printk(ST_DEB_MSG "st%d: Number of partitions %d.\n",dev,result);
+#endif
     return result;
 }
 
 
 /* Partition the tape into two partitions if size > 0 or one partition if
    size == 0 */
+
+/* Extensive changes made March 2000 by Eric Lee Green <[EMAIL PROTECTED]>
+ * in order to produce a SCSI-3-compliant Medium Partition Page in the
+ * case where we can have more than 1 additional partition (i.e., for most
+ * new tape drives, though this was tested with the Exabyte Mammoth 2).
+ * This perhaps is not the best way of detirmining whether I need to send
+ * the DAT-style medium partition page or the SCSI-3 style medium partition
+ * page, but it's the best that I can do :-(. 
+ */
        static int
 partition_tape(struct inode * inode, int size)
 {
     int dev = TAPE_NR(inode->i_rdev), result;
     int length;
+    int scsi3=0;
     Scsi_Tape *STp;
     Scsi_Cmnd * SCpnt = NULL;
     unsigned char cmd[10], *bp;
 
-    if ((result = nbr_partitions(inode)) < 0)
+    if ((result = nbr_partitions(inode)) < 0) {
+#if DEBUG
+      if (debugging) 
+       printk(ST_DEB_MSG "st%d: nbr_partitions=%d\n", dev, result);
+#endif
       return result;
+    }
     STp = &(scsi_tapes[dev]);
 
     /* The mode page is in the buffer. Let's modify it and write it. */
     bp = &((STp->buffer)->b_data[0]);
+#if DEBUG
+    if (debugging)
+    {
+      int i,j;
+      for (i=1; i < MODE_HEADER_LENGTH+10; i++) {
+       if (i < MODE_HEADER_LENGTH) {
+         printk(ST_DEB_MSG "st%d: sense mode_header[%d]=0x%x\n",dev,i,bp[i]);
+       } else {
+         j=i-MODE_HEADER_LENGTH;
+         printk(ST_DEB_MSG "st%d: sense mode_sense[%d]=0x%x\n",dev,j,bp[i]);
+       }
+      }
+    }
+#endif 
+    scsi3=1; /* default to scsi3.... */
+    if (bp[MODE_HEADER_LENGTH+3]==1 && bp[MODE_HEADER_LENGTH+1]==8) {
+#if DEBUG
+        if (debugging)
+            printk(ST_DEB_MSG "st%d: 2 partition, length 8, using old format.\n",dev);
+#endif
+
+       scsi3=0; /* nope, it's the older dds. Maybe. */
+    } else if (bp[MODE_HEADER_LENGTH+3]==0 && bp[MODE_HEADER_LENGTH+1]==6) {
+#if DEBUG
+        if (debugging)
+           printk(ST_DEB_MSG "st%d: 1 partition, length 6, using old format.\n",dev);
+#endif
+        scsi3=0;  /* older dds. Maybe. */
+    }
+   
+    if (bp[MODE_HEADER_LENGTH + 2] > 1) {
+#if DEBUG
+      if (debugging)
+         printk(ST_DEB_MSG "st%d: Can do more than 2 partitions, using NEW 
+format.\n",dev);
+#endif
+      scsi3=1; /* well, if we can do more than 1 partition, we KNOW we ain't old 
+DDS... */
+    }
+ 
     if (size <= 0) {
-      length = 8;
+      bp[MODE_HEADER_LENGTH + 4] = 0x30;   /* IDP | PSUM = MB */
+      if (!scsi3) {/* we must be doing a dat or older SLR... */
+       length = 8;
+      } else {
+       length=bp[MODE_HEADER_LENGTH+1]+2; /* length field in the mode sense */
+       /* bp[MODE_HEADER_LENGTH + 4] = 0x10;  /* PSUM = MB. Otherwise, 1 part. */
+      }
       bp[MODE_HEADER_LENGTH + 3] = 0;
+      if (scsi3) {   /* to zap these in SCSI 3, must have length = 0? */
+       bp[MODE_HEADER_LENGTH + 8] = 0xff;
+       bp[MODE_HEADER_LENGTH + 9] = 0xff;
+        bp[MODE_HEADER_LENGTH + 10] = 0;
+        bp[MODE_HEADER_LENGTH + 11] = 0;
+      }
 #if DEBUG
       if (debugging)
        printk(ST_DEB_MSG "st%d: Formatting tape with one partition.\n", dev);
 #endif
     }
     else {
-      length = 10;
+      if (!scsi3) {
+       length = 10;
+      } else {
+       length=bp[MODE_HEADER_LENGTH+1]+2;
+      }
       bp[MODE_HEADER_LENGTH + 3] = 1;
       bp[MODE_HEADER_LENGTH + 8] = (size >> 8) & 0xff;
       bp[MODE_HEADER_LENGTH + 9] = size & 0xff;
+      bp[MODE_HEADER_LENGTH + 4] = 0x30;   /* IDP | PSUM = MB */
+      if (scsi3) {
+       bp[MODE_HEADER_LENGTH +10]=bp[MODE_HEADER_LENGTH + 8];
+        bp[MODE_HEADER_LENGTH +11]=bp[MODE_HEADER_LENGTH + 9];
+        bp[MODE_HEADER_LENGTH +8] = 0xff;  /* rest of tape for part. 0 */
+        bp[MODE_HEADER_LENGTH +9]=  0xff;  /* rest of tape for part. 0 */
+      }
 #if DEBUG
       if (debugging)
        printk(ST_DEB_MSG "st%d: Formatting tape with two partition (1 = %d MB).\n",
               dev, size);
 #endif
     }
+#if DEBUG
+    if (debugging)
+      printk(ST_DEB_MSG "st%d: Length=%d\n",dev,length);
+#endif
     bp[MODE_HEADER_LENGTH + 6] = 0;
     bp[MODE_HEADER_LENGTH + 7] = 0;
-    bp[MODE_HEADER_LENGTH + 4] = 0x30;   /* IDP | PSUM = MB */
+
 
     bp[0] = 0;
     bp[1] = 0;
     bp[MODE_HEADER_LENGTH] &= 0x3f;
     bp[MODE_HEADER_LENGTH + 1] = length - 2;
 
+#if DEBUG
+    if (debugging)
+    {
+      int i,j;
+      for (i=0; i < MODE_HEADER_LENGTH+length; i++) {
+       if (i < MODE_HEADER_LENGTH) {
+         printk(ST_DEB_MSG "st%d: mode_header[%d]=0x%x\n",dev,i,bp[i]);
+       } else {
+         j=i-MODE_HEADER_LENGTH;
+         printk(ST_DEB_MSG "st%d: mode_sense[%d]=0x%x\n",dev,j,bp[i]);
+       }
+      }
+    }
+#endif 
+
     memset(cmd, 0, 10);
     cmd[0] = MODE_SELECT;
     cmd[1] = 0x10;
     cmd[4] = length + MODE_HEADER_LENGTH;
+
+#if DEBUG
+   if (debugging)
+   {
+     int i;
+     for (i=0; i< 6; i++) {
+        printk(ST_DEB_MSG "st%d: cdb[%d]=0x%x\n",dev,i,cmd[i]);
+    }
+  }
+#endif
 
     SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->long_timeout,
                       MAX_READY_RETRIES, TRUE);

Reply via email to