comparison src/cs/drivers/drv_app/ffs/board/drv.c @ 0:b6a5e36de839

src/cs: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:39:26 +0000
parents
children 559a8b3ef10b
comparison
equal deleted inserted replaced
-1:000000000000 0:b6a5e36de839
1 /******************************************************************************
2 * Flash File System (ffs)
3 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
4 *
5 * ffs low level flash driver
6 *
7 * $Id: drv.c 1.30.1.6.1.51.1.1.1.13.1.11 Tue, 06 Jan 2004 14:36:52 +0100 tsj $
8 *
9 ******************************************************************************/
10
11 #ifndef TARGET
12 #include "ffs.cfg"
13 #endif
14
15 #include "ffs/ffs.h"
16 #include "ffs/board/drv.h"
17 #include "ffs/board/ffstrace.h"
18
19 #if (TARGET == 0)
20
21 #ifdef WIN32
22 #include "windows.h"
23 #else //WIN32
24 #include "sys/mman.h"
25 #include "unistd.h"
26 #endif //WIN32
27
28 #include "stdio.h"
29 #include "sys/types.h"
30 #include "sys/stat.h"
31 #include "fcntl.h"
32 #else
33 #include "nucleus.h"
34
35 #endif
36
37
38 // Note that all code notes and comments pertaining to single-bank flash
39 // drivers are located in the AMD SB driver (amdsbdrv.c). Consider this as
40 // the reference.
41
42
43 /******************************************************************************
44 * Globals
45 ******************************************************************************/
46
47 #if (TARGET == 1)
48 // NOTE: This is the size in bytes of the single-bank driver code that is
49 // copied to RAM. The only way to determine the amount of memory needed is
50 // to look into the linker output file (.map) or the assembler output of
51 // both amdsbdrv.obj and intelsbdrv.obj files.
52 #define FFSDRV_CODE_SIZE (0x200)
53
54 uint8 ffsdrv_code[FFSDRV_CODE_SIZE];
55
56 #endif
57
58 #define INTEL_UNLOCK_SLOW 1
59
60 struct dev_s dev;
61 struct ffsdrv_s ffsdrv;
62
63 uint32 int_disable(void);
64 void int_enable(uint32 tmp);
65
66 /******************************************************************************
67 * Macros
68 ******************************************************************************/
69
70 #define addr2offset(address) ( (int) (address) - (int) dev.base )
71
72
73 /******************************************************************************
74 * Generic Driver Functions
75 ******************************************************************************/
76
77 void ffsdrv_generic_write(void *dst, const void *src, uint16 size)
78 {
79 uint8 *mydst = dst;
80 const uint8 *mysrc = src;
81
82 if (size > 0)
83 {
84 if ((unsigned int) mydst & 1) {
85 ffsdrv_write_byte(mydst++, *mysrc++);
86 size--;
87 }
88 while (size >= 2) {
89 ffsdrv.write_halfword((uint16 *) mydst,
90 mysrc[0] | (mysrc[1] << 8));
91 size -= 2;
92 mysrc += 2;
93 mydst += 2;
94 }
95 if (size == 1)
96 ffsdrv_write_byte(mydst++, *mysrc++);
97 }
98 }
99
100
101 /******************************************************************************
102 * AMD Single Bank Driver Functions
103 ******************************************************************************/
104
105 #if (TARGET == 1)
106
107 // Forward declaration of functions in file amdsbdrv.c
108 void ffsdrv_ram_amd_sb_write_halfword(volatile uint16 *addr, uint16 value);
109 void ffsdrv_ram_amd_sb_erase(uint8 block);
110
111 #else // (TARGET == 0)
112
113 // On PC these functions are empty
114 void ffsdrv_ram_amd_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
115 void ffsdrv_ram_amd_sb_erase(uint8 block) {}
116
117 #endif // (TARGET == 1)
118
119
120 /******************************************************************************
121 * AMD Pseudo Single Bank Driver Functions
122 ******************************************************************************/
123
124 // This is a pseudo single-bank flash driver. It simulates a single-bank
125 // flash device on a dual-bank device.
126
127 #if (TARGET == 1)
128
129 void ffsdrv_amd_pseudo_sb_write_halfword(volatile uint16 *addr, uint16 value)
130 {
131 volatile char *flash = dev.base;
132 uint32 cpsr, i, x;
133
134 ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));
135
136 if (~*addr & value) {
137 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
138 return;
139 }
140
141 cpsr = int_disable();
142 tlw(led_on(LED_WRITE));
143
144 flash[0xAAAA] = 0xAA; // unlock cycle 1
145 flash[0x5555] = 0x55; // unlock cycle 2
146 flash[0xAAAA] = 0xA0;
147 *addr = value;
148
149 while ((*dev.addr ^ dev.data) & 0x80)
150 ;
151
152 tlw(led_off(LED_WRITE));
153 int_enable(cpsr);
154 }
155
156 // This VERY simple way of erase suspending only works because we run under
157 // a pre-emptive operating system, so whenever an interrupt occurs, another
158 // task takes the CPU, and at the end of the interrupt, FFS gets the CPU
159 // again.
160 void ffsdrv_amd_pseudo_sb_erase(uint8 block)
161 {
162 volatile char *flash = dev.base;
163 volatile char *addr;
164 uint32 cpsr;
165 uint16 flashpoll;
166
167 addr = block2addr(block);
168
169 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
170
171 cpsr = int_disable();
172 tlw(led_on(LED_ERASE));
173
174 flash[0xAAAA] = 0xAA; // unlock cycle 1
175 flash[0x5555] = 0x55; // unlock cycle 2
176 flash[0xAAAA] = 0x80;
177 flash[0xAAAA] = 0xAA; // unlock cycle 1
178 flash[0x5555] = 0x55; // unlock cycle 2
179 *addr = 0x30; // AMD erase sector command
180
181 // Wait for erase to finish.
182 while ((*addr & 0x80) == 0) {
183 tlw(led_toggle(LED_ERASE));
184 // Poll interrupts, taking interrupt mask into account.
185 if (INT_REQUESTED)
186 {
187 // 1. suspend erase
188 // 2. enable interrupts
189 // .. now the interrupt code executes
190 // 3. disable interrupts
191 // 4. resume erase
192
193 tlw(led_on(LED_ERASE_SUSPEND));
194 *addr = 0xB0;
195
196 // wait for erase suspend to finish
197 while ((*addr & 0x80) == 0)
198 ;
199
200 tlw(led_off(LED_ERASE_SUSPEND));
201 int_enable(cpsr);
202
203 // Other interrupts and tasks run now...
204
205 cpsr = int_disable();
206 tlw(led_on(LED_ERASE_SUSPEND));
207
208 // Before resuming erase we must? check if the erase is really
209 // suspended or if it did finish
210 flashpoll = *addr;
211 *addr = 0x30;
212
213 tlw(led_off(LED_ERASE_SUSPEND));
214 }
215 }
216
217 tlw(led_on(LED_ERASE));
218 tlw(led_off(LED_ERASE));
219 int_enable(cpsr);
220 }
221
222 #else // (TARGET == 0)
223
224 void ffsdrv_amd_pseudo_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
225 void ffsdrv_amd_pseudo_sb_erase(uint8 block) {}
226
227 #endif // (TARGET == 1)
228
229
230 /******************************************************************************
231 * AMD Dual/Multi Bank Driver Functions
232 ******************************************************************************/
233
234 // All erase and write operations are performed atomically (interrupts
235 // disabled). Otherwise we cannot trust the value of dev.state and we cannot
236 // determine exactly how many of the command words have already been
237 // written.
238
239 // in ffs_end() when we resume an erasure that was previously suspended, how
240 // does that affect multiple tasks doing that simultaneously?
241
242 void ffsdrv_amd_write_end(void);
243 void ffsdrv_amd_erase_end(void);
244
245 void ffsdrv_amd_write_halfword(volatile uint16 *addr, uint16 value)
246 {
247 volatile uint16 *flash = (volatile uint16 *)dev.base;
248 uint32 cpsr;
249
250 tlw(led_on(LED_WRITE));
251 ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));
252
253 dev.addr = addr;
254 dev.data = value;
255
256 if (~*addr & value) {
257 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
258 return;
259 }
260
261 cpsr = int_disable();
262 tlw(led_toggle(LED_WRITE_SUSPEND));
263 dev.state = DEV_WRITE;
264 flash[0x555] = 0xAA; // unlock cycle 1
265 flash[0x2AA] = 0x55; // unlock cycle 2
266 flash[0x555] = 0xA0;
267 *addr = value;
268 int_enable(cpsr);
269 tlw(led_toggle(LED_WRITE_SUSPEND));
270
271 ffsdrv_amd_write_end();
272 }
273
274 void ffsdrv_amd_write(void *dst, const void *src, uint16 size)
275 {
276 uint8 *mydst = dst;
277 const uint8 *mysrc = src;
278
279 if (size > 0)
280 {
281 if ((unsigned int) mydst & 1) {
282 ffsdrv_write_byte(mydst++, *mysrc++);
283 size--;
284 }
285 while (size >= 2) {
286 ffsdrv_amd_write_halfword((uint16 *) mydst,
287 mysrc[0] | (mysrc[1] << 8));
288 size -= 2;
289 mysrc += 2;
290 mydst += 2;
291 }
292 if (size == 1)
293 ffsdrv_write_byte(mydst++, *mysrc++);
294 }
295 }
296
297 void ffsdrv_amd_write_end(void)
298 {
299 while ((*dev.addr ^ dev.data) & 0x80)
300 tlw(led_toggle(LED_WRITE_SUSPEND));
301
302 dev.state = DEV_READ;
303
304 tlw(led_off(LED_WRITE));
305 }
306
307 void ffsdrv_amd_erase(uint8 block)
308 {
309 volatile uint16 *flash = (volatile uint16 *)dev.base;
310 uint32 cpsr;
311
312 tlw(led_on(LED_ERASE));
313 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
314
315 dev.addr = (uint16 *) block2addr(block);
316
317 cpsr = int_disable();
318 dev.state = DEV_ERASE;
319 flash[0x555] = 0xAA; // unlock cycle 1
320 flash[0x2AA] = 0x55; // unlock cycle 2
321 flash[0x555] = 0x80;
322 flash[0x555] = 0xAA; // unlock cycle 1
323 flash[0x2AA] = 0x55; // unlock cycle 2
324 *dev.addr = 0x30; // AMD erase sector command
325 int_enable(cpsr);
326
327 ffsdrv_amd_erase_end();
328 }
329
330 void ffsdrv_amd_erase_end(void)
331 {
332 while ((*dev.addr & 0x80) == 0)
333 ;
334
335 dev.state = DEV_READ;
336
337 tlw(led_off(LED_ERASE));
338 }
339
340 void ffsdrv_amd_erase_suspend(void)
341 {
342 uint32 cpsr;
343
344 tlw(led_on(LED_ERASE_SUSPEND));
345 ttw(str(TTrDrvErase, "es" NL));
346
347 // if erase has finished then all is ok
348 if (*dev.addr & 0x80) {
349 ffsdrv_amd_erase_end();
350 tlw(led_off(LED_ERASE_SUSPEND));
351 return;
352 }
353
354 // NOTEME: As there is no way to be absolutely certain that erase
355 // doesn't finish between last poll and the following erase suspend
356 // command, we assume that the erase suspend is safe even though the
357 // erase IS actually already finished.
358
359 cpsr = int_disable();
360 dev.state = DEV_ERASE_SUSPEND;
361 *dev.addr = 0xB0;
362
363 // Wait for erase suspend to finish
364 while ((*dev.addr & 0x80) == 0)
365 ;
366
367 int_enable(cpsr);
368 }
369
370 void ffsdrv_amd_erase_resume(void)
371 {
372 uint32 cpsr;
373
374 ttw(str(TTrDrvErase, "er" NL));
375
376 // NOTEME: See note in erase_suspend()... We assume that the erase
377 // resume is safe even though the erase IS actually already finished.
378 cpsr = int_disable();
379 dev.state = DEV_ERASE;
380 *dev.addr = 0x30;
381 int_enable(cpsr);
382
383 tlw(led_off(LED_ERASE_SUSPEND));
384 }
385
386
387 /******************************************************************************
388 * SST Dual/Multi Bank Driver Functions
389 ******************************************************************************/
390
391 // SST flashes use almost same command set as AMD flashes. Only the command
392 // addresses (4 more bits) and erase command data (0x50 instead of 0x30) are
393 // different. SST flashes have no erase suspend/resume commands because they
394 // are so fast at erasing!
395
396 void ffsdrv_sst_write_end(void);
397 void ffsdrv_sst_erase_end(void);
398
399 void ffsdrv_sst_write(void *dst, const void *src, uint16 size)
400 {
401 uint8 *mydst = dst;
402 const uint8 *mysrc = src;
403
404 if (size > 0)
405 {
406 if ((unsigned int) mydst & 1) {
407 ffsdrv_write_byte(mydst++, *mysrc++);
408 size--;
409 }
410 while (size >= 2) {
411 ffsdrv_amd_write_halfword((uint16 *) mydst,
412 mysrc[0] | (mysrc[1] << 8));
413 size -= 2;
414 mysrc += 2;
415 mydst += 2;
416 }
417 if (size == 1)
418 ffsdrv_write_byte(mydst++, *mysrc++);
419 }
420 }
421
422 // Note that SST flashes have smaller sectors than other flash families.
423 // Fortunately they support erasure of several of these sectors in a logical
424 // unit called a "block".
425 void ffsdrv_sst_erase(uint8 block)
426 {
427 volatile char *flash = dev.base;
428 uint32 cpsr;
429
430 tlw(led_on(LED_ERASE));
431 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
432
433 dev.addr = (uint16 *) block2addr(block);
434
435 cpsr = int_disable();
436 dev.state = DEV_ERASE;
437 flash[0xAAAA] = 0xAA; // unlock cycle 1
438 flash[0x5555] = 0x55; // unlock cycle 2
439 flash[0xAAAA] = 0x80;
440 flash[0xAAAA] = 0xAA; // unlock cycle 1
441 flash[0x5555] = 0x55; // unlock cycle 2
442 *dev.addr = 0x50; // SST erase block command
443 int_enable(cpsr);
444
445 ffsdrv_sst_erase_end();
446 }
447
448 void ffsdrv_sst_erase_end(void)
449 {
450 // Wait for erase end
451 while ((*dev.addr & 0x80) == 0)
452 ;
453
454 dev.state = DEV_READ;
455
456 tlw(led_off(LED_ERASE));
457 }
458
459 // Erase suspend/resume commands do not exist for SST flashes, so we just
460 // poll for the end of the erase operation...
461
462 void ffsdrv_sst_erase_suspend(void)
463 {
464 ttw(str(TTrDrvErase, "es" NL));
465
466 ffsdrv_sst_erase_end();
467 }
468
469
470 /******************************************************************************
471 * Intel Single Bank Driver Functions
472 ******************************************************************************/
473
474 #if (TARGET == 1)
475
476 // Forward declaration of functions in file intelsbdrv.c
477 int ffsdrv_ram_intel_sb_init(void);
478 void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value);
479 void ffsdrv_ram_intel_sb_erase(uint8 block);
480 void ffsdrv_ram_intel_erase(uint8 block);
481
482 #else // (TARGET == 0)
483
484 // On PC these functions are empty
485 void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
486 void ffsdrv_ram_intel_sb_erase(uint8 block) {}
487 void ffsdrv_ram_intel_erase(uint8 block) {}
488
489 #endif // (TARGET == 1)
490
491
492 /******************************************************************************
493 * Intel Dual/Multi Bank Driver Functions
494 ******************************************************************************/
495
496 void ffsdrv_intel_write_end(void);
497 void ffsdrv_intel_erase_end(void);
498
499
500 // ffsdrv_intel_write_halfword and ffsdrv_intel_write_end is not used
501 // because of the bug in the intel flash device. Instead is the functions
502 // ffsdrv_ram_intel_sb_write_halfword and ffsdrv_ram_intel_erase used.
503 void ffsdrv_intel_write_halfword(volatile uint16 *addr, uint16 value)
504 {
505 uint32 cpsr;
506
507 tlw(led_on(LED_WRITE));
508 ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));
509
510 dev.addr = addr;
511
512 if (~*addr & value) {
513 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
514 return;
515 }
516
517 cpsr = int_disable();
518 dev.state = DEV_WRITE;
519
520 #if (INTEL_UNLOCK_SLOW == 1)
521 *addr = 0x60; // Intel Config setup
522 *addr = 0xD0; // Intel Unlock block
523 *addr = 0x50; // Intel Clear Status Register
524 #endif
525
526 *addr = 0x40; // Intel program byte/word
527 *addr = value;
528
529 int_enable(cpsr);
530
531 ffsdrv_intel_write_end();
532 }
533
534 void ffsdrv_intel_write(void *dst, const void *src, uint16 size)
535 {
536 uint8 *mydst = dst;
537 const uint8 *mysrc = src;
538
539 if (size > 0)
540 {
541 if ((unsigned int) mydst & 1) {
542 ffsdrv_write_byte(mydst++, *mysrc++);
543 size--;
544 }
545 while (size >= 2) {
546 ffsdrv_intel_write_halfword((uint16 *) mydst,
547 mysrc[0] | (mysrc[1] << 8));
548 size -= 2;
549 mysrc += 2;
550 mydst += 2;
551 }
552 if (size == 1)
553 ffsdrv_write_byte(mydst++, *mysrc++);
554 }
555 }
556
557 void ffsdrv_intel_write_end(void)
558 {
559 uint32 cpsr;
560 // We can be interrupted and reentered thus the state can have been changed.
561 while ((*dev.addr & 0x80) == 0 && dev.state == DEV_WRITE)
562 ;
563
564 // The flash state and dev.state must be in sync thus the stat changes
565 // must be protect from being interrupted
566 cpsr = int_disable();
567 *dev.addr = 0xFF; // Intel read array
568 dev.state = DEV_READ;
569 int_enable(cpsr);
570
571 tlw(led_off(LED_WRITE));
572 }
573
574
575 void ffsdrv_intel_erase(uint8 block)
576 {
577 uint32 cpsr;
578
579 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
580 tlw(led_on(LED_ERASE));
581
582 dev.addr = (uint16 *) block2addr(block);
583
584 cpsr = int_disable();
585 dev.state = DEV_ERASE;
586
587 #if (INTEL_UNLOCK_SLOW == 1)
588 *dev.addr = 0x60; // Intel Config setup
589 *dev.addr = 0xD0; // Intel Unlock block
590 #endif
591
592 *dev.addr = 0x50; // Intel clear status register (not really necessary)
593 *dev.addr = 0x20; // Intel erase setup
594 *dev.addr = 0xD0; // Intel erase confirm
595
596 int_enable(cpsr);
597
598 ffsdrv_intel_erase_end();
599 }
600
601 void ffsdrv_intel_erase_end(void)
602 {
603 while ((*dev.addr & 0x80) == 0 && dev.state == DEV_ERASE)
604 ;
605
606 *dev.addr = 0xFF; // Intel read array
607
608 dev.state = DEV_READ;
609 tlw(led_off(LED_ERASE));
610 }
611
612 void ffsdrv_intel_erase_suspend(void)
613 {
614 uint32 cpsr;
615 uint16 poll;
616
617 ttw(str(TTrDrvErase, "es" NL));
618 tlw(led_on(LED_ERASE_SUSPEND));
619
620 cpsr = int_disable();
621 dev.state = DEV_ERASE_SUSPEND;
622 *dev.addr = 0xB0; // Intel Erase Suspend
623 *dev.addr = 0x70; // Intel Read Status Register
624 while (((poll = *dev.addr) & 0x80) == 0)
625 ;
626
627 if ((poll & 0x40) == 0) {
628 // Block erase has completed
629 tlw(led_off(LED_ERASE_SUSPEND));
630 dev.state = DEV_READ;
631 tlw(led_off(LED_ERASE));
632 }
633 *dev.addr = 0xFF; // Intel read array
634 int_enable(cpsr);
635 }
636
637 void ffsdrv_intel_erase_resume(void)
638 {
639 uint32 cpsr;
640
641 ttw(str(TTrDrvErase, "er" NL));
642
643 cpsr = int_disable();
644 dev.state = DEV_ERASE;
645 *dev.addr = 0xD0; // Intel erase resume
646
647 // The following "extra" Read Status command is required because Intel
648 // has changed the specification of the W30 flash! (See "1.8 Volt Intel®
649 // Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30,
650 // 28F320W30 Specification Update")
651 *dev.addr = 0x70; // Intel Read Status Register
652
653 int_enable(cpsr);
654
655 tlw(led_off(LED_ERASE_SUSPEND));
656 }
657
658
659 /******************************************************************************
660 * RAM Family Functions
661 ******************************************************************************/
662
663 void ffsdrv_ram_write_halfword(volatile uint16 *dst, uint16 value)
664 {
665 *dst = value;
666 }
667
668 void ffsdrv_ram_write(void *dst, const void *src, uint16 size)
669 {
670 uint8 *mydst = dst;
671 const uint8 *mysrc = src;
672
673 if (size == 0)
674 return;
675 else if (size == 1)
676 ffsdrv_write_byte(mydst, *mysrc);
677 else {
678 if ((int) mydst & 1) {
679 ffsdrv_write_byte(mydst++, *mysrc++);
680 size--;
681 }
682 while (size >= 2) {
683 ffsdrv_ram_write_halfword((uint16 *) mydst, mysrc[0]|(mysrc[1] << 8));
684 size -= 2;
685 mysrc += 2;
686 mydst += 2;
687 }
688 if (size == 1)
689 ffsdrv_write_byte(mydst++, *mysrc++);
690 }
691 }
692
693 void ffsdrv_ram_erase(uint8 block)
694 {
695 int i;
696 char *addr;
697
698 addr = block2addr(block);
699
700 for (i = 0; i < (1 << dev.binfo[block].size_ld); i++) {
701 *addr++ = 0xFF;
702 }
703 }
704
705 /******************************************************************************
706 * Void Functions
707 ******************************************************************************/
708
709 int ffsdrv_null_init(void)
710 {
711 ttw(ttr(TTrDrvOther, "ffsdrv_null_init()" NL));
712
713 return 0;
714 }
715
716 void ffsdrv_null_erase(uint8 block)
717 {
718 ttw(ttr(TTrDrvErase, "ffsdrv_null_erase(%d)" NL, block));
719 }
720
721 void ffsdrv_null_write_halfword(volatile uint16 *addr, uint16 value)
722 {
723 ttw(ttr(TTrDrvWrite, "ffsdrv_null_write_halfword(0x%x, 0x%x)" NL, addr, value));
724 }
725
726 void ffsdrv_null_write(void *dst, const void *src, uint16 size)
727 {
728 ttw(ttr(TTrDrvWrite, "ffsdrv_null_write(0x%x, 0x%x, %d)" NL, dst, src, size));
729 }
730
731 void ffsdrv_null_erase_suspend(void)
732 {
733 ttw(str(TTrDrvErase, "ffsdrv_null_erase_suspend()" NL));
734 }
735
736 void ffsdrv_null_erase_resume(void)
737 {
738 ttw(str(TTrDrvErase, "ffsdrv_null_erase_resume()" NL));
739 }
740
741 void ffsdrv_null_write_end(void)
742 {
743 ttw(str(TTrDrvWrite, "ffsdrv_null_write_end()" NL));
744 }
745
746 void ffsdrv_null_erase_end(void)
747 {
748 ttw(str(TTrDrvErase, "ffsdrv_null_erase_end()" NL));
749 }
750
751
752 /******************************************************************************
753 * Test Driver Functions
754 ******************************************************************************/
755
756 #if (TARGET == 0)
757
758 static char *image_addr = 0;
759 static int image_size = 0;
760 #ifdef WIN32
761 HANDLE image_fd, map_fd;
762 #else //WIN32
763 static int image_fd = 0;
764 #endif //WIN32
765
766 extern int arg_removeimage;
767 extern char *arg_imagename;
768
769 extern void test_fatal_printf(char *format, ...);
770
771 void ffsdrv_write_check(char *addr, int size)
772 {
773 offset_t offset, last;
774
775 offset = addr2offset(addr);
776 last = dev.binfo[dev.numblocks-1].offset
777 + (1 << dev.binfo[dev.numblocks-1].size_ld);
778
779 if (offset < 0 || (offset + size) > last) {
780 fprintf(stderr, "ffsdrv_write_check() failed (addr = 0x%x, size = %d)\n",
781 (int) addr, size);
782 fprintf(stdout, "ffsdrv_write_check() failed (addr = 0x%x, size = %d)\n",
783 (int) addr, size);
784 exit (1);
785 }
786 }
787
788
789 void ffsdrv_write_error(uint16 old, uint16 new)
790 {
791 test_fatal_printf("FATAL: Attempt to rewrite 0 to 1 bit "
792 "(old:0x%x/%c new:0x%x/%c)\n",
793 old, (old < ' ' ? '?' : old),
794 new, (new < ' ' ? '?' : new));
795 }
796
797 void ffsdrv_test_write_halfword(volatile uint16 *addr, uint16 value)
798 {
799 tw(tr(TR_FUNC, TrDrvWrite, "test_write_halfword(0x%05x, 0x%x)\n",
800 addr2offset(addr), value));
801
802 ffsdrv_write_check((uint8 *) addr, 2);
803
804 if (~*addr & value)
805 ffsdrv_write_error(*addr, value);
806
807 *addr = value;
808 }
809
810 void ffsdrv_test_write(void *dst, const void *src, uint16 size)
811 {
812 uint8 *mydst = dst;
813 const uint8 *mysrc = src;
814
815 tw(tr(TR_FUNC, TrDrvWrite, "test_write(0x%05x, 0x%x, %d)\n",
816 addr2offset(mydst), mysrc, size));
817
818 if (size > 0)
819 {
820 if ((int) mydst & 1) {
821 ffsdrv_write_byte(mydst++, *mysrc++);
822 size--;
823 }
824 while (size >= 2) {
825 ffsdrv_test_write_halfword((uint16 *) mydst, mysrc[0]|(mysrc[1] << 8));
826 size -= 2;
827 mysrc += 2;
828 mydst += 2;
829 }
830 if (size == 1)
831 ffsdrv_write_byte(mydst++, *mysrc++);
832 }
833 }
834
835 void ffsdrv_test_erase(uint8 block)
836 {
837 int i;
838 uint8 *addr;
839
840 addr = block2addr(block);
841
842 tw(tr(TR_FUNC, TrDrvErase, "ffsdrv_test_erase(%d)\n", block));
843
844 for (i = 0; i < 1 << dev.binfo[block].size_ld; i++) {
845 *addr++ = 0xFF;
846 }
847 }
848
849 char *ffsdrv_test_create(void)
850 {
851 // If flash image file already exists, open the file, and mmap it.
852 // Otherwise, create file, fill file with 1's, then mmap it.
853
854 int i;
855 struct stat statbuf;
856 #ifdef WIN32
857 OFSTRUCT lpReOpenBuff;
858 DWORD last_error;
859 SECURITY_ATTRIBUTES lpAttributes;
860
861 lpAttributes.nLength = sizeof (lpAttributes);
862 lpAttributes.lpSecurityDescriptor = NULL;
863 lpAttributes.bInheritHandle = TRUE;
864 #endif
865 image_size = (int) dev.binfo[dev.numblocks - 1].offset +
866 (1 << dev.binfo[dev.numblocks - 1].size_ld);
867
868 tw(tr(TR_BEGIN, TrDrvInit, "ffsdrv_test_create() {\n"));
869 tw(tr(TR_FUNC, TrDrvInit, "%s image: '%s', size = %d\n",
870 arg_removeimage ? "new" : "current", arg_imagename, image_size));
871
872 // create file if it does not exist
873 #ifdef WIN32
874 if( arg_removeimage || OpenFile( arg_imagename, &lpReOpenBuff, OF_EXIST) == HFILE_ERROR )
875 #else
876 if (arg_removeimage || lstat(arg_imagename, &statbuf) == -1)
877 #endif
878 {
879 char data[64];
880 #ifdef WIN32
881 DWORD bwritten;
882 #endif
883 // only the first run should remove the flash image file
884 arg_removeimage = 0;
885
886 tw(tr(TR_FUNC, TrDrvInit, "creating new flash image file '%s'\n",
887 arg_imagename));
888 #ifdef WIN32
889 image_fd = CreateFile(arg_imagename,
890 GENERIC_WRITE | GENERIC_READ,
891 0,
892 NULL,
893 OPEN_ALWAYS,
894 FILE_ATTRIBUTE_NORMAL,
895 NULL );
896 #else
897 image_fd = open(arg_imagename , O_RDWR|O_CREAT,
898 (S_IRWXU & ~S_IXUSR) |
899 ( S_IRWXG & ~S_IXGRP) | (S_IRWXO & ~S_IXOTH));
900 #endif
901 if (image_fd == -1) {
902 perror("Failed to create flash image");
903 exit(1);
904 }
905
906 // write 1's to the file.
907 for (i = 0; i < 64; i++)
908 data[i] = 0xff;
909
910 #ifdef WIN32
911 for (i = 0; i < image_size/64; i++)
912 WriteFile(image_fd, data, 64, &bwritten, NULL);
913 CloseHandle(image_fd);
914 #else
915 for (i = 0; i < image_size/64; i++)
916 write(image_fd, data, 64);
917
918 close(image_fd);
919 #endif
920 image_fd = 0;
921 tw(tr(TR_FUNC, TrDrvInit, "flash image file created\n"));
922 }
923
924 // only open image file if this is the first initialization.
925 if (image_fd > 0) {
926 tw(tr(TR_FUNC, TrDrvInit, "re-opening '%s' file of size %d\n",
927 arg_imagename, image_size));
928 }
929 else {
930 tw(tr(TR_FUNC, TrDrvInit, "opening '%s' file of size %d\n",
931 arg_imagename, image_size));
932
933 #ifdef WIN32
934 image_fd = OpenFile( arg_imagename, &lpReOpenBuff, OF_READWRITE);
935 map_fd = CreateFileMapping (image_fd,
936 &lpAttributes,
937 PAGE_READWRITE,
938 0,
939 0,
940 arg_imagename);
941 #else
942 image_fd = open(arg_imagename, O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
943 #endif
944 if (image_fd == -1) {
945 perror("Failed to open flash image");
946 exit(1);
947 }
948
949 // memory map the file and update block addresses of binfo array
950 #ifdef WIN32
951 image_addr = MapViewOfFile( map_fd,
952 FILE_MAP_ALL_ACCESS,
953 0,
954 0,
955 0);
956 #else
957 image_addr = mmap(0, image_size, PROT_READ|PROT_WRITE,
958 MAP_FILE|MAP_SHARED, image_fd, 0);
959 #endif
960 }
961
962 tw(tr(TR_END, TrDrvInit, "}\n"));
963
964 return image_addr;
965 }
966
967 #endif // (TARGET == 0)
968
969
970 /******************************************************************************
971 * Device Detection and Copying of Driver to RAM
972 ******************************************************************************/
973
974 #if (TARGET == 1)
975
976 // Note that this function reads device code of any of the three known flash
977 // families; Intel, AMD and SST. This works because Intel and AMD use
978 // the same command data for entering READ_IDENTIFIER mode (0x90).
979 // The function should be copied and executed from RAM!
980 void ffsdrv_device_id_read(uint16 *manufact, uint16 *device)
981 {
982 int addr, i;
983
984 // This silly looking code has one purpose; to set addr = 0xAAAA. It is
985 // necessary in order to force the compiler NOT to produce code that
986 // uses LDR opcode(s) with PC-relative addressing. The assember code
987 // produced from this C code is completely relocatable!
988 for (i = 0, addr = 0; i < 2; i++)
989 addr |= addr << 8 | 0xAA;
990
991 FLASH_WRITE_HALFWORD (addr, 0xAA);
992 FLASH_WRITE_HALFWORD (addr >> 1, 0x55);
993 FLASH_WRITE_HALFWORD (addr, 0x90); // Intel/AMD read id command
994
995 *manufact = FLASH_READ_HALFWORD (0); // flash a0 = 0
996 *device = FLASH_READ_HALFWORD (2); // flash a0 = 1
997
998 // Read extended id
999 device[1] = FLASH_READ_HALFWORD (0xE << 1);
1000 device[2] = FLASH_READ_HALFWORD (0xF << 1);
1001 FLASH_WRITE_HALFWORD (0, 0xFF); // Intel read-array command
1002
1003 // AMD devices do not need the two unlock cycles but SST devices do,
1004 // even though the SST datasheets states otherwise ;-)
1005 FLASH_WRITE_HALFWORD (addr, 0xAA);
1006 FLASH_WRITE_HALFWORD (addr >> 1, 0x55);
1007 FLASH_WRITE_HALFWORD (addr, 0xF0); // AMD read-array/reset command
1008 }
1009
1010 // Copy ffsdrv_device_id_read() function code to RAM. The only known way to
1011 // determine the size of the code is to look either in the linker-generated
1012 // map file or in the assember output file.
1013 void ffsdrv_device_id_read_copy_to_ram(uint16 *dst, int size)
1014 {
1015 uint16 *src = (uint16 *) &ffsdrv_device_id_read;
1016
1017 // The ARM7TDMI compiler sets bit 0 for thumb mode function pointers, so
1018 // we need to clear this in order to copy *all* bytes. Otherwise we
1019 // exclude first byte and the resulting copy becomes garbage
1020 src = (uint16 *) (~1 & (int) src);
1021 size /= 2;
1022
1023 while (size--)
1024 *dst++ = *src++;
1025 }
1026
1027 // Copy ffsdrv_xxx_sb_erase() and ffsdrv_xxx_sb_write_halfword() functions
1028 // to RAM. The only known way to determine the size of the code is to look
1029 // either in the linker-generated map file or in the assember output file.
1030 int ffsdrv_driver_copy_to_ram(int type)
1031 {
1032 int size;
1033 uint16 *src, *dst;
1034 extern uint16 ffsdrv_ram_amd_begin[];
1035 extern uint16 ffsdrv_ram_intel_begin[];
1036 uint32 offset_of_init;
1037 uint32 offset_of_erase;
1038 uint32 offset_of_write_halfword;
1039
1040 ttw(ttr(TTrDrvOther, "ffsdrv_driver_copy_to_ram() {" NL));
1041
1042 switch (type) {
1043 case FFS_DRIVER_AMD:
1044 case FFS_DRIVER_AMD_SB:
1045 src = ffsdrv_ram_amd_begin;
1046 offset_of_erase =
1047 (uint32) ffsdrv_ram_amd_sb_erase - (uint32) src;
1048 offset_of_write_halfword =
1049 (uint32) ffsdrv_ram_amd_sb_write_halfword - (uint32) src;
1050 break;
1051 case FFS_DRIVER_INTEL_SB:
1052 src = ffsdrv_ram_intel_begin;
1053 offset_of_init =
1054 (uint32) ffsdrv_ram_intel_sb_init - (uint32) src;
1055 offset_of_erase =
1056 (uint32) ffsdrv_ram_intel_sb_erase - (uint32) src;
1057 offset_of_write_halfword =
1058 (uint32) ffsdrv_ram_intel_sb_write_halfword - (uint32) src;
1059 break;
1060 case FFS_DRIVER_INTEL:
1061 src = ffsdrv_ram_intel_begin;
1062 offset_of_init =
1063 (uint32) ffsdrv_ram_intel_sb_init - (uint32) src;
1064 offset_of_erase =
1065 (uint32) ffsdrv_ram_intel_erase - (uint32) src;
1066 offset_of_write_halfword =
1067 (uint32) ffsdrv_ram_intel_sb_write_halfword - (uint32) src;
1068 break;
1069 default:
1070 ttw(ttr(TTrDrvOther, "}" NL));
1071 return 0;
1072 }
1073
1074 // Make sure we are handling a half-word aligned address (Thumb mode
1075 // function pointers have lsb set!)
1076 src = (uint16 *) (~1 & (int) src);
1077
1078 // If we detect that the linker allocated the driver to RUN in RAM, the
1079 // user has obviously NOT removed those linker lines and we bail out!
1080 if (offset_of_erase > FFSDRV_CODE_SIZE)
1081 return EFFS_DRIVER;
1082
1083 dst = (uint16 *) &ffsdrv_code;
1084
1085 // Code size in halfwords
1086 size = FFSDRV_CODE_SIZE / 2;
1087
1088 // Rebind the two changed driver functions
1089 if (type == FFS_DRIVER_AMD_SB || type == FFS_DRIVER_INTEL_SB) {
1090 ffsdrv.erase =
1091 (void (*)(uint8))
1092 (offset_of_erase + (uint32) dst);
1093 ffsdrv.write_halfword =
1094 (void (*)(volatile uint16 *, uint16))
1095 (offset_of_write_halfword + (uint32) dst);
1096 }
1097 if (type == FFS_DRIVER_INTEL_SB) {
1098 ffsdrv.init =
1099 (int (*)(void))
1100 (offset_of_init + (uint32) dst);
1101 }
1102
1103 ttw(ttr(TTrDrvOther, "ffsdrv_code, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
1104 dst, (uint32) ffsdrv.init,
1105 (uint32) ffsdrv.write_halfword, (uint32) ffsdrv.erase));
1106
1107 ttw(ttr(TTrDrvOther, "amd_begin, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
1108 ffsdrv_ram_amd_begin, ffsdrv_null_init,
1109 ffsdrv_ram_amd_sb_write_halfword, ffsdrv_ram_amd_sb_erase));
1110
1111 ttw(ttr(TTrDrvOther, "intel_begin, init, write, erase = 0x%07x, 0x%07x, 0x%07x, 0x%07x" NL,
1112 ffsdrv_ram_intel_begin, ffsdrv_ram_intel_sb_init,
1113 ffsdrv_ram_intel_sb_write_halfword, ffsdrv_ram_intel_sb_erase));
1114
1115 // Copy the code to RAM
1116 while (size--)
1117 *dst++ = *src++;
1118
1119 ttw(ttr(TTrDrvOther, "}" NL));
1120
1121 return 0;
1122 }
1123
1124 #else // (TARGET == 0)
1125
1126 void ffsdrv_device_id_read(uint16 *manufact, uint16 *device) {}
1127 int ffsdrv_driver_copy_to_ram(int type) { return 0; }
1128
1129 #endif // (TARGET == 1)
1130
1131
1132 /******************************************************************************
1133 * Initialization
1134 ******************************************************************************/
1135
1136 const struct ffsdrv_s ffsdrv_amd = {
1137 ffsdrv_null_init,
1138 ffsdrv_amd_erase,
1139 ffsdrv_amd_write_halfword,
1140 ffsdrv_amd_write,
1141 ffsdrv_amd_write_end,
1142 ffsdrv_amd_erase_suspend,
1143 ffsdrv_amd_erase_resume
1144 };
1145
1146 const struct ffsdrv_s ffsdrv_amd_sb = {
1147 ffsdrv_null_init,
1148 ffsdrv_ram_amd_sb_erase,
1149 ffsdrv_ram_amd_sb_write_halfword,
1150 ffsdrv_generic_write,
1151 ffsdrv_null_write_end,
1152 ffsdrv_null_erase_suspend,
1153 ffsdrv_null_erase_resume
1154 };
1155
1156 const struct ffsdrv_s ffsdrv_sst = {
1157 ffsdrv_null_init,
1158 ffsdrv_sst_erase,
1159 ffsdrv_amd_write_halfword, // Use AMD driver function
1160 ffsdrv_sst_write,
1161 ffsdrv_amd_write_end, // Use AMD driver function
1162 ffsdrv_sst_erase_suspend,
1163 ffsdrv_null_erase_resume
1164 };
1165
1166 const struct ffsdrv_s ffsdrv_sst_sb = {
1167 ffsdrv_null_init,
1168 ffsdrv_null_erase,
1169 ffsdrv_null_write_halfword,
1170 ffsdrv_null_write,
1171 ffsdrv_null_write_end,
1172 ffsdrv_null_erase_suspend,
1173 ffsdrv_null_erase_resume
1174 };
1175
1176 // We use the functions ffsdrv_ram_intel_sb_write_halfword and
1177 // ffsdrv_ram_intel_erase due to the bug in the intel wireless flash
1178 // device. See 28F640W30.pdf specification Errata 5.
1179 const struct ffsdrv_s ffsdrv_intel = {
1180 ffsdrv_null_init,
1181 ffsdrv_intel_erase,
1182 ffsdrv_intel_write_halfword,
1183 ffsdrv_generic_write,
1184 ffsdrv_intel_write_end,
1185 ffsdrv_intel_erase_suspend,
1186 ffsdrv_intel_erase_resume
1187 };
1188
1189 const struct ffsdrv_s ffsdrv_intel_sb = {
1190 ffsdrv_null_init,
1191 ffsdrv_ram_intel_sb_erase,
1192 ffsdrv_ram_intel_sb_write_halfword,
1193 ffsdrv_generic_write,
1194 ffsdrv_null_write_end,
1195 ffsdrv_null_erase_suspend,
1196 ffsdrv_null_erase_resume
1197 };
1198
1199 const struct ffsdrv_s ffsdrv_null = {
1200 ffsdrv_null_init,
1201 ffsdrv_null_erase,
1202 ffsdrv_null_write_halfword,
1203 ffsdrv_null_write,
1204 ffsdrv_null_write_end,
1205 ffsdrv_null_erase_suspend,
1206 ffsdrv_null_erase_resume
1207 };
1208
1209 const struct ffsdrv_s ffsdrv_amd_pseudo_sb = {
1210 ffsdrv_null_init,
1211 ffsdrv_amd_pseudo_sb_erase,
1212 ffsdrv_amd_pseudo_sb_write_halfword,
1213 ffsdrv_generic_write,
1214 ffsdrv_null_write_end,
1215 ffsdrv_null_erase_suspend,
1216 ffsdrv_null_erase_resume
1217 };
1218
1219 const struct ffsdrv_s ffsdrv_ram = {
1220 ffsdrv_null_init,
1221 ffsdrv_ram_erase,
1222 ffsdrv_ram_write_halfword,
1223 ffsdrv_ram_write,
1224 ffsdrv_null_write_end,
1225 ffsdrv_null_erase_suspend,
1226 ffsdrv_null_erase_resume
1227 };
1228
1229 #if (TARGET == 0)
1230 const struct ffsdrv_s ffsdrv_test = {
1231 ffsdrv_null_init,
1232 ffsdrv_test_erase,
1233 ffsdrv_test_write_halfword,
1234 ffsdrv_test_write,
1235 ffsdrv_null_write_end,
1236 ffsdrv_null_erase_suspend,
1237 ffsdrv_null_erase_resume
1238 };
1239 #endif
1240
1241 // Note: This function is designed for little-endian memory addressing!
1242 void ffsdrv_write_byte(void *dst, uint8 value)
1243 {
1244 uint16 halfword;
1245
1246 tw(tr(TR_FUNC, TrDrvWrite, "ffsdrv_write_byte(0x%05x, 0x%x)\n",
1247 (int) (addr2offset(dst)), value));
1248 ttw(str(TTrDrvWrite, "wb" NL));
1249
1250 if ((int) dst & 1)
1251 halfword = (value << 8) | *((uint8 *) dst - 1);
1252 else
1253 halfword = (*((uint8 *) dst + 1) << 8) | (value);
1254
1255 ffsdrv.write_halfword((uint16 *) ((int) dst & ~1), halfword);
1256 }
1257
1258
1259 extern uint16 ffs_flash_manufact;
1260 extern uint16 ffs_flash_device;
1261
1262 effs_t ffsdrv_init(void)
1263 {
1264 const struct ffsdrv_s *p;
1265 const struct flash_info_s *flash = &flash_info[0];
1266 int error;
1267
1268 tw(tr(TR_BEGIN, TrDrvInit, "drv_init() {\n"));
1269 ttw(str(TTrDrvOther, "ffsdrv_init() {" NL));
1270
1271 dev.state = DEV_READ;
1272 dev.binfo = 0;
1273 dev.base = 0;
1274 dev.numblocks = 0;
1275
1276 // If ffs_flash_device is zero, detect device automatically by copying
1277 // the detect function into RAM and execute it from there...
1278 if (ffs_flash_manufact == 0 && ffs_flash_device == 0)
1279 {
1280 #if (TARGET == 1)
1281 char detect_code[80];
1282 typedef (*pf_t)(uint16 *, uint16 *);
1283 pf_t myfp;
1284 uint16 device_id[3];
1285
1286 ffsdrv_device_id_read_copy_to_ram((uint16 *) detect_code,
1287 sizeof(detect_code));
1288 // Combine bit 0 of the thumb mode function pointer with the address
1289 // of the code in RAM. Then call the detect function in RAM.
1290 myfp = (pf_t) (((int) &ffsdrv_device_id_read & 1) | (int) detect_code);
1291 (*myfp)(&dev.manufact, device_id);
1292
1293 if ((dev.manufact == MANUFACT_AMD || dev.manufact == MANUFACT_FUJITSU) &&
1294 device_id[0] == 0x227E) {
1295 // This is a multi-id device
1296 dev.device = (device_id[1] << 8) | (device_id[2] & 0xFF);
1297 }
1298 else
1299 dev.device = device_id[0];
1300 #endif
1301 }
1302 else {
1303 dev.manufact = ffs_flash_manufact;
1304 dev.device = ffs_flash_device;
1305 }
1306
1307 tw(tr(TR_FUNC, TrDrvInit, "TARGET = %d\n", TARGET));
1308 tw(tr(TR_FUNC, TrDrvInit, "Looking up device (0x%2x,0x%4x): ",
1309 dev.manufact, dev.device));
1310 while (flash->manufact) {
1311 tw(tr(TR_NULL, TrDrvInit, "(0x%02x,0x%04x) ",
1312 flash->manufact, flash->device));
1313 if (dev.manufact == flash->manufact && dev.device == flash->device) {
1314 tw(tr(TR_NULL, TrDrvInit, "FOUND "));
1315 break;
1316 }
1317 flash++;
1318 }
1319 tw(tr(TR_NULL, TrDrvInit, "\n"));
1320
1321 if (flash->manufact == 0) {
1322 tw(tr(TR_END, TrDrvInit, "} (%d)\n", EFFS_NODEVICE));
1323 return EFFS_NODEVICE;
1324 }
1325
1326 dev.binfo = (struct block_info_s *) flash->binfo;
1327
1328 if (flash->driver == FFS_DRIVER_RAM && flash->base == 0) {
1329 if (ffs_ram_image_address <= 0) {
1330 tw(tr(TR_END, TrDrvInit, "} (%d)\n", EFFS_DRIVER));
1331 return EFFS_DRIVER;
1332 }
1333 dev.base = (char *) ffs_ram_image_address;
1334 }
1335 else
1336 dev.base = (char *) flash->base;
1337
1338 dev.numblocks = flash->numblocks;
1339 dev.driver = flash->driver;
1340
1341 // We assume that ALL blocks are of equal size
1342 dev.blocksize_ld = dev.binfo[0].size_ld;
1343 dev.blocksize = (1 << dev.blocksize_ld);
1344
1345 dev.atomlog2 = FFS_ATOM_LOG2;
1346 dev.atomsize = 1 << dev.atomlog2;
1347 dev.atomnotmask = dev.atomsize - 1;
1348
1349 #if (TARGET == 0)
1350 if (dev.manufact == MANUFACT_TEST)
1351 dev.base = ffsdrv_test_create();
1352
1353 p = &ffsdrv_test;
1354
1355 #else // (TARGET == 1)
1356
1357 // Initialize hardware independent driver functions array
1358 switch (dev.driver) {
1359 case FFS_DRIVER_AMD: p = &ffsdrv_amd; break;
1360 case FFS_DRIVER_AMD_SB: p = &ffsdrv_amd_sb; break;
1361 case FFS_DRIVER_SST: p = &ffsdrv_sst; break;
1362 case FFS_DRIVER_SST_SB: p = &ffsdrv_sst_sb; break;
1363 case FFS_DRIVER_INTEL: p = &ffsdrv_intel; break;
1364 case FFS_DRIVER_INTEL_SB: p = &ffsdrv_intel_sb; break;
1365 case FFS_DRIVER_AMD_PSEUDO_SB: p = &ffsdrv_amd_pseudo_sb; break;
1366 case FFS_DRIVER_RAM: p = &ffsdrv_ram; break;
1367 default: p = &ffsdrv_null; break;
1368 }
1369
1370 #endif // (TARGET == 0)
1371
1372 // Bind the driver functions
1373 ffsdrv.init = p->init;
1374 ffsdrv.erase = p->erase;
1375 ffsdrv.write_halfword = p->write_halfword;
1376 ffsdrv.write = p->write;
1377 ffsdrv.write_end = p->write_end;
1378 ffsdrv.erase_suspend = p->erase_suspend;
1379 ffsdrv.erase_resume = p->erase_resume;
1380
1381 // Copy single bank driver code to RAM (and possibly re-bind some of the
1382 // driver functions)
1383 error = ffsdrv_driver_copy_to_ram(dev.driver);
1384
1385 if (error >= 0)
1386 error = ffsdrv.init();
1387
1388 tw(tr(TR_FUNC, TrDrvInit, "dev.binfo = 0x%x\n", (unsigned int) dev.binfo));
1389 tw(tr(TR_FUNC, TrDrvInit, "dev.base = 0x%x\n", (unsigned int) dev.base));
1390 tw(tr(TR_FUNC, TrDrvInit, "dev.numblocks = %d\n", dev.numblocks));
1391 tw(tr(TR_FUNC, TrDrvInit, "dev.blocksize = %d\n", dev.blocksize));
1392 tw(tr(TR_FUNC, TrDrvInit, "dev.atomlog2/atomsize/atomnotmask = %d/%d/%x\n",
1393 dev.atomlog2, dev.atomsize, dev.atomnotmask));
1394 tw(tr(TR_END, TrDrvInit, "} %d\n", error));
1395 ttw(ttr(TTrDrvOther, "} %d" NL, error));
1396
1397 return error;
1398 }
1399
1400
1401 /******************************************************************************
1402 * Interrupt Enable/Disable
1403 ******************************************************************************/
1404
1405 // IMPORTANT NOTE! Apparently, locating this ARM assembly code at the top of
1406 // this file will make the compiler trash the A1 register between the calls
1407 // of arm_int_disable and arm_int_enable() thus crashing the whole system.
1408 // If the code is placed AFTER the usage of the functions, the compiler
1409 // saves the A1 register. Strange but true.
1410
1411 // IMPORTANT NOTE! Apparently, another strange thing is that if the
1412 // functions are declared static, they don't work!
1413
1414 // Executing code from RAM is NOT trivial when we need to jump between ROM
1415 // (flash) and RAM memory. The ARM only supports 26-bit relative branch
1416 // offsets. This is the reason why we have a local copy of the
1417 // arm_int_disable/enable() functions in this file plus each of the
1418 // single-bank drivers.
1419
1420 #if (TARGET == 1)
1421 // Note that we use our own interrupt disable/enable function because
1422 // Nucleus allegedly should have a bug in its implementation for this.
1423
1424 uint32 int_disable(void)
1425 {
1426 asm(" .state16");
1427 asm(" mov A1, #0xC0");
1428 asm(" ldr A2, tct_disable");
1429 asm(" bx A2 ");
1430
1431 asm("tct_disable .field _TCT_Control_Interrupts+0,32");
1432 asm(" .global _TCT_Control_Interrupts");
1433 }
1434
1435 void int_enable(uint32 cpsr)
1436 {
1437 asm(" .state16");
1438 asm(" ldr A2, tct_enable");
1439 asm(" bx A2 ");
1440
1441 asm("tct_enable .field _TCT_Control_Interrupts+0,32");
1442 asm(" .global _TCT_Control_Interrupts");
1443 }
1444
1445 #else
1446
1447 uint32 int_disable(void) { return 0; }
1448 void int_enable(uint32 tmp) {}
1449
1450 #endif // (TARGET == 1)
1451
1452