Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

IdeAta.h File Reference

IDE driver::ATA Protocol header. More...

#include <const.h>

Go to the source code of this file.

Functions

int IdeDeviceSelection (int Dev)
void IdeDeviceDetection (int Dev)
void IdeDeviceTypeDetection (int Dev)
int IdeSoftReset (int SkipFlag, int UseInterrupt)
int IdeNonData (int Dev, int Cmd, int Feat, int SecC, dword Cyl, int Head, int Sec, int UseInterrupt)
int IdePioDataInLba (int Dev, int Cmd, int Feat, int SecC, uint64 Lba, word *Buffer, int NumSect, int MultiCnt, int UseInterrupt)
int IdePioDataIn (int Dev, int Cmd, int Feat, int SecC, dword Cyl, int Head, int Sect, word *Buffer, int NumSect, int MultiCnt, int UseInterrupt)
int IdePioDataOutLba (int Dev, int Cmd, int Feat, int SecC, uint64 Lba, word *Buffer, int NumSect, int MultiCnt, int UseInterrupt)
int IdePioDataOut (int Dev, int Cmd, int Feat, int SecC, dword Cyl, int Head, int Sect, word *Buffer, int NumSect, int MultiCnt, int UseInterrupt)


Detailed Description

IDE driver::ATA Protocol header.

Author:
Luca Giovacchini
Date:
Last update: 2003-11-07
Note:
Copyright (©) 2003 Luca Giovacchini
This driver is based on Atadrv by Hale Landis but it is completely rearranged for the minirighi32.
IMPORTANT!!!
Here you can find sub implementing tha ATA-Standard protocols. Each Hd command must be executed throught one of these protocols. Parameters meanings are command dependent. Refer to Ata-4 document to see what protocol to use for each command and the meaning of each parameter. Some protocols are not developed exactly as T13 says.

Read IdeDebug for Error Return Code Explain.

Definition in file IdeAta.h.


Function Documentation

void IdeDeviceDetection int    Dev
 

Definition at line 45 of file IdeAta.c.

00046 {
00047         byte Sc,Sn;
00048 
00049         // Select the device
00050         SetDevBit(Dev);
00051 
00052         // we must try to issue a command (ex. write and read a readable and writeable register)
00053         // See Ata-4 9.16.2
00054         
00055         // try to write some value (do not use 00 or FF)
00056         OutPortAta(CC_SECC, 0x55 );
00057         OutPortAta(CC_SECN, 0xaa );
00058         OutPortAta(CC_SECC, 0xaa );
00059         OutPortAta(CC_SECN, 0x55 );
00060         OutPortAta(CC_SECC, 0x55 );
00061         OutPortAta(CC_SECN, 0xaa );
00062    
00063         // read if last value are stored correctly
00064         Sc = InPortAta( CC_SECC );
00065         Sn = InPortAta( CC_SECN );
00066 
00067         if ( ( Sc == 0x55 ) && ( Sn == 0xaa ) )    
00068         {
00069                 // we think (but not sure) there is a device but we don't know what type                
00070                 CurrentChannel->Device[Dev].Type=CC_DEVTYPE_UNKN;
00071         }
00072         else
00073         {
00074                 // we think (but not sure) there isn't a device
00075                 CurrentChannel->Device[Dev].Type=CC_DEVTYPE_NONE;
00076         }
00077 }

int IdeDeviceSelection int    Dev
 

Definition at line 206 of file IdeAta.c.

