|
|
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.