00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIN32
00023 #include <avr/io.h>
00024 #include <avr/interrupt.h>
00025 #include <avr/pgmspace.h>
00026
00027 #endif
00028 #include "global.h"
00029 #include "timer.h"
00030 #include "rprintf.h"
00031
00032 #include "ata.h"
00033
00034
00035
00036
00037
00038
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
00053 rprintfProgStrM("\r\nScanning IDE interface...\r\n");
00054
00055 ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00056
00057 ataWriteByte(ATA_REG_CMDSTATUS1, 0xEC);
00058
00059 ataStatusWait(ATA_SR_DRQ, ATA_SR_DRQ);
00060 timerPause(200);
00061
00062 ataReadDataBuffer(buffer, 512);
00063
00064
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
00071 for(i=0; i<40; i+=2)
00072 {
00073
00074 ataDriveInfo.model[i ] = buffer[(ATA_IDENT_MODEL*2) + i + 1];
00075 ataDriveInfo.model[i+1] = buffer[(ATA_IDENT_MODEL*2) + i ];
00076 }
00077
00078 ataDriveInfo.model[40] = 0;
00079
00080
00081 if(ataDriveInfo.LBAsupport)
00082 {
00083
00084 rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
00085 rprintf("LBA mode -- MODEL: ");
00086 }
00087 else
00088 {
00089
00090
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
00097 rprintfStr(ataDriveInfo.model); rprintfCRLF();
00098
00099
00100
00101
00102
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
00119 ataDriveSelect(DriveNo);
00120
00121 ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00122
00123
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
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
00152 for(j=0; j<0x20; j++)
00153 {
00154
00155 rprintfu16(j<<4);
00156 rprintfProgStrM(" ");
00157
00158
00159 for(i=0; i<0x10; i++)
00160 {
00161 rprintfu08(buf[(j<<4)+i]);
00162 rprintfProgStrM(" ");
00163 }
00164
00165
00166 rprintfProgStrM(" ");
00167
00168
00169 for(i=0; i<0x10; i++)
00170 {
00171 s = buf[(j<<4)+i];
00172
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
00192
00193
00194 for (i=0; i<(numBytes/16); i++)
00195 {
00196
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
00215
00216 }
00217
00218 void ataWriteDataBuffer(u08 *Buffer, u16 numBytes)
00219 {
00220 register unsigned char temp;
00221 unsigned int i;
00222
00223
00224
00225
00226 for (i=0; i<(numBytes/16); i++)
00227 {
00228
00229
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
00256
00257 }
00258
00259 u08 ataStatusWait(u08 mask, u08 waitStatus)
00260 {
00261 register u08 status;
00262
00263 delay(100);
00264
00265
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
00282 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00283
00284
00285 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head);
00286 ataWriteByte(ATA_REG_CYLHI, Track>>8);
00287 ataWriteByte(ATA_REG_CYLLO, Track);
00288 ataWriteByte(ATA_REG_STARTSEC, Sector);
00289 ataWriteByte(ATA_REG_SECCOUNT, numsectors);
00290
00291
00292 ataWriteByte(ATA_REG_CMDSTATUS1, 0x21);
00293
00294
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
00304 ataStatusWait(ATA_SR_DRQ, 0);
00305
00306
00307 ataReadDataBuffer(Buffer, 512*numsectors);
00308
00309
00310 temp = ataReadByte(ATA_REG_CMDSTATUS1);
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
00326 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00327
00328
00329 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head);
00330 ataWriteByte(ATA_REG_CYLHI, Track>>8);
00331 ataWriteByte(ATA_REG_CYLLO, Track);
00332 ataWriteByte(ATA_REG_STARTSEC, Sector);
00333 ataWriteByte(ATA_REG_SECCOUNT, numsectors);
00334
00335
00336 ataWriteByte(ATA_REG_CMDSTATUS1, 0x31);
00337
00338
00339
00340
00341 ataStatusWait(ATA_SR_DRQ, 0);
00342
00343
00344 ataWriteDataBuffer(Buffer, 512*numsectors);
00345
00346
00347 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00348
00349
00350 if (temp & ATA_SR_ERR)
00351 {
00352 rprintfProgStrM("WR ERR\r\n");
00353 return 1;
00354 }
00355
00356
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
00428 if(ataDriveInfo.LBAsupport)
00429 {
00430
00431 temp = ataReadSectorsLBA(Drive, lba, numsectors, Buffer);
00432 }
00433 else
00434 {
00435
00436 #ifdef DEBUG_ATA
00437
00438 rprintfProgStrM("ATA LBA for CHS read: ");
00439 rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
00440 #endif
00441
00442
00443
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
00475 if(ataDriveInfo.LBAsupport)
00476 {
00477
00478 temp = ataWriteSectorsLBA(Drive, lba, numsectors, Buffer);
00479 }
00480 else
00481 {
00482
00483 #ifdef DEBUG_ATA
00484
00485 rprintfProgStrM("ATA LBA for CHS write: ");
00486 rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
00487 #endif
00488
00489
00490
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));
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 u08 ataReadByte(u08 reg)
00551 {
00552 register u08 ret;
00553
00554 ret = *((volatile unsigned char*) ATA_REG_BASE + reg);
00555
00556 return ret;
00557 }
00558
00559 void ataWriteByte(u08 reg, u08 data)
00560 {
00561
00562 *((volatile unsigned char*) ATA_REG_BASE + reg) = data;
00563
00564 }
00565
00566
00567 void ataShowRegisters(unsigned char DriveNo)
00568 {
00569 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0 + (DriveNo ? 0x10:0x00));
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);
00584 delay(10);
00585 ataWriteByte(ATA_REG_HDDEVSEL, 0x02);
00586 delay(10);
00587
00588 while( (ataReadByte(ATA_REG_CMDSTATUS1) & 0xC0) != 0x40 );
00589
00590 return ataReadByte(ATA_REG_CMDSTATUS1) + ataReadByte(ATA_REG_ERROR);
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605