Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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

Generated on Sun Oct 29 03:41:06 2006 for Procyon AVRlib by  doxygen 1.4.2