Esempio n. 1
0
/**
 * We rely on our bootloader setting the A20, but we have code for it just in case.
 */
void SetupA20() {
    uint8_t response_byte;

    /* Do a couple of dummy writes to clear the output buffers. */
    PS2ReadData();
    PS2ReadData();

    /* Disable interrupts. */
    PICDisableInterrupts();

    /* Disable both PS/2 ports. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_DISABLE_PORT1);

    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_DISABLE_PORT2);

    A20_check:

    /* Tell the PS/2 controller to send us the config. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_READ_CONFIG);

    /* Get the status byte. */
    response_byte = PS2ReadData();

    /* Check if the A20 bit is set. */
    if((response_byte & 0x02) != 0x02) {
        /* A20 is NOT set. Set it and write it. */
        PS2WaitOutputBuffer();
        PS2SendCommand(PS2_COMMAND_WRITE_CONFIG);
        PS2WaitOutputBuffer();
        PS2SendData(response_byte | 0x02);
        goto A20_check;
    } else {
        /* A20 was set. */
        printf("PS/2 A20 line set.\n");
    }

    /* Re-enable both ports. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_ENABLE_PORT1);

    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_ENABLE_PORT2);

    /* And finally re-enable interrupts. */
    PICResumeInterrupts();

    return;
}
Esempio n. 2
0
void SetupPS2() {
    char response_byte;

    /* Do a couple of dummy writes to clear the output buffers. */
    PS2ReadData();
    PS2ReadData();

    /* Initialize USB controllers. */
    /* Determine if PS2 exists using ACPI. */

    /* Disable devices so they don't send data. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_DISABLE_PORT1);

    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_DISABLE_PORT2);

    /* Flush output buffer. */
    PS2ReadStatus();

    /* Set the controller configuration byte. */
    response_byte = PS2ReadStatus();

    /* Perform controller self test. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_TEST_CONTROLLER);

    PS2WaitOutputBuffer();
    if(PS2ReadData() == PS2_RESPONSE_TEST_PASS) {
        printf("PS/2 controller passed self test.\n");
    } else {
        printf("PS/2 controller did not pass self test.\n");
    }

    /* Determine if there is 2 channels. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_ENABLE_PORT2);

    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_READ_CONFIG);

    response_byte = PS2ReadData();

    /* Check if bit 5 of the controller config is set. */
    if(BIT_CHECK(response_byte, 5)) {
        printf("PS/2 controller has no second channel.\n");
        ps2_has_second_channel = false;
    } else {
        printf("PS/2 controller has a second channel.\n");
        ps2_has_second_channel = true;
    }

    /* Disable port 2 again to finish startup. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_DISABLE_PORT2);

    /* Test port 1. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_TEST_PORT1);

    PS2WaitOutputBuffer();
    response_byte = PS2ReadData();

    switch(response_byte) {
        case PS2_RESPONSE_PORT_TEST_PASS:
            printf("PS/2 port 1 has passed self-test.\n");
            break;
        case PS2_RESPONSE_CLOCK_STUCK_LOW:
            printf("PS/2 port 1 has stuck low clock.\n");
            break;
        case PS2_RESPONSE_CLOCK_STUCK_HIGH:
            printf("PS/2 port 1 has stuck high clock.\n");
            break;
        case PS2_RESPONSE_DATA_STUCK_LOW:
            printf("PS/2 port 1 has stuck low data line.\n");
            break;
        case PS2_RESPONSE_DATA_STUCK_HIGH:
            printf("PS/2 port 1 has stuck high data line.\n");
            break;
        default:
            printf("PS/2 port 1 has failed self-test.\n");
            break;
    }

    /* Test port 2. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_TEST_PORT2);

    PS2WaitOutputBuffer();
    response_byte = PS2ReadData();

    switch(response_byte) {
        case PS2_RESPONSE_PORT_TEST_PASS:
            printf("PS/2 port 2 has passed self-test.\n");
            break;
        case PS2_RESPONSE_CLOCK_STUCK_LOW:
            printf("PS/2 port 2 has stuck low clock.\n");
            break;
        case PS2_RESPONSE_CLOCK_STUCK_HIGH:
            printf("PS/2 port 2 has stuck high clock.\n");
            break;
        case PS2_RESPONSE_DATA_STUCK_LOW:
            printf("PS/2 port 2 has stuck low data line.\n");
            break;
        case PS2_RESPONSE_DATA_STUCK_HIGH:
            printf("PS/2 port 2 has stuck high data line.\n");
            break;
        default:
            printf("PS/2 port 2 has failed self-test.\n");
            break;
    }

    /* Re-enable device 1. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_ENABLE_PORT1);

    /* Re-enable device 2. */
    PS2WaitInputBuffer();
    PS2SendCommand(PS2_COMMAND_ENABLE_PORT2);

    /* Identify device 1. */

    /* Identify device 2. */

}
Esempio n. 3
0
static VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
{
    if (Port == PS2_CONTROL_PORT)
    {
        switch (Data)
        {
        /* Read configuration byte */
        case 0x20:
        {
            OutputBuffer = ControllerConfig;
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Write configuration byte */
        case 0x60:
        /* Write controller output port */
        case 0xD1:
        /* Write to the first PS/2 port output buffer */
        case 0xD2:
        /* Write to the second PS/2 port output buffer */
        case 0xD3:
        /* Write to the second PS/2 port input buffer */
        case 0xD4:
        {
            /* These commands require a response */
            ControllerCommand = Data;
            StatusRegister |= (1 << 3); // This is a controller command
            break;
        }

        /* Disable second PS/2 port */
        case 0xA7:
        {
            Ports[1].IsEnabled = FALSE;
            break;
        }

        /* Enable second PS/2 port */
        case 0xA8:
        {
            Ports[1].IsEnabled = TRUE;
            break;
        }

        /* Test second PS/2 port */
        case 0xA9:
        {
            OutputBuffer = 0x00; // Success code
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Test PS/2 controller */
        case 0xAA:
        {
            OutputBuffer = 0x55; // Success code
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Test first PS/2 port */
        case 0xAB:
        {
            OutputBuffer = 0x00; // Success code
            StatusRegister |= (1 << 0); // There is something to read
            break;
        }

        /* Disable first PS/2 port */
        case 0xAD:
        {
            Ports[0].IsEnabled = FALSE;
            break;
        }

        /* Enable first PS/2 port */
        case 0xAE:
        {
            Ports[0].IsEnabled = TRUE;
            break;
        }

        /* Read controller output port */
        case 0xD0:
        {
            // TODO: Not implemented
            break;
        }

        /* CPU Reset */
        case 0xF0:
        case 0xF2:
        case 0xF4:
        case 0xF6:
        case 0xF8:
        case 0xFA:
        case 0xFC:
        case 0xFE:
        {
            /* Stop the VDM */
            EmulatorTerminate();
            break;
        }
        }
    }
    else if (Port == PS2_DATA_PORT)
    {
        /* Check if the controller is waiting for a response */
        if (StatusRegister & (1 << 3)) // If we have data for the controller
        {
            StatusRegister &= ~(1 << 3);

            /* Check which command it was */
            switch (ControllerCommand)
            {
            /* Write configuration byte */
            case 0x60:
            {
                ControllerConfig = Data;
                break;
            }

            /* Write controller output */
            case 0xD1:
            {
                /* Check if bit 0 is unset */
                if (!(Data & (1 << 0)))
                {
                    /* CPU disabled - Stop the VDM */
                    EmulatorTerminate();
                }

                /* Update the A20 line setting */
                EmulatorSetA20(Data & (1 << 1));

                break;
            }

            /* Push the data byte into the first PS/2 port queue */
            case 0xD2:
            {
                PS2QueuePush(0, Data);
                break;
            }

            /* Push the data byte into the second PS/2 port queue */
            case 0xD3:
            {
                PS2QueuePush(1, Data);
                break;
            }

            /*
             * Send a command to the second PS/2 port (by default
             * it is a command for the first PS/2 port)
             */
            case 0xD4:
            {
                PS2SendCommand(&Ports[1], Data);
                break;
            }
            }

            return;
        }

        /* By default, send a command to the first PS/2 port */
        PS2SendCommand(&Ports[0], Data);
    }
}