Beispiel #1
0
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
}
Beispiel #2
0
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])();
}
Beispiel #3
0
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;
}
Beispiel #4
0
void MsBopB(){

    switch (getAH()) {

        case 0 :
            setAH(0);
        while (!tkbhit());
        setAL((BYTE)tgetch());
            break;

        case 1 :
        tputch(getAL());
            break;
    }
}
Beispiel #5
0
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);
        }
    }
}
Beispiel #6
0
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());
        }
    }
}
Beispiel #7
0
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;
        }
Beispiel #8
0
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
}
Beispiel #9
0
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;
   }
}
Beispiel #10
0
/*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());
        }
    }
}