From akiyama@kme.mei.co.jp  Wed Jul  8 02:44:43 1998
Received: from vcgate2.mei.co.jp (vcgate2.mei.co.jp [202.32.14.52])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id CAA14413
          for <FreeBSD-gnats-submit@freebsd.org>; Wed, 8 Jul 1998 02:44:39 -0700 (PDT)
          (envelope-from akiyama@kme.mei.co.jp)
Received: by vcgate2.mei.co.jp (8.9.0/3.7W) with ESMTP
	id RAA16601
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 8 Jul 1998 17:43:44 +0900 (JST)
Received: by vcgate3.mei.co.jp (8.9.0/3.7W) with ESMTP
	id RAA24581
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 8 Jul 1998 17:39:27 +0900 (JST)
Received: by vcmei.vanc.mei.co.jp (8.8.7/5.9:4.9:vcmei:980629)
	id RAA05236; Wed, 8 Jul 1998 17:38:25 +0900 (JST)
Received: by kmegate.kme.mei.co.jp (4.1/5.5:4.6:kmegate:980629)
	id AA25557; Wed, 8 Jul 98 17:39:58 JST
Message-Id: <9807080839.AA25557@kmegate.kme.mei.co.jp>
Date: Wed, 8 Jul 98 17:39:58 JST
From: Shunsuke Akiyama <akiyama@kme.mei.co.jp>
Reply-To: akiyama@kme.mei.co.jp
To: FreeBSD-gnats-submit@freebsd.org
Subject: [PATCH] od(4) bug fixes and enhancements, including LF-D100 DVD-RAM drive support.
X-Send-Pr-Version: 3.2

>Number:         7210
>Category:       kern
>Synopsis:       [PATCH] od(4) bug fixes and enhancements, including LF-D100 DVD-RAM drive support.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul  8 03:40:06 PDT 1998
>Closed-Date:    Tue Jun 11 18:33:32 PDT 2002
>Last-Modified:  Tue Jun 11 18:33:32 PDT 2002
>Originator:     Shunsuke Akiyama
>Release:        FreeBSD 2.2.6-STABLE i386
>Organization:
Kyushu Matsushita Electric Co., Ltd.
>Environment:

	FreeBSD 2.2-STABLE, Adaptec AHA-2940, Fujitsu M251[23]A MO
	drive, Matsushita/Panasonic LF-D100 DVD-RAM drive.

>Description:

	Patches for od(4) bug fixes and enhancements, including
	Matsushita/Panasonic LF-D100 DVD-RAM drive.

	  * od(4) bug fix and enhancement.
	  * Matsushita/Panasonic LF-D100 DVD-RAM drive support.
	  * UFS and MSDOS-FS on 1024/2048 byte/sector media support
	    with NetBSD (i386) compatibility.

>How-To-Repeat:

	N/A

>Fix:

	There were two part of patches.

	1. Basic patch
	  * od(4) bug fixes.
	    Correct sense code printing if silent flag was specified.
	    Correct device quirks.

	  * od(4) enhancements.
	    Add booting capability from od(4).
	    Add waiting until device busy.
	    Matsushita/Panasonic LF-D100 DVD-RAM drive support.

	2. Extended patch
	  * Add support for UFS and MSDOS-FS on 1024/2048 byte/sector
	    media with NetBSD (i386) compatibility.
	    LF-D100 DVD-RAM drive support must require this patches.

1. Basic patch
----------------------------------------------------------------------
Index: src/sys/conf/options
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/conf/options,v
retrieving revision 1.18.2.13
diff -u -r1.18.2.13 options
--- options	1998/06/25 00:46:17	1.18.2.13
+++ options	1998/07/06 15:37:53
@@ -77,6 +77,7 @@
 # Options used only in scsi/od.c.
 OD_AUTO_TURNOFF		opt_od.h
 OD_BOGUS_NOT_READY	opt_od.h
+OD_WAIT_READY		opt_od.h
 
 # Options used only in pci/ncr.c
 SCSI_NCR_DEBUG		opt_ncr.h
Index: src/sys/i386/boot/biosboot/Makefile
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/i386/boot/biosboot/Makefile,v
retrieving revision 1.50.2.5
diff -u -r1.50.2.5 Makefile
--- Makefile	1998/05/27 23:46:03	1.50.2.5
+++ Makefile	1998/07/06 15:38:44
@@ -41,6 +41,9 @@
 # SCSI and have BIOS drive number (sd_unit_number + BOOT_HD_BIAS).  E.g.,
 # BOOT_HD_BIAS=1 makes sd(0,a) correspond to 1:sd(0,a) instead of 0:sd(0,a).
 
+# Enable boot from SCSI optical disk.
+#CFLAGS+=	-DODBOOT
+
 CLEANFILES+=	boot.nohdr boot.strip boot1 boot2 sizetest
 LDFLAGS+=	-N -T 0 -nostdlib
 #LINKS=		${BINDIR}/sdboot ${BINDIR}/wdboot\
Index: src/sys/i386/boot/biosboot/sys.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/i386/boot/biosboot/sys.c,v
retrieving revision 1.16.2.1
diff -u -r1.16.2.1 sys.c
--- sys.c	1997/07/01 05:55:54	1.16.2.1
+++ sys.c	1998/07/06 14:14:56
@@ -261,13 +261,20 @@
 		biosdrive = unit;
 #if BOOT_HD_BIAS > 0
 		/* XXX */
+#ifdef ODBOOT
+		if (maj == 3 || maj == 4)
+#else
 		if (maj == 4)
