|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: #include <mach_kdb.h>
23: #include <zone_debug.h>
24: #include <mach_kdb.h>
25:
26: #include <mach/boolean.h>
27: #include <mach/kern_return.h>
28: #include <mach/mig_errors.h>
29: #include <mach/port.h>
30: #include <mach/vm_param.h>
31: #include <mach/notify.h>
32: #include <mach/mach_host_server.h>
33: #include <mach/mach_types.h>
34:
35: #include <machine/machparam.h> /* spl definitions */
36:
37: #include <ipc/ipc_port.h>
38: #include <ipc/ipc_space.h>
39:
40: #include <kern/clock.h>
41: #include <kern/spl.h>
42: #include <kern/ast.h>
43: #include <kern/counters.h>
44: #include <kern/queue.h>
45: #include <kern/zalloc.h>
46: #include <kern/thread.h>
47: #include <kern/thread_swap.h>
48: #include <kern/task.h>
49: #include <kern/sched_prim.h>
50: #include <kern/misc_protos.h>
51:
52: #include <vm/pmap.h>
53: #include <vm/vm_map.h>
54: #include <vm/vm_kern.h>
55:
56: #include <device/device_types.h>
57: #include <device/device_port.h>
58: #include <device/device_server.h>
59:
60: #include <sys/ioctl.h>
61:
62: #include <machine/machparam.h>
63:
64: #ifdef __ppc__
65: #include <ppc/mappings.h>
66: #include <ppc/pmap_internals.h>
67: #endif
68: #include <IOKit/IOTypes.h>
69:
70: #undef DEBUG
71: #define DEBUG
72: #define EXTERN
73: #define MIGEXTERN
74:
75: /*
76: * Functions in iokit:IOUserClient.cpp
77: */
78:
79: extern void iokit_add_reference( io_object_t obj );
80:
81: extern void iokit_remove_reference( io_object_t obj );
82:
83: extern ipc_port_t iokit_port_for_object( io_object_t obj,
84: ipc_kobject_type_t type );
85:
86: extern kern_return_t iokit_client_died( io_object_t obj,
87: ipc_port_t port, ipc_kobject_type_t type );
88:
89: extern kern_return_t
90: iokit_client_memory_for_type(
91: io_object_t connect,
92: unsigned int type,
93: unsigned int * flags,
94: vm_address_t * address,
95: vm_size_t * size );
96:
97: /*
98: * Lookup a device by its port.
99: * Doesn't consume the naked send right; produces a device reference.
100: */
101: MIGEXTERN io_object_t
102: iokit_lookup_object_port(
103: ipc_port_t port)
104: {
105: register io_object_t obj;
106:
107: if (!IP_VALID(port))
108: return (NULL);
109:
110: ip_lock(port);
111: if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_OBJECT)) {
112: obj = (io_object_t) port->ip_kobject;
113: iokit_add_reference( obj );
114: }
115: else
116: obj = NULL;
117:
118: ip_unlock(port);
119:
120: return( obj );
121: }
122:
123: MIGEXTERN io_object_t
124: iokit_lookup_connect_port(
125: ipc_port_t port)
126: {
127: register io_object_t obj;
128:
129: if (!IP_VALID(port))
130: return (NULL);
131:
132: ip_lock(port);
133: if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_CONNECT)) {
134: obj = (io_object_t) port->ip_kobject;
135: iokit_add_reference( obj );
136: }
137: else
138: obj = NULL;
139:
140: ip_unlock(port);
141:
142: return( obj );
143: }
144:
145: /*
146: * Get the port for a device.
147: * Consumes a device reference; produces a naked send right.
148: */
149: MIGEXTERN ipc_port_t
150: iokit_make_object_port(
151: io_object_t obj )
152: {
153: register ipc_port_t port;
154:
155: if( obj == NULL)
156: return IP_NULL;
157:
158: port = iokit_port_for_object( obj, IKOT_IOKIT_OBJECT );
159: if( port)
160: port = ipc_port_make_send( port);
161:
162: iokit_remove_reference( obj );
163:
164: return( port);
165: }
166:
167: MIGEXTERN ipc_port_t
168: iokit_make_connect_port(
169: io_object_t obj )
170: {
171: register ipc_port_t port;
172:
173: if( obj == NULL)
174: return IP_NULL;
175:
176: port = iokit_port_for_object( obj, IKOT_IOKIT_CONNECT );
177: if( port)
178: port = ipc_port_make_send( port);
179:
180: iokit_remove_reference( obj );
181:
182: return( port);
183: }
184:
185:
186: EXTERN ipc_port_t
187: iokit_alloc_object_port( io_object_t obj, ipc_kobject_type_t type );
188:
189: int gIOKitPortCount;
190:
191: EXTERN ipc_port_t
192: iokit_alloc_object_port( io_object_t obj, ipc_kobject_type_t type )
193: {
194: ipc_port_t notify;
195: ipc_port_t port;
196:
197: do {
198:
199: /* Allocate port, keeping a reference for it. */
200: port = ipc_port_alloc_kernel();
201: if( port == IP_NULL)
202: continue;
203:
204: /* set kobject & type */
205: // iokit_add_reference( obj );
206: ipc_kobject_set( port, (ipc_kobject_t) obj, type);
207:
208: /* Request no-senders notifications on the port. */
209: notify = ipc_port_make_sonce( port);
210: ip_lock( port);
211: ipc_port_nsrequest( port, 1, notify, ¬ify);
212: assert( notify == IP_NULL);
213: gIOKitPortCount++;
214:
215: } while( FALSE);
216:
217: return( port );
218: }
219:
220:
221: EXTERN kern_return_t
222: iokit_destroy_object_port( ipc_port_t port )
223: {
224: ipc_kobject_set( port, IKO_NULL, IKOT_NONE);
225:
226: // iokit_remove_reference( obj );
227:
228: ipc_port_dealloc_kernel( port);
229: gIOKitPortCount--;
230:
231: return( KERN_SUCCESS);
232: }
233:
234: EXTERN mach_port_name_t
235: iokit_make_send_right( task_t task, io_object_t obj, ipc_kobject_type_t type )
236: {
237: kern_return_t kr;
238: ipc_port_t port;
239: mach_port_name_t name;
240:
241: if( obj == NULL)
242: return MACH_PORT_NULL;
243:
244: port = iokit_port_for_object( obj, type );
245: if( port)
246: port = ipc_port_make_send( port);
247: if( port == IP_NULL)
248: return MACH_PORT_NULL;
249:
250: kr = ipc_object_copyout( task->itk_space, (ipc_object_t) port,
251: MACH_MSG_TYPE_PORT_SEND, TRUE, &name);
252:
253: if( kr != KERN_SUCCESS)
254: name = MACH_PORT_NULL;
255:
256: iokit_remove_reference( obj );
257:
258: return( name );
259: }
260:
261: EXTERN vm_map_t
262: iokit_task_map( task_t task )
263: {
264: return( task->map );
265: }
266:
267: EXTERN pmap_t
268: iokit_map_pmap( vm_map_t map )
269: {
270: return( map->pmap );
271: }
272:
273: /*
274: * Handle the No-More_Senders notification generated from a device port destroy.
275: * Since there are no longer any tasks which hold a send right to this device
276: * port a NMS notification has been generated.
277: */
278:
279: static void
280: iokit_no_senders( mach_no_senders_notification_t * notification )
281: {
282: ipc_port_t port;
283: io_object_t obj;
284: ipc_kobject_type_t type;
285:
286: port = (ipc_port_t) notification->not_header.msgh_remote_port;
287:
288: // convert a port to io_object_t.
289: if( IP_VALID(port)) {
290: ip_lock(port);
291: if( ip_active(port)) {
292: obj = (io_object_t) port->ip_kobject;
293: type = ip_kotype( port );
294: if( (IKOT_IOKIT_OBJECT == type)
295: || (IKOT_IOKIT_CONNECT == type))
296: iokit_add_reference( obj );
297: else
298: obj = NULL;
299: }
300: ip_unlock(port);
301:
302: if( obj ) {
303: (void) iokit_client_died( obj, port, type );
304: iokit_remove_reference( obj );
305: }
306: }
307: }
308:
309:
310: EXTERN
311: boolean_t
312: iokit_notify( mach_msg_header_t * msg )
313: {
314: switch (msg->msgh_id) {
315: case MACH_NOTIFY_NO_SENDERS:
316: iokit_no_senders((mach_no_senders_notification_t *) msg);
317: return TRUE;
318:
319: case MACH_NOTIFY_PORT_DELETED:
320: case MACH_NOTIFY_PORT_DESTROYED:
321: case MACH_NOTIFY_SEND_ONCE:
322: case MACH_NOTIFY_DEAD_NAME:
323: default:
324: printf("iokit_notify: strange notification %ld\n", msg->msgh_id);
325: return FALSE;
326: }
327: }
328:
329: static void IOMapPage(vm_map_t map, vm_offset_t va, vm_offset_t pa,
330: int mapFlags)
331:
332: {
333: #ifdef __ppc__
334: struct phys_entry * pp;
335: spl_t spl;
336: int memattr;
337: #endif
338: vm_prot_t prot;
339: pmap_t pmap = map->pmap;
340:
341: prot = (mapFlags & kIOMapReadOnly)
342: ? VM_PROT_READ : (VM_PROT_READ|VM_PROT_WRITE);
343:
344: #if __ppc__
345:
346: /* Get the physent for this physical page */
347: pp = pmap_find_physentry(pa);
348: spl = splhigh();
349:
350: /* Remove any other mapping at this address */
351: mapping_remove(pmap->space, va);
352:
353: switch( mapFlags & kIOMapCacheMask ) {
354:
355: case kIOMapDefaultCache:
356: default:
357: if( pp )
358: memattr = ((pp->pte1 & 0x00000078) >> 3);
359: else
360: memattr = PTE_WIMG_UNCACHED_COHERENT_GUARDED;
361: break;
362:
363: case kIOMapInhibitCache:
364: memattr = PTE_WIMG_UNCACHED_COHERENT_GUARDED;
365: break;
366:
367: case kIOMapWriteThruCache:
368: memattr = PTE_WIMG_WT_CACHED_COHERENT_GUARDED;
369: break;
370: case kIOMapCopybackCache:
371: // memattr = PTE_WIMG_CB_CACHED_COHERENT;
372: memattr = PTE_WIMG_CB_CACHED;
373: break;
374: }
375:
376: /* Make the address mapping */
377: mapping_make(pmap, pmap->space, 0, va, pa, prot, memattr);
378:
379: splx(spl);
380: #else
381: pmap_enter( pmap, va, pa, prot, TRUE);
382: #endif
383: }
384:
385: kern_return_t IOMapPages(vm_map_t map, vm_offset_t va, vm_offset_t pa,
386: vm_size_t length, unsigned int options)
387: {
388: vm_size_t off;
389:
390: #if __ppc__
391: /* TEMPORARY - make sure there are enough free mappings */
392: mapping_prealloc( length );
393: #endif
394:
395: // enter each page's physical address in the target map
396: for ( off = 0; off < length; off += page_size ) {
397: IOMapPage( map, va + off, pa + off, options );
398: }
399:
400: #ifdef __ppc__
401: /* TEMPORARY - make sure there are enough free mappings */
402: mapping_relpre();
403: #endif
404:
405: return( KERN_SUCCESS );
406: }
407:
408: void IOGetTime( mach_timespec_t * clock_time);
409: void IOGetTime( mach_timespec_t * clock_time)
410: {
411: *clock_time = clock_get_system_value();
412: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.