Commit 3b0d4f61c917c4612b561d75b33a11f4da00738b
1 parent
87f48e6a
OS X: support for the built in CD-ROM drive (Mike Kronenberg)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1583 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
107 additions
and
1 deletions
block.c
| ... | ... | @@ -32,9 +32,79 @@ |
| 32 | 32 | #include <sys/disk.h> |
| 33 | 33 | #endif |
| 34 | 34 | |
| 35 | +#ifdef CONFIG_COCOA | |
| 36 | +#include <paths.h> | |
| 37 | +#include <sys/param.h> | |
| 38 | +#include <IOKit/IOKitLib.h> | |
| 39 | +#include <IOKit/IOBSD.h> | |
| 40 | +#include <IOKit/storage/IOMediaBSDClient.h> | |
| 41 | +#include <IOKit/storage/IOMedia.h> | |
| 42 | +#include <IOKit/storage/IOCDMedia.h> | |
| 43 | +//#include <IOKit/storage/IOCDTypes.h> | |
| 44 | +#include <CoreFoundation/CoreFoundation.h> | |
| 45 | +#endif | |
| 46 | + | |
| 35 | 47 | static BlockDriverState *bdrv_first; |
| 36 | 48 | static BlockDriver *first_drv; |
| 37 | 49 | |
| 50 | +#ifdef CONFIG_COCOA | |
| 51 | +static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ); | |
| 52 | +static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ); | |
| 53 | + | |
| 54 | +kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ) | |
| 55 | +{ | |
| 56 | + kern_return_t kernResult; | |
| 57 | + mach_port_t masterPort; | |
| 58 | + CFMutableDictionaryRef classesToMatch; | |
| 59 | + | |
| 60 | + kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort ); | |
| 61 | + if ( KERN_SUCCESS != kernResult ) { | |
| 62 | + printf( "IOMasterPort returned %d\n", kernResult ); | |
| 63 | + } | |
| 64 | + | |
| 65 | + classesToMatch = IOServiceMatching( kIOCDMediaClass ); | |
| 66 | + if ( classesToMatch == NULL ) { | |
| 67 | + printf( "IOServiceMatching returned a NULL dictionary.\n" ); | |
| 68 | + } else { | |
| 69 | + CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); | |
| 70 | + } | |
| 71 | + kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator ); | |
| 72 | + if ( KERN_SUCCESS != kernResult ) | |
| 73 | + { | |
| 74 | + printf( "IOServiceGetMatchingServices returned %d\n", kernResult ); | |
| 75 | + } | |
| 76 | + | |
| 77 | + return kernResult; | |
| 78 | +} | |
| 79 | + | |
| 80 | +kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ) | |
| 81 | +{ | |
| 82 | + io_object_t nextMedia; | |
| 83 | + kern_return_t kernResult = KERN_FAILURE; | |
| 84 | + *bsdPath = '\0'; | |
| 85 | + nextMedia = IOIteratorNext( mediaIterator ); | |
| 86 | + if ( nextMedia ) | |
| 87 | + { | |
| 88 | + CFTypeRef bsdPathAsCFString; | |
| 89 | + bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); | |
| 90 | + if ( bsdPathAsCFString ) { | |
| 91 | + size_t devPathLength; | |
| 92 | + strcpy( bsdPath, _PATH_DEV ); | |
| 93 | + strcat( bsdPath, "r" ); | |
| 94 | + devPathLength = strlen( bsdPath ); | |
| 95 | + if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) { | |
| 96 | + kernResult = KERN_SUCCESS; | |
| 97 | + } | |
| 98 | + CFRelease( bsdPathAsCFString ); | |
| 99 | + } | |
| 100 | + IOObjectRelease( nextMedia ); | |
| 101 | + } | |
| 102 | + | |
| 103 | + return kernResult; | |
| 104 | +} | |
| 105 | + | |
| 106 | +#endif | |
| 107 | + | |
| 38 | 108 | void bdrv_register(BlockDriver *bdrv) |
| 39 | 109 | { |
| 40 | 110 | bdrv->next = first_drv; |
| ... | ... | @@ -118,6 +188,12 @@ static BlockDriver *find_image_format(const char *filename) |
| 118 | 188 | bufsize = sectorsize; |
| 119 | 189 | } |
| 120 | 190 | #endif |
| 191 | +#ifdef CONFIG_COCOA | |
| 192 | + u_int32_t blockSize = 512; | |
| 193 | + if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) { | |
| 194 | + bufsize = blockSize; | |
| 195 | + } | |
| 196 | +#endif | |
| 121 | 197 | buf = qemu_malloc(bufsize); |
| 122 | 198 | if (!buf) |
| 123 | 199 | return NULL; |
| ... | ... | @@ -145,6 +221,32 @@ static BlockDriver *find_image_format(const char *filename) |
| 145 | 221 | |
| 146 | 222 | int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot) |
| 147 | 223 | { |
| 224 | +#ifdef CONFIG_COCOA | |
| 225 | + if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) { | |
| 226 | + kern_return_t kernResult; | |
| 227 | + io_iterator_t mediaIterator; | |
| 228 | + char bsdPath[ MAXPATHLEN ]; | |
| 229 | + int fd; | |
| 230 | + | |
| 231 | + kernResult = FindEjectableCDMedia( &mediaIterator ); | |
| 232 | + kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) ); | |
| 233 | + | |
| 234 | + if ( bsdPath[ 0 ] != '\0' ) { | |
| 235 | + strcat(bsdPath,"s0"); | |
| 236 | + /* some CDs don't have a partition 0 */ | |
| 237 | + fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); | |
| 238 | + if (fd < 0) { | |
| 239 | + bsdPath[strlen(bsdPath)-1] = '1'; | |
| 240 | + } else { | |
| 241 | + close(fd); | |
| 242 | + } | |
| 243 | + filename = bsdPath; | |
| 244 | + } | |
| 245 | + | |
| 246 | + if ( mediaIterator ) | |
| 247 | + IOObjectRelease( mediaIterator ); | |
| 248 | + } | |
| 249 | +#endif | |
| 148 | 250 | return bdrv_open2(bs, filename, snapshot, NULL); |
| 149 | 251 | } |
| 150 | 252 | |
| ... | ... | @@ -567,7 +669,11 @@ static int raw_open(BlockDriverState *bs, const char *filename) |
| 567 | 669 | #ifdef DIOCGMEDIASIZE |
| 568 | 670 | if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) |
| 569 | 671 | #endif |
| 570 | - size = lseek(fd, 0LL, SEEK_END); | |
| 672 | +#ifdef CONFIG_COCOA | |
| 673 | + size = LONG_LONG_MAX; | |
| 674 | +#else | |
| 675 | + size = lseek(fd, 0LL, SEEK_END); | |
| 676 | +#endif | |
| 571 | 677 | } else |
| 572 | 678 | #endif |
| 573 | 679 | { | ... | ... |