]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
2d21ac55 | 2 | * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. |
1c79356b | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | #include <mach_kdb.h> | |
29 | #include <zone_debug.h> | |
30 | #include <mach_kdb.h> | |
31 | ||
32 | #include <mach/boolean.h> | |
33 | #include <mach/kern_return.h> | |
34 | #include <mach/mig_errors.h> | |
35 | #include <mach/port.h> | |
36 | #include <mach/vm_param.h> | |
37 | #include <mach/notify.h> | |
2d21ac55 | 38 | //#include <mach/mach_host_server.h> |
1c79356b A |
39 | #include <mach/mach_types.h> |
40 | ||
41 | #include <machine/machparam.h> /* spl definitions */ | |
42 | ||
43 | #include <ipc/ipc_port.h> | |
44 | #include <ipc/ipc_space.h> | |
45 | ||
46 | #include <kern/clock.h> | |
47 | #include <kern/spl.h> | |
1c79356b A |
48 | #include <kern/counters.h> |
49 | #include <kern/queue.h> | |
50 | #include <kern/zalloc.h> | |
51 | #include <kern/thread.h> | |
1c79356b A |
52 | #include <kern/task.h> |
53 | #include <kern/sched_prim.h> | |
54 | #include <kern/misc_protos.h> | |
55 | ||
56 | #include <vm/pmap.h> | |
57 | #include <vm/vm_map.h> | |
58 | #include <vm/vm_kern.h> | |
59 | ||
60 | #include <device/device_types.h> | |
61 | #include <device/device_port.h> | |
62 | #include <device/device_server.h> | |
63 | ||
1c79356b A |
64 | #include <machine/machparam.h> |
65 | ||
b0d623f7 | 66 | #if defined(__i386__) || defined(__x86_64__) |
91447636 A |
67 | #include <i386/pmap.h> |
68 | #endif | |
1c79356b A |
69 | #include <IOKit/IOTypes.h> |
70 | ||
71 | #define EXTERN | |
72 | #define MIGEXTERN | |
73 | ||
74 | /* | |
75 | * Functions in iokit:IOUserClient.cpp | |
76 | */ | |
77 | ||
78 | extern void iokit_add_reference( io_object_t obj ); | |
79 | ||
1c79356b A |
80 | extern ipc_port_t iokit_port_for_object( io_object_t obj, |
81 | ipc_kobject_type_t type ); | |
82 | ||
83 | extern kern_return_t iokit_client_died( io_object_t obj, | |
55e303ae | 84 | ipc_port_t port, ipc_kobject_type_t type, mach_port_mscount_t * mscount ); |
1c79356b A |
85 | |
86 | extern kern_return_t | |
87 | iokit_client_memory_for_type( | |
88 | io_object_t connect, | |
89 | unsigned int type, | |
90 | unsigned int * flags, | |
91 | vm_address_t * address, | |
92 | vm_size_t * size ); | |
93 | ||
0c530ab8 A |
94 | |
95 | extern ppnum_t IOGetLastPageNumber(void); | |
96 | ||
2d21ac55 A |
97 | /* |
98 | * Functions imported by iokit:IOUserClient.cpp | |
99 | */ | |
100 | ||
101 | extern ipc_port_t iokit_alloc_object_port( io_object_t obj, | |
102 | ipc_kobject_type_t type ); | |
103 | ||
104 | extern kern_return_t iokit_destroy_object_port( ipc_port_t port ); | |
105 | ||
106 | extern mach_port_name_t iokit_make_send_right( task_t task, | |
107 | io_object_t obj, ipc_kobject_type_t type ); | |
108 | ||
109 | extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ); | |
110 | ||
111 | extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task); | |
112 | ||
113 | extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef); | |
114 | ||
115 | extern void iokit_retain_port( ipc_port_t port ); | |
116 | extern void iokit_release_port( ipc_port_t port ); | |
b0d623f7 | 117 | extern void iokit_release_port_send( ipc_port_t port ); |
2d21ac55 A |
118 | |
119 | extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type ); | |
120 | ||
121 | /* | |
122 | * Functions imported by iokit:IOMemoryDescriptor.cpp | |
123 | */ | |
124 | ||
125 | extern kern_return_t IOMapPages(vm_map_t map, mach_vm_address_t va, mach_vm_address_t pa, | |
126 | mach_vm_size_t length, unsigned int mapFlags); | |
127 | ||
128 | extern kern_return_t IOUnmapPages(vm_map_t map, mach_vm_address_t va, mach_vm_size_t length); | |
129 | ||
130 | extern kern_return_t IOProtectCacheMode(vm_map_t map, mach_vm_address_t va, | |
131 | mach_vm_size_t length, unsigned int options); | |
132 | ||
133 | extern unsigned int IODefaultCacheBits(addr64_t pa); | |
134 | ||
1c79356b A |
135 | /* |
136 | * Lookup a device by its port. | |
137 | * Doesn't consume the naked send right; produces a device reference. | |
138 | */ | |
139 | MIGEXTERN io_object_t | |
140 | iokit_lookup_object_port( | |
141 | ipc_port_t port) | |
142 | { | |
143 | register io_object_t obj; | |
144 | ||
145 | if (!IP_VALID(port)) | |
146 | return (NULL); | |
147 | ||
148 | ip_lock(port); | |
149 | if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_OBJECT)) { | |
150 | obj = (io_object_t) port->ip_kobject; | |
151 | iokit_add_reference( obj ); | |
152 | } | |
153 | else | |
154 | obj = NULL; | |
155 | ||
156 | ip_unlock(port); | |
157 | ||
158 | return( obj ); | |
159 | } | |
160 | ||
161 | MIGEXTERN io_object_t | |
162 | iokit_lookup_connect_port( | |
163 | ipc_port_t port) | |
164 | { | |
165 | register io_object_t obj; | |
166 | ||
167 | if (!IP_VALID(port)) | |
168 | return (NULL); | |
169 | ||
170 | ip_lock(port); | |
171 | if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_CONNECT)) { | |
172 | obj = (io_object_t) port->ip_kobject; | |
173 | iokit_add_reference( obj ); | |
174 | } | |
175 | else | |
176 | obj = NULL; | |
177 | ||
178 | ip_unlock(port); | |
179 | ||
180 | return( obj ); | |
181 | } | |
182 | ||
183 | EXTERN io_object_t | |
184 | iokit_lookup_connect_ref(io_object_t connectRef, ipc_space_t space) | |
185 | { | |
186 | io_object_t obj = NULL; | |
187 | ||
b0d623f7 | 188 | if (connectRef && MACH_PORT_VALID(CAST_MACH_PORT_TO_NAME(connectRef))) { |
1c79356b A |
189 | ipc_port_t port; |
190 | kern_return_t kr; | |
191 | ||
b0d623f7 | 192 | kr = ipc_object_translate(space, CAST_MACH_PORT_TO_NAME(connectRef), MACH_PORT_RIGHT_SEND, (ipc_object_t *)&port); |
1c79356b A |
193 | |
194 | if (kr == KERN_SUCCESS) { | |
195 | assert(IP_VALID(port)); | |
196 | ||
197 | if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_CONNECT)) { | |
198 | obj = (io_object_t) port->ip_kobject; | |
199 | iokit_add_reference(obj); | |
200 | } | |
201 | ||
202 | ip_unlock(port); | |
203 | } | |
204 | } | |
205 | ||
206 | return obj; | |
207 | } | |
208 | ||
209 | EXTERN io_object_t | |
210 | iokit_lookup_connect_ref_current_task(io_object_t connectRef) | |
211 | { | |
212 | return iokit_lookup_connect_ref(connectRef, current_space()); | |
213 | } | |
214 | ||
9bccf70c A |
215 | EXTERN void |
216 | iokit_retain_port( ipc_port_t port ) | |
217 | { | |
218 | ipc_port_reference( port ); | |
219 | } | |
220 | ||
221 | EXTERN void | |
222 | iokit_release_port( ipc_port_t port ) | |
223 | { | |
224 | ipc_port_release( port ); | |
225 | } | |
226 | ||
b0d623f7 A |
227 | EXTERN void |
228 | iokit_release_port_send( ipc_port_t port ) | |
229 | { | |
230 | ipc_port_release_send( port ); | |
231 | } | |
232 | ||
1c79356b A |
233 | /* |
234 | * Get the port for a device. | |
235 | * Consumes a device reference; produces a naked send right. | |
236 | */ | |
237 | MIGEXTERN ipc_port_t | |
238 | iokit_make_object_port( | |
239 | io_object_t obj ) | |
240 | { | |
241 | register ipc_port_t port; | |
9bccf70c | 242 | register ipc_port_t sendPort; |
1c79356b A |
243 | |
244 | if( obj == NULL) | |
245 | return IP_NULL; | |
246 | ||
247 | port = iokit_port_for_object( obj, IKOT_IOKIT_OBJECT ); | |
9bccf70c A |
248 | if( port) { |
249 | sendPort = ipc_port_make_send( port); | |
250 | iokit_release_port( port ); | |
251 | } else | |
252 | sendPort = IP_NULL; | |
1c79356b A |
253 | |
254 | iokit_remove_reference( obj ); | |
255 | ||
9bccf70c | 256 | return( sendPort); |
1c79356b A |
257 | } |
258 | ||
259 | MIGEXTERN ipc_port_t | |
260 | iokit_make_connect_port( | |
261 | io_object_t obj ) | |
262 | { | |
263 | register ipc_port_t port; | |
9bccf70c | 264 | register ipc_port_t sendPort; |
1c79356b A |
265 | |
266 | if( obj == NULL) | |
267 | return IP_NULL; | |
268 | ||
269 | port = iokit_port_for_object( obj, IKOT_IOKIT_CONNECT ); | |
9bccf70c A |
270 | if( port) { |
271 | sendPort = ipc_port_make_send( port); | |
272 | iokit_release_port( port ); | |
273 | } else | |
274 | sendPort = IP_NULL; | |
1c79356b A |
275 | |
276 | iokit_remove_reference( obj ); | |
277 | ||
9bccf70c | 278 | return( sendPort); |
1c79356b A |
279 | } |
280 | ||
1c79356b A |
281 | int gIOKitPortCount; |
282 | ||
283 | EXTERN ipc_port_t | |
284 | iokit_alloc_object_port( io_object_t obj, ipc_kobject_type_t type ) | |
285 | { | |
286 | ipc_port_t notify; | |
287 | ipc_port_t port; | |
288 | ||
289 | do { | |
290 | ||
291 | /* Allocate port, keeping a reference for it. */ | |
292 | port = ipc_port_alloc_kernel(); | |
293 | if( port == IP_NULL) | |
294 | continue; | |
295 | ||
296 | /* set kobject & type */ | |
297 | // iokit_add_reference( obj ); | |
298 | ipc_kobject_set( port, (ipc_kobject_t) obj, type); | |
299 | ||
300 | /* Request no-senders notifications on the port. */ | |
301 | notify = ipc_port_make_sonce( port); | |
302 | ip_lock( port); | |
303 | ipc_port_nsrequest( port, 1, notify, ¬ify); | |
304 | assert( notify == IP_NULL); | |
305 | gIOKitPortCount++; | |
306 | ||
307 | } while( FALSE); | |
308 | ||
309 | return( port ); | |
310 | } | |
311 | ||
312 | ||
313 | EXTERN kern_return_t | |
314 | iokit_destroy_object_port( ipc_port_t port ) | |
315 | { | |
316 | ipc_kobject_set( port, IKO_NULL, IKOT_NONE); | |
317 | ||
318 | // iokit_remove_reference( obj ); | |
319 | ||
320 | ipc_port_dealloc_kernel( port); | |
321 | gIOKitPortCount--; | |
322 | ||
323 | return( KERN_SUCCESS); | |
324 | } | |
325 | ||
43866e37 A |
326 | EXTERN kern_return_t |
327 | iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type ) | |
328 | { | |
329 | ipc_kobject_set( port, (ipc_kobject_t) obj, type); | |
330 | ||
331 | return( KERN_SUCCESS); | |
332 | } | |
333 | ||
1c79356b A |
334 | EXTERN mach_port_name_t |
335 | iokit_make_send_right( task_t task, io_object_t obj, ipc_kobject_type_t type ) | |
336 | { | |
1c79356b | 337 | ipc_port_t port; |
9bccf70c | 338 | ipc_port_t sendPort; |
1c79356b A |
339 | mach_port_name_t name; |
340 | ||
341 | if( obj == NULL) | |
342 | return MACH_PORT_NULL; | |
343 | ||
344 | port = iokit_port_for_object( obj, type ); | |
9bccf70c A |
345 | if( port) { |
346 | sendPort = ipc_port_make_send( port); | |
347 | iokit_release_port( port ); | |
348 | } else | |
349 | sendPort = IP_NULL; | |
350 | ||
351 | if (IP_VALID( sendPort )) { | |
352 | kern_return_t kr; | |
353 | kr = ipc_object_copyout( task->itk_space, (ipc_object_t) sendPort, | |
1c79356b | 354 | MACH_MSG_TYPE_PORT_SEND, TRUE, &name); |
9bccf70c A |
355 | if ( kr != KERN_SUCCESS) |
356 | name = MACH_PORT_NULL; | |
357 | } else if ( sendPort == IP_NULL) | |
358 | name = MACH_PORT_NULL; | |
359 | else if ( sendPort == IP_DEAD) | |
360 | name = MACH_PORT_DEAD; | |
1c79356b A |
361 | |
362 | iokit_remove_reference( obj ); | |
363 | ||
364 | return( name ); | |
365 | } | |
366 | ||
91447636 A |
367 | EXTERN kern_return_t |
368 | iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ) | |
369 | { | |
370 | return (mach_port_mod_refs( task->itk_space, name, MACH_PORT_RIGHT_SEND, delta )); | |
371 | } | |
372 | ||
1c79356b A |
373 | /* |
374 | * Handle the No-More_Senders notification generated from a device port destroy. | |
375 | * Since there are no longer any tasks which hold a send right to this device | |
376 | * port a NMS notification has been generated. | |
377 | */ | |
378 | ||
379 | static void | |
380 | iokit_no_senders( mach_no_senders_notification_t * notification ) | |
381 | { | |
382 | ipc_port_t port; | |
383 | io_object_t obj = NULL; | |
2d21ac55 | 384 | ipc_kobject_type_t type = IKOT_NONE; |
9bccf70c | 385 | ipc_port_t notify; |
1c79356b A |
386 | |
387 | port = (ipc_port_t) notification->not_header.msgh_remote_port; | |
388 | ||
389 | // convert a port to io_object_t. | |
390 | if( IP_VALID(port)) { | |
391 | ip_lock(port); | |
392 | if( ip_active(port)) { | |
393 | obj = (io_object_t) port->ip_kobject; | |
394 | type = ip_kotype( port ); | |
395 | if( (IKOT_IOKIT_OBJECT == type) | |
396 | || (IKOT_IOKIT_CONNECT == type)) | |
397 | iokit_add_reference( obj ); | |
e3027f41 | 398 | else |
1c79356b A |
399 | obj = NULL; |
400 | } | |
401 | ip_unlock(port); | |
402 | ||
403 | if( obj ) { | |
9bccf70c A |
404 | |
405 | mach_port_mscount_t mscount = notification->not_count; | |
406 | ||
407 | if( KERN_SUCCESS != iokit_client_died( obj, port, type, &mscount )) | |
408 | { | |
409 | /* Re-request no-senders notifications on the port. */ | |
410 | notify = ipc_port_make_sonce( port); | |
411 | ip_lock( port); | |
412 | ipc_port_nsrequest( port, mscount + 1, notify, ¬ify); | |
413 | assert( notify == IP_NULL); | |
414 | } | |
1c79356b A |
415 | iokit_remove_reference( obj ); |
416 | } | |
417 | } | |
418 | } | |
419 | ||
420 | ||
421 | EXTERN | |
422 | boolean_t | |
423 | iokit_notify( mach_msg_header_t * msg ) | |
424 | { | |
425 | switch (msg->msgh_id) { | |
426 | case MACH_NOTIFY_NO_SENDERS: | |
427 | iokit_no_senders((mach_no_senders_notification_t *) msg); | |
428 | return TRUE; | |
429 | ||
430 | case MACH_NOTIFY_PORT_DELETED: | |
431 | case MACH_NOTIFY_PORT_DESTROYED: | |
432 | case MACH_NOTIFY_SEND_ONCE: | |
433 | case MACH_NOTIFY_DEAD_NAME: | |
434 | default: | |
2d21ac55 | 435 | printf("iokit_notify: strange notification %d\n", msg->msgh_id); |
1c79356b A |
436 | return FALSE; |
437 | } | |
438 | } | |
439 | ||
55e303ae A |
440 | /* need to create a pmap function to generalize */ |
441 | unsigned int IODefaultCacheBits(addr64_t pa) | |
de355530 | 442 | { |
b0d623f7 | 443 | return(pmap_cache_attributes((ppnum_t)(pa >> PAGE_SHIFT))); |
9bccf70c | 444 | } |
9bccf70c | 445 | |
0c530ab8 A |
446 | kern_return_t IOMapPages(vm_map_t map, mach_vm_address_t va, mach_vm_address_t pa, |
447 | mach_vm_size_t length, unsigned int options) | |
1c79356b | 448 | { |
6d2010ae | 449 | vm_prot_t prot; |
55e303ae | 450 | unsigned int flags; |
6d2010ae | 451 | ppnum_t pagenum; |
55e303ae | 452 | pmap_t pmap = map->pmap; |
1c79356b A |
453 | |
454 | prot = (options & kIOMapReadOnly) | |
455 | ? VM_PROT_READ : (VM_PROT_READ|VM_PROT_WRITE); | |
456 | ||
6d2010ae A |
457 | pagenum = (ppnum_t)atop_64(pa); |
458 | ||
55e303ae A |
459 | switch(options & kIOMapCacheMask ) { /* What cache mode do we need? */ |
460 | ||
461 | case kIOMapDefaultCache: | |
462 | default: | |
463 | flags = IODefaultCacheBits(pa); | |
464 | break; | |
465 | ||
466 | case kIOMapInhibitCache: | |
467 | flags = VM_WIMG_IO; | |
468 | break; | |
469 | ||
470 | case kIOMapWriteThruCache: | |
471 | flags = VM_WIMG_WTHRU; | |
472 | break; | |
473 | ||
0c530ab8 | 474 | case kIOMapWriteCombineCache: |
55e303ae A |
475 | flags = VM_WIMG_WCOMB; |
476 | break; | |
477 | ||
478 | case kIOMapCopybackCache: | |
479 | flags = VM_WIMG_COPYBACK; | |
480 | break; | |
481 | } | |
1c79356b | 482 | |
6d2010ae A |
483 | pmap_set_cache_attributes(pagenum, flags); |
484 | ||
485 | vm_map_set_cache_attr(map, (vm_map_offset_t)va); | |
486 | ||
487 | ||
55e303ae | 488 | // Set up a block mapped area |
6d2010ae | 489 | pmap_map_block(pmap, va, pagenum, (uint32_t) atop_64(round_page_64(length)), prot, 0, 0); |
0c530ab8 A |
490 | |
491 | return( KERN_SUCCESS ); | |
492 | } | |
493 | ||
494 | kern_return_t IOUnmapPages(vm_map_t map, mach_vm_address_t va, mach_vm_size_t length) | |
495 | { | |
496 | pmap_t pmap = map->pmap; | |
497 | ||
498 | pmap_remove(pmap, trunc_page_64(va), round_page_64(va + length)); | |
499 | ||
500 | return( KERN_SUCCESS ); | |
501 | } | |
502 | ||
2d21ac55 A |
503 | kern_return_t IOProtectCacheMode(vm_map_t __unused map, mach_vm_address_t __unused va, |
504 | mach_vm_size_t __unused length, unsigned int __unused options) | |
0c530ab8 A |
505 | { |
506 | mach_vm_size_t off; | |
507 | vm_prot_t prot; | |
508 | unsigned int flags; | |
509 | pmap_t pmap = map->pmap; | |
510 | ||
511 | prot = (options & kIOMapReadOnly) | |
512 | ? VM_PROT_READ : (VM_PROT_READ|VM_PROT_WRITE); | |
513 | ||
514 | switch (options & kIOMapCacheMask) | |
515 | { | |
2d21ac55 | 516 | // what cache mode do we need? |
0c530ab8 A |
517 | case kIOMapDefaultCache: |
518 | default: | |
519 | return (KERN_INVALID_ARGUMENT); | |
520 | ||
521 | case kIOMapInhibitCache: | |
522 | flags = VM_WIMG_IO; | |
523 | break; | |
524 | ||
525 | case kIOMapWriteThruCache: | |
526 | flags = VM_WIMG_WTHRU; | |
527 | break; | |
4452a7af | 528 | |
0c530ab8 A |
529 | case kIOMapWriteCombineCache: |
530 | flags = VM_WIMG_WCOMB; | |
531 | break; | |
532 | ||
533 | case kIOMapCopybackCache: | |
534 | flags = VM_WIMG_COPYBACK; | |
535 | break; | |
536 | } | |
55e303ae | 537 | |
0c530ab8 | 538 | // enter each page's physical address in the target map |
55e303ae | 539 | for (off = 0; off < length; off += page_size) |
0c530ab8 A |
540 | { |
541 | ppnum_t ppnum = pmap_find_phys(pmap, va + off); | |
542 | if (ppnum) | |
543 | pmap_enter(pmap, va + off, ppnum, prot, flags, TRUE); | |
544 | } | |
55e303ae | 545 | |
0c530ab8 | 546 | return (KERN_SUCCESS); |
1c79356b A |
547 | } |
548 | ||
0c530ab8 | 549 | ppnum_t IOGetLastPageNumber(void) |
e3027f41 | 550 | { |
6d2010ae A |
551 | #if __i386__ || __x86_64__ |
552 | ppnum_t lastPage, highest = 0; | |
553 | unsigned int idx; | |
554 | ||
555 | for (idx = 0; idx < pmap_memory_region_count; idx++) | |
556 | { | |
557 | lastPage = pmap_memory_regions[idx].end - 1; | |
558 | if (lastPage > highest) | |
559 | highest = lastPage; | |
560 | } | |
561 | return (highest); | |
0c530ab8 | 562 | #else |
6d2010ae | 563 | #error unknown arch |
0c530ab8 | 564 | #endif |
6601e61a | 565 | } |
4452a7af | 566 | |
0c530ab8 | 567 | |
1c79356b A |
568 | void IOGetTime( mach_timespec_t * clock_time); |
569 | void IOGetTime( mach_timespec_t * clock_time) | |
570 | { | |
b0d623f7 A |
571 | clock_sec_t sec; |
572 | clock_nsec_t nsec; | |
573 | clock_get_system_nanotime(&sec, &nsec); | |
574 | clock_time->tv_sec = (typeof(clock_time->tv_sec))sec; | |
575 | clock_time->tv_nsec = nsec; | |
1c79356b | 576 | } |
0c530ab8 | 577 |