Statistics
| Branch: | Revision:

root / block-raw.c @ a50a6282

History | View | Annotate | Download (35 kB)

1
/*
2
 * Block driver for RAW files
3
 *
4
 * Copyright (c) 2006 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25
#include "block_int.h"
26
#include <assert.h>
27
#ifndef _WIN32
28
#include <aio.h>
29

    
30
#ifndef QEMU_TOOL
31
#include "exec-all.h"
32
#endif
33

    
34
#ifdef CONFIG_COCOA
35
#include <paths.h>
36
#include <sys/param.h>
37
#include <IOKit/IOKitLib.h>
38
#include <IOKit/IOBSD.h>
39
#include <IOKit/storage/IOMediaBSDClient.h>
40
#include <IOKit/storage/IOMedia.h>
41
#include <IOKit/storage/IOCDMedia.h>
42
//#include <IOKit/storage/IOCDTypes.h>
43
#include <CoreFoundation/CoreFoundation.h>
44
#endif
45

    
46
#ifdef __sun__
47
#define _POSIX_PTHREAD_SEMANTICS 1
48
#include <signal.h>
49
#include <sys/dkio.h>
50
#endif
51
#ifdef __linux__
52
#include <sys/ioctl.h>
53
#include <linux/cdrom.h>
54
#include <linux/fd.h>
55
#endif
56
#ifdef __FreeBSD__
57
#include <sys/disk.h>
58
#endif
59

    
60
//#define DEBUG_FLOPPY
61

    
62
#define DEBUG_BLOCK
63
#if defined(DEBUG_BLOCK) && !defined(QEMU_TOOL)
64
#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)        \
65
    { fprintf(stderr, formatCstr, ##args); fflush(stderr); } } while (0)
66
#else
67
#define DEBUG_BLOCK_PRINT(formatCstr, args...)
68
#endif
69

    
70
#define FTYPE_FILE   0
71
#define FTYPE_CD     1
72
#define FTYPE_FD     2
73

    
74
/* if the FD is not accessed during that time (in ms), we try to
75
   reopen it to see if the disk has been changed */
76
#define FD_OPEN_TIMEOUT 1000
77

    
78
typedef struct BDRVRawState {
79
    int fd;
80
    int type;
81
    unsigned int lseek_err_cnt;
82
#if defined(__linux__)
83
    /* linux floppy specific */
84
    int fd_open_flags;
85
    int64_t fd_open_time;
86
    int64_t fd_error_time;
87
    int fd_got_error;
88
    int fd_media_changed;
89
#endif
90
} BDRVRawState;
91

    
92
static int fd_open(BlockDriverState *bs);
93

    
94
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
95
{
96
    BDRVRawState *s = bs->opaque;
97
    int fd, open_flags, ret;
98

    
99
    s->lseek_err_cnt = 0;
100

    
101
    open_flags = O_BINARY;
102
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
103
        open_flags |= O_RDWR;
104
    } else {
105
        open_flags |= O_RDONLY;
106
        bs->read_only = 1;
107
    }
108
    if (flags & BDRV_O_CREAT)
109
        open_flags |= O_CREAT | O_TRUNC;
110

    
111
    s->type = FTYPE_FILE;
112

    
113
    fd = open(filename, open_flags, 0644);
114
    if (fd < 0) {
115
        ret = -errno;
116
        if (ret == -EROFS)
117
            ret = -EACCES;
118
        return ret;
119
    }
120
    s->fd = fd;
121
    return 0;
122
}
123

    
124
/* XXX: use host sector size if necessary with:
125
#ifdef DIOCGSECTORSIZE
126
        {
127
            unsigned int sectorsize = 512;
128
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
129
                sectorsize > bufsize)
130
                bufsize = sectorsize;
131
        }
132
#endif
133
#ifdef CONFIG_COCOA
134
        u_int32_t   blockSize = 512;
135
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
136
            bufsize = blockSize;
137
        }
138
#endif
139
*/
140

    
141
static int raw_pread(BlockDriverState *bs, int64_t offset,
142
                     uint8_t *buf, int count)
143
{
144
    BDRVRawState *s = bs->opaque;
145
    int ret;
146

    
147
    ret = fd_open(bs);
148
    if (ret < 0)
149
        return ret;
150

    
151
    if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
152
        ++(s->lseek_err_cnt);
153
        if(s->lseek_err_cnt <= 10) {
154
            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
155
                              s->fd, bs->filename, offset, buf, count,
156
                              bs->total_sectors, errno, strerror(errno));
157
        }
158
        return -1;
159
    }
160
    s->lseek_err_cnt=0;
161

    
162
    ret = read(s->fd, buf, count);
163
    if (ret == count)
164
        goto label__raw_read__success;
165

    
166
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] read failed %d : %d = %s\n",
167
                      s->fd, bs->filename, offset, buf, count,
168
                      bs->total_sectors, ret, errno, strerror(errno));
169

    
170
    /* Try harder for CDrom. */
171
    if (bs->type == BDRV_TYPE_CDROM) {
172
        lseek(s->fd, offset, SEEK_SET);
173
        ret = read(s->fd, buf, count);
174
        if (ret == count)
175
            goto label__raw_read__success;
176
        lseek(s->fd, offset, SEEK_SET);
177
        ret = read(s->fd, buf, count);
178
        if (ret == count)
179
            goto label__raw_read__success;
180

    
181
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] retry read failed %d : %d = %s\n",
182
                          s->fd, bs->filename, offset, buf, count,
