|
|
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) 1991-1997 NeXT Software, Inc. All rights reserved.
28: *
29: * IdeCnt.m - IDE Controller class.
30: *
31: */
32:
33: #import <sys/systm.h>
34: #import <driverkit/kernelDriver.h>
35: #import <driverkit/interruptMsg.h>
36: #import <mach/mach_interface.h>
37: #import <driverkit/IODevice.h>
38: #import <driverkit/ppc/IOTreeDevice.h>
39: #import <driverkit/align.h>
40: #import <machkit/NXLock.h>
41: #import "io_inline.h"
42: #import "IdeDDM.h"
43:
44: #import "IdeCnt.h"
45: #import "IdeCntInit.h"
46: #import "IdeCntCmds.h"
47: #import "IdeCntDma.h"
48:
49: #import "IdeCntInline.h"
50:
51: #import "Cmd646xRegs.h"
52:
53: static int hcUnitNum = 0;
54:
55:
56: @implementation IdeController
57:
58: /*
59: * For PCI ATA the driver is running attached to a different node
60: * than OpenFirmware - patch up the path to match.
61: */
62: #define PCIATASUBNODE "ata-4@0"
63:
64: - getDevicePath:(char *)path maxLength:(int)maxLen useAlias:(BOOL)doAlias
65: {
66: if( [super getDevicePath:path maxLength:maxLen useAlias:doAlias]) {
67:
68: if( _controllerType == kControllerTypeCmd646X) {
69:
70: int len = maxLen - strlen( path );
71:
72: len -= strlen( PCIATASUBNODE );
73: if( len < 0)
74: return( nil);
75: strcat( path, "/" PCIATASUBNODE );
76:
77: if( doAlias)
78: IOAliasPath( path);
79: }
80: return( self);
81: }
82: return( nil);
83: }
84:
85: - (char *) matchDevicePath:(char *)matchPath
86: {
87: char * tail;
88: char * skip;
89:
90: tail = [super matchDevicePath:matchPath];
91: if( tail && (_controllerType == kControllerTypeCmd646X)) {
92:
93: /* skip the extra path component */
94: if( (0 == strncmp( tail + 1, PCIATASUBNODE, strlen( PCIATASUBNODE )))
95: && (skip = strchr( tail + 1, '/')) )
96: tail = skip;
97: }
98: return( tail);
99: }
100:
101: /*
102: * Create and initialize one instance of IDE Controller.
103: */
104:
105: void call_kdp(void);
106:
107: + (BOOL)probe:(IOTreeDevice *)deviceDescription
108: {
109: IdeController *idec;
110: char devName[20];
111: int numInts, numRange;
112: int maxInts, maxRange;
113:
114: // call_kdp();
115:
116: idec = [[self alloc] initFromDeviceDescription:deviceDescription];
117:
118: if ( strcmp([deviceDescription nodeName], "pci-ata") == 0 )
119: {
120: idec->_controllerType = kControllerTypeCmd646X;
121: }
122:
123: numRange = [deviceDescription numMemoryRanges];
124: numInts = [deviceDescription numInterrupts];
125:
126: if ( idec->_controllerType == kControllerTypeCmd646X )
127: {
128: maxRange = 5;
129: maxInts = 1;
130: }
131: else
132: {
133: maxRange = 2;
134: maxInts = 2;
135: }
136:
137: if ( numRange != maxRange )
138: {
139: IOLog("Disk(ata): Invalid port ranges: %d.\n", numRange);
140: [idec free];
141: return NO;
142: }
143:
144: if (numInts != maxInts)
145: {
146: IOLog("Disk(ata): Invalid number of interrupts: %d.\n", numInts);
147: [idec free];
148: return NO;
149: }
150:
151: if ( [idec checkMediaBayOption: deviceDescription] == NO )
152: {
153: IOLog("Disk(ata): Non-ATA/ATAPI Media Bay option detected\n\r");
154: [idec free];
155: return NO;
156: }
157:
158: /*
159: * Proceed with initialization.
160: */
161: [idec setUnit:hcUnitNum];
162: sprintf(devName, "hc%d", hcUnitNum);
163: [idec setName:devName];
164: [idec setDeviceKind:"IdeController"];
165:
166: if ([idec ideControllerInit:deviceDescription] != YES)
167: {
168: [idec free];
169: return NO;
170: }
171:
172: if ([idec registerDevice] == nil)
173: {
174: IOLog("Disk(ata): %s: Failed to register device.\n", [self name]);
175: [idec free];
176: return NO;
177: }
178:
179: hcUnitNum++;
180:
181: return YES;
182: }
183:
184: /*
185: * Wait for interrupt or timeout. Returns IDER_SUCCESS or IDER_TIMEOUT.
186: */
187: - (ide_return_t)ideWaitForInterrupt:(unsigned int)command
188: ideStatus:(unsigned char *)status
189: {
190: msg_return_t result;
191: msg_header_t msg;
192: u_int8_t cfgByte;
193:
194: msg.msg_local_port = _ideInterruptPort;
195: msg.msg_size = sizeof(msg);
196:
197: result = msg_receive(&msg, RCV_TIMEOUT, _interruptTimeOut);
198:
199: if (result == RCV_SUCCESS || result == RCV_TOO_LARGE)
200: {
201: if (status != NULL)
202: *status = inb(_ideRegsAddrs.status); /* acknowledge */
203: else
204: inb(_ideRegsAddrs.status);
205:
206: if ( _controllerType == kControllerTypeCmd646X )
207: {
208: u_int32_t intReg;
209:
210: intReg = (_busNum == 0) ? kCmd646xCFR : kCmd646xARTTIM23;
211: [self configReadByte: intReg value: &cfgByte];
212: [self configWriteByte: intReg value: cfgByte];
213: [self enableInterrupt:0];
214:
215: #if 0
216: [self configReadByte: intReg value: &cfgByte];
217: IOLog( "Int Mask = %08x Int Levels = %08x Int Events = %08x CmdInt = %02x\n\r",
218: *(volatile u_int32_t *)0x80800024, *(volatile u_int32_t *)0x8080002c,
219: *(volatile u_int32_t *)0x80800020, cfgByte );
220: #endif
221: }
222:
223: return IDER_SUCCESS;
224: }
225:
226: if (result == RCV_TIMED_OUT)
227: {
228: IOLog("Disk(ata): %s: interrupt timeout, cmd: 0x%0x\n", [self name], command);
229: }
230: else
231: IOLog("Disk(ata): %s: Error %d in receiving interrupt, cmd: 0x%0x\n",
232: [self name], result, command);
233:
234: return IDER_CMD_ERROR;
235: }
236:
237: /*
238: * Remove any interrupts messages that have queued up. This will get rid of
239: * any spurious or duplicate interrupts.
240: */
241: - (void)clearInterrupts
242: {
243: msg_return_t result;
244: msg_header_t msg;
245: int count;
246:
247: count = 0;
248:
249: while (1) {
250:
251: msg.msg_local_port = _ideInterruptPort;
252: msg.msg_size = sizeof(msg);
253:
254: result = msg_receive(&msg, RCV_TIMEOUT, 0);
255:
256: if (result != RCV_SUCCESS)
257: {
258: return;
259: }
260: count += 1;
261: }
262: }
263:
264: - (ide_return_t)waitForNotBusy
265: {
266: int delay = MAX_BUSY_DELAY; /* microseconds */
267: unsigned char status;
268:
269: delay -= 2; /* Or else will block on second try */
270: while (delay > 0) {
271: status = inb(_ideRegsAddrs.status);
272: if (!(status & BUSY)) {
273: return IDER_SUCCESS;
274: }
275: if (delay % 1000) {
276: IODelay(2);
277: delay -= 2;
278: } else {
279: IOSleep(1);
280: delay -= 1000;
281: }
282: }
283:
284: return IDER_TIMEOUT;
285: }
286:
287: - (ide_return_t)waitForDeviceReady
288: {
289: int delay = MAX_BUSY_DELAY;
290: unsigned char status;
291:
292: delay -= 2;
293: while (delay > 0) {
294: status = inb(_ideRegsAddrs.status);
295: if ((!(status & BUSY)) && (status & READY)) {
296: return IDER_SUCCESS;
297: }
298: if (delay % 1000) {
299: IODelay(2);
300: delay -= 2;
301: } else {
302: IOSleep(1);
303: delay -= 1000;
304: }
305: }
306: return IDER_TIMEOUT;
307: }
308:
309: - (ide_return_t)waitForDataReady
310: {
311: int delay = MAX_DATA_READY_DELAY;
312: unsigned char status;
313:
314: delay -= 2;
315: while (delay > 0) {
316: status = inb(_ideRegsAddrs.altStatus);
317: if ((!(status & BUSY)) && (status & DREQUEST))
318: return (IDER_SUCCESS);
319: if (delay % 1000) {
320: IODelay(2);
321: delay -= 2;
322: } else {
323: IOSleep(1);
324: delay -= 1000;
325: }
326: }
327:
328: return IDER_TIMEOUT;
329: }
330:
331:
332: /*
333: * This is a private version for ideReadGetInfoCommon. It has a short delay
334: * time. This is the same situation as atapiIdentifyDeviceWaitForDataReady in
335: * AtapiCntCmds.m. The problem in both cases is that some devices pass
336: * identification checks even when they should not. Now the first command
337: * issued after can really confirm that but we don't want to wait too long.
338: */
339: - (ide_return_t)ataIdeReadGetInfoCommonWaitForDataReady
340: {
341: int delay = MAX_DATA_READY_DELAY/25;
342: unsigned char status;
343:
344: delay -= 2;
345: while (delay > 0) {
346: status = inb(_ideRegsAddrs.altStatus);
347: if ((!(status & BUSY)) && (status & DREQUEST))
348: return (IDER_SUCCESS);
349: if (delay % 1000) {
350: IODelay(2);
351: delay -= 2;
352: } else {
353: IOSleep(1);
354: delay -= 1000;
355: }
356: }
357:
358: return IDER_TIMEOUT;
359: }
360:
361:
362: - (void)enableInterrupts
363: {
364: outb(_ideRegsAddrs.deviceControl, DISK_INTERRUPT_ENABLE);
365: [self enableInterrupt:0];
366: }
367:
368: - (void)disableInterrupts
369: {
370: [self disableInterrupt: 0];
371: outb(_ideRegsAddrs.deviceControl, DISK_INTERRUPT_DISABLE);
372: }
373:
374: - (void)setInterruptTimeOut:(unsigned int)timeOut
375: {
376: _interruptTimeOut = timeOut;
377: }
378:
379: - (unsigned int)interruptTimeOut
380: {
381: return _interruptTimeOut;
382: }
383:
384: - (IOReturn) ideExecuteCmd:(ideIoReq_t *)ideIoReq ToDrive:(unsigned char)drive
385: {
386: return [self _ideExecuteCmd:ideIoReq ToDrive:drive];
387: }
388:
389:
390: /*
391: * Return task file values, optionally print them if given a non-null string.
392: */
393: - (void)getIdeRegisters:(ideRegsVal_t *)rvp Print:(char *)printString
394: {
395: ideRegsVal_t ideRegs;
396:
397: ideRegs.error = inb(_ideRegsAddrs.error);
398: ideRegs.sectCnt = inb(_ideRegsAddrs.sectCnt);
399: ideRegs.sectNum = inb(_ideRegsAddrs.sectNum);
400: ideRegs.cylLow = inb(_ideRegsAddrs.cylLow);
401: ideRegs.cylHigh = inb(_ideRegsAddrs.cylHigh);
402: ideRegs.drHead = inb(_ideRegsAddrs.drHead);
403: ideRegs.status = inb(_ideRegsAddrs.altStatus); /* don't ack */
404:
405: if (rvp != NULL)
406: *rvp = ideRegs;
407:
408: if (printString != NULL) {
409: IOLog("Disk(ata): %s: %s: error=0x%x secCnt=0x%x "
410: "secNum=0x%x cyl=0x%x drhd=0x%x status=0x%x\n",
411: [self name], printString,
412: ideRegs.error, ideRegs.sectCnt, ideRegs.sectNum,
413: ((ideRegs.cylHigh << 8) | ideRegs.cylLow),
414: ideRegs.drHead, ideRegs.status);
415: }
416: }
417:
418: /*
419: * Read maximum of one page from the sector buffer to "addr", write maximum
420: * of one page from "addr" into the sector buffer. Note that (length <=
421: * PAGE_SIZE).
422: */
423: - (void)xferData:(caddr_t)addr read:(BOOL)read client:(struct vm_map *)client
424: length:(unsigned)length
425: {
426: ideXferData(addr, read, client, length, _ideRegsAddrs );
427: }
428:
429: - (BOOL)isMultiSectorAllowed:(unsigned int)unit
430: {
431: return (_multiSector[unit] != 0);
432: }
433:
434: -(unsigned int)getMultiSectorValue:(unsigned int)unit
435: {
436: return _ideIdentifyInfoSupported[unit] ? _multiSector[unit] : 0;
437: }
438:
439: - (ideIdentifyInfo_t *) getIdeIdentifyInfo:(unsigned int)unit
440: {
441: return _ideIdentifyInfoSupported[unit] ?
442: &_ideIdentifyInfo[unit] : NULL;
443: }
444:
445: - (ideDriveInfo_t *) getIdeDriveInfo:(unsigned int)unit
446: {
447: return (&_ideInfo[unit]);
448: }
449:
450: - (BOOL) isDmaSupported:(unsigned int)unit
451: {
452: return (_dmaSupported[unit] == YES);
453: }
454:
455: - (u_int) getControllerType
456: {
457: return _controllerType;
458: }
459:
460: /*
461: * Set the IDE Channel transfer rate to indicated drive
462: */
463: -(void) setTransferRate: (int) unit UseDMA: (BOOL) fUseDMA
464: {
465: Cmd646xRegs_t *cfgRegs;
466: u_int8_t cfgByte;
467: u_int8_t drwtimReg;
468: ideDMATypes_t dmaType;
469:
470: if ( _cycleTimes[unit].fChanged == NO && _cycleTimes[unit].useDMA == fUseDMA )
471: {
472: return;
473: }
474: _cycleTimes[unit].fChanged = NO;
475: _cycleTimes[unit].useDMA = fUseDMA;
476:
477: if ( _controllerType == kControllerTypeCmd646X )
478: {
479: /*
480: *
481: */
482: cfgRegs = &_cycleTimes[unit].ideConfig.cmd646XConfig;
483:
484: if ( _busNum == 0 )
485: {
486: if ( unit == 0 )
487: {
488: [self configReadByte: kCmd646xCNTRL value:&cfgByte];
489: cfgByte &= ~kCmd646xCNTRL_Drive0ReadAhead;
490: cfgByte |= cfgRegs->cntrlReg;
491: [self configWriteByte: kCmd646xCNTRL value:cfgByte];
492:
493: [self configWriteByte: kCmd646xCMDTIM value:cfgRegs->cmdtimReg];
494:
495: [self configWriteByte: kCmd646xARTTIM0 value:cfgRegs->arttimReg];
496:
497: dmaType = _cycleTimes[unit].dmaType;
498: if ( _cycleTimes[unit].useDMA && ((dmaType != IDE_DMA_NONE) || (dmaType != IDE_DMA_ULTRA)) )
499: {
500: drwtimReg = cfgRegs->drwtimRegDMA;
501: }
502: else
503: {
504: drwtimReg = cfgRegs->drwtimRegPIO;
505: }
506: [self configWriteByte: kCmd646xDRWTIM0 value:drwtimReg];
507:
508: [self configReadByte: kCmd646xUDIDETCR0 value:&cfgByte];
509: cfgByte &= ~(kCmd646xUDIDETCR0_Drive0UDMACycleTime | kCmd646xUDIDETCR0_Drive0UDMAEnable);
510: cfgByte |= cfgRegs->udidetcrReg;
511: [self configWriteByte: kCmd646xUDIDETCR0 value:cfgByte];
512: }
513: else
514: {
515: [self configReadByte: kCmd646xCNTRL value:&cfgByte];
516: cfgByte &= ~kCmd646xCNTRL_Drive1ReadAhead;
517: cfgByte |= cfgRegs->cntrlReg;
518: [self configWriteByte: kCmd646xCNTRL value:cfgByte];
519:
520: [self configWriteByte: kCmd646xARTTIM1 value:cfgRegs->arttimReg];
521:
522: dmaType = _cycleTimes[unit].dmaType;
523: if ( _cycleTimes[unit].useDMA && ((dmaType != IDE_DMA_NONE) || (dmaType != IDE_DMA_ULTRA)) )
524: {
525: drwtimReg = cfgRegs->drwtimRegDMA;
526: }
527: else
528: {
529: drwtimReg = cfgRegs->drwtimRegPIO;
530: }
531: [self configWriteByte: kCmd646xDRWTIM1 value:drwtimReg];
532:
533: [self configReadByte: kCmd646xUDIDETCR0 value:&cfgByte];
534: cfgByte &= ~(kCmd646xUDIDETCR0_Drive1UDMACycleTime | kCmd646xUDIDETCR0_Drive1UDMAEnable);
535: cfgByte |= cfgRegs->udidetcrReg;
536: [self configWriteByte: kCmd646xUDIDETCR0 value:cfgByte];
537: }
538: }
539: else
540: {
541: if ( unit == 0 )
542: {
543: [self configReadByte: kCmd646xARTTIM23 value:&cfgByte];
544: cfgByte &= ~(kCmd646xARTTIM23_Drive2ReadAhead | kCmd646xARTTIM23_AddrSetup);
545: cfgByte |= (cfgRegs->cntrlReg >> 4) | cfgRegs->arttimReg;
546: [self configWriteByte: kCmd646xARTTIM23 value:cfgByte];
547:
548: [self configWriteByte: kCmd646xCMDTIM value:cfgRegs->cmdtimReg];
549:
550: dmaType = _cycleTimes[unit].dmaType;
551: if ( _cycleTimes[unit].useDMA && ((dmaType != IDE_DMA_NONE) || (dmaType != IDE_DMA_ULTRA)) )
552: {
553: drwtimReg = cfgRegs->drwtimRegDMA;
554: }
555: else
556: {
557: drwtimReg = cfgRegs->drwtimRegPIO;
558: }
559: [self configWriteByte: kCmd646xDRWTIM2 value:drwtimReg];
560:
561: [self configReadByte: kCmd646xUDIDETCR1 value:&cfgByte];
562: cfgByte &= ~(kCmd646xUDIDETCR1_Drive2UDMACycleTime | kCmd646xUDIDETCR1_Drive2UDMAEnable);
563: cfgByte |= cfgRegs->udidetcrReg;
564: [self configWriteByte: kCmd646xUDIDETCR1 value:cfgByte];
565: }
566: else
567: {
568: [self configReadByte: kCmd646xARTTIM23 value:&cfgByte];
569: cfgByte &= ~(kCmd646xARTTIM23_Drive3ReadAhead | kCmd646xARTTIM23_AddrSetup);
570: cfgByte |= (cfgRegs->cntrlReg >> 4) | cfgRegs->arttimReg;
571: [self configWriteByte: kCmd646xARTTIM23 value:cfgByte];
572:
573: dmaType = _cycleTimes[unit].dmaType;
574: if ( _cycleTimes[unit].useDMA && ((dmaType != IDE_DMA_NONE) || (dmaType != IDE_DMA_ULTRA)) )
575: {
576: drwtimReg = cfgRegs->drwtimRegDMA;
577: }
578: else
579: {
580: drwtimReg = cfgRegs->drwtimRegPIO;
581: }
582: [self configWriteByte: kCmd646xDRWTIM3 value:drwtimReg];
583:
584: [self configReadByte: kCmd646xUDIDETCR1 value:&cfgByte];
585: cfgByte &= ~(kCmd646xUDIDETCR1_Drive3UDMACycleTime | kCmd646xUDIDETCR1_Drive3UDMAEnable);
586: cfgByte |= cfgRegs->udidetcrReg;
587: [self configWriteByte: kCmd646xUDIDETCR1 value:cfgByte];
588: }
589:
590: }
591: return;
592: }
593: else
594: {
595: *(volatile uint *)_ideRegsAddrs.channelConfig = _cycleTimes[unit].ideConfig.dbdmaConfig;
596: eieio();
597: _cycleTimes[unit ^ 1].fChanged = YES;
598: }
599: }
600:
601: /*
602: * Set the data transfer rate for the specified drive.
603: */
604: -(void) setTransferMode:(int) unit
605: {
606: int value;
607:
608: value = IDE_FEATURE_MODE_PIO | _cycleTimes[unit].pioMode;
609: [self ideSetDriveFeature:FEATURE_SET_TRANSFER_MODE value: value];
610:
611: if ( _cycleTimes[unit].dmaType != IDE_DMA_NONE )
612: {
613: value = _cycleTimes[unit].dmaMode;
614: switch ( _cycleTimes[unit].dmaType )
615: {
616: case IDE_DMA_NONE:
617: return;
618: case IDE_DMA_SINGLEWORD:
619: value |= IDE_FEATURE_MODE_SWDMA;
620: break;
621: case IDE_DMA_MULTIWORD:
622: value |= IDE_FEATURE_MODE_MWDMA;
623: break;
624: case IDE_DMA_ULTRA:
625: value |= IDE_FEATURE_MODE_ULTRADMA;
626: break;
627: }
628: [self ideSetDriveFeature:FEATURE_SET_TRANSFER_MODE value: value];
629: }
630: }
631:
632: - (void)ideCntrlrLock
633: {
634: [_ideCmdLock lock];
635: }
636:
637: - (void)ideCntrlrUnLock
638: {
639: [_ideCmdLock unlock];
640: }
641:
642: - (u_int) numberOfDrives
643: {
644: return (MAX_IDE_DRIVES);
645: }
646:
647:
648: /*
649: * There is no need for separate ATAPI locks but we keep them for testing
650: * purposes.
651: */
652: - (void)atapiCntrlrLock
653: {
654: [_ideCmdLock lock];
655: }
656:
657: - (void)atapiCntrlrUnLock
658: {
659: [_ideCmdLock unlock];
660: }
661:
662: /*
663: * The ATAPI driver (CD-ROM or Tape) will scan thorugh this list of devices
664: * looking for ATAPI hardware.
665: */
666: - (unsigned int)numDevices
667: {
668: return MAX_IDE_DRIVES;
669: }
670:
671: - (BOOL)isAtapiDevice:(unsigned char)unit
672: {
673: if (unit >= MAX_IDE_DRIVES)
674: return NO;
675:
676: return _atapiDevice[unit];
677: }
678:
679: - (BOOL)isAtapiCommandActive:(unsigned char)unit
680: {
681: return _atapiCommandActive[unit];
682: }
683:
684: - (void)setAtapiCommandActive:(BOOL)state forUnit:(unsigned char)unit
685: {
686: _atapiCommandActive[unit] = state;
687: }
688:
689: /*
690: * Power management.
691: */
692: - (idePowerState_t)drivePowerState
693: {
694: return _drivePowerState;
695: }
696:
697: - (void)setDrivePowerState:(idePowerState_t)state
698: {
699: _drivePowerState = state;
700: }
701:
702: - (void)putDriveToSleep
703: {
704: if ([self drivePowerState] == IDE_PM_SLEEP)
705: return;
706:
707: _driveSleepRequest = YES;
708: ddm_ide_lock("putDriveToSleep: acquiring lock, suspend\n",1,2,3,4,5);
709: [self ideCntrlrLock];
710: ddm_ide_lock("putDriveToSleep: acquired lock, suspend\n",1,2,3,4,5);
711: #ifdef DEBUG
712: IOLog("Disk(ata): %s: Entering suspend mode.\n", [self name]);
713: #endif DEBUG
714: [self setDrivePowerState:IDE_PM_SLEEP];
715: }
716:
717: /*
718: * The method wakeUpDrive simply sets a flag. The drive is actually woken up
719: * the next time we need it. This is done by a call from
720: * ideExecuteCmd:ToDrive: method to the spinUpDrive:unit: method below.
721: */
722: - (void)wakeUpDrive
723: {
724: if ([self drivePowerState] == IDE_PM_ACTIVE)
725: return;
726:
727: _driveSleepRequest = NO;
728: ddm_ide_lock("wakeUpDrive: Exiting suspend mode.\n", 1,2,3,4,5);
729: [self setDrivePowerState:IDE_PM_STANDBY];
730: ddm_ide_lock("wakeUpDrive: releasing lock, recovered\n",1,2,3,4,5);
731: [self ideCntrlrUnLock];
732: }
733:
734: /*
735: * This will get the drive to spin up. We simply try to read a single sector
736: * and are prepared to camp out for a very long time (>>30 secs).
737: */
738: #define MAX_MEDIA_ACCESS_TRIES 30
739:
740: - (BOOL)spinUpDrive:(unsigned int)unit
741: {
742: unsigned char status;
743: int i, j;
744: unsigned char dh;
745:
746: dh = _addressMode[unit] | (unit ? SEL_DRIVE1 : SEL_DRIVE0);
747:
748: for (i = 0; i < MAX_MEDIA_ACCESS_TRIES; i++) {
749:
750: [self ideReset];
751: [self disableInterrupts];
752:
753: /*
754: * Read one sector at (0,0,1). (LBA == 1).
755: */
756: outb(_ideRegsAddrs.drHead, dh);
757: outb(_ideRegsAddrs.sectNum, 0x1);
758: outb(_ideRegsAddrs.sectCnt, 0x1);
759: outb(_ideRegsAddrs.cylLow, 0x0);
760: outb(_ideRegsAddrs.cylHigh, 0x0);
761: outb(_ideRegsAddrs.command, IDE_READ);
762:
763: /*
764: * Wait for about ten seconds for response from drive.
765: */
766: for (j = 0; j < 5; j++) {
767: IOSleep(2000);
768: status = inb(_ideRegsAddrs.status);
769: if ((!(status & BUSY)) && (status & DREQUEST)) {
770: [self ideReset]; /* FIXME: may not be needed */
771: IOLog("Disk(ata): %s: Recovered from suspend mode.\n", [self name]);
772: return YES;
773: }
774: }
775: IOLog("Disk(ata): %s: Retrying to recover from suspend mode.\n", [self name]);
776: }
777:
778: IOLog("Disk(ata): %s: Failed to recover from suspend mode.\n", [self name]);
779: return NO;
780: }
781:
782: /*
783: * We need to get the ATA drives spinning before we can try to reset them.
784: * The situation gets complicated if the ATA and ATAPI device share the same
785: * cable. We basically start up all devices on this controller.
786: */
787: - (BOOL)startUpAttachedDevices
788: {
789: int i;
790: BOOL status = YES;
791:
792: /* Spin up only ATA drives */
793: for (i = 0; i < MAX_IDE_DRIVES; i++) {
794: if ((_ideInfo[i].type != 0) && ([self isAtapiDevice:i] == NO)){
795: status = [self spinUpDrive:i];
796: }
797: }
798:
799: [self resetAndInit];
800: [self setDrivePowerState:IDE_PM_ACTIVE];
801:
802: return status;
803: }
804:
805: - (IOReturn) getPowerState:(PMPowerState *)state_p
806: {
807: return IO_R_UNSUPPORTED;
808: }
809:
810: - (IOReturn) setPowerState:(PMPowerState)state
811: {
812: if (state == PM_READY) {
813: [self wakeUpDrive];
814: } else if (state == PM_SUSPENDED) {
815: [self putDriveToSleep];
816: } else {
817: //IOLog("Disk(ata): %s: unknown APM event %x\n", [self name], (unsigned int)state);
818: }
819:
820: return IO_R_SUCCESS;
821: }
822:
823: - (IOReturn) getPowerManagement:(PMPowerManagementState *)state_p
824: {
825: return IO_R_UNSUPPORTED;
826: }
827:
828: - (IOReturn) setPowerManagement:(PMPowerManagementState)state
829: {
830: return IO_R_UNSUPPORTED;
831: }
832:
833: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
834: {
835: strcpy( classes, IOClassIDEController);
836: return( self);
837: }
838:
839: - property_IODeviceType:(char *)types length:(unsigned int *)maxLen
840: {
841: strcat( types, " "IOTypeIDE);
842: return( self);
843: }
844:
845:
846: - (void) configWriteByte: (u_int32_t)reg value: (u_int8_t)cfgByte
847: {
848: union
849: {
850: unsigned long word;
851: unsigned char byte[4];
852: } cfgReg;
853:
854: u_int32_t regWord;
855:
856: regWord = reg & ~0x03;
857:
858: [[self deviceDescription] configReadLong: regWord value: &cfgReg.word];
859: cfgReg.word = EndianSwap32(cfgReg.word);
860: switch (regWord)
861: {
862: case kCmd646xCFR:
863: cfgReg.byte[kCmd646xCFR & 0x03] &= ~kCmd646xCFR_IDEIntPRI;
864: break;
865: case kCmd646xDRWTIM0:
866: cfgReg.byte[kCmd646xARTTIM23 & 0x03] &= ~kCmd646xARTTIM23_IDEIntSDY;
867: break;
868: case kCmd646xBMIDECR0:
869: cfgReg.byte[kCmd646xMRDMODE & 0x03 ] &= ~(kCmd646xMRDMODE_IDEIntPRI | kCmd646xMRDMODE_IDEIntSDY);
870: cfgReg.byte[kCmd646xBMIDESR0 & 0x03] &= ~(kCmd646xBMIDESR0_DMAIntPRI | kCmd646xBMIDESR0_DMAErrorPRI);
871: break;
872: case kCmd646xBMIDECR1:
873: cfgReg.byte[kCmd646xBMIDESR1 & 0x03] &= ~(kCmd646xBMIDESR1_DMAIntSDY | kCmd646xBMIDESR1_DMAErrorSDY);
874: break;
875: }
876: cfgReg.byte[reg & 0x03] = cfgByte;
877:
878: cfgReg.word = EndianSwap32(cfgReg.word);
879: [[self deviceDescription] configWriteLong: regWord value: cfgReg.word];
880: }
881:
882:
883: - (void) configReadByte: (u_int32_t)reg value: (u_int8_t *)cfgByte
884: {
885: union
886: {
887: unsigned long word;
888: unsigned char byte[4];
889: } cfgReg;
890:
891: [[self deviceDescription] configReadLong: reg value:&cfgReg.word];
892: *cfgByte = cfgReg.byte[3 - (reg & 0x03)];
893: return;
894: }
895:
896: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.