|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.