aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dlog.h2
-rw-r--r--dosmain.c42
-rw-r--r--dostsr.c2
-rw-r--r--dostsr.h1
-rw-r--r--vbox.c82
-rw-r--r--vbox.h33
-rw-r--r--vboxlog.h12
-rw-r--r--vds.h61
8 files changed, 146 insertions, 89 deletions
diff --git a/dlog.h b/dlog.h
index 67f430a..6556089 100644
--- a/dlog.h
+++ b/dlog.h
@@ -25,7 +25,7 @@
#if ENABLE_DLOG
#if 1
-#include "vbox.h"
+#include "vboxlog.h"
#define dlog_putc vbox_log_putc
#endif
diff --git a/dosmain.c b/dosmain.c
index f1c2291..ee6389c 100644
--- a/dosmain.c
+++ b/dosmain.c
@@ -36,24 +36,34 @@ static int set_integration(LPTSRDATA data, bool enable)
data->vbavail = false; // Reinitialize it even if already enabled
- if ((err = vbox_init(&data->vb)) == 0) {
- printf("Found VirtualBox device at IO 0x%x\n", data->vb.iobase);
- printf("Physical address used for VBox communication: 0x%lx\n", data->vb.buf_physaddr);
-
- if ((err = vbox_report_guest_info(&data->vb, VBOXOSTYPE_DOS)) == 0) {
- printf("VirtualBox integration enabled\n");
- data->vbavail = true;
- } else {
- fprintf(stderr, "VirtualBox communication is not working, err=%d\n", err);
- return err;
- }
- } else {
+ err = vbox_init_device(&data->vb);
+ if (err) {
fprintf(stderr, "Cannot find VirtualBox PCI device, err=%d\n", err);
return err;
}
+
+ printf("Found VirtualBox device at IO 0x%x\n", data->vb.iobase);
+
+ err = vbox_init_buffer(&data->vb);
+ if (err) {
+ fprintf(stderr, "Cannot lock buffer used for VirtualBox communication, err=%d\n", err);
+ return err;
+ }
+
+ err = vbox_report_guest_info(&data->vb, VBOXOSTYPE_DOS);
+ if (err) {
+ fprintf(stderr, "VirtualBox communication is not working, err=%d\n", err);
+ return err;
+ }
+
+ printf("VirtualBox integration enabled\n");
+ data->vbavail = true;
} else {
if (data->vbavail) {
vbox_set_mouse(&data->vb, false, false);
+
+ vbox_release_buffer(&data->vb);
+
printf("Disabled VirtualBox integration\n");
data->vbavail = false;
} else {
@@ -208,12 +218,6 @@ static int driver_reset(void)
return int33_call(0x0) == 0xFFFF;
}
-static int driver_test(void)
-{
- int2f_call(0x1234);
- return EXIT_FAILURE;
-}
-
static int driver_not_found(void)
{
fprintf(stderr, "Driver data not found (driver not installed?)\n");
@@ -311,8 +315,6 @@ int main(int argc, const char *argv[])
#endif
} else if (stricmp(argv[argi], "reset") == 0) {
return driver_reset();
- } else if (stricmp(argv[argi], "test") == 0) {
- return driver_test();
}
print_help();
diff --git a/dostsr.c b/dostsr.c
index aab2855..57ec089 100644
--- a/dostsr.c
+++ b/dostsr.c
@@ -366,7 +366,7 @@ static void load_cursor(void)
dlog_puts("Loading cursor to VBox");
- vbox_send_request(data.vb.iobase, data.vb.buf_physaddr);
+ vbox_send_request(data.vb.iobase, data.vb.dds.physicalAddress);
if (req->header.rc != 0) {
dlog_puts("Could not send cursor to VirtualBox");
diff --git a/dostsr.h b/dostsr.h
index 268b2aa..b9a5b73 100644
--- a/dostsr.h
+++ b/dostsr.h
@@ -161,6 +161,7 @@ extern void __declspec(naked) __far int2f_isr(void);
extern LPTSRDATA __far get_tsr_data(bool installed);
+/** This symbol is always at the end of the TSR segment */
extern int resident_end;
/** This is not just data, but the entire segment. */
diff --git a/vbox.c b/vbox.c
index 6d33659..28fb02d 100644
--- a/vbox.c
+++ b/vbox.c
@@ -38,9 +38,7 @@ enum {
CFG_BAR1 = 0x14, /* DWord */
};
-/** Finds the VirtualBox PCI device and reads the current IO base.
- * @returns 0 if the device was found. */
-static int vbox_find_iobase(uint16_t __far *iobase)
+int vbox_init_device(LPVBOXCOMM vb)
{
int err;
pcisel pcidev;
@@ -73,65 +71,61 @@ static int vbox_find_iobase(uint16_t __far *iobase)
return -2;
}
- *iobase = bar & 0xFFFC;
+ vb->iobase = bar & 0xFFFC;
return 0;
}
-static int vbox_get_phys_addr(uint32_t __far *physaddr, void __far *buf)
+int vbox_init_buffer(LPVBOXCOMM vb)
{
- int err = 0;
-#if 0
if (vds_available()) {
// Use the Virtual DMA Service to get the physical address of this buffer
- bufdds.regionSize = bufferSize;
- bufdds.segOrSelector = FP_SEG(pBuf);
- bufdds.offset = FP_OFF(pBuf);
- bufdds.bufferId = 0;
- bufdds.physicalAddress = 0;
-
- err = vds_lock_dma_buffer_region(&bufdds, VDS_NO_AUTO_ALLOC);
- if (err == VDS_REGION_NOT_CONTIGUOUS) {
- // This is why we made the allocation double the required size
- // If the buffer happens to be on a page boundary,
- // it may not be contiguous and cause the call to fail.
- // So, we try to lock the 2nd half of the allocation,
- // which should not be on a page boundary.
- vbox_logs("VDS try again\n");
- pBuf = (char FAR*) pBuf + bufferSize;
- bufdds.regionSize = bufferSize;
- bufdds.offset += bufferSize;
- err = vds_lock_dma_buffer_region(&bufdds, VDS_NO_AUTO_ALLOC);
- }
+ int err;
+
+ vb->dds.regionSize = sizeof(vb->buf);
+ vb->dds.segOrSelector = FP_SEG(&vb->buf);
+ vb->dds.offset = FP_OFF(&vb->buf);
+ vb->dds.bufferId = 0;
+ vb->dds.physicalAddress = 0;
+
+ err = vds_lock_dma_buffer_region(&vb->dds, VDS_NO_AUTO_ALLOC);
if (err) {
- vbox_logs("VDS lock failure\n");
+ // As far as I have seen, most VDS providers always keep low memory contiguous,
+ // so I'm not handling VDS_REGION_NOT_CONTIGUOUS here.
+ dlog_print("Error while VDS locking, err=");
+ dlog_printd(err);
+ dlog_endline();
+ return err;
}
} else {
- bufdds.regionSize = 0; // Indicates we don't have to unlock this later on
+ vb->dds.regionSize = 0; // So that we don't try to unlock it later
+ vb->dds.segOrSelector = FP_SEG(&vb->buf);
+ vb->dds.offset = FP_OFF(&vb->buf);
+ vb->dds.bufferId = 0;
- // If VDS is not available, assume we are not paging
- // Just use the linear address as physical
- bufdds.physicalAddress = FP_SEG(pBuf + FP_OFF(pBuf);
- err = 0;
+ vb->dds.physicalAddress = vds_ptr_to_linear(&vb->buf);
}
-#endif
- *physaddr = ((uint32_t)(FP_SEG(buf)) << 4) + FP_OFF(buf);
-
- return err;
+ return 0;
}
-int vbox_init(LPVBOXCOMM vb)
+int vbox_release_buffer(LPVBOXCOMM vb)
{
- int err;
+ if (vds_available() && vb->dds.regionSize) {
- if ((err = vbox_find_iobase(&vb->iobase))) {
- return err;
- }
-
- if (err = vbox_get_phys_addr(&vb->buf_physaddr, vb->buf)) {
- return err;
+ int err = vds_unlock_dma_buffer_region(&vb->dds, 0);
+ if (err) {
+ dlog_print("Error while VDS unlocking, err=");
+ dlog_printd(err);
+ dlog_endline();
+ // Ignore the error, it's not like we can do anything
+ }
}
+ vb->dds.regionSize = 0;
+ vb->dds.segOrSelector = 0;
+ vb->dds.offset = 0;
+ vb->dds.bufferId = 0;
+ vb->dds.physicalAddress = 0;
return 0;
}
diff --git a/vbox.h b/vbox.h
index dfa124b..69721aa 100644
--- a/vbox.h
+++ b/vbox.h
@@ -23,6 +23,8 @@
#include <stdbool.h>
#include <stdint.h>
+#include "dlog.h"
+#include "vds.h"
#include "utils.h"
#include "vboxdev.h"
@@ -32,18 +34,10 @@
typedef struct vboxcomm {
uint16_t iobase;
char buf[VBOX_BUFFER_SIZE];
- uint32_t buf_physaddr;
+ VDSDDS dds;
} vboxcomm_t;
typedef vboxcomm_t __far * LPVBOXCOMM;
-/** Logs a single character to the VBox debug message port. */
-static void vbox_log_putc(char c);
-#pragma aux vbox_log_putc = \
- "mov dx, 0x504" \
- "out dx, al" \
- __parm [al] \
- __modify [dx]
-
/** Actually send a request to the VirtualBox VMM device.
* @param addr 32-bit physical address containing the VMMDevRequest struct.
*/
@@ -58,7 +52,16 @@ static void vbox_send_request(uint16_t iobase, uint32_t addr);
__parm [dx] [bx ax] \
__modify [dx]
-extern int vbox_init(LPVBOXCOMM vb);
+/** Finds the VirtualBox PCI device and reads the current IO base.
+ * @returns 0 if the device was found. */
+extern int vbox_init_device(LPVBOXCOMM vb);
+
+/** Prepares the buffer used for communicating with VBox and
+ * computes its physical address (using VDS if necessary). */
+extern int vbox_init_buffer(LPVBOXCOMM vb);
+
+/** Releases/unlocks buffer, no further use possible. */
+extern int vbox_release_buffer(LPVBOXCOMM vb);
/** Lets VirtualBox know that there are VirtualBox Guest Additions on this guest.
* @param osType os installed on this guest. */
@@ -75,7 +78,7 @@ static int vbox_report_guest_info(LPVBOXCOMM vb, uint32_t osType)
req->guestInfo.interfaceVersion = VMMDEV_VERSION;
req->guestInfo.osType = osType;
- vbox_send_request(vb->iobase, vb->buf_physaddr);
+ vbox_send_request(vb->iobase, vb->dds.physicalAddress);
return req->header.rc;
}
@@ -94,7 +97,7 @@ static int vbox_set_mouse(LPVBOXCOMM vb, bool absolute, bool pointer)
if (absolute) req->mouseFeatures |= VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE;
if (pointer) req->mouseFeatures |= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
- vbox_send_request(vb->iobase, vb->buf_physaddr);
+ vbox_send_request(vb->iobase, vb->dds.physicalAddress);
return req->header.rc;
}
@@ -114,7 +117,7 @@ static int vbox_get_mouse(LPVBOXCOMM vb, bool __far *abs,
req->header.requestType = VMMDevReq_GetMouseStatus;
req->header.rc = -1;
- vbox_send_request(vb->iobase, vb->buf_physaddr);
+ vbox_send_request(vb->iobase, vb->dds.physicalAddress);
*abs = req->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE;
*xpos = req->pointerXPos;
@@ -123,7 +126,7 @@ static int vbox_get_mouse(LPVBOXCOMM vb, bool __far *abs,
return req->header.rc;
}
-/** @todo */
+/** Asks the host to render the mouse cursor for us. */
static int vbox_set_pointer_visible(LPVBOXCOMM vb, bool visible)
{
VMMDevReqMousePointer __far *req = (void __far *) vb->buf;
@@ -137,7 +140,7 @@ static int vbox_set_pointer_visible(LPVBOXCOMM vb, bool visible)
if (visible) req->fFlags |= VBOX_MOUSE_POINTER_VISIBLE;
- vbox_send_request(vb->iobase, vb->buf_physaddr);
+ vbox_send_request(vb->iobase, vb->dds.physicalAddress);
return req->header.rc;
}
diff --git a/vboxlog.h b/vboxlog.h
new file mode 100644
index 0000000..11ecf68
--- /dev/null
+++ b/vboxlog.h
@@ -0,0 +1,12 @@
+#ifndef VBOXDLOG_H
+#define VBOXDLOG_H
+
+/** Logs a single character to the VBox debug message port. */
+static void vbox_log_putc(char c);
+#pragma aux vbox_log_putc = \
+ "mov dx, 0x504" \
+ "out dx, al" \
+ __parm [al] \
+ __modify [dx]
+
+#endif // VBOXDLOG_H
diff --git a/vds.h b/vds.h
index c006e1d..508a0ca 100644
--- a/vds.h
+++ b/vds.h
@@ -24,7 +24,7 @@
#include <stdint.h>
typedef unsigned char vdserr;
-enum {
+enum vds_errors {
VDS_SUCCESSFUL = 0,
VDS_REGION_NOT_CONTIGUOUS = 1,
VDS_REGION_NOT_ALIGNED = 2,
@@ -44,7 +44,7 @@ enum {
VDS_FLAGS_NOT_SUPPORTED = 0x10,
};
-enum {
+enum vds_flags {
/*
Bit 1 = Automatically copy to/from buffer
Bit 2 = Disable automatic buffer allocation
@@ -62,7 +62,7 @@ enum {
};
/** DMA Descriptor structure. Describes a potentially DMA-lockable buffer. */
-typedef _Packed struct VDS_DDS
+typedef _Packed struct VDSDDS
{
/** Size of this buffer. */
uint32_t regionSize;
@@ -74,7 +74,15 @@ typedef _Packed struct VDS_DDS
uint16_t bufferId;
/** Physical address of this buffer. */
uint32_t physicalAddress;
-} VDS_DDS;
+} VDSDDS;
+
+/** Converts a far pointer into equivalent linear address.
+ * Note that under protected mode linear != physical.
+ * That's what VDS is for. */
+static inline uint32_t vds_ptr_to_linear(const void __far * ptr)
+{
+ return ((uint32_t)(FP_SEG(ptr)) << 4) + FP_OFF(ptr);
+}
static bool vds_available(void);
#pragma aux vds_available = \
@@ -89,9 +97,9 @@ static bool vds_available(void);
/** 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(VDS_DDS __far * dds, unsigned char flags);
+static vdserr vds_lock_dma_buffer_region(VDSDDS __far * dds, unsigned char flags);
#pragma aux vds_lock_dma_buffer_region = \
- "stc" /* If nothing happens, assume failure. */ \
+ "stc" \
"mov ax, 0x8103" \
"int 0x4B" \
"jc fail" \
@@ -99,14 +107,14 @@ static vdserr vds_lock_dma_buffer_region(VDS_DDS __far * dds, unsigned char flag
"jmp end" \
"fail: test al, al" \
"jnz end" \
- "mov al, 0xFF" /* Force a error code if there was none. */ \
+ "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(VDS_DDS __far * dds, unsigned char flags);
+static vdserr vds_unlock_dma_buffer_region(VDSDDS __far * dds, unsigned char flags);
#pragma aux vds_unlock_dma_buffer_region = \
"stc" \
"mov ax, 0x8104" \
@@ -122,4 +130,41 @@ static vdserr vds_unlock_dma_buffer_region(VDS_DDS __far * dds, unsigned char fl
__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