Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Jan 1997 21:18:48 -0800 (PST)
From:      John-Mark Gurney <jmg@hydrogen.nike.efn.org>
To:        FreeBSD-gnats@freefall.FreeBSD.org
Subject:   kern/2423: some cdrom drives return bcd encoded track numbers instead of std binary (such as Chinon CDS-535, Q10 and Q20)
Message-ID:  <199701090518.VAA00622@hydrogen.nike.efn.org>
Resent-Message-ID: <199701090530.VAA04333@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         2423
>Category:       kern
>Synopsis:       some cdrom drives return bcd encoded track numbers instead of std binary (such as Chinon CDS-535, Q10 and Q20)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan  8 21:30:00 PST 1997
>Last-Modified:
>Originator:     John-Mark Gurney
>Organization:
Cu Networking
>Release:        FreeBSD 2.2-960801-SNAP i386
>Environment:

basicly you need a broken cdrom drive such as a Chinon CDS-535 that returns the tracks as packed BCD instead of standard binary...  this is applicable to all platforms and all os's...
	

>Description:

basicly the cdrom drive returns exactly what is on the cdrom (packed bcd) instead of what the newer cdroms return (std binary)...  most programs such as cdcontrol expect binary...  if they give packed bcd strange things happen..  such as cd's with more than 9 tracks will have appox 16/10 time more tracks than normal...

which causes interesting things to happen.. such as cds with 99 tracks being reported as have 153 (0x99) tracks...  and the standard buffer isn't big enough to read/handle 153...  
	

>How-To-Repeat:

find a broken drive...  stick a 99 track cd in it... and try to get track info... it will fail...  (can't read 153 toc entries in only 100 spaces)..

then try something fun like playing track 11...  hmm...  interesting results happen...
	

>Fix:
	
this first patch simply addes the option CD_BCD_HACK to config, used for testing...  
*** src/sys/conf/options	Wed Jan  8 20:37:46 1997
--- /usr/src/sys/conf/options	Wed Jan  8 19:31:39 1997
***************
*** 73,75 ****
--- 73,77 ----
  IPFIREWALL		opt_ipfw.h
  IPFIREWALL_VERBOSE	opt_ipfw.h
  IPFIREWALL_VERBOSE_LIMIT	opt_ipfw.h
+ 
+ CD_BCD_HACK	opt_myhacks.h

now this is the patch the does all the dirty work... it adds two static functions, bcdtob and btobcd to convert to and from bcd numbers...  then it encases and changes all track id's (as far as I know I caught them all)...  so that the programs can understand the returned info... also converts binary to bcd on play track command also...  I'm running the patches over here and they work great... as far as I can tell :)

I'm imbarsed on how easy this fix was...  thanks to Joerg Wunsch who pointed out that their the the device specific quirks...  after that it all fell into place...

I just started using these patches...  but I doubt that they will cause other stuff to fail...  so far my 99 track cd is playing beautifully...

Index: cd.c
===================================================================
RCS file: /usr/cvs/src/sys/scsi/cd.c,v
retrieving revision 1.75
diff -c -r1.75 cd.c
*** cd.c	1996/12/24 11:35:24	1.75
--- cd.c	1997/01/09 05:13:22
***************
*** 19,24 ****
--- 19,25 ----
  
  #include "opt_bounce.h"
  #include "opt_scsi.h"
+ #include "opt_myhacks.h"
  
  #define SPLCD splbio
  #define ESUCCESS 0
***************
*** 117,122 ****
--- 118,128 ----
  #endif
  };
  
+ #if CD_BCD_HACK > 0
+ static u_char bcdtob(u_char);
+ static u_char btobcd(u_char);
+ #endif
+ 
  static int cdunit(dev_t dev) { return CDUNIT(dev); }
  static dev_t cdsetunit(dev_t dev, int unit) { return CDSETUNIT(dev, unit); }
  
***************
*** 635,640 ****
--- 641,654 ----
  			error = cd_set_mode(unit, &data);
  			if (error)
  				break;
+ 
+ #if CD_BCD_HACK > 0
+ 			if(sc_link->quirks & CD_Q_BCD_TRACKS) {
+ 				args->start_track=btobcd(args->start_track);
+ 				args->end_track=btobcd(args->end_track);
+ 			}
+ #endif
+ 
  			return (cd_play_tracks(unit
  				,args->start_track
  				,args->start_index
***************
*** 694,703 ****
  				error = EINVAL;
  				break;
  			}
  			error = cd_read_subchannel(unit, args->address_format,
  				args->data_format, args->track, &data, len);
  			if (error)
! 				break;
  			len = min(len, ((data.header.data_len[0] << 8) +
  				data.header.data_len[1] +
  				sizeof(struct cd_sub_channel_header)));
--- 708,726 ----
  				error = EINVAL;
  				break;
  			}
