Root/
Source at commit 1084 created 13 years 1 month ago. By meklort, BiosDisk Read() function working. Write() complete but untested | |
---|---|
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 | #if __ppc__␊ |
24 | ␊ |
25 | /*!␊ |
26 | @header IOFireWireSBP2LSIWorkaroundDescriptor␊ |
27 | Contains the class definition for IOFireWireSBP2LSIWorkaroundDescriptor.␊ |
28 | */␊ |
29 | ␊ |
30 | #ifndef _IOKIT_IOFIREWIRESBP2LSIWORKAROUNDDESCRIPTOR_H␊ |
31 | #define _IOKIT_IOFIREWIRESBP2LSIWORKAROUNDDESCRIPTOR_H␊ |
32 | ␊ |
33 | #include <IOKit/IOMemoryDescriptor.h>␊ |
34 | ␊ |
35 | class IOFireWireSBP2LSIRange;␊ |
36 | ␊ |
37 | /*!␊ |
38 | @class IOFireWireSBP2LSIWorkaroundDescriptor␊ |
39 | @abstract This is a subclass of IOGeneralMemoryDescriptor. It is designed to work around␊ |
40 | a hardware problem in a common SBP2 target. It takes a memory descriptor as␊ |
41 | ␉an argument. It retains this descriptor and returns a new one with resegmented␊ |
42 | ␉physical segments and potentially some "unfixable" segments double buffered.␊ |
43 | ␊ |
44 | If the transfer will cause data to be sent from the Mac, syncBuffersForOutput␊ |
45 | must be called before the transfer.␊ |
46 | ␊ |
47 | If the transfer will cause data to be recieve by the Mac, syncBuffersForInput␊ |
48 | must be called after the transfer.␊ |
49 | ␊ |
50 | This class calculates the new segmentation only once when it is created.␊ |
51 | Any changes to the structure of the original memory descriptor will render␊ |
52 | this one useless. It must be released and a new IOFireWireSBP2LSIWorkaroundDescriptor␊ |
53 | can be created.␊ |
54 | ␊ |
55 | LSI Bridge Workaround Algorithm Details␊ |
56 | ␊ |
57 | Goals:␊ |
58 | 1. Avoid LSI Logic "< 16 byte" bug - prevent any data packet smaller than 16 bytes␊ |
59 | 2. Minimize double-buffering␊ |
60 | 3. Support non-multiple-of-512-byte devices, e.g. CD Audio␊ |
61 | ␊ |
62 | Solution:␊ |
63 | Write a page table such that the bridge will nor use packets smaller than 16 bytes.␊ |
64 | In other words, rearrange the memory descriptor to avoid the bug, and do it such␊ |
65 | that the SBP-2 layer will not break up a segment (du ro the 64k-1 limit) and␊ |
66 | re-introduces the problem␊ |
67 | ␊ |
68 | SBP-2 defines the kFWSBP2MaxPageClusterSize constant. We simply make sure␊ |
69 | none of our segments are larger than this size and SBP-2 will not break them␊ |
70 | up when it writes the SBP-2 page table.␊ |
71 | ␊ |
72 | Notes:␊ |
73 | - Some double buffering is unavoidable. Discontiguous pages may yield page␊ |
74 | fragments at the start or end of the buffer (or both, with non-512x buffers).␊ |
75 | solution uses less than 33 bytes of double-buffer per segment in original␊ |
76 | memory descriptor.␊ |
77 | - If driver must break up IO to meet ATA limit of 255 (250?) blocks, assume␊ |
78 | the driver does this at a higher level (before applying workaround).␊ |
79 | - It is expected that the original memory descriptor has been prepared (wired)␊ |
80 | */␊ |
81 | ␊ |
82 | class IOFireWireSBP2LSIWorkaroundDescriptor : public IOGeneralMemoryDescriptor␊ |
83 | {␊ |
84 | ␉OSDeclareDefaultStructors(IOFireWireSBP2LSIWorkaroundDescriptor)␊ |
85 | ␊ |
86 | ␉friend class IOFireWireSBP2LSIRange;␊ |
87 | ␊ |
88 | protected:␊ |
89 | ␊ |
90 | // reserved for future use␊ |
91 | struct ExpansionData { };␊ |
92 | ExpansionData *reserved; ␊ |
93 | ␊ |
94 | ␉bool␉fFixedCapacity; ␉// for both allocators␊ |
95 | ␉␊ |
96 | ␉//////////////////////////////////////␊ |
97 | ␉// for range allocator␊ |
98 | ␊ |
99 | ␉OSArray *␉␉␉␉fPermanentRanges;␊ |
100 | ␉UInt32␉␉␉␉␉fAllocatedRangesCount;␊ |
101 | ␊ |
102 | ␉virtual IOReturn rangeAllocatorInitialize( UInt32 rangeCount );␊ |
103 | ␉virtual void rangeAllocatorDeallocateAllRanges( void );␊ |
104 | ␉virtual IOFireWireSBP2LSIRange * rangeAllocatorNewRange( void );␊ |
105 | ␉virtual void rangeAllocatorFree( void );␊ |
106 | ␊ |
107 | ␉//////////////////////////////////////␊ |
108 | ␉// for buffer allocator␊ |
109 | ␉␊ |
110 | ␉OSArray *␉␉␉␉fBufferDescriptors;␊ |
111 | ␉UInt32␉␉␉␉␉fPermanentPages;␊ |
112 | ␉IOByteCount␉␉␉␉fAllocatedBytesCount;␊ |
113 | ␊ |
114 | ␉virtual IOReturn bufferAllocatorInitialize( IOByteCount requestedBufferSize );␊ |
115 | ␉virtual void bufferAllocatorDeallocateAllBuffers( void );␊ |
116 | ␉virtual void * bufferAllocatorNewBuffer( IOPhysicalAddress * address );␊ |
117 | ␉virtual void bufferAllocatorFree( void );␊ |
118 | ␊ |
119 | ␉//////////////////////////////////////␊ |
120 | ␉// for range table allocator␊ |
121 | ␉␊ |
122 | ␉IOPhysicalRange * ␉␉fRangeTable;␊ |
123 | ␉IOByteCount␉␉␉␉fRangeTableSize;␊ |
124 | ␊ |
125 | ␉virtual IOReturn rangeTableAllocatorInitialize( UInt32 requestedBufferSize );␊ |
126 | ␉virtual IOPhysicalRange * rangeTableAllocatorNewTable( UInt32 entries );␊ |
127 | ␉virtual void rangeTableAllocatorFree( void );␊ |
128 | ␊ |
129 | ␉//////////////////////////////////////␊ |
130 | ␉// for workaround␊ |
131 | ␊ |
132 | ␉IOMemoryDescriptor * ␉fOriginalDesc;␉␊ |
133 | ␉OSArray *␉␉␉␉fRanges;␉␊ |
134 | ␉IOByteCount ␉␉␉fOffset;␊ |
135 | ␉IOByteCount␉␉␉␉fLength;␊ |
136 | ␉IODirection␉␉␉␉fDirection;␊ |
137 | ␉␊ |
138 | ␉␉␉␉␉␉ ␊ |
139 | ␉virtual bool initWithCapacity␊ |
140 | ␉␉␉␉␉( UInt32 permanentRanges, IOByteCount permanentBufferSpace, bool fixedCapacity );␊ |
141 | ␊ |
142 | ␉virtual void free();␊ |
143 | ␉␊ |
144 | ␉virtual IOReturn resetToInitialCapacity( void );␊ |
145 | ␉virtual IOReturn initializeRangesArray( void );␊ |
146 | ␉virtual IOReturn recalculateSmallSegments( void );␊ |
147 | ␉virtual IOReturn splitLargeSegments( void );␊ |
148 | ␉virtual IOReturn resegmentOddLengthSegments( void );␊ |
149 | ␉virtual IOReturn initializeBuffers( void );␊ |
150 | ␊ |
151 | ␉virtual bool initWithAddress( void * address, /* not supported */␊ |
152 | IOByteCount withLength,␊ |
153 | IODirection withDirection );␊ |
154 | ␊ |
155 | virtual bool initWithAddress( vm_address_t address, /* not supported */␊ |
156 | IOByteCount withLength,␊ |
157 | IODirection withDirection,␊ |
158 | task_t withTask );␊ |
159 | ␊ |
160 | virtual bool initWithPhysicalAddress( ␊ |
161 | IOPhysicalAddress address, /* not supported */␊ |
162 | IOByteCount withLength,␊ |
163 | IODirection withDirection );␊ |
164 | ␊ |
165 | virtual bool initWithPhysicalRanges( ␊ |
166 | IOPhysicalRange * ranges, /* not supported */␊ |
167 | UInt32 withCount,␊ |
168 | IODirection withDirection,␊ |
169 | bool asReference = false );␊ |
170 | ␊ |
171 | virtual bool initWithRanges( IOVirtualRange * ranges, /* not supported */␊ |
172 | UInt32 withCount,␊ |
173 | IODirection withDirection,␊ |
174 | task_t withTask,␊ |
175 | bool asReference = false );␊ |
176 | ␊ |
177 | public:␊ |
178 | ␉␊ |
179 | ␉// static factory methods and intializers ␊ |
180 | ␉␊ |
181 | ␉//␊ |
182 | ␉// create a new instance␊ |
183 | ␉//␊ |
184 | ␉␊ |
185 | ␉␊ |
186 | /*!␊ |
187 | ␉␉@function withDescriptor␊ |
188 | ␉␉@abstract Creates a new IOFireWireSBP2LSIWorkaroundDescriptor.␊ |
189 | ␉␉@discussion␉Create a IOFireWireSBP2LSIWorkaroundDescriptor with no permanent capacity then ␊ |
190 | inits it the given descriptor. This is basicly a short cut for calling ␊ |
191 | withCapacity( 0, 0, false) and the initWithDescriptor()␊ |
192 | @param desc Original memory descriptor.␊ |
193 | @param offset Offset of data to "fix" in bytes from beginning of descriptor.␊ |
194 | @param len Length of data in bytes to "fix"␊ |
195 | @param direction IODirection of data transfer.␊ |
196 | @result Returns a new IOFireWireSBP2LSIWorkaroundDescriptor if successful.␊ |
197 | ␉*/␊ |
198 | ␊ |
199 | ␉static IOFireWireSBP2LSIWorkaroundDescriptor * withDescriptor␊ |
200 | ␉␉␉␉␉( IOMemoryDescriptor * desc, IOByteCount offset = 0, ␊ |
201 | ␉␉␉␉␉ IOByteCount len = 0, IODirection direction = kIODirectionOutIn );␊ |
202 | ␉␊ |
203 | ␉// initialize with descriptor␉␉␉␉ ␊ |
204 | ␉␊ |
205 | /*!␊ |
206 | ␉␉@function initWithDescriptor␊ |
207 | ␉␉@abstract Initialize an IOFireWireSBP2LSIWorkaroundDescriptor with the given descriptor.␊ |
208 | ␉␉@discussion␉Initialize the workaround descriptor with the given descriptor. ␊ |
209 | @param desc Original memory descriptor.␊ |
210 | @param offset Offset of data to "fix" in bytes from beginning of descriptor.␊ |
211 | @param len Length of data in bytes to "fix"␊ |
212 | @param direction IODirection of data transfer.␊ |
213 | @result Returns true if the initialization was successful.␊ |
214 | ␉*/␊ |
215 | ␊ |
216 | virtual bool initWithDescriptor( IOMemoryDescriptor * desc, IOByteCount offset = 0, ␊ |
217 | ␉␉␉␉␉␉␉␉ IOByteCount len = 0, IODirection direction = kIODirectionOutIn );␊ |
218 | ␉␊ |
219 | ␉␊ |
220 | ␉///////////////////////////////////␊ |
221 | ␉␊ |
222 | ␊ |
223 | /*!␊ |
224 | ␉␉@function withCapacity␊ |
225 | ␉␉@abstract Create a new descriptor with possibly a permanent capacity.␊ |
226 | ␉␉@discussion␉Create and IOFireWireSBP2LSIWorkaroundDescriptor with a permanent fixed capacity. ␊ |
227 | You should call initWithDescriptor afterward. permanentRanges is number of ranges to keep ␊ |
228 | permanently allocated for use by the algorithm. If fixedCapacity is false additional ranges ␊ |
229 | may be allocated and deallocated dyanmicly if needed. The algorithm may require more or less ␊ |
230 | ranges than either the original descriptor or the final fixed may decriptor contain.␊ |
231 | permanentBufferSpace is the number of bytes of permanent buffer to keep arround. If fixedCapacity ␊ |
232 | is false additional buffer space may be allocated and deallocated dynamically. permanentBufferSpace ␊ |
233 | should generally be set to 32 * maximum number of ranges. fixedCapacity is a flag indicating ␊ |
234 | whether dynamic allocations are allowed. When making decisions about the maximum amount of ␊ |
235 | buffer space to keep around, it should be noted tha the maximum number of ranges maybe different ␊ |
236 | from permanentRanges if fixedCapcity is false.␊ |
237 | @param permanentRanges Count of permanent ranges.␊ |
238 | @param permanentBufferSpace Byte count of permanent buffers.␊ |
239 | @param fixedCapacity bool indicating if dynamic allocations can be made.␊ |
240 | @result Returns true if the initialization was successful.␊ |
241 | ␉*/␊ |
242 | ␊ |
243 | ␉static IOFireWireSBP2LSIWorkaroundDescriptor * withCapacity␊ |
244 | ␉␉␉␉␉␉( UInt32 permanentRanges, IOByteCount permanentBufferSpace, bool fixedCapacity );␊ |
245 | ␊ |
246 | ␊ |
247 | ␉///////////////////////////////////␊ |
248 | ␊ |
249 | ␉//␊ |
250 | ␉// manipulate buffers for IO␊ |
251 | ␉//␊ |
252 | ␊ |
253 | /*!␊ |
254 | ␉␉@function syncBuffersForOutput␊ |
255 | ␉␉@abstract Synchronize the buffers for output.␊ |
256 | ␉␉@discussion␉Since double buffering may be invovled in the workaround. The driver needs to ␊ |
257 | indicate when these buffers should be syncronized with the original descriptor. For data ␊ |
258 | that will be output syncBuffersForOutput should be called before submiting the ORB.␊ |
259 | @result Returns kIOReturnSuccess if sync was successful.␊ |
260 | ␉*/␊ |
261 | ␉␊ |
262 | ␉virtual IOReturn syncBuffersForOutput( void ); // call before output␊ |
263 | ␊ |
264 | /*!␊ |
265 | ␉␉@function syncBuffersForInput␊ |
266 | ␉␉@abstract Synchronize the buffers for input.␊ |
267 | ␉␉@discussion␉Since double buffering may be invovled in the workaround. The driver needs to ␊ |
268 | indicate when these buffers should be syncronized with the original descriptor. For data ␊ |
269 | that will be input syncBuffersForOutput should be called after receiving completion status ␊ |
270 | for the ORB.␊ |
271 | @result Returns kIOReturnSuccess if sync was successful.␊ |
272 | ␉*/␊ |
273 | ␊ |
274 | virtual IOReturn syncBuffersForInput( void );␉// call after input␊ |
275 | ␊ |
276 | private:␊ |
277 | ␊ |
278 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 0);␊ |
279 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 1);␊ |
280 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 2);␊ |
281 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 3);␊ |
282 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 4);␊ |
283 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 5);␊ |
284 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 6);␊ |
285 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 7);␊ |
286 | OSMetaClassDeclareReservedUnused(IOFireWireSBP2LSIWorkaroundDescriptor, 8);␊ |
287 | ␊ |
288 | };␊ |
289 | ␊ |
290 | #endif␊ |
291 | ␊ |
292 | #endif␊ |
293 |