Ken's Thoughts...
Recent Pictures

 
Sun, 23 Feb 2003

Blog pix
Although I've taken a few month hiatus from working on my blog, I've decided to try and be more serious with it. To that end, I've added "blog pix" to the bloxsom blogger-cgi I'd been using. This will allow me to provide both a visual outlet as well as my writing.

It'll display the 10 most recent photos in my digital camera archive. I started the archive by copying some photos up from tonight. Sandy pestering the neighbors cat, Sandy at starbucks, the Hippo, and some others. The cat and dog in bed together are pretty funny since the cat hates just about everyone, but he insisted on jumping in bed with Dali.

I'll probably re-write bloxsom from scratch soon. It's really ugly code, I'll put something a little prettier together for the rest of the world soon.

Posted at: 04:34 on 23/02/2003   [ / ] #


Wed, 23 Oct 2002

Bad Day
Today was a bad day at work. I didn't get much sleep because I was up late finishing up the st driver patch, and then it was just radically hectic at work. Blech.

Patch is done. I've submitted a note to Theo offering it. We'll see if he bites. Here it is:

--- /usr/src/sys/scsi/t/st.c	Sun Oct 20 16:24:21 2002
+++ /usr/src/sys/scsi/st.c	Wed Oct 23 14:52:40 2002
@@ -1,4 +1,4 @@
-/*	$OpenBSD: st.c,v 1.29 2001/06/22 14:35:43 deraadt Exp $	*/
+/*	$OpenBSD: st.c,v 1.29 2002/23/10 sallot Exp $	        */
 /*	$NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $	*/
 
 /*
@@ -54,6 +54,12 @@
  * to be depending on whether we expect to retension or not.
  */
 
+/* 
+ * filenumber/block support added for fsf/bsf, open, close, write, read, and eom.
+ *
+ */
+
+
 #include 
 #include 
 #include 
@@ -81,6 +87,11 @@
 #define STUNIT(z)	((minor(z) >> 4)       )
 #define CTLMODE	3
 
+#define NORMAL_MODE     0
+#define NOREW_MODE      1
+#define EJECT_MODE      2
+#define CTRL_MODE       3
+
 #define	ST_IO_TIME	(3 * 60 * 1000)		/* 3 minutes */
 #define	ST_CTL_TIME	(30 * 1000)		/* 30 seconds */
 #define	ST_SPC_TIME	(4 * 60 * 60 * 1000)	/* 4 hours */
@@ -107,6 +118,9 @@
 #define	ST_Q_IGNORE_LOADS	0x0004
 #define	ST_Q_BLKSIZE		0x0008	/* variable-block media_blksize > 0 */
 #define	ST_Q_UNIMODAL		0x0010	/* unimode drive rejects mode select */
+#define ST_Q_NOPREVENT          0x0020  /* does not support PREVENT */
+#define ST_Q_ERASE_NOIMM        0x0040  /* drive rejects ERASE/w Immed bit */
+#define ST_Q_NOFILEMARKS        0x0080  /* can only write 0 filemarks */
 	u_int page_0_size;
 #define	MAX_PAGE_0_SIZE	64
 	struct modes modes[4];
@@ -259,6 +273,12 @@
 	u_int last_dsty;	/* last density opened                */
 	short mt_resid;		/* last (short) resid                 */
 	short mt_erreg;		/* last error (sense key) seen        */
+        /* relative to beginning of tape */
+        daddr_t fileno;         /* current file number */
+	daddr_t blkno;
+        int32_t last_io_resid;
+        int32_t last_ctl_resid;
+
 /*--------------------device/scsi parameters----------------------------------*/
 	struct scsi_link *sc_link;	/* our link to the adpter etc.        */
 /*--------------------parameters reported by the device ----------------------*/
@@ -340,11 +360,15 @@
 #define	ST_2FM_AT_EOD	0x0400	/* write 2 file marks at EOD */
 #define	ST_MOUNTED	0x0800	/* Device is presently mounted */
 #define	ST_DONTBUFFER	0x1000	/* Disable buffering/caching */
