Hi Jungs und Mädels! Hat irgendjemand es schon geschafft IDE PATA Festplatten (wie zum Beispiel Mastor 40GB Typen) direkt mit dem MBED oder ähnlichem zu betreiben und anzusprechen? Mir geht es eher um die direkte Positionierung der Leseköpfe. Sind die Dinger sowas wie Register die man schreibt und liest, oder wie muß man sich das vorstellen? Liebe Grüße, Martin
Hast du denn überhaupt schonmal zu diesem Thema gegoogelt? Es gibt Massenweise infos zu IDE. Und JA es ist nur Registergewutze!
Ja, habe ich. Gefunden hab ich auch so manches. Aber alles nur Theorie. Ich fände es dumm das Rad nochmal erfinden zu müssen, wenn es schon jemand vor mir gelöst hat. Hier eine schöne Zusammenfassung der PIO Schnittstelle: http://www.uni-koblenz.de/~physik/informatik/ECC/ide.pdf Aber mehr nutzbares finde ich nicht wenn ich "ide ansteuerung" suche im googl. Ich denke es gibt schon C++ oder C Libraries dafür...
Hallo, dann such doch nach "IDE register" oder "IDE befehle" oder etwas in der Art. Es gibt Libraries, die einem nach oben ein Filesystem bieten (z.B. http://ultra-embedded.com/?fat_filelib für ne FAT). Aber nach unten wird man für die konkrete Hardware noch den low-level Zugriff implementieren müssen. Bei IDE ist das allerdings nicht mehr als den Zugriff auf die Register zu handlen... Tom
Martin G. schrieb: > Mir geht es eher um die direkte Positionierung der Leseköpfe. Ich kann mir nicht vorstellen, daß das geht. Um die Positionierung der Köpfe kümmert sich die Platte selbst. Du liest und schreibst nur Sektoren.
http://mbed.org Das ist von NXP ein niedlicher ARM, einfach über Cloud Compiler zu programieren. Mich interessiert eigentlich nicht die Logische Fileebene, sondern die direkte Positionierung der Schreib-Leseköpfe. Ich hab mit den Dingern vor, Spiegel hochgenau zu bewegen. Die Drives sind ja perfekte Servosteuerungen, mit perfektem Halten der Position auf einem Track. OK. Der Track hat eine geringe Exzentrizität, aber ich denke das winzige gezappel ist zu verkraften. Da ich ein paar von den Platten im Keller habe, dachte ich, ich mache mal daraus eine Laser Direct Imaging Maschine, ohne den ganzen analogen Schnickschnack. Die Platte muß nicht einmal geöffnet werden, da die Lesekopf-Achse auch von Außen erreichbar ist wenn man das Pickerl runternimmt. Mit meiner Analogen LDI Maschine hatte ich nur schlechte Ergebnisse. Sie ist nicht zuverlässig genug. Siehe: http://www.gyurma.de/LDI1 Bilder könnt ihr hier sehen: http://www.gyurma.de/LDIBilder1 Und ersten Erfolg hier: http://www.gyurma.de/ldisuccess1 Mein Problem war mit den analogen Dingern, daß sie bei größeren Auslenkungen anfingen komisch zu wackeln. Total ungewohnt, als wenn die Regelung nicht gepasst hätte, oder die Spannung eingebrochen wäre.
Probleme können noch die internen Cache Speicher machen, die ich bei Tests mit einem Linux PC auch hatte.
Stampede schrieb: > was ist MBED ? Ich habe mal eine Ansteuerung geschrieben für IDE Platten > für PIC32 COntroller in C. Darf ich das mal bitte haben? mfg Martin
Martin G. schrieb: > Mich interessiert eigentlich nicht die Logische Fileebene, sondern die > direkte Positionierung der Schreib-Leseköpfe. > Ich hab mit den Dingern vor, Spiegel hochgenau zu bewegen. Das geht nicht über die IDE-Schnittstelle. Keine Chance. Da wirst Du die Spulen der Linearantriebe selbst ansteuern müssen -- wobei das dann auch nicht mehr hochgenau wird, weil die zur genauen Positionierung erforderliche Servoinformation fehlt, die auf den Magnetscheiben aufgeprägt ist.
Wie gesagt, für PIC32 und die FSLIB von Microchip. Die Funtkionen sind zum Lesen einzelner Sektoren. Damit wirst du die Spiegel aber nicht positionieren können.
1 | /******************************************************************************
|
2 | *
|
3 | * HDD Memory Disk Drive File System
|
4 | *
|
5 | ******************************************************************************
|
6 | * FileName: HDD.c
|
7 | * Dependencies: HDD.h
|
8 | * string.h
|
9 | * FSIO.h
|
10 | * FSDefs.h
|
11 | * Processor: PIC32 with PMP
|
12 | * Compiler: None
|
13 | * Author: Stefan Dreyer
|
14 | * Version: 1.0.2
|
15 | *
|
16 | * Software License Agreement
|
17 | *
|
18 | *
|
19 | *
|
20 | * THIS SOFTWARE IS PROVIDED IN AN AS IS CONDITION. NO WARRANTIES,
|
21 | * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
|
22 | * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
23 | * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE AUTHOR SHALL NOT,
|
24 | * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
|
25 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
26 | *
|
27 | * Info Version 1.0.0:
|
28 | * This physical layer routines is intended to access a HDD by the Microchip
|
29 | * "Memory Disk Drive File System".
|
30 | * At the moment, the routines are limited to PIC32 processers with PMP
|
31 | * interface. PBclock can be set to 80MHz.
|
32 | *
|
33 | * Info Version 1.0.1:
|
34 | * - added BYTE MDD_HDD_DEVICE_READY(void) to MDD_HDD_MediaInitialize(void)
|
35 | * in order to wait until the disk has spin up.
|
36 | * - resolved a bug on startup in BYTE MDD_HDD_DEVICE_READY(void).
|
37 | *
|
38 | * Info Version 1.0.2:
|
39 | * - changed access to registers: Only those bit are chanced that are
|
40 | * really needed. This results in 35 word smaller code and thus a little
|
41 | * speedup.
|
42 | * - minor improvements to optimize speed
|
43 | *
|
44 | * Info Version 1.0.3: (in progress)
|
45 | * - update for 48Bit LBA
|
46 | *****************************************************************************/
|
47 | #include "Compiler.h" |
48 | #include "GenericTypeDefs.h" |
49 | #include "MDD File System\FSIO.h" |
50 | #include "MDD File System\FSDefs.h" |
51 | #include "MDD File System\HDD.h" |
52 | #include "string.h" |
53 | #include "FSConfig.h" |
54 | #include "HardwareProfile.h" |
55 | |
56 | /******************************************************************************
|
57 | * Global Variables
|
58 | *****************************************************************************/
|
59 | #ifdef SUPPORT_48_BIT_LBA
|
60 | QWORD MDD_HDD_finalLBA; |
61 | #else
|
62 | DWORD MDD_HDD_finalLBA; |
63 | #endif
|
64 | static MEDIA_INFORMATION mediaInformation; |
65 | extern BOOL IDE_DEVICE; |
66 | HDD_IDENTIFY_RESPONSE identifyResponse; |
67 | |
68 | /******************************************************************************
|
69 | * Prototypes
|
70 | *****************************************************************************/
|
71 | BYTE MDD_HDD_BUSY(void); |
72 | BYTE MDD_HDD_DATA_READY(void); |
73 | BYTE MDD_HDD_DEVICE_READY(void); |
74 | void MDD_HDD_IDENTIFY_DEVICE(void); |
75 | MEDIA_INFORMATION * MDD_HDD_MediaInitialize(void); |
76 | |
77 | //#define DEBUG_MODE
|
78 | |
79 | /******************************************************************************
|
80 | * Function: BYTE MDD_HDD_MediaDetect(void)
|
81 | *
|
82 | * PreCondition: InitIO() function has been executed.
|
83 | *
|
84 | * Input: void
|
85 | *
|
86 | * Output: TRUE - HDD detected
|
87 | * FALSE - HDD detected
|
88 | *
|
89 | * Side Effects: None
|
90 | *
|
91 | * Overview: None
|
92 | *
|
93 | * Note: This function could be changed to determine what is
|
94 | * connected on the IDE bus
|
95 | *****************************************************************************/
|
96 | BYTE MDD_HDD_MediaDetect() |
97 | {
|
98 | return TRUE; |
99 | }//end MediaDetect |
100 | |
101 | |
102 | /******************************************************************************
|
103 | * Function: void MDD_HDD_InitIO(void)
|
104 | *
|
105 | * PreCondition: None
|
106 | *
|
107 | * Input: void
|
108 | *
|
109 | * Output: void
|
110 | *
|
111 | * Side Effects: None
|
112 | *
|
113 | * Overview: None
|
114 | *
|
115 | * Note: None
|
116 | *****************************************************************************/
|
117 | void MDD_HDD_InitIO (void) |
118 | {
|
119 | IDE_WR_TRIS = OUTPUT; |
120 | IDE_RESET_TRIS = OUTPUT; |
121 | IDE_RESET = 1; |
122 | IDE_RD_TRIS = OUTPUT; |
123 | IDE_CS0_TRIS = OUTPUT; |
124 | IDE_CS1_TRIS = OUTPUT; |
125 | IDE_IRQ_TRIS = INPUT; |
126 | IDE_DIR_TRIS = OUTPUT; |
127 | #ifdef USE_LEVELSHIFTER
|
128 | mIDE_SET_OUTPUT(); |
129 | #endif
|
130 | IDE_A0_TRIS = OUTPUT; |
131 | IDE_A1_TRIS = OUTPUT; |
132 | IDE_A2_TRIS = OUTPUT; |
133 | |
134 | IDE_CS0 = 1; // Deselect the device |
135 | IDE_CS1 = 1; |
136 | }
|
137 | |
138 | /******************************************************************************
|
139 | * Function: void IDENTIFY_DEVICE(void)
|
140 | *
|
141 | * PreCondition: None
|
142 | *
|
143 | * Input: None
|
144 | *
|
145 | * Output: None
|
146 | *
|
147 | * Side Effects: None
|
148 | *
|
149 | * Overview: None
|
150 | *
|
151 | * Note: None
|
152 | *****************************************************************************/
|
153 | void MDD_HDD_IDENTIFY_DEVICE(void) |
154 | {
|
155 | unsigned int counter = 0; |
156 | BYTE i; |
157 | QWORD data; |
158 | |
159 | #ifdef DEBUG_MODE
|
160 | UART2PrintString("HDD IDENTIFY DEVICE\n\r"); |
161 | #endif
|
162 | IDE_CS0 = 0; |
163 | // IDE_CS1 = 1;
|
164 | mPMPOpen(PMP_HDD_CONTROL, PMP_HDD_MODE, PMP_HDD_PORT, PMP_HDD_INTERRUPT); |
165 | MDD_HDD_BUSY(); // Ready for command? |
166 | |
167 | #ifdef USE_LEVELSHIFTER
|
168 | mIDE_SET_OUTPUT(); |
169 | #endif
|
170 | |
171 | // TODO: LBA3 SETS MASTER / SLAVE !!!
|
172 | mMMD_HDD_LBA3(); // Set Device |
173 | if(IDE_DEVICE == MASTER) |
174 | PMDIN = 0x00; // DEVICE 0 |
175 | else
|
176 | PMDIN = 0x10; // DEVICE 1 |
177 | while(PMMODEbits.BUSY); |
178 | mMMD_HDD_COMMAND_REGISTER(); // Set READ COMMAND |
179 | Nop(); |
180 | PMDIN = IDENTIFY_DEVICE; |
181 | while(PMMODEbits.BUSY); // Wait until PMP is free |
182 | |
183 | MDD_HDD_DATA_READY(); // Ready for data to be received? |
184 | #ifdef USE_LEVELSHIFTER
|
185 | mIDE_SET_INPUT(); |
186 | #endif
|
187 | mMMD_HDD_IO_REGISTER(); // Set to IO Register to get data |
188 | Nop(); |
189 | PMDIN; // dummy read to clear latches |
190 | while(PMMODEbits.BUSY); |
191 | while(counter < 256) // 256 WORDS are to be transmitted |
192 | {
|
193 | if(27 == counter) // here is the modelnumber |
194 | {
|
195 | for(i=0;i<40;i=i+2) // copy the 40Bytes |
196 | {
|
197 | data = PMDIN; |
198 | while(PMMODEbits.BUSY); |
199 | identifyResponse.model_number[i+1] = (data&0xFF); |
200 | identifyResponse.model_number[i] = (data>>8)&0xFF; |
201 | counter++; |
202 | }
|
203 | }
|
204 | else if(100 == counter) |
205 | {
|
206 | identifyResponse.LBA_48 = PMDIN; |
207 | while(PMMODEbits.BUSY); // Wait until PMP is free |
208 | data = PMDIN; |
209 | identifyResponse.LBA_48 |= (data&0xFF)<<16; |
210 | while(PMMODEbits.BUSY); // Wait until PMP is free |
211 | data = PMDIN; |
212 | identifyResponse.LBA_48 |= (data&0xFF)<<32; |
213 | while(PMMODEbits.BUSY); // Wait until PMP is free |
214 | data = PMDIN; |
215 | identifyResponse.LBA_48 |= (data&0xFF)<<48; |
216 | while(PMMODEbits.BUSY); // Wait until PMP is free |
217 | counter += 4; |
218 | }
|
219 | else if(counter == 85) |
220 | {
|
221 | data = PMDIN&0x1; // LSB shows if SMART is supported |
222 | while(PMMODEbits.BUSY); |
223 | counter++; |
224 | if(data == 0x1) //SMART supported |
225 | {
|
226 | identifyResponse.SMART = 1; |
227 | #ifdef DEBUG_MODE
|
228 | UART2PrintString("SMART supported\n\r"); |
229 | #endif
|
230 | }
|
231 | else
|
232 | {
|
233 | identifyResponse.SMART = 0; |
234 | }
|
235 | }
|
236 | else if(counter == 86) |
237 | {
|
238 | data = PMDIN&0x400; // Bit shows if 48Bit LBA is supported |
239 | while(PMMODEbits.BUSY); |
240 | counter++; |
241 | if(data == 0x400) // supported |
242 | {
|
243 | identifyResponse.LBA_48_SUPPORT_BIT = 1; |
244 | #ifdef DEBUG_MODE
|
245 | UART2PrintString("Use 48 Bit LBA\n\r"); |
246 | #endif
|
247 | }
|
248 | else
|
249 | {
|
250 | identifyResponse.LBA_48_SUPPORT_BIT = 0; |
251 | }
|
252 | }
|
253 | else
|
254 | {
|
255 | PMDIN; // discard data |
256 | while(PMMODEbits.BUSY); |
257 | counter++; |
258 | }
|
259 | }
|
260 | #ifdef USE_LEVELSHIFTER
|
261 | mIDE_SET_OUTPUT(); |
262 | #endif
|
263 | IDE_CS0 = 1; |
264 | UART2PrintString((char*)identifyResponse.model_number ); |
265 | // IDE_CS1 = 1;
|
266 | }
|
267 | |
268 | |
269 | /*********************************************************
|
270 | Function:
|
271 | DWORD MDD_HDD_ReadCapacity (void)
|
272 | Summary:
|
273 | Determines the current capacity of the HDD
|
274 | Conditions:
|
275 | MDD_MediaInitialize() is complete
|
276 | Input:
|
277 | None
|
278 | Return:
|
279 | The capacity of the device
|
280 | Side Effects:
|
281 | None.
|
282 | Description:
|
283 | The MDD_HDD_ReadCapacity function is used by the
|
284 | USB mass storage class to return the total number
|
285 | of sectors on the HDD. To get the capacity, the
|
286 | READ_NATIVE_MAX_ADDRESS is executed, which gives
|
287 | the number of sectors available on the device.
|
288 | Remarks:
|
289 | None
|
290 | *********************************************************/
|
291 | DWORD MDD_HDD_ReadCapacity(void) |
292 | {
|
293 | MDD_HDD_finalLBA = 0; |
294 | #ifdef DEBUG_MODE
|
295 | UART2PrintString("HDD READ CAPACITIY: "); |
296 | #endif
|
297 | IDE_CS0 = 0; |
298 | IDE_CS1 = 1; |
299 | mPMPOpen(PMP_HDD_CONTROL, PMP_HDD_MODE, PMP_HDD_PORT, PMP_HDD_INTERRUPT); |
300 | MDD_HDD_BUSY(); // Ready for command? |
301 | |
302 | #ifdef USE_LEVELSHIFTER
|
303 | mIDE_SET_OUTPUT(); |
304 | #endif
|
305 | |
306 | IDE_CS0 = 1; |
307 | IDE_CS1 = 0; |
308 | MMD_HDD_DEVICE_CONTOL_REGISTER(); |
309 | PMDIN = 0x00; // Set HOB Bit to 0 again |
310 | while(PMMODEbits.BUSY); // Wait until PMP is free |
311 | IDE_CS0 = 0; |
312 | IDE_CS1 = 1; |
313 | Nop(); |
314 | mMMD_HDD_LBA3(); // Set Device |
315 | Nop(); |
316 | if(IDE_DEVICE == MASTER) |
317 | PMDIN = 0x00; // DEVICE 0 |
318 | else
|
319 | PMDIN = 0x10; // DEVICE 1 |
320 | while(PMMODEbits.BUSY); |
321 | mMMD_HDD_COMMAND_REGISTER(); // Set READ COMMAND |
322 | Nop(); |
323 | Nop(); |
324 | |
325 | switch(identifyResponse.LBA_48_SUPPORT_BIT) |
326 | {
|
327 | case (1): // We need to use 48 Bit LBA |
328 | PMDIN = READ_NATIVE_MAX_ADDRESS_EXT; |
329 | while(PMMODEbits.BUSY); // Wait until PMP is free |
330 | MDD_HDD_BUSY(); // |
331 | // Device is set to HOB = 0;
|
332 | mMMD_HDD_LBA0(); |
333 | while(PMMODEbits.BUSY); // Wait until PMP is free |
334 | PMDIN; // Dummy to clear latches |
335 | while(PMMODEbits.BUSY); // Wait until PMP is free |
336 | MDD_HDD_finalLBA |= (PMDIN&0xFF); // Read MAX_LBA 7:0 |
337 | while(PMMODEbits.BUSY); // Wait until PMP is free |
338 | mMMD_HDD_LBA1(); |
339 | while(PMMODEbits.BUSY); // Wait until PMP is free |
340 | PMDIN; |
341 | MDD_HDD_finalLBA |= ((PMDIN&0xFF)<<8);// Read MAX_LBA 15:8 |
342 | while(PMMODEbits.BUSY); // Wait until PMP is free |
343 | mMMD_HDD_LBA2(); |
344 | while(PMMODEbits.BUSY); // Wait until PMP is free |
345 | PMDIN; |
346 | MDD_HDD_finalLBA |= ((PMDIN&0xFF)<<16); // Read MAX_LBA 23:16 |
347 | while(PMMODEbits.BUSY); // Wait until PMP is free |
348 | // Set to HOB 1
|
349 | #ifdef USE_LEVELSHIFTER
|
350 | mIDE_SET_OUTPUT(); // Set to output again |
351 | #endif
|
352 | IDE_CS0 = 1; |
353 | IDE_CS1 = 0; |
354 | MMD_HDD_DEVICE_CONTOL_REGISTER(); |
355 | Nop(); |
356 | PMDIN = 0x80; // Set HOB Bit to 1 |
357 | while(PMMODEbits.BUSY); // Wait until PMP is free |
358 | IDE_CS0 = 0; |
359 | IDE_CS1 = 1; |
360 | #ifdef USE_LEVELSHIFTER
|
361 | mIDE_SET_INPUT(); // Set to output again |
362 | #endif
|
363 | mMMD_HDD_LBA0(); |
364 | Nop(); |
365 | while(PMMODEbits.BUSY); // Wait until PMP is free |
366 | PMDIN; // Dummy to clear latches |
367 | while(PMMODEbits.BUSY); // Wait until PMP is free |
368 | MDD_HDD_finalLBA |= ((PMDIN&0xFF)<<24); // Read MAX_LBA 31:24 |
369 | while(PMMODEbits.BUSY); // Wait until PMP is free |
370 | // Currently, only 32 Bit sector adresses (for 2TB disks) are used
|
371 | // For this reason, the following LBA bytes are not used.
|
372 | #ifdef USE_LEVELSHIFTER
|
373 | mIDE_SET_OUTPUT(); // Set to output again |
374 | #endif
|
375 | IDE_CS0 = 1; |
376 | IDE_CS1 = 0; |
377 | MMD_HDD_DEVICE_CONTOL_REGISTER(); |
378 | PMDIN = 0x00; // Set HOB Bit to 0 again |
379 | while(PMMODEbits.BUSY); // Wait until PMP is free |
380 | break; |
381 | |
382 | case (0): // We need to use 28 Bit LBA |
383 | default:
|
384 | PMDIN = READ_NATIVE_MAX_ADDRESS; |
385 | while(PMMODEbits.BUSY); // Wait until PMP is free |
386 | MDD_HDD_BUSY(); // |
387 | mMMD_HDD_LBA3(); // Get the LBA |
388 | while(PMMODEbits.BUSY); |
389 | PMDIN; // dummy |
390 | while(PMMODEbits.BUSY); // Wait until PMP is free |
391 | MDD_HDD_finalLBA |= ((PMDIN&0x0F)<<24); // only 24Bit are used |
392 | while(PMMODEbits.BUSY); // Wait until PMP is free |
393 | mMMD_HDD_LBA2(); |
394 | Nop(); |
395 | while(PMMODEbits.BUSY); // Wait until PMP is free |
396 | PMDIN; |
397 | while(PMMODEbits.BUSY); // Wait until PMP is free |
398 | MDD_HDD_finalLBA |= ((PMDIN&0xFF)<<16); |
399 | while(PMMODEbits.BUSY); // Wait until PMP is free |
400 | mMMD_HDD_LBA1(); |
401 | Nop(); |
402 | while(PMMODEbits.BUSY); // Wait until PMP is free |
403 | PMDIN; |
404 | while(PMMODEbits.BUSY); // Wait until PMP is free |
405 | MDD_HDD_finalLBA |= ((PMDIN&0xFF)<<8); |
406 | while(PMMODEbits.BUSY); // Wait until PMP is free |
407 | mMMD_HDD_LBA0(); |
408 | Nop(); |
409 | while(PMMODEbits.BUSY); // Wait until PMP is free |
410 | PMDIN; |
411 | while(PMMODEbits.BUSY); // Wait until PMP is free |
412 | MDD_HDD_finalLBA |= (PMDIN&0xFF); |
413 | while(PMMODEbits.BUSY); // Wait until PMP is free |
414 | break; |
415 | }
|
416 | |
417 | #ifdef USE_LEVELSHIFTER
|
418 | mIDE_SET_OUTPUT(); |
419 | #endif
|
420 | IDE_CS1 = 1; // Deselect IDE Drive |
421 | IDE_CS0 = 1; |
422 | #ifdef DEBUG_MODE
|
423 | UART2PutHexDWord(MDD_HDD_finalLBA); |
424 | UART2PrintString(" HEX\n\r"); |
425 | #endif
|
426 | return (MDD_HDD_finalLBA); |
427 | }
|
428 | |
429 | |
430 | |
431 | /*********************************************************
|
432 | Function:
|
433 | WORD MDD_SDSPI_ReadSectorSize (void)
|
434 | Summary:
|
435 | Determines the current sector size on the HDD
|
436 | Conditions:
|
437 | MDD_MediaInitialize() is complete
|
438 | Input:
|
439 | None
|
440 | Return:
|
441 | The size of the sectors for the physical media
|
442 | Side Effects:
|
443 | None.
|
444 | Description:
|
445 | The MDD_SDSPI_ReadSectorSize function is used by the
|
446 | USB mass storage class to return the card's sector
|
447 | size to the PC on request.
|
448 | Remarks:
|
449 | None
|
450 | *********************************************************/
|
451 | WORD MDD_HDD_ReadSectorSize(void) |
452 | {
|
453 | return MEDIA_SECTOR_SIZE; |
454 | }
|
455 | |
456 | |
457 | /******************************************************************************
|
458 | * Function: MEDIA_INFORMATION * MMDD_HDD_MediaInitialize(void)
|
459 | *
|
460 | * PreCondition: None
|
461 | *
|
462 | * Input: None
|
463 | *
|
464 | * Output: Returns TRUE if media is initialized, FALSE otherwise
|
465 | *
|
466 | * Overview: MediaInitialize initializes the media card and supporting variables.
|
467 | *
|
468 | * Note: None
|
469 | *****************************************************************************/
|
470 | MEDIA_INFORMATION * MDD_HDD_MediaInitialize(void) |
471 | {
|
472 | // Example initialization
|
473 | |
474 | // You can define error codes depending on how your device works
|
475 | // 0x00 (MEDIA_NO_ERRORS) indicates success
|
476 | // if (result == FAILURE)
|
477 | // mediaInformation.errorCode = 0x00;
|
478 | // else
|
479 | // mediaInformation.errorCode = 0x01;
|
480 | // MDD_HDD_DEVICE_READY();
|
481 | // MDD_HDD_IDENTIFY_DEVICE();
|
482 | mediaInformation.errorCode = MEDIA_NO_ERROR; |
483 | mediaInformation.validityFlags.value = 0; |
484 | return &mediaInformation; |
485 | }//end MediaInitialize |
486 | |
487 | |
488 | /******************************************************************************
|
489 | * Function: BYTE MDD_HDD_SectorRead(DWORD sector_addr, BYTE *buffer, WORD blocks)
|
490 | *
|
491 | * PreCondition: None
|
492 | *
|
493 | * Input: sector_addr - Sector address, each sector contains 512-byte
|
494 | * buffer - Buffer where data will be stored
|
495 | *
|
496 | * Output: Returns TRUE if read successful, false otherwise
|
497 | *
|
498 | * Side Effects: None
|
499 | *
|
500 | * Overview: SectorRead reads 512 bytes of data from the disk starting
|
501 | * at the sector address specified by sector_addr and stores
|
502 | * them in the location pointed to by 'buffer'.
|
503 | *
|
504 | * Note: At the moment, no error checking is supported.
|
505 | *
|
506 | * Depending on the disksize, LBA28 or LBA48 will be used:
|
507 | *
|
508 | * Sector Count Current -
|
509 | * number of sectors to be transferred low order, bits (7:0).
|
510 | * Sector Count Previous -
|
511 | * number of sectors to be transferred high order, bits (15:8).
|
512 | * LBA Low Current - ( = LBA0)
|
513 | * LBA (7:0).
|
514 | * LBA Low Previous -
|
515 | * LBA (31:24).
|
516 | * LBA Mid Current - ( = LBA1)
|
517 | * LBA (15:8).
|
518 | * LBA Mid Previous -
|
519 | * LBA (39:32).
|
520 | * LBA High Current - ( = LBA2)
|
521 | * LBA (23:16).
|
522 | * LBA High Previous -
|
523 | * LBA (47:40).
|
524 | *****************************************************************************/
|
525 | BYTE MDD_HDD_SectorRead(DWORD sector_addr, BYTE* buffer, WORD blocks) |
526 | {
|
527 | WORD data; |
528 | WORD index, i; |
529 | BYTE status = TRUE; |
530 | BYTE *bptr; |
531 | |
532 | IDE_CS0 = 0; |
533 | // IDE_CS1 = 1;
|
534 | mPMPOpen(PMP_HDD_CONTROL, PMP_HDD_MODE, PMP_HDD_PORT, PMP_HDD_INTERRUPT); // This takes 30 word of program memory!!! |
535 | MDD_HDD_BUSY(); // Ready for command? |
536 | |
537 | #ifdef USE_LEVELSHIFTER
|
538 | mIDE_SET_OUTPUT(); |
539 | #endif // Set Levelshifter to Output
|
540 | /* // TODO: LBA3 SETS MASTER / SLAVE !!!
|
541 | mMMD_HDD_LBA3(); // Set to LBA3 Register
|
542 | PMDIN = (((sector_addr>>24)&0x0F)|0xE0); // Write byte
|
543 | while(PMMODEbits.BUSY); // Wait until PMP is free
|
544 | mMMD_HDD_LBA2(); // Set to LBA2 Register
|
545 | PMDIN = (sector_addr>>16); // Write byte
|
546 | while(PMMODEbits.BUSY); // Wait until PMP is free
|
547 | mMMD_HDD_LBA1(); // Set to LBA1 Register
|
548 | PMDIN = (sector_addr>>8); // Write byte
|
549 | while(PMMODEbits.BUSY); // Wait until PMP is free
|
550 | mMMD_HDD_LBA0(); // Set to LBA0 Register
|
551 | PMDIN = sector_addr; // Write byte
|
552 | while(PMMODEbits.BUSY); // Wait until PMP is free
|
553 | |
554 | // TODO CHANGE COUNT FOR HIGH BANDWIDTH
|
555 | mMMD_HDD_SECTOR_COUNT(); // Number of sector (512Byte) to be transfered
|
556 | PMDIN = 0x1; // transfer only one sector
|
557 | while(PMMODEbits.BUSY); // Wait until PMP is free
|
558 | |
559 | mMMD_HDD_COMMAND_REGISTER(); // Set READ COMMAND*/
|
560 | |
561 | #ifdef DEBUG_MODE
|
562 | UART2PrintString("READ10 Sector: "); |
563 | UART2PutHexDWord(sector_addr); |
564 | UART2PrintString("\n\r"); |
565 | UART2PrintString("READ10 Nr: "); |
566 | UART2PutHexDWord(blocks); |
567 | UART2PrintString("\n\r"); |
568 | #endif
|
569 | |
570 | switch(identifyResponse.LBA_48_SUPPORT_BIT) |
571 | {
|
572 | case (1): // We need to use 48 Bit LBA |
573 | //optimized to minimize instructions on register change:
|
574 | mMMD_HDD_LBA1(); // LBA1 Register (LBA Mid) |
575 | PMDIN = 0x0; // Write LBA Mid previous byte (39:32) |
576 | while(PMMODEbits.BUSY); // Wait until PMP is free |
577 | PMDIN = (sector_addr>>8)&0xFF; // Write LBA Mid current byte (15:8) |
578 | while(PMMODEbits.BUSY); // Wait until PMP is free |
579 | |
580 | IDE_A0 = 1; // LBA2 (LBA High) |
581 | Nop(); |
582 | PMDIN = 0x0; // Write LBA High previous byte (47:40) |
583 | while(PMMODEbits.BUSY); // Wait until PMP is free |
584 | PMDIN = (sector_addr>>16)&0xFF; // Write LBA High current byte (23:16) |
585 | while(PMMODEbits.BUSY); // Wait until PMP is free |
586 | |
587 | IDE_A1 = 1; // LBA3 (Device) |
588 | IDE_A0 = 0; // LBA bit has to be set |
589 | Nop(); |
590 | if(IDE_DEVICE == MASTER) |
591 | PMDIN = 0xE; // Write byte, set to MASTER device |
592 | else
|
593 | PMDIN = 0xF; // Write byte, set to SLAVE device |
594 | while(PMMODEbits.BUSY); // Wait until PMP is free |
595 | |
596 | IDE_A2 = 0; // LBA0 (LBA Low) |
597 | IDE_A0 = 1; |
598 | Nop(); |
599 | PMDIN = (sector_addr>>24)&0xFF; // Write LBA Mid previous byte (31:24) |
600 | while(PMMODEbits.BUSY); // Wait until PMP is free |
601 | PMDIN = sector_addr&0xFF; // Write LBA Mid current byte (7:0) |
602 | while(PMMODEbits.BUSY); // Wait until PMP is free |
603 | |
604 | IDE_A0 = 0; // SectorCount |
605 | Nop(); |
606 | PMDIN = (blocks>>8)&0xFF; // Write sector cout (15:8) |
607 | while(PMMODEbits.BUSY); // Wait until PMP is free |
608 | PMDIN = blocks&0xFF; // Write sector count (7:0) |
609 | while(PMMODEbits.BUSY); // Wait until PMP is free |
610 | |
611 | IDE_A2 = 1; |
612 | IDE_A0 = 1; |
613 | Nop(); |
614 | PMDIN = READ_SECTOR_EXT; // |
615 | while(PMMODEbits.BUSY); // Wait until PMP is free |
616 | /*MDD_HDD_DATA_READY(); // Ready for data to be received?
|
617 | mMMD_HDD_IO_REGISTER(); // Set to IO Register to get data
|
618 | Nop();
|
619 | PMDIN; // Dummy read to clear latches
|
620 | while(PMMODEbits.BUSY); // Wait until PMP is free*/
|
621 | bptr = buffer; |
622 | break; |
623 | case (0): // Use old 28 Bit LBA |
624 | default:
|
625 | //optimized to minimize instructions on register change:
|
626 | mMMD_HDD_LBA1(); // Set to LBA1 Register |
627 | PMDIN = (sector_addr>>8)&0xFF; // Write byte |
628 | while(PMMODEbits.BUSY); // Wait until PMP is free |
629 | |
630 | IDE_A0 = 1; // LBA2 |
631 | Nop(); |
632 | PMDIN = (sector_addr>>16)&0xFF; // Write byte |
633 | while(PMMODEbits.BUSY); // Wait until PMP is free |
634 | |
635 | IDE_A1 = 1; // LBA3 |
636 | IDE_A0 = 0; |
637 | data = (((sector_addr>>24)&0x0F)|0xE0); // |
638 | if(IDE_DEVICE == MASTER) |
639 | PMDIN = data; // Write byte |
640 | else
|
641 | PMDIN = (data | 0x10); // Write byte |
642 | while(PMMODEbits.BUSY); // Wait until PMP is free |
643 | |
644 | IDE_A2 = 0; // LBA0 |
645 | IDE_A0 = 1; |
646 | PMDIN = sector_addr&0xFF; // Write byte |
647 | while(PMMODEbits.BUSY); // Wait until PMP is free |
648 | |
649 | IDE_A0 = 0; // SectorCount |
650 | if(blocks == 256) |
651 | PMDIN = 0; // transfer 256 sector |
652 | else
|
653 | PMDIN = blocks; // transfer x sector |
654 | while(PMMODEbits.BUSY); // Wait until PMP is free |
655 | |
656 | IDE_A2 = 1; |
657 | IDE_A0 = 1; |
658 | Nop(); |
659 | PMDIN = READ_SECTOR; // |
660 | while(PMMODEbits.BUSY); // Wait until PMP is free |
661 | /*MDD_HDD_DATA_READY(); // Ready for data to be received?
|
662 | mMMD_HDD_IO_REGISTER(); // Set to IO Register to get data
|
663 | Nop();
|
664 | PMDIN; // Dummy read to clear latches
|
665 | while(PMMODEbits.BUSY); // Wait until PMP is free*/
|
666 | bptr = buffer; |
667 | break; |
668 | } // End Switch LBA Mode |
669 | |
670 | for (index = 0; index < blocks; index++) // Copy data |
671 | {
|
672 | MDD_HDD_DATA_READY(); |
673 | mMMD_HDD_IO_REGISTER(); // Set to IO Register to get data |
674 | Nop(); |
675 | Nop(); |
676 | #ifdef DEBUG_MODE
|
677 | UART2PrintString("ReadSector\n\r"); |
678 | #endif
|
679 | PMDIN; // Dummy read to clear latches |
680 | while(PMMODEbits.BUSY); // Wait until PMP is free |
681 | for(i = 0; i < (MEDIA_SECTOR_SIZE/2); i++) //Reads in 512-byte of data |
682 | {
|
683 | while(PMMODEbits.BUSY); // Wait until PMP is free |
684 | data = PMDIN; |
685 | (*bptr++) = data; |
686 | (*bptr++) = (data>>8)&0xFF; |
687 | |
688 | }
|
689 | }
|
690 | |
691 | #ifdef USE_LEVELSHIFTER
|
692 | mIDE_SET_OUTPUT(); |
693 | #endif
|
694 | //IDE_CS1 = 1; // Deselect IDE Drive
|
695 | IDE_CS0 = 1; |
696 | //mPMPClose(); // Close to free for other functions (RAM, LCD, etc.)
|
697 | return(status); |
698 | }//end SectorRead |
699 | |
700 | /******************************************************************************
|
701 | * Function: BYTE MDD_HDD_SectorWrite(DWORD sector_addr, BYTE *buffer, BYTE allowWriteToZero)
|
702 | *
|
703 | * PreCondition: None
|
704 | *
|
705 | * Input: sector_addr - Sector address, each sector contains 512-byte
|
706 | * buffer - Buffer where data will be read
|
707 | * allowWriteToZero - If true, writes to the MBR will be valid
|
708 | *
|
709 | * Output: Returns TRUE if write successful, FALSE otherwise
|
710 | *
|
711 | * Side Effects: None
|
712 | *
|
713 | * Overview: SectorWrite sends 512 bytes of data from the location
|
714 | * pointed to by 'buffer' to the card starting
|
715 | * at the sector address specified by sector_addr.
|
716 | *
|
717 | * Note: Write to sector 0 must be allowed so that the dive can
|
718 | * be formatted.
|
719 | * At the moment, no error checking is supported.
|
720 | *****************************************************************************/
|
721 | BYTE MDD_HDD_SectorWrite(DWORD sector_addr, BYTE* buffer, BYTE allowWriteToZero) |
722 | {
|
723 | WORD data; |
724 | WORD index; |
725 | BYTE status = TRUE; |
726 | BYTE *bptr; |
727 | |
728 | IDE_CS0 = 0; // |
729 | // IDE_CS1 = 1; // Select device
|
730 | |
731 | mPMPOpen(PMP_HDD_CONTROL, PMP_HDD_MODE, PMP_HDD_PORT, PMP_HDD_INTERRUPT); |
732 | MDD_HDD_BUSY(); // Ready for command? |
733 | #ifdef USE_LEVELSHIFTER
|
734 | mIDE_SET_OUTPUT(); |
735 | #endif // Set Levelshifter to Output
|
736 | // TODO: LBA3 SETS MASTER / SLAVE !!!
|
737 | mMMD_HDD_LBA3(); // Set to LBA3 Register |
738 | data = (((sector_addr>>24)&0x0F)|0xE0); // Write byte |
739 | if(IDE_DEVICE == MASTER) |
740 | PMDIN = data; // Write byte |
741 | else
|
742 | PMDIN = (data | 0x10); // Write byte |
743 | while(PMMODEbits.BUSY); // Wait until PMP is free |
744 | mMMD_HDD_LBA2(); // Set to LBA2 Register |
745 | PMDIN = (sector_addr>>16); // Write byte |
746 | while(PMMODEbits.BUSY); // Wait until PMP is free |
747 | mMMD_HDD_LBA1(); // Set to LBA1 Register |
748 | PMDIN = (sector_addr>>8); // Write byte |
749 | while(PMMODEbits.BUSY); // Wait until PMP is free |
750 | mMMD_HDD_LBA0(); // Set to LBA0 Register |
751 | PMDIN = sector_addr; // Write byte |
752 | while(PMMODEbits.BUSY); // Wait until PMP is free |
753 | |
754 | // TODO CHANGE COUNT FOR HIGH BANDWIDTH
|
755 | mMMD_HDD_SECTOR_COUNT(); // Number of sector (512Byte) to be transfered |
756 | PMDIN = 0x1; // transfer only one sector |
757 | while(PMMODEbits.BUSY); // Wait until PMP is free |
758 | |
759 | mMMD_HDD_COMMAND_REGISTER(); // Set READ COMMAND |
760 | |
761 | PMDIN = WRITE_SECTOR; // |
762 | while(PMMODEbits.BUSY); // Wait until PMP is free |
763 | MDD_HDD_DATA_READY(); // Ready for data to be received? |
764 | mMMD_HDD_IO_REGISTER(); // Set to IO Register |
765 | |
766 | #ifdef USE_LEVELSHIFTER
|
767 | mIDE_SET_OUTPUT(); |
768 | #endif // Set Levelshifter to Output
|
769 | |
770 | bptr = buffer; |
771 | for(index = 0; index < MEDIA_SECTOR_SIZE/2; index++) //Reads in 512-byte of data |
772 | {
|
773 | data = (*bptr++); |
774 | (data |= (*bptr++)<<8); |
775 | PMDIN = data; |
776 | while(PMMODEbits.BUSY); |
777 | }
|
778 | MDD_HDD_BUSY(); // Wait for data to be written |
779 | // IDE_CS1 = 1; // Deselect IDE Drive
|
780 | IDE_CS0 = 1; |
781 | //mPMPClose(); // Close to free for other functions (RAM, LCD, etc.)
|
782 | return(status); |
783 | // }
|
784 | } //end SectorWrite |
785 | |
786 | |
787 | /******************************************************************************
|
788 | * Function: BYTE MDD_HDD_WriteProtectState(void)
|
789 | *
|
790 | * PreCondition: None
|
791 | *
|
792 | * Input: None
|
793 | *
|
794 | * Output: BYTE - Returns the status of the "write enabled" pin
|
795 | *
|
796 | * Side Effects: None
|
797 | *
|
798 | * Overview: Determines if the HDD is write-protected
|
799 | *
|
800 | * Note: Here writing to the device could be prohibited
|
801 | *****************************************************************************/
|
802 | BYTE MDD_HDD_WriteProtectState(void) |
803 | {
|
804 | return(FALSE); |
805 | }
|
806 | |
807 | /******************************************************************************
|
808 | * Function: BYTE MDD_HDD_BUSY(void)
|
809 | *
|
810 | * PreCondition: None
|
811 | *
|
812 | * Input: None
|
813 | *
|
814 | * Output: BYTE
|
815 | *
|
816 | * Side Effects: Sets Levelshifter to INPUT !!!
|
817 | *
|
818 | * Overview: Determines if the HDD device is busy by checking the status register
|
819 | *
|
820 | * Note: None
|
821 | *****************************************************************************/
|
822 | BYTE MDD_HDD_BUSY(void) |
823 | {
|
824 | HDD_STATUS HDDStatus; |
825 | // TODO: TEST IF MASTER OR SLAVE
|
826 | while(PMMODEbits.BUSY); // Wait for all actions finished |
827 | #ifdef USE_LEVELSHIFTER
|
828 | mIDE_SET_INPUT(); // Set Levelshifter to Output |
829 | #endif
|
830 | mMMD_HDD_STATUS_REGISTER(); |
831 | Nop(); |
832 | PMDIN; |
833 | while(PMMODEbits.BUSY); // Dummy to flush latches |
834 | do
|
835 | {
|
836 | HDDStatus._byte = (PMDIN&0xFF); // read |
837 | while(PMMODEbits.BUSY); // Wait until PMP is free |
838 | }
|
839 | while(HDDStatus.BUSY==1); |
840 | }
|
841 | |
842 | |
843 | /******************************************************************************
|
844 | * Function: BYTE MDD_HDD_DATA_READY(void)
|
845 | *
|
846 | * PreCondition: A proper command (like READ_SECTOR) has been initiated
|
847 | *
|
848 | * Input: None
|
849 | *
|
850 | * Output: BYTE
|
851 | *
|
852 | * Side Effects: Sets Levelshifter to INPUT !!!
|
853 | *
|
854 | * Overview: Determines if the HDD device is ready for data (TX or RX)
|
855 | *
|
856 | * Note: None
|
857 | *****************************************************************************/
|
858 | BYTE MDD_HDD_DATA_READY(void) |
859 | {
|
860 | HDD_STATUS HDDStatus; |
861 | // TODO: TEST IF MASTER OR SLAVE
|
862 | //while(PMMODEbits.BUSY); // Wait for all actions finished
|
863 | #ifdef USE_LEVELSHIFTER
|
864 | mIDE_SET_INPUT(); // Set Levelshifter to Input |
865 | #endif
|
866 | mMMD_HDD_STATUS_REGISTER(); |
867 | Nop(); |
868 | PMDIN; |
869 | while(PMMODEbits.BUSY); // Dummy to flush latches |
870 | do
|
871 | {
|
872 | HDDStatus._byte = (PMDIN&0xFF); // read |
873 | while(PMMODEbits.BUSY); // Wait until PMP is free |
874 | }
|
875 | while(HDDStatus.DRQ==0 || HDDStatus.BUSY==1); |
876 | }
|
877 | |
878 | |
879 | /******************************************************************************
|
880 | * Function: BYTE MDD_HDD_DEVICE_READY(void)
|
881 | *
|
882 | * PreCondition: None
|
883 | *
|
884 | * Input: None
|
885 | *
|
886 | * Output: void
|
887 | *
|
888 | * Side Effects: Sets Levelshifter to INPUT !!!
|
889 | *
|
890 | * Overview: Determines if the HDD device has spin up
|
891 | *
|
892 | * Note: None
|
893 | *****************************************************************************/
|
894 | BYTE MDD_HDD_DEVICE_READY(void) |
895 | {
|
896 | BYTE status = TRUE; |
897 | BYTE Timeout = FALSE; |
898 | IDE_CS0 = 0; // |
899 | // IDE_CS1 = 1; // Select device
|
900 | mPMPOpen(PMP_HDD_CONTROL, PMP_HDD_MODE, PMP_HDD_PORT, PMP_HDD_INTERRUPT); |
901 | HDD_STATUS HDDStatus; |
902 | // TODO: TEST IF MASTER OR SLAVE
|
903 | while(PMMODEbits.BUSY); // Wait for all actions finished |
904 | #ifdef USE_LEVELSHIFTER
|
905 | mIDE_SET_OUTPUT(); // Set Levelshifter to Output |
906 | #endif
|
907 | |
908 | // TODO: LBA3 SETS MASTER / SLAVE !!!
|
909 | mMMD_HDD_LBA3(); // Set Device |
910 | if(IDE_DEVICE == MASTER) |
911 | PMDIN = 0x00; // DEVICE 0 |
912 | else
|
913 | PMDIN = 0x10; // DEVICE 1 |
914 | while(PMMODEbits.BUSY); |
915 | |
916 | OpenCoreTimer(0); |
917 | #ifdef USE_LEVELSHIFTER
|
918 | mIDE_SET_INPUT(); // Set Levelshifter to Output |
919 | #endif
|
920 | mMMD_HDD_STATUS_REGISTER(); |
921 | PMDIN; |
922 | while(PMMODEbits.BUSY); // Dummy to flush latches |
923 | do
|
924 | {
|
925 | HDDStatus._byte = (PMDIN&0xFF); // read |
926 | while(PMMODEbits.BUSY); // Wait until PMP is free |
927 | if(ReadCoreTimer() >= 400000000ul) |
928 | {
|
929 | Timeout = TRUE; |
930 | status = FALSE; |
931 | }
|
932 | }
|
933 | while((HDDStatus.READY==0 || HDDStatus.BUSY==1) && Timeout == FALSE); |
934 | IDE_CS0 = 1; |
935 | IDE_CS1 = 0; |
936 | MMD_HDD_DEVICE_CONTOL_REGISTER(); |
937 | #ifdef USE_LEVELSHIFTER
|
938 | mIDE_SET_OUTPUT(); // Set Levelshifter to Output |
939 | #endif
|
940 | Nop(); |
941 | PMDIN = 0x1; // INT OFF |
942 | while(PMMODEbits.BUSY); // Wait until PMP is free |
943 | IDE_CS1 = 1; |
944 | |
945 | mPMPClose(); // Close to free for other functions (RAM, LCD, etc.) |
946 | #ifdef DEBUG_MODE
|
947 | UART2PrintString("HDD DEVICE READY:\n\r"); |
948 | #endif
|
949 | return status; |
950 | }
|
Danke! Wieso sollte das unmöglich sein. Man müsste nur den Cache überlisten, und ihm sagen, welchen Sektor ich lesen oder schreiben will. Vielleicht gibts da auch irgend welche Debug modi, die man dafür verwenden kann. Kennt die jemand? Wenn das mit dem direkten Sektorlesen ohne Aussetzer geht, kann ich dann eine Kalibrierung machen, welcher Sektor zu welchem Winkel gehört. Das müsste ich eh machen. Cache überlisten ist eher das Problem... mfg Martin
Noch den HEader
1 | /******************************************************************************
|
2 | *
|
3 | * HDD Memory Disk Drive File System
|
4 | *
|
5 | ******************************************************************************
|
6 | * FileName: HDD.c
|
7 | * Dependencies: HDD.h
|
8 | * string.h
|
9 | * FSIO.h
|
10 | * FSDefs.h
|
11 | * Processor: PIC32 with PMP
|
12 | * Compiler: C32
|
13 | * Author: Stefan Dreyer
|
14 | * Version: see HDD.c
|
15 | *
|
16 | * Software License Agreement
|
17 | *
|
18 | *
|
19 | *
|
20 | * THIS SOFTWARE IS PROVIDED IN AN AS IS CONDITION. NO WARRANTIES,
|
21 | * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
|
22 | * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
23 | * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE AUTHOR SHALL NOT,
|
24 | * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
|
25 | * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
26 | *****************************************************************************/
|
27 | #ifndef HDD_H
|
28 | #define HDD_H
|
29 | |
30 | |
31 | #include "GenericTypeDefs.h" |
32 | #include "FSconfig.h" |
33 | #include "MDD File System\FSDefs.h" |
34 | |
35 | |
36 | #define MASTER 0
|
37 | #define SLAVE 1
|
38 | |
39 | #define FALSE 0
|
40 | #define TRUE !FALSE
|
41 | |
42 | #define INPUT 1
|
43 | #define OUTPUT 0
|
44 | |
45 | #define PMP_HDD_CONTROL (PMP_ON | PMP_IDLE_CON | PMP_MUX_OFF | PMP_READ_WRITE_EN | PMP_TTL |\
|
46 | PMP_CS2_CS1_OFF | PMP_WRITE_POL_LO | PMP_READ_POL_LO | PMP_LATCH_POL_HI)
|
47 | #define PMP_HDD_MODE (PMP_IRQ_OFF | PMP_AUTO_ADDR_OFF | PMP_DATA_BUS_16 | PMP_MODE_MASTER2 |\
|
48 | PMP_WAIT_BEG_4 | PMP_WAIT_MID_4 | PMP_WAIT_END_4 )
|
49 | #define PMP_HDD_PORT (PMP_PEN_OFF)
|
50 | #define PMP_HDD_INTERRUPT (PMP_INT_OFF)
|
51 | |
52 | // NOTE: MDD_HDD_InitIO() must be executed in main on INIT
|
53 | // Is now done by FSInit()
|
54 | |
55 | /***************************************************************/
|
56 | /* IDE REGISTERS */
|
57 | /***************************************************************/
|
58 | /*
|
59 | /CS0=0, /CS1=1, A2..A0=111B: command/status register. When
|
60 | written the IDE device regards the data you write to this
|
61 | register as a command. When read you get the status of the IDE
|
62 | device. Reading his register also clears any interrupts from the
|
63 | IDE device to the controller. */
|
64 | #define MMD_HDD_COMMAND_REGISTER() (IDE_A2 = 1, IDE_A1 = 1, IDE_A0 = 1)
|
65 | #define MMD_HDD_STATUS_REGISTER() (IDE_A2 = 1, IDE_A1 = 1, IDE_A0 = 1)
|
66 | |
67 | #define MMD_HDD_DEVICE_CONTOL_REGISTER() (IDE_A2 = 1, IDE_A1 = 1, IDE_A0 = 0) // CHIP SELECTS !!!
|
68 | #define mMMD_HDD_LBA0() (IDE_A2 = 0, IDE_A1 = 1, IDE_A0 = 1)
|
69 | #define mMMD_HDD_LBA1() (IDE_A2 = 1, IDE_A1 = 0, IDE_A0 = 0)
|
70 | #define mMMD_HDD_LBA2() (IDE_A2 = 1, IDE_A1 = 0, IDE_A0 = 1)
|
71 | #define mMMD_HDD_LBA3() (IDE_A2 = 1, IDE_A1 = 1, IDE_A0 = 0)
|
72 | #define mMMD_HDD_SECTOR_COUNT() (IDE_A2 = 0, IDE_A1 = 1, IDE_A0 = 0)
|
73 | #define mMMD_HDD_IO_REGISTER() (IDE_A2 = 0, IDE_A1 = 0, IDE_A0 = 0)
|
74 | #define mMMD_HDD_COMMAND_REGISTER() (IDE_A2 = 1, IDE_A1 = 1, IDE_A0 = 1)
|
75 | #define mMMD_HDD_STATUS_REGISTER() (IDE_A2 = 1, IDE_A1 = 1, IDE_A0 = 1)
|
76 | |
77 | #define mMMD_HDD_2ND_STATUS_REGISTER() (IDE_A2 = 1, IDE_A1 = 1, IDE_A0 = 0)
|
78 | |
79 | |
80 | // These functions are used to change the direction of the
|
81 | // 74LVC245A levelshifter. This levelshifter is needed if
|
82 | // other deviced are present on the PMP bus that do not
|
83 | // allow the 5V TTL levels
|
84 | #define USE_LEVELSHIFTER
|
85 | |
86 | #define mIDE_SET_OUTPUT() IDE_DIR = 1;
|
87 | #define mIDE_SET_INPUT() IDE_DIR = 0;
|
88 | |
89 | // Summary: The format of an HDD_STATUS response
|
90 | /* IDE Status Register:
|
91 | ; bit 7: Busy 1=busy, 0=not busy
|
92 | ; bit 6: Ready 1=ready for command, 0=not ready yet
|
93 | ; bit 5: DF 1=fault occured inside drive
|
94 | ; bit 4: DSC 1=seek complete
|
95 | ; bit 3: DRQ 1=data request ready, 0=not ready to xfer yet
|
96 | ; bit 2: CORR 1=correctable error occured
|
97 | ; bit 1: IDX vendor specific
|
98 | ; bit 0: ERR 1=error occured */
|
99 | |
100 | typedef union |
101 | {
|
102 | BYTE _byte; // Byte-wise access |
103 | // This structure allows bitwise access of the response
|
104 | struct
|
105 | {
|
106 | unsigned ERR:1; // 1=error occured |
107 | unsigned IDX:1; // vendor specific |
108 | unsigned CORR:1; // 1=correctable error occured |
109 | unsigned DRQ:1; // 1=data request ready, 0=not ready to xfer yet |
110 | unsigned DSC:1; // 1=seek complete |
111 | unsigned DF:1; // 1=fault occured inside drive |
112 | unsigned READY:1; // 1=ready for command, 0=not ready yet |
113 | unsigned BUSY:1; // 1=busy, 0=not busy |
114 | };
|
115 | }HDD_STATUS; |
116 | |
117 | typedef union |
118 | {
|
119 | struct
|
120 | {
|
121 | CHAR model_number[40]; |
122 | QWORD LBA_48; |
123 | };
|
124 | struct
|
125 | {
|
126 | unsigned LBA_48_SUPPORT_BIT:1; // 1= 48Bit LBA is supported |
127 | unsigned SMART:1; // 1=SMART is supported |
128 | };
|
129 | }HDD_IDENTIFY_RESPONSE; |
130 | |
131 | |
132 | |
133 | /***************************************************************/
|
134 | /* COMMANDS */
|
135 | /***************************************************************/
|
136 | |
137 | #define READ_SECTOR 0x20 // Reads Sector(s)
|
138 | #define READ_SECTOR_EXT 0x24 // Reads Sector(s) 48 Bit LBA
|
139 | #define WRITE_SECTOR 0x30 // Writes Sector(s)
|
140 | #define WRITE_SECTOR_EXT 0x34 // Writes Sector(s) 48 Bit LBA
|
141 | #define IDENTIFY_PACKET_DEVICE 0xA1 //
|
142 | #define STANDBY_IMMEDIATE 0xE0 //
|
143 | #define IDLE_IMMEDIATE 0xE1 //
|
144 | #define IDENTIFY_DEVICE 0xEC //
|
145 | #define READ_NATIVE_MAX_ADDRESS 0xF8 //
|
146 | #define READ_NATIVE_MAX_ADDRESS_EXT 0x27 //
|
147 | |
148 | |
149 | |
150 | |
151 | /* PROTOTYPES */
|
152 | /***************************************************************/
|
153 | void MDD_HDD_InitIO(void); |
154 | BYTE MDD_HDD_MediaDetect(void); |
155 | MEDIA_INFORMATION * MDD_HDD_MediaInitialize(void); |
156 | BYTE MDD_HDD_SectorRead(DWORD sector_addr, BYTE* buffer, WORD blocks); |
157 | BYTE MDD_HDD_SectorWrite(DWORD sector_addr, BYTE* buffer, BYTE allowWriteToZero); |
158 | DWORD MDD_HDD_ReadCapacity(void); |
159 | WORD MDD_HDD_ReadSectorSize(void); |
160 | BYTE MDD_HDD_WriteProtectState(void); |
161 | |
162 | #endif
|
Wichtige Regeln - erst lesen, dann posten! Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
PATA Enthusiasten! Mir ist gestern das hier über den Weg gelaufen: http://code.google.com/p/idefat-arduino/ Ist zwar kein MBED, aber das Ziel ist ja eine funktionierende HW, und ich habe grade einen Arduino Mega da rumliegen und sich langweilen. Das Kompilieren dieses Libraries macht aber beim Arduino IDE >= 1.0 Probleme. Habe da die Include "WProgram.h" auf "Arduino.h" ändern müssen in den .h Dateien, und auch der Rückgabewert der virtuellen write( ) funktionen stimmt nicht mit dem neuen gcc oder was auch immer überein, wodurch ich das auch noch ändern musste. Ausserdem passt im IDEFatUtils.h das mit dem ...Serial.print(c); nicht. das muß jetzt ...Serial.write(c); heißen. Jetzt redet wenigstens der Arduino mit mir, aber ich habe noch keine HDD dran. Mal sehen wie weit ich damit heute abend komme... mfg Martin http://www.gyurma.de
Danke fuer diese :) ich hatte meine HDD-for-microchip-PIC geschreibert und... es schaus knapp similar zu deinen. Hatte ich nun einen neue problem mit "STATUS=0xD0" manchmal... hoffe ich kann das solvieren.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.