+#endif
 			biosdrive += BOOT_HD_BIAS;
 #endif
 	}
 	switch(maj)
 	{
 	case 0:
+#ifdef ODBOOT
+	case 3:
+#endif
 	case 4:
 		dosdev_copy = biosdrive | 0x80;
 		break;
Index: src/sys/i386/boot/biosboot/table.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/i386/boot/biosboot/table.c,v
retrieving revision 1.13
diff -u -r1.13 table.c
--- table.c	1996/09/14 07:12:02	1.13
+++ table.c	1998/07/06 14:14:56
@@ -136,5 +136,9 @@
  * All initialized data is defined in one file to reduce space wastage from
  * fragmentation.
  */
+#ifdef ODBOOT
+char *devs[] = { "wd", "dk", "fd", "od", "sd", 0 };	/* XXX */
+#else
 char *devs[] = { "wd", "dk", "fd", "wt", "sd", 0 };
+#endif
 unsigned long tw_chars = 0x5C2D2F7C;	/* "\-/|" */
Index: src/sys/i386/conf/LINT
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/i386/conf/LINT,v
retrieving revision 1.286.2.55
diff -u -r1.286.2.55 LINT
--- LINT	1998/06/24 08:45:20	1.286.2.55
+++ LINT	1998/07/06 15:39:42
@@ -539,6 +539,15 @@
 # out.
 #
 options		OD_AUTO_TURNOFF
+#
+# To wait if unit becoming ready.  In most case you got an error for
+# opening od device when you inserting a media into the drive, after
+# a while.  This is because most drives reading the DMA information
+# from the media in this period, then returns an error to the host
+# adapter.
+# If you want to avoid this, usr following option.
+#
+options		OD_WAIT_READY
 
 
 
Index: src/sys/i386/i386/autoconf.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/i386/i386/autoconf.c,v
retrieving revision 1.56.2.15
diff -u -r1.56.2.15 autoconf.c
--- autoconf.c	1998/05/20 19:32:10	1.56.2.15
+++ autoconf.c	1998/07/06 15:40:31
@@ -434,7 +434,11 @@
 	"wfd",
 #define FDMAJOR 2
 	"fd",
+#ifdef ODBOOT
+	"od",	/* major 3 = od -- real major number is 20 */
+#else
 	"wt",
+#endif
 	"sd",
 };
 
@@ -471,6 +475,13 @@
 		part = RAW_PART;
 		mindev = unit << FDUNITSHIFT;
 	}
+#ifdef ODBOOT
+	else if (majdev == 3) {
+		majdev = 20;
+		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
+		mindev = dkmakeminor(unit, slice, part);
+	}
+#endif
 	else {
 		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
 		mindev = dkmakeminor(unit, slice, part);
@@ -484,6 +495,10 @@
 	 */
 	if ((rootdev & ~0xff0000) == (orootdev & ~0xff0000))
 		return;
+#ifdef ODBOOT
+	if (majdev == 20)
+		majdev = 3;
+#endif
 	sname = dsname(devname[majdev], unit, slice, part, partname);
 	printf("changing root device to %s%s\n", sname, partname);
 }
Index: src/sys/i386/scsi/aic7xxx.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/i386/scsi/aic7xxx.c,v
retrieving revision 1.81.2.30
diff -u -r1.81.2.30 aic7xxx.c
--- aic7xxx.c	1997/09/27 19:47:12	1.81.2.30
+++ aic7xxx.c	1998/07/06 14:14:57
@@ -88,6 +88,10 @@
  *
  */
 
+#if defined(__FreeBSD__)
+#include "opt_od.h"
+#endif /* defined(__FreeBSD__) */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #if defined(__NetBSD__)
@@ -1346,8 +1350,16 @@
 			/* Fall Through... */
 		case SCSI_BUSY:
 			xs->error = XS_BUSY;
+#ifdef OD_WAIT_READY
+			if (major(xs->sc_link->dev) != 70	/* not od */
+			    || (xs->flags & SCSI_SILENT) == 0) {
+				sc_print_addr(xs->sc_link);
+				printf("Target Busy\n");
+			}
+#else /* OD_WAIT_READY */
 			sc_print_addr(xs->sc_link);
 			printf("Target Busy\n");
+#endif /* OD_WAIT_READY */
 			break;
 		case SCSI_RSVD:
 			xs->error = XS_BUSY;	/*XXX*/
Index: src/sys/pc98/boot/biosboot/Makefile
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/pc98/boot/biosboot/Makefile,v
retrieving revision 1.4.2.6
diff -u -r1.4.2.6 Makefile
--- Makefile	1997/08/17 04:31:32	1.4.2.6
+++ Makefile	1998/07/06 14:14:57
@@ -45,6 +45,9 @@
 # 1:wd(1,a).  If `sd' is given explicitly, then the drive is assumed to be
 # SCSI and have BIOS drive number (sd_unit_number + BOOT_HD_BIAS).  E.g.,
 # BOOT_HD_BIAS=1 makes sd(0,a) correspond to 1:sd(0,a) instead of 0:sd(0,a).
+
+# Enable boot from SCSI optical disk.
+#CFLAGS+=	-DODBOOT
 
 CLEANFILES+=	boot.nohdr boot.strip boot1 boot2 sizetest
 LDFLAGS+=	-N -T 0 -nostdlib
Index: src/sys/pc98/boot/biosboot/sys.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/pc98/boot/biosboot/sys.c,v
retrieving revision 1.6.2.5
diff -u -r1.6.2.5 sys.c
--- sys.c	1998/05/02 02:06:53	1.6.2.5
+++ sys.c	1998/07/06 15:42:02
@@ -269,17 +269,27 @@
 #endif
 #if BOOT_HD_BIAS > 0
 		/* XXX */
+#ifdef ODBOOT
+		if (maj == 3 || maj == 4)
+#else
 		if (maj == 4)
+#endif
 			biosdrive += BOOT_HD_BIAS;
 #endif
 	}
 	switch(maj)
 	{
 #ifdef PC98
+#ifdef ODBOOT
+	case 3:	/* od */
+#endif
 	case 4: /* sd */
 		dosdev_copy = biosdrive | 0xa0;
 #else	/* IBM-PC */
 	case 0:
+#ifdef ODBOOT
+	case 3:
+#endif
 	case 4:
 		dosdev_copy = biosdrive | 0x80;
 #endif
Index: src/sys/pc98/boot/biosboot/table.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/pc98/boot/biosboot/table.c,v
retrieving revision 1.2.2.2
diff -u -r1.2.2.2 table.c
--- table.c	1998/05/02 02:06:53	1.2.2.2
+++ table.c	1998/07/06 15:43:03
@@ -145,5 +145,9 @@
  * All initialized data is defined in one file to reduce space wastage from
  * fragmentation.
  */
+#ifdef ODBOOT
+char *devs[] = { "wd", "dk", "fd", "od", "sd", "dk", "fd", 0 };	/* XXX */
+#else
 char *devs[] = { "wd", "dk", "fd", "wt", "sd", "dk", "fd", 0 };
+#endif
 unsigned long tw_chars = 0x5C2D2F7C;	/* "\-/|" */
Index: src/sys/scsi/od.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/scsi/od.c,v
retrieving revision 1.22.2.3
diff -u -r1.22.2.3 od.c
--- od.c	1998/05/06 19:12:43	1.22.2.3
+++ od.c	1998/07/06 15:43:51
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 1995,1996 Shunsuke Akiyama.  All rights reserved.
+ * Copyright (c) 1995-1997 Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
+ *   All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,9 +53,22 @@
  * WARNING!  Use at your own risk.  Joerg's ancient SONY SMO drive
  * groks it fine, while Shunsuke's Fujitsu chokes on it and times
  * out.
+ *
 #define OD_AUTO_TURNOFF
  */
 
+/*
+ * To wait if unit becoming ready.  In most case you got an error for
+ * opening od device when you inserting a media into the drive, after
+ * a while.  This is because most drives reading the DMA information
+ * from the media in this period, then returns an error to the host
+ * adapter.
+ * If you want to avoid this, try to put this option in your config
+ * file.
+ *
+#define OD_WAIT_READY
+ */
+
 #include "opt_bounce.h"
 #include "opt_scsi.h"
 #include "opt_od.h"
@@ -86,6 +100,9 @@
 #include <vm/vm.h>
 #include <sys/dkstat.h>
 #include <machine/md_var.h>
+#ifdef OD_WAIT_READY
+#include <machine/clock.h>
+#endif /* OD_WAIT_READY */
 
 static u_int32_t odstrats, odqueues;
 
@@ -111,9 +128,10 @@
 		u_int32_t disksize;	/* total number sectors */
 		u_int16_t rpm;		/* medium rotation rate */
 	} params;
+	int	kbtodb;			/* kernel to driver block shift */
 	struct diskslices *dk_slices;	/* virtual drives */
 	struct buf_queue_head buf_queue;
-	int dkunit;		/* disk stats unit number */
+	int	dkunit;			/* disk stats unit number */
 #ifdef DEVFS
 	/* Eventually move all these to common disk struct. */
 	void	*b_devfs_token;
@@ -127,6 +145,10 @@
 static errval	od_reassign_blocks __P((int unit, int block));
 #endif
 static u_int32_t	od_size __P((int unit, int flags));
+#ifdef OD_WAIT_READY
+static errval	od_test_unit_ready __P((struct scsi_link *, u_int32_t));
+static errval	od_check_unit __P((struct scsi_link *, u_int32_t, int));
+#endif /* OD_WAIT_READY */
 static int	od_sense_handler __P((struct scsi_xfer *));
 static void	odstart __P((u_int32_t, u_int32_t));
 static void	odstrategy1 __P((struct buf *));
@@ -145,6 +167,7 @@
 static	d_open_t	odopen;
 static	d_close_t	odclose;
 static	d_ioctl_t	odioctl;
+static	d_psize_t	odsize;
 static	d_strategy_t	odstrategy;
 
 #define CDEV_MAJOR 70
@@ -152,7 +175,7 @@
 static struct cdevsw od_cdevsw;
 static struct bdevsw od_bdevsw = 
 	{ odopen,	odclose,	odstrategy,	odioctl,	/*20*/
-	  nodump,	nopsize,	0,	"od",	&od_cdevsw,	-1 };
+	  nodump,	odsize,		0,	"od",	&od_cdevsw,	-1 };
 
 
 /*
@@ -224,8 +247,17 @@
 	 * the drive. We cannot use interrupts yet, so the
 	 * request must specify this.
 	 */
+#ifdef OD_WAIT_READY
+	od_check_unit(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT,
+		      OD_RETRIES * 2);	/* check the drive becoming ready */
+#endif /* OD_WAIT_READY */
 	scsi_start_unit(sc_link, SCSI_NOSLEEP | SCSI_NOMASK
 				 | SCSI_ERR_OK | SCSI_SILENT);
+#ifdef OD_WAIT_READY
+	od_check_unit(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT,
+		      OD_RETRIES * 2);
+			/* check the drive becoming ready, again */
+#endif /* OD_WAIT_READY */
 	od_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
 	/*
 	 * if we don't have actual parameters, assume 512 bytes/sec
@@ -308,23 +340,50 @@
 	    ("od_open: dev=0x%lx (unit %ld, partition %d)\n",
 		dev, unit, PARTITION(dev)));
 
+#ifdef OD_WAIT_READY
+	/*
+	 * Check the drive is ready or not, especially becoming ready.
+	 * This operation clears "Unit Attention" condition,
+	 * when media had been changed before.
+	 * And also clears the SDEV_MEDIA_LOADED flag.
+	 * This is ** IMPORTANT ** side effect to handle media change.
+	 */
+	if (od_check_unit(sc_link, SCSI_SILENT, OD_RETRIES * 2) != 0) {
+		SC_DEBUG(sc_link, SDEV_DB3, ("becoming ready\n"));
+		errcode = ENXIO;
+		goto bad;
+	}
+
+	/*
+	 * Try to start and lock the drive.
+	 */
+	scsi_start_unit(sc_link, SCSI_ERR_OK);
+	if (od_check_unit(sc_link, 0, OD_RETRIES * 2) != 0) {
+		errcode = ENXIO;
+		goto bad;
+	}
+	scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK);
+#else /* OD_WAIT_READY */
 	/*
-	 * Try to start the drive, and try to clear "Unit Attention"
-	 * condition, when media had been changed before.
-	 * This operation also clears the SDEV_MEDIA_LOADED flag in its
+	 * Try to clear "Unit Attention" condition, when media had
+	 * been changed before.
+	 * This operation also clears the SDEV_MEDIA_LOADED flag in it's
 	 * error handling routine.
+	 * And MUST be a first SCSI I/O operation in od_open().
 	 */
-	scsi_start_unit(sc_link, SCSI_SILENT);
-	scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
+	scsi_test_unit_ready(sc_link, SCSI_SILENT);
 
 	/*
-	 * Make sure the drive is ready.
+	 * Try to start and lock the drive (ignore failure).
 	 */
-	scsi_test_unit_ready(sc_link, 0);
+	scsi_start_unit(sc_link, SCSI_ERR_OK | SCSI_SILENT);
+	scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
+#endif /* OD_WAIT_READY */
 
 	SC_DEBUG(sc_link, SDEV_DB3, ("'start' attempted "));
 
 	sc_link->flags |= SDEV_OPEN;	/* unit attn becomes an err now */
+
 	/*
 	 * If it's been invalidated, then forget the label.
 	 */
@@ -360,8 +419,13 @@
 	}
 	switch (od->params.secsiz) {
 	case SECSIZE :
+		od->kbtodb = 0;
+		break;
 	case 1024 :
+		od->kbtodb = 1;
+		break;
 	case 2048 :
+		od->kbtodb = 2;
 		break;
 	default :
 		printf("od%ld: Can't deal with %d bytes logical blocks\n",
@@ -446,6 +510,7 @@
 	u_int32_t opri;
 	struct scsi_data *od;
 	u_int32_t unit;
+	int scale;
 
 	odstrats++;
 	unit = ODUNIT((bp->b_dev));
@@ -460,17 +525,62 @@
 	}
 
 	/*
+	 * Check it's not too big a transfer for our adapter
+	 */
+	odminphys(bp);
+
+	/*
 	 * Odd number of bytes or negative offset
 	 */
-	if (bp->b_blkno < 0 || bp->b_bcount % DEV_BSIZE != 0) {
+	if (bp->b_blkno < 0) {
+		bp->b_error = EINVAL;
+		printf("od_strategy: Negative block number: 0x%x\n",
+		       bp->b_blkno);
+		goto bad;
+	}
+
+	scale = od->kbtodb;
+
+	/* make sure the blkno is scalable */
+	if ((bp->b_blkno & ((1 << scale) - 1)) != 0) {
 		bp->b_error = EINVAL;
+		printf("od_strategy: Block number is not multiple of sector size (2): 0x%x\n", bp->b_blkno);
 		goto bad;
 	}
+
+	/* make sure that the transfer size is a multiple of the sector size */
+	if ((bp->b_bcount & (od->params.secsiz - 1)) != 0) {
+		bp->b_error = EINVAL;
+		printf("od_strategy: Invalid b_bcount %d at block number: 0x%x\n", bp->b_bcount, bp->b_blkno);
+		goto bad;
+	}
+
 	/*
-	 * Do bounds checking, adjust transfer, set b_cylin and b_pbklno.
+	 * Do bounds checking, adjust transfer, and set b_pblkno.
 	 */
-	if (dscheck(bp, od->dk_slices) <= 0)
-		goto done;	/* XXX check b_resid */
+	{
+		int status;
+		daddr_t b_blkno = bp->b_blkno;
+
+		/* Replace blkno and count with scaled values. */
+		bp->b_blkno >>= scale;
+		bp->b_bcount >>= scale;
+	
+		/* enforce limits and map to physical block number */
+		status = dscheck(bp, od->dk_slices);
+
+		/*
+		 * Restore blkno and unscale the values set by dscheck(),
+		 * except for b_pblkno.
+		 */
+		bp->b_blkno = b_blkno;
+		bp->b_bcount <<= scale;
+		bp->b_resid <<= scale;		/* scale resid */
+
+		/* see if the mapping failed */
+		if (status <= 0)
+			goto done;		/* XXX check b_resid */
+	}
 
 	opri = SPLOD();
 
@@ -541,7 +651,6 @@
 	struct buf *bp = 0;
 	struct scsi_rw_big cmd;
 	u_int32_t blkno, nblk;
-	u_int32_t secsize;
 
 	SC_DEBUG(sc_link, SDEV_DB2, ("odstart "));
 	/*
@@ -578,13 +687,12 @@
 		 * We have a buf, now we know we are going to go through
 		 * With this thing..
 		 */
-		secsize = od->params.secsiz;
-		blkno = bp->b_pblkno / (secsize / DEV_BSIZE);
-		if (bp->b_bcount & (secsize - 1))
+		blkno = bp->b_pblkno;
+		if (bp->b_bcount & (od->params.secsiz - 1))
 		{
 		    goto bad;
 		}
-		nblk = (bp->b_bcount + (secsize - 1)) / secsize;
+		nblk = bp->b_bcount >> (DEV_BSHIFT + od->kbtodb);
 
 		/*
 		 *  Fill out the scsi command
@@ -873,6 +981,81 @@
 	return retval;
 }
 
+static int
+odsize(dev_t dev)
+{
+	struct scsi_data *od;
+
+	od = SCSI_DATA(&od_switch, (u_int32_t) ODUNIT(dev));
+	if (od == NULL)
+		return -1;
+	return dssize(dev, &od->dk_slices, odopen, odclose);
+}
+
+#ifdef OD_WAIT_READY
+/*
+ * send a TEST UNIT READY to target.
+ */
+
+static errval
+od_test_unit_ready(sc_link, flags)
+	struct scsi_link *sc_link;
+	u_int32_t flags;
+{
+	struct scsi_test_unit_ready scsi_cmd;
+
+	bzero(&scsi_cmd, sizeof(scsi_cmd));
+	scsi_cmd.op_code = TEST_UNIT_READY;
+
+	return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &scsi_cmd,
+		sizeof (scsi_cmd), 0, 0, 0, 100000, NULL, flags);
+}
+
+/*
+ * check unit status, especially becoming ready (TARGET BUSY).
+ */
+
+static errval
+od_check_unit(sc_link, flags, retry)
+	struct scsi_link *sc_link;
+	u_int32_t flags;
+	int retry;
+{
+	int n;
+	errval retval;
+
+	for (n = retry; n > 0; --n) {
+		retval = od_test_unit_ready(sc_link, flags);
+
+		switch (retval) {
+		case 0:		/* ESUCCESS, device ready, or got UA */
+			/* check it again for UA */
+			retval = od_test_unit_ready(sc_link, flags);
+			if (retval == 0)
+				return 0;
+			if (retval == EBUSY && (flags & SCSI_NOSLEEP))
+				return 0;
+			break;
+		case EBUSY:	/* device not ready */
+			if (flags & SCSI_NOSLEEP)
+				return 0;
+			break;
+		default:	/* may be device is busy */
+			break;
+		}
+
+		/* wait 2 seconds */
+		if (flags & SCSI_NOSLEEP) {
+			DELAY(2000000);
+		} else {
+			tsleep(&retval, PRIBIO, "odwait", hz * 2);
+		}
+	}
+
+	return EBUSY;
+}
+#endif /* OD_WAIT_READY */
+
 /*
  * sense handler: Called to determine what to do when the
  * device returns a CHECK CONDITION.
@@ -939,11 +1122,13 @@
 
 	/* Retry all disk errors.
 	 */
-	scsi_sense_print(xs);
-	if (xs->retries)
-		printf(", retries:%d\n", xs->retries);
-	else
-		printf(", FAILURE\n");
+	if (!(xs->flags & SCSI_SILENT)) {
+		scsi_sense_print(xs);
+		if (xs->retries)
+			printf(", retries:%d\n", xs->retries);
+		else
+			printf(", FAILURE\n");
+	}
 
 	return SCSIRET_DO_RETRY;
 }
