#endif
#ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#include <signal.h>
#include <sys/dkio.h>
#endif
#ifdef __linux__
#include <linux/cdrom.h>
#include <linux/fd.h>
#endif
+#ifdef __FreeBSD__
+#include <sys/disk.h>
+#endif
//#define DEBUG_FLOPPY
the_end: ;
}
+/* Wait for all IO requests to complete. */
+void qemu_aio_flush(void)
+{
+ qemu_aio_wait_start();
+ qemu_aio_poll();
+ while (first_aio) {
+ qemu_aio_wait();
+ }
+ qemu_aio_wait_end();
+}
+
/* wait until at least one AIO was handled */
static sigset_t wait_oset;
#define FTYPE_FILE 0
#define FTYPE_CD 1
+#define FTYPE_HARDDISK 2
typedef struct BDRVRawState {
HANDLE hfile;
int type;
- char drive_letter[2];
+ char drive_path[16]; /* format: "d:\" */
} BDRVRawState;
typedef struct RawAIOCB {
BDRVRawState *s = bs->opaque;
int access_flags, create_flags;
DWORD overlapped;
- char device_name[64];
- const char *p;
- if (strstart(filename, "/dev/cdrom", NULL)) {
- if (find_cdrom(device_name, sizeof(device_name)) < 0)
- return -ENOENT;
- filename = device_name;
- } else {
- /* transform drive letters into device name */
- if (((filename[0] >= 'a' && filename[0] <= 'z') ||
- (filename[0] >= 'A' && filename[0] <= 'Z')) &&
- filename[1] == ':' && filename[2] == '\0') {
- snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
- filename = device_name;
- }
- }
- s->type = find_device_type(filename);
+ s->type = FTYPE_FILE;
if ((flags & BDRV_O_ACCESS) == O_RDWR) {
access_flags = GENERIC_READ | GENERIC_WRITE;
create_flags = OPEN_EXISTING;
}
#ifdef QEMU_TOOL
- overlapped = 0;
+ overlapped = FILE_ATTRIBUTE_NORMAL;
#else
overlapped = FILE_FLAG_OVERLAPPED;
#endif
s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
- create_flags, overlapped, 0);
- if (s->hfile == INVALID_HANDLE_VALUE)
+ create_flags, overlapped, NULL);
+ if (s->hfile == INVALID_HANDLE_VALUE) {
+ int err = GetLastError();
+
+ if (err == ERROR_ACCESS_DENIED)
+ return -EACCES;
return -1;
+ }
return 0;
}
return ret_count;
}
+#if 0
#ifndef QEMU_TOOL
static void raw_aio_cb(void *opaque)
{
qemu_aio_release(acb);
#endif
}
+#endif /* #if 0 */
static void raw_flush(BlockDriverState *bs)
{
- /* XXX: add it */
+ BDRVRawState *s = bs->opaque;
+ FlushFileBuffers(s->hfile);
}
static void raw_close(BlockDriverState *bs)
return 0;
}
-static int64_t raw_getlength(BlockDriverState *bs)
+static int64_t raw_getlength(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
LARGE_INTEGER l;
ULARGE_INTEGER available, total, total_free;
+ DISK_GEOMETRY dg;
+ DWORD count;
+ BOOL status;
- switch(s->ftype) {
+ switch(s->type) {
case FTYPE_FILE:
l.LowPart = GetFileSize(s->hfile, &l.HighPart);
if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
return -EIO;
break;
case FTYPE_CD:
- if (!GetDiskFreeSpaceEx(s->drive_letter, &available, &total, &total_free))
+ if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
return -EIO;
- l = total;
+ l.QuadPart = total.QuadPart;
+ break;
+ case FTYPE_HARDDISK:
+ status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL, 0, &dg, sizeof(dg), &count, NULL);
+ if (status != FALSE) {
+ l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
+ * dg.SectorsPerTrack * dg.BytesPerSector;
+ }
break;
default:
return -EIO;
{
}
+void qemu_aio_flush(void)
+{
+}
+
void qemu_aio_wait_start(void)
{
}
void qemu_aio_wait(void)
{
+#ifndef QEMU_TOOL
+ qemu_bh_poll();
+#endif
}
void qemu_aio_wait_end(void)
char drives[256], *pdrv = drives;
UINT type;
- memset(drives, 0, sizeof(drivers));
+ memset(drives, 0, sizeof(drives));
GetLogicalDriveStrings(sizeof(drives), drives);
while(pdrv[0] != '\0') {
type = GetDriveType(pdrv);
return -1;
}
-static int find_device_type(const char *filename)
+static int find_device_type(BlockDriverState *bs, const char *filename)
{
+ BDRVRawState *s = bs->opaque;
UINT type;
const char *p;
if (strstart(filename, "\\\\.\\", &p) ||
strstart(filename, "//./", &p)) {
- s->drive_letter[0] = p[0];
- s->drive_letter[1] = '\0';
- type = GetDriveType(s->drive_letter);
+ if (stristart(p, "PhysicalDrive", NULL))
+ return FTYPE_HARDDISK;
+ snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
+ type = GetDriveType(s->drive_path);
if (type == DRIVE_CDROM)
return FTYPE_CD;
else
int access_flags, create_flags;
DWORD overlapped;
char device_name[64];
- const char *p;
if (strstart(filename, "/dev/cdrom", NULL)) {
if (find_cdrom(device_name, sizeof(device_name)) < 0)
filename = device_name;
}
}
- s->type = find_device_type(filename);
-
+ s->type = find_device_type(bs, filename);
+
if ((flags & BDRV_O_ACCESS) == O_RDWR) {
access_flags = GENERIC_READ | GENERIC_WRITE;
} else {
create_flags = OPEN_EXISTING;
#ifdef QEMU_TOOL
- overlapped = 0;
+ overlapped = FILE_ATTRIBUTE_NORMAL;
#else
overlapped = FILE_FLAG_OVERLAPPED;
#endif
s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
- create_flags, overlapped, 0);
- if (s->hfile == INVALID_HANDLE_VALUE)
+ create_flags, overlapped, NULL);
+ if (s->hfile == INVALID_HANDLE_VALUE) {
+ int err = GetLastError();
+
+ if (err == ERROR_ACCESS_DENIED)
+ return -EACCES;
return -1;
+ }
return 0;
}