183
                          bs->total_sectors, ret, errno, strerror(errno));
184
    }
185

    
186
label__raw_read__success:
187

    
188
    return ret;
189
}
190

    
191
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
192
                      const uint8_t *buf, int count)
193
{
194
    BDRVRawState *s = bs->opaque;
195
    int ret;
196

    
197
    ret = fd_open(bs);
198
    if (ret < 0)
199
        return ret;
200

    
201
    if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
202
        ++(s->lseek_err_cnt);
203
        if(s->lseek_err_cnt) {
204
            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
205
                              s->fd, bs->filename, offset, buf, count,
206
                              bs->total_sectors, errno, strerror(errno));
207
        }
208
        return -1;
209
    }
210
    s->lseek_err_cnt = 0;
211

    
212
    ret = write(s->fd, buf, count);
213
    if (ret == count)
214
        goto label__raw_write__success;
215

    
216
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] write failed %d : %d = %s\n",
217
                      s->fd, bs->filename, offset, buf, count,
218
                      bs->total_sectors, ret, errno, strerror(errno));
219

    
220
label__raw_write__success:
221

    
222
    return ret;
223
}
224

    
225
/***********************************************************/
226
/* Unix AIO using POSIX AIO */
227

    
228
typedef struct RawAIOCB {
229
    BlockDriverAIOCB common;
230
    struct aiocb aiocb;
231
    struct RawAIOCB *next;
232
} RawAIOCB;
233

    
234
static int aio_sig_num = SIGUSR2;
235
static RawAIOCB *first_aio; /* AIO issued */
236
static int aio_initialized = 0;
237

    
238
static void aio_signal_handler(int signum)
239
{
240
#ifndef QEMU_TOOL
241
    CPUState *env = cpu_single_env;
242
    if (env) {
243
        /* stop the currently executing cpu because a timer occured */
244
        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
245
#ifdef USE_KQEMU
246
        if (env->kqemu_enabled) {
247
            kqemu_cpu_interrupt(env);
248
        }
249
#endif
250
    }
251
#endif
252
}
253

    
254
void qemu_aio_init(void)
255
{
256
    struct sigaction act;
257

    
258
    aio_initialized = 1;
259

    
260
    sigfillset(&act.sa_mask);
261
    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
262
    act.sa_handler = aio_signal_handler;
263
    sigaction(aio_sig_num, &act, NULL);
264

    
265
#if defined(__GLIBC__) && defined(__linux__)
266
    {
267
        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
268
           seems to fix the problem. */
269
        struct aioinit ai;
270
        memset(&ai, 0, sizeof(ai));
271
        ai.aio_threads = 1;
272
        ai.aio_num = 1;
273
        ai.aio_idle_time = 365 * 100000;
274
        aio_init(&ai);
275
    }
276
#endif
277
}
278

    
279
void qemu_aio_poll(void)
280
{
281
    RawAIOCB *acb, **pacb;
282
    int ret;
283

    
284
    for(;;) {
285
        pacb = &first_aio;
286
        for(;;) {
287
            acb = *pacb;
288
            if (!acb)
289
                goto the_end;
290
            ret = aio_error(&acb->aiocb);
291
            if (ret == ECANCELED) {
292
                /* remove the request */
293
                *pacb = acb->next;
294
                qemu_aio_release(acb);
295
            } else if (ret != EINPROGRESS) {
296
                /* end of aio */
297
                if (ret == 0) {
298
                    ret = aio_return(&acb->aiocb);
299
                    if (ret == acb->aiocb.aio_nbytes)
300
                        ret = 0;
301
                    else
302
                        ret = -EINVAL;
303
                } else {
304
                    ret = -ret;
305
                }
306
                /* remove the request */
307
                *pacb = acb->next;
308
                /* call the callback */
309
                acb->common.cb(acb->common.opaque, ret);
310
                qemu_aio_release(acb);
311
                break;
312
            } else {
313
                pacb = &acb->next;
314
            }
315
        }
316
    }
317
 the_end: ;
318
}
319

    
320
/* Wait for all IO requests to complete.  */
321
void qemu_aio_flush(void)
322
{
323
    qemu_aio_wait_start();
324
    qemu_aio_poll();
325
    while (first_aio) {
326
        qemu_aio_wait();
327
    }
328
    qemu_aio_wait_end();
329
}
330

    
331
/* wait until at least one AIO was handled */
332
static sigset_t wait_oset;
333

    
334
void qemu_aio_wait_start(void)
335
{
336
    sigset_t set;
337

    
338
    if (!aio_initialized)
339
        qemu_aio_init();
340
    sigemptyset(&set);
341
    sigaddset(&set, aio_sig_num);
342
    sigprocmask(SIG_BLOCK, &set, &wait_oset);
343
}
344

    
345
void qemu_aio_wait(void)
346
{
347
    sigset_t set;
348
    int nb_sigs;
349

    
350
#ifndef QEMU_TOOL
351
    if (qemu_bh_poll())
352
        return;
353
#endif
354
    sigemptyset(&set);
355
    sigaddset(&set, aio_sig_num);
356
    sigwait(&set, &nb_sigs);
357
    qemu_aio_poll();
358
}
359

    
360
void qemu_aio_wait_end(void)
361
{
362
    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
363
}
364

    
365
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
366
        int64_t sector_num, uint8_t *buf, int nb_sectors,
