?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

Line No. Rev Author Line
1 6 kaklik /*! \file ata.c \brief IDE-ATA hard disk interface driver. */
2 //*****************************************************************************
3 //
4 // File Name : 'ata.c'
5 // Title : IDE-ATA interface driver for hard disks
6 // Author : Pascal Stang
7 // Date : 11/22/2000
8 // Revised : 4/19/2003
9 // Version : 0.3
10 // Target MCU : Atmel AVR Series
11 // Editor Tabs : 4
12 //
13 // NOTE: This code is currently below version 1.0, and therefore is considered
14 // to be lacking in some functionality or documentation, or may not be fully
15 // tested. Nonetheless, you can expect most functions to work.
16 //
17 // This code is distributed under the GNU Public License
18 // which can be found at http://www.gnu.org/licenses/gpl.txt
19 //
20 //*****************************************************************************
21  
22 #ifndef WIN32
23 #include <avr/io.h>
24 #include <avr/interrupt.h>
25 #include <avr/pgmspace.h>
26 // #include <stdio.h>
27 #endif
28 #include "global.h"
29 #include "timer.h"
30 #include "rprintf.h"
31  
32 #include "ata.h"
33  
34 //#define DEBUG_ATA 1
35  
36 // global variables
37  
38 // drive information
39 typeDriveInfo ataDriveInfo;
40  
41  
42 void ataInit(void)
43 {
44  
45 }
46  
47 void ataDriveInit(void)
48 {
49 u08 i;
50 unsigned char* buffer = (unsigned char*) SECTOR_BUFFER_ADDR;
51  
52 // read drive identity
53 rprintfProgStrM("\r\nScanning IDE interface...\r\n");
54 // Wait for drive to be ready
55 ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
56 // issue identify command
57 ataWriteByte(ATA_REG_CMDSTATUS1, 0xEC);
58 // wait for drive to request data transfer
59 ataStatusWait(ATA_SR_DRQ, ATA_SR_DRQ);
60 timerPause(200);
61 // read in the data
62 ataReadDataBuffer(buffer, 512);
63  
64 // set local drive info parameters
65 ataDriveInfo.cylinders = *( ((unsigned int*) buffer) + ATA_IDENT_CYLINDERS );
66 ataDriveInfo.heads = *( ((unsigned int*) buffer) + ATA_IDENT_HEADS );
67 ataDriveInfo.sectors = *( ((unsigned int*) buffer) + ATA_IDENT_SECTORS );
68 ataDriveInfo.LBAsupport = *( ((unsigned int*) buffer) + ATA_IDENT_FIELDVALID );
69 ataDriveInfo.sizeinsectors = *( (unsigned long*) (buffer + ATA_IDENT_LBASECTORS*2) );
70 // copy model string
71 for(i=0; i<40; i+=2)
72 {
73 // correct for byte order
74 ataDriveInfo.model[i ] = buffer[(ATA_IDENT_MODEL*2) + i + 1];
75 ataDriveInfo.model[i+1] = buffer[(ATA_IDENT_MODEL*2) + i ];
76 }
77 // terminate string
78 ataDriveInfo.model[40] = 0;
79  
80 // process and print info
81 if(ataDriveInfo.LBAsupport)
82 {
83 // LBA support
84 rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
85 rprintf("LBA mode -- MODEL: ");
86 }
87 else
88 {
89 // CHS, no LBA support
90 // calculate drive size
91 ataDriveInfo.sizeinsectors = (unsigned long) ataDriveInfo.cylinders*
92 ataDriveInfo.heads*ataDriveInfo.sectors;
93 rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
94 rprintf("CHS mode C=%d H=%d S=%d -- MODEL: ", ataDriveInfo.cylinders, ataDriveInfo.heads, ataDriveInfo.sectors );
95 }
96 // print model information
97 rprintfStr(ataDriveInfo.model); rprintfCRLF();
98  
99 // initialize local disk parameters
100 //ataDriveInfo.cylinders = ATA_DISKPARM_CLYS;
101 //ataDriveInfo.heads = ATA_DISKPARM_HEADS;
102 //ataDriveInfo.sectors = ATA_DISKPARM_SECTORS;
103  
104 }
105  
106 void ataDiskErr(void)
107 {
108 unsigned char b;
109  
110 b = ataReadByte(ATA_REG_ERROR);
111 rprintfProgStrM("ATA Error: ");
112 rprintfu08(b);
113 rprintfCRLF();
114 }
115  
116 void ataSetDrivePowerMode(u08 DriveNo, u08 mode, u08 timeout)
117 {
118 // select drive
119 ataDriveSelect(DriveNo);
120 // Wait for drive to be ready
121 ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
122  
123 // set mode
124 switch(mode)
125 {
126 case ATA_DISKMODE_SPINDOWN: ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SPINDOWN); break;
127 case ATA_DISKMODE_SPINUP: ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SPINUP); break;
128 case ATA_DISKMODE_SETTIMEOUT:
129 ataWriteByte(ATA_REG_SECCOUNT, timeout);
130 ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_IDLE_5SU);
131 break;
132 case ATA_DISKMODE_SLEEP: ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SLEEP); break;
133 default:
134 break;
135 }
136 }
137  
138 void ataPrintSector( u08 *Buffer)
139 {
140 u08 i;
141 u16 j;
142 u08 *buf;
143 u08 s;
144  
145 buf = Buffer;
146  
147 // print the low order address indicies
148 rprintfProgStrM(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF\r\n");
149 rprintfProgStrM(" ----------------------------------------------- ---- ASCII -----\r\n");
150  
151 // print the data
152 for(j=0; j<0x20; j++)
153 {
154 // print the high order address index for this line
155 rprintfu16(j<<4);
156 rprintfProgStrM(" ");
157  
158 // print the hex data
159 for(i=0; i<0x10; i++)
160 {
161 rprintfu08(buf[(j<<4)+i]);
162 rprintfProgStrM(" ");
163 }
164  
165 // leave some space
166 rprintfProgStrM(" ");
167  
168 // print the ascii data
169 for(i=0; i<0x10; i++)
170 {
171 s = buf[(j<<4)+i];
172 // make sure character is printable
173 if(s >= 0x20)
174 {
175 rprintfChar(s);
176 }
177 else
178 {
179 rprintfChar(0x20);
180 }
181  
182 }
183 rprintfCRLF();
184 }
185 }
186  
187 void ataReadDataBuffer(u08 *Buffer, u16 numBytes)
188 {
189 unsigned int i;
190  
191 //sbi(MCUCR, SRW); // enable RAM waitstate
192  
193 // read data from drive
194 for (i=0; i<(numBytes/16); i++)
195 {
196 // optimize by reading 16 bytes in-line before looping
197 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
198 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
199 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
200 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
201 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
202 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
203 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
204 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
205 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
206 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
207 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
208 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
209 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
210 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
211 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
212 *Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
213 }
214 //cbi(MCUCR, SRW); // disable RAM waitstate
215  
216 }
217  
218 void ataWriteDataBuffer(u08 *Buffer, u16 numBytes)
219 {
220 register unsigned char temp;
221 unsigned int i;
222  
223 //sbi(MCUCR, SRW); // enable RAM waitstate
224  
225 // write data to drive
226 for (i=0; i<(numBytes/16); i++)
227 {
228 // optimize by writing 16 bytes in-line before looping
229 // keep byte order correct by using temp register
230 temp = *Buffer++;
231 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
232 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
233 temp = *Buffer++;
234 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
235 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
236 temp = *Buffer++;
237 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
238 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
239 temp = *Buffer++;
240 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
241 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
242 temp = *Buffer++;
243 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
244 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
245 temp = *Buffer++;
246 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
247 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
248 temp = *Buffer++;
249 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
250 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
251 temp = *Buffer++;
252 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
253 *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
254 }
255 //cbi(MCUCR, SRW); // disable RAM waitstate
256  
257 }
258  
259 u08 ataStatusWait(u08 mask, u08 waitStatus)
260 {
261 register u08 status;
262  
263 delay(100);
264  
265 // wait for desired status
266 while( ((status = ataReadByte(ATA_REG_CMDSTATUS1)) & mask) == waitStatus );
267  
268 return status;
269 }
270  
271  
272 unsigned char ataReadSectorsCHS( unsigned char Drive,
273 unsigned char Head,
274 unsigned int Track,
275 unsigned char Sector,
276 unsigned int numsectors,
277 unsigned char *Buffer)
278 {
279 unsigned char temp;
280  
281 // Wait for drive to be ready
282 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
283  
284 // Prepare parameters...
285 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
286 ataWriteByte(ATA_REG_CYLHI, Track>>8); // MSB of track
287 ataWriteByte(ATA_REG_CYLLO, Track); // LSB of track
288 ataWriteByte(ATA_REG_STARTSEC, Sector); // sector
289 ataWriteByte(ATA_REG_SECCOUNT, numsectors); // # of sectors
290  
291 // Issue read sector command...
292 ataWriteByte(ATA_REG_CMDSTATUS1, 0x21);
293  
294 // Wait for drive to be ready
295 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
296  
297 if (temp & ATA_SR_ERR)
298 {
299 rprintfProgStrM("RD ERR\r\n");
300 return 1;
301 }
302  
303 // Wait for drive to request data transfer
304 ataStatusWait(ATA_SR_DRQ, 0);
305  
306 // read data from drive
307 ataReadDataBuffer(Buffer, 512*numsectors);
308  
309 // Return the error bit from the status register...
310 temp = ataReadByte(ATA_REG_CMDSTATUS1); // read status register
311  
312 return (temp & ATA_SR_ERR) ? 1:0;
313 }
314  
315  
316 unsigned char ataWriteSectorsCHS(unsigned char Drive,
317 unsigned char Head,
318 unsigned int Track,
319 unsigned char Sector,
320 unsigned int numsectors,
321 unsigned char *Buffer)
322 {
323 unsigned char temp;
324  
325 // Wait for drive to be ready
326 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
327  
328 // Prepare parameters...
329 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
330 ataWriteByte(ATA_REG_CYLHI, Track>>8); // MSB of track
331 ataWriteByte(ATA_REG_CYLLO, Track); // LSB of track
332 ataWriteByte(ATA_REG_STARTSEC, Sector); // sector
333 ataWriteByte(ATA_REG_SECCOUNT, numsectors); // # of sectors
334  
335 // Issue write sector command
336 ataWriteByte(ATA_REG_CMDSTATUS1, 0x31);
337  
338 //delay(100);
339  
340 // Wait for drive to request data transfer
341 ataStatusWait(ATA_SR_DRQ, 0);
342  
343 // write data to drive
344 ataWriteDataBuffer(Buffer, 512*numsectors);
345  
346 // Wait for drive to finish write
347 temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
348  
349 // check for errors
350 if (temp & ATA_SR_ERR)
351 {
352 rprintfProgStrM("WR ERR\r\n");
353 return 1;
354 }
355  
356 // Return the error bit from the status register...
357 return (temp & ATA_SR_ERR) ? 1:0;
358 }
359  
360 unsigned char ataReadSectorsLBA( unsigned char Drive,
361 unsigned long lba,
362 unsigned int numsectors,
363 unsigned char *Buffer)
364 {
365 unsigned int cyl, head, sect;
366 unsigned char temp;
367  
368 #ifdef DEBUG_ATA
369 rprintfProgStrM("ATA LBA read ");
370 rprintfu32(lba); rprintfProgStrM(" ");
371 rprintfu16(numsectors); rprintfProgStrM(" ");
372 rprintfu16((unsigned int)Buffer);
373 rprintfCRLF();
374 #endif
375  
376 sect = (int) ( lba & 0x000000ffL );
377 lba = lba >> 8;
378 cyl = (int) ( lba & 0x0000ffff );
379 lba = lba >> 16;
380 head = ( (int) ( lba & 0x0fL ) ) | ATA_HEAD_USE_LBA;
381  
382 temp = ataReadSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
383  
384 if(temp)
385 ataDiskErr();
386 return temp;
387 }
388  
389 unsigned char ataWriteSectorsLBA( unsigned char Drive,
390 unsigned long lba,
391 unsigned int numsectors,
392 unsigned char *Buffer)
393 {
394 unsigned int cyl, head, sect;
395 unsigned char temp;
396  
397 #ifdef DEBUG_ATA
398 rprintfProgStrM("ATA LBA write ");
399 rprintfu32(lba); rprintfProgStrM(" ");
400 rprintfu16(numsectors); rprintfProgStrM(" ");
401 rprintfu16((unsigned int)Buffer);
402 rprintfCRLF();
403 #endif
404  
405 sect = (int) ( lba & 0x000000ffL );
406 lba = lba >> 8;
407 cyl = (int) ( lba & 0x0000ffff );
408 lba = lba >> 16;
409 head = ( (int) ( lba & 0x0fL ) ) | ATA_HEAD_USE_LBA;
410  
411 temp = ataWriteSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
412  
413 if(temp)
414 ataDiskErr();
415 return temp;
416 }
417  
418  
419 unsigned char ataReadSectors( unsigned char Drive,
420 unsigned long lba,
421 unsigned int numsectors,
422 unsigned char *Buffer)
423 {
424 unsigned int cyl, head, sect;
425 unsigned char temp;
426  
427 // check if drive supports native LBA mode
428 if(ataDriveInfo.LBAsupport)
429 {
430 // drive supports using native LBA
431 temp = ataReadSectorsLBA(Drive, lba, numsectors, Buffer);
432 }
433 else
434 {
435 // drive required CHS access
436 #ifdef DEBUG_ATA
437 // do this defore destroying lba
438 rprintfProgStrM("ATA LBA for CHS read: ");
439 rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
440 #endif
441  
442 // convert LBA to pseudo CHS
443 // remember to offset the sector count by one
444 sect = (u08) (lba % ataDriveInfo.sectors)+1;
445 lba = lba / ataDriveInfo.sectors;
446 head = (u08) (lba % ataDriveInfo.heads);
447 lba = lba / ataDriveInfo.heads;
448 cyl = (u16) lba;
449  
450 #ifdef DEBUG_ATA
451 rprintfProgStrM("C:H:S=");
452 rprintfu16(cyl); rprintfProgStrM(":");
453 rprintfu08(head); rprintfProgStrM(":");
454 rprintfu08(sect); rprintfCRLF();
455 #endif
456  
457 temp = ataReadSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
458 }
459  
460 if(temp)
461 ataDiskErr();
462 return temp;
463 }
464  
465  
466 unsigned char ataWriteSectors(unsigned char Drive,
467 unsigned long lba,
468 unsigned int numsectors,
469 unsigned char *Buffer)
470 {
471 unsigned int cyl, head, sect;
472 unsigned char temp;
473  
474 // check if drive supports native LBA mode
475 if(ataDriveInfo.LBAsupport)
476 {
477 // drive supports using native LBA
478 temp = ataWriteSectorsLBA(Drive, lba, numsectors, Buffer);
479 }
480 else
481 {
482 // drive required CHS access
483 #ifdef DEBUG_ATA
484 // do this defore destroying lba
485 rprintfProgStrM("ATA LBA for CHS write: ");
486 rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
487 #endif
488  
489 // convert LBA to pseudo CHS
490 // remember to offset the sector count by one
491 sect = (u08) (lba % ataDriveInfo.sectors)+1;
492 lba = lba / ataDriveInfo.sectors;
493 head = (u08) (lba % ataDriveInfo.heads);
494 lba = lba / ataDriveInfo.heads;
495 cyl = (u16) lba;
496  
497 #ifdef DEBUG_ATA
498 rprintfProgStrM("C:H:S=");
499 rprintfu16(cyl); rprintfProgStrM(":");
500 rprintfu08(head); rprintfProgStrM(":");
501 rprintfu08(sect); rprintfCRLF();
502 #endif
503  
504 temp = ataWriteSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
505 }
506  
507 if(temp)
508 ataDiskErr();
509 return temp;
510 }
511  
512 void ataDriveSelect(u08 DriveNo)
513 {
514 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(DriveNo ? 0x10:00)); // Drive selection
515 }
516  
517 //----------------------------------------------------------------------------
518 // Set drive mode (STANDBY, IDLE)
519 //----------------------------------------------------------------------------
520 /*#define STANDBY 0
521 #define IDLE 1
522 #define SLEEP 2
523 */
524  
525 /*
526 unsigned char SetMode(unsigned char DriveNo, unsigned char Mode, unsigned char PwrDown)
527 {
528 WriteBYTE(CMD, 6, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
529 WriteBYTE(CMD, 2, (PwrDown ? 0x01:0x00)); // Enable automatic power down
530 switch (Mode)
531 {
532 case STANDBY: WriteBYTE(CMD,7, 0xE2); break;
533 case IDLE: WriteBYTE(CMD,7, 0xE3); break;
534 // NOTE: To recover from sleep, either issue a soft or hardware reset !
535 // (But not on all drives, f.ex seagate ST3655A it's not nessecary to reset
536 // but only to go in Idle mode, But on a Conner CFA170A it's nessecary with
537 // a reset)
538 case SLEEP: WriteBYTE(CMD,7, 0xE6); break;
539 }
540 Timer10mSec=10000;
541 while ((ReadBYTE(CMD,7) & 0xC0)!=0x40 && Timer10mSec); // Wait for DRDY & NOT BUSY
542 if (Timer10mSec==0) return 0xFF; // or timeout
543  
544 // Return the error register...
545 return ReadBYTE(CMD, 1);
546 }
547  
548 */
549  
550 u08 ataReadByte(u08 reg)
551 {
552 register u08 ret;
553 //sbi(MCUCR, SRW); // enable RAM waitstate
554 ret = *((volatile unsigned char*) ATA_REG_BASE + reg);
555 //cbi(MCUCR, SRW); // disable RAM waitstate
556 return ret;
557 }
558  
559 void ataWriteByte(u08 reg, u08 data)
560 {
561 //sbi(MCUCR, SRW); // enable RAM waitstate
562 *((volatile unsigned char*) ATA_REG_BASE + reg) = data;
563 //cbi(MCUCR, SRW); // disable RAM waitstate
564 }
565  
566  
567 void ataShowRegisters(unsigned char DriveNo)
568 {
569 ataWriteByte(ATA_REG_HDDEVSEL, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
570  
571 rprintfProgStrM("R0: DATALOW = 0x"); rprintfu08(ataReadByte(ATA_REG_DATAL )); rprintfProgStrM(" \r\n");
572 rprintfProgStrM("R1: ERROR = 0x"); rprintfu08(ataReadByte(ATA_REG_ERROR )); rprintfProgStrM(" \r\n");
573 rprintfProgStrM("R2: SECT CNT = 0x"); rprintfu08(ataReadByte(ATA_REG_SECCOUNT)); rprintfProgStrM(" \r\n");
574 rprintfProgStrM("R3: SECT NUM = 0x"); rprintfu08(ataReadByte(ATA_REG_STARTSEC)); rprintfProgStrM(" \r\n");
575 rprintfProgStrM("R4: CYL LOW = 0x"); rprintfu08(ataReadByte(ATA_REG_CYLLO )); rprintfProgStrM(" \r\n");
576 rprintfProgStrM("R5: CYL HIGH = 0x"); rprintfu08(ataReadByte(ATA_REG_CYLHI )); rprintfProgStrM(" \r\n");
577 rprintfProgStrM("R6: HEAD/DEV = 0x"); rprintfu08(ataReadByte(ATA_REG_HDDEVSEL)); rprintfProgStrM(" \r\n");
578 rprintfProgStrM("R7: CMD/STA = 0x"); rprintfu08(ataReadByte(ATA_REG_CMDSTATUS1)); rprintfProgStrM("\r\n");
579 }
580  
581 unsigned char ataSWReset(void)
582 {
583 ataWriteByte(ATA_REG_HDDEVSEL, 0x06); // SRST and nIEN bits
584 delay(10); // 10uS delay
585 ataWriteByte(ATA_REG_HDDEVSEL, 0x02); // nIEN bits
586 delay(10); // 10 uS delay
587  
588 while( (ataReadByte(ATA_REG_CMDSTATUS1) & 0xC0) != 0x40 ); // Wait for DRDY and not BSY
589  
590 return ataReadByte(ATA_REG_CMDSTATUS1) + ataReadByte(ATA_REG_ERROR);
591 }
592  
593 /*
594 unsigned char ATA_Idle(unsigned char Drive)
595 {
596  
597 WriteBYTE(CMD, 6, 0xA0 + (Drive ? 0x10:0x00)); // Select drive
598 WriteBYTE(CMD,7, 0xE1);
599  
600 while ((ReadBYTE(CMD,7) & 0xC0)!=0x40); // Wait for DRDY & NOT BUSY
601  
602 // Return the error register...
603 return ReadBYTE(CMD, 1);
604 }
605 */
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3