+#define ST_EARLYWARN    0x2000  /* Do (deferred) EOM for variable mode */
+
+#define ST_POSUPDATED   0x8000  /* tape position has been updated */
 
 #define	ST_PER_ACTION	(ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
 #define	ST_PER_MOUNT	(ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
 			 ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
-			 ST_2FM_AT_EOD | ST_PER_ACTION)
+			 ST_2FM_AT_EOD | ST_PER_ACTION | ST_EARLYWARN)
+#define ST_INIT_FLAGS    ST_EARLYWARN
 
 struct scsi_inquiry_pattern st_patterns[] = {
 	{T_SEQUENTIAL, T_REMOV,
@@ -388,6 +412,8 @@
 	sc_link->device_softc = st;
 	sc_link->openings = 1;
 
+	st->flags = ST_INIT_FLAGS;
+
 	/*
 	 * Check if the drive is a known criminal and take
 	 * Any steps needed to bring it into line
@@ -558,7 +584,8 @@
 	 * mount session.
 	 */
 	if (!(st->flags & ST_MOUNTED)) {
-		st_mount_tape(dev, flags);
+		if ((error = st_mount_tape(dev, flags)) !=0 )
+                        goto bad;
 		st->last_dsty = dsty;
 	}
 
@@ -590,30 +617,80 @@
 	int mode;
 	struct proc *p;
 {
+        int stxx, error=0;
 	struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
+	struct scsi_link *sclink = st->sc_link;
+	
+	
+	/*
+	 * Make sure that a tape opened in write-only mode will have
+	 * file marks written on it when closed, even if not written to.
+	 *
+	 * This is for SUN compatibility. Actually, the Sun way of
+	 * things is to:
+	 *
+	 *	only write filemarks if there are fmks to be written and
+	 *   		- open for write (possibly read/write)
+	 *		- the last operation was a write
+	 * 	or:
+	 *		- opened for wronly
+	 *		- no data was written (including filemarks)
+	 */
+
+	stxx = st->flags & (ST_WRITTEN | ST_FM_WRITTEN);
+	if (((flags & FWRITE) && stxx == ST_WRITTEN) ||
+	    ((flags & O_ACCMODE) == FWRITE && stxx == 0)) {
+		int nm;
+		error = st_check_eod(st, FALSE, &nm, 0);
+	}
 
-	SC_DEBUG(st->sc_link, SDEV_DB1, ("closing\n"));
-	if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
-		st_write_filemarks(st, 1, 0);
 	switch (STMODE(dev)) {
-	case 0:		/* normal */
+	case NORMAL_MODE:
 		st_unmount(st, NOEJECT, DOREWIND);
 		break;
-	case 3:		/* eject, no rewind */
-		st_unmount(st, EJECT, NOREWIND);
-		break;
-	case 1:		/* no rewind */
-		/* leave mounted unless media seems to have been removed */
-		if (!(st->sc_link->flags & SDEV_MEDIA_LOADED))
-			st_unmount(st, NOEJECT, NOREWIND);
+	case NOREW_MODE:
+	case CTRL_MODE:
+		/*
+		 * Leave mounted unless media seems to have been removed.
+		 *
+		 * Otherwise, if we're to terminate a tape with more than one
+		 * filemark [ and because we're not rewinding here ], backspace
+		 * one filemark so that later appends will see an unbroken
+		 * sequence of:
+		 *
+		 *	file - FMK - file - FMK ... file - FMK FMK (EOM)
+		 */
+		if ((sclink->flags & SDEV_MEDIA_LOADED) == 0) {
+			st_unmount(st, NOEJECT,DOREWIND);
+		} else if (error == 0) {
+			/*
+			 * ST_WRITTEN was preserved from above.
+			 *
+			 * All we need to know here is:
+			 *
+			 *	Were we writing this tape and was the last
+			 *	operation a write?
+			 *
+			 *	Are there supposed to be 2FM at EOD?
+			 *
+			 * If both statements are true, then we backspace
+			 * one filemark.
+			 */
+			stxx |= (st->flags & ST_2FM_AT_EOD);
+			if ((flags & FWRITE) != 0 &&
+			    (stxx == (ST_2FM_AT_EOD|ST_WRITTEN))) {
+				error = st_space(st, -1, SP_FILEMARKS, 0);
+			}
+		}
 		break;
-	case 2:		/* rewind, eject */
-		st_unmount(st, EJECT, DOREWIND);
+	case EJECT_MODE:
+		st_unmount(st, EJECT,DOREWIND);
 		break;
 	}
-	st->sc_link->flags &= ~SDEV_OPEN;
 
-	return 0;
+	sclink->flags &= ~SDEV_OPEN;
+
+	return (error);
 }
 
 /*
@@ -715,6 +792,7 @@
 	st->flags &= ~ST_NEW_MOUNT;
 	st->flags |= ST_MOUNTED;
 	sc_link->flags |= SDEV_MEDIA_LOADED;	/* move earlier? */
+        st->blkno = st->fileno = (daddr_t) 0;
 
 	return 0;
 }
@@ -741,8 +819,12 @@
 		st_rewind(st, 0, SCSI_IGNORE_NOT_READY);
 	scsi_prevent(sc_link, PR_ALLOW,
 	    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
-	if (eject)
+	if (eject) {
 		st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY);
+                st->blkno = st->fileno = (daddr_t) -1;
+	} else {
+	  st->blkno = st->fileno = (daddr_t) 0;
+        }
 	st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
 	sc_link->flags &= ~SDEV_MEDIA_LOADED;
 }
