00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <const.h>
00023 #include <string.h>
00024
00025 #include <arch/i386.h>
00026 #include <arch/mem.h>
00027 #include <arch/interrupt.h>
00028
00029 #include <kernel/Ide.h>
00030 #include <kernel/IdeLow.h>
00031 #include <kernel/clock.h>
00032 #include <kernel/IdeTimer.h>
00033 #include <kernel/IdeDebug.h>
00034 #include <kernel/video.h>
00035
00036 #include <kernel/IdeAta.h>
00037
00038 extern IdeChannel_Struct * CurrentChannel;
00039
00040
00041
00042
00043
00044
00045 void IdeDeviceDetection (int Dev)
00046 {
00047 byte Sc,Sn;
00048
00049
00050 SetDevBit(Dev);
00051
00052
00053
00054
00055
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
00064 Sc = InPortAta( CC_SECC );
00065 Sn = InPortAta( CC_SECN );
00066
00067 if ( ( Sc == 0x55 ) && ( Sn == 0xaa ) )
00068 {
00069
00070 CurrentChannel->Device[Dev].Type=CC_DEVTYPE_UNKN;
00071 }
00072 else
00073 {
00074
00075 CurrentChannel->Device[Dev].Type=CC_DEVTYPE_NONE;
00076 }
00077 }
00078
00079
00080
00081
00082 void IdeDeviceTypeDetection (int Dev)
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 }
00108
00109
00110
00111
00112
00113
00114
00115
00116 int IdeSoftReset( int SkipFlag, int UseInterrupt )
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
00126 DevCtrl = HDC_DEVC_HD15 | ( UseInterrupt ? 0 : HDC_DEVC_NIEN );
00127
00128
00129 Timer=TimerStart(HDC_ATATIMEOUT);
00130
00131
00132
00133
00134
00135
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
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
00155
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
00177 if ( !Err1 && !Err2 )
00178 {
00179 Status=InPortAta( CC_STAT );
00180 if ( Status & HDC_STAT_BSY )
00181 Err3=TRUE;
00182 }
00183 }
00184
00185
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 }
00199
00200
00201
00202
00203
00204
00205
00206 int IdeDeviceSelection( int Dev )
00207 {
00208 byte Status;
00209 Timer_Struct Timer;
00210
00211
00212
00213
00214
00215
00216
00217 if ( CurrentChannel->Device[Dev].Type != CC_DEVTYPE_ATA && CurrentChannel->Device[Dev].Type != CC_DEVTYPE_ATAPI )
00218 {
00219
00220 SetDevBit(Dev);
00221 return 0;
00222 }
00223
00224 Timer=TimerStart(HDC_ATATIMEOUT);
00225
00226
00227
00228
00229
00230
00231 if (WaitForBsy(Timer,CC_STAT))
00232 return 11;
00233
00234
00235
00236 SetDevBit(Dev);
00237
00238
00239
00240
00241
00242
00243
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 }
00265
00266
00267
00268
00269
00270 int IdeNonData( int Dev, int Cmd,
00271 int Feat, int SecC,
00272 dword Cyl, int Head, int Sect, int UseInterrupt )
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
00297
00298
00299 Err=IdeDeviceSelection(Dev);
00300 if ( Err )
00301 return Err;
00302
00303
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
00354
00355
00356
00357
00358 Status = InPortAta( CC_STAT );
00359
00360
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 }
00370
00371
00372
00373
00374
00375
00376 int IdePioDataInLba(int Dev, int Cmd,
00377 int Feat, int SecC, uint64 Lba,
00378 word * Buffer,
00379 int NumSect, int MultiCnt, int UseInterrupt)
00380 {
00381 dword Cyl;
00382 int Head, Sect;
00383
00384
00385 Sect = (int) ( Lba & 0x000000ffL );
00386 Lba = Lba >> 8;
00387
00388 Cyl = (int) ( Lba & 0x0000ffff );
00389 Lba = Lba >> 16;
00390
00391
00392
00393 Head = ( (int) ( Lba & 0x0fL ) ) | HDC_DEVH_LBA;
00394
00395 return IdePioDataIn( Dev, Cmd, Feat, SecC,
00396 Cyl, Head, Sect, Buffer,
00397 NumSect, MultiCnt, UseInterrupt);
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 int IdePioDataIn( int Dev, int Cmd,
00414 int Feat, int SecC,
00415 dword Cyl, int Head, int Sect,
00416 word * Buffer,
00417 int NumSect, int MultiCnt, int UseInterrupt)
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
00430 DevCtrl = HDC_DEVC_HD15 | (UseInterrupt ? 0 : HDC_DEVC_NIEN);
00431 DevHead = CurrentChannel->Device[Dev].RegBit;
00432
00433 DevHead = DevHead | ( Head & 0x4f );
00434 CylLow = Cyl & 0x00ff;
00435 CylHigh = ( Cyl & 0xff00 ) >> 8;
00436
00437
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
00449 Timer=TimerStart(HDC_ATATIMEOUT);
00450
00451
00452 Err=IdeDeviceSelection( Dev );
00453 if ( Err )
00454 return Err;
00455
00456
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
00466
00467 CurrentChannel->IntDone = FALSE;
00468 OutPortAta(CC_CMD,Cmd);
00469
00470
00471
00472 DELAY400NS;
00473
00474
00475 while ( TRUE )
00476 {
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 AtapiDelay(Dev);
00494
00495 if (UseInterrupt)
00496 TimeOut=WaitForInt(Timer);
00497 else
00498 TimeOut=WaitForBsy(Timer,CC_ASTAT);
00499
00500
00501
00502
00503
00504
00505 Status = InPortAta( CC_STAT );
00506
00507
00508 if (TimeOut)
00509 return ( UseInterrupt ? 34 : 35);
00510
00511
00512
00513
00514 if ( ( Status & ( HDC_STAT_BSY | HDC_STAT_DRQ ) ) == HDC_STAT_DRQ )
00515 {
00516
00517
00518
00519
00520
00521 WordCnt = MultiCnt ? MultiCnt : 1;
00522 if ( WordCnt > NumSect )
00523 WordCnt = NumSect;
00524 WordCnt = WordCnt * 256;
00525
00526
00527
00528 InPortAtaMul(CC_DATA,Buffer,WordCnt);
00529
00530 DELAY400NS;
00531
00532
00533
00534
00535
00536
00537
00538 NumSect = NumSect - 1;
00539
00540 Buffer+=WordCnt;
00541 }
00542 else
00543 return 32;
00544
00545
00546 if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_ERR ) )
00547 return 31;
00548
00549
00550 if ( ( Status & HDC_STAT_DRQ ) == 0 )
00551 return 32;
00552
00553
00554
00555 if ( NumSect < 1 )
00556 {
00557
00558
00559
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
00567 break;
00568 }
00569
00570
00571
00572 }
00573
00574 return 0;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583 int IdePioDataOutLba(int Dev, int Cmd,
00584 int Feat, int SecC, uint64 Lba,
00585 word * Buffer,
00586 int NumSect, int MultiCnt, int UseInterrupt)
00587 {
00588 dword Cyl;
00589 int Head, Sect;
00590
00591
00592 Sect = (int) ( Lba & 0x000000ffL );
00593 Lba = Lba >> 8;
00594
00595 Cyl = (int) ( Lba & 0x0000ffff );
00596 Lba = Lba >> 16;
00597
00598
00599
00600 Head = ( (int) ( Lba & 0x0fL ) ) | HDC_DEVH_LBA;
00601
00602 return IdePioDataOut( Dev, Cmd, Feat, SecC,
00603 Cyl, Head, Sect, Buffer,
00604 NumSect, MultiCnt, UseInterrupt);
00605 }
00606
00607
00608
00609
00610
00611
00612 int IdePioDataOut( int Dev, int Cmd,
00613 int Feat, int SecC,
00614 dword Cyl, int Head, int Sect,
00615 word * Buffer,
00616 int NumSect, int MultiCnt, int UseInterrupt)
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
00630 DevCtrl = HDC_DEVC_HD15 | ( UseInterrupt ? 0 : HDC_DEVC_NIEN );
00631 DevHead = CurrentChannel->Device[Dev].RegBit;
00632
00633 DevHead = DevHead | ( Head & 0x4F );
00634 CylLow = Cyl & 0x00FF;
00635 CylHigh = ( Cyl & 0xFF00 ) >> 8;
00636
00637 if ( Cmd == HDC_CMD_WRITE_BUFFER )
00638 NumSect = 1;
00639
00640 if ( ( Cmd != HDC_CMD_WRITE_MULTIPLE )
00641 && ( Cmd != HDC_CMD_CFA_WRITE_MULTIPLE_WO_ERASE )
00642 )
00643 MultiCnt = 1;
00644
00645
00646 TimerStart(HDC_ATATIMEOUT);
00647
00648
00649 Err=IdeDeviceSelection( Dev );
00650 if ( Err )
00651 return Err;
00652
00653
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
00663
00664 CurrentChannel->IntDone = FALSE;
00665 OutPortAta(CC_CMD,Cmd);
00666
00667
00668
00669 DELAY400NS;
00670
00671
00672
00673
00674
00675 AtapiDelay(Dev);
00676
00677 if ( WaitForBsy(Timer,CC_ASTAT) )
00678 return 47;
00679
00680
00681
00682 Status=InPortAta(CC_ASTAT);
00683
00684
00685
00686 if ( loopFlag && ( UseInterrupt && CurrentChannel->IntDone ) )
00687 return 46;
00688
00689
00690 while ( loopFlag )
00691 {
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 if ( ( Status & ( HDC_STAT_BSY | HDC_STAT_DRQ ) ) == HDC_STAT_DRQ )
00710 {
00711
00712
00713 WordCnt = MultiCnt ? MultiCnt : 1;
00714 if ( WordCnt > NumSect )
00715 WordCnt = NumSect;
00716 WordCnt = WordCnt * 256;
00717
00718
00719 OutPortAtaMul( CC_DATA, Buffer,WordCnt );
00720
00721 DELAY400NS;
00722
00723
00724
00725
00726
00727
00728 NumSect = NumSect - ( MultiCnt ? MultiCnt : 1 );
00729 Buffer+=WordCnt;
00730 }
00731 else
00732 return 42;
00733
00734
00735 if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_ERR ) )
00736 return 41;
00737
00738
00739 if ( ( Status & HDC_STAT_DRQ ) == 0 )
00740 return 42;
00741
00742 AtapiDelay(Dev);
00743
00744
00745
00746 if ( UseInterrupt )
00747 TimeOut=WaitForInt(Timer);
00748 else
00749 TimeOut=WaitForBsy(Timer,CC_ASTAT);
00750
00751
00752
00753
00754 if ( TimeOut )
00755 return ( UseInterrupt ? 44 : 45);
00756
00757
00758
00759
00760 if ( NumSect < 1 )
00761 {
00762
00763
00764
00765
00766 if ( Status & ( HDC_STAT_BSY | HDC_STAT_DF | HDC_STAT_DRQ | HDC_STAT_ERR ) )
00767 return 43;
00768
00769
00770
00771 break;
00772
00773 }
00774
00775
00776
00777
00778 }
00779
00780 return 0;
00781 }
00782