367
        BlockDriverCompletionFunc *cb, void *opaque)
368
{
369
    BDRVRawState *s = bs->opaque;
370
    RawAIOCB *acb;
371

    
372
    if (fd_open(bs) < 0)
373
        return NULL;
374

    
375
    acb = qemu_aio_get(bs, cb, opaque);
376
    if (!acb)
377
        return NULL;
378
    acb->aiocb.aio_fildes = s->fd;
379
    acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
380
    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
381
    acb->aiocb.aio_buf = buf;
382
    acb->aiocb.aio_nbytes = nb_sectors * 512;
383
    acb->aiocb.aio_offset = sector_num * 512;
384
    acb->next = first_aio;
385
    first_aio = acb;
386
    return acb;
387
}
388

    
389
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
390
        int64_t sector_num, uint8_t *buf, int nb_sectors,
391
        BlockDriverCompletionFunc *cb, void *opaque)
392
{
393
    RawAIOCB *acb;
394

    
395
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
396
    if (!acb)
397
        return NULL;
398
    if (aio_read(&acb->aiocb) < 0) {
399
        qemu_aio_release(acb);
400
        return NULL;
401
    }
402
    return &acb->common;
403
}
404

    
405
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
406
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
407
        BlockDriverCompletionFunc *cb, void *opaque)
408
{
409
    RawAIOCB *acb;
410

    
411
    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
412
    if (!acb)
413
        return NULL;
414
    if (aio_write(&acb->aiocb) < 0) {
415
        qemu_aio_release(acb);
416
        return NULL;
417
    }
418
    return &acb->common;
419
}
420

    
421
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
422
{
423
    int ret;
424
    RawAIOCB *acb = (RawAIOCB *)blockacb;
425
    RawAIOCB **pacb;
426

    
427
    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
428
    if (ret == AIO_NOTCANCELED) {
429
        /* fail safe: if the aio could not be canceled, we wait for
430
           it */
431
        while (aio_error(&acb->aiocb) == EINPROGRESS);
432
    }
433

    
434
    /* remove the callback from the queue */
435
    pacb = &first_aio;
436
    for(;;) {
437
        if (*pacb == NULL) {
438
            break;
439
        } else if (*pacb == acb) {
440
            *pacb = acb->next;
441
            qemu_aio_release(acb);
442
            break;
443
        }
444
        pacb = &acb->next;
445
    }
446
}
447

    
448
static void raw_close(BlockDriverState *bs)
449
{
450
    BDRVRawState *s = bs->opaque;
451
    if (s->fd >= 0) {
452
        close(s->fd);
453
        s->fd = -1;
454
    }
455
}
456

    
457
static int raw_truncate(BlockDriverState *bs, int64_t offset)
458
{
459
    BDRVRawState *s = bs->opaque;
460
    if (s->type != FTYPE_FILE)
461
        return -ENOTSUP;
462
    if (ftruncate(s->fd, offset) < 0)
463
        return -errno;
464
    return 0;
465
}
466

    
467
static int64_t  raw_getlength(BlockDriverState *bs)
468
{
469
    BDRVRawState *s = bs->opaque;
470
    int fd = s->fd;
471
    int64_t size;
472
#ifdef _BSD
473
    struct stat sb;
474
#endif
475
#ifdef __sun__
476
    struct dk_minfo minfo;
477
    int rv;
478
#endif
479
    int ret;
480

    
481
    ret = fd_open(bs);
482
    if (ret < 0)
483
        return ret;
484

    
485
#ifdef _BSD
486
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
487
#ifdef DIOCGMEDIASIZE
488
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
489
#endif
490
#ifdef CONFIG_COCOA
491
        size = LONG_LONG_MAX;
492
#else
493
        size = lseek(fd, 0LL, SEEK_END);
494
#endif
495
    } else
496
#endif
497
#ifdef __sun__
498
    /*
499
     * use the DKIOCGMEDIAINFO ioctl to read the size.
500
     */
501
    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
502
    if ( rv != -1 ) {
503
        size = minfo.dki_lbsize * minfo.dki_capacity;
504
    } else /* there are reports that lseek on some devices
505
              fails, but irc discussion said that contingency
506
              on contingency was overkill */
507
#endif
508
    {
509
        size = lseek(fd, 0, SEEK_END);
510
    }
511
    return size;
512
}
513

    
514
static int raw_create(const char *filename, int64_t total_size,
515
                      const char *backing_file, int flags)
516
{
517
    int fd;
518

    
519
    if (flags || backing_file)
520
        return -ENOTSUP;
521

    
522
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
523
              0644);
524
    if (fd < 0)
525
        return -EIO;
526
    ftruncate(fd, total_size * 512);
527
    close(fd);
528
    return 0;
