]> git.saurik.com Git - apple/xnu.git/blob - iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.cpp
1c064379ffd3d3157feec96a5e359d711ad46188
[apple/xnu.git] / iokit / Drivers / hidsystem / drvAppleADBDevices / AppleADBDisplay.cpp
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-1998 Apple Computer, Inc.
24 *
25 *
26 * HISTORY
27 *
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 23 Jul 98 - start IOKit
30 * suurballe 17 Nov 98 - ported to C++
31 */
32
33 #include <assert.h>
34 #include <IOKit/IOLib.h>
35
36 #include "AppleADBDisplay.h"
37
38
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40
41 #define super IODisplay
42 OSDefineMetaClassAndStructors( AppleADBDisplay, IODisplay )
43
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45
46 IOReturn AppleADBDisplay::findADBDisplayInfoForType( UInt16 deviceType )
47 {
48 char stringBuf[ 32 ];
49 OSNumber * off;
50 OSString * key;
51 OSData * data;
52
53 sprintf( stringBuf, "adb%dWiggle", deviceType);
54 if( (off = OSDynamicCast( OSNumber, getProperty( stringBuf ))))
55 wiggleLADAddr = off->unsigned32BitValue();
56 else
57 wiggleLADAddr = kWiggleLADAddr;
58
59 sprintf( stringBuf, "adb%dModes", deviceType);
60 key = OSDynamicCast( OSString, getProperty( stringBuf ));
61
62 if( key && (data = OSDynamicCast( OSData, getProperty( key )))) {
63 modeList = (UInt32 *) data->getBytesNoCopy();
64 numModes = data->getLength() / sizeof( UInt32);
65 }
66 if( modeList )
67 return(kIOReturnSuccess);
68 else
69 return( -49 );
70 }
71
72
73 IOReturn AppleADBDisplay::getConnectFlagsForDisplayMode(
74 IODisplayModeID mode, UInt32 * flags )
75 {
76 IOReturn err;
77 IODisplayConnect * connect;
78 IOFramebuffer * framebuffer;
79 int timingNum;
80 IOTimingInformation info;
81
82 *flags = 0;
83
84 connect = getConnection();
85 assert( connect );
86 framebuffer = connect->getFramebuffer();
87 assert( framebuffer );
88
89 err = framebuffer->getTimingInfoForDisplayMode( mode, &info );
90
91 if( kIOReturnSuccess == err) {
92 for( timingNum = 0; timingNum < numModes; timingNum++ ) {
93 if( info.appleTimingID == modeList[ timingNum ] ) {
94 *flags = timingNum
95 ? ( kDisplayModeValidFlag | kDisplayModeSafeFlag )
96 : ( kDisplayModeValidFlag | kDisplayModeSafeFlag
97 | kDisplayModeDefaultFlag );
98 break;
99 }
100 }
101 }
102
103 return( err );
104 }
105
106 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
107
108 IOReturn AppleADBDisplay::doConnect( void )
109 {
110 IOReturn err;
111 UInt16 value;
112 UInt32 retries = 9;
113 IOByteCount length;
114
115 while ( retries-- ) {
116
117 value = 0x6000 | (adbDevice->address() << 8);
118 length = sizeof( value);
119 err = adbDevice->writeRegister( 3, (UInt8 *) &value, &length );
120 if( err)
121 continue;
122
123 /* IOSleep(10); */
124 /* IODelay(1000); */
125 length = sizeof( value);
126 err = adbDevice->readRegister( 3, (UInt8 *) &value, &length );
127 if( err)
128 continue;
129
130 if( (value & 0xf000) == 0x6000 )
131 break;
132 else
133 err = kIOReturnNotAttached;
134 }
135
136 if( err)
137 kprintf("%s: %d\n", __FUNCTION__, err);
138
139 return(err);
140 }
141
142 static void autoPollHandler( IOService * self, UInt8 adbCommand,
143 IOByteCount length, UInt8 * data )
144 {
145 ((AppleADBDisplay *)self)->packet( adbCommand, length, data );
146 }
147
148 void AppleADBDisplay::packet( UInt8 adbCommand,
149 IOByteCount length, UInt8 * data )
150 {
151 if( length && (*data == waitAckValue) )
152 waitAckValue = 0;
153 }
154
155 IOReturn AppleADBDisplay::writeWithAcknowledge( UInt8 regNum,
156 UInt16 data, UInt8 ackValue )
157 {
158 IOReturn err;
159 enum { kTimeoutMS = 400 };
160 UInt32 timeout;
161 IOByteCount length;
162
163 waitAckValue = ackValue;
164
165 length = sizeof(data);
166 err = adbDevice->writeRegister( regNum, (UInt8 *) &data, &length );
167
168 if( !err) {
169 timeout = kTimeoutMS / 50;
170 while( waitAckValue && timeout-- )
171 IOSleep( 50 );
172
173 if( waitAckValue )
174 err = -3;
175 }
176 waitAckValue = 0;
177
178 return( err );
179 }
180
181 IOReturn AppleADBDisplay::setLogicalRegister( UInt16 address, UInt16 data )
182 {
183 IOReturn err = -1;
184 UInt32 reconnects = 3;
185
186 while( err && reconnects-- ) {
187 err = writeWithAcknowledge( kADBReg1, address, kReg2DataRdy);
188 if( err == kIOReturnSuccess )
189 err = writeWithAcknowledge( kADBReg2, data, kReg2DataAck);
190
191 if( err ) {
192 if( doConnect() )
193 break;
194 }
195 }
196 if( err)
197 kprintf( "%s: %x, %d\n", __FUNCTION__, address, err);
198
199 return( err);
200 }
201
202 IOReturn AppleADBDisplay::getLogicalRegister( UInt16 address, UInt16 * data )
203 {
204 IOReturn err = -1;
205 UInt32 reconnects = 3;
206 UInt16 value;
207 IOByteCount length;
208
209 while ( err && reconnects--) {
210 err = writeWithAcknowledge( kADBReg1, address, kReg2DataRdy);
211 if( err == kIOReturnSuccess ) {
212 length = sizeof( value);
213 err = adbDevice->readRegister( 2, (UInt8 *)&value, &length);
214 *data = value & 0xff; // actually only 8 bits
215 }
216 if( err) {
217 if ( doConnect())
218 break;
219 }
220 }
221 if( err)
222 kprintf( "%s: %x=%x, %d\n", __FUNCTION__, address, *data, err);
223
224 return err;
225 }
226
227 void AppleADBDisplay::setWiggle( bool active )
228 {
229 setLogicalRegister( wiggleLADAddr, (active ? 1 : 0));
230 }
231
232 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
233
234 bool AppleADBDisplay::start( IOService * nub )
235 {
236 IOReturn err;
237 UInt16 data, deviceType;
238
239 if( !super::start( nub))
240 return false;
241
242 if( OSDynamicCast( IODisplayConnect, nub ))
243 return( true );
244
245 assert( OSDynamicCast( IOADBDevice, nub ));
246 adbDevice = (IOADBDevice *) nub;
247
248 if( !adbDevice->seizeForClient( this, &autoPollHandler) ) {
249 IOLog("%s: sieze failed\n", getName());
250 return( false);
251 }
252
253 do {
254 err = doConnect();
255 if( err )
256 continue;
257
258 err = setLogicalRegister( 0xff, 0xff);
259 if( err)
260 continue;
261
262 err = getLogicalRegister( 0xff, &data);
263 if( err)
264 continue;
265
266 err = getLogicalRegister( 0xff, &deviceType);
267 if( err)
268 continue;
269
270 kprintf("%s: found AVType %d\n",
271 adbDevice->getName(), deviceType );
272
273 err = findADBDisplayInfoForType( deviceType );
274 if( err)
275 continue;
276
277 avDisplayID = deviceType;
278 setWiggle( false);
279
280 registerService();
281 return( true );
282
283 } while( false );
284
285 adbDevice->releaseFromClient( this );
286 return( false );
287 }
288
289
290 bool AppleADBDisplay::tryAttach( IODisplayConnect * connect )
291 {
292 IOReturn err;
293 bool attached = false;
294 UInt32 sense, extSense;
295 IOFramebuffer * framebuffer;
296 IOIndex fbConnect;
297 UInt32 senseType;
298 enum {
299 kRSCFour = 4,
300 kRSCSix = 6,
301 kESCFourNTSC = 0x0A,
302 kESCSixStandard = 0x2B,
303 };
304
305 do {
306
307 framebuffer = connect->getFramebuffer();
308 fbConnect = connect->getConnection();
309 assert( framebuffer );
310
311 if( kIOReturnSuccess != framebuffer->getAttributeForConnection(
312 fbConnect,
313 kConnectionSupportsAppleSense, NULL ))
314 continue;
315
316 err = framebuffer->getAppleSense( fbConnect,
317 &senseType, &sense, &extSense, 0 );
318 if( err)
319 continue;
320 if( (sense != kRSCSix) || (extSense != kESCSixStandard) ) // straight-6
321 continue;
322
323 setWiggle( true );
324 err = framebuffer->getAppleSense( fbConnect,
325 &senseType, &sense, &extSense, 0 );
326 setWiggle( false );
327 if( err)
328 continue;
329 if( (sense != kRSCFour) || (extSense != kESCFourNTSC) ) // straight-4
330 continue;
331
332 kprintf( "%s: attached to %s\n",
333 adbDevice->getName(), framebuffer->getName() );
334
335 attached = true;
336
337 } while( false);
338
339 return( attached);
340 }
341
342
343 IOService * AppleADBDisplay::probe( IOService * nub, SInt32 * score )
344 {
345 IODisplayConnect * connect;
346
347 // both ADB device & display connections come here!
348
349 do {
350 if( OSDynamicCast( IOADBDevice, nub))
351 continue;
352
353 if( (connect = OSDynamicCast( IODisplayConnect, nub))
354 && tryAttach( connect))
355 continue;
356
357 nub = 0;
358
359 } while( false );
360
361 if( nub)
362 return( super::probe( nub, score ));
363 else
364 return( 0 );
365 }
366
367
368