@@ -1065,6 +1147,8 @@
 			_lto3b(bp->b_bcount / st->blksize, cmd.len);
 		} else
 			_lto3b(bp->b_bcount, cmd.len);
+                /* clear position updated indicator */
+                st->flags &= ~ST_POSUPDATED;
 
 		/*
 		 * go ask the adapter to do all this for us
@@ -1113,7 +1197,7 @@
 	struct proc *p;
 {
 	int error = 0;
-	int unit;
+	int unit,count;
 	int number, nmarks, dsty;
 	int flags;
 	struct st_softc *st;
@@ -1156,6 +1240,8 @@
 		g->mt_mdensity[1] = st->modes[1].density;
 		g->mt_mdensity[2] = st->modes[2].density;
 		g->mt_mdensity[3] = st->modes[3].density;
+		g->mt_fileno = st->fileno;
+		g->mt_blkno = st->blkno;
 		if (st->flags & ST_READONLY)
 			g->mt_dsreg |= MT_DS_RDONLY;
 		if (st->flags & ST_MOUNTED)
@@ -1183,11 +1269,11 @@
 		case MTBSF:	/* backward space file */
 			number = -number;
 		case MTFSF:	/* forward space file */
-			error = st_check_eod(st, FALSE, &nmarks, flags);
-			if (!error)
-				error = st_space(st, number - nmarks,
-				    SP_FILEMARKS, flags);
-			break;
+                       error = st_check_eod(st, FALSE, &nmarks, flags);
+                        if (!error)
+                                error = st_space(st, number - nmarks,
+                                    SP_FILEMARKS, flags);
+                        break;
 		case MTBSR:	/* backward space record */
 			number = -number;
 		case MTFSR:	/* forward space record */
@@ -1208,10 +1294,27 @@
 			if (!error)
 				error = st_load(st, LD_LOAD, flags);
 			break;
