2 * Block driver for RAW files
4 * Copyright (c) 2006 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
25 #include "block_int.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>
47 #define _POSIX_PTHREAD_SEMANTICS 1
52 #include <sys/ioctl.h>
53 #include <linux/cdrom.h>
60 //#define DEBUG_FLOPPY
63 #if defined(DEBUG_BLOCK) && !defined(QEMU_TOOL)
64 #define DEBUG_BLOCK_PRINT(formatCstr, args...) fprintf(logfile, formatCstr, ##args); fflush(logfile)
66 #define DEBUG_BLOCK_PRINT(formatCstr, args...)
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
77 typedef struct BDRVRawState
{
80 unsigned int lseek_err_cnt
;
81 #if defined(__linux__)
82 /* linux floppy specific */
85 int64_t fd_error_time
;
91 static int fd_open(BlockDriverState
*bs
);
93 static int raw_open(BlockDriverState
*bs
, const char *filename
, int flags
)
95 BDRVRawState
*s
= bs
->opaque
;
96 int fd
, open_flags
, ret
;
100 open_flags
= O_BINARY
;
101 if ((flags
& BDRV_O_ACCESS
) == O_RDWR
) {
102 open_flags
|= O_RDWR
;
104 open_flags
|= O_RDONLY
;
107 if (flags
& BDRV_O_CREAT
)
108 open_flags
|= O_CREAT
| O_TRUNC
;
110 s
->type
= FTYPE_FILE
;
112 fd
= open(filename
, open_flags
, 0644);
123 /* XXX: use host sector size if necessary with:
124 #ifdef DIOCGSECTORSIZE
126 unsigned int sectorsize = 512;
127 if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) &&
128 sectorsize > bufsize)
129 bufsize = sectorsize;
133 u_int32_t blockSize = 512;
134 if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
140 static int raw_pread(BlockDriverState
*bs
, int64_t offset
,
141 uint8_t *buf
, int count
)
143 BDRVRawState
*s
= bs
->opaque
;
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
));
161 ret
= read(s
->fd
, buf
, count
);
163 goto label__raw_read__success
;
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
));
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
);
174 goto label__raw_read__success
;
175 lseek(s
->fd
, offset
, SEEK_SET
);
176 ret
= read(s
->fd
, buf
, count
);
178 goto label__raw_read__success
;
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
));
187 label__raw_read__success
:
192 static int raw_pwrite(BlockDriverState
*bs
, int64_t offset
,
193 const uint8_t *buf
, int count
)
195 BDRVRawState
*s
= bs
->opaque
;
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
));
211 s
->lseek_err_cnt
= 0;
213 ret
= write(s
->fd
, buf
, count
);
215 goto label__raw_write__success
;
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
));
223 label__raw_write__success
:
228 /***********************************************************/
229 /* Unix AIO using POSIX AIO */
231 typedef struct RawAIOCB
{
232 BlockDriverAIOCB common
;
234 struct RawAIOCB
*next
;
237 static int aio_sig_num
= SIGUSR2
;
238 static RawAIOCB
*first_aio
; /* AIO issued */
239 static int aio_initialized
= 0;
241 static void aio_signal_handler(int signum
)
244 CPUState
*env
= cpu_single_env
;
246 /* stop the currently executing cpu because a timer occured */
247 cpu_interrupt(env
, CPU_INTERRUPT_EXIT
);
249 if (env
->kqemu_enabled
) {
250 kqemu_cpu_interrupt(env
);
257 void qemu_aio_init(void)
259 struct sigaction act
;
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
);
268 #if defined(__GLIBC__) && defined(__linux__)
270 /* XXX: aio thread exit seems to hang on RedHat 9 and this init
271 seems to fix the problem. */
273 memset(&ai
, 0, sizeof(ai
));
276 ai
.aio_idle_time
= 365 * 100000;
282 void qemu_aio_poll(void)
284 RawAIOCB
*acb
, **pacb
;
293 ret
= aio_error(&acb
->aiocb
);
294 if (ret
== ECANCELED
) {
295 /* remove the request */
297 qemu_aio_release(acb
);
298 } else if (ret
!= EINPROGRESS
) {
301 ret
= aio_return(&acb
->aiocb
);
302 if (ret
== acb
->aiocb
.aio_nbytes
)
309 /* remove the request */
311 /* call the callback */
312 acb
->common
.cb(acb
->common
.opaque
, ret
);
313 qemu_aio_release(acb
);
323 /* Wait for all IO requests to complete. */
324 void qemu_aio_flush(void)
326 qemu_aio_wait_start();
334 /* wait until at least one AIO was handled */
335 static sigset_t wait_oset
;
337 void qemu_aio_wait_start(void)
341 if (!aio_initialized
)
344 sigaddset(&set
, aio_sig_num
);
345 sigprocmask(SIG_BLOCK
, &set
, &wait_oset
);
348 void qemu_aio_wait(void)
358 sigaddset(&set
, aio_sig_num
);
359 sigwait(&set
, &nb_sigs
);
363 void qemu_aio_wait_end(void)
365 sigprocmask(SIG_SETMASK
, &wait_oset
, NULL
);
368 static RawAIOCB
*raw_aio_setup(BlockDriverState
*bs
,
369 int64_t sector_num
, uint8_t *buf
, int nb_sectors
,
370 BlockDriverCompletionFunc
*cb
, void *opaque
)
372 BDRVRawState
*s
= bs
->opaque
;
378 acb
= qemu_aio_get(bs
, cb
, opaque
);
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
;
392 static BlockDriverAIOCB
*raw_aio_read(BlockDriverState
*bs
,
393 int64_t sector_num
, uint8_t *buf
, int nb_sectors
,
394 BlockDriverCompletionFunc
*cb
, void *opaque
)
398 acb
= raw_aio_setup(bs
, sector_num
, buf
, nb_sectors
, cb
, opaque
);
401 if (aio_read(&acb
->aiocb
) < 0) {
402 qemu_aio_release(acb
);
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
)
414 acb
= raw_aio_setup(bs
, sector_num
, (uint8_t*)buf
, nb_sectors
, cb
, opaque
);
417 if (aio_write(&acb
->aiocb
) < 0) {
418 qemu_aio_release(acb
);
424 static void raw_aio_cancel(BlockDriverAIOCB
*blockacb
)
427 RawAIOCB
*acb
= (RawAIOCB
*)blockacb
;
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
434 while (aio_error(&acb
->aiocb
) == EINPROGRESS
);
437 /* remove the callback from the queue */
442 } else if (*pacb
== acb
) {
444 qemu_aio_release(acb
);
451 static void raw_close(BlockDriverState
*bs
)
453 BDRVRawState
*s
= bs
->opaque
;
460 static int raw_truncate(BlockDriverState
*bs
, int64_t offset
)
462 BDRVRawState
*s
= bs
->opaque
;
463 if (s
->type
!= FTYPE_FILE
)
465 if (ftruncate(s
->fd
, offset
) < 0)
470 static int64_t raw_getlength(BlockDriverState
*bs
)
472 BDRVRawState
*s
= bs
->opaque
;
479 struct dk_minfo minfo
;
489 if (!fstat(fd
, &sb
) && (S_IFCHR
& sb
.st_mode
)) {
490 #ifdef DIOCGMEDIASIZE
491 if (ioctl(fd
, DIOCGMEDIASIZE
, (off_t
*)&size
))
494 size
= LONG_LONG_MAX
;
496 size
= lseek(fd
, 0LL, SEEK_END
);
502 * use the DKIOCGMEDIAINFO ioctl to read the size.
504 rv
= ioctl ( fd
, DKIOCGMEDIAINFO
, &minfo
);
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 */
512 size
= lseek(fd
, 0, SEEK_END
);
517 static int raw_create(const char *filename
, int64_t total_size
,
518 const char *backing_file
, int flags
)
522 if (flags
|| backing_file
)
525 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
,
529 ftruncate(fd
, total_size
* 512);
534 static void raw_flush(BlockDriverState
*bs
)
536 BDRVRawState
*s
= bs
->opaque
;
540 BlockDriver bdrv_raw
= {
542 sizeof(BDRVRawState
),
543 NULL
, /* no probe for protocols */
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
,
562 /***********************************************/
566 static kern_return_t
FindEjectableCDMedia( io_iterator_t
*mediaIterator
);
567 static kern_return_t
GetBSDPath( io_iterator_t mediaIterator
, char *bsdPath
, CFIndex maxPathSize
);
569 kern_return_t
FindEjectableCDMedia( io_iterator_t
*mediaIterator
)
571 kern_return_t kernResult
;
572 mach_port_t masterPort
;
573 CFMutableDictionaryRef classesToMatch
;
575 kernResult
= IOMasterPort( MACH_PORT_NULL
, &masterPort
);
576 if ( KERN_SUCCESS
!= kernResult
) {
577 printf( "IOMasterPort returned %d\n", kernResult
);
580 classesToMatch
= IOServiceMatching( kIOCDMediaClass
);
581 if ( classesToMatch
== NULL
) {
582 printf( "IOServiceMatching returned a NULL dictionary.\n" );
584 CFDictionarySetValue( classesToMatch
, CFSTR( kIOMediaEjectableKey
), kCFBooleanTrue
);
586 kernResult
= IOServiceGetMatchingServices( masterPort
, classesToMatch
, mediaIterator
);
587 if ( KERN_SUCCESS
!= kernResult
)
589 printf( "IOServiceGetMatchingServices returned %d\n", kernResult
);
595 kern_return_t
GetBSDPath( io_iterator_t mediaIterator
, char *bsdPath
, CFIndex maxPathSize
)
597 io_object_t nextMedia
;
598 kern_return_t kernResult
= KERN_FAILURE
;
600 nextMedia
= IOIteratorNext( mediaIterator
);
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
;
613 CFRelease( bsdPathAsCFString
);
615 IOObjectRelease( nextMedia
);
623 static int hdev_open(BlockDriverState
*bs
, const char *filename
, int flags
)
625 BDRVRawState
*s
= bs
->opaque
;
626 int fd
, open_flags
, ret
;
629 if (strstart(filename
, "/dev/cdrom", NULL
)) {
630 kern_return_t kernResult
;
631 io_iterator_t mediaIterator
;
632 char bsdPath
[ MAXPATHLEN
];
635 kernResult
= FindEjectableCDMedia( &mediaIterator
);
636 kernResult
= GetBSDPath( mediaIterator
, bsdPath
, sizeof( bsdPath
) );
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
);
643 bsdPath
[strlen(bsdPath
)-1] = '1';
651 IOObjectRelease( mediaIterator
);
654 open_flags
= O_BINARY
;
655 if ((flags
& BDRV_O_ACCESS
) == O_RDWR
) {
656 open_flags
|= O_RDWR
;
658 open_flags
|= O_RDONLY
;
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
;
668 } else if (strstart(filename
, "/dev/fd", NULL
)) {
670 s
->fd_open_flags
= open_flags
;
671 /* open will not fail even if no floppy is inserted */
672 open_flags
|= O_NONBLOCK
;
675 fd
= open(filename
, open_flags
, 0644);
683 #if defined(__linux__)
684 /* close fd so that we can reopen it as needed */
685 if (s
->type
== FTYPE_FD
) {
688 s
->fd_media_changed
= 1;
694 #if defined(__linux__) && !defined(QEMU_TOOL)
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
)
701 BDRVRawState
*s
= bs
->opaque
;
702 int last_media_present
;
704 if (s
->type
!= FTYPE_FD
)
706 last_media_present
= (s
->fd
>= 0);
708 (qemu_get_clock(rt_clock
) - s
->fd_open_time
) >= FD_OPEN_TIMEOUT
) {
712 printf("Floppy closed\n");
716 if (s
->fd_got_error
&&
717 (qemu_get_clock(rt_clock
) - s
->fd_error_time
) < FD_OPEN_TIMEOUT
) {
719 printf("No floppy (open delayed)\n");
723 s
->fd
= open(bs
->filename
, s
->fd_open_flags
);
725 s
->fd_error_time
= qemu_get_clock(rt_clock
);
727 if (last_media_present
)
728 s
->fd_media_changed
= 1;
730 printf("No floppy\n");
735 printf("Floppy opened\n");
738 if (!last_media_present
)
739 s
->fd_media_changed
= 1;
740 s
->fd_open_time
= qemu_get_clock(rt_clock
);
745 static int fd_open(BlockDriverState
*bs
)
751 #if defined(__linux__)
753 static int raw_is_inserted(BlockDriverState
*bs
)
755 BDRVRawState
*s
= bs
->opaque
;
760 ret
= ioctl(s
->fd
, CDROM_DRIVE_STATUS
, CDSL_CURRENT
);
761 if (ret
== CDS_DISC_OK
)
774 /* currently only used by fdc.c, but a CD version would be good too */
775 static int raw_media_changed(BlockDriverState
*bs
)
777 BDRVRawState
*s
= bs
->opaque
;
783 /* XXX: we do not have a true media changed indication. It
784 does not work if the floppy is changed without trying
787 ret
= s
->fd_media_changed
;
788 s
->fd_media_changed
= 0;
790 printf("Floppy changed=%d\n", ret
);
799 static int raw_eject(BlockDriverState
*bs
, int eject_flag
)
801 BDRVRawState
*s
= bs
->opaque
;
806 if (ioctl (s
->fd
, CDROMEJECT
, NULL
) < 0)
807 perror("CDROMEJECT");
809 if (ioctl (s
->fd
, CDROMCLOSETRAY
, NULL
) < 0)
810 perror("CDROMEJECT");
820 fd
= open(bs
->filename
, s
->fd_open_flags
| O_NONBLOCK
);
822 if (ioctl(fd
, FDEJECT
, 0) < 0)
834 static int raw_set_locked(BlockDriverState
*bs
, int locked
)
836 BDRVRawState
*s
= bs
->opaque
;
840 if (ioctl (s
->fd
, CDROM_LOCKDOOR
, locked
) < 0) {
841 /* Note: an error can happen if the distribution automatically
843 // perror("CDROM_LOCKDOOR");
854 static int raw_is_inserted(BlockDriverState
*bs
)
859 static int raw_media_changed(BlockDriverState
*bs
)
864 static int raw_eject(BlockDriverState
*bs
, int eject_flag
)
869 static int raw_set_locked(BlockDriverState
*bs
, int locked
)
876 BlockDriver bdrv_host_device
= {
878 sizeof(BDRVRawState
),
879 NULL
, /* no probe for protocols */
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
,
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
,
904 /* XXX: use another file ? */
905 #include <winioctl.h>
909 #define FTYPE_HARDDISK 2
911 typedef struct BDRVRawState
{
914 char drive_path
[16]; /* format: "d:\" */
917 typedef struct RawAIOCB
{
918 BlockDriverAIOCB common
;
924 int qemu_ftruncate64(int fd
, int64_t length
)
931 if ((GetVersion() & 0x80000000UL
) && (length
>> 32) != 0)
934 h
= (HANDLE
)_get_osfhandle(fd
);
936 /* get current position, ftruncate do not change position */
938 li
.LowPart
= SetFilePointer (h
, 0, &li
.HighPart
, FILE_CURRENT
);
939 if (li
.LowPart
== 0xffffffffUL
&& GetLastError() != NO_ERROR
)
943 if (!SetFilePointer(h
, (DWORD
) length
, &high
, FILE_BEGIN
))
945 res
= SetEndOfFile(h
);
947 /* back to old position */
948 SetFilePointer(h
, li
.LowPart
, &li
.HighPart
, FILE_BEGIN
);
952 static int set_sparse(int fd
)
955 return (int) DeviceIoControl((HANDLE
)_get_osfhandle(fd
), FSCTL_SET_SPARSE
,
956 NULL
, 0, NULL
, 0, &returned
, NULL
);
959 static int raw_open(BlockDriverState
*bs
, const char *filename
, int flags
)
961 BDRVRawState
*s
= bs
->opaque
;
962 int access_flags
, create_flags
;
965 s
->type
= FTYPE_FILE
;
967 if ((flags
& BDRV_O_ACCESS
) == O_RDWR
) {
968 access_flags
= GENERIC_READ
| GENERIC_WRITE
;
970 access_flags
= GENERIC_READ
;
972 if (flags
& BDRV_O_CREAT
) {
973 create_flags
= CREATE_ALWAYS
;
975 create_flags
= OPEN_EXISTING
;
978 overlapped
= FILE_ATTRIBUTE_NORMAL
;
980 overlapped
= FILE_FLAG_OVERLAPPED
;
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();
988 if (err
== ERROR_ACCESS_DENIED
)
995 static int raw_pread(BlockDriverState
*bs
, int64_t offset
,
996 uint8_t *buf
, int count
)
998 BDRVRawState
*s
= bs
->opaque
;
1003 memset(&ov
, 0, sizeof(ov
));
1005 ov
.OffsetHigh
= offset
>> 32;
1006 ret
= ReadFile(s
->hfile
, buf
, count
, &ret_count
, &ov
);
1008 ret
= GetOverlappedResult(s
->hfile
, &ov
, &ret_count
, TRUE
);
1017 static int raw_pwrite(BlockDriverState
*bs
, int64_t offset
,
1018 const uint8_t *buf
, int count
)
1020 BDRVRawState
*s
= bs
->opaque
;
1025 memset(&ov
, 0, sizeof(ov
));
1027 ov
.OffsetHigh
= offset
>> 32;
1028 ret
= WriteFile(s
->hfile
, buf
, count
, &ret_count
, &ov
);
1030 ret
= GetOverlappedResult(s
->hfile
, &ov
, &ret_count
, TRUE
);
1041 static void raw_aio_cb(void *opaque
)
1043 RawAIOCB
*acb
= opaque
;
1044 BlockDriverState
*bs
= acb
->common
.bs
;
1045 BDRVRawState
*s
= bs
->opaque
;
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
);
1053 acb
->common
.cb(acb
->common
.opaque
, 0);
1058 static RawAIOCB
*raw_aio_setup(BlockDriverState
*bs
,
1059 int64_t sector_num
, uint8_t *buf
, int nb_sectors
,
1060 BlockDriverCompletionFunc
*cb
, void *opaque
)
1065 acb
= qemu_aio_get(bs
, cb
, opaque
);
1067 acb
->hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
1069 qemu_aio_release(acb
);
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;
1080 qemu_add_wait_object(acb
->ov
.hEvent
, raw_aio_cb
, acb
);
1085 static BlockDriverAIOCB
*raw_aio_read(BlockDriverState
*bs
,
1086 int64_t sector_num
, uint8_t *buf
, int nb_sectors
,
1087 BlockDriverCompletionFunc
*cb
, void *opaque
)
1089 BDRVRawState
*s
= bs
->opaque
;
1093 acb
= raw_aio_setup(bs
, sector_num
, buf
, nb_sectors
, cb
, opaque
);
1096 ret
= ReadFile(s
->hfile
, buf
, acb
->count
, NULL
, &acb
->ov
);
1098 qemu_aio_release(acb
);
1102 qemu_aio_release(acb
);
1104 return (BlockDriverAIOCB
*)acb
;
1107 static BlockDriverAIOCB
*raw_aio_write(BlockDriverState
*bs
,
1108 int64_t sector_num
, uint8_t *buf
, int nb_sectors
,
1109 BlockDriverCompletionFunc
*cb
, void *opaque
)
1111 BDRVRawState
*s
= bs
->opaque
;
1115 acb
= raw_aio_setup(bs
, sector_num
, buf
, nb_sectors
, cb
, opaque
);
1118 ret
= WriteFile(s
->hfile
, buf
, acb
->count
, NULL
, &acb
->ov
);
1120 qemu_aio_release(acb
);
1124 qemu_aio_release(acb
);
1126 return (BlockDriverAIOCB
*)acb
;
1129 static void raw_aio_cancel(BlockDriverAIOCB
*blockacb
)
1132 RawAIOCB
*acb
= (RawAIOCB
*)blockacb
;
1133 BlockDriverState
*bs
= acb
->common
.bs
;
1134 BDRVRawState
*s
= bs
->opaque
;
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 */
1139 qemu_aio_release(acb
);
1144 static void raw_flush(BlockDriverState
*bs
)
1146 BDRVRawState
*s
= bs
->opaque
;
1147 FlushFileBuffers(s
->hfile
);
1150 static void raw_close(BlockDriverState
*bs
)
1152 BDRVRawState
*s
= bs
->opaque
;
1153 CloseHandle(s
->hfile
);
1156 static int raw_truncate(BlockDriverState
*bs
, int64_t offset
)
1158 BDRVRawState
*s
= bs
->opaque
;
1162 high
= offset
>> 32;
1163 if (!SetFilePointer(s
->hfile
, low
, &high
, FILE_BEGIN
))
1165 if (!SetEndOfFile(s
->hfile
))
1170 static int64_t raw_getlength(BlockDriverState
*bs
)
1172 BDRVRawState
*s
= bs
->opaque
;
1174 ULARGE_INTEGER available
, total
, total_free
;
1181 l
.LowPart
= GetFileSize(s
->hfile
, &l
.HighPart
);
1182 if (l
.LowPart
== 0xffffffffUL
&& GetLastError() != NO_ERROR
)
1186 if (!GetDiskFreeSpaceEx(s
->drive_path
, &available
, &total
, &total_free
))
1188 l
.QuadPart
= total
.QuadPart
;
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
;
1204 static int raw_create(const char *filename
, int64_t total_size
,
1205 const char *backing_file
, int flags
)
1209 if (flags
|| backing_file
)
1212 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
,
1217 ftruncate(fd
, total_size
* 512);
1222 void qemu_aio_init(void)
1226 void qemu_aio_poll(void)
1230 void qemu_aio_flush(void)
1234 void qemu_aio_wait_start(void)
1238 void qemu_aio_wait(void)
1245 void qemu_aio_wait_end(void)
1249 BlockDriver bdrv_raw
= {
1251 sizeof(BDRVRawState
),
1252 NULL
, /* no probe for protocols */
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
);
1266 .protocol_name
= "file",
1267 .bdrv_pread
= raw_pread
,
1268 .bdrv_pwrite
= raw_pwrite
,
1269 .bdrv_truncate
= raw_truncate
,
1270 .bdrv_getlength
= raw_getlength
,
1273 /***********************************************/
1276 static int find_cdrom(char *cdrom_name
, int cdrom_name_size
)
1278 char drives
[256], *pdrv
= drives
;
1281 memset(drives
, 0, sizeof(drives
));
1282 GetLogicalDriveStrings(sizeof(drives
), drives
);
1283 while(pdrv
[0] != '\0') {
1284 type
= GetDriveType(pdrv
);
1287 snprintf(cdrom_name
, cdrom_name_size
, "\\\\.\\%c:", pdrv
[0]);
1291 pdrv
+= lstrlen(pdrv
) + 1;
1296 static int find_device_type(BlockDriverState
*bs
, const char *filename
)
1298 BDRVRawState
*s
= bs
->opaque
;
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
)
1317 static int hdev_open(BlockDriverState
*bs
, const char *filename
, int flags
)
1319 BDRVRawState
*s
= bs
->opaque
;
1320 int access_flags
, create_flags
;
1322 char device_name
[64];
1324 if (strstart(filename
, "/dev/cdrom", NULL
)) {
1325 if (find_cdrom(device_name
, sizeof(device_name
)) < 0)
1327 filename
= device_name
;
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
;
1337 s
->type
= find_device_type(bs
, filename
);
1339 if ((flags
& BDRV_O_ACCESS
) == O_RDWR
) {
1340 access_flags
= GENERIC_READ
| GENERIC_WRITE
;
1342 access_flags
= GENERIC_READ
;
1344 create_flags
= OPEN_EXISTING
;
1347 overlapped
= FILE_ATTRIBUTE_NORMAL
;
1349 overlapped
= FILE_FLAG_OVERLAPPED
;
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();
1357 if (err
== ERROR_ACCESS_DENIED
)
1365 /***********************************************/
1366 /* removable device additional commands */
1368 static int raw_is_inserted(BlockDriverState
*bs
)
1373 static int raw_media_changed(BlockDriverState
*bs
)
1378 static int raw_eject(BlockDriverState
*bs
, int eject_flag
)
1382 if (s
->type
== FTYPE_FILE
)
1385 DeviceIoControl(s
->hfile
, IOCTL_STORAGE_EJECT_MEDIA
,
1386 NULL
, 0, NULL
, 0, &lpBytesReturned
, NULL
);
1388 DeviceIoControl(s
->hfile
, IOCTL_STORAGE_LOAD_MEDIA
,
1389 NULL
, 0, NULL
, 0, &lpBytesReturned
, NULL
);
1393 static int raw_set_locked(BlockDriverState
*bs
, int locked
)
1399 BlockDriver bdrv_host_device
= {
1401 sizeof(BDRVRawState
),
1402 NULL
, /* no probe for protocols */
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
);
1416 .bdrv_pread
= raw_pread
,
1417 .bdrv_pwrite
= raw_pwrite
,
1418 .bdrv_getlength
= raw_getlength
,