[RESENT 2/4] winedos: implement true CDROM DOS device driver
Petr Tesarik
petr at tesarici.cz
Tue Apr 11 03:34:04 CDT 2006
Hi,
while I was trying to make Kindler Literaturlexikon work in Wine, I
found out that this program uses a DOS program to access the CDROM,
and that it requires a real working MSCDEX device driver (and not only
that, the driver has to reside in a different segment than the DOS
core).
To make the patches as small as possible, I've split the patch into
several parts.
This part provides moves the device driver code from MSCDEX_Handler()
to a new function MSCDEX_Request() which can be later called both by
MSCDEX_Handler() and by the MSCDEX interrupt routine.
In short, this is another patch which mostly just moves code around.
ChangeLog:
* dlls/winedos/int2f.c:
winedos: move most of MSCDEX stuff into a separate function
-------------- next part --------------
Index: int2f.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int2f.c,v
retrieving revision 1.8
diff -u -r1.8 int2f.c
--- int2f.c 28 Nov 2005 20:10:42 -0000 1.8
+++ int2f.c 10 Apr 2006 13:52:13 -0000
@@ -42,6 +42,24 @@
/* base WPROCS.DLL ordinal number for VxDs */
#define VXD_BASE 400
+typedef struct
+{
+ DOS_DEVICE_HEADER hdr;
+
+ WORD reserved; /* must be 0 */
+ BYTE drive; /* drive letter (0=A:, 1=B:, ...) */
+ BYTE units; /* number of supported units */
+} CDROM_DEVICE_HEADER;
+
+typedef struct
+{
+ CDROM_DEVICE_HEADER hdr;
+ WINEDEV_THUNK thunk;
+
+ WORD cdrom_segment; /* Real mode segment for CDROM_HEAP */
+ WORD cdrom_selector; /* Protected mode selector for CDROM_HEAP */
+} CDROM_HEAP;
+
static void do_int2f_16( CONTEXT86 *context );
static void MSCDEX_Handler( CONTEXT86 *context );
@@ -470,6 +488,470 @@
return (GetDriveTypeA(root) == DRIVE_CDROM);
}
+/***********************************************************************
+ * CDROM_FillHeap
+ *
+ * Initialize CDROM heap.
+ *
+ */
+static void CDROM_FillHeap( CDROM_HEAP *heap )
+{
+ int drive, count;
+
+ /* Count the number of contiguous CDROM drives
+ */
+ for (drive = count = 0; drive < 26; drive++) {
+ if (is_cdrom(drive)) {
+ while (is_cdrom(drive + count)) count++;
+ break;
+ }
+ }
+ TRACE("Installation check: %d cdroms, starting at %d\n", count, drive);
+ heap->hdr.drive = (drive < 26) ? drive : 0;
+ heap->hdr.units = count;
+ heap->hdr.reserved = 0;
+}
+
+/**********************************************************************
+ * CDROM_GetHeap
+ *
+ * Get pointer for CDROM heap (CDROM_HEAP).
+ * Creates and initializes heap on first call.
+ */
+static CDROM_HEAP *CDROM_GetHeap( void )
+{
+ static CDROM_HEAP *heap_pointer = NULL;
+
+ if ( !heap_pointer )
+ {
+ WORD heap_segment;
+ WORD heap_selector;
+
+ /* allocate a new DOS data segment */
+ heap_pointer = DOSVM_AllocDataUMB( sizeof(CDROM_HEAP),
+ &heap_segment,
+ &heap_selector );
+
+ heap_pointer->cdrom_segment = heap_segment;
+ heap_pointer->cdrom_selector = heap_selector;
+ CDROM_FillHeap( heap_pointer );
+ }
+
+ return heap_pointer;
+}
+
+static void MSCDEX_Request(BYTE *driver_request, BOOL dorealmode)
+{
+ BYTE* io_stru;
+ BYTE Error = 255; /* No Error */
+ char devName[] = "\\\\.\\@:";
+ HANDLE h;
+ CDROM_TOC toc;
+ CDROM_SUB_Q_DATA_FORMAT fmt;
+ SUB_Q_CHANNEL_DATA data;
+ DWORD br;
+ DWORD present = TRUE;
+
+ /* FIXME
+ * the following tests are wrong because lots of functions don't require the
+ * tray to be closed with a CD inside
+ */
+ TRACE("CDROM device driver -> command <%d>\n", (unsigned char)driver_request[2]);
+
+ MSCDEX_Dump("Beg", driver_request, dorealmode);
+
+ /* set status to 0 */
+ PTR_AT(driver_request, 3, WORD) = 0;
+ devName[4] = 'A' + CDROM_GetHeap()->hdr.drive + driver_request[1];
+ h = CreateFileA(devName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (!h) {
+ WARN("Couldn't open cdrom handle\n");
+ driver_request[4] |= 0x80;
+ driver_request[3] = 1; /* unknown unit */
+ return;
+ }
+
+ fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
+ if (!DeviceIoControl(h, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &br, NULL) ||
+ !DeviceIoControl(h, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt),
+ &data, sizeof(data), &br, NULL)) {
+ if (GetLastError() == STATUS_NO_MEDIA_IN_DEVICE)
+ {
+ if (driver_request[2] != 6 && driver_request[2] != 15)
+ {
+ driver_request[4] |= 0x80;
+ driver_request[3] = 2; /* drive not ready */
+ CloseHandle(h);
+ return;
+ }
+ present = FALSE;
+ }
+ else
+ {
+ driver_request[4] |= 0x80;
+ driver_request[3] = 1; /* unknown unit */
+ CloseHandle(h);
+ return;
+ }
+ }
+
+ switch (driver_request[2]) {
+ case 3:
+ io_stru = (dorealmode) ?
+ PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD) ) :
+ MapSL( MAKESEGPTR(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)));
+
+ TRACE(" --> IOCTL INPUT <%d>\n", io_stru[0]);
+ switch (io_stru[0]) {
+#if 0
+ case 0: /* Get device Header */
+ {
+ static LPSTR ptr = 0;
+ if (ptr == 0) {
+ ptr = SEGPTR_ALLOC(22);
+ PTR_AT(ptr, 0, DWORD) = ~1; /* Next Device Driver */
+ PTR_AT(ptr, 4, WORD) = 0xC800; /* Device attributes */
+ PTR_AT(ptr, 6, WORD) = 0x1234; /* Pointer to device strategy routine: FIXME */
+ PTR_AT(ptr, 8, WORD) = 0x3142; /* Pointer to device interrupt routine: FIXME */
+ PTR_AT(ptr, 10, char) = 'W'; /* 8-byte character device name field */
+ PTR_AT(ptr, 11, char) = 'I';
+ PTR_AT(ptr, 12, char) = 'N';
+ PTR_AT(ptr, 13, char) = 'E';
+ PTR_AT(ptr, 14, char) = '_';
+ PTR_AT(ptr, 15, char) = 'C';
+ PTR_AT(ptr, 16, char) = 'D';
+ PTR_AT(ptr, 17, char) = '_';
+ PTR_AT(ptr, 18, WORD) = 0; /* Reserved (must be zero) */
+ PTR_AT(ptr, 20, BYTE) = 0; /* Drive letter (must be zero) */
+ PTR_AT(ptr, 21, BYTE) = 1; /* Number of units supported (one or more) FIXME*/
+ }
+ PTR_AT(io_stru, DWORD, 0) = SEGPTR_GET(ptr);
+ }
+ break;
+#endif
+
+ case 1: /* location of head */
+ switch (io_stru[1]) {
+ case 0:
+ PTR_AT(io_stru, 2, DWORD) =
+ FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
+ break;
+ case 1:
+ MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress),
+ io_stru + 2);
+ break;
+ default:
+ ERR("CD-ROM driver: unsupported addressing mode !!\n");
+ Error = 0x0c;
+ }
+ TRACE(" ----> HEAD LOCATION <%ld>\n", PTR_AT(io_stru, 2, DWORD));
+ break;
+
+ case 4: /* Audio channel info */
+ io_stru[1] = 0;
+ io_stru[2] = 0xff;
+ io_stru[3] = 1;
+ io_stru[4] = 0xff;
+ io_stru[5] = 2;
+ io_stru[6] = 0;
+ io_stru[7] = 3;
+ io_stru[8] = 0;
+ TRACE(" ----> AUDIO CHANNEL INFO\n");
+ break;
+
+ case 6: /* device status */
+ PTR_AT(io_stru, 1, DWORD) = 0x00000290;
+ /* 290 =>
+ * 1 Supports HSG and Red Book addressing modes
+ * 0 Supports audio channel manipulation
+ *
+ * 1 Supports prefetching requests
+ * 0 Reserved
+ * 0 No interleaving
+ * 1 Data read and plays audio/video tracks
+ *
+ * 0 Read only
+ * 0 Supports only cooked reading
+ * 0 Door locked
+ * 0 see below (Door closed/opened)
+ */
+ if (!present) PTR_AT(io_stru, 1, DWORD) |= 1;
+ TRACE(" ----> DEVICE STATUS <0x%08lx>\n", PTR_AT(io_stru, 1, DWORD));
+ break;
+
+ case 8: /* Volume size */
+ PTR_AT(io_stru, 1, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1) -
+ FRAME_OF_TOC(toc, toc.FirstTrack) - 1;
+ TRACE(" ----> VOLUME SIZE <%ld>\n", PTR_AT(io_stru, 1, DWORD));
+ break;
+
+ case 9: /* media changed ? */
+ /* answers don't know... -1/1 for yes/no would be better */
+ io_stru[1] = 0; /* FIXME? 1? */
+ TRACE(" ----> MEDIA CHANGED <%d>\n", io_stru[1]);
+ break;
+
+ case 10: /* audio disk info */
+ io_stru[1] = toc.FirstTrack; /* starting track of the disc */
+ io_stru[2] = toc.LastTrack; /* ending track */
+ MSCDEX_StoreMSF(FRAME_OF_TOC(toc, toc.LastTrack + 1) -
+ FRAME_OF_TOC(toc, toc.FirstTrack) - 1, io_stru + 3);
+
+ TRACE(" ----> AUDIO DISK INFO <%d-%d/%08lx>\n",
+ io_stru[1], io_stru[2], PTR_AT(io_stru, 3, DWORD));
+ break;
+
+ case 11: /* audio track info */
+ if (io_stru[1] >= toc.FirstTrack && io_stru[1] <= toc.LastTrack) {
+ MSCDEX_StoreMSF(FRAME_OF_TOC(toc, io_stru[1]), io_stru + 2);
+ /* starting point if the track */
+ io_stru[6] = CTRL_OF_TOC(toc, io_stru[1]);
+ } else {
+ PTR_AT(io_stru, 2, DWORD) = 0;
+ io_stru[6] = 0;
+ }
+ TRACE(" ----> AUDIO TRACK INFO[%d] = [%08lx:%d]\n",
+ io_stru[1], PTR_AT(io_stru, 2, DWORD), io_stru[6]);
+ break;
+
+ case 12: /* get Q-Channel info */
+ io_stru[1] = CTRL_OF_TOC(toc, data.CurrentPosition.TrackNumber);
+ io_stru[2] = data.CurrentPosition.TrackNumber;
+ io_stru[3] = 0; /* FIXME ?? */
+
+ /* why the heck did MS use another format for 0MSF information... sigh */
+ {
+ BYTE bTmp[4];
+
+ MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.TrackRelativeAddress), bTmp);
+ io_stru[ 4] = bTmp[2];
+ io_stru[ 5] = bTmp[1];
+ io_stru[ 6] = bTmp[0];
+ io_stru[ 7] = 0;
+
+ MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress), bTmp);
+ io_stru[ 8] = bTmp[2];
+ io_stru[ 9] = bTmp[1];
+ io_stru[10] = bTmp[0];
+ io_stru[11] = 0;
+ }
+ TRACE("Q-Channel info: Ctrl/adr=%02x TNO=%02x X=%02x rtt=%02x:%02x:%02x rtd=%02x:%02x:%02x (cf=%08x, tp=%08x)\n",
+ io_stru[ 1], io_stru[ 2], io_stru[ 3],
+ io_stru[ 4], io_stru[ 5], io_stru[ 6],
+ io_stru[ 8], io_stru[ 9], io_stru[10],
+ FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress),
+ FRAME_OF_TOC(toc, data.CurrentPosition.TrackNumber));
+ break;
+
+ case 15: /* Audio status info */
+ /* !!!! FIXME FIXME FIXME !! */
+ PTR_AT(io_stru, 1, WORD) = 2 | ((data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED) ? 1 : 0);
+ if (!present) {
+ PTR_AT(io_stru, 3, DWORD) = 0;
+ PTR_AT(io_stru, 7, DWORD) = 0;
+ } else {
+ PTR_AT(io_stru, 3, DWORD) = FRAME_OF_TOC(toc, toc.FirstTrack);
+ PTR_AT(io_stru, 7, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1);
+ }
+ TRACE("Audio status info: status=%04x startLoc=%ld endLoc=%ld\n",
+ PTR_AT(io_stru, 1, WORD), PTR_AT(io_stru, 3, DWORD), PTR_AT(io_stru, 7, DWORD));
+ break;
+
+ default:
+ FIXME("IOCTL INPUT: Unimplemented <%d>!!\n", io_stru[0]);
+ Error = 0x0c;
+ break;
+ }
+ break;
+
+ case 12:
+ io_stru = (dorealmode) ?
+ PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)) :
+ MapSL( MAKESEGPTR(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)));
+
+ TRACE(" --> IOCTL OUTPUT <%d>\n", io_stru[0]);
+ switch (io_stru[0]) {
+ case 0: /* eject */
+ DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &br, NULL);
+ TRACE(" ----> EJECT\n");
+ break;
+ case 2: /* reset drive */
+ DeviceIoControl(h, IOCTL_STORAGE_RESET_DEVICE, NULL, 0, NULL, 0, &br, NULL);
+ TRACE(" ----> RESET\n");
+ break;
+ case 3: /* Audio Channel Control */
+ FIXME(" ----> AUDIO CHANNEL CONTROL (NIY)\n");
+ break;
+ case 5: /* close tray */
+ DeviceIoControl(h, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &br, NULL);
+ TRACE(" ----> CLOSE TRAY\n");
+ break;
+ default:
+ FIXME(" IOCTL OUTPUT: Unimplemented <%d>!!\n", io_stru[0]);
+ Error = 0x0c;
+ break;
+ }
+ break;
+
+ case 128: /* read long */
+ {
+ LPVOID dst = MapSL(MAKESEGPTR(PTR_AT(driver_request, 16, WORD),
+ PTR_AT(driver_request, 14, WORD)));
+ DWORD at = PTR_AT(driver_request, 20, DWORD);
+ WORD num = PTR_AT(driver_request, 18, WORD);
+ RAW_READ_INFO rri;
+
+ switch (driver_request[13]) {
+ case 1: /* Red book addressing mode = 0:m:s:f */
+ /* FIXME : frame <=> msf conversion routines could be shared
+ * between mscdex and mcicda
+ */
+ at = LOBYTE(HIWORD(at)) * CDFRAMES_PERMIN +
+ HIBYTE(LOWORD(at)) * CDFRAMES_PERSEC +
+ LOBYTE(LOWORD(at));
+ /* fall through */
+ case 0: /* HSG addressing mode */
+ switch (PTR_AT(driver_request, 24, BYTE))
+ {
+ case 0: /* cooked */
+ ReadFile(h, dst, num * 2048, &br, NULL);
+ break;
+ case 1:
+ /* FIXME: computation is wrong */
+ rri.DiskOffset.u.HighPart = 0;
+ rri.DiskOffset.u.LowPart = at << 11;
+ rri.TrackMode = YellowMode2;
+ rri.SectorCount = num;
+ DeviceIoControl(h, IOCTL_CDROM_RAW_READ, &rri, sizeof(rri),
+ dst, num * 2352, &br, NULL);
+ break;
+ default:
+ ERR("Unsupported read mode !!\n");
+ Error = 0x0c;
+ break;
+ }
+ break;
+ default:
+ ERR("Unsupported address mode !!\n");
+ Error = 0x0c;
+ break;
+ }
+ }
+ break;
+
+ case 131: /* seek */
+ {
+ DWORD at;
+ CDROM_SEEK_AUDIO_MSF seek;
+
+ at = PTR_AT(driver_request, 20, DWORD);
+
+ TRACE(" --> SEEK AUDIO mode :<0x%02X>, [%ld]\n",
+ (BYTE)driver_request[13], at);
+
+ switch (driver_request[13]) {
+ case 1: /* Red book addressing mode = 0:m:s:f */
+ /* FIXME : frame <=> msf conversion routines could be shared
+ * between mscdex and mcicda
+ */
+ at = LOBYTE(HIWORD(at)) * CDFRAMES_PERMIN +
+ HIBYTE(LOWORD(at)) * CDFRAMES_PERSEC +
+ LOBYTE(LOWORD(at));
+ /* fall through */
+ case 0: /* HSG addressing mode */
+ seek.M = at / CDFRAMES_PERMIN;
+ seek.S = (at / CDFRAMES_PERSEC) % 60;
+ seek.F = at % CDFRAMES_PERSEC;
+ DeviceIoControl(h, IOCTL_CDROM_SEEK_AUDIO_MSF, &seek, sizeof(seek),
+ NULL, 0, &br, NULL);
+ break;
+ default:
+ ERR("Unsupported address mode !!\n");
+ Error = 0x0c;
+ break;
+ }
+ }
+ break;
+
+ case 132: /* play */
+ {
+ DWORD beg, end;
+ CDROM_PLAY_AUDIO_MSF play;
+
+ beg = end = PTR_AT(driver_request, 14, DWORD);
+ end += PTR_AT(driver_request, 18, DWORD);
+
+ TRACE(" --> PLAY AUDIO mode :<0x%02X>, [%ld-%ld]\n",
+ (BYTE)driver_request[13], beg, end);
+
+ switch (driver_request[13]) {
+ case 1:
+ /* Red book addressing mode = 0:m:s:f */
+ /* FIXME : frame <=> msf conversion routines could be shared
+ * between mscdex and mcicda
+ */
+ beg = LOBYTE(LOWORD(beg)) * CDFRAMES_PERMIN +
+ HIBYTE(LOWORD(beg)) * CDFRAMES_PERSEC +
+ LOBYTE(HIWORD(beg));
+ end = LOBYTE(LOWORD(end)) * CDFRAMES_PERMIN +
+ HIBYTE(LOWORD(end)) * CDFRAMES_PERSEC +
+ LOBYTE(HIWORD(end));
+ /* fall through */
+ case 0: /* HSG addressing mode */
+ play.StartingM = beg / CDFRAMES_PERMIN;
+ play.StartingS = (beg / CDFRAMES_PERSEC) % 60;
+ play.StartingF = beg % CDFRAMES_PERSEC;
+ play.EndingM = end / CDFRAMES_PERMIN;
+ play.EndingS = (end / CDFRAMES_PERSEC) % 60;
+ play.EndingF = end % CDFRAMES_PERSEC;
+ DeviceIoControl(h, IOCTL_CDROM_PLAY_AUDIO_MSF, &play, sizeof(play),
+ NULL, 0, &br, NULL);
+ break;
+ default:
+ ERR("Unsupported address mode !!\n");
+ Error = 0x0c;
+ break;
+ }
+ }
+ break;
+
+ case 133:
+ if (data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) {
+ DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
+ TRACE(" --> STOP AUDIO (Paused)\n");
+ } else {
+ DeviceIoControl(h, IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &br, NULL);
+ TRACE(" --> STOP AUDIO (Stopped)\n");
+ }
+ break;
+
+ case 136:
+ TRACE(" --> RESUME AUDIO\n");
+ DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
+ break;
+
+ default:
+ FIXME(" ioctl unimplemented <%d>\n", driver_request[2]);
+ Error = 0x0c;
+ }
+
+ /* setting error codes if any */
+ if (Error < 255) {
+ driver_request[4] |= 0x80;
+ driver_request[3] = Error;
+ }
+
+ CloseHandle(h);
+ /* setting status bits
+ * 3 == playing && done
+ * 1 == done
+ */
+ driver_request[4] |=
+ (data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) ? 3 : 1;
+
+ MSCDEX_Dump("End", driver_request, dorealmode);
+}
+
static void MSCDEX_Handler(CONTEXT86* context)
{
int drive, count;
@@ -512,16 +994,14 @@
case 0x10: /* direct driver access */
{
BYTE* driver_request;
- BYTE* io_stru;
- BYTE Error = 255; /* No Error */
- int dorealmode = ISV86(context);
- char devName[] = "\\\\.\\@:";
- HANDLE h;
- CDROM_TOC toc;
- CDROM_SUB_Q_DATA_FORMAT fmt;
- SUB_Q_CHANNEL_DATA data;
- DWORD br;
- DWORD present = TRUE;
+ CDROM_HEAP* cdrom_heap = CDROM_GetHeap();
+
+ if (!is_cdrom(CX_reg(context))) {
+ WARN("Request made doesn't match a CD ROM drive (%d)\n", CX_reg(context));
+ SET_CFLAG( context );
+ SET_AX( context, 0x000f ); /* invalid drive */
+ return;
+ }
driver_request = CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx);
@@ -534,411 +1014,9 @@
driver_request[3] = 5; /* bad request length */
return;
}
- /* FIXME
- * the following tests are wrong because lots of functions don't require the
- * tray to be closed with a CD inside
- */
- TRACE("CDROM device driver -> command <%d>\n", (unsigned char)driver_request[2]);
-
- if (!is_cdrom(CX_reg(context))) {
- WARN("Request made doesn't match a CD ROM drive (%d)\n", CX_reg(context));
- driver_request[4] |= 0x80;
- driver_request[3] = 1; /* unknown unit */
- return;
- }
-
- MSCDEX_Dump("Beg", driver_request, dorealmode);
-
- /* set status to 0 */
- PTR_AT(driver_request, 3, WORD) = 0;
- devName[4] = 'A' + CX_reg(context);
- h = CreateFileA(devName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
- if (!h) {
- WARN("Couldn't open cdrom handle\n");
- driver_request[4] |= 0x80;
- driver_request[3] = 1; /* unknown unit */
- return;
- }
-
- fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
- if (!DeviceIoControl(h, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &br, NULL) ||
- !DeviceIoControl(h, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt),
- &data, sizeof(data), &br, NULL)) {
- if (GetLastError() == STATUS_NO_MEDIA_IN_DEVICE)
- {
- if (driver_request[2] != 6 && driver_request[2] != 15)
- {
- driver_request[4] |= 0x80;
- driver_request[3] = 2; /* drive not ready */
- CloseHandle(h);
- return;
- }
- present = FALSE;
- }
- else
- {
- driver_request[4] |= 0x80;
- driver_request[3] = 1; /* unknown unit */
- CloseHandle(h);
- return;
- }
- }
-
- switch (driver_request[2]) {
- case 3:
- io_stru = (dorealmode) ?
- PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD) ) :
- MapSL( MAKESEGPTR(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)));
-
- TRACE(" --> IOCTL INPUT <%d>\n", io_stru[0]);
- switch (io_stru[0]) {
-#if 0
- case 0: /* Get device Header */
- {
- static LPSTR ptr = 0;
- if (ptr == 0) {
- ptr = SEGPTR_ALLOC(22);
- PTR_AT(ptr, 0, DWORD) = ~1; /* Next Device Driver */
- PTR_AT(ptr, 4, WORD) = 0xC800; /* Device attributes */
- PTR_AT(ptr, 6, WORD) = 0x1234; /* Pointer to device strategy routine: FIXME */
- PTR_AT(ptr, 8, WORD) = 0x3142; /* Pointer to device interrupt routine: FIXME */
- PTR_AT(ptr, 10, char) = 'W'; /* 8-byte character device name field */
- PTR_AT(ptr, 11, char) = 'I';
- PTR_AT(ptr, 12, char) = 'N';
- PTR_AT(ptr, 13, char) = 'E';
- PTR_AT(ptr, 14, char) = '_';
- PTR_AT(ptr, 15, char) = 'C';
- PTR_AT(ptr, 16, char) = 'D';
- PTR_AT(ptr, 17, char) = '_';
- PTR_AT(ptr, 18, WORD) = 0; /* Reserved (must be zero) */
- PTR_AT(ptr, 20, BYTE) = 0; /* Drive letter (must be zero) */
- PTR_AT(ptr, 21, BYTE) = 1; /* Number of units supported (one or more) FIXME*/
- }
- PTR_AT(io_stru, DWORD, 0) = SEGPTR_GET(ptr);
- }
- break;
-#endif
-
- case 1: /* location of head */
- switch (io_stru[1]) {
- case 0:
- PTR_AT(io_stru, 2, DWORD) =
- FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
- break;
- case 1:
- MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress),
- io_stru + 2);
- break;
- default:
- ERR("CD-ROM driver: unsupported addressing mode !!\n");
- Error = 0x0c;
- }
- TRACE(" ----> HEAD LOCATION <%ld>\n", PTR_AT(io_stru, 2, DWORD));
- break;
-
- case 4: /* Audio channel info */
- io_stru[1] = 0;
- io_stru[2] = 0xff;
- io_stru[3] = 1;
- io_stru[4] = 0xff;
- io_stru[5] = 2;
- io_stru[6] = 0;
- io_stru[7] = 3;
- io_stru[8] = 0;
- TRACE(" ----> AUDIO CHANNEL INFO\n");
- break;
-
- case 6: /* device status */
- PTR_AT(io_stru, 1, DWORD) = 0x00000290;
- /* 290 =>
- * 1 Supports HSG and Red Book addressing modes
- * 0 Supports audio channel manipulation
- *
- * 1 Supports prefetching requests
- * 0 Reserved
- * 0 No interleaving
- * 1 Data read and plays audio/video tracks
- *
- * 0 Read only
- * 0 Supports only cooked reading
- * 0 Door locked
- * 0 see below (Door closed/opened)
- */
- if (!present) PTR_AT(io_stru, 1, DWORD) |= 1;
- TRACE(" ----> DEVICE STATUS <0x%08lx>\n", PTR_AT(io_stru, 1, DWORD));
- break;
-
- case 8: /* Volume size */
- PTR_AT(io_stru, 1, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1) -
- FRAME_OF_TOC(toc, toc.FirstTrack) - 1;
- TRACE(" ----> VOLUME SIZE <%ld>\n", PTR_AT(io_stru, 1, DWORD));
- break;
-
- case 9: /* media changed ? */
- /* answers don't know... -1/1 for yes/no would be better */
- io_stru[1] = 0; /* FIXME? 1? */
- TRACE(" ----> MEDIA CHANGED <%d>\n", io_stru[1]);
- break;
-
- case 10: /* audio disk info */
- io_stru[1] = toc.FirstTrack; /* starting track of the disc */
- io_stru[2] = toc.LastTrack; /* ending track */
- MSCDEX_StoreMSF(FRAME_OF_TOC(toc, toc.LastTrack + 1) -
- FRAME_OF_TOC(toc, toc.FirstTrack) - 1, io_stru + 3);
-
- TRACE(" ----> AUDIO DISK INFO <%d-%d/%08lx>\n",
- io_stru[1], io_stru[2], PTR_AT(io_stru, 3, DWORD));
- break;
-
- case 11: /* audio track info */
- if (io_stru[1] >= toc.FirstTrack && io_stru[1] <= toc.LastTrack) {
- MSCDEX_StoreMSF(FRAME_OF_TOC(toc, io_stru[1]), io_stru + 2);
- /* starting point if the track */
- io_stru[6] = CTRL_OF_TOC(toc, io_stru[1]);
- } else {
- PTR_AT(io_stru, 2, DWORD) = 0;
- io_stru[6] = 0;
- }
- TRACE(" ----> AUDIO TRACK INFO[%d] = [%08lx:%d]\n",
- io_stru[1], PTR_AT(io_stru, 2, DWORD), io_stru[6]);
- break;
-
- case 12: /* get Q-Channel info */
- io_stru[1] = CTRL_OF_TOC(toc, data.CurrentPosition.TrackNumber);
- io_stru[2] = data.CurrentPosition.TrackNumber;
- io_stru[3] = 0; /* FIXME ?? */
-
- /* why the heck did MS use another format for 0MSF information... sigh */
- {
- BYTE bTmp[4];
-
- MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.TrackRelativeAddress), bTmp);
- io_stru[ 4] = bTmp[2];
- io_stru[ 5] = bTmp[1];
- io_stru[ 6] = bTmp[0];
- io_stru[ 7] = 0;
-
- MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress), bTmp);
- io_stru[ 8] = bTmp[2];
- io_stru[ 9] = bTmp[1];
- io_stru[10] = bTmp[0];
- io_stru[11] = 0;
- }
- TRACE("Q-Channel info: Ctrl/adr=%02x TNO=%02x X=%02x rtt=%02x:%02x:%02x rtd=%02x:%02x:%02x (cf=%08x, tp=%08x)\n",
- io_stru[ 1], io_stru[ 2], io_stru[ 3],
- io_stru[ 4], io_stru[ 5], io_stru[ 6],
- io_stru[ 8], io_stru[ 9], io_stru[10],
- FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress),
- FRAME_OF_TOC(toc, data.CurrentPosition.TrackNumber));
- break;
-
- case 15: /* Audio status info */
- /* !!!! FIXME FIXME FIXME !! */
- PTR_AT(io_stru, 1, WORD) = 2 | ((data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED) ? 1 : 0);
- if (!present) {
- PTR_AT(io_stru, 3, DWORD) = 0;
- PTR_AT(io_stru, 7, DWORD) = 0;
- } else {
- PTR_AT(io_stru, 3, DWORD) = FRAME_OF_TOC(toc, toc.FirstTrack);
- PTR_AT(io_stru, 7, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1);
- }
- TRACE("Audio status info: status=%04x startLoc=%ld endLoc=%ld\n",
- PTR_AT(io_stru, 1, WORD), PTR_AT(io_stru, 3, DWORD), PTR_AT(io_stru, 7, DWORD));
- break;
-
- default:
- FIXME("IOCTL INPUT: Unimplemented <%d>!!\n", io_stru[0]);
- Error = 0x0c;
- break;
- }
- break;
-
- case 12:
- io_stru = (dorealmode) ?
- PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)) :
- MapSL( MAKESEGPTR(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)));
-
- TRACE(" --> IOCTL OUTPUT <%d>\n", io_stru[0]);
- switch (io_stru[0]) {
- case 0: /* eject */
- DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &br, NULL);
- TRACE(" ----> EJECT\n");
- break;
- case 2: /* reset drive */
- DeviceIoControl(h, IOCTL_STORAGE_RESET_DEVICE, NULL, 0, NULL, 0, &br, NULL);
- TRACE(" ----> RESET\n");
- break;
- case 3: /* Audio Channel Control */
- FIXME(" ----> AUDIO CHANNEL CONTROL (NIY)\n");
- break;
- case 5: /* close tray */
- DeviceIoControl(h, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &br, NULL);
- TRACE(" ----> CLOSE TRAY\n");
- break;
- default:
- FIXME(" IOCTL OUTPUT: Unimplemented <%d>!!\n", io_stru[0]);
- Error = 0x0c;
- break;
- }
- break;
-
- case 128: /* read long */
- {
- LPVOID dst = MapSL(MAKESEGPTR(PTR_AT(driver_request, 16, WORD),
- PTR_AT(driver_request, 14, WORD)));
- DWORD at = PTR_AT(driver_request, 20, DWORD);
- WORD num = PTR_AT(driver_request, 18, WORD);
- RAW_READ_INFO rri;
-
- switch (driver_request[13]) {
- case 1: /* Red book addressing mode = 0:m:s:f */
- /* FIXME : frame <=> msf conversion routines could be shared
- * between mscdex and mcicda
- */
- at = LOBYTE(HIWORD(at)) * CDFRAMES_PERMIN +
- HIBYTE(LOWORD(at)) * CDFRAMES_PERSEC +
- LOBYTE(LOWORD(at));
- /* fall through */
- case 0: /* HSG addressing mode */
- switch (PTR_AT(driver_request, 24, BYTE))
- {
- case 0: /* cooked */
- ReadFile(h, dst, num * 2048, &br, NULL);
- break;
- case 1:
- /* FIXME: computation is wrong */
- rri.DiskOffset.u.HighPart = 0;
- rri.DiskOffset.u.LowPart = at << 11;
- rri.TrackMode = YellowMode2;
- rri.SectorCount = num;
- DeviceIoControl(h, IOCTL_CDROM_RAW_READ, &rri, sizeof(rri),
- dst, num * 2352, &br, NULL);
- break;
- default:
- ERR("Unsupported read mode !!\n");
- Error = 0x0c;
- break;
- }
- break;
- default:
- ERR("Unsupported address mode !!\n");
- Error = 0x0c;
- break;
- }
- }
- break;
-
- case 131: /* seek */
- {
- DWORD at;
- CDROM_SEEK_AUDIO_MSF seek;
-
- at = PTR_AT(driver_request, 20, DWORD);
-
- TRACE(" --> SEEK AUDIO mode :<0x%02X>, [%ld]\n",
- (BYTE)driver_request[13], at);
-
- switch (driver_request[13]) {
- case 1: /* Red book addressing mode = 0:m:s:f */
- /* FIXME : frame <=> msf conversion routines could be shared
- * between mscdex and mcicda
- */
- at = LOBYTE(HIWORD(at)) * CDFRAMES_PERMIN +
- HIBYTE(LOWORD(at)) * CDFRAMES_PERSEC +
- LOBYTE(LOWORD(at));
- /* fall through */
- case 0: /* HSG addressing mode */
- seek.M = at / CDFRAMES_PERMIN;
- seek.S = (at / CDFRAMES_PERSEC) % 60;
- seek.F = at % CDFRAMES_PERSEC;
- DeviceIoControl(h, IOCTL_CDROM_SEEK_AUDIO_MSF, &seek, sizeof(seek),
- NULL, 0, &br, NULL);
- break;
- default:
- ERR("Unsupported address mode !!\n");
- Error = 0x0c;
- break;
- }
- }
- break;
-
- case 132: /* play */
- {
- DWORD beg, end;
- CDROM_PLAY_AUDIO_MSF play;
-
- beg = end = PTR_AT(driver_request, 14, DWORD);
- end += PTR_AT(driver_request, 18, DWORD);
-
- TRACE(" --> PLAY AUDIO mode :<0x%02X>, [%ld-%ld]\n",
- (BYTE)driver_request[13], beg, end);
-
- switch (driver_request[13]) {
- case 1:
- /* Red book addressing mode = 0:m:s:f */
- /* FIXME : frame <=> msf conversion routines could be shared
- * between mscdex and mcicda
- */
- beg = LOBYTE(LOWORD(beg)) * CDFRAMES_PERMIN +
- HIBYTE(LOWORD(beg)) * CDFRAMES_PERSEC +
- LOBYTE(HIWORD(beg));
- end = LOBYTE(LOWORD(end)) * CDFRAMES_PERMIN +
- HIBYTE(LOWORD(end)) * CDFRAMES_PERSEC +
- LOBYTE(HIWORD(end));
- /* fall through */
- case 0: /* HSG addressing mode */
- play.StartingM = beg / CDFRAMES_PERMIN;
- play.StartingS = (beg / CDFRAMES_PERSEC) % 60;
- play.StartingF = beg % CDFRAMES_PERSEC;
- play.EndingM = end / CDFRAMES_PERMIN;
- play.EndingS = (end / CDFRAMES_PERSEC) % 60;
- play.EndingF = end % CDFRAMES_PERSEC;
- DeviceIoControl(h, IOCTL_CDROM_PLAY_AUDIO_MSF, &play, sizeof(play),
- NULL, 0, &br, NULL);
- break;
- default:
- ERR("Unsupported address mode !!\n");
- Error = 0x0c;
- break;
- }
- }
- break;
-
- case 133:
- if (data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) {
- DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
- TRACE(" --> STOP AUDIO (Paused)\n");
- } else {
- DeviceIoControl(h, IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &br, NULL);
- TRACE(" --> STOP AUDIO (Stopped)\n");
- }
- break;
-
- case 136:
- TRACE(" --> RESUME AUDIO\n");
- DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
- break;
-
- default:
- FIXME(" ioctl unimplemented <%d>\n", driver_request[2]);
- Error = 0x0c;
- }
-
- /* setting error codes if any */
- if (Error < 255) {
- driver_request[4] |= 0x80;
- driver_request[3] = Error;
- }
-
- CloseHandle(h);
- /* setting status bits
- * 3 == playing && done
- * 1 == done
- */
- driver_request[4] |=
- (data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) ? 3 : 1;
- MSCDEX_Dump("End", driver_request, dorealmode);
+ driver_request[1] = CX_reg(context) - cdrom_heap->hdr.drive;
+ MSCDEX_Request(driver_request, ISV86(context));
}
break;
default:
More information about the wine-patches
mailing list