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