00207 {
00208         byte Status;
00209         Timer_Struct Timer;
00210 
00211         // PAY ATTENTION HERE
00212         // The caller may want to issue a command to a device that doesn't
00213         // exist (for example, Exec Dev Diag), so if we see this,
00214         // just select that device, skip all status checking and return.
00215         // We assume the caller knows what they are doing!
00216 
00217         if ( CurrentChannel->Device[Dev].Type != CC_DEVTYPE_ATA && CurrentChannel->Device[Dev].Type != CC_DEVTYPE_ATAPI )
00218         {
00219                 // select the device and return
00220                 SetDevBit(Dev);
00221                 return 0; 
00222         }
00223 
00224         Timer=TimerStart(HDC_ATATIMEOUT);
00225    // The rest of this is the normal ATA stuff for device selection
00226    // and we don't expect the caller to be selecting a device that
00227    // does not exist.
00228    // We don't know which drive is currently selected but we should
00229    // wait for it to be not BUSY.  Normally it will be not BUSY
00230    // unless something is very wrong!
00231         if (WaitForBsy(Timer,CC_STAT))  
00232                 return 11;              
00233 
00234    // Here we select the drive we really want to work with by
00235    // putting 0xA0 or 0xB0 in the Drive/Head register (1f6).
00236         SetDevBit(Dev);
00237 
00238    // If the selected device is an ATA device,
00239    // wait for it to have READY and SEEK COMPLETE
00240    // status.  Normally the drive should be in this state unless
00241    // something is very wrong (or initial power up is still in
00242    // progress).  For any other type of device, just wait for
00243    // BSY=0 and assume the caller knows what they are doing.
00244 
00245         while ( TRUE )
00246         {
00247                 Status = InPortAta( CC_STAT );
00248                 if ( CurrentChannel->Device[Dev].Type == CC_DEVTYPE_ATA )
00249                 {
00250                         if ( ( Status & ( HDC_STAT_BSY | HDC_STAT_RDY | HDC_STAT_SKC ) )
00251                                                 == ( HDC_STAT_RDY | HDC_STAT_SKC ) )
00252                                 break;
00253                 }
00254                 else
00255                 {
00256                         if ( ( Status & HDC_STAT_BSY ) == 0 )
00257                     break;
00258                 }
00259                 if ( TimerElapsed(Timer) )
00260                         return 12;
00261         }
00262 
00263         return 0;
00264 }

void IdeDeviceTypeDetection int    Dev
 

Definition at line 82 of file IdeAta.c.

00083 {
00084         byte Sc,Sn,Cl,Ch,St;
00085 
00086         if ( CurrentChannel->Device[Dev].Type != CC_DEVTYPE_NONE )
00087         {
00088                 SetDevBit(Dev);
00089 
00090                 Sc = InPortAta( CC_SECC );
00091                 Sn = InPortAta( CC_SECN );
00092                 if ( ( Sc == 0x01 ) && ( Sn == 0x01 ) ) 
00093                 {
00094                         Cl = InPortAta( CC_CYLL );
00095                         Ch = InPortAta( CC_CYLH );
00096                         St = InPortAta( CC_STAT );
00097                         if ( ( Cl == 0x14 ) && ( Ch == 0xEB ) )
00098                                 CurrentChannel->Device[Dev].Type=CC_DEVTYPE_ATAPI;
00099                         else if ( ( Cl == 0x00 ) && ( Ch == 0x00 ) && ( St != 0x00 ) )
00100                                 CurrentChannel->Device[Dev].Type=CC_DEVTYPE_ATA;
00101                         else
00102                                 CurrentChannel->Device[Dev].Type=CC_DEVTYPE_UNKN;       
00103                 }
00104                 else
00105                         CurrentChannel->Device[Dev].Type=CC_DEVTYPE_NONE;
00106         }
00107 }

int IdeNonData int    Dev,
int    Cmd,
int    Feat,
int    SecC,
dword    Cyl,
int    Head,
int    Sec,
int    UseInterrupt
 

Definition at line 270 of file IdeAta.c.

