Main Page   Data Structures   File List   Data Fields   Globals  

/ata.c

Go to the documentation of this file.
00001 /*! \file ata.c \brief IDE-ATA hard disk interface driver. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'ata.c'
00005 // Title        : IDE-ATA interface driver for hard disks
00006 // Author       : Pascal Stang
00007 // Date         : 11/22/2000
00008 // Revised      : 4/19/2003
00009 // Version      : 0.3
00010 // Target MCU   : Atmel AVR Series
00011 // Editor Tabs  : 4
00012 //
00013 // NOTE: This code is currently below version 1.0, and therefore is considered
00014 // to be lacking in some functionality or documentation, or may not be fully
00015 // tested.  Nonetheless, you can expect most functions to work.
00016 //
00017 // This code is distributed under the GNU Public License
00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00019 //
00020 //*****************************************************************************
00021 
00022 #ifndef WIN32
00023     #include <avr/io.h>
00024     #include <avr/interrupt.h>
00025     #include <avr/signal.h>
00026     #include <avr/pgmspace.h>
00027 //  #include <stdio.h>
00028 #endif
00029 #include "global.h"
00030 #include "timer.h"
00031 #include "rprintf.h"
00032 
00033 #include "ata.h"
00034 
00035 //#define DEBUG_ATA 1
00036 
00037 // global variables
00038 
00039 // drive information
00040 typeDriveInfo ataDriveInfo;
00041 
00042 
00043 void ataInit(void)
00044 {
00045 
00046 }
00047 
00048 void ataDriveInit(void)
00049 {
00050     u08 i;
00051     unsigned char* buffer = (unsigned char*) SECTOR_BUFFER_ADDR;
00052 
00053     // read drive identity
00054     rprintfProgStrM("\r\nScanning IDE interface...\r\n");
00055     // Wait for drive to be ready
00056     ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00057     // issue identify command
00058     ataWriteByte(ATA_REG_CMDSTATUS1, 0xEC);
00059     // wait for drive to request data transfer
00060     ataStatusWait(ATA_SR_DRQ, ATA_SR_DRQ);
00061     timerPause(200);
00062     // read in the data
00063     ataReadDataBuffer(buffer, 512);
00064 
00065     // set local drive info parameters
00066     ataDriveInfo.cylinders =        *( ((unsigned int*) buffer) + ATA_IDENT_CYLINDERS );
00067     ataDriveInfo.heads =            *( ((unsigned int*) buffer) + ATA_IDENT_HEADS );
00068     ataDriveInfo.sectors =          *( ((unsigned int*) buffer) + ATA_IDENT_SECTORS );
00069     ataDriveInfo.LBAsupport =       *( ((unsigned int*) buffer) + ATA_IDENT_FIELDVALID );
00070     ataDriveInfo.sizeinsectors =    *( (unsigned long*) (buffer + ATA_IDENT_LBASECTORS*2) );
00071     // copy model string
00072     for(i=0; i<40; i+=2)
00073     {
00074         // correct for byte order
00075         ataDriveInfo.model[i  ] = buffer[(ATA_IDENT_MODEL*2) + i + 1];
00076         ataDriveInfo.model[i+1] = buffer[(ATA_IDENT_MODEL*2) + i    ];
00077     }
00078     // terminate string
00079     ataDriveInfo.model[40] = 0;
00080 
00081     // process and print info
00082     if(ataDriveInfo.LBAsupport)
00083     {
00084         // LBA support
00085         rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
00086         rprintf("LBA mode -- MODEL: ");
00087     }
00088     else
00089     {
00090         // CHS, no LBA support
00091         // calculate drive size
00092         ataDriveInfo.sizeinsectors = (unsigned long) ataDriveInfo.cylinders*
00093                                                 ataDriveInfo.heads*ataDriveInfo.sectors;
00094         rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
00095         rprintf("CHS mode C=%d H=%d S=%d -- MODEL: ", ataDriveInfo.cylinders, ataDriveInfo.heads, ataDriveInfo.sectors );
00096     }
00097     // print model information  
00098     rprintfStr(ataDriveInfo.model); rprintfCRLF();
00099 
00100     // initialize local disk parameters
00101     //ataDriveInfo.cylinders = ATA_DISKPARM_CLYS;
00102     //ataDriveInfo.heads = ATA_DISKPARM_HEADS;
00103     //ataDriveInfo.sectors = ATA_DISKPARM_SECTORS;
00104 
00105 }
00106 
00107 void ataDiskErr(void)
00108 {
00109     unsigned char b;
00110 
00111     b = ataReadByte(ATA_REG_ERROR); 
00112     rprintfProgStrM("ATA Error: "); 
00113     rprintfu08(b); 
00114     rprintfCRLF();
00115 }
00116 
00117 void ataSetDrivePowerMode(u08 DriveNo, u08 mode, u08 timeout)
00118 {
00119     // select drive
00120     ataDriveSelect(DriveNo);
00121     // Wait for drive to be ready
00122     ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00123 
00124     // set mode
00125     switch(mode)
00126     {
00127     case ATA_DISKMODE_SPINDOWN:     ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SPINDOWN); break;
00128     case ATA_DISKMODE_SPINUP:       ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SPINUP); break;
00129     case ATA_DISKMODE_SETTIMEOUT:
00130         ataWriteByte(ATA_REG_SECCOUNT, timeout);
00131         ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_IDLE_5SU);
00132         break;
00133     case ATA_DISKMODE_SLEEP:        ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SLEEP); break;
00134     default:
00135         break;
00136     }
00137 }
00138 
00139 void ataPrintSector( u08 *Buffer)
00140 {
00141     u08 i;
00142     u16 j;
00143     u08 *buf;
00144     u08 s;
00145 
00146     buf = Buffer;
00147     
00148     // print the low order address indicies
00149     rprintfProgStrM("     00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  0123456789ABCDEF\r\n");
00150     rprintfProgStrM("     -----------------------------------------------  ---- ASCII -----\r\n");
00151     
00152     // print the data
00153     for(j=0; j<0x20; j++)
00154     {
00155         // print the high order address index for this line
00156         rprintfu16(j<<4);
00157         rprintfProgStrM(" ");
00158 
00159         // print the hex data
00160         for(i=0; i<0x10; i++)
00161         {
00162             rprintfu08(buf[(j<<4)+i]);
00163             rprintfProgStrM(" ");
00164         }
00165         
00166         // leave some space
00167         rprintfProgStrM(" ");
00168 
00169         // print the ascii data
00170         for(i=0; i<0x10; i++)
00171         {
00172             s = buf[(j<<4)+i]; 
00173             // make sure character is printable
00174             if(s >= 0x20)
00175             {
00176                 rprintfChar(s);
00177             }
00178             else
00179             {
00180                 rprintfChar(0x20);
00181             }
00182 
00183         }
00184         rprintfCRLF();
00185     }
00186 }
00187 
00188 void ataReadDataBuffer(u08 *Buffer, u16 numBytes)
00189 {
00190     unsigned int i;
00191 
00192     //sbi(MCUCR, SRW);          // enable RAM waitstate
00193 
00194     // read data from drive
00195     for (i=0; i<(numBytes/16); i++)
00196     {
00197         // optimize by reading 16 bytes in-line before looping
00198         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00199         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00200         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00201         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00202         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00203         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00204         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00205         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00206         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00207         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00208         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00209         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00210         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00211         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00212         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
00213         *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
00214     }
00215     //cbi(MCUCR, SRW);          // disable RAM waitstate
00216     
00217 }
00218 
00219 void ataWriteDataBuffer(u08 *Buffer, u16 numBytes)
00220 {
00221     register unsigned char temp;
00222     unsigned int i;
00223 
00224     //sbi(MCUCR, SRW);          // enable RAM waitstate
00225 
00226     // write data to drive
00227     for (i=0; i<(numBytes/16); i++)     
00228     {
00229         // optimize by writing 16 bytes in-line before looping
00230         // keep byte order correct by using temp register
00231         temp = *Buffer++;
00232         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00233         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00234         temp = *Buffer++;
00235         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00236         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00237         temp = *Buffer++;
00238         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00239         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00240         temp = *Buffer++;
00241         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00242         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00243         temp = *Buffer++;
00244         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00245         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00246         temp = *Buffer++;
00247         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00248         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00249         temp = *Buffer++;
00250         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00251         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00252         temp = *Buffer++;
00253         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
00254         *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
00255     }
00256     //cbi(MCUCR, SRW);          // disable RAM waitstate
00257 
00258 }
00259 
00260 u08 ataStatusWait(u08 mask, u08 waitStatus)
00261 {
00262     register u08 status;
00263 
00264     delay(100);
00265 
00266     // wait for desired status
00267     while( ((status = ataReadByte(ATA_REG_CMDSTATUS1)) & mask) == waitStatus );
00268 
00269     return status;
00270 }
00271 
00272 
00273 unsigned char ataReadSectorsCHS(    unsigned char Drive, 
00274                                             unsigned char Head, 
00275                                             unsigned int Track,
00276                                             unsigned char Sector,
00277                                             unsigned int numsectors,
00278                                             unsigned char *Buffer)
00279 {
00280     unsigned char temp;
00281 
00282     // Wait for drive to be ready
00283     temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00284 
00285     // Prepare parameters...
00286     ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
00287     ataWriteByte(ATA_REG_CYLHI, Track>>8);          // MSB of track
00288     ataWriteByte(ATA_REG_CYLLO, Track);             // LSB of track
00289     ataWriteByte(ATA_REG_STARTSEC, Sector);     // sector
00290     ataWriteByte(ATA_REG_SECCOUNT, numsectors); // # of sectors
00291 
00292     // Issue read sector command...
00293     ataWriteByte(ATA_REG_CMDSTATUS1, 0x21);
00294 
00295     // Wait for drive to be ready
00296     temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00297 
00298     if (temp & ATA_SR_ERR)
00299     {
00300         rprintfProgStrM("RD ERR\r\n");
00301         return 1;
00302     }
00303 
00304     // Wait for drive to request data transfer
00305     ataStatusWait(ATA_SR_DRQ, 0);
00306 
00307     // read data from drive
00308     ataReadDataBuffer(Buffer, 512*numsectors);
00309 
00310     // Return the error bit from the status register...
00311     temp = ataReadByte(ATA_REG_CMDSTATUS1); // read status register
00312 
00313     return (temp & ATA_SR_ERR) ? 1:0;
00314 }
00315 
00316 
00317 unsigned char ataWriteSectorsCHS(unsigned char Drive, 
00318                                             unsigned char Head, 
00319                                             unsigned int Track,
00320                                             unsigned char Sector,
00321                                             unsigned int numsectors,
00322                                             unsigned char *Buffer)
00323 {
00324     unsigned char temp;
00325 
00326     // Wait for drive to be ready
00327     temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00328 
00329     // Prepare parameters...
00330     ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
00331     ataWriteByte(ATA_REG_CYLHI, Track>>8);          // MSB of track
00332     ataWriteByte(ATA_REG_CYLLO, Track);             // LSB of track
00333     ataWriteByte(ATA_REG_STARTSEC, Sector);     // sector
00334     ataWriteByte(ATA_REG_SECCOUNT, numsectors); // # of sectors
00335 
00336     // Issue write sector command
00337     ataWriteByte(ATA_REG_CMDSTATUS1, 0x31);
00338 
00339     //delay(100);
00340 
00341     // Wait for drive to request data transfer
00342     ataStatusWait(ATA_SR_DRQ, 0);
00343 
00344     // write data to drive
00345     ataWriteDataBuffer(Buffer, 512*numsectors);
00346     
00347     // Wait for drive to finish write
00348     temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00349 
00350     // check for errors
00351     if (temp & ATA_SR_ERR)
00352     {
00353         rprintfProgStrM("WR ERR\r\n");
00354         return 1;
00355     }
00356 
00357     // Return the error bit from the status register...
00358     return (temp & ATA_SR_ERR) ? 1:0;
00359 }
00360 
00361 unsigned char ataReadSectorsLBA(    unsigned char Drive, 
00362                                             unsigned long lba,
00363                                             unsigned int numsectors,
00364                                     unsigned char *Buffer)
00365 {
00366     unsigned int cyl, head, sect;
00367     unsigned char temp;
00368 
00369 #ifdef DEBUG_ATA
00370     rprintfProgStrM("ATA LBA read ");
00371     rprintfu32(lba); rprintfProgStrM(" ");
00372     rprintfu16(numsectors); rprintfProgStrM(" ");
00373     rprintfu16((unsigned int)Buffer); 
00374     rprintfCRLF();
00375 #endif
00376 
00377     sect = (int) ( lba & 0x000000ffL );
00378     lba = lba >> 8;
00379     cyl = (int) ( lba & 0x0000ffff );
00380     lba = lba >> 16;
00381     head = ( (int) ( lba & 0x0fL ) ) | ATA_HEAD_USE_LBA;
00382 
00383     temp = ataReadSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
00384 
00385     if(temp)
00386         ataDiskErr();
00387     return temp;
00388 }
00389 
00390 unsigned char ataWriteSectorsLBA(   unsigned char Drive, 
00391                                                 unsigned long lba,
00392                                                 unsigned int numsectors,
00393                                         unsigned char *Buffer)
00394 {
00395     unsigned int cyl, head, sect;
00396     unsigned char temp;
00397 
00398 #ifdef DEBUG_ATA
00399     rprintfProgStrM("ATA LBA write ");
00400     rprintfu32(lba); rprintfProgStrM(" ");
00401     rprintfu16(numsectors); rprintfProgStrM(" ");
00402     rprintfu16((unsigned int)Buffer); 
00403     rprintfCRLF();
00404 #endif
00405 
00406     sect = (int) ( lba & 0x000000ffL );
00407     lba = lba >> 8;
00408     cyl = (int) ( lba & 0x0000ffff );
00409     lba = lba >> 16;
00410     head = ( (int) ( lba & 0x0fL ) ) | ATA_HEAD_USE_LBA;
00411 
00412     temp = ataWriteSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
00413 
00414     if(temp)
00415         ataDiskErr();
00416     return temp;
00417 }                                   
00418 
00419 
00420 unsigned char ataReadSectors(   unsigned char Drive, 
00421                                         unsigned long lba,
00422                                         unsigned int numsectors,
00423                                 unsigned char *Buffer)
00424 {
00425     unsigned int cyl, head, sect;
00426     unsigned char temp;
00427 
00428     // check if drive supports native LBA mode
00429     if(ataDriveInfo.LBAsupport)
00430     {
00431         // drive supports using native LBA
00432         temp = ataReadSectorsLBA(Drive, lba, numsectors, Buffer);
00433     }
00434     else
00435     {
00436         // drive required CHS access
00437         #ifdef DEBUG_ATA
00438             // do this defore destroying lba
00439             rprintfProgStrM("ATA LBA for CHS read: ");
00440             rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
00441         #endif
00442 
00443         // convert LBA to pseudo CHS
00444         // remember to offset the sector count by one
00445         sect = (u08) (lba % ataDriveInfo.sectors)+1;
00446         lba = lba / ataDriveInfo.sectors;
00447         head = (u08) (lba % ataDriveInfo.heads);
00448         lba = lba / ataDriveInfo.heads;
00449         cyl = (u16) lba;
00450 
00451         #ifdef DEBUG_ATA
00452             rprintfProgStrM("C:H:S=");
00453             rprintfu16(cyl); rprintfProgStrM(":");
00454             rprintfu08(head); rprintfProgStrM(":");
00455             rprintfu08(sect); rprintfCRLF();
00456         #endif
00457 
00458         temp = ataReadSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
00459     }
00460 
00461     if(temp)
00462         ataDiskErr();
00463     return temp;
00464 }
00465 
00466 
00467 unsigned char ataWriteSectors(unsigned char Drive, 
00468                                         unsigned long lba,
00469                                         unsigned int numsectors,
00470                                 unsigned char *Buffer)
00471 {
00472     unsigned int cyl, head, sect;
00473     unsigned char temp;
00474 
00475     // check if drive supports native LBA mode
00476     if(ataDriveInfo.LBAsupport)
00477     {
00478         // drive supports using native LBA
00479         temp = ataWriteSectorsLBA(Drive, lba, numsectors, Buffer);
00480     }
00481     else
00482     {
00483         // drive required CHS access
00484         #ifdef DEBUG_ATA
00485             // do this defore destroying lba
00486             rprintfProgStrM("ATA LBA for CHS write: ");
00487             rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
00488         #endif
00489 
00490         // convert LBA to pseudo CHS
00491         // remember to offset the sector count by one
00492         sect = (u08) (lba % ataDriveInfo.sectors)+1;
00493         lba = lba / ataDriveInfo.sectors;
00494         head = (u08) (lba % ataDriveInfo.heads);
00495         lba = lba / ataDriveInfo.heads;
00496         cyl = (u16) lba;
00497 
00498         #ifdef DEBUG_ATA
00499             rprintfProgStrM("C:H:S=");
00500             rprintfu16(cyl); rprintfProgStrM(":");
00501             rprintfu08(head); rprintfProgStrM(":");
00502             rprintfu08(sect); rprintfCRLF();
00503         #endif
00504 
00505         temp = ataWriteSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
00506     }
00507 
00508     if(temp)
00509         ataDiskErr();
00510     return temp;
00511 }                                   
00512 
00513 void ataDriveSelect(u08 DriveNo)
00514 {
00515     ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(DriveNo ? 0x10:00)); // Drive selection
00516 }
00517  
00518 //----------------------------------------------------------------------------
00519 // Set drive mode (STANDBY, IDLE)
00520 //----------------------------------------------------------------------------
00521 /*#define STANDBY 0
00522 #define IDLE    1
00523 #define SLEEP   2 
00524 */ 
00525 
00526 /*
00527 unsigned char SetMode(unsigned char DriveNo, unsigned char Mode, unsigned char PwrDown) 
00528 {
00529   WriteBYTE(CMD, 6, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
00530   WriteBYTE(CMD, 2, (PwrDown ? 0x01:0x00)); // Enable automatic power down
00531   switch (Mode) 
00532   {
00533     case STANDBY: WriteBYTE(CMD,7, 0xE2); break;
00534     case IDLE:    WriteBYTE(CMD,7, 0xE3); break;
00535     // NOTE: To recover from sleep, either issue a soft or hardware reset !
00536     // (But not on all drives, f.ex seagate ST3655A it's not nessecary to reset
00537     // but only to go in Idle mode, But on a Conner CFA170A it's nessecary with
00538     // a reset)
00539     case SLEEP:   WriteBYTE(CMD,7, 0xE6); break;
00540   }
00541   Timer10mSec=10000;
00542   while ((ReadBYTE(CMD,7) & 0xC0)!=0x40 && Timer10mSec); // Wait for DRDY & NOT BUSY 
00543   if (Timer10mSec==0) return 0xFF;                       //   or timeout
00544  
00545   // Return the error register...
00546   return ReadBYTE(CMD, 1);
00547 }
00548 
00549 */
00550 
00551 u08 ataReadByte(u08 reg)
00552 {
00553     register u08 ret;
00554     //sbi(MCUCR, SRW);          // enable RAM waitstate
00555     ret = *((volatile unsigned char*) ATA_REG_BASE + reg);
00556     //cbi(MCUCR, SRW);          // disable RAM waitstate
00557     return ret;
00558 }
00559 
00560 void ataWriteByte(u08 reg, u08 data)
00561 {
00562     //sbi(MCUCR, SRW);          // enable RAM waitstate
00563     *((volatile unsigned char*) ATA_REG_BASE + reg) = data;
00564     //cbi(MCUCR, SRW);          // disable RAM waitstate
00565 }
00566 
00567  
00568 void ataShowRegisters(unsigned char DriveNo) 
00569 { 
00570     ataWriteByte(ATA_REG_HDDEVSEL, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
00571     
00572     rprintfProgStrM("Reg 0=");  rprintfu08(ataReadByte(ATA_REG_DATAL    )); rprintfProgStrM(" ");
00573     rprintfProgStrM("1=");      rprintfu08(ataReadByte(ATA_REG_ERROR    )); rprintfProgStrM(" ");
00574     rprintfProgStrM("2=");      rprintfu08(ataReadByte(ATA_REG_SECCOUNT));  rprintfProgStrM(" ");
00575     rprintfProgStrM("3=");      rprintfu08(ataReadByte(ATA_REG_STARTSEC));  rprintfProgStrM(" ");
00576     rprintfProgStrM("4=");      rprintfu08(ataReadByte(ATA_REG_CYLLO    )); rprintfProgStrM(" ");
00577     rprintfProgStrM("5=");      rprintfu08(ataReadByte(ATA_REG_CYLHI    )); rprintfProgStrM(" ");
00578     rprintfProgStrM("6=");      rprintfu08(ataReadByte(ATA_REG_HDDEVSEL));  rprintfProgStrM(" ");
00579     rprintfProgStrM("7=");      rprintfu08(ataReadByte(ATA_REG_CMDSTATUS1));    rprintfProgStrM("\n\r");
00580 } 
00581 
00582 unsigned char ataSWReset(void)
00583 {
00584     ataWriteByte(ATA_REG_HDDEVSEL, 0x06);   // SRST and nIEN bits
00585     delay(10);  // 10uS delay
00586     ataWriteByte(ATA_REG_HDDEVSEL, 0x02);   // nIEN bits
00587     delay(10);  // 10 uS delay
00588    
00589    while( (ataReadByte(ATA_REG_CMDSTATUS1) & 0xC0) != 0x40 ); // Wait for DRDY and not BSY
00590     
00591     return ataReadByte(ATA_REG_CMDSTATUS1) + ataReadByte(ATA_REG_ERROR);
00592 }
00593 
00594 /*
00595 unsigned char ATA_Idle(unsigned char Drive)
00596 {
00597 
00598   WriteBYTE(CMD, 6, 0xA0 + (Drive ? 0x10:0x00)); // Select drive
00599   WriteBYTE(CMD,7, 0xE1);
00600 
00601   while ((ReadBYTE(CMD,7) & 0xC0)!=0x40); // Wait for DRDY & NOT BUSY 
00602 
00603   // Return the error register...
00604   return ReadBYTE(CMD, 1);
00605 }
00606 */

Generated on Fri Aug 1 10:42:40 2003 for Procyon AVRlib by doxygen1.2.18