]>
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 | 27 | */ |
1c79356b | 28 | #include <zone_debug.h> |
1c79356b A |
29 | #include <mach/boolean.h> |
30 | #include <mach/kern_return.h> | |
31 | #include <mach/mig_errors.h> | |
32 | #include <mach/port.h> | |
33 | #include <mach/vm_param.h> | |
34 | #include <mach/notify.h> | |
2d21ac55 | 35 | //#include <mach/mach_host_server.h> |
1c79356b A |
36 | #include <mach/mach_types.h> |
37 | ||
38 | #include <machine/machparam.h> /* spl definitions */ | |
39 | ||
40 | #include <ipc/ipc_port.h> | |
41 | #include <ipc/ipc_space.h> | |
42 | ||
43 | #include <kern/clock.h> | |
44 | #include <kern/spl.h> | |
1c79356b A |
45 | #include <kern/counters.h> |
46 | #include <kern/queue.h> | |
47 | #include <kern/zalloc.h> | |
48 | #include <kern/thread.h> | |
1c79356b A |
49 | #include <kern/task.h> |
50 | #include <kern/sched_prim.h> | |
51 | #include <kern/misc_protos.h> | |
52 | ||
53 | #include <vm/pmap.h> | |
54 | #include <vm/vm_map.h> | |
55 | #include <vm/vm_kern.h> | |
56 | ||
57 | #include <device/device_types.h> | |
58 | #include <device/device_port.h> | |
59 | #include <device/device_server.h> | |
60 | ||
1c79356b A |
61 | #include <machine/machparam.h> |
62 | ||
b0d623f7 | 63 | #if defined(__i386__) || defined(__x86_64__) |
91447636 A |
64 | #include <i386/pmap.h> |
65 | #endif | |
1c79356b A |
66 | #include <IOKit/IOTypes.h> |
67 | ||
68 | #define EXTERN | |
69 | #define MIGEXTERN | |
70 | ||
71 | /* | |
72 | * Functions in iokit:IOUserClient.cpp | |
73 | */ | |
74 | ||
75 | extern void iokit_add_reference( io_object_t obj ); | |
76 | ||
1c79356b A |
77 | extern ipc_port_t iokit_port_for_object( io_object_t obj, |
78 | ipc_kobject_type_t type ); | |
79 | ||
80 | extern kern_return_t iokit_client_died( io_object_t obj, | |
55e303ae | 81 | ipc_port_t port, ipc_kobject_type_t type, mach_port_mscount_t * mscount ); |
1c79356b A |
82 | |
83 | extern kern_return_t | |
84 | iokit_client_memory_for_type( | |
85 | io_object_t connect, | |
86 | unsigned int type, | |
87 | unsigned int * flags, | |
88 | vm_address_t * address, | |
89 | vm_size_t * size ); | |
90 | ||
0c530ab8 A |
91 | |
92 | extern ppnum_t IOGetLastPageNumber(void); | |
93 | ||
2d21ac55 A |
94 | /* |
95 | * Functions imported by iokit:IOUserClient.cpp | |
96 | */ | |
97 | ||
98 | extern ipc_port_t iokit_alloc_object_port( io_object_t obj, | |
99 | ipc_kobject_type_t type ); | |
100 | ||
101 | extern kern_return_t iokit_destroy_object_port( ipc_port_t port ); | |
102 | ||
103 | extern mach_port_name_t iokit_make_send_right( task_t task, | |
104 | io_object_t obj, ipc_kobject_type_t type ); | |
105 | ||
106 | extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ); | |
107 | ||
108 | extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task); | |
109 | ||
110 | extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef); | |
111 | ||
112 | extern void iokit_retain_port( ipc_port_t port ); | |
113 | extern void iokit_release_port( ipc_port_t port ); | |
b0d623f7 | 114 | extern void iokit_release_port_send( ipc_port_t port ); |
2d21ac55 | 115 | |
316670eb A |
116 | extern void iokit_lock_port(ipc_port_t port); |
117 | extern void iokit_unlock_port(ipc_port_t port); | |
118 | ||
2d21ac55 A |
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 | ||
316670eb | 148 | iokit_lock_port(port); |
1c79356b A |
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 | ||
316670eb | 156 | iokit_unlock_port(port); |
1c79356b A |
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 | ||
316670eb | 170 | iokit_lock_port(port); |
1c79356b A |
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 | ||
316670eb | 178 | iokit_unlock_port(port); |
1c79356b A |
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) { | |
316670eb A |
195 | assert(IP_VALID(port)); |
196 | ||
197 | ip_reference(port); | |
198 | ip_unlock(port); | |
199 | ||
200 | iokit_lock_port(port); | |
201 | if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_CONNECT)) { | |
202 | obj = (io_object_t) port->ip_kobject; | |
203 | iokit_add_reference(obj); | |
204 | } | |
205 | iokit_unlock_port(port); | |
206 | ||
207 | ip_release(port); | |
1c79356b A |
208 | } |
209 | } | |
210 | ||
211 | return obj; | |
212 | } | |
213 | ||
214 | EXTERN io_object_t | |
215 | iokit_lookup_connect_ref_current_task(io_object_t connectRef) | |
216 | { | |
217 | return iokit_lookup_connect_ref(connectRef, current_space()); | |
218 | } | |
219 | ||
9bccf70c A |
220 | EXTERN void |
221 | iokit_retain_port( ipc_port_t port ) | |
222 | { | |
223 | ipc_port_reference( port ); | |
224 | } | |
225 | ||
226 | EXTERN void | |
227 | iokit_release_port( ipc_port_t port ) | |
228 | { | |
229 | ipc_port_release( port ); | |
230 | } | |
231 | ||
b0d623f7 A |
232 | EXTERN void |
233 | iokit_release_port_send( ipc_port_t port ) | |
234 | { | |
235 | ipc_port_release_send( port ); | |
236 | } | |
237 | ||
316670eb A |
238 | extern lck_mtx_t iokit_obj_to_port_binding_lock; |
239 | ||
240 | EXTERN void | |
241 | iokit_lock_port( __unused ipc_port_t port ) | |
242 | { | |
243 | lck_mtx_lock(&iokit_obj_to_port_binding_lock); | |
244 | } | |
245 | ||
246 | EXTERN void | |
247 | iokit_unlock_port( __unused ipc_port_t port ) | |
248 | { | |
249 | lck_mtx_unlock(&iokit_obj_to_port_binding_lock); | |
250 | } | |
251 | ||
1c79356b A |
252 | /* |
253 | * Get the port for a device. | |
254 | * Consumes a device reference; produces a naked send right. | |
255 | */ | |
256 | MIGEXTERN ipc_port_t | |
257 | iokit_make_object_port( | |
258 | io_object_t obj ) | |
259 | { | |
260 | register ipc_port_t port; | |
9bccf70c | 261 | register ipc_port_t sendPort; |
1c79356b A |
262 | |
263 | if( obj == NULL) | |
264 | return IP_NULL; | |
265 | ||
266 | port = iokit_port_for_object( obj, IKOT_IOKIT_OBJECT ); | |
9bccf70c A |
267 | if( port) { |
268 | sendPort = ipc_port_make_send( port); | |
269 | iokit_release_port( port ); | |
270 | } else | |
271 | sendPort = IP_NULL; | |
1c79356b A |
272 | |
273 | iokit_remove_reference( obj ); | |
274 | ||
9bccf70c | 275 | return( sendPort); |
1c79356b A |
276 | } |
277 | ||
278 | MIGEXTERN ipc_port_t | |
279 | iokit_make_connect_port( | |
280 | io_object_t obj ) | |
281 | { | |
282 | register ipc_port_t port; | |
9bccf70c | 283 | register ipc_port_t sendPort; |
1c79356b A |
284 | |
285 | if( obj == NULL) | |
286 | return IP_NULL; | |
287 | ||
288 | port = iokit_port_for_object( obj, IKOT_IOKIT_CONNECT ); | |
9bccf70c A |
289 | if( port) { |
290 | sendPort = ipc_port_make_send( port); | |
291 | iokit_release_port( port ); | |
292 | } else | |
293 | sendPort = IP_NULL; | |
1c79356b A |
294 | |
295 | iokit_remove_reference( obj ); | |
296 | ||
9bccf70c | 297 | return( sendPort); |
1c79356b A |
298 | } |
299 | ||
1c79356b A |
300 | int gIOKitPortCount; |
301 | ||
302 | EXTERN ipc_port_t | |
303 | iokit_alloc_object_port( io_object_t obj, ipc_kobject_type_t type ) | |
304 | { | |
305 | ipc_port_t notify; | |
306 | ipc_port_t port; | |
307 | ||
308 | do { | |
309 | ||
310 | /* Allocate port, keeping a reference for it. */ | |
311 | port = ipc_port_alloc_kernel(); | |
312 | if( port == IP_NULL) | |
313 | continue; | |
314 | ||
315 | /* set kobject & type */ | |
316 | // iokit_add_reference( obj ); | |
317 | ipc_kobject_set( port, (ipc_kobject_t) obj, type); | |
318 | ||
319 | /* Request no-senders notifications on the port. */ | |
1c79356b | 320 | ip_lock( port); |
316670eb | 321 | notify = ipc_port_make_sonce_locked( port); |
1c79356b | 322 | ipc_port_nsrequest( port, 1, notify, ¬ify); |
316670eb | 323 | /* port unlocked */ |
1c79356b A |
324 | assert( notify == IP_NULL); |
325 | gIOKitPortCount++; | |
326 | ||
327 | } while( FALSE); | |
328 | ||
329 | return( port ); | |
330 | } | |
331 | ||
332 | ||
333 | EXTERN kern_return_t | |
334 | iokit_destroy_object_port( ipc_port_t port ) | |
335 | { | |
39236c6e A |
336 | |
337 | iokit_lock_port(port); | |
1c79356b A |
338 | ipc_kobject_set( port, IKO_NULL, IKOT_NONE); |
339 | ||
340 | // iokit_remove_reference( obj ); | |
39236c6e | 341 | iokit_unlock_port(port); |
1c79356b A |
342 | ipc_port_dealloc_kernel( port); |
343 | gIOKitPortCount--; | |
344 | ||
345 | return( KERN_SUCCESS); | |
346 | } | |
347 | ||
43866e37 A |
348 | EXTERN kern_return_t |
349 | iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type ) | |
350 | { | |
316670eb | 351 | iokit_lock_port(port); |
43866e37 | 352 | ipc_kobject_set( port, (ipc_kobject_t) obj, type); |
316670eb | 353 | iokit_unlock_port(port); |
43866e37 A |
354 | |
355 | return( KERN_SUCCESS); | |
356 | } | |
357 | ||
1c79356b A |
358 | EXTERN mach_port_name_t |
359 | iokit_make_send_right( task_t task, io_object_t obj, ipc_kobject_type_t type ) | |
360 | { | |
1c79356b | 361 | ipc_port_t port; |
9bccf70c | 362 | ipc_port_t sendPort; |
39236c6e | 363 | mach_port_name_t name = 0; |
1c79356b A |
364 | |
365 | if( obj == NULL) | |
366 | return MACH_PORT_NULL; | |
367 | ||
368 | port = iokit_port_for_object( obj, type ); | |
9bccf70c A |
369 | if( port) { |
370 | sendPort = ipc_port_make_send( port); | |
371 | iokit_release_port( port ); | |
372 | } else | |
373 | sendPort = IP_NULL; | |
374 | ||
375 | if (IP_VALID( sendPort )) { | |
376 | kern_return_t kr; | |
377 | kr = ipc_object_copyout( task->itk_space, (ipc_object_t) sendPort, | |
1c79356b | 378 | MACH_MSG_TYPE_PORT_SEND, TRUE, &name); |
39236c6e A |
379 | if ( kr != KERN_SUCCESS) { |
380 | ipc_port_release_send( sendPort ); | |
381 | name = MACH_PORT_NULL; | |
382 | } | |
9bccf70c A |
383 | } else if ( sendPort == IP_NULL) |
384 | name = MACH_PORT_NULL; | |
385 | else if ( sendPort == IP_DEAD) | |
386 | name = MACH_PORT_DEAD; | |
1c79356b A |
387 | |
388 | iokit_remove_reference( obj ); | |
389 | ||
390 | return( name ); | |
391 | } | |
392 | ||
91447636 A |
393 | EXTERN kern_return_t |
394 | iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ) | |
395 | { | |
396 | return (mach_port_mod_refs( task->itk_space, name, MACH_PORT_RIGHT_SEND, delta )); | |
397 | } | |
398 | ||
1c79356b A |
399 | /* |
400 | * Handle the No-More_Senders notification generated from a device port destroy. | |
401 | * Since there are no longer any tasks which hold a send right to this device | |
402 | * port a NMS notification has been generated. | |
403 | */ | |
404 | ||
405 | static void | |
406 | iokit_no_senders( mach_no_senders_notification_t * notification ) | |
407 | { | |
408 | ipc_port_t port; | |
409 | io_object_t obj = NULL; | |
2d21ac55 | 410 | ipc_kobject_type_t type = IKOT_NONE; |
9bccf70c | 411 | ipc_port_t notify; |
1c79356b A |
412 | |
413 | port = (ipc_port_t) notification->not_header.msgh_remote_port; | |
414 | ||
415 | // convert a port to io_object_t. | |
416 | if( IP_VALID(port)) { | |
316670eb | 417 | iokit_lock_port(port); |
1c79356b A |
418 | if( ip_active(port)) { |
419 | obj = (io_object_t) port->ip_kobject; | |
420 | type = ip_kotype( port ); | |
421 | if( (IKOT_IOKIT_OBJECT == type) | |
422 | || (IKOT_IOKIT_CONNECT == type)) | |
423 | iokit_add_reference( obj ); | |
e3027f41 | 424 | else |
1c79356b A |
425 | obj = NULL; |
426 | } | |
316670eb | 427 | iokit_unlock_port(port); |
1c79356b A |
428 | |
429 | if( obj ) { | |
9bccf70c A |
430 | |
431 | mach_port_mscount_t mscount = notification->not_count; | |
432 | ||
433 | if( KERN_SUCCESS != iokit_client_died( obj, port, type, &mscount )) | |
434 | { | |
316670eb A |
435 | /* Re-request no-senders notifications on the port (if still active) */ |
436 | ip_lock(port); | |
437 | if (ip_active(port)) { | |
438 | notify = ipc_port_make_sonce_locked(port); | |
439 | ipc_port_nsrequest( port, mscount + 1, notify, ¬ify); | |
440 | /* port unlocked */ | |
441 | if ( notify != IP_NULL) | |
442 | ipc_port_release_sonce(notify); | |
4b17d6b6 A |
443 | } else { |
444 | ip_unlock(port); | |
316670eb | 445 | } |
9bccf70c | 446 | } |
1c79356b A |
447 | iokit_remove_reference( obj ); |
448 | } | |
449 | } | |
450 | } | |
451 | ||
452 | ||
453 | EXTERN | |
454 | boolean_t | |
455 | iokit_notify( mach_msg_header_t * msg ) | |
456 | { | |
457 | switch (msg->msgh_id) { | |
458 | case MACH_NOTIFY_NO_SENDERS: | |
459 | iokit_no_senders((mach_no_senders_notification_t *) msg); | |
460 | return TRUE; | |
461 | ||
462 | case MACH_NOTIFY_PORT_DELETED: | |
463 | case MACH_NOTIFY_PORT_DESTROYED: | |
464 | case MACH_NOTIFY_SEND_ONCE: | |
465 | case MACH_NOTIFY_DEAD_NAME: | |
466 | default: | |
2d21ac55 | 467 | printf("iokit_notify: strange notification %d\n", msg->msgh_id); |
1c79356b A |
468 | return FALSE; |
469 | } | |
470 | } | |
471 | ||
55e303ae A |
472 | /* need to create a pmap function to generalize */ |
473 | unsigned int IODefaultCacheBits(addr64_t pa) | |
de355530 | 474 | { |
b0d623f7 | 475 | return(pmap_cache_attributes((ppnum_t)(pa >> PAGE_SHIFT))); |
9bccf70c | 476 | } |
9bccf70c | 477 | |
0c530ab8 A |
478 | kern_return_t IOMapPages(vm_map_t map, mach_vm_address_t va, mach_vm_address_t pa, |
479 | mach_vm_size_t length, unsigned int options) | |
1c79356b | 480 | { |
6d2010ae | 481 | vm_prot_t prot; |
55e303ae | 482 | unsigned int flags; |
6d2010ae | 483 | ppnum_t pagenum; |
55e303ae | 484 | pmap_t pmap = map->pmap; |
1c79356b A |
485 | |
486 | prot = (options & kIOMapReadOnly) | |
487 | ? VM_PROT_READ : (VM_PROT_READ|VM_PROT_WRITE); | |
488 | ||
6d2010ae A |
489 | pagenum = (ppnum_t)atop_64(pa); |
490 | ||
55e303ae A |
491 | switch(options & kIOMapCacheMask ) { /* What cache mode do we need? */ |
492 | ||
493 | case kIOMapDefaultCache: | |
494 | default: | |
495 | flags = IODefaultCacheBits(pa); | |
496 | break; | |
497 | ||
498 | case kIOMapInhibitCache: | |
499 | flags = VM_WIMG_IO; | |
500 | break; | |
501 | ||
502 | case kIOMapWriteThruCache: | |
503 | flags = VM_WIMG_WTHRU; | |
504 | break; | |
505 | ||
0c530ab8 | 506 | case kIOMapWriteCombineCache: |
55e303ae A |
507 | flags = VM_WIMG_WCOMB; |
508 | break; | |
509 | ||
510 | case kIOMapCopybackCache: | |
511 | flags = VM_WIMG_COPYBACK; | |
512 | break; | |
316670eb A |
513 | case kIOMapCopybackInnerCache: |
514 | flags = VM_WIMG_INNERWBACK; | |
515 | break; | |
55e303ae | 516 | } |
1c79356b | 517 | |
6d2010ae A |
518 | pmap_set_cache_attributes(pagenum, flags); |
519 | ||
520 | vm_map_set_cache_attr(map, (vm_map_offset_t)va); | |
521 | ||
522 | ||
55e303ae | 523 | // Set up a block mapped area |
6d2010ae | 524 | pmap_map_block(pmap, va, pagenum, (uint32_t) atop_64(round_page_64(length)), prot, 0, 0); |
0c530ab8 A |
525 | |
526 | return( KERN_SUCCESS ); | |
527 | } | |
528 | ||
529 | kern_return_t IOUnmapPages(vm_map_t map, mach_vm_address_t va, mach_vm_size_t length) | |
530 | { | |
531 | pmap_t pmap = map->pmap; | |
532 | ||
533 | pmap_remove(pmap, trunc_page_64(va), round_page_64(va + length)); | |
534 | ||
535 | return( KERN_SUCCESS ); | |
536 | } | |
537 | ||
2d21ac55 A |
538 | kern_return_t IOProtectCacheMode(vm_map_t __unused map, mach_vm_address_t __unused va, |
539 | mach_vm_size_t __unused length, unsigned int __unused options) | |
0c530ab8 A |
540 | { |
541 | mach_vm_size_t off; | |
542 | vm_prot_t prot; | |
543 | unsigned int flags; | |
544 | pmap_t pmap = map->pmap; | |
39236c6e A |
545 | pmap_flush_context pmap_flush_context_storage; |
546 | boolean_t delayed_pmap_flush = FALSE; | |
0c530ab8 A |
547 | |
548 | prot = (options & kIOMapReadOnly) | |
549 | ? VM_PROT_READ : (VM_PROT_READ|VM_PROT_WRITE); | |
550 | ||
551 | switch (options & kIOMapCacheMask) | |
552 | { | |
2d21ac55 | 553 | // what cache mode do we need? |
0c530ab8 A |
554 | case kIOMapDefaultCache: |
555 | default: | |
556 | return (KERN_INVALID_ARGUMENT); | |
557 | ||
558 | case kIOMapInhibitCache: | |
559 | flags = VM_WIMG_IO; | |
560 | break; | |
561 | ||
562 | case kIOMapWriteThruCache: | |
563 | flags = VM_WIMG_WTHRU; | |
564 | break; | |
4452a7af | 565 | |
0c530ab8 A |
566 | case kIOMapWriteCombineCache: |
567 | flags = VM_WIMG_WCOMB; | |
568 | break; | |
569 | ||
570 | case kIOMapCopybackCache: | |
571 | flags = VM_WIMG_COPYBACK; | |
572 | break; | |
573 | } | |
55e303ae | 574 | |
39236c6e A |
575 | pmap_flush_context_init(&pmap_flush_context_storage); |
576 | delayed_pmap_flush = FALSE; | |
577 | ||
0c530ab8 | 578 | // enter each page's physical address in the target map |
55e303ae | 579 | for (off = 0; off < length; off += page_size) |
0c530ab8 A |
580 | { |
581 | ppnum_t ppnum = pmap_find_phys(pmap, va + off); | |
39236c6e A |
582 | if (ppnum) { |
583 | pmap_enter_options(pmap, va + off, ppnum, prot, VM_PROT_NONE, flags, TRUE, | |
584 | PMAP_OPTIONS_NOFLUSH, (void *)&pmap_flush_context_storage); | |
585 | delayed_pmap_flush = TRUE; | |
586 | } | |
0c530ab8 | 587 | } |
39236c6e A |
588 | if (delayed_pmap_flush == TRUE) |
589 | pmap_flush(&pmap_flush_context_storage); | |
55e303ae | 590 | |
0c530ab8 | 591 | return (KERN_SUCCESS); |
1c79356b A |
592 | } |
593 | ||
0c530ab8 | 594 | ppnum_t IOGetLastPageNumber(void) |
e3027f41 | 595 | { |
6d2010ae A |
596 | #if __i386__ || __x86_64__ |
597 | ppnum_t lastPage, highest = 0; | |
598 | unsigned int idx; | |
599 | ||
600 | for (idx = 0; idx < pmap_memory_region_count; idx++) | |
601 | { | |
602 | lastPage = pmap_memory_regions[idx].end - 1; | |
603 | if (lastPage > highest) | |
604 | highest = lastPage; | |
605 | } | |
606 | return (highest); | |
0c530ab8 | 607 | #else |
6d2010ae | 608 | #error unknown arch |
0c530ab8 | 609 | #endif |
6601e61a | 610 | } |
4452a7af | 611 | |
0c530ab8 | 612 | |
1c79356b A |
613 | void IOGetTime( mach_timespec_t * clock_time); |
614 | void IOGetTime( mach_timespec_t * clock_time) | |
615 | { | |
b0d623f7 A |
616 | clock_sec_t sec; |
617 | clock_nsec_t nsec; | |
618 | clock_get_system_nanotime(&sec, &nsec); | |
619 | clock_time->tv_sec = (typeof(clock_time->tv_sec))sec; | |
620 | clock_time->tv_nsec = nsec; | |
1c79356b | 621 | } |
0c530ab8 | 622 |