Attempt to fix incorrect colours on some BGR displays
[qemu] / block-raw.c
index 4dc0b9a..29882e1 100644 (file)
@@ -44,6 +44,8 @@
 #endif
 
 #ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#include <signal.h>
 #include <sys/dkio.h>
 #endif
 #ifdef __linux__
@@ -51,6 +53,9 @@
 #include <linux/cdrom.h>
 #include <linux/fd.h>
 #endif
+#ifdef __FreeBSD__
+#include <sys/disk.h>
+#endif
 
 //#define DEBUG_FLOPPY
 
@@ -247,6 +252,17 @@ void qemu_aio_poll(void)
  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;
 
@@ -822,11 +838,12 @@ BlockDriver bdrv_host_device = {
 
 #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 {
@@ -876,23 +893,8 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
     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;
@@ -905,15 +907,20 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
         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;
 }
 
@@ -961,6 +968,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
     return ret_count;
 }
 
+#if 0
 #ifndef QEMU_TOOL
 static void raw_aio_cb(void *opaque)
 {
@@ -1063,10 +1071,12 @@ static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
     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)
@@ -1089,22 +1099,33 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
     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;
@@ -1138,12 +1159,19 @@ void qemu_aio_poll(void)
 {
 }
 
+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)
@@ -1182,7 +1210,7 @@ static int find_cdrom(char *cdrom_name, int cdrom_name_size)
     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);
@@ -1197,16 +1225,18 @@ static int find_cdrom(char *cdrom_name, int cdrom_name_size)
     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
@@ -1222,7 +1252,6 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
     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)
@@ -1237,8 +1266,8 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
             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 {
@@ -1247,15 +1276,20 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
     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;
 }