Search
lxdream.org :: lxdream/src/drivers/cd_osx.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/cd_osx.c
changeset 1023:264e2fd90be8
prev786:8f6ece92500e
author nkeynes
date Fri Jun 26 13:53:54 2009 +0000 (14 years ago)
permissions -rw-r--r--
last change Do the save-to-temp and rename thing when saving VMUs, for the sake of limiting corruption possibilities
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * OSX native cd-rom driver.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <IOKit/IOKitLib.h>
    20 #include <IOKit/IOBSD.h>
    21 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
    22 #include <IOKit/storage/IOCDMediaBSDClient.h>
    23 #include <IOKit/storage/IOCDTypes.h>
    24 #include <sys/param.h>
    25 #include <errno.h>
    26 #include <stdio.h>
    27 #include <string.h>
    28 #include <paths.h>
    29 #include "gdrom/gddriver.h"
    30 #include "gdrom/packet.h"
    31 #include "drivers/osx_iokit.h"
    33 #define MAXTOCENTRIES 600  /* This is a fairly generous overestimate really */
    34 #define MAXTOCSIZE 4 + (MAXTOCENTRIES*11)
    36 static gboolean cdrom_osx_image_is_valid( FILE *f );
    37 static gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f );
    38 static gdrom_error_t cdrom_osx_read_toc( gdrom_disc_t disc );
    39 static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t sector,
    40                                             int mode, unsigned char *buf, uint32_t *length );
    42 struct gdrom_image_class cdrom_device_class = { "osx", NULL,
    43         cdrom_osx_image_is_valid, cdrom_osx_open_device };
    45 #define OSX_DRIVE(disc) ( (osx_cdrom_drive_t)(((gdrom_disc_t)disc)->impl_data) )
    47 static void cdrom_osx_destroy( gdrom_disc_t disc, gboolean close_fh )
    48 {
    49     if( close_fh ) {
    50         osx_cdrom_close_drive( OSX_DRIVE(disc) );
    51     }
    52     gdrom_disc_destroy( disc, FALSE ); /* chain to the main destroy */
    53 }
    55 static void cdrom_osx_media_changed( osx_cdrom_drive_t drive, gboolean present,
    56                                      void *user_data )
    57 {
    58     gdrom_disc_t disc = (gdrom_disc_t)user_data;
    59     if( present ) {
    60         cdrom_osx_read_toc( disc );
    61     } else {
    62         disc->disc_type = IDE_DISC_NONE;
    63         disc->track_count = 0;        
    64     }
    65 }
    68 static gdrom_disc_t cdrom_osx_new( const char *name, osx_cdrom_drive_t drive )
    69 {
    70     char tmp[strlen(name)+7];
    71     sprintf( tmp, "dvd://%s", name );
    72     gdrom_disc_t disc = gdrom_disc_new(tmp, NULL);
    73     disc->impl_data = drive;
    75     disc->read_sector = cdrom_osx_read_sector;
    76     disc->destroy = cdrom_osx_destroy;
    77     cdrom_osx_read_toc(disc);
    78     osx_cdrom_set_media_changed_callback( drive, cdrom_osx_media_changed, disc );
    79     return (gdrom_disc_t)disc;
    80 }
    82 gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )
    83 {
    84     gdrom_disc_t result = NULL;
    86     osx_cdrom_drive_t drive = osx_cdrom_open_drive(path);
    87     if( drive == NULL ) {
    88         return NULL;
    89     } else {
    90         return cdrom_osx_new( path, drive );
    91     }
    92 }
    96 static gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, char *iopath, void *ptr )
    97 {
    98     GList **list = (GList **)ptr;
    99     char tmp1[sizeof(io_string_t) + 6];
   100     char tmp2[512];
   101     snprintf( tmp1, sizeof(tmp1), "dvd://%s", iopath );
   102     snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product );
   103     *list = g_list_append( *list, gdrom_device_new( tmp1, tmp2 ) );
   104     return FALSE;
   105 }
   107 GList *cdrom_get_native_devices(void)
   108 {
   109     GList *list = NULL;
   110     find_cdrom_drive(cdrom_enum_callback, &list);
   112     osx_register_iokit_notifications();
   113     return list;
   114 }
   118 static gboolean cdrom_osx_image_is_valid( FILE *f )
   119 {
   120     return FALSE;
   121 }
   123 static gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f )
   124 {
   125     return NULL;
   126 }
   128 static gdrom_error_t cdrom_osx_read_toc( gdrom_disc_t disc )
   129 {
   130     osx_cdrom_drive_t drive = OSX_DRIVE(disc);
   132     int fh = osx_cdrom_get_media_handle(drive);
   133     if( fh == -1 ) {
   134         disc->disc_type = IDE_DISC_NONE;
   135         disc->track_count = 0;
   136         return -1;
   137     } else {
   138         unsigned char buf[MAXTOCSIZE];
   139         dk_cd_read_toc_t readtoc;
   140         memset( &readtoc, 0, sizeof(readtoc) );
   141         readtoc.format = 2;
   142         readtoc.formatAsTime = 0;
   143         readtoc.address.session = 0;
   144         readtoc.bufferLength = sizeof(buf);
   145         readtoc.buffer = buf;
   147         if( ioctl(fh, DKIOCCDREADTOC, &readtoc ) == -1 ) {
   148             WARN( "Failed to read TOC (%s)", strerror(errno) );
   149             disc->disc_type = IDE_DISC_NONE;
   150             disc->track_count = 0;
   151             return -1;
   152         } else {
   153             mmc_parse_toc2( disc, buf );
   154         }
   155     }
   156     return 0;
   157 }
   159 static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t lba,
   160                                             int mode, unsigned char *buf, uint32_t *length ) 
   161 {
   162     int real_lba = lba - 150;
   163     int sector_size = 2352;
   164     int direct_read = 1;
   165     char data[MAX_SECTOR_SIZE];
   166     osx_cdrom_drive_t drive = OSX_DRIVE(disc);
   168     int fh = osx_cdrom_get_media_handle(drive);
   169     if( fh == -1 ) {
   170         return PKT_ERR_NODISC;
   171     } else {
   172         dk_cd_read_t readcd;
   173         memset( &readcd, 0, sizeof(readcd) );
   174         readcd.buffer = buf;
   176         // This is complicated by needing to know the exact read size. Gah.
   177         if( READ_CD_RAW(mode) ) {
   178             sector_size = 2352;
   179             readcd.sectorArea = 0xF8; 
   180         } else if ( READ_CD_MODE(mode) == READ_CD_MODE_ANY ) {
   181             /* Sector could be anything - need to do a raw read and then parse
   182              * the requested data out ourselves
   183              */
   184             int track_no = gdrom_disc_get_track_by_lba( disc, lba );
   185             struct gdrom_track *track = &disc->track[track_no-1];
   187             sector_size = 2352;
   188             if( track->mode == GDROM_CDDA ) {
   189                 readcd.sectorArea = kCDSectorAreaUser;
   190             } else {
   191                 readcd.sectorArea = 0xF8;
   192                 readcd.buffer = data;
   193                 direct_read = 0;
   194             }
   195         } else {
   196             // This is incomplete...
   197             if( READ_CD_DATA(mode) ) {
   198                 readcd.sectorArea = kCDSectorAreaUser;
   199                 switch( READ_CD_MODE(mode) ) {
   200                 case READ_CD_MODE_CDDA:
   201                     sector_size = 2352;
   202                     break;
   203                 case READ_CD_MODE_1:
   204                 case READ_CD_MODE_2_FORM_1:
   205                     sector_size = 2048;
   206                     break;
   207                 case READ_CD_MODE_2:
   208                     sector_size = 2336;
   209                     break;
   210                 case READ_CD_MODE_2_FORM_2:
   211                     sector_size = 2324;
   212                     break;
   213                 }
   214             }
   215         }
   217         readcd.offset = sector_size * real_lba;
   218         readcd.sectorType = READ_CD_MODE(mode)>>1;
   219         readcd.bufferLength = sector_size;
   220         if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {
   221             return -1;
   222         }
   224         if( direct_read ) {
   225             *length = sector_size;
   226         } else {
   227             gdrom_extract_raw_data_sector( data, mode, buf, length );
   228         }
   229         return 0;
   230     }
   231 }
.