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/signal.h>
00026 #include <avr/pgmspace.h>
00027
00028 #endif
00029 #include "global.h"
00030 #include "timer.h"
00031 #include "rprintf.h"
00032
00033 #include "ata.h"
00034
00035
00036
00037
00038
00039
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
00054 rprintfProgStrM("\r\nScanning IDE interface...\r\n");
00055
00056 ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00057
00058 ataWriteByte(ATA_REG_CMDSTATUS1, 0xEC);
00059
00060 ataStatusWait(ATA_SR_DRQ, ATA_SR_DRQ);
00061 timerPause(200);
00062
00063 ataReadDataBuffer(buffer, 512);
00064
00065
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
00072 for(i=0; i<40; i+=2)
00073 {
00074
00075 ataDriveInfo.model[i ] = buffer[(ATA_IDENT_MODEL*2) + i + 1];
00076 ataDriveInfo.model[i+1] = buffer[(ATA_IDENT_MODEL*2) + i ];
00077 }
00078
00079 ataDriveInfo.model[40] = 0;
00080
00081
00082 if(ataDriveInfo.LBAsupport)
00083 {
00084
00085 rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
00086 rprintf("LBA mode -- MODEL: ");
00087 }
00088 else
00089 {
00090
00091
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
00098 rprintfStr(ataDriveInfo.model); rprintfCRLF();
00099
00100
00101
00102
00103
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
00120 ataDriveSelect(DriveNo);
00121
00122 ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00123
00124
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
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
00153 for(j=0; j<0x20; j++)
00154 {
00155
00156 rprintfu16(j<<4);
00157 rprintfProgStrM(" ");
00158
00159
00160 for(i=0; i<0x10; i++)
00161 {
00162 rprintfu08(buf[(j<<4)+i]);
00163 rprintfProgStrM(" ");
00164 }
00165
00166
00167 rprintfProgStrM(" ");
00168
00169
00170 for(i=0; i<0x10; i++)
00171 {
00172 s = buf[(j<<4)+i];
00173
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
00193
00194
00195 for (i=0; i<(numBytes/16); i++)
00196 {
00197
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
00216
00217 }
00218
00219 void ataWriteDataBuffer(u08 *Buffer, u16 numBytes)
00220 {
00221 register unsigned char temp;
00222 unsigned int i;
00223
00224
00225
00226
00227 for (i=0; i<(numBytes/16); i++)
00228 {
00229
00230
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
00257
00258 }
00259
00260 u08 ataStatusWait(u08 mask, u08 waitStatus)
00261 {
00262 register u08 status;
00263
00264 delay(100);
00265
00266
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
00283 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00284
00285
00286 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head);
00287 ataWriteByte(ATA_REG_CYLHI, Track>>8);
00288 ataWriteByte(ATA_REG_CYLLO, Track);
00289 ataWriteByte(ATA_REG_STARTSEC, Sector);
00290 ataWriteByte(ATA_REG_SECCOUNT, numsectors);
00291
00292
00293 ataWriteByte(ATA_REG_CMDSTATUS1, 0x21);
00294
00295
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
00305 ataStatusWait(ATA_SR_DRQ, 0);
00306
00307
00308 ataReadDataBuffer(Buffer, 512*numsectors);
00309
00310
00311 temp = ataReadByte(ATA_REG_CMDSTATUS1);
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
00327 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00328
00329
00330 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head);
00331 ataWriteByte(ATA_REG_CYLHI, Track>>8);
00332 ataWriteByte(ATA_REG_CYLLO, Track);
00333 ataWriteByte(ATA_REG_STARTSEC, Sector);
00334 ataWriteByte(ATA_REG_SECCOUNT, numsectors);
00335
00336
00337 ataWriteByte(ATA_REG_CMDSTATUS1, 0x31);
00338
00339
00340
00341
00342 ataStatusWait(ATA_SR_DRQ, 0);
00343
00344
00345 ataWriteDataBuffer(Buffer, 512*numsectors);
00346
00347
00348 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
00349
00350
00351 if (temp & ATA_SR_ERR)
00352 {
00353 rprintfProgStrM("WR ERR\r\n");
00354 return 1;
00355 }
00356
00357
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
00429 if(ataDriveInfo.LBAsupport)
00430 {
00431
00432 temp = ataReadSectorsLBA(Drive, lba, numsectors, Buffer);
00433 }
00434 else
00435 {
00436
00437 #ifdef DEBUG_ATA
00438
00439 rprintfProgStrM("ATA LBA for CHS read: ");
00440 rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
00441 #endif
00442
00443
00444
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
00476 if(ataDriveInfo.LBAsupport)
00477 {
00478
00479 temp = ataWriteSectorsLBA(Drive, lba, numsectors, Buffer);
00480 }
00481 else
00482 {
00483
00484 #ifdef DEBUG_ATA
00485
00486 rprintfProgStrM("ATA LBA for CHS write: ");
00487 rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
00488 #endif
00489
00490
00491
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));
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
00551 u08 ataReadByte(u08 reg)
00552 {
00553 register u08 ret;
00554
00555 ret = *((volatile unsigned char*) ATA_REG_BASE + reg);
00556
00557 return ret;
00558 }
00559
00560 void ataWriteByte(u08 reg, u08 data)
00561 {
00562
00563 *((volatile unsigned char*) ATA_REG_BASE + reg) = data;
00564
00565 }
00566
00567
00568 void ataShowRegisters(unsigned char DriveNo)
00569 {
00570 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0 + (DriveNo ? 0x10:0x00));
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);
00585 delay(10);
00586 ataWriteByte(ATA_REG_HDDEVSEL, 0x02);
00587 delay(10);
00588
00589 while( (ataReadByte(ATA_REG_CMDSTATUS1) & 0xC0) != 0x40 );
00590
00591 return ataReadByte(ATA_REG_CMDSTATUS1) + ataReadByte(ATA_REG_ERROR);
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606