filename | src/drivers/cd_osx.c |
changeset | 1023:264e2fd90be8 |
prev | 786:8f6ece92500e |
author | nkeynes |
date | Sun Dec 20 21:01:03 2009 +1000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Fix 64-bit x86 disassembly Add crash-report hook to SIGILL and SIGBUS |
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 }
.