Annotation of driverkit/libDriver/Kernel/generalFuncsPrivate.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
                     25:  *
                     26:  * generalFuncsPrivate.m - Kernel internal (KERNEL_PRIVATE) portion of 
                     27:  * generalFuncs module.
                     28:  *
                     29:  * HISTORY
                     30:  * 31-Oct-91    Doug Mitchell at NeXT
                     31:  *      Created.
                     32:  */
                     33: 
                     34: #define ARCH_PRIVATE   1
                     35: 
                     36: #import <mach/mach_types.h>
                     37: 
                     38: #import <objc/objc.h> 
                     39: #import <driverkit/generalFuncs.h>
                     40: #import <driverkit/kernelDriver.h>
                     41: #import <stdarg.h>
                     42: #import <kern/sched.h>
                     43: #import <machkit/NXLock.h>
                     44: #import <machine/param.h>
                     45: 
                     46: #import <mach/vm_param.h>
                     47: 
                     48: extern void    *_io_vm_task(void *);
                     49: extern void    *_io_vm_task_self(void);
                     50: extern void    *_io_vm_task_pmap(vm_task_t     task);
                     51: extern void    *_io_vm_task_current(void);
                     52: extern void    *_io_vm_task_buf(void *);
                     53: extern void    *_io_convert_port_in(port_t port);
                     54: extern port_t  _io_convert_port_out(void *kport);
                     55: extern port_t  _io_host_priv_self(void);
                     56: extern void    *_io_get_kern_port(port_name_t port);
                     57: extern port_name_t     _io_task_get_port(void *kport);
                     58: 
                     59:        
                     60: 
                     61: 
                     62: /*
                     63:  * Static variables for this module.
                     64:  */
                     65: static IOThreadFunc threadArgFcn;
                     66: static void *threadArgArg;
                     67: static int libInitialized;
                     68: 
                     69: /*
                     70:  * globals shared with libDriver's libIO.m and the kern_dev server.
                     71:  */
                     72: port_name_t IOTask;                    // IOTask's version of its own 
                     73:                                        //    task_t
                     74: task_t IOTask_kern;                    // kernel internal version of IOTask
                     75: 
                     76: static id threadArgLock;               // NXLock 
                     77: 
                     78: 
                     79: #ifdef DEBUG
                     80: extern void iotaskTest();
                     81: #endif DEBUG;
                     82: 
                     83: /*
                     84:  * Local prototypes.
                     85:  */
                     86: static void ioThreadStart();
                     87: 
                     88: void IOInitGeneralFuncs(void)
                     89: {
                     90:        if(libInitialized) {
                     91:                return; 
                     92:        }
                     93: 
                     94:        threadArgLock = [NXLock new];
                     95: 
                     96:        libInitialized = 1;
                     97: }
                     98: 
                     99: /*
                    100:  * We pass an argument to a new thread by saving fcn and arg in some
                    101:  * locked variables and starting the thread at ioThreadStart(). This
                    102:  * function retrives fcn and arg and makes the appropriate call.
                    103:  *
                    104:  * Note in the kernel, IOThread == thread_t. 
                    105:  */
                    106: IOThread IOForkThread(IOThreadFunc fcn, void *arg)
                    107: {
                    108:        IOThread thread;
                    109:        /*
                    110:         * We do the lock, ioThreadStart() does the unlock.
                    111:         */
                    112:        [threadArgLock lock];
                    113:        threadArgFcn = fcn;
                    114:        threadArgArg = arg;
                    115:        thread = (IOThread)kernel_thread(IOTask_kern, ioThreadStart);
                    116:        (void) thread_priority(thread, MAXPRI_USER, FALSE);
                    117:        return(thread);
                    118: }
                    119: 
                    120: /*
                    121:  * All kernel IOThreads start here.
                    122:  */
                    123: static void ioThreadStart()
                    124: {
                    125:        IOThreadFunc fcn = threadArgFcn;
                    126:        void *arg = threadArgArg;
                    127: 
                    128:        [threadArgLock unlock];
                    129:        
                    130:        (void) thread_wire(1, (thread_t)current_thread_EXTERNAL(), TRUE);
                    131: 
                    132:        (*fcn)(arg);
                    133:        
                    134:        /*
                    135:         * And just in case...
                    136:         */
                    137:        IOExitThread();
                    138: }
                    139: 
                    140: IOReturn
                    141: IOSetThreadPriority(IOThread iothread, int priority)
                    142: {
                    143:     thread_t           thread = (thread_t)iothread;
                    144:     kern_return_t      result;
                    145:     
                    146:     result = thread_priority(thread, priority, FALSE);
                    147:     if (result == KERN_INVALID_ARGUMENT)
                    148:        return (IO_R_INVALID_ARG);
                    149:     else if (result == KERN_FAILURE)
                    150:        return (IO_R_PRIVILEGE);
                    151:        
                    152:     return (IO_R_SUCCESS);
                    153: }
                    154: 
                    155: IOReturn
                    156: IOSetThreadPolicy(IOThread iothread, int policy)
                    157: {
                    158:     thread_t           thread = (thread_t)iothread;
                    159:     int                        policy_data;
                    160:     kern_return_t      result;
                    161:     
                    162:     if (policy == POLICY_FIXEDPRI)
                    163:        policy_data = min_quantum;
                    164:     else
                    165:        policy_data = 0;
                    166:     
                    167:     result = thread_policy(thread, policy, policy_data);
                    168:     if (result == KERN_INVALID_ARGUMENT)
                    169:        return (IO_R_INVALID_ARG);
                    170:     else if (result == KERN_FAILURE)
                    171:        return (IO_R_PRIVILEGE);
                    172:        
                    173:     return (IO_R_SUCCESS);
                    174: }
                    175: 
                    176: void IOSuspendThread(IOThread thread)
                    177: {
                    178:        thread_suspend((thread_t)thread);
                    179: }
                    180: 
                    181: void IOResumeThread(IOThread thread)
                    182: {
                    183:        thread_resume((thread_t)thread);
                    184: }
                    185: 
                    186: volatile void IOExitThread()
                    187: {
                    188:        thread_terminate((thread_t)current_thread_EXTERNAL());
                    189:        (volatile void)thread_halt_self(); 
                    190: }
                    191: 
                    192: 
                    193: /*
                    194:  * This returns the kernel's map under the assumption that this function 
                    195:  * is called in preparation for setting up a DMA via IOEnqueueDmaInt(). 
                    196:  * The IOTask itself can not access memory in its vm_map (IOTask_kern->map).
                    197:  * For actual VM operations using the Mach API, use task_self().
                    198:  */
                    199: vm_task_t IOVmTaskSelf()
                    200: {
                    201:        return((vm_task_t)_io_vm_task_self());
                    202: }
                    203: 
                    204: /*
                    205:  * Returns the current task's vm_task_t.
                    206:  */
                    207: vm_task_t IOVmTaskCurrent()
                    208: {
                    209: 
                    210:        return ((vm_task_t)_io_vm_task_current());
                    211: }
                    212: 
                    213: /*
                    214:  * Set the current thread's UNIX errno.
                    215:  */
                    216: void IOSetUNIXError(int errno)
                    217: {
                    218: #warning u.u_error passing disabled
                    219: #if 0
                    220:        u.u_error = errno;
                    221: #endif 0
                    222: }
                    223:  
                    224: /*
                    225:  * Get an IOTask version of a kern_port_t. 
                    226:  */
                    227: port_name_t IOTaskGetPort(port_t kern_port)
                    228: {
                    229:        void *                  kport = (void *)kern_port;
                    230: 
                    231:        return (_io_task_get_port(kport));
                    232: }
                    233: 
                    234: /* 
                    235:  * Get a kern_port_t version of an IOTask port.
                    236:  */
                    237: port_t IOGetKernPort(port_name_t userPort)
                    238: {
                    239:        return ((port_t)_io_get_kern_port(userPort));
                    240: }
                    241: 
                    242: 
                    243: /*
                    244:  * Convert any kind of port to any other kind.
                    245:  * Returns PORT_NULL on error.
                    246:  */
                    247: port_t IOConvertPort(port_t inPort,    // to be converted
                    248:        IOIPCSpace from,                // IPC space of inPort
                    249:        IOIPCSpace to)                  // IPCSpace of returned port
                    250: {
                    251:        void *          inPortKern;
                    252:        port_t          outPort;
                    253:        
                    254:        /*
                    255:         * First get a kern_port_t version of inPort.
                    256:         */
                    257:        switch(from) {
                    258:            case IO_Kernel:
                    259:                inPortKern = (void *)inPort;
                    260:                break;
                    261:            case IO_KernelIOTask:
                    262:                inPortKern = (void *)IOGetKernPort(inPort);
                    263:                break;
                    264:            case IO_CurrentTask:
                    265:                        inPortKern = _io_convert_port_in(inPort);
                    266:                if(!inPortKern) {
                    267:                        IOLog("IOConvertPort: Bad Port\n");
                    268:                        return PORT_NULL;
                    269:                }
                    270:                break;
                    271:        }
                    272:        
                    273:        /*
                    274:         * Now convert as appropriate.
                    275:         */
                    276:        switch(to) {
                    277:            case IO_Kernel:
                    278:                outPort = (port_t)inPortKern;
                    279:                break;
                    280:            case IO_KernelIOTask:
                    281:                outPort = IOTaskGetPort((port_t)inPortKern);
                    282:                break;
                    283:            case IO_CurrentTask:
                    284:                outPort = _io_convert_port_out(inPortKern);
                    285:                break;
                    286:        }
                    287:        return outPort;
                    288: }
                    289: 
                    290: /*
                    291:  * Returns vm_task_t associated with a struct buf. 
                    292:  */
                    293: vm_task_t IOVmTaskForBuf(struct buf *buf)
                    294: {
                    295:        return ((vm_task_t)_io_vm_task_buf(buf));
                    296: }
                    297: 
                    298: /*
                    299:  * Obtain the IOTask version of host_priv_self() (the privileged host port).
                    300:  */
                    301: 
                    302: port_t IOHostPrivSelf()
                    303: {
                    304:        return (_io_host_priv_self());
                    305: }
                    306: 
                    307: /*
                    308:  *  Find a physical address (if any) for the specified virtual address.
                    309:  */
                    310: IOReturn IOPhysicalFromVirtual(vm_task_t task, 
                    311:        vm_address_t virtualAddress,
                    312:        unsigned *physicalAddress)
                    313: {
                    314:        *physicalAddress = pmap_extract(_io_vm_task_pmap(task),
                    315:                virtualAddress);
                    316:        if(*physicalAddress == 0) {
                    317:                return IO_R_INVALID_ARG;
                    318:        }
                    319:        else {
                    320:                return IO_R_SUCCESS;
                    321:        }
                    322: }
                    323: 
                    324: /*
                    325:  * Create a mapping in the IOTask address map
                    326:  * for the specified physical region.  Assumes
                    327:  * that the physical memory is already wired.
                    328:  */
                    329: IOReturn
                    330: IOMapPhysicalIntoIOTask(
                    331:     unsigned           physicalAddress,
                    332:     unsigned           length,
                    333:     vm_address_t       *virtualAddressP
                    334: )
                    335: {
                    336:     kern_return_t      result;
                    337:     vm_offset_t                vAddr;
                    338:     
                    339:     result = vm_allocate(_io_vm_task_self(), virtualAddressP, length, TRUE);
                    340:     if (result != KERN_SUCCESS)
                    341:        return (IO_R_NO_SPACE);
                    342:        
                    343:     vAddr = *virtualAddressP;
                    344:     vAddr = trunc_page(vAddr);
                    345:     length = round_page(length);
                    346:     
                    347:     physicalAddress = trunc_page(physicalAddress);
                    348:     
                    349:     while (length > 0) {
                    350:        pmap_enter(_io_vm_task_pmap((vm_task_t)_io_vm_task_self()),
                    351:                vAddr, physicalAddress, VM_PROT_READ|VM_PROT_WRITE, TRUE);
                    352:                
                    353:        vAddr += PAGE_SIZE; length -= PAGE_SIZE; physicalAddress += PAGE_SIZE;
                    354:     }
                    355:     
                    356:     return (IO_R_SUCCESS);
                    357: }
                    358: 
                    359: IOReturn
                    360: IOMapPhysicalIntoIOTaskUnaligned(
                    361:     unsigned           physicalAddress,
                    362:     unsigned           length,
                    363:     vm_address_t       *virtualAddressP
                    364: )
                    365: {
                    366:     IOReturn           result;
                    367: 
                    368:     /* Recompute the length based on the actual region requested */
                    369:     length = round_page(physicalAddress + length) - physicalAddress;
                    370: 
                    371:     result = IOMapPhysicalIntoIOTask(physicalAddress, length, virtualAddressP);
                    372:     if (result == IO_R_SUCCESS) {
                    373:        /* Now remap the alloced pointer to point to the right place */ 
                    374:        *virtualAddressP += physicalAddress - trunc_page(physicalAddress);
                    375:     }
                    376:     return result;
                    377: }
                    378: 
                    379: /*
                    380:  * Destroy a mapping created by
                    381:  * IOTaskCreateVirtualFromPhysical()
                    382:  */
                    383: IOReturn
                    384: IOUnmapPhysicalFromIOTask(
                    385:     vm_address_t       virtualAddress,
                    386:     unsigned           length
                    387: )
                    388: {
                    389:     (void) vm_deallocate(_io_vm_task_self(), virtualAddress, length);
                    390: 
                    391:     return (IO_R_SUCCESS);
                    392: }
                    393: 
                    394: /* end of generalFuncsPrivate.m */

unix.superglobalmegacorp.com

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