|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.