diff options
Diffstat (limited to 'vdservice')
-rw-r--r-- | vdservice/pci_vdi_port.cpp | 256 | ||||
-rw-r--r-- | vdservice/pci_vdi_port.h | 2 | ||||
-rw-r--r-- | vdservice/vdi_port.h | 134 | ||||
-rw-r--r-- | vdservice/virtio_vdi_port.cpp | 328 | ||||
-rw-r--r-- | vdservice/virtio_vdi_port.h | 4 |
5 files changed, 362 insertions, 362 deletions
diff --git a/vdservice/pci_vdi_port.cpp b/vdservice/pci_vdi_port.cpp index b055c5a..d07eab7 100644 --- a/vdservice/pci_vdi_port.cpp +++ b/vdservice/pci_vdi_port.cpp @@ -1,128 +1,128 @@ -/* - Copyright (C) 2009 Red Hat, Inc. - - 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, see <http://www.gnu.org/licenses/>. -*/ - -#include "stdio.h" -#include "pci_vdi_port.h" -#include "vdlog.h" - -#define VDI_PORT_DEV_NAME TEXT("\\\\.\\VDIPort") -#define FILE_DEVICE_UNKNOWN 0x00000022 -#define METHOD_BUFFERED 0 -#define FILE_ANY_ACCESS 0 - -#define CTL_CODE(DeviceType, Function, Method, Access) ( \ - ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ -) - -#define FIRST_AVAIL_IO_FUNC 0x800 -#define RED_TUNNEL_CTL_FUNC FIRST_AVAIL_IO_FUNC - -#define IOCTL_RED_TUNNEL_SET_EVENT \ - CTL_CODE(FILE_DEVICE_UNKNOWN, RED_TUNNEL_CTL_FUNC, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - -PCIVDIPort::PCIVDIPort() - : _handle (INVALID_HANDLE_VALUE) - , _event (NULL) -{ -} - -PCIVDIPort::~PCIVDIPort() -{ - if (_handle != INVALID_HANDLE_VALUE) { - CloseHandle(_handle); - } - if (_event) { - CloseHandle(_event); - } -} - -void PCIVDIPort::fill_events(HANDLE *handle) {
- handle[PCI_VDI_PORT_EVENT] = _event;
-} - -bool PCIVDIPort::init() -{ - DWORD io_ret_len; - _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, 0, NULL); - if (_handle == INVALID_HANDLE_VALUE) { - vd_printf("CreateFile() failed: %u", GetLastError()); - return false; - } - _event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (_event == NULL) { - vd_printf("CreateEvent() failed: %u", GetLastError()); - return false; - } - if (!DeviceIoControl(_handle, IOCTL_RED_TUNNEL_SET_EVENT, &_event, sizeof(_event), - NULL, 0, &io_ret_len, NULL)) { - vd_printf("DeviceIoControl() failed: %u", GetLastError()); - return false; - } - return true; -} - -int PCIVDIPort::write() -{ - int size; - int n; - - if (_write.start == _write.end) { - return 0; - } - if (_write.start < _write.end) { - size = (int)(_write.end - _write.start); - } else { - size = (int)(&_write.ring[BUF_SIZE] - _write.start); - } - if (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) { - return handle_error(); - } - _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE; - return n; -} - -int PCIVDIPort::read() -{ - int size; - int n; - - if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) { - return 0; - } - if (_read.start == _read.end) { - _read.start = _read.end = _read.ring; - } - if (_read.start <= _read.end) { - size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end)); - } else { - size = (int)(_read.start - _read.end - 1); - } - if (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) { - return handle_error(); - } - _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE; - return n; -} - -void PCIVDIPort::handle_event(int event) -{ - // do nothing - the event merely serves to wake us up, then we call read/write - // at VDService::execute start of while(_running) loop. -} +/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "pci_vdi_port.h"
+#include "vdlog.h"
+
+#define VDI_PORT_DEV_NAME TEXT("\\\\.\\VDIPort")
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define METHOD_BUFFERED 0
+#define FILE_ANY_ACCESS 0
+
+#define CTL_CODE(DeviceType, Function, Method, Access) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define FIRST_AVAIL_IO_FUNC 0x800
+#define RED_TUNNEL_CTL_FUNC FIRST_AVAIL_IO_FUNC
+
+#define IOCTL_RED_TUNNEL_SET_EVENT \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, RED_TUNNEL_CTL_FUNC, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+PCIVDIPort::PCIVDIPort()
+ : _handle (INVALID_HANDLE_VALUE)
+ , _event (NULL)
+{
+}
+
+PCIVDIPort::~PCIVDIPort()
+{
+ if (_handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(_handle);
+ }
+ if (_event) {
+ CloseHandle(_event);
+ }
+}
+
+void PCIVDIPort::fill_events(HANDLE* handles) {
+ handles[PCI_VDI_PORT_EVENT] = _event;
+}
+
+bool PCIVDIPort::init()
+{
+ DWORD io_ret_len;
+ _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, 0, NULL);
+ if (_handle == INVALID_HANDLE_VALUE) {
+ vd_printf("CreateFile() failed: %u", GetLastError());
+ return false;
+ }
+ _event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (_event == NULL) {
+ vd_printf("CreateEvent() failed: %u", GetLastError());
+ return false;
+ }
+ if (!DeviceIoControl(_handle, IOCTL_RED_TUNNEL_SET_EVENT, &_event, sizeof(_event),
+ NULL, 0, &io_ret_len, NULL)) {
+ vd_printf("DeviceIoControl() failed: %u", GetLastError());
+ return false;
+ }
+ return true;
+}
+
+int PCIVDIPort::write()
+{
+ int size;
+ int n;
+
+ if (_write.start == _write.end) {
+ return 0;
+ }
+ if (_write.start < _write.end) {
+ size = (int)(_write.end - _write.start);
+ } else {
+ size = (int)(&_write.ring[BUF_SIZE] - _write.start);
+ }
+ if (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) {
+ return handle_error();
+ }
+ _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE;
+ return n;
+}
+
+int PCIVDIPort::read()
+{
+ int size;
+ int n;
+
+ if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
+ return 0;
+ }
+ if (_read.start == _read.end) {
+ _read.start = _read.end = _read.ring;
+ }
+ if (_read.start <= _read.end) {
+ size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
+ } else {
+ size = (int)(_read.start - _read.end - 1);
+ }
+ if (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) {
+ return handle_error();
+ }
+ _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE;
+ return n;
+}
+
+void PCIVDIPort::handle_event(int event)
+{
+ // do nothing - the event merely serves to wake us up, then we call read/write
+ // at VDService::execute start of while(_running) loop.
+}
diff --git a/vdservice/pci_vdi_port.h b/vdservice/pci_vdi_port.h index d9b6d67..caa990f 100644 --- a/vdservice/pci_vdi_port.h +++ b/vdservice/pci_vdi_port.h @@ -40,7 +40,7 @@ public: virtual int write();
virtual int read();
virtual unsigned get_num_events() { return PCI_VDI_PORT_EVENT_COUNT; }
- virtual void fill_events(HANDLE* handle);
+ virtual void fill_events(HANDLE* handles);
virtual void handle_event(int event);
private:
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h index b5c6f46..50c4d29 100644 --- a/vdservice/vdi_port.h +++ b/vdservice/vdi_port.h @@ -1,33 +1,33 @@ -/* - Copyright (C) 2009 Red Hat, Inc. - - 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, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_VDI_PORT -#define _H_VDI_PORT - -#include <windows.h> -#include <stdint.h> - -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - -#define BUF_SIZE (1024 * 1024) - -#define VDI_PORT_BLOCKED 0 -#define VDI_PORT_RESET -1 -#define VDI_PORT_ERROR -2 +/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_VDI_PORT
+#define _H_VDI_PORT
+
+#include <windows.h>
+#include <stdint.h>
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+#define BUF_SIZE (1024 * 1024)
+
+#define VDI_PORT_BLOCKED 0
+#define VDI_PORT_RESET -1
+#define VDI_PORT_ERROR -2
// Ring notes:
// _end is one after the end of data
@@ -36,40 +36,40 @@ // _start-1 is never used
// ring_write & read on right side of the ring (update _end)
// ring_read & write from left (update _start)
- -typedef struct VDIPortBuffer { - OVERLAPPED overlap; - uint8_t* start; - uint8_t* end; - bool pending; - int bytes; - uint8_t ring[BUF_SIZE]; -} VDIPortBuffer; - -class VDIPort { -public: - VDIPort(); - virtual ~VDIPort() {} - - size_t ring_write(const void* buf, size_t size); - size_t write_ring_free_space(); - size_t ring_read(void* buf, size_t size); - size_t read_ring_size(); - size_t read_ring_continuous_remaining_size(); - - virtual const char *name() = 0; - virtual bool init() = 0; - virtual unsigned get_num_events() = 0; - virtual void fill_events(HANDLE *handle) = 0; - virtual void handle_event(int event) = 0; - virtual int write() = 0; - virtual int read() = 0; - -protected: - int handle_error(); - - VDIPortBuffer _write; - VDIPortBuffer _read; -}; - -#endif +
+typedef struct VDIPortBuffer {
+ OVERLAPPED overlap;
+ uint8_t* start;
+ uint8_t* end;
+ bool pending;
+ int bytes;
+ uint8_t ring[BUF_SIZE];
+} VDIPortBuffer;
+
+class VDIPort {
+public:
+ VDIPort();
+ virtual ~VDIPort() {}
+
+ size_t ring_write(const void* buf, size_t size);
+ size_t write_ring_free_space();
+ size_t ring_read(void* buf, size_t size);
+ size_t read_ring_size();
+ size_t read_ring_continuous_remaining_size();
+
+ virtual const char *name() = 0;
+ virtual bool init() = 0;
+ virtual unsigned get_num_events() = 0;
+ virtual void fill_events(HANDLE* handles) = 0;
+ virtual void handle_event(int event) = 0;
+ virtual int write() = 0;
+ virtual int read() = 0;
+
+protected:
+ int handle_error();
+
+ VDIPortBuffer _write;
+ VDIPortBuffer _read;
+};
+
+#endif
diff --git a/vdservice/virtio_vdi_port.cpp b/vdservice/virtio_vdi_port.cpp index bbdd59e..ce4d80a 100644 --- a/vdservice/virtio_vdi_port.cpp +++ b/vdservice/virtio_vdi_port.cpp @@ -1,56 +1,56 @@ -/* - Copyright (C) 2009 Red Hat, Inc. - - 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, see <http://www.gnu.org/licenses/>. -*/ - -#include "stdio.h" -#include "virtio_vdi_port.h" -#include "vdlog.h" - -#define VIOSERIAL_PORT_PATH L"\\\\.\\Global\\com.redhat.spice.0" - -// Current limitation of virtio-serial windows driver (RHBZ 617000) -#define VIOSERIAL_PORT_MAX_WRITE_BYTES 2048 - -VirtioVDIPort* VirtioVDIPort::_singleton; - -VirtioVDIPort::VirtioVDIPort() - : VDIPort() - , _handle (INVALID_HANDLE_VALUE) -{ - _singleton = this; -} - -VirtioVDIPort::~VirtioVDIPort() -{ - if (_handle != INVALID_HANDLE_VALUE) { - CloseHandle(_handle); - } - if (_read.overlap.hEvent) { - CloseHandle(_read.overlap.hEvent); - } - if (_write.overlap.hEvent) { - CloseHandle(_write.overlap.hEvent); - } -} - -void VirtioVDIPort::fill_events(HANDLE *handle) {
- handle[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
- handle[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
-} - +/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "virtio_vdi_port.h"
+#include "vdlog.h"
+
+#define VIOSERIAL_PORT_PATH L"\\\\.\\Global\\com.redhat.spice.0"
+
+// Current limitation of virtio-serial windows driver (RHBZ 617000)
+#define VIOSERIAL_PORT_MAX_WRITE_BYTES 2048
+
+VirtioVDIPort* VirtioVDIPort::_singleton;
+
+VirtioVDIPort::VirtioVDIPort()
+ : VDIPort()
+ , _handle (INVALID_HANDLE_VALUE)
+{
+ _singleton = this;
+}
+
+VirtioVDIPort::~VirtioVDIPort()
+{
+ if (_handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(_handle);
+ }
+ if (_read.overlap.hEvent) {
+ CloseHandle(_read.overlap.hEvent);
+ }
+ if (_write.overlap.hEvent) {
+ CloseHandle(_write.overlap.hEvent);
+ }
+}
+
+void VirtioVDIPort::fill_events(HANDLE* handles) {
+ handles[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
+ handles[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
+}
+
void VirtioVDIPort::handle_event(int event) {
switch (event) {
case VIRTIO_VDI_PORT_EVENT_WRITE:
@@ -62,114 +62,114 @@ void VirtioVDIPort::handle_event(int event) { default:
vd_printf("ERROR: unexpected event %d", event);
}
-} - -bool VirtioVDIPort::init() -{ - _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (_handle == INVALID_HANDLE_VALUE) { - vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError()); - return false; - } - _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (_write.overlap.hEvent == NULL) { - vd_printf("CreateEvent() failed: %u", GetLastError()); - return false; - } - _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (_read.overlap.hEvent == NULL) { - vd_printf("CreateEvent() failed: %u", GetLastError()); - return false; - } - return true; -} - -int VirtioVDIPort::write() -{ - int size; - int ret; - - //FIXME: return VDI_PORT_NO_DATA - if (_write.start == _write.end) { - return 0; - } - if (!_write.pending) { - if (_write.start < _write.end) { - size = (int)(_write.end - _write.start); - } else { - size = (int)(&_write.ring[BUF_SIZE] - _write.start); - } - size = MIN(size, VIOSERIAL_PORT_MAX_WRITE_BYTES); - _write.pending = true; - if (WriteFile(_handle, _write.start, size, NULL, &_write.overlap)) { - write_completion(); - } if (GetLastError() != ERROR_IO_PENDING) { - return handle_error(); - } - } - ret = _write.bytes; - _write.bytes = 0; - return ret; -} - -void VirtioVDIPort::write_completion() -{ - DWORD bytes; - - if (!_write.pending) { - return; - } - if (!GetOverlappedResult(_handle, &_write.overlap, &bytes, FALSE)) { - vd_printf("GetOverlappedResult failed: %u", GetLastError()); - return; - } - _write.start = _write.ring + (_write.start - _write.ring + bytes) % BUF_SIZE; - _write.bytes = bytes; - _write.pending = false; -} - -int VirtioVDIPort::read() -{ - int size; - int ret; - - if (!_read.pending) { - //FIXME: read_ring_continuous_remaining_size? return VDI_PORT_BUFFER_FULL - if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) { - vd_printf("DEBUG: buffer full"); - return 0; - } - if (_read.start == _read.end) { - _read.start = _read.end = _read.ring; - } - if (_read.start <= _read.end) { - size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end)); - } else { - size = (int)(_read.start - _read.end - 1); - } - _read.pending = true; - if (ReadFile(_handle, _read.end, size, NULL, &_read.overlap)) { - read_completion(); - } else if (GetLastError() != ERROR_IO_PENDING) { - return handle_error(); - } - } - ret = _read.bytes; - _read.bytes = 0; - return ret; -} - -void VirtioVDIPort::read_completion() -{ - DWORD bytes; - - if (!GetOverlappedResult(_handle, &_read.overlap, &bytes, FALSE) && - GetLastError() != ERROR_MORE_DATA) { - vd_printf("GetOverlappedResult failed: %u", GetLastError()); - return; - } - _read.end = _read.ring + (_read.end - _read.ring + bytes) % BUF_SIZE; - _read.bytes = bytes; - _read.pending = false; -} +}
+
+bool VirtioVDIPort::init()
+{
+ _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ if (_handle == INVALID_HANDLE_VALUE) {
+ vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError());
+ return false;
+ }
+ _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (_write.overlap.hEvent == NULL) {
+ vd_printf("CreateEvent() failed: %u", GetLastError());
+ return false;
+ }
+ _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (_read.overlap.hEvent == NULL) {
+ vd_printf("CreateEvent() failed: %u", GetLastError());
+ return false;
+ }
+ return true;
+}
+
+int VirtioVDIPort::write()
+{
+ int size;
+ int ret;
+
+ //FIXME: return VDI_PORT_NO_DATA
+ if (_write.start == _write.end) {
+ return 0;
+ }
+ if (!_write.pending) {
+ if (_write.start < _write.end) {
+ size = (int)(_write.end - _write.start);
+ } else {
+ size = (int)(&_write.ring[BUF_SIZE] - _write.start);
+ }
+ size = MIN(size, VIOSERIAL_PORT_MAX_WRITE_BYTES);
+ _write.pending = true;
+ if (WriteFile(_handle, _write.start, size, NULL, &_write.overlap)) {
+ write_completion();
+ } if (GetLastError() != ERROR_IO_PENDING) {
+ return handle_error();
+ }
+ }
+ ret = _write.bytes;
+ _write.bytes = 0;
+ return ret;
+}
+
+void VirtioVDIPort::write_completion()
+{
+ DWORD bytes;
+
+ if (!_write.pending) {
+ return;
+ }
+ if (!GetOverlappedResult(_handle, &_write.overlap, &bytes, FALSE)) {
+ vd_printf("GetOverlappedResult failed: %u", GetLastError());
+ return;
+ }
+ _write.start = _write.ring + (_write.start - _write.ring + bytes) % BUF_SIZE;
+ _write.bytes = bytes;
+ _write.pending = false;
+}
+
+int VirtioVDIPort::read()
+{
+ int size;
+ int ret;
+
+ if (!_read.pending) {
+ //FIXME: read_ring_continuous_remaining_size? return VDI_PORT_BUFFER_FULL
+ if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
+ vd_printf("DEBUG: buffer full");
+ return 0;
+ }
+ if (_read.start == _read.end) {
+ _read.start = _read.end = _read.ring;
+ }
+ if (_read.start <= _read.end) {
+ size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
+ } else {
+ size = (int)(_read.start - _read.end - 1);
+ }
+ _read.pending = true;
+ if (ReadFile(_handle, _read.end, size, NULL, &_read.overlap)) {
+ read_completion();
+ } else if (GetLastError() != ERROR_IO_PENDING) {
+ return handle_error();
+ }
+ }
+ ret = _read.bytes;
+ _read.bytes = 0;
+ return ret;
+}
+
+void VirtioVDIPort::read_completion()
+{
+ DWORD bytes;
+
+ if (!GetOverlappedResult(_handle, &_read.overlap, &bytes, FALSE) &&
+ GetLastError() != ERROR_MORE_DATA) {
+ vd_printf("GetOverlappedResult failed: %u", GetLastError());
+ return;
+ }
+ _read.end = _read.ring + (_read.end - _read.ring + bytes) % BUF_SIZE;
+ _read.bytes = bytes;
+ _read.pending = false;
+}
diff --git a/vdservice/virtio_vdi_port.h b/vdservice/virtio_vdi_port.h index 04d3412..15b6811 100644 --- a/vdservice/virtio_vdi_port.h +++ b/vdservice/virtio_vdi_port.h @@ -16,7 +16,7 @@ public: virtual const char *name() { return "VirtioVDIPort"; }
virtual bool init();
virtual unsigned get_num_events() { return VIRTIO_VDI_PORT_EVENT_COUNT; }
- virtual void fill_events(HANDLE *handle);
+ virtual void fill_events(HANDLE* handles);
virtual void handle_event(int event);
virtual int write();
virtual int read();
@@ -30,4 +30,4 @@ private: HANDLE _handle;
};
-#endif //_H_VIRTIO_VDI_PORT
\ No newline at end of file +#endif //_H_VIRTIO_VDI_PORT
|