00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "define.h"
00023 #include <dos.h>
00024 #include <stdio.h>
00025 #include "ide.h"
00026 #include "rtxapi.h"
00027 #include "rtos.h"
00028 #include "hwapi.h"
00029
00030
00031
00032
00033 #define IDE_IDENTIFY (uchar)0xEC
00034 #define IDE_READ_SECTOR (uchar)0x20
00035 #define IDE_WRITE_SECTOR (uchar)0x30
00036 #define IDE_VERIFY_SECTOR (uchar)0x40
00037 #define IDE_SEEK (uchar)0x70
00038 #define IDE_SET_FEATURES (uchar)0xEF
00039 #define IDE_STANDBY (uchar)0xE2
00040 #define IDE_IDLE_MODE (uchar)0xE3
00041 #define IDE_SET_DRV_PARAM (uchar)0x91
00042 #define IDE_RECALIBRATE (uchar)0x10
00043
00044 #define IDE_DATA (IDE_PORT0 + 0) // Data (8/16 Bit) r/w
00045 #define IDE_FEATURE (IDE_PORT0 + 1) // Features w
00046 #define IDE_ERROR (IDE_PORT0 + 1) // Error r
00047 #define IDE_COUNT (IDE_PORT0 + 2) // Sector Count r/w
00048 #define IDE_SECTOR (IDE_PORT0 + 3) // Sector Number r/w
00049 #define IDE_CYL_LO (IDE_PORT0 + 4) // Cylinder low r/w
00050 #define IDE_CYL_HI (IDE_PORT0 + 5) // Cylinder high r/w
00051 #define IDE_HEAD (IDE_PORT0 + 6) // Drive/Head r/w
00052 #define IDE_COMMAND (IDE_PORT0 + 7) // Command w
00053 #define IDE_STATUS (IDE_PORT0 + 7) // Status r
00054
00055 #define IDE_CONTROL (IDE_PORT1 + 6) // Device Control w
00056 #define IDE_ALT_STS (IDE_PORT1 + 6) // Alternate Status r
00057 #define IDE_ADDRESS (IDE_PORT1 + 7) // Drive Address r
00058
00060
00062
00063 #define IDE_STS_BSY (uchar)0x80
00064 #define IDE_STS_DRDY (uchar)0x40
00065 #define IDE_STS_DWF (uchar)0x20
00066 #define IDE_STS_DSC (uchar)0x10
00067 #define IDE_STS_DRQ (uchar)0x08
00068 #define IDE_STS_CORR (uchar)0x04
00069 #define IDE_STS_ERR (uchar)0x01
00070
00072
00074
00075 #define IDE_ERR_BBK (uchar)0x80
00076 #define IDE_ERR_UNC (uchar)0x40
00077 #define IDE_ERR_TMOUT (uchar)0x20
00078 #define IDE_ERR_IDNF (uchar)0x10
00079 #define IDE_ERR_ABRT (uchar)0x04
00080 #define IDE_ERR_TK0NF (uchar)0x02
00081 #define IDE_ERR_AMNF (uchar)0x01
00082
00083
00084
00085
00086
00087 typedef unsigned char uchar;
00088 typedef unsigned int uint;
00089
00090
00091
00092
00093
00094 #if DATABUS == 16
00095 uchar FEATURE = 0x81;
00096 #elif DATABUS == 8
00097 uchar FEATURE = 0x01;
00098 #endif
00099
00100 uchar err,sts;
00101 T_DRIVE_PARAM drive = {0};
00102
00103
00104
00105
00106
00107 static uchar near IDE_waitirq( void );
00108 static uchar near IDE_waitdrq( void );
00109 static uchar near IDE_datarequest( void );
00110 static uchar near IDE_error( void );
00111 static uchar near IDE_status( void );
00112
00113
00114
00115
00116
00118
00120
00121 {
00122 if ( IDE_waitirq() ) return IDE_datarequest();
00123 return 0;
00124 }
00125
00126
00128
00130
00131 {
00132 return IDE_status() & IDE_STS_DRQ;
00133 }
00134
00135
00137
00139
00140 {
00141 unsigned long t0, t1;
00142
00143 RTX_Get_System_Ticks(&t0);
00144
00145 while((( IDE_status()) & ( IDE_STS_BSY|IDE_STS_DRDY|IDE_STS_DSC )) !=
00146 ( IDE_STS_DRDY|IDE_STS_DSC ))
00147 {
00148 RTX_Get_System_Ticks(&t1);
00149 if( (t1-t0) > 2000)
00150 {
00151 hal_outportb(IDE_FEATURE,IDE_ERR_TMOUT);
00152 printf("\r\nIDE: Drive IRQ not ready\r\n");
00153 return 0;
00154 }
00155 }
00156 return 1;
00157 }
00158
00159
00161
00163
00164 uchar cnt, uchar cmd )
00165 {
00166 IDE_waitdrq();
00167 hal_outportb(IDE_CONTROL, 8);
00168 hal_outportb(IDE_FEATURE, feat);
00169 hal_outportb(IDE_COUNT, cnt);
00170 hal_outportb(IDE_SECTOR, sect);
00171 hal_outportb(IDE_CYL_LO, cyl&0xff);
00172 hal_outportb(IDE_CYL_HI, cyl>>8);
00173 hal_outportb(IDE_HEAD, (head &0x0f)|0xE0);
00174 hal_outportb(IDE_COMMAND, cmd);
00175 return cnt;
00176 }
00177
00178
00180
00182
00183 uchar cnt, uchar cmd )
00184 {
00185 uchar tmp;
00186
00187 IDE_waitdrq();
00188 hal_outportb(IDE_CONTROL, 8);
00189 hal_outportb(IDE_FEATURE, feat);
00190 hal_outportb(IDE_COUNT, cnt);
00191 tmp=(unsigned char)(sector&0xff); hal_outportb(IDE_SECTOR, tmp);
00192 sector=sector>>8;
00193 tmp=(unsigned char)(sector&0xff); hal_outportb(IDE_CYL_LO, tmp);
00194 sector=sector>>8;
00195 tmp=(unsigned char)(sector&0xff); hal_outportb(IDE_CYL_HI, tmp);
00196 sector=sector>>8;
00197 tmp=(unsigned char)(sector&0xff); hal_outportb(IDE_HEAD, (tmp &0x0f)|0xE0);
00198 hal_outportb(IDE_COMMAND, cmd);
00199 return cnt;
00200 }
00201
00202
00204
00206
00207 {
00208 sts = hal_inportb(IDE_STATUS);
00209 return(sts);
00210 }
00211
00212
00214
00216
00217 static void near IDE_readbuf(int cnt, unsigned char *buf)
00218 {
00219 hal_inportb_block(IDE_DATA,IDE_DATA,buf,cnt);
00220 }
00221 #elif DATABUS == 16
00222 static void near IDE_readbuf(int cnt, unsigned char *buf)
00223 {
00224 cnt=cnt/2;
00225
00226 asm les bx, buf
00227 asm mov cx, cnt
00228
00229 l1:
00230 asm mov dx, IDE_DATA
00231 asm in al, dx
00232 asm mov es:[bx], al
00233 asm inc bx
00234 asm mov dx, IDE_DATA+8
00235 asm in al, dx
00236 asm mov es:[bx], al
00237 asm inc bx
00238 asm loop l1
00239 }
00240 #endif
00241
00243
00245
00246 static void near IDE_writebuf(int cnt, unsigned char *buf)
00247 {
00248 hal_outportb_block(IDE_DATA,IDE_DATA,buf,cnt);
00249 }
00250 #elif DATABUS == 16
00251 static void near IDE_writebuf(int cnt, unsigned char *buf)
00252 {
00253 cnt=cnt/2;
00254
00255 asm les bx, buf
00256 asm mov cx, cnt
00257
00258 l2:
00259 asm mov dx, IDE_DATA+8
00260 asm mov al, es:[bx+1]
00261 asm out dx, al
00262 asm mov dx, IDE_DATA
00263 asm mov al, es:[bx]
00264 asm out dx, al
00265 asm inc bx
00266 asm inc bx
00267 asm loop l2
00268 }
00269 #endif
00270
00272
00274
00275 {
00276 sts = IDE_status();
00277 if( sts & IDE_STS_ERR )
00278 {
00279 err=hal_inportb(IDE_ERROR);
00280 printf(" Error %02Xh ",err);
00281 }
00282 else err= 0;
00283 return(( sts & ( IDE_STS_ERR|IDE_STS_DWF )));
00284 }
00285
00286
00288
00290
00291 {
00292 IDE_command( FEATURE,-1,0,0,0,IDE_SET_FEATURES );
00293 IDE_waitirq();
00294 }
00295
00296
00298
00300
00301 {
00302 int retries = 1;
00303 int error;
00304
00305 do
00306 {
00307 #ifdef TRACE
00308 printf("\r\nIDE software Reset\r\n");
00309 #endif
00310
00311 hal_outportb(IDE_CONTROL,0x0E);
00312 RTX_Sleep_Time(1);
00313 hal_outportb(IDE_CONTROL,0x0A);
00314
00315 error = IDE_status();
00316 if( error < IDE_STS_BSY )
00317 {
00318 printf("\r\nDrive not found, error %02Xh\r\n", error);
00319 return;
00320 }
00321 RTX_Sleep_Time(100);
00322
00323
00324 if( IDE_waitirq())
00325 {
00326
00327 IDE_bit_mode();
00328 return;
00329 }
00330
00331 printf("\r\nIDE: Reset failed\r\n");
00332
00333 } while( retries-- );
00334 }
00335
00336
00338
00340
00341 {
00342 unsigned char huge *b = buf;
00343
00344 while (cnt)
00345 {
00346 #ifdef TRACE
00347 printf("\r\nreading sector %lu cnt=%d SEG:OFF=%p,%p",sector,cnt,b,buf);
00348 #endif
00349
00350 IDE_LBA_command( 0, sector,1,IDE_READ_SECTOR );
00351 if( IDE_waitdrq() )
00352 {
00353 if( IDE_error())
00354 {
00355 printf("\r\nIDE: Error on READ_SECTOR command");
00356 return 0;
00357 }
00358 IDE_readbuf( 512, (unsigned char *) b );
00359 }
00360 else
00361 {
00362 printf("FAILED: DRQ TIMEOUT on LBA read\r\n");
00363 return 0;
00364 }
00365 b+=512;
00366 cnt--;
00367 sector++;
00368 }
00369
00370 return 1;
00371 }
00372
00373
00375
00377
00378 {
00379 unsigned char huge *b = buf;
00380
00381 while (cnt)
00382 {
00383 #ifdef TRACE
00384 printf("\r\nwriting sector %lu cnt=%d SEG:OFF=%p,%p",sector,cnt,b,buf);
00385 #endif
00386
00387 IDE_LBA_command( 0, sector,1,IDE_WRITE_SECTOR );
00388 if (IDE_error())
00389 {
00390 printf("\r\nError=0x%X\r\n",IDE_error());
00391 return 0;
00392 }
00393 if( IDE_waitdrq() )
00394 {
00395 IDE_writebuf( 512, (unsigned char *) b );
00396 if(( IDE_waitirq() == 0 ) || IDE_error())
00397 {
00398 printf("FAILED (IRQ TIMEOUT)\r\n");
00399 return 0;
00400 }
00401 }
00402 else
00403 {
00404 printf("FAILED (DRQ TIMEOUT)\r\n");
00405 return 0;
00406 }
00407 b+=512;
00408 cnt--;
00409 sector++;
00410 }
00411
00412 return 1;
00413 }
00414
00415
00417
00419
00420 {
00421 unsigned char huge *b = buf;
00422
00423 cnt = IDE_command( 0, cyl,head,sect,cnt,IDE_READ_SECTOR );
00424 do
00425 {
00426 if( IDE_waitdrq() && ( IDE_error() == 0 ))
00427 {
00428 IDE_readbuf( 512, (unsigned char *)b );
00429 if( IDE_error())
00430 {
00431 return 0;
00432 }
00433 }
00434 else
00435 {
00436 printf("FAILED (TIMEOUT)\r\n");
00437 return 0;
00438 }
00439 b+=512;
00440 cnt--;
00441 } while( cnt );
00442
00443 return 1;
00444 }
00445
00446
00448
00450
00451 {
00452 unsigned char huge *b = buf;
00453
00454 cnt = IDE_command( 0, cyl,head,sect,cnt,IDE_WRITE_SECTOR );
00455
00456 do
00457 {
00458 if( IDE_waitdrq() && ( IDE_error() == 0 ))
00459 {
00460 IDE_writebuf( 512, (unsigned char *) b);
00461 if(( IDE_waitirq() == 0 ) || IDE_error())
00462 {
00463 printf("FAILED (TIMEOUT)\r\n");
00464 return 0;
00465 }
00466 }
00467 else
00468 {
00469 printf("FAILED (ERROR)\r\n");
00470 return 0;
00471 }
00472 b+=512;
00473 cnt--;
00474 } while( cnt );
00475
00476 return 1;
00477 }
00478
00479
00481
00483
00484 {
00485 hal_outportb(IDE_HEAD, 0xE0);
00486 hal_outportb(IDE_COMMAND, 0xE4);
00487 if (IDE_waitdrq())
00488 {
00489 IDE_readbuf( 512, bfr );
00490 }
00491 else
00492 {
00493 return 0;
00494 }
00495 return 1;
00496 }
00497
00498
00500
00502
00503 {
00504 hal_outportb(IDE_HEAD, 0xE0);
00505 hal_outportb(IDE_COMMAND, 0xE8);
00506 if (IDE_waitdrq())
00507 {
00508 IDE_writebuf( 512, bfr );
00509 }
00510 else
00511 {
00512 return 0;
00513 }
00514 return 1;
00515 }
00516
00517
00518
00519 #define ID_CYL 1
00520 #define ID_HEADS 3
00521 #define ID_SECT 6 // Anz. Sektoren/Spur
00522
00523
00525
00527
00528 {
00529 uint IDbuf[256];
00530
00531 IDE_reset();
00532 IDE_bit_mode();
00533
00534 hal_outportb(IDE_HEAD, 0xE0);
00535 hal_outportb(IDE_COMMAND, IDE_IDENTIFY);
00536
00537 if( IDE_waitdrq() == 0 )
00538 {
00539 return 0;
00540 }
00541
00542 if( IDE_datarequest())
00543 {
00544 if( IDE_error())
00545 {
00546 return 0;
00547 }
00548 IDE_readbuf( 256*2 , (unsigned char *)IDbuf );
00549
00550 drive.id = IDbuf[0];
00551 drive.cylinders = IDbuf[ID_CYL];
00552 drive.heads = IDbuf[ID_HEADS];
00553 drive.sectors = IDbuf[ID_SECT];
00554 drive.sector_size = 512;
00555 }
00556 else
00557 {
00558
00559 return 0;
00560 }
00561
00562 return 1;
00563 }
00564
00565
00566