Annotation of drvEIDE/EIDE.drvproj/EIDE.lksproj/IdeCnt.m, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.