Annotation of kernel/bsd/dev/ppc/drvPPCATA/IdeCntInit.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) 1994-1997 NeXT Software, Inc.  All rights reserved. 
        !            28:  *
        !            29:  * IdeCntInit.m - ATA controller initialization module. 
        !            30:  *
        !            31:  */
        !            32: 
        !            33: #import <driverkit/kernelDriver.h>
        !            34: #import <driverkit/interruptMsg.h>
        !            35: #import <mach/mach_interface.h>
        !            36: #import <driverkit/IODevice.h>
        !            37: #import <driverkit/ppc/IOTreeDevice.h>
        !            38: #import <driverkit/ppc/IODBDMA.h>
        !            39: #import <driverkit/align.h>
        !            40: #import <machkit/NXLock.h>
        !            41: #import "IdeDDM.h"
        !            42: #import "io_inline.h"
        !            43: #import <driverkit/return.h>
        !            44: #import <mach/port.h>
        !            45: #import <machdep/ppc/powermac.h>
        !            46: #import <bsd/sys/systm.h>
        !            47: 
        !            48: #import "IdeCnt.h"
        !            49: #import "IdeCntInit.h"
        !            50: #import "IdeCntCmds.h"
        !            51: #import "IdeCntDma.h"
        !            52: #import "AtapiCntCmds.h"
        !            53: 
        !            54: 
        !            55: #define IDE_SYSCLK_NS  30
        !            56: 
        !            57: typedef struct
        !            58: {
        !            59:     int                accessTime;
        !            60:     int                cycleTime;
        !            61: } ideModes_t;
        !            62: 
        !            63: static ideModes_t pioModes[] =
        !            64: {
        !            65:     { 165,    600 },   /* Mode 0 */
        !            66:     { 125,    383 },   /*      1 */ 
        !            67:     { 100,    240 },   /*      2 */
        !            68:     {  80,    180 },   /*      3 */
        !            69:     {  70,    120 }    /*      4 */
        !            70: };
        !            71: #define MAX_PIO_MODES  (sizeof(pioModes) / sizeof(ideModes_t))
        !            72: 
        !            73: static ideModes_t singleWordModes[] =
        !            74: {
        !            75:     { 480,    960 },   /* Mode 0 */
        !            76:     { 100,    480 },   /*      1 */
        !            77:     { 120,    240 }    /*      2 */
        !            78: };
        !            79: #define MAX_SINGLEWORD_MODES  (sizeof(singleWordModes) / sizeof(ideModes_t))
        !            80: 
        !            81: static ideModes_t multiWordModes[] =
        !            82: {
        !            83:     { 215,    480 },   /* Mode 0 */
        !            84:     {  80,    150 },   /*      1 */
        !            85:     {  70,    120 }    /*      2 */
        !            86: };
        !            87: #define MAX_MULTIWORD_MODES  (sizeof(multiWordModes) / sizeof(ideModes_t))
        !            88: 
        !            89: 
        !            90: static ideModes_t ultraModes[] =
        !            91: {
        !            92:     {   0,    114 },   /* Mode 0 */
        !            93:     {   0,     75 },   /*      1 */
        !            94:     {   0,     55 }    /*      2 */
        !            95: };
        !            96: 
        !            97: #define MAX_ULTRA_MODES  (sizeof(ultraModes) / sizeof(ideModes_t))
        !            98: 
        !            99: 
        !           100: static void endianSwap16Bit( volatile u_int16_t *p16 )
        !           101: {
        !           102:     u_int16_t     tmp16;
        !           103:     
        !           104:     tmp16 = *p16;
        !           105:     tmp16 = (tmp16 >> 8) | (tmp16 << 8);
        !           106:     *p16  = tmp16;
        !           107: }
        !           108: 
        !           109: static void endianSwap32Bit( volatile u_int32_t *p32 )
        !           110: {
        !           111:     u_int32_t     tmp32;
        !           112:     
        !           113:     tmp32 = *p32;
        !           114: 
        !           115:     tmp32 = ( ((tmp32 & 0x000000ff) << 24)
        !           116:             | ((tmp32 & 0x0000ff00) <<  8)
        !           117:             | ((tmp32 & 0x00ff0000) >>  8)
        !           118:             | ((tmp32 & 0xff000000) >> 24) );
        !           119: 
        !           120:     *p32  = tmp32;
        !           121: }
        !           122: 
        !           123: static int rnddiv( int x, int y )
        !           124: {
        !           125:     if ( x < 0 )
        !           126:       return 0;
        !           127:     else
        !           128:       return ( (x / y) + (( x % y ) ? 1 : 0) );
        !           129: }
        !           130: 
        !           131: @implementation IdeController(Initialize)
        !           132: 
        !           133: 
        !           134: /*
        !           135:  * Check for MediaBay 
        !           136:  *
        !           137:  * Returns: NO  - MediaBay implementation with non-ATA/ATAPI option installed
        !           138:  *          YES - Non-MediaBay implementation or MediaBay with ATA/ATAPI option
        !           139:  */
        !           140: - (BOOL) checkMediaBayOption: (IOTreeDevice *)deviceDescription
        !           141: {
        !           142:     int                        n;
        !           143:     u_int32_t          *heathrowIdReg;
        !           144:     u_int32_t          heathrowIds;
        !           145:     IOTreeDevice       *devDescParent;
        !           146:     char               *nodeNameParent;
        !           147: 
        !           148:     /*
        !           149:      * Check for MediaBay implementation 
        !           150:      */
        !           151:     devDescParent  = [[deviceDescription parent] deviceDescription];
        !           152:     nodeNameParent = [devDescParent nodeName];
        !           153: 
        !           154:     if ( strcmp( nodeNameParent, "media-bay" ) )
        !           155:     {
        !           156:         return YES;    /* Non-MediaBay implementation */
        !           157:     }
        !           158:     if ( (n = [devDescParent numMemoryRanges]) < 1 )
        !           159:     {
        !           160:         return YES;    /* Misc OF Device Tree problem */
        !           161:     }
        !           162:        
        !           163:     /* 
        !           164:      * Check for ATA/ATAPI MediaBay option installed
        !           165:      */
        !           166:     heathrowIdReg = (u_int32_t *)[devDescParent memoryRangeList][0].start; 
        !           167:     heathrowIds   = *heathrowIdReg;
        !           168:     endianSwap32Bit( &heathrowIds );
        !           169: 
        !           170:     if ( (heathrowIds & MEDIA_BAY_ID_MASK) == MEDIA_BAY_ID_CDROM )
        !           171:     {
        !           172:         return YES;    /* Media Bay with ATA/ATAPI option */
        !           173:     }
        !           174: 
        !           175:     return NO; 
        !           176: }
        !           177: 
        !           178: #define ATAPI_SIGNATURE_LOW            0x14
        !           179: #define ATAPI_SIGNATURE_HIGH           0xeb
        !           180: 
        !           181: #define ATA_SIGNATURE_LOW              0x00
        !           182: #define ATA_SIGNATURE_HIGH             0x00
        !           183: 
        !           184: /*
        !           185:  * This is called just after resetting the drives connected to this
        !           186:  * controller. We read the drive registers to figure out if it is an ATAPI
        !           187:  * drive. If it is then we make a note of it and return YES. 
        !           188:  */
        !           189: - (BOOL)controllerPresent
        !           190: {
        !           191:     unsigned char dh;
        !           192:     unsigned char unit;
        !           193:     
        !           194:     unit = 0;
        !           195:     
        !           196:     dh = _addressMode[unit];
        !           197:     
        !           198:     dh |= (unit ? SEL_DRIVE1 : SEL_DRIVE0);
        !           199:     outb(_ideRegsAddrs.drHead, dh);
        !           200: 
        !           201:     /*
        !           202:      * Test with some data. 
        !           203:      */
        !           204:     
        !           205:     if (unit == 0)     
        !           206:     {
        !           207:        outb(_ideRegsAddrs.cylLow, 0xaa);
        !           208:        outb(_ideRegsAddrs.cylHigh, 0xbb);
        !           209:     } 
        !           210:     else 
        !           211:     {
        !           212:        outb(_ideRegsAddrs.cylLow, 0xba);
        !           213:        outb(_ideRegsAddrs.cylHigh, 0xbe);
        !           214:     }
        !           215:     
        !           216:     if (unit == 0) 
        !           217:     {
        !           218:        if ((inb(_ideRegsAddrs.cylLow) != 0xaa) ||
        !           219:            (inb(_ideRegsAddrs.cylHigh) != 0xbb)) 
        !           220:         {
        !           221:            return NO;
        !           222:        }
        !           223:     } 
        !           224:     else 
        !           225:     {
        !           226:        if ((inb(_ideRegsAddrs.cylLow) != 0xba) ||
        !           227:            (inb(_ideRegsAddrs.cylHigh) != 0xbe)) 
        !           228:         {
        !           229:            return NO;
        !           230:        }
        !           231:     }
        !           232:     
        !           233:     return YES;
        !           234: }
        !           235: 
        !           236: 
        !           237: /*
        !           238:  * One-time only init. Returns NO on failure. 
        !           239:  */
        !           240: - (BOOL)ideControllerInit:(IOTreeDevice *)deviceDescription
        !           241: {
        !           242:     int                unit;
        !           243:     int                drivesPresent = 0;
        !           244:     ns_time_t          time, startTime;
        !           245: 
        !           246:     if ([self enableInterrupt:0]) {
        !           247:                IOLog("ideControllerInit: failed enableAllInterrupts\n");
        !           248:                return NO;
        !           249:     }
        !           250: 
        !           251:     
        !           252:     if ((_ideCmdLock = [NXLock new]) == NULL) {
        !           253:                IOLog("ideControllerInit: failed _ideCmdLock\n");
        !           254:        return NO;
        !           255:     }
        !           256:     
        !           257:     /*
        !           258:      * We don't want to execute any IDE commands from Disk until
        !           259:      * initialization is complete. 
        !           260:      */
        !           261:     [self ideCntrlrLock];
        !           262:     
        !           263:     /*
        !           264:      * Initialize the register address values.
        !           265:      */
        !           266:     [self assignRegisterAddresses: deviceDescription];
        !           267:         
        !           268:     for (unit = 0; unit < MAX_IDE_DRIVES; unit++) {
        !           269:        _atapiDevice[unit] = NO;
        !           270:     }
        !           271:     
        !           272:     /*
        !           273:      * We have to test here if the controller is present or else we will
        !           274:      * block looking for a drive (in ideReset). 
        !           275:      */
        !           276:     
        !           277:     if ([self controllerPresent] == NO)        
        !           278:     {
        !           279:        IOLog("%s: no devices detected at port 0x%0x\n", [self name],
        !           280:                _ideRegsAddrs.data);
        !           281:        [self ideCntrlrUnLock];
        !           282:        return NO;
        !           283:     } 
        !           284:     else 
        !           285:     {
        !           286:        IOLog("%s: device detected at port 0x%x irq %d\n", [self name], 
        !           287:                        _ideRegsAddrs.data, [deviceDescription interrupt]);
        !           288:     }
        !           289:     
        !           290:     _ideInterruptPort = [self interruptPort];
        !           291:     _ideDevicePort = [deviceDescription devicePort];
        !           292: 
        !           293:     [self setInterruptTimeOut:IDE_INTR_TIMEOUT];
        !           294: 
        !           295:     _multiSectorRequested = YES;
        !           296: 
        !           297:     for (unit = 0; unit < MAX_IDE_DRIVES; unit++) 
        !           298:     {
        !           299:        _addressMode[unit] = ADDRESS_MODE_LBA;
        !           300:     }
        !           301: 
        !           302:     _driveNum = unit;
        !           303:     
        !           304:     for (unit = 0; unit < MAX_IDE_DRIVES; unit++) 
        !           305:     {
        !           306:     
        !           307:        bzero(&_ideInfo[unit], sizeof(ideDriveInfo_t));
        !           308:        
        !           309:        [self ideReset];
        !           310:        
        !           311:         IOGetTimestamp(&startTime);
        !           312:        if ([self ideDetectDrive:unit] == YES)  
        !           313:         {
        !           314:            _ideInfo[unit].type = 255;
        !           315:        }
        !           316:         IOGetTimestamp(&time);
        !           317:         time = (time - startTime) / (1000*1000);
        !           318:         kprintf( "Disk(ata) - ideDetectDrive:%d - %d ms\n\r", unit, (u_int32_t)time ); 
        !           319:  
        !           320:        /*
        !           321:         * If we didn't find ATA drive then look for ATAPI device. 
        !           322:         */
        !           323:        if ((_ideInfo[unit].type == 0)  && ([self ideDetectATAPIDevice:unit] == YES)) 
        !           324:         {
        !           325:            _ideInfo[unit].type = 127;
        !           326:        }
        !           327: 
        !           328:        if (_ideInfo[unit].type != 0)
        !           329:            drivesPresent += 1 ;
        !           330:     }
        !           331:     
        !           332:     if (drivesPresent == 0)    
        !           333:     {
        !           334:        [self ideCntrlrUnLock];
        !           335:        IOLog("ideControllerInit: failed drivesPresent\n");
        !           336:        return NO;
        !           337:     }
        !           338: 
        !           339:     /*
        !           340:      * Initialization was successful. We should release the lock so that the
        !           341:      * controller can now execute commands from disk objects. 
        !           342:      */
        !           343:     
        !           344:     [self resetAndInit];
        !           345: 
        !           346:     /*
        !           347:      * Set drive power state to active.
        !           348:      */
        !           349:     for (unit = 0; unit < MAX_IDE_DRIVES; unit++) 
        !           350:     {
        !           351:        if (_ideInfo[unit].type != 0)
        !           352:            [self setDrivePowerState:IDE_PM_ACTIVE];
        !           353:     }
        !           354:     
        !           355:     _driveSleepRequest = NO;
        !           356:     
        !           357:     [self enableInterrupts];
        !           358: 
        !           359:     [self ideCntrlrUnLock];
        !           360:     
        !           361:     return YES;
        !           362: }    
        !           363: 
        !           364: #define ATA_RESET_DELAY                (30 * 1000)             /* milliseconds */
        !           365: 
        !           366: /*
        !           367:  * Determine the presence and type of drive (IDE/ATAPI) attached to this
        !           368:  * controller. 
        !           369:  *
        !           370:  */
        !           371: 
        !           372: -(BOOL)ideDetectDrive:(unsigned int)unit
        !           373: {
        !           374:     unsigned char      dh = _addressMode[unit];
        !           375:     int                i;
        !           376:     unsigned char      status;
        !           377:     BOOL               found = NO;
        !           378: 
        !           379:     [self disableInterrupts];
        !           380:     
        !           381:     dh |= (unit ? SEL_DRIVE1 : SEL_DRIVE0);
        !           382:     outb(_ideRegsAddrs.drHead, dh);
        !           383:     IODelay(10);
        !           384: 
        !           385:     status = inb(_ideRegsAddrs.status);
        !           386:     if ( !(status & READY) )
        !           387:     {
        !           388:         return found;
        !           389:     }
        !           390:   
        !           391:     outb(_ideRegsAddrs.command, IDE_IDENTIFY_DRIVE);
        !           392: 
        !           393:     for (i = 0; i < (ATA_RESET_DELAY * 5); i++) 
        !           394:     {
        !           395:        IODelay(200);
        !           396:         status = inb(_ideRegsAddrs.status);
        !           397: 
        !           398:        if ((!(status & BUSY)) && (status & (ERROR | WRITE_FAULT | ERROR_CORRECTED)) )
        !           399:         {
        !           400:            break;                              /* certain failure */
        !           401:        }
        !           402:        
        !           403:        if ((!(status & BUSY)) && (status & DREQUEST))  
        !           404:         {
        !           405:            found = YES;                        /* success */
        !           406:            break;
        !           407:        }    
        !           408:     }
        !           409: 
        !           410:     return found;    
        !           411: }
        !           412: 
        !           413: /*
        !           414:  * We send the device ATAPI soft reset command and check for signature. This
        !           415:  * is the first command that ATAPI devices need. 
        !           416:  */
        !           417: -(BOOL)ideDetectATAPIDevice:(unsigned int)unit
        !           418: {
        !           419:     unsigned char low, high;
        !           420:     BOOL found = NO;
        !           421:        
        !           422:     [self atapiSoftReset:unit];
        !           423: 
        !           424:     low = inb(_ideRegsAddrs.cylLow);
        !           425:     high = inb(_ideRegsAddrs.cylHigh);
        !           426:     
        !           427:     if ((low == ATAPI_SIGNATURE_LOW) && (high == ATAPI_SIGNATURE_HIGH))
        !           428:     {
        !           429:        _atapiDevice[unit] = YES;
        !           430:        IOLog("%s: ATAPI device %d detected.\n", [self name], unit);
        !           431:        found = YES;
        !           432:     }
        !           433:     /*
        !           434:      * Clear ATAPI signature
        !           435:      */
        !           436:     outb(_ideRegsAddrs.cylLow, 0 );
        !           437:     outb(_ideRegsAddrs.cylHigh, 0 );
        !           438:     
        !           439:     return found;    
        !           440: }
        !           441: 
        !           442: 
        !           443: -(ideDriveInfo_t *)getIdeDriveInfo:(unsigned int)unit
        !           444: {
        !           445:     return &_ideInfo[unit];
        !           446: }
        !           447: 
        !           448: #define MAX_RESET_ATTEMPTS             2
        !           449: 
        !           450: - (void)ideReset
        !           451: {
        !           452:     int                count;
        !           453:     int                delay;
        !           454:     unsigned char      status;
        !           455: 
        !           456:     for ( count = 0; count < MAX_IDE_DRIVES; count++ )
        !           457:     {
        !           458:         _driveReset[count] = YES;
        !           459:     }
        !           460: 
        !           461:     for (count = 0; count < MAX_RESET_ATTEMPTS; count++) 
        !           462:     {
        !           463:        outb(_ideRegsAddrs.deviceControl, DISK_RESET_ENABLE);
        !           464:        IODelay(100);                   /* spec >= 25 us */
        !           465:        outb(_ideRegsAddrs.deviceControl, 0x0);
        !           466:        
        !           467:        [self enableInterrupts];
        !           468: 
        !           469:        delay = 31 * 1000 * 1000;       /* thirty one seconds */
        !           470:        
        !           471:        IOSleep(1000);                  /* Enough time to assert busy */
        !           472:        
        !           473:        while (delay > 0) 
        !           474:         {
        !           475:            status = inb(_ideRegsAddrs.status);
        !           476:            if (!(status & BUSY)) 
        !           477:             {
        !           478:                return;
        !           479:            }
        !           480:            
        !           481:            IOSleep(1);
        !           482:            delay -= 1000;
        !           483:        }
        !           484:        
        !           485:        IOLog("%s: Reset failed, retrying..\n", [self name]);
        !           486:        IOSleep(2000);
        !           487:     }    
        !           488: }
        !           489: 
        !           490: 
        !           491: /*
        !           492:  * Initialize the IDE interface. Find about drive capabilities (by
        !           493:  * IDE_IDENTIFY_DRIVE command) and configure drive.
        !           494:  * 
        !           495:  * By the time we enter this routine we know about all devices connected to this controller. 
        !           496:  */
        !           497: - (void)resetAndInit
        !           498: {
        !           499:     int                        i;
        !           500:     unsigned char              unit;
        !           501:     ide_return_t               rtn;
        !           502:     atapi_return_t             atapi_rtn;
        !           503:     BOOL                       ataDevicePresent;
        !           504: 
        !           505:     /*
        !           506:      * If there is at least one ATA drive connected to this controller then
        !           507:      * is is not necessary to (ATA style) reset them. We use the ATAPI reset
        !           508:      * instead. 
        !           509:      */
        !           510:     ataDevicePresent = NO;
        !           511:     for (i = 0; i < MAX_IDE_DRIVES; i++)       
        !           512:     {
        !           513:        if ((_ideInfo[i].type != 0) && ([self isAtapiDevice:i] == NO))
        !           514:         {
        !           515:            ataDevicePresent = YES;
        !           516:            break;
        !           517:        }
        !           518:     }
        !           519: 
        !           520:     if (ataDevicePresent == YES)       
        !           521:     {
        !           522:        [self ideReset];
        !           523:     }
        !           524:     
        !           525:     /*
        !           526:      * Send the controller necessary commands to set capabilities and then
        !           527:      * set drive parameters. It is necessary to set drive parameters before
        !           528:      * any data I/O can be done from the disk. 
        !           529:      */
        !           530:     for (unit = 0; unit < MAX_IDE_DRIVES; unit++) 
        !           531:     {
        !           532:        if (_ideInfo[unit].type == 0)   
        !           533:         {
        !           534:            continue;
        !           535:        }
        !           536:        
        !           537:        _driveNum = unit;
        !           538: 
        !           539:         _cycleTimes[unit].pioMode = 0;
        !           540:         _cycleTimes[unit].pioAccessTime  = pioModes[0].accessTime;
        !           541:         _cycleTimes[unit].pioCycleTime   = pioModes[0].cycleTime;
        !           542: 
        !           543:         [self calcIdeConfig: unit];          
        !           544:        
        !           545:        if ( [self isAtapiDevice:unit] == YES ) 
        !           546:         {
        !           547:            [self atapiSoftReset:unit];
        !           548: 
        !           549:            /*
        !           550:             * We have to do this test because of "task file shadow" bug
        !           551:             * present in many ATAPI CD-ROMs. 
        !           552:             */
        !           553:            atapi_rtn = 
        !           554:                [self atapiIdentifyDevice:(struct vm_map *)IOVmTaskSelf() 
        !           555:                    addr:(unsigned char *)&_ideIdentifyInfo[unit] unit:unit];
        !           556:                
        !           557:            /* Too bad.. */
        !           558:            if (atapi_rtn != IDER_SUCCESS)      
        !           559:             {
        !           560:                _atapiDevice[unit] = NO;
        !           561:                _ideInfo[unit].type = 0;
        !           562:                continue;
        !           563:            }
        !           564:                
        !           565:             [self endianSwapIdentifyData: &_ideIdentifyInfo[unit]];
        !           566: 
        !           567:            [self printAtapiInfo:&_ideIdentifyInfo[unit] Device:unit];
        !           568:            [self atapiInitParameters:&_ideIdentifyInfo[unit] Device:unit];
        !           569:            continue;
        !           570:        }
        !           571: 
        !           572:        rtn = [self setATADriveCapabilities:unit];
        !           573:        if (rtn != IDER_SUCCESS)        
        !           574:         {
        !           575:                _ideInfo[unit].type = 0;
        !           576:                continue;
        !           577:        }
        !           578:     }
        !           579: }
        !           580: 
        !           581: /*
        !           582:  * FIXME: Need to figure out multi-word DMA.
        !           583:  */
        !           584: - (ide_return_t)getTransferModes:(ideIdentifyInfo_t *)infoPtr Unit: (int)unit
        !           585: {
        !           586:     int                i, n;
        !           587:      
        !           588:     int         pioMode                = 0;
        !           589:     int                pioCycleTime    = 0;
        !           590:     int         dmaMode                = 0;
        !           591:     int         dmaType                = IDE_DMA_NONE;
        !           592:     int         dmaCycleTime   = 0;
        !           593:     
        !           594:     /*
        !           595:      *  PIO Cycle timing......  
        !           596:      *
        !           597:      *  1. Try to match Word 51 (pioCycleTime) with cycle timings
        !           598:      *     in our pioModes table to get mode/CycleTime. (Valid for Modes 0-2)
        !           599:      *  2. If Words 64-68 are supported and Mode 3 or 4 supported check, 
        !           600:      *     update CycleTime with Word 68 (CycleTimeWithIORDY).
        !           601:      */
        !           602: 
        !           603:     pioCycleTime = infoPtr->pioDataTransferCyleTimingMode;
        !           604: 
        !           605:     if ( pioCycleTime > 2 )
        !           606:     {
        !           607:         for ( i=MAX_PIO_MODES-1; i != -1; i-- )
        !           608:         {
        !           609:             if ( pioCycleTime <= pioModes[i].cycleTime )
        !           610:             {
        !           611:                 pioMode = i;
        !           612:                 break;
        !           613:             }
        !           614:          }
        !           615: 
        !           616:          if ( i == -1 )
        !           617:          {
        !           618:              pioCycleTime = pioModes[pioMode].cycleTime;
        !           619:          }
        !           620:     }
        !           621:     else
        !           622:     {
        !           623:         pioMode      = pioCycleTime;
        !           624:         pioCycleTime = pioModes[pioMode].cycleTime;
        !           625:     }
        !           626: 
        !           627:     if (infoPtr->fieldValidity & IDE_WORDS64_TO_68_SUPPORTED) 
        !           628:     {
        !           629:        if (infoPtr->fcPioDataTransferCyleTimingMode & IDE_FC_PIO_MODE_4_SUPPORTED)
        !           630:             pioMode = 4;
        !           631:        else if (infoPtr->fcPioDataTransferCyleTimingMode & IDE_FC_PIO_MODE_3_SUPPORTED)
        !           632:             pioMode = 3;
        !           633: 
        !           634:         if ( (pioMode >= 3) && infoPtr->MinPIOTransferCycleTimeWithIORDY )
        !           635:         {
        !           636:             pioCycleTime = infoPtr->MinPIOTransferCycleTimeWithIORDY;
        !           637:         }
        !           638:     }
        !           639:     
        !           640:     /* 
        !           641:      *  Ultra DMA timing.....
        !           642:      *
        !           643:      */                                                                
        !           644:     if ( (_controllerType == kControllerTypeCmd646X) && (infoPtr->fieldValidity & IDE_WORD_88_SUPPORTED) ) 
        !           645:     {
        !           646:         n = infoPtr->ultraDma & IDE_ULTRA_DMA_SUPPORTED;
        !           647:         if ( n )
        !           648:         {
        !           649:             dmaType = IDE_DMA_ULTRA;
        !           650:             for ( i=0; n; i++, n>>=1 )
        !           651:               ;
        !           652: 
        !           653:             dmaMode = i - 1;
        !           654:             if ( dmaMode > MAX_ULTRA_MODES-1 )
        !           655:             {
        !           656:                 dmaMode = MAX_ULTRA_MODES-1;
        !           657:             }
        !           658:             dmaCycleTime = ultraModes[dmaMode].cycleTime;
        !           659: 
        !           660:             goto getCycleTimes_exit;
        !           661:         }
        !           662:     }
        !           663:             
        !           664:     /* 
        !           665:      *  Multiword DMA timing.....
        !           666:      *
        !           667:      *  1. Check Word 63(7:0) (Multiword DMA Modes Supported). Lookup
        !           668:      *     CycleTime for highest mode we support.
        !           669:      *  2. If Words 64-68 supported, update CycleTime from Word 66
        !           670:      *     (RecommendedMultiWordCycleTime) if specified.
        !           671:      */                                                                
        !           672: 
        !           673:     n = infoPtr->mwDma & IDE_MW_DMA_SUPPORTED;
        !           674:     if ( n )
        !           675:     {
        !           676:         dmaType = IDE_DMA_MULTIWORD;
        !           677:         for ( i=0; n; i++, n>>=1 )
        !           678:           ;
        !           679: 
        !           680:         dmaMode = i - 1;
        !           681:         if ( dmaMode > MAX_MULTIWORD_MODES-1 )
        !           682:         {
        !           683:             dmaMode = MAX_MULTIWORD_MODES-1;
        !           684:         }
        !           685:         dmaCycleTime = multiWordModes[dmaMode].cycleTime;
        !           686: 
        !           687:         if (infoPtr->fieldValidity & IDE_WORDS64_TO_68_SUPPORTED) 
        !           688:         {
        !           689:             if ( infoPtr->RecommendedMwDMACycleTime )
        !           690:             {
        !           691:                 dmaCycleTime = infoPtr->RecommendedMwDMACycleTime;
        !           692:             }
        !           693:         }
        !           694:         goto getCycleTimes_exit;
        !           695:     }
        !           696: 
        !           697:     /*
        !           698:      *  Single Word DMA timing.....
        !           699:      *
        !           700:      *  1. If Word 64(7:0) (SingleWord DMA Modes supported) is non-zero,
        !           701:      *     find highest supported mode and get CycleTime from table.
        !           702:      *  2. If Word 64(7:0) (SingleWord DMA Modes supported) is zero,
        !           703:      *     then match Word 52 (Single Word DMA Cycle Time) against
        !           704:      *     cycle times in singleWordModes table.
        !           705:      */          
        !           706:        
        !           707:     n = infoPtr->swDma & IDE_SW_DMA_SUPPORTED;
        !           708:     if ( n )
        !           709:     {
        !           710:         dmaType = IDE_DMA_SINGLEWORD;
        !           711:         for ( i=0; n; i++, n>>=1 )
        !           712:           ;
        !           713: 
        !           714:         dmaMode = i - 1;
        !           715:         if ( dmaMode > MAX_SINGLEWORD_MODES-1 )
        !           716:         {
        !           717:             dmaMode = MAX_SINGLEWORD_MODES-1;
        !           718:         }
        !           719:         dmaCycleTime = singleWordModes[dmaMode].cycleTime;
        !           720:     }
        !           721:     else
        !           722:     {
        !           723:         dmaCycleTime = infoPtr->dmaDataTransferCyleTimingMode;
        !           724:         for ( i=MAX_SINGLEWORD_MODES-1; i != -1; i-- )
        !           725:         {
        !           726:             if ( dmaCycleTime <= singleWordModes[i].cycleTime )
        !           727:             {
        !           728:                 dmaType = IDE_DMA_SINGLEWORD;
        !           729:                 dmaMode = i;
        !           730:                 dmaCycleTime = singleWordModes[i].cycleTime;
        !           731:                 break;
        !           732:             }
        !           733:         }
        !           734:     }
        !           735: 
        !           736: 
        !           737: getCycleTimes_exit: ;
        !           738: 
        !           739:     _cycleTimes[unit].pioCycleTime   = pioCycleTime;
        !           740:     _cycleTimes[unit].pioAccessTime  = pioModes[pioMode].accessTime;
        !           741:     _cycleTimes[unit].pioMode        = pioMode;
        !           742: 
        !           743:     if ( dmaType != IDE_DMA_NONE )
        !           744:     {
        !           745:         _cycleTimes[unit].dmaType        = dmaType;
        !           746:         _cycleTimes[unit].dmaMode        = dmaMode;
        !           747:         _cycleTimes[unit].dmaCycleTime   = dmaCycleTime;
        !           748:         switch ( dmaMode )
        !           749:         {
        !           750:             case IDE_DMA_SINGLEWORD:
        !           751:                 _cycleTimes[unit].dmaAccessTime = singleWordModes[dmaMode].accessTime;
        !           752:                 break;
        !           753:             case IDE_DMA_MULTIWORD:
        !           754:                 _cycleTimes[unit].dmaAccessTime = multiWordModes[dmaMode].accessTime;
        !           755:                 break;
        !           756:             case IDE_DMA_ULTRA:
        !           757:                 _cycleTimes[unit].dmaAccessTime = ultraModes[dmaMode].accessTime;
        !           758:                 break;
        !           759:         }    
        !           760:     }
        !           761: 
        !           762:     [self calcIdeConfig: (int)unit];
        !           763: 
        !           764:     
        !           765:     return IDER_SUCCESS;
        !           766: }
        !           767: 
        !           768: -(void) calcIdeConfig:(int)unit
        !           769: {
        !           770:     _cycleTimes[unit].fChanged = YES;
        !           771: 
        !           772:     if ( _controllerType == kControllerTypeCmd646X )
        !           773:     {
        !           774:         [self calcIdeTimingsCmd646X:unit];
        !           775:     }
        !           776:     else
        !           777:     {
        !           778:         [self calcIdeTimingsDBDMA:unit];
        !           779:     }
        !           780: }
        !           781: 
        !           782: -(void) calcIdeTimingsCmd646X:(int) unit
        !           783: {
        !           784:     u_int32_t          cycleClks;
        !           785:     u_int32_t          cycleTime,  accessTime;
        !           786:     u_int32_t          drwActClks, drwRecClks;
        !           787:     u_int32_t          drwActTime, drwRecTime;
        !           788:    
        !           789:     _cycleTimes[unit].ideConfig.cmd646XConfig.arttimReg  = 0x40;
        !           790:     _cycleTimes[unit].ideConfig.cmd646XConfig.cmdtimReg  = 0xA9;
        !           791: 
        !           792:     accessTime = pioModes[_cycleTimes[unit].pioMode].accessTime;
        !           793: 
        !           794:     drwActClks    =  accessTime / IDE_SYSCLK_NS;
        !           795:     drwActClks   += (accessTime % IDE_SYSCLK_NS) ? 1 : 0;
        !           796:     drwActTime    = drwActClks * IDE_SYSCLK_NS;
        !           797: 
        !           798:     drwRecTime    = pioModes[_cycleTimes[unit].pioMode].cycleTime - drwActTime;
        !           799:     drwRecClks    = drwRecTime / IDE_SYSCLK_NS;
        !           800:     drwRecClks   += (drwRecTime % IDE_SYSCLK_NS) ? 1 : 0;
        !           801: 
        !           802:     if ( drwRecClks >= 16 ) 
        !           803:         drwRecClks = 1;
        !           804:     else if ( drwRecClks <= 1 )
        !           805:         drwRecClks = 16;
        !           806: 
        !           807:     _cycleTimes[unit].ideConfig.cmd646XConfig.drwtimRegPIO = ((drwActClks & 0x0f) << 4) | ((drwRecClks-1)  & 0x0f);
        !           808: 
        !           809: 
        !           810:     _cycleTimes[unit].ideConfig.cmd646XConfig.udidetcrReg = 0;      
        !           811: 
        !           812:     if ( _cycleTimes[unit].dmaType == IDE_DMA_ULTRA )
        !           813:     {
        !           814:         cycleTime = _cycleTimes[unit].dmaCycleTime;
        !           815:         
        !           816:         cycleClks  = cycleTime / IDE_SYSCLK_NS;
        !           817:         cycleClks += (cycleTime % IDE_SYSCLK_NS) ? 1 : 0;
        !           818: 
        !           819:         _cycleTimes[unit].ideConfig.cmd646XConfig.udidetcrReg = (0x01 << unit) | ((cycleClks-1) << ((!unit) ? 4 : 6)) ;  
        !           820:     }
        !           821:     else if ( _cycleTimes[unit].dmaType != IDE_DMA_NONE )
        !           822:     {
        !           823:         accessTime    = _cycleTimes[unit].dmaAccessTime;
        !           824: 
        !           825:         drwActClks    =  accessTime / IDE_SYSCLK_NS;
        !           826:         drwActClks   += (accessTime % IDE_SYSCLK_NS) ? 1 : 0;
        !           827:         drwActTime    = drwActClks * IDE_SYSCLK_NS;
        !           828: 
        !           829:         drwRecTime    = _cycleTimes[unit].dmaCycleTime - drwActTime;
        !           830:         drwRecClks    = drwRecTime / IDE_SYSCLK_NS;
        !           831:         drwRecClks   += (drwRecTime % IDE_SYSCLK_NS) ? 1 : 0;
        !           832: 
        !           833:         if ( drwRecClks >= 16 ) 
        !           834:             drwRecClks = 1;
        !           835:         else if ( drwRecClks <= 1 )
        !           836:             drwRecClks = 16;
        !           837: 
        !           838:         _cycleTimes[0].ideConfig.cmd646XConfig.drwtimRegDMA = ((drwActClks & 0x0f) << 4) | ((drwRecClks-1)  & 0x0f);        
        !           839:     }
        !           840: }
        !           841:         
        !           842:  
        !           843: 
        !           844: -(void) calcIdeTimingsDBDMA:(int) unit
        !           845: {
        !           846:     int                        accessTime;
        !           847:     int                        accessTicks;
        !           848:     int                recTime;
        !           849:     int                        recTicks;
        !           850:     int                        cycleTime;
        !           851:     int                 cycleTimeOrig;
        !           852:     int                halfTick = 0;
        !           853:     uint                ideConfigWord = 0;
        !           854: 
        !           855:     /*
        !           856:      * Calc PIO access time >= pioAccessTime in SYSCLK increments
        !           857:      */
        !           858:     accessTicks = rnddiv(_cycleTimes[unit].pioAccessTime, IDE_SYSCLK_NS);
        !           859:     /*
        !           860:      * Hardware limits access times to >= 120 ns 
        !           861:      */
        !           862:     accessTicks -= IDE_PIO_ACCESS_BASE;
        !           863:     if (accessTicks < IDE_PIO_ACCESS_MIN )
        !           864:     {
        !           865:         accessTicks = IDE_PIO_ACCESS_MIN;
        !           866:     }
        !           867:     accessTime = (accessTicks + IDE_PIO_ACCESS_BASE) * IDE_SYSCLK_NS;
        !           868: 
        !           869:     /*
        !           870:      * Calc recovery time in SYSCLK increments based on time remaining in cycle
        !           871:      */
        !           872:     recTime = _cycleTimes[unit].pioCycleTime - accessTime;
        !           873:     recTicks = rnddiv( recTime, IDE_SYSCLK_NS );
        !           874:     /*
        !           875:      * Hardware limits recovery time to >= 150ns 
        !           876:      */
        !           877:     recTicks -= IDE_PIO_RECOVERY_BASE;
        !           878:     if ( recTicks < IDE_PIO_RECOVERY_MIN )
        !           879:     {
        !           880:       recTicks = IDE_PIO_RECOVERY_MIN;
        !           881:     }
        !           882: 
        !           883:     cycleTime = (recTicks + IDE_PIO_RECOVERY_BASE + accessTicks + IDE_PIO_ACCESS_BASE) * IDE_SYSCLK_NS;
        !           884: 
        !           885:     ideConfigWord = accessTicks | (recTicks << 5);
        !           886: 
        !           887:     kprintf("Disk(ata): Controller Base = %08x\n\r", _ideRegsAddrs.data );
        !           888:     kprintf("Disk(ata): Unit %1d: PIO Requested Timings: Access: %3dns Cycle: %3dns \n\r", 
        !           889:              unit, _cycleTimes[unit].pioAccessTime, _cycleTimes[unit].pioCycleTime);
        !           890:     kprintf("Disk(ata):         PIO Actual    Timings: Access: %3dns Cycle: %3dns\n\r",
        !           891:              accessTime, cycleTime );
        !           892: 
        !           893:     if ( _cycleTimes[unit].dmaType == IDE_DMA_NONE )
        !           894:     {
        !           895:       goto calcConfigWordDone;
        !           896:     }
        !           897: 
        !           898:     /*
        !           899:      * Calc DMA access time >= dmaAccessTime in SYSCLK increments
        !           900:      */
        !           901: 
        !           902:     /*
        !           903:      * OHare II erata - Cant handle write cycle times below 150ns
        !           904:      */
        !           905:     cycleTimeOrig = _cycleTimes[unit].dmaCycleTime;
        !           906:     if ( IsPowerStar() )
        !           907:     {
        !           908:         if ( cycleTimeOrig < 150 ) _cycleTimes[unit].dmaCycleTime = 150;
        !           909:     }
        !           910: 
        !           911:     accessTicks = rnddiv(_cycleTimes[unit].dmaAccessTime, IDE_SYSCLK_NS);
        !           912: 
        !           913:     accessTicks -= IDE_DMA_ACCESS_BASE;
        !           914:     if ( accessTicks < IDE_DMA_ACCESS_MIN )
        !           915:     {
        !           916:         accessTicks = IDE_DMA_ACCESS_MIN;
        !           917:     }
        !           918:     accessTime = (accessTicks + IDE_DMA_ACCESS_BASE) * IDE_SYSCLK_NS;
        !           919: 
        !           920:     /*
        !           921:      * Calc recovery time in SYSCLK increments based on time remaining in cycle
        !           922:      */
        !           923:     recTime = _cycleTimes[unit].dmaCycleTime - accessTime;    
        !           924:     recTicks = rnddiv( recTime, IDE_SYSCLK_NS );
        !           925: 
        !           926:     recTicks -= IDE_DMA_RECOVERY_BASE;
        !           927:     if ( recTicks < IDE_DMA_RECOVERY_MIN )
        !           928:     {
        !           929:         recTicks = IDE_DMA_RECOVERY_MIN;
        !           930:     }
        !           931:     cycleTime = (recTicks + IDE_DMA_RECOVERY_BASE + accessTicks + IDE_DMA_ACCESS_BASE) * IDE_SYSCLK_NS;
        !           932:  
        !           933:     /*
        !           934:      * If our calculated access time is at least SYSCLK/2 > than what the disk requires, 
        !           935:      * see if selecting the 1/2 Clock option will help. This adds SYSCLK/2 to 
        !           936:      * the access time and subtracts SYSCLK/2 from the recovery time.
        !           937:      * 
        !           938:      * By setting the H-bit and subtracting one from the current access tick count,
        !           939:      * we are reducing the current access time by SYSCLK/2 and the current recovery
        !           940:      * time by SYSCLK/2. Now, check if the new cycle time still meets the disk's requirements.
        !           941:      */  
        !           942:     if ( (accessTicks > IDE_DMA_ACCESS_MIN) &&  ((accessTime - IDE_SYSCLK_NS/2) >= _cycleTimes[unit].dmaAccessTime) )
        !           943:     {
        !           944:         if ( (cycleTime - IDE_SYSCLK_NS) >= _cycleTimes[unit].dmaCycleTime )
        !           945:         {
        !           946:             halfTick    = 1;
        !           947:             accessTicks--;
        !           948:             accessTime -= IDE_SYSCLK_NS/2;
        !           949:             cycleTime  -= IDE_SYSCLK_NS;
        !           950:         }
        !           951:     }
        !           952: 
        !           953:     ideConfigWord |= (accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
        !           954: 
        !           955:     kprintf("Disk(ata):         DMA Requested Timings: Access: %3dns Cycle: %3dns \n\r",  
        !           956:              _cycleTimes[unit].dmaAccessTime, cycleTimeOrig);
        !           957:     kprintf("Disk(ata):         DMA Actual    Timings: Access: %3dns Cycle: %3dns\n\r",   
        !           958:              accessTime, cycleTime );
        !           959: 
        !           960: calcConfigWordDone: ;
        !           961:     endianSwap32Bit( &ideConfigWord );
        !           962:     _cycleTimes[unit].ideConfig.dbdmaConfig = ideConfigWord;
        !           963: 
        !           964: }
        !           965: 
        !           966: 
        !           967: /*
        !           968:  * Send the Set Parameters command to the drive and set multi-sector mode
        !           969:  * etc. if the drive supports them. If biosInfo is YES, then we are using
        !           970:  * drive geometry information from the BIOS else we use Identify command to
        !           971:  * get this. 
        !           972:  */
        !           973: - (ide_return_t)setATADriveCapabilities:(unsigned int)unit     
        !           974: {
        !           975:     ideRegsVal_t               ideRegs;
        !           976:     unsigned char              nSectors;
        !           977:     char                       *buf;
        !           978:     
        !           979:     ideIdentifyInfo_t          *infoPtr = &_ideIdentifyInfo[unit];
        !           980: 
        !           981: 
        !           982:     _multiSector[unit] = 0;
        !           983:     _dmaSupported[unit] = NO;
        !           984: 
        !           985:     _ideIdentifyInfoSupported[unit] = YES;
        !           986:     bzero(infoPtr, sizeof(ideIdentifyInfo_t));
        !           987: 
        !           988:     /*
        !           989:      * Remember this command is optional. Failure means that either this
        !           990:      * command is not supported or the drive is not present.
        !           991:      */
        !           992:     _driveNum = unit;
        !           993: 
        !           994:     [self setTransferRate: _driveNum UseDMA:NO];
        !           995: 
        !           996:     if ([self ideReadGetInfoCommon:&ideRegs 
        !           997:                client:(struct vm_map *)IOVmTaskSelf() 
        !           998:                addr:(unsigned char *)infoPtr
        !           999:                command:IDE_IDENTIFY_DRIVE] != IDER_SUCCESS) 
        !          1000:     {
        !          1001:        _ideIdentifyInfoSupported[unit] = NO;
        !          1002:        [self ideReset];        /* necessary */
        !          1003:         return IDER_CMD_ERROR;
        !          1004:     }
        !          1005: 
        !          1006:     [self endianSwapIdentifyData: infoPtr];
        !          1007: 
        !          1008:     /*
        !          1009:      * Fill in this struct similar to which we would have gotten from CMOS. 
        !          1010:      */
        !          1011:     _ideInfo[unit].cylinders           = _ideIdentifyInfo[unit].cylinders;
        !          1012:     _ideInfo[unit].heads               = _ideIdentifyInfo[unit].heads;
        !          1013:     _ideInfo[unit].control_byte        = 0;
        !          1014:     _ideInfo[unit].landing_zone        = 0;
        !          1015:     _ideInfo[unit].sectors_per_trk     = _ideIdentifyInfo[unit].sectorsPerTrack;
        !          1016:     _ideInfo[unit].bytes_per_sector    = IDE_SECTOR_SIZE;
        !          1017: 
        !          1018:     if ( infoPtr->capabilities & IDE_CAP_LBA_SUPPORTED)
        !          1019:     {
        !          1020:     _ideInfo[unit].total_sectors = infoPtr->userAddressableSectors;
        !          1021:     }
        !          1022:     else
        !          1023:     {
        !          1024:         _ideInfo[unit].total_sectors = _ideInfo[unit].sectors_per_trk  
        !          1025:                                        * _ideInfo[unit].heads 
        !          1026:                                        * _ideInfo[unit].cylinders;
        !          1027:     }
        !          1028: 
        !          1029:     /*
        !          1030:      * Set address mode. The only case in which we need to override user
        !          1031:      * selection if the user chooses LBA and the drive supports only CHS. 
        !          1032:      */
        !          1033:     if ((infoPtr->capabilities & IDE_CAP_LBA_SUPPORTED) == 0x0)        
        !          1034:     {
        !          1035:        _addressMode[unit] = ADDRESS_MODE_CHS;
        !          1036:     }
        !          1037: 
        !          1038:     /*
        !          1039:      * Set disk parameters. 
        !          1040:      */
        !          1041:     [self ideSetParams:_ideInfo[unit].sectors_per_trk
        !          1042:            numHeads:_ideInfo[unit].heads ForDrive:unit];
        !          1043: 
        !          1044:     /*
        !          1045:      * Decide how are we going to do data transfers. Is DMA supported?
        !          1046:      * Multisector support? Verify that the data transfer mode really works
        !          1047:      * by doing a read operation in that mode. 
        !          1048:      */
        !          1049:     [self getTransferModes:infoPtr Unit:unit];
        !          1050: 
        !          1051:     /*
        !          1052:      * Set the Disk/CDROM transfer mode (Set Features SC=3) 
        !          1053:      */
        !          1054:     [self setTransferMode: unit]; 
        !          1055: 
        !          1056:     if (infoPtr->capabilities & IDE_CAP_DMA_SUPPORTED) 
        !          1057:     {
        !          1058:         if ( [self allocDmaMemory] == IDER_SUCCESS )
        !          1059:         { 
        !          1060:             _dmaSupported[unit] = YES;
        !          1061:             [self initIdeDma: unit];
        !          1062:         }
        !          1063:     }
        !          1064: 
        !          1065:     /*
        !          1066:      * We don't expect errors here since the drive claims that it can do
        !          1067:      * multiple sector transfers.
        !          1068:      */
        !          1069:     nSectors = infoPtr->multipleSectors & IDE_MULTI_SECTOR_MASK;
        !          1070: 
        !          1071:     if ( nSectors )    
        !          1072:     {  
        !          1073:        if ([self ideSetMultiSectorMode:&ideRegs
        !          1074:                         numSectors:nSectors] == IDER_SUCCESS) 
        !          1075:         {
        !          1076: 
        !          1077:             [self setTransferRate: unit UseDMA: NO];
        !          1078: 
        !          1079:            _multiSector[unit] = nSectors;
        !          1080:            ideRegs = [self logToPhys:0 numOfBlocks:nSectors];
        !          1081: 
        !          1082:            buf = IOMalloc(nSectors * IDE_SECTOR_SIZE);
        !          1083:            if ([self ideReadMultiple:&ideRegs 
        !          1084:                        client:(struct vm_map *)IOVmTaskSelf()
        !          1085:                        addr:buf] != IDER_SUCCESS)      
        !          1086:             {
        !          1087:                IOLog("%s: Read Multiple does not work!\n", [self name]);
        !          1088:                _multiSector[unit] = 0;
        !          1089:            }
        !          1090:            IOFree(buf, nSectors * IDE_SECTOR_SIZE);
        !          1091:        }
        !          1092:     }
        !          1093:     /*
        !          1094:      * A drive may not support set features command. Do we need to do
        !          1095:      * anything special if this command fails?
        !          1096:      */
        !          1097: 
        !          1098:     return IDER_SUCCESS;
        !          1099: }
        !          1100: 
        !          1101: -(ideIdentifyInfo_t *)getIdeIdentifyInfo:(unsigned int)unit
        !          1102: {
        !          1103:     return _ideIdentifyInfoSupported[unit] ? &_ideIdentifyInfo[unit] : NULL;
        !          1104: }
        !          1105: 
        !          1106: -(void)endianSwapIdentifyData:(ideIdentifyInfo_t *)pID
        !          1107: {
        !          1108:     endianSwap16Bit(&pID->genConfig);
        !          1109:     endianSwap16Bit(&pID->cylinders);
        !          1110:     endianSwap16Bit(&pID->heads);
        !          1111:     endianSwap16Bit(&pID->unformattedBytesPerTrack);
        !          1112:     endianSwap16Bit(&pID->unformattedBytesPerSector);
        !          1113:     endianSwap16Bit(&pID->sectorsPerTrack);
        !          1114:     endianSwap16Bit(&pID->bufferType);
        !          1115:     endianSwap16Bit(&pID->bufferSize); 
        !          1116:     endianSwap16Bit(&pID->eccBytes); 
        !          1117:     endianSwap16Bit(&pID->multipleSectors);
        !          1118:     endianSwap16Bit(&pID->doubleWordIO);                       
        !          1119:     endianSwap16Bit(&pID->capabilities);
        !          1120:     endianSwap16Bit(&pID->pioDataTransferCyleTimingMode);
        !          1121:     endianSwap16Bit(&pID->dmaDataTransferCyleTimingMode);
        !          1122:     endianSwap16Bit(&pID->fieldValidity);      
        !          1123:     endianSwap16Bit(&pID->currentCylinders);
        !          1124:     endianSwap16Bit(&pID->currentHeads);
        !          1125:     endianSwap16Bit(&pID->currentSectorsPerTrack);
        !          1126:     endianSwap16Bit(&pID->capacity[0]);
        !          1127:     endianSwap16Bit(&pID->capacity[1]);        
        !          1128:     endianSwap16Bit(&pID->multiSectorInfo);
        !          1129:     endianSwap32Bit(&pID->userAddressableSectors);             
        !          1130:     endianSwap16Bit(&pID->swDma);      
        !          1131:     endianSwap16Bit(&pID->mwDma);      
        !          1132:     endianSwap16Bit(&pID->ultraDma);   
        !          1133:     endianSwap16Bit(&pID->fcPioDataTransferCyleTimingMode); 
        !          1134:     endianSwap16Bit(&pID->minMwDMATransferCycleTimePerWord);
        !          1135:     endianSwap16Bit(&pID->RecommendedMwDMACycleTime);
        !          1136:     endianSwap16Bit(&pID->MinPIOTransferCycleTimeWithoutFlowControl);
        !          1137:     endianSwap16Bit(&pID->MinPIOTransferCycleTimeWithIORDY);
        !          1138: } 
        !          1139: 
        !          1140: -(void) assignRegisterAddresses: (IOTreeDevice *) deviceDescription
        !          1141: {
        !          1142:   
        !          1143:     if ( _controllerType == kControllerTypeCmd646X )
        !          1144:     {
        !          1145:         u_int32_t              pciRange1, pciRange2;
        !          1146: 
        !          1147:         [self mapMemoryRange: 0 to:(vm_address_t *)&pciRange1 findSpace:YES cache:IO_CacheOff];
        !          1148:         [self mapMemoryRange: 1 to:(vm_address_t *)&pciRange2 findSpace:YES cache:IO_CacheOff];
        !          1149: 
        !          1150:         _ideRegsAddrs.data      = pciRange1;    
        !          1151:         _ideRegsAddrs.error    = pciRange1 + 0x1;
        !          1152:         _ideRegsAddrs.features         = pciRange1 + 0x1;
        !          1153:         _ideRegsAddrs.sectCnt  = pciRange1 + 0x2;
        !          1154:         _ideRegsAddrs.sectNum  = pciRange1 + 0x3;
        !          1155:         _ideRegsAddrs.cylLow   = pciRange1 + 0x4;
        !          1156:         _ideRegsAddrs.cylHigh  = pciRange1 + 0x5;
        !          1157:         _ideRegsAddrs.drHead   = pciRange1 + 0x6;
        !          1158:         _ideRegsAddrs.status   = pciRange1 + 0x7;
        !          1159:         _ideRegsAddrs.command  = pciRange1 + 0x7;
        !          1160: 
        !          1161:         _ideRegsAddrs.deviceControl = pciRange2 + 0x2;
        !          1162:         _ideRegsAddrs.altStatus     = pciRange2 + 0x2;
        !          1163: 
        !          1164:         [(IOPCIDevice *)deviceDescription configWriteLong:0x04 value:0x05];
        !          1165: 
        !          1166:     }
        !          1167:     else
        !          1168:     {
        !          1169:         IORange                *IORanges;
        !          1170: 
        !          1171:         IORanges = [deviceDescription memoryRangeList];
        !          1172: 
        !          1173:         _ideRegsAddrs.data     = IORanges[0].start;
        !          1174:         _ideRegsAddrs.error    = IORanges[0].start + 0x10;
        !          1175:         _ideRegsAddrs.features         = IORanges[0].start + 0x10;
        !          1176:         _ideRegsAddrs.sectCnt  = IORanges[0].start + 0x20;
        !          1177:         _ideRegsAddrs.sectNum  = IORanges[0].start + 0x30;
        !          1178:         _ideRegsAddrs.cylLow   = IORanges[0].start + 0x40;
        !          1179:         _ideRegsAddrs.cylHigh  = IORanges[0].start + 0x50;
        !          1180:         _ideRegsAddrs.drHead   = IORanges[0].start + 0x60;
        !          1181:         _ideRegsAddrs.status   = IORanges[0].start + 0x70;
        !          1182:         _ideRegsAddrs.command  = IORanges[0].start + 0x70;
        !          1183:     
        !          1184:         _ideRegsAddrs.deviceControl = IORanges[0].start + 0x160;
        !          1185:         _ideRegsAddrs.altStatus     = IORanges[0].start + 0x160;
        !          1186:  
        !          1187:         _ideRegsAddrs.channelConfig = IORanges[0].start + 0x200;
        !          1188: 
        !          1189:         _ideDMARegs                = (IODBDMAChannelRegisters *)IORanges[1].start;
        !          1190:     }
        !          1191: }
        !          1192: 
        !          1193: 
        !          1194: @end
        !          1195: 

unix.superglobalmegacorp.com

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