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>