529
}
530

    
531
static void raw_flush(BlockDriverState *bs)
532
{
533
    BDRVRawState *s = bs->opaque;
534
    fsync(s->fd);
535
}
536

    
537
BlockDriver bdrv_raw = {
538
    "raw",
539
    sizeof(BDRVRawState),
540
    NULL, /* no probe for protocols */
541
    raw_open,
542
    NULL,
543
    NULL,
544
    raw_close,
545
    raw_create,
546
    raw_flush,
547

    
548
    .bdrv_aio_read = raw_aio_read,
549
    .bdrv_aio_write = raw_aio_write,
550
    .bdrv_aio_cancel = raw_aio_cancel,
551
    .aiocb_size = sizeof(RawAIOCB),
552
    .protocol_name = "file",
553
    .bdrv_pread = raw_pread,
554
    .bdrv_pwrite = raw_pwrite,
555
    .bdrv_truncate = raw_truncate,
556
    .bdrv_getlength = raw_getlength,
557
};
558

    
559
/***********************************************/
560
/* host device */
561

    
562
#ifdef CONFIG_COCOA
563
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
564
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
565

    
566
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
567
{
568
    kern_return_t       kernResult;
569
    mach_port_t     masterPort;
570
    CFMutableDictionaryRef  classesToMatch;
571

    
572
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
573
    if ( KERN_SUCCESS != kernResult ) {
574
        printf( "IOMasterPort returned %d\n", kernResult );
575
    }
576

    
577
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
578
    if ( classesToMatch == NULL ) {
579
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
580
    } else {
581
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
582
    }
583
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
584
    if ( KERN_SUCCESS != kernResult )
585
    {
586
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
587
    }
588

    
589
    return kernResult;
590
}
591

    
592
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
593
{
594
    io_object_t     nextMedia;
595
    kern_return_t   kernResult = KERN_FAILURE;
596
    *bsdPath = '\0';
597
    nextMedia = IOIteratorNext( mediaIterator );
598
    if ( nextMedia )
599
    {
600
        CFTypeRef   bsdPathAsCFString;
601
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
602
        if ( bsdPathAsCFString ) {
603
            size_t devPathLength;
604
            strcpy( bsdPath, _PATH_DEV );
605
            strcat( bsdPath, "r" );
606
            devPathLength = strlen( bsdPath );
607
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
608
                kernResult = KERN_SUCCESS;
609
            }
610
            CFRelease( bsdPathAsCFString );
611
        }
612
        IOObjectRelease( nextMedia );
613
    }
614

    
615
    return kernResult;
616
}
617

    
618
#endif
619

    
620
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
621
{
622
    BDRVRawState *s = bs->opaque;
623
    int fd, open_flags, ret;
624

    
625
#ifdef CONFIG_COCOA
626
    if (strstart(filename, "/dev/cdrom", NULL)) {
627
        kern_return_t kernResult;
628
        io_iterator_t mediaIterator;
629
        char bsdPath[ MAXPATHLEN ];
630
        int fd;
631

    
632
        kernResult = FindEjectableCDMedia( &mediaIterator );
633
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
634

    
635
        if ( bsdPath[ 0 ] != '\0' ) {
636
            strcat(bsdPath,"s0");
637
            /* some CDs don't have a partition 0 */
638
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
639
            if (fd < 0) {
640
                bsdPath[strlen(bsdPath)-1] = '1';
641
            } else {
642
                close(fd);
643
            }
644
            filename = bsdPath;
645
        }
646

    
647
        if ( mediaIterator )
648
            IOObjectRelease( mediaIterator );
649
    }
650
#endif
651
    open_flags = O_BINARY;
652
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
653
        open_flags |= O_RDWR;
654
    } else {
655
        open_flags |= O_RDONLY;
656
        bs->read_only = 1;
657
    }
658

    
659
    s->type = FTYPE_FILE;
660
#if defined(__linux__)
661
    if (strstart(filename, "/dev/cd", NULL)) {
662
        /* open will not fail even if no CD is inserted */
663
        open_flags |= O_NONBLOCK;
664
        s->type = FTYPE_CD;
665
    } else if (strstart(filename, "/dev/fd", NULL)) {
666
        s->type = FTYPE_FD;
667
        s->fd_open_flags = open_flags;
668
        /* open will not fail even if no floppy is inserted */
669
        open_flags |= O_NONBLOCK;
670
    }
671
#endif
672
    fd = open(filename, open_flags, 0644);
673
    if (fd < 0) {
674
        ret = -errno;
675
        if (ret == -EROFS)
676
            ret = -EACCES;
677
        return ret;
678
    }
679
    s->fd = fd;
680
#if defined(__linux__)
681
    /* close fd so that we can reopen it as needed */
682
    if (s->type == FTYPE_FD) {
683
        close(s->fd);
684
        s->fd = -1;
685
        s->fd_media_changed = 1;
686
    }
687
#endif
688
    return 0;
689
}
690

    
691
#if defined(__linux__) && !defined(QEMU_TOOL)
692

    
693
/* Note: we do not have a reliable method to detect if the floppy is
694
   present. The current method is to try to open the floppy at every
695
   I/O and to keep it opened during a few hundreds of ms. */
