Annotation of XNU/iokit/Drivers/ata/drvAppleATA/AppleATAPIIX.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc.  All rights reserved. 
        !             3:  *
        !             4:  * AppleATAPIIX.cpp - ATA controller driver for Intel PIIX/PIIX3/PIIX4.
        !             5:  *
        !             6:  * HISTORY
        !             7:  *
        !             8:  */
        !             9: 
        !            10: #include <architecture/i386/pio.h>
        !            11: #include <IOKit/IOService.h>
        !            12: #include <IOKit/assert.h>
        !            13: #include "AppleATAPIIX.h"
        !            14: #include "AppleATAPIIXTiming.h"
        !            15: 
        !            16: extern pmap_t                      kernel_pmap;        // for pmap_extract()
        !            17: 
        !            18: // Resources shared between the two IDE channels are protected
        !            19: // by this mutex.
        !            20: //
        !            21: static IOLock *            gPIIXLock = 0;
        !            22: #define PIIX_LOCK                  IOLockLock(gPIIXLock)
        !            23: #define PIIX_UNLOCK                IOLockUnlock(gPIIXLock)
        !            24: 
        !            25: #define IOREG(x)                   (ioBMRange + PIIX_IO_ ## x)
        !            26: 
        !            27: #define CHECK_UNIT(drv)            assert(drv < 2)
        !            28: 
        !            29: #ifdef  DEBUG_XXX
        !            30: #define DLOG(fmt, args...)     IOLog(fmt, ## args)
        !            31: #else
        !            32: #define DLOG(fmt, args...)
        !            33: #endif
        !            34: 
        !            35: //--------------------------------------------------------------------------
        !            36: // Metaclass macro.
        !            37: //
        !            38: #undef  super
        !            39: #define super AppleATA
        !            40: 
        !            41: OSDefineMetaClassAndStructorsWithInit( AppleATAPIIX, AppleATA,
        !            42:                                        AppleATAPIIX::initialize() )
        !            43: 
        !            44: //--------------------------------------------------------------------------
        !            45: // PIIX class initializer.
        !            46: //
        !            47: void AppleATAPIIX::initialize()
        !            48: {
        !            49:        gPIIXLock = IOLockAlloc();
        !            50:        assert(gPIIXLock);
        !            51: }
        !            52: 
        !            53: //--------------------------------------------------------------------------
        !            54: // Defines a table of supported PIIX device types, listing their
        !            55: // PCI ID, and a name string. Also supply some utility functions
        !            56: // to locate a table entry based on an arbitrary PCI ID.
        !            57: //
        !            58: static struct {
        !            59:        UInt32        CFID;
        !            60:        const char *  name;
        !            61: } piixDeviceTable[] = {{ PCI_ID_PIIX,  "PIIX"  },
        !            62:                        { PCI_ID_PIIX3, "PIIX3" },
        !            63:                        { PCI_ID_PIIX4, "PIIX4" },
        !            64:                        { PCI_ID_NONE,   NULL   }};
        !            65: 
        !            66: static const char *
        !            67: PIIXGetName(UInt32 pciID)
        !            68: {
        !            69:        for (int i = 0; piixDeviceTable[i].name; i++) {
        !            70:                if (piixDeviceTable[i].CFID == pciID)
        !            71:                        return piixDeviceTable[i].name;
        !            72:        }
        !            73:        return 0;
        !            74: }
        !            75: 
        !            76: static bool
        !            77: PIIXVerifyID(UInt32 pciID)
        !            78: {
        !            79:        return (PIIXGetName(pciID) == 0) ? false : true;
        !            80: }
        !            81: 
        !            82: //--------------------------------------------------------------------------
        !            83: // A hack to modify our PCI nub to have two interrupts.
        !            84: // This code was borrowed from the setupIntelPIC() function
        !            85: // in iokit/Families/IOPCIBus/IOPCIBridge.cpp.
        !            86: //
        !            87: static void setupProviderInterrupts(IOPCIDevice * nub, long irq_p, long irq_s)
        !            88: {
        !            89:        OSArray *         controller;
        !            90:        OSArray *         specifier;
        !            91:        OSData *          tmpData;
        !            92:        extern OSSymbol * gIntelPICName;
        !            93: 
        !            94:        do {
        !            95:                // Create the interrupt specifer array.
        !            96:                specifier = OSArray::withCapacity(2);
        !            97:                if (!specifier)
        !            98:                        break;
        !            99: 
        !           100:         tmpData = OSData::withBytes(&irq_p, sizeof(irq_p));
        !           101:         if (tmpData) {
        !           102:             specifier->setObject(tmpData);
        !           103:             tmpData->release();
        !           104:         }
        !           105:         tmpData = OSData::withBytes(&irq_s, sizeof(irq_s));
        !           106:         if (tmpData) {
        !           107:             specifier->setObject(tmpData);
        !           108:             tmpData->release();
        !           109:         }
        !           110: 
        !           111:         controller = OSArray::withCapacity(2);
        !           112:         if (controller) {
        !           113:                        controller->setObject(gIntelPICName);
        !           114:                        controller->setObject(gIntelPICName);
        !           115: 
        !           116:             // Put the two arrays into the property table.
        !           117:                        nub->setProperty(gIOInterruptControllersKey, controller);
        !           118:             controller->release();
        !           119:         }
        !           120:         nub->setProperty(gIOInterruptSpecifiersKey, specifier);
        !           121:         specifier->release();
        !           122: 
        !           123:     } while( false );
        !           124: }
        !           125: 
        !           126: //--------------------------------------------------------------------------
        !           127: // A static member function that returns the IDE channel for the
        !           128: // current driver instance, and also registers the interrupts in
        !           129: // the IOPCIDevice nub.
        !           130: //
        !           131: int AppleATAPIIX::PIIXGetChannel(IOPCIDevice * provider)
        !           132: {
        !           133:        static bool       primaryRegistered = false;
        !           134:        int               rc;
        !           135:        extern OSSymbol * gIntelPICName;
        !           136: 
        !           137:        PIIX_LOCK;
        !           138:        
        !           139:        if (primaryRegistered == false) {
        !           140:                rc = PIIX_CHANNEL_PRIMARY;
        !           141:                primaryRegistered = true;
        !           142: 
        !           143:                // Is this necessary?
        !           144:                waitForService(resourceMatching(gIntelPICName));
        !           145: 
        !           146:                setupProviderInterrupts(provider, PIIX_P_IRQ, PIIX_S_IRQ);
        !           147:        }
        !           148:        else {
        !           149:                rc = PIIX_CHANNEL_SECONDARY;
        !           150:        }
        !           151: 
        !           152:        PIIX_UNLOCK;
        !           153: 
        !           154:        if (rc == PIIX_CHANNEL_SECONDARY) IOSleep(20);
        !           155: 
        !           156:        return rc;
        !           157: }
        !           158: 
        !           159: //--------------------------------------------------------------------------
        !           160: // Private function: _getIDERanges
        !           161: //
        !           162: // Setup the variables that stores the start of the Command and Control
        !           163: // block in I/O space. The variable 'channel' must have been previously
        !           164: // set. These ISA I/O ranges are implicit and does not show up in PCI
        !           165: // config space.
        !           166: //
        !           167: bool AppleATAPIIX::_getIDERanges(IOPCIDevice * provider)
        !           168: {
        !           169:        ioCmdRange = (channel == PIIX_CHANNEL_PRIMARY) ?
        !           170:                  PIIX_P_CMD_ADDR : PIIX_S_CMD_ADDR;
        !           171:        
        !           172:        ioCtlRange = (channel == PIIX_CHANNEL_PRIMARY) ?
        !           173:                  PIIX_P_CTL_ADDR : PIIX_S_CTL_ADDR;
        !           174: 
        !           175:        DLOG("%s: ioCmdRange - %04x\n", getName(), ioCmdRange);
        !           176:        DLOG("%s: ioCtlRange - %04x\n", getName(), ioCtlRange);
        !           177: 
        !           178:        return true;
        !           179: }
        !           180: 
        !           181: //--------------------------------------------------------------------------
        !           182: // Private function: _getBMRange
        !           183: //
        !           184: // Determine the start of the I/O mapped Bus-Master registers.
        !           185: // This range is defined by PCI config space register PIIX_PCI_BMIBA.
        !           186: //
        !           187: bool AppleATAPIIX::_getBMRange(IOPCIDevice * provider)
        !           188: {
        !           189:        UInt32 bmiba;
        !           190: 
        !           191:        bmiba = provider->configRead32(PIIX_PCI_BMIBA);
        !           192:        if ((bmiba & PIIX_PCI_BMIBA_RTE) == 0) {
        !           193:                IOLog("%s: PCI memory range 0x%02x (0x%08lx) is not an I/O range\n",
        !           194:                        getName(), PIIX_PCI_BMIBA, bmiba);
        !           195:                return false;
        !           196:        }
        !           197:        
        !           198:        bmiba &= PIIX_PCI_BMIBA_MASK;   // get the address portion
        !           199: 
        !           200:        // If bmiba is zero, it is likely that the user has elected to
        !           201:        // turn off PCI IDE support in the BIOS.
        !           202:        //
        !           203:        if (bmiba == 0)
        !           204:                return false;
        !           205: 
        !           206:        if (channel == PIIX_CHANNEL_SECONDARY)
        !           207:                bmiba += PIIX_IO_BM_OFFSET;
        !           208: 
        !           209:        ioBMRange = (UInt16) bmiba;
        !           210:        
        !           211:        DLOG("%s: ioBMRange - %04x\n", getName(), ioBMRange);
        !           212: 
        !           213:        return true;
        !           214: }
        !           215: 
        !           216: //--------------------------------------------------------------------------
        !           217: // Private function: _resetTimings()
        !           218: //
        !           219: // Reset all timing registers to the slowest (most compatible) timing.
        !           220: // UDMA modes are disabled. We take a lock to prevent the other IDE
        !           221: // channel from modifying the shared PCI config space.
        !           222: //
        !           223: bool AppleATAPIIX::_resetTimings()
        !           224: {
        !           225:        union {
        !           226:                UInt32 b32;
        !           227:                struct {
        !           228:                        UInt16 pri;
        !           229:                        UInt16 sec;
        !           230:                } b16;
        !           231:        } timing;
        !           232: 
        !           233:        UInt32  udmaControl;
        !           234: 
        !           235:        PIIX_LOCK;
        !           236: 
        !           237:        timing.b32 = provider->configRead32(PIIX_PCI_IDETIM);
        !           238:        udmaControl = provider->configRead32(PIIX_PCI_UDMACTL);
        !           239: 
        !           240:        // Set slowest timing, and disable UDMA. Only modify the flags
        !           241:        // associated with the local channel.
        !           242:        //
        !           243:        switch (channel) {
        !           244:                case PIIX_CHANNEL_PRIMARY:
        !           245:                        timing.b16.pri &= PIIX_PCI_IDETIM_IDE;                  
        !           246:                        udmaControl &= ~(PIIX_PCI_UDMACTL_PSDE0 | PIIX_PCI_UDMACTL_PSDE1);
        !           247:                        break;
        !           248:                
        !           249:                case PIIX_CHANNEL_SECONDARY:
        !           250:                        timing.b16.sec &= PIIX_PCI_IDETIM_IDE;
        !           251:                        udmaControl &= ~(PIIX_PCI_UDMACTL_SSDE0 | PIIX_PCI_UDMACTL_SSDE1);
        !           252:                        break;
        !           253:        }
        !           254: 
        !           255:        provider->configWrite32(PIIX_PCI_UDMACTL, udmaControl);
        !           256:        provider->configWrite32(PIIX_PCI_IDETIM,  timing.b32);
        !           257: 
        !           258:        PIIX_UNLOCK;
        !           259: 
        !           260:        return true;
        !           261: }
        !           262: 
        !           263: //--------------------------------------------------------------------------
        !           264: // Private function: _allocatePRDTable()
        !           265: //
        !           266: // Allocate the physical region descriptor (PRD) table. The physical
        !           267: // address of this table is stored in 'prdTablePhys'. Look at Intel
        !           268: // documentation for the alignment requirements.
        !           269: //
        !           270: bool AppleATAPIIX::_allocatePRDTable()
        !           271: {
        !           272:        prdTable = (prdEntry_t *) IOMallocAligned(PRD_TABLE_SIZE, PAGE_SIZE);
        !           273:        if (!prdTable)
        !           274:                return false;
        !           275: 
        !           276:        prdTablePhys = (UInt32) pmap_extract(kernel_pmap, (vm_offset_t) prdTable);
        !           277: 
        !           278:        bzero(prdTable, PRD_TABLE_SIZE);
        !           279: 
        !           280:        return true;
        !           281: }
        !           282: 
        !           283: //--------------------------------------------------------------------------
        !           284: // Private function: _deallocatePRDTable()
        !           285: //
        !           286: void AppleATAPIIX::_deallocatePRDTable()
        !           287: {
        !           288:        IOFreeAligned(prdTable, PRD_TABLE_SIZE);
        !           289:        prdTable = NULL;
        !           290:        prdTablePhys = 0;
        !           291: }
        !           292: 
        !           293: //--------------------------------------------------------------------------
        !           294: // Function inherited from IOATAController.
        !           295: //
        !           296: // Configure the driver/controller. This is the first function called by
        !           297: // our superclass, in its start() function, to initialize the controller
        !           298: // hardware.
        !           299: //
        !           300: bool
        !           301: AppleATAPIIX::configure(IOService * forProvider,
        !           302:                         UInt32 *    controllerDataSize)
        !           303: {
        !           304:        UInt32  reg;
        !           305: 
        !           306: //     IOSleep(1000);
        !           307: 
        !           308:     *controllerDataSize = 0;
        !           309: 
        !           310:     provider = OSDynamicCast(IOPCIDevice, forProvider);
        !           311:        if (!provider)
        !           312:                return false;
        !           313:        
        !           314:        // Superclass performs an exclusive open on the provider, we close
        !           315:        // it to allow more than one instance of this driver to attach to
        !           316:        // the same PCI nub. We should maintain an non-exclusive open on
        !           317:        // the provider.
        !           318:        //
        !           319:        provider->close(this);
        !           320: 
        !           321:        // Determine the type of PIIX controller. Save the controller's
        !           322:        // PCI ID in pciCFID.
        !           323:        //
        !           324:        pciCFID = provider->configRead32(PIIX_PCI_CFID);
        !           325:        if (PIIXVerifyID(pciCFID) == false) {
        !           326:                IOLog("%s: Unknown PCI IDE controller (0x%08lx)\n",
        !           327:               getName(),
        !           328:               pciCFID);
        !           329:                return false;
        !           330:        }
        !           331: 
        !           332:        // Determine our IDE channel, primary or secondary.
        !           333:        //
        !           334:        channel = PIIXGetChannel(provider);
        !           335: 
        !           336:        _getIDERanges(provider);
        !           337: 
        !           338:        IOLog("%s: %s %s IDE controller, 0x%x, irq %d\n",
        !           339:                getName(),
        !           340:                (channel == PIIX_CHANNEL_PRIMARY) ? "Primary" : "Secondary",
        !           341:                PIIXGetName(pciCFID),
        !           342:                ioCmdRange,
        !           343:                (channel == PIIX_CHANNEL_PRIMARY) ? PIIX_P_IRQ : PIIX_S_IRQ);
        !           344: 
        !           345:        // Check the I/O Space Enable bit in the PCI command register.
        !           346:        // This is the master enable bit for the PIIX controller.
        !           347:        // Each IDE channel also has its own enable bit, which is
        !           348:        // checked later.
        !           349:        //
        !           350:        reg = provider->configRead32(PIIX_PCI_PCICMD);
        !           351:        if ((reg & PIIX_PCI_PCICMD_IOSE) == 0) {
        !           352:                IOLog("%s: PCI IDE controller is not enabled\n", getName());
        !           353:                return false;
        !           354:        }
        !           355: 
        !           356:        // Set BME bit to enable bus-master.
        !           357:        //
        !           358:        if ((reg & PIIX_PCI_PCICMD_BME) == 0) {
        !           359:                reg |= PIIX_PCI_PCICMD_BME;
        !           360:                PIIX_LOCK;
        !           361:                provider->configWrite32(PIIX_PCI_PCICMD, reg);
        !           362:                PIIX_UNLOCK;
        !           363:        }
        !           364: 
        !           365:        // Fetch the corresponding primary/secondary IDETIM register and
        !           366:        // check the individual channel enable bit.
        !           367:        //
        !           368:        reg = provider->configRead32(PIIX_PCI_IDETIM);
        !           369:        if (channel == PIIX_CHANNEL_SECONDARY)
        !           370:                reg >>= 16;             // PIIX_PCI_IDETIM + 2 for secondary channel
        !           371: 
        !           372:        if ((reg & PIIX_PCI_IDETIM_IDE) == 0) {
        !           373:                IOLog("%s: %s PCI IDE channel is not enabled\n",
        !           374:                        getName(),
        !           375:                        (channel == PIIX_CHANNEL_PRIMARY) ? "Primary" : "Secondary");
        !           376:                return false;
        !           377:        }
        !           378: 
        !           379:        // Locate and add the I/O mapped bus-master registers to
        !           380:        // ioRange[] array.
        !           381:        //
        !           382:        if (_getBMRange(provider) == false) {
        !           383:                IOLog("%s: Bus master I/O range is invalid\n", getName());
        !           384:                return false;
        !           385:        }
        !           386: 
        !           387:        // Allocate page-aligned memory for the PRD table.
        !           388:        //
        !           389:        if (_allocatePRDTable() == false) {
        !           390:                IOLog("%s: unable to allocate descriptor table\n", getName());
        !           391:                return false;
        !           392:        }
        !           393: 
        !           394:        // Allocate a cursor object to generate the scatter-gather list
        !           395:        // for each transfer request. Maximum segment size is set to 64K.
        !           396:        // However, there is no way to indicate our requirement that each
        !           397:        // memory segment cannot cross a 64K boundary. We have to do this
        !           398:        // manually.
        !           399:        //
        !           400:     prdCursor = IOLittleMemoryCursor::withSpecification(64 * 1024, 0xffffffff);
        !           401:     if (prdCursor == 0)
        !           402:         return false;
        !           403: 
        !           404:        // Revert to default (compatible) timing.
        !           405:        //
        !           406:        _resetTimings();
        !           407: 
        !           408:        DLOG("AppleATAPIIX::%s() completed successfully\n", __FUNCTION__);
        !           409: 
        !           410:     return true;
        !           411: }
        !           412: 
        !           413: //--------------------------------------------------------------------------
        !           414: // Function inherited from IOATAController.
        !           415: //
        !           416: // Create a workloop and attach various event sources to the newly created 
        !           417: // workloop.
        !           418: //
        !           419: bool AppleATAPIIX::createWorkLoop(IOWorkLoop ** workLoop)
        !           420: {
        !           421:     if (super::createWorkLoop(workLoop) != true)
        !           422:         return false;
        !           423: 
        !           424:     interruptEventSource = IOInterruptEventSource::interruptEventSource(
        !           425:                      (OSObject *)             this,
        !           426:                      (IOInterruptEventAction) &AppleATAPIIX::interruptOccurred,
        !           427:                      (IOService *)            provider,
        !           428:                      (channel == PIIX_CHANNEL_PRIMARY) ? 0 : 1);
        !           429:     if (interruptEventSource == 0) {
        !           430:                IOLog("%s: unable to create an IOInterruptEventSource object\n",
        !           431:                          getName());
        !           432:         return false;
        !           433:        }
        !           434: 
        !           435:        disableControllerInterrupts();
        !           436: 
        !           437:     (*workLoop)->addEventSource(interruptEventSource); 
        !           438: 
        !           439:     timerEventSource = IOTimerEventSource::timerEventSource(
        !           440:                           this,
        !           441:                           (IOTimerEventSource::Action) &AppleATAPIIX::ataTimer);
        !           442:     if (timerEventSource == 0)
        !           443:         return false;
        !           444: 
        !           445:     (*workLoop)->addEventSource(timerEventSource); 
        !           446:  
        !           447:        ataTimer(timerEventSource); 
        !           448: 
        !           449:        DLOG("AppleATAPIIX::%s() completed successfully\n", __FUNCTION__);
        !           450: 
        !           451:     return true;
        !           452: }
        !           453: 
        !           454: //--------------------------------------------------------------------------
        !           455: //
        !           456: //
        !           457: bool AppleATAPIIX::provideProtocols(enum ATAProtocol * protocolsSupported)
        !           458: {
        !           459:     return false;
        !           460: }
        !           461: 
        !           462: //--------------------------------------------------------------------------
        !           463: //
        !           464: //
        !           465: bool AppleATAPIIX::provideTimings(UInt32 *    numTimings,
        !           466:                                   ATATiming * timingsSupported)
        !           467: {
        !           468:     return false;
        !           469: }
        !           470: 
        !           471: //--------------------------------------------------------------------------
        !           472: // Determine the timing selection based on the ATATiming structure given.
        !           473: //
        !           474: bool AppleATAPIIX::calculateTiming(UInt32 unit, ATATiming * pTiming)
        !           475: {
        !           476:        int           i;
        !           477:        PIIXProtocol  protocol = ataToPIIXProtocol(pTiming->timingProtocol);
        !           478: 
        !           479:        DLOG("AppleATAPIIX::%s() - unit:%ld protocol:%d minCycles:%ld\n",
        !           480:                 __FUNCTION__, unit, protocol, pTiming->minDataCycle);
        !           481: 
        !           482:        CHECK_UNIT(unit);
        !           483: 
        !           484:        timings[unit].validTimings[protocol] = 0;
        !           485: 
        !           486:        switch (protocol) {
        !           487: 
        !           488:                case kPIIXProtocolPIO:
        !           489: 
        !           490:                        for (i = 0; i < PIIXPIOTimingTableSize; i++)
        !           491:                        {
        !           492:                                if (PIIXPIOTimingTable[i].pioMode == _NVM_)
        !           493:                                        continue;
        !           494: 
        !           495:                                if (PIIXPIOTimingTable[i].cycle < pTiming->minDataCycle)
        !           496:                                        break;
        !           497: 
        !           498:                                timings[unit].validTimings[protocol] = i;
        !           499:                        }
        !           500:                        break;
        !           501: 
        !           502:                case kPIIXProtocolDMA:
        !           503: 
        !           504:                        for (i = 0; i < PIIXPIOTimingTableSize; i++)
        !           505:                        {
        !           506:                                if (PIIXPIOTimingTable[i].mwDMAMode == _NVM_)
        !           507:                                        continue;
        !           508: 
        !           509:                                if (PIIXPIOTimingTable[i].cycle < pTiming->minDataCycle)
        !           510:                                        break;
        !           511: 
        !           512:                                timings[unit].validTimings[protocol] = i;
        !           513:                        }
        !           514:                        break;
        !           515:                
        !           516:                case kPIIXProtocolUDMA33:
        !           517:                        
        !           518:                        for (i = 0; i < PIIXUDMATimingTableSize; i++)
        !           519:                        {
        !           520:                                if (PIIXUDMATimingTable[i].strobe < pTiming->minDataCycle)
        !           521:                                        break;
        !           522:                        
        !           523:                                timings[unit].validTimings[protocol] = i;
        !           524:                        }
        !           525:                        break;
        !           526:                
        !           527:                default:
        !           528:                        return false;
        !           529:        }
        !           530: 
        !           531:        timings[unit].validFlag |= (1 << protocol);
        !           532: 
        !           533:        return true;
        !           534: }
        !           535: 
        !           536: //--------------------------------------------------------------------------
        !           537: // Setup the timing register for the given timing protocol.
        !           538: //
        !           539: bool AppleATAPIIX::selectTiming(UInt32            unit,
        !           540:                                 ATATimingProtocol timingProtocol)
        !           541: {
        !           542:        bool          ret = false;
        !           543:        UInt8         pciConfig[256];
        !           544:        PIIXProtocol  protocol = ataToPIIXProtocol(timingProtocol);
        !           545: 
        !           546:        DLOG("AppleATAPIIX::%s() - unit:%ld protocol:%d\n",
        !           547:                 __FUNCTION__, unit, protocol);
        !           548: 
        !           549:        CHECK_UNIT(unit);
        !           550: 
        !           551:        PIIX_LOCK;
        !           552: 
        !           553:        do {
        !           554:                if (protocol >= kPIIXProtocolLast)
        !           555:                        break;
        !           556:                
        !           557:                if (PIIX_PROTOCOL_IS_VALID(protocol) == 0) {
        !           558:                        
        !           559:                        // superclass error, calculateTiming() was not called
        !           560:                        // before calling selectTiming().
        !           561:                        
        !           562:                        IOLog("%s: timing protocol selected is invalid\n", getName());
        !           563:                        break;
        !           564:                }
        !           565: 
        !           566:                if (!_readPCIConfigSpace(pciConfig) ||
        !           567:                        !_selectTiming(unit, protocol, pciConfig) ||
        !           568:                        !_writePCIConfigSpace(pciConfig))
        !           569:                        break;
        !           570: 
        !           571:                ret = true;
        !           572:        }
        !           573:        while (0);
        !           574: 
        !           575:        PIIX_UNLOCK;
        !           576: 
        !           577:        return ret;
        !           578: }
        !           579: 
        !           580: //--------------------------------------------------------------------------
        !           581: // Setup the timing registers.
        !           582: //
        !           583: bool AppleATAPIIX::_selectTiming(UInt32         unit,
        !           584:                                  PIIXProtocol   protocol,
        !           585:                                                                 UInt8 *        pciConfig)
        !           586: {
        !           587:        UInt8     isp, rtc;
        !           588:        UInt8     index, dma, pio;
        !           589:        bool      dmaActive;
        !           590:        bool      pioActive;
        !           591:        bool      useCompatiblePIOTiming = false;
        !           592:        bool      ret = true;
        !           593:        UInt16 *  idetim;
        !           594:        UInt8 *   sidetim = (UInt8 *)  &pciConfig[PIIX_PCI_SIDETIM];
        !           595:        UInt8 *   udmactl = (UInt8 *)  &pciConfig[PIIX_PCI_UDMACTL];
        !           596:        UInt16 *  udmatim = (UInt16 *) &pciConfig[PIIX_PCI_UDMATIM];
        !           597: 
        !           598:        idetim = (channel == PIIX_CHANNEL_PRIMARY) ? 
        !           599:              (UInt16 *) &pciConfig[PIIX_PCI_IDETIM] :
        !           600:                         (UInt16 *) &pciConfig[PIIX_PCI_IDETIM_S];
        !           601: 
        !           602:        switch (protocol) {
        !           603:                case kPIIXProtocolUDMA66:
        !           604:                        // Not yet!
        !           605:                        return false;
        !           606: 
        !           607:                case kPIIXProtocolUDMA33:
        !           608:                        if ((pciCFID == PCI_ID_PIIX) || (pciCFID == PCI_ID_PIIX3)) {
        !           609:                                // Only PIIX4 (and newer devices) supports UDMA.
        !           610:                                return false;
        !           611:                        }
        !           612:                        PIIX_DEACTIVATE_PROTOCOL(kPIIXProtocolDMA);
        !           613:                        break;
        !           614: 
        !           615:                case kPIIXProtocolDMA:
        !           616:                        PIIX_DEACTIVATE_PROTOCOL(kPIIXProtocolUDMA33);
        !           617:                        break;
        !           618: 
        !           619:                case kPIIXProtocolPIO:
        !           620:                        break;
        !           621: 
        !           622:                default:
        !           623:                        IOLog("%s: PIIX protocol not handled (%d)\n", getName(),
        !           624:                                  protocol);
        !           625:                        return false;
        !           626:        }
        !           627:        PIIX_ACTIVATE_PROTOCOL(protocol);
        !           628: 
        !           629: 
        !           630:        if (PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolUDMA33)) {
        !           631: 
        !           632:                index = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolUDMA33);
        !           633: 
        !           634:                if (unit == 0) {
        !           635:                        if (channel == PIIX_CHANNEL_PRIMARY) {
        !           636:                                *udmactl |= PIIX_PCI_UDMACTL_PSDE0;
        !           637:                                SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_PCT0,
        !           638:                                                                PIIXUDMATimingTable[index].bits);
        !           639:                        }
        !           640:                        else {
        !           641:                                *udmactl |= PIIX_PCI_UDMACTL_SSDE0;
        !           642:                                SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_SCT0,
        !           643:                                                                PIIXUDMATimingTable[index].bits);
        !           644:                        }
        !           645:                }
        !           646:                else {
        !           647:                        if (channel == PIIX_CHANNEL_PRIMARY) {
        !           648:                                *udmactl |= PIIX_PCI_UDMACTL_PSDE1;
        !           649:                                SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_PCT1,
        !           650:                                                                PIIXUDMATimingTable[index].bits);
        !           651:                        }
        !           652:                        else {
        !           653:                                *udmactl |= PIIX_PCI_UDMACTL_SSDE1;
        !           654:                                SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_SCT1,
        !           655:                                                                PIIXUDMATimingTable[index].bits);
        !           656:                        }
        !           657:                }
        !           658:        }
        !           659:        else {
        !           660:                if (unit == 0) {
        !           661:                        if (channel == PIIX_CHANNEL_PRIMARY) {
        !           662:                                *udmactl &= ~PIIX_PCI_UDMACTL_PSDE0;
        !           663:                        }
        !           664:                        else {
        !           665:                                *udmactl &= ~PIIX_PCI_UDMACTL_SSDE0;
        !           666:                        }
        !           667:                }
        !           668:                else {
        !           669:                        if (channel == PIIX_CHANNEL_PRIMARY) {
        !           670:                                *udmactl &= ~PIIX_PCI_UDMACTL_PSDE1;
        !           671:                        }
        !           672:                        else {
        !           673:                                *udmactl &= ~PIIX_PCI_UDMACTL_SSDE1;
        !           674:                        }
        !           675:                }
        !           676:        }
        !           677: 
        !           678:        dmaActive = PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolDMA);
        !           679:        pioActive = PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolPIO);
        !           680:                
        !           681:        if (dmaActive || pioActive) {
        !           682: 
        !           683:                dma = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolDMA);
        !           684:                pio = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolPIO);
        !           685: 
        !           686:                // Early PIIX devices does not have a slave timing register.
        !           687:                // Rather than switching timing registers whenever a new
        !           688:                // drive was selected, We program in a (slower) timing that
        !           689:                // is acceptable for both drive0 and drive1.
        !           690: 
        !           691:                if (pciCFID == PCI_ID_PIIX) {
        !           692: 
        !           693:                        unit = (unit ^ 1) & 1;          // unit <- other drive unit
        !           694: 
        !           695:                        if (PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolPIO)) {
        !           696:                                if (!pioActive || 
        !           697:                                        (PIIX_GET_ACTIVE_TIMING(kPIIXProtocolPIO) < pio)) {
        !           698:                                        pio = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolPIO);
        !           699:                                }
        !           700:                                pioActive = true;
        !           701:                        }
        !           702: 
        !           703:                        if (PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolDMA)) {
        !           704:                                if (!dmaActive ||
        !           705:                                        (PIIX_GET_ACTIVE_TIMING(kPIIXProtocolDMA) < dma)) {
        !           706:                                        dma = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolDMA);
        !           707:                                }
        !           708:                                dmaActive = true;
        !           709:                        }
        !           710: 
        !           711:                        *idetim &= ~PIIX_PCI_IDETIM_SITRE;      // disable slave timing
        !           712:                        unit = 0;
        !           713:                }
        !           714:                else {
        !           715:                        *idetim |= PIIX_PCI_IDETIM_SITRE;       // enable slave timing
        !           716:                }
        !           717: 
        !           718:                // Pick an index to the PIIXPIOTimingTable[] for the new
        !           719:                // timing selection.
        !           720:                //
        !           721:                if (dmaActive && pioActive) {
        !           722: 
        !           723:                        // Both PIO and DMA are active, select DMA timing to
        !           724:                        // optimize DMA transfer.
        !           725: 
        !           726:                        index = dma;            // pick DMA timing
        !           727: 
        !           728:                        if (pio < dma)
        !           729:                                useCompatiblePIOTiming = true;
        !           730:                }
        !           731:                else if (dmaActive) {
        !           732:                        index = dma;
        !           733:                }
        !           734:                else {
        !           735:                        index = pio;
        !           736:                }
        !           737: 
        !           738:                isp = PIIX_CLK_TO_ISP(PIIXPIOTimingTable[index].isp);
        !           739:                rtc = PIIX_CLK_TO_RTC(PIIXPIOTimingTable[index].rtc);
        !           740: 
        !           741:                if (unit == 0) {
        !           742:                        SET_REG_FIELD(*idetim, PIIX_PCI_IDETIM_ISP, isp);
        !           743:                        SET_REG_FIELD(*idetim, PIIX_PCI_IDETIM_RTC, rtc);
        !           744:                        if (useCompatiblePIOTiming)
        !           745:                                *idetim |= PIIX_PCI_IDETIM_DTE0;
        !           746:                        else
        !           747:                                *idetim &= ~PIIX_PCI_IDETIM_DTE0;
        !           748:                        
        !           749:                        if (pciCFID == PCI_ID_PIIX) {
        !           750:                                if (useCompatiblePIOTiming)
        !           751:                                        *idetim |= PIIX_PCI_IDETIM_DTE1;
        !           752:                                else
        !           753:                                        *idetim &= ~PIIX_PCI_IDETIM_DTE1;
        !           754:                        }
        !           755:                }
        !           756:                else {
        !           757:                        if (channel == PIIX_CHANNEL_PRIMARY) {
        !           758:                                SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_PISP1, isp);
        !           759:                                SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_PRTC1, rtc);
        !           760:                        }
        !           761:                        else {
        !           762:                                SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_SISP1, isp);
        !           763:                                SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_SRTC1, rtc);
        !           764:                        }
        !           765:                        if (useCompatiblePIOTiming)
        !           766:                                *idetim |= PIIX_PCI_IDETIM_DTE1;
        !           767:                        else
        !           768:                                *idetim &= ~PIIX_PCI_IDETIM_DTE1;
        !           769:                }
        !           770: 
        !           771:                *idetim |= (PIIX_PCI_IDETIM_TIME0 |
        !           772:                                        PIIX_PCI_IDETIM_PPE0  | 
        !           773:                                        PIIX_PCI_IDETIM_IE0   |
        !           774:                                        PIIX_PCI_IDETIM_TIME1 |
        !           775:                                        PIIX_PCI_IDETIM_PPE1  | 
        !           776:                                        PIIX_PCI_IDETIM_IE1);
        !           777:        }
        !           778: 
        !           779: #ifdef DEBUG_XXX
        !           780:        IOLog("\n%s: %s channel\n", getName(), 
        !           781:                  (channel == PIIX_CHANNEL_PRIMARY) ? "Primary" : "Secondary");
        !           782:        IOLog("%s: IDETIM : %04x\n", getName(), *idetim);
        !           783:        IOLog("%s: SIDETIM: %02x\n", getName(), *sidetim);
        !           784:        IOLog("%s: UDMACTL: %02x\n", getName(), *udmactl);
        !           785:        IOLog("%s: UDMATIM: %04x\n", getName(), *udmatim);
        !           786:        IOLog("%s: Active : %04lx\n", getName(), timings[unit].activeFlag);
        !           787:        IOLog("%s: Valid  : %04lx\n", getName(), timings[unit].validFlag);
        !           788:        IOLog("%s: PIO:%d DMA:%d UDMA:%d\n\n", getName(),
        !           789:                timings[unit].activeTimings[kPIIXProtocolPIO],
        !           790:                timings[unit].activeTimings[kPIIXProtocolDMA],
        !           791:                timings[unit].activeTimings[kPIIXProtocolUDMA33]);
        !           792: #endif /* DEBUG */
        !           793: 
        !           794:        return ret;
        !           795: }
        !           796: 
        !           797: //--------------------------------------------------------------------------
        !           798: // Setup the descriptor table to perform the transfer indicated by the
        !           799: // IOMemoryDescriptor in the IOATACommand object provided.
        !           800: //
        !           801: bool AppleATAPIIX::programDma(IOATACommand * cmd)
        !           802: {
        !           803:     IOPhysicalSegment       physSeg;
        !           804:     IOByteCount                                offset = 0;
        !           805:     IOMemoryDescriptor *       memDesc;
        !           806:        prdEntry_t *            prd = prdTable;
        !           807:     UInt32                                     startSeg;
        !           808:        UInt32                  endSeg;
        !           809:        UInt32                  partialCount;
        !           810:     UInt32                                     bytesLeft;
        !           811: 
        !           812:     cmd->getPointers(&memDesc, &dmaReqLength, &dmaIsWrite);
        !           813: 
        !           814:     if (dmaReqLength == 0)
        !           815:         return true;
        !           816: 
        !           817:        bytesLeft = dmaReqLength;
        !           818: 
        !           819:        // Setup the PRD entries in the descriptor table in memory.
        !           820:        //
        !           821:     for (UInt32 i = 0; i < (PRD_ENTRIES - 1); i++, prd++)
        !           822:        {
        !           823:                if (prdCursor->getPhysicalSegments(memDesc, offset, &physSeg, 1) != 1)
        !           824:                        break;
        !           825:                
        !           826:                startSeg = (physSeg.location & ~0xffff);
        !           827:                endSeg   = (physSeg.location + physSeg.length - 1) & ~0xffff;
        !           828:                
        !           829:                prd->base  = physSeg.location;
        !           830:                prd->flags = 0;
        !           831:                
        !           832:                if (startSeg == endSeg) {                       
        !           833:                        prd->count = PRD_COUNT(physSeg.length);
        !           834:                }
        !           835:                else {
        !           836:                        partialCount = (-physSeg.location & 0xffff);
        !           837:                        prd->count = PRD_COUNT(partialCount);
        !           838:                        prd++;
        !           839:                        i++;
        !           840:                        prd->base  = physSeg.location + partialCount;
        !           841:                        prd->count = physSeg.length - partialCount;
        !           842:                        prd->flags = 0;
        !           843:                }
        !           844:                
        !           845:                bytesLeft -= physSeg.length;
        !           846:                offset += physSeg.length;
        !           847:        }
        !           848:        if (bytesLeft != 0)
        !           849:                return false;
        !           850:        
        !           851:        // Set the 'end-of-table' bit on the last PRD entry.
        !           852:        //
        !           853:        prd--;
        !           854:        prd->flags = PRD_FLAG_EOT;
        !           855: 
        !           856:        /*
        !           857:         * Provide the starting address of the PRD table by loading the
        !           858:         * PRD Table Pointer Register.
        !           859:         */
        !           860:        outl(IOREG(BMIDTPX), prdTablePhys);
        !           861: 
        !           862:        return true;
        !           863: }
        !           864: 
        !           865: //--------------------------------------------------------------------------
        !           866: // Start the DMA engine.
        !           867: //
        !           868: bool AppleATAPIIX::startDma(IOATACommand * cmd)
        !           869: {
        !           870:        /*
        !           871:         * Clear interrupt and error bits in the Status Register.
        !           872:         */
        !           873:        outb(IOREG(BMISX), PIIX_IO_BMISX_ERROR   |
        !           874:                        PIIX_IO_BMISX_IDEINTS |
        !           875:                                           PIIX_IO_BMISX_DMA0CAP |
        !           876:                                           PIIX_IO_BMISX_DMA1CAP);
        !           877: 
        !           878:        /*
        !           879:         * Engage the bus master by writing 1 to the start bit in the
        !           880:         * Command Register. Also set the RWCON bit for the direction
        !           881:         * of the data transfer.
        !           882:         */
        !           883:        outb(IOREG(BMICX), (dmaIsWrite ? 0 : PIIX_IO_BMICX_RWCON) | 
        !           884:                           PIIX_IO_BMICX_SSBM);
        !           885: 
        !           886:        return true;
        !           887: }
        !           888: 
        !           889: //--------------------------------------------------------------------------
        !           890: // Stop the DMA engine.
        !           891: //
        !           892: bool AppleATAPIIX::stopDma(IOATACommand * cmd, UInt32 * transferCount)
        !           893: {
        !           894:        UInt8  bmisx;
        !           895: 
        !           896:        *transferCount = 0;
        !           897:        
        !           898:     if (dmaReqLength == 0)
        !           899:         return true;
        !           900: 
        !           901:        outb(IOREG(BMICX), 0);  // stop the bus-master
        !           902: 
        !           903:        bmisx = inb(IOREG(BMISX));
        !           904: 
        !           905:        if ((bmisx & PIIX_IO_BMISX_STATUS) != PIIX_IO_BMISX_IDEINTS) {
        !           906:                IOLog("AppleATAPIIX::%s() DMA error (0x%02x)\n", __FUNCTION__, bmisx);
        !           907:                return false;
        !           908:        }
        !           909: 
        !           910:        *transferCount = dmaReqLength;
        !           911: 
        !           912:        return true;
        !           913: }
        !           914: 
        !           915: //--------------------------------------------------------------------------
        !           916: //
        !           917: //
        !           918: void AppleATAPIIX::ataTimer( IOTimerEventSource * /* sender */ )
        !           919: {
        !           920:     UInt32             transferCount;
        !           921: 
        !           922:     if ( xferCmdTimer != 0 )
        !           923:     {
        !           924:         if ( --xferCmdTimer == 0 )
        !           925:         {
        !           926:             IOLog("AppleATAPIIX::%s() - Timeout occurred\n\r", __FUNCTION__ );
        !           927:            
        !           928:             stopDma( xferCmd, &transferCount ); 
        !           929: 
        !           930:             resetBusRequest();
        !           931: 
        !           932:             if ( xferCmdSave != NULL )
        !           933:             {
        !           934:                 xferCmd     = xferCmdSave;
        !           935:                 xferCmdSave = NULL;
        !           936:             }
        !           937:             completeCmd( xferCmd, ataReturnErrorInterruptTimeout );
        !           938:         }
        !           939:     }
        !           940: 
        !           941:     timerEventSource->setTimeoutMS(ATATimerIntervalmS);
        !           942: }
        !           943: 
        !           944: //--------------------------------------------------------------------------
        !           945: // Perform a write to the ATA block registers.
        !           946: //
        !           947: void AppleATAPIIX::writeATAReg(UInt32 regIndex, UInt32 regValue)
        !           948: {
        !           949:     if (regIndex == 0) {
        !           950:                outw(ioCmdRange, (UInt16) regValue);
        !           951:     }
        !           952:     else if (regIndex < ataRegDeviceControl) {
        !           953:                outb(ioCmdRange + regIndex, (UInt8) regValue);
        !           954:     }     
        !           955:     else {
        !           956:                outb(ioCtlRange + regIndex - ataRegDeviceControl + 2, 
        !           957:                     (UInt8) regValue);
        !           958:     }
        !           959: }
        !           960: 
        !           961: //--------------------------------------------------------------------------
        !           962: // Perform a read from the ATA block registers.
        !           963: //
        !           964: UInt32 AppleATAPIIX::readATAReg( UInt32 regIndex )
        !           965: {
        !           966:     if (regIndex == 0) {
        !           967:                return inw(ioCmdRange);
        !           968:     }
        !           969:     else if (regIndex < ataRegDeviceControl) {
        !           970:                return inb(ioCmdRange + regIndex);
        !           971:     }
        !           972:        return inb(ioCtlRange + regIndex - ataRegDeviceControl + 2);
        !           973: }
        !           974: 
        !           975: //--------------------------------------------------------------------------
        !           976: // Frees the drivers instance. Make sure all objects allocated during
        !           977: // our initialization are freed.
        !           978: //
        !           979: void AppleATAPIIX::free()
        !           980: {
        !           981:     if (interruptEventSource) {
        !           982:         interruptEventSource->disable();
        !           983:         interruptEventSource->release();
        !           984:     }
        !           985:   
        !           986:     if (timerEventSource)
        !           987:         timerEventSource->release();
        !           988:        
        !           989:        if (prdCursor)
        !           990:                prdCursor->release();
        !           991:  
        !           992:     if (prdTable != 0)
        !           993:                _deallocatePRDTable();
        !           994:        
        !           995:        return super::free();
        !           996: }
        !           997: 
        !           998: //--------------------------------------------------------------------------
        !           999: // This function is called when our interruptEventSource receives an
        !          1000: // interrupt. Simply pass the action to our superclass to advance its
        !          1001: // state machine.
        !          1002: //
        !          1003: void AppleATAPIIX::interruptOccurred()
        !          1004: {
        !          1005:     super::interruptOccurred();
        !          1006: }
        !          1007: 
        !          1008: //--------------------------------------------------------------------------
        !          1009: // This function is called by our superclass to disable controller
        !          1010: // interrupts.
        !          1011: //
        !          1012: void AppleATAPIIX::disableControllerInterrupts()
        !          1013: {
        !          1014:     interruptEventSource->disable();
        !          1015: }
        !          1016: 
        !          1017: //--------------------------------------------------------------------------
        !          1018: // This function is called by our superclass to enable controller
        !          1019: // interrupts.
        !          1020: //
        !          1021: void AppleATAPIIX::enableControllerInterrupts()
        !          1022: {
        !          1023:     interruptEventSource->enable();
        !          1024: }
        !          1025: 
        !          1026: //--------------------------------------------------------------------------
        !          1027: // Private function: _readPCIConfigSpace
        !          1028: //
        !          1029: // Read the entire PCI config space and stores it to the buffer
        !          1030: // pointed by 'configSpace'.
        !          1031: //
        !          1032: bool AppleATAPIIX::_readPCIConfigSpace(UInt8 * configSpace)
        !          1033: {
        !          1034:        UInt32 * dwordPtr = (UInt32 *) configSpace;
        !          1035: 
        !          1036:        for (int i = 0; i < 64; i++, dwordPtr++)
        !          1037:                *dwordPtr = provider->configRead32(i * 4);
        !          1038: 
        !          1039:        return true;
        !          1040: }
        !          1041: 
        !          1042: //--------------------------------------------------------------------------
        !          1043: // Private function: _writePCIConfigSpace
        !          1044: //
        !          1045: // Write the entire PCI config space from the buffer pointed
        !          1046: // by 'configSpace'.
        !          1047: //
        !          1048: bool AppleATAPIIX::_writePCIConfigSpace(UInt8 * configSpace)
        !          1049: {
        !          1050:        UInt32 * dwordPtr = (UInt32 *) configSpace;
        !          1051: 
        !          1052:        for (int i = 0; i < 64; i++, dwordPtr++)
        !          1053:                provider->configWrite32(i * 4, *dwordPtr);
        !          1054: 
        !          1055:        return true;
        !          1056: }

unix.superglobalmegacorp.com

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