Annotation of drvEIDE/EIDE.drvproj/EIDE.lksproj/IdeCnt.m, revision 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.