696
static int fd_open(BlockDriverState *bs)
697
{
698
    BDRVRawState *s = bs->opaque;
699
    int last_media_present;
700

    
701
    if (s->type != FTYPE_FD)
702
        return 0;
703
    last_media_present = (s->fd >= 0);
704
    if (s->fd >= 0 &&
705
        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
706
        close(s->fd);
707
        s->fd = -1;
708
#ifdef DEBUG_FLOPPY
709
        printf("Floppy closed\n");
710
#endif
711
    }
712
    if (s->fd < 0) {
713
        if (s->fd_got_error &&
714
            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
715
#ifdef DEBUG_FLOPPY
716
            printf("No floppy (open delayed)\n");
717
#endif
718
            return -EIO;
719
        }
720
        s->fd = open(bs->filename, s->fd_open_flags);
721
        if (s->fd < 0) {
722
            s->fd_error_time = qemu_get_clock(rt_clock);
723
            s->fd_got_error = 1;
724
            if (last_media_present)
725
                s->fd_media_changed = 1;
726
#ifdef DEBUG_FLOPPY
727
            printf("No floppy\n");
728
#endif
729
            return -EIO;
730
        }
731
#ifdef DEBUG_FLOPPY
732
        printf("Floppy opened\n");
733
#endif
734
    }
735
    if (!last_media_present)
736
        s->fd_media_changed = 1;
737
    s->fd_open_time = qemu_get_clock(rt_clock);
738
    s->fd_got_error = 0;
739
    return 0;
740
}
741
#else
742
static int fd_open(BlockDriverState *bs)
743
{
744
    return 0;
745
}
746
#endif
747

    
748
#if defined(__linux__)
749

    
750
static int raw_is_inserted(BlockDriverState *bs)
751
{
752
    BDRVRawState *s = bs->opaque;
753
    int ret;
754

    
755
    switch(s->type) {
756
    case FTYPE_CD:
757
        ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
758
        if (ret == CDS_DISC_OK)
759
            return 1;
760
        else
761
            return 0;
762
        break;
763
    case FTYPE_FD:
764
        ret = fd_open(bs);
765
        return (ret >= 0);
766
    default:
767
        return 1;
768
    }
769
}
770

    
771
/* currently only used by fdc.c, but a CD version would be good too */
772
static int raw_media_changed(BlockDriverState *bs)
773
{
774
    BDRVRawState *s = bs->opaque;
775

    
776
    switch(s->type) {
777
    case FTYPE_FD:
778
        {
779
            int ret;
780
            /* XXX: we do not have a true media changed indication. It
781
               does not work if the floppy is changed without trying
782
               to read it */
783
            fd_open(bs);
784
            ret = s->fd_media_changed;
785
            s->fd_media_changed = 0;
786
#ifdef DEBUG_FLOPPY
787
            printf("Floppy changed=%d\n", ret);
788
#endif
789
            return ret;
790
        }
791
    default:
792
        return -ENOTSUP;
793
    }
794
}
795

    
796
static int raw_eject(BlockDriverState *bs, int eject_flag)
797
{
798
    BDRVRawState *s = bs->opaque;
799

    
800
    switch(s->type) {
801
    case FTYPE_CD:
802
        if (eject_flag) {
803
            if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
804
                perror("CDROMEJECT");
805
        } else {
806
            if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
807
                perror("CDROMEJECT");
808
        }
809
        break;
810
    case FTYPE_FD:
811
        {
812
            int fd;
813
            if (s->fd >= 0) {
814
                close(s->fd);
815
                s->fd = -1;
816
            }
817
            fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
818
            if (fd >= 0) {
819
                if (ioctl(fd, FDEJECT, 0) < 0)
820
                    perror("FDEJECT");
821
                close(fd);
822
            }
823
        }
824
        break;
825
    default:
826
        return -ENOTSUP;
827
    }
828
    return 0;
829
}
830

    
831
static int raw_set_locked(BlockDriverState *bs, int locked)
832
{
833
    BDRVRawState *s = bs->opaque;
834

    
835
    switch(s->type) {
836
    case FTYPE_CD:
837
        if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
838
            /* Note: an error can happen if the distribution automatically
839
               mounts the CD-ROM */
840
            //        perror("CDROM_LOCKDOOR");
841
        }
842
        break;
843
    default:
844
        return -ENOTSUP;
845
    }
846
    return 0;
847
}
848

    
849
#else
850

    
851
static int raw_is_inserted(BlockDriverState *bs)
852
{
853
    return 1;
854
}
855

    
856
static int raw_media_changed(BlockDriverState *bs)
857
{
858
    return -ENOTSUP;
859
}
860

    
861
static int raw_eject(BlockDriverState *bs, int eject_flag)
862
{
863
    return -ENOTSUP;
864
}
865

    
866
static int raw_set_locked(BlockDriverState *bs, int locked)
867
{
868
    return -ENOTSUP;
869
}
870

    
871
#endif /* !linux */
872

    
873
BlockDriver bdrv_host_device = {
874
    "host_device",
875
    sizeof(BDRVRawState),
876
    NULL, /* no probe for protocols */
877
    hdev_open,
878
    NULL,
879
    NULL,
880
    raw_close,
881
    NULL,
882
    raw_flush,
883

    
884
    .bdrv_aio_read = raw_aio_read,
885
    .bdrv_aio_write = raw_aio_write,
886
    .bdrv_aio_cancel = raw_aio_cancel,
887
    .aiocb_size = sizeof(RawAIOCB),
888
    .bdrv_pread = raw_pread,
889
    .bdrv_pwrite = raw_pwrite,
890
    .bdrv_getlength = raw_getlength,
891

    
892
    /* removable device support */
893
    .bdrv_is_inserted = raw_is_inserted,
894
    .bdrv_media_changed = raw_media_changed,
895
    .bdrv_eject = raw_eject,
896
    .bdrv_set_locked = raw_set_locked,
897
};
898

    
899
#else /* _WIN32 */
900

    
901
/* XXX: use another file ? */
902
#include <winioctl.h>
903

    
904
#define FTYPE_FILE 0
905
#define FTYPE_CD     1
906
#define FTYPE_HARDDISK 2
907

    
908
typedef struct BDRVRawState {
909
    HANDLE hfile;
910
    int type;
911
    char drive_path[16]; /* format: "d:\" */
912
} BDRVRawState;
913

    
914
typedef struct RawAIOCB {
915
    BlockDriverAIOCB common;
916
    HANDLE hEvent;
917
    OVERLAPPED ov;
918
    int count;
919
} RawAIOCB;
920

    
921
int qemu_ftruncate64(int fd, int64_t length)
922
{
923
    LARGE_INTEGER li;
924
    LONG high;
925
    HANDLE h;
926
    BOOL res;
927

    
928
    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
929
        return -1;
930

    
931
    h = (HANDLE)_get_osfhandle(fd);
932

    
933
    /* get current position, ftruncate do not change position */
934
    li.HighPart = 0;
935
    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
936
    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
937
        return -1;
938

    
939
    high = length >> 32;
940
    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
941
        return -1;
942
    res = SetEndOfFile(h);
943

    
944
    /* back to old position */
945
    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
946
    return res ? 0 : -1;
947
}
948

    
949
static int set_sparse(int fd)
950
{
951
    DWORD returned;
952
    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
953
                                 NULL, 0, NULL, 0, &returned, NULL);
954
}
955

    
956
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
957
{
958
    BDRVRawState *s = bs->opaque;
959
    int access_flags, create_flags;
960
    DWORD overlapped;
961

    
962
    s->type = FTYPE_FILE;
963

    
964
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
965
        access_flags = GENERIC_READ | GENERIC_WRITE;
966
    } else {
967
        access_flags = GENERIC_READ;
968
    }
969
    if (flags & BDRV_O_CREAT) {
970
        create_flags = CREATE_ALWAYS;
971
    } else {
972
        create_flags = OPEN_EXISTING;
973
    }
974
#ifdef QEMU_TOOL
975
    overlapped = FILE_ATTRIBUTE_NORMAL;
976
#else
977
    overlapped = FILE_FLAG_OVERLAPPED;
978
#endif
979
    s->hfile = CreateFile(filename, access_flags,
980
                          FILE_SHARE_READ, NULL,
981
                          create_flags, overlapped, NULL);
982
    if (s->hfile == INVALID_HANDLE_VALUE) {
983
        int err = GetLastError();
984

    
985
        if (err == ERROR_ACCESS_DENIED)
986
            return -EACCES;
987
        return -1;
988
    }
989
    return 0;
990
}
991

    
992
static int raw_pread(BlockDriverState *bs, int64_t offset,
993
                     uint8_t *buf, int count)
994
{
995
    BDRVRawState *s = bs->opaque;
996
    OVERLAPPED ov;
997
    DWORD ret_count;
998
    int ret;
999

    
1000
    memset(&ov, 0, sizeof(ov));
1001
    ov.Offset = offset;
1002
    ov.OffsetHigh = offset >> 32;
1003
    ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
1004
    if (!ret) {
1005
        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
1006
        if (!ret)
1007
            return -EIO;
1008
        else
1009
            return ret_count;
1010
    }
1011
    return ret_count;
1012
}
1013

    
1014
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
1015
                      const uint8_t *buf, int count)
1016
{
1017
    BDRVRawState *s = bs->opaque;
1018
    OVERLAPPED ov;
1019
    DWORD ret_count;
1020
    int ret;
1021

    
1022
    memset(&ov, 0, sizeof(ov));
1023
    ov.Offset = offset;
1024
    ov.OffsetHigh = offset >> 32;
1025
    ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
1026
    if (!ret) {
1027
        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
1028
        if (!ret)
1029
            return -EIO;
1030
        else
1031
            return ret_count;
1032
    }
1033
    return ret_count;
1034
}
1035

    
1036
#if 0
1037
#ifndef QEMU_TOOL
1038
static void raw_aio_cb(void *opaque)
1039
{
1040
    RawAIOCB *acb = opaque;
1041
    BlockDriverState *bs = acb->common.bs;
1042
    BDRVRawState *s = bs->opaque;
1043
    DWORD ret_count;
1044
    int ret;
1045

1046
    ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
1047
    if (!ret || ret_count != acb->count) {
1048
        acb->common.cb(acb->common.opaque, -EIO);
1049
    } else {
1050
        acb->common.cb(acb->common.opaque, 0);
1051
    }
1052
}
1053
#endif
1054

    
1055
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
1056
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1057
        BlockDriverCompletionFunc *cb, void *opaque)
1058
{
1059
    RawAIOCB *acb;
1060
    int64_t offset;
1061

    
1062
    acb = qemu_aio_get(bs, cb, opaque);
1063
    if (acb->hEvent) {
1064
        acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1065
        if (!acb->hEvent) {
1066
            qemu_aio_release(acb);
1067
            return NULL;
1068
        }
1069
    }
1070
    memset(&acb->ov, 0, sizeof(acb->ov));
1071
    offset = sector_num * 512;
1072
    acb->ov.Offset = offset;
1073
    acb->ov.OffsetHigh = offset >> 32;
1074
    acb->ov.hEvent = acb->hEvent;
1075
    acb->count = nb_sectors * 512;
1076
#ifndef QEMU_TOOL
1077
    qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
1078
#endif
1079
    return acb;
1080
}
1081

    
1082
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
1083
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1084
        BlockDriverCompletionFunc *cb, void *opaque)
