|
|
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.0 (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-1998 by Apple Computer, Inc., All rights reserved.
26: * Copyright 1994-1997 NeXT Software, Inc., All rights reserved.
27: *
28: * IdeCnt.m - IDE Controller class.
29: *
30: * HISTORY
31: *
32: * 1-Feb-1998 Joe Liu at Apple
33: * Created an initFromDeviceDescription method to do things that used to be
34: * done in the probe method. This allows us to call [super init...] after
35: * we have finished munging with our resources.
36: *
37: * 04-Sep-1996 Becky Divinski at NeXT
38: * Added code in probe method to handle Dual EIDE personality case.
39: *
40: * 07-Jul-1994 Rakesh Dubey at NeXT
41: * Created from original driver written by David Somayajulu.
42: */
43:
44: #if 0
45: #define KERNEL 1
46: #define KERNEL_PRIVATE 1
47: #define ARCH_PRIVATE 1
48: #undef MACH_USER_API
49: #endif
50:
51: #import "IdeCnt.h"
52: #import "IdeCntInit.h"
53: #import "IdeCntCmds.h"
54: #import "IdePIIX.h"
55: #import <driverkit/i386/IOPCIDeviceDescription.h>
56: #import <driverkit/i386/IOPCIDirectDevice.h>
57: #import <driverkit/kernelDriver.h>
58: #import <driverkit/interruptMsg.h>
59: #if (IO_DRIVERKIT_VERSION != 330)
60: #import <machdep/machine/pmap.h> // XXX get rid of this
61: #endif
62: #import <mach/mach_interface.h>
63: #import <driverkit/IODevice.h>
64: #import <driverkit/align.h>
65: #import <machkit/NXLock.h>
66: #import <machdep/i386/io_inline.h>
67: #import <kernserv/i386/spl.h>
68: #ifdef NO_IRQ_MSG
69: #import <kern/sched_prim.h>
70: #endif NO_IRQ_MSG
71: #import <kern/lock.h>
72: #import "IdeDDM.h"
73: #import <bsd/stdio.h>
74:
75: // XXX get rid of this
76: #if (IO_DRIVERKIT_VERSION != 330)
77: #import <machdep/machine/pmap.h>
78: #endif
79: #import "IdeCntInline.h"
80: #import "DualEide.h"
81:
82: /*
83: * If set to non-zero some debugging messages will be prinetd in case of
84: * failure.
85: */
86: __private_extern__ unsigned int _ide_debug = 0;
87:
88: /*
89: * Config table keys that determine our configuration.
90: */
91: #define CONTROLLER_INSTANCE "Instance"
92: #define ATA_DEBUG "Debug"
93:
94: #ifdef NO_IRQ_MSG
95: #warning Interrupt messaging OFF
96: typedef struct _ideStruct {
97: @defs(IdeController)
98: } ideStruct_t;
99: #endif NO_IRQ_MSG
100:
101: @implementation IdeController
102:
103: /*
104: * Create and initialize one instance of IDE Controller.
105: */
106:
107: + (BOOL)probe:(IODeviceDescription *)devDesc
108: {
109: IdeController *idec;
110:
111: idec = [self alloc];
112: if (idec == nil) {
113: IOLog("%s: Failed to alloc instance\n", [self name]);
114: return NO;
115: }
116:
117: return ([idec initFromDeviceDescription:devDesc] != nil);
118: }
119:
120: - initFromDeviceDescription:(IODeviceDescription *)devDesc
121: {
122: char devName[20];
123: const char *ctlType, *param;
124: int n, hcUnitNum;
125:
126: IOEISADeviceDescription *deviceDescription =
127: (IOEISADeviceDescription *)devDesc;
128:
129: if ((n = [deviceDescription numPortRanges]) != 1) {
130: IOLog("ATA: Invalid port ranges: %d.\n", n);
131: [self free];
132: return nil;
133: }
134:
135: if ((n = [deviceDescription numInterrupts]) != 1) {
136: IOLog("ATA: Invalid number of interrupts: %d.\n", n);
137: [self free];
138: return nil;
139: }
140:
141: ctlType = [[deviceDescription configTable]
142: valueForStringKey: CONTROLLER_INSTANCE];
143:
144: hcUnitNum = (unsigned char) ctlType[0] - '0';
145:
146: // Hack for Dual EIDE case
147:
148: if (dualEide)
149: {
150: if (instanceNum > 0)
151: hcUnitNum = instanceNum;
152: }
153:
154: if (hcUnitNum > MAX_IDE_CONTROLLERS-1) {
155: IOLog("ATA: Controller %d not supported.\n", hcUnitNum);
156: [self free];
157: return nil;
158: }
159:
160: param = [[deviceDescription configTable]
161: valueForStringKey: ATA_DEBUG];
162: if ((param != NULL) && (strcmp(param, "Yes") == 0)) {
163: _ide_debug = 1;
164: IOLog("ATA/ATAPI: Debug mode enabled.\n");
165: } else {
166: _ide_debug = 0;
167: }
168:
169: /*
170: * Proceed with initialization.
171: */
172: [self setUnit:hcUnitNum];
173: sprintf(devName, "hc%d", hcUnitNum);
174: [self setName:devName];
175: [self setDeviceKind:"IdeController"];
176:
177: /*
178: * Allocate storage for the ideIdentifyInfo_t structures.
179: */
180: for (n = 0; n < MAX_IDE_DRIVES; n++) {
181: _drives[n].ideIdentifyInfo =
182: (ideIdentifyInfo_t *)IOMalloc(sizeof(ideIdentifyInfo_t));
183: if (_drives[n].ideIdentifyInfo == NULL) {
184: [self free];
185: return nil;
186: }
187: }
188:
189: /*
190: * This must be called before [super init...] so that we can append
191: * to the portRangeList before it is registered.
192: */
193: if ([self probePCIController:(IOPCIDeviceDescription *)devDesc] != YES) {
194: [self free];
195: return nil;
196: }
197:
198: if ([super initFromDeviceDescription:deviceDescription] == nil) {
199: IOLog("%s: initFromDeviceDescription failed.\n", [self name]);
200: [self free];
201: return nil;
202: }
203:
204: if ([self ideControllerInit:devDesc] != YES) {
205: [self free];
206: return nil;
207: }
208:
209: if ([self registerDevice] == nil) {
210: IOLog("%s: Failed to register device.\n", [self name]);
211: [self free];
212: return nil;
213: }
214:
215: return self;
216: }
217:
218: static int logInterrupts = 0;
219: static unsigned short lastCommand = 0;
220:
221: /*
222: * Wait for interrupt or timeout. Returns IDER_SUCCESS or IDER_TIMEOUT.
223: */
224: - (ide_return_t)ideWaitForInterrupt:(unsigned int)command
225: ideStatus:(unsigned char *)status
226: {
227: #ifdef NO_IRQ_MSG
228: ide_return_t ret;
229: u_int s;
230: BOOL _interruptOccurred;
231:
232: s = spldevice();
233:
234: assert_wait((void *)&waitQueue, TRUE);
235: thread_set_timeout(HZ * _interruptTimeOut / 1000); // value in ticks
236: thread_block_with_continuation((void (*)()) 0);
237:
238: _interruptOccurred = interruptOccurred;
239:
240: splx(s);
241:
242: if (_interruptOccurred == YES) {
243: if (status != NULL)
244: *status = inb(_ideRegsAddrs.status); /* acknowledge */
245: else
246: inb(_ideRegsAddrs.status);
247:
248: logInterrupts -= 1;
249: lastCommand = command;
250:
251: ret = IDER_SUCCESS;
252: }
253: else {
254: IOLog("%s: interrupt timeout, cmd: 0x%0x\n", [self name], command);
255: ret = IDER_CMD_ERROR;
256: }
257:
258: return (ret);
259:
260: #else NO_IRQ_MSG
261:
262: msg_return_t result;
263: msg_header_t msg;
264:
265: msg.msg_local_port = _ideInterruptPort;
266: msg.msg_size = sizeof(msg);
267:
268: #ifdef undef
269: if (logInterrupts > 0)
270: IOLog("%s: waiting for interrupt for command %x\n",
271: [self name], command);
272: #endif undef
273:
274: result = msg_receive(&msg, RCV_TIMEOUT, _interruptTimeOut);
275:
276: if (result == RCV_SUCCESS || result == RCV_TOO_LARGE) {
277: if (status != NULL)
278: *status = inb(_ideRegsAddrs.status); /* acknowledge */
279: else
280: inb(_ideRegsAddrs.status);
281:
282: #ifdef undef
283: if (logInterrupts > 0)
284: IOLog("%s: interrupt received for cmd: 0x%0x, status: 0x%0x\n",
285: [self name], command, (status == NULL) ? 0 : *status);
286: #endif undef
287: logInterrupts -= 1;
288: lastCommand = command;
289:
290: return IDER_SUCCESS;
291: }
292:
293: if (result == RCV_TIMED_OUT)
294: IOLog("%s: interrupt timeout, cmd: 0x%0x\n", [self name], command);
295: else
296: IOLog("%s: Error %d in receiving interrupt, cmd: 0x%0x\n",
297: [self name], result, command);
298:
299: return IDER_CMD_ERROR;
300: #endif NO_IRQ_MSG
301: }
302:
303: /*
304: * Remove any interrupts messages that have queued up. This will get rid of
305: * any spurious or duplicate interrupts.
306: */
307: - (void)clearInterrupts
308: {
309: #ifdef NO_IRQ_MSG
310: return;
311: #else NO_IRQ_MSG
312: msg_return_t result;
313: msg_header_t msg;
314: int count;
315:
316: count = 0;
317:
318: while (1) {
319:
320: msg.msg_local_port = _ideInterruptPort;
321: msg.msg_size = sizeof(msg);
322:
323: result = msg_receive(&msg, RCV_TIMEOUT, 0);
324:
325: if (result != RCV_SUCCESS) {
326: if (count != 0) {
327: #ifdef DEBUG
328: IOLog("%s: %d spurious interrupts after command 0x%0x\n",
329: [self name], count, lastCommand);
330: #endif DEBUG
331: }
332: return;
333: }
334: count += 1;
335: }
336: #endif NO_IRQ_MSG
337: }
338:
339: - free
340: {
341: int n;
342:
343: [self resetController];
344:
345: if ((_controllerID == PCI_ID_PIIX) ||
346: (_controllerID == PCI_ID_PIIX3) ||
347: (_controllerID == PCI_ID_PIIX4)) {
348: if (_prdTable.ptr)
349: IOFree(_prdTable.ptrReal, _prdTable.sizeReal);
350: }
351:
352: for (n = 0; n < MAX_IDE_DRIVES; n++) {
353: if (_drives[n].ideIdentifyInfo)
354: IOFree(_drives[n].ideIdentifyInfo, sizeof(ideIdentifyInfo_t));
355: }
356:
357: return [super free];
358: }
359:
360: - (ide_return_t)waitForNotBusy
361: {
362: int delay = MAX_BUSY_DELAY; /* microseconds */
363: unsigned char status;
364:
365: #ifdef undef
366: IOLog("%s: waitForNotBusy\n", [self name]);
367: #endif undef
368:
369: delay -= 2; /* Or else will block on second try */
370: while (delay > 0) {
371: status = inb(_ideRegsAddrs.status);
372: if (!(status & BUSY)) {
373: return IDER_SUCCESS;
374: }
375: if (delay % 1000) {
376: IODelay(2);
377: delay -= 2;
378: } else {
379: IOSleep(1);
380: delay -= 1000;
381: }
382:
383: #ifdef undef
384: if ((_printWaitForNotBusy) && (delay % 20000 == 0)) {
385: IOLog("%s: waitForNotBusy, status = %x\n",
386: [self name], status);
387: }
388: #endif undef
389: }
390:
391: return IDER_TIMEOUT;
392: }
393:
394: - (ide_return_t)waitForDeviceReady
395: {
396: int delay = MAX_BUSY_DELAY;
397: unsigned char status;
398:
399: #ifdef undef
400: if (_printWaitForNotBusy)
401: IOLog("%s: waitForDeviceReady\n", [self name]);
402: #endif undef
403:
404: delay -= 2;
405: while (delay > 0) {
406: status = inb(_ideRegsAddrs.status);
407: if ((!(status & BUSY)) && (status & READY)) {
408: return IDER_SUCCESS;
409: }
410: if (delay % 1000) {
411: IODelay(2);
412: delay -= 2;
413: } else {
414: IOSleep(1);
415: delay -= 1000;
416: }
417:
418: #ifdef undef
419: if ((_printWaitForNotBusy) && (delay % 20000 == 0)) {
420: IOLog("%s: waitForDeviceReady, status = %x\n",
421: [self name], status);
422: }
423: #endif undef
424:
425: }
426: return IDER_TIMEOUT;
427: }
428:
429: #define ATA_IDLE_BIT_MASK (BUSY | DREQUEST)
430: - (ide_return_t)waitForDeviceIdle
431: {
432: int delay = MAX_BUSY_DELAY;
433: unsigned char status;
434:
435: #ifdef undef
436: IOLog("%s: waitForDeviceIdle\n", [self name]);
437: #endif undef
438:
439: delay -= 2;
440: while (delay > 0) {
441: status = inb(_ideRegsAddrs.status);
442: if ((status & ATA_IDLE_BIT_MASK) == 0)
443: return IDER_SUCCESS;
444: if (delay % 1000) {
445: IODelay(2);
446: delay -= 2;
447: } else {
448: IOSleep(1);
449: delay -= 1000;
450: }
451: }
452: return IDER_TIMEOUT;
453: }
454:
455: - (ide_return_t)waitForDataReady
456: {
457: int delay = MAX_DATA_READY_DELAY;
458: unsigned char status;
459:
460: #ifdef undef
461: IOLog("waitForDataReady\n");
462: #endif undef
463:
464: delay -= 2;
465: while (delay > 0) {
466: status = inb(_ideRegsAddrs.altStatus);
467: if ((!(status & BUSY)) && (status & DREQUEST))
468: return (IDER_SUCCESS);
469: if (delay % 1000) {
470: IODelay(2);
471: delay -= 2;
472: } else {
473: IOSleep(1);
474: delay -= 1000;
475: }
476: }
477:
478: return IDER_TIMEOUT;
479: }
480:
481:
482: /*
483: * This is a private version for ideReadGetInfoCommon. It has a short delay
484: * time. This is the same situation as atapiIdentifyDeviceWaitForDataReady in
485: * AtapiCntCmds.m. The problem in both cases is that some devices pass
486: * identification checks even when they should not. Now the first command
487: * issued after can really confirm that but we don't want to wait too long.
488: */
489: - (ide_return_t)ataIdeReadGetInfoCommonWaitForDataReady
490: {
491: int delay = MAX_DATA_READY_DELAY/25;
492: unsigned char status;
493:
494: #ifdef undef
495: IOLog("waitForDataReady\n");
496: #endif undef
497:
498: delay -= 2;
499: while (delay > 0) {
500: status = inb(_ideRegsAddrs.altStatus);
501: if ((!(status & BUSY)) && (status & DREQUEST))
502: return (IDER_SUCCESS);
503: if (delay % 1000) {
504: IODelay(2);
505: delay -= 2;
506: } else {
507: IOSleep(1);
508: delay -= 1000;
509: }
510: }
511:
512: return IDER_TIMEOUT;
513: }
514:
515:
516: - (void)enableInterrupts
517: {
518: outb(_ideRegsAddrs.deviceControl, DISK_INTERRUPT_ENABLE);
519: }
520:
521: - (void)disableInterrupts
522: {
523: outb(_ideRegsAddrs.deviceControl, DISK_INTERRUPT_DISABLE);
524: }
525:
526: - (void)setInterruptTimeOut:(unsigned int)timeOut
527: {
528: _interruptTimeOut = timeOut;
529: }
530:
531: - (unsigned int)interruptTimeOut
532: {
533: return _interruptTimeOut;
534: }
535:
536:
537: /*
538: * Return task file values, optionally print them if given a non-null string.
539: */
540: - (void)getIdeRegisters:(ideRegsVal_t *)rvp Print:(char *)printString
541: {
542: ideRegsVal_t ideRegs;
543:
544: ideRegs.error = inb(_ideRegsAddrs.error);
545: ideRegs.sectCnt = inb(_ideRegsAddrs.sectCnt);
546: ideRegs.sectNum = inb(_ideRegsAddrs.sectNum);
547: ideRegs.cylLow = inb(_ideRegsAddrs.cylLow);
548: ideRegs.cylHigh = inb(_ideRegsAddrs.cylHigh);
549: ideRegs.drHead = inb(_ideRegsAddrs.drHead);
550: ideRegs.status = inb(_ideRegsAddrs.altStatus); /* don't ack */
551:
552: if (rvp != NULL)
553: *rvp = ideRegs;
554:
555: if (printString != NULL) {
556: IOLog("%s: %s: error=0x%x secCnt=0x%x "
557: "secNum=0x%x cyl=0x%x drhd=0x%x status=0x%x\n",
558: [self name], printString,
559: ideRegs.error, ideRegs.sectCnt, ideRegs.sectNum,
560: ((ideRegs.cylHigh << 8) | ideRegs.cylLow),
561: ideRegs.drHead, ideRegs.status);
562: }
563: }
564:
565: /*
566: * Read maximum of one page from the sector buffer to "addr", write maximum
567: * of one page from "addr" into the sector buffer. Note that (length <=
568: * PAGE_SIZE).
569: */
570: - (void)xferData:(caddr_t)addr read:(BOOL)read client:(struct vm_map *)client
571: length:(unsigned)length
572: {
573: ideXferData(addr, read, client, length, _ideRegsAddrs, _transferWidth);
574: }
575:
576: - (BOOL)isMultiSectorAllowed:(unsigned int)unit
577: {
578: return (_drives[unit].multiSector != 0);
579: }
580:
581: -(unsigned int)getMultiSectorValue:(unsigned int)unit
582: {
583: return _drives[unit].ideIdentifyInfoSupported ?
584: _drives[unit].multiSector : 0;
585: }
586:
587: - (void)ideCntrlrLock
588: {
589: [_ideCmdLock lock];
590: }
591:
592: - (void)ideCntrlrUnLock
593: {
594: [_ideCmdLock unlock];
595: }
596:
597: /*
598: * There is no need for separate ATAPI locks but we keep them for testing
599: * purposes.
600: */
601: - (void)atapiCntrlrLock
602: {
603: [_ideCmdLock lock];
604: }
605:
606: - (void)atapiCntrlrUnLock
607: {
608: [_ideCmdLock unlock];
609: }
610:
611: /*
612: * The ATAPI driver (CD-ROM or Tape) will scan thorugh this list of devices
613: * looking for ATAPI hardware.
614: */
615: - (unsigned int)numDevices
616: {
617: return MAX_IDE_DRIVES;
618: }
619:
620: - (BOOL)isAtapiDevice:(unsigned char)unit
621: {
622: if (unit >= MAX_IDE_DRIVES)
623: return NO;
624:
625: return _drives[unit].atapiDevice;
626: }
627:
628: - (BOOL)isAtapiCommandActive:(unsigned char)unit
629: {
630: return _drives[unit].atapiCommandActive;
631: }
632:
633: - (void)setAtapiCommandActive:(BOOL)state forUnit:(unsigned char)unit
634: {
635: _drives[unit].atapiCommandActive = state;
636: }
637:
638: - (BOOL) isDmaSupported:(unsigned int)unit
639: {
640: return (_drives[unit].transferType != IDE_TRANSFER_PIO);
641: }
642:
643: /*
644: * Simply forward the interrupt.
645: */
646: static void ideInterruptHandler(void *identity, void *state, unsigned int arg)
647: {
648: #ifdef NO_IRQ_MSG
649: ideStruct_t *obj = (ideStruct_t *)arg;
650: obj->interruptOccurred = YES;
651: thread_wakeup_one(&obj->waitQueue);
652: #else NO_IRQ_MSG
653: IOSendInterrupt(identity, state, IO_DEVICE_INTERRUPT_MSG);
654: #endif NO_IRQ_MSG
655: }
656:
657: - (BOOL)getHandler:(IOEISAInterruptHandler *)handler
658: level:(unsigned int *)ipl
659: argument:(unsigned int *)arg
660: forInterrupt:(unsigned int)localInterrupt
661: {
662: *handler = ideInterruptHandler;
663: *ipl = IPLDEVICE;
664: *arg = (unsigned int)self;
665: return YES;
666: }
667:
668: /*
669: * Power management.
670: */
671: - (idePowerState_t)drivePowerState
672: {
673: return _drivePowerState;
674: }
675:
676: - (void)setDrivePowerState:(idePowerState_t)state
677: {
678: _drivePowerState = state;
679: }
680:
681: - (void)putDriveToSleep
682: {
683: if ([self drivePowerState] == IDE_PM_SLEEP)
684: return;
685:
686: _driveSleepRequest = YES;
687: ddm_ide_lock("putDriveToSleep: acquiring lock, suspend\n",1,2,3,4,5);
688: [self ideCntrlrLock];
689: ddm_ide_lock("putDriveToSleep: acquired lock, suspend\n",1,2,3,4,5);
690: #ifdef DEBUG
691: IOLog("%s: Entering suspend mode.\n", [self name]);
692: #endif DEBUG
693: [self setDrivePowerState:IDE_PM_SLEEP];
694: }
695:
696: /*
697: * The method wakeUpDrive simply sets a flag. The drive is actually woken up
698: * the next time we need it. This is done by a call from
699: * ideExecuteCmd:ToDrive: method to the spinUpDrive:unit: method below.
700: */
701: - (void)wakeUpDrive
702: {
703: if ([self drivePowerState] == IDE_PM_ACTIVE)
704: return;
705:
706: _driveSleepRequest = NO;
707: ddm_ide_lock("wakeUpDrive: Exiting suspend mode.\n", 1,2,3,4,5);
708: [self setDrivePowerState:IDE_PM_STANDBY];
709: ddm_ide_lock("wakeUpDrive: releasing lock, recovered\n",1,2,3,4,5);
710: [self ideCntrlrUnLock];
711: }
712:
713: /*
714: * This will get the drive to spin up. We simply try to read a single sector
715: * and are prepared to camp out for a very long time (>>30 secs).
716: */
717: #define MAX_MEDIA_ACCESS_TRIES 30
718:
719: - (BOOL)spinUpDrive:(unsigned int)unit
720: {
721: unsigned char status;
722: int i, j;
723: unsigned char dh;
724:
725: dh = _drives[unit].addressMode | (unit ? SEL_DRIVE1 : SEL_DRIVE0);
726:
727: for (i = 0; i < MAX_MEDIA_ACCESS_TRIES; i++) {
728:
729: [self ideReset];
730: [self disableInterrupts];
731:
732: /*
733: * Read one sector at (0,0,1). (LBA == 1).
734: */
735: outb(_ideRegsAddrs.drHead, dh);
736: outb(_ideRegsAddrs.sectNum, 0x1);
737: outb(_ideRegsAddrs.sectCnt, 0x1);
738: outb(_ideRegsAddrs.cylLow, 0x0);
739: outb(_ideRegsAddrs.cylHigh, 0x0);
740: outb(_ideRegsAddrs.command, IDE_READ);
741:
742: /*
743: * Wait for about ten seconds for response from drive.
744: */
745: for (j = 0; j < 5; j++) {
746: IOSleep(2000);
747: status = inb(_ideRegsAddrs.status);
748: if ((!(status & BUSY)) && (status & DREQUEST)) {
749: [self ideReset]; /* FIXME: may not be needed */
750: IOLog("%s: Recovered from suspend mode.\n", [self name]);
751: return YES;
752: }
753: }
754: IOLog("%s: Retrying to recover from suspend mode.\n", [self name]);
755: }
756:
757: IOLog("%s: Failed to recover from suspend mode.\n", [self name]);
758: return NO;
759: }
760:
761: /*
762: * We need to get the ATA drives spinning before we can try to reset them.
763: * The situation gets complicated if the ATA and ATAPI device share the same
764: * cable. We basically start up all devices on this controller.
765: */
766: - (BOOL)startUpAttachedDevices
767: {
768: int i;
769: BOOL status = YES;
770:
771: /* Spin up only ATA drives */
772: for (i = 0; i < MAX_IDE_DRIVES; i++) {
773: if ((_drives[i].ideInfo.type != 0) && ([self isAtapiDevice:i] == NO)) {
774: status = [self spinUpDrive:i];
775: }
776: }
777:
778: [self resetAndInit];
779: [self setDrivePowerState:IDE_PM_ACTIVE];
780:
781: return status;
782: }
783:
784: - (IOReturn) getPowerState:(PMPowerState *)state_p
785: {
786: return IO_R_UNSUPPORTED;
787: }
788:
789: - (IOReturn) setPowerState:(PMPowerState)state
790: {
791: if (state == PM_READY) {
792: [self wakeUpDrive];
793: } else if (state == PM_SUSPENDED) {
794: [self putDriveToSleep];
795: } else {
796: //IOLog("%s: unknown APM event %x\n", [self name], (unsigned int)state);
797: }
798:
799: return IO_R_SUCCESS;
800: }
801:
802: - (IOReturn) getPowerManagement:(PMPowerManagementState *)state_p
803: {
804: return IO_R_UNSUPPORTED;
805: }
806:
807: - (IOReturn) setPowerManagement:(PMPowerManagementState)state
808: {
809: return IO_R_UNSUPPORTED;
810: }
811:
812: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
813: {
814: strcpy( classes, IOClassIDEController);
815: return( self);
816: }
817:
818: - property_IODeviceType:(char *)types length:(unsigned int *)maxLen
819: {
820: strcat( types, " "IOTypeIDE);
821: return( self);
822: }
823:
824: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.