|
|
1.1 root 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: *
24: * IOATADevice.cpp
25: *
26: */
27:
28: #include <IOKit/IOSyncer.h>
29: #include <IOKit/ata/IOATA.h>
30: #include <IOKit/ata/IOATAController.h>
31: #include "ATAPrivate.h"
32:
33: #undef super
34: #define super IOService
35:
36: OSDefineMetaClassAndStructors( IOATADevice, IOService );
37:
38: extern EndianTable AppleIdentifyEndianTable[];
39:
40: extern UInt32 AppleNumPIOModes;
41: extern ATAModeTable ApplePIOModes[];
42: extern UInt32 AppleNumDMAModes;
43: extern ATAModeTable AppleDMAModes[];
44: extern UInt32 AppleNumUltraModes;
45: extern ATAModeTable AppleUltraModes[];
46:
47: /*
48: *
49: *
50: */
51: bool IOATADevice::probeDevice()
52: {
53: OSDictionary *propTable = 0;
54:
55: if ( open( this ) != true )
56: {
57: goto probeDevice_error;
58: }
59:
60: if ( doIdentify( (void **)&identifyData ) != ataReturnNoError )
61: {
62: goto probeDevice_error;
63: }
64:
65: if ( deviceType == ataDeviceATA )
66: {
67: doSpinUp();
68: }
69:
70: else if ( deviceType == ataDeviceATAPI )
71: {
72: atapiPktInt = ((identifyData->generalConfiguration & atapiPktProtocolIntDRQ) != 0);
73:
74: if ( doInquiry( (void **)&inquiryData ) != ataReturnNoError )
75: {
76: goto probeDevice_error;
77: }
78:
79: reqSenseCmd = allocCommand();
80: }
81:
82: if ( getATATimings() != true )
83: {
84: goto probeDevice_error;
85: }
86:
87: propTable = createProperties();
88: if ( !propTable )
89: {
90: goto probeDevice_error;
91: }
92:
93: setPropertyTable( propTable );
94:
95: propTable->release();
96:
97: close( this );
98:
99: return true;
100:
101: probeDevice_error: ;
102: close( this );
103: return false;
104: }
105:
106: /*
107: *
108: *
109: *
110: */
111: ATADeviceType IOATADevice::probeDeviceType()
112: {
113: ATATaskfile taskfile;
114: ATAResults results;
115:
116: bzero( (void *)&taskfile, sizeof(taskfile) );
117:
118: taskfile.protocol = ataProtocolSetRegs;
119: taskfile.regmask = ATARegtoMask(ataRegDriveHead);
120:
121: taskfile.resultmask = ATARegtoMask(ataRegSectorCount)
122: | ATARegtoMask(ataRegSectorNumber)
123: | ATARegtoMask(ataRegCylinderLow)
124: | ATARegtoMask(ataRegCylinderHigh)
125: | ATARegtoMask(ataRegStatus);
126:
127: taskfile.ataRegs[ataRegDriveHead] = ataModeLBA | (getUnit() << 4);
128:
129: utilCmd->setTaskfile( &taskfile );
130: utilCmd->execute();
131:
132: if ( utilCmd->getResults( &results ) != ataReturnNoError )
133: {
134: return (deviceType = ataDeviceNone);
135: }
136:
137: if ( results.ataRegs[ataRegSectorCount] == ataSignatureSectorCount
138: && results.ataRegs[ataRegSectorNumber] == ataSignatureSectorNumber
139: && results.ataRegs[ataRegCylinderLow] == ataSignatureCylinderLow
140: && results.ataRegs[ataRegCylinderHigh] == ataSignatureCylinderHigh )
141: {
142: if ( !(results.ataRegs[ataRegStatus] & ataStatusBSY)
143: && (results.ataRegs[ataRegStatus] & ataStatusDRDY) )
144: {
145: return (deviceType = ataDeviceATA);
146: }
147: }
148:
149: if ( results.ataRegs[ataRegCylinderLow] == atapiSignatureCylinderLow
150: && results.ataRegs[ataRegCylinderHigh] == atapiSignatureCylinderHigh )
151: {
152: return (deviceType = ataDeviceATAPI);
153: }
154:
155: return (deviceType = ataDeviceNone);
156: }
157:
158:
159: /*
160: *
161: *
162: *
163: */
164: ATAReturnCode IOATADevice::doSpinUp()
165: {
166: void *buffer = NULL;
167: ATAReturnCode rc;
168:
169: rc = doSectorCommand( ataCommandReadSector, 0, 1, &buffer );
170:
171: if ( rc != ataReturnNoError )
172: {
173: return rc;
174: }
175:
176: IOFree( buffer, 512 );
177:
178: return rc ;
179: }
180:
181: /*
182: *
183: *
184: *
185: */
186: ATAReturnCode IOATADevice::doIdentify( void **dataPtr )
187: {
188: ATACommand ataCmd;
189: ATAReturnCode rc;
190:
191: ataCmd = (deviceType == ataDeviceATA) ? ataCommandIdentify : atapiCommandIdentify;
192:
193: rc = doSectorCommand( ataCmd, 0, 1, dataPtr );
194:
195: if ( rc != ataReturnNoError )
196: {
197: return rc;
198: }
199:
200: endianConvertData( *dataPtr, AppleIdentifyEndianTable );
201:
202: return rc;
203: }
204:
205:
206:
207: /*
208: *
209: *
210: *
211: */
212: ATAReturnCode IOATADevice::doSectorCommand( ATACommand ataCmd, UInt32 ataLBA, UInt32 ataCount, void **dataPtr )
213: {
214: ATATaskfile taskfile;
215: ATAResults result;
216: IOMemoryDescriptor *desc;
217: UInt32 size;
218: void *data;
219: UInt32 i;
220: ATAReturnCode rc;
221:
222: *dataPtr = NULL;
223:
224: size = ataCount * 512;
225:
226: if ( !(data = (void *)IOMalloc(size)) )
227: {
228: return ataReturnNoResource;
229: }
230:
231: bzero( &taskfile, sizeof(taskfile) );
232:
233: desc = IOMemoryDescriptor::withAddress( data, size, kIODirectionIn );
234: if ( desc == NULL )
235: {
236: rc = ataReturnNoResource;
237: goto doSectorCommand_error;
238: }
239:
240:
241: taskfile.protocol = ataProtocolPIO;
242: taskfile.regmask = ATARegtoMask(ataRegDriveHead)
243: | ATARegtoMask(ataRegSectorCount)
244: | ATARegtoMask(ataRegSectorNumber)
245: | ATARegtoMask(ataRegCylinderLow)
246: | ATARegtoMask(ataRegCylinderHigh)
247: | ATARegtoMask(ataRegFeatures)
248: | ATARegtoMask(ataRegCommand);
249:
250:
251: taskfile.resultmask = ATARegtoMask(ataRegError)
252: | ATARegtoMask(ataRegStatus);
253:
254: taskfile.ataRegs[ataRegSectorCount] = ataCount;
255: taskfile.ataRegs[ataRegSectorNumber] = ataLBA & 0xff;
256: taskfile.ataRegs[ataRegCylinderLow] = (ataLBA >> 8) & 0xff;
257: taskfile.ataRegs[ataRegCylinderHigh] = (ataLBA >> 16) & 0xff;
258: taskfile.ataRegs[ataRegDriveHead] = (ataLBA >> 24) & 0x0f;
259:
260: taskfile.ataRegs[ataRegDriveHead] |= ataModeLBA | (getUnit() << 4);
261: taskfile.ataRegs[ataRegCommand] = ataCmd;
262:
263: for ( i = 0; i < 2; i++ )
264: {
265: utilCmd->setTimeout( 25000 );
266: utilCmd->setTaskfile( &taskfile );
267: utilCmd->setPointers( desc, size, false );
268: submitCommand( utilCmd );
269:
270: rc = utilCmd->getResults( &result );
271: if ( rc == ataReturnNoError )
272: {
273: break;
274: }
275: }
276:
277:
278: doSectorCommand_error: ;
279:
280: desc->release();
281:
282: if ( rc != ataReturnNoError )
283: {
284: IOFree( data, size );
285: return result.returnCode;
286: }
287:
288: *dataPtr = data;
289:
290: return ataReturnNoError;
291: }
292:
293:
294: /*
295: *
296: *
297: */
298: ATAReturnCode IOATADevice::doInquiry( void **dataPtr )
299: {
300: ATATaskfile taskfile;
301: ATAPICmd atapiCmd;
302: ATAResults result;
303: void *data;
304: IOMemoryDescriptor *desc;
305: UInt32 size = sizeof(ATAPIInquiry);
306:
307: *dataPtr = 0;
308:
309: if ( !(data = (void *)IOMalloc(size)) )
310: {
311: return ataReturnNoResource;;
312: }
313:
314: bzero( &taskfile, sizeof(taskfile) );
315: bzero( &atapiCmd, sizeof(atapiCmd) );
316:
317: desc = IOMemoryDescriptor::withAddress( data, size, kIODirectionIn );
318:
319: taskfile.protocol = atapiProtocolPIO;
320: taskfile.regmask = ATARegtoMask(atapiRegDeviceSelect)
321: | ATARegtoMask(atapiRegCommand)
322: | ATARegtoMask(atapiRegByteCountLow)
323: | ATARegtoMask(atapiRegByteCountHigh)
324: | ATARegtoMask(atapiRegFeatures);
325: taskfile.ataRegs[atapiRegDeviceSelect] = ataModeLBA | (getUnit() << 4);
326: taskfile.ataRegs[atapiRegCommand] = atapiCommandPacket;
327: taskfile.ataRegs[atapiRegFeatures] = 0;
328: taskfile.ataRegs[atapiRegByteCountLow] = 0xfe;
329: taskfile.ataRegs[atapiRegByteCountHigh] = 0xff;
330:
331: atapiCmd.cdbLength = 12; // Fix 16 byte cmdpkts??
332: atapiCmd.cdb[0] = 0x12;
333: atapiCmd.cdb[4] = size;
334:
335: utilCmd->setATAPICmd( &atapiCmd, 0, 0 );
336: utilCmd->setTaskfile( &taskfile );
337: utilCmd->setPointers( desc, size, false );
338: utilCmd->setTimeout( 5000 );
339: submitCommand( utilCmd );
340:
341: if ( utilCmd->getResults(&result) == ataReturnNoError )
342: {
343: *dataPtr = data;
344: }
345: else
346: {
347: IOFree( data, size );
348: }
349:
350: desc->release();
351:
352: return result.returnCode;
353: }
354:
355: /*
356: *
357: *
358: */
359: bool IOATADevice::getDeviceCapacity( UInt32 *blockMax, UInt32 *blockSize )
360: {
361: UInt32 i;
362: UInt32 data[2];
363:
364: if ( deviceType == ataDeviceATA )
365: {
366: if ( identifyData != NULL )
367: {
368: *blockMax = *(UInt32 *)identifyData->userAddressableSectors - 1;
369: *blockSize = 512;
370: return true;
371: }
372: }
373:
374: if ( deviceType == ataDeviceATAPI )
375: {
376: for ( i=0; i < 8; i++ )
377: {
378: if ( doTestUnitReady() == ataReturnNoError )
379: {
380: break;
381: }
382: }
383:
384: if ( doReadCapacity( data ) == ataReturnNoError )
385: {
386: *blockMax = OSSwapBigToHostInt32( data[0] );
387: *blockSize = OSSwapBigToHostInt32( data[1] );
388: return true;
389: }
390: }
391:
392: return false;
393: }
394:
395:
396: ATAReturnCode IOATADevice::doTestUnitReady()
397: {
398: ATATaskfile taskfile;
399: ATAPICmd atapiCmd;
400: ATAResults result;
401:
402: bzero( &taskfile, sizeof(taskfile) );
403: bzero( &atapiCmd, sizeof(atapiCmd) );
404:
405: taskfile.protocol = atapiProtocolPIO;
406:
407: taskfile.regmask = ATARegtoMask(atapiRegDeviceSelect)
408: | ATARegtoMask(atapiRegCommand)
409: | ATARegtoMask(atapiRegByteCountLow)
410: | ATARegtoMask(atapiRegByteCountHigh)
411: | ATARegtoMask(atapiRegFeatures);
412:
413: taskfile.ataRegs[atapiRegDeviceSelect] = ataModeLBA | (getUnit() << 4);
414: taskfile.ataRegs[atapiRegCommand] = atapiCommandPacket;
415: taskfile.ataRegs[atapiRegFeatures] = 0;
416: taskfile.ataRegs[atapiRegByteCountLow] = 0xfe;
417: taskfile.ataRegs[atapiRegByteCountHigh] = 0xff;
418:
419: atapiCmd.cdbLength = 12; // Fix 16 byte cmdpkts??
420: atapiCmd.cdb[0] = 0x00;
421:
422: utilCmd->setATAPICmd( &atapiCmd );
423: utilCmd->setTaskfile( &taskfile );
424: utilCmd->setPointers( (IOMemoryDescriptor *)NULL, 0, false );
425: utilCmd->setTimeout( 5000 );
426: submitCommand( utilCmd );
427: utilCmd->getResults(&result);
428:
429: return result.returnCode;
430: }
431:
432:
433: /*
434: *
435: *
436: */
437: ATAReturnCode IOATADevice::doReadCapacity( void *data )
438: {
439: ATATaskfile taskfile;
440: ATAPICmd atapiCmd;
441: ATAResults result;
442: IOMemoryDescriptor *dataDesc;
443: UInt32 size = 8;
444:
445:
446: bzero( &taskfile, sizeof(taskfile) );
447: bzero( &atapiCmd, sizeof(atapiCmd) );
448:
449: dataDesc = IOMemoryDescriptor::withAddress( data, size, kIODirectionIn );
450: if ( dataDesc == NULL )
451: {
452: return ataReturnNoResource;
453: }
454:
455: taskfile.protocol = atapiProtocolPIO;
456: taskfile.regmask = ATARegtoMask(atapiRegDeviceSelect)
457: | ATARegtoMask(atapiRegCommand)
458: | ATARegtoMask(atapiRegByteCountLow)
459: | ATARegtoMask(atapiRegByteCountHigh)
460: | ATARegtoMask(atapiRegFeatures);
461: taskfile.ataRegs[atapiRegDeviceSelect] = ataModeLBA | (getUnit() << 4);
462: taskfile.ataRegs[atapiRegCommand] = atapiCommandPacket;
463: taskfile.ataRegs[atapiRegFeatures] = 0;
464: taskfile.ataRegs[atapiRegByteCountLow] = 0xfe;
465: taskfile.ataRegs[atapiRegByteCountHigh] = 0xff;
466:
467: atapiCmd.cdbLength = 12; // Fix 16 byte cmdpkts??
468: atapiCmd.cdb[0] = 0x25;
469:
470: utilCmd->setATAPICmd( &atapiCmd );
471: utilCmd->setTaskfile( &taskfile );
472: utilCmd->setPointers( dataDesc, size, false );
473: utilCmd->setTimeout( 5000 );
474: submitCommand( utilCmd );
475:
476: utilCmd->getResults(&result);
477:
478: dataDesc->release();
479:
480: return result.returnCode;
481: }
482:
483:
484: /*
485: *
486: *
487: */
488: IOATACommand *IOATADevice::makeRequestSense( IOATACommand *origCmd )
489: {
490: ATATaskfile taskfile;
491: ATAPICmd atapiCmd;
492:
493: if ( reqSenseCmd == NULL )
494: {
495: return NULL;
496: }
497:
498: bzero( &taskfile, sizeof(taskfile) );
499: bzero( &atapiCmd, sizeof(atapiCmd) );
500:
501: taskfile.protocol = atapiProtocolPIO;
502:
503: taskfile.regmask = ATARegtoMask(atapiRegDeviceSelect)
504: | ATARegtoMask(atapiRegCommand)
505: | ATARegtoMask(atapiRegByteCountLow)
506: | ATARegtoMask(atapiRegByteCountHigh)
507: | ATARegtoMask(atapiRegFeatures);
508:
509: taskfile.ataRegs[atapiRegDeviceSelect] = ataModeLBA | (getUnit() << 4);
510: taskfile.ataRegs[atapiRegCommand] = atapiCommandPacket;
511: taskfile.ataRegs[atapiRegFeatures] = 0;
512: taskfile.ataRegs[atapiRegByteCountLow] = origCmd->senseLength & 0xff;
513: taskfile.ataRegs[atapiRegByteCountHigh] = 0;
514:
515: atapiCmd.cdbLength = 12; // Fix 16 byte cmdpkts??
516: atapiCmd.cdb[0] = 0x03;
517: atapiCmd.cdb[4] = origCmd->senseLength;
518:
519: reqSenseCmd->setATAPICmd( &atapiCmd, 0, 0 );
520: reqSenseCmd->setTaskfile( &taskfile );
521: reqSenseCmd->setPointers( origCmd->senseData, origCmd->senseLength, false );
522:
523: return reqSenseCmd;
524: }
525:
526: /*
527: *
528: *
529: */
530: bool IOATADevice::completeRequestSense( IOATACommand *origCmd, IOATACommand *reqSense )
531: {
532: ATAResults result;
533:
534: if ( reqSense->getResults(&result) != ataReturnNoError )
535: {
536: return false;
537: }
538:
539: origCmd->results.senseLength = result.bytesTransferred;
540: return true;
541: }
542:
543:
544: /*
545: *
546: *
547: */
548: bool IOATADevice::getTimingsSupported( ATATimingProtocol *timingsSupported )
549: {
550: UInt32 i;
551:
552: *(UInt32 *)timingsSupported = 0;
553:
554: for ( i=0; i < numTimings; i++ )
555: {
556: *(UInt32 *) timingsSupported |= (UInt32)ataTimings[i].timingProtocol;
557: }
558:
559: return true;
560: }
561:
562: /*
563: *
564: *
565: */
566: bool IOATADevice::getTiming( ATATimingProtocol *timingProtocol, ATATiming *timing )
567: {
568: UInt32 i;
569:
570: for ( i=0; i < numTimings; i++ )
571: {
572: if ( ataTimings[i].timingProtocol == *timingProtocol )
573: {
574: bcopy( &ataTimings[i], timing, sizeof(ATATiming) );
575: return true;
576: }
577: }
578:
579: return false;
580: }
581:
582:
583: /*
584: *
585: *
586: */
587: bool IOATADevice::selectTiming( ATATimingProtocol timingProtocol )
588: {
589: ATATaskfile taskfile;
590: ATAResults result;
591: bool rc = false;
592: UInt32 i;
593:
594: for ( i=0; i < numTimings; i++ )
595: {
596: if ( ataTimings[i].timingProtocol == timingProtocol )
597: {
598: rc = true;
599: break;
600: }
601: }
602:
603: if ( rc == false ) return rc;
604:
605: if ( controller->selectTiming( getUnit(), timingProtocol ) == false )
606: {
607: return false;
608: }
609:
610: bzero( &taskfile, sizeof(taskfile) );
611: bzero( &result, sizeof(result) );
612:
613: taskfile.protocol = ataProtocolPIO;
614: taskfile.regmask = ATARegtoMask(ataRegFeatures)
615: | ATARegtoMask(ataRegSectorCount)
616: | ATARegtoMask(ataRegDriveHead)
617: | ATARegtoMask(ataRegCommand);
618:
619: taskfile.ataRegs[ataRegSectorCount] = ataTimings[i].featureSetting;
620: taskfile.ataRegs[ataRegFeatures] = ataFeatureTransferMode;
621: taskfile.ataRegs[ataRegDriveHead] = ataModeLBA | (getUnit() << 4);
622: taskfile.ataRegs[ataRegCommand] = ataCommandSetFeatures;
623:
624: utilCmd->setTaskfile( &taskfile );
625: utilCmd->setPointers( (IOMemoryDescriptor *)NULL, 0, false );
626: utilCmd->setTimeout( 5000 );
627: utilCmd->setCallback();
628: submitCommand( utilCmd );
629:
630: if ( utilCmd->getResults( &result ) != ataReturnNoError )
631: {
632: rc = false;
633: }
634: return rc;
635: }
636:
637:
638: /*
639: *
640: *
641: */
642: bool IOATADevice::getATATimings()
643: {
644: int i, n;
645: UInt32 mode = 0;
646: UInt32 cycleTime = 0;
647:
648: ATATiming *pTimings;
649:
650: pTimings = ataTimings;
651:
652: /*
653: * PIO Cycle timing......
654: *
655: * 1. Try to match Word 51 (pioCycleTime) with cycle timings
656: * in our pioModes table to get mode/CycleTime. (Valid for Modes 0-2)
657: * 2. If Words 64-68 are supported and Mode 3 or 4 supported check,
658: * update CycleTime with Word 68 (CycleTimeWithIORDY).
659: */
660:
661: cycleTime = identifyData->pioMode;
662:
663: if ( cycleTime > 2 )
664: {
665: for ( i=AppleNumPIOModes-1; i != -1; i-- )
666: {
667: if ( cycleTime <= ApplePIOModes[i].minDataCycle )
668: {
669: mode = i;
670: break;
671: }
672: }
673:
674: if ( i == -1 )
675: {
676: cycleTime = ApplePIOModes[mode].minDataCycle;
677: }
678: }
679: else
680: {
681: mode = cycleTime;
682: cycleTime = ApplePIOModes[mode].minDataCycle;
683: }
684:
685:
686: if ( identifyData->validFields & identifyWords_64to70_Valid )
687: {
688: if (identifyData->advancedPIOModes & advPIOModes_Mode4_Supported)
689: mode = 4;
690: else if (identifyData->advancedPIOModes & advPIOModes_Mode3_Supported)
691: mode = 3;
692:
693: if ( (mode >= 3) && identifyData->minPIOCyclcTimeIORDY )
694: {
695: cycleTime = identifyData->minPIOCyclcTimeIORDY;
696: }
697: }
698:
699: pTimings->timingProtocol = ataTimingPIO;
700: pTimings->mode = mode;
701: pTimings->featureSetting = mode | ataTransferModePIOwFC;
702: pTimings->minDataCycle = cycleTime;
703: pTimings->minDataAccess = ApplePIOModes[mode].minDataAccess;
704:
705: if ( controller->calculateTiming( getUnit(), pTimings ) == false )
706: {
707: IOLog("IOATADevice::%s() - Controller driver must support PIO timings\n\r", __FUNCTION__);
708: return false;
709: }
710:
711: pTimings++;
712: numTimings++;
713:
714: /*
715: * Multiword DMA timing.....
716: *
717: * 1. Check Word 63(7:0) (Multiword DMA Modes Supported). Lookup
718: * CycleTime for highest mode we support.
719: * 2. If Words 64-68 supported, update CycleTime from Word 66
720: * (RecommendedMultiWordCycleTime) if specified.
721: */
722:
723: n = identifyData->dmaModes & dmaModes_Supported;
724: if ( n )
725: {
726: for ( i=0; n; i++, n>>=1 )
727: ;
728:
729: mode = i - 1;
730: if ( mode > AppleNumDMAModes-1 )
731: {
732: mode = AppleNumDMAModes-1;
733: }
734: cycleTime = AppleDMAModes[mode].minDataCycle;
735:
736: if (identifyData->validFields & identifyWords_64to70_Valid)
737: {
738: if ( identifyData->recDMACycleTime )
739: {
740: cycleTime = identifyData->recDMACycleTime;
741: }
742: }
743: pTimings->timingProtocol = ataTimingDMA;
744: pTimings->mode = mode;
745: pTimings->featureSetting = mode | ataTransferModeDMA;
746: pTimings->minDataCycle = cycleTime;
747: pTimings->minDataAccess = AppleDMAModes[mode].minDataAccess;
748:
749: if ( controller->calculateTiming( getUnit(), pTimings ) == true )
750: {
751: pTimings++;
752: numTimings++;
753: }
754: }
755:
756: /*
757: * Ultra DMA timing.....
758: *
759: */
760: if ( identifyData->validFields & identifyWords_88to88_Valid )
761: {
762: n = identifyData->ultraDMAModes & ultraDMAModes_Supported;
763: if ( n )
764: {
765: for ( i=0; n; i++, n>>=1 )
766: ;
767:
768: mode = i - 1;
769: if ( mode > AppleNumUltraModes-1 )
770: {
771: mode = AppleNumUltraModes-1;
772: }
773:
774: /*
775: * Build a separate timing entry for Ultra DMA/33 (mode <= 2) and Ultra DMA/66
776: */
777: while ( 1 )
778: {
779: cycleTime = AppleUltraModes[mode].minDataCycle;
780:
781: pTimings->timingProtocol = (mode > 2) ? ataTimingUltraDMA66 : ataTimingUltraDMA33;
782: pTimings->mode = mode;
783: pTimings->featureSetting = mode | ataTransferModeUltraDMA33;
784: pTimings->minDataCycle = cycleTime;
785: pTimings->minDataAccess = AppleUltraModes[mode].minDataAccess;
786:
787: if ( controller->calculateTiming( getUnit(), pTimings ) == true )
788: {
789: pTimings++;
790: numTimings++;
791: }
792:
793: if ( mode < 3 ) break;
794:
795: mode = 2;
796: }
797: }
798: }
799:
800: return true;
801: }
802:
803: /*
804: *
805: *
806: */
807: void IOATADevice::submitCommand( IOATACommand *cmd )
808: {
809: cmd->execute();
810: IOWriteLock( resetSem );
811: IORWUnlock( resetSem );
812: }
813:
814: /*
815: *
816: *
817: */
818: bool IOATADevice::executeCommand( IOATACommand *cmd )
819: {
820: bool isSync;
821:
822: isSync = !(cmd->flags & IOATACommand::atacmdCallbackValid);
823:
824: if ( isSync )
825: {
826: cmd->completionInfo.sync.syncer = IOSyncer::create();
827: }
828:
829: cmd->deviceQueue = deviceQueue;
830:
831: controller->executeCommand( cmd );
832:
833: if ( isSync )
834: {
835: cmd->completionInfo.sync.syncer->wait();
836: }
837:
838: return true;
839: }
840:
841: /*
842: *
843: *
844: */
845: void IOATADevice::completeCommand( IOATACommand *cmd )
846: {
847: ATATaskfile tf;
848: ATAResults res;
849: UInt32 i;
850:
851: cmd->getTaskfile(&tf);
852: cmd->getResults(&res);
853:
854: #if 0
855: IOLog("ATA command = %02x, RegMask = %04x ResultMask = %04x ReturnCode = %04x\n\r",
856: tf.protocol, (int)tf.regmask, (int)tf.resultmask, (int)res.returnCode );
857:
858: IOLog("ATA command regs: ");
859:
860: for (i=0; i < MAX_ATA_REGS; i++ )
861: {
862: IOLog("%04x ", tf.ataRegs[i]);
863: }
864:
865: IOLog("\n\rATA result regs: ");
866:
867: for (i=0; i < MAX_ATA_REGS; i++ )
868: {
869: IOLog("%04x ", res.ataRegs[i]);
870: }
871: IOLog("\n\r");
872: #endif
873:
874: if ( cmd->flags & IOATACommand::atacmdCallbackValid )
875: {
876: (*cmd->completionInfo.async.ataDoneFn)( cmd->completionInfo.async.target,
877: (IOService *)this,
878: cmd,
879: cmd->completionInfo.async.refcon );
880: }
881: else
882: {
883: cmd->completionInfo.sync.syncer->signal();
884: }
885: }
886:
887: /*
888: *
889: *
890: */
891: IOReturn IOATADevice::message( UInt32 p0, IOService *p1, void *p2 )
892: {
893: UInt32 msgId;
894: IOATADevice *ataDev;
895:
896: msgId = (UInt32) p0;
897: ataDev = (IOATADevice *)p1;
898:
899: switch ( msgId )
900: {
901: case ataMessageResetStarted:
902: lock_init( resetSem, true, NULL, NULL );
903: IORWLockWrite( resetSem );
904: break;
905:
906: case ataMessageResetComplete:
907: IORWLockUnlock( resetSem );
908: break;
909:
910: default:
911: ;
912: }
913:
914: return kIOReturnSuccess;
915: }
916:
917: /*
918: *
919: *
920: */
921: UInt32 IOATADevice::getUnit()
922: {
923: return unit;
924: }
925:
926: /*
927: *
928: *
929: */
930: IOCommandQueue *IOATADevice::getDeviceQueue()
931: {
932: return deviceQueue;
933: }
934:
935:
936: /*
937: *
938: *
939: */
940: ATADeviceType IOATADevice::getDeviceType()
941: {
942: return deviceType;
943: }
944:
945: /*
946: *
947: *
948: */
949: bool IOATADevice::getATAPIPktInt()
950: {
951: return atapiPktInt;
952: }
953:
954: /*
955: *
956: *
957: */
958: bool IOATADevice::getIdentifyData( ATAIdentify *identifyBuffer )
959: {
960: if ( identifyData == NULL )
961: {
962: bzero( identifyBuffer, sizeof(ATAIdentify) );
963: return false;
964: }
965:
966: bcopy( identifyData, identifyBuffer, sizeof(ATAIdentify) );
967: return true;
968: }
969:
970: /*
971: *
972: *
973: */
974: bool IOATADevice::getInquiryData( UInt32 inquiryBufLength, ATAPIInquiry *inquiryBuffer )
975: {
976: bzero( inquiryBuffer, inquiryBufLength );
977:
978: if ( inquiryData == NULL )
979: {
980: return false;
981: }
982:
983: bcopy( inquiryData, inquiryBuffer, inquiryBufLength );
984:
985: return true;
986: }
987:
988: /*
989: *
990: *
991: */
992: bool IOATADevice::init( UInt32 unitNum, IOATAController *ctlr )
993: {
994: controller = ctlr;
995: unit = unitNum;
996:
997: if ( super::init() != true )
998: {
999: return false;
1000: }
1001:
1002: deviceQueue = controller->createDeviceQueue( this );
1003: if ( deviceQueue == NULL )
1004: {
1005: return false;
1006: }
1007:
1008: utilCmd = allocCommand();
1009: if ( utilCmd == NULL )
1010: {
1011: return false;
1012: }
1013:
1014: resetSem = IORWLockAlloc();
1015: if ( resetSem == NULL )
1016: {
1017: return false;
1018: }
1019:
1020: return true;
1021: }
1022:
1023:
1024: /*
1025: *
1026: *
1027: */
1028: OSDictionary *IOATADevice::createProperties()
1029: {
1030: OSDictionary *propTable = 0;
1031: OSObject *regObj;
1032: char tmpbuf[81];
1033: char *s, *d;
1034:
1035:
1036: propTable = OSDictionary::withCapacity(ATAMaxProperties);
1037: if ( propTable == NULL )
1038: {
1039: return NULL;
1040: }
1041:
1042: s = (deviceType == ataDeviceATA) ? ATAPropertyProtocolATA : ATAPropertyProtocolATAPI;
1043: regObj = (OSObject *)OSString::withCString( s );
1044: if ( addToRegistry( propTable, regObj, ATAPropertyProtocol ) != true )
1045: {
1046: goto createprop_error;
1047: }
1048:
1049: regObj = (OSObject *)OSNumber::withNumber(unit,32);
1050: if ( addToRegistry( propTable, regObj, ATAPropertyDeviceNumber ) != true )
1051: {
1052: goto createprop_error;
1053: }
1054:
1055: regObj = (OSObject *)OSNumber::withNumber(unit,32);
1056: if ( addToRegistry( propTable, regObj, ATAPropertyLocation ) != true )
1057: {
1058: goto createprop_error;
1059: }
1060:
1061: d = tmpbuf;
1062: stripBlanks( d, identifyData->modelNumber, sizeof(identifyData->modelNumber));
1063: regObj = (OSObject *)OSString::withCString( d );
1064: if ( addToRegistry( propTable, regObj, ATAPropertyModelNumber ) != true )
1065: {
1066: goto createprop_error;
1067: }
1068:
1069: d = tmpbuf;
1070: stripBlanks( d, identifyData->firmwareRevision, sizeof(identifyData->firmwareRevision));
1071: regObj = (OSObject *)OSString::withCString( d );
1072: if ( addToRegistry( propTable, regObj, ATAPropertyFirmwareRev ) != true )
1073: {
1074: goto createprop_error;
1075: }
1076:
1077: if ( inquiryData )
1078: {
1079: stripBlanks( d, inquiryData->vendorName, sizeof(inquiryData->vendorName) );
1080: regObj = (OSObject *)OSString::withCString( d );
1081: if ( addToRegistry( propTable, regObj, ATAPropertyVendorName ) != true )
1082: {
1083: goto createprop_error;
1084: }
1085:
1086: stripBlanks( d, inquiryData->productName, sizeof(inquiryData->productName) );
1087: regObj = (OSObject *)OSString::withCString( d );
1088: if ( addToRegistry( propTable, regObj, ATAPropertyProductName ) != true )
1089: {
1090: goto createprop_error;
1091: }
1092:
1093: stripBlanks( d, inquiryData->productRevision, sizeof(inquiryData->productRevision) );
1094: regObj = (OSObject *)OSString::withCString( d );
1095: if ( addToRegistry( propTable, regObj, ATAPropertyProductRevision ) != true )
1096: {
1097: goto createprop_error;
1098: }
1099: }
1100: return propTable;
1101:
1102: createprop_error: ;
1103: propTable->release();
1104: return NULL;
1105: }
1106:
1107: /*
1108: *
1109: *
1110: */
1111:
1112: bool IOATADevice::matchPropertyTable( OSDictionary * table )
1113: {
1114: return( controller->matchNubWithPropertyTable( this, table ));
1115: }
1116:
1117: IOService *IOATADevice::matchLocation( IOService * )
1118: {
1119: // IOLog( "IOATADevice::%s - called\n\r", __FUNCTION__ );
1120:
1121: return this;
1122: }
1123:
1124: /*
1125: *
1126: *
1127: */
1128: bool IOATADevice::open( IOService *customer )
1129: {
1130: bool rc;
1131:
1132: rc = super::open( customer );
1133:
1134: if ( rc == true )
1135: {
1136: client = customer;
1137: }
1138:
1139: return rc;
1140: }
1141:
1142:
1143: /*
1144: *
1145: *
1146: */
1147: void IOATADevice::close( IOService *customer )
1148: {
1149: super::close( customer );
1150: client = NULL;
1151: }
1152:
1153:
1154: /*
1155: *
1156: *
1157: */
1158: void IOATADevice::free()
1159: {
1160: if ( identifyData ) IOFree( identifyData, sizeof(*identifyData) );
1161: if ( inquiryData ) IOFree( inquiryData, sizeof(*inquiryData) );
1162: if ( utilCmd ) utilCmd->release();
1163: if ( reqSenseCmd ) reqSenseCmd->release();
1164: if ( deviceQueue ) deviceQueue->release();
1165: if ( resetSem ) IORWLockFree( resetSem );
1166:
1167: super::free();
1168: }
1169:
1170: /*
1171: *
1172: *
1173: */
1174: IOService *IOATADevice::getClient()
1175: {
1176: return client;
1177: }
1178:
1179:
1180: /*
1181: *
1182: *
1183: */
1184: IOATACommand *IOATADevice::allocCommand( UInt32 clientDataSize )
1185: {
1186: IOATACommand *cmd;
1187:
1188: if ( (cmd = controller->allocCommand( clientDataSize )) )
1189: {
1190: cmd->setDevice( this );
1191: }
1192: return cmd;
1193: }
1194:
1195: /*
1196: *
1197: *
1198: */
1199: bool IOATADevice::addToRegistry( OSDictionary *propTable, OSObject *regObj, char *key )
1200: {
1201: bool ret;
1202:
1203: if ( regObj == NULL )
1204: {
1205: return false;
1206: }
1207:
1208: ret = propTable->setObject( key, regObj );
1209:
1210: regObj->release();
1211:
1212: return ret;
1213: }
1214:
1215: /*
1216: *
1217: *
1218: */
1219: void IOATADevice::stripBlanks( char *d, char *s, UInt32 l )
1220: {
1221: char *p, c;
1222:
1223: for ( p = d, c = *s; l && c ; l--)
1224: {
1225: c = (*d++ = *s++);
1226: if ( c != ' ' )
1227: {
1228: p = d;
1229: }
1230: }
1231: *p = 0;
1232: }
1233:
1234:
1235: /*
1236: *
1237: *
1238: */
1239: void IOATADevice::endianConvertData( void *data, void *endianTable )
1240: {
1241: EndianTable *t;
1242:
1243: union EndianPtr
1244: {
1245: void *voidPtr;
1246: UInt8 *bytePtr;
1247: UInt16 *shortPtr;
1248: UInt32 *longPtr;
1249: UInt64 *longlongPtr;
1250: } p;
1251:
1252: UInt32 i,j;
1253:
1254: p.voidPtr = data;
1255:
1256: t = (EndianTable *)endianTable;
1257:
1258: for ( ; t->type; t++ )
1259: {
1260: i = t->size/t->type;
1261:
1262: switch ( t->type )
1263: {
1264:
1265: /* Note:
1266: *
1267: * The ATA standard defines identify strings as arrays of short ints,
1268: * with the left-most character of the string as the most significant
1269: * byte of the short int. Strings are not normally affected by the host
1270: * endianess. However, the way ATA defines strings would cause strings
1271: * to appear byte reversed. We do a manditory short int byte-swap here,
1272: * although strictly speaking this is not an endian issue.
1273: *
1274: */
1275: case sizeof(UInt8):
1276: for ( j = 0; j < i/2; j++ )
1277: {
1278: *p.shortPtr++ = OSSwapInt16(*p.shortPtr);
1279: }
1280:
1281: break;
1282:
1283: case sizeof(UInt16):
1284: for ( j = 0; j < i; j++ )
1285: {
1286: *p.shortPtr++ = OSSwapLittleToHostInt16(*p.shortPtr);
1287: }
1288: break;
1289:
1290: case sizeof(UInt32):
1291: for ( j = 0; j < i; j++ )
1292: {
1293: *p.longPtr++ = OSSwapLittleToHostInt32(*p.longPtr);
1294: }
1295: break;
1296:
1297: case sizeof(UInt64):
1298: for ( j = 0; j < i; j++ )
1299: {
1300: *p.longlongPtr++ = OSSwapLittleToHostInt64(*p.longlongPtr);
1301: }
1302: break;
1303:
1304: default:
1305: ;
1306: }
1307: }
1308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.