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 

Generated on Sun Aug 4 21:47:27 2002 for k/os mp3v2 by doxygen1.2.16