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 | }
|