089a1f4a99d6bfaff4202290bd94b057b3c597dd
[qemu] / block-raw-posix.c
1 /*
2  * Block driver for RAW files (posix)
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 "qemu-common.h"
25 #ifndef QEMU_IMG
26 #include "qemu-timer.h"
27 #include "exec-all.h"
28 #endif
29 #include "block_int.h"
30 #include <assert.h>
31 #include <aio.h>
32
33 #ifdef CONFIG_COCOA
34 #include <paths.h>
35 #include <sys/param.h>
36 #include <IOKit/IOKitLib.h>
37 #include <IOKit/IOBSD.h>
38 #include <IOKit/storage/IOMediaBSDClient.h>
39 #include <IOKit/storage/IOMedia.h>
40 #include <IOKit/storage/IOCDMedia.h>
41 //#include <IOKit/storage/IOCDTypes.h>
42 #include <CoreFoundation/CoreFoundation.h>
43 #endif
44
45 #ifdef __sun__
46 #define _POSIX_PTHREAD_SEMANTICS 1
47 #include <signal.h>
48 #include <sys/dkio.h>
49 #endif
50 #ifdef __linux__
51 #include <sys/ioctl.h>
52 #include <linux/cdrom.h>
53 #include <linux/fd.h>
54 #endif
55 #ifdef __FreeBSD__
56 #include <sys/disk.h>
57 #endif
58
59 //#define DEBUG_FLOPPY
60
61 //#define DEBUG_BLOCK
62 #if defined(DEBUG_BLOCK) && !defined(QEMU_IMG)
63 #define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)  \
64     { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
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, %" PRId64 ", %p, %d) [%" PRId64
154                               "] lseek failed : %d = %s\n",
155                               s->fd, bs->filename, offset, buf, count,
156                               bs->total_sectors, errno, strerror(errno));
157         }
158         return -1;
159     }
160     s->lseek_err_cnt=0;
161
162     ret = read(s->fd, buf, count);
163     if (ret == count)
164         goto label__raw_read__success;
165
166     DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
167                       "] read failed %d : %d = %s\n",
168                       s->fd, bs->filename, offset, buf, count,
169                       bs->total_sectors, ret, errno, strerror(errno));
170
171     /* Try harder for CDrom. */
172     if (bs->type == BDRV_TYPE_CDROM) {
173         lseek(s->fd, offset, SEEK_SET);
174         ret = read(s->fd, buf, count);
175         if (ret == count)
176             goto label__raw_read__success;
177         lseek(s->fd, offset, SEEK_SET);
178         ret = read(s->fd, buf, count);
179         if (ret == count)
180             goto label__raw_read__success;
181
182         DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
183                           "] retry read failed %d : %d = %s\n",
184                           s->fd, bs->filename, offset, buf, count,
185                           bs->total_sectors, ret, errno, strerror(errno));
186     }
187
188 label__raw_read__success:
189
190     return ret;
191 }
192
193 static int raw_pwrite(BlockDriverState *bs, int64_t offset,
194                       const uint8_t *buf, int count)
195 {
196     BDRVRawState *s = bs->opaque;
197     int ret;
198
199     ret = fd_open(bs);
200     if (ret < 0)
201         return ret;
202
203     if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
204         ++(s->lseek_err_cnt);
205         if(s->lseek_err_cnt) {
206             DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
207                               PRId64 "] lseek failed : %d = %s\n",
208                               s->fd, bs->filename, offset, buf, count,
209                               bs->total_sectors, errno, strerror(errno));
210         }
211         return -1;
212     }
213     s->lseek_err_cnt = 0;
214
215     ret = write(s->fd, buf, count);
216     if (ret == count)
217         goto label__raw_write__success;
218
219     DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
220                       "] write failed %d : %d = %s\n",
221                       s->fd, bs->filename, offset, buf, count,
222                       bs->total_sectors, ret, errno, strerror(errno));
223
224 label__raw_write__success:
225
226     return ret;
227 }
228
229 /***********************************************************/
230 /* Unix AIO using POSIX AIO */
231
232 typedef struct RawAIOCB {
233     BlockDriverAIOCB common;
234     struct aiocb aiocb;
235     struct RawAIOCB *next;
236 } RawAIOCB;
237
238 static int aio_sig_num = SIGUSR2;
239 static RawAIOCB *first_aio; /* AIO issued */
240 static int aio_initialized = 0;
241
242 static void aio_signal_handler(int signum)
243 {
244 #ifndef QEMU_IMG
245     CPUState *env = cpu_single_env;
246     if (env) {
247         /* stop the currently executing cpu because a timer occured */
248         cpu_interrupt(env, CPU_INTERRUPT_EXIT);
249 #ifdef USE_KQEMU
250         if (env->kqemu_enabled) {
251             kqemu_cpu_interrupt(env);
252         }
253 #endif
254     }
255 #endif
256 }
257
258 void qemu_aio_init(void)
259 {
260     struct sigaction act;
261
262     aio_initialized = 1;
263
264     sigfillset(&act.sa_mask);
265     act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
266     act.sa_handler = aio_signal_handler;
267     sigaction(aio_sig_num, &act, NULL);
268
269 #if defined(__GLIBC__) && defined(__linux__)
270     {
271         /* XXX: aio thread exit seems to hang on RedHat 9 and this init
272            seems to fix the problem. */
273         struct aioinit ai;
274         memset(&ai, 0, sizeof(ai));
275         ai.aio_threads = 1;
276         ai.aio_num = 1;
277         ai.aio_idle_time = 365 * 100000;
278         aio_init(&ai);
279     }
280 #endif
281 }
282
283 void qemu_aio_poll(void)
284 {
285     RawAIOCB *acb, **pacb;
286     int ret;
287
288     for(;;) {
289         pacb = &first_aio;
290         for(;;) {
291             acb = *pacb;
292             if (!acb)
293                 goto the_end;
294             ret = aio_error(&acb->aiocb);
295             if (ret == ECANCELED) {
296                 /* remove the request */
297                 *pacb = acb->next;
298                 qemu_aio_release(acb);
299             } else if (ret != EINPROGRESS) {
300                 /* end of aio */
301                 if (ret == 0) {
302                     ret = aio_return(&acb->aiocb);
303                     if (ret == acb->aiocb.aio_nbytes)
304                         ret = 0;
305                     else
306                         ret = -EINVAL;
307                 } else {
308                     ret = -ret;
309                 }
310                 /* remove the request */
311                 *pacb = acb->next;
312                 /* call the callback */
313                 acb->common.cb(acb->common.opaque, ret);
314                 qemu_aio_release(acb);
315                 break;
316             } else {
317                 pacb = &acb->next;
318             }
319         }
320     }
321  the_end: ;
322 }
323
324 /* Wait for all IO requests to complete.  */
325 void qemu_aio_flush(void)
326 {
327     qemu_aio_wait_start();
328     qemu_aio_poll();
329     while (first_aio) {
330         qemu_aio_wait();
331     }
332     qemu_aio_wait_end();
333 }
334
335 /* wait until at least one AIO was handled */
336 static sigset_t wait_oset;
337
338 void qemu_aio_wait_start(void)
339 {
340     sigset_t set;
341
342     if (!aio_initialized)
343         qemu_aio_init();
344     sigemptyset(&set);
345     sigaddset(&set, aio_sig_num);
346     sigprocmask(SIG_BLOCK, &set, &wait_oset);
347 }
348
349 void qemu_aio_wait(void)
350 {
351     sigset_t set;
352     int nb_sigs;
353
354 #ifndef QEMU_IMG
355     if (qemu_bh_poll())
356         return;
357 #endif
358     sigemptyset(&set);
359     sigaddset(&set, aio_sig_num);
360     sigwait(&set, &nb_sigs);
361     qemu_aio_poll();
362 }
363
364 void qemu_aio_wait_end(void)
365 {
366     sigprocmask(SIG_SETMASK, &wait_oset, NULL);
367 }
368
369 static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
370         int64_t sector_num, uint8_t *buf, int nb_sectors,
371         BlockDriverCompletionFunc *cb, void *opaque)
372 {
373     BDRVRawState *s = bs->opaque;
374     RawAIOCB *acb;
375
376     if (fd_open(bs) < 0)
377         return NULL;
378
379     acb = qemu_aio_get(bs, cb, opaque);
380     if (!acb)
381         return NULL;
382     acb->aiocb.aio_fildes = s->fd;
383     acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
384     acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
385     acb->aiocb.aio_buf = buf;
386     acb->aiocb.aio_nbytes = nb_sectors * 512;
387     acb->aiocb.aio_offset = sector_num * 512;
388     acb->next = first_aio;
389     first_aio = acb;
390     return acb;
391 }
392
393 static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
394         int64_t sector_num, uint8_t *buf, int nb_sectors,
395         BlockDriverCompletionFunc *cb, void *opaque)
396 {
397     RawAIOCB *acb;
398
399     acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
400     if (!acb)
401         return NULL;
402     if (aio_read(&acb->aiocb) < 0) {
403         qemu_aio_release(acb);
404         return NULL;
405     }
406     return &acb->common;
407 }
408
409 static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
410         int64_t sector_num, const uint8_t *buf, int nb_sectors,
411         BlockDriverCompletionFunc *cb, void *opaque)
412 {
413     RawAIOCB *acb;
414
415     acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
416     if (!acb)
417         return NULL;
418     if (aio_write(&acb->aiocb) < 0) {
419         qemu_aio_release(acb);
420         return NULL;
421     }
422     return &acb->common;
423 }
424
425 static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
426 {
427     int ret;
428     RawAIOCB *acb = (RawAIOCB *)blockacb;
429     RawAIOCB **pacb;
430
431     ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
432     if (ret == AIO_NOTCANCELED) {
433         /* fail safe: if the aio could not be canceled, we wait for
434            it */
435         while (aio_error(&acb->aiocb) == EINPROGRESS);
436     }
437
438     /* remove the callback from the queue */
439     pacb = &first_aio;
440     for(;;) {
441         if (*pacb == NULL) {
442             break;
443         } else if (*pacb == acb) {
444             *pacb = acb->next;
445             qemu_aio_release(acb);
446             break;
447         }
448         pacb = &acb->next;
449     }
450 }
451
452 static void raw_close(BlockDriverState *bs)
453 {
454     BDRVRawState *s = bs->opaque;
455     if (s->fd >= 0) {
456         close(s->fd);
457         s->fd = -1;
458     }
459 }
460
461 static int raw_truncate(BlockDriverState *bs, int64_t offset)
462 {
463     BDRVRawState *s = bs->opaque;
464     if (s->type != FTYPE_FILE)
465         return -ENOTSUP;
466     if (ftruncate(s->fd, offset) < 0)
467         return -errno;
468     return 0;
469 }
470
471 static int64_t  raw_getlength(BlockDriverState *bs)
472 {
473     BDRVRawState *s = bs->opaque;
474     int fd = s->fd;
475     int64_t size;
476 #ifdef _BSD
477     struct stat sb;
478 #endif
479 #ifdef __sun__
480     struct dk_minfo minfo;
481     int rv;
482 #endif
483     int ret;
484
485     ret = fd_open(bs);
486     if (ret < 0)
487         return ret;
488
489 #ifdef _BSD
490     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
491 #ifdef DIOCGMEDIASIZE
492         if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
493 #endif
494 #ifdef CONFIG_COCOA
495         size = LONG_LONG_MAX;
496 #else
497         size = lseek(fd, 0LL, SEEK_END);
498 #endif
499     } else
500 #endif
501 #ifdef __sun__
502     /*
503      * use the DKIOCGMEDIAINFO ioctl to read the size.
504      */
505     rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
506     if ( rv != -1 ) {
507         size = minfo.dki_lbsize * minfo.dki_capacity;
508     } else /* there are reports that lseek on some devices
509               fails, but irc discussion said that contingency
510               on contingency was overkill */
511 #endif
512     {
513         size = lseek(fd, 0, SEEK_END);
514     }
515     return size;
516 }
517
518 static int raw_create(const char *filename, int64_t total_size,
519                       const char *backing_file, int flags)
520 {
521     int fd;
522
523     if (flags || backing_file)
524         return -ENOTSUP;
525
526     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
527               0644);
528     if (fd < 0)
529         return -EIO;
530     ftruncate(fd, total_size * 512);
531     close(fd);
532     return 0;
533 }
534
535 static void raw_flush(BlockDriverState *bs)
536 {
537     BDRVRawState *s = bs->opaque;
538     fsync(s->fd);
539 }
540
541 BlockDriver bdrv_raw = {
542     "raw",
543     sizeof(BDRVRawState),
544     NULL, /* no probe for protocols */
545     raw_open,
546     NULL,
547     NULL,
548     raw_close,
549     raw_create,
550     raw_flush,
551
552     .bdrv_aio_read = raw_aio_read,
553     .bdrv_aio_write = raw_aio_write,
554     .bdrv_aio_cancel = raw_aio_cancel,
555     .aiocb_size = sizeof(RawAIOCB),
556     .protocol_name = "file",
557     .bdrv_pread = raw_pread,
558     .bdrv_pwrite = raw_pwrite,
559     .bdrv_truncate = raw_truncate,
560     .bdrv_getlength = raw_getlength,
561 };
562
563 /***********************************************/
564 /* host device */
565
566 #ifdef CONFIG_COCOA
567 static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
568 static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
569
570 kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
571 {
572     kern_return_t       kernResult;
573     mach_port_t     masterPort;
574     CFMutableDictionaryRef  classesToMatch;
575
576     kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
577     if ( KERN_SUCCESS != kernResult ) {
578         printf( "IOMasterPort returned %d\n", kernResult );
579     }
580
581     classesToMatch = IOServiceMatching( kIOCDMediaClass );
582     if ( classesToMatch == NULL ) {
583         printf( "IOServiceMatching returned a NULL dictionary.\n" );
584     } else {
585     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
586     }
587     kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
588     if ( KERN_SUCCESS != kernResult )
589     {
590         printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
591     }
592
593     return kernResult;
594 }
595
596 kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
597 {
598     io_object_t     nextMedia;
599     kern_return_t   kernResult = KERN_FAILURE;
600     *bsdPath = '\0';
601     nextMedia = IOIteratorNext( mediaIterator );
602     if ( nextMedia )
603     {
604         CFTypeRef   bsdPathAsCFString;
605     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
606         if ( bsdPathAsCFString ) {
607             size_t devPathLength;
608             strcpy( bsdPath, _PATH_DEV );
609             strcat( bsdPath, "r" );
610             devPathLength = strlen( bsdPath );
611             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
612                 kernResult = KERN_SUCCESS;
613             }
614             CFRelease( bsdPathAsCFString );
615         }
616         IOObjectRelease( nextMedia );
617     }
618
619     return kernResult;
620 }
621
622 #endif
623
624 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
625 {
626     BDRVRawState *s = bs->opaque;
627     int fd, open_flags, ret;
628
629 #ifdef CONFIG_COCOA
630     if (strstart(filename, "/dev/cdrom", NULL)) {
631         kern_return_t kernResult;
632         io_iterator_t mediaIterator;
633         char bsdPath[ MAXPATHLEN ];
634         int fd;
635
636         kernResult = FindEjectableCDMedia( &mediaIterator );
637         kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
638
639         if ( bsdPath[ 0 ] != '\0' ) {
640             strcat(bsdPath,"s0");
641             /* some CDs don't have a partition 0 */
642             fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
643             if (fd < 0) {
644                 bsdPath[strlen(bsdPath)-1] = '1';
645             } else {
646                 close(fd);
647             }
648             filename = bsdPath;
649         }
650
651         if ( mediaIterator )
652             IOObjectRelease( mediaIterator );
653     }
654 #endif
655     open_flags = O_BINARY;
656     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
657         open_flags |= O_RDWR;
658     } else {
659         open_flags |= O_RDONLY;
660         bs->read_only = 1;
661     }
662
663     s->type = FTYPE_FILE;
664 #if defined(__linux__)
665     if (strstart(filename, "/dev/cd", NULL)) {
666         /* open will not fail even if no CD is inserted */
667         open_flags |= O_NONBLOCK;
668         s->type = FTYPE_CD;
669     } else if (strstart(filename, "/dev/fd", NULL)) {
670         s->type = FTYPE_FD;
671         s->fd_open_flags = open_flags;
672         /* open will not fail even if no floppy is inserted */
673         open_flags |= O_NONBLOCK;
674     }
675 #endif
676     fd = open(filename, open_flags, 0644);
677     if (fd < 0) {
678         ret = -errno;
679         if (ret == -EROFS)
680             ret = -EACCES;
681         return ret;
682     }
683     s->fd = fd;
684 #if defined(__linux__)
685     /* close fd so that we can reopen it as needed */
686     if (s->type == FTYPE_FD) {
687         close(s->fd);
688         s->fd = -1;
689         s->fd_media_changed = 1;
690     }
691 #endif
692     return 0;
693 }
694
695 #if defined(__linux__) && !defined(QEMU_IMG)
696
697 /* Note: we do not have a reliable method to detect if the floppy is
698    present. The current method is to try to open the floppy at every
699    I/O and to keep it opened during a few hundreds of ms. */
700 static int fd_open(BlockDriverState *bs)
701 {
702     BDRVRawState *s = bs->opaque;
703     int last_media_present;
704
705     if (s->type != FTYPE_FD)
706         return 0;
707     last_media_present = (s->fd >= 0);
708     if (s->fd >= 0 &&
709         (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
710         close(s->fd);
711         s->fd = -1;
712 #ifdef DEBUG_FLOPPY
713         printf("Floppy closed\n");
714 #endif
715     }
716     if (s->fd < 0) {
717         if (s->fd_got_error &&
718             (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
719 #ifdef DEBUG_FLOPPY
720             printf("No floppy (open delayed)\n");
721 #endif
722             return -EIO;
723         }
724         s->fd = open(bs->filename, s->fd_open_flags);
725         if (s->fd < 0) {
726             s->fd_error_time = qemu_get_clock(rt_clock);
727             s->fd_got_error = 1;
728             if (last_media_present)
729                 s->fd_media_changed = 1;
730 #ifdef DEBUG_FLOPPY
731             printf("No floppy\n");
732 #endif
733             return -EIO;
734         }
735 #ifdef DEBUG_FLOPPY
736         printf("Floppy opened\n");
737 #endif
738     }
739     if (!last_media_present)
740         s->fd_media_changed = 1;
741     s->fd_open_time = qemu_get_clock(rt_clock);
742     s->fd_got_error = 0;
743     return 0;
744 }
745 #else
746 static int fd_open(BlockDriverState *bs)
747 {
748     return 0;
749 }
750 #endif
751
752 #if defined(__linux__)
753
754 static int raw_is_inserted(BlockDriverState *bs)
755 {
756     BDRVRawState *s = bs->opaque;
757     int ret;
758
759     switch(s->type) {
760     case FTYPE_CD:
761         ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
762         if (ret == CDS_DISC_OK)
763             return 1;
764         else
765             return 0;
766         break;
767     case FTYPE_FD:
768         ret = fd_open(bs);
769         return (ret >= 0);
770     default:
771         return 1;
772     }
773 }
774
775 /* currently only used by fdc.c, but a CD version would be good too */
776 static int raw_media_changed(BlockDriverState *bs)
777 {
778     BDRVRawState *s = bs->opaque;
779
780     switch(s->type) {
781     case FTYPE_FD:
782         {
783             int ret;
784             /* XXX: we do not have a true media changed indication. It
785                does not work if the floppy is changed without trying
786                to read it */
787             fd_open(bs);
788             ret = s->fd_media_changed;
789             s->fd_media_changed = 0;
790 #ifdef DEBUG_FLOPPY
791             printf("Floppy changed=%d\n", ret);
792 #endif
793             return ret;
794         }
795     default:
796         return -ENOTSUP;
797     }
798 }
799
800 static int raw_eject(BlockDriverState *bs, int eject_flag)
801 {
802     BDRVRawState *s = bs->opaque;
803
804     switch(s->type) {
805     case FTYPE_CD:
806         if (eject_flag) {
807             if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
808                 perror("CDROMEJECT");
809         } else {
810             if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
811                 perror("CDROMEJECT");
812         }
813         break;
814     case FTYPE_FD:
815         {
816             int fd;
817             if (s->fd >= 0) {
818                 close(s->fd);
819                 s->fd = -1;
820             }
821             fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
822             if (fd >= 0) {
823                 if (ioctl(fd, FDEJECT, 0) < 0)
824                     perror("FDEJECT");
825                 close(fd);
826             }
827         }
828         break;
829     default:
830         return -ENOTSUP;
831     }
832     return 0;
833 }
834
835 static int raw_set_locked(BlockDriverState *bs, int locked)
836 {
837     BDRVRawState *s = bs->opaque;
838
839     switch(s->type) {
840     case FTYPE_CD:
841         if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
842             /* Note: an error can happen if the distribution automatically
843                mounts the CD-ROM */
844             //        perror("CDROM_LOCKDOOR");
845         }
846         break;
847     default:
848         return -ENOTSUP;
849     }
850     return 0;
851 }
852
853 #else
854
855 static int raw_is_inserted(BlockDriverState *bs)
856 {
857     return 1;
858 }
859
860 static int raw_media_changed(BlockDriverState *bs)
861 {
862     return -ENOTSUP;
863 }
864
865 static int raw_eject(BlockDriverState *bs, int eject_flag)
866 {
867     return -ENOTSUP;
868 }
869
870 static int raw_set_locked(BlockDriverState *bs, int locked)
871 {
872     return -ENOTSUP;
873 }
874
875 #endif /* !linux */
876
877 BlockDriver bdrv_host_device = {
878     "host_device",
879     sizeof(BDRVRawState),
880     NULL, /* no probe for protocols */
881     hdev_open,
882     NULL,
883     NULL,
884     raw_close,
885     NULL,
886     raw_flush,
887
888     .bdrv_aio_read = raw_aio_read,
889     .bdrv_aio_write = raw_aio_write,
890     .bdrv_aio_cancel = raw_aio_cancel,
891     .aiocb_size = sizeof(RawAIOCB),
892     .bdrv_pread = raw_pread,
893     .bdrv_pwrite = raw_pwrite,
894     .bdrv_getlength = raw_getlength,
895
896     /* removable device support */
897     .bdrv_is_inserted = raw_is_inserted,
898     .bdrv_media_changed = raw_media_changed,
899     .bdrv_eject = raw_eject,
900     .bdrv_set_locked = raw_set_locked,
901 };