1085
{
1086
    BDRVRawState *s = bs->opaque;
1087
    RawAIOCB *acb;
1088
    int ret;
1089

    
1090
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
1091
    if (!acb)
1092
        return NULL;
1093
    ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
1094
    if (!ret) {
1095
        qemu_aio_release(acb);
1096
        return NULL;
1097
    }
1098
#ifdef QEMU_TOOL
1099
    qemu_aio_release(acb);
1100
#endif
1101
    return (BlockDriverAIOCB *)acb;
1102
}
1103

    
1104
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
1105
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1106
        BlockDriverCompletionFunc *cb, void *opaque)
1107
{
1108
    BDRVRawState *s = bs->opaque;
1109
    RawAIOCB *acb;
1110
    int ret;
1111

    
1112
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
1113
    if (!acb)
1114
        return NULL;
1115
    ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
1116
    if (!ret) {
1117
        qemu_aio_release(acb);
1118
        return NULL;
1119
    }
1120
#ifdef QEMU_TOOL
1121
    qemu_aio_release(acb);
1122
#endif
1123
    return (BlockDriverAIOCB *)acb;
1124
}
1125

    
1126
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
1127
{
1128
#ifndef QEMU_TOOL
1129
    RawAIOCB *acb = (RawAIOCB *)blockacb;
1130
    BlockDriverState *bs = acb->common.bs;
1131
    BDRVRawState *s = bs->opaque;
1132

    
1133
    qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
1134
    /* XXX: if more than one async I/O it is not correct */
1135
    CancelIo(s->hfile);
1136
    qemu_aio_release(acb);
1137
#endif
1138
}
1139
#endif /* #if 0 */
1140

    
1141
static void raw_flush(BlockDriverState *bs)
1142
{
1143
    BDRVRawState *s = bs->opaque;
1144
    FlushFileBuffers(s->hfile);
1145
}
1146

    
1147
static void raw_close(BlockDriverState *bs)
1148
{
1149
    BDRVRawState *s = bs->opaque;
1150
    CloseHandle(s->hfile);
1151
}
1152

    
1153
static int raw_truncate(BlockDriverState *bs, int64_t offset)
1154
{
1155
    BDRVRawState *s = bs->opaque;
1156
    DWORD low, high;
1157

    
1158
    low = offset;
1159
    high = offset >> 32;
1160
    if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
1161
        return -EIO;
1162
    if (!SetEndOfFile(s->hfile))
1163
        return -EIO;
1164
    return 0;
1165
}
1166

    
1167
static int64_t raw_getlength(BlockDriverState *bs)
1168
{
1169
    BDRVRawState *s = bs->opaque;
1170
    LARGE_INTEGER l;
1171
    ULARGE_INTEGER available, total, total_free;
1172
    DISK_GEOMETRY dg;
1173
    DWORD count;
1174
    BOOL status;
1175

    
1176
    switch(s->type) {
1177
    case FTYPE_FILE:
1178
        l.LowPart = GetFileSize(s->hfile, &l.HighPart);
1179
        if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
1180
            return -EIO;
1181
        break;
1182
    case FTYPE_CD:
1183
        if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
1184
            return -EIO;
1185
        l.QuadPart = total.QuadPart;
1186
        break;
1187
    case FTYPE_HARDDISK:
1188
        status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
1189
                                 NULL, 0, &dg, sizeof(dg), &count, NULL);
1190
        if (status != FALSE) {
1191
            l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
1192
                * dg.SectorsPerTrack * dg.BytesPerSector;
1193
        }
1194
        break;
1195
    default:
1196
        return -EIO;
1197
    }
1198
    return l.QuadPart;
1199
}
1200

    
1201
static int raw_create(const char *filename, int64_t total_size,
1202
                      const char *backing_file, int flags)
1203
{
1204
    int fd;
1205

    
1206
    if (flags || backing_file)
1207
        return -ENOTSUP;
1208

    
1209
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
1210
              0644);
1211
    if (fd < 0)
1212
        return -EIO;
1213
    set_sparse(fd);
1214
    ftruncate(fd, total_size * 512);
1215
    close(fd);
1216
    return 0;
