Statistics
| Branch: | Revision:

root / block-raw.c @ ae5fc450

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
#ifdef QEMU_IMG
25
#include "qemu-common.h"
26
#else
27
#include "vl.h"
28
#include "exec-all.h"
29
#endif
30
#include "block_int.h"
31
#include <assert.h>
32
#ifndef _WIN32
33
#include <aio.h>
34

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

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

    
61
//#define DEBUG_FLOPPY
62

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

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

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

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

    
93
static int fd_open(BlockDriverState *bs);
94

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

    
100
    s->lseek_err_cnt = 0;
101

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

    
112
    s->type = FTYPE_FILE;
113

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

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

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

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

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

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

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

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

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

    
190
label__raw_read__success:
191

    
192
    return ret;
193
}
194

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

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

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

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

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

    
226
label__raw_write__success:
227

    
228
    return ret;
229
}
230

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

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

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

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

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

    
264
    aio_initialized = 1;
265

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
565
/***********************************************/
566
/* host device */
567

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

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

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

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

    
595
    return kernResult;
596
}
597

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

    
621
    return kernResult;
622
}
623

    
624
#endif
625

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

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

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

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

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

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

    
697
#if defined(__linux__) && !defined(QEMU_IMG)
698

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

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

    
754
#if defined(__linux__)
755

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

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

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

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

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

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

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

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

    
855
#else
856

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

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

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

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

    
877
#endif /* !linux */
878

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

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

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

    
905
#else /* _WIN32 */
906

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

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

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

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

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

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

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

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

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

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

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

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

    
968
    s->type = FTYPE_FILE;
969

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1224
void qemu_aio_init(void)
1225
{
1226
}
1227

    
1228
void qemu_aio_poll(void)
1229
{
1230
}
1231

    
1232
void qemu_aio_flush(void)
1233
{
1234
}
1235

    
1236
void qemu_aio_wait_start(void)
1237
{
1238
}
1239

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

    
1247
void qemu_aio_wait_end(void)
1248
{
1249
}
1250

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

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

    
1275
/***********************************************/
1276
/* host device */
1277

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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