From 8aea756f5094de4b357c125b75973d82328e0c31 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 15 Apr 2022 21:44:44 +0200 Subject: rename some headers for consistency --- dlog.h | 2 +- int15ps2.h | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int1Apci.h | 122 ++++++++++++++++++++++++++++++++ int4Bvds.h | 162 ++++++++++++++++++++++++++++++++++++++++++ mousetsr.c | 2 +- mousmain.c | 2 +- pci.h | 122 -------------------------------- ps2.h | 235 ------------------------------------------------------------- vbox.c | 4 +- vbox.h | 2 +- vds.h | 162 ------------------------------------------ 11 files changed, 525 insertions(+), 525 deletions(-) create mode 100644 int15ps2.h create mode 100644 int1Apci.h create mode 100644 int4Bvds.h delete mode 100644 pci.h delete mode 100644 ps2.h delete mode 100644 vds.h diff --git a/dlog.h b/dlog.h index 944edfb..7b39a5a 100644 --- a/dlog.h +++ b/dlog.h @@ -24,7 +24,7 @@ // Customizable defines /** If 0, these routines become nops */ -#define ENABLE_DLOG 1 +#define ENABLE_DLOG 0 /** 1 means target serial port, 0 means target IO port. */ #define DLOG_TARGET_SERIAL 0 /** IO port to target. diff --git a/int15ps2.h b/int15ps2.h new file mode 100644 index 0000000..6b6c415 --- /dev/null +++ b/int15ps2.h @@ -0,0 +1,235 @@ +/* + * VBMouse - Routines to access the PS2 BIOS services + * Copyright (C) 2022 Javier S. Pedro + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef INT15PS2_H +#define INT15PS2_H + +#include +#include + +/** Standard PS/2 mouse IRQ. At least on VirtualBox. */ +#define PS2_MOUSE_IRQ 12 +/** The corresponding interrupt vector for IRQ 12. */ +#define PS2_MOUSE_INT_VECTOR 0x74 + +typedef uint8_t ps2m_err; +enum ps2m_errors { + PS2M_ERR_INVALID_FUNCTION = 1, + PSM2_ERR_INVALID_INPUT = 2, + PSM2_ERR_INTERFACE_ERROR = 3, + PSM2_ERR_RESEND = 4, + PSM2_ERR_NO_CALLBACK = 5, +}; + +enum ps2m_status { + PS2M_STATUS_BUTTON_1 = 1 << 0, + PS2M_STATUS_BUTTON_2 = 1 << 1, + PS2M_STATUS_BUTTON_3 = 1 << 2, + PS2M_STATUS_X_NEG = 1 << 4, + PS2M_STATUS_Y_NEG = 1 << 5, + PS2M_STATUS_X_OVF = 1 << 6, + PS2M_STATUS_Y_OVF = 1 << 7, +}; + +enum ps2m_packet_size { + PS2M_PACKET_SIZE_PLAIN = 3, + PS2M_PACKET_SIZE_EXT = 4, +}; + +enum ps2m_device_ids { + /** Standard PS/2 mouse, 2 buttons. */ + PS2M_DEVICE_ID_PLAIN = 0, + /** IntelliMouse PS/2, with wheel. */ + PS2M_DEVICE_ID_IMPS2 = 3, + /** IntelliMouse Explorer, wheel and 5 buttons. */ + PS2M_DEVICE_ID_IMEX = 4, + /** IntelliMouse Explorer, wheel, 5 buttons, and horizontal scrolling. */ + PS2M_DEVICE_ID_IMEX_HORZ = 5 +}; + +enum ps2m_resolution { + PS2M_RESOLUTION_25 = 0, + PS2M_RESOLUTION_50 = 1, + PS2M_RESOLUTION_100 = 2, + PS2M_RESOLUTION_200 = 3 +}; + +enum ps2m_sample_rate { + PS2M_SAMPLE_RATE_10 = 0, + PS2M_SAMPLE_RATE_20 = 1, + PS2M_SAMPLE_RATE_40 = 2, + PS2M_SAMPLE_RATE_60 = 3, + PS2M_SAMPLE_RATE_80 = 4, + PS2M_SAMPLE_RATE_100 = 5, + PS2M_SAMPLE_RATE_200 = 6 +}; + +/** Invoked by the BIOS when there is a mouse event. */ +typedef void (__far * LPFN_PS2CALLBACK)(); + +static ps2m_err ps2m_init(uint8_t packet_size); +#pragma aux ps2m_init = \ + "stc" /* If nothing happens, assume failure */ \ + "mov ax, 0xC205" /* Pointing device: initialization (packet size in bh) */ \ + "int 0x15" \ + "jnc end" /* Success */ \ + "fail: test ah, ah" /* Ensure we have some error code back, set ah to -1 if we don't */ \ + "jnz end" \ + "dec ah" \ + "end:" \ + __parm [bh] \ + __value [ah] \ + __modify [ax] + +static ps2m_err ps2m_reset(void); +#pragma aux ps2m_reset = \ + "stc" \ + "mov ax, 0xC201" /* Pointing device: reset */ \ + "int 0x15" \ + "jnc end" \ + "fail: test ah, ah" \ + "jnz end" \ + "dec ah" \ + "end:" \ + __value [ah] \ + __modify [ax] + +static ps2m_err ps2m_get_device_id(uint8_t __far *device_id); +#pragma aux ps2m_get_device_id = \ + "stc" \ + "mov ax, 0xC204" /* Pointing device: get device ID */ \ + "int 0x15" \ + "mov es:[di], bh" /* Save returned value */ \ + "jnc end" \ + "fail: test ah, ah" \ + "jnz end" \ + "dec ah" \ + "end:" \ + __parm [es di] \ + __value [ah] \ + __modify [ax] + +static ps2m_err ps2m_set_resolution(uint8_t resolution); +#pragma aux ps2m_set_resolution = \ + "stc" \ + "mov ax, 0xC203" /* Pointing device: set resolution (in bh) */ \ + "int 0x15" \ + "jnc end" \ + "fail: test ah, ah" \ + "jnz end" \ + "dec ah" \ + "end:" \ + __parm [bh] \ + __value [ah] \ + __modify [ax] + +static ps2m_err ps2m_set_sample_rate(uint8_t sample_rate); +#pragma aux ps2m_set_sample_rate = \ + "stc" \ + "mov ax, 0xC202" /* Pointing device: set sample rate (in bh) */ \ + "int 0x15" \ + "jnc end" \ + "fail: test ah, ah" \ + "jnz end" \ + "dec ah" \ + "end:" \ + __parm [bh] \ + __value [ah] \ + __modify [ax] + +static ps2m_err ps2m_set_scaling_factor(uint8_t scaling_factor); +#pragma aux ps2m_set_scaling_factor = \ + "stc" \ + "mov ax, 0xC206" /* Pointing device: extended commands (with bh > 0, set scaling factor) */ \ + "int 0x15" \ + "jnc end" \ + "fail: test ah, ah" \ + "jnz end" \ + "dec ah" \ + "end:" \ + __parm [bh] \ + __value [ah] \ + __modify [ax] + +static ps2m_err ps2m_set_callback(LPFN_PS2CALLBACK callback); +#pragma aux ps2m_set_callback = \ + "stc" \ + "mov ax, 0xC207" /* Pointing device: set interrupt callback (in es:bx) */ \ + "int 0x15" \ + "jnc end" \ + "fail: test ah, ah" \ + "jnz end" \ + "dec ah" \ + "end:" \ + __parm [es bx] \ + __value [ah] \ + __modify [ax] + +static ps2m_err ps2m_enable(bool enable); +#pragma aux ps2m_enable = \ + "test bh, bh" /* Ensure enable is either 1 or 0 */ \ + "setnz bh" \ + "stc" \ + "mov ax, 0xC200" /* Pointing device enable/disable (in bh) */ \ + "int 0x15" \ + "jnc end" \ + "fail: test ah, ah" \ + "jnz end" \ + "dec ah" \ + "end:" \ + __parm [bh] \ + __value [ah] \ + __modify [ax] + +static void ps2m_send_imps2_sequence(void) +{ + ps2m_set_sample_rate(PS2M_SAMPLE_RATE_200); + ps2m_set_sample_rate(PS2M_SAMPLE_RATE_100); + ps2m_set_sample_rate(PS2M_SAMPLE_RATE_80); +} + +static bool ps2m_detect_wheel(void) +{ + int err; + uint8_t device_id; + + // Switch to the 4-byte packet and reset the mouse. + // We are not supposed to receive messages at this time anyway. + err = ps2m_init(PS2M_PACKET_SIZE_EXT); + if (err) { + return false; + } + + // Get the initial mouse device id + err = ps2m_get_device_id(&device_id); + if (err || device_id != 0) { + // TODO : Likely have to accept more device_ids here. + return false; + } + + // Send the knock sequence to activate the extended packet + ps2m_send_imps2_sequence(); + + // Now check if the device id has changed + err = ps2m_get_device_id(&device_id); + + return err == 0 && device_id == PS2M_DEVICE_ID_IMPS2; +} + +#endif /* INT15PS2_H */ diff --git a/int1Apci.h b/int1Apci.h new file mode 100644 index 0000000..92f347e --- /dev/null +++ b/int1Apci.h @@ -0,0 +1,122 @@ +/* + * VBMouse - PCI BIOS communication routines + * Copyright (C) 2022 Javier S. Pedro + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef INT1APCI_H +#define INT1APCI_H + +typedef unsigned char pcierr; +enum { + PCI_SUCCESSFUL = 0, + PCI_GENERIC_ERROR = 1, + PCI_FUNC_NOT_SUPPORTED = 0x81, + PCI_BAD_VENDOR_ID = 0x83, + PCI_DEVICE_NOT_FOUND = 0x86, + PCI_BAD_REGISTER_NUMBER = 0x87, + PCI_SET_FAILED = 0x88, + PCI_BUFFER_TOO_SMALL = 0x89 +}; + +typedef unsigned short pcisel; + +static pcierr pci_init_bios(void); +#pragma aux pci_init_bios = \ + "mov ax, 0xB101" \ + "int 0x1A" \ + "jc not_found" \ + "cmp ah, 0" \ + "jne not_found" \ + "cmp edx, ' ICP'" \ + "jne not_found" \ + "mov ah, 0" \ + "jmp end" \ + "not_found: mov ah, 1" \ + "end:" \ + __value [ah] \ + __modify [ax bx cx dx] + +static pcierr pci_find_device(pcisel __far *sel, unsigned short vendor_id, unsigned short dev_id, unsigned short index); +#pragma aux pci_find_device = \ + "mov ax, 0xB102" \ + "int 0x1A" \ + "jnc success" \ + "mov ah, 1" \ + "success: mov [es:di], bx" \ + __parm [es di] [dx] [cx] [si] \ + __value [ah] \ + __modify [ax bx] + +/* Reading from configuration space */ + +static pcierr pci_read_config_byte(pcisel sel, unsigned char reg, unsigned char __far *data); +#pragma aux pci_read_config_byte = \ + "mov ax, 0xB108" \ + "int 0x1A" \ + "mov [es:si], cl" \ + __parm [bx] [di] [es si] \ + __value [ah] \ + __modify [ax cx] + +static pcierr pci_read_config_word(pcisel sel, unsigned char reg, unsigned short __far *data); +#pragma aux pci_read_config_word = \ + "mov ax, 0xB109" \ + "int 0x1A" \ + "mov [es:si], cx" \ + __parm [bx] [di] [es si] \ + __value [ah] \ + __modify [ax cx] + +static pcierr pci_read_config_dword(pcisel sel, unsigned char reg, unsigned long __far *data); +#pragma aux pci_read_config_dword = \ + "mov ax, 0xB10A" \ + "int 0x1A" \ + "mov [es:si], ecx" \ + __parm [bx] [di] [es si] \ + __value [ah] \ + __modify [ax cx] + +/* Writing to configuration space */ + +static pcierr pci_write_config_byte(pcisel sel, unsigned char reg, unsigned char data); +#pragma aux pci_write_config_byte = \ + "mov ax, 0xB10B" \ + "int 0x1A" \ + __parm [bx] [di] [cl] \ + __value [ah] \ + __modify [ax] + +static pcierr pci_write_config_word(pcisel sel, unsigned char reg, unsigned short data); +#pragma aux pci_write_config_word = \ + "mov ax, 0xB10C" \ + "int 0x1A" \ + __parm [bx] [di] [cx] \ + __value [ah] \ + __modify [ax cx] + +static pcierr pci_write_config_dword(pcisel sel, unsigned char reg, unsigned long data); +#pragma aux pci_write_config_dword = \ + "mov ax, 0xB10D" \ + "shl esi, 16" \ + "and ecx, 0xFFFF" \ + "or ecx, esi" \ + "int 0x1A" \ + __parm [bx] [di] [si cx] \ + __value [ah] \ + __modify [ax cx] + +#endif /* INT1APCI_H */ diff --git a/int4Bvds.h b/int4Bvds.h new file mode 100644 index 0000000..511cb0f --- /dev/null +++ b/int4Bvds.h @@ -0,0 +1,162 @@ +/* + * VBMouse - Interface to the Virtual DMA Service (VDS) + * Copyright (C) 2022 Javier S. Pedro + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef INT4BVDS_H +#define INT4BVDS_H + +#include +#include + +typedef unsigned char vdserr; +enum vds_errors { + VDS_SUCCESSFUL = 0, + VDS_REGION_NOT_CONTIGUOUS = 1, + VDS_REGION_NOT_ALIGNED = 2, + VDS_UNABLE_TO_LOCK = 3, + VDS_NO_BUFFER_AVAIL = 4, + VDS_REGION_TOO_LARGE = 5, + VDS_BUFFER_IN_USE = 6, + VDS_INVALID_REGION = 7, + VDS_REGION_NOT_LOCKED = 8, + VDS_TOO_MANY_PAGES = 9, + VDS_INVALID_BUFFER_ID = 0xA, + VDS_BUFFER_BOUNDARY = 0xB, + VDS_INVALID_DMA_CHANNEL = 0xC, + VDS_DISABLE_COUNT_OVRFLOW = 0xD, + VDS_DISABLE_COUNT_UNDFLOW = 0xE, + VDS_NOT_SUPPORTED = 0xF, + VDS_FLAGS_NOT_SUPPORTED = 0x10, +}; + +enum vds_flags { +/* + Bit 1 = Automatically copy to/from buffer + Bit 2 = Disable automatic buffer allocation + Bit 3 = Disable automatic remap feature + Bit 4 = Region must not cross 64K physical alignment boundary + Bit 5 = Region must not cross 128K physical alignment boundary + Bit 6 = Copy page-table for scatter/gather remap + Bit 7 = Allow non-present pages for scatter/gather remap +*/ + VDS_AUTO_COPY_DATA = 1 << 1, + VDS_NO_AUTO_ALLOC = 1 << 2, + VDS_NO_AUTO_REMAP = 1 << 3, + VDS_ALIGN_64K = 1 << 4, + VDS_ALIGN_128K = 1 << 5 +}; + +/** DMA Descriptor structure. Describes a potentially DMA-lockable buffer. */ +typedef _Packed struct VDSDDS +{ + /** Size of this buffer. */ + uint32_t regionSize; + /** Logical/segmented address of this buffer, offset part */ + uint32_t offset; + /** Segment of this buffer. */ + uint16_t segOrSelector; + /** Internal VDS buffer ID. */ + uint16_t bufferId; + /** Physical address of this buffer. */ + uint32_t physicalAddress; +} VDSDDS; + +static bool vds_available(void); +#pragma aux vds_available = \ + "mov ax, 0x40" \ + "mov es, ax" \ + "mov al, es:[0x7B]" \ + "and al, 0x20" \ + "setnz al" \ + __value [al] \ + __modify [ax es] + +/** Locks an already allocated buffer into a physical memory location. + * regionSize, offset and segment must be valid in the DDS, + * while the physical address is returned. */ +static vdserr vds_lock_dma_buffer_region(VDSDDS __far * dds, unsigned char flags); +#pragma aux vds_lock_dma_buffer_region = \ + "stc" \ + "mov ax, 0x8103" \ + "int 0x4B" \ + "jc fail" \ + "mov al, 0" \ + "jmp end" \ + "fail: test al, al" \ + "jnz end" \ + "mov al, 0xFF" /* Force a error code if there was none. */ \ + "end:" \ + __parm [es di] [dx] \ + __value [al] \ + __modify [ax] + +/** Unlocks a locked buffer. */ +static vdserr vds_unlock_dma_buffer_region(VDSDDS __far * dds, unsigned char flags); +#pragma aux vds_unlock_dma_buffer_region = \ + "stc" \ + "mov ax, 0x8104" \ + "int 0x4B" \ + "jc fail" \ + "mov al, 0" \ + "jmp end" \ + "fail: test al, al" \ + "jnz end" \ + "mov al, 0xFF" \ + "end:" \ + __parm [es di] [dx] \ + __value [al] \ + __modify [ax] + +/** Allocates a DMA buffer. + * @param dds regionSize must be valid. + * @return dds Physical_Address, Buffer_ID, and Region_Size + */ +static vdserr vds_request_dma_buffer(VDSDDS __far * dds, unsigned char flags); +#pragma aux vds_request_dma_buffer = \ + "stc" \ + "mov ax, 0x8107" \ + "int 0x4B" \ + "jc fail" \ + "mov al, 0" \ + "jmp end" \ + "fail: test al, al" \ + "jnz end" \ + "mov al, 0xFF" \ + "end:" \ + __parm [es di] [dx] \ + __value [al] \ + __modify [ax] + +/** Frees a DMA buffer. */ +static vdserr vds_release_dma_buffer(VDSDDS __far * dds, unsigned char flags); +#pragma aux vds_release_dma_buffer = \ + "stc" \ + "mov ax, 0x8108" \ + "int 0x4B" \ + "jc fail" \ + "mov al, 0" \ + "jmp end" \ + "fail: test al, al" \ + "jnz end" \ + "mov al, 0xFF" \ + "end:" \ + __parm [es di] [dx] \ + __value [al] \ + __modify [ax] + +#endif /* INT4BVDS_H */ diff --git a/mousetsr.c b/mousetsr.c index b9fad9e..4fcc381 100644 --- a/mousetsr.c +++ b/mousetsr.c @@ -22,7 +22,7 @@ #include #include "dlog.h" -#include "ps2.h" +#include "int15ps2.h" #include "int10vga.h" #include "int16kbd.h" #include "int2fwin.h" diff --git a/mousmain.c b/mousmain.c index c62712c..93a8c0d 100644 --- a/mousmain.c +++ b/mousmain.c @@ -26,7 +26,7 @@ #include "dlog.h" #include "int33.h" #include "int21dos.h" -#include "ps2.h" +#include "int15ps2.h" #include "vbox.h" #include "vmware.h" #include "dostsr.h" diff --git a/pci.h b/pci.h deleted file mode 100644 index 8d0b7a8..0000000 --- a/pci.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * VBMouse - PCI BIOS communication routines - * Copyright (C) 2022 Javier S. Pedro - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef PCI_H -#define PCI_H - -typedef unsigned char pcierr; -enum { - PCI_SUCCESSFUL = 0, - PCI_GENERIC_ERROR = 1, - PCI_FUNC_NOT_SUPPORTED = 0x81, - PCI_BAD_VENDOR_ID = 0x83, - PCI_DEVICE_NOT_FOUND = 0x86, - PCI_BAD_REGISTER_NUMBER = 0x87, - PCI_SET_FAILED = 0x88, - PCI_BUFFER_TOO_SMALL = 0x89 -}; - -typedef unsigned short pcisel; - -static pcierr pci_init_bios(void); -#pragma aux pci_init_bios = \ - "mov ax, 0xB101" \ - "int 0x1A" \ - "jc not_found" \ - "cmp ah, 0" \ - "jne not_found" \ - "cmp edx, ' ICP'" \ - "jne not_found" \ - "mov ah, 0" \ - "jmp end" \ - "not_found: mov ah, 1" \ - "end:" \ - __value [ah] \ - __modify [ax bx cx dx] - -static pcierr pci_find_device(pcisel __far *sel, unsigned short vendor_id, unsigned short dev_id, unsigned short index); -#pragma aux pci_find_device = \ - "mov ax, 0xB102" \ - "int 0x1A" \ - "jnc success" \ - "mov ah, 1" \ - "success: mov [es:di], bx" \ - __parm [es di] [dx] [cx] [si] \ - __value [ah] \ - __modify [ax bx] - -/* Reading from configuration space */ - -static pcierr pci_read_config_byte(pcisel sel, unsigned char reg, unsigned char __far *data); -#pragma aux pci_read_config_byte = \ - "mov ax, 0xB108" \ - "int 0x1A" \ - "mov [es:si], cl" \ - __parm [bx] [di] [es si] \ - __value [ah] \ - __modify [ax cx] - -static pcierr pci_read_config_word(pcisel sel, unsigned char reg, unsigned short __far *data); -#pragma aux pci_read_config_word = \ - "mov ax, 0xB109" \ - "int 0x1A" \ - "mov [es:si], cx" \ - __parm [bx] [di] [es si] \ - __value [ah] \ - __modify [ax cx] - -static pcierr pci_read_config_dword(pcisel sel, unsigned char reg, unsigned long __far *data); -#pragma aux pci_read_config_dword = \ - "mov ax, 0xB10A" \ - "int 0x1A" \ - "mov [es:si], ecx" \ - __parm [bx] [di] [es si] \ - __value [ah] \ - __modify [ax cx] - -/* Writing to configuration space */ - -static pcierr pci_write_config_byte(pcisel sel, unsigned char reg, unsigned char data); -#pragma aux pci_write_config_byte = \ - "mov ax, 0xB10B" \ - "int 0x1A" \ - __parm [bx] [di] [cl] \ - __value [ah] \ - __modify [ax] - -static pcierr pci_write_config_word(pcisel sel, unsigned char reg, unsigned short data); -#pragma aux pci_write_config_word = \ - "mov ax, 0xB10C" \ - "int 0x1A" \ - __parm [bx] [di] [cx] \ - __value [ah] \ - __modify [ax cx] - -static pcierr pci_write_config_dword(pcisel sel, unsigned char reg, unsigned long data); -#pragma aux pci_write_config_dword = \ - "mov ax, 0xB10D" \ - "shl esi, 16" \ - "and ecx, 0xFFFF" \ - "or ecx, esi" \ - "int 0x1A" \ - __parm [bx] [di] [si cx] \ - __value [ah] \ - __modify [ax cx] - -#endif diff --git a/ps2.h b/ps2.h deleted file mode 100644 index ffcf7bb..0000000 --- a/ps2.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * VBMouse - Routines to access the PS2 BIOS services - * Copyright (C) 2022 Javier S. Pedro - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef PS2_H -#define PS2_H - -#include -#include - -/** Standard PS/2 mouse IRQ. At least on VirtualBox. */ -#define PS2_MOUSE_IRQ 12 -/** The corresponding interrupt vector for IRQ 12. */ -#define PS2_MOUSE_INT_VECTOR 0x74 - -typedef uint8_t ps2m_err; -enum ps2m_errors { - PS2M_ERR_INVALID_FUNCTION = 1, - PSM2_ERR_INVALID_INPUT = 2, - PSM2_ERR_INTERFACE_ERROR = 3, - PSM2_ERR_RESEND = 4, - PSM2_ERR_NO_CALLBACK = 5, -}; - -enum ps2m_status { - PS2M_STATUS_BUTTON_1 = 1 << 0, - PS2M_STATUS_BUTTON_2 = 1 << 1, - PS2M_STATUS_BUTTON_3 = 1 << 2, - PS2M_STATUS_X_NEG = 1 << 4, - PS2M_STATUS_Y_NEG = 1 << 5, - PS2M_STATUS_X_OVF = 1 << 6, - PS2M_STATUS_Y_OVF = 1 << 7, -}; - -enum ps2m_packet_size { - PS2M_PACKET_SIZE_PLAIN = 3, - PS2M_PACKET_SIZE_EXT = 4, -}; - -enum ps2m_device_ids { - /** Standard PS/2 mouse, 2 buttons. */ - PS2M_DEVICE_ID_PLAIN = 0, - /** IntelliMouse PS/2, with wheel. */ - PS2M_DEVICE_ID_IMPS2 = 3, - /** IntelliMouse Explorer, wheel and 5 buttons. */ - PS2M_DEVICE_ID_IMEX = 4, - /** IntelliMouse Explorer, wheel, 5 buttons, and horizontal scrolling. */ - PS2M_DEVICE_ID_IMEX_HORZ = 5 -}; - -enum ps2m_resolution { - PS2M_RESOLUTION_25 = 0, - PS2M_RESOLUTION_50 = 1, - PS2M_RESOLUTION_100 = 2, - PS2M_RESOLUTION_200 = 3 -}; - -enum ps2m_sample_rate { - PS2M_SAMPLE_RATE_10 = 0, - PS2M_SAMPLE_RATE_20 = 1, - PS2M_SAMPLE_RATE_40 = 2, - PS2M_SAMPLE_RATE_60 = 3, - PS2M_SAMPLE_RATE_80 = 4, - PS2M_SAMPLE_RATE_100 = 5, - PS2M_SAMPLE_RATE_200 = 6 -}; - -/** Invoked by the BIOS when there is a mouse event. */ -typedef void (__far * LPFN_PS2CALLBACK)(); - -static ps2m_err ps2m_init(uint8_t packet_size); -#pragma aux ps2m_init = \ - "stc" /* If nothing happens, assume failure */ \ - "mov ax, 0xC205" /* Pointing device: initialization (packet size in bh) */ \ - "int 0x15" \ - "jnc end" /* Success */ \ - "fail: test ah, ah" /* Ensure we have some error code back, set ah to -1 if we don't */ \ - "jnz end" \ - "dec ah" \ - "end:" \ - __parm [bh] \ - __value [ah] \ - __modify [ax] - -static ps2m_err ps2m_reset(void); -#pragma aux ps2m_reset = \ - "stc" \ - "mov ax, 0xC201" /* Pointing device: reset */ \ - "int 0x15" \ - "jnc end" \ - "fail: test ah, ah" \ - "jnz end" \ - "dec ah" \ - "end:" \ - __value [ah] \ - __modify [ax] - -static ps2m_err ps2m_get_device_id(uint8_t __far *device_id); -#pragma aux ps2m_get_device_id = \ - "stc" \ - "mov ax, 0xC204" /* Pointing device: get device ID */ \ - "int 0x15" \ - "mov es:[di], bh" /* Save returned value */ \ - "jnc end" \ - "fail: test ah, ah" \ - "jnz end" \ - "dec ah" \ - "end:" \ - __parm [es di] \ - __value [ah] \ - __modify [ax] - -static ps2m_err ps2m_set_resolution(uint8_t resolution); -#pragma aux ps2m_set_resolution = \ - "stc" \ - "mov ax, 0xC203" /* Pointing device: set resolution (in bh) */ \ - "int 0x15" \ - "jnc end" \ - "fail: test ah, ah" \ - "jnz end" \ - "dec ah" \ - "end:" \ - __parm [bh] \ - __value [ah] \ - __modify [ax] - -static ps2m_err ps2m_set_sample_rate(uint8_t sample_rate); -#pragma aux ps2m_set_sample_rate = \ - "stc" \ - "mov ax, 0xC202" /* Pointing device: set sample rate (in bh) */ \ - "int 0x15" \ - "jnc end" \ - "fail: test ah, ah" \ - "jnz end" \ - "dec ah" \ - "end:" \ - __parm [bh] \ - __value [ah] \ - __modify [ax] - -static ps2m_err ps2m_set_scaling_factor(uint8_t scaling_factor); -#pragma aux ps2m_set_scaling_factor = \ - "stc" \ - "mov ax, 0xC206" /* Pointing device: extended commands (with bh > 0, set scaling factor) */ \ - "int 0x15" \ - "jnc end" \ - "fail: test ah, ah" \ - "jnz end" \ - "dec ah" \ - "end:" \ - __parm [bh] \ - __value [ah] \ - __modify [ax] - -static ps2m_err ps2m_set_callback(LPFN_PS2CALLBACK callback); -#pragma aux ps2m_set_callback = \ - "stc" \ - "mov ax, 0xC207" /* Pointing device: set interrupt callback (in es:bx) */ \ - "int 0x15" \ - "jnc end" \ - "fail: test ah, ah" \ - "jnz end" \ - "dec ah" \ - "end:" \ - __parm [es bx] \ - __value [ah] \ - __modify [ax] - -static ps2m_err ps2m_enable(bool enable); -#pragma aux ps2m_enable = \ - "test bh, bh" /* Ensure enable is either 1 or 0 */ \ - "setnz bh" \ - "stc" \ - "mov ax, 0xC200" /* Pointing device enable/disable (in bh) */ \ - "int 0x15" \ - "jnc end" \ - "fail: test ah, ah" \ - "jnz end" \ - "dec ah" \ - "end:" \ - __parm [bh] \ - __value [ah] \ - __modify [ax] - -static void ps2m_send_imps2_sequence(void) -{ - ps2m_set_sample_rate(PS2M_SAMPLE_RATE_200); - ps2m_set_sample_rate(PS2M_SAMPLE_RATE_100); - ps2m_set_sample_rate(PS2M_SAMPLE_RATE_80); -} - -static bool ps2m_detect_wheel(void) -{ - int err; - uint8_t device_id; - - // Switch to the 4-byte packet and reset the mouse. - // We are not supposed to receive messages at this time anyway. - err = ps2m_init(PS2M_PACKET_SIZE_EXT); - if (err) { - return false; - } - - // Get the initial mouse device id - err = ps2m_get_device_id(&device_id); - if (err || device_id != 0) { - // TODO : Likely have to accept more device_ids here. - return false; - } - - // Send the knock sequence to activate the extended packet - ps2m_send_imps2_sequence(); - - // Now check if the device id has changed - err = ps2m_get_device_id(&device_id); - - return err == 0 && device_id == PS2M_DEVICE_ID_IMPS2; -} - -#endif diff --git a/vbox.c b/vbox.c index 8c6d28a..9fd0aa4 100644 --- a/vbox.c +++ b/vbox.c @@ -24,8 +24,8 @@ #include "dlog.h" #include "utils.h" -#include "pci.h" -#include "vds.h" +#include "int1Apci.h" +#include "int4Bvds.h" #include "vboxdev.h" #include "vbox.h" diff --git a/vbox.h b/vbox.h index 8bbfed9..d47c01a 100644 --- a/vbox.h +++ b/vbox.h @@ -27,7 +27,7 @@ #include #include "dlog.h" -#include "vds.h" +#include "int4Bvds.h" #include "utils.h" #include "vboxdev.h" diff --git a/vds.h b/vds.h deleted file mode 100644 index c8822c4..0000000 --- a/vds.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * VBMouse - Interface to the Virtual DMA Service (VDS) - * Copyright (C) 2022 Javier S. Pedro - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef VDS_H -#define VDS_H - -#include -#include - -typedef unsigned char vdserr; -enum vds_errors { - VDS_SUCCESSFUL = 0, - VDS_REGION_NOT_CONTIGUOUS = 1, - VDS_REGION_NOT_ALIGNED = 2, - VDS_UNABLE_TO_LOCK = 3, - VDS_NO_BUFFER_AVAIL = 4, - VDS_REGION_TOO_LARGE = 5, - VDS_BUFFER_IN_USE = 6, - VDS_INVALID_REGION = 7, - VDS_REGION_NOT_LOCKED = 8, - VDS_TOO_MANY_PAGES = 9, - VDS_INVALID_BUFFER_ID = 0xA, - VDS_BUFFER_BOUNDARY = 0xB, - VDS_INVALID_DMA_CHANNEL = 0xC, - VDS_DISABLE_COUNT_OVRFLOW = 0xD, - VDS_DISABLE_COUNT_UNDFLOW = 0xE, - VDS_NOT_SUPPORTED = 0xF, - VDS_FLAGS_NOT_SUPPORTED = 0x10, -}; - -enum vds_flags { -/* - Bit 1 = Automatically copy to/from buffer - Bit 2 = Disable automatic buffer allocation - Bit 3 = Disable automatic remap feature - Bit 4 = Region must not cross 64K physical alignment boundary - Bit 5 = Region must not cross 128K physical alignment boundary - Bit 6 = Copy page-table for scatter/gather remap - Bit 7 = Allow non-present pages for scatter/gather remap -*/ - VDS_AUTO_COPY_DATA = 1 << 1, - VDS_NO_AUTO_ALLOC = 1 << 2, - VDS_NO_AUTO_REMAP = 1 << 3, - VDS_ALIGN_64K = 1 << 4, - VDS_ALIGN_128K = 1 << 5 -}; - -/** DMA Descriptor structure. Describes a potentially DMA-lockable buffer. */ -typedef _Packed struct VDSDDS -{ - /** Size of this buffer. */ - uint32_t regionSize; - /** Logical/segmented address of this buffer, offset part */ - uint32_t offset; - /** Segment of this buffer. */ - uint16_t segOrSelector; - /** Internal VDS buffer ID. */ - uint16_t bufferId; - /** Physical address of this buffer. */ - uint32_t physicalAddress; -} VDSDDS; - -static bool vds_available(void); -#pragma aux vds_available = \ - "mov ax, 0x40" \ - "mov es, ax" \ - "mov al, es:[0x7B]" \ - "and al, 0x20" \ - "setnz al" \ - __value [al] \ - __modify [ax es] - -/** Locks an already allocated buffer into a physical memory location. - * regionSize, offset and segment must be valid in the DDS, - * while the physical address is returned. */ -static vdserr vds_lock_dma_buffer_region(VDSDDS __far * dds, unsigned char flags); -#pragma aux vds_lock_dma_buffer_region = \ - "stc" \ - "mov ax, 0x8103" \ - "int 0x4B" \ - "jc fail" \ - "mov al, 0" \ - "jmp end" \ - "fail: test al, al" \ - "jnz end" \ - "mov al, 0xFF" /* Force a error code if there was none. */ \ - "end:" \ - __parm [es di] [dx] \ - __value [al] \ - __modify [ax] - -/** Unlocks a locked buffer. */ -static vdserr vds_unlock_dma_buffer_region(VDSDDS __far * dds, unsigned char flags); -#pragma aux vds_unlock_dma_buffer_region = \ - "stc" \ - "mov ax, 0x8104" \ - "int 0x4B" \ - "jc fail" \ - "mov al, 0" \ - "jmp end" \ - "fail: test al, al" \ - "jnz end" \ - "mov al, 0xFF" \ - "end:" \ - __parm [es di] [dx] \ - __value [al] \ - __modify [ax] - -/** Allocates a DMA buffer. - * @param dds regionSize must be valid. - * @return dds Physical_Address, Buffer_ID, and Region_Size - */ -static vdserr vds_request_dma_buffer(VDSDDS __far * dds, unsigned char flags); -#pragma aux vds_request_dma_buffer = \ - "stc" \ - "mov ax, 0x8107" \ - "int 0x4B" \ - "jc fail" \ - "mov al, 0" \ - "jmp end" \ - "fail: test al, al" \ - "jnz end" \ - "mov al, 0xFF" \ - "end:" \ - __parm [es di] [dx] \ - __value [al] \ - __modify [ax] - -/** Frees a DMA buffer. */ -static vdserr vds_release_dma_buffer(VDSDDS __far * dds, unsigned char flags); -#pragma aux vds_release_dma_buffer = \ - "stc" \ - "mov ax, 0x8108" \ - "int 0x4B" \ - "jc fail" \ - "mov al, 0" \ - "jmp end" \ - "fail: test al, al" \ - "jnz end" \ - "mov al, 0xFF" \ - "end:" \ - __parm [es di] [dx] \ - __value [al] \ - __modify [ax] - -#endif -- cgit v1.2.3