Main Page Data Structures File List Data Fields Globals Related Pages

# clib/ide.c

Go to the documentation of this file.

    00001 /***************************************************************************/
    00002 //   Example of using the external disk interface.
    00003 //
    00004 //   Tested with Borland C/C++ 5.02 on a SC12 with Bios version 1.01 Beta
    00005 //
    00006 //   Copyright Beck IPC GmbH
    00007 //
    00008 //   Info: http://www.bcl-online.de
    00009 //
    00010 //   $Header: ide.c, 4, 05.09.2001 11:53:54, Andre Pribil$
    00011 //
    00012 //   $Log:
    00013 //    2    @Chip-DOS 1.1         09.01.01 14:31:30    Andre Pribil    First example
    00014 //         on customer board (ALE, PCS5, PCS6)
    00015 //    1    @Chip-DOS 1.0         20.12.00 12:15:10    Andre Pribil
    00016 //   $
    00017 /***************************************************************************/
    00018
    00019 /***************************************************************************/
    00020 // Includes
    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 // Defines
    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 // IDE State-Bits
    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 // IDE Error-Bits
    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 // Typedefs
    00085 /***************************************************************************/
    00086
    00087 typedef unsigned char uchar;
    00088 typedef unsigned int  uint;
    00089
    00090 /***************************************************************************/
    00091 // Variables
    00092 /***************************************************************************/
    00093
    00094 #if DATABUS == 16
    00095   uchar FEATURE = 0x81; // disable 8 Bit Mode
    00096 #elif DATABUS == 8
    00097   uchar FEATURE = 0x01; // enable 8 Bit Mode
    00098 #endif
    00099
    00100 uchar err,sts;
    00101 T_DRIVE_PARAM drive = {0};   // filled by IDE_identify
    00102
    00103 /***************************************************************************/
    00104 // Prototypes
    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 // Functions
    00115 /***************************************************************************/
    00116
    00118 // wait for DRQ Bit: Ready for data
    00120 static uchar near IDE_waitdrq( void ) // ret 0 if not ready
    00121 {
    00122   if ( IDE_waitirq() ) return IDE_datarequest();
    00123   return 0;
    00124 } // IDE_waitdrq
    00125
    00126
    00128 // Test DRQ-Bit
    00130 static uchar near IDE_datarequest( void )
    00131 {
    00132   return IDE_status() & IDE_STS_DRQ;
    00133 } // IDE_datarequest
    00134
    00135
    00137 // Wait until BUSY-Bit is cleared
    00139 static uchar near IDE_waitirq( void )  // ret 0 on error
    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     } // if
    00155   } // while
    00156   return 1;
    00157 }
    00158
    00159
    00161 // Send command to disk
    00163 static uchar near IDE_command( uchar feat, uint  cyl, uchar head, uchar sect,
    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 // Send LBA command to disk
    00182 static uchar near IDE_LBA_command( uchar feat, unsigned long sector,
    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); // LBA bit set, drive 0
    00198   hal_outportb(IDE_COMMAND, cmd);
    00199   return cnt;
    00200 }
    00201
    00202
    00204 // Read state register
    00206 static uchar near IDE_status( void )
    00207 {
    00208   sts = hal_inportb(IDE_STATUS);
    00209   return(sts);
    00210 }
    00211
    00212
    00214 // Read buffer
    00216 #if DATABUS == 8
    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 // Write buffer
    00245 #if DATABUS == 8
    00246  static void near IDE_writebuf(int cnt, unsigned char *buf)
    00247  {
    00248     hal_outportb_block(IDE_DATA,IDE_DATA,buf,cnt);
    00249  } // IDE_writebuf
    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 // Test Error-Bit
    00274 static uchar near IDE_error( void )
    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 } // IDE_error
    00285
    00286
    00288 // Switch to 8-Bit mode
    00290 static void IDE_bit_mode( void )
    00291 {
    00292   IDE_command( FEATURE,-1,0,0,0,IDE_SET_FEATURES );
    00293   IDE_waitirq();
    00294 } // IDE_bit_mode
    00295
    00296
    00298 // Reset Kittyhawk IDE
    00300 void IDE_reset( void )
    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);   // activate software reset
    00312     RTX_Sleep_Time(1);
    00313     hal_outportb(IDE_CONTROL,0x0A);  // remove reset, no IRQ
    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     } // if
    00321     RTX_Sleep_Time(100);
    00322
    00323     // Busy abwarten
    00324     if( IDE_waitirq())
    00325     {
    00326       // 8-Bit-Mode restaurieren
    00327       IDE_bit_mode();
    00328       return;
    00329     } // if
    00330
    00331     printf("\r\nIDE: Reset failed\r\n");
    00332
    00333   } while( retries-- );
    00334 } // IDE_reset
    00335
    00336
    00338 // Read sectors in LBA mode / ret 1 if o.k.,  0 if error
    00340 int IDE_LBA_read( unsigned long sector, int cnt, unsigned char *buf)
    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;      // Lesefehler
    00357       } // if
    00358       IDE_readbuf( 512, (unsigned char *) b );
    00359     }
    00360     else
    00361     {
    00362       printf("FAILED: DRQ TIMEOUT on LBA read\r\n");
    00363       return 0;      // Lesefehler
    00364     } // if
    00365     b+=512;
    00366     cnt--;
    00367     sector++;
    00368   }
    00369
    00370   return 1;
    00371 }
    00372
    00373
    00375 // Write sectors in LBA mode / ret 1 if o.k., 0 if error
    00377 int IDE_LBA_write( unsigned long sector, int cnt, unsigned char *buf )
    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;      // Schreibfehler
    00400       } // if
    00401     }
    00402     else
    00403     {
    00404       printf("FAILED (DRQ TIMEOUT)\r\n");
    00405       return 0;      // Schreibfehler
    00406     } // if
    00407     b+=512;
    00408     cnt--;
    00409     sector++;
    00410   }
    00411
    00412   return 1;
    00413 } // IDE_write
    00414
    00415
    00417 // Read n sectors
    00419 int IDE_read( int cyl, int head, int sect, int cnt, unsigned char *buf )
    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;      // Lesefehler
    00432       } // if
    00433     }
    00434     else
    00435     {
    00436       printf("FAILED (TIMEOUT)\r\n");
    00437       return 0;      // Lesefehler
    00438     } // if
    00439     b+=512;
    00440     cnt--;
    00441   } while( cnt );
    00442
    00443   return 1;
    00444 } // IDE_read
    00445
    00446
    00448 // Write n sectors
    00450 int IDE_write( int cyl, int head, int sect, int cnt, unsigned char *buf )
    00451 {
    00452   unsigned char huge *b = buf;
    00453
    00454   cnt = IDE_command( 0, cyl,head,sect,cnt,IDE_WRITE_SECTOR );
    00455   // RTX_Sleep_Time(1);
    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;      // Schreibfehler
    00465       } // if
    00466     }
    00467     else
    00468     {
    00469       printf("FAILED (ERROR)\r\n");
    00470       return 0;      // Schreibfehler
    00471     } // if
    00472     b+=512;
    00473     cnt--;
    00474   } while( cnt );
    00475
    00476   return 1;
    00477 } // IDE_write
    00478
    00479
    00481 // Read SRAM
    00483 int IDE_ReadSRAM(unsigned char *bfr)
    00484 {
    00485   hal_outportb(IDE_HEAD,  0xE0);  // set drive 0 and LBA mode
    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 // Write SRAM
    00502 int IDE_WriteSRAM(unsigned char *bfr)
    00503 {
    00504   hal_outportb(IDE_HEAD,  0xE0);  // set drive 0 and LBA mode
    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 // int positions
    00519 #define ID_CYL    1
    00520 #define ID_HEADS  3
    00521 #define ID_SECT   6  // Anz. Sektoren/Spur
    00522
    00523
    00525 // Identify disk
    00527 int IDE_identify(void)   // ret 1 if o.k.
    00528 {
    00529   uint IDbuf[256];
    00530
    00531   IDE_reset();
    00532   IDE_bit_mode();
    00533
    00534   hal_outportb(IDE_HEAD, 0xE0);  // set drive 0 and LBA mode
    00535   hal_outportb(IDE_COMMAND, IDE_IDENTIFY);
    00536
    00537   if( IDE_waitdrq() == 0 )  // wait for data transfer
    00538   {
    00539     return 0;
    00540   }
    00541
    00542   if( IDE_datarequest()) // o.k. if 8 bit
    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     // Not 8 Bit
    00559     return 0;
    00560   }
    00561
    00562   return 1;
    00563 }
    00564
    00565 // End of file
    00566