File:  [Qemu by Fabrice Bellard] / qemu / block-raw.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:45:09 2018 UTC (23 months, 1 week ago) by root
Branches: qemu, MAIN
CVS tags: qemu0090, HEAD
qemu 0.9.0

    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 FTYPE_FILE   0
   63: #define FTYPE_CD     1
   64: #define FTYPE_FD     2
   65: 
   66: /* if the FD is not accessed during that time (in ms), we try to
   67:    reopen it to see if the disk has been changed */
   68: #define FD_OPEN_TIMEOUT 1000
   69: 
   70: typedef struct BDRVRawState {
   71:     int fd;
   72:     int type;
   73: #if defined(__linux__)
   74:     /* linux floppy specific */
   75:     int fd_open_flags;
   76:     int64_t fd_open_time;
   77:     int64_t fd_error_time;
   78:     int fd_got_error;
   79:     int fd_media_changed;
   80: #endif
   81: } BDRVRawState;
   82: 
   83: static int fd_open(BlockDriverState *bs);
   84: 
   85: static int raw_open(BlockDriverState *bs, const char *filename, int flags)
   86: {
   87:     BDRVRawState *s = bs->opaque;
   88:     int fd, open_flags, ret;
   89: 
   90:     open_flags = O_BINARY;
   91:     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
   92:         open_flags |= O_RDWR;
   93:     } else {
   94:         open_flags |= O_RDONLY;
   95:         bs->read_only = 1;
   96:     }
   97:     if (flags & BDRV_O_CREAT)
   98:         open_flags |= O_CREAT | O_TRUNC;
   99: 
  100:     s->type = FTYPE_FILE;
  101: 
  102:     fd = open(filename, open_flags, 0644);
  103:     if (fd < 0) {
  104:         ret = -errno;
  105:         if (ret == -EROFS)
  106:             ret = -EACCES;
  107:         return ret;
  108:     }
  109:     s->fd = fd;
  110:     return 0;
  111: }
  112: 
  113: /* XXX: use host sector size if necessary with:
  114: #ifdef DIOCGSECTORSIZE
  115:         {
  116:             unsigned int sectorsize = 512;
  117:             if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  118:                 sectorsize > bufsize)
  119:                 bufsize = sectorsize;
  120:         }
  121: #endif
  122: #ifdef CONFIG_COCOA
  123:         u_int32_t   blockSize = 512;
  124:         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
  125:             bufsize = blockSize;
  126:         }
  127: #endif
  128: */
  129: 
  130: static int raw_pread(BlockDriverState *bs, int64_t offset, 
  131:                      uint8_t *buf, int count)
  132: {
  133:     BDRVRawState *s = bs->opaque;
  134:     int ret;
  135:     
  136:     ret = fd_open(bs);
  137:     if (ret < 0)
  138:         return ret;
  139: 
  140:     lseek(s->fd, offset, SEEK_SET);
  141:     ret = read(s->fd, buf, count);
  142:     return ret;
  143: }
  144: 
  145: static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
  146:                       const uint8_t *buf, int count)
  147: {
  148:     BDRVRawState *s = bs->opaque;
  149:     int ret;
  150:     
  151:     ret = fd_open(bs);
  152:     if (ret < 0)
  153:         return ret;
  154: 
  155:     lseek(s->fd, offset, SEEK_SET);
  156:     ret = write(s->fd, buf, count);
  157:     return ret;
  158: }
  159: 
  160: /***********************************************************/
  161: /* Unix AIO using POSIX AIO */
  162: 
  163: typedef struct RawAIOCB {
  164:     BlockDriverAIOCB common;
  165:     struct aiocb aiocb;
  166:     struct RawAIOCB *next;
  167: } RawAIOCB;
  168: 
  169: static int aio_sig_num = SIGUSR2;
  170: static RawAIOCB *first_aio; /* AIO issued */
  171: static int aio_initialized = 0;
  172: 
  173: static void aio_signal_handler(int signum)
  174: {
  175: #ifndef QEMU_TOOL
  176:     CPUState *env = cpu_single_env;
  177:     if (env) {
  178:         /* stop the currently executing cpu because a timer occured */
  179:         cpu_interrupt(env, CPU_INTERRUPT_EXIT);
  180: #ifdef USE_KQEMU
  181:         if (env->kqemu_enabled) {
  182:             kqemu_cpu_interrupt(env);
  183:         }
  184: #endif
  185:     }
  186: #endif
  187: }
  188: 
  189: void qemu_aio_init(void)
  190: {
  191:     struct sigaction act;
  192: 
  193:     aio_initialized = 1;
  194:     
  195:     sigfillset(&act.sa_mask);
  196:     act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
  197:     act.sa_handler = aio_signal_handler;
  198:     sigaction(aio_sig_num, &act, NULL);
  199: 
  200: #if defined(__GLIBC__) && defined(__linux__)
  201:     {
  202:         /* XXX: aio thread exit seems to hang on RedHat 9 and this init
  203:            seems to fix the problem. */
  204:         struct aioinit ai;
  205:         memset(&ai, 0, sizeof(ai));
  206:         ai.aio_threads = 1;
  207:         ai.aio_num = 1;
  208:         ai.aio_idle_time = 365 * 100000;
  209:         aio_init(&ai);
  210:     }
  211: #endif
  212: }
  213: 
  214: void qemu_aio_poll(void)
  215: {
  216:     RawAIOCB *acb, **pacb;
  217:     int ret;
  218: 
  219:     for(;;) {
  220:         pacb = &first_aio;
  221:         for(;;) {
  222:             acb = *pacb;
  223:             if (!acb)
  224:                 goto the_end;
  225:             ret = aio_error(&acb->aiocb);
  226:             if (ret == ECANCELED) {
  227:                 /* remove the request */
  228:                 *pacb = acb->next;
  229:                 qemu_aio_release(acb);
  230:             } else if (ret != EINPROGRESS) {
  231:                 /* end of aio */
  232:                 if (ret == 0) {
  233:                     ret = aio_return(&acb->aiocb);
  234:                     if (ret == acb->aiocb.aio_nbytes)
  235:                         ret = 0;
  236:                     else
  237:                         ret = -EINVAL;
  238:                 } else {
  239:                     ret = -ret;
  240:                 }
  241:                 /* remove the request */
  242:                 *pacb = acb->next;
  243:                 /* call the callback */
  244:                 acb->common.cb(acb->common.opaque, ret);
  245:                 qemu_aio_release(acb);
  246:                 break;
  247:             } else {
  248:                 pacb = &acb->next;
  249:             }
  250:         }
  251:     }
  252:  the_end: ;
  253: }
  254: 
  255: /* Wait for all IO requests to complete.  */
  256: void qemu_aio_flush(void)
  257: {
  258:     qemu_aio_wait_start();
  259:     qemu_aio_poll();
  260:     while (first_aio) {
  261:         qemu_aio_wait();
  262:     }
  263:     qemu_aio_wait_end();
  264: }
  265: 
  266: /* wait until at least one AIO was handled */
  267: static sigset_t wait_oset;
  268: 
  269: void qemu_aio_wait_start(void)
  270: {
  271:     sigset_t set;
  272: 
  273:     if (!aio_initialized)
  274:         qemu_aio_init();
  275:     sigemptyset(&set);
  276:     sigaddset(&set, aio_sig_num);
  277:     sigprocmask(SIG_BLOCK, &set, &wait_oset);
  278: }
  279: 
  280: void qemu_aio_wait(void)
  281: {
  282:     sigset_t set;
  283:     int nb_sigs;
  284: 
  285: #ifndef QEMU_TOOL
  286:     if (qemu_bh_poll())
  287:         return;
  288: #endif
  289:     sigemptyset(&set);
  290:     sigaddset(&set, aio_sig_num);
  291:     sigwait(&set, &nb_sigs);
  292:     qemu_aio_poll();
  293: }
  294: 
  295: void qemu_aio_wait_end(void)
  296: {
  297:     sigprocmask(SIG_SETMASK, &wait_oset, NULL);
  298: }
  299: 
  300: static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  301:         int64_t sector_num, uint8_t *buf, int nb_sectors,
  302:         BlockDriverCompletionFunc *cb, void *opaque)
  303: {
  304:     BDRVRawState *s = bs->opaque;
  305:     RawAIOCB *acb;
  306: 
  307:     if (fd_open(bs) < 0)
  308:         return NULL;
  309: 
  310:     acb = qemu_aio_get(bs, cb, opaque);
  311:     if (!acb)
  312:         return NULL;
  313:     acb->aiocb.aio_fildes = s->fd;
  314:     acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
  315:     acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  316:     acb->aiocb.aio_buf = buf;
  317:     acb->aiocb.aio_nbytes = nb_sectors * 512;
  318:     acb->aiocb.aio_offset = sector_num * 512;
  319:     acb->next = first_aio;
  320:     first_aio = acb;
  321:     return acb;
  322: }
  323: 
  324: static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
  325:         int64_t sector_num, uint8_t *buf, int nb_sectors,
  326:         BlockDriverCompletionFunc *cb, void *opaque)
  327: {
  328:     RawAIOCB *acb;
  329: 
  330:     acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  331:     if (!acb)
  332:         return NULL;
  333:     if (aio_read(&acb->aiocb) < 0) {
  334:         qemu_aio_release(acb);
  335:         return NULL;
  336:     } 
  337:     return &acb->common;
  338: }
  339: 
  340: static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
  341:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
  342:         BlockDriverCompletionFunc *cb, void *opaque)
  343: {
  344:     RawAIOCB *acb;
  345: 
  346:     acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
  347:     if (!acb)
  348:         return NULL;
  349:     if (aio_write(&acb->aiocb) < 0) {
  350:         qemu_aio_release(acb);
  351:         return NULL;
  352:     } 
  353:     return &acb->common;
  354: }
  355: 
  356: static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
  357: {
  358:     int ret;
  359:     RawAIOCB *acb = (RawAIOCB *)blockacb;
  360:     RawAIOCB **pacb;
  361: 
  362:     ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
  363:     if (ret == AIO_NOTCANCELED) {
  364:         /* fail safe: if the aio could not be canceled, we wait for
  365:            it */
  366:         while (aio_error(&acb->aiocb) == EINPROGRESS);
  367:     }
  368: 
  369:     /* remove the callback from the queue */
  370:     pacb = &first_aio;
  371:     for(;;) {
  372:         if (*pacb == NULL) {
  373:             break;
  374:         } else if (*pacb == acb) {
  375:             *pacb = acb->next;
  376:             qemu_aio_release(acb);
  377:             break;
  378:         }
  379:         pacb = &acb->next;
  380:     }
  381: }
  382: 
  383: static void raw_close(BlockDriverState *bs)
  384: {
  385:     BDRVRawState *s = bs->opaque;
  386:     if (s->fd >= 0) {
  387:         close(s->fd);
  388:         s->fd = -1;
  389:     }
  390: }
  391: 
  392: static int raw_truncate(BlockDriverState *bs, int64_t offset)
  393: {
  394:     BDRVRawState *s = bs->opaque;
  395:     if (s->type != FTYPE_FILE)
  396:         return -ENOTSUP;
  397:     if (ftruncate(s->fd, offset) < 0)
  398:         return -errno;
  399:     return 0;
  400: }
  401: 
  402: static int64_t  raw_getlength(BlockDriverState *bs)
  403: {
  404:     BDRVRawState *s = bs->opaque;
  405:     int fd = s->fd;
  406:     int64_t size;
  407: #ifdef _BSD
  408:     struct stat sb;
  409: #endif
  410: #ifdef __sun__
  411:     struct dk_minfo minfo;
  412:     int rv;
  413: #endif
  414:     int ret;
  415: 
  416:     ret = fd_open(bs);
  417:     if (ret < 0)
  418:         return ret;
  419: 
  420: #ifdef _BSD
  421:     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
  422: #ifdef DIOCGMEDIASIZE
  423: 	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
  424: #endif
  425: #ifdef CONFIG_COCOA
  426:         size = LONG_LONG_MAX;
  427: #else
  428:         size = lseek(fd, 0LL, SEEK_END);
  429: #endif
  430:     } else
  431: #endif
  432: #ifdef __sun__
  433:     /*
  434:      * use the DKIOCGMEDIAINFO ioctl to read the size.
  435:      */
  436:     rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
  437:     if ( rv != -1 ) {
  438:         size = minfo.dki_lbsize * minfo.dki_capacity;
  439:     } else /* there are reports that lseek on some devices
  440:               fails, but irc discussion said that contingency
  441:               on contingency was overkill */
  442: #endif
  443:     {
  444:         size = lseek(fd, 0, SEEK_END);
  445:     }
  446:     return size;
  447: }
  448: 
  449: static int raw_create(const char *filename, int64_t total_size,
  450:                       const char *backing_file, int flags)
  451: {
  452:     int fd;
  453: 
  454:     if (flags || backing_file)
  455:         return -ENOTSUP;
  456: 
  457:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
  458:               0644);
  459:     if (fd < 0)
  460:         return -EIO;
  461:     ftruncate(fd, total_size * 512);
  462:     close(fd);
  463:     return 0;
  464: }
  465: 
  466: static void raw_flush(BlockDriverState *bs)
  467: {
  468:     BDRVRawState *s = bs->opaque;
  469:     fsync(s->fd);
  470: }
  471: 
  472: BlockDriver bdrv_raw = {
  473:     "raw",
  474:     sizeof(BDRVRawState),
  475:     NULL, /* no probe for protocols */
  476:     raw_open,
  477:     NULL,
  478:     NULL,
  479:     raw_close,
  480:     raw_create,
  481:     raw_flush,
  482:     
  483:     .bdrv_aio_read = raw_aio_read,
  484:     .bdrv_aio_write = raw_aio_write,
  485:     .bdrv_aio_cancel = raw_aio_cancel,
  486:     .aiocb_size = sizeof(RawAIOCB),
  487:     .protocol_name = "file",
  488:     .bdrv_pread = raw_pread,
  489:     .bdrv_pwrite = raw_pwrite,
  490:     .bdrv_truncate = raw_truncate,
  491:     .bdrv_getlength = raw_getlength,
  492: };
  493: 
  494: /***********************************************/
  495: /* host device */
  496: 
  497: #ifdef CONFIG_COCOA
  498: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
  499: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
  500: 
  501: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
  502: {
  503:     kern_return_t       kernResult; 
  504:     mach_port_t     masterPort;
  505:     CFMutableDictionaryRef  classesToMatch;
  506: 
  507:     kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
  508:     if ( KERN_SUCCESS != kernResult ) {
  509:         printf( "IOMasterPort returned %d\n", kernResult );
  510:     }
  511:     
  512:     classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
  513:     if ( classesToMatch == NULL ) {
  514:         printf( "IOServiceMatching returned a NULL dictionary.\n" );
  515:     } else {
  516:     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
  517:     }
  518:     kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
  519:     if ( KERN_SUCCESS != kernResult )
  520:     {
  521:         printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
  522:     }
  523:     
  524:     return kernResult;
  525: }
  526: 
  527: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
  528: {
  529:     io_object_t     nextMedia;
  530:     kern_return_t   kernResult = KERN_FAILURE;
  531:     *bsdPath = '\0';
  532:     nextMedia = IOIteratorNext( mediaIterator );
  533:     if ( nextMedia )
  534:     {
  535:         CFTypeRef   bsdPathAsCFString;
  536:     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
  537:         if ( bsdPathAsCFString ) {
  538:             size_t devPathLength;
  539:             strcpy( bsdPath, _PATH_DEV );
  540:             strcat( bsdPath, "r" );
  541:             devPathLength = strlen( bsdPath );
  542:             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
  543:                 kernResult = KERN_SUCCESS;
  544:             }
  545:             CFRelease( bsdPathAsCFString );
  546:         }
  547:         IOObjectRelease( nextMedia );
  548:     }
  549:     
  550:     return kernResult;
  551: }
  552: 
  553: #endif
  554: 
  555: static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
  556: {
  557:     BDRVRawState *s = bs->opaque;
  558:     int fd, open_flags, ret;
  559: 
  560: #ifdef CONFIG_COCOA
  561:     if (strstart(filename, "/dev/cdrom", NULL)) {
  562:         kern_return_t kernResult;
  563:         io_iterator_t mediaIterator;
  564:         char bsdPath[ MAXPATHLEN ];
  565:         int fd;
  566:  
  567:         kernResult = FindEjectableCDMedia( &mediaIterator );
  568:         kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
  569:     
  570:         if ( bsdPath[ 0 ] != '\0' ) {
  571:             strcat(bsdPath,"s0");
  572:             /* some CDs don't have a partition 0 */
  573:             fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
  574:             if (fd < 0) {
  575:                 bsdPath[strlen(bsdPath)-1] = '1';
  576:             } else {
  577:                 close(fd);
  578:             }
  579:             filename = bsdPath;
  580:         }
  581:         
  582:         if ( mediaIterator )
  583:             IOObjectRelease( mediaIterator );
  584:     }
  585: #endif
  586:     open_flags = O_BINARY;
  587:     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  588:         open_flags |= O_RDWR;
  589:     } else {
  590:         open_flags |= O_RDONLY;
  591:         bs->read_only = 1;
  592:     }
  593: 
  594:     s->type = FTYPE_FILE;
  595: #if defined(__linux__)
  596:     if (strstart(filename, "/dev/cd", NULL)) {
  597:         /* open will not fail even if no CD is inserted */
  598:         open_flags |= O_NONBLOCK;
  599:         s->type = FTYPE_CD;
  600:     } else if (strstart(filename, "/dev/fd", NULL)) {
  601:         s->type = FTYPE_FD;
  602:         s->fd_open_flags = open_flags;
  603:         /* open will not fail even if no floppy is inserted */
  604:         open_flags |= O_NONBLOCK;
  605:     }
  606: #endif
  607:     fd = open(filename, open_flags, 0644);
  608:     if (fd < 0) {
  609:         ret = -errno;
  610:         if (ret == -EROFS)
  611:             ret = -EACCES;
  612:         return ret;
  613:     }
  614:     s->fd = fd;
  615: #if defined(__linux__)
  616:     /* close fd so that we can reopen it as needed */
  617:     if (s->type == FTYPE_FD) {
  618:         close(s->fd);
  619:         s->fd = -1;
  620:         s->fd_media_changed = 1;
  621:     }
  622: #endif
  623:     return 0;
  624: }
  625: 
  626: #if defined(__linux__) && !defined(QEMU_TOOL)
  627: 
  628: /* Note: we do not have a reliable method to detect if the floppy is
  629:    present. The current method is to try to open the floppy at every
  630:    I/O and to keep it opened during a few hundreds of ms. */
  631: static int fd_open(BlockDriverState *bs)
  632: {
  633:     BDRVRawState *s = bs->opaque;
  634:     int last_media_present;
  635: 
  636:     if (s->type != FTYPE_FD)
  637:         return 0;
  638:     last_media_present = (s->fd >= 0);
  639:     if (s->fd >= 0 && 
  640:         (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
  641:         close(s->fd);
  642:         s->fd = -1;
  643: #ifdef DEBUG_FLOPPY
  644:         printf("Floppy closed\n");
  645: #endif
  646:     }
  647:     if (s->fd < 0) {
  648:         if (s->fd_got_error && 
  649:             (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
  650: #ifdef DEBUG_FLOPPY
  651:             printf("No floppy (open delayed)\n");
  652: #endif
  653:             return -EIO;
  654:         }
  655:         s->fd = open(bs->filename, s->fd_open_flags);
  656:         if (s->fd < 0) {
  657:             s->fd_error_time = qemu_get_clock(rt_clock);
  658:             s->fd_got_error = 1;
  659:             if (last_media_present)
  660:                 s->fd_media_changed = 1;
  661: #ifdef DEBUG_FLOPPY
  662:             printf("No floppy\n");
  663: #endif
  664:             return -EIO;
  665:         }
  666: #ifdef DEBUG_FLOPPY
  667:         printf("Floppy opened\n");
  668: #endif
  669:     }
  670:     if (!last_media_present)
  671:         s->fd_media_changed = 1;
  672:     s->fd_open_time = qemu_get_clock(rt_clock);
  673:     s->fd_got_error = 0;
  674:     return 0;
  675: }
  676: #else
  677: static int fd_open(BlockDriverState *bs)
  678: {
  679:     return 0;
  680: }
  681: #endif
  682: 
  683: #if defined(__linux__)
  684: 
  685: static int raw_is_inserted(BlockDriverState *bs)
  686: {
  687:     BDRVRawState *s = bs->opaque;
  688:     int ret;
  689: 
  690:     switch(s->type) {
  691:     case FTYPE_CD:
  692:         ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
  693:         if (ret == CDS_DISC_OK)
  694:             return 1;
  695:         else
  696:             return 0;
  697:         break;
  698:     case FTYPE_FD:
  699:         ret = fd_open(bs);
  700:         return (ret >= 0);
  701:     default:
  702:         return 1;
  703:     }
  704: }
  705: 
  706: /* currently only used by fdc.c, but a CD version would be good too */
  707: static int raw_media_changed(BlockDriverState *bs)
  708: {
  709:     BDRVRawState *s = bs->opaque;
  710: 
  711:     switch(s->type) {
  712:     case FTYPE_FD:
  713:         {
  714:             int ret;
  715:             /* XXX: we do not have a true media changed indication. It
  716:                does not work if the floppy is changed without trying
  717:                to read it */
  718:             fd_open(bs);
  719:             ret = s->fd_media_changed;
  720:             s->fd_media_changed = 0;
  721: #ifdef DEBUG_FLOPPY
  722:             printf("Floppy changed=%d\n", ret);
  723: #endif
  724:             return ret;
  725:         }
  726:     default:
  727:         return -ENOTSUP;
  728:     }
  729: }
  730: 
  731: static int raw_eject(BlockDriverState *bs, int eject_flag)
  732: {
  733:     BDRVRawState *s = bs->opaque;
  734: 
  735:     switch(s->type) {
  736:     case FTYPE_CD:
  737:         if (eject_flag) {
  738:             if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
  739:                 perror("CDROMEJECT");
  740:         } else {
  741:             if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
  742:                 perror("CDROMEJECT");
  743:         }
  744:         break;
  745:     case FTYPE_FD:
  746:         {
  747:             int fd;
  748:             if (s->fd >= 0) {
  749:                 close(s->fd);
  750:                 s->fd = -1;
  751:             }
  752:             fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
  753:             if (fd >= 0) {
  754:                 if (ioctl(fd, FDEJECT, 0) < 0)
  755:                     perror("FDEJECT");
  756:                 close(fd);
  757:             }
  758:         }
  759:         break;
  760:     default:
  761:         return -ENOTSUP;
  762:     }
  763:     return 0;
  764: }
  765: 
  766: static int raw_set_locked(BlockDriverState *bs, int locked)
  767: {
  768:     BDRVRawState *s = bs->opaque;
  769: 
  770:     switch(s->type) {
  771:     case FTYPE_CD:
  772:         if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
  773:             /* Note: an error can happen if the distribution automatically
  774:                mounts the CD-ROM */
  775:             //        perror("CDROM_LOCKDOOR");
  776:         }
  777:         break;
  778:     default:
  779:         return -ENOTSUP;
  780:     }
  781:     return 0;
  782: }
  783: 
  784: #else
  785: 
  786: static int raw_is_inserted(BlockDriverState *bs)
  787: {
  788:     return 1;
  789: }
  790: 
  791: static int raw_media_changed(BlockDriverState *bs)
  792: {
  793:     return -ENOTSUP;
  794: }
  795: 
  796: static int raw_eject(BlockDriverState *bs, int eject_flag)
  797: {
  798:     return -ENOTSUP;
  799: }
  800: 
  801: static int raw_set_locked(BlockDriverState *bs, int locked)
  802: {
  803:     return -ENOTSUP;
  804: }
  805: 
  806: #endif /* !linux */
  807: 
  808: BlockDriver bdrv_host_device = {
  809:     "host_device",
  810:     sizeof(BDRVRawState),
  811:     NULL, /* no probe for protocols */
  812:     hdev_open,
  813:     NULL,
  814:     NULL,
  815:     raw_close,
  816:     NULL,
  817:     raw_flush,
  818:     
  819:     .bdrv_aio_read = raw_aio_read,
  820:     .bdrv_aio_write = raw_aio_write,
  821:     .bdrv_aio_cancel = raw_aio_cancel,
  822:     .aiocb_size = sizeof(RawAIOCB),
  823:     .bdrv_pread = raw_pread,
  824:     .bdrv_pwrite = raw_pwrite,
  825:     .bdrv_getlength = raw_getlength,
  826: 
  827:     /* removable device support */
  828:     .bdrv_is_inserted = raw_is_inserted,
  829:     .bdrv_media_changed = raw_media_changed,
  830:     .bdrv_eject = raw_eject,
  831:     .bdrv_set_locked = raw_set_locked,
  832: };
  833: 
  834: #else /* _WIN32 */
  835: 
  836: /* XXX: use another file ? */
  837: #include <winioctl.h>
  838: 
  839: #define FTYPE_FILE 0
  840: #define FTYPE_CD     1
  841: #define FTYPE_HARDDISK 2
  842: 
  843: typedef struct BDRVRawState {
  844:     HANDLE hfile;
  845:     int type;
  846:     char drive_path[16]; /* format: "d:\" */
  847: } BDRVRawState;
  848: 
  849: typedef struct RawAIOCB {
  850:     BlockDriverAIOCB common;
  851:     HANDLE hEvent;
  852:     OVERLAPPED ov;
  853:     int count;
  854: } RawAIOCB;
  855: 
  856: int qemu_ftruncate64(int fd, int64_t length)
  857: {
  858:     LARGE_INTEGER li;
  859:     LONG high;
  860:     HANDLE h;
  861:     BOOL res;
  862: 
  863:     if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
  864: 	return -1;
  865: 
  866:     h = (HANDLE)_get_osfhandle(fd);
  867: 
  868:     /* get current position, ftruncate do not change position */
  869:     li.HighPart = 0;
  870:     li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
  871:     if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
  872: 	return -1;
  873: 
  874:     high = length >> 32;
  875:     if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
  876: 	return -1;
  877:     res = SetEndOfFile(h);
  878: 
  879:     /* back to old position */
  880:     SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
  881:     return res ? 0 : -1;
  882: }
  883: 
  884: static int set_sparse(int fd)
  885: {
  886:     DWORD returned;
  887:     return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
  888: 				 NULL, 0, NULL, 0, &returned, NULL);
  889: }
  890: 
  891: static int raw_open(BlockDriverState *bs, const char *filename, int flags)
  892: {
  893:     BDRVRawState *s = bs->opaque;
  894:     int access_flags, create_flags;
  895:     DWORD overlapped;
  896: 
  897:     s->type = FTYPE_FILE;
  898: 
  899:     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  900:         access_flags = GENERIC_READ | GENERIC_WRITE;
  901:     } else {
  902:         access_flags = GENERIC_READ;
  903:     }
  904:     if (flags & BDRV_O_CREAT) {
  905:         create_flags = CREATE_ALWAYS;
  906:     } else {
  907:         create_flags = OPEN_EXISTING;
  908:     }
  909: #ifdef QEMU_TOOL
  910:     overlapped = FILE_ATTRIBUTE_NORMAL;
  911: #else
  912:     overlapped = FILE_FLAG_OVERLAPPED;
  913: #endif
  914:     s->hfile = CreateFile(filename, access_flags, 
  915:                           FILE_SHARE_READ, NULL,
  916:                           create_flags, overlapped, NULL);
  917:     if (s->hfile == INVALID_HANDLE_VALUE) {
  918:         int err = GetLastError();
  919: 
  920:         if (err == ERROR_ACCESS_DENIED)
  921:             return -EACCES;
  922:         return -1;
  923:     }
  924:     return 0;
  925: }
  926: 
  927: static int raw_pread(BlockDriverState *bs, int64_t offset, 
  928:                      uint8_t *buf, int count)
  929: {
  930:     BDRVRawState *s = bs->opaque;
  931:     OVERLAPPED ov;
  932:     DWORD ret_count;
  933:     int ret;
  934:     
  935:     memset(&ov, 0, sizeof(ov));
  936:     ov.Offset = offset;
  937:     ov.OffsetHigh = offset >> 32;
  938:     ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
  939:     if (!ret) {
  940:         ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  941:         if (!ret)
  942:             return -EIO;
  943:         else
  944:             return ret_count;
  945:     }
  946:     return ret_count;
  947: }
  948: 
  949: static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
  950:                       const uint8_t *buf, int count)
  951: {
  952:     BDRVRawState *s = bs->opaque;
  953:     OVERLAPPED ov;
  954:     DWORD ret_count;
  955:     int ret;
  956:     
  957:     memset(&ov, 0, sizeof(ov));
  958:     ov.Offset = offset;
  959:     ov.OffsetHigh = offset >> 32;
  960:     ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
  961:     if (!ret) {
  962:         ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  963:         if (!ret)
  964:             return -EIO;
  965:         else
  966:             return ret_count;
  967:     }
  968:     return ret_count;
  969: }
  970: 
  971: #if 0
  972: #ifndef QEMU_TOOL
  973: static void raw_aio_cb(void *opaque)
  974: {
  975:     RawAIOCB *acb = opaque;
  976:     BlockDriverState *bs = acb->common.bs;
  977:     BDRVRawState *s = bs->opaque;
  978:     DWORD ret_count;
  979:     int ret;
  980: 
  981:     ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
  982:     if (!ret || ret_count != acb->count) {
  983:         acb->common.cb(acb->common.opaque, -EIO);
  984:     } else {
  985:         acb->common.cb(acb->common.opaque, 0);
  986:     }
  987: }
  988: #endif
  989: 
  990: static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  991:         int64_t sector_num, uint8_t *buf, int nb_sectors,
  992:         BlockDriverCompletionFunc *cb, void *opaque)
  993: {
  994:     RawAIOCB *acb;
  995:     int64_t offset;
  996: 
  997:     acb = qemu_aio_get(bs, cb, opaque);
  998:     if (acb->hEvent) {
  999:         acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 1000:         if (!acb->hEvent) {
 1001:             qemu_aio_release(acb);
 1002:             return NULL;
 1003:         }
 1004:     }
 1005:     memset(&acb->ov, 0, sizeof(acb->ov));
 1006:     offset = sector_num * 512;
 1007:     acb->ov.Offset = offset;
 1008:     acb->ov.OffsetHigh = offset >> 32;
 1009:     acb->ov.hEvent = acb->hEvent;
 1010:     acb->count = nb_sectors * 512;
 1011: #ifndef QEMU_TOOL
 1012:     qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
 1013: #endif
 1014:     return acb;
 1015: }
 1016: 
 1017: static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
 1018:         int64_t sector_num, uint8_t *buf, int nb_sectors,
 1019:         BlockDriverCompletionFunc *cb, void *opaque)
 1020: {
 1021:     BDRVRawState *s = bs->opaque;
 1022:     RawAIOCB *acb;
 1023:     int ret;
 1024: 
 1025:     acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
 1026:     if (!acb)
 1027:         return NULL;
 1028:     ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
 1029:     if (!ret) {
 1030:         qemu_aio_release(acb);
 1031:         return NULL;
 1032:     }
 1033: #ifdef QEMU_TOOL
 1034:     qemu_aio_release(acb);
 1035: #endif
 1036:     return (BlockDriverAIOCB *)acb;
 1037: }
 1038: 
 1039: static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
 1040:         int64_t sector_num, uint8_t *buf, int nb_sectors,
 1041:         BlockDriverCompletionFunc *cb, void *opaque)
 1042: {
 1043:     BDRVRawState *s = bs->opaque;
 1044:     RawAIOCB *acb;
 1045:     int ret;
 1046: 
 1047:     acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
 1048:     if (!acb)
 1049:         return NULL;
 1050:     ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
 1051:     if (!ret) {
 1052:         qemu_aio_release(acb);
 1053:         return NULL;
 1054:     }
 1055: #ifdef QEMU_TOOL
 1056:     qemu_aio_release(acb);
 1057: #endif
 1058:     return (BlockDriverAIOCB *)acb;
 1059: }
 1060: 
 1061: static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
 1062: {
 1063: #ifndef QEMU_TOOL
 1064:     RawAIOCB *acb = (RawAIOCB *)blockacb;
 1065:     BlockDriverState *bs = acb->common.bs;
 1066:     BDRVRawState *s = bs->opaque;
 1067: 
 1068:     qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
 1069:     /* XXX: if more than one async I/O it is not correct */
 1070:     CancelIo(s->hfile);
 1071:     qemu_aio_release(acb);
 1072: #endif
 1073: }
 1074: #endif /* #if 0 */
 1075: 
 1076: static void raw_flush(BlockDriverState *bs)
 1077: {
 1078:     BDRVRawState *s = bs->opaque;
 1079:     FlushFileBuffers(s->hfile);
 1080: }
 1081: 
 1082: static void raw_close(BlockDriverState *bs)
 1083: {
 1084:     BDRVRawState *s = bs->opaque;
 1085:     CloseHandle(s->hfile);
 1086: }
 1087: 
 1088: static int raw_truncate(BlockDriverState *bs, int64_t offset)
 1089: {
 1090:     BDRVRawState *s = bs->opaque;
 1091:     DWORD low, high;
 1092: 
 1093:     low = offset;
 1094:     high = offset >> 32;
 1095:     if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
 1096: 	return -EIO;
 1097:     if (!SetEndOfFile(s->hfile))
 1098:         return -EIO;
 1099:     return 0;
 1100: }
 1101: 
 1102: static int64_t raw_getlength(BlockDriverState *bs)
 1103: {
 1104:     BDRVRawState *s = bs->opaque;
 1105:     LARGE_INTEGER l;
 1106:     ULARGE_INTEGER available, total, total_free; 
 1107:     DISK_GEOMETRY dg;
 1108:     DWORD count;
 1109:     BOOL status;
 1110: 
 1111:     switch(s->type) {
 1112:     case FTYPE_FILE:
 1113:         l.LowPart = GetFileSize(s->hfile, &l.HighPart);
 1114:         if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
 1115:             return -EIO;
 1116:         break;
 1117:     case FTYPE_CD:
 1118:         if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
 1119:             return -EIO;
 1120:         l.QuadPart = total.QuadPart;
 1121:         break;
 1122:     case FTYPE_HARDDISK:
 1123:         status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
 1124:                                  NULL, 0, &dg, sizeof(dg), &count, NULL);
 1125:         if (status != FALSE) {
 1126:             l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
 1127:                 * dg.SectorsPerTrack * dg.BytesPerSector;
 1128:         }
 1129:         break;
 1130:     default:
 1131:         return -EIO;
 1132:     }
 1133:     return l.QuadPart;
 1134: }
 1135: 
 1136: static int raw_create(const char *filename, int64_t total_size,
 1137:                       const char *backing_file, int flags)
 1138: {
 1139:     int fd;
 1140: 
 1141:     if (flags || backing_file)
 1142:         return -ENOTSUP;
 1143: 
 1144:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
 1145:               0644);
 1146:     if (fd < 0)
 1147:         return -EIO;
 1148:     set_sparse(fd);
 1149:     ftruncate(fd, total_size * 512);
 1150:     close(fd);
 1151:     return 0;
 1152: }
 1153: 
 1154: void qemu_aio_init(void)
 1155: {
 1156: }
 1157: 
 1158: void qemu_aio_poll(void)
 1159: {
 1160: }
 1161: 
 1162: void qemu_aio_flush(void)
 1163: {
 1164: }
 1165: 
 1166: void qemu_aio_wait_start(void)
 1167: {
 1168: }
 1169: 
 1170: void qemu_aio_wait(void)
 1171: {
 1172: #ifndef QEMU_TOOL
 1173:     qemu_bh_poll();
 1174: #endif
 1175: }
 1176: 
 1177: void qemu_aio_wait_end(void)
 1178: {
 1179: }
 1180: 
 1181: BlockDriver bdrv_raw = {
 1182:     "raw",
 1183:     sizeof(BDRVRawState),
 1184:     NULL, /* no probe for protocols */
 1185:     raw_open,
 1186:     NULL,
 1187:     NULL,
 1188:     raw_close,
 1189:     raw_create,
 1190:     raw_flush,
 1191:     
 1192: #if 0
 1193:     .bdrv_aio_read = raw_aio_read,
 1194:     .bdrv_aio_write = raw_aio_write,
 1195:     .bdrv_aio_cancel = raw_aio_cancel,
 1196:     .aiocb_size = sizeof(RawAIOCB);
 1197: #endif
 1198:     .protocol_name = "file",
 1199:     .bdrv_pread = raw_pread,
 1200:     .bdrv_pwrite = raw_pwrite,
 1201:     .bdrv_truncate = raw_truncate,
 1202:     .bdrv_getlength = raw_getlength,
 1203: };
 1204: 
 1205: /***********************************************/
 1206: /* host device */
 1207: 
 1208: static int find_cdrom(char *cdrom_name, int cdrom_name_size)
 1209: {
 1210:     char drives[256], *pdrv = drives;
 1211:     UINT type;
 1212: 
 1213:     memset(drives, 0, sizeof(drives));
 1214:     GetLogicalDriveStrings(sizeof(drives), drives);
 1215:     while(pdrv[0] != '\0') {
 1216:         type = GetDriveType(pdrv);
 1217:         switch(type) {
 1218:         case DRIVE_CDROM:
 1219:             snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
 1220:             return 0;
 1221:             break;
 1222:         }
 1223:         pdrv += lstrlen(pdrv) + 1;
 1224:     }
 1225:     return -1;
 1226: }
 1227: 
 1228: static int find_device_type(BlockDriverState *bs, const char *filename)
 1229: {
 1230:     BDRVRawState *s = bs->opaque;
 1231:     UINT type;
 1232:     const char *p;
 1233: 
 1234:     if (strstart(filename, "\\\\.\\", &p) ||
 1235:         strstart(filename, "//./", &p)) {
 1236:         if (stristart(p, "PhysicalDrive", NULL))
 1237:             return FTYPE_HARDDISK;
 1238:         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
 1239:         type = GetDriveType(s->drive_path);
 1240:         if (type == DRIVE_CDROM)
 1241:             return FTYPE_CD;
 1242:         else
 1243:             return FTYPE_FILE;
 1244:     } else {
 1245:         return FTYPE_FILE;
 1246:     }
 1247: }
 1248: 
 1249: static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
 1250: {
 1251:     BDRVRawState *s = bs->opaque;
 1252:     int access_flags, create_flags;
 1253:     DWORD overlapped;
 1254:     char device_name[64];
 1255: 
 1256:     if (strstart(filename, "/dev/cdrom", NULL)) {
 1257:         if (find_cdrom(device_name, sizeof(device_name)) < 0)
 1258:             return -ENOENT;
 1259:         filename = device_name;
 1260:     } else {
 1261:         /* transform drive letters into device name */
 1262:         if (((filename[0] >= 'a' && filename[0] <= 'z') ||
 1263:              (filename[0] >= 'A' && filename[0] <= 'Z')) &&
 1264:             filename[1] == ':' && filename[2] == '\0') {
 1265:             snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
 1266:             filename = device_name;
 1267:         }
 1268:     }
 1269:     s->type = find_device_type(bs, filename);
 1270:     
 1271:     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
 1272:         access_flags = GENERIC_READ | GENERIC_WRITE;
 1273:     } else {
 1274:         access_flags = GENERIC_READ;
 1275:     }
 1276:     create_flags = OPEN_EXISTING;
 1277: 
 1278: #ifdef QEMU_TOOL
 1279:     overlapped = FILE_ATTRIBUTE_NORMAL;
 1280: #else
 1281:     overlapped = FILE_FLAG_OVERLAPPED;
 1282: #endif
 1283:     s->hfile = CreateFile(filename, access_flags, 
 1284:                           FILE_SHARE_READ, NULL,
 1285:                           create_flags, overlapped, NULL);
 1286:     if (s->hfile == INVALID_HANDLE_VALUE) {
 1287:         int err = GetLastError();
 1288: 
 1289:         if (err == ERROR_ACCESS_DENIED)
 1290:             return -EACCES;
 1291:         return -1;
 1292:     }
 1293:     return 0;
 1294: }
 1295: 
 1296: #if 0
 1297: /***********************************************/
 1298: /* removable device additionnal commands */
 1299: 
 1300: static int raw_is_inserted(BlockDriverState *bs)
 1301: {
 1302:     return 1;
 1303: }
 1304: 
 1305: static int raw_media_changed(BlockDriverState *bs)
 1306: {
 1307:     return -ENOTSUP;
 1308: }
 1309: 
 1310: static int raw_eject(BlockDriverState *bs, int eject_flag)
 1311: {
 1312:     DWORD ret_count;
 1313: 
 1314:     if (s->type == FTYPE_FILE)
 1315:         return -ENOTSUP;
 1316:     if (eject_flag) {
 1317:         DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA, 
 1318:                         NULL, 0, NULL, 0, &lpBytesReturned, NULL);
 1319:     } else {
 1320:         DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA, 
 1321:                         NULL, 0, NULL, 0, &lpBytesReturned, NULL);
 1322:     }
 1323: }
 1324: 
 1325: static int raw_set_locked(BlockDriverState *bs, int locked)
 1326: {
 1327:     return -ENOTSUP;
 1328: }
 1329: #endif
 1330: 
 1331: BlockDriver bdrv_host_device = {
 1332:     "host_device",
 1333:     sizeof(BDRVRawState),
 1334:     NULL, /* no probe for protocols */
 1335:     hdev_open,
 1336:     NULL,
 1337:     NULL,
 1338:     raw_close,
 1339:     NULL,
 1340:     raw_flush,
 1341:     
 1342: #if 0
 1343:     .bdrv_aio_read = raw_aio_read,
 1344:     .bdrv_aio_write = raw_aio_write,
 1345:     .bdrv_aio_cancel = raw_aio_cancel,
 1346:     .aiocb_size = sizeof(RawAIOCB);
 1347: #endif
 1348:     .bdrv_pread = raw_pread,
 1349:     .bdrv_pwrite = raw_pwrite,
 1350:     .bdrv_getlength = raw_getlength,
 1351: };
 1352: #endif /* _WIN32 */

unix.superglobalmegacorp.com