00273 {
00274         byte SecCnt;
00275         byte SecNum;
00276         byte DevHead;
00277         byte DevCtrl;
00278         byte CylLow;
00279         byte CylHigh;
00280         byte Status;
00281         int TimeOut=FALSE;
00282         int Err=FALSE;
00283         Timer_Struct Timer;
00284 
00285         DevCtrl = HDC_DEVC_HD15 | (UseInterrupt ? 0 : HDC_DEVC_NIEN);
00286         DevHead = CurrentChannel->Device[Dev].RegBit;
00287         DevHead = DevHead | ( Head & 0x4f );
00288         CylLow = Cyl & 0x00ff;
00289         CylHigh = ( Cyl & 0xff00 ) >> 8;
00290 
00291 
00292         Timer=TimerStart(HDC_ATATIMEOUT);
00293 
00294         if ( Cmd != HDC_CMD_DEVICE_RESET )
00295         {
00296                 // Select the drive - call the sub_select function.
00297                 // Quit now if this fails.
00298 
00299                 Err=IdeDeviceSelection(Dev);
00300                 if ( Err )
00301                         return Err;
00302 
00303                 // Set up all the registers except the command register.
00304 
00305                 OutPortAta( CC_DEVC, DevCtrl );
00306                 OutPortAta( CC_FEAT, Feat );
00307                 OutPortAta( CC_SECC, SecC );
00308                 OutPortAta( CC_SECN, Sect );
00309                 OutPortAta( CC_CYLL, CylLow );
00310                 OutPortAta( CC_CYLH, CylHigh );
00311                 OutPortAta( CC_DEVH, DevHead );
00312         }
00313 
00314 
00315         OutPortAta( CC_CMD, Cmd );
00316         DELAY400NS;
00317 
00318         AtapiDelay(CC_DEV0);
00319         AtapiDelay(CC_DEV1);    
00320 
00321         if ( ( Cmd == HDC_CMD_EXECUTE_DEVICE_DIAGNOSTIC ) &&
00322        ( CurrentChannel->Device[CC_DEV0].Type == CC_DEVTYPE_NONE ) )
00323         {
00324     
00325                 while ( TRUE )
00326                 {
00327                         OutPortAta( CC_DEVH, HDC_DEVH_DEV1 );
00328                         DELAY400NS;
00329                         SecCnt = InPortAta( CC_SECC );
00330                         SecNum = InPortAta( CC_SECN );
00331                         if ( ( SecCnt == 0x01 ) && ( SecNum == 0x01 ) )
00332                                 break;
00333                         if ( TimerElapsed(Timer) )
00334                         {
00335                                 Err=24;
00336                                 break;
00337                         }
00338                 }
00339         }
00340         else
00341         {               
00342                 if ( Cmd == HDC_CMD_DEVICE_RESET || !UseInterrupt )
00343                 {
00344                         TimeOut=WaitForBsy(Timer,CC_ASTAT);
00345                         Err=23;
00346                 }
00347                 else
00348                 {
00349                         TimeOut=WaitForInt(Timer);
00350                         Err=22; 
00351                 }
00352         }
00353         // We MUST read status register even if we have a timeout
00354         // for clear pending interrupt
00355         // Read the primary status register.  In keeping with the rules
00356         // stated above the primary status register is read only
00357         // ONCE.
00358         Status = InPortAta( CC_STAT );
00359 
00360         // Error if BUSY, DEVICE FAULT, DRQ or ERROR status now.
00361 
00362         if (Err)
00363                 return Err;
00364 
00365         if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_DRQ | HDC_STAT_ERR ) ) 
00366                 return 21;
00367 
00368         return 0;
00369 }

int IdePioDataIn int    Dev,
int    Cmd,
int    Feat,
int    SecC,
dword    Cyl,
int    Head,
int    Sect,
word   Buffer,
int    NumSect,
int    MultiCnt,
int    UseInterrupt
 

Definition at line 413 of file IdeAta.c.

00418 {
00419         byte DevHead;
00420         byte DevCtrl;
00421         byte CylLow;
00422         byte CylHigh;
00423         byte Status;
00424         dword WordCnt=0;
00425         int TimeOut=FALSE;
00426         int Err=FALSE;
00427         Timer_Struct Timer;
00428         
00429         // setup register values and adjust parameters
00430         DevCtrl = HDC_DEVC_HD15 | (UseInterrupt ? 0 : HDC_DEVC_NIEN);
00431         DevHead = CurrentChannel->Device[Dev].RegBit;
00432         // with 4f i let pass head number and lba bit
00433         DevHead = DevHead | ( Head & 0x4f );
00434         CylLow = Cyl & 0x00ff;
00435         CylHigh = ( Cyl & 0xff00 ) >> 8;
00436 
00437         // these commands transfer only 1 sector
00438         if (    ( Cmd == HDC_CMD_IDENTIFY_DEVICE )
00439                         || ( Cmd == HDC_CMD_IDENTIFY_PACKET_DEVICE )
00440                         || ( Cmd == HDC_CMD_READ_BUFFER )
00441                 )
00442 
00443                 NumSect = 1;
00444 
00445         if ( Cmd != HDC_CMD_READ_MULTIPLE )
00446                 MultiCnt=1;
00447         
00448         // Set command time out.
00449         Timer=TimerStart(HDC_ATATIMEOUT);
00450 
00451         //Select device if it is not busy
00452         Err=IdeDeviceSelection( Dev );
00453         if ( Err )
00454                 return Err;     
00455 
00456         // Set up all the registers except the command register.
00457         OutPortAta( CC_DEVC, DevCtrl );
00458         OutPortAta( CC_FEAT, Feat );
00459         OutPortAta( CC_SECC, SecC );
00460         OutPortAta( CC_SECN, Sect );
00461         OutPortAta( CC_CYLL, CylLow );
00462         OutPortAta( CC_CYLH, CylHigh );
00463         OutPortAta( CC_DEVH, DevHead );
00464         
00465         // Start the command by setting the Command register.  The drive
00466         // should immediately set BUSY status.
00467         CurrentChannel->IntDone = FALSE;
00468         OutPortAta(CC_CMD,Cmd); 
00469         
00470         // We MUST waste some time by reading the alternate status a few times,
00471         // for gives drive the time to set BUSY in the status register (400ns).
00472         DELAY400NS;
00473 
00474         // Loop to read each sector.
00475         while ( TRUE )
00476         {
00477                 // NOTE NOTE NOTE ...  The primary status register (1f7) MUST NOT be
00478                 // read more than ONCE for each sector transferred!  When the
00479                 // primary status register is read, the drive resets IRQ 14.  The
00480                 // alternate status register (3f6) can be read any number of times.
00481                 // After INT 7x read the the primary status register ONCE
00482                 // and transfer the 256 words (REP INSW).  AS SOON as BOTH the
00483                 // primary status register has been read AND the last of the 256
00484                 // words has been read, the drive is allowed to generate the next
00485                 // IRQ 14 (newer and faster drives could generate the next IRQ 14 in
00486                 // 50 microseconds or less).  If the primary status register is read
00487                 // more than once, there is the possibility of a race between the
00488                 // drive and the software and the next IRQ 14 could be reset before
00489                 // the system interrupt controller sees it.
00490 
00491                 // Wait for INT or wait for not BUSY or wait for time out.
00492 
00493                 AtapiDelay(Dev);
00494 
00495                 if (UseInterrupt)
00496                         TimeOut=WaitForInt(Timer);
00497                 else
00498                         TimeOut=WaitForBsy(Timer,CC_ASTAT);
00499 
00500 
00501                 // Read the primary status register even if there was a timeout
00502                 // to clear pending interrupt.  
00503                 // In keeping with the rules stated above the primary status
00504                 // register is read only ONCE.
00505                 Status = InPortAta( CC_STAT );
00506 
00507 
00508                 if (TimeOut)
00509                         return ( UseInterrupt ? 34 : 35);
00510 
00511 
00512                 // If BSY=0 and DRQ=1, transfer the data,
00513                 // even if we find out there is an error later.
00514                 if ( ( Status & ( HDC_STAT_BSY | HDC_STAT_DRQ ) ) == HDC_STAT_DRQ )
00515                 {
00516                         // determine the number of sectors to transfer
00517                         // MultiCnt is >1 only on Read Multiple command
00518                         // Read Multiple need that we use Set Multiple to
00519                         // indicate numsect per block to transfer. An interrupt
00520                         // is sent only after each block and not after each sector
00521                         WordCnt = MultiCnt ? MultiCnt : 1;
00522                         if ( WordCnt > NumSect )
00523                                 WordCnt = NumSect;
00524                         WordCnt = WordCnt * 256;
00525 
00526                         // A sector is 512 byte or 256 word                     
00527                         // Do the REP INSW to read the data for one block.
00528                         InPortAtaMul(CC_DATA,Buffer,WordCnt);
00529 
00530                         DELAY400NS;    // delay so device can get the status updated
00531 
00532                         // Note: The drive should have dropped DATA REQUEST by now.  If there
00533                         // are more sectors to transfer, BUSY should be active now (unless
00534                         // there is an error).
00535 
00536                         // Decrement the count of sectors to be transferred
00537                         // and increment buffer address.
00538                         NumSect = NumSect - 1;
00539 
00540                         Buffer+=WordCnt;                        
00541                 }
00542                 else
00543                         return 32;                      
00544 
00545                 // So was there any error condition?
00546                 if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_ERR ) )
00547                         return 31;
00548 
00549                 // DRQ should have been set -- was it?
00550                 if ( ( Status & HDC_STAT_DRQ ) == 0 )
00551                         return 32;                      
00552 
00553                 // If all of the requested sectors have been transferred, make a
00554                 // few more checks before we exit.
00555                 if ( NumSect < 1 )
00556                 {
00557                         // Since the drive has transferred all of the requested sectors
00558                         // without error, the drive should not have BUSY, DEVICE FAULT,
00559                         // DATA REQUEST or ERROR active now.
00560                         AtapiDelay(Dev);
00561 
00562                         Status = InPortAta( CC_STAT );
00563                         if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_DRQ | HDC_STAT_ERR ) )
00564                                 return 33;
00565 
00566                         // All sectors have been read without error
00567                         break;   
00568                 }
00569 
00570       // This is the end of the read loop.  If we get here, the loop is
00571       // repeated to read the next sector.  Go back 
00572         }
00573         
00574         return 0;
00575 }

int IdePioDataInLba int    Dev,
int    Cmd,
int    Feat,
int    SecC,
uint64    Lba,
word   Buffer,
int    NumSect,
int    MultiCnt,
int    UseInterrupt
 

Definition at line 376 of file IdeAta.c.

00380 {
00381         dword Cyl;
00382         int Head, Sect;
00383 
00384         // Decompose Lba part for Sector register
00385         Sect = (int) ( Lba & 0x000000ffL );
00386         Lba = Lba >> 8;
00387         // Decompose lba part for Cylinder register
00388         Cyl = (int) ( Lba & 0x0000ffff );
00389         Lba = Lba >> 16;
00390         // Decompose last part of lba address to be used in Head 
00391         // register and set the bit to indicate that this is Lba
00392         // and not head number
00393         Head = ( (int) ( Lba & 0x0fL ) ) | HDC_DEVH_LBA;
00394         // Call Chs function with value meaning Lba address
00395         return IdePioDataIn( Dev, Cmd, Feat, SecC,
00396                          Cyl, Head, Sect, Buffer,
00397                          NumSect, MultiCnt, UseInterrupt);
00398 }

int IdePioDataOut int    Dev,
int    Cmd,
int    Feat,
int    SecC,
dword    Cyl,
int    Head,
int    Sect,
word   Buffer,
int    NumSect,
int    MultiCnt,
int    UseInterrupt
 

Definition at line 612 of file IdeAta.c.

00617 {
00618         byte DevHead;
00619         byte DevCtrl;
00620         byte CylLow;
00621         byte CylHigh;
00622         byte Status;
00623         int TimeOut=FALSE;
00624         int loopFlag = TRUE;
00625         dword WordCnt;
00626         int Err=FALSE;
00627         Timer_Struct Timer;
00628 
00629         // setup register values and adjust parameters
00630         DevCtrl = HDC_DEVC_HD15 | ( UseInterrupt ? 0 : HDC_DEVC_NIEN );
00631         DevHead = CurrentChannel->Device[Dev].RegBit;
00632         // with 4f i let pass head number and lba bit
00633         DevHead = DevHead | ( Head & 0x4F );
00634         CylLow = Cyl & 0x00FF;
00635         CylHigh = ( Cyl & 0xFF00 ) >> 8;
00636         // these commands transfer only 1 sector
00637         if ( Cmd == HDC_CMD_WRITE_BUFFER )
00638                 NumSect = 1;
00639         // only Write Multiple and CFA Write Multiple W/O Erase uses multCnt
00640         if (    ( Cmd != HDC_CMD_WRITE_MULTIPLE )
00641                 && ( Cmd != HDC_CMD_CFA_WRITE_MULTIPLE_WO_ERASE )
00642                 )
00643                 MultiCnt = 1;
00644 
00645         // Set command time out.
00646         TimerStart(HDC_ATATIMEOUT);
00647 
00648         //Select device if it is not busy 
00649         Err=IdeDeviceSelection( Dev );
00650         if ( Err )
00651                 return Err;
00652 
00653         // Set up all the registers except the command register.
00654         OutPortAta( CC_DEVC, DevCtrl );
00655         OutPortAta( CC_FEAT, Feat );
00656         OutPortAta( CC_SECC, SecC );
00657         OutPortAta( CC_SECN, Sect );
00658         OutPortAta( CC_CYLL, CylLow );
00659         OutPortAta( CC_CYLH, CylHigh );
00660         OutPortAta( CC_DEVH, DevHead );
00661 
00662         // Start the command by setting the Command register.  The drive
00663         // should immediately set BUSY status.
00664         CurrentChannel->IntDone = FALSE;
00665         OutPortAta(CC_CMD,Cmd); 
00666 
00667         // We MUST waste some time by reading the alternate status a few times,
00668         // for gives drive the time to set BUSY in the status register (400ns).
00669         DELAY400NS;
00670 
00671         // Wait for not BUSY or time out. 
00672         // NOTE: No interrupt is generated for the first sector of a write
00673         // command.  Well... that's not really true we are working with
00674         // a PCMCIA PC Card ATA device.
00675         AtapiDelay(Dev);        
00676         
00677         if ( WaitForBsy(Timer,CC_ASTAT) )
00678                 return 47;
00679         
00680         // Need to know the current status inside the while
00681         // (i use astat because it not reset interrupt)
00682         Status=InPortAta(CC_ASTAT);
00683 
00684         // If we are using interrupts and we just got an interrupt, this is
00685         // wrong.  The drive must not generate an interrupt at this time.
00686         if ( loopFlag && ( UseInterrupt && CurrentChannel->IntDone ) )
00687                 return 46;
00688         
00689         // This loop writes each sector.
00690         while ( loopFlag )
00691         {
00692                 // NOTE NOTE NOTE ...  The primary status register (1f7) MUST NOT be
00693                 // read more than ONCE for each sector transferred!  When the
00694                 // primary status register is read, the drive resets IRQ 14.  The
00695                 // alternate status register (3f6) can be read any number of times.
00696                 // For correct results, transfer the 256 words (REP OUTSW), wait for
00697                 // INT and then read the primary status register.  AS
00698                 // SOON as BOTH the primary status register has been read AND the
00699                 // last of the 256 words has been written, the drive is allowed to
00700                 // generate the next IRQ 14 (newer and faster drives could generate
00701                 // the next IRQ 14 in 50 microseconds or less).  If the primary
00702                 // status register is read more than once, there is the possibility
00703                 // of a race between the drive and the software and the next IRQ 14
00704                 // could be reset before the system interrupt controller sees it.
00705 
00706                 // If BSY=0 and DRQ=1, transfer the data,
00707                 // even if we find out there is an error later.
00708 
00709                 if ( ( Status & ( HDC_STAT_BSY | HDC_STAT_DRQ ) ) == HDC_STAT_DRQ )
00710                 {
00711                         // determine the number of sectors to transfer
00712 
00713                         WordCnt = MultiCnt ? MultiCnt : 1;
00714                         if ( WordCnt > NumSect )
00715                                 WordCnt = NumSect;
00716                         WordCnt = WordCnt * 256;
00717 
00718                         // Do the REP OUTSW to write the data for one block.
00719                         OutPortAtaMul( CC_DATA, Buffer,WordCnt );
00720 
00721                         DELAY400NS;    // delay so device can get the status updated
00722 
00723                         // Note: The drive should have dropped DATA REQUEST and
00724                         // raised BUSY by now.
00725 
00726                         // Decrement the count of sectors to be transferred
00727                         // and increment buffer address.
00728                         NumSect = NumSect - ( MultiCnt ? MultiCnt : 1 );
00729                         Buffer+=WordCnt;
00730                 }
00731                 else
00732                         return 42;
00733 
00734                 // So was there any error condition?
00735                 if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_ERR ) )
00736                         return 41;
00737 
00738                 // DRQ should have been set -- was it?
00739                 if ( ( Status & HDC_STAT_DRQ ) == 0 )
00740                         return 42;
00741 
00742                 AtapiDelay(Dev);
00743 
00744                 // if there was a timeout we must read the status register
00745                 // to clear pending interrupt before exit
00746                 if ( UseInterrupt )
00747                         TimeOut=WaitForInt(Timer);
00748                 else
00749                         TimeOut=WaitForBsy(Timer,CC_ASTAT);
00750 
00751 
00752                 // Read the primary status register.  In keeping with the rules
00753                 // stated above the primary status register is read only ONCE.
00754                 if ( TimeOut )
00755                         return ( UseInterrupt ? 44 : 45);
00756 
00757                 // If all of the requested sectors have been transferred, make a
00758                 // few more checks before we exit.
00759 
00760                 if ( NumSect < 1 )
00761                 {
00762                         // Since the drive has transferred all of the sectors without
00763                         // error, the drive MUST not have BUSY, DEVICE FAULT, DATA REQUEST
00764                         // or ERROR status at this time.
00765 
00766                         if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_DRQ | HDC_STAT_ERR ) )
00767                                 return 43;
00768 
00769                         // All sectors have been written without error, go to WRITE_DONE.
00770 
00771                         break;
00772 
00773                 }
00774 
00775         
00776                 // This is the end of the write loop.  If we get here, the loop
00777                 // is repeated to write the next sector.  Go back
00778         }
00779 
00780         return 0;
00781 }

