Ztardust Posted November 27, 2008 Share Posted November 27, 2008 Hey! I´ve been trying a lot of different kexts in an attempt to get my boot time down... If I delete the IOATAFamily kext(or other S-ATA relevant kexts), and just startup from my external USB disk, I get rid of the IOKitWaitQuiet timeout and my boot time is only 33 seconds. But when I try to use AppleViaAta or other kexts to get my internal sata disk booting, I get the IOKitWaitQuiet timeout and the boot takes about 1 minute 15 seconds. I feel like I´ve tried everything, but the boot time sits there on 1:15 like a wall... I´m using the machine in my signature, Acer Aspire 5104, with S-ATA 150, ATI SATA controller(ID: 4379:1002). Any suggestions? Link to comment Share on other sites More sharing options...
Ztardust Posted November 29, 2008 Author Share Posted November 29, 2008 Nobody? Link to comment Share on other sites More sharing options...
ar4er Posted November 30, 2008 Share Posted November 30, 2008 I have the same problem on a PC in the signature has not been able to find solutions. Maybe someone has ideas? Link to comment Share on other sites More sharing options...
coolyou Posted December 3, 2008 Share Posted December 3, 2008 I don't know how yet but I'm certain that this timeout value can be changed if we had access to the source code for the kext that IOKitWait is from. It's probably from IOATAFamily.kext. If so, all we really have to do is time how long the timeout lasts for and search for that value in the source code, change it to an extremely low value and build it in Xcode again. I've never tried this, but it should have some sort of variable, all timeouts usually does have a hardcoded variable that we can change this way. Link to comment Share on other sites More sharing options...
ar4er Posted December 3, 2008 Share Posted December 3, 2008 I'm find in IOATAFamily source timeout on 31sec i'm done it IOATAFamily.kext.zip Link to comment Share on other sites More sharing options...
Ztardust Posted December 4, 2008 Author Share Posted December 4, 2008 I'm find in IOATAFamily source timeout on 31sec i'm done it THANK YOU THANK YOU THANK YOU!!!! You solved my problem! I really had only two problems left on my machine, not having 100% support for my graphics card(only 1024x768 on internal screen), and this IOKitWaitQuiet timeout. For me the most important of these problems was the timeout problem, since I often need to be able to start up the machine quickly. This cut my startup time from about 1:15 to ca. 40 seconds. Do you mind perhaps giving a quick explanation of exactly how you did this? I know a lot of people have had this issue, and it would be good to know how you fixed this, in case there is an update of OSX that requires a new version of this kext... Again thank you!! - Ztardust - Link to comment Share on other sites More sharing options...
scififan68 Posted December 4, 2008 Share Posted December 4, 2008 Holy {censored}! it fixed my only issue left, slow boot times! Thank You!! Link to comment Share on other sites More sharing options...
ar4er Posted December 4, 2008 Share Posted December 4, 2008 I'm fix IOATAController.cpp before: for( int i = 0; i < 3100; i++) { // read the status register - helps deal with devices which errantly // set interrupt pending states during resets. Reset operations are not // supposed to generate interrupts, but some devices do anyway. // interrupt handlers should be prepared to deal with errant interrupts on ATA busses. OSSynchronizeIO(); UInt8 status = *_tfStatusCmdReg; // when drive is ready, break the loop if( ( status & readyMask )== readyOn) { // device reset completed in time resetFailed = false; break; } IOSleep( 10 ); // sleep thread for another 10 ms } if( resetFailed ) { // it is likely that this hardware is broken. // There's no recovery action if the drive fails // to reset. DLOG("IOATA device failed to reset.\n"); result = kATATimeoutErr; } DLOG("IOATA reset complete.\n"); return result; } /*--------------------------------------------------------------------------- * * Subclasses should take necessary action to create DMA channel programs, * for the current memory descriptor in _currentCommand and activate the * the DMA hardware ---------------------------------------------------------------------------*/ IOReturn IOATAController::startDMA( void ) { DLOG("IOATA Bus controllers that offer DMA must provide implementation/n"); return kATAModeNotSupported; } /*--------------------------------------------------------------------------- * Subclasses should take all actions necesary to safely shutdown DMA engines * in any state of activity, whether finished, pending or stopped. Calling * this function must be harmless reguardless of the state of the engine. * ---------------------------------------------------------------------------*/ IOReturn IOATAController::stopDMA( void ) { DLOG("IOATA Bus controllers that offer DMA must provide implementation/n"); return kATAModeNotSupported; } /*--------------------------------------------------------------------------- // WaitForU8Status // Will wait up to one millisecond for the value in the altStatus register & mask to equal the value // passed in. Note that I always use the altStatus register so as not to have the side affect of clearing // the interrupt if there is one. ---------------------------------------------------------------------------*/ bool IOATAController::waitForU8Status (UInt8 mask, UInt8 value) { int i; // we will read the status from the alt status register so as not // to clear the interrupt accidentally for (i=0; i < kStatusDelayLoopMS; i++) { OSSynchronizeIO(); if ((*_tfAltSDevCReg & mask) == value) { return true; } IODelay( kStatusDelayTime ); } return false; // time's up } /*---------------------------------------------------------------------------------------------------- ** Routine ATAPISlaveExists ** ** Purpose: Determines whether an ATAPI device seen as a "slave" of a master ATAPI device ** is actually present, or the product of the master shadowing a not-present slave's registers ** Call this function when the master device shows EBh 14h, and the slave also shows the ATAPI ** protocol signature. ** Returns: False if a device is ruled out. True if a device is verified. Leaves device in a ready state, ** But no longer showing signatures. NOTE: Device 1 (slave) is assumed already selected. */ bool IOATAController::ATAPISlaveExists( void ) { UInt8 scratchByte; UInt16 scratchWord; UInt32 dataCounter; UInt32 loopCounter; // The only option is to issue a command and see what happens. OSSynchronizeIO(); *_tfAltSDevCReg = 0x02; // disable interrupts //issue INDENTIFY PACKET DEVICE OSSynchronizeIO(); *_tfStatusCmdReg = 0xA1; // reading and disreguarding a register provides the required 400ns delay time. OSSynchronizeIO(); scratchByte = *_tfAltSDevCReg; OSSynchronizeIO(); scratchByte = *_tfAltSDevCReg; // if the device returns status 00h, we declare it not present. A real device would probably be // status BSY (80h) now. An incredibly fast device might be ready to move data and show DRQ. // However, by ATA standards, a not present device is required to return 00h. // Lucky break, no device and we figured it out in a hurry. if( (scratchByte == 0x00) ) { // enable device interrupt *_tfAltSDevCReg = 0x00; OSSynchronizeIO(); return false; } // OK we probably have a device now. We have to wait for drive to send data, and read it and clear it. // It is possible that the a misbehaving master has decided to respond to the command. So, we'll // break on error bit and say it's not a real slave should that happen. // take a leisurely approach, this will take a while. // give the device up to 10 seconds to respond with data. for( loopCounter = 0; loopCounter < 10000; loopCounter++) { OSSynchronizeIO(); scratchByte = *_tfAltSDevCReg; // If drive sets error, clear status and return false. It's probably a misbehaving master if( scratchByte & 0x01 ) break; // this means the drive is really there. Clear the data and return true. if( (scratchByte & 0x58) == 0x58) // RDY=1 DRQ=1 { OSSynchronizeIO(); scratchByte = *_tfStatusCmdReg; // clear pending interrupt state for( dataCounter = 0; dataCounter < 256; dataCounter++ ) { OSSynchronizeIO(); scratchWord = *_tfDataReg; } // enable device interrupt *_tfAltSDevCReg = 0x00; OSSynchronizeIO(); return true; } // OK, sleep for 10 ms and try again. IOSleep(10); } // In the ugly case, a drive set BSY, and didn't respond within 10 seconds with data. // Otherwise, this is the for loop terminating on seeing the error bit. // We'll read status and return false. OSSynchronizeIO(); scratchByte = *_tfStatusCmdReg; // clear pending interrupt state // enable device interrupt *_tfAltSDevCReg = 0x00; OSSynchronizeIO(); return false; } /*--------------------------------------------------------------------------- * scan the bus to see if devices are attached. The assumption is that the * devices are in a cleanly-reset state, showing their protocol signatures, * and the bus is properly wired with a pull down resistor on DD:7. * If your bus controller does not meet these conditions, you should override * and supply your own function which meets your specific hardware needs. * Your controller may or may not require a reset, or it may require more * thorough scanning, or additional configuration prior to looking for drives, * or it may aquire information from firmware indicating the devices attached. * This function should be self contained and not rely upon work loop or * or anything other than the register pointers being setup and enabled for access ---------------------------------------------------------------------------*/ UInt32 IOATAController::scanForDrives( void ) { UInt32 unitsFound = 0; UInt8 status = 0x00; // count total time spent searching max time allowed = 31 secs // it RARELY takes this long. UInt32 milsSpent = 0; // wait for a not busy bus // should be ready, but some devices may be slow to wake or spin up. for( int loopMils = 0; milsSpent < 3100; loopMils++ ) { OSSynchronizeIO(); status = *_tfStatusCmdReg; if( (status & mATABusy) == 0x00 ) break; IOSleep( 10 ); milsSpent++; } // spun on BSY for too long, declare bus empty if( ! (milsSpent < 3100) ) goto AllDone; // select each possible device on the bus, wait for BSY- // then check for protocol signatures. for( int unit = 0; unit < 2; unit++ ) { // wait for a not busy bus for( int loopMils = 0; milsSpent < 3100; loopMils++ ) { // write the selection bit OSSynchronizeIO(); *_tfSDHReg = ( unit << 4 ); IODelay( 10 ); // typically, devices respond quickly to selection // but we'll give it a chance in case it is slow for some reason. status = *_tfStatusCmdReg; if( (status & mATABusy) == 0x00 ) { break; } IOSleep( 10 ); milsSpent++; } // spun on BSY too long, probably bad device if( ! (milsSpent < 3100) ) goto AllDone; // check for ATAPI device signature first if ( ( *_tfCylLoReg == 0x14) && ( *_tfCylHiReg == 0xEB) ) { if( (unit == 1 ) && ( _devInfo[0].type == kATAPIDeviceType ) ) { // OK we've met the condition for an indeterminate bus, master is atapi and we see a slave atapi // signature. This is legal ATA, though we are fortunate enough that most devices don't do this. if( ATAPISlaveExists( ) != true ) { _devInfo[unit].type = kUnknownATADeviceType; goto AllDone; } } _devInfo[unit].type = kATAPIDeviceType; _devInfo[unit].packetSend = kATAPIDRQFast; // this is the safest default setting unitsFound++; } // check for ATA signature, including status RDY=1 and ERR=0 else if ( (*_tfCylLoReg == 0x00) && (*_tfCylHiReg == 0x00) && (*_tfSCountReg == 0x01) && (*_tfSectorNReg == 0x01) && ( (*_tfAltSDevCReg & 0x51) == 0x50) ) { _devInfo[unit].type = kATADeviceType; _devInfo[unit].packetSend = kATAPIUnknown; unitsFound++; }else{ _devInfo[unit].type = kUnknownATADeviceType; _devInfo[unit].packetSend = kATAPIUnknown; } } after: for( int i = 0; i < 100; i++) { // read the status register - helps deal with devices which errantly // set interrupt pending states during resets. Reset operations are not // supposed to generate interrupts, but some devices do anyway. // interrupt handlers should be prepared to deal with errant interrupts on ATA busses. OSSynchronizeIO(); UInt8 status = *_tfStatusCmdReg; // when drive is ready, break the loop if( ( status & readyMask )== readyOn) { // device reset completed in time resetFailed = false; break; } IOSleep( 10 ); // sleep thread for another 10 ms } if( resetFailed ) { // it is likely that this hardware is broken. // There's no recovery action if the drive fails // to reset. DLOG("IOATA device failed to reset.\n"); result = kATATimeoutErr; } DLOG("IOATA reset complete.\n"); return result; } /*--------------------------------------------------------------------------- * * Subclasses should take necessary action to create DMA channel programs, * for the current memory descriptor in _currentCommand and activate the * the DMA hardware ---------------------------------------------------------------------------*/ IOReturn IOATAController::startDMA( void ) { DLOG("IOATA Bus controllers that offer DMA must provide implementation/n"); return kATAModeNotSupported; } /*--------------------------------------------------------------------------- * Subclasses should take all actions necesary to safely shutdown DMA engines * in any state of activity, whether finished, pending or stopped. Calling * this function must be harmless reguardless of the state of the engine. * ---------------------------------------------------------------------------*/ IOReturn IOATAController::stopDMA( void ) { DLOG("IOATA Bus controllers that offer DMA must provide implementation/n"); return kATAModeNotSupported; } /*--------------------------------------------------------------------------- // WaitForU8Status // Will wait up to one millisecond for the value in the altStatus register & mask to equal the value // passed in. Note that I always use the altStatus register so as not to have the side affect of clearing // the interrupt if there is one. ---------------------------------------------------------------------------*/ bool IOATAController::waitForU8Status (UInt8 mask, UInt8 value) { int i; // we will read the status from the alt status register so as not // to clear the interrupt accidentally for (i=0; i < kStatusDelayLoopMS; i++) { OSSynchronizeIO(); if ((*_tfAltSDevCReg & mask) == value) { return true; } IODelay( kStatusDelayTime ); } return false; // time's up } /*---------------------------------------------------------------------------------------------------- ** Routine ATAPISlaveExists ** ** Purpose: Determines whether an ATAPI device seen as a "slave" of a master ATAPI device ** is actually present, or the product of the master shadowing a not-present slave's registers ** Call this function when the master device shows EBh 14h, and the slave also shows the ATAPI ** protocol signature. ** Returns: False if a device is ruled out. True if a device is verified. Leaves device in a ready state, ** But no longer showing signatures. NOTE: Device 1 (slave) is assumed already selected. */ bool IOATAController::ATAPISlaveExists( void ) { UInt8 scratchByte; UInt16 scratchWord; UInt32 dataCounter; UInt32 loopCounter; // The only option is to issue a command and see what happens. OSSynchronizeIO(); *_tfAltSDevCReg = 0x02; // disable interrupts //issue INDENTIFY PACKET DEVICE OSSynchronizeIO(); *_tfStatusCmdReg = 0xA1; // reading and disreguarding a register provides the required 400ns delay time. OSSynchronizeIO(); scratchByte = *_tfAltSDevCReg; OSSynchronizeIO(); scratchByte = *_tfAltSDevCReg; // if the device returns status 00h, we declare it not present. A real device would probably be // status BSY (80h) now. An incredibly fast device might be ready to move data and show DRQ. // However, by ATA standards, a not present device is required to return 00h. // Lucky break, no device and we figured it out in a hurry. if( (scratchByte == 0x00) ) { // enable device interrupt *_tfAltSDevCReg = 0x00; OSSynchronizeIO(); return false; } // OK we probably have a device now. We have to wait for drive to send data, and read it and clear it. // It is possible that the a misbehaving master has decided to respond to the command. So, we'll // break on error bit and say it's not a real slave should that happen. // take a leisurely approach, this will take a while. // give the device up to 10 seconds to respond with data. for( loopCounter = 0; loopCounter < 10000; loopCounter++) { OSSynchronizeIO(); scratchByte = *_tfAltSDevCReg; // If drive sets error, clear status and return false. It's probably a misbehaving master if( scratchByte & 0x01 ) break; // this means the drive is really there. Clear the data and return true. if( (scratchByte & 0x58) == 0x58) // RDY=1 DRQ=1 { OSSynchronizeIO(); scratchByte = *_tfStatusCmdReg; // clear pending interrupt state for( dataCounter = 0; dataCounter < 256; dataCounter++ ) { OSSynchronizeIO(); scratchWord = *_tfDataReg; } // enable device interrupt *_tfAltSDevCReg = 0x00; OSSynchronizeIO(); return true; } // OK, sleep for 10 ms and try again. IOSleep(10); } // In the ugly case, a drive set BSY, and didn't respond within 10 seconds with data. // Otherwise, this is the for loop terminating on seeing the error bit. // We'll read status and return false. OSSynchronizeIO(); scratchByte = *_tfStatusCmdReg; // clear pending interrupt state // enable device interrupt *_tfAltSDevCReg = 0x00; OSSynchronizeIO(); return false; } /*--------------------------------------------------------------------------- * scan the bus to see if devices are attached. The assumption is that the * devices are in a cleanly-reset state, showing their protocol signatures, * and the bus is properly wired with a pull down resistor on DD:7. * If your bus controller does not meet these conditions, you should override * and supply your own function which meets your specific hardware needs. * Your controller may or may not require a reset, or it may require more * thorough scanning, or additional configuration prior to looking for drives, * or it may aquire information from firmware indicating the devices attached. * This function should be self contained and not rely upon work loop or * or anything other than the register pointers being setup and enabled for access ---------------------------------------------------------------------------*/ UInt32 IOATAController::scanForDrives( void ) { UInt32 unitsFound = 0; UInt8 status = 0x00; // count total time spent searching max time allowed = 31 secs // it RARELY takes this long. UInt32 milsSpent = 0; // wait for a not busy bus // should be ready, but some devices may be slow to wake or spin up. for( int loopMils = 0; milsSpent < 100; loopMils++ ) { OSSynchronizeIO(); status = *_tfStatusCmdReg; if( (status & mATABusy) == 0x00 ) break; IOSleep( 10 ); milsSpent++; } // spun on BSY for too long, declare bus empty if( ! (milsSpent < 100) ) goto AllDone; // select each possible device on the bus, wait for BSY- // then check for protocol signatures. for( int unit = 0; unit < 2; unit++ ) { // wait for a not busy bus for( int loopMils = 0; milsSpent < 100; loopMils++ ) { // write the selection bit OSSynchronizeIO(); *_tfSDHReg = ( unit << 4 ); IODelay( 10 ); // typically, devices respond quickly to selection // but we'll give it a chance in case it is slow for some reason. status = *_tfStatusCmdReg; if( (status & mATABusy) == 0x00 ) { break; } IOSleep( 10 ); milsSpent++; } // spun on BSY too long, probably bad device if( ! (milsSpent < 100) ) goto AllDone; // check for ATAPI device signature first if ( ( *_tfCylLoReg == 0x14) && ( *_tfCylHiReg == 0xEB) ) { if( (unit == 1 ) && ( _devInfo[0].type == kATAPIDeviceType ) ) { // OK we've met the condition for an indeterminate bus, master is atapi and we see a slave atapi // signature. This is legal ATA, though we are fortunate enough that most devices don't do this. if( ATAPISlaveExists( ) != true ) { _devInfo[unit].type = kUnknownATADeviceType; goto AllDone; } } _devInfo[unit].type = kATAPIDeviceType; _devInfo[unit].packetSend = kATAPIDRQFast; // this is the safest default setting unitsFound++; } // check for ATA signature, including status RDY=1 and ERR=0 else if ( (*_tfCylLoReg == 0x00) && (*_tfCylHiReg == 0x00) && (*_tfSCountReg == 0x01) && (*_tfSectorNReg == 0x01) && ( (*_tfAltSDevCReg & 0x51) == 0x50) ) { _devInfo[unit].type = kATADeviceType; _devInfo[unit].packetSend = kATAPIUnknown; unitsFound++; }else{ _devInfo[unit].type = kUnknownATADeviceType; _devInfo[unit].packetSend = kATAPIUnknown; } } Link to comment Share on other sites More sharing options...
R0GUE Posted December 4, 2008 Share Posted December 4, 2008 Excellent work ar4er! My long boot times have now been resolved with this kext. Thanks Link to comment Share on other sites More sharing options...
Lord Darth Vader Posted December 4, 2008 Share Posted December 4, 2008 Big Milestone! my boot time is now under 26 seconds - great job! Thanks a lot. Darth Vader Link to comment Share on other sites More sharing options...
pauℓzurrr. Posted December 4, 2008 Share Posted December 4, 2008 Wow thanks!, solved my problems as well! Link to comment Share on other sites More sharing options...
aliasa_anderson Posted December 4, 2008 Share Posted December 4, 2008 Great Work Indeed !!! Any side-effects as of now ? Link to comment Share on other sites More sharing options...
zuz_242 Posted December 4, 2008 Share Posted December 4, 2008 thanks, worked so far from 75sec down to 33 Link to comment Share on other sites More sharing options...
Lanceomni Posted December 4, 2008 Share Posted December 4, 2008 Problem. I get an error on shutdown. Well this sweet action dropped my boot time to 28.6 Seconds from Post to Desktop but now when I shut down I get this error: Break on __THE_PROCESS_HASFORKED_AND_YOCANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY__YOU_ UST_EXEC__() to debug. The process has forked and you cannot use this CoreFoundation functionality safely. You Must exec(). Link to comment Share on other sites More sharing options...
Fahrenheit457 Posted December 6, 2008 Share Posted December 6, 2008 Thnx. @ar4er My boot time is now from 96 sec. down to 22 sec. Works great! Link to comment Share on other sites More sharing options...
SP1950 Posted December 7, 2008 Share Posted December 7, 2008 thanks!!!! you are a lifesaver!!! even though my rig still hangs at applenforceata, it's good see the desktop one minute earlier than usual!!! Link to comment Share on other sites More sharing options...
viiddee Posted December 8, 2008 Share Posted December 8, 2008 it works! Thanks! Link to comment Share on other sites More sharing options...
lnerrrka Posted December 11, 2008 Share Posted December 11, 2008 Wow thanx, now from ~90sec to ~22 sec. From POST to Desktop :D :thumbsup_anim: Link to comment Share on other sites More sharing options...
ar4er Posted December 17, 2008 Share Posted December 17, 2008 New version for 10.5.6 in post №21 Link to comment Share on other sites More sharing options...
pauℓzurrr. Posted December 17, 2008 Share Posted December 17, 2008 Still waiting for root device for me... Other version work great Edit: Found the reason i think... Seems there are some folders missing? Link to comment Share on other sites More sharing options...
ar4er Posted December 17, 2008 Share Posted December 17, 2008 Just need to add plug-ins. Here with plug-ins: IOATAFamily.kext.zip Link to comment Share on other sites More sharing options...
pauℓzurrr. Posted December 17, 2008 Share Posted December 17, 2008 Thank you, working great now Even seems that I'm starting up a little faster. Link to comment Share on other sites More sharing options...
xypep Posted December 19, 2008 Share Posted December 19, 2008 it works! My long boot times have now been resolved with this kext. Thanks Link to comment Share on other sites More sharing options...
kyle c Posted December 24, 2008 Share Posted December 24, 2008 How do you install this kext? I need to get my boot time down! It is 3min! Thanks How do you install this kext? I need to get my boot time down! It is 3min! Thanks Link to comment Share on other sites More sharing options...
嗯哼恩赫 Posted December 28, 2008 Share Posted December 28, 2008 oh!but why i can't download it!! Link to comment Share on other sites More sharing options...
Recommended Posts