Index: src/sys/scsi/scsiconf.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/scsi/scsiconf.c,v
retrieving revision 1.64.2.26
diff -u -r1.64.2.26 scsiconf.c
--- scsiconf.c	1998/03/08 06:53:13	1.64.2.26
+++ scsiconf.c	1998/07/06 14:14:58
@@ -180,6 +180,7 @@
 #define SC_SHOWME	0x01
 #define	SC_ONE_LU	0x00
 #define	SC_MORE_LUS	0x02
+#define	SC_DUAL_FACE	0x04
 
 static struct scsidevs unknowndev =
 	{
@@ -246,11 +247,29 @@
  * than their respective fields, trailing spaces are implied.
  */
 
+#if NOD > 0
+static struct scsidevs DVD_LF_D100[] =
+{
+#if NCD > 0
+	/*
+	 * Panasonic DVD-RAM drive, another type of dual-faced device.
+	 */
+	{
+		T_READONLY, T_READONLY, T_REMOV, "MATSHITA", "PD-2 LF-D*", "*",
+		"cd", SC_ONE_LU
+	},
+#endif	/* NCD */
+	{
+		0
+	}
+};
+#endif	/* NOD */
+
 static struct scsidevs knowndevs[] =
 {
 #if NOD > 0
 	{
-		T_OPTICAL, T_OPTICAL, T_REMOV, "MATSHITA", "PD-1 LF-100*", "*",
+		T_OPTICAL, T_OPTICAL, T_REMOV, "MATSHITA", "PD-1 LF-1*", "*",
 		"od", SC_MORE_LUS
 	},
 	{
@@ -265,6 +284,13 @@
 		T_DIRECT, T_OPTICAL, T_REMOV, "RICOH", "RO-*", "*",
 		"od", SC_ONE_LU
 	},
+	/*
+	 * Panasonic DVD-RAM drive, another type of dual-faced device.
+	 */
+	{
+		T_READONLY, T_OPTICAL, T_REMOV, "MATSHITA", "PD-2 LF-D*", "*",
+		"od", SC_ONE_LU | SC_DUAL_FACE, 0, DVD_LF_D100
+	},
 #endif	/* NOD */
 #if NSD > 0
 	{
@@ -419,6 +445,13 @@
 		T_READONLY, T_READONLY, T_REMOV, "IODATA", "CD-C68E" ,"*",
 		"cd", SC_MORE_LUS
 	},
+	/*
+	 * COMPAQ PD drive probed CD-UNIT first.
+	 */
+	{
+		T_READONLY, T_READONLY, T_REMOV, "COMPAQ", "PD-1 LF-1*", "*",
+		"cd", SC_MORE_LUS
+	},
 #endif /* !UKTEST */
 #endif	/* NCD */
 #if NWORM > 0
@@ -513,9 +546,11 @@
 /*
  * Declarations
  */
-static struct scsidevs *scsi_probedev __P((struct scsi_link *sc_link,
+static struct scsidevs *scsi_probedev __P((struct scsidevs *known_devs,
+				    struct scsi_link *sc_link,
 				    boolean *maybe_more, int *type_p));
-static struct scsidevs *scsi_selectdev __P((u_int32_t qualifier, u_int32_t type,
+static struct scsidevs *scsi_selectdev __P((struct scsidevs *known_devs,
+				     u_int32_t qualifier, u_int32_t type,
 				     boolean remov, char *manu, char *model,
 				     char *rev));
 
@@ -1084,6 +1119,8 @@
 	struct scsi_link *sc_link = NULL;
 	boolean maybe_more;
 	int type;
+	struct scsidevs *known_devs;
+	int again;
 
 	if ((bus < 0 ) || ( bus >= scbusses->nelem)) {
 		return ENXIO;
@@ -1123,41 +1160,53 @@
 				maybe_more = 1;
 				continue;
 			}
-			/*
-			 * If we presently don't have a link block
-			 * then allocate one to use while probing
-			 */
-			if (!sc_link) {
-				sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
-			}
-			*sc_link = *sc_link_proto;	/* struct copy */
-			sc_link->device = &probe_switch;
-			sc_link->target = targ;
-			sc_link->lun = lun;
-			sc_link->quirks = 0;
-			bestmatch = scsi_probedev(sc_link, &maybe_more, &type);
-			if (bestmatch) {
-			    sc_link->quirks = bestmatch->quirks;
-			    sc_link->devmodes = bestmatch->devmodes;
-			} else {
-			    sc_link->quirks = 0;
-			    sc_link->devmodes = NULL;
-			}
-			if (bestmatch) {		/* FOUND */
-				sc_link->device = scsi_device_lookup(type);
-
-				(void)scsi_assign_unit(sc_link);
-
-				if (scsi_alloc_unit(sc_link)) {
-
-					if (scsi_device_attach(sc_link) == 0) {
-						(*scsibus_data->sc_link)[targ][lun] = sc_link;
-						sc_link = NULL;		/* it's been used */
+			known_devs = knowndevs;
+			do {
+				/*
+				 * If we presently don't have a link block
+				 * then allocate one to use while probing
+				 */
+				if (!sc_link) {
+					sc_link = malloc(sizeof(*sc_link),
+							 M_TEMP, M_NOWAIT);
+				}
+				*sc_link = *sc_link_proto;    /* struct copy */
+				sc_link->device = &probe_switch;
+				sc_link->target = targ;
+				sc_link->lun = lun;
+				sc_link->quirks = 0;
+				bestmatch = scsi_probedev(known_devs, sc_link,
+							  &maybe_more, &type);
+				if (bestmatch) {
+					sc_link->quirks = bestmatch->quirks;
+					sc_link->devmodes = bestmatch->devmodes;
+					known_devs = bestmatch->devmodes;
+					again = bestmatch->flags & SC_DUAL_FACE;
+					sc_link->flags &= (~SC_DUAL_FACE);
+				} else {
+					sc_link->quirks = 0;
+					sc_link->devmodes = NULL;
+					known_devs = knowndevs;
+					again = 0;
+				}
+				if (bestmatch) {		/* FOUND */
+					sc_link->device =
+					  scsi_device_lookup(type);
+
+					(void)scsi_assign_unit(sc_link);
+
+					if (scsi_alloc_unit(sc_link)) {
+
+						if (scsi_device_attach(sc_link)
+						    == 0) {
+							(*scsibus_data->sc_link)[targ][lun] = sc_link;
+							sc_link = NULL;		/* it's been used */
+						}
+						else
+							scsi_free_unit(sc_link);
 					}
-					else
-						scsi_free_unit(sc_link);
 				}
-			}
+			} while (again);
 
 			if (!(maybe_more)) {	/* nothing suggests we'll find more */
 				break;				/* nothing here, skip to next targ */
@@ -1214,7 +1263,8 @@
  * entry.
  */
 static struct scsidevs *
-scsi_probedev(sc_link, maybe_more, type_p)
+scsi_probedev(known_devs, sc_link, maybe_more, type_p)
+	struct scsidevs *known_devs;
 	boolean *maybe_more;
 	struct scsi_link *sc_link;
 	int *type_p;
@@ -1365,7 +1415,8 @@
 	 * available sub drivers
 	 */
 	bestmatch = (scsi_selectdev(
-		qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version));
+		known_devs, qualifier, type, remov ? T_REMOV : T_FIXED,
+		manu, model, version));
 	if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) {
 		*maybe_more = 1;
 	}
@@ -1430,7 +1481,8 @@
  * available sub drivers
  */
 static struct scsidevs *
-scsi_selectdev(qualifier, type, remov, manu, model, rev)
+scsi_selectdev(known_devs, qualifier, type, remov, manu, model, rev)
+	struct scsidevs *known_devs;
 	u_int32_t qualifier, type;
 	boolean remov;
 	char   *manu, *model, *rev;
@@ -1440,7 +1492,7 @@
 
 	type |= qualifier;	/* why? */
 
-	for ( thisentry = knowndevs; thisentry->manufacturer; thisentry++ )
+	for ( thisentry = known_devs; thisentry->manufacturer; thisentry++ )
 	{
 		if (type != thisentry->type) {
 			continue;
----------------------------------------------------------------------

2. Extended patch
----------------------------------------------------------------------
Index: src/sys/kern/subr_diskslice.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/kern/subr_diskslice.c,v
retrieving revision 1.30.2.4
diff -u -r1.30.2.4 subr_diskslice.c
--- subr_diskslice.c	1998/06/06 03:13:54	1.30.2.4
+++ subr_diskslice.c	1998/07/06 15:41:18
@@ -210,6 +210,8 @@
 		ic->ic_prev_iodone_chain = bp->b_iodone_chain;
 		ic->ic_args[0].ia_long = (LABELSECTOR + labelsect - blkno)
 					 << DEV_BSHIFT;
+		if (lp)
+			ic->ic_args[0].ia_long *= lp->d_secsize / DEV_BSIZE;
 		ic->ic_args[1].ia_ptr = sp;
 		bp->b_flags |= B_CALL;
 		bp->b_iodone = dsiodone;
Index: src/sys/msdosfs/msdosfs_fat.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/msdosfs/msdosfs_fat.c,v
retrieving revision 1.10
diff -u -r1.10 msdosfs_fat.c
--- msdosfs_fat.c	1995/12/03 16:41:57	1.10
+++ msdosfs_fat.c	1998/07/06 14:16:23
@@ -116,7 +116,7 @@
 	    * pmp->pm_BytesPerSec;
 	bn += pmp->pm_fatblk;
 	if (bnp)
-		*bnp = bn;
+		*bnp = bn * pmp->pm_SecBlkRatio;
 	if (sizep)
 		*sizep = size;
 	if (bop)
@@ -185,7 +185,7 @@
 				return E2BIG;
 			}
 			if (bnp)
-				*bnp = pmp->pm_rootdirblk + (findcn * pmp->pm_SectPerClust);
+				*bnp = (pmp->pm_rootdirblk + (findcn * pmp->pm_SectPerClust)) * pmp->pm_SecBlkRatio;
 			if (cnp)
 				*cnp = MSDOSFSROOT;
 			return 0;
@@ -340,7 +340,7 @@
 	 * bwrite()'s and really slow things down.
 	 */
 	for (i = 1; i < pmp->pm_FATs; i++) {
-		fatbn += pmp->pm_FATsecs;
+		fatbn += pmp->pm_FATsecs * pmp->pm_SecBlkRatio;
 		/* getblk() never fails */
 		bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount, 0, 0);
 		bcopy(bp->b_data, bpn->b_data, bp->b_bcount);
Index: src/sys/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.13.2.1
diff -u -r1.13.2.1 msdosfs_vfsops.c
--- msdosfs_vfsops.c	1998/03/23 18:28:14	1.13.2.1
+++ msdosfs_vfsops.c	1998/07/06 14:16:23
@@ -58,6 +58,9 @@
 #include <sys/mount.h>
 #include <sys/buf.h>
 #include <sys/file.h>
+#include <sys/disklabel.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
 #include <sys/malloc.h>
 
 #include <msdosfs/bpb.h>
@@ -273,6 +276,8 @@
 	struct buf *bp0 = NULL;
 	struct byte_bpb33 *b33;
 	struct byte_bpb50 *b50;
+	struct partinfo msdosfspart;
+	int secsize;
 #ifdef	PC98
 	u_int	pc98_wrk;
 	u_int	Phy_Sector_Size;
@@ -300,14 +305,16 @@
 	if (error)
 		return error;
 	needclose = 1;
-#ifdef HDSUPPORT
+
 	/*
 	 * Put this in when we support reading dos filesystems from
 	 * partitioned harddisks.
 	 */
-	if (VOP_IOCTL(devvp, DIOCGPART, &msdosfspart, FREAD, NOCRED, p) == 0) {
+	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&msdosfspart, FREAD, NOCRED, p) == 0) {
+		secsize = msdosfspart.disklab->d_secsize;
+	} else {
+		secsize = DEV_BSIZE;
 	}
-#endif
 
 	/*
 	 * Read the boot sector of the filesystem, and then check the boot
@@ -319,7 +326,7 @@
 	devvp->v_flag &= 0xffff; 
 	error = bread(devvp, 0, 1024, NOCRED, &bp0);
 #else
-	error = bread(devvp, 0, 512, NOCRED, &bp0);
+	error = bread(devvp, 0, secsize, NOCRED, &bp0);
 #endif
 	if (error)
 		goto error_exit;
@@ -349,6 +356,9 @@
 	pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);
 	bzero((caddr_t)pmp, sizeof *pmp);
 	pmp->pm_mountp = mp;
+
+	/* calculate the ratio of sector size to DEV_BSIZE */
+	pmp->pm_SecBlkRatio = secsize/DEV_BSIZE;
 
 	/*
 	 * Compute several useful quantities from the bpb in the
Index: src/sys/msdosfs/msdosfsmount.h
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/msdosfs/msdosfsmount.h,v
retrieving revision 1.6
diff -u -r1.6 msdosfsmount.h
--- msdosfsmount.h	1996/01/30 22:57:25	1.6
+++ msdosfsmount.h	1998/07/06 14:16:23
@@ -60,6 +60,9 @@
 	mode_t pm_mask;		/* mask to and with file protection bits */
 	struct vnode *pm_devvp;	/* vnode for block device mntd */
 	struct bpb50 pm_bpb;	/* BIOS parameter blk for this fs */
+	int pm_SecBlkRatio;	/* How many DEV_BSIZE blocks fit inside
+				 * a physical sector
+				 */
 	u_long pm_fatblk;	/* block # of first FAT */
 	u_long pm_rootdirblk;	/* block # of root directory */
 	u_long pm_rootdirsize;	/* size in blocks (not clusters) */
@@ -124,20 +127,20 @@
  * Map a cluster number into a filesystem relative block number.
  */
 #define	cntobn(pmp, cn) \
-	((((cn)-CLUST_FIRST) * (pmp)->pm_SectPerClust) + (pmp)->pm_firstcluster)
+	(((((cn)-CLUST_FIRST) * (pmp)->pm_SectPerClust) + (pmp)->pm_firstcluster) * (pmp)->pm_SecBlkRatio)
 
 /*
  * Map a filesystem relative block number back into a cluster number.
  */
 #define	bntocn(pmp, bn) \
-	((((bn) - pmp->pm_firstcluster)/ (pmp)->pm_SectPerClust) + CLUST_FIRST)
+	(((((bn)/((pmp)->pm_SecBlkRatio)) - pmp->pm_firstcluster)/ (pmp)->pm_SectPerClust) + CLUST_FIRST)
 
 /*
  * Calculate block number for directory entry in root dir, offset dirofs
  */
 #define	roottobn(pmp, dirofs) \
-	(((dirofs) / (pmp)->pm_depclust) * (pmp)->pm_SectPerClust \
-	+ (pmp)->pm_rootdirblk)
+	((((dirofs) / (pmp)->pm_depclust) * (pmp)->pm_SectPerClust \
+	+ (pmp)->pm_rootdirblk) * (pmp)->pm_SecBlkRatio)
 
 /*
  * Calculate block number for directory entry at cluster dirclu, offset
Index: src/sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.41.2.2
diff -u -r1.41.2.2 ffs_vfsops.c
--- ffs_vfsops.c	1997/03/26 20:05:53	1.41.2.2
+++ ffs_vfsops.c	1998/07/06 14:16:24
@@ -461,9 +461,8 @@
 	struct buf *bp;
 	register struct fs *fs;
 	dev_t dev = devvp->v_rdev;
-	struct partinfo dpart;
 	caddr_t base, space;
-	int havepart = 0, blks;
+	int blks;
 	int error, i, size;
 	int ronly;
 	u_int strsize;
@@ -491,12 +490,16 @@
 	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
 	if (error)
 		return (error);
+#if 0
 	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
 		size = DEV_BSIZE;
 	else {
 		havepart = 1;
 		size = dpart.disklab->d_secsize;
 	}
+#else
+	size = DEV_BSIZE;
+#endif
 
 	bp = NULL;
 	ump = NULL;
@@ -519,6 +522,9 @@
 			goto out;
 		}
 	}
+	/* XXX bread assumes b_blkno in DEV_BSIZE unit, calculate fsbtodb */
+	fs->fs_fsbtodb = ffs(fs->fs_fsize / DEV_BSIZE) - 1;
+
 	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
 	bzero((caddr_t)ump, sizeof *ump);
 	ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
@@ -1051,6 +1057,10 @@
 	/* Restore compatibility to old file systems.		   XXX */
 	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
 		((struct fs *)bp->b_data)->fs_nrpos = -1;	/* XXX */
+
+	/* XXX restore fsbtodb which was modified for fixed b_blkno unit */
+	((struct fs *)bp->b_data)->fs_fsbtodb = ffs(fs->fs_nspf) - 1;
+
 	if (waitfor == MNT_WAIT)
 		error = bwrite(bp);
 	else
Index: src/sys/ufs/ufs/ufs_disksubr.c
===================================================================
RCS file: /mo1/FreeBSD-CVS/src/sys/ufs/ufs/ufs_disksubr.c,v
retrieving revision 1.26.2.1
diff -u -r1.26.2.1 ufs_disksubr.c
--- ufs_disksubr.c	1998/05/06 19:16:03	1.26.2.1
+++ ufs_disksubr.c	1998/07/06 15:44:34
@@ -159,7 +159,7 @@
 
 	bp = geteblk((int)lp->d_secsize);
 	bp->b_dev = dev;
-	bp->b_blkno = LABELSECTOR;
+	bp->b_blkno = LABELSECTOR * ((int)lp->d_secsize/DEV_BSIZE);
 	bp->b_bcount = lp->d_secsize;
 	bp->b_flags &= ~B_INVAL;
 	bp->b_flags |= B_BUSY | B_READ;
@@ -261,7 +261,7 @@
 	}
 	bp = geteblk((int)lp->d_secsize);
 	bp->b_dev = dkmodpart(dev, labelpart);
-	bp->b_blkno = LABELSECTOR;
+	bp->b_blkno = LABELSECTOR * ((int)lp->d_secsize/DEV_BSIZE);
 	bp->b_bcount = lp->d_secsize;
 #if 1
 	/*
----------------------------------------------------------------------
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: phk 
State-Changed-When: Wed Jul 8 23:27:12 PDT 1998 
State-Changed-Why:  
please don't mix three so different things in the same patch 
please resubmit as three PRs 
State-Changed-From-To: closed->suspended 
State-Changed-By: des 
State-Changed-When: Thu Jul 9 01:22:58 PDT 1998 
State-Changed-Why:  
Perfectly valid PR awaiting committer. 
State-Changed-From-To: suspended->feedback 
State-Changed-By: iedowse 
State-Changed-When: Sat Jan 19 14:11:47 PST 2002 
State-Changed-Why:  

Are the issues addressed by the old patch in this PR still present 
in releases? If so, please try to update the patch and supply it 
in smaller parts. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=7210 
State-Changed-From-To: feedback->closed 
State-Changed-By: johan 
State-Changed-When: Tue Jun 11 18:31:42 PDT 2002 
State-Changed-Why:  
Feedback timed out. 

od(4) has been replaced by CAM. 

If the UFS/MSDOS part still is an issue 
please open a new PR with a patch for that. 



http://www.freebsd.org/cgi/query-pr.cgi?pr=7210 
>Unformatted:
