LOCAL void ms_not_a_bop() { #ifndef PROD printf ("AH=%x, This is not a valid value for an MS BOP\n", getAH()); illegal_bop(); #ifdef YODA force_yoda (); #endif #endif }
GLOBAL void ms_bop () /* called from MS_bop_5 ie bop 0x55 */ { half_word ah = getAH(); /* get the value in AH */ /*........................................Valid then call the MS function */ if(ah >= MAX_SLOTS || MS_bop_tab[ah] == NULL) ms_not_a_bop(); else (*MS_bop_tab[ah])(); }
VOID cmdExec (VOID) { DWORD i; DWORD dwRet; PCHAR pCommandTail; PCHAR pEnv; CHAR Buffer[MAX_PATH]; pCommandTail = (PCHAR) GetVDMAddr ((USHORT)getDS(),(USHORT)getSI()); pEnv = (PCHAR) GetVDMAddr ((USHORT)getES(),0); for (i=0 ; i<124 ; i++) { if (pCommandTail[i] == 0x0d){ pCommandTail[i] = 0; break; } } if (i == 124){ setCF(0); setAL((UCHAR)ERROR_BAD_FORMAT); return; } chDefaultDrive = (CHAR)(getAL() + 'A'); if (getAH() == 0) { cmdExec32 (pCommandTail,pEnv); } else { dwRet = GetEnvironmentVariable ("COMSPEC",Buffer,MAX_PATH); if (dwRet == 0 || dwRet >= MAX_PATH){ setCF(0); setAL((UCHAR)ERROR_BAD_ENVIRONMENT); return; } if ((dwRet + 4 + strlen(pCommandTail)) > MAX_PATH) { setCF(0); setAL((UCHAR)ERROR_BAD_ENVIRONMENT); return; } strcat (Buffer, " /c "); strcat (Buffer, pCommandTail); cmdExec32 (Buffer,pEnv); } return; }
void MsBopB(){ switch (getAH()) { case 0 : setAH(0); while (!tkbhit()); setAL((BYTE)tgetch()); break; case 1 : tputch(getAL()); break; } }
static VOID WINAPI XmsBopProcedure(LPWORD Stack) { switch (getAH()) { /* Get XMS Version */ case 0x00: { setAX(0x0300); /* XMS version 3.00 */ setBX(0x0301); /* Driver version 3.01 */ setDX(0x0001); /* HMA present */ break; } /* Request HMA */ case 0x01: { /* Check whether HMA is already reserved */ if (IsHmaReserved) { /* It is, bail out */ setAX(0x0000); setBL(XMS_STATUS_HMA_IN_USE); break; } // NOTE: We implicitely suppose that we always have HMA. // If not, we should fail there with the XMS_STATUS_HMA_DOES_NOT_EXIST // error code. /* Check whether the requested size is above the minimal allowed one */ if (getDX() < HmaMinSize) { /* It is not, bail out */ setAX(0x0000); setBL(XMS_STATUS_HMA_MIN_SIZE); break; } /* Reserve it */ IsHmaReserved = TRUE; setAX(0x0001); setBL(XMS_STATUS_SUCCESS); break; } /* Release HMA */ case 0x02: { /* Check whether HMA was reserved */ if (!IsHmaReserved) { /* It was not, bail out */ setAX(0x0000); setBL(XMS_STATUS_HMA_NOT_ALLOCATED); break; } /* Release it */ IsHmaReserved = FALSE; setAX(0x0001); setBL(XMS_STATUS_SUCCESS); break; } /* Global Enable A20 */ case 0x03: { /* Enable A20 if needed */ if (!IsA20Enabled) { XmsLocalEnableA20(); if (getAX() != 0x0001) { /* XmsLocalEnableA20 failed and already set AX and BL to their correct values */ break; } IsA20Enabled = TRUE; } setAX(0x0001); /* Line successfully enabled */ setBL(XMS_STATUS_SUCCESS); break; } /* Global Disable A20 */ case 0x04: { UCHAR Result = XMS_STATUS_SUCCESS; /* Disable A20 if needed */ if (IsA20Enabled) { XmsLocalDisableA20(); if (getAX() != 0x0001) { /* XmsLocalDisableA20 failed and already set AX and BL to their correct values */ break; } IsA20Enabled = FALSE; Result = getBL(); } setAX(0x0001); /* Line successfully disabled */ setBL(Result); break; } /* Local Enable A20 */ case 0x05: { /* This call sets AX and BL to their correct values */ XmsLocalEnableA20(); break; } /* Local Disable A20 */ case 0x06: { /* This call sets AX and BL to their correct values */ XmsLocalDisableA20(); break; } /* Query A20 State */ case 0x07: { setAX(EmulatorGetA20()); setBL(XMS_STATUS_SUCCESS); break; } /* Query Free Extended Memory */ case 0x08: { setAX(XmsGetLargestFreeBlock()); setDX(FreeBlocks); if (FreeBlocks > 0) setBL(XMS_STATUS_SUCCESS); else setBL(XMS_STATUS_OUT_OF_MEMORY); break; } /* Allocate Extended Memory Block */ case 0x09: { WORD Handle; UCHAR Result = XmsAlloc(getDX(), &Handle); if (Result == XMS_STATUS_SUCCESS) { setAX(1); setDX(Handle); } else { setAX(0); setBL(Result); } break; } /* Free Extended Memory Block */ case 0x0A: { UCHAR Result = XmsFree(getDX()); setAX(Result == XMS_STATUS_SUCCESS); setBL(Result); break; } /* Move Extended Memory Block */ case 0x0B: { PVOID SourceAddress, DestAddress; PXMS_COPY_DATA CopyData = (PXMS_COPY_DATA)SEG_OFF_TO_PTR(getDS(), getSI()); PXMS_HANDLE HandleEntry; if (CopyData->SourceHandle) { HandleEntry = GetHandleRecord(CopyData->SourceHandle); if (!ValidateHandle(HandleEntry)) { setAX(0); setBL(XMS_STATUS_BAD_SRC_HANDLE); break; } if (CopyData->SourceOffset >= HandleEntry->Size * XMS_BLOCK_SIZE) { setAX(0); setBL(XMS_STATUS_BAD_SRC_OFFSET); } SourceAddress = (PVOID)REAL_TO_PHYS(HandleEntry->Address + CopyData->SourceOffset); } else { /* The offset is actually a 16-bit segment:offset pointer */ SourceAddress = FAR_POINTER(CopyData->SourceOffset); } if (CopyData->DestHandle) { HandleEntry = GetHandleRecord(CopyData->DestHandle); if (!ValidateHandle(HandleEntry)) { setAX(0); setBL(XMS_STATUS_BAD_DEST_HANDLE); break; } if (CopyData->DestOffset >= HandleEntry->Size * XMS_BLOCK_SIZE) { setAX(0); setBL(XMS_STATUS_BAD_DEST_OFFSET); } DestAddress = (PVOID)REAL_TO_PHYS(HandleEntry->Address + CopyData->DestOffset); } else { /* The offset is actually a 16-bit segment:offset pointer */ DestAddress = FAR_POINTER(CopyData->DestOffset); } /* Perform the move */ RtlMoveMemory(DestAddress, SourceAddress, CopyData->Count); setAX(1); setBL(XMS_STATUS_SUCCESS); break; } /* Lock Extended Memory Block */ case 0x0C: { DWORD Address; UCHAR Result = XmsLock(getDX(), &Address); if (Result == XMS_STATUS_SUCCESS) { setAX(1); /* Store the LINEAR address in DX:BX */ setDX(HIWORD(Address)); setBX(LOWORD(Address)); } else { setAX(0); setBL(Result); } break; } /* Unlock Extended Memory Block */ case 0x0D: { UCHAR Result = XmsUnlock(getDX()); setAX(Result == XMS_STATUS_SUCCESS); setBL(Result); break; } /* Get Handle Information */ case 0x0E: { PXMS_HANDLE HandleEntry = GetHandleRecord(getDX()); UINT i; UCHAR Handles = 0; if (!ValidateHandle(HandleEntry)) { setAX(0); setBL(XMS_STATUS_INVALID_HANDLE); break; } for (i = 0; i < XMS_MAX_HANDLES; i++) { if (HandleTable[i].Handle == 0) Handles++; } setAX(1); setBH(HandleEntry->LockCount); setBL(Handles); setDX(HandleEntry->Size); break; } /* Reallocate Extended Memory Block */ case 0x0F: { UCHAR Result = XmsRealloc(getDX(), getBX()); setAX(Result == XMS_STATUS_SUCCESS); setBL(Result); break; } /* Request UMB */ case 0x10: { BOOLEAN Result; USHORT Segment = 0x0000; /* No preferred segment */ USHORT Size = getDX(); /* Size is in paragraphs */ Result = UmaDescReserve(&Segment, &Size); if (Result) setBX(Segment); else setBL(Size > 0 ? XMS_STATUS_SMALLER_UMB : XMS_STATUS_OUT_OF_UMBS); setDX(Size); setAX(Result); break; } /* Release UMB */ case 0x11: { BOOLEAN Result; USHORT Segment = getDX(); Result = UmaDescRelease(Segment); if (!Result) setBL(XMS_STATUS_INVALID_UMB); setAX(Result); break; } /* Reallocate UMB */ case 0x12: { BOOLEAN Result; USHORT Segment = getDX(); USHORT Size = getBX(); /* Size is in paragraphs */ Result = UmaDescReallocate(Segment, &Size); if (!Result) { if (Size > 0) { setBL(XMS_STATUS_SMALLER_UMB); setDX(Size); } else { setBL(XMS_STATUS_INVALID_UMB); } } setAX(Result); break; } default: { DPRINT1("XMS command AH = 0x%02X NOT IMPLEMENTED\n", getAH()); setBL(XMS_STATUS_NOT_IMPLEMENTED); } } }
static VOID WINAPI BiosKeyboardService(LPWORD Stack) { switch (getAH()) { /* Wait for keystroke and read */ case 0x00: /* Wait for extended keystroke and read */ case 0x10: // FIXME: Temporarily do the same as INT 16h, 00h { /* Read the character (and wait if necessary) */ WORD Character = BiosGetCharacter(); if (Character == 0xFFFF) { /* No key available. Set the handler CF to repeat the BOP */ setCF(1); break; } setAX(Character); break; } /* Get keystroke status */ case 0x01: /* Get extended keystroke status */ case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h { WORD Character = BiosPeekCharacter(); if (Character != 0xFFFF) { /* There is a character, clear ZF and return it */ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF; setAX(Character); } else { /* No character, set ZF */ Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF; } break; } /* Get shift status */ case 0x02: { /* Return the lower byte of the keyboard shift status word */ setAL(LOBYTE(Bda->KeybdShiftFlags)); break; } /* Reserved */ case 0x04: { DPRINT1("BIOS Function INT 16h, AH = 0x04 is RESERVED\n"); break; } /* Push keystroke */ case 0x05: { /* Return 0 if success, 1 if failure */ setAL(BiosKbdBufferPush(getCX()) == FALSE); break; } /* Get extended shift status */ case 0x12: { /* * Be careful! The returned word is similar to Bda->KeybdShiftFlags * but the high byte is organized differently: * the bytes 2 and 3 of the high byte are not the same... */ WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF); /* Return the extended keyboard shift status word */ setAX(KeybdShiftFlags); break; } default: { DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n", getAH()); } } }
static VOID WINAPI EmsIntHandler(LPWORD Stack) { switch (getAH()) { /* Get Manager Status */ case 0x40: { setAH(EMS_STATUS_SUCCESS); break; } /* Get Page Frame Segment */ case 0x41: { setAH(EMS_STATUS_SUCCESS); setBX(EmsSegment); break; } /* Get Number of Unallocated Pages */ case 0x42: { setAH(EMS_STATUS_SUCCESS); setBX(RtlNumberOfClearBits(&AllocBitmap)); setDX(EmsTotalPages); break; } /* Get Handle and Allocate Memory */ case 0x43: { USHORT Handle; UCHAR Status = EmsAlloc(getBX(), &Handle); if (Status == EMS_STATUS_SUCCESS) setDX(Handle); setAH(Status); break; } /* Map Memory */ case 0x44: { setAH(EmsMap(getDX(), getAL(), getBX())); break; } /* Release Handle and Memory */ case 0x45: { setAH(EmsFree(getDX())); break; } /* Get EMM Version */ case 0x46: { setAH(EMS_STATUS_SUCCESS); setAL(EMS_VERSION_NUM); break; } /* Save Page Map */ case 0x47: { // FIXME: This depends on an EMS handle given in DX RtlCopyMemory(MappingBackup, Mapping, sizeof(Mapping)); setAH(EMS_STATUS_SUCCESS); break; } /* Restore Page Map */ case 0x48: { // FIXME: This depends on an EMS handle given in DX RtlCopyMemory(Mapping, MappingBackup, sizeof(Mapping)); setAH(EMS_STATUS_SUCCESS); break; } /* Get Number of Opened Handles */ case 0x4B: { USHORT NumOpenHandles = 0; USHORT i; for (i = 0; i < ARRAYSIZE(HandleTable); i++) { if (HandleTable[i].Allocated) ++NumOpenHandles; } setAH(EMS_STATUS_SUCCESS); setBX(NumOpenHandles); break; } /* Get Handle Number of Pages */ case 0x4C: { PEMS_HANDLE HandleEntry = GetHandleRecord(getDX()); if (!ValidateHandle(HandleEntry)) { setAH(EMS_STATUS_INVALID_HANDLE); break; } setAH(EMS_STATUS_SUCCESS); setBX(HandleEntry->PageCount); break; } /* Get All Handles Number of Pages */ case 0x4D: { PEMS_HANDLE_PAGE_INFO HandlePageInfo = (PEMS_HANDLE_PAGE_INFO)SEG_OFF_TO_PTR(getES(), getDI()); USHORT NumOpenHandles = 0; USHORT i; for (i = 0; i < ARRAYSIZE(HandleTable); i++) { if (HandleTable[i].Allocated) { HandlePageInfo->Handle = i; HandlePageInfo->PageCount = HandleTable[i].PageCount; ++HandlePageInfo; ++NumOpenHandles; } } setAH(EMS_STATUS_SUCCESS); setBX(NumOpenHandles); break; } /* Get or Set Page Map */ case 0x4E: { switch (getAL()) { /* Get Mapping Registers */ // case 0x00: // TODO: NOT IMPLEMENTED /* Set Mapping Registers */ // case 0x01: // TODO: NOT IMPLEMENTED /* Get and Set Mapping Registers At Once */ // case 0x02: // TODO: NOT IMPLEMENTED /* Get Size of Page-Mapping Array */ case 0x03: { setAH(EMS_STATUS_SUCCESS); setAL(sizeof(Mapping)); break; } default: { DPRINT1("EMS function AH = 0x4E, subfunction AL = %02X NOT IMPLEMENTED\n", getAL()); setAH(EMS_STATUS_UNKNOWN_FUNCTION); break; } } break; } /* Get/Set Handle Name */ case 0x53: { PEMS_HANDLE HandleEntry = GetHandleRecord(getDX()); if (!ValidateHandle(HandleEntry)) { setAH(EMS_STATUS_INVALID_HANDLE); break; } if (getAL() == 0x00) { /* Retrieve the name */ RtlCopyMemory(SEG_OFF_TO_PTR(getES(), getDI()), HandleEntry->Name, sizeof(HandleEntry->Name)); setAH(EMS_STATUS_SUCCESS); } else if (getAL() == 0x01) { /* Store the name */ RtlCopyMemory(HandleEntry->Name, SEG_OFF_TO_PTR(getDS(), getSI()), sizeof(HandleEntry->Name)); setAH(EMS_STATUS_SUCCESS); } else { DPRINT1("Invalid subfunction %02X for EMS function AH = 53h\n", getAL()); setAH(EMS_STATUS_INVALID_SUBFUNCTION); } break; } /* Handle Directory functions */ case 0x54: { if (getAL() == 0x00) { /* Get Handle Directory */ PEMS_HANDLE_DIR_ENTRY HandleDir = (PEMS_HANDLE_DIR_ENTRY)SEG_OFF_TO_PTR(getES(), getDI()); USHORT NumOpenHandles = 0; USHORT i; for (i = 0; i < ARRAYSIZE(HandleTable); i++) { if (HandleTable[i].Allocated) { HandleDir->Handle = i; RtlCopyMemory(HandleDir->Name, HandleTable[i].Name, sizeof(HandleDir->Name)); ++HandleDir; ++NumOpenHandles; } } setAH(EMS_STATUS_SUCCESS); setAL((UCHAR)NumOpenHandles); } else if (getAL() == 0x01) { /* Search for Named Handle */ PUCHAR HandleName = (PUCHAR)SEG_OFF_TO_PTR(getDS(), getSI()); PEMS_HANDLE HandleFound = NULL; USHORT i; for (i = 0; i < ARRAYSIZE(HandleTable); i++) { if (HandleTable[i].Allocated && RtlCompareMemory(HandleName, HandleTable[i].Name, sizeof(HandleTable[i].Name)) == sizeof(HandleTable[i].Name)) { HandleFound = &HandleTable[i]; break; } } /* Bail out if no handle was found */ if (i >= ARRAYSIZE(HandleTable)) // HandleFound == NULL { setAH(EMS_STATUS_HANDLE_NOT_FOUND); break; } /* Return the handle number */ setDX(i); /* Sanity check: Check whether the handle was unnamed */ i = 0; while ((i < sizeof(HandleFound->Name)) && (HandleFound->Name[i] == '\0')) ++i; if (i >= sizeof(HandleFound->Name)) { setAH(EMS_STATUS_UNNAMED_HANDLE); } else { setAH(EMS_STATUS_SUCCESS); } } else if (getAL() == 0x02) { /* * Get Total Number of Handles * * This function retrieves the maximum number of handles * (allocated or not) the memory manager supports, which * a program may request. */ setAH(EMS_STATUS_SUCCESS); setBX(ARRAYSIZE(HandleTable)); } else { DPRINT1("Invalid subfunction %02X for EMS function AH = 54h\n", getAL()); setAH(EMS_STATUS_INVALID_SUBFUNCTION); } break; } /* Move/Exchange Memory */ case 0x57: { PUCHAR SourcePtr, DestPtr; PEMS_HANDLE HandleEntry; PEMS_PAGE PageEntry; BOOLEAN Exchange = getAL(); PEMS_COPY_DATA Data = (PEMS_COPY_DATA)SEG_OFF_TO_PTR(getDS(), getSI()); if (Data->SourceType) { /* Expanded memory */ HandleEntry = GetHandleRecord(Data->SourceHandle); if (!ValidateHandle(HandleEntry)) { setAH(EMS_STATUS_INVALID_HANDLE); break; } PageEntry = GetLogicalPage(HandleEntry, Data->SourceSegment); if (!PageEntry) { setAH(EMS_STATUS_INV_LOGICAL_PAGE); break; } SourcePtr = (PUCHAR)((ULONG_PTR)EmsMemory + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE + Data->SourceOffset); } else { /* Conventional memory */ SourcePtr = (PUCHAR)SEG_OFF_TO_PTR(Data->SourceSegment, Data->SourceOffset); } if (Data->DestType) { /* Expanded memory */ HandleEntry = GetHandleRecord(Data->DestHandle); if (!ValidateHandle(HandleEntry)) { setAH(EMS_STATUS_INVALID_HANDLE); break; } PageEntry = GetLogicalPage(HandleEntry, Data->DestSegment); if (!PageEntry) { setAH(EMS_STATUS_INV_LOGICAL_PAGE); break; } DestPtr = (PUCHAR)((ULONG_PTR)EmsMemory + ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE + Data->DestOffset); } else { /* Conventional memory */ DestPtr = (PUCHAR)SEG_OFF_TO_PTR(Data->DestSegment, Data->DestOffset); } if (Exchange) { ULONG i; /* Exchange */ for (i = 0; i < Data->RegionLength; i++) { UCHAR Temp = DestPtr[i]; DestPtr[i] = SourcePtr[i]; SourcePtr[i] = Temp; } } else { /* Move */ RtlMoveMemory(DestPtr, SourcePtr, Data->RegionLength); } setAH(EMS_STATUS_SUCCESS); break; } /* Get Mappable Physical Address Array */ case 0x58: { if (getAL() == 0x00) { PEMS_MAPPABLE_PHYS_PAGE PageArray = (PEMS_MAPPABLE_PHYS_PAGE)SEG_OFF_TO_PTR(getES(), getDI()); ULONG i; for (i = 0; i < EMS_PHYSICAL_PAGES; i++) { PageArray->PageSegment = EMS_SEGMENT + i * (EMS_PAGE_SIZE >> 4); PageArray->PageNumber = i; ++PageArray; } setAH(EMS_STATUS_SUCCESS); setCX(EMS_PHYSICAL_PAGES); } else if (getAL() == 0x01) { setAH(EMS_STATUS_SUCCESS); setCX(EMS_PHYSICAL_PAGES); } else { DPRINT1("Invalid subfunction %02X for EMS function AH = 58h\n", getAL()); setAH(EMS_STATUS_INVALID_SUBFUNCTION); } break; }
void printer_io() { #ifdef PRINTER half_word time_out, status; word printer_io_address, printer_io_reg, printer_status_reg, printer_control_reg; boolean printer_busy = TRUE; unsigned long time_count; int adapter; #ifdef NTVDM int bopsubfunction = getSI(); switch (bopsubfunction) { #ifdef MONITOR case 0: /* this is the bop to flush 16bit printer buffer */ printer_bop_flush (); return; #endif case 1: case 2: /* this is the bop to track a DOS open/close on LPTn */ printer_bop_openclose (bopsubfunction); return; } #endif setIF(1); adapter = getDX() % NUM_PARALLEL_PORTS; sas_loadw(port_address[adapter], &printer_io_address); printer_io_reg = printer_io_address; printer_status_reg = printer_io_address + 1; printer_control_reg = printer_io_address + 2; sas_load(timeout_address[adapter], &time_out); time_count = time_out * 0xFFFF; if (printer_io_address != 0) { IDLE_comlpt (); switch(getAH()) { case 0: /* Check the port status for busy before sending the character*/ while(printer_busy && time_count > 0) { /* The host_lpt_status() should check for status changes */ /* possibly by calling AsyncEventManager() if it's using */ /* XON /XOFF flow control. */ inb(printer_status_reg, &status); if (status & 0x80) printer_busy = FALSE; else time_count--; } if (printer_busy) { status &= 0xF8; /* clear bottom unused bits */ status |= 1; /* set error flag */ } else { /* Only send the character if the port isn't still busy */ outb(printer_io_reg, getAL()); outb(printer_control_reg, 0x0D); /* strobe low-high */ outb(printer_control_reg, 0x0C); /* strobe high-low */ inb(printer_status_reg, &status); status &= 0xF8; /* clear unused bits */ } status ^= 0x48; /* flip the odd bit */ setAH(status); break; case 1: outb(printer_control_reg, 0x08); /* set init line low */ outb(printer_control_reg, 0x0C); /* set init line high */ inb(printer_status_reg, &status); status &= 0xF8; /* clear unused bits */ status ^= 0x48; /* flip the odd bit */ setAH(status); break; case 2: inb(printer_status_reg, &status); status &= 0xF8; /* clear unused bits */ status ^= 0x48; /* flip the odd bit */ setAH(status); break; default: break; } } #endif }
void rs232_io() { #ifdef BIT_ORDER2 union { half_word all; struct { HALF_WORD_BIT_FIELD word_length:2; HALF_WORD_BIT_FIELD stop_bit:1; HALF_WORD_BIT_FIELD parity:2; HALF_WORD_BIT_FIELD baud_rate:3; } bit; } parameters; #endif #ifdef BIT_ORDER1 union { half_word all; struct { HALF_WORD_BIT_FIELD baud_rate:3; HALF_WORD_BIT_FIELD parity:2; HALF_WORD_BIT_FIELD stop_bit:1; HALF_WORD_BIT_FIELD word_length:2; } bit; } parameters; #endif DIVISOR_LATCH divisor_latch; int j; half_word timeout; sys_addr timeout_location; /* clear com/lpt idle flag */ IDLE_comlpt (); setIF(1); /* * Which adapter? */ switch (getDX ()) { case 0: port = RS232_COM1_PORT_START; timeout_location = RS232_COM1_TIMEOUT; break; case 1: port = RS232_COM2_PORT_START; timeout_location = RS232_COM2_TIMEOUT; break; case 2: port = RS232_COM3_PORT_START; timeout_location = RS232_COM3_TIMEOUT; break; case 3: port = RS232_COM4_PORT_START; timeout_location = RS232_COM4_TIMEOUT; break; default: break; } /* * Determine function */ switch (getAH ()) { case 0: /* * Initialise the communication port */ value = 0x80; /* set DLAB */ outb(port + (io_addr) RS232_LCR, value); /* * Set baud rate */ parameters.all = getAL(); divisor_latch.all = divisors[parameters.bit.baud_rate]; outb(port + (io_addr) RS232_IER, divisor_latch.byte.MSByte); outb(port + (io_addr) RS232_TX_RX, divisor_latch.byte.LSByte); /* * Set word length, stop bits and parity */ parameters.bit.baud_rate = 0; outb(port + (io_addr) RS232_LCR, parameters.all); /* * Disable interrupts */ value = 0; outb(port + (io_addr) RS232_IER, value); return_status(); break; case 1: /* * Send char over the comms line */ /* * Set DTR and RTS */ outb(port + (io_addr) RS232_MCR, 3); /* * Real BIOS checks CTS and DSR - we know DSR ok. * Real BIOS check THRE - we know it's ok. * We only check CTS - this is supported on a few ports, eg. Macintosh. */ /* * Wait for CTS to go high, or timeout */ sas_load(timeout_location, &timeout); for ( j = 0; j < timeout; j++) { inb(port + (io_addr) RS232_MSR, &value); if(value & 0x10)break; /* CTS High, all is well */ } if(j < timeout) { outb(port + (io_addr) RS232_TX_RX, getAL()); /* Send byte */ inb(port + (io_addr) RS232_LSR, &value); setAH(value); /* Return Line Status Reg in AH */ } else { setAH(value | 0x80); /* Indicate time out */ } break; case 2: /* * Receive char over the comms line */ /* * Set DTR */ value = 1; outb(port + (io_addr) RS232_MCR, value); /* * Real BIOS checks DSR - we know it's ok. */ /* * Wait for data to appear, or timeout(just an empirical guess) */ sas_load(timeout_location, &timeout); for ( j = 0; j < timeout; j++) { inb(port + (io_addr) RS232_LSR, &value); if ( (value & 1) == 1 ) { /* * Data ready go read it */ value &= 0x1e; /* keep error bits only */ setAH(value); inb(port + (io_addr) RS232_TX_RX, &value); setAL(value); return; } } /* * Set timeout */ value |= 0x80; setAH(value); break; case 3: /* * Return the communication port status */ return_status(); break; case 4: /* * EXTENDED (PS/2) Initialise the communication port */ value = 0x80; /* set DLAB */ outb(port + (io_addr) RS232_LCR, value); parameters.bit.word_length = getCH(); parameters.bit.stop_bit = getBL(); parameters.bit.parity = getBH(); parameters.bit.baud_rate = getCL(); /* Set baud rate */ divisor_latch.all = divisors[parameters.bit.baud_rate]; outb(port + (io_addr) RS232_IER, divisor_latch.byte.MSByte); outb(port + (io_addr) RS232_TX_RX, divisor_latch.byte.LSByte); /* * Set word length, stop bits and parity */ parameters.bit.baud_rate = 0; outb(port + (io_addr) RS232_LCR, parameters.all); /* * Disable interrupts */ value = 0; outb(port + (io_addr) RS232_IER, value); return_status(); break; case 5: /* EXTENDED Comms Port Control */ switch( getAL() ) { case 0: /* Read modem control register */ inb( port + (io_addr) RS232_MCR, &value); setBL(value); break; case 1: /* Write modem control register */ outb( port + (io_addr) RS232_MCR, getBL()); break; } /* Return the communication port status */ return_status(); break; default: /* ** Yes both XT and AT BIOS's really do this. */ setAH( getAH()-3 ); break; } }
/*static*/ VOID WINAPI BiosDiskService(LPWORD Stack) { BYTE Drive; PDISK_IMAGE DiskImage; switch (getAH()) { /* Disk -- Reset Disk System */ case 0x00: { Drive = getDL(); if (Drive & 0x80) { AllDisksReset(); /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; break; } Drive &= ~0x80; if (Drive >= ARRAYSIZE(FloppyDrive)) { DPRINT1("BiosDiskService(0x00): Drive number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } // TODO: Reset drive /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; break; } /* Disk -- Get Status of Last Operation */ case 0x01: { BYTE LastOperationStatus = 0x00; Drive = getDL(); DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x01): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } LastOperationStatus = DiskImage->LastOperationStatus; if (Drive & 0x80) Bda->LastDiskOperation = LastOperationStatus; else Bda->LastDisketteOperation = LastOperationStatus; /* Return last error */ setAH(LastOperationStatus); if (LastOperationStatus == 0x00) Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; else Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } /* Disk -- Read Sectors into Memory */ case 0x02: { BYTE Status; BYTE Head = getDH(); BYTE NumSectors = getAL(); // CH: Low eight bits of cylinder number // CL: High two bits of cylinder (bits 6-7, hard disk only) WORD Cylinder = MAKEWORD(getCH(), (getCL() >> 6) & 0x02); // CL: Sector number 1-63 (bits 0-5) BYTE Sector = (getCL() & 0x3F); // 1-based Drive = getDL(); DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x02): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } /* Read the sectors */ Status = ReadDisk(DiskImage, Cylinder, Head, Sector, NumSectors); if (Status == 0x00) { /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; } else { DPRINT1("BiosDiskService(0x02): Error when reading from disk number 0x%02X (0x%02X)\n", Drive, Status); /* Return error */ setAH(Status); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; } break; } /* Disk -- Write Disk Sectors */ case 0x03: { BYTE Status; BYTE Head = getDH(); BYTE NumSectors = getAL(); // CH: Low eight bits of cylinder number // CL: High two bits of cylinder (bits 6-7, hard disk only) WORD Cylinder = MAKEWORD(getCH(), (getCL() >> 6) & 0x02); // CL: Sector number 1-63 (bits 0-5) BYTE Sector = (getCL() & 0x3F); // 1-based Drive = getDL(); DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x03): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } /* Write the sectors */ Status = WriteDisk(DiskImage, Cylinder, Head, Sector, NumSectors); if (Status == 0x00) { /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; } else { DPRINT1("BiosDiskService(0x03): Error when writing to disk number 0x%02X (0x%02X)\n", Drive, Status); /* Return error */ setAH(Status); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; } break; } /* Disk -- Verify Disk Sectors */ case 0x04: /* Floppy/Fixed Disk -- Format Track */ case 0x05: /* Fixed Disk -- Format Track and Set Bad Sector Flags */ case 0x06: /* Fixed Disk -- Format Drive starting at Given Track */ case 0x07: goto Default; /* Disk -- Get Drive Parameters */ case 0x08: { WORD MaxCylinders; BYTE MaxHeads; BYTE PresentDrives = 0; BYTE i; Drive = getDL(); DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x08): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } // Minus 2 because it's the maximum cylinder number (not count), // and the last cylinder is reserved (for compatibility with BIOSes // which reserve it for testing purposes). MaxCylinders = DiskImage->DiskInfo.Cylinders - 2; // Minus 1 because it's the maximum head number (not count). MaxHeads = DiskImage->DiskInfo.Heads - 1; // CL: Sector number 1-63 (bits 0-5) // High two bits of cylinder (bits 6-7, hard disk only) setCL((DiskImage->DiskInfo.Sectors & 0x3F) | ((HIBYTE(MaxCylinders) & 0x02) << 6)); // CH: Low eight bits of cylinder number setCH(LOBYTE(MaxCylinders)); setDH(MaxHeads); if (Drive & 0x80) { /* Count the number of active HDDs */ for (i = 0; i < ARRAYSIZE(HardDrive); ++i) { if (IsDiskPresent(HardDrive[i])) ++PresentDrives; } /* Reset ES:DI to NULL */ // FIXME: NONONO!! Apps expect (for example, MS-DOS kernel) // that this function does not modify ES:DI if it was called // for a HDD. // setES(0x0000); // setDI(0x0000); } else { /* Count the number of active floppies */ for (i = 0; i < ARRAYSIZE(FloppyDrive); ++i) { if (IsDiskPresent(FloppyDrive[i])) ++PresentDrives; } /* ES:DI points to the floppy parameter table */ setES(HIWORD(((PULONG)BaseAddress)[0x1E])); setDI(LOWORD(((PULONG)BaseAddress)[0x1E])); } setDL(PresentDrives); setBL(DiskImage->DiskType); // DiskGeometryList[DiskImage->DiskType].biosval setAL(0x00); /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; break; } /* Hard Disk -- Initialize Controller with Drive Parameters */ case 0x09: /* Hard Disk -- Read Long Sectors */ case 0x0A: /* Hard Disk -- Write Long Sectors */ case 0x0B: goto Default; /* Hard Disk -- Seek to Cylinder */ case 0x0C: { BYTE Status; BYTE Head = getDH(); // CH: Low eight bits of cylinder number // CL: High two bits of cylinder (bits 6-7, hard disk only) WORD Cylinder = MAKEWORD(getCH(), (getCL() >> 6) & 0x02); // CL: Sector number 1-63 (bits 0-5) BYTE Sector = (getCL() & 0x3F); // 1-based Drive = getDL(); if (!(Drive & 0x80)) { DPRINT1("BiosDiskService(0x0C): Disk number 0x%02X is not a HDD\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x0C): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } /* Set position */ Status = SeekDisk(DiskImage, Cylinder, Head, Sector); if (Status == 0x00) { /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; } else { DPRINT1("BiosDiskService(0x0C): Error when seeking in disk number 0x%02X (0x%02X)\n", Drive, Status); /* Return error */ setAH(Status); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; } break; } /* Hard Disk -- Reset Hard Disks */ case 0x0D: { // FIXME: Should do what 0x11 does. UNIMPLEMENTED; } /* Hard Disk -- Read Sector Buffer (XT only) */ case 0x0E: /* Hard Disk -- Write Sector Buffer (XT only) */ case 0x0F: goto Default; /* Hard Disk -- Check if Drive is ready */ case 0x10: { Drive = getDL(); if (!(Drive & 0x80)) { DPRINT1("BiosDiskService(0x10): Disk number 0x%02X is not a HDD\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x10): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; break; } /* Hard Disk -- Recalibrate Drive */ case 0x11: { BYTE Status; Drive = getDL(); if (!(Drive & 0x80)) { DPRINT1("BiosDiskService(0x11): Disk number 0x%02X is not a HDD\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x11): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } /* Set position to zero */ Status = SeekDisk(DiskImage, /*Cylinder*/ 0, /*Head*/ 0, /*Sector*/ 1); if (Status == 0x00) { /* Return success */ setAH(0x00); Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; } else { DPRINT1("BiosDiskService(0x11): Error when recalibrating disk number 0x%02X (0x%02X)\n", Drive, Status); /* Return error */ setAH(Status); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; } break; } /* Hard Disk -- Controller RAM Diagnostic */ case 0x12: /* Hard Disk -- Drive Diagnostic */ case 0x13: /* Hard Disk -- Controller Internal Diagnostic */ case 0x14: goto Default; /* Disk -- Get Disk Type */ case 0x15: { Drive = getDL(); DiskImage = GetDisk(Drive); if (!DiskImage || !IsDiskPresent(DiskImage)) { DPRINT1("BiosDiskService(0x15): Disk number 0x%02X invalid\n", Drive); /* Return error */ setAH(0x01); Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; break; } if (Drive & 0x80) { ULONG NumSectors; /* Hard disk */ setAH(0x03); /* Number of 512-byte sectors in CX:DX */ NumSectors = (ULONG)((ULONG)DiskImage->DiskInfo.Cylinders * DiskImage->DiskInfo.Heads) * DiskImage->DiskInfo.Sectors; setCX(HIWORD(NumSectors)); setDX(LOWORD(NumSectors)); } else { /* Floppy */ setAH(0x01); } /* Return success */ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; break; } /* Floppy Disk -- Detect Disk Change */ case 0x16: /* Floppy Disk -- Set Disk Type for Format */ case 0x17: /* Disk -- Set Media Type for Format */ case 0x18: goto Default; default: Default: { DPRINT1("BIOS Function INT 13h, AH = 0x%02X, AL = 0x%02X, BH = 0x%02X NOT IMPLEMENTED\n", getAH(), getAL(), getBH()); } } }