Add support for "simplified direct" (aka RBC) devices.

This reveals some ugly points in the sd driver, as
the PQUIRK_ONLYBIG flag (there are 6, 10, 12 and 16 byte
CDBs for r/w) and the handling of small/big mode
select/sense. This should be cleaned up.
Also the "long" struct disk_parms.disksize is worth
a thought...
This commit is contained in:
drochner 2003-03-07 16:18:57 +00:00
parent 5c5aa9ba83
commit 49e6bf0fa5

View File

@ -1,4 +1,4 @@
/* $NetBSD: sd_scsi.c,v 1.26 2002/10/04 03:43:06 soren Exp $ */
/* $NetBSD: sd_scsi.c,v 1.27 2003/03/07 16:18:57 drochner Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sd_scsi.c,v 1.26 2002/10/04 03:43:06 soren Exp $");
__KERNEL_RCSID(0, "$NetBSD: sd_scsi.c,v 1.27 2003/03/07 16:18:57 drochner Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -88,6 +88,10 @@ struct scsipi_inquiry_pattern sd_scsibus_patterns[] = {
"", "", ""},
{T_OPTICAL, T_REMOV,
"", "", ""},
{T_SIMPLE_DIRECT, T_FIXED,
"", "", ""},
{T_SIMPLE_DIRECT, T_REMOV,
"", "", ""},
};
struct sd_scsibus_mode_sense_data {
@ -102,6 +106,8 @@ static int sd_scsibus_get_parms __P((struct sd_softc *,
struct disk_parms *, int));
static int sd_scsibus_get_optparms __P((struct sd_softc *,
struct disk_parms *, int));
static int sd_scsibus_get_simplifiedparms __P((struct sd_softc *,
struct disk_parms *, int));
static int sd_scsibus_flush __P((struct sd_softc *, int));
static int sd_scsibus_getcache __P((struct sd_softc *, int *));
static int sd_scsibus_setcache __P((struct sd_softc *, int));
@ -156,6 +162,10 @@ sd_scsibus_attach(parent, self, aux)
if (periph->periph_version == 0)
sd->flags |= SDF_ANCIENT;
if (sd->type == T_SIMPLE_DIRECT)
periph->periph_quirks |=
(PQUIRK_ONLYBIG | PQUIRK_NOBIGMODESENSE);
sdattach(parent, sd, periph, &sd_scsibus_ops);
}
@ -230,6 +240,67 @@ sd_scsibus_get_optparms(sd, dp, flags)
return (SDGP_RESULT_OK);
}
static int
sd_scsibus_get_simplifiedparms(sd, dp, flags)
struct sd_softc *sd;
struct disk_parms *dp;
int flags;
{
struct {
struct scsipi_mode_header header;
/* no block descriptor */
u_int8_t pg_code; /* page code (should be 6) */
u_int8_t pg_length; /* page length (should be 11) */
u_int8_t wcd; /* bit0: cache disable */
u_int8_t lbs[2]; /* logical block size */
u_int8_t size[5]; /* number of log. blocks */
u_int8_t pp; /* power/performance */
u_int8_t flags;
u_int8_t resvd;
} scsipi_sense;
u_long sectors;
int error;
/*
* scsipi_size (ie "read capacity") and mode sense page 6
* give the same information. Do both for now, and check
* for consistency.
* XXX probably differs for removable media
*/
dp->blksize = 512;
if ((sectors = scsipi_size(sd->sc_periph, flags)) == 0)
return (SDGP_RESULT_OFFLINE); /* XXX? */
error = scsipi_mode_sense(sd->sc_periph, SMS_DBD, 6,
&scsipi_sense.header, sizeof(scsipi_sense),
flags | XS_CTL_DATA_ONSTACK, SDRETRIES, 6000);
if (error != 0)
return (SDGP_RESULT_OFFLINE); /* XXX? */
dp->blksize = _2btol(scsipi_sense.lbs);
if (dp->blksize == 0)
dp->blksize = 512;
/*
* Create a pseudo-geometry.
*/
dp->heads = 64;
dp->sectors = 32;
dp->cyls = sectors / (dp->heads * dp->sectors);
/* XXX disksize is only a "long" currently */
dp->disksize = /* XXX _5btol */
(_3btol(scsipi_sense.size) << 16)
| (_2btol(&scsipi_sense.size[3]));
if (dp->disksize != sectors) {
printf("RBC size: mode sense=%ld, get cap=%ld\n",
dp->disksize, sectors);
dp->disksize = sectors;
}
return (SDGP_RESULT_OK);
}
/*
* Get the scsi driver to send a full inquiry to the * device and use the
* results to fill out the disk parameter structure.
@ -254,6 +325,9 @@ sd_scsibus_get_parms(sd, dp, flags)
if (sd->type == T_OPTICAL)
return (sd_scsibus_get_optparms(sd, dp, flags));
if (sd->type == T_SIMPLE_DIRECT)
return (sd_scsibus_get_simplifiedparms(sd, dp, flags));
if ((error = sd_scsibus_mode_sense(sd, &scsipi_sense, page = 4,
flags)) == 0) {
SC_DEBUG(sd->sc_periph, SCSIPI_DB3,