Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 May 96 09:21:11 JST
From:      akiyama@kme.mei.co.jp
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/1196: SCSI optical disk driver update.
Message-ID:  <9605130021.AA04581@kmegate.kme.mei.co.jp>
Resent-Message-ID: <199605130030.RAA28124@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         1196
>Category:       kern
>Synopsis:       sys/scsi/od.c update by author.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun May 12 17:30:00 PDT 1996
>Last-Modified:
>Originator:     Shunsuke Akiyama
>Organization:
Kyushu Matsushita Electric Co., Ltd.
>Release:        FreeBSD 2.2-960501-SNAP i386
>Environment:

	all FreeBSD-2.2-960501-SNAP systems.

>Description:

	N/A

>How-To-Repeat:

	N/A

>Fix:

	This patch updates sys/scsi/od.c:

	  * Improve ficticious geometry translation.
	  * CD compatible ioctl's, CDIOCALLOW, CDIOCPREVENT and CDIOCEJECT.
	  * Additional sense code handling for some drives.

===================================================================
RCS file: sys/scsi/RCS/od.c,v
retrieving revision 1.15
diff -u -r1.15 sys/scsi/od.c
--- 1.15	1996/03/27 18:50:08
+++ sys/scsi/od.c	1996/05/08 14:49:31
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995 Shunsuke Akiyama.  All rights reserved.
+ * Copyright (c) 1995,1996 Shunsuke Akiyama.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -18,22 +18,30 @@
  *
  * THIS SOFTWARE IS PROVIDED BY Shunsuke Akiyama AND CONTRIBUTORS ``AS IS''
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Shunsuke Akiyama OR CONTRIBUTORS BE
  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: od.c,v 1.15 1996/03/27 18:50:08 bde Exp $
+ *	$Id: od.c,v 1.15.1.3 1996/05/06 15:14:57 shun Exp $
  */
 
 /*
- * TODO:
- *   1. Add optical disk specific ioctl functions, such as eject etc.
+ * Compile option defines:
+ */
+
+/*
+ * If drive returns sense key as 0x02 with vendor specific additional
+ * sense code (ASC) and additional sense code qualifier (ASCQ), or
+ * illegal ASC and ASCQ. This cause an error (NOT READY) and retrying.
+ * To suppress this, uncomment this.
+ *
+#define OD_BOGUS_NOT_READY
  */
 
 #include "opt_bounce.h"
@@ -52,6 +60,7 @@
 #include <sys/buf.h>
 #include <sys/uio.h>
 #include <sys/malloc.h>
+#include <sys/cdio.h>
 #include <sys/errno.h>
 #include <sys/dkstat.h>
 #include <sys/disklabel.h>
@@ -69,10 +78,9 @@
 
 static u_int32_t odstrats, odqueues;
 
-#define SECSIZE 512
+#define SECSIZE		512	/* default sector size */
 #define	ODOUTSTANDING	4
 #define	OD_RETRIES	4
-#define	MAXTRANSFER	8		/* 1 page at a time */
 
 #define	PARTITION(dev)	dkpart(dev)
 #define	ODUNIT(dev)	dkunit(dev)
@@ -102,6 +110,8 @@
 #endif
 };
 
+static void	od_get_geometry __P((u_int32_t, u_int16_t *,
+				     u_char *, u_char *));
 static errval	od_get_parms __P((int unit, int flags));
 static errval	od_reassign_blocks __P((int unit, int block));
 static u_int32_t	od_size __P((int unit, int flags));
@@ -145,18 +155,18 @@
 
 static struct scsi_device od_switch =
 {
-    od_sense_handler,
-    odstart,			/* have a queue, served by this */
-    NULL,			/* have no async handler */
-    NULL,			/* Use default 'done' routine */
-    "od",
-    0,
+	od_sense_handler,
+	odstart,		/* have a queue, served by this */
+	NULL,			/* have no async handler */
+	NULL,			/* Use default 'done' routine */
+	"od",
+	0,
 	{0, 0},
-	0,				/* Link flags */
+	0,			/* Link flags */
 	odattach,
 	"Optical",
 	odopen,
-    sizeof(struct scsi_data),
+	sizeof(struct scsi_data),
 	T_OPTICAL,
 	odunit,
 	odsetunit,
@@ -194,7 +204,7 @@
 	dev_attach(kdc);
 	if(dk_ndrive < DK_NDRIVE) {
 		sprintf(dk_names[dk_ndrive], "od%d", unit);
-		dk_wpms[dk_ndrive] = (8*1024*1024/2);
+		dk_wpms[dk_ndrive] = (4*1024*1024/2);	/* 4MB/sec */
 		SCSI_DATA(&od_switch, unit)->dkunit = dk_ndrive++;
 	} else {
 		SCSI_DATA(&od_switch, unit)->dkunit = -1;
@@ -302,7 +312,7 @@
 	 * to look for a new device if we are not initted
 	 */
 	if ((!od) || (!(od->flags & ODINIT))) {
-		return (ENXIO);
+		return ENXIO;
 	}
 
 	SC_DEBUG(sc_link, SDEV_DB1,
@@ -360,7 +370,14 @@
 	if (errcode) {
 		goto bad;
 	}
-	if (od->params.secsiz != SECSIZE) {	/* XXX One day... */
+	switch (od->params.secsiz) {
+	case SECSIZE :
+	case 1024 :
+#ifdef notyet
+	case 2048 :
+#endif
+		break;
+	default :
 		printf("od%ld: Can't deal with %d bytes logical blocks\n",
 		    unit, od->params.secsiz);
 		Debugger("od");
@@ -377,8 +394,10 @@
 	label.d_ncylinders = od->params.cyls;
 	label.d_secpercyl = od->params.heads * od->params.sectors;
 	if (label.d_secpercyl == 0)
-		label.d_secpercyl = 100;
-		/* XXX as long as it's not 0 - readdisklabel divides by it (?) */
+		label.d_secpercyl = 64*32;
+		/* XXX as long as it's not 0
+		 *  - readdisklabel divides by it (?)
+		 */
 	label.d_secperunit = od->params.disksize;
 
 	/* Initialize slice tables. */
@@ -420,7 +439,7 @@
 		scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
 		sc_link->flags &= ~SDEV_OPEN;
 	}
-	return (0);
+	return 0;
 }
 
 /*
@@ -529,6 +548,7 @@
 	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 "));
 	/*
@@ -565,17 +585,17 @@
 		 * We have a buf, now we know we are going to go through
 		 * With this thing..
 		 */
-		blkno = bp->b_pblkno;
-		if (bp->b_bcount & (SECSIZE - 1))
+		secsize = od->params.secsiz;
+		blkno = bp->b_pblkno / (secsize / DEV_BSIZE);
+		if (bp->b_bcount & (secsize - 1))
 		{
 		    goto bad;
 		}
-		nblk = bp->b_bcount >> 9;
+		nblk = (bp->b_bcount + (secsize - 1)) / secsize;
 
 		/*
 		 *  Fill out the scsi command
 		 */
-		bzero(&cmd, sizeof(cmd));
 		cmd.op_code = (bp->b_flags & B_READ)
 		    ? READ_BIG : WRITE_BIG;
 		cmd.addr_3 = (blkno & 0xff000000UL) >> 24;
@@ -584,6 +604,7 @@
 		cmd.addr_0 = blkno & 0xff;
 		cmd.length2 = (nblk & 0xff00) >> 8;
 		cmd.length1 = (nblk & 0xff);
+		cmd.byte2 = cmd.reserved = cmd.control = 0;
 		/*
 		 * Call the routine that chats with the adapter.
 		 * Note: we cannot sleep as we may be an interrupt
@@ -633,27 +654,39 @@
 	od = sc_link->sd;
 	SC_DEBUG(sc_link, SDEV_DB1, ("odioctl (0x%x)", cmd));
 
-#if 0
-	/* Wait until we have exclusive access to the device. */
-	/* XXX this is how wd does it.  How did we work without this? */
-	wdsleep(du->dk_ctrlr, "wdioct");
-#endif
-
 	/*
 	 * If the device is not valid.. abandon ship
 	 */
 	if (!(sc_link->flags & SDEV_MEDIA_LOADED))
-		return (EIO);
+		return EIO;
 
-	if (cmd ==  DIOCSBAD)
-		return (EINVAL);	/* XXX */
-	error = dsioctl("od", dev, cmd, addr, flag, &od->dk_slices,
-			odstrategy1, (ds_setgeom_t *)NULL);
-	if (error != -1)
-		return (error);
-	if (PARTITION(dev) != RAW_PART)
-		return (ENOTTY);
-	return (scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link));
+	switch (cmd) {
+	case DIOCSBAD:
+		error = EINVAL;
+		break;
+	case CDIOCEJECT:
+		error = scsi_stop_unit(sc_link, 1, 0);
+		break;
+	case CDIOCALLOW:
+		error = scsi_prevent(sc_link, PR_ALLOW, 0);
+		break;
+	case CDIOCPREVENT:
+		error = scsi_prevent(sc_link, PR_PREVENT, 0);
+		break;
+	default:
+		error = dsioctl("od", dev, cmd, addr, flag, &od->dk_slices,
+				odstrategy1, (ds_setgeom_t *)NULL);
+		if (error == -1) {
+			if (PARTITION(dev) != RAW_PART) {
+				error = ENOTTY;
+			} else {
+				error = scsi_do_ioctl(dev, cmd, addr,
+						      flag, p, sc_link);
+			}
+		}
+		break;
+	}
+	return error;
 }
 
 /*
@@ -666,7 +699,9 @@
 	struct scsi_read_cap_data rdcap;
 	struct scsi_read_capacity scsi_cmd;
 	u_int32_t size;
+	u_int32_t secsize;
 	struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
+	struct scsi_data *od = sc_link->sd;
 
 	/*
 	 * make up a scsi command and ask the scsi driver to do
@@ -688,14 +723,21 @@
 		20000,
 		NULL,
 		flags | SCSI_DATA_IN) != 0) {
-		return (0);
+		return 0;
 	} else {
-		size = rdcap.addr_0 + 1;
+		size = rdcap.addr_0;
 		size += rdcap.addr_1 << 8;
 		size += rdcap.addr_2 << 16;
 		size += rdcap.addr_3 << 24;
-	}
-	return (size);
+		size += 1;
+		secsize = rdcap.length_0;
+		secsize += rdcap.length_1 << 8;
+		secsize += rdcap.length_2 << 16;
+		secsize += rdcap.length_3 << 24;
+	}
+	od->params.disksize = size;
+	od->params.secsiz = secsize;
+	return size;
 }
 
 #ifdef notyet
@@ -721,7 +763,7 @@
 	rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff);
 	rbdata.defect_descriptor[0].dlbaddr_0 = ((block) & 0xff);
 
-	return (scsi_scsi_cmd(sc_link,
+	return scsi_scsi_cmd(sc_link,
 		(struct scsi_generic *) &scsi_cmd,
 		sizeof(scsi_cmd),
 		(u_char *) & rbdata,
@@ -729,12 +771,52 @@
 		OD_RETRIES,
 		20000,
 		NULL,
-		SCSI_DATA_OUT));
+		SCSI_DATA_OUT);
 }
 #endif
 #define b2tol(a)	(((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
 
 /*
+ * Get ficticious geometry from total sectors.
+ */
+static void
+od_get_geometry(total, cp, hp, sp)
+	u_int32_t total;
+	u_int16_t *cp;
+	u_char *hp;
+	u_char *sp;
+{
+	u_int16_t cyls;
+	u_char heads;
+	u_char sectors;
+
+	heads = 64;
+	sectors = 32;
+
+	if (total != 0) {
+		cyls = total / (64 * 32);
+		while (cyls >= 1024) {
+			if (heads < 128) {
+				heads *= 2;
+			} else {
+				heads = 255;
+				sectors = 63;
+				cyls = total / (heads * sectors);
+				break;
+			}
+			cyls = total / (heads * sectors);
+		}
+		if (total > (cyls * heads * sectors))
+			cyls++;
+	} else
+		cyls = 0;
+
+	*cp = cyls;
+	*hp = heads;
+	*sp = sectors;
+}
+
+/*
  * Get the scsi driver to send a full inquiry to the
  * device and use the results to fill out the disk
  * parameter structure.
@@ -756,16 +838,13 @@
 		return 0;
 
 	/*
-	 * use adaptec standard ficticious geometry
-	 * this depends on which controller (e.g. 1542C is
-	 * different. but we have to put SOMETHING here..)
+	 * Use ficticious geometry, this depends on the size of medium.
 	 */
 	sectors = od_size(unit, flags);
-	disk_parms->heads = 64;
-	disk_parms->sectors = 32;
-	disk_parms->cyls = sectors / (64 * 32);
-	disk_parms->secsiz = SECSIZE;
-	disk_parms->disksize = sectors;
+	/* od_size() sets secsiz and disksize */
+
+	od_get_geometry(sectors, &disk_parms->cyls, &disk_parms->heads,
+			&disk_parms->sectors);
 
 	if (sectors != 0) {
 		sc_link->flags |= SDEV_MEDIA_LOADED;
@@ -796,6 +875,13 @@
 	 */
 	if ((sense->error_code & SSD_ERRCODE) == 0x71)
 		return SCSIRET_CONTINUE;
+
+#ifdef OD_BOGUS_NOT_READY
+	if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
+		((sense->ext.extended.flags & SSD_KEY) == 0x02))
+		/* No point in retrying Not Ready */
+			return SCSIRET_CONTINUE;
+#endif
 
 	if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
 		((sense->ext.extended.flags & SSD_KEY) == 0x04))

-- 
Shunsuke Akiyama
Kyushu Matsushita Electric Co., Ltd. Fukuoka, Japan.
akiyama@kme.mei.co.jp

>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9605130021.AA04581>