Statistics
| Branch: | Revision:

root / block-raw.c @ 741402f9

History | View | Annotate | Download (35.1 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(logfile, formatCstr, ##args); fflush(logfile); } } 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, %" PRId64 ", %p, %d) [%" PRId64
155
                              "] lseek failed : %d = %s\n",
156
                              s->fd, bs->filename, offset, buf, count,
157
                              bs->total_sectors, errno, strerror(errno));
158
        }
159
        return -1;
160
    }
161
    s->lseek_err_cnt=0;
162

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

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

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

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

    
189
label__raw_read__success:
190

    
191
    return ret;
192
}
193

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

    
200
    ret = fd_open(bs);
201
    if (ret < 0)
202
        return ret;
203

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

    
216
    ret = write(s->fd, buf, count);
217
    if (ret == count)
218
        goto label__raw_write__success;
219

    
220
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
221
                      "] write failed %d : %d = %s\n",
222
                      s->fd, bs->filename, offset, buf, count,
223
                      bs->total_sectors, ret, errno, strerror(errno));
224

    
225
label__raw_write__success:
226

    
227
    return ret;
228
}
229

    
230
/***********************************************************/
231
/* Unix AIO using POSIX AIO */
232

    
233
typedef struct RawAIOCB {
234
    BlockDriverAIOCB common;
235
    struct aiocb aiocb;
236
    struct RawAIOCB *next;
237
} RawAIOCB;
238

    
239
static int aio_sig_num = SIGUSR2;
240
static RawAIOCB *first_aio; /* AIO issued */
241
static int aio_initialized = 0;
242

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

    
259
void qemu_aio_init(void)
260
{
261
    struct sigaction act;
262

    
263
    aio_initialized = 1;
264

    
265
    sigfillset(&act.sa_mask);
266
    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
267
    act.sa_handler = aio_signal_handler;
268
    sigaction(aio_sig_num, &act, NULL);
269

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

    
284
void qemu_aio_poll(void)
285
{
286
    RawAIOCB *acb, **pacb;
287
    int ret;
288

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

    
325
/* Wait for all IO requests to complete.  */
326
void qemu_aio_flush(void)
327
{
328
    qemu_aio_wait_start();
329
    qemu_aio_poll();
330
    while (first_aio) {
331
        qemu_aio_wait();
332
    }
333
    qemu_aio_wait_end();
334
}
335

    
336
/* wait until at least one AIO was handled */
337
static sigset_t wait_oset;
338

    
339
void qemu_aio_wait_start(void)
340
{
341
    sigset_t set;
342

    
343
    if (!aio_initialized)
344
        qemu_aio_init();
345
    sigemptyset(&set);
346
    sigaddset(&set, aio_sig_num);
347
    sigprocmask(SIG_BLOCK, &set, &wait_oset);
348
}
349

    
350
void qemu_aio_wait(void)
351
{
352
    sigset_t set;
353
    int nb_sigs;
354

    
355
#ifndef QEMU_TOOL
356
    if (qemu_bh_poll())
357
        return;
358
#endif
359
    sigemptyset(&set);
360
    sigaddset(&set, aio_sig_num);
361
    sigwait(&set, &nb_sigs);
362
    qemu_aio_poll();
363
}
364

    
365
void qemu_aio_wait_end(void)
366
{
367
    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
368
}
369

    
370
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
371
        int64_t sector_num, uint8_t *buf, int nb_sectors,
372
        BlockDriverCompletionFunc *cb, void *opaque)
373
{
374
    BDRVRawState *s = bs->opaque;
375
    RawAIOCB *acb;
376

    
377
    if (fd_open(bs) < 0)
378
        return NULL;
379

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

    
394
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
395
        int64_t sector_num, uint8_t *buf, int nb_sectors,
396
        BlockDriverCompletionFunc *cb, void *opaque)
397
{
398
    RawAIOCB *acb;
399

    
400
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
401
    if (!acb)
402
        return NULL;
403
    if (aio_read(&acb->aiocb) < 0) {
404
        qemu_aio_release(acb);
405
        return NULL;
406
    }
407
    return &acb->common;
408
}
409

    
410
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
411
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
412
        BlockDriverCompletionFunc *cb, void *opaque)
