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

unix.superglobalmegacorp.com

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