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 | */ |
Powered by WebSVN v2.8.3