| /* | |
| * Cdrom - device driver emulation - Audio features. | |
| * (c) 1998 Petr Tomasek <tomasek@etf.cuni.cz> | |
| * | |
| */ | |
| #ifdef linux | |
| #include "config.h" | |
| #include <fcntl.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/types.h> | |
| /* FIXME - how to make this OS independent ?? */ | |
| #ifdef HAVE_LINUX_CDROM_H | |
| # include <linux/cdrom.h> | |
| #endif | |
| #ifdef HAVE_LINUX_UCDROM_H | |
| # include <linux/ucdrom.h> | |
| #endif | |
| #include "ldt.h" | |
| #include "drive.h" | |
| #include "msdos.h" | |
| #include "miscemu.h" | |
| #include "module.h" | |
| /* #define DEBUG_INT */ | |
| #include "debug.h" | |
| /* FIXME - more general ?? */ | |
| #define cdrom_dev "/dev/cdrom" | |
| u_char cdrom_a_status (int fd) | |
| { | |
| struct cdrom_subchnl sc; | |
| ioctl(fd,CDROMSUBCHNL,&sc); | |
| return sc.cdsc_audiostatus; | |
| } | |
| BYTE * get_io_stru (WORD * reqh,int dorealmode) | |
| { | |
| WORD ofst,segm; | |
| BYTE * io_stru; | |
| ofst = reqh[7]; segm = reqh[8]; | |
| if (dorealmode) | |
| io_stru = DOSMEM_MapRealToLinear (MAKELONG(ofst,segm)); | |
| else | |
| io_stru = PTR_SEG_OFF_TO_LIN(segm,ofst); | |
| return io_stru; | |
| } | |
| DWORD msf0_to_abs (struct cdrom_msf0 msf) | |
| { | |
| return (msf.minute *60 + | |
| msf.second) *75 + | |
| msf.frame-150; | |
| } | |
| void abs_to_msf0 (DWORD abs, struct cdrom_msf0 * msf) | |
| { | |
| DWORD d; | |
| d=abs+150; | |
| msf->frame=d%75; d=d/75; | |
| msf->second=d%60; msf->minute=d/60; | |
| } | |
| void msf0_to_msf (struct cdrom_msf0 from, struct cdrom_msf0 to, struct cdrom_msf * msf) | |
| { | |
| msf->cdmsf_min0=from.minute; | |
| msf->cdmsf_min1=to.minute; | |
| msf->cdmsf_sec0=from.second; | |
| msf->cdmsf_sec1=to.second; | |
| msf->cdmsf_frame0=from.frame; | |
| msf->cdmsf_frame1=to.frame; | |
| } | |
| void abs_to_msf (DWORD from, DWORD to, struct cdrom_msf * msf) | |
| { | |
| struct cdrom_msf0 fr,tt; | |
| abs_to_msf0(from, &fr); | |
| abs_to_msf0(to, &tt); | |
| msf0_to_msf(fr,tt,msf); | |
| } | |
| /************************************************************ | |
| * | |
| * Cdrom ms-dos driver emulation. | |
| * (accesible throught the MSCDEX 0x10 function.) | |
| */ | |
| extern void do_mscdex_dd (CONTEXT * context, int dorealmode) | |
| { | |
| BYTE * driver_request; | |
| BYTE * io_stru; | |
| static int fdcd=-1; /* file descriptor.. */ | |
| struct cdrom_tochdr tochdr; /* the Toc header */ | |
| struct cdrom_tocentry tocentry; /* a Toc entry */ | |
| struct cdrom_msf msf; | |
| struct cdrom_subchnl subchnl; | |
| u_char Error=255; /*No Error */ | |
| if (dorealmode) | |
| driver_request=DOSMEM_MapRealToLinear | |
| (MAKELONG(BX_reg(context),ES_reg(context))); | |
| else | |
| driver_request=PTR_SEG_OFF_TO_LIN(ES_reg(context),BX_reg(context)); | |
| if (!driver_request) | |
| { /* FIXME - to be deleted ?? */ | |
| ERR(int," ES:BX==0 ! SEGFAULT ?\n"); | |
| ERR(int," -->BX=0x%04x, ES=0x%04lx, DS=0x%04lx, CX=0x%04x\n\n", | |
| BX_reg(context), | |
| ES_reg(context), | |
| DS_reg(context), | |
| CX_reg(context)); | |
| } | |
| else | |
| /* FIXME - would be best to open the device at the begining of the wine | |
| session .... */ | |
| if (fdcd<0) fdcd=open(cdrom_dev,O_RDONLY); | |
| TRACE(int,"CDROM device driver -> command <%d>\n", | |
| (unsigned char)driver_request[2]); | |
| /* set status to 0 */ | |
| driver_request[3]=0; | |
| driver_request[4]=0; | |
| switch(driver_request[2]) | |
| { | |
| case 3: | |
| io_stru=get_io_stru((WORD *)driver_request,dorealmode); | |
| FIXME(int," --> IOCTL INPUT <%d>\n",io_stru[0]); | |
| switch (io_stru[0]) | |
| { | |
| case 1: /* location of head */ | |
| if (io_stru[1]==0) | |
| { | |
| ioctl(fdcd,CDROMSUBCHNL,&subchnl); | |
| ((DWORD*)io_stru+2)[0]=(DWORD)msf0_to_abs(subchnl.cdsc_absaddr.msf); | |
| FIXME(int," ----> HEAD LOCATION <%ld>\n\n", | |
| ((DWORD *)io_stru+2)[0]); | |
| } | |
| else | |
| { | |
| ERR(int,"CDRom-Driver: Unsupported address mode !!\n"); | |
| Error=0x0c; | |
| } | |
| break; | |
| case 6: /* device status */ | |
| /* FIXME .. does this work properly ?? */ | |
| io_stru[3]=io_stru[4]=0; | |
| io_stru[2]=1; /* supports audio channels (?? FIXME ??) */ | |
| io_stru[1]=16; /* data read and plays audio racks */ | |
| io_stru[1]|=(ioctl(fdcd,CDROM_DRIVE_STATUS,0)==CDS_TRAY_OPEN); | |
| TRACE(int," ----> DEVICE STATUS <0x%08lx>\n\n",(DWORD)io_stru[1]); | |
| break; | |
| case 9: /* media changed ? */ | |
| if (ioctl(fdcd,CDROM_MEDIA_CHANGED,0)) | |
| io_stru[1]=0xff; | |
| else | |
| io_stru[0]=0; /* FIXME? 1? */ | |
| break; | |
| case 10: /* audio disk info */ | |
| ioctl(fdcd,CDROMREADTOCHDR,&tochdr); | |
| io_stru[1]=tochdr.cdth_trk0; /* staring track of the disc */ | |
| io_stru[2]=tochdr.cdth_trk1; /* ending track */ | |
| tocentry.cdte_track=CDROM_LEADOUT; /* Now the leadout track ...*/ | |
| tocentry.cdte_format=CDROM_MSF; | |
| ioctl(fdcd,CDROMREADTOCENTRY,&tocentry); /* ... get position of it */ | |
| ((DWORD*)io_stru+3)[0]=(DWORD)msf0_to_abs(tocentry.cdte_addr.msf); | |
| TRACE(int," ----> AUDIO DISK INFO <%d-%d/%ld>\n\n", | |
| io_stru[1],io_stru[2], | |
| ((DWORD *)io_stru+3)[0]); | |
| break; | |
| case 11: /* audio track info */ | |
| tocentry.cdte_track=io_stru[1]; /* track of the disc */ | |
| tocentry.cdte_format=CDROM_MSF; | |
| ioctl(fdcd,CDROMREADTOCENTRY,&tocentry); | |
| ((DWORD*)io_stru+2)[0]=(DWORD)msf0_to_abs(tocentry.cdte_addr.msf); | |
| /* starting point if the track */ | |
| io_stru[6]=tocentry.cdte_adr+16*tocentry.cdte_ctrl; | |
| TRACE(int," ----> AUDIO TRACK INFO <track=%d>[%ld] \n\n", | |
| io_stru[1],((DWORD *)io_stru+2)[0]); | |
| break; | |
| case 12: /* get Q-Channel / Subchannel (??) info */ | |
| subchnl.cdsc_format=CDROM_MSF; | |
| ioctl(fdcd,CDROMSUBCHNL,&subchnl); | |
| io_stru[1]=subchnl.cdsc_adr+16*subchnl.cdsc_ctrl; | |
| io_stru[2]=subchnl.cdsc_trk; | |
| io_stru[3]=subchnl.cdsc_ind; /* FIXME - ?? */ | |
| io_stru[4]=subchnl.cdsc_reladdr.msf.minute; | |
| io_stru[5]=subchnl.cdsc_reladdr.msf.second; | |
| io_stru[6]=subchnl.cdsc_reladdr.msf.frame; | |
| io_stru[7]=0; /* always zero */ | |
| io_stru[8]=subchnl.cdsc_absaddr.msf.minute; | |
| io_stru[9]=subchnl.cdsc_absaddr.msf.second; | |
| io_stru[10]=subchnl.cdsc_absaddr.msf.frame; | |
| break; | |
| case 15: /* fixme !!!!!!! just a small workaround ! */ | |
| /* !!!! FIXME FIXME FIXME !! */ | |
| tocentry.cdte_track=CDROM_LEADOUT; /* Now the leadout track ...*/ | |
| tocentry.cdte_format=CDROM_MSF; | |
| ioctl(fdcd,CDROMREADTOCENTRY,&tocentry); /* ... get position of it */ | |
| ((DWORD*)io_stru+7)[0]=(DWORD)msf0_to_abs(tocentry.cdte_addr.msf); | |
| break; | |
| default: | |
| FIXME(int," Cdrom-driver: IOCTL INPUT: Unimplemented <%d>!! \n", | |
| io_stru[0]); | |
| Error=0x0c; | |
| break; | |
| } | |
| break; | |
| case 12: | |
| io_stru=get_io_stru((WORD *)driver_request,dorealmode); | |
| TRACE(int," --> IOCTL OUTPUT <%d>\n",io_stru[0]); | |
| switch (io_stru[0]) | |
| { | |
| case 0: /* eject */ | |
| ioctl (fdcd,CDROMEJECT); | |
| TRACE(int," ----> EJECT \n\n"); | |
| break; | |
| case 5: /* close tray */ | |
| ioctl (fdcd,CDROMCLOSETRAY); | |
| TRACE(int," ----> CLOSE TRAY \n\n"); | |
| break; | |
| case 2: /* reset drive */ | |
| ioctl (fdcd,CDROMRESET); | |
| TRACE(int," ----> RESET \n\n"); | |
| break; | |
| default: | |
| FIXME(int," Cdrom-driver: IOCTL OUPUT: Unimplemented <%d>!! \n", | |
| io_stru[0]); | |
| Error=0x0c; | |
| break; | |
| } | |
| break; | |
| case 133: | |
| if (cdrom_a_status(fdcd)==CDROM_AUDIO_PLAY) | |
| { | |
| ioctl (fdcd,CDROMPAUSE); | |
| TRACE(int," --> STOP AUDIO (Paused)\n\n"); | |
| } | |
| else | |
| { | |
| ioctl (fdcd,CDROMSTOP); | |
| TRACE(int," --> STOP AUDIO (Stopped)\n\n"); | |
| } | |
| break; | |
| case 132: /* FIXME - It didn't function for me... */ | |
| FIXME(int," --> PLAY AUDIO \n"); | |
| ioctl (fdcd,CDROMSTART); | |
| FIXME(int,"Mode :<0x%02X> , [%ld-%ld]\n\n", | |
| (unsigned char)driver_request[13], | |
| ((DWORD*)driver_request+14)[0], | |
| ((DWORD*)driver_request+18)[0]); | |
| if (driver_request[13]==0) | |
| { | |
| abs_to_msf(((DWORD*)driver_request+14)[0], | |
| ((DWORD*)driver_request+18)[0],&msf); | |
| ioctl(fdcd,CDROMPLAYMSF,&msf); | |
| } | |
| else | |
| { | |
| ERR(int,"CDRom-Driver: Unsupported address mode !!\n"); | |
| Error=0x0c; | |
| } | |
| break; | |
| case 136: | |
| TRACE(int," --> RESUME AUDIO \n\n"); | |
| ioctl(fdcd,CDROMRESUME); | |
| break; | |
| default: | |
| FIXME(int," CDRom-Driver - ioctl uninplemented <%d>\n",driver_request[2]); | |
| Error=0x0c; | |
| } | |
| if (Error<255) | |
| { | |
| driver_request[4]|=127; | |
| driver_request[3]=Error; | |
| } | |
| driver_request[4]|=2*(cdrom_a_status(fdcd)==CDROM_AUDIO_PLAY); | |
| /* close (fdcd); FIXME !! -- cannot use close when ejecting | |
| the cd-rom - close would close it again */ | |
| } | |
| #endif | |