-		case MTEOM:	/* forward space to end of media */
-			error = st_check_eod(st, FALSE, &nmarks, flags);
-			if (!error)
-				error = st_space(st, 1, SP_EOM, flags);
+		case MTEOM:   /* rather than call SP_EOM and lose
+			       * the file count, we'll just FSF once
+			       * per file until we reach the end of the
+			       * tape.  
+			       */ 
+		        error=0;
+			count=0;
+			while ( (error==0) && (count<2000) ) { 
+			   /* do we think there'll be more than 2k filesets on a tape??  god I hope not */ 
+		  	   error = st_check_eod(st, FALSE, &nmarks, flags);
+			   if (!error)
+				error = st_space(st, 1, SP_FILEMARKS, flags);
+			   count++;
+			}
+			if (error==EIO)   /* 
+					   * good, we hit the end of the tape, BUT
+					   * we don't want to produce an error output
+					   * just for doing what we're supposed to..
+					   *
+					   */
+			  error=0;
 			break;
 		case MTCACHE:	/* enable controller cache */
 			st->flags &= ~ST_DONTBUFFER;
@@ -1575,7 +1678,7 @@
 {
 	struct scsi_space cmd;
 	int error;
-
+	
 	switch (what) {
 	case SP_BLKS:
 		if (st->flags & ST_PER_ACTION) {
@@ -1603,7 +1706,7 @@
 		}
 		break;
 	case SP_FILEMARKS:
-		if (st->flags & ST_EIO_PENDING) {
+	  if (st->flags & ST_EIO_PENDING) { /* check scsi_base */
 			if (number > 0) {
 				/* pretend we just discovered the error */
 				st->flags &= ~ST_EIO_PENDING;
@@ -1641,8 +1744,47 @@
 	cmd.byte2 = what;
 	_lto3b(number, cmd.number);
 
-	return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+	st->flags &= ~ST_POSUPDATED;
+	st->last_ctl_resid = 0;
+
+        error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
 	    sizeof(cmd), 0, 0, 0, ST_SPC_TIME, NULL, flags);
+
+         if ( (error == 0) || ((error==EIO) && (number<0)) ) {
+	       /* requests still in command queue */
+               if (number>0) { /* we're counting forward */
+                   number = number - st->last_ctl_resid; 
+		} else if (number<0) {  /* we're counting down sir! */
+		  number = number + st->last_ctl_resid;
+		}
+		if (what == SP_BLKS) {
+			if (st->blkno != -1) {
+				st->blkno += number;
+			}
+		} else if (what == SP_FILEMARKS) {  /* was != -1 */
+			if (st->fileno > -1) {
+                                st->fileno += number;
+				if (number > 0) {
+	  				st->blkno = 0;
+				} else if (number < 0) {
+					st->blkno = -1;
+				}
+			}
+		} else if (what == SP_EOM) { 
+			/*
+			 * This loses us relative position. 
+			 * But, we should never be here.
+			 */
+		  	      	st->fileno = st->blkno = -1;  
+		}
+		if (st->flags & ST_POSUPDATED) { /* if we're here, there's an error.  most likely end of tape data */
+		  error=EIO;
+		}
+
+	 }
+
+	return (error);
+
 }
 
 /*
@@ -1654,6 +1796,7 @@
 	int flags;
 	int number;
 {
+        int error;
 	struct scsi_write_filemarks cmd;
 
 	/*
@@ -1680,8 +1823,13 @@
 	cmd.opcode = WRITE_FILEMARKS;
 	_lto3b(number, cmd.number);
 
-	return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+	error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
 	    sizeof(cmd), 0, 0, 0, ST_IO_TIME * 4, NULL, flags);
+        if (error == 0 && st->fileno != -1) {
+		st->fileno += number;
+	}
+	return (error);
+
 }
 
 /*
@@ -1778,9 +1926,20 @@
 	cmd.opcode = REWIND;
 	cmd.byte2 = immediate;
 
-	return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+	error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
 	    sizeof(cmd), 0, 0, ST_RETRIES,
 	    immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
+        if (error) {
+		printf("%s: error %d trying to rewind\n",
+		    st->sc_dev.dv_xname, error);
+		/* lost position */
+		st->fileno = st->blkno = -1;
+	} else {
+		st->fileno = st->blkno = 0;
+	}
+	return (error);
+
+
 }
 
 /*
@@ -1806,19 +1965,39 @@
 		info = _4btol(sense->info);
 	else
 		info = xs->datalen;	/* bad choice if fixed blocks */
-	if ((sense->error_code & SSD_ERRCODE) != 0x70)
-		return SCSIRET_CONTINUE; /* let the generic code handle it */
+
+	if ((sense->error_code & SSD_ERRCODE) != 0x70) {
+
+	  return SCSIRET_CONTINUE; /* let the generic code handle it */
+	}
+
+        xs->resid = info;
+
 	if (st->flags & ST_FIXEDBLOCKS) {
-		xs->resid = info * st->blksize;
+	  if (bp) {
+		     xs->resid *=  st->blksize;
+                     st->last_io_resid = xs->resid;
+	  } else {
+	             st->last_ctl_resid = xs->resid;
+	  }
+
 		if (sense->flags & SSD_EOM) {
-			st->flags |= ST_EIO_PENDING;
-			if (bp)
+	  	        st->flags |= ST_EIO_PENDING;
+ 			if (bp) {
 				bp->b_resid = xs->resid;
+                                st->last_io_resid = xs->resid;
+                        } else {
+			        st->last_ctl_resid = xs->resid;
+                        }
 		}
 		if (sense->flags & SSD_FILEMARK) {
 			st->flags |= ST_AT_FILEMARK;
-			if (bp)
+			if (bp) {
 				bp->b_resid = xs->resid;
+				st->last_io_resid = xs->resid;
+                        } else {
+			        st->last_ctl_resid = xs->resid;
+                        }
 		}
 		if (sense->flags & SSD_ILI) {
 			st->flags |= ST_EIO_PENDING;
@@ -1840,6 +2019,19 @@
 			    !(sc_link->flags & SDEV_MEDIA_LOADED))
 				st->blksize -= 512;
 		}
+		if (sense->flags & SSD_EOM) {
+		  st->flags |= ST_EIO_PENDING;
+		  if (bp) {
+				/*
+				 * Grotesque as it seems, the few times
+				 * I've actually seen a non-zero resid,
+				 * the tape drive actually lied and had
+				 * written all the data!
+				 */
+	
+		    bp->b_resid = 0;
+		  }
+		}
 		/*
 		 * If no data was tranfered, do it immediatly
 		 */
@@ -1853,20 +2045,36 @@
 			}
 		}
 	} else {		/* must be variable mode */
-		xs->resid = xs->datalen;	/* to be sure */
-		if (sense->flags & SSD_EOM)
+
+		if (bp) {
+		  st->last_io_resid = xs->resid;
+		} else {
+		  st->last_ctl_resid = xs->resid;
+		}
+
+		if (sense->flags & SSD_EOM) {
 			return EIO;
+		}
+
+		/* xs->resid = xs->datalen; */	/* to be sure we've lost our mind.. */
+
 		if (sense->flags & SSD_FILEMARK) {
 			if (bp)
 				bp->b_resid = bp->b_bcount;
+			if (st->fileno != (daddr_t) -1) {
+			  st->fileno++;
+			  st->blkno=0;
+			  st->flags |= ST_POSUPDATED;
+			}
 			return 0;
 		}
+
 		if (sense->flags & SSD_ILI) {
 			if (info < 0) {
 				/*
 				 * the record was bigger than the read
 				 */
-				if ((xs->flags & SCSI_SILENT) == 0)
+				if ((xs->flags & SCSI_SILENT) == 0) 
 					printf("%s: %d-byte record too big\n",
 					    st->sc_dev.dv_xname,
 					    xs->datalen - info);
@@ -1882,8 +2090,15 @@
 					    xs->datalen);
 					return (EIO);
 				}
+			} else {
+			  if (st->blkno != (daddr_t) -1) {
+			    st->blkno++;
+			    st->flags |= ST_POSUPDATED;
+			  }
 			}