1217
}
1218

    
1219
void qemu_aio_init(void)
1220
{
1221
}
1222

    
1223
void qemu_aio_poll(void)
1224
{
1225
}
1226

    
1227
void qemu_aio_flush(void)
1228
{
1229
}
1230

    
1231
void qemu_aio_wait_start(void)
1232
{
1233
}
1234

    
1235
void qemu_aio_wait(void)
1236
{
1237
#ifndef QEMU_TOOL
1238
    qemu_bh_poll();
1239
#endif
1240
}
1241

    
1242
void qemu_aio_wait_end(void)
1243
{
1244
}
1245

    
1246
BlockDriver bdrv_raw = {
1247
    "raw",
1248
    sizeof(BDRVRawState),
1249
    NULL, /* no probe for protocols */
1250
    raw_open,
1251
    NULL,
1252
    NULL,
1253
    raw_close,
1254
    raw_create,
1255
    raw_flush,
1256

    
1257
#if 0
1258
    .bdrv_aio_read = raw_aio_read,
1259
    .bdrv_aio_write = raw_aio_write,
1260
    .bdrv_aio_cancel = raw_aio_cancel,
1261
    .aiocb_size = sizeof(RawAIOCB);
1262
#endif
1263
    .protocol_name = "file",
1264
    .bdrv_pread = raw_pread,
1265
    .bdrv_pwrite = raw_pwrite,
1266
    .bdrv_truncate = raw_truncate,
1267
    .bdrv_getlength = raw_getlength,
1268
};
1269

    
1270
/***********************************************/
1271
/* host device */
1272

    
1273
static int find_cdrom(char *cdrom_name, int cdrom_name_size)
1274
{
1275
    char drives[256], *pdrv = drives;
1276
    UINT type;
1277

    
1278
    memset(drives, 0, sizeof(drives));
1279
    GetLogicalDriveStrings(sizeof(drives), drives);
1280
    while(pdrv[0] != '\0') {
1281
        type = GetDriveType(pdrv);
1282
        switch(type) {
1283
        case DRIVE_CDROM:
1284
            snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
1285
            return 0;
1286
            break;
1287
        }
1288
        pdrv += lstrlen(pdrv) + 1;
1289
    }
1290
    return -1;
1291
}
1292

    
1293
static int find_device_type(BlockDriverState *bs, const char *filename)
1294
{
1295
    BDRVRawState *s = bs->opaque;
1296
    UINT type;
1297
    const char *p;
1298

    
1299
    if (strstart(filename, "\\\\.\\", &p) ||
1300
        strstart(filename, "//./", &p)) {
1301
        if (stristart(p, "PhysicalDrive", NULL))
1302
            return FTYPE_HARDDISK;
1303
        snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
1304
        type = GetDriveType(s->drive_path);
1305
        if (type == DRIVE_CDROM)
1306
            return FTYPE_CD;
1307
        else
1308
            return FTYPE_FILE;
1309
    } else {
1310
        return FTYPE_FILE;
1311
    }
1312
}
1313

    
1314
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
1315
{
1316
    BDRVRawState *s = bs->opaque;
1317
    int access_flags, create_flags;
1318
    DWORD overlapped;
1319
    char device_name[64];
1320

    
1321
    if (strstart(filename, "/dev/cdrom", NULL)) {
1322
        if (find_cdrom(device_name, sizeof(device_name)) < 0)
1323
            return -ENOENT;
1324
        filename = device_name;
1325
    } else {
1326
        /* transform drive letters into device name */
1327
        if (((filename[0] >= 'a' && filename[0] <= 'z') ||
1328
             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
1329
            filename[1] == ':' && filename[2] == '\0') {
1330
            snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
1331
            filename = device_name;
1332
        }
1333
    }
1334
    s->type = find_device_type(bs, filename);
1335

    
1336
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
1337
        access_flags = GENERIC_READ | GENERIC_WRITE;
1338
    } else {
1339
        access_flags = GENERIC_READ;
1340
    }
1341
    create_flags = OPEN_EXISTING;
1342

    
1343
#ifdef QEMU_TOOL
1344
    overlapped = FILE_ATTRIBUTE_NORMAL;
1345
#else
1346
    overlapped = FILE_FLAG_OVERLAPPED;
1347
#endif
1348
    s->hfile = CreateFile(filename, access_flags,
1349
                          FILE_SHARE_READ, NULL,
1350
                          create_flags, overlapped, NULL);
1351
    if (s->hfile == INVALID_HANDLE_VALUE) {
1352
        int err = GetLastError();
1353

    
1354
        if (err == ERROR_ACCESS_DENIED)
1355
            return -EACCES;
1356
        return -1;
1357
    }
1358
    return 0;
1359
}
1360

    
1361
#if 0
1362
/***********************************************/
1363
/* removable device additional commands */
1364

1365
static int raw_is_inserted(BlockDriverState *bs)
1366
{
1367
    return 1;
1368
}
1369

1370
static int raw_media_changed(BlockDriverState *bs)
1371
{
1372
    return -ENOTSUP;
1373
}
1374

1375
static int raw_eject(BlockDriverState *bs, int eject_flag)
1376
{
1377
    DWORD ret_count;
1378

1379
    if (s->type == FTYPE_FILE)
1380
        return -ENOTSUP;
1381
    if (eject_flag) {
1382
        DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,
1383
                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
1384
    } else {
1385
        DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,
1386
                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
1387
    }
1388
}
1389

1390
static int raw_set_locked(BlockDriverState *bs, int locked)
1391
{
1392
    return -ENOTSUP;
1393
}
1394
#endif
1395

    
1396
BlockDriver bdrv_host_device = {
1397
    "host_device",
1398
    sizeof(BDRVRawState),
1399
    NULL, /* no probe for protocols */
1400
    hdev_open,
1401
    NULL,
1402
    NULL,
1403
    raw_close,
1404
    NULL,
1405
    raw_flush,
1406

    
1407
#if 0
1408
    .bdrv_aio_read = raw_aio_read,
1409
    .bdrv_aio_write = raw_aio_write,
1410
    .bdrv_aio_cancel = raw_aio_cancel,
1411
    .aiocb_size = sizeof(RawAIOCB);
1412
#endif
1413
    .bdrv_pread = raw_pread,
1414
    .bdrv_pwrite = raw_pwrite,
1415
    .bdrv_getlength = raw_getlength,
1416
};
1417
#endif /* _WIN32 */