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: