Annotation of XNU/osfmk/device/iokit_rpc.c, revision 1.1

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, &notify);
        !           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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.