Statistics
| Branch: | Revision:

root / block-raw.c @ 5fafdf24

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...) fprintf(logfile, formatCstr, ##args); fflush(logfile)
65
#else
66
#define DEBUG_BLOCK_PRINT(formatCstr, args...)
67
#endif
68

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

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

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

    
91
static int fd_open(BlockDriverState *bs);
92

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

    
98
    s->lseek_err_cnt = 0;
99

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

    
110
    s->type = FTYPE_FILE;
111

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

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

    
140
static int raw_pread(BlockDriverState *bs, int64_t offset,
141
                     uint8_t *buf, int count)
142
{
143
    BDRVRawState *s = bs->opaque;
144
    int ret;
145
   
146
    ret = fd_open(bs);
147
    if (ret < 0)
148
        return ret;
149

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

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

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

    
169
    /* Try harder for CDrom. */
170
    if (bs->type == BDRV_TYPE_CDROM) {
171
        lseek(s->fd, offset, SEEK_SET);
172
        ret = read(s->fd, buf, count);
173
        if (ret == count)
174
            goto label__raw_read__success;
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

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

    
185
    return -1;
186

    
187
label__raw_read__success:
188

    
189
    return ret;
190
}
191

    
192
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
193
                      const uint8_t *buf, int count)
194
{
195
    BDRVRawState *s = bs->opaque;
196
    int ret;
197
   
198
    ret = fd_open(bs);
199
    if (ret < 0)
200
        return ret;
201

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

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

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

    
221
    return -1;
222

    
223
label__raw_write__success:
224

    
225
    return ret;
226
}
227

    
228
/***********************************************************/
229
/* Unix AIO using POSIX AIO */
230

    
231
typedef struct RawAIOCB {
232
    BlockDriverAIOCB common;
233
    struct aiocb aiocb;
234
    struct RawAIOCB *next;
235
} RawAIOCB;
236

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

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

    
257
void qemu_aio_init(void)
258
{
259
    struct sigaction act;
260

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

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

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

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

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

    
334
/* wait until at least one AIO was handled */
335
static sigset_t wait_oset;
336

    
337
void qemu_aio_wait_start(void)
338
{
339
    sigset_t set;
340

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

    
348
void qemu_aio_wait(void)
349
{
350
    sigset_t set;
351
    int nb_sigs;
352

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

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

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

    
375
    if (fd_open(bs) < 0)
376
        return NULL;
377

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

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

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

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

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

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

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

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

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

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

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

    
484
    ret = fd_open(bs);
485
    if (ret < 0)
486
        return ret;
487

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

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

    
522
    if (flags || backing_file)
523
        return -ENOTSUP;
524

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

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

    
540
BlockDriver bdrv_raw = {
541
    "raw",
542
    sizeof(BDRVRawState),
543
    NULL, /* no probe for protocols */
544
    raw_open,
545
    NULL,
546
    NULL,
547
    raw_close,
548
    raw_create,
549
    raw_flush,
550
   
551
    .bdrv_aio_read = raw_aio_read,
552
    .bdrv_aio_write = raw_aio_write,
553
    .bdrv_aio_cancel = raw_aio_cancel,
554
    .aiocb_size = sizeof(RawAIOCB),
555
    .protocol_name = "file",
556
    .bdrv_pread = raw_pread,
557
    .bdrv_pwrite = raw_pwrite,
558
    .bdrv_truncate = raw_truncate,
559
    .bdrv_getlength = raw_getlength,
560
};
561

    
562
/***********************************************/
563
/* host device */
564

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

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

    
575
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
576
    if ( KERN_SUCCESS != kernResult ) {
577
        printf( "IOMasterPort returned %d\n", kernResult );
578
    }
579
   
580
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
581
    if ( classesToMatch == NULL ) {
582
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
583
    } else {
584
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
585
    }
586
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
587
    if ( KERN_SUCCESS != kernResult )
588
    {
589
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
590
    }
591
   
592
    return kernResult;
593
}
594

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

    
621
#endif
622

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

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

    
635
        kernResult = FindEjectableCDMedia( &mediaIterator );
636
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
637
   
638
        if ( bsdPath[ 0 ] != '\0' ) {
639
            strcat(bsdPath,"s0");
640
            /* some CDs don't have a partition 0 */
641
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
642
            if (fd < 0) {
643
                bsdPath[strlen(bsdPath)-1] = '1';
644
            } else {
645
                close(fd);
646
            }
647
            filename = bsdPath;
648
        }
649
       
650
        if ( mediaIterator )
651
            IOObjectRelease( mediaIterator );
652
    }
653
#endif
654
    open_flags = O_BINARY;
655
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
656
        open_flags |= O_RDWR;
657
    } else {
658
        open_flags |= O_RDONLY;
659
        bs->read_only = 1;
660
    }
661

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

    
694
#if defined(__linux__) && !defined(QEMU_TOOL)
695

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

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

    
751
#if defined(__linux__)
752

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

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

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

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

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

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

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

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

    
852
#else
853

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

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

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

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

    
874
#endif /* !linux */
875

    
876
BlockDriver bdrv_host_device = {
877
    "host_device",
878
    sizeof(BDRVRawState),
879
    NULL, /* no probe for protocols */
880
    hdev_open,
881
    NULL,
882
    NULL,
883
    raw_close,
884
    NULL,
885
    raw_flush,
886
   
887
    .bdrv_aio_read = raw_aio_read,
888
    .bdrv_aio_write = raw_aio_write,
889
    .bdrv_aio_cancel = raw_aio_cancel,
890
    .aiocb_size = sizeof(RawAIOCB),
891
    .bdrv_pread = raw_pread,
892
    .bdrv_pwrite = raw_pwrite,
893
    .bdrv_getlength = raw_getlength,
894

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

    
902
#else /* _WIN32 */
903

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

    
907
#define FTYPE_FILE 0
908
#define FTYPE_CD     1
909
#define FTYPE_HARDDISK 2
910

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

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

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

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

    
934
    h = (HANDLE)_get_osfhandle(fd);
935

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

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

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

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

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

    
965
    s->type = FTYPE_FILE;
966

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

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

    
995
static int raw_pread(BlockDriverState *bs, int64_t offset,
996
                     uint8_t *buf, int count)
997
{
998
    BDRVRawState *s = bs->opaque;
999
    OVERLAPPED ov;
1000
    DWORD ret_count;
1001
    int ret;
1002
   
1003
    memset(&ov, 0, sizeof(ov));
1004
    ov.Offset = offset;
1005
    ov.OffsetHigh = offset >> 32;
1006
    ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
1007
    if (!ret) {
1008
        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
1009
        if (!ret)
1010
            return -EIO;
1011
        else
1012
            return ret_count;
1013
    }
1014
    return ret_count;
1015
}
1016

    
1017
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
1018
                      const uint8_t *buf, int count)
1019
{
1020
    BDRVRawState *s = bs->opaque;
1021
    OVERLAPPED ov;
1022
    DWORD ret_count;
1023
    int ret;
1024
   
1025
    memset(&ov, 0, sizeof(ov));
1026
    ov.Offset = offset;
1027
    ov.OffsetHigh = offset >> 32;
1028
    ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
1029
    if (!ret) {
1030
        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
1031
        if (!ret)
1032
            return -EIO;
1033
        else
1034
            return ret_count;
1035
    }
1036
    return ret_count;
1037
}
1038

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1222
void qemu_aio_init(void)
1223
{
1224
}
1225

    
1226
void qemu_aio_poll(void)
1227
{
1228
}
1229

    
1230
void qemu_aio_flush(void)
1231
{
1232
}
1233

    
1234
void qemu_aio_wait_start(void)
1235
{
1236
}
1237

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

    
1245
void qemu_aio_wait_end(void)
1246
{
1247
}
1248

    
1249
BlockDriver bdrv_raw = {
1250
    "raw",
1251
    sizeof(BDRVRawState),
1252
    NULL, /* no probe for protocols */
1253
    raw_open,
1254
    NULL,
1255
    NULL,
1256
    raw_close,
1257
    raw_create,
1258
    raw_flush,
1259
   
1260
#if 0
1261
    .bdrv_aio_read = raw_aio_read,
1262
    .bdrv_aio_write = raw_aio_write,
1263
    .bdrv_aio_cancel = raw_aio_cancel,
1264
    .aiocb_size = sizeof(RawAIOCB);
1265
#endif
1266
    .protocol_name = "file",
1267
    .bdrv_pread = raw_pread,
1268
    .bdrv_pwrite = raw_pwrite,
1269
    .bdrv_truncate = raw_truncate,
1270
    .bdrv_getlength = raw_getlength,
1271
};
1272

    
1273
/***********************************************/
1274
/* host device */
1275

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1399
BlockDriver bdrv_host_device = {
1400
    "host_device",
1401
    sizeof(BDRVRawState),
1402
    NULL, /* no probe for protocols */
1403
    hdev_open,
1404
    NULL,
1405
    NULL,
1406
    raw_close,
1407
    NULL,
1408
    raw_flush,
1409
   
1410
#if 0
1411
    .bdrv_aio_read = raw_aio_read,
1412
    .bdrv_aio_write = raw_aio_write,
1413
    .bdrv_aio_cancel = raw_aio_cancel,
1414
    .aiocb_size = sizeof(RawAIOCB);
1415
#endif
1416
    .bdrv_pread = raw_pread,
1417
    .bdrv_pwrite = raw_pwrite,
1418
    .bdrv_getlength = raw_getlength,
1419
};
1420
#endif /* _WIN32 */