|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: // Copyright 1997 by Apple Computer, Inc., all rights reserved.
26: /*
27: * Copyright (c) 1994-1997 NeXT Software, Inc. All rights reserved.
28: *
29: * IdeCntInit.m - ATA controller initialization module.
30: *
31: */
32:
33: #import <driverkit/kernelDriver.h>
34: #import <driverkit/interruptMsg.h>
35: #import <mach/mach_interface.h>
36: #import <driverkit/IODevice.h>
37: #import <driverkit/ppc/IOTreeDevice.h>
38: #import <driverkit/ppc/IODBDMA.h>
39: #import <driverkit/align.h>
40: #import <machkit/NXLock.h>
41: #import "IdeDDM.h"
42: #import "io_inline.h"
43: #import <driverkit/return.h>
44: #import <mach/port.h>
45: #import <machdep/ppc/powermac.h>
46: #import <bsd/sys/systm.h>
47:
48: #import "IdeCnt.h"
49: #import "IdeCntInit.h"
50: #import "IdeCntCmds.h"
51: #import "IdeCntDma.h"
52: #import "AtapiCntCmds.h"
53:
54:
55: #define IDE_SYSCLK_NS 30
56:
57: typedef struct
58: {
59: int accessTime;
60: int cycleTime;
61: } ideModes_t;
62:
63: static ideModes_t pioModes[] =
64: {
65: { 165, 600 }, /* Mode 0 */
66: { 125, 383 }, /* 1 */
67: { 100, 240 }, /* 2 */
68: { 80, 180 }, /* 3 */
69: { 70, 120 } /* 4 */
70: };
71: #define MAX_PIO_MODES (sizeof(pioModes) / sizeof(ideModes_t))
72:
73: static ideModes_t singleWordModes[] =
74: {
75: { 480, 960 }, /* Mode 0 */
76: { 100, 480 }, /* 1 */
77: { 120, 240 } /* 2 */
78: };
79: #define MAX_SINGLEWORD_MODES (sizeof(singleWordModes) / sizeof(ideModes_t))
80:
81: static ideModes_t multiWordModes[] =
82: {
83: { 215, 480 }, /* Mode 0 */
84: { 80, 150 }, /* 1 */
85: { 70, 120 } /* 2 */
86: };
87: #define MAX_MULTIWORD_MODES (sizeof(multiWordModes) / sizeof(ideModes_t))
88:
89:
90: static ideModes_t ultraModes[] =
91: {
92: { 0, 114 }, /* Mode 0 */
93: { 0, 75 }, /* 1 */
94: { 0, 55 } /* 2 */
95: };
96:
97: #define MAX_ULTRA_MODES (sizeof(ultraModes) / sizeof(ideModes_t))
98:
99:
100: static void endianSwap16Bit( volatile u_int16_t *p16 )
101: {
102: u_int16_t tmp16;
103:
104: tmp16 = *p16;
105: tmp16 = (tmp16 >> 8) | (tmp16 << 8);
106: *p16 = tmp16;
107: }
108:
109: static void endianSwap32Bit( volatile u_int32_t *p32 )
110: {
111: u_int32_t tmp32;
112:
113: tmp32 = *p32;
114:
115: tmp32 = ( ((tmp32 & 0x000000ff) << 24)
116: | ((tmp32 & 0x0000ff00) << 8)
117: | ((tmp32 & 0x00ff0000) >> 8)
118: | ((tmp32 & 0xff000000) >> 24) );
119:
120: *p32 = tmp32;
121: }
122:
123: static int rnddiv( int x, int y )
124: {
125: if ( x < 0 )
126: return 0;
127: else
128: return ( (x / y) + (( x % y ) ? 1 : 0) );
129: }
130:
131: @implementation IdeController(Initialize)
132:
133:
134: /*
135: * Check for MediaBay
136: *
137: * Returns: NO - MediaBay implementation with non-ATA/ATAPI option installed
138: * YES - Non-MediaBay implementation or MediaBay with ATA/ATAPI option
139: */
140: - (BOOL) checkMediaBayOption: (IOTreeDevice *)deviceDescription
141: {
142: int n;
143: u_int32_t *heathrowIdReg;
144: u_int32_t heathrowIds;
145: IOTreeDevice *devDescParent;
146: char *nodeNameParent;
147:
148: /*
149: * Check for MediaBay implementation
150: */
151: devDescParent = [[deviceDescription parent] deviceDescription];
152: nodeNameParent = [devDescParent nodeName];
153:
154: if ( strcmp( nodeNameParent, "media-bay" ) )
155: {
156: return YES; /* Non-MediaBay implementation */
157: }
158: if ( (n = [devDescParent numMemoryRanges]) < 1 )
159: {
160: return YES; /* Misc OF Device Tree problem */
161: }
162:
163: /*
164: * Check for ATA/ATAPI MediaBay option installed
165: */
166: heathrowIdReg = (u_int32_t *)[devDescParent memoryRangeList][0].start;
167: heathrowIds = *heathrowIdReg;
168: endianSwap32Bit( &heathrowIds );
169:
170: if ( (heathrowIds & MEDIA_BAY_ID_MASK) == MEDIA_BAY_ID_CDROM )
171: {
172: return YES; /* Media Bay with ATA/ATAPI option */
173: }
174:
175: return NO;
176: }
177:
178: #define ATAPI_SIGNATURE_LOW 0x14
179: #define ATAPI_SIGNATURE_HIGH 0xeb
180:
181: #define ATA_SIGNATURE_LOW 0x00
182: #define ATA_SIGNATURE_HIGH 0x00
183:
184: /*
185: * This is called just after resetting the drives connected to this
186: * controller. We read the drive registers to figure out if it is an ATAPI
187: * drive. If it is then we make a note of it and return YES.
188: */
189: - (BOOL)controllerPresent
190: {
191: unsigned char dh;
192: unsigned char unit;
193:
194: unit = 0;
195:
196: dh = _addressMode[unit];
197:
198: dh |= (unit ? SEL_DRIVE1 : SEL_DRIVE0);
199: outb(_ideRegsAddrs.drHead, dh);
200:
201: /*
202: * Test with some data.
203: */
204:
205: if (unit == 0)
206: {
207: outb(_ideRegsAddrs.cylLow, 0xaa);
208: outb(_ideRegsAddrs.cylHigh, 0xbb);
209: }
210: else
211: {
212: outb(_ideRegsAddrs.cylLow, 0xba);
213: outb(_ideRegsAddrs.cylHigh, 0xbe);
214: }
215:
216: if (unit == 0)
217: {
218: if ((inb(_ideRegsAddrs.cylLow) != 0xaa) ||
219: (inb(_ideRegsAddrs.cylHigh) != 0xbb))
220: {
221: return NO;
222: }
223: }
224: else
225: {
226: if ((inb(_ideRegsAddrs.cylLow) != 0xba) ||
227: (inb(_ideRegsAddrs.cylHigh) != 0xbe))
228: {
229: return NO;
230: }
231: }
232:
233: return YES;
234: }
235:
236:
237: /*
238: * One-time only init. Returns NO on failure.
239: */
240: - (BOOL)ideControllerInit:(IOTreeDevice *)deviceDescription
241: {
242: int unit;
243: int drivesPresent = 0;
244: ns_time_t time, startTime;
245:
246: if ([self enableInterrupt:0]) {
247: IOLog("ideControllerInit: failed enableAllInterrupts\n");
248: return NO;
249: }
250:
251:
252: if ((_ideCmdLock = [NXLock new]) == NULL) {
253: IOLog("ideControllerInit: failed _ideCmdLock\n");
254: return NO;
255: }
256:
257: /*
258: * We don't want to execute any IDE commands from Disk until
259: * initialization is complete.
260: */
261: [self ideCntrlrLock];
262:
263: /*
264: * Initialize the register address values.
265: */
266: [self assignRegisterAddresses: deviceDescription];
267:
268: for (unit = 0; unit < MAX_IDE_DRIVES; unit++) {
269: _atapiDevice[unit] = NO;
270: }
271:
272: /*
273: * We have to test here if the controller is present or else we will
274: * block looking for a drive (in ideReset).
275: */
276:
277: if ([self controllerPresent] == NO)
278: {
279: IOLog("%s: no devices detected at port 0x%0x\n", [self name],
280: _ideRegsAddrs.data);
281: [self ideCntrlrUnLock];
282: return NO;
283: }
284: else
285: {
286: IOLog("%s: device detected at port 0x%x irq %d\n", [self name],
287: _ideRegsAddrs.data, [deviceDescription interrupt]);
288: }
289:
290: _ideInterruptPort = [self interruptPort];
291: _ideDevicePort = [deviceDescription devicePort];
292:
293: [self setInterruptTimeOut:IDE_INTR_TIMEOUT];
294:
295: _multiSectorRequested = YES;
296:
297: for (unit = 0; unit < MAX_IDE_DRIVES; unit++)
298: {
299: _addressMode[unit] = ADDRESS_MODE_LBA;
300: }
301:
302: _driveNum = unit;
303:
304: for (unit = 0; unit < MAX_IDE_DRIVES; unit++)
305: {
306:
307: bzero(&_ideInfo[unit], sizeof(ideDriveInfo_t));
308:
309: [self ideReset];
310:
311: IOGetTimestamp(&startTime);
312: if ([self ideDetectDrive:unit] == YES)
313: {
314: _ideInfo[unit].type = 255;
315: }
316: IOGetTimestamp(&time);
317: time = (time - startTime) / (1000*1000);
318: kprintf( "Disk(ata) - ideDetectDrive:%d - %d ms\n\r", unit, (u_int32_t)time );
319:
320: /*
321: * If we didn't find ATA drive then look for ATAPI device.
322: */
323: if ((_ideInfo[unit].type == 0) && ([self ideDetectATAPIDevice:unit] == YES))
324: {
325: _ideInfo[unit].type = 127;
326: }
327:
328: if (_ideInfo[unit].type != 0)
329: drivesPresent += 1 ;
330: }
331:
332: if (drivesPresent == 0)
333: {
334: [self ideCntrlrUnLock];
335: IOLog("ideControllerInit: failed drivesPresent\n");
336: return NO;
337: }
338:
339: /*
340: * Initialization was successful. We should release the lock so that the
341: * controller can now execute commands from disk objects.
342: */
343:
344: [self resetAndInit];
345:
346: /*
347: * Set drive power state to active.
348: */
349: for (unit = 0; unit < MAX_IDE_DRIVES; unit++)
350: {
351: if (_ideInfo[unit].type != 0)
352: [self setDrivePowerState:IDE_PM_ACTIVE];
353: }
354:
355: _driveSleepRequest = NO;
356:
357: [self enableInterrupts];
358:
359: [self ideCntrlrUnLock];
360:
361: return YES;
362: }
363:
364: #define ATA_RESET_DELAY (30 * 1000) /* milliseconds */
365:
366: /*
367: * Determine the presence and type of drive (IDE/ATAPI) attached to this
368: * controller.
369: *
370: */
371:
372: -(BOOL)ideDetectDrive:(unsigned int)unit
373: {
374: unsigned char dh = _addressMode[unit];
375: int i;
376: unsigned char status;
377: BOOL found = NO;
378:
379: [self disableInterrupts];
380:
381: dh |= (unit ? SEL_DRIVE1 : SEL_DRIVE0);
382: outb(_ideRegsAddrs.drHead, dh);
383: IODelay(10);
384:
385: status = inb(_ideRegsAddrs.status);
386: if ( !(status & READY) )
387: {
388: return found;
389: }
390:
391: outb(_ideRegsAddrs.command, IDE_IDENTIFY_DRIVE);
392:
393: for (i = 0; i < (ATA_RESET_DELAY * 5); i++)
394: {
395: IODelay(200);
396: status = inb(_ideRegsAddrs.status);
397:
398: if ((!(status & BUSY)) && (status & (ERROR | WRITE_FAULT | ERROR_CORRECTED)) )
399: {
400: break; /* certain failure */
401: }
402:
403: if ((!(status & BUSY)) && (status & DREQUEST))
404: {
405: found = YES; /* success */
406: break;
407: }
408: }
409:
410: return found;
411: }
412:
413: /*
414: * We send the device ATAPI soft reset command and check for signature. This
415: * is the first command that ATAPI devices need.
416: */
417: -(BOOL)ideDetectATAPIDevice:(unsigned int)unit
418: {
419: unsigned char low, high;
420: BOOL found = NO;
421:
422: [self atapiSoftReset:unit];
423:
424: low = inb(_ideRegsAddrs.cylLow);
425: high = inb(_ideRegsAddrs.cylHigh);
426:
427: if ((low == ATAPI_SIGNATURE_LOW) && (high == ATAPI_SIGNATURE_HIGH))
428: {
429: _atapiDevice[unit] = YES;
430: IOLog("%s: ATAPI device %d detected.\n", [self name], unit);
431: found = YES;
432: }
433: /*
434: * Clear ATAPI signature
435: */
436: outb(_ideRegsAddrs.cylLow, 0 );
437: outb(_ideRegsAddrs.cylHigh, 0 );
438:
439: return found;
440: }
441:
442:
443: -(ideDriveInfo_t *)getIdeDriveInfo:(unsigned int)unit
444: {
445: return &_ideInfo[unit];
446: }
447:
448: #define MAX_RESET_ATTEMPTS 2
449:
450: - (void)ideReset
451: {
452: int count;
453: int delay;
454: unsigned char status;
455:
456: for ( count = 0; count < MAX_IDE_DRIVES; count++ )
457: {
458: _driveReset[count] = YES;
459: }
460:
461: for (count = 0; count < MAX_RESET_ATTEMPTS; count++)
462: {
463: outb(_ideRegsAddrs.deviceControl, DISK_RESET_ENABLE);
464: IODelay(100); /* spec >= 25 us */
465: outb(_ideRegsAddrs.deviceControl, 0x0);
466:
467: [self enableInterrupts];
468:
469: delay = 31 * 1000 * 1000; /* thirty one seconds */
470:
471: IOSleep(1000); /* Enough time to assert busy */
472:
473: while (delay > 0)
474: {
475: status = inb(_ideRegsAddrs.status);
476: if (!(status & BUSY))
477: {
478: return;
479: }
480:
481: IOSleep(1);
482: delay -= 1000;
483: }
484:
485: IOLog("%s: Reset failed, retrying..\n", [self name]);
486: IOSleep(2000);
487: }
488: }
489:
490:
491: /*
492: * Initialize the IDE interface. Find about drive capabilities (by
493: * IDE_IDENTIFY_DRIVE command) and configure drive.
494: *
495: * By the time we enter this routine we know about all devices connected to this controller.
496: */
497: - (void)resetAndInit
498: {
499: int i;
500: unsigned char unit;
501: ide_return_t rtn;
502: atapi_return_t atapi_rtn;
503: BOOL ataDevicePresent;
504:
505: /*
506: * If there is at least one ATA drive connected to this controller then
507: * is is not necessary to (ATA style) reset them. We use the ATAPI reset
508: * instead.
509: */
510: ataDevicePresent = NO;
511: for (i = 0; i < MAX_IDE_DRIVES; i++)
512: {
513: if ((_ideInfo[i].type != 0) && ([self isAtapiDevice:i] == NO))
514: {
515: ataDevicePresent = YES;
516: break;
517: }
518: }
519:
520: if (ataDevicePresent == YES)
521: {
522: [self ideReset];
523: }
524:
525: /*
526: * Send the controller necessary commands to set capabilities and then
527: * set drive parameters. It is necessary to set drive parameters before
528: * any data I/O can be done from the disk.
529: */
530: for (unit = 0; unit < MAX_IDE_DRIVES; unit++)
531: {
532: if (_ideInfo[unit].type == 0)
533: {
534: continue;
535: }
536:
537: _driveNum = unit;
538:
539: _cycleTimes[unit].pioMode = 0;
540: _cycleTimes[unit].pioAccessTime = pioModes[0].accessTime;
541: _cycleTimes[unit].pioCycleTime = pioModes[0].cycleTime;
542:
543: [self calcIdeConfig: unit];
544:
545: if ( [self isAtapiDevice:unit] == YES )
546: {
547: [self atapiSoftReset:unit];
548:
549: /*
550: * We have to do this test because of "task file shadow" bug
551: * present in many ATAPI CD-ROMs.
552: */
553: atapi_rtn =
554: [self atapiIdentifyDevice:(struct vm_map *)IOVmTaskSelf()
555: addr:(unsigned char *)&_ideIdentifyInfo[unit] unit:unit];
556:
557: /* Too bad.. */
558: if (atapi_rtn != IDER_SUCCESS)
559: {
560: _atapiDevice[unit] = NO;
561: _ideInfo[unit].type = 0;
562: continue;
563: }
564:
565: [self endianSwapIdentifyData: &_ideIdentifyInfo[unit]];
566:
567: [self printAtapiInfo:&_ideIdentifyInfo[unit] Device:unit];
568: [self atapiInitParameters:&_ideIdentifyInfo[unit] Device:unit];
569: continue;
570: }
571:
572: rtn = [self setATADriveCapabilities:unit];
573: if (rtn != IDER_SUCCESS)
574: {
575: _ideInfo[unit].type = 0;
576: continue;
577: }
578: }
579: }
580:
581: /*
582: * FIXME: Need to figure out multi-word DMA.
583: */
584: - (ide_return_t)getTransferModes:(ideIdentifyInfo_t *)infoPtr Unit: (int)unit
585: {
586: int i, n;
587:
588: int pioMode = 0;
589: int pioCycleTime = 0;
590: int dmaMode = 0;
591: int dmaType = IDE_DMA_NONE;
592: int dmaCycleTime = 0;
593:
594: /*
595: * PIO Cycle timing......
596: *
597: * 1. Try to match Word 51 (pioCycleTime) with cycle timings
598: * in our pioModes table to get mode/CycleTime. (Valid for Modes 0-2)
599: * 2. If Words 64-68 are supported and Mode 3 or 4 supported check,
600: * update CycleTime with Word 68 (CycleTimeWithIORDY).
601: */
602:
603: pioCycleTime = infoPtr->pioDataTransferCyleTimingMode;
604:
605: if ( pioCycleTime > 2 )
606: {
607: for ( i=MAX_PIO_MODES-1; i != -1; i-- )
608: {
609: if ( pioCycleTime <= pioModes[i].cycleTime )
610: {
611: pioMode = i;
612: break;
613: }
614: }
615:
616: if ( i == -1 )
617: {
618: pioCycleTime = pioModes[pioMode].cycleTime;
619: }
620: }
621: else
622: {
623: pioMode = pioCycleTime;
624: pioCycleTime = pioModes[pioMode].cycleTime;
625: }
626:
627: if (infoPtr->fieldValidity & IDE_WORDS64_TO_68_SUPPORTED)
628: {
629: if (infoPtr->fcPioDataTransferCyleTimingMode & IDE_FC_PIO_MODE_4_SUPPORTED)
630: pioMode = 4;
631: else if (infoPtr->fcPioDataTransferCyleTimingMode & IDE_FC_PIO_MODE_3_SUPPORTED)
632: pioMode = 3;
633:
634: if ( (pioMode >= 3) && infoPtr->MinPIOTransferCycleTimeWithIORDY )
635: {
636: pioCycleTime = infoPtr->MinPIOTransferCycleTimeWithIORDY;
637: }
638: }
639:
640: /*
641: * Ultra DMA timing.....
642: *
643: */
644: if ( (_controllerType == kControllerTypeCmd646X) && (infoPtr->fieldValidity & IDE_WORD_88_SUPPORTED) )
645: {
646: n = infoPtr->ultraDma & IDE_ULTRA_DMA_SUPPORTED;
647: if ( n )
648: {
649: dmaType = IDE_DMA_ULTRA;
650: for ( i=0; n; i++, n>>=1 )
651: ;
652:
653: dmaMode = i - 1;
654: if ( dmaMode > MAX_ULTRA_MODES-1 )
655: {
656: dmaMode = MAX_ULTRA_MODES-1;
657: }
658: dmaCycleTime = ultraModes[dmaMode].cycleTime;
659:
660: goto getCycleTimes_exit;
661: }
662: }
663:
664: /*
665: * Multiword DMA timing.....
666: *
667: * 1. Check Word 63(7:0) (Multiword DMA Modes Supported). Lookup
668: * CycleTime for highest mode we support.
669: * 2. If Words 64-68 supported, update CycleTime from Word 66
670: * (RecommendedMultiWordCycleTime) if specified.
671: */
672:
673: n = infoPtr->mwDma & IDE_MW_DMA_SUPPORTED;
674: if ( n )
675: {
676: dmaType = IDE_DMA_MULTIWORD;
677: for ( i=0; n; i++, n>>=1 )
678: ;
679:
680: dmaMode = i - 1;
681: if ( dmaMode > MAX_MULTIWORD_MODES-1 )
682: {
683: dmaMode = MAX_MULTIWORD_MODES-1;
684: }
685: dmaCycleTime = multiWordModes[dmaMode].cycleTime;
686:
687: if (infoPtr->fieldValidity & IDE_WORDS64_TO_68_SUPPORTED)
688: {
689: if ( infoPtr->RecommendedMwDMACycleTime )
690: {
691: dmaCycleTime = infoPtr->RecommendedMwDMACycleTime;
692: }
693: }
694: goto getCycleTimes_exit;
695: }
696:
697: /*
698: * Single Word DMA timing.....
699: *
700: * 1. If Word 64(7:0) (SingleWord DMA Modes supported) is non-zero,
701: * find highest supported mode and get CycleTime from table.
702: * 2. If Word 64(7:0) (SingleWord DMA Modes supported) is zero,
703: * then match Word 52 (Single Word DMA Cycle Time) against
704: * cycle times in singleWordModes table.
705: */
706:
707: n = infoPtr->swDma & IDE_SW_DMA_SUPPORTED;
708: if ( n )
709: {
710: dmaType = IDE_DMA_SINGLEWORD;
711: for ( i=0; n; i++, n>>=1 )
712: ;
713:
714: dmaMode = i - 1;
715: if ( dmaMode > MAX_SINGLEWORD_MODES-1 )
716: {
717: dmaMode = MAX_SINGLEWORD_MODES-1;
718: }
719: dmaCycleTime = singleWordModes[dmaMode].cycleTime;
720: }
721: else
722: {
723: dmaCycleTime = infoPtr->dmaDataTransferCyleTimingMode;
724: for ( i=MAX_SINGLEWORD_MODES-1; i != -1; i-- )
725: {
726: if ( dmaCycleTime <= singleWordModes[i].cycleTime )
727: {
728: dmaType = IDE_DMA_SINGLEWORD;
729: dmaMode = i;
730: dmaCycleTime = singleWordModes[i].cycleTime;
731: break;
732: }
733: }
734: }
735:
736:
737: getCycleTimes_exit: ;
738:
739: _cycleTimes[unit].pioCycleTime = pioCycleTime;
740: _cycleTimes[unit].pioAccessTime = pioModes[pioMode].accessTime;
741: _cycleTimes[unit].pioMode = pioMode;
742:
743: if ( dmaType != IDE_DMA_NONE )
744: {
745: _cycleTimes[unit].dmaType = dmaType;
746: _cycleTimes[unit].dmaMode = dmaMode;
747: _cycleTimes[unit].dmaCycleTime = dmaCycleTime;
748: switch ( dmaMode )
749: {
750: case IDE_DMA_SINGLEWORD:
751: _cycleTimes[unit].dmaAccessTime = singleWordModes[dmaMode].accessTime;
752: break;
753: case IDE_DMA_MULTIWORD:
754: _cycleTimes[unit].dmaAccessTime = multiWordModes[dmaMode].accessTime;
755: break;
756: case IDE_DMA_ULTRA:
757: _cycleTimes[unit].dmaAccessTime = ultraModes[dmaMode].accessTime;
758: break;
759: }
760: }
761:
762: [self calcIdeConfig: (int)unit];
763:
764:
765: return IDER_SUCCESS;
766: }
767:
768: -(void) calcIdeConfig:(int)unit
769: {
770: _cycleTimes[unit].fChanged = YES;
771:
772: if ( _controllerType == kControllerTypeCmd646X )
773: {
774: [self calcIdeTimingsCmd646X:unit];
775: }
776: else
777: {
778: [self calcIdeTimingsDBDMA:unit];
779: }
780: }
781:
782: -(void) calcIdeTimingsCmd646X:(int) unit
783: {
784: u_int32_t cycleClks;
785: u_int32_t cycleTime, accessTime;
786: u_int32_t drwActClks, drwRecClks;
787: u_int32_t drwActTime, drwRecTime;
788:
789: _cycleTimes[unit].ideConfig.cmd646XConfig.arttimReg = 0x40;
790: _cycleTimes[unit].ideConfig.cmd646XConfig.cmdtimReg = 0xA9;
791:
792: accessTime = pioModes[_cycleTimes[unit].pioMode].accessTime;
793:
794: drwActClks = accessTime / IDE_SYSCLK_NS;
795: drwActClks += (accessTime % IDE_SYSCLK_NS) ? 1 : 0;
796: drwActTime = drwActClks * IDE_SYSCLK_NS;
797:
798: drwRecTime = pioModes[_cycleTimes[unit].pioMode].cycleTime - drwActTime;
799: drwRecClks = drwRecTime / IDE_SYSCLK_NS;
800: drwRecClks += (drwRecTime % IDE_SYSCLK_NS) ? 1 : 0;
801:
802: if ( drwRecClks >= 16 )
803: drwRecClks = 1;
804: else if ( drwRecClks <= 1 )
805: drwRecClks = 16;
806:
807: _cycleTimes[unit].ideConfig.cmd646XConfig.drwtimRegPIO = ((drwActClks & 0x0f) << 4) | ((drwRecClks-1) & 0x0f);
808:
809:
810: _cycleTimes[unit].ideConfig.cmd646XConfig.udidetcrReg = 0;
811:
812: if ( _cycleTimes[unit].dmaType == IDE_DMA_ULTRA )
813: {
814: cycleTime = _cycleTimes[unit].dmaCycleTime;
815:
816: cycleClks = cycleTime / IDE_SYSCLK_NS;
817: cycleClks += (cycleTime % IDE_SYSCLK_NS) ? 1 : 0;
818:
819: _cycleTimes[unit].ideConfig.cmd646XConfig.udidetcrReg = (0x01 << unit) | ((cycleClks-1) << ((!unit) ? 4 : 6)) ;
820: }
821: else if ( _cycleTimes[unit].dmaType != IDE_DMA_NONE )
822: {
823: accessTime = _cycleTimes[unit].dmaAccessTime;
824:
825: drwActClks = accessTime / IDE_SYSCLK_NS;
826: drwActClks += (accessTime % IDE_SYSCLK_NS) ? 1 : 0;
827: drwActTime = drwActClks * IDE_SYSCLK_NS;
828:
829: drwRecTime = _cycleTimes[unit].dmaCycleTime - drwActTime;
830: drwRecClks = drwRecTime / IDE_SYSCLK_NS;
831: drwRecClks += (drwRecTime % IDE_SYSCLK_NS) ? 1 : 0;
832:
833: if ( drwRecClks >= 16 )
834: drwRecClks = 1;
835: else if ( drwRecClks <= 1 )
836: drwRecClks = 16;
837:
838: _cycleTimes[0].ideConfig.cmd646XConfig.drwtimRegDMA = ((drwActClks & 0x0f) << 4) | ((drwRecClks-1) & 0x0f);
839: }
840: }
841:
842:
843:
844: -(void) calcIdeTimingsDBDMA:(int) unit
845: {
846: int accessTime;
847: int accessTicks;
848: int recTime;
849: int recTicks;
850: int cycleTime;
851: int cycleTimeOrig;
852: int halfTick = 0;
853: uint ideConfigWord = 0;
854:
855: /*
856: * Calc PIO access time >= pioAccessTime in SYSCLK increments
857: */
858: accessTicks = rnddiv(_cycleTimes[unit].pioAccessTime, IDE_SYSCLK_NS);
859: /*
860: * Hardware limits access times to >= 120 ns
861: */
862: accessTicks -= IDE_PIO_ACCESS_BASE;
863: if (accessTicks < IDE_PIO_ACCESS_MIN )
864: {
865: accessTicks = IDE_PIO_ACCESS_MIN;
866: }
867: accessTime = (accessTicks + IDE_PIO_ACCESS_BASE) * IDE_SYSCLK_NS;
868:
869: /*
870: * Calc recovery time in SYSCLK increments based on time remaining in cycle
871: */
872: recTime = _cycleTimes[unit].pioCycleTime - accessTime;
873: recTicks = rnddiv( recTime, IDE_SYSCLK_NS );
874: /*
875: * Hardware limits recovery time to >= 150ns
876: */
877: recTicks -= IDE_PIO_RECOVERY_BASE;
878: if ( recTicks < IDE_PIO_RECOVERY_MIN )
879: {
880: recTicks = IDE_PIO_RECOVERY_MIN;
881: }
882:
883: cycleTime = (recTicks + IDE_PIO_RECOVERY_BASE + accessTicks + IDE_PIO_ACCESS_BASE) * IDE_SYSCLK_NS;
884:
885: ideConfigWord = accessTicks | (recTicks << 5);
886:
887: kprintf("Disk(ata): Controller Base = %08x\n\r", _ideRegsAddrs.data );
888: kprintf("Disk(ata): Unit %1d: PIO Requested Timings: Access: %3dns Cycle: %3dns \n\r",
889: unit, _cycleTimes[unit].pioAccessTime, _cycleTimes[unit].pioCycleTime);
890: kprintf("Disk(ata): PIO Actual Timings: Access: %3dns Cycle: %3dns\n\r",
891: accessTime, cycleTime );
892:
893: if ( _cycleTimes[unit].dmaType == IDE_DMA_NONE )
894: {
895: goto calcConfigWordDone;
896: }
897:
898: /*
899: * Calc DMA access time >= dmaAccessTime in SYSCLK increments
900: */
901:
902: /*
903: * OHare II erata - Cant handle write cycle times below 150ns
904: */
905: cycleTimeOrig = _cycleTimes[unit].dmaCycleTime;
906: if ( IsPowerStar() )
907: {
908: if ( cycleTimeOrig < 150 ) _cycleTimes[unit].dmaCycleTime = 150;
909: }
910:
911: accessTicks = rnddiv(_cycleTimes[unit].dmaAccessTime, IDE_SYSCLK_NS);
912:
913: accessTicks -= IDE_DMA_ACCESS_BASE;
914: if ( accessTicks < IDE_DMA_ACCESS_MIN )
915: {
916: accessTicks = IDE_DMA_ACCESS_MIN;
917: }
918: accessTime = (accessTicks + IDE_DMA_ACCESS_BASE) * IDE_SYSCLK_NS;
919:
920: /*
921: * Calc recovery time in SYSCLK increments based on time remaining in cycle
922: */
923: recTime = _cycleTimes[unit].dmaCycleTime - accessTime;
924: recTicks = rnddiv( recTime, IDE_SYSCLK_NS );
925:
926: recTicks -= IDE_DMA_RECOVERY_BASE;
927: if ( recTicks < IDE_DMA_RECOVERY_MIN )
928: {
929: recTicks = IDE_DMA_RECOVERY_MIN;
930: }
931: cycleTime = (recTicks + IDE_DMA_RECOVERY_BASE + accessTicks + IDE_DMA_ACCESS_BASE) * IDE_SYSCLK_NS;
932:
933: /*
934: * If our calculated access time is at least SYSCLK/2 > than what the disk requires,
935: * see if selecting the 1/2 Clock option will help. This adds SYSCLK/2 to
936: * the access time and subtracts SYSCLK/2 from the recovery time.
937: *
938: * By setting the H-bit and subtracting one from the current access tick count,
939: * we are reducing the current access time by SYSCLK/2 and the current recovery
940: * time by SYSCLK/2. Now, check if the new cycle time still meets the disk's requirements.
941: */
942: if ( (accessTicks > IDE_DMA_ACCESS_MIN) && ((accessTime - IDE_SYSCLK_NS/2) >= _cycleTimes[unit].dmaAccessTime) )
943: {
944: if ( (cycleTime - IDE_SYSCLK_NS) >= _cycleTimes[unit].dmaCycleTime )
945: {
946: halfTick = 1;
947: accessTicks--;
948: accessTime -= IDE_SYSCLK_NS/2;
949: cycleTime -= IDE_SYSCLK_NS;
950: }
951: }
952:
953: ideConfigWord |= (accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
954:
955: kprintf("Disk(ata): DMA Requested Timings: Access: %3dns Cycle: %3dns \n\r",
956: _cycleTimes[unit].dmaAccessTime, cycleTimeOrig);
957: kprintf("Disk(ata): DMA Actual Timings: Access: %3dns Cycle: %3dns\n\r",
958: accessTime, cycleTime );
959:
960: calcConfigWordDone: ;
961: endianSwap32Bit( &ideConfigWord );
962: _cycleTimes[unit].ideConfig.dbdmaConfig = ideConfigWord;
963:
964: }
965:
966:
967: /*
968: * Send the Set Parameters command to the drive and set multi-sector mode
969: * etc. if the drive supports them. If biosInfo is YES, then we are using
970: * drive geometry information from the BIOS else we use Identify command to
971: * get this.
972: */
973: - (ide_return_t)setATADriveCapabilities:(unsigned int)unit
974: {
975: ideRegsVal_t ideRegs;
976: unsigned char nSectors;
977: char *buf;
978:
979: ideIdentifyInfo_t *infoPtr = &_ideIdentifyInfo[unit];
980:
981:
982: _multiSector[unit] = 0;
983: _dmaSupported[unit] = NO;
984:
985: _ideIdentifyInfoSupported[unit] = YES;
986: bzero(infoPtr, sizeof(ideIdentifyInfo_t));
987:
988: /*
989: * Remember this command is optional. Failure means that either this
990: * command is not supported or the drive is not present.
991: */
992: _driveNum = unit;
993:
994: [self setTransferRate: _driveNum UseDMA:NO];
995:
996: if ([self ideReadGetInfoCommon:&ideRegs
997: client:(struct vm_map *)IOVmTaskSelf()
998: addr:(unsigned char *)infoPtr
999: command:IDE_IDENTIFY_DRIVE] != IDER_SUCCESS)
1000: {
1001: _ideIdentifyInfoSupported[unit] = NO;
1002: [self ideReset]; /* necessary */
1003: return IDER_CMD_ERROR;
1004: }
1005:
1006: [self endianSwapIdentifyData: infoPtr];
1007:
1008: /*
1009: * Fill in this struct similar to which we would have gotten from CMOS.
1010: */
1011: _ideInfo[unit].cylinders = _ideIdentifyInfo[unit].cylinders;
1012: _ideInfo[unit].heads = _ideIdentifyInfo[unit].heads;
1013: _ideInfo[unit].control_byte = 0;
1014: _ideInfo[unit].landing_zone = 0;
1015: _ideInfo[unit].sectors_per_trk = _ideIdentifyInfo[unit].sectorsPerTrack;
1016: _ideInfo[unit].bytes_per_sector = IDE_SECTOR_SIZE;
1017:
1018: if ( infoPtr->capabilities & IDE_CAP_LBA_SUPPORTED)
1019: {
1020: _ideInfo[unit].total_sectors = infoPtr->userAddressableSectors;
1021: }
1022: else
1023: {
1024: _ideInfo[unit].total_sectors = _ideInfo[unit].sectors_per_trk
1025: * _ideInfo[unit].heads
1026: * _ideInfo[unit].cylinders;
1027: }
1028:
1029: /*
1030: * Set address mode. The only case in which we need to override user
1031: * selection if the user chooses LBA and the drive supports only CHS.
1032: */
1033: if ((infoPtr->capabilities & IDE_CAP_LBA_SUPPORTED) == 0x0)
1034: {
1035: _addressMode[unit] = ADDRESS_MODE_CHS;
1036: }
1037:
1038: /*
1039: * Set disk parameters.
1040: */
1041: [self ideSetParams:_ideInfo[unit].sectors_per_trk
1042: numHeads:_ideInfo[unit].heads ForDrive:unit];
1043:
1044: /*
1045: * Decide how are we going to do data transfers. Is DMA supported?
1046: * Multisector support? Verify that the data transfer mode really works
1047: * by doing a read operation in that mode.
1048: */
1049: [self getTransferModes:infoPtr Unit:unit];
1050:
1051: /*
1052: * Set the Disk/CDROM transfer mode (Set Features SC=3)
1053: */
1054: [self setTransferMode: unit];
1055:
1056: if (infoPtr->capabilities & IDE_CAP_DMA_SUPPORTED)
1057: {
1058: if ( [self allocDmaMemory] == IDER_SUCCESS )
1059: {
1060: _dmaSupported[unit] = YES;
1061: [self initIdeDma: unit];
1062: }
1063: }
1064:
1065: /*
1066: * We don't expect errors here since the drive claims that it can do
1067: * multiple sector transfers.
1068: */
1069: nSectors = infoPtr->multipleSectors & IDE_MULTI_SECTOR_MASK;
1070:
1071: if ( nSectors )
1072: {
1073: if ([self ideSetMultiSectorMode:&ideRegs
1074: numSectors:nSectors] == IDER_SUCCESS)
1075: {
1076:
1077: [self setTransferRate: unit UseDMA: NO];
1078:
1079: _multiSector[unit] = nSectors;
1080: ideRegs = [self logToPhys:0 numOfBlocks:nSectors];
1081:
1082: buf = IOMalloc(nSectors * IDE_SECTOR_SIZE);
1083: if ([self ideReadMultiple:&ideRegs
1084: client:(struct vm_map *)IOVmTaskSelf()
1085: addr:buf] != IDER_SUCCESS)
1086: {
1087: IOLog("%s: Read Multiple does not work!\n", [self name]);
1088: _multiSector[unit] = 0;
1089: }
1090: IOFree(buf, nSectors * IDE_SECTOR_SIZE);
1091: }
1092: }
1093: /*
1094: * A drive may not support set features command. Do we need to do
1095: * anything special if this command fails?
1096: */
1097:
1098: return IDER_SUCCESS;
1099: }
1100:
1101: -(ideIdentifyInfo_t *)getIdeIdentifyInfo:(unsigned int)unit
1102: {
1103: return _ideIdentifyInfoSupported[unit] ? &_ideIdentifyInfo[unit] : NULL;
1104: }
1105:
1106: -(void)endianSwapIdentifyData:(ideIdentifyInfo_t *)pID
1107: {
1108: endianSwap16Bit(&pID->genConfig);
1109: endianSwap16Bit(&pID->cylinders);
1110: endianSwap16Bit(&pID->heads);
1111: endianSwap16Bit(&pID->unformattedBytesPerTrack);
1112: endianSwap16Bit(&pID->unformattedBytesPerSector);
1113: endianSwap16Bit(&pID->sectorsPerTrack);
1114: endianSwap16Bit(&pID->bufferType);
1115: endianSwap16Bit(&pID->bufferSize);
1116: endianSwap16Bit(&pID->eccBytes);
1117: endianSwap16Bit(&pID->multipleSectors);
1118: endianSwap16Bit(&pID->doubleWordIO);
1119: endianSwap16Bit(&pID->capabilities);
1120: endianSwap16Bit(&pID->pioDataTransferCyleTimingMode);
1121: endianSwap16Bit(&pID->dmaDataTransferCyleTimingMode);
1122: endianSwap16Bit(&pID->fieldValidity);
1123: endianSwap16Bit(&pID->currentCylinders);
1124: endianSwap16Bit(&pID->currentHeads);
1125: endianSwap16Bit(&pID->currentSectorsPerTrack);
1126: endianSwap16Bit(&pID->capacity[0]);
1127: endianSwap16Bit(&pID->capacity[1]);
1128: endianSwap16Bit(&pID->multiSectorInfo);
1129: endianSwap32Bit(&pID->userAddressableSectors);
1130: endianSwap16Bit(&pID->swDma);
1131: endianSwap16Bit(&pID->mwDma);
1132: endianSwap16Bit(&pID->ultraDma);
1133: endianSwap16Bit(&pID->fcPioDataTransferCyleTimingMode);
1134: endianSwap16Bit(&pID->minMwDMATransferCycleTimePerWord);
1135: endianSwap16Bit(&pID->RecommendedMwDMACycleTime);
1136: endianSwap16Bit(&pID->MinPIOTransferCycleTimeWithoutFlowControl);
1137: endianSwap16Bit(&pID->MinPIOTransferCycleTimeWithIORDY);
1138: }
1139:
1140: -(void) assignRegisterAddresses: (IOTreeDevice *) deviceDescription
1141: {
1142:
1143: if ( _controllerType == kControllerTypeCmd646X )
1144: {
1145: u_int32_t pciRange1, pciRange2;
1146:
1147: [self mapMemoryRange: 0 to:(vm_address_t *)&pciRange1 findSpace:YES cache:IO_CacheOff];
1148: [self mapMemoryRange: 1 to:(vm_address_t *)&pciRange2 findSpace:YES cache:IO_CacheOff];
1149:
1150: _ideRegsAddrs.data = pciRange1;
1151: _ideRegsAddrs.error = pciRange1 + 0x1;
1152: _ideRegsAddrs.features = pciRange1 + 0x1;
1153: _ideRegsAddrs.sectCnt = pciRange1 + 0x2;
1154: _ideRegsAddrs.sectNum = pciRange1 + 0x3;
1155: _ideRegsAddrs.cylLow = pciRange1 + 0x4;
1156: _ideRegsAddrs.cylHigh = pciRange1 + 0x5;
1157: _ideRegsAddrs.drHead = pciRange1 + 0x6;
1158: _ideRegsAddrs.status = pciRange1 + 0x7;
1159: _ideRegsAddrs.command = pciRange1 + 0x7;
1160:
1161: _ideRegsAddrs.deviceControl = pciRange2 + 0x2;
1162: _ideRegsAddrs.altStatus = pciRange2 + 0x2;
1163:
1164: [(IOPCIDevice *)deviceDescription configWriteLong:0x04 value:0x05];
1165:
1166: }
1167: else
1168: {
1169: IORange *IORanges;
1170:
1171: IORanges = [deviceDescription memoryRangeList];
1172:
1173: _ideRegsAddrs.data = IORanges[0].start;
1174: _ideRegsAddrs.error = IORanges[0].start + 0x10;
1175: _ideRegsAddrs.features = IORanges[0].start + 0x10;
1176: _ideRegsAddrs.sectCnt = IORanges[0].start + 0x20;
1177: _ideRegsAddrs.sectNum = IORanges[0].start + 0x30;
1178: _ideRegsAddrs.cylLow = IORanges[0].start + 0x40;
1179: _ideRegsAddrs.cylHigh = IORanges[0].start + 0x50;
1180: _ideRegsAddrs.drHead = IORanges[0].start + 0x60;
1181: _ideRegsAddrs.status = IORanges[0].start + 0x70;
1182: _ideRegsAddrs.command = IORanges[0].start + 0x70;
1183:
1184: _ideRegsAddrs.deviceControl = IORanges[0].start + 0x160;
1185: _ideRegsAddrs.altStatus = IORanges[0].start + 0x160;
1186:
1187: _ideRegsAddrs.channelConfig = IORanges[0].start + 0x200;
1188:
1189: _ideDMARegs = (IODBDMAChannelRegisters *)IORanges[1].start;
1190: }
1191: }
1192:
1193:
1194: @end
1195:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.