00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "includes.h"
00012
00013 #if(DEBUG_FDC1_ENABLE==1)
00014 #define DEBUG_FDC_INFO 1
00015 #define DEBUG_FDC_MSR 1
00016 #define DEBUG_FDC_ST0 1
00017 #define DEBUG_FDC_TIMEOUT 1
00018 #define DEBUG_FDC_INTERRUPT 1
00019 #define DEBUG_FDC_FIFO 1
00020 #endif
00021
00022 static const FDC_RECORD FdcTypes[7] ={
00023 {0, 0,1000000,3000000,20000,3000000,{ 7, 4, 8, 2, 1, 5, 3,10 },0, "unknown" },
00024 {1, 4,1000000,3000000,20000,3000000,{ 1, 0, 0, 0, 0, 0, 0, 0 },1, "5.25\" DD, 360 KiB" },
00025 {2, 8, 400000,3000000,20000,3000000,{ 2, 5, 6,23,10,20,12, 0 },2, "5.25\" HD, 1200 KiB" },
00026 {3, 4,1000000,3000000,20000,3000000,{ 4,22,21,30, 3, 0, 0, 0 },4, "3.5\" DD, 720 KiB" },
00027 {4, 8, 400000,3000000,20000,1500000,{ 7, 4,25,22,31,21,29,11 },7, "3.5\" HD, 1440 KiB" },
00028 {5, 15, 400000,3000000,20000,3000000,{ 7, 8, 4,25,28,22,31,21 },8, "3.5\" ED, 2880 KiB AMI" },
00029 {6, 15, 400000,3000000,20000,3000000,{ 7, 8, 4,25,28,22,31,21 },8, "3.5\" ED, 2880 KiB" }
00030 };
00031
00032 U8 Fdc1CommandBuffer[8];
00033 U8 Fdc1ResultBuffer[8];
00034 U16 BufferIndex;
00035 FDC_CONTROL Fdc1Ctrl;
00036
00037 void Fdc1Init(void){
00038 PicIrqDisable(IRQ6_FDC);
00039 Fdc1Ctrl.State=FDC_IN_NONDATA;
00040 Fdc1Ctrl.HasInterrupt=false;
00041 Fdc1Ctrl.ControllerType=FDC_DEVICE_NEC765;
00042 Fdc1Ctrl.Device0Type=0;
00043 Fdc1Ctrl.Device1Type=0;
00044 Fdc1Ctrl.Flags=0;
00045 Fdc1Ctrl.DorReg=0;
00046 Fdc1Ctrl.SectorSize=FDC_SECTORSIZE_512;
00047 Fdc1Ctrl.Timer=0;
00048 Fdc1Initialization();
00049 InterruptIrqHandlerSet(IRQ6_FDC,Fdc1Handler);
00050 PicIrqEnable(IRQ6_FDC);
00051 }
00052
00053 void Fdc1Handler(void){
00054 Fdc1Ctrl.HasInterrupt=true;
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064 void Fdc1TimeDelay(U16 Time){
00065 OsTimeDelay(Time);
00066 }
00067
00068
00069
00070
00071
00072
00073 bool Fdc1WriteFifo(U8 Data){
00074 U32 k;
00075
00076 #if(DEBUG_FDC_FIFO==1)
00077 GuiStringPrint("\nfifowrite[");
00078 GuiU8Print(Data);
00079 GuiStringPrint("] ");
00080 #endif
00081 for(Fdc1Ctrl.ReTries=0;Fdc1Ctrl.ReTries<128;Fdc1Ctrl.ReTries++){
00082 Fdc1ReadMsr();
00083 if((Fdc1Ctrl.MsrReg&0xc0)==0x80){
00084 OutByte(FDC1_FIFO_REG,Data);
00085 return true;
00086 }
00087 for(k=0;k<1000;k++);
00088 }
00089 #if(DEBUG_FDC_FIFO==1)
00090 if(Fdc1Ctrl.ReTries==128) GuiStringPrint("\n Retry error");
00091 #endif
00092 return false;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101 U8 Fdc1ReadFifo(void){
00102 U32 k;
00103
00104 #if(DEBUG_FDC_FIFO==1)
00105 GuiStringPrint("fiforead ");
00106 #endif
00107 for(Fdc1Ctrl.ReTries=0;Fdc1Ctrl.ReTries<128;Fdc1Ctrl.ReTries++){
00108 Fdc1ReadMsr();
00109 if((Fdc1Ctrl.MsrReg&0xc0)==0xc0) return InByte(FDC1_FIFO_REG);
00110 for(k=0;k<1000;k++);
00111 }
00112 #if(DEBUG_FDC_FIFO==1)
00113 if(Fdc1Ctrl.ReTries==128) GuiStringPrint("\n Retry error");
00114 #endif
00115 return 0;
00116 }
00117
00118
00119
00120
00121
00122
00123 void Fdc1WriteDor(U8 Data){
00124 Fdc1Ctrl.DorReg=Data;
00125 OutByte(FDC1_DOR_REG,Data);
00126 }
00127
00128
00129
00130
00131
00132
00133 U8 Fdc1ReadMsr(void){
00134 Fdc1Ctrl.MsrReg=InByte(FDC1_MSR_REG);
00135 #if(DEBUG_FDC_MSR==1)
00136 GuiStringPrint("MSR:");
00137 GuiU8Print(Fdc1Ctrl.MsrReg);
00138 GuiStringPrint(" ");
00139
00140
00141
00142
00143
00144
00145
00146
00147 #endif
00148 return Fdc1Ctrl.MsrReg;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 void Fdc1Initialization(void){
00165 U8 i,i2;
00166 U32 j;
00167
00168
00169 Fdc1WriteDor(0x00);
00170 for(j=0;j<10000;j++);
00171 Fdc1WriteDor(0x0c);
00172 for(j=0;j<10000;j++);
00173
00174
00175 OutByte(FDC1_CCR_REG,0x00);
00176 for(j=0;j<10000;j++);
00177 for(j=0;j<4;j++) Fdc1SenseInterruptStatus();
00178 Fdc1Version();
00179 Fdc1Specify();
00180 OutByte(RTC_ADDRESS_PORT,0x10);
00181 i=InByte(0x71);
00182 i2=i;
00183 i=i>>4;
00184 i2=i2&0x0f;
00185 if((i>=0)&&(i<=6)){
00186 Fdc1Ctrl.Device0Type=i;
00187 #if(DEBUG_FDC_INFO==1)
00188 GuiStringPrint("\nFloppy primary: ");
00189 GuiStringPrint(FdcTypes[i].name);
00190 #endif
00191 }
00192 if((i2>=0)&&(i2<=6)){
00193 Fdc1Ctrl.Device1Type=i2;
00194 #if(DEBUG_FDC_INFO==1)
00195 GuiStringPrint("\nFloppy secondary: ");
00196 GuiStringPrint(FdcTypes[i2].name);
00197 #endif
00198 }
00199 return true;
00200 }
00201
00202 void Fdc1MotorOn(void){
00203 if(Fdc1Ctrl.Flags&FDC_SPIN_DOWN) Fdc1Ctrl.Flags=Fdc1Ctrl.Flags&(~FDC_SPIN_DOWN);
00204
00205 if(Fdc1Ctrl.DorReg&FDC_DOR_MOTORON_FDD0) return;
00206 Fdc1WriteDor(FDC_DOR_MOTORON_FDD0|(Fdc1Ctrl.DorReg&0xfc)|FDC_DOR_DEVICENUM0);
00207 }
00208
00209 void Fdc1MotorOff(void){
00210 if((Fdc1Ctrl.DorReg&FDC_DOR_MOTORON_FDD0)==0) return;
00211
00212 Fdc1WriteDor(Fdc1Ctrl.DorReg&(~FDC_DOR_MOTORON_FDD0));
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 bool Fdc1Recalibrate(void){
00224 U8 i;
00225
00226 Fdc1Ctrl.State==FDC_IN_NONDATA;
00227 Fdc1WriteFifo(FDC_CMD_RECALIBRATE);
00228 Fdc1WriteFifo(FDC_DRIVE0);
00229 Fdc1Ctrl.Timer=1000;
00230 while(Fdc1Ctrl.Timer!=0){
00231 if(Fdc1Ctrl.HasInterrupt==true) break;
00232 }
00233 if(Fdc1Ctrl.HasInterrupt==true){
00234 #if(DEBUG_FDC_INTERRUPT==1)
00235 GuiStringPrint("\nsee interrupt");
00236 #endif
00237 Fdc1Ctrl.HasInterrupt=false;
00238 }
00239 if(Fdc1Ctrl.Timer==0){
00240 #if(DEBUG_FDC_TIMEOUT==1)
00241 GuiStringPrint("\ncalibrate time out");
00242 #endif
00243 return false;
00244 }
00245 BufferIndex=0;
00246 Fdc1ReadMsr();
00247 return true;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 bool Fdc1SenseInterruptStatus(void){
00257 U8 i,i2;
00258
00259 Fdc1Ctrl.State==FDC_IN_NONDATA;
00260 BufferIndex=0;
00261 Fdc1WriteFifo(FDC_CMD_SENSEINTERRUPTSTATUS);
00262 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00263 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00264 Fdc1ReadMsr();
00265 #if(DEBUG_FDC_INFO==1)
00266
00267
00268
00269
00270
00271 #endif
00272 if((Fdc1ResultBuffer[0]&0xc0)==FDC_IC_NORMAL){
00273 #if(DEBUG_FDC_ST0==1)
00274 GuiStringPrint("\nnormal termination.");
00275 #endif
00276 return true;
00277 }
00278 else{
00279 #if(DEBUG_FDC_ST0==1)
00280 if((Fdc1ResultBuffer[0]&0xc0)==FDC_IC_ABNORMAL) GuiStringPrint("\nabnormal termination");
00281 else if((Fdc1ResultBuffer[0]&0xc0)==FDC_IC_INVALID) GuiStringPrint("\ninvalid termination");
00282 else if((Fdc1ResultBuffer[0]&0xc0)==FDC_IC_ABNORMAL_POLLING) GuiStringPrint("\nabnormal termination by polling");
00283 #endif
00284
00285 return true;
00286 }
00287 }
00288
00289
00290
00291
00292
00293 void Fdc1Version(void){
00294 Fdc1Ctrl.State==FDC_IN_NONDATA;
00295 Fdc1WriteFifo(FDC_CMD_VERSION);
00296 Fdc1ResultBuffer[0]=Fdc1ReadFifo();
00297 #if(DEBUG_FDC_INFO==1)
00298 GuiStringPrint("\ndetermine controller version: ");
00299 GuiU8Print(Fdc1ResultBuffer[0]);
00300 #endif
00301 switch(Fdc1ResultBuffer[0]){
00302 case 0x80:
00303 Fdc1Ctrl.ControllerType=FDC_DEVICE_NEC765;
00304 #if(DEBUG_FDC_INFO==1)
00305 GuiStringPrint("\n8272A/765A FDC is found on 0x3f0");
00306 #endif
00307 break;
00308 case 0x90:
00309 Fdc1Ctrl.ControllerType=FDC_DEVICE_ENHENCED;
00310 #if(DEBUG_FDC_INFO==1)
00311 GuiStringPrint("\n82077AA FDC is found on 0x3f0");
00312 #endif
00313 break;
00314 default:
00315 Fdc1Ctrl.ControllerType=FDC_DEVICE_NONE;
00316 #if(DEBUG_FDC_INFO==1)
00317 GuiStringPrint("\nUNKNOW FDC ");
00318 #endif
00319 break;
00320 }
00321 #if(DEBUG_FDC_INFO==1)
00322 GuiStringPrint("\n");
00323 #endif
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 bool Fdc1Specify(void){
00338 Fdc1Ctrl.State==FDC_IN_NONDATA;
00339 Fdc1WriteFifo(FDC_CMD_SPECIFY);
00340 Fdc1WriteFifo((FDC_SRT*0x10)|FDC_HUT);
00341 Fdc1WriteFifo(FDC_HLT|FDC_ND);
00342 if(Fdc1ReadMsr()&FDC_MSR_FDC_BUSY) return false;
00343 else return true;
00344 }
00345
00346 void Fdc1ReadId(void){
00347 U8 i;
00348
00349 Fdc1Ctrl.State==FDC_IN_NONDATA;
00350 Fdc1WriteFifo(FDC_CMD_READID);
00351
00352 Fdc1WriteFifo(0x00);
00353 Fdc1Ctrl.Timer=1000;
00354 while(Fdc1Ctrl.Timer!=0){
00355 if(Fdc1Ctrl.HasInterrupt==true) break;
00356 }
00357 if(Fdc1Ctrl.HasInterrupt==true){
00358 #if(DEBUG_FDC_INTERRUPT==1)
00359 GuiStringPrint("\nsee interrupt");
00360 #endif
00361 Fdc1Ctrl.HasInterrupt=false;
00362 }
00363 if(Fdc1Ctrl.Timer==0){
00364 #if(DEBUG_FDC_TIMEOUT==1)
00365 GuiStringPrint("\nreadid time out");
00366 #endif
00367 return false;
00368 }
00369 BufferIndex=0;
00370 Fdc1ReadMsr();
00371 BufferIndex=0;
00372 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00373 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00374 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00375 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00376 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00377 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00378 Fdc1ResultBuffer[BufferIndex++]=Fdc1ReadFifo();
00379 #if(DEBUG_FDC_INFO==1)
00380 GuiStringPrint("\nST0: ");
00381 GuiU8Print(Fdc1ResultBuffer[0]);
00382 GuiStringPrint("\nST1: ");
00383 GuiU8Print(Fdc1ResultBuffer[1]);
00384 GuiStringPrint("\nST2: ");
00385 GuiU8Print(Fdc1ResultBuffer[2]);
00386 GuiStringPrint("\n C : ");
00387 GuiU8Print(Fdc1ResultBuffer[3]);
00388 GuiStringPrint("\n H : ");
00389 GuiU8Print(Fdc1ResultBuffer[4]);
00390 GuiStringPrint("\n R : ");
00391 GuiU8Print(Fdc1ResultBuffer[5]);
00392 GuiStringPrint("\n N : ");
00393 GuiU8Print(Fdc1ResultBuffer[6]);
00394 #endif
00395 }
00396
00397 bool Fdc1Seek(U8 TrackNumber){
00398 U8 i;
00399
00400
00401 Fdc1Ctrl.State==FDC_IN_NONDATA;
00402 Fdc1WriteFifo(FDC_CMD_SEEK);
00403 Fdc1WriteFifo(0x00);
00404 Fdc1WriteFifo(TrackNumber);
00405
00406 Fdc1Ctrl.Timer=1000;
00407 while(Fdc1Ctrl.Timer!=0){
00408 if(Fdc1Ctrl.HasInterrupt==true) break;
00409 }
00410 if(Fdc1Ctrl.HasInterrupt==true){
00411 #if(DEBUG_FDC_INTERRUPT==1)
00412 GuiStringPrint("\nsee interrupt");
00413 #endif
00414 Fdc1Ctrl.HasInterrupt=false;
00415 }
00416 if(Fdc1Ctrl.Timer==0){
00417 #if(DEBUG_FDC_TIMEOUT==1)
00418 GuiStringPrint("\nseek time out");
00419 #endif
00420 return false;
00421 }
00422 return true;
00423 }
00424
00425 bool Fdc1RecalibrateProcedure(void){
00426 if((Fdc1Ctrl.DorReg&(FDC_DOR_MOTORON_FDD0|0x0c))!=(FDC_DOR_MOTORON_FDD0|0x0c)){
00427 Fdc1WriteDor(FDC_DOR_MOTORON_FDD0|0x0c);
00428 Fdc1TimeDelay(20);
00429 }
00430 Fdc1Recalibrate();
00431 if(Fdc1SenseInterruptStatus()==true) return true;
00432 else return false;
00433 }
00434
00435 bool Fdc1SeekProcedure(U8 TrackNumber){
00436 if((Fdc1Ctrl.DorReg&(FDC_DOR_MOTORON_FDD0|0x0c))!=(FDC_DOR_MOTORON_FDD0|0x0c)){
00437 Fdc1WriteDor(FDC_DOR_MOTORON_FDD0|0x0c);
00438 Fdc1TimeDelay(20);
00439 }
00440 Fdc1Seek(TrackNumber);
00441 if(Fdc1SenseInterruptStatus()==true) return true;
00442 else return false;
00443 }