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])); }
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_SetupDevice(const WINEDEV * devinfo, WORD seg, WORD off_dev, WORD off_thunk) { DOS_DEVICE_HEADER *dev = PTR_REAL_TO_LIN(seg, off_dev); WINEDEV_THUNK *thunk = PTR_REAL_TO_LIN(seg, off_thunk); DOS_DATASEG *dataseg = (DOS_DATASEG*)DOSMEM_LOL(); dev->attr = devinfo->attr; dev->strategy = off_thunk + FIELD_OFFSET(WINEDEV_THUNK, ljmp1); dev->interrupt = off_thunk + FIELD_OFFSET(WINEDEV_THUNK, ljmp2); memcpy(dev->name, devinfo->name, 8); thunk->ljmp1 = LJMP; thunk->strategy = DPMI_AllocInternalRMCB(devinfo->strategy); thunk->ljmp2 = LJMP; thunk->interrupt = DPMI_AllocInternalRMCB(devinfo->interrupt); dev->next_dev = NONEXT; if (dataseg->last_dev) dataseg->last_dev->next_dev = MAKESEGPTR(seg, off_dev); dataseg->last_dev = dev; }
SEGPTR DOSDEV_GetLOL(BOOL v86) { if (v86) return DOSMEM_LOL()->wine_rm_lol; else return DOSMEM_LOL()->wine_pm_lol; }
void DOSDEV_SetSharingRetry(WORD delay, WORD count) { DOSMEM_LOL()->sharing_retry_delay = delay; if (count) DOSMEM_LOL()->sharing_retry_count = count; }
static void WINAPI con_interrupt(CONTEXT*ctx) { int *scan; REQUEST_HEADER *hdr = get_hdr(SYSTEM_STRATEGY_CON,(void **)&scan); BIOSDATA *bios = DOSVM_BiosData(); WORD CurOfs = bios->NextKbdCharPtr; DOS_LISTOFLISTS *lol = DOSMEM_LOL(); DOS_DATASEG *dataseg = (DOS_DATASEG *)lol; BYTE *linebuffer = dataseg->buffer; BYTE *curbuffer = (lol->offs_unread_CON) ? (((BYTE*)dataseg) + lol->offs_unread_CON) : NULL; DOS_DEVICE_HEADER *con = dataseg->dev; DWORD w; switch (hdr->command) { case CMD_INPUT: { REQ_IO *io = (REQ_IO *)hdr; WORD count = io->count, len = 0; BYTE *buffer = CTX_SEG_OFF_TO_LIN(ctx, SELECTOROF(io->buffer), (DWORD)OFFSETOF(io->buffer)); hdr->status = STAT_BUSY; /* first, check whether we already have data in line buffer */ if (curbuffer) { /* yep, copy as much as we can */ BYTE data = 0; while ((len<count) && (data != '\r')) { data = *curbuffer++; buffer[len++] = data; } if (data == '\r') { /* line buffer emptied */ lol->offs_unread_CON = 0; curbuffer = NULL; /* if we're not in raw mode, call it a day */ if (!(con->attr & ATTR_RAW)) { hdr->status = STAT_DONE; io->count = len; break; } } else { /* still some data left */ lol->offs_unread_CON = curbuffer - (BYTE*)lol; /* but buffer was filled, we're done */ hdr->status = STAT_DONE; io->count = len; break; } } /* if we're in raw mode, we just need to fill the buffer */ if (con->attr & ATTR_RAW) { while (len<count) { WORD data; /* do we have a waiting scancode? */ if (*scan) { /* yes, store scancode in buffer */ buffer[len++] = *scan; *scan = 0; if (len==count) break; } /* check for new keyboard input */ while (CurOfs == bios->FirstKbdCharPtr) { /* no input available yet, so wait... */ DOSVM_Wait( ctx ); } /* read from keyboard queue (call int16?) */ data = ((WORD*)bios)[CurOfs]; CurOfs += 2; if (CurOfs >= bios->KbdBufferEnd) CurOfs = bios->KbdBufferStart; bios->NextKbdCharPtr = CurOfs; /* if it's an extended key, save scancode */ if (LOBYTE(data) == 0) *scan = HIBYTE(data); /* store ASCII char in buffer */ buffer[len++] = LOBYTE(data); } } else { /* we're not in raw mode, so we need to do line input... */ while (TRUE) { WORD data; /* check for new keyboard input */ while (CurOfs == bios->FirstKbdCharPtr) { /* no input available yet, so wait... */ DOSVM_Wait( ctx ); } /* read from keyboard queue (call int16?) */ data = ((WORD*)bios)[CurOfs]; CurOfs += 2; if (CurOfs >= bios->KbdBufferEnd) CurOfs = bios->KbdBufferStart; bios->NextKbdCharPtr = CurOfs; if (LOBYTE(data) == '\r') { /* it's the return key, we're done */ linebuffer[len++] = LOBYTE(data); break; } else if (LOBYTE(data) >= ' ') { /* a character */ if ((len+1)<CON_BUFFER) { linebuffer[len] = LOBYTE(data); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &linebuffer[len++], 1, &w, NULL); } /* else beep, but I don't like noise */ } else switch (LOBYTE(data)) { case '\b': if (len>0) { len--; WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\b \b", 3, &w, NULL); } break; } } if (len > count) { /* save rest of line for later */ lol->offs_unread_CON = linebuffer - (BYTE*)lol + count; len = count; } memcpy(buffer, linebuffer, len); } hdr->status = STAT_DONE; io->count = len; } break; case CMD_SAFEINPUT: if (curbuffer) { /* some line input waiting */ hdr->status = STAT_DONE; ((REQ_SAFEINPUT*)hdr)->data = *curbuffer; } else if (con->attr & ATTR_RAW) { if (CurOfs == bios->FirstKbdCharPtr) { /* no input */ hdr->status = STAT_DONE|STAT_BUSY; } else { /* some keyboard input waiting */ hdr->status = STAT_DONE; ((REQ_SAFEINPUT*)hdr)->data = ((BYTE*)bios)[CurOfs]; } } else { /* no line input */ hdr->status = STAT_DONE|STAT_BUSY; } break; case CMD_INSTATUS: if (curbuffer) { /* we have data */ hdr->status = STAT_DONE; } else if (con->attr & ATTR_RAW) { if (CurOfs == bios->FirstKbdCharPtr) { /* no input */ hdr->status = STAT_DONE|STAT_BUSY; } else { /* some keyboard input waiting */ hdr->status = STAT_DONE; } } else { /* no line input */ hdr->status = STAT_DONE|STAT_BUSY; } break; case CMD_INFLUSH: /* flush line and keyboard queue */ lol->offs_unread_CON = 0; bios->NextKbdCharPtr = bios->FirstKbdCharPtr; break; case CMD_OUTPUT: case CMD_SAFEOUTPUT: { REQ_IO *io = (REQ_IO *)hdr; BYTE *buffer = CTX_SEG_OFF_TO_LIN(ctx, SELECTOROF(io->buffer), (DWORD)OFFSETOF(io->buffer)); DWORD result = 0; WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, io->count, &result, NULL); io->count = result; hdr->status = STAT_DONE; } break; default: hdr->status = STAT_DONE; } do_lret(ctx); }
DWORD DOSDEV_Console(void) { return DOSMEM_LOL()->ptr_CON_dev_hdr; }