Subject: kern/4267: SCSI CDROM cannot play audio CD
To: None <gnats-bugs@gnats.netbsd.org, t-nkyma@tcp-ip.or.jp>
From: None <t-nkyma@tcp-ip.or.jp>
List: netbsd-bugs
Date: 10/14/1997 00:43:52
>Number:         4267
>Category:       kern
>Synopsis:       SCSI CDROM cannot play audio CD
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Oct 13 08:50:03 1997
>Last-Modified:
>Originator:     Takeshi Nakayama
>Organization:
Tokai Communication Platform for Inter Person
>Release:        NetBSD-current [Oct 11 1997]
>Environment:
NetBSD/i386 and ncr driver
NetBSD/x68k and mmspc driver (not included in -current yet)

>Description:
The ncr driver puts the next message when I play an audio CD in the 
SCSI CDROM:

  cd0(ncr0:6:0):  Check Condition on opcode 0x15
      SENSE KEY:  Illegal Request
       ASC/ASCQ:  Parameter List
           SKSV:  Error in CDB, Offset 

And also, in NetBSD/x68k with the mmspc driver, causes a kernel
panic for its poor error handling.

>How-To-Repeat:
Try to use ioctls CDIOCPLAYTRACS, CDIOCSETVOL....

>Fix:
The following patch refer to cd_atapi.c solves this probrem.

*** src/sys/dev/scsipi/cd_scsi.c	Fri Oct 10 21:24:29 1997
--- obj/sys/dev/scsipi/cd_scsi.c	Sun Oct 12 18:51:39 1997
***************
*** 73,81 ****
  #endif
  void	cd_scsibus_attach __P((struct device *, struct device *, void *));
  int	cd_scsibus_get_mode __P((struct cd_softc *,
! 	    struct scsi_cd_mode_data *, int));
  int	cd_scsibus_set_mode __P((struct cd_softc *,
! 	    struct scsi_cd_mode_data *));
  
  struct cfattach cd_scsibus_ca = {
  	sizeof(struct cd_softc), cd_scsibus_match, cd_scsibus_attach
--- 73,81 ----
  #endif
  void	cd_scsibus_attach __P((struct device *, struct device *, void *));
  int	cd_scsibus_get_mode __P((struct cd_softc *,
! 	    struct scsi_cd_mode_data *, int, int));
  int	cd_scsibus_set_mode __P((struct cd_softc *,
! 	    struct scsi_cd_mode_data *, int));
  
  struct cfattach cd_scsibus_ca = {
  	sizeof(struct cd_softc), cd_scsibus_match, cd_scsibus_attach
***************
*** 157,166 ****
   * Get the requested page into the buffer given
   */
  int
! cd_scsibus_get_mode(cd, data, page)
  	struct cd_softc *cd;
  	struct scsi_cd_mode_data *data;
! 	int page;
  {
  	struct scsi_mode_sense scsipi_cmd;
  
--- 157,166 ----
   * Get the requested page into the buffer given
   */
  int
! cd_scsibus_get_mode(cd, data, page, len)
  	struct cd_softc *cd;
  	struct scsi_cd_mode_data *data;
! 	int page, len;
  {
  	struct scsi_mode_sense scsipi_cmd;
  
***************
*** 168,174 ****
  	bzero(data, sizeof(*data));
  	scsipi_cmd.opcode = SCSI_MODE_SENSE;
  	scsipi_cmd.page = page;
! 	scsipi_cmd.length = sizeof(*data) & 0xff;
  	return ((*cd->sc_link->scsipi_cmd)(cd->sc_link,
  	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
  	    (u_char *)data, sizeof(*data), CDRETRIES, 20000, NULL,
--- 168,174 ----
  	bzero(data, sizeof(*data));
  	scsipi_cmd.opcode = SCSI_MODE_SENSE;
  	scsipi_cmd.page = page;
! 	scsipi_cmd.length = len & 0xff;
  	return ((*cd->sc_link->scsipi_cmd)(cd->sc_link,
  	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
  	    (u_char *)data, sizeof(*data), CDRETRIES, 20000, NULL,
***************
*** 179,194 ****
   * Get the requested page into the buffer given
   */
  int
! cd_scsibus_set_mode(cd, data)
  	struct cd_softc *cd;
  	struct scsi_cd_mode_data *data;
  {
  	struct scsi_mode_select scsipi_cmd;
  
  	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
  	scsipi_cmd.opcode = SCSI_MODE_SELECT;
  	scsipi_cmd.byte2 |= SMS_PF;
! 	scsipi_cmd.length = sizeof(*data) & 0xff;
  	data->header.data_length = 0;
  	return ((*cd->sc_link->scsipi_cmd)(cd->sc_link,
  	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
--- 179,195 ----
   * Get the requested page into the buffer given
   */
  int
! cd_scsibus_set_mode(cd, data, len)
  	struct cd_softc *cd;
  	struct scsi_cd_mode_data *data;
+ 	int len;
  {
  	struct scsi_mode_select scsipi_cmd;
  
  	bzero(&scsipi_cmd, sizeof(scsipi_cmd));
  	scsipi_cmd.opcode = SCSI_MODE_SELECT;
  	scsipi_cmd.byte2 |= SMS_PF;
! 	scsipi_cmd.length = len & 0xff;
  	data->header.data_length = 0;
  	return ((*cd->sc_link->scsipi_cmd)(cd->sc_link,
  	    (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
***************
*** 203,213 ****
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE)) != 0)
  		return (error);
  	data.page.audio.flags &= ~CD_PA_SOTC;
  	data.page.audio.flags |= CD_PA_IMMED;
! 	return (cd_scsibus_set_mode(cd, &data));
  }
  
  int
--- 204,215 ----
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE,
! 	    AUDIOPAGESIZE)) != 0)
  		return (error);
  	data.page.audio.flags &= ~CD_PA_SOTC;
  	data.page.audio.flags |= CD_PA_IMMED;
! 	return (cd_scsibus_set_mode(cd, &data, AUDIOPAGESIZE));
  }
  
  int
***************
*** 218,230 ****
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE)) != 0)
  		return (error);
  	data.page.audio.port[LEFT_PORT].channels = p0;
  	data.page.audio.port[RIGHT_PORT].channels = p1;
  	data.page.audio.port[2].channels = p2;
  	data.page.audio.port[3].channels = p3;
! 	return (cd_scsibus_set_mode(cd, &data));
  }
  
  int
--- 220,233 ----
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE,
! 	    AUDIOPAGESIZE)) != 0)
  		return (error);
  	data.page.audio.port[LEFT_PORT].channels = p0;
  	data.page.audio.port[RIGHT_PORT].channels = p1;
  	data.page.audio.port[2].channels = p2;
  	data.page.audio.port[3].channels = p3;
