static void DOSDEV_DoReq(void*req, DWORD dev) { REQUEST_HEADER *hdr = (REQUEST_HEADER *)req; DOS_DEVICE_HEADER *dhdr; CONTEXT86 ctx; char *phdr; dhdr = PTR_REAL_TO_LIN(SELECTOROF(dev),OFFSETOF(dev)); phdr = ((char*)DOSMEM_LOL()) + DOS_DATASEG_OFF(req); /* copy request to request scratch area */ memcpy(phdr, req, hdr->size); /* prepare to call device driver */ memset(&ctx, 0, sizeof(ctx)); ctx.EFlags |= V86_FLAG; /* ES:BX points to request for strategy routine */ ctx.SegEs = HIWORD(DOS_LOLSeg); ctx.Ebx = DOS_DATASEG_OFF(req); /* call strategy routine */ ctx.SegCs = SELECTOROF(dev); ctx.Eip = dhdr->strategy; DPMI_CallRMProc(&ctx, 0, 0, 0); /* call interrupt routine */ ctx.SegCs = SELECTOROF(dev); ctx.Eip = dhdr->interrupt; DPMI_CallRMProc(&ctx, 0, 0, 0); /* completed, copy request back */ memcpy(req, phdr, hdr->size); if (hdr->status & STAT_ERROR) { switch (hdr->status & STAT_MASK) { case 0x0F: /* invalid disk change */ /* this error seems to fit the bill */ SetLastError(ERROR_NOT_SAME_DEVICE); break; default: SetLastError((hdr->status & STAT_MASK) + 0x13); break; } } }
void DOSDEV_InstallDOSDevices(void) { DOS_DATASEG *dataseg; WORD seg; WORD selector; unsigned int n; /* allocate DOS data segment or something */ dataseg = DOSVM_AllocDataUMB( sizeof(DOS_DATASEG), &seg, &selector ); DOS_LOLSeg = MAKESEGPTR( seg, 0 ); DOSMEM_LOL()->wine_rm_lol = MAKESEGPTR( seg, FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB) ); DOSMEM_LOL()->wine_pm_lol = MAKESEGPTR( selector, FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB) ); /* initialize the magnificent List Of Lists */ InitListOfLists(&dataseg->lol); /* Set up first device (NUL) */ dataseg->last_dev = NULL; DOSDEV_SetupDevice( &devs[0], seg, DOS_DATASEG_OFF(lol.NUL_dev), DOS_DATASEG_OFF(thunk[0]) ); /* Set up the remaining devices */ for (n = 1; n < NR_DEVS; n++) DOSDEV_SetupDevice( &devs[n], seg, DOS_DATASEG_OFF(dev[n-1]), DOS_DATASEG_OFF(thunk[n]) ); /* CON is device 1 */ dataseg->lol.ptr_CON_dev_hdr = MAKESEGPTR(seg, DOS_DATASEG_OFF(dev[0])); }