-			xs->resid = info;
+			/* let's go ahead and corrupt the results why don't we?? */
+			/*			xs->resid=info; */
+
 			if (bp)
 				bp->b_resid = info;
 			return 0;
@@ -1892,6 +2107,7 @@
 	key = sense->flags & SSD_KEY;
 
 	if (key == 0x8) {
+	  printf("key = 0x8\n");
 		/*
 		 * This quirk code helps the drive read the
 		 * first tape block, regardless of format.  That
@@ -1905,13 +2121,28 @@
 		} else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
 			st->flags |= ST_BLANK_READ;
 			xs->resid = xs->datalen;
+			if (st->blkno != (daddr_t) -1) {
+			  if (st->blksize>0) {
+			    st->blkno += (xs->datalen / st->blksize);
+			    st->flags |= ST_POSUPDATED;
+			  }
+                        }
 			if (bp) {
 				bp->b_resid = xs->resid;
 				/* return an EOF */
 			}
+			/* lost position */
+			st->fileno = st->blkno = -1;
 			return 0;
 		}
 	}
+
+	  /* trap this before it gets ugly. */
+      	if (sense->error_code & SSD_EOM) {
+  	     st->flags &= ~ST_EIO_PENDING;
+	     st->flags |= ST_POSUPDATED;
+	}
+
 	return SCSIRET_CONTINUE;
 }
 
