Subject: kern/22960: fix sd(4) on atapibus
To: None <gnats-bugs@gnats.netbsd.org>
From: None <hira@po6.nsk.ne.jp>
List: netbsd-bugs
Date: 09/26/2003 04:50:12
>Number:         22960
>Category:       kern
>Synopsis:       fix sd(4) on atapibus
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Sep 25 19:51:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Kouichirou Hiratsuka
>Release:        NetBSD 1.6ZC
>Organization:
>Environment:
System: NetBSD firefly.localdomain 1.6ZC NetBSD 1.6ZC (FIREFLY) #178: Fri Sep 26 01:42:03 JST 2003 root@firefly.localdomain:/usr/src/sys/arch/i386/compile/FIREFLY i386
Architecture: i386
Machine: i386
>Description:
	On atapibus, sd(4) driver does not work. In sd(4) driver, atapibus
	specific get_parms() is needed (maybe). I'm sorry, my PR kern/22938
	was bogus.

>How-To-Repeat:
	
>Fix:
	This is patch.

Index: sd.c
===================================================================
RCS file: /cvs/cvsroot/src/sys/dev/scsipi/sd.c,v
retrieving revision 1.210
diff -u -r1.210 sd.c
--- sd.c	18 Sep 2003 06:55:53 -0000	1.210
+++ sd.c	25 Sep 2003 06:05:03 -0000
@@ -87,6 +87,7 @@
 #include <dev/scsipi/scsi_disk.h>
 #include <dev/scsipi/scsiconf.h>
 #include <dev/scsipi/sdvar.h>
+#include <dev/scsipi/atapi_disk.h>
 
 #define	SDUNIT(dev)			DISKUNIT(dev)
 #define	SDPART(dev)			DISKPART(dev)
@@ -114,6 +115,9 @@
 	    int));
 int	sd_get_capacity __P((struct sd_softc *, struct disk_parms *, int));
 int	sd_get_parms __P((struct sd_softc *, struct disk_parms *, int));
+int	sd_scsibus_get_parms __P((struct sd_softc *, struct disk_parms *, int));
+int	sd_atapibus_get_parms __P((struct sd_softc *, struct disk_parms *,
+	    int));
 int	sd_flush __P((struct sd_softc *, int));
 int	sd_getcache __P((struct sd_softc *, int *));
 int	sd_setcache __P((struct sd_softc *, int));
@@ -1773,6 +1777,27 @@
 	struct disk_parms *dp;
 	int flags;
 {
+	switch (scsipi_periph_bustype(sd->sc_periph)) {
+	case SCSIPI_BUSTYPE_SCSI:
+		return (sd_scsibus_get_parms(sd, dp, flags));
+		break;
+	case SCSIPI_BUSTYPE_ATAPI:
+		return (sd_atapibus_get_parms(sd, dp, flags));
+		break;
+	default:
+		return (SDGP_RESULT_OFFLINE);
+		break;
+	}
+	/* NOTREACHED */
+	return (SDGP_RESULT_OFFLINE);
+}
+
+int
+sd_scsibus_get_parms(sd, dp, flags)
+	struct sd_softc *sd;
+	struct disk_parms *dp;
+	int flags;
+{
 	struct sd_mode_sense_data scsipi_sense;
 	int error;
 	int big;
@@ -1907,6 +1932,84 @@
 
 blksize:
 	return (SDGP_RESULT_OK);
+}
+
+int
+sd_atapibus_get_parms(sd, dp, flags)
+        struct sd_softc *sd;
+        struct disk_parms *dp;
+        int flags;
+{
+        struct atapi_read_format_capacities scsipi_cmd;
+        struct atapi_capacity_descriptor *descp;
+        struct atapi_sd_mode_data sense_data;
+        char capacity_data[ATAPI_CAP_DESC_SIZE(1)];
+        int error;
+
+        memset(&scsipi_cmd, 0, sizeof scsipi_cmd);
+        scsipi_cmd.opcode = ATAPI_READ_FORMAT_CAPACITIES;
+        _lto2b(ATAPI_CAP_DESC_SIZE(1), scsipi_cmd.length);
+
+        error = scsipi_command(sd->sc_periph,
+            (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
+            (void *)capacity_data, ATAPI_CAP_DESC_SIZE(1), SDRETRIES, 20000,
+            NULL, flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
+        SC_DEBUG(sd->sc_periph, SCSIPI_DB2,
+            ("sd_atapibus_get_parms: read format capacities error=%d\n",
+            error));
+
+        if (error != 0)
+                return (SDGP_RESULT_OFFLINE);
+        descp = (struct atapi_capacity_descriptor *)
+            &capacity_data[ATAPI_CAP_DESC_OFFSET_DESC(0)];
+
+        switch (descp->byte5 & ATAPI_CAP_DESC_CODE_MASK) {
+        case ATAPI_CAP_DESC_CODE_UNFORMATTED:
+                return SDGP_RESULT_UNFORMATTED;
+
+        case ATAPI_CAP_DESC_CODE_RESERVED:
+        case ATAPI_CAP_DESC_CODE_FORMATTED:
+                break;
+
+        case ATAPI_CAP_DESC_CODE_NONE:
+                return SDGP_RESULT_OFFLINE;
+        }
+
+        dp->disksize = _4btol(descp->nblks);
+        dp->blksize = _3btol(descp->blklen);
+        if (dp->blksize == 0)
+                dp->disksize512 = dp->disksize;
+        else
+                dp->disksize512 = (dp->disksize * dp->blksize) / DEV_BSIZE;
+
+       /*
+         * First, set up standard fictitious geometry, a la sd_scsi.c.
+         */
+        dp->heads = 64;
+        dp->sectors = 32;
+        dp->cyls = dp->disksize / (64 * 32);
+        dp->rot_rate = 3600;
+
+        /*
+         * Then try to get something better.  If we can't, that's
+         * still OK.
+         *
+         * XXX Rigid geometry page?
+         */
+        error = scsipi_mode_sense_big(sd->sc_periph, 0,
+            ATAPI_FLEX_GEOMETRY_PAGE, &sense_data.header, FLEXGEOMETRYPAGESIZE,
+            flags | XS_CTL_DATA_ONSTACK, SDRETRIES, 20000);
+        SC_DEBUG(sd->sc_periph, SCSIPI_DB2,
+            ("sd_atapibus_get_parms: mode sense (flex) error=%d\n", error));
+        if (error != 0)
+                return (SDGP_RESULT_OK);
+
+        dp->heads = sense_data.pages.flex_geometry.nheads;
+        dp->sectors = sense_data.pages.flex_geometry.ph_sec_tr;
+        dp->cyls = _2btol(sense_data.pages.flex_geometry.ncyl);
+        dp->rot_rate = _2btol(sense_data.pages.flex_geometry.rot_rate);
+
+        return (SDGP_RESULT_OK);
 }
 
 int

>Release-Note:
>Audit-Trail:
>Unformatted: