Jump to content

S-ATA & IOKitWait timeout...


  • Please log in to reply
57 replies to this topic

#1
Ztardust

Ztardust

    InsanelyMac Geek

  • Members
  • PipPipPip
  • 122 posts
  • Gender:Male
  • Location:Oslo
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?

#2
Ztardust

Ztardust

    InsanelyMac Geek

  • Members
  • PipPipPip
  • 122 posts
  • Gender:Male
  • Location:Oslo
Nobody? :D

#3
ar4er

ar4er

    InsanelyMac Protégé

  • Members
  • Pip
  • 34 posts
  • Gender:Male
  • Location:Donetsk, Ukraine
I have the same problem on a PC in the signature has not been able to find solutions. Maybe someone has ideas?

#4
coolyou

coolyou

    InsanelyMac Protégé

  • Members
  • Pip
  • 8 posts
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.

#5
ar4er

ar4er

    InsanelyMac Protégé

  • Members
  • Pip
  • 34 posts
  • Gender:Male
  • Location:Donetsk, Ukraine
I'm find in IOATAFamily source timeout on 31sec

i'm done it

Attached Files



#6
Ztardust

Ztardust

    InsanelyMac Geek

  • Members
  • PipPipPip
  • 122 posts
  • Gender:Male
  • Location:Oslo

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 -

#7
scififan68

scififan68

    InsanelyMac Geek

  • Members
  • PipPipPip
  • 151 posts
  • Gender:Male
Holy {censored}! it fixed my only issue left, slow boot times! Thank You!! :)

#8
ar4er

ar4er

    InsanelyMac Protégé

  • Members
  • Pip
  • 34 posts
  • Gender:Male
  • Location:Donetsk, Ukraine
I'm fix IOATAController.cpp

before:
[codebox]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;
}

}[/codebox]
after:
[codebox] 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;
}

}[/codebox]

#9
R0GUE

R0GUE

    InsanelyMac Protégé

  • Members
  • PipPip
  • 54 posts
  • Gender:Male
  • Location:www.infinitemac.com
Excellent work ar4er! My long boot times have now been resolved with this kext. Thanks :)

#10
Lord Darth Vader

Lord Darth Vader

    InsanelyMac Protégé

  • Just Joined
  • Pip
  • 1 posts
Big Milestone!

my boot time is now under 26 seconds - great job!


Thanks a lot.

Darth Vader

#11
pauℓzurrr.

pauℓzurrr.

    Paul

  • Members
  • PipPipPipPipPipPipPip
  • 552 posts
  • Gender:Male
  • Location:Amsterdam
Wow thanks!, solved my problems as well! :thumbsup_anim:

#12
aliasa_anderson

aliasa_anderson

    InsanelyMac Geek

  • Members
  • PipPipPip
  • 171 posts
Great Work Indeed !!!

Any side-effects as of now ?

#13
zuz_242

zuz_242

    InsanelyMac Geek

  • Members
  • PipPipPip
  • 159 posts
thanks, worked so far
from 75sec down to 33 :)

#14
Lanceomni

Lanceomni

    infinitemac.com (φοίνιξ) !

  • Donators
  • 614 posts
  • Gender:Male
  • Location:Florida
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().

#15
Fahrenheit457

Fahrenheit457

    InsanelyMac Protégé

  • Members
  • Pip
  • 7 posts
:) Thnx. @ar4er

My boot time is now from 96 sec. down to 22 sec.

Works great!

#16
SP1950

SP1950

    InsanelyMac Protégé

  • Members
  • Pip
  • 16 posts
thanks!!!!
you are a lifesaver!!!
even though my rig still hangs at applenforceata, it's good see the desktop one minute earlier than usual!!!
:blink:

#17
viiddee

viiddee

    InsanelyMac Protégé

  • Members
  • Pip
  • 21 posts
  • Gender:Male
  • Location:Germany
it works! Thanks!

#18
lnerrrka

lnerrrka

    InsanelyMac Protégé

  • Members
  • Pip
  • 20 posts
Wow thanx, now from ~90sec to ~22 sec.
From POST to Desktop :smoke: :D :D :thumbsup_anim: :thumbsup_anim: :gun:

#19
ar4er

ar4er

    InsanelyMac Protégé

  • Members
  • Pip
  • 34 posts
  • Gender:Male
  • Location:Donetsk, Ukraine
New version for 10.5.6 in post №21

#20
pauℓzurrr.

pauℓzurrr.

    Paul

  • Members
  • PipPipPipPipPipPipPip
  • 552 posts
  • Gender:Male
  • Location:Amsterdam
Still waiting for root device for me...

Other version work great :P

Edit:

Found the reason i think...

Posted Image

Seems there are some folders missing?





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

© 2014 InsanelyMac  |   News  |   Forum  |   Downloads  |   OSx86 Wiki  |   Mac Netbook  |   PHP hosting by CatN  |   Designed by Ed Gain  |   Logo by irfan  |   Privacy Policy