@@ -1981,3 +2212,4 @@
 	/* Not implemented. */
 	return ENXIO;
 }
+

Well, Jim Greenlee's in town. I'm supposed to grab dinner with him, so I better call it a night..

Posted at: 22:49 on 23/10/2002   [ / ] #


Mon, 21 Oct 2002

She sells C Shells by the C Shore
So, I dropped the scsi card into urchin a few days ago. Dropped the tape drive on it. Thought I had backups working perfectly. I was wrong...

The openbsd mt utility doesn't return an error code when you reach the end of the tape. Whoops.

Also, the OpenBSD scsi-tape driver does not implement file number counting and block counting. Personally, I don't care about block counting, but I do really want file counting..

So, I've spent some time hacking on the openbsd scsi tape driver today. The hacking is slow because it requires a recompile of the kernel for any change, ugh. I'm integrating the file number code from the netbsd scsi-tape driver and putting in the openbsd scsi tape driver. It's still VERY beta, but I have a preliminary version working (mt fsf correctly counts numbers until you hit eom).

If you care, here's the current patches. The first patch is for the mt utility to provide displaying of the file number. The second is for the 3.0_stable kernel st driver. It's funny, it looks like back in 1997 someone thought about adding this support since the "mt_fileno" construct was added to the scsi tape driver..

I'll continue working on them until I'm happy with the change, then I'll go ahead and submit the patches to theo and company..

Patch for the mt utility

--- /usr/src/bin/mt/t/mt.c	Sun Oct 20 16:59:04 2002
+++ /usr/src/bin/mt/mt.c	Sun Oct 20 17:01:35 2002
@@ -261,6 +261,7 @@
 	printreg("ds", bp->mt_dsreg, mt->t_dsbits);
 	printreg("\ner", bp->mt_erreg, mt->t_erbits);
 	(void)putchar('\n');
+	(void)printf("file number=%d\n",bp->mt_fileno);
 	(void)printf("blocksize: %d (%d, %d, %d, %d)\n",
 		bp->mt_blksiz, bp->mt_mblksiz[0], bp->mt_mblksiz[1],
 		bp->mt_mblksiz[2], bp->mt_mblksiz[3]);