+ #if CD_BCD_HACK > 0
+ 			if(sc_link->quirks & CD_Q_BCD_TRACKS)
+ 				args->track=btobcd(args->track);
+ #endif
  			error = cd_read_subchannel(unit, args->address_format,
  				args->data_format, args->track, &data, len);
  			if (error)
! 	 			break;
! #if CD_BCD_HACK > 0
! 			if(sc_link->quirks & CD_Q_BCD_TRACKS)
! 				data.what.track_info.track_number=
! 				    bcdtob(data.what.track_info.track_number);
! #endif
  			len = min(len, ((data.header.data_len[0] << 8) +
  				data.header.data_len[1] +
  				sizeof(struct cd_sub_channel_header)));
***************
*** 713,718 ****
--- 736,751 ----
  					(struct cd_toc_entry *)&th, sizeof th);
  			if (error)
  				break;
+ 
+ #if CD_BCD_HACK > 0
+ 			if(sc_link->quirks & CD_Q_BCD_TRACKS) {
+ 				/* we are going to have to convert the BCD
+ 				 * encoding on the cd to what is expected
+ 				 */
+ 				th.starting_track=bcdtob(th.starting_track);
+ 				th.ending_track=bcdtob(th.ending_track);
+ 			}
+ #endif
  			NTOHS(th.len);
  			bcopy(&th, addr, sizeof th);
  		}
***************
*** 748,753 ****
--- 781,796 ----
  			if (error)
  				break;
  
+ #if CD_BCD_HACK > 0
+ 			if(sc_link->quirks & CD_Q_BCD_TRACKS) {
+ 				/* we are going to have to convert the BCD
+ 				 * encoding on the cd to what is expected
+ 				 */
+ 				th->starting_track=bcdtob(th->starting_track);
+ 				th->ending_track=bcdtob(th->ending_track);
+ 			}
+ #endif
+ 
  			if (starting_track == 0)
  				starting_track = th->starting_track;
  			else if (starting_track == LEADOUT)
***************
*** 786,791 ****
--- 829,840 ----
  
  			/* make leadout entry if needed */
  			idx = starting_track + num - 1;
+ 
+ #if CD_BCD_HACK > 0
+ 			if(sc_link->quirks & CD_Q_BCD_TRACKS)
+ 				th->ending_track=bcdtob(th->ending_track);
+ #endif
+ 			
  			if (idx == th->ending_track + 1) {
  				error = cd_read_toc(unit, te->address_format,
  					LEADOUT,
***************
*** 796,801 ****
--- 845,859 ----
  				data.entries[idx - starting_track] = lead.entry;
  			}
  
+ #if CD_BCD_HACK > 0
+ 			if(sc_link->quirks & CD_Q_BCD_TRACKS) {
+ 				for(idx=0; idx<num-1; idx++) {
+ 					data.entries[idx].track=
+ 					    bcdtob(data.entries[idx].track);
+ 				}
+ 			}
+ #endif
+ 
  			error = copyout(data.entries, te->data, len);
  		}
  		break;
***************
*** 1389,1394 ****
--- 1447,1464 ----
  		cd_devsw_installed = 1;
      	}
  }
+ 
+ #if CD_BCD_HACK > 0
+ static u_char bcdtob(u_char num)
+ {
+ 	return (num & 0xf) + (num >> 4) * 10;
+ }
+ 
+ static u_char btobcd(u_char num)
+ {
+ 	return (num % 10) + ((num / 10) << 4);
+ }
+ #endif
  
  SYSINIT(cddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cd_drvinit,NULL)
  
Index: scsiconf.h
===================================================================
RCS file: /usr/cvs/src/sys/scsi/scsiconf.h,v
retrieving revision 1.46
diff -c -r1.46 scsiconf.h
*** scsiconf.h	1996/09/10 23:37:52	1.46
--- scsiconf.h	1997/01/09 05:14:40
***************
*** 275,280 ****
--- 275,281 ----
  
  /* cd specific CD_Q_* */
  #define CD_Q_NO_TOUCH		0x0001
+ #define CD_Q_BCD_TRACKS		0x0002
  
  
  /*
	

>Audit-Trail:
>Unformatted:
John-Mark Gurney



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199701090518.VAA00622>