Subject: Re: sd(4) on atapibus
To: None <current-users@NetBSD.org>
From: Kouichirou Hiratsuka <hira@po6.nsk.ne.jp>
List: current-users
Date: 09/25/2003 15:07:43
Hello,

> USB floppy drive does not work on -current (my PR kern/22875). It has not
> worked since this commit.
> 
> http://mail-index.netbsd.org/source-changes/2003/09/18/0000.html
> 
> Now, sd_atapi.c and sd_scsi.c were merged into sd.c. According to sd_atapi.c,
> on atapibus, third argument of scsipi_mode_sense_big() was constant value. On
> atapibus, must it be ATAPI_FLEX_GEOMETRY_PAGE?
> 
> My USB floppy drive does work well with a following patch.

Is get_parms() necessary for both of SCSI and ATAPI bus? According to sd_scsi.c
and sd_atapi.c, it considerably differed in case of SCSI and ATAPI. I tried
switch of it by bus type.

This patch also does work well for my USB floppy drive. Maybe it's better than
my previous patch.

best regards.

--
 Kouichirou Hiratsuka
   hira@po6.nsk.ne.jp

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