Subject: kern/3009: SCSI disk driver optical support.
To: None <gnats-bugs@gnats.netbsd.org>
From: =?ISO-2022-JP?B?Ik1JTk9VUkEgTWFrb3RvIC8gGyRCTCcxOhsoQiAbJEI/PxsoQiI=?= <minoura@kw.netlaputa.or.jp>
List: netbsd-bugs
Date: 12/08/1996 18:12:58
>Number:         3009
>Category:       kern
>Synopsis:       SCSI disk driver (sd.c) optical support.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Dec  8 04:05:04 1996
>Last-Modified:
>Originator:     Naofumi HONDA / MINOURA Makoto
>Organization:
NetBSD/pc98 Core Team
>Release:        Dec.7, '96
>Environment:
System: NetBSD daisy 1.2B NetBSD 1.2B (DAISY) #7: Sat Dec 7 19:09:41 JST 1996 root@daisy:/usr/src/sys/arch/i386/compile/DAISY i386


>Description:
	SCSI optical disks (e.g. MO and PD) are supported by sd.c.
	There are two problems:-
	- sd.c does not know MODE_SENSE page 6 (optical device specific).
	 Instead, it tries page 4 and 5.
	- Some drives (such as FUJITSU M2513A 640/540MB magneto-optical) are
	  very slow so that 10 second timeout is not enough.
>How-To-Repeat:
>Fix:
	Written by Naofumi HONDA and MINOURA Makoto.
	Or, we can port FreeBSD od driver.

diff -rc scsi.ORIG/sd.c scsi/sd.c
*** scsi.ORIG/sd.c	Thu Dec  5 21:19:58 1996
--- scsi/sd.c	Sun Dec  8 17:54:53 1996
***************
*** 95,100 ****
--- 95,101 ----
  		u_long disksize;	/* total number sectors */
  	} params;
  	struct buf buf_queue;
+ 	u_int8_t type;
  };
  
  struct scsi_mode_sense_data {
***************
*** 116,121 ****
--- 117,123 ----
  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,193 ****
--- 190,196 ----
  	 * 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,625 ****
  		 */
  		error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,
  		    (u_char *)bp->b_data, bp->b_bcount,
! 		    SDRETRIES, 10000, bp, SCSI_NOSLEEP |
  		    ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT));
  		if (error)
  			printf("%s: not queued, error %d\n",
--- 622,628 ----
  		 */
  		error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,
  		    (u_char *)bp->b_data, bp->b_bcount,
! 		    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,802 ****
  		/* as long as it's not 0 - readdisklabel divides by it (?) */
  	}
  
! 	strncpy(lp->d_typename, "SCSI disk", 16);
  	lp->d_type = DTYPE_SCSI;
  	strncpy(lp->d_packname, "fictitious", 16);
  	lp->d_secperunit = sd->params.disksize;
--- 799,808 ----
  		/* as long as it's not 0 - readdisklabel divides by it (?) */
  	}
  
! 	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,883 ****
--- 884,934 ----
  	    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 = 0;
+ 
+ 	dp->blksize = 512L;
+ 	if ((sectors = scsi_size(sd->sc_link, flags)) == 0)
+ 		error = 1;
+ 	/* XXX:
+ 	 * I know 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)
+ 	{
+ 		dp->blksize = _3btol(scsi_sense.blk_desc.blklen);
+ 		if (dp->blksize == 0)
+ 			dp->blksize = 512L;
+ 	}
+ 	dp->heads = 64;
+ 	dp->sectors = 32;
+ 	dp->cyls = sectors / (64 * 32);
+ 	dp->disksize = sectors;
+ 	return error;
+ }
+ 
  /*
   * Get the scsi driver to send a full inquiry to the * device and use the
   * results to fill out the disk parameter structure.
***************
*** 892,897 ****
--- 943,956 ----
  	u_long sectors;
  	int page;
  	int error;
+ 
+ 	if (sd->type == T_OPTICAL) {
+ 		int error;
+ 
+ 		if (error = sd_get_optparms(sd, flags, dp))
+ 			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,
>Audit-Trail:
>Unformatted: