1/*
2 * Copyright (c) 2000-2008 Apple 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/*
24 *
25 *	IOATADevConfig.cpp
26 *
27 */
28
29const int configword 		= 00;
30const int pioModeNumber 	= 51;
31const int fieldValidity 	= 53;
32const int mwDMAWord 		= 63;
33const int pioAdvancedMode 	= 64;
34const int minimumDMATime 	= 65;
35const int recommendDMATime 	= 66;
36const int pioCycleNoFlow 	= 67;
37const int pioCycleIORDY 	= 68;
38const int ultraDMAWord 		= 88;
39
40#include<IOKit/IOTypes.h>
41#include"IOATATypes.h"
42#include"IOATADevConfig.h"
43#include"IOATABusInfo.h"
44
45
46#ifdef DLOG
47#undef DLOG
48#endif
49
50#ifdef  ATA_DEBUG
51#define DLOG(fmt, args...)  IOLog(fmt, ## args)
52#else
53#define DLOG(fmt, args...)
54#endif
55
56
57//---------------------------------------------------------------------------
58
59#define super OSObject
60OSDefineMetaClassAndStructors ( IOATADevConfig, OSObject )
61    OSMetaClassDefineReservedUnused(IOATADevConfig, 0);
62    OSMetaClassDefineReservedUnused(IOATADevConfig, 1);
63    OSMetaClassDefineReservedUnused(IOATADevConfig, 2);
64    OSMetaClassDefineReservedUnused(IOATADevConfig, 3);
65    OSMetaClassDefineReservedUnused(IOATADevConfig, 4);
66    OSMetaClassDefineReservedUnused(IOATADevConfig, 5);
67    OSMetaClassDefineReservedUnused(IOATADevConfig, 6);
68    OSMetaClassDefineReservedUnused(IOATADevConfig, 7);
69    OSMetaClassDefineReservedUnused(IOATADevConfig, 8);
70    OSMetaClassDefineReservedUnused(IOATADevConfig, 9);
71    OSMetaClassDefineReservedUnused(IOATADevConfig, 10);
72    OSMetaClassDefineReservedUnused(IOATADevConfig, 11);
73    OSMetaClassDefineReservedUnused(IOATADevConfig, 12);
74    OSMetaClassDefineReservedUnused(IOATADevConfig, 13);
75    OSMetaClassDefineReservedUnused(IOATADevConfig, 14);
76    OSMetaClassDefineReservedUnused(IOATADevConfig, 15);
77    OSMetaClassDefineReservedUnused(IOATADevConfig, 16);
78    OSMetaClassDefineReservedUnused(IOATADevConfig, 17);
79    OSMetaClassDefineReservedUnused(IOATADevConfig, 18);
80    OSMetaClassDefineReservedUnused(IOATADevConfig, 19);
81    OSMetaClassDefineReservedUnused(IOATADevConfig, 20);
82
83
84IOATADevConfig*
85IOATADevConfig::atadevconfig(void)
86{
87
88	IOATADevConfig* config = new IOATADevConfig;
89
90	if( !config )
91		return 0L;
92
93	if( !config->init() )
94	{
95
96		return 0L;
97
98	}
99
100
101	return config;
102
103}
104
105
106// intialize the data fields to nil values
107
108/*-----------------------------------------------------------------------------
109 *
110 *
111 *-----------------------------------------------------------------------------*/
112
113bool
114IOATADevConfig::init( )
115{
116
117	if( ! super::init() )
118		return false;
119
120	_atapiIRQForPacket = kATAPIUnknown;
121
122	_ataPIOMode = 0x00;
123	_ataPIOCycleTime = 0;
124	_ataMultiDMAMode = 0x00;
125	_ataMultiCycleTime = 0;
126	_ataUltraDMAMode = 0x00;
127//	_ataUltraCycleTime = 0;
128
129	return true;
130}
131
132
133
134/*-----------------------------------------------------------------------------
135 *
136 *
137 *-----------------------------------------------------------------------------*/
138
139IOReturn
140IOATADevConfig::initWithBestSelection( const UInt16* identifyData, IOATABusInfo* busInfo)
141{
142	IOReturn err = kATANoErr;
143
144	err = assignFromData( identifyData );
145	if( err )
146		return err;
147
148	// AND mask with the modes supported by the bus controller
149
150	_ataPIOMode	     = _ataPIOMode & busInfo->getPIOModes();
151	_ataMultiDMAMode = _ataMultiDMAMode & busInfo->getDMAModes();
152	_ataUltraDMAMode = _ataUltraDMAMode & busInfo->getUltraModes();
153
154	// select only one kind of DMA mode, preferring UDMA over MWDMA
155
156	if( _ataUltraDMAMode != 0x00 )
157	{
158		_ataMultiDMAMode = 0x00;
159	}
160
161	// clear all but the most-significant matching bit to indicate the best match between
162	// device and bus.
163
164	_ataPIOMode = _MostSignificantBit(_ataPIOMode);
165	_ataMultiDMAMode = _MostSignificantBit(_ataMultiDMAMode);
166	_ataUltraDMAMode = _MostSignificantBit(_ataUltraDMAMode);
167
168	return kATANoErr;
169
170}
171
172
173//-----------------------------------------------------------------------------
174IOReturn
175IOATADevConfig::assignFromData( const UInt16* identifyData )
176{
177
178	if ( ( identifyData[0] & 0xC000 ) == 0xC000 )
179	{
180		// unknown device type
181		return kATAErrUnknownType;
182	}
183
184	// for atapi devices, figure out the command-to-packet protocol
185	if( ( identifyData[0] & 0x8000 )  )
186	{
187
188		// Atapi device that uses INTRQ
189		_atapiIRQForPacket = ( atapiConfig )( ( identifyData[0] & 0x0060 ) >> 5 );
190
191	}
192
193
194
195	_AssignPIOData ( identifyData );
196	_AssignDMAData ( identifyData );
197	_AssignUltraData ( identifyData );
198
199	return kATANoErr;
200
201}
202
203
204
205/*-----------------------------------------------------------------------------
206 *
207 *
208 *-----------------------------------------------------------------------------*/
209
210IOReturn
211IOATADevConfig::_AssignPIOData( const UInt16* identifyData)
212{
213	UInt16 advancedPIO = 0x0000;
214
215	// set internal fields to no modes.
216	_ataPIOCycleTime = 0;
217	_ataPIOMode = 0;
218
219	//Check word 53 bit 1 if advanced fields are valid.
220	if( 0x0002 & identifyData[fieldValidity] )
221	{
222
223		advancedPIO = (identifyData[ pioAdvancedMode ] & 0x03) << 3	;
224
225		if(advancedPIO != 0x0000)
226		{
227
228			// set ns cycle time.
229			_ataPIOCycleTime = identifyData[ pioCycleIORDY ];
230			if( _ataPIOCycleTime == 0 )
231			{
232				//  some devices fail to support cycle times.
233				// supply a default setting that equals PIO mode 3 timing
234				_ataPIOCycleTime = 180;
235
236			}
237
238			// set all lower mode bits as per ATA standards
239			_ataPIOMode = advancedPIO | 0x0007;
240			return kATANoErr;
241		}
242
243		// otherwise fall through and use the mode number in word 51.
244
245	}
246
247
248
249	// Otherwise, this is a basic device
250	switch( identifyData[ pioModeNumber] & 0xFF00 )
251	{
252		case 0x0200:
253		 	_ataPIOMode = 0x07; 	// mode 2, 1, 0
254			_ataPIOCycleTime = 240;
255		break;
256
257		case 0x0100:
258			_ataPIOMode = 0x03;	// mode 1, 0
259			_ataPIOCycleTime = 383;
260		break;
261
262		default:
263			_ataPIOMode = 0x01;	// mode 0 only.
264			_ataPIOCycleTime = 600;
265		break;
266
267
268	}
269
270	return kATANoErr;
271
272}
273
274
275/*-----------------------------------------------------------------------------
276 *
277 *
278 *-----------------------------------------------------------------------------*/
279
280IOReturn
281IOATADevConfig::_AssignDMAData(const UInt16* identifyData)
282{
283
284	// set internal fields to no support
285	_ataMultiDMAMode = 0;
286	_ataMultiCycleTime = 0;
287
288
289	//Check word 53 bit 1 if dma fields are valid.
290	if( 0x0002 & identifyData[fieldValidity] )
291	{
292		_ataMultiDMAMode = identifyData[mwDMAWord] & 0x0007;
293
294		if( identifyData[recommendDMATime] > identifyData[minimumDMATime] )
295		{
296			_ataMultiCycleTime = identifyData[recommendDMATime];
297
298		} else {
299
300			_ataMultiCycleTime = identifyData[minimumDMATime];
301		}
302
303	}
304
305	return kATANoErr;
306
307
308}
309
310
311
312
313/*-----------------------------------------------------------------------------
314 *
315 *
316 *-----------------------------------------------------------------------------*/
317
318IOReturn
319IOATADevConfig::_AssignUltraData(const UInt16* identifyData)
320{
321
322	// set internal fields to no support
323	_ataUltraDMAMode = 0;
324
325
326	//Check word 53 bit 2 if ultra fields are valid.
327	if( 0x0004 & identifyData[fieldValidity] )
328	{
329		_ataUltraDMAMode = identifyData[ultraDMAWord] & 0x00FF;
330	}
331
332	return kATANoErr;
333
334
335
336}
337
338
339
340/*-----------------------------------------------------------------------------
341 *
342 *
343 *-----------------------------------------------------------------------------*/
344
345void
346IOATADevConfig::setPacketConfig ( atapiConfig packetConfig)
347{
348
349	_atapiIRQForPacket = packetConfig;
350
351}
352
353
354/*-----------------------------------------------------------------------------
355 *
356 *
357 *-----------------------------------------------------------------------------*/
358
359atapiConfig
360IOATADevConfig::getPacketConfig( void )
361{
362
363	return _atapiIRQForPacket;
364
365}
366
367
368
369
370/*-----------------------------------------------------------------------------
371 *
372 *
373 *-----------------------------------------------------------------------------*/
374
375void
376IOATADevConfig::setPIOMode( UInt8 inModeBitMap)
377{
378
379	_ataPIOMode = inModeBitMap;
380
381
382}
383
384
385/*-----------------------------------------------------------------------------
386 *
387 *
388 *-----------------------------------------------------------------------------*/
389
390UInt8
391IOATADevConfig::getPIOMode( void )
392{
393
394
395	return _ataPIOMode;
396
397}
398
399
400/*-----------------------------------------------------------------------------
401 *
402 *
403 *-----------------------------------------------------------------------------*/
404
405void
406IOATADevConfig::setDMAMode( UInt8 inModeBitMap )
407{
408
409	_ataMultiDMAMode = inModeBitMap;
410
411
412}
413
414
415/*-----------------------------------------------------------------------------
416 *
417 *
418 *-----------------------------------------------------------------------------*/
419
420UInt8
421IOATADevConfig::getDMAMode( void )
422{
423
424	return _ataMultiDMAMode;
425
426}
427
428
429/*-----------------------------------------------------------------------------
430 *
431 *
432 *-----------------------------------------------------------------------------*/
433
434void
435IOATADevConfig::setUltraMode( UInt8 inModeBitMap )
436{
437
438
439	_ataUltraDMAMode = inModeBitMap;
440
441}
442
443
444/*-----------------------------------------------------------------------------
445 *
446 *
447 *-----------------------------------------------------------------------------*/
448
449UInt8
450IOATADevConfig::getUltraMode( void )
451{
452
453
454	return _ataUltraDMAMode;
455
456}
457
458
459/*-----------------------------------------------------------------------------
460 *
461 *
462 *-----------------------------------------------------------------------------*/
463
464void
465IOATADevConfig::setPIOCycleTime( UInt16 inNS )
466{
467
468
469	_ataPIOCycleTime = inNS;
470
471}
472
473
474/*-----------------------------------------------------------------------------
475 *
476 *
477 *-----------------------------------------------------------------------------*/
478
479UInt16
480IOATADevConfig::getPIOCycleTime( void )
481{
482
483	return _ataPIOCycleTime;
484
485
486}
487
488
489/*-----------------------------------------------------------------------------
490 *
491 *
492 *-----------------------------------------------------------------------------*/
493
494void
495IOATADevConfig::setDMACycleTime( UInt16 inNS )
496{
497
498
499	_ataMultiCycleTime = inNS;
500
501}
502
503
504/*-----------------------------------------------------------------------------
505 *
506 *
507 *-----------------------------------------------------------------------------*/
508
509UInt16
510IOATADevConfig::getDMACycleTime( void )
511{
512
513	return _ataMultiCycleTime;
514
515
516}
517
518
519/*-----------------------------------------------------------------------------
520 *
521 *
522 *-----------------------------------------------------------------------------*/
523
524UInt8
525IOATADevConfig::_MostSignificantBit( UInt8 inByte)
526{
527	// return 0 if input is 0
528	if( inByte == 0)
529		return inByte;
530
531	// start at the top and work down.
532	UInt8 mask = 0x80;
533
534	for( int i = 7; i >0; i--)
535	{
536		// if it masks, return.
537		if( mask & inByte )
538		{
539			return mask;
540		}
541
542		// shift one right and try again.
543		mask >>= 1;
544	}
545
546	// bit zero is the winner.
547	return 0x01;
548
549}
550
551/*****************************************************************************
552**  Function bitSigToNumeric
553**	This function converts a bit-significant value into an integer which
554**	corresponds to the highest-order bit which is active. For example,
555**	0x0035 is converted to 5, which is the bit-number of the high bit of 0x0035.
556**  Input variable binary = zero is technically illegal; the routine does not check
557**  explicitly for this value, but rather returns 0xFFFF as a result of no
558**  bit being found, and the return value is decemented below zero. The
559**  loop terminates when i becomes zero because of binary = 0.
560**	Implicit maximum value of binary: 0x00FF.
561**
562** Explicit Inputs:
563**	binary - a non-zero binary number (0 has no corresponding bit number)
564** Return Value:
565**	integer - the bit-number of the highest bit active in binary.
566**
567******************************************************************************/
568
569UInt8
570IOATADevConfig::bitSigToNumeric(UInt16 binary)
571{
572	UInt16  i, integer;
573
574	/* Test all bits from left to right, terminating at the first non-zero bit. */
575	for (i = 0x0080, integer = 7; ((i & binary) == 0 && i != 0) ; i >>= 1, integer-- )
576	{;}
577	return (integer);
578}	/* end BitSigToNumeric() */
579
580bool
581IOATADevConfig::sDriveSupports48BitLBA( const UInt16* identifyData )
582{
583
584	if( (identifyData[83] & 0x0400)
585		&& (identifyData[86] & 0x0400))
586	{
587		return true;
588	}
589
590	return false;
591}
592
593UInt32
594IOATADevConfig::sDriveExtendedLBASize( UInt32* lbaHi, UInt32* lbaLo, const UInt16* identifyData)
595{
596
597	UInt32 lowerLBA = 0;
598	UInt32 upperLBA = 0;
599
600	if( IOATADevConfig::sDriveSupports48BitLBA( identifyData ) )
601	{
602		lowerLBA = identifyData[ 100 ] | ( identifyData[101] << 16 );
603		upperLBA = identifyData[102] | ( identifyData[103] << 16 );
604	}
605
606	*lbaLo = lowerLBA;
607	*lbaHi = upperLBA;
608
609	return lowerLBA;
610
611}