#include <const.h>
#include <string.h>
#include <arch/i386.h>
#include <arch/mem.h>
#include <arch/interrupt.h>
#include <kernel/Ide.h>
#include <kernel/IdeLow.h>
#include <kernel/clock.h>
#include <kernel/IdeTimer.h>
#include <kernel/IdeDebug.h>
#include <kernel/video.h>
#include <kernel/IdeAta.h>
Go to the source code of this file.
Functions | |
void | IdeDeviceDetection (int Dev) |
void | IdeDeviceTypeDetection (int Dev) |
int | IdeSoftReset (int SkipFlag, int UseInterrupt) |
int | IdeDeviceSelection (int Dev) |
int | IdeNonData (int Dev, int Cmd, int Feat, int SecC, dword Cyl, int Head, int Sect, 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) |
Variables | |
IdeChannel_Struct * | CurrentChannel |
Read IdeDebug for Error Return Code Explain.
Definition in file IdeAta.c.
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
|