#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) |
Read IdeDebug for Error Return Code Explain.
Definition in file IdeAta.h.
|
|
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 }
|
1.2.18