Patch for the OpenBSD 3.0_stable scsi-tape kernel driver
--- /usr/src/sys/scsi/t/st.c	Sun Oct 20 16:24:21 2002
+++ /usr/src/sys/scsi/st.c	Sun Oct 20 19:34:44 2002
@@ -1,3 +1,6 @@
+/* to still do -- fsf rewinding past eom switches fileno to a negative
+   #..  Should be in the st_space function */
+
 /*	$OpenBSD: st.c,v 1.29 2001/06/22 14:35:43 deraadt Exp $	*/
 /*	$NetBSD: st.c,v 1.71 1997/02/21 23:03:49 thorpej Exp $	*/
 
@@ -259,6 +262,12 @@
 	u_int last_dsty;	/* last density opened                */
 	short mt_resid;		/* last (short) resid                 */
 	short mt_erreg;		/* last error (sense key) seen        */
+        /* relative to beginning of tape */
+        daddr_t fileno;         /* current file number */
+	daddr_t blkno;
+        int32_t last_io_resid;
+        int32_t last_ctl_resid;
+
 /*--------------------device/scsi parameters----------------------------------*/
 	struct scsi_link *sc_link;	/* our link to the adpter etc.        */
 /*--------------------parameters reported by the device ----------------------*/
@@ -340,6 +349,7 @@
 #define	ST_2FM_AT_EOD	0x0400	/* write 2 file marks at EOD */
 #define	ST_MOUNTED	0x0800	/* Device is presently mounted */
 #define	ST_DONTBUFFER	0x1000	/* Disable buffering/caching */
+#define ST_POSUPDATED   0x8000  /* tape position has been updated */
 
 #define	ST_PER_ACTION	(ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
 #define	ST_PER_MOUNT	(ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
@@ -715,6 +725,7 @@
 	st->flags &= ~ST_NEW_MOUNT;
 	st->flags |= ST_MOUNTED;
 	sc_link->flags |= SDEV_MEDIA_LOADED;	/* move earlier? */
+        st->blkno = st->fileno = (daddr_t) 0;
 
 	return 0;
 }
@@ -741,8 +752,12 @@
 		st_rewind(st, 0, SCSI_IGNORE_NOT_READY);
 	scsi_prevent(sc_link, PR_ALLOW,
 	    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
-	if (eject)
+	if (eject) {
 		st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY);
+                st->blkno = st->fileno = (daddr_t) -1;
+	} else {
+	  st->blkno = st->fileno = (daddr_t) 0;
+        }
 	st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
 	sc_link->flags &= ~SDEV_MEDIA_LOADED;
 }
@@ -1065,6 +1080,8 @@
 			_lto3b(bp->b_bcount / st->blksize, cmd.len);
 		} else
 			_lto3b(bp->b_bcount, cmd.len);
