1 | /* |
2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License |
8 | * Version 2.0 (the 'License'). You may not use this file except in |
9 | * compliance with the License. The rights granted to you under the License |
10 | * may not be used to create, or enable the creation or redistribution of, |
11 | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | * circumvent, violate, or enable the circumvention or violation of, any |
13 | * terms of an Apple operating system software license agreement. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and |
24 | * limitations under the License. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | |
29 | #define _IOMEMORYDESCRIPTOR_INTERNAL_ |
30 | |
31 | #include <IOKit/assert.h> |
32 | #include <IOKit/system.h> |
33 | |
34 | #include <IOKit/IOLib.h> |
35 | #include <IOKit/IOMapper.h> |
36 | #include <IOKit/IOBufferMemoryDescriptor.h> |
37 | #include <libkern/OSDebug.h> |
38 | #include <mach/mach_vm.h> |
39 | |
40 | #include "IOKitKernelInternal.h" |
41 | |
42 | #ifdef IOALLOCDEBUG |
43 | #include <libkern/c++/OSCPPDebug.h> |
44 | #endif |
45 | #include <IOKit/IOStatisticsPrivate.h> |
46 | |
47 | #if IOKITSTATS |
48 | #define IOStatisticsAlloc(type, size) \ |
49 | do { \ |
50 | IOStatistics::countAlloc(type, size); \ |
51 | } while (0) |
52 | #else |
53 | #define IOStatisticsAlloc(type, size) |
54 | #endif /* IOKITSTATS */ |
55 | |
56 | |
57 | __BEGIN_DECLS |
58 | void ipc_port_release_send(ipc_port_t port); |
59 | #include <vm/pmap.h> |
60 | |
61 | __END_DECLS |
62 | |
63 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
64 | |
65 | enum |
66 | { |
67 | kInternalFlagPhysical = 0x00000001, |
68 | kInternalFlagPageSized = 0x00000002, |
69 | kInternalFlagPageAllocated = 0x00000004, |
70 | kInternalFlagInit = 0x00000008 |
71 | }; |
72 | |
73 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
74 | |
75 | #define super IOGeneralMemoryDescriptor |
76 | OSDefineMetaClassAndStructors(IOBufferMemoryDescriptor, |
77 | IOGeneralMemoryDescriptor); |
78 | |
79 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
80 | |
81 | static uintptr_t IOBMDPageProc(iopa_t * a) |
82 | { |
83 | kern_return_t kr; |
84 | vm_address_t vmaddr = 0; |
85 | int options = 0; // KMA_LOMEM; |
86 | |
87 | kr = kernel_memory_allocate(kernel_map, &vmaddr, |
88 | page_size, 0, options, VM_KERN_MEMORY_IOKIT); |
89 | |
90 | if (KERN_SUCCESS != kr) vmaddr = 0; |
91 | else bzero((void *) vmaddr, page_size); |
92 | |
93 | return ((uintptr_t) vmaddr); |
94 | } |
95 | |
96 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
97 | |
98 | #ifndef __LP64__ |
99 | bool IOBufferMemoryDescriptor::initWithOptions( |
100 | IOOptionBits options, |
101 | vm_size_t capacity, |
102 | vm_offset_t alignment, |
103 | task_t inTask) |
104 | { |
105 | mach_vm_address_t physicalMask = 0; |
106 | return (initWithPhysicalMask(inTask, options, capacity, alignment, physicalMask)); |
107 | } |
108 | #endif /* !__LP64__ */ |
109 | |
110 | bool IOBufferMemoryDescriptor::initWithPhysicalMask( |
111 | task_t inTask, |
112 | IOOptionBits options, |
113 | mach_vm_size_t capacity, |
114 | mach_vm_address_t alignment, |
115 | mach_vm_address_t physicalMask) |
116 | { |
117 | task_t mapTask = NULL; |
118 | vm_map_t vmmap = NULL; |
119 | mach_vm_address_t highestMask = 0; |
120 | IOOptionBits iomdOptions = kIOMemoryTypeVirtual64 | kIOMemoryAsReference; |
121 | IODMAMapSpecification mapSpec; |
122 | bool mapped = false; |
123 | bool needZero; |
124 | |
125 | if (!capacity) return false; |
126 | |
127 | _options = options; |
128 | _capacity = capacity; |
129 | _internalFlags = 0; |
130 | _internalReserved = 0; |
131 | _buffer = 0; |
132 | |
133 | _ranges.v64 = IONew(IOAddressRange, 1); |
134 | if (!_ranges.v64) |
135 | return (false); |
136 | _ranges.v64->address = 0; |
137 | _ranges.v64->length = 0; |
138 | // make sure super::free doesn't dealloc _ranges before super::init |
139 | _flags = kIOMemoryAsReference; |
140 | |
141 | // Grab IOMD bits from the Buffer MD options |
142 | iomdOptions |= (options & kIOBufferDescriptorMemoryFlags); |
143 | |
144 | if (!(kIOMemoryMapperNone & options)) |
145 | { |
146 | IOMapper::checkForSystemMapper(); |
147 | mapped = (0 != IOMapper::gSystem); |
148 | } |
149 | needZero = (mapped || (0 != (kIOMemorySharingTypeMask & options))); |
150 | |
151 | if (physicalMask && (alignment <= 1)) |
152 | { |
153 | alignment = ((physicalMask ^ (-1ULL)) & (physicalMask - 1)); |
154 | highestMask = (physicalMask | alignment); |
155 | alignment++; |
156 | if (alignment < page_size) |
157 | alignment = page_size; |
158 | } |
159 | |
160 | if ((options & (kIOMemorySharingTypeMask | kIOMapCacheMask | kIOMemoryClearEncrypt)) && (alignment < page_size)) |
161 | alignment = page_size; |
162 | |
163 | if (alignment >= page_size) |
164 | capacity = round_page(capacity); |
165 | |
166 | if (alignment > page_size) |
167 | options |= kIOMemoryPhysicallyContiguous; |
168 | |
169 | _alignment = alignment; |
170 | |
171 | if ((capacity + alignment) < _capacity) return (false); |
172 | |
173 | if ((inTask != kernel_task) && !(options & kIOMemoryPageable)) |
174 | return false; |
175 | |
176 | bzero(&mapSpec, sizeof(mapSpec)); |
177 | mapSpec.alignment = _alignment; |
178 | mapSpec.numAddressBits = 64; |
179 | if (highestMask && mapped) |
180 | { |
181 | if (highestMask <= 0xFFFFFFFF) |
182 | mapSpec.numAddressBits = (32 - __builtin_clz((unsigned int) highestMask)); |
183 | else |
184 | mapSpec.numAddressBits = (64 - __builtin_clz((unsigned int) (highestMask >> 32))); |
185 | highestMask = 0; |
186 | } |
187 | |
188 | // set memory entry cache mode, pageable, purgeable |
189 | iomdOptions |= ((options & kIOMapCacheMask) >> kIOMapCacheShift) << kIOMemoryBufferCacheShift; |
190 | if (options & kIOMemoryPageable) |
191 | { |
192 | iomdOptions |= kIOMemoryBufferPageable; |
193 | if (options & kIOMemoryPurgeable) iomdOptions |= kIOMemoryBufferPurgeable; |
194 | } |
195 | else |
196 | { |
197 | vmmap = kernel_map; |
198 | |
199 | // Buffer shouldn't auto prepare they should be prepared explicitly |
200 | // But it never was enforced so what are you going to do? |
201 | iomdOptions |= kIOMemoryAutoPrepare; |
202 | |
203 | /* Allocate a wired-down buffer inside kernel space. */ |
204 | |
205 | bool contig = (0 != (options & kIOMemoryHostPhysicallyContiguous)); |
206 | |
207 | if (!contig && (0 != (options & kIOMemoryPhysicallyContiguous))) |
208 | { |
209 | contig |= (!mapped); |
210 | contig |= (0 != (kIOMemoryMapperNone & options)); |
211 | #if 0 |
212 | // treat kIOMemoryPhysicallyContiguous as kIOMemoryHostPhysicallyContiguous for now |
213 | contig |= true; |
214 | #endif |
215 | } |
216 | |
217 | if (contig || highestMask || (alignment > page_size)) |
218 | { |
219 | _internalFlags |= kInternalFlagPhysical; |
220 | if (highestMask) |
221 | { |
222 | _internalFlags |= kInternalFlagPageSized; |
223 | capacity = round_page(capacity); |
224 | } |
225 | _buffer = (void *) IOKernelAllocateWithPhysicalRestrict( |
226 | capacity, highestMask, alignment, contig); |
227 | } |
228 | else if (needZero |
229 | && ((capacity + alignment) <= (page_size - gIOPageAllocChunkBytes))) |
230 | { |
231 | _internalFlags |= kInternalFlagPageAllocated; |
232 | needZero = false; |
233 | _buffer = (void *) iopa_alloc(&gIOBMDPageAllocator, &IOBMDPageProc, capacity, alignment); |
234 | if (_buffer) |
235 | { |
236 | IOStatisticsAlloc(kIOStatisticsMallocAligned, capacity); |
237 | #if IOALLOCDEBUG |
238 | OSAddAtomic(capacity, &debug_iomalloc_size); |
239 | #endif |
240 | } |
241 | } |
242 | else if (alignment > 1) |
243 | { |
244 | _buffer = IOMallocAligned(capacity, alignment); |
245 | } |
246 | else |
247 | { |
248 | _buffer = IOMalloc(capacity); |
249 | } |
250 | if (!_buffer) |
251 | { |
252 | return false; |
253 | } |
254 | if (needZero) bzero(_buffer, capacity); |
255 | } |
256 | |
257 | if( (options & (kIOMemoryPageable | kIOMapCacheMask))) { |
258 | vm_size_t size = round_page(capacity); |
259 | |
260 | // initWithOptions will create memory entry |
261 | iomdOptions |= kIOMemoryPersistent; |
262 | |
263 | if( options & kIOMemoryPageable) { |
264 | #if IOALLOCDEBUG |
265 | OSAddAtomicLong(size, &debug_iomallocpageable_size); |
266 | #endif |
267 | mapTask = inTask; |
268 | if (NULL == inTask) |
269 | inTask = kernel_task; |
270 | } |
271 | else if (options & kIOMapCacheMask) |
272 | { |
273 | // Prefetch each page to put entries into the pmap |
274 | volatile UInt8 * startAddr = (UInt8 *)_buffer; |
275 | volatile UInt8 * endAddr = (UInt8 *)_buffer + capacity; |
276 | |
277 | while (startAddr < endAddr) |
278 | { |
279 | UInt8 dummyVar = *startAddr; |
280 | (void) dummyVar; |
281 | startAddr += page_size; |
282 | } |
283 | } |
284 | } |
285 | |
286 | _ranges.v64->address = (mach_vm_address_t) _buffer;; |
287 | _ranges.v64->length = _capacity; |
288 | |
289 | if (!super::initWithOptions(_ranges.v64, 1, 0, |
290 | inTask, iomdOptions, /* System mapper */ 0)) |
291 | return false; |
292 | |
293 | _internalFlags |= kInternalFlagInit; |
294 | #if IOTRACKING |
295 | if (!(options & kIOMemoryPageable)) trackingAccumSize(capacity); |
296 | #endif /* IOTRACKING */ |
297 | |
298 | // give any system mapper the allocation params |
299 | if (kIOReturnSuccess != dmaCommandOperation(kIOMDAddDMAMapSpec, |
300 | &mapSpec, sizeof(mapSpec))) |
301 | return false; |
302 | |
303 | if (mapTask) |
304 | { |
305 | if (!reserved) { |
306 | reserved = IONew( ExpansionData, 1 ); |
307 | if( !reserved) |
308 | return( false ); |
309 | } |
310 | reserved->map = createMappingInTask(mapTask, 0, |
311 | kIOMapAnywhere | (options & kIOMapPrefault) | (options & kIOMapCacheMask), 0, 0); |
312 | if (!reserved->map) |
313 | { |
314 | _buffer = 0; |
315 | return( false ); |
316 | } |
317 | release(); // map took a retain on this |
318 | reserved->map->retain(); |
319 | removeMapping(reserved->map); |
320 | mach_vm_address_t buffer = reserved->map->getAddress(); |
321 | _buffer = (void *) buffer; |
322 | if (kIOMemoryTypeVirtual64 == (kIOMemoryTypeMask & iomdOptions)) |
323 | _ranges.v64->address = buffer; |
324 | } |
325 | |
326 | setLength(_capacity); |
327 | |
328 | return true; |
329 | } |
330 | |
331 | IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::inTaskWithOptions( |
332 | task_t inTask, |
333 | IOOptionBits options, |
334 | vm_size_t capacity, |
335 | vm_offset_t alignment) |
336 | { |
337 | IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; |
338 | |
339 | if (me && !me->initWithPhysicalMask(inTask, options, capacity, alignment, 0)) { |
340 | me->release(); |
341 | me = 0; |
342 | } |
343 | return me; |
344 | } |
345 | |
346 | IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::inTaskWithPhysicalMask( |
347 | task_t inTask, |
348 | IOOptionBits options, |
349 | mach_vm_size_t capacity, |
350 | mach_vm_address_t physicalMask) |
351 | { |
352 | IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; |
353 | |
354 | if (me && !me->initWithPhysicalMask(inTask, options, capacity, 1, physicalMask)) |
355 | { |
356 | me->release(); |
357 | me = 0; |
358 | } |
359 | return me; |
360 | } |
361 | |
362 | #ifndef __LP64__ |
363 | bool IOBufferMemoryDescriptor::initWithOptions( |
364 | IOOptionBits options, |
365 | vm_size_t capacity, |
366 | vm_offset_t alignment) |
367 | { |
368 | return (initWithPhysicalMask(kernel_task, options, capacity, alignment, (mach_vm_address_t)0)); |
369 | } |
370 | #endif /* !__LP64__ */ |
371 | |
372 | IOBufferMemoryDescriptor * IOBufferMemoryDescriptor::withOptions( |
373 | IOOptionBits options, |
374 | vm_size_t capacity, |
375 | vm_offset_t alignment) |
376 | { |
377 | IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; |
378 | |
379 | if (me && !me->initWithPhysicalMask(kernel_task, options, capacity, alignment, 0)) { |
380 | me->release(); |
381 | me = 0; |
382 | } |
383 | return me; |
384 | } |
385 | |
386 | |
387 | /* |
388 | * withCapacity: |
389 | * |
390 | * Returns a new IOBufferMemoryDescriptor with a buffer large enough to |
391 | * hold capacity bytes. The descriptor's length is initially set to the capacity. |
392 | */ |
393 | IOBufferMemoryDescriptor * |
394 | IOBufferMemoryDescriptor::withCapacity(vm_size_t inCapacity, |
395 | IODirection inDirection, |
396 | bool inContiguous) |
397 | { |
398 | return( IOBufferMemoryDescriptor::withOptions( |
399 | inDirection | kIOMemoryUnshared |
400 | | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), |
401 | inCapacity, inContiguous ? inCapacity : 1 )); |
402 | } |
403 | |
404 | #ifndef __LP64__ |
405 | /* |
406 | * initWithBytes: |
407 | * |
408 | * Initialize a new IOBufferMemoryDescriptor preloaded with bytes (copied). |
409 | * The descriptor's length and capacity are set to the input buffer's size. |
410 | */ |
411 | bool IOBufferMemoryDescriptor::initWithBytes(const void * inBytes, |
412 | vm_size_t inLength, |
413 | IODirection inDirection, |
414 | bool inContiguous) |
415 | { |
416 | if (!initWithPhysicalMask(kernel_task, inDirection | kIOMemoryUnshared |
417 | | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), |
418 | inLength, inLength, (mach_vm_address_t)0)) |
419 | return false; |
420 | |
421 | // start out with no data |
422 | setLength(0); |
423 | |
424 | if (!appendBytes(inBytes, inLength)) |
425 | return false; |
426 | |
427 | return true; |
428 | } |
429 | #endif /* !__LP64__ */ |
430 | |
431 | /* |
432 | * withBytes: |
433 | * |
434 | * Returns a new IOBufferMemoryDescriptor preloaded with bytes (copied). |
435 | * The descriptor's length and capacity are set to the input buffer's size. |
436 | */ |
437 | IOBufferMemoryDescriptor * |
438 | IOBufferMemoryDescriptor::withBytes(const void * inBytes, |
439 | vm_size_t inLength, |
440 | IODirection inDirection, |
441 | bool inContiguous) |
442 | { |
443 | IOBufferMemoryDescriptor *me = new IOBufferMemoryDescriptor; |
444 | |
445 | if (me && !me->initWithPhysicalMask( |
446 | kernel_task, inDirection | kIOMemoryUnshared |
447 | | (inContiguous ? kIOMemoryPhysicallyContiguous : 0), |
448 | inLength, inLength, 0 )) |
449 | { |
450 | me->release(); |
451 | me = 0; |
452 | } |
453 | |
454 | if (me) |
455 | { |
456 | // start out with no data |
457 | me->setLength(0); |
458 | |
459 | if (!me->appendBytes(inBytes, inLength)) |
460 | { |
461 | me->release(); |
462 | me = 0; |
463 | } |
464 | } |
465 | return me; |
466 | } |
467 | |
468 | /* |
469 | * free: |
470 | * |
471 | * Free resources |
472 | */ |
473 | void IOBufferMemoryDescriptor::free() |
474 | { |
475 | // Cache all of the relevant information on the stack for use |
476 | // after we call super::free()! |
477 | IOOptionBits flags = _flags; |
478 | IOOptionBits internalFlags = _internalFlags; |
479 | IOOptionBits options = _options; |
480 | vm_size_t size = _capacity; |
481 | void * buffer = _buffer; |
482 | IOMemoryMap * map = 0; |
483 | IOAddressRange * range = _ranges.v64; |
484 | vm_offset_t alignment = _alignment; |
485 | |
486 | if (alignment >= page_size) |
487 | size = round_page(size); |
488 | |
489 | if (reserved) |
490 | { |
491 | map = reserved->map; |
492 | IODelete( reserved, ExpansionData, 1 ); |
493 | if (map) |
494 | map->release(); |
495 | } |
496 | |
497 | if ((options & kIOMemoryPageable) |
498 | || (kInternalFlagPageSized & internalFlags)) size = round_page(size); |
499 | |
500 | #if IOTRACKING |
501 | if (!(options & kIOMemoryPageable) |
502 | && buffer |
503 | && (kInternalFlagInit & _internalFlags)) trackingAccumSize(-size); |
504 | #endif /* IOTRACKING */ |
505 | |
506 | /* super::free may unwire - deallocate buffer afterwards */ |
507 | super::free(); |
508 | |
509 | if (options & kIOMemoryPageable) |
510 | { |
511 | #if IOALLOCDEBUG |
512 | OSAddAtomicLong(-size, &debug_iomallocpageable_size); |
513 | #endif |
514 | } |
515 | else if (buffer) |
516 | { |
517 | if (kInternalFlagPhysical & internalFlags) |
518 | { |
519 | IOKernelFreePhysical((mach_vm_address_t) buffer, size); |
520 | } |
521 | else if (kInternalFlagPageAllocated & internalFlags) |
522 | { |
523 | uintptr_t page; |
524 | page = iopa_free(&gIOBMDPageAllocator, (uintptr_t) buffer, size); |
525 | if (page) |
526 | { |
527 | kmem_free(kernel_map, page, page_size); |
528 | } |
529 | #if IOALLOCDEBUG |
530 | OSAddAtomic(-size, &debug_iomalloc_size); |
531 | #endif |
532 | IOStatisticsAlloc(kIOStatisticsFreeAligned, size); |
533 | } |
534 | else if (alignment > 1) |
535 | { |
536 | IOFreeAligned(buffer, size); |
537 | } |
538 | else |
539 | { |
540 | IOFree(buffer, size); |
541 | } |
542 | } |
543 | if (range && (kIOMemoryAsReference & flags)) |
544 | IODelete(range, IOAddressRange, 1); |
545 | } |
546 | |
547 | /* |
548 | * getCapacity: |
549 | * |
550 | * Get the buffer capacity |
551 | */ |
552 | vm_size_t IOBufferMemoryDescriptor::getCapacity() const |
553 | { |
554 | return _capacity; |
555 | } |
556 | |
557 | /* |
558 | * setLength: |
559 | * |
560 | * Change the buffer length of the memory descriptor. When a new buffer |
561 | * is created, the initial length of the buffer is set to be the same as |
562 | * the capacity. The length can be adjusted via setLength for a shorter |
563 | * transfer (there is no need to create more buffer descriptors when you |
564 | * can reuse an existing one, even for different transfer sizes). Note |
565 | * that the specified length must not exceed the capacity of the buffer. |
566 | */ |
567 | void IOBufferMemoryDescriptor::setLength(vm_size_t length) |
568 | { |
569 | assert(length <= _capacity); |
570 | if (length > _capacity) return; |
571 | |
572 | _length = length; |
573 | _ranges.v64->length = length; |
574 | } |
575 | |
576 | /* |
577 | * setDirection: |
578 | * |
579 | * Change the direction of the transfer. This method allows one to redirect |
580 | * the descriptor's transfer direction. This eliminates the need to destroy |
581 | * and create new buffers when different transfer directions are needed. |
582 | */ |
583 | void IOBufferMemoryDescriptor::setDirection(IODirection direction) |
584 | { |
585 | _flags = (_flags & ~kIOMemoryDirectionMask) | direction; |
586 | #ifndef __LP64__ |
587 | _direction = (IODirection) (_flags & kIOMemoryDirectionMask); |
588 | #endif /* !__LP64__ */ |
589 | } |
590 | |
591 | /* |
592 | * appendBytes: |
593 | * |
594 | * Add some data to the end of the buffer. This method automatically |
595 | * maintains the memory descriptor buffer length. Note that appendBytes |
596 | * will not copy past the end of the memory descriptor's current capacity. |
597 | */ |
598 | bool |
599 | IOBufferMemoryDescriptor::appendBytes(const void * bytes, vm_size_t withLength) |
600 | { |
601 | vm_size_t actualBytesToCopy = min(withLength, _capacity - _length); |
602 | IOByteCount offset; |
603 | |
604 | assert(_length <= _capacity); |
605 | |
606 | offset = _length; |
607 | _length += actualBytesToCopy; |
608 | _ranges.v64->length += actualBytesToCopy; |
609 | |
610 | if (_task == kernel_task) |
611 | bcopy(/* from */ bytes, (void *)(_ranges.v64->address + offset), |
612 | actualBytesToCopy); |
613 | else |
614 | writeBytes(offset, bytes, actualBytesToCopy); |
615 | |
616 | return true; |
617 | } |
618 | |
619 | /* |
620 | * getBytesNoCopy: |
621 | * |
622 | * Return the virtual address of the beginning of the buffer |
623 | */ |
624 | void * IOBufferMemoryDescriptor::getBytesNoCopy() |
625 | { |
626 | if (kIOMemoryTypePhysical64 == (_flags & kIOMemoryTypeMask)) |
627 | return _buffer; |
628 | else |
629 | return (void *)_ranges.v64->address; |
630 | } |
631 | |
632 | |
633 | /* |
634 | * getBytesNoCopy: |
635 | * |
636 | * Return the virtual address of an offset from the beginning of the buffer |
637 | */ |
638 | void * |
639 | IOBufferMemoryDescriptor::getBytesNoCopy(vm_size_t start, vm_size_t withLength) |
640 | { |
641 | IOVirtualAddress address; |
642 | |
643 | if ((start + withLength) < start) return 0; |
644 | |
645 | if (kIOMemoryTypePhysical64 == (_flags & kIOMemoryTypeMask)) |
646 | address = (IOVirtualAddress) _buffer; |
647 | else |
648 | address = _ranges.v64->address; |
649 | |
650 | if (start < _length && (start + withLength) <= _length) |
651 | return (void *)(address + start); |
652 | return 0; |
653 | } |
654 | |
655 | #ifndef __LP64__ |
656 | void * IOBufferMemoryDescriptor::getVirtualSegment(IOByteCount offset, |
657 | IOByteCount * lengthOfSegment) |
658 | { |
659 | void * bytes = getBytesNoCopy(offset, 0); |
660 | |
661 | if (bytes && lengthOfSegment) |
662 | *lengthOfSegment = _length - offset; |
663 | |
664 | return bytes; |
665 | } |
666 | #endif /* !__LP64__ */ |
667 | |
668 | #ifdef __LP64__ |
669 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 0); |
670 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 1); |
671 | #else /* !__LP64__ */ |
672 | OSMetaClassDefineReservedUsed(IOBufferMemoryDescriptor, 0); |
673 | OSMetaClassDefineReservedUsed(IOBufferMemoryDescriptor, 1); |
674 | #endif /* !__LP64__ */ |
675 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 2); |
676 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 3); |
677 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 4); |
678 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 5); |
679 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 6); |
680 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 7); |
681 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 8); |
682 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 9); |
683 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 10); |
684 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 11); |
685 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 12); |
686 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 13); |
687 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 14); |
688 | OSMetaClassDefineReservedUnused(IOBufferMemoryDescriptor, 15); |
689 | |