413
{
414
    RawAIOCB *acb;
415

    
416
    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
417
    if (!acb)
418
        return NULL;
419
    if (aio_write(&acb->aiocb) < 0) {
420
        qemu_aio_release(acb);
421
        return NULL;
422
    }
423
    return &acb->common;
424
}
425

    
426
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
427
{
428
    int ret;
429
    RawAIOCB *acb = (RawAIOCB *)blockacb;
430
    RawAIOCB **pacb;
431

    
432
    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
433
    if (ret == AIO_NOTCANCELED) {
434
        /* fail safe: if the aio could not be canceled, we wait for
435
           it */
436
        while (aio_error(&acb->aiocb) == EINPROGRESS);
437
    }
438

    
439
    /* remove the callback from the queue */
440
    pacb = &first_aio;
441
    for(;;) {
442
        if (*pacb == NULL) {
443
            break;
444
        } else if (*pacb == acb) {
445
            *pacb = acb->next;
446
            qemu_aio_release(acb);
447
            break;
448
        }
449
        pacb = &acb->next;
450
    }
451
}
452

    
453
static void raw_close(BlockDriverState *bs)
454
{
455
    BDRVRawState *s = bs->opaque;
456
    if (s->fd >= 0) {
457
        close(s->fd);
458
        s->fd = -1;
459
    }
460
}
461

    
462
static int raw_truncate(BlockDriverState *bs, int64_t offset)
463
{
464
    BDRVRawState *s = bs->opaque;
465
    if (s->type != FTYPE_FILE)
466
        return -ENOTSUP;
467
    if (ftruncate(s->fd, offset) < 0)
468
        return -errno;
469
    return 0;
470
}
471

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

    
486
    ret = fd_open(bs);
487
    if (ret < 0)
488
        return ret;
489

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

    
519
static int raw_create(const char *filename, int64_t total_size,
520
                      const char *backing_file, int flags)
521
{
522
    int fd;
523

    
524
    if (flags || backing_file)
525
        return -ENOTSUP;
526

    
527
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
528
              0644);
529
    if (fd < 0)
530
        return -EIO;
531
    ftruncate(fd, total_size * 512);
532
    close(fd);
533
    return 0;
534
}
535

    
536
static void raw_flush(BlockDriverState *bs)
537
{
538
    BDRVRawState *s = bs->opaque;
539
    fsync(s->fd);
540
}
541

    
542
BlockDriver bdrv_raw = {
543
    "raw",
544
    sizeof(BDRVRawState),
545
    NULL, /* no probe for protocols */
546
    raw_open,
547
    NULL,
548
    NULL,
549
    raw_close,
550
    raw_create,
551
    raw_flush,
552

    
553
    .bdrv_aio_read = raw_aio_read,
554
    .bdrv_aio_write = raw_aio_write,
555
    .bdrv_aio_cancel = raw_aio_cancel,
556
    .aiocb_size = sizeof(RawAIOCB),
557
    .protocol_name = "file",
558
    .bdrv_pread = raw_pread,
559
    .bdrv_pwrite = raw_pwrite,
560
    .bdrv_truncate = raw_truncate,
561
    .bdrv_getlength = raw_getlength,
562
};
563

    
564
/***********************************************/
565
/* host device */
566

    
567
#ifdef CONFIG_COCOA
568
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
569
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
570

    
571
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
572
{
573
    kern_return_t       kernResult;
574
    mach_port_t     masterPort;
575
    CFMutableDictionaryRef  classesToMatch;
576

    
577
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
578
    if ( KERN_SUCCESS != kernResult ) {
579
        printf( "IOMasterPort returned %d\n", kernResult );
580
    }
581

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

    
594
    return kernResult;
595
}
596

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

    
620
    return kernResult;
