|
|
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: /**
25: * IOMemoryDescriptor.m
26: * Copyright 1997-98 Apple Computer Inc. All Rights Reserved.
27: *
28: * IOMemoryDescriptor describes the client memory needed to perform an I/O
29: * request. It contains a single IOMemoryContainer that describes one or
30: * more ranges of memory. IOMemoryDescriptor is used directly for simple
31: * (non-RAID) transfers, and is the underlying object used for striped or
32: * mirrored requests. Logical and Physical memory cannot be mixed in a single
33: * IOMemoryDescriptor. Several IOMemoryDescriptors may reference a single
34: * IOMemoryContainer (by using the replicate method).
35: */
36: #import <driverkit/IOMemoryDescriptor.h>
37: #import <mach/vm_param.h>
38: #import <limits.h>
39:
40: /*
41: * Compute the start of the next physical page
42: */
43: #define next_page(x) (trunc_page(((unsigned int) x) + page_size))
44:
45: @interface IOMemoryDescriptor(Private)
46: /**
47: * Initialize an IOMemoryDescriptor object.
48: */
49: - (id) initWithIOMemoryContainer
50: : (IOMemoryContainer *) ioMemoryContainer;
51: /**
52: * Free the descriptor and it's container.
53: */
54: - (id) free;
55: /*
56: * validate is called when the state needs to be validated.
57: */
58: - (void) validate;
59: /*
60: * Retrieve the current logical range (returns a zero-length range on failure).
61: */
62: - (void) getCurrentLogicalRange;
63:
64: /*
65: * Retrieve the current physical range. This can fail if the O.S. returns
66: * an error status.
67: */
68: - (IOReturn) getCurrentPhysicalRange;
69:
70: /*
71: * Force the state to the end of the entire container (for reposition
72: * errors).
73: */
74: - (void) setPositionAtEnd;
75: @end /* IOMemoryContainer(Private) */
76:
77: @implementation IOMemoryDescriptor(Private)
78: /**
79: * Create an empty IOMemoryDescriptor object.
80: */
81: - (id) initWithIOMemoryContainer
82: : (IOMemoryContainer *) thisIOMemoryContainer
83: {
84: ioMemoryContainer = thisIOMemoryContainer;
85: state.currentOffset = 0;
86: retainCount = 1;
87: valid = FALSE; /* Resets other values */
88: [self setMaxSegmentCount : UINT_MAX];
89: return (self);
90: }
91:
92: /**
93: * Dispose of the object. This decrements the IOMemoryContainer's
94: * reference count and frees the IOMemoryContainer if this IOMemoryDescriptor
95: * is the last referencer.
96: */
97: - free
98: {
99: [ioMemoryContainer release];
100: return ([super free]);
101: }
102:
103: /**
104: * Extract the next logical range from the IOMemoryContainer.
105: * If this fails because rangeIndex exceeds the container max,
106: * a zero-length range will be returned.
107: */
108: - (void) getCurrentLogicalRange
109: {
110: if ([ioMemoryContainer logicalRange: &state.ioRange
111: index: state.rangeIndex] != IO_R_SUCCESS) {
112: state.ioRange.start = 0xDEADBEEF;
113: state.ioRange.size = 0xFFFFFFFF;
114: }
115: state.logicalOffset = 0;
116: state.physicalOffset = 0;
117: }
118:
119: /**
120: * Return the physical address that corresponds to the current logical
121: * address. The state is valid at this point. This method sets the
122: * physicalPageLength to the maximumn number of bytes that can be
123: * transferred in this page.
124: */
125: - (IOReturn) getCurrentPhysicalRange
126: {
127: IOReturn ioReturn;
128: unsigned int nextPageAddress;
129:
130: state.physicalOffset = 0; /* At page start */
131: ioReturn = IOPhysicalFromVirtual(
132: [ioMemoryContainer client],
133: state.ioRange.start + state.logicalOffset,
134: (vm_offset_t *) &state.physical.address
135: );
136: if (ioReturn != IO_R_SUCCESS) {
137: state.physical.address = 0;
138: state.physical.length = 0;
139: }
140: else {
141: /*
142: * The amount we can transfer is the number of bytes
143: * from the current start index to the next page
144: * (limited by scsiReq->maxTransfer). Mach lacks
145: * a method for determining the page size. We'll
146: * use 4096 for convenience (the only cost is extra
147: * cycles through the for loop).
148: */
149: nextPageAddress = next_page(state.physical.address);
150: state.physical.length =
151: nextPageAddress - ((unsigned int) state.physical.address);
152: }
153: return (ioReturn);
154: }
155:
156: /**
157: * Validate the state so that all state values agree with
158: * the currentOffset.
159: */
160: - (void) validate
161: {
162: unsigned int totalByteCount = [ioMemoryContainer totalByteCount];
163: unsigned int totalRangeCount = [ioMemoryContainer rangeCount];
164:
165: if (state.currentOffset >= totalByteCount) {
166: [self setPositionAtEnd];
167: }
168: else {
169: unsigned int offsetAtRangeStart = 0;
170: unsigned int offsetAtRangeEnd;
171: for (state.rangeIndex = 0;
172: state.rangeIndex < totalRangeCount;
173: state.rangeIndex++) {
174:
175: /* Check for an invalid range or other problems */
176: [self getCurrentLogicalRange];
177: if (0xDEADBEEF == state.ioRange.start
178: && 0xFFFFFFFF == state.ioRange.size) {
179: IOPanic("IOMemoryDescriptor: "
180: "validate fell of the end of the world\n");
181: }
182: offsetAtRangeEnd = offsetAtRangeStart + state.ioRange.size;
183: if (offsetAtRangeEnd > state.currentOffset) {
184: state.logicalOffset =
185: state.currentOffset - offsetAtRangeStart;
186: break; /* Normal exit */
187: }
188: offsetAtRangeStart = offsetAtRangeEnd;
189: }
190: if (state.rangeIndex >= totalRangeCount) {
191: [self setPositionAtEnd]; /* Bug: can't happen */
192: }
193: }
194: state.physicalOffset = 0; /* Invalidate physical */
195: valid = TRUE;
196: }
197:
198: /*
199: * Force the state to the end of the entire container (for reposition
200: * errors).
201: */
202: - (void) setPositionAtEnd
203: {
204: state.rangeIndex = [ioMemoryContainer rangeCount] - 1;
205: [self getCurrentLogicalRange];
206: state.logicalOffset = state.ioRange.size;
207: }
208:
209: @end /* IOMemoryDescriptor(Private) */
210:
211: @implementation IOMemoryDescriptor
212:
213: /**
214: * Initialize an IOMemoryDescriptor object for a logical scatter-gather list.
215: * The scatter-gather list is provided in DriverKit IORange format. If byReference
216: * is TRUE, the associated IOMemoryContainer will hold a reference to the range
217: * vector (which must remain addressable during the lifetime of the object). If
218: * FALSE, the range vector will be copied into the IOMemoryContainer object.
219: */
220: - (id) initWithIORange
221: : (const IORange *) ioRange
222: count : (unsigned int) count
223: byReference : (BOOL) byReference
224: {
225: IOMemoryContainer *thisIOMemoryContainer =
226: [[IOMemoryContainer alloc] initWithIORange
227: : ioRange
228: count : count
229: byReference : byReference
230: ];
231: [self initWithIOMemoryContainer : thisIOMemoryContainer];
232: return (self);
233:
234: }
235:
236: /**
237: * Initialize an IOMemoryDescriptor object for a single logical range.
238: */
239: - (id) initWithAddress
240: : (void *) address
241: length : (unsigned int) length
242: {
243: IOMemoryContainer *thisIOMemoryContainer =
244: [[IOMemoryContainer alloc] initWithAddress
245: : address
246: length : length
247: ];
248: [self initWithIOMemoryContainer : thisIOMemoryContainer];
249: return (self);
250: }
251:
252:
253: - (id) initWithIOV
254: : (const struct iovec *) iov
255: count : (unsigned int) count
256: {
257: IOMemoryContainer *thisIOMemoryContainer =
258: [[IOMemoryContainer alloc] initWithIOV
259: : iov
260: count : count
261: ];
262: [self initWithIOMemoryContainer : thisIOMemoryContainer];
263: return (self);
264: }
265:
266: /**
267: * Manage the retain/release reference count. See NSObject for details.
268: */
269: - (unsigned int) retainCount
270: {
271: return (retainCount);
272: }
273:
274: - (id) retain
275: {
276: ++retainCount;
277: return (self);
278: }
279:
280: - (oneway void) release
281: {
282: if (--retainCount == 0) {
283: [self free];
284: }
285: }
286:
287:
288: /**
289: * Return a copy of this IOMemoryDescriptor and its IOMemoryContainer.
290: * The IOMemoryContainer's reference count will be incremented.
291: * The current position is not duplicated: the clone will be reset
292: * to position zero.
293: */
294: - (id) replicate
295: {
296: IOMemoryDescriptor *result;
297:
298: [ioMemoryContainer retain];
299: result = [[self copy] initWithIOMemoryContainer
300: : ioMemoryContainer
301: ];
302: if (result) {
303: [result setMaxSegmentCount : maxSegmentCount];
304: [result setClient : [self client]];
305: }
306: return (result);
307: }
308:
309: /**
310: * Accessor methods
311: */
312: - (unsigned int) currentOffset
313: {
314: return (state.currentOffset);
315: }
316:
317: - (unsigned int) totalByteCount
318: {
319: return ([ioMemoryContainer totalByteCount]);
320: }
321:
322: - (unsigned int) maxSegmentCount
323: {
324: return (maxSegmentCount);
325: }
326: /*
327: * Retrieve the ioMemoryContainer
328: */
329: - (id) ioMemoryContainer
330: {
331: return (ioMemoryContainer);
332: }
333:
334:
335:
336: - (void) setMaxSegmentCount
337: : (unsigned int) newMaxSegmentCount
338: {
339: maxSegmentCount = (newMaxSegmentCount == 0)
340: ? [self totalByteCount]
341: : newMaxSegmentCount;
342: }
343:
344: - (vm_task_t) client
345: {
346: return ([ioMemoryContainer client]);
347: }
348:
349: - (void) setClient
350: : (vm_task_t) client
351: {
352: [ioMemoryContainer setClient : client];
353: }
354:
355: - (void) setIOMemoryContainer
356: : (id) newIOMemoryContainer
357: {
358: if (ioMemoryContainer != newIOMemoryContainer) {
359: [ioMemoryContainer release];
360: [newIOMemoryContainer retain];
361: ioMemoryContainer = newIOMemoryContainer;
362: }
363: state.currentOffset = 0;
364: valid = FALSE; /* Resets other values */
365: }
366:
367: /**
368: * This retrieves all positioning information -- it is intended for
369: * processing SCSI Save Data Pointers messages. Callers should treat
370: * IOMemoryDescriptorState as an opaque object.
371: */
372: - (void) state
373: : (IOMemoryDescriptorState *) statePtr
374: {
375: /*
376: * If we're called without a valid state, setState will
377: * fail (as the new state will be invalid). Note that the
378: * state is invalid when the IOMemoryDescriptor is first
379: * created.
380: */
381: if (valid == FALSE) {
382: [self validate];
383: }
384: *statePtr = state;
385: }
386:
387:
388: /**
389: * Reposition the IOMemoryDescriptor's current access point. (The TECO "dot").
390: * setState should be be called with the results of a previous state
391: * method. It is very fast. The caller must not modify the state.
392: */
393: - (void) setState
394: : (const IOMemoryDescriptorState *) statePtr
395: {
396: state = *statePtr;
397: valid = TRUE;
398: }
399:
400: /**
401: * Set the current access point to the specified byte index. This is an
402: * absolute position within the IOMemoryDescriptor. This will be slow
403: * for complex memory descriptors. setPosition does not check the parameter
404: * for validity -- this is done by the nextPhysicalRange method.
405: */
406: - (void) setPosition
407: : (unsigned int) newPosition
408: {
409: if (state.currentOffset != newPosition) {
410: state.currentOffset = newPosition;
411: valid = FALSE;
412: }
413: }
414:
415: /**
416: * Set the current access point to the relative position with respect
417: * to the current position. This is equivalent to writing:
418: * [ioMemoryDescriptor setPosition
419: * : [ioMemoryDescriptor currentOffset] + offset];
420: * This will be slow for complex memory descriptors. setOffset does not check
421: * the parameter for validity -- this is done by the nextPhysicalRange method.
422: */
423: - (void) setOffset
424: : (signed int) offset
425: {
426: state.currentOffset += offset;
427: valid = FALSE;
428: }
429:
430:
431: /**
432: * Return one or more logical ranges. Return zero if the transfer is outside
433: * of the defined range (I.e., if all data has been transferred).
434: * @param maxRanges The maximum number of ranges to retrieve.
435: * @param maxByteCount The maximum number of bytes to retrieve
436: * in the entire sequence. To use the remaining
437: * transfer count, specify UINT_MAX (from limits.h).
438: * @param newPosition The new value of currentOffset (may be NULL)
439: * @param actualRanges The actual number of ranges retrieved
440: * (NULL if not needed)
441: * @param logicalRanges A vector of logical range elements.
442: * Return the total number of bytes in all ranges. Return zero if the current
443: * offset is beyond the end of the range.
444: */
445: - (unsigned int) getLogicalRanges
446: : (unsigned int) maxRanges
447: maxByteCount : (unsigned int) maxByteCount
448: newPosition : (unsigned int *) newPosition
449: actualRanges : (unsigned int *) actualRanges
450: logicalRanges : (IORange *) logicalRanges
451: {
452: unsigned int byteCount;
453: unsigned int transferCount = 0;
454: unsigned int rangeCount;
455: unsigned int totalByteCount = [ioMemoryContainer totalByteCount];
456:
457: if (valid == FALSE) {
458: [self validate];
459: }
460: for (rangeCount = 0; rangeCount < maxRanges; rangeCount++) {
461: byteCount = totalByteCount - state.currentOffset;
462: if (state.logicalOffset >= state.ioRange.size) {
463: ++state.rangeIndex;
464: [self getCurrentLogicalRange];
465: }
466: if (byteCount > (state.ioRange.size - state.logicalOffset)) {
467: byteCount = state.ioRange.size - state.logicalOffset;
468: }
469: if (byteCount > maxSegmentCount) {
470: byteCount = maxSegmentCount;
471: }
472: if (byteCount > maxByteCount) {
473: byteCount = maxByteCount;
474: }
475: if (byteCount == 0) {
476: break; /* Fell off the end */
477: }
478: logicalRanges->size = byteCount;
479: logicalRanges->start = state.ioRange.start
480: + state.logicalOffset;
481: ++logicalRanges;
482: state.logicalOffset += byteCount;
483: transferCount += byteCount;
484: state.currentOffset += transferCount;
485: }
486: if (actualRanges != NULL) {
487: *actualRanges = rangeCount;
488: }
489: if (newPosition != NULL) {
490: *newPosition = state.currentOffset;
491: }
492: state.physicalOffset = 0; /* Invalid physical range */
493: return (transferCount);
494: }
495:
496: /**
497: * Return one or more physical ranges. Return zero if the transfer is outside
498: * of the defined range (I.e., if all data has been transferred).
499: * @param maxRanges The maximum number of ranges to retrieve.
500: * @param maxByteCount The maximum number of bytes to retrieve
501: * in the entire sequence. To use the remaining
502: * transfer count, use UINT_MAX (from limits.h).
503: * @param newPosition The new value of currentOffset (may be NULL)
504: * @param actualRanges The actual number of ranges retrieved
505: * (NULL if not needed)
506: * @param physicalRanges A vector of physical range elements.
507: * Return the total number of bytes in all ranges. Return zero if the current
508: * offset is beyond the end of the range.
509: */
510: - (unsigned int) getPhysicalRanges
511: : (unsigned int) maxRanges
512: maxByteCount : (unsigned int) maxByteCount
513: newPosition : (unsigned int *) newPosition
514: actualRanges : (unsigned int *) actualRanges
515: physicalRanges : (PhysicalRange *) physicalRanges
516: {
517: unsigned int byteCount;
518: unsigned int transferCount = 0;
519: unsigned int rangeCount;
520: unsigned int totalByteCount = [ioMemoryContainer totalByteCount];
521:
522: if (valid == FALSE) {
523: [self validate];
524: }
525: for (rangeCount = 0; rangeCount < maxRanges; rangeCount++) {
526: byteCount = totalByteCount - state.currentOffset;
527: if (state.logicalOffset >= state.ioRange.size) {
528: ++state.rangeIndex;
529: [self getCurrentLogicalRange];
530: }
531: if (byteCount > (state.ioRange.size - state.logicalOffset)) {
532: byteCount = state.ioRange.size - state.logicalOffset;
533: }
534: if ((byteCount + transferCount) > maxSegmentCount) {
535: byteCount = maxSegmentCount - transferCount;
536: }
537: if ((byteCount + transferCount) > maxByteCount) {
538: byteCount = maxByteCount - transferCount;
539: }
540: if (byteCount == 0) {
541: break; /* Fell off the end */
542: }
543: if (state.physicalOffset == 0
544: || state.physicalOffset >= state.physical.length) {
545: if ([self getCurrentPhysicalRange] != IO_R_SUCCESS) {
546: break;
547: }
548: }
549: if (byteCount > (state.physical.length - state.physicalOffset)) {
550: byteCount = state.physical.length - state.physicalOffset;
551: }
552: physicalRanges->length = byteCount;
553: physicalRanges->address = (void *)
554: (((unsigned int) state.physical.address)
555: + state.physicalOffset);
556: ++physicalRanges;
557: transferCount += byteCount;
558: state.physicalOffset += byteCount;
559: state.logicalOffset += byteCount;
560: state.currentOffset += byteCount;
561: }
562: if (actualRanges != NULL) {
563: *actualRanges = rangeCount;
564: }
565: if (newPosition != NULL) {
566: *newPosition = state.currentOffset;
567: }
568: return (transferCount);
569: }
570:
571: /**
572: * Copy bytes from the caller's address space to the IOMemoryContainer
573: * client address space. This is an inefficient routine that should only
574: * be used for "corner cases" such as handling unaligned transfers.
575: * The copy begins at the current logical address. The current logical
576: * position will be incremented.
577: * @param buffer The starting buffer address in the caller's
578: * address space.
579: * @param count The number of bytes to transfer.
580: * @return The actual number of bytes transferred.
581: */
582: - (unsigned int) writeToClient
583: : (void *) buffer
584: count : (unsigned int) count
585: {
586: unsigned int totalByteCount;
587: unsigned int thisCount;
588: PhysicalRange range;
589: vm_address_t clientVirtualAddress;
590:
591: for (totalByteCount = 0; totalByteCount < count;) {
592: thisCount = [self getPhysicalRanges
593: : 1 /* Only one range */
594: maxByteCount : count - totalByteCount
595: newPosition : NULL
596: actualRanges : NULL
597: physicalRanges : &range
598: ];
599: if (thisCount == 0) {
600: break; /* Ran off the end of the user buffer */
601: }
602: clientVirtualAddress = [self mapPhysicalAddressIntoIOTask : &range];
603: if (clientVirtualAddress == (vm_address_t) NULL) {
604: [self setOffset : -range.length];
605: break;
606: }
607: else {
608: bcopy(buffer, clientVirtualAddress, range.length);
609: ((unsigned char *) buffer) += range.length;
610: totalByteCount += range.length;
611: [self unmapVirtualAddressFromIOTask
612: : clientVirtualAddress
613: length : range.length
614: ];
615: }
616: }
617: return (totalByteCount);
618: }
619:
620: /**
621: * Copy bytes from the IOMemoryContainer client's address space to the
622: * caller's address space. This is an inefficient routine that should only
623: * be used for "corner cases" such as handling unaligned transfers.
624: * The copy begins at the current logical address. The current logical
625: * position will be incremented.
626: * @param buffer The starting buffer address in the caller's
627: * address space.
628: * @param count The number of bytes to transfer.
629: * @return The actual number of bytes transferred.
630: */
631: - (unsigned int) readFromClient
632: : (void *) buffer
633: count : (unsigned int) count
634: {
635: unsigned int totalByteCount;
636: unsigned int thisCount;
637: PhysicalRange range;
638: vm_address_t clientVirtualAddress;
639:
640: for (totalByteCount = 0; totalByteCount < count;) {
641: thisCount = [self getPhysicalRanges
642: : 1 /* Only one range */
643: maxByteCount : count - totalByteCount
644: newPosition : NULL
645: actualRanges : NULL
646: physicalRanges : &range
647: ];
648: if (thisCount == 0) {
649: break; /* Ran off the end of the user buffer */
650: }
651: clientVirtualAddress = [self mapPhysicalAddressIntoIOTask : &range];
652: if (clientVirtualAddress == (vm_address_t) NULL) {
653: [self setOffset : -range.length];
654: break;
655: }
656: else {
657: bcopy(clientVirtualAddress, buffer, range.length);
658: ((unsigned char *) buffer) += range.length;
659: totalByteCount += range.length;
660: [self unmapVirtualAddressFromIOTask
661: : clientVirtualAddress
662: length : range.length
663: ];
664: }
665: }
666: return (totalByteCount);
667: }
668:
669: /**
670: * mapPhysicalAddressIntoIOTask is used to map a potentially
671: * unaligned physical address and range into our virtual address
672: * space. It is a direct wrapper for IOMapPhysicalIntoIOTask
673: * that handles unaligned physical addresses.
674: */
675: - (vm_address_t) mapPhysicalAddressIntoIOTask
676: : (const PhysicalRange *) range
677: {
678: vm_address_t clientVirtualAddress;
679: unsigned int offset;
680: IOReturn ioReturn;
681:
682: offset = ((unsigned int) range->address) & page_mask;
683: ioReturn = IOMapPhysicalIntoIOTask(
684: range->address - offset,
685: range->length + offset,
686: &clientVirtualAddress
687: );
688: if (ioReturn != IO_R_SUCCESS) {
689: clientVirtualAddress = (vm_address_t) NULL;
690: }
691: else {
692: /*
693: * Ensure that clientVirtualAddress is on a page
694: * boundary and add in the actual offset.
695: */
696: clientVirtualAddress = (vm_address_t)
697: (((unsigned int) clientVirtualAddress) & ~page_mask)
698: + offset;
699: }
700: return (clientVirtualAddress);
701: }
702:
703: /**
704: * Un-map a range that was mapped by mapPhysicalAddressIntoIOTask.
705: * rangeLength must be identical to the range.length parameter passed
706: * to mapPhysicalAddressIntoIOTask.
707: */
708: - (void) unmapVirtualAddressFromIOTask
709: : (vm_address_t) clientVirtualAddress
710: length : (unsigned int) rangeLength
711: {
712: unsigned int offset;
713: vm_address_t pageBaseAddress;
714:
715: offset = ((unsigned int) clientVirtualAddress) & page_mask;
716: pageBaseAddress = (vm_address_t)
717: ((unsigned int) clientVirtualAddress) & ~page_mask;
718: (void) IOUnmapPhysicalFromIOTask(
719: pageBaseAddress, rangeLength + offset);
720: }
721:
722: /**
723: * Make the memory described by this IOMemoryDescriptor resident.
724: * This is called by the virtual memory manager and/or file system before
725: * starting an I/O request. Residency is an all-or-nothing process. The
726: * IOMemoryDescriptor maintains a reference count: the first caller makes the
727: * memory resident; the others just increment the count. This method returns
728: * an error status if any range cannot be made resident and all memory will
729: * be made pageable. This method may only be called by kernel servers.
730: */
731: - (IOReturn) wireMemory
732: : (BOOL) forReading
733: {
734: return ([ioMemoryContainer wireMemory : forReading]);
735: }
736:
737: /**
738: * Make the memory described by this underlying IOMemoryDescriptor pageable.
739: * This is called by the virtual memory manager and/or file system after
740: * completing an I/O request. The IOMemoryDescriptor maintains a reference
741: * count: the last caller frees the memory the others just decrement the count.
742: * This method returns an error status if any range could not be freed,
743: * but always tries to free all ranges. Return IO_R_VM_FAILURE if any range
744: * can't be unwired (but there is no indication as to which range).
745: */
746: - (IOReturn) unwireMemory
747: {
748: return ([ioMemoryContainer unwireMemory]);
749: }
750:
751: /**
752: * Normalize cache coherency (if needed by this particular hardware
753: * architecture) before starting a DMA operation. This normalizes all
754: * memory described by this IOMemoryContainer. This is used as follows:
755: * mem = [IOMemoryDescriptor allocLogicalRange
756: * : address
757: * length : length];
758: * [mem makeResident];
759: * [mem checkpoint : ioCheckpointInput];
760: * ... Extract physical ranges and do DMA I/O ...
761: * [mem checkpoint : ioCheckpointComplete];
762: * [mem makePageable];
763: * [mem free];
764: * A checkpoint call may specify any combination of ioCheckpointInput,
765: * ioCheckpointOutput, or ioCheckpointNoDirection. After DMA completes,
766: * drivers must call checkpoint with ioCheckpointComplete as the only
767: * parameter. The actual operation of checkpoint is processor-specific.
768: */
769: - (IOReturn) checkpoint
770: : (IOMemoryCheckpointOption) option
771: {
772: /*
773: * *** Hmm: if we have multiple users, the checkpoint probably should be
774: * *** inside the descriptor, not the container
775: */
776: return ([ioMemoryContainer checkpoint : option]);
777: }
778:
779: @end /* IOMemoryDescriptor : IOObject */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.