ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/sys_darwin.cpp
Revision: 1.5
Committed: 2004-01-27T04:37:23Z (20 years, 9 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-15
Changes since 1.4: +6 -2 lines
Log Message:
Can only use floppy location code on OS X 10.2 or above?

File Contents

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