; /*\ ; |*| cdrom.c ; |*| ; |*| routines for c-interface to mscdex audio functions ; |*| ; |*| Copyright (c) 1992, Media Vision, Inc. All Rights Reserved ; |*| ; \*/ #include "cdrom.h" static int OURDISCSTATUS[26]; ; /*\ ; |*| cdplay(int drive, long frame, long lframe) ; |*| ; |*| begin audio play on drive from frame for lframe frames ; |*| ; |*| Entry: drive number, starting frame, count of frames to play ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdplay(int drive, long frame, long lframe) { struct ioctlplay iop; iop.cdh.len= 13; iop.cdh.unit= (char) drive; iop.cdh.cmd= CD_CMD_PLAY; iop.cdh.stat= 0; iop.addrmode= 0; iop.startsector= frame- 150; iop.sectorcount= lframe; senddevreq(drive, &iop); if (!(iop.cdh.stat& 0x8000) || (iop.cdh.stat& 0x0100)) { OURDISCSTATUS[drive]|= CDISPLAYING; OURDISCSTATUS[drive]&= (-1^ CDISPAUSED); } return(iop.cdh.stat); } ; /*\ ; |*| cdstop(int drive) ; |*| ; |*| stop audio play on drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdstop(int drive) { struct ioctlstop ios; if (cdstatus(drive)& CDISPLAYING) cdpause(drive); ios.cdh.len= 13; ios.cdh.unit= (char) drive; ios.cdh.cmd= CD_CMD_STOP; ios.cdh.stat= 0; senddevreq(drive, &ios); if (!(ios.cdh.stat& 0x8000) || (ios.cdh.stat& 0x0100)) { OURDISCSTATUS[drive]&= (-1^ (CDISPAUSED| CDISPLAYING)); } return(ios.cdh.stat); } ; /*\ ; |*| cdpause(int drive) ; |*| ; |*| pause audio play on drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: return 0 if not playing, else return driver status ; |*| ; \*/ cdpause(int drive) { struct ioctlstop ios; if (!(cdstatus(drive)& CDISPLAYING)) return(0); ios.cdh.len= 13; ios.cdh.unit= (char) drive; ios.cdh.cmd= CD_CMD_STOP; ios.cdh.stat= 0; senddevreq(drive, &ios); if (!(ios.cdh.stat& 0x8000)) { OURDISCSTATUS[drive]|= CDISPAUSED; OURDISCSTATUS[drive]&= (-1^ CDISPLAYING); } return(ios.cdh.stat); } ; /*\ ; |*| cdresume(int drive) ; |*| ; |*| resume paused audio play on drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdresume(int drive) { struct ioctlresume ior; ior.cdh.len= 13; ior.cdh.unit= (char) drive; ior.cdh.cmd= CD_CMD_RESUME; ior.cdh.stat= 0; senddevreq(drive, &ior); if (!(ior.cdh.stat& 0x8000)) { if ((cdstatus(drive)& CDISPLAYING)) OURDISCSTATUS[drive]|= CDISPLAYING; OURDISCSTATUS[drive]&= (-1^ CDISPAUSED); } return(ior.cdh.stat); } ; /*\ ; |*| cdseek(int drive, long frame) ; |*| ; |*| move head on drive to specified frame ; |*| ; |*| Entry: drive number, frame number ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdseek(int drive, long frame) { struct ioctlseek ios; ios.cdh.len= 13; ios.cdh.unit= (char) drive; ios.cdh.cmd= CD_CMD_SEEK; ios.cdh.stat= 0; ios.addrmode= 0; ios.buffer= (void far *) 0; ios.sectorcount= 0; ios.startsector= frame- 150; senddevreq(drive, &ios); if (!(ios.cdh.stat& 0x8000)) { OURDISCSTATUS[drive]&= (-1^ (CDISPLAYING| CDISPAUSED)); } return(ios.cdh.stat); } ; /*\ ; |*| cdreset(int drive) ; |*| ; |*| reset the driver for specified drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdreset(int drive) { struct ioctlwrite iow; char dummy= CD_CMD_RESET; iow.cdh.len= 13; iow.cdh.unit= (char) drive; iow.cdh.cmd= IOCTL_WRITE; iow.cdh.stat= 0; iow.mdb= 0; iow.buffer= (void far *) &dummy; iow.size= sizeof(dummy); iow.ssn= 0; iow.errbuf= (void far *) 0; senddevreq(drive, &iow); if (!(iow.cdh.stat& 0x8000)) OURDISCSTATUS[drive]&= (-1^ (CDISPAUSED| CDISPLAYING| CDISHERE)); return(iow.cdh.stat); } ; /*\ ; |*| cdeject(int drive) ; |*| ; |*| eject disc in drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdeject(int drive) { struct ioctlwrite iow; char dummy= CD_CMD_EJECT; iow.cdh.len= 13; iow.cdh.unit= (char) drive; iow.cdh.cmd= IOCTL_WRITE; iow.cdh.stat= 0; iow.mdb= 0; iow.buffer= (void far *) &dummy; iow.size= sizeof(dummy); iow.ssn= 0; iow.errbuf= (void far *) 0; senddevreq(drive, &iow); if (!(iow.cdh.stat& 0x8000)) OURDISCSTATUS[drive]&= (-1^ (CDISPAUSED| CDISPLAYING| CDISHERE)); return(iow.cdh.stat); } ; /*\ ; |*| cdstatus(int drive) ; |*| ; |*| get audio status of drive number, update internal status variable ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: internal status variable ; |*| ; \*/ cdstatus(int drive) { int status= 0; long d1, d2; status= cdaudiostatus(drive, &d1, &d2); return(OURDISCSTATUS[drive]); } ; /*\ ; |*| cdaudiostatus(int drive, long *nextstart, long *nextend) ; |*| ; |*| get audio status of drive number, update internal status variable ; |*| ; |*| Entry: drive number, pointers to nextstart and nextend frames ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdaudiostatus(int drive, long *nextstart, long *nextend) { int status= 0; struct ioctlread ior; struct ioctlstat ios; struct qchaninfo sqi; cdqchaninfo(drive, &sqi); ior.cdh.len= 13; ior.cdh.unit= (char) drive; ior.cdh.cmd= IOCTL_READ; ior.cdh.stat= 0; ior.mdb= 0; ior.buffer= (void far *) &ios; ior.size= sizeof(ios); ior.ssn= 0; ior.errbuf= (void far *) 0; ios.cmd= 15; ios.status= 0; ios.startloc= 0; ios.endloc= 0; senddevreq(drive, &ior); if (ior.cdh.stat& 0x0200) status|= CDISPLAYING; if (ios.status& 0x0001) status|= CDISPAUSED; OURDISCSTATUS[drive]&= CDISHERE; if (OURDISCSTATUS[drive]& CDISHERE) if (!status) { int i= 0; long d; long s; struct qchaninfo dqi; s= msftolong(* ((long *) &sqi.min)); do { long *pd= (long *) &dqi.min; cdqchaninfo(drive, &dqi); d= msftolong(*pd); } while (++i < 5 && d - s < 75); if (i < 5) status|= CDISPLAYING; } OURDISCSTATUS[drive]|= status; *nextstart= ios.startloc; *nextend= ios.endloc; return(ios.status); } ; /*\ ; |*| cdmediachanged(int drive, int *yesorno) ; |*| ; |*| check if media has changed for drive ; |*| ; |*| Entry: drive number, pointer to flag ; |*| ; |*| Exit: return 0 if successful, else return -1 if error occurred ; |*| ; \*/ cdmediachanged(int drive, int *yesorno) { int status= 0; struct ioctlread ior; struct { char cmd; char changed; } dummy; ior.cdh.len= sizeof(struct cdreqheader); ior.cdh.unit= (char) drive; ior.cdh.cmd= IOCTL_READ; ior.cdh.stat= 0; ior.mdb= 0; ior.buffer= (void far *) &dummy; ior.size= sizeof(dummy); ior.ssn= 0; ior.errbuf= (void far *) 0; dummy.cmd= 9; dummy.changed= 0; senddevreq(drive, &ior); status= ior.cdh.stat; if (status& 0x8000) return(-1); *yesorno= dummy.changed; return(0); } ; /*\ ; |*| int cddiscinfo(int drive, struct discinfo *di) ; |*| ; |*| get information on disc in drive ; |*| ; |*| Entry: drive number, address of buffer ; |*| ; |*| Exit: return driver status ; |*| ; \*/ int cddiscinfo(int drive, struct discinfo *di) { int status= 0; struct ioctlread ior; ior.cdh.len= sizeof(struct cdreqheader); ior.cdh.unit= (char) drive; ior.cdh.cmd= IOCTL_READ; ior.cdh.stat= 0; ior.mdb= 0; ior.buffer= (void far *) di; ior.size= sizeof(struct discinfo); ior.ssn= 0; ior.errbuf= (void far *) 0; di->cmd= CD_GETDISCINFO; di->strk= 0; di->ltrk= 0; di->eodisc= 0; senddevreq(drive, &ior); status= ior.cdh.stat; if (status& 0x8000 || !(status& 0x0100)) OURDISCSTATUS[drive]&= (-1^ CDISHERE); else OURDISCSTATUS[drive]|= CDISHERE; return(status); } ; /*\ ; |*| int cdtrackinfo(int drive, int track, struct trackinfo *ti) ; |*| ; |*| get information on track of disc in drive ; |*| ; |*| Entry: drive number, track number, address of buffer ; |*| ; |*| Exit: return driver status ; |*| ; \*/ int cdtrackinfo(int drive, int track, struct trackinfo *ti) { int status= 0; struct ioctlread ior; ior.cdh.len= 13; ior.cdh.unit= (char) drive; ior.cdh.cmd= IOCTL_READ; ior.cdh.stat= 0; ior.mdb= 0; ior.buffer= (void far *) ti; ior.size= sizeof(struct trackinfo); ior.ssn= 0; ior.errbuf= (void far *) 0; ti->cmd= CD_GETTRACKINFO; ti->track= (char) track; ti->min= 0; ti->sec= 0; ti->frame= 0; ti->control= 0; senddevreq(drive, &ior); status|= ior.cdh.stat; return(status); } ; /*\ ; |*| int cdqchaninfo(int drive, struct qchaninfo *qi) ; |*| ; |*| get status from q-channel for drive ; |*| ; |*| Entry: drive number, address of buffer ; |*| ; |*| Exit: return driver status ; |*| ; \*/ int cdqchaninfo(int drive, struct qchaninfo *qi) { int status= 0; struct ioctlread ior; ior.cdh.len= sizeof(struct cdreqheader); ior.cdh.unit= (char) drive; ior.cdh.cmd= IOCTL_READ; ior.cdh.stat= 0; ior.mdb= 0; ior.buffer= (void far *) qi; ior.size= sizeof(struct qchaninfo); ior.ssn= 0; ior.errbuf= (void far *) 0; qi->cmd= CD_GETQCHANINFO; qi->caa= 0; qi->track= 0; qi->index= 0; qi->min= 0; qi->sec= 0; qi->frame= 0; qi->reserved1= 0; qi->amin= 0; qi->asec= 0; qi->aframe= 0; senddevreq(drive, &ior); status= ior.cdh.stat; if (status& 0x8000 || !(status& 0x0100)) OURDISCSTATUS[drive]&= (-1^ CDISHERE); else OURDISCSTATUS[drive]|= CDISHERE; return(status); } ; /*\ ; |*| isanaudiocd(int drive) ; |*| ; |*| check if disc in drive is an audio cd ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: return 1 if is an audio cd, else return 0 ; |*| ; \*/ isanaudiocd(int drive) { int failcount= 0; struct discinfo di; do { if (!((cddiscinfo(drive, &di))& 0x8000)) return(1); } while (++failcount < 5); return(0); } ; /*\ ; |*| cdseekmsf(int drive, int min, int sec, int frame) ; |*| ; |*| move head on drive to frame specified by min:sec:frame ; |*| ; |*| Entry: drive number, minutes, seconds, frames ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdseekmsf(int drive, int min, int sec, int frame) { long f; f= (long) min* 60; f+= (long) sec; f*= (long) 75; f+= (long) frame; return(cdseek(drive, f)); } ; /*\ ; |*| cdplaymsf(int drive, int min, int sec, int frame, int lmin, int lsec, int lframe) ; |*| ; |*| begin play for drive according at min:sec:frame for min:sec:frame ; |*| ; |*| Entry: drive number, minutes:seconds:frames to start and ; |*| minutes:seconds:frames for length ; |*| ; |*| Exit: return driver status ; |*| ; \*/ cdplaymsf(int drive, int min, int sec, int frame, int lmin, int lsec, int lframe) { long f; long lf; f= (long) min* 60; f+= (long) sec; f*= (long) 75; f+= (long) frame; lf= (long) lmin* 60; lf+= (long) lsec; lf*= (long) 75; lf+= (long) lframe; return(cdplay(drive, f, lf)); } ; /*\ ; |*| long redtolong(long redaddress) ; |*| ; |*| convert redbook address to frame number ; |*| ; |*| Entry: redbook address (0x00MMSSFF) ; |*| ; |*| Exit: frame number ; |*| ; \*/ long redtolong(long redaddress) { long longval= 0; union { struct { char frame; char sec; char min; char dead; } rtl; long l; } d; d.l= redaddress; longval+= d.rtl.min; longval*= 60; longval+= d.rtl.sec; longval*= 75; longval+= d.rtl.frame; return(longval); } ; /*\ ; |*| long longtored(long longval) ; |*| ; |*| convert frame number to redbook address ; |*| ; |*| Entry: frame value ; |*| ; |*| Exit: redbook address (0x00MMSSFF) ; |*| ; \*/ long longtored(long longval) { union { struct { char frame; char sec; char min; char dead; } rtl; long l; } d; d.rtl.min= longval/ 4500; d.rtl.sec= (longval% 4500)/ 75; d.rtl.frame= (longval% 4500)% 75; return(d.l); } ; /*\ ; |*| long msftolong(long msfvalue) ; |*| ; |*| convert FFSSMM00 value to frame number ; |*| ; |*| Entry: msf value (0xFFSSMM00) ; |*| ; |*| Exit: frame number ; |*| ; \*/ long msftolong(long msfvalue) { long longval= 0; union { struct { char min; char sec; char frame; char dead; } mtl; long l; } d; d.l= msfvalue; longval+= d.mtl.min; longval*= 60; longval+= d.mtl.sec; longval*= 75; longval+= d.mtl.frame; return(longval); } ; /*\ ; |*| inttobcd(int data) ; |*| ; |*| convert an integer to BCD representation ; |*| ; |*| Entry: integer ; |*| ; |*| Exit: value as BCD ; |*| ; \*/ inttobcd(int data) { int val; val= (data/ 10)<< 4; val+= (data% 10); return(val); } ; /*\ ; |*| bcdtoint(int data) ; |*| ; |*| convert a BCD number to an integer ; |*| ; |*| Entry: BCD number ; |*| ; |*| Exit: integer value ; |*| ; \*/ bcdtoint(int data) { int val; val= data& 0x0F; val+= ((data&0xF0)>> 4)* 10; return(val); } ; /*\ ; |*| fixmsf(int *min, int *sec, int *frame) ; |*| ; |*| boundarize elements of msf number ; |*| ; |*| Entry: int pointers to minutes, seconds and frame variables ; |*| ; |*| Exit: return -1 if minute ends up negative, 0 if not and ; |*| affect pointed to numbers ; |*| ; \*/ fixmsf(int *min, int *sec, int *frame) { int f= *frame; int s= *sec; int m= *min; while (f >= 75) { f-= 75; s+= 1; } while (s >= 60) { s-= 60; m+= 1; } while (f < 0) { f+= 75; s-= 1; } while (s < 0) { s+= 60; m-= 1; } if (m < 0) return(-1); *frame= f; *sec= s; *min= m; return(0); }