]>
Commit | Line | Data |
---|---|---|
1c79356b A |
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) 1997 Apple Computer, Inc. | |
24 | * | |
25 | * | |
26 | * HISTORY | |
27 | * | |
28 | * sdouglas 22 Oct 97 - first checked in. | |
29 | * sdouglas 21 Jul 98 - start IOKit | |
30 | * sdouglas 14 Dec 98 - start cpp. | |
31 | */ | |
32 | ||
33 | ||
34 | ||
35 | #include <IOKit/IOLib.h> | |
36 | #include <libkern/c++/OSContainers.h> | |
37 | ||
38 | extern "C" { | |
39 | #include <pexpert/pexpert.h> | |
40 | }; | |
41 | ||
42 | #include "IONDRV.h" | |
43 | #include "IOPEFLoader.h" | |
44 | ||
45 | #define LOG if(1) kprintf | |
46 | ||
47 | #define USE_TREE_NDRVS 1 | |
48 | #define USE_ROM_NDRVS 1 | |
49 | ||
50 | ||
51 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
52 | ||
53 | #define super OSObject | |
54 | ||
55 | OSDefineMetaClassAndStructors(IONDRV, OSObject) | |
56 | ||
57 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
58 | ||
59 | IONDRV * IONDRV::instantiate( IORegistryEntry * regEntry, | |
60 | IOLogicalAddress container, | |
61 | IOByteCount containerSize, | |
62 | IONDRVUndefinedSymbolHandler undefHandler, | |
63 | void * self ) | |
64 | { | |
65 | OSStatus err = 1; | |
66 | IONDRV * inst; | |
67 | ||
68 | inst = new IONDRV; | |
69 | ||
70 | if( inst) do { | |
71 | if( false == inst->init()) | |
72 | continue; | |
73 | ||
74 | err = PCodeOpen( (void *)container, containerSize, &inst->pcInst ); | |
75 | if( err) | |
76 | continue; | |
77 | ||
78 | err = PCodeInstantiate( inst->pcInst, undefHandler, self ); | |
79 | if( err) | |
80 | continue; | |
81 | ||
82 | inst->getSymbol( "DoDriverIO", | |
83 | (IOLogicalAddress *) &inst->fDoDriverIO ); | |
84 | if( kIOReturnSuccess == inst->getSymbol( "TheDriverDescription", | |
85 | (IOLogicalAddress *) &inst->theDriverDesc )) { | |
86 | ||
87 | char * name; | |
88 | int plen; | |
89 | ||
90 | name = (char *) inst->theDriverDesc->driverOSRuntimeInfo.driverName; | |
91 | plen = name[ 0 ]; | |
92 | strncpy( name, name + 1, plen); | |
93 | name[ plen ] = 0; | |
94 | ||
95 | kprintf("ndrv version %08x\n", | |
96 | inst->theDriverDesc-> driverType.version); | |
97 | } | |
98 | ||
99 | } while( false); | |
100 | ||
101 | if( inst && err) { | |
102 | inst->release(); | |
103 | inst = 0; | |
104 | } | |
105 | ||
106 | return( inst ); | |
107 | } | |
108 | ||
109 | void IONDRV::free( void ) | |
110 | { | |
111 | if( pcInst) | |
112 | PCodeClose( pcInst ); | |
113 | super::free(); | |
114 | } | |
115 | ||
116 | IOReturn IONDRV::getSymbol( const char * symbolName, | |
117 | IOLogicalAddress * address ) | |
118 | { | |
119 | OSStatus err; | |
120 | ||
121 | err = PCodeFindExport( pcInst, symbolName, | |
122 | (LogicalAddress *)address, NULL ); | |
123 | if( err) | |
124 | *address = 0; | |
125 | ||
126 | return( err); | |
127 | } | |
128 | ||
129 | #if 0 | |
130 | if( (err = NDRVGetShimClass( ioDevice, instance, 0, classNames )) | |
131 | ) continue; | |
132 | err = [propTable createProperty:"AAPL,dk_Driver Name" flags:0 | |
133 | value:classNames length:strlen( classNames) ]; | |
134 | err = [propTable createProperty:"AAPL,dk_Server Name" flags:0 | |
135 | value:classNames length:strlen( classNames) ]; | |
136 | ||
137 | OSStatus NDRVGetShimClass( id ioDevice, NDRVInstance instance, UInt32 serviceIndex, char * className ) | |
138 | { | |
139 | NDRVInstanceVars * ndrvInst = (NDRVInstanceVars *) instance; | |
140 | OSStatus err; | |
141 | static const char * driverDescProperty = "TheDriverDescription"; | |
142 | static const char * frameBufferShim = "IONDRVFramebuffer"; | |
143 | DriverDescription * desc; | |
144 | UInt32 serviceType; | |
145 | ||
146 | className[ 0 ] = 0; | |
147 | do { | |
148 | err = PCodeFindExport( ndrvInst->pcInst, driverDescProperty, (IOLogicalAddress *)&desc, NULL ); | |
149 | if( err) continue; | |
150 | ||
151 | if( desc->driverDescSignature != kTheDescriptionSignature) { | |
152 | err = -1; | |
153 | continue; | |
154 | } | |
155 | if( serviceIndex >= desc->driverServices.nServices) { | |
156 | err = -1; | |
157 | continue; | |
158 | } | |
159 | ||
160 | serviceType = desc->driverServices.service[ serviceIndex ].serviceType; | |
161 | switch( desc->driverServices.service[ serviceIndex ].serviceCategory) { | |
162 | ||
163 | case kServiceCategoryNdrvDriver: | |
164 | if( serviceType == kNdrvTypeIsVideo) { | |
165 | strcpy( className, frameBufferShim); | |
166 | break; | |
167 | } | |
168 | default: | |
169 | err = -1; | |
170 | } | |
171 | } while( false); | |
172 | ||
173 | return( err); | |
174 | } | |
175 | #endif | |
176 | ||
177 | ||
178 | ||
179 | IOReturn IONDRV::doDriverIO( UInt32 commandID, void * contents, | |
180 | UInt32 commandCode, UInt32 commandKind ) | |
181 | { | |
182 | OSStatus err; | |
183 | ||
184 | if( 0 == fDoDriverIO) | |
185 | return( kIOReturnUnsupported ); | |
186 | ||
187 | err = CallTVector( /*AddressSpaceID*/ 0, (void *)commandID, contents, | |
188 | (void *)commandCode, (void *)commandKind, /*p6*/ 0, | |
189 | fDoDriverIO ); | |
190 | ||
191 | #if 0 | |
192 | if( err) { | |
193 | UInt32 i; | |
194 | static const char * commands[] = | |
195 | { "kOpenCommand", "kCloseCommand", | |
196 | "kReadCommand", "kWriteCommand", | |
197 | "kControlCommand", "kStatusCommand", "kKillIOCommand", | |
198 | "kInitializeCommand", "kFinalizeCommand", | |
199 | "kReplaceCommand", "kSupersededCommand" }; | |
200 | ||
201 | LOG("Driver failed (%d) on %s : ", err, commands[ commandCode ] ); | |
202 | ||
203 | switch( commandCode) { | |
204 | case kControlCommand: | |
205 | case kStatusCommand: | |
206 | LOG("%d : ", ((UInt16 *)contents)[ 0x1a / 2 ]); | |
207 | contents = ((void **)contents)[ 0x1c / 4 ]; | |
208 | for( i = 0; i<5; i++ ) | |
209 | LOG("%08x, ", ((UInt32 *)contents)[i] ); | |
210 | break; | |
211 | } | |
212 | LOG("\n"); | |
213 | } | |
214 | #endif | |
215 | ||
216 | return( err); | |
217 | } | |
218 | ||
219 | ||
220 | IONDRV * IONDRV::fromRegistryEntry( IORegistryEntry * regEntry, | |
221 | IONDRVUndefinedSymbolHandler handler, | |
222 | void * self ) | |
223 | { | |
224 | IOLogicalAddress pef = 0; | |
225 | IOByteCount propSize = 0; | |
226 | OSData * prop; | |
227 | IONDRV * inst; | |
228 | ||
229 | inst = (IONDRV *) regEntry->getProperty("AAPL,ndrvInst"); | |
230 | if( inst) { | |
231 | inst->retain(); | |
232 | return( inst ); | |
233 | } | |
234 | ||
235 | prop = (OSData *) regEntry->getProperty( "driver,AAPL,MacOS,PowerPC" ); | |
236 | if( USE_TREE_NDRVS && prop) { | |
237 | pef = (IOLogicalAddress) prop->getBytesNoCopy(); | |
238 | propSize = prop->getLength(); | |
239 | } | |
240 | ||
241 | // God awful hack: | |
242 | // Some onboard devices don't have the ndrv in the tree. The booter | |
243 | // can load & match PEF's but only from disk, not network boots. | |
244 | ||
245 | #if USE_ROM_NDRVS | |
246 | if( !pef && (0 == strcmp( regEntry->getName(), "ATY,mach64_3DU")) ) { | |
247 | ||
248 | int * patch; | |
249 | ||
250 | patch = (int *) 0xffe88140; | |
251 | propSize = 0x10a80; | |
252 | ||
253 | // Check ati PEF exists there | |
254 | if( patch[ 0x1f0 / 4 ] == 'ATIU') { | |
255 | ||
256 | pef = (IOLogicalAddress) IOMalloc( propSize ); | |
257 | bcopy( (void *) patch, (void *) pef, propSize ); | |
258 | } | |
259 | } | |
260 | ||
261 | if( !pef && (0 == strcmp( regEntry->getName(), "ATY,mach64_3DUPro")) ) { | |
262 | ||
263 | int * patch; | |
264 | ||
265 | patch = (int *) 0xffe99510; | |
266 | propSize = 0x12008; | |
267 | // Check ati PEF exists there | |
268 | if( patch[ 0x1fc / 4 ] != 'ATIU') { | |
269 | ||
270 | // silk version | |
271 | patch = (int *) 0xffe99550; | |
272 | propSize = 0x12058; | |
273 | if( patch[ 0x1fc / 4 ] != 'ATIU') | |
274 | propSize = 0; | |
275 | } | |
276 | ||
277 | if( propSize) { | |
278 | pef = (IOLogicalAddress) IOMalloc( propSize ); | |
279 | bcopy( (void *) patch, (void *) pef, propSize ); | |
280 | } | |
281 | } | |
282 | ||
283 | if( !pef && (0 == strcmp( regEntry->getName(), "control")) ) { | |
284 | ||
285 | #define ins(i,d,a,simm) ((i<<26)+(d<<21)+(a<<16)+simm) | |
286 | int * patch; | |
287 | ||
288 | patch = (int *) 0xffe6bd50; | |
289 | propSize = 0xac10; | |
290 | ||
291 | // Check control PEF exists there | |
292 | if( patch[ 0x41ac / 4 ] == ins( 32, 3, 0, 0x544)) { // lwz r3,0x544(0) | |
293 | ||
294 | pef = (IOLogicalAddress) IOMalloc( propSize ); | |
295 | bcopy( (void *) patch, (void *) pef, propSize ); | |
296 | patch = (int *) pef; | |
297 | // patch out low mem accesses | |
298 | patch[ 0x8680 / 4 ] = ins( 14, 12, 0, 0); // addi r12,0,0x0 | |
299 | patch[ 0x41ac / 4 ] = ins( 14, 3, 0, 0x544); // addi r3,0,0x544; | |
300 | patch[ 0x8fa0 / 4 ] = ins( 14, 3, 0, 0x648); // addi r3,0,0x648; | |
301 | } | |
302 | } | |
303 | #endif | |
304 | ||
305 | if( pef) { | |
306 | kprintf( "pef = %08x, %08x\n", pef, propSize ); | |
307 | inst = IONDRV::instantiate( regEntry, pef, propSize, handler, self ); | |
308 | if( inst ) | |
309 | regEntry->setProperty( "AAPL,ndrvInst", inst); | |
310 | ||
311 | } else | |
312 | inst = 0; | |
313 | ||
314 | return( inst ); | |
315 | } | |
316 | ||
317 | const char * IONDRV::driverName( void ) | |
318 | { | |
319 | return( (const char *) theDriverDesc->driverOSRuntimeInfo.driverName); | |
320 | } | |
321 | ||
322 |