Annotation of kernel/bsd/dev/ppc/drvPPCATA/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.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.