|
|
1.1 root 1: /*
2: * Copyright (c) 1998-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: /*
23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24: *
25: * HISTORY
26: *
27: * 17-Apr-91 Portions from libIO.m, Doug Mitchell at NeXT.
28: * 17-Nov-98 cpp
29: *
30: */
31:
32: #include <IOKit/system.h>
33: #include <mach/sync_policy.h>
34: #include <machine/machine_routines.h>
35: #include <libkern/c++/OSCPPDebug.h>
36:
37: #include <IOKit/assert.h>
38:
39: #include <IOKit/IOReturn.h>
40: #include <IOKit/IOLib.h>
41: #include <IOKit/IOKitDebug.h>
42:
43: mach_timespec_t IOZeroTvalspec = { 0, 0 };
44:
45: /*
46: * Static variables for this module.
47: */
48:
49: static IOThreadFunc threadArgFcn;
50: static void * threadArgArg;
51: static lock_t * threadArgLock;
52:
53: void IOLibInit(void)
54: {
55: static bool libInitialized;
56:
57: if(libInitialized)
58: return;
59:
60: threadArgLock = lock_alloc( true, NULL, NULL );
61:
62: libInitialized = true;
63: }
64:
65: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
66:
67: /*
68: * We pass an argument to a new thread by saving fcn and arg in some
69: * locked variables and starting the thread at ioThreadStart(). This
70: * function retrives fcn and arg and makes the appropriate call.
71: *
72: */
73:
74: static void ioThreadStart( void )
75: {
76: IOThreadFunc fcn;
77: void * arg;
78:
79: fcn = threadArgFcn;
80: arg = threadArgArg;
81: lock_done( threadArgLock);
82:
83: (*fcn)(arg);
84:
85: IOExitThread();
86: }
87:
88: IOThread IOCreateThread(IOThreadFunc fcn, void *arg)
89: {
90: IOThread thread;
91:
92: lock_write( threadArgLock);
93: threadArgFcn = fcn;
94: threadArgArg = arg;
95:
96: thread = kernel_thread( kernel_task, ioThreadStart);
97:
98: return(thread);
99: }
100:
101:
102: volatile void IOExitThread()
103: {
104: (void) thread_terminate(current_act());
105: }
106:
107: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
108:
109:
110: void * IOMalloc(vm_size_t size)
111: {
112: void * address;
113:
114: address = (void *)kalloc(size);
115: #ifdef DEBUG
116: if (address)
117: debug_iomalloc_size += size;
118: #endif
119: return address;
120: }
121:
122: void IOFree(void * address, vm_size_t size)
123: {
124: if (address) {
125: kfree((vm_offset_t)address, size);
126: #ifdef DEBUG
127: debug_iomalloc_size -= size;
128: #endif
129: }
130: }
131:
132: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
133:
134: #define KMA_HERE 0x01
135: #define KMA_NOPAGEWAIT 0x02
136: #define KMA_KOBJECT 0x04
137:
138: extern kern_return_t
139: kernel_memory_allocate(
140: register vm_map_t map,
141: register vm_offset_t *addrp,
142: register vm_size_t size,
143: register vm_offset_t mask,
144: int flags);
145:
146: extern void
147: kmem_free(
148: vm_map_t map,
149: vm_offset_t addr,
150: vm_size_t size);
151:
152: void * IOMallocAligned(vm_size_t size, vm_size_t alignment)
153: {
154: kern_return_t kr;
155: vm_address_t address;
156: vm_address_t allocationAddress;
157: vm_size_t adjustedSize;
158: vm_offset_t alignMask = alignment - 1;
159:
160: if (size == 0) return 0;
161:
162: adjustedSize = size + sizeof(vm_size_t) + sizeof(vm_address_t);
163: if (adjustedSize >= page_size) {
164:
165: kr = kernel_memory_allocate(kernel_map, &address,
166: size, alignMask, KMA_KOBJECT);
167: if (KERN_SUCCESS != kr) {
168: IOLog("Failed %08x, %08x\n", size, alignment);
169: address = 0;
170: }
171: } else {
172:
173: adjustedSize += alignMask;
174: allocationAddress = (vm_address_t) kalloc(adjustedSize);
175:
176: if (allocationAddress) {
177: address = (allocationAddress + alignMask
178: + (sizeof(vm_size_t) + sizeof(vm_address_t)))
179: & (~alignMask);
180:
181: *((vm_size_t *)(address - sizeof(vm_size_t)
182: - sizeof(vm_address_t))) = adjustedSize;
183: *((vm_address_t *)(address - sizeof(vm_address_t)))
184: = allocationAddress;
185: } else
186: address = 0;
187: }
188:
189: assert(0 == (address & alignMask));
190:
191: #ifdef DEBUG
192: if( address)
193: debug_iomalloc_size += size;
194: #endif
195:
196: return (void *) address;
197: }
198:
199: void IOFreeAligned(void * address, vm_size_t size)
200: {
201: vm_address_t allocationAddress;
202: vm_size_t adjustedSize;
203:
204: if( !address)
205: return;
206:
207: assert(size);
208:
209: adjustedSize = size + sizeof(vm_size_t) + sizeof(vm_address_t);
210: if (adjustedSize >= page_size) {
211:
212: kmem_free( kernel_map, (vm_address_t) address, size);
213:
214: } else {
215: adjustedSize = *((vm_size_t *)( (vm_address_t) address
216: - sizeof(vm_address_t) - sizeof(vm_size_t)));
217: allocationAddress = *((vm_address_t *)( (vm_address_t) address
218: - sizeof(vm_address_t) ));
219:
220: kfree((vm_offset_t) allocationAddress, adjustedSize);
221: }
222:
223: #ifdef DEBUG
224: debug_iomalloc_size -= size;
225: #endif
226: }
227:
228: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
229:
230: extern kern_return_t kmem_alloc_contig(
231: vm_map_t map,
232: vm_offset_t *addrp,
233: vm_size_t size,
234: vm_offset_t mask,
235: int flags);
236:
237: void * IOMallocContiguous(vm_size_t size, vm_size_t alignment,
238: IOPhysicalAddress * physicalAddress)
239: {
240: kern_return_t kr;
241: vm_address_t address;
242: vm_address_t allocationAddress;
243: vm_size_t adjustedSize;
244: vm_offset_t alignMask;
245:
246: if (size == 0) return 0;
247: if (alignment == 0) alignment = 1;
248:
249: alignMask = alignment - 1;
250: adjustedSize = (2 * size) + sizeof(vm_size_t) + sizeof(vm_address_t);
251: if (adjustedSize >= page_size) {
252:
253: kr = kmem_alloc_contig(kernel_map, &address, size,
254: alignMask, KMA_KOBJECT);
255: if (KERN_SUCCESS != kr)
256: address = 0;
257:
258: } else {
259:
260: adjustedSize += alignMask;
261: allocationAddress = (vm_address_t)
262: kalloc(adjustedSize);
263: if (allocationAddress) {
264:
265: address = (allocationAddress + alignMask
266: + (sizeof(vm_size_t) + sizeof(vm_address_t)))
267: & (~alignMask);
268:
269: if (atop(address) != atop(address + size - 1))
270: address = round_page(address);
271:
272: *((vm_size_t *)(address - sizeof(vm_size_t)
273: - sizeof(vm_address_t))) = adjustedSize;
274: *((vm_address_t *)(address - sizeof(vm_address_t)))
275: = allocationAddress;
276: } else
277: address = 0;
278: }
279:
280: if( address && physicalAddress)
281: *physicalAddress = (IOPhysicalAddress) pmap_extract( kernel_pmap,
282: address );
283:
284: assert(0 == (address & alignMask));
285:
286: #ifdef DEBUG
287: if( address)
288: debug_iomalloc_size += size;
289: #endif
290:
291: return (void *) address;
292: }
293:
294: void IOFreeContiguous(void * address, vm_size_t size)
295: {
296: vm_address_t allocationAddress;
297: vm_size_t adjustedSize;
298:
299: if( !address)
300: return;
301:
302: assert(size);
303:
304: adjustedSize = (2 * size) + sizeof(vm_size_t) + sizeof(vm_address_t);
305: if (adjustedSize >= page_size) {
306:
307: kmem_free( kernel_map, (vm_address_t) address, size);
308:
309: } else {
310: adjustedSize = *((vm_size_t *)( (vm_address_t) address
311: - sizeof(vm_address_t) - sizeof(vm_size_t)));
312: allocationAddress = *((vm_address_t *)( (vm_address_t) address
313: - sizeof(vm_address_t) ));
314:
315: kfree((vm_offset_t) allocationAddress, adjustedSize);
316: }
317:
318: #ifdef DEBUG
319: debug_iomalloc_size -= size;
320: #endif
321: }
322:
323: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
324:
325: extern kern_return_t IOMapPages(vm_map_t map, vm_offset_t va, vm_offset_t pa,
326: vm_size_t length, unsigned int options);
327:
328: IOReturn IOSetProcessorCacheMode( task_t task, IOVirtualAddress address,
329: IOByteCount length, IOOptionBits cacheMode )
330: {
331: IOReturn ret = kIOReturnSuccess;
332: vm_offset_t physAddr;
333:
334: if( task != kernel_task)
335: return( kIOReturnUnsupported );
336:
337: length = round_page(address + length) - trunc_page( address );
338: address = trunc_page( address );
339:
340: // make map mode
341: cacheMode = (cacheMode << kIOMapCacheShift) & kIOMapCacheMask;
342:
343: while( (kIOReturnSuccess == ret) && (length > 0) ) {
344:
345: physAddr = pmap_extract( kernel_pmap, address );
346: if( physAddr)
347: ret = IOMapPages( get_task_map(task), address, physAddr, page_size, cacheMode );
348: else
349: ret = kIOReturnVMError;
350:
351: length -= page_size;
352: }
353:
354: return( ret );
355: }
356:
357:
358: IOReturn IOFlushProcessorCache( task_t task, IOVirtualAddress address,
359: IOByteCount length )
360: {
361: if( task != kernel_task)
362: return( kIOReturnUnsupported );
363:
364: #if __ppc__
365: flush_dcache( (vm_offset_t) address, (unsigned) length, false );
366: #endif
367:
368: return( kIOReturnSuccess );
369: }
370:
371: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
372:
373: SInt32 OSKernelStackRemaining( void )
374: {
375: SInt32 stack;
376:
377: stack = (((SInt32) &stack) & (KERNEL_STACK_SIZE - 1));
378:
379: return( stack );
380: }
381:
382: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
383:
384: void IOSleep(unsigned milliseconds)
385: {
386: assert_wait_timeout(milliseconds, THREAD_INTERRUPTIBLE);
387: thread_block((void (*)(void))0);
388: thread_cancel_timer();
389: }
390:
391: /*
392: * Spin for indicated number of microseconds.
393: */
394: void IODelay(unsigned microseconds)
395: {
396: extern void delay(int usec);
397:
398: delay(microseconds);
399: }
400:
401: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
402:
403: void IOLog(const char *format, ...)
404: {
405: va_list ap;
406: extern void conslog_putc(char);
407: extern void logwakeup();
408:
409: va_start(ap, format);
410: _doprnt(format, &ap, conslog_putc, 16);
411: va_end(ap);
412: logwakeup();
413: }
414:
415: void IOPanic(const char *reason)
416: {
417: panic(reason);
418: }
419:
420: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
421:
422: /*
423: * Convert a integer constant (typically a #define or enum) to a string.
424: */
425: static char noValue[80]; // that's pretty
426:
427: const char *IOFindNameForValue(int value, const IONamedValue *regValueArray)
428: {
429: for( ; regValueArray->name; regValueArray++) {
430: if(regValueArray->value == value)
431: return(regValueArray->name);
432: }
433: sprintf(noValue, "%d(d) (UNDEFINED)", value);
434: return((const char *)noValue);
435: }
436:
437: IOReturn IOFindValueForName(const char *string,
438: const IONamedValue *regValueArray,
439: int *value)
440: {
441: for( ; regValueArray->name; regValueArray++) {
442: if(!strcmp(regValueArray->name, string)) {
443: *value = regValueArray->value;
444: return kIOReturnSuccess;
445: }
446: }
447: return kIOReturnBadArgument;
448: }
449:
450: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
451:
452: IOAlignment IOSizeToAlignment(unsigned int size)
453: {
454: register int shift;
455: const int intsize = sizeof(unsigned int) * 8;
456:
457: for (shift = 1; shift < intsize; shift++) {
458: if (size & 0x80000000)
459: return (IOAlignment)(intsize - shift);
460: size <<= 1;
461: }
462: return 0;
463: }
464:
465: unsigned int IOAlignmentToSize(IOAlignment align)
466: {
467: unsigned int size;
468:
469: for (size = 1; align; align--) {
470: size <<= 1;
471: }
472: return size;
473: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.