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>
