diff options
| author | Javier <dev.git@javispedro.com> | 2022-04-02 16:34:17 +0200 | 
|---|---|---|
| committer | Javier <dev.git@javispedro.com> | 2022-04-02 16:38:30 +0200 | 
| commit | 3ca7b6c9cc23e118968b49a79f2b64fe4a3b73b3 (patch) | |
| tree | 588b776137790d189b0f3f81b4ef22fbef04f2d3 | |
| parent | aade1f47d34594216500f26ed0d21b23a1d1f4f1 (diff) | |
| download | vbados-3ca7b6c9cc23e118968b49a79f2b64fe4a3b73b3.tar.gz vbados-3ca7b6c9cc23e118968b49a79f2b64fe4a3b73b3.zip | |
readd VDS support so that it works under emm386 and win386+swap
| -rw-r--r-- | dlog.h | 2 | ||||
| -rw-r--r-- | dosmain.c | 42 | ||||
| -rw-r--r-- | dostsr.c | 2 | ||||
| -rw-r--r-- | dostsr.h | 1 | ||||
| -rw-r--r-- | vbox.c | 82 | ||||
| -rw-r--r-- | vbox.h | 33 | ||||
| -rw-r--r-- | vboxlog.h | 12 | ||||
| -rw-r--r-- | vds.h | 61 | 
8 files changed, 146 insertions, 89 deletions
| @@ -25,7 +25,7 @@  #if ENABLE_DLOG  #if 1 -#include "vbox.h" +#include "vboxlog.h"  #define dlog_putc vbox_log_putc  #endif @@ -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(); @@ -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"); @@ -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. */ @@ -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;  } @@ -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 @@ -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 | 