! 	return (cd_scsibus_set_mode(cd, &data, AUDIOPAGESIZE));
  }
  
  int
***************
*** 236,242 ****
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE)) != 0)
  		return (error);
  	arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
  	arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
--- 239,246 ----
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE,
! 	    AUDIOPAGESIZE)) != 0)
  		return (error);
  	arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
  	arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
***************
*** 253,259 ****
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE)) != 0)
  		return (error);
  	data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
  	data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
--- 257,264 ----
  	struct scsi_cd_mode_data data;
  	int error;
  
! 	if ((error = cd_scsibus_get_mode(cd, &data, SCSI_AUDIO_PAGE,
! 	    AUDIOPAGESIZE)) != 0)
  		return (error);
  	data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
  	data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
***************
*** 261,265 ****
  	data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
  	data.page.audio.port[2].volume = arg->vol[2];
  	data.page.audio.port[3].volume = arg->vol[3];
! 	return (cd_scsibus_set_mode(cd, &data));
  }
--- 266,270 ----
  	data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
  	data.page.audio.port[2].volume = arg->vol[2];
  	data.page.audio.port[3].volume = arg->vol[3];
! 	return (cd_scsibus_set_mode(cd, &data, AUDIOPAGESIZE));
  }
*** src/sys/dev/scsipi/scsi_cd.h	Fri Oct  3 20:23:41 1997
--- obj/sys/dev/scsipi/scsi_cd.h	Sun Oct 12 18:51:51 1997
***************
*** 83,87 ****
  	struct scsi_blk_desc blk_desc;
  	union scsi_cd_pages page;
  };
- #endif /*_SCSI_SCSI_CD_H*/
  
--- 83,91 ----
  	struct scsi_blk_desc blk_desc;
  	union scsi_cd_pages page;
  };
  
+ #define AUDIOPAGESIZE \
+ 	(sizeof(struct scsi_mode_header) + sizeof(struct scsi_blk_desc) \
+ 	    + sizeof(struct cd_audio_page))
+ 
+ #endif /*_SCSI_SCSI_CD_H*/

>Audit-Trail:
>Unformatted: