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