Subject: kern/11425: CD drive does not play last track
To: None <gnats-bugs@gnats.netbsd.org>
From: Julian Coleman <Julian.Coleman@coris.demon.co.uk>
List: netbsd-bugs
Date: 11/05/2000 03:53:17
>Number:         11425
>Category:       kern
>Synopsis:       CD drive does not play last track
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 05 03:53:01 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Julian Coleman
>Release:        1.5_BETA
>Organization:
@home
>Environment:
System: NetBSD orthanc.coris.org.uk 1.5_BETA NetBSD 1.5_BETA (SUN4-300) #2: Sun Oct 29 10:38:14 GMT 2000 root@mariner.coris.org.uk:/usr/obj/sys/arch/sparc/compile/SUN4-300 sparc


>Description:
Trying to play the whole disk (or last track of) an audio CD on :

> cd0 at scsibus0 target 6 lun 0: <SONY, CD-ROM CDU-8012, 3.1e> SCSI2 5/cdrom removable

results in :

> cd0(esp0:6:0):  Check Condition on CDB: 0x47 00 00 00 02 20 38 00 0a 00
>     SENSE KEY:  Illegal Request
>    INFO FIELD:  1007312
>      ASC/ASCQ:  Logical Block Address Out of Range

for the audio CD with contents :

>   1   0:02.32   5:04.20      32   22670  audio
> 
>  12  52:11.37   3:50.48  234712   17148  audio
> 170  56:00.10         -  251860       -      -

>How-To-Repeat:

Run cdplay with the above Sony drive.

>Fix:

It appears the problem is that cd_play_tracks() plays from the start msf of
the first track to the start msf of the last + 1 track.  This drive does not
like that.  The fix is to subtract one frame from the end msf :

--- sys/dev/scsipi/cd.c.dist	Sat Jun 10 11:14:46 2000
+++ sys/dev/scsipi/cd.c	Sun Oct 29 10:29:16 2000
@@ -1286,6 +1286,7 @@
 	int strack, sindex, etrack, eindex;
 {
 	struct cd_toc toc;
+	union msf_lba emsf;
 	int error;
 
 	if (!etrack)
@@ -1304,12 +1305,31 @@
 	if (strack < 0)
 		return (EINVAL);
 
+	/*
+	 * Subtract 1 frame from end location if etrack is the last track,
+	 * as some drives will give an error when asked to play this frame.
+	 */
+	emsf.msf.minute = toc.entries[etrack].addr.msf.minute;
+	emsf.msf.second = toc.entries[etrack].addr.msf.second;
+	emsf.msf.frame = toc.entries[etrack].addr.msf.frame;
+	if (etrack == toc.header.ending_track) {
+		if (emsf.msf.frame)
+			emsf.msf.frame -= 1;
+		else {
+			emsf.msf.frame = 74;
+			if (emsf.msf.second)
+				emsf.msf.second -= 1;
+			else {
+				emsf.msf.second = 59;
+				if (emsf.msf.minute)
+					emsf.msf.minute -=1;
+			}
+		}
+	}
 	return (cd_play_msf(cd, toc.entries[strack].addr.msf.minute,
 	    toc.entries[strack].addr.msf.second,
 	    toc.entries[strack].addr.msf.frame,
-	    toc.entries[etrack].addr.msf.minute,
-	    toc.entries[etrack].addr.msf.second,
-	    toc.entries[etrack].addr.msf.frame));
+	    emsf.msf.minute, emsf.msf.second, emsf.msf.frame));
 }
 
 /*

It may be better to calculate the end msf from the start of the last track
plus the length of that track instead.  Above fix also tested on :

> cd1 at scsibus0 target 5 lun 0: <YAMAHA, CRW4416S, 1.0g> SCSI2 5/cdrom removable
> cd0 at scsibus0 target 6 lun 0: <TOSHIBA, XM-4101TASUNSLCD, 1755> SCSI2 5/cdrom removable
>Release-Note:
>Audit-Trail:
>Unformatted: