From 625d310b1b8896f195c950ec15f5b61d52997045 Mon Sep 17 00:00:00 2001 From: thorpej Date: Fri, 21 Feb 1997 21:51:59 +0000 Subject: [PATCH] Handle optical disks a little better, from Naofumi HONDA / MINOURA Makoto in PR #3009, with some slight KNF from me. --- sys/dev/scsipi/sd.c | 70 +++++++++++++++++++++++++++++++++++++++++++-- sys/scsi/sd.c | 70 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 134 insertions(+), 6 deletions(-) diff --git a/sys/dev/scsipi/sd.c b/sys/dev/scsipi/sd.c index 41f65bc00fc5..8d95179ac2d5 100644 --- a/sys/dev/scsipi/sd.c +++ b/sys/dev/scsipi/sd.c @@ -1,4 +1,4 @@ -/* $NetBSD: sd.c,v 1.107 1996/12/05 01:06:43 cgd Exp $ */ +/* $NetBSD: sd.c,v 1.108 1997/02/21 21:51:59 thorpej Exp $ */ /* * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. @@ -95,6 +95,7 @@ struct sd_softc { u_long disksize; /* total number sectors */ } params; struct buf buf_queue; + u_int8_t type; }; struct scsi_mode_sense_data { @@ -116,6 +117,7 @@ void sdgetdisklabel __P((struct sd_softc *)); void sdstart __P((void *)); int sddone __P((struct scsi_xfer *, int)); int sd_reassign_blocks __P((struct sd_softc *, u_long)); +int sd_get_optparms __P((struct sd_softc *, int, struct disk_parms *)); int sd_get_parms __P((struct sd_softc *, int)); static int sd_mode_sense __P((struct sd_softc *, struct scsi_mode_sense_data *, int, int)); @@ -188,6 +190,7 @@ sdattach(parent, self, aux) * Store information needed to contact our base driver */ sd->sc_link = sc_link; + sd->type = (sa->sa_inqbuf->device & SID_TYPE); sc_link->device = &sd_switch; sc_link->device_softc = sd; if (sc_link->openings > SDOUTSTANDING) @@ -619,7 +622,7 @@ sdstart(v) */ error = scsi_scsi_cmd(sc_link, cmdp, cmdlen, (u_char *)bp->b_data, bp->b_bcount, - SDRETRIES, 10000, bp, SCSI_NOSLEEP | + SDRETRIES, 60000, bp, SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT)); if (error) printf("%s: not queued, error %d\n", @@ -796,7 +799,10 @@ sdgetdisklabel(sd) /* as long as it's not 0 - readdisklabel divides by it (?) */ } - strncpy(lp->d_typename, "SCSI disk", 16); + if (sd->type == T_OPTICAL) + strncpy(lp->d_typename, "SCSI optical", 16); + else + strncpy(lp->d_typename, "SCSI disk", 16); lp->d_type = DTYPE_SCSI; strncpy(lp->d_packname, "fictitious", 16); lp->d_secperunit = sd->params.disksize; @@ -878,6 +884,58 @@ sd_mode_sense(sd, scsi_sense, page, flags) SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN | SCSI_SILENT); } +int +sd_get_optparms(sd, flags, dp) + struct sd_softc *sd; + int flags; + struct disk_parms *dp; +{ + struct scsi_mode_sense scsi_cmd; + struct scsi_mode_sense_data { + struct scsi_mode_header header; + struct scsi_blk_desc blk_desc; + union disk_pages pages; + } scsi_sense; + u_long sectors; + int error; + + dp->blksize = 512; + if ((sectors = scsi_size(sd->sc_link, flags)) == 0) + return 1; + + /* XXX + * It is better to get the following params from the + * mode sense page 6 only (optical device parameter page). + * However, there are stupid optical devices which does NOT + * support the page 6. Ghaa.... + */ + bzero(&scsi_cmd, sizeof(scsi_cmd)); + scsi_cmd.opcode = MODE_SENSE; + scsi_cmd.page = 0x3f; /* all pages */ + scsi_cmd.length = sizeof(struct scsi_mode_header) + + sizeof(struct scsi_blk_desc); + + if ((error = scsi_scsi_cmd(sd->sc_link, + (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd), + (u_char *)&scsi_sense, sizeof(scsi_sense), SDRETRIES, + 6000, NULL, flags | SCSI_DATA_IN)) != 0) + return error; + + dp->blksize = _3btol(scsi_sense.blk_desc.blklen); + if (dp->blksize == 0) + dp->blksize = 512; + + /* + * Create a pseudo-geometry. + */ + dp->heads = 64; + dp->sectors = 32; + dp->cyls = sectors / (dp->heads * dp->sectors); + dp->disksize = sectors; + + return 0; +} + /* * Get the scsi driver to send a full inquiry to the * device and use the * results to fill out the disk parameter structure. @@ -893,6 +951,12 @@ sd_get_parms(sd, flags) int page; int error; + if (sd->type == T_OPTICAL) { + if ((error = sd_get_optparms(sd, flags, dp)) != 0) + sd->sc_link->flags &= ~SDEV_MEDIA_LOADED; + return error; + } + if ((error = sd_mode_sense(sd, &scsi_sense, page = 4, flags)) == 0) { SC_DEBUG(sd->sc_link, SDEV_DB3, ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n", diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index 41f65bc00fc5..8d95179ac2d5 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -1,4 +1,4 @@ -/* $NetBSD: sd.c,v 1.107 1996/12/05 01:06:43 cgd Exp $ */ +/* $NetBSD: sd.c,v 1.108 1997/02/21 21:51:59 thorpej Exp $ */ /* * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. @@ -95,6 +95,7 @@ struct sd_softc { u_long disksize; /* total number sectors */ } params; struct buf buf_queue; + u_int8_t type; }; struct scsi_mode_sense_data { @@ -116,6 +117,7 @@ void sdgetdisklabel __P((struct sd_softc *)); void sdstart __P((void *)); int sddone __P((struct scsi_xfer *, int)); int sd_reassign_blocks __P((struct sd_softc *, u_long)); +int sd_get_optparms __P((struct sd_softc *, int, struct disk_parms *)); int sd_get_parms __P((struct sd_softc *, int)); static int sd_mode_sense __P((struct sd_softc *, struct scsi_mode_sense_data *, int, int)); @@ -188,6 +190,7 @@ sdattach(parent, self, aux) * Store information needed to contact our base driver */ sd->sc_link = sc_link; + sd->type = (sa->sa_inqbuf->device & SID_TYPE); sc_link->device = &sd_switch; sc_link->device_softc = sd; if (sc_link->openings > SDOUTSTANDING) @@ -619,7 +622,7 @@ sdstart(v) */ error = scsi_scsi_cmd(sc_link, cmdp, cmdlen, (u_char *)bp->b_data, bp->b_bcount, - SDRETRIES, 10000, bp, SCSI_NOSLEEP | + SDRETRIES, 60000, bp, SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT)); if (error) printf("%s: not queued, error %d\n", @@ -796,7 +799,10 @@ sdgetdisklabel(sd) /* as long as it's not 0 - readdisklabel divides by it (?) */ } - strncpy(lp->d_typename, "SCSI disk", 16); + if (sd->type == T_OPTICAL) + strncpy(lp->d_typename, "SCSI optical", 16); + else + strncpy(lp->d_typename, "SCSI disk", 16); lp->d_type = DTYPE_SCSI; strncpy(lp->d_packname, "fictitious", 16); lp->d_secperunit = sd->params.disksize; @@ -878,6 +884,58 @@ sd_mode_sense(sd, scsi_sense, page, flags) SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN | SCSI_SILENT); } +int +sd_get_optparms(sd, flags, dp) + struct sd_softc *sd; + int flags; + struct disk_parms *dp; +{ + struct scsi_mode_sense scsi_cmd; + struct scsi_mode_sense_data { + struct scsi_mode_header header; + struct scsi_blk_desc blk_desc; + union disk_pages pages; + } scsi_sense; + u_long sectors; + int error; + + dp->blksize = 512; + if ((sectors = scsi_size(sd->sc_link, flags)) == 0) + return 1; + + /* XXX + * It is better to get the following params from the + * mode sense page 6 only (optical device parameter page). + * However, there are stupid optical devices which does NOT + * support the page 6. Ghaa.... + */ + bzero(&scsi_cmd, sizeof(scsi_cmd)); + scsi_cmd.opcode = MODE_SENSE; + scsi_cmd.page = 0x3f; /* all pages */ + scsi_cmd.length = sizeof(struct scsi_mode_header) + + sizeof(struct scsi_blk_desc); + + if ((error = scsi_scsi_cmd(sd->sc_link, + (struct scsi_generic *)&scsi_cmd, sizeof(scsi_cmd), + (u_char *)&scsi_sense, sizeof(scsi_sense), SDRETRIES, + 6000, NULL, flags | SCSI_DATA_IN)) != 0) + return error; + + dp->blksize = _3btol(scsi_sense.blk_desc.blklen); + if (dp->blksize == 0) + dp->blksize = 512; + + /* + * Create a pseudo-geometry. + */ + dp->heads = 64; + dp->sectors = 32; + dp->cyls = sectors / (dp->heads * dp->sectors); + dp->disksize = sectors; + + return 0; +} + /* * Get the scsi driver to send a full inquiry to the * device and use the * results to fill out the disk parameter structure. @@ -893,6 +951,12 @@ sd_get_parms(sd, flags) int page; int error; + if (sd->type == T_OPTICAL) { + if ((error = sd_get_optparms(sd, flags, dp)) != 0) + sd->sc_link->flags &= ~SDEV_MEDIA_LOADED; + return error; + } + if ((error = sd_mode_sense(sd, &scsi_sense, page = 4, flags)) == 0) { SC_DEBUG(sd->sc_link, SDEV_DB3, ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n",