ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/sys_darwin.cpp
Revision: 1.4
Committed: 2004-01-26T11:11:33Z (20 years, 5 months ago) by nigel
Branch: MAIN
Changes since 1.3: +150 -8 lines
Log Message:
Special serial/floppy device locating code

File Contents

# Content
1 /*
2 * $Id: sys_darwin.cpp,v 1.3 2004/01/20 23:31:46 nigel Exp $
3 *
4 * sys_darwin.cpp - Extra Darwin system dependant routines. Called by:
5 *
6 * sys_unix.cpp - System dependent routines, Unix implementation
7 *
8 * Based on Apple's CDROMSample.c and Evan Jones' cd-discid.c patches
9 *
10 * Basilisk II (C) 1997-2004 Christian Bauer
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27 #import <errno.h>
28 #import <sys/param.h>
29 #import <IOKit/IOKitLib.h>
30 #import <IOKit/IOBSD.h>
31 #import <IOKit/serial/IOSerialKeys.h>
32 #import <IOKit/storage/IOMedia.h>
33 #import <IOKit/storage/IOMediaBSDClient.h>
34 #import <IOKit/storage/IOBlockStorageDevice.h>
35 #import <IOKit/storage/IOCDMedia.h>
36 #import <IOKit/storage/IOCDMediaBSDClient.h>
37 #import <CoreFoundation/CoreFoundation.h>
38
39 #import "sysdeps.h"
40
41 #import "prefs.h"
42
43 #define DEBUG 0
44 #import "debug.h"
45
46
47
48 /*
49 * This gets called when no "cdrom" prefs items are found
50 * It scans for available CD-ROM drives and adds appropriate prefs items
51 */
52
53 void DarwinAddCDROMPrefs(void)
54 {
55 mach_port_t masterPort; // The way to talk to the kernel
56 io_iterator_t allCDs; // List of CD drives on the system
57 CFMutableDictionaryRef classesToMatch;
58 io_object_t nextCD;
59
60
61 // Don't scan for drives if nocdrom option given
62 if ( PrefsFindBool("nocdrom") )
63 return;
64
65
66 // Let this task talk to the guts of the kernel:
67 if ( IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS )
68 bug("IOMasterPort failed. Won't be able to do anything with CD drives\n");
69
70
71 // CD media are instances of class kIOCDMediaClass
72 classesToMatch = IOServiceMatching(kIOCDMediaClass);
73 if ( classesToMatch )
74 {
75 // Narrow the search a little further. Each IOMedia object
76 // has a property with key kIOMediaEjectable. We limit
77 // the match only to those CDs that are actually ejectable
78 CFDictionarySetValue(classesToMatch,
79 CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
80 }
81
82 if ( IOServiceGetMatchingServices(masterPort,
83 classesToMatch, &allCDs) != KERN_SUCCESS )
84 {
85 D(bug("IOServiceGetMatchingServices failed. No CD media drives found?\n"));
86 return;
87 }
88
89
90 // Iterate through each CD drive
91 while ( nextCD = IOIteratorNext(allCDs))
92 {
93 char bsdPath[MAXPATHLEN];
94 CFTypeRef bsdPathAsCFString =
95 IORegistryEntryCreateCFProperty(nextCD,
96 CFSTR(kIOBSDNameKey),
97 kCFAllocatorDefault, 0);
98 *bsdPath = '\0';
99 if ( bsdPathAsCFString )
100 {
101 size_t devPathLength;
102
103 strcpy(bsdPath, "/dev/");
104 devPathLength = strlen(bsdPath);
105
106 if ( CFStringGetCString((const __CFString *)bsdPathAsCFString,
107 bsdPath + devPathLength,
108 MAXPATHLEN - devPathLength,
109 kCFStringEncodingASCII) )
110 {
111 D(bug("CDROM BSD path: %s\n", bsdPath));
112 PrefsAddString("cdrom", bsdPath);
113 }
114 else
115 D(bug("Could not get BSD device path for CD\n"));
116
117 CFRelease(bsdPathAsCFString);
118 }
119 else
120 D(bug("Cannot determine bsdPath for CD\n"));
121 }
122
123 IOObjectRelease(nextCD);
124 IOObjectRelease(allCDs);
125 }
126
127
128 void DarwinAddFloppyPrefs(void)
129 {
130 mach_port_t masterPort; // The way to talk to the kernel
131 io_iterator_t allFloppies; // List of CD drives on the system
132 CFMutableDictionaryRef classesToMatch;
133 io_object_t nextFloppy;
134
135
136 if ( IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS )
137 bug("IOMasterPort failed. Won't be able to do anything with floppy drives\n");
138
139
140 classesToMatch = IOServiceMatching(kIOMediaClass);
141 if ( classesToMatch )
142 {
143 // We acually want removables that are _not_ CDs,
144 // but I don't know how to do that yet.
145 CFDictionarySetValue(classesToMatch,
146 CFSTR(kIOMediaRemovableKey), kCFBooleanTrue);
147 }
148
149 if ( IOServiceGetMatchingServices(masterPort,
150 classesToMatch, &allFloppies) != KERN_SUCCESS )
151 {
152 D(bug("IOServiceGetMatchingServices failed. No removable drives found?\n"));
153 return;
154 }
155
156
157 // Iterate through each floppy
158 while ( nextFloppy = IOIteratorNext(allFloppies))
159 {
160 char bsdPath[MAXPATHLEN];
161 CFTypeRef bsdPathAsCFString =
162 IORegistryEntryCreateCFProperty(nextFloppy,
163 CFSTR(kIOBSDNameKey),
164 kCFAllocatorDefault, 0);
165 *bsdPath = '\0';
166 if ( bsdPathAsCFString )
167 {
168 size_t devPathLength;
169
170 strcpy(bsdPath, "/dev/");
171 devPathLength = strlen(bsdPath);
172
173 if ( CFStringGetCString((const __CFString *)bsdPathAsCFString,
174 bsdPath + devPathLength,
175 MAXPATHLEN - devPathLength,
176 kCFStringEncodingASCII) )
177 {
178 D(bug("Floppy BSD path: %s\n", bsdPath));
179 PrefsAddString("floppy", bsdPath);
180 }
181 else
182 D(bug("Could not get BSD device path for floppy\n"));
183
184 CFRelease(bsdPathAsCFString);
185 }
186 else
187 D(bug("Cannot determine bsdPath for floppy\n"));
188 }
189
190 IOObjectRelease(nextFloppy);
191 IOObjectRelease(allFloppies);
192 }
193
194
195 void DarwinAddSerialPrefs(void)
196 {
197 mach_port_t masterPort; // The way to talk to the kernel
198 io_iterator_t allModems; // List of modems on the system
199 CFMutableDictionaryRef classesToMatch;
200 io_object_t nextModem;
201
202
203 if ( IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS )
204 bug("IOMasterPort failed. Won't be able to do anything with modems\n");
205
206
207 // Serial devices are instances of class IOSerialBSDClient
208 classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
209 if ( classesToMatch )
210 {
211 // Narrow the search a little further. Each serial device object has
212 // a property with key kIOSerialBSDTypeKey and a value that is one of
213 // kIOSerialBSDAllTypes, kIOSerialBSDModemType, or kIOSerialBSDRS232Type.
214
215 CFDictionarySetValue(classesToMatch,
216 CFSTR(kIOSerialBSDTypeKey),
217 CFSTR(kIOSerialBSDModemType));
218
219 // This will find built-in and USB modems, but not serial modems.
220 }
221
222 if ( IOServiceGetMatchingServices(masterPort,
223 classesToMatch, &allModems) != KERN_SUCCESS )
224 {
225 D(bug("IOServiceGetMatchingServices failed. No modems found?\n"));
226 return;
227 }
228
229 // Iterate through each modem
230 while ( nextModem = IOIteratorNext(allModems))
231 {
232 char bsdPath[MAXPATHLEN];
233 CFTypeRef bsdPathAsCFString =
234 IORegistryEntryCreateCFProperty(nextModem,
235 CFSTR(kIOCalloutDeviceKey),
236 // kIODialinDeviceKey?
237 kCFAllocatorDefault, 0);
238 *bsdPath = '\0';
239 if ( bsdPathAsCFString )
240 {
241 if ( CFStringGetCString((const __CFString *)bsdPathAsCFString,
242 bsdPath, MAXPATHLEN,
243 kCFStringEncodingASCII) )
244 {
245 D(bug("Modem BSD path: %s\n", bsdPath));
246
247 // Note that if there are multiple modems, we only get the last
248 PrefsAddString("seriala", bsdPath);
249 }
250 else
251 D(bug("Could not get BSD device path for modem\n"));
252
253 CFRelease(bsdPathAsCFString);
254 }
255 else
256 D(puts("Cannot determine bsdPath for modem\n"));
257 }
258
259 IOObjectRelease(nextModem);
260 IOObjectRelease(allModems);
261
262
263 // Getting a printer device is a bit harder. Creating a fake device
264 // that emulates a simple printer (e.g. a HP DeskJet) is one possibility,
265 // but for now I will just create a fake, safe, device entry:
266
267 PrefsAddString("serialb", "/dev/null");
268 }
269
270
271 #ifdef MAC_OS_X_VERSION_10_2
272 /*
273 * Read CD-ROM TOC (binary MSF format, 804 bytes max.)
274 */
275
276 bool DarwinCDReadTOC(char *name, uint8 *toc)
277 {
278 char *c, *devname;
279 int fd;
280
281
282 // The open filehandle is something like /dev/disk5s1
283 // The DKIOCCDREADTOC ioctl needs the original cd file,
284 // so we strip the s1 suffix off it, and open the file just for this ioctl
285
286 devname = strdup(name);
287 if ( ! devname )
288 return false;
289
290 for ( c = devname; *c; ++c ) ; // Go to the end of the name,
291 --c, --c; // point to the 's1' on the end,
292 *c = '\0'; // and truncate the string
293
294 fd = open(devname, O_RDONLY);
295 if ( ! fd )
296 {
297 printf("Failed to open CD device %s for ioctl\n", devname);
298 free(devname);
299 return false;
300 }
301
302 D(bug("Opened %s for ioctl()\n", devname));
303
304 dk_cd_read_toc_t TOCrequest;
305
306 // Setup the ioctl request structure:
307
308 memset(&TOCrequest, 0, sizeof(TOCrequest));
309 TOCrequest.buffer = toc;
310 TOCrequest.bufferLength = 804;
311 TOCrequest.formatAsTime = kCDTrackInfoAddressTypeTrackNumber;
312
313 if ( ioctl(fd, DKIOCCDREADTOC, &TOCrequest) < 0 )
314 {
315 printf("ioctl(DKIOCCDREADTOC) failed: %s\n", strerror(errno));
316 close(fd);
317 free(devname);
318 return false;
319 }
320 if ( TOCrequest.bufferLength < sizeof(CDTOC) )
321 {
322 printf("ioctl(DKIOCCDREADTOC): only read %d bytes (a CDTOC is at least %d)\n",
323 TOCrequest.bufferLength, (int)sizeof(CDTOC));
324 close(fd);
325 free(devname);
326 return false;
327 }
328 D(bug("ioctl(DKIOCCDREADTOC) read %d bytes\n", TOCrequest.bufferLength));
329
330 close(fd);
331 free(devname);
332 return true;
333 }
334 #endif