+                /* clear position updated indicator */
+                st->flags &= ~ST_POSUPDATED;
 
 		/*
 		 * go ask the adapter to do all this for us
@@ -1156,6 +1173,8 @@
 		g->mt_mdensity[1] = st->modes[1].density;
 		g->mt_mdensity[2] = st->modes[2].density;
 		g->mt_mdensity[3] = st->modes[3].density;
+		g->mt_fileno = st->fileno;
+		g->mt_blkno = st->blkno;
 		if (st->flags & ST_READONLY)
 			g->mt_dsreg |= MT_DS_RDONLY;
 		if (st->flags & ST_MOUNTED)
@@ -1641,8 +1660,37 @@
 	cmd.byte2 = what;
 	_lto3b(number, cmd.number);
 
-	return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+	st->flags &= ~ST_POSUPDATED;
+	st->last_ctl_resid = 0;
+
+        error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
 	    sizeof(cmd), 0, 0, 0, ST_SPC_TIME, NULL, flags);
+
+         if (error == 0 && (st->flags & ST_POSUPDATED) == 0) {
+		number = number - st->last_ctl_resid;
+		if (what == SP_BLKS) {
+			if (st->blkno != -1) {
+				st->blkno += number;
+			}
+		} else if (what == SP_FILEMARKS) {
+			if (st->fileno != -1) {
+				if (number > 0) {
+				  /* ks */
+	  			        st->fileno += number;
+					st->blkno = 0;
+				} else if (number < 0) {
+					st->blkno = -1;
+				}
+			}
+		} else if (what == SP_EOM) {
+			/*
+			 * This loses us relative position.
+			 */
+		  			st->fileno = st->blkno = -1; 
+		}
+	}
+	return (error);
+
 }
 
 /*
@@ -1654,6 +1702,7 @@
 	int flags;
 	int number;
 {
+        int error;
 	struct scsi_write_filemarks cmd;
 
 	/*
@@ -1680,8 +1729,13 @@
 	cmd.opcode = WRITE_FILEMARKS;
 	_lto3b(number, cmd.number);
 
-	return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+	error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
 	    sizeof(cmd), 0, 0, 0, ST_IO_TIME * 4, NULL, flags);
+        if (error == 0 && st->fileno != -1) {
+		st->fileno += number;
+	}
+	return (error);
+
 }
 
 /*
@@ -1778,9 +1832,20 @@
 	cmd.opcode = REWIND;
 	cmd.byte2 = immediate;
 
-	return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
+	error=scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
 	    sizeof(cmd), 0, 0, ST_RETRIES,
 	    immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
+        if (error) {
+		printf("%s: error %d trying to rewind\n",
+		    st->sc_dev.dv_xname, error);
+		/* lost position */
+		st->fileno = st->blkno = -1;
+	} else {
+		st->fileno = st->blkno = 0;
+	}
+	return (error);
+
+
 }
 
 /*
@@ -1810,15 +1875,23 @@
 		return SCSIRET_CONTINUE; /* let the generic code handle it */
 	if (st->flags & ST_FIXEDBLOCKS) {
 		xs->resid = info * st->blksize;
+		st->last_io_resid = xs->resid;
 		if (sense->flags & SSD_EOM) {
 			st->flags |= ST_EIO_PENDING;
 			if (bp)
 				bp->b_resid = xs->resid;
+		} else {
+		                st->last_ctl_resid = xs->resid;
 		}
 		if (sense->flags & SSD_FILEMARK) {
 			st->flags |= ST_AT_FILEMARK;
 			if (bp)
 				bp->b_resid = xs->resid;
+                        if (st->fileno != (daddr_t) -1) {
+       			        st->fileno++;
+				st->blkno=0;
+				st->flags |= ST_POSUPDATED;
+			}
 		}
 		if (sense->flags & SSD_ILI) {
 			st->flags |= ST_EIO_PENDING;
@@ -1853,10 +1926,20 @@
 			}
 		}
 	} else {		/* must be variable mode */
+	       if (bp) {
+		 st->last_io_resid = xs->resid;
+	       } else {
+		 st->last_ctl_resid = xs->resid;
+	       }
 		xs->resid = xs->datalen;	/* to be sure */
 		if (sense->flags & SSD_EOM)
 			return EIO;
 		if (sense->flags & SSD_FILEMARK) {
+		        if (st->fileno != (daddr_t) -1) {
+        	        	st->fileno++;
+				st->blkno=0;
+				st->flags |= ST_POSUPDATED;
+			}
 			if (bp)
 				bp->b_resid = bp->b_bcount;
 			return 0;
@@ -1909,6 +1992,8 @@
 				bp->b_resid = xs->resid;
 				/* return an EOF */
 			}
+			/* lost position */
+			st->fileno = st->blkno = (daddr_t) -1;
 			return 0;
 		}
 	}

Posted at: 00:51 on 21/10/2002   [ / ] #



 
Articles
diary
eassays
travel
code

My photo album
My resume

Presentations and Papers

SAP Filtering 1998
Border Manager 1999
Astronomy Status 2002
Astronomy Update 2003
Linux on a CTX FC2A300
Honeynet Challenge entry