621
}
622

    
623
#endif
624

    
625
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
626
{
627
    BDRVRawState *s = bs->opaque;
628
    int fd, open_flags, ret;
629

    
630
#ifdef CONFIG_COCOA
631
    if (strstart(filename, "/dev/cdrom", NULL)) {
632
        kern_return_t kernResult;
633
        io_iterator_t mediaIterator;
634
        char bsdPath[ MAXPATHLEN ];
635
        int fd;
636

    
637
        kernResult = FindEjectableCDMedia( &mediaIterator );
638
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
639

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

    
652
        if ( mediaIterator )
653
            IOObjectRelease( mediaIterator );
654
    }
655
#endif
656
    open_flags = O_BINARY;
657
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
658
        open_flags |= O_RDWR;
659
    } else {
660
        open_flags |= O_RDONLY;
661
        bs->read_only = 1;
662
    }
663

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

    
696
#if defined(__linux__) && !defined(QEMU_TOOL)
697

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

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

    
753
#if defined(__linux__)
754

    
755
static int raw_is_inserted(BlockDriverState *bs)
756
{
757
    BDRVRawState *s = bs->opaque;
758
    int ret;
759

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

    
776
/* currently only used by fdc.c, but a CD version would be good too */
777
static int raw_media_changed(BlockDriverState *bs)
778
{
779
    BDRVRawState *s = bs->opaque;
780

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

    
801
static int raw_eject(BlockDriverState *bs, int eject_flag)
802
{
803
    BDRVRawState *s = bs->opaque;
804

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

    
836
static int raw_set_locked(BlockDriverState *bs, int locked)
837
{
838
    BDRVRawState *s = bs->opaque;
839

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

    
854
#else
855

    
856
static int raw_is_inserted(BlockDriverState *bs)
857
{
858
    return 1;
859
}
860

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

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

    
871
static int raw_set_locked(BlockDriverState *bs, int locked)
872
{
873
    return -ENOTSUP;
874
}
875

    
876
#endif /* !linux */
877

    
878
BlockDriver bdrv_host_device = {
879
    "host_device",
880
    sizeof(BDRVRawState),
881
    NULL, /* no probe for protocols */
882
    hdev_open,
883
    NULL,
884
    NULL,
885
    raw_close,
886
    NULL,
887
    raw_flush,
888

    
889
    .bdrv_aio_read = raw_aio_read,
890
    .bdrv_aio_write = raw_aio_write,
891
    .bdrv_aio_cancel = raw_aio_cancel,
892
    .aiocb_size = sizeof(RawAIOCB),
893
    .bdrv_pread = raw_pread,
894
    .bdrv_pwrite = raw_pwrite,
895
    .bdrv_getlength = raw_getlength,
896

    
897
    /* removable device support */
898
    .bdrv_is_inserted = raw_is_inserted,
899
    .bdrv_media_changed = raw_media_changed,
900
    .bdrv_eject = raw_eject,
901
    .bdrv_set_locked = raw_set_locked,
902
};
903

    
904
#else /* _WIN32 */
905

    
906
/* XXX: use another file ? */
907
#include <winioctl.h>
908

    
909
#define FTYPE_FILE 0
910
#define FTYPE_CD     1
911
#define FTYPE_HARDDISK 2
912

    
913
typedef struct BDRVRawState {
914
    HANDLE hfile;
915
    int type;
916
    char drive_path[16]; /* format: "d:\" */
917
} BDRVRawState;
918

    
919
typedef struct RawAIOCB {
920
    BlockDriverAIOCB common;
921
    HANDLE hEvent;
922
    OVERLAPPED ov;
923
    int count;
924
} RawAIOCB;
925

    
926
int qemu_ftruncate64(int fd, int64_t length)
927
{
928
    LARGE_INTEGER li;
929
    LONG high;
930
    HANDLE h;
931
    BOOL res;
932

    
933
    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
934
        return -1;
935

    
936
    h = (HANDLE)_get_osfhandle(fd);
937

    
938
    /* get current position, ftruncate do not change position */
939
    li.HighPart = 0;
940
    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
941
    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
942
        return -1;
943

    
944
    high = length >> 32;
945
    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
946
        return -1;
947
    res = SetEndOfFile(h);
948

    
949
    /* back to old position */
950
    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
951
    return res ? 0 : -1;
952
}
953

    
954
static int set_sparse(int fd)
955
{
956
    DWORD returned;
957
    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
958
                                 NULL, 0, NULL, 0, &returned, NULL);
959
}
960

    
961
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
962
{
963
    BDRVRawState *s = bs->opaque;
964
    int access_flags, create_flags;
965
    DWORD overlapped;
966

    
967
    s->type = FTYPE_FILE;
968

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

    
990
        if (err == ERROR_ACCESS_DENIED)
991
            return -EACCES;
992
        return -1;
993
    }
994
    return 0;
995
}
996

    
997
static int raw_pread(BlockDriverState *bs, int64_t offset,
998
                     uint8_t *buf, int count)
999
{
1000
    BDRVRawState *s = bs->opaque;
1001
    OVERLAPPED ov;
1002
    DWORD ret_count;
1003
    int ret;
1004

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

    
1019
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
1020
                      const uint8_t *buf, int count)
1021
{
1022
    BDRVRawState *s = bs->opaque;
1023
    OVERLAPPED ov;
1024
    DWORD ret_count;
1025
    int ret;
1026

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

    
1041
#if 0
1042
#ifndef QEMU_TOOL
1043
static void raw_aio_cb(void *opaque)
1044
{
1045
    RawAIOCB *acb = opaque;
1046
    BlockDriverState *bs = acb->common.bs;
1047
    BDRVRawState *s = bs->opaque;
1048
    DWORD ret_count;
1049
    int ret;
1050

1051
    ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
1052
    if (!ret || ret_count != acb->count) {
1053
        acb->common.cb(acb->common.opaque, -EIO);
1054
    } else {
1055
        acb->common.cb(acb->common.opaque, 0);
1056
    }
1057
}
1058
#endif
1059

    
1060
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
1061
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1062
        BlockDriverCompletionFunc *cb, void *opaque)
1063
{
1064
    RawAIOCB *acb;
1065
    int64_t offset;
1066

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

    
1087
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
1088
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1089
        BlockDriverCompletionFunc *cb, void *opaque)
1090
{
1091
    BDRVRawState *s = bs->opaque;
1092
    RawAIOCB *acb;
1093
    int ret;
1094

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

    
1109
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
1110
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1111
        BlockDriverCompletionFunc *cb, void *opaque)
1112
{
1113
    BDRVRawState *s = bs->opaque;
1114
    RawAIOCB *acb;
1115
    int ret;
1116

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

    
1131
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
1132
{
1133
#ifndef QEMU_TOOL
1134
    RawAIOCB *acb = (RawAIOCB *)blockacb;
1135
    BlockDriverState *bs = acb->common.bs;
1136
    BDRVRawState *s = bs->opaque;
1137

    
1138
    qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
1139
    /* XXX: if more than one async I/O it is not correct */
1140
    CancelIo(s->hfile);
1141
    qemu_aio_release(acb);
1142
#endif
1143
}
1144
#endif /* #if 0 */
1145

    
1146
static void raw_flush(BlockDriverState *bs)
1147
{
1148
    BDRVRawState *s = bs->opaque;
1149
    FlushFileBuffers(s->hfile);
1150
}
1151

    
1152
static void raw_close(BlockDriverState *bs)
1153
{
1154
    BDRVRawState *s = bs->opaque;
1155
    CloseHandle(s->hfile);
1156
}
1157

    
1158
static int raw_truncate(BlockDriverState *bs, int64_t offset)
1159
{
1160
    BDRVRawState *s = bs->opaque;
1161
    DWORD low, high;
1162

    
1163
    low = offset;
1164
    high = offset >> 32;
1165
    if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
1166
        return -EIO;
1167
    if (!SetEndOfFile(s->hfile))
1168
        return -EIO;
1169
    return 0;
1170
}
1171

    
1172
static int64_t raw_getlength(BlockDriverState *bs)
1173
{
1174
    BDRVRawState *s = bs->opaque;
1175
    LARGE_INTEGER l;
1176
    ULARGE_INTEGER available, total, total_free;
1177
    DISK_GEOMETRY_EX dg;
1178
    DWORD count;
1179
    BOOL status;
1180

    
1181
    switch(s->type) {
1182
    case FTYPE_FILE:
1183
        l.LowPart = GetFileSize(s->hfile, &l.HighPart);
1184
        if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
1185
            return -EIO;
1186
        break;
1187
    case FTYPE_CD:
1188
        if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
1189
            return -EIO;
1190
        l.QuadPart = total.QuadPart;
1191
        break;
1192
    case FTYPE_HARDDISK:
1193
        status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
1194
                                 NULL, 0, &dg, sizeof(dg), &count, NULL);
1195
        if (status != 0) {
1196
            l = dg.DiskSize;
1197
        }
1198
        break;
1199
    default:
1200
        return -EIO;
1201
    }
1202
    return l.QuadPart;
1203
}
1204

    
1205
static int raw_create(const char *filename, int64_t total_size,
1206
                      const char *backing_file, int flags)
1207
{
1208
    int fd;
1209

    
1210
    if (flags || backing_file)
1211
        return -ENOTSUP;
1212

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

    
1223
void qemu_aio_init(void)
1224
{
1225
}
1226

    
1227
void qemu_aio_poll(void)
1228
{
1229
}
1230

    
1231
void qemu_aio_flush(void)
1232
{
1233
}
1234

    
1235
void qemu_aio_wait_start(void)
1236
{
1237
}
1238

    
1239
void qemu_aio_wait(void)
1240
{
1241
#ifndef QEMU_TOOL
1242
    qemu_bh_poll();
1243
#endif
1244
}
1245

    
1246
void qemu_aio_wait_end(void)
1247
{
1248
}
1249

    
1250
BlockDriver bdrv_raw = {
1251
    "raw",
1252
    sizeof(BDRVRawState),
1253
    NULL, /* no probe for protocols */
1254
    raw_open,
1255
    NULL,
1256
    NULL,
1257
    raw_close,
1258
    raw_create,
1259
    raw_flush,
1260

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

    
1274
/***********************************************/
1275
/* host device */
1276

    
1277
static int find_cdrom(char *cdrom_name, int cdrom_name_size)
1278
{
1279
    char drives[256], *pdrv = drives;
1280
    UINT type;
1281

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

    
1297
static int find_device_type(BlockDriverState *bs, const char *filename)
1298
{
1299
    BDRVRawState *s = bs->opaque;
1300
    UINT type;
1301
    const char *p;
1302

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

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

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

    
1340
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
1341
        access_flags = GENERIC_READ | GENERIC_WRITE;
1342
    } else {
1343
        access_flags = GENERIC_READ;
1344
    }
1345
    create_flags = OPEN_EXISTING;
1346

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

    
1358
        if (err == ERROR_ACCESS_DENIED)
1359
            return -EACCES;
1360
        return -1;
1361
    }
1362
    return 0;
1363
}
1364

    
1365
#if 0
1366
/***********************************************/
1367
/* removable device additional commands */
1368

1369
static int raw_is_inserted(BlockDriverState *bs)
1370
{
1371
    return 1;
1372
}
1373

1374
static int raw_media_changed(BlockDriverState *bs)
1375
{
1376
    return -ENOTSUP;
1377
}
1378

1379
static int raw_eject(BlockDriverState *bs, int eject_flag)
1380
{
1381
    DWORD ret_count;
1382

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

1394
static int raw_set_locked(BlockDriverState *bs, int locked)
1395
{
1396
    return -ENOTSUP;
1397
}
1398
#endif
1399

    
1400
BlockDriver bdrv_host_device = {
1401
    "host_device",
1402
    sizeof(BDRVRawState),
1403
    NULL, /* no probe for protocols */
1404
    hdev_open,
1405
    NULL,
1406
    NULL,
1407
    raw_close,
1408
    NULL,
1409
    raw_flush,
1410

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