int IdePioDataOutLba int    Dev,
int    Cmd,
int    Feat,
int    SecC,
uint64    Lba,
word   Buffer,
int    NumSect,
int    MultiCnt,
int    UseInterrupt
 

Definition at line 583 of file IdeAta.c.

00587 {
00588         dword Cyl;
00589         int Head, Sect;
00590 
00591         // Decompose Lba part for Sector register
00592         Sect = (int) ( Lba & 0x000000ffL );
00593         Lba = Lba >> 8;
00594         // Decompose lba part for Cylinder register
00595         Cyl = (int) ( Lba & 0x0000ffff );
00596         Lba = Lba >> 16;
00597         // Decompose last part of lba address to be used in Head 
00598         // register and set the bit to indicate that this is Lba
00599         // and not head number
00600         Head = ( (int) ( Lba & 0x0fL ) ) | HDC_DEVH_LBA;
00601         // Call Chs function with value meaning Lba address
00602         return IdePioDataOut( Dev, Cmd, Feat, SecC,
00603                          Cyl, Head, Sect, Buffer,
00604                          NumSect, MultiCnt, UseInterrupt);
00605 }

int IdeSoftReset int    SkipFlag,
int    UseInterrupt
 

Definition at line 116 of file IdeAta.c.

00117 {
00118         byte Sc,Sn,DevCtrl;
00119         byte Status;
00120         int Err1=FALSE;
00121         int Err2=FALSE;
00122         int Err3=FALSE;
00123         Timer_Struct Timer;
00124 
00125         // setup register values
00126         DevCtrl = HDC_DEVC_HD15 | ( UseInterrupt ? 0 : HDC_DEVC_NIEN );
00127 
00128         // initialize the command timeout counter
00129         Timer=TimerStart(HDC_ATATIMEOUT);
00130 
00131         // Set and then reset the soft reset bit in the Device Control register.
00132         // for at least x Ns (x may change with Ata version)
00133         // This causes device 0 be selected   
00134         // and both device initiate reset protocol.
00135         // Both Device shall be ready within 31 s
00136         if ( ! SkipFlag )
00137         {
00138                 OutPortAta( CC_DEVC, DevCtrl | HDC_DEVC_SRST );
00139                 DELAY400NS;
00140                 OutPortAta( CC_DEVC, DevCtrl );
00141                 DELAY400NS;
00142         }
00143         
00144 
00145         // If there is a device 0, wait for device 0 to set BSY=0.
00146         if ( CurrentChannel->Device[CC_DEV0].Type != CC_DEVTYPE_NONE ) 
00147         {
00148                 AtapiDelay(CC_DEV0);
00149                 if (WaitForBsy(Timer,CC_STAT))
00150                         Err1=TRUE;
00151         }       
00152         
00153 
00154         // If there is a device 1, wait until device 1 allows
00155         // register access.
00156         if ( CurrentChannel->Device[CC_DEV1].Type != CC_DEVTYPE_NONE ) {
00157                 AtapiDelay(CC_DEV1);
00158 
00159                 while ( TRUE )
00160                 {
00161                         SetDevBit(CC_DEV1);
00162 
00163                         Sc = InPortAta( CC_SECC );
00164                         Sn = InPortAta( CC_SECN );
00165                         if ( ( Sc == 0x01 ) && ( Sn == 0x01 ) )
00166                                 break;
00167 
00168                         if ( TimerElapsed(Timer) )
00169                         {
00170                                 Err2=TRUE;              
00171                                 break;
00172                         }
00173                         GoIdle();
00174                 }
00175 
00176                 // Now check if drive 1 set BSY=0.
00177                 if ( !Err1 && !Err2 ) 
00178                 {
00179                         Status=InPortAta( CC_STAT );
00180                         if ( Status & HDC_STAT_BSY )
00181                                 Err3=TRUE;
00182                 }
00183         }       
00184 
00185         // RESET_DONE:
00186         SetFirstDevBit();       
00187 
00188         if (Err3)
00189                 return 3;
00190         else if (Err1 && Err2)
00191                 return 4;
00192         else if (Err2)
00193                 return 2;
00194         else if (Err1)
00195                 return 1;
00196                 
00197         return 0;
00198 }


Generated on Fri Feb 20 15:32:18 2004 for Minirighi by doxygen1.2.18