ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/sys_darwin.cpp
(Generate patch)

Comparing BasiliskII/src/MacOSX/sys_darwin.cpp (file contents):
Revision 1.2 by cebix, 2004-01-12T15:29:24Z vs.
Revision 1.9 by gbeauche, 2006-05-08T12:15:58Z

# Line 7 | Line 7
7   *
8   *      Based on Apple's CDROMSample.c and Evan Jones' cd-discid.c patches
9   *
10 < *  Basilisk II (C) 1997-2004 Christian Bauer
10 > *  Basilisk II (C) 1997-2005 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
# Line 28 | Line 28
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 + #ifdef HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDEVICE_H
35 +        #import <IOKit/storage/IOBlockStorageDevice.h>
36 + #endif
37   #import <IOKit/storage/IOCDMedia.h>
38   #import <IOKit/storage/IOCDMediaBSDClient.h>
39   #import <CoreFoundation/CoreFoundation.h>
40  
41 < #import "sysdeps.h"
41 > #include "sysdeps.h"
42  
43 < #import "prefs.h"
43 > #include "sys.h"
44 > #include "prefs.h"
45  
46   #define DEBUG 0
47   #import "debug.h"
48  
49  
50 + // Global variables
51 + static CFRunLoopRef media_poll_loop = NULL;
52 + static bool media_thread_active = false;
53 + static pthread_t media_thread;
54 +
55 + // Prototypes
56 + static void *media_poll_func(void *);
57 +
58 + // From sys_unix.cpp
59 + extern void SysMediaArrived(const char *path, int type);
60 + extern void SysMediaRemoved(const char *path, int type);
61 +
62  
63   /*
64 < *  This gets called when no "cdrom" prefs items are found
48 < *  It scans for available CD-ROM drives and adds appropriate prefs items
64 > *  Initialization
65   */
66  
67 < void DarwinAddCDROMPrefs(void)
67 > void DarwinSysInit(void)
68   {
69 <        mach_port_t                             masterPort;     // The way to talk to the kernel
70 <        io_iterator_t                   allCDs;         // List of CD drives on the system
71 <        CFMutableDictionaryRef  classesToMatch;
56 <        io_object_t                             nextCD;
69 >        media_thread_active = (pthread_create(&media_thread, NULL, media_poll_func, NULL) == 0);
70 >        D(bug("Media poll thread installed (%ld)\n", media_thread));
71 > }
72  
73  
74 <        // Don't scan for drives if nocdrom option given
75 <        if ( PrefsFindBool("nocdrom") )
76 <                return;
74 > /*
75 > *  Deinitialization
76 > */
77 >
78 > void DarwinSysExit(void)
79 > {
80 >        // Stop media poll thread
81 >        if (media_poll_loop)
82 >                CFRunLoopStop(media_poll_loop);
83 >        if (media_thread_active)
84 >                pthread_join(media_thread, NULL);
85 > }
86 >
87 >
88 > /*
89 > *  Get the BSD-style path of specified object
90 > */
91 >
92 > static kern_return_t get_device_path(io_object_t obj, char *path, size_t maxPathLength)
93 > {
94 >        kern_return_t kernResult = KERN_FAILURE;
95 >        CFTypeRef pathAsCFString = IORegistryEntryCreateCFProperty(obj, CFSTR(kIOBSDNameKey),
96 >                                                                                                                           kCFAllocatorDefault, 0);
97 >        if (pathAsCFString) {
98 >                strcpy(path, "/dev/");
99 >                size_t pathLength = strlen(path);
100 >                if (CFStringGetCString((const __CFString *)pathAsCFString,
101 >                                                           path + pathLength,
102 >                                                           maxPathLength - pathLength,
103 >                                                           kCFStringEncodingASCII))
104 >                        kernResult = KERN_SUCCESS;
105 >                CFRelease(pathAsCFString);
106 >        }
107 >        return kernResult;
108 > }
109 >
110 >
111 > /*
112 > *  kIOMatchedNotification handler
113 > */
114 >
115 > static void media_arrived(int type, io_iterator_t iterator)
116 > {
117 >        io_object_t obj;
118 >        while ((obj = IOIteratorNext(iterator)) != NULL) {
119 >                char path[MAXPATHLEN];
120 >                kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
121 >                if (kernResult == KERN_SUCCESS) {
122 >                        D(bug("Media Arrived: %s\n", path));
123 >                        SysMediaArrived(path, type);
124 >                }
125 >                kernResult = IOObjectRelease(obj);
126 >                if (kernResult != KERN_SUCCESS) {
127 >                        fprintf(stderr, "IOObjectRelease() returned %d\n", kernResult);
128 >                }
129 >        }
130 > }
131 >
132 >
133 > /*
134 > *  kIOTerminatedNotification handler
135 > */
136 >
137 > static void media_removed(int type, io_iterator_t iterator)
138 > {
139 >        io_object_t obj;
140 >        while ((obj = IOIteratorNext(iterator)) != NULL) {
141 >                char path[MAXPATHLEN];
142 >                kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
143 >                if (kernResult == KERN_SUCCESS) {
144 >                        D(bug("Media Removed: %s\n", path));
145 >                        SysMediaRemoved(path, type);
146 >                }
147 >                kernResult = IOObjectRelease(obj);
148 >                if (kernResult != KERN_SUCCESS) {
149 >                        fprintf(stderr, "IOObjectRelease() returned %d\n", kernResult);
150 >                }
151 >        }
152 > }
153 >
154 >
155 > /*
156 > *  Media poll function
157 > */
158 >
159 > static void *media_poll_func(void *)
160 > {
161 >        media_poll_loop = CFRunLoopGetCurrent();
162 >
163 >        mach_port_t masterPort;
164 >        kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort);
165 >        if (kernResult != KERN_SUCCESS) {
166 >                fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
167 >                return NULL;
168 >        }
169 >
170 >        CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass);
171 >        if (matchingDictionary == NULL) {
172 >                fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n");
173 >                return NULL;
174 >        }
175 >        matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
176 >
177 >        IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
178 >        CFRunLoopAddSource(media_poll_loop,
179 >                                           IONotificationPortGetRunLoopSource(notificationPort),
180 >                                           kCFRunLoopDefaultMode);
181 >
182 >        io_iterator_t mediaArrivedIterator;
183 >        kernResult = IOServiceAddMatchingNotification(notificationPort,
184 >                                                                                                  kIOMatchedNotification,
185 >                                                                                                  matchingDictionary,
186 >                                                                                                  (IOServiceMatchingCallback)media_arrived,
187 >                                                                                                  (void *)MEDIA_CD, &mediaArrivedIterator);
188 >        if (kernResult != KERN_SUCCESS)
189 >                fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
190 >        media_arrived(MEDIA_CD, mediaArrivedIterator);
191 >
192 >        io_iterator_t mediaRemovedIterator;
193 >        kernResult = IOServiceAddMatchingNotification(notificationPort,
194 >                                                                                                  kIOTerminatedNotification,
195 >                                                                                                  matchingDictionary,
196 >                                                                                                  (IOServiceMatchingCallback)media_removed,
197 >                                                                                                  (void *)MEDIA_CD, &mediaRemovedIterator);
198 >        if (kernResult != KERN_SUCCESS)
199 >                fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
200 >        media_removed(MEDIA_CD, mediaRemovedIterator);
201 >
202 >        CFRunLoopRun();
203 >        return NULL;
204 > }
205 >
206 >
207 > void DarwinAddFloppyPrefs(void)
208 > {
209 >        mach_port_t                             masterPort;             // The way to talk to the kernel
210 >        io_iterator_t                   allFloppies;    // List of possible floppys
211 >        CFMutableDictionaryRef  classesToMatch;
212 >        io_object_t                             nextFloppy;
213  
214  
64        // Let this task talk to the guts of the kernel:
215          if ( IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS )
216 <                bug("IOMasterPort failed. Won't be able to do anything with CD drives");
216 >                bug("IOMasterPort failed. Won't be able to do anything with floppy drives\n");
217  
218  
219 <        // CD media are instances of class kIOCDMediaClass
220 <        classesToMatch = IOServiceMatching(kIOCDMediaClass);
219 >        // This selects all partitions of all disks
220 >        classesToMatch = IOServiceMatching(kIOMediaClass);
221          if ( classesToMatch )
222          {
223 <                // Narrow the search a little further. Each IOMedia object
74 <                // has a property with key kIOMediaEjectable.  We limit
75 <                // the match only to those CDs that are actually ejectable
223 >                // Skip drivers and partitions
224                  CFDictionarySetValue(classesToMatch,
225 <                                                         CFSTR(kIOMediaEjectable), kCFBooleanTrue);
225 >                                                         CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
226 >        
227 >                // Skip fixed drives (hard disks?)
228 >                CFDictionarySetValue(classesToMatch,
229 >                                                         CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
230          }
231  
232          if ( IOServiceGetMatchingServices(masterPort,
233 <                                                                          classesToMatch, &allCDs) != KERN_SUCCESS )
233 >                                                                          classesToMatch, &allFloppies) != KERN_SUCCESS )
234          {
235 <                D(bug("IOServiceGetMatchingServices failed. No CD media drives found?\n"));
235 >                D(bug("IOServiceGetMatchingServices failed. No removable drives found?\n"));
236                  return;
237          }
238  
239  
240 <        // Iterate through each CD drive
241 <        while ( nextCD = IOIteratorNext(allCDs))
240 >        // Iterate through each floppy
241 >        while ( nextFloppy = IOIteratorNext(allFloppies))
242          {
243                  char            bsdPath[MAXPATHLEN];
244                  CFTypeRef       bsdPathAsCFString =
245 <                                                IORegistryEntryCreateCFProperty(nextCD, CFSTR(kIOBSDName),
246 <                                                                                                                        kCFAllocatorDefault, 0);
245 >                                                IORegistryEntryCreateCFProperty(nextFloppy,
246 >                                                                                                                CFSTR(kIOBSDNameKey),
247 >                                                                                                                kCFAllocatorDefault, 0);
248 >                long            size;
249 >                CFTypeRef       sizeAsCFNumber =
250 >                                                IORegistryEntryCreateCFProperty(nextFloppy,
251 >                                                                                                                CFSTR(kIOMediaSizeKey),
252 >                                                                                                                kCFAllocatorDefault, 0);
253 >
254 >                if ( CFNumberGetValue((CFNumberRef)sizeAsCFNumber,
255 >                                                                kCFNumberSInt32Type, &size) )
256 >                {
257 >                        D(bug("Got size of %ld\n", size));
258 >                        if ( size < 800 * 1024 || size > 1440 * 1024 )
259 >                        {
260 >                                D(puts("Device does not appear to be 800k or 1440k"));
261 >                                continue;
262 >                        }
263 >                }
264 >                else
265 >                        bug("Couldn't get kIOMediaSizeKey of device");
266 >                
267 >                
268                  *bsdPath = '\0';
269                  if ( bsdPathAsCFString )
270                  {
# Line 105 | Line 278 | void DarwinAddCDROMPrefs(void)
278                                                                           MAXPATHLEN - devPathLength,
279                                                                           kCFStringEncodingASCII) )
280                          {
281 <                                // If we try to do raw reads on the file bsdPath (e.g. /dev/disk5),
282 <                                // we get a lot of extra padding in the data. For some reason,
110 <                                // the device we need has a different name (e.g. /dev/disk5s1)
111 <                                //strcat(bsdPath, "s1");
112 <                                D(bug("CDROM BSD path: %s\n", bsdPath));
281 >                                D(bug("Floppy BSD path: %s\n", bsdPath));
282 >                                PrefsAddString("floppy", bsdPath);
283                          }
284                          else
285 <                                D(bug("Could not get BSD device path for CD\n"));
285 >                                D(bug("Could not get BSD device path for floppy\n"));
286  
287                          CFRelease(bsdPathAsCFString);
288                  }
289 +                else
290 +                        D(bug("Cannot determine bsdPath for floppy\n"));
291 +        }
292 +
293 +        IOObjectRelease(nextFloppy);
294 +        IOObjectRelease(allFloppies);
295 + }
296  
297 <                PrefsAddString("cdrom", bsdPath);
297 >
298 > void DarwinAddSerialPrefs(void)
299 > {
300 >        mach_port_t                             masterPort;             // The way to talk to the kernel
301 >        io_iterator_t                   allModems;              // List of modems on the system
302 >        CFMutableDictionaryRef  classesToMatch;
303 >        io_object_t                             nextModem;
304 >
305 >
306 >        if ( IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS )
307 >                bug("IOMasterPort failed. Won't be able to do anything with modems\n");
308 >
309 >
310 >    // Serial devices are instances of class IOSerialBSDClient
311 >    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
312 >        if ( classesToMatch )
313 >        {
314 >                // Narrow the search a little further. Each serial device object has
315 >                // a property with key kIOSerialBSDTypeKey and a value that is one of
316 >                // kIOSerialBSDAllTypes, kIOSerialBSDModemType, or kIOSerialBSDRS232Type.
317 >
318 >        CFDictionarySetValue(classesToMatch,
319 >                             CFSTR(kIOSerialBSDTypeKey),
320 >                             CFSTR(kIOSerialBSDModemType));
321 >
322 >        // This will find built-in and USB modems, but not serial modems.
323          }
324  
325 <        IOObjectRelease(nextCD);
326 <        IOObjectRelease(allCDs);
325 >        if ( IOServiceGetMatchingServices(masterPort,
326 >                                                                          classesToMatch, &allModems) != KERN_SUCCESS )
327 >        {
328 >                D(bug("IOServiceGetMatchingServices failed. No modems found?\n"));
329 >                return;
330 >        }
331 >
332 >        // Iterate through each modem
333 >        while ( nextModem = IOIteratorNext(allModems))
334 >        {
335 >                char            bsdPath[MAXPATHLEN];
336 >                CFTypeRef       bsdPathAsCFString =
337 >                                                IORegistryEntryCreateCFProperty(nextModem,
338 >                                                                                                                CFSTR(kIOCalloutDeviceKey),
339 >                                                                                                                // kIODialinDeviceKey?
340 >                                                                                                                kCFAllocatorDefault, 0);
341 >                *bsdPath = '\0';
342 >                if ( bsdPathAsCFString )
343 >                {
344 >                        if ( CFStringGetCString((const __CFString *)bsdPathAsCFString,
345 >                                                                         bsdPath, MAXPATHLEN,
346 >                                                                         kCFStringEncodingASCII) )
347 >                        {
348 >                                D(bug("Modem BSD path: %s\n", bsdPath));
349 >
350 >                                // Note that if there are multiple modems, we only get the last
351 >                                PrefsAddString("seriala", bsdPath);
352 >                        }
353 >                        else
354 >                                D(bug("Could not get BSD device path for modem\n"));
355 >
356 >                        CFRelease(bsdPathAsCFString);
357 >                }
358 >                else
359 >                        D(puts("Cannot determine bsdPath for modem\n"));
360 >        }
361 >
362 >        IOObjectRelease(nextModem);
363 >        IOObjectRelease(allModems);
364 >
365 >
366 >        // Getting a printer device is a bit harder. Creating a fake device
367 >        // that emulates a simple printer (e.g. a HP DeskJet) is one possibility,
368 >        // but for now I will just create a fake, safe, device entry:
369 >
370 >        PrefsAddString("serialb", "/dev/null");
371   }
372  
373  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines