OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [block/] [blkmem.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/* blkmem.c: Block access to memory spaces
2
 *
3
 * Copyright (C) 1997, 1998  D. Jeff Dionne <jeff@pfnet.com>,
4
 *                           Kenneth Albanowski <kjahds@kjahds.com>,
5
 *                           The Silver Hammer Group, Ltd.
6
 *
7
 * Based z2ram - Amiga pseudo-driver to access 16bit-RAM in ZorroII space
8
 * Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
9
 *
10
 * Permission to use, copy, modify, and distribute this software and its
11
 * documentation for any purpose and without fee is hereby granted, provided
12
 * that the above copyright notice appear in all copies and that both that
13
 * copyright notice and this permission notice appear in supporting
14
 * documentation.  This software is provided "as is" without express or
15
 * implied warranty.
16
*/
17
 
18
 
19
 
20
#include <linux/config.h>
21
#include <linux/major.h>
22
#include <linux/malloc.h>
23
 
24
#define MAJOR_NR    BLKMEM_MAJOR
25
 
26
#define VERBOSE
27
#define DEBUG
28
 
29
#include <linux/blk.h>
30
 
31
#include <linux/blkmem.h>
32
 
33
#if 0
34
#include <linux/init.h>
35
#endif
36
 
37
#if defined(MODULE)
38
#include <linux/module.h>
39
#endif
40
 
41
#include <asm/bitops.h>
42
#include <asm/delay.h>
43
/*
44
#include <asm/shglports.h>
45
*/
46
#define TRUE                  (1)
47
#define FALSE                 (0)
48
 
49
/*
50
 * Please, configure the ROMFS for your system here
51
 */
52
#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )
53
#define CAT_ROMARRAY
54
#endif
55
 
56
#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 )
57
extern char _flashstart[];
58
#define FIXED_ROMARRAY _flashstart
59
#endif
60
 
61
#ifdef CONFIG_UCSIMM
62
#define CAT_ROMARRAY
63
#endif
64
 
65
#ifdef CONFIG_M68EZ328ADS
66
#ifdef CONFIG_M68EZ328ADS_RAM
67
extern char _flashstart[];
68
#define FIXED_ROMARRAY _flashstart
69
#else
70
#define CAT_ROMARRAY
71
#endif 
72
#endif 
73
 
74
#ifdef CONFIG_ALMA_ANS
75
#ifdef CONFIG_ALMA_ANS_RAM
76
extern char _flashstart[];
77
#define FIXED_ROMARRAY _flashstart
78
#else
79
#define CAT_ROMARRAY
80
#endif 
81
#endif 
82
 
83
 
84
 
85
 
86
 
87
 
88
 
89
/******* END OF BOARD-SPECIFIC CONFIGURATION ************/
90
 
91
/* Simple romfs, at internal, cat on the end of kernel, or seperate fixed adderess romfs. */
92
 
93
#ifdef INTERNAL_ROMARRAY
94
#include "testromfs.c"
95
#endif
96
 
97
#ifdef CAT_ROMARRAY
98
unsigned char *romarray;
99
extern char __data_rom_start[];
100
extern char _edata[];
101
extern char __data_start[];
102
#endif
103
 
104
#ifdef FIXED_ROMARRAY
105
unsigned char *romarray = (char *)(FIXED_ROMARRAY);
106
#endif
107
 
108
/* If defined, ROOT_ARENA causes the root device to be the specified arena, useful with romfs */
109
 
110
/* Now defining ROOT_DEV in arch/setup.c */
111
/*#define ROOT_ARENA 0*/
112
 
113
struct arena_t;
114
 
115
typedef void (*xfer_func_t)(struct arena_t *, unsigned long address, unsigned long length, char * buffer);
116
typedef void (*erase_func_t)(struct arena_t *, unsigned long address);
117
typedef void (*program_func_t)(struct arena_t *, struct blkmem_program_t * prog);
118
 
119
void program_main(struct arena_t *, struct blkmem_program_t *);
120
void read_spare(struct arena_t *, unsigned long, unsigned long, char *);
121
void write_spare(struct arena_t *, unsigned long, unsigned long, char *);
122
void erase_spare(struct arena_t *, unsigned long);
123
 
124
 
125
/* This array of structures defines the actual set of memory arenas, including
126
   access functions (if the memory isn't part of the main address space) */
127
 
128
struct arena_t {
129
        int rw;
130
 
131
        unsigned long address; /* Address of memory arena */
132
        unsigned long length;  /* Length of memory arena. If -1, try to get size from romfs header */
133
 
134
        program_func_t program_func; /* Function to program in one go */
135
 
136
        xfer_func_t read_func; /* Function to transfer data to main memory, or zero if none needed */
137
        xfer_func_t write_func; /* Function to transfer data from main memory, zero if none needed */
138
 
139
        erase_func_t erase_func; /* Function to erase a block of memory to zeros, or 0 if N/A */
140
        unsigned long blksize; /* Size of block that can be erased at one time, or 0 if N/A */
141
        unsigned long unitsize;
142
        unsigned char erasevalue; /* Contents of sectors when erased */
143
 
144
        /*unsigned int auto_erase_bits;
145
        unsigned int did_erase_bits;*/
146
 
147
} arena[] = {
148
 
149
#ifdef INTERNAL_ROMARRAY
150
        {romarray, sizeof(romarray)},
151
#endif
152
 
153
#ifdef CAT_ROMARRAY
154
        {0, 0, -1},
155
#define FIXUP_ARENAS \
156
        arena[0].address = (unsigned long)__data_rom_start + (unsigned long)_edata - (unsigned long)__data_start;
157
#endif
158
 
159
#ifdef FIXED_ROMARRAY
160
        {0, FIXED_ROMARRAY, -1},
161
#endif
162
 
163
#ifdef CONFIG_SHGLCORE
164
 
165
#ifdef CONFIG_SHGLCORE_2MEG
166
        {0, 0x0A0000, 0x200000-0x0A0000},        /* ROM FS */
167
        {1, SHGLCORE_FLASH_BANK_0_ADDR, 0x80000, 0, 0, write_spare, erase_spare, 0x10000, 0x80000, 0xff},
168
        {1, 0x000000, 0x200000, program_main, 0,0,0, 0x20000, 0x100000}, /* All main FLASH */
169
#else
170
        {0, 0x0A0000, 0x100000-0x0A0000},        /* ROM FS */
171
        {1, SHGLCORE_FLASH_BANK_0_ADDR, 0x80000, 0, 0, write_spare, erase_spare, 0x10000, 0x80000, 0xff},
172
        {1, 0x000000, 0x100000, program_main, 0,0,0, 0x20000, 0x100000}, /* All main FLASH */
173
#endif
174
 
175
#define FIXUP_ARENAS \
176
        extern unsigned long rom_length; \
177
        arena[0].length = (unsigned long)rom_length - 0xA0000; \
178
        arena[2].length = (unsigned long)rom_length;
179
 
180
#endif
181
};
182
 
183
#define arenas (sizeof(arena) / sizeof(struct arena_t))
184
 
185
 
186
static int blkmem_blocksizes[arenas];
187
static int blkmem_sizes[arenas];
188
 
189
 
190
#ifdef CONFIG_SHGLCORE
191
static struct semaphore spare_lock = MUTEX;
192
 
193
void read_spare(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer)
194
{
195
 
196
#ifdef DEBUG
197
  printk("rsl\n");
198
#endif
199
 
200
  /* Mutex all access to FLASH */
201
  down(&spare_lock);
202
 
203
#ifdef DEBUG
204
  printk("rsld\n");
205
#endif
206
 
207
  /* Just copy the data into target buffer */
208
  memcpy( buffer, (void*)(a->address+pos), length);
209
 
210
  /* Release MUTEX */
211
  up(&spare_lock);
212
 
213
#ifdef DEBUG
214
  printk("rsud\n");
215
#endif
216
}
217
 
218
void write_spare(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer)
219
{
220
  unsigned long start;
221
  unsigned char c;
222
  volatile unsigned char * address;
223
  unsigned char result;
224
  unsigned long fbase = a->address;
225
  unsigned long flags;
226
 
227
#if 0
228
  for(i = pos / a->blksize; i <= ((pos+length-1) / a->blksize); i++) {
229
    if (test_bit(i, &a->auto_erase_bits)) {
230
      /* erase sector start */
231
      printk("Autoerase of sector %d\n", i);
232
      erase_spare(a, i * a->blksize);
233
      clear_bit(i, &a->auto_erase_bits);
234
    }
235
  }
236
#endif
237
 
238
#ifdef DEBUG
239
  printk("wsl\n");
240
#endif
241
 
242
  down(&spare_lock);
243
 
244
#ifdef DEBUG
245
  printk("wsld\n");
246
#endif
247
 
248
  start = jiffies;
249
 
250
  address = (unsigned volatile char*)(fbase+pos);
251
 
252
  while (length>0) {
253
 
254
    c = *buffer++;
255
 
256
    /*printk("Checking spare_flash program of byte %lx, at address %p, value %x (%c), current %x (%c)\n", pos, address, c, c, *address, *address);*/
257
 
258
    if (*address != c) {
259
 
260
      /*printk("Starting spare_flash program of byte %lx, at address %p\n", pos, address);*/
261
 
262
 
263
      if (c & ~*address) {
264
        printk("Unable to write byte at %p (impossible bit transition in %x, actual %x)\n", address, c, *address);
265
        /*continue;*/
266
      }
267
 
268
        save_flags(flags); cli();
269
 
270
      *(unsigned volatile char *)(fbase | 0x5555)=0x0aa;
271
      *(unsigned volatile char *)(fbase | 0x2aaa)=0x055;
272
      *(unsigned volatile char *)(fbase | 0x5555)=0x0a0;
273
 
274
      *address = c;
275
 
276
      for(;;) {
277
        result = *address;
278
        /*printk("Read value %x (%c)\n", result, result);*/
279
        if ((result & 0x80) == (c & 0x80))
280
          break;
281
        if (result & 0x20) {
282
          printk("timeout of FLASH write at address %p of value %x (actual %x)\n", address, c, *address);
283
          *(unsigned volatile char *)(fbase)=0x0f0; /* Reset */
284
          break;
285
        }
286
      }
287
 
288
      restore_flags(flags);
289
 
290
      /*printk("Completed spare_flash program of byte %lx, at address %p\n", pos, address);*/
291
 
292
#if 0
293
      if (jiffies != start) {
294
        /*printk("Spare_flash rescheduling in write\n");*/
295
        current->state = TASK_INTERRUPTIBLE;
296
        current->timeout = jiffies;
297
        schedule();
298
        current->timeout = 0;
299
        /*schedule();*/
300
        start = jiffies;
301
      }
302
#endif
303
    }
304
 
305
    address++;
306
    length--;
307
  }
308
 
309
  up(&spare_lock);
310
 
311
#ifdef DEBUG
312
  printk("wsud\n");
313
#endif
314
}
315
 
316
void erase_spare(struct arena_t * a, unsigned long pos)
317
{
318
  unsigned long fbase = a->address;
319
  int delay;
320
  unsigned volatile char * address;
321
  unsigned long flags;
322
 
323
  if (pos >= a->length)
324
    return;
325
 
326
  /* Mutex all access to FLASH memory */
327
 
328
#ifdef DEBUG
329
  printk("esl\n");
330
#endif
331
 
332
  down(&spare_lock);
333
 
334
#ifdef DEBUG
335
  printk("esld\n");
336
#endif
337
 
338
  address = (unsigned volatile char*)(fbase + pos);
339
 
340
  printk("Starting spare_flash erase of byte %lx, at address %p\n", pos, address);
341
 
342
  save_flags(flags); cli();
343
 
344
again:
345
 
346
  delay = HZ/4+1;
347
 
348
  /* Initiate erase of FLASH sector */
349
 
350
  *(unsigned volatile char *)(fbase | 0x5555)=0x0aa;
351
  *(unsigned volatile char *)(fbase | 0x2aaa)=0x055;
352
  *(unsigned volatile char *)(fbase | 0x5555)=0x080;
353
  *(unsigned volatile char *)(fbase | 0x5555)=0x0aa;
354
  *(unsigned volatile char *)(fbase | 0x2aaa)=0x055;
355
 
356
  *address = 0x030;
357
 
358
  /* Delay until erase is complete */
359
 
360
  for (;;) {
361
    unsigned char result;
362
#ifdef original_spare_erase_delay
363
    struct wait_queue *wait = NULL;
364
#ifdef DEBUG
365
    printk("Spare_flash erase delaying for %d ticks, status is %x\n", delay, (unsigned int)*address);
366
#endif
367
 
368
    current->timeout = jiffies + delay;
369
#if 0    
370
    current->state = TASK_INTERRUPTIBLE;
371
    schedule();
372
    current->timeout = 0;
373
#endif
374
    interruptible_sleep_on(&wait);
375
#endif
376
    udelay(100000);
377
 
378
    result = *address;
379
    if (result & 0x80)
380
       break;
381
    if (result & 0x20) {
382
       printk("timeout of Spare_flash erase of address %p\n", address);
383
       *(unsigned volatile char *)(fbase)=0x0f0; /* Reset */
384
       printk("Sleeping a second and retrying\n");
385
 
386
       udelay(1000000);
387
 
388
       goto again;
389
    }
390
  }
391
 
392
  restore_flags(flags);
393
 
394
#ifdef DEBUG
395
  printk("Completed spare_flash erase of byte %lx, at address %p\n", pos, address);
396
#endif
397
 
398
  up(&spare_lock);
399
 
400
#ifdef DEBUG
401
  printk("esud\n");
402
#endif
403
 
404
}
405
 
406
#define VSP(X) (*(volatile unsigned short *)(X))
407
#define VSC(X) (*(volatile unsigned char *)(X))
408
 
409
#define SCSR  VSP(0xfffc0c)
410
#define SCSR_TDRE (1<<8)
411
 
412
#define SCDR  VSP(0xfffC0e)
413
 
414
#define print_char(x) ({                        \
415
        while (!(SCSR & SCSR_TDRE))             \
416
                ;                               \
417
        SCDR = (x);                             \
418
})
419
 
420
#define print_hexdigit(x) ({                    \
421
        int digit = (x) & 0xf;                  \
422
        if (digit>9)                            \
423
                print_char('a'+digit-10);       \
424
        else                                    \
425
                print_char('0'+digit);          \
426
                                                \
427
})
428
 
429
#define print_num(x) ({                         \
430
        unsigned long num = (x);                \
431
        print_hexdigit(num >> 28);              \
432
        print_hexdigit(num >> 24);              \
433
        print_hexdigit(num >> 20);              \
434
        print_hexdigit(num >> 16);              \
435
        print_hexdigit(num >> 12);              \
436
        print_hexdigit(num >> 8);               \
437
        print_hexdigit(num >> 4);               \
438
        print_hexdigit(num >> 0);                \
439
})
440
 
441
/* Note: sub_program_main must not reference _any_ data or code outside of itself,
442
   or leave interrupts enabled, due to the fact that it is probably erasing
443
   & reloading the kernel. */
444
 
445
#define SET_SHORT(x,y) VSP((x)) = (y)
446
/*#define SET_SHORT(x,y) ({})*/ /*print_char('>');print_num(x);*/ /*printk("%8.8lx <= %04x\n", (x), (y))*/
447
 
448
#define SET_CHAR(x,y) VSC((x)) = (y)
449
/*#define SET_CHAR(x,y) ({})*/ /*print_char('>');print_num(x);*/ /*printk("%8.8lx <= %02x\n", (x), (y))*/
450
 
451
#define GET_SHORT(x) VSP((x))
452
/*#define GET_SHORT(x) ({0;})*/ /*({print_char('<');print_num(x);0;})*/ /*(printk("%8.8lx => ....\n", (x)),0)*/
453
 
454
#define GET_CHAR(x) VSC((x))
455
/*#define GET_CHAR(x) ({0;})*/ /*({print_char('<');print_num(x);0;})*/ /*(printk("%8.8lx => ..\n", (x)),0)*/
456
 
457
 
458
void sub_program_main(struct arena_t * a, struct blkmem_program_t * prog)
459
{
460
  volatile int i,l;
461
  unsigned long base, offset, ptr, min, max;
462
  unsigned char * c;
463
  unsigned int erased = 0;
464
  int failures;
465
  int retry;
466
 
467
  cli();
468
 
469
  retry = 0;
470
 
471
again:
472
 
473
  SET_ALARM_LED(1);
474
 
475
  retry++;
476
 
477
  if (retry>5) {
478
        goto give_up;
479
  }
480
 
481
    print_char('\r');
482
    print_char('\n');
483
    print_char('R');
484
    print_char('0' + retry);
485
 
486
  failures = 0;
487
  erased = 0;
488
 
489
/*  for(i=prog->blocks-1;i>=0;i--) {*/
490
  for(i=0;i<prog->blocks;i++) {
491
 
492
    SET_COMM_STATUS_LED(!GET_COMM_STATUS_LED());
493
 
494
    print_char('\r');
495
    print_char('\n');
496
    print_num(prog->block[i].pos+a->address);
497
    print_char('-');
498
    print_num(prog->block[i].pos+prog->block[i].length-1+a->address);
499
    print_char('\r');
500
    print_char('\n');
501
 
502
    if(prog->block[i].length > 0xE0000)
503
      break;
504
 
505
    for(l=prog->block[i].pos / a->blksize; l <= ((prog->block[i].pos+prog->block[i].length-1) / a->blksize); l++) {
506
      if (!test_bit(l, &erased)) {
507
 
508
        print_char('E');
509
        print_char('0' + l / 10);
510
        print_char('0' + l % 10);
511
        print_char('\r');
512
        print_char('\n');
513
 
514
        if (l <  1)
515
          break;
516
        /*if (l >= 8)
517
          break;*/
518
 
519
        ptr = l * a->blksize;
520
        offset = ptr % a->unitsize;
521
        base = ptr - offset;
522
 
523
        base += a->address;
524
        ptr += a->address;
525
 
526
        print_char('b');
527
        print_char('a');
528
        print_char('s');
529
        print_char('e');
530
        print_char(' ');
531
        print_num(base);
532
        print_char('\r');
533
        print_char('\n');
534
        print_char('o');
535
        print_char('f');
536
        print_char('f');
537
        print_char(' ');
538
        print_num(offset);
539
        print_char('\r');
540
        print_char('\n');
541
        print_char('p');
542
        print_char('t');
543
        print_char('r');
544
        print_char(' ');
545
        print_num(ptr);
546
        print_char('\r');
547
        print_char('\n');
548
 
549
        set_bit(l, &erased);
550
 
551
        if (ptr <  0x020000)
552
          break;
553
        /*if (ptr >= 0x100000)
554
          break;*/
555
 
556
        print_num(ptr);
557
 
558
        SET_COMM_ERROR_LED(1);
559
 
560
        /* Erase even half of sector */
561
        SET_SHORT( (base | (0x5555 << 1)), 0xaa00);
562
        SET_SHORT( (base | (0x2aaa << 1)), 0x5500);
563
        SET_SHORT( (base | (0x5555 << 1)), 0x8000);
564
        SET_SHORT( (base | (0x5555 << 1)), 0xaa00);
565
        SET_SHORT( (base | (0x2aaa << 1)), 0x5500);
566
 
567
        SET_SHORT( ptr, 0x3000);
568
#ifdef original_erase_logic
569
        while (!(GET_SHORT(ptr) & 0x8000))
570
          ;
571
#else
572
        for (;;) {
573
                unsigned int status = GET_SHORT(ptr);
574
                if (status & 0x8000) {
575
                        /* Erase complete */
576
                        break;
577
                }
578
                if (status & 0x2000) {
579
                        /* Check again */
580
                        status = GET_SHORT(ptr);
581
                        if (status & 0x8000) {
582
                                /* Erase complete */
583
                                break;
584
                        }
585
 
586
                        /* Erase failed */
587
                        print_char('F');
588
 
589
                        /* Reset FLASH unit */
590
                        SET_SHORT( base, 0xf000);
591
 
592
                        failures++;
593
 
594
                        /* Continue (with unerased sector) */
595
                        break;
596
                }
597
        }
598
#endif
599
 
600
        print_char(':');
601
 
602
        /* Erase odd half of sector */
603
        SET_SHORT( (base | (0x5555 << 1)), 0x00aa);
604
        SET_SHORT( (base | (0x2aaa << 1)), 0x0055);
605
        SET_SHORT( (base | (0x5555 << 1)), 0x0080);
606
        SET_SHORT( (base | (0x5555 << 1)), 0x00aa);
607
        SET_SHORT( (base | (0x2aaa << 1)), 0x0055);
608
 
609
        SET_SHORT( ptr, 0x0030);
610
#ifdef original_erase_logic
611
        while (!(GET_SHORT(ptr) & 0x0080))
612
          ;
613
#else
614
        for (;;) {
615
                unsigned int status = GET_SHORT(ptr);
616
                if (status & 0x0080) {
617
                        /* Erase complete */
618
                        break;
619
                }
620
                if (status & 0x0020) {
621
 
622
                        /* Check again */
623
                        status = GET_SHORT(ptr);
624
                        if (status & 0x0080) {
625
                                /* Erase complete */
626
                                break;
627
                        }
628
 
629
                        /* Erase failed */
630
                        print_char('F');
631
 
632
                        /* Reset FLASH unit */
633
                        SET_SHORT( base, 0x00f0);
634
 
635
                        failures++;
636
 
637
                        /* Continue (with unerased sector) */
638
                        break;
639
                }
640
        }
641
#endif
642
 
643
        print_char(':');
644
 
645
#if 0
646
        probe = (volatile unsigned short*)(fbase + a->blksize * l);
647
        *probe = 0x3000;
648
        while (!(*probe & 0x8000))
649
          ;
650
 
651
        print_char('.');
652
 
653
        /* Erase odd half of sector */
654
        *(unsigned volatile short *)(fbase | (0x5555 << 1))=0x00aa;
655
        *(unsigned volatile short *)(fbase | (0x2aaa << 1))=0x0055;
656
        *(unsigned volatile short *)(fbase | (0x5555 << 1))=0x0080;
657
        *(unsigned volatile short *)(fbase | (0x5555 << 1))=0x00aa;
658
        *(unsigned volatile short *)(fbase | (0x2aaa << 1))=0x0055;
659
 
660
        probe = (volatile unsigned short*)(fbase + a->blksize * l);
661
        *probe = 0x0030;
662
        while (!(*probe & 0x0080))
663
          break;
664
 
665
        print_char('.');
666
#endif
667
 
668
        SET_COMM_ERROR_LED(0);
669
      }
670
    }
671
 
672
 
673
    min = prog->block[i].pos+a->address;
674
    max = prog->block[i].pos+prog->block[i].length+a->address;
675
    for(ptr=min, c=prog->block[i].data; ptr<max; ptr++, c++) {
676
 
677
      offset = (ptr-a->address) % a->unitsize;
678
      base = ptr - offset;
679
 
680
      if (ptr <  0x020000)
681
        break;
682
      /*if (ptr >= 0x100000)
683
        break;*/
684
 
685
      /*print_char('.');*/
686
 
687
#if 0
688
      if ((fbase & 1) == 0) { /* Even bank */
689
        *(unsigned volatile short *)(fbase | (0x5555 << 1))=0xaa00;
690
        *(unsigned volatile short *)(fbase | (0x2aaa << 1))=0x5500;
691
        *(unsigned volatile short *)(fbase | (0x5555 << 1))=0xa000;
692
        *(unsigned volatile short *)(fbase + (b & ~1))     =*c << 8;
693
      } else { /* Odd bank */
694
        *(unsigned volatile short *)(fbase | (0x5555 << 1))=0x00aa;
695
        *(unsigned volatile short *)(fbase | (0x2aaa << 1))=0x0055;
696
        *(unsigned volatile short *)(fbase | (0x5555 << 1))=0x00a0;
697
        *(unsigned volatile short *)(fbase + (b & ~1))     =*c;
698
      }
699
 
700
      probe = (volatile unsigned char*)(fbase + b);
701
      while (*probe != *c)
702
          break;
703
#endif
704
 
705
      if ((ptr & 1) == 0) { /* Even bank */
706
        SET_SHORT( (base | (0x5555 << 1)), 0xaa00);
707
        SET_SHORT( (base | (0x2aaa << 1)), 0x5500);
708
        SET_SHORT( (base | (0x5555 << 1)), 0xa000);
709
        SET_SHORT( (ptr & ~1),      *c << 8);
710
      } else { /* Odd bank */
711
        SET_SHORT( (base | (0x5555 << 1)), 0x00aa);
712
        SET_SHORT( (base | (0x2aaa << 1)), 0x0055);
713
        SET_SHORT( (base | (0x5555 << 1)), 0x00a0);
714
        SET_SHORT( (ptr & ~1),      *c);
715
      }
716
 
717
#ifdef original_write_logic
718
      while (GET_CHAR(ptr) != *c)
719
        ;
720
#else
721
        for (;;) {
722
                unsigned char status = GET_CHAR(ptr);
723
                if ((status & 0x80) == (*c & 0x80)) {
724
                        /* Program complete */
725
                        break;
726
                }
727
                if (status & 0x20) {
728
                        /* Check again */
729
                        status = GET_CHAR(ptr);
730
                        if ((status & 0x80) == (*c & 0x80)) {
731
                                /* Program complete */
732
                                break;
733
                        }
734
 
735
                        /* Program failed */
736
                        print_char('F');
737
 
738
                        /* Reset FLASH unit */
739
                        if ((ptr & 1) == 0) { /* Even bank */
740
                                SET_SHORT( base, 0xf000);
741
                        } else { /* Odd bank */
742
                                SET_SHORT( base, 0x00f0);
743
                        }
744
 
745
                        failures++;
746
 
747
                        /* Continue */
748
                        break;
749
                }
750
        }
751
#endif
752
 
753
      /*print_char(' ');*/
754
    }
755
  }
756
 
757
  if (failures > 0) {
758
        /* There were failures erasing the FLASH, so go back to the beginning and
759
        try it all again -- for lack of anything better to do. */
760
 
761
        print_char('!');
762
        goto again;
763
  }
764
 
765
give_up:
766
 
767
  SET_ALARM_LED(1);
768
 
769
 
770
  HARD_RESET_NOW();
771
 
772
  i = 1;
773
  while(i)
774
    ;
775
 
776
}
777
 
778
void program_main(struct arena_t * a, struct blkmem_program_t * prog)
779
{
780
  int len;
781
  void (*code)(struct arena_t*, struct blkmem_program_t *);
782
 
783
  printk("program_main entered, blocks = %d\n", prog->blocks);
784
 
785
  len = &program_main-&sub_program_main;
786
  code = kmalloc(len, GFP_KERNEL);
787
  memcpy(code, &sub_program_main, len);
788
 
789
  code(a, prog);
790
 
791
  kfree(code);
792
 
793
  /*sub_program_main(a, prog);*/
794
}
795
#endif /* CONFIG_SHGLCORE */
796
 
797
int general_program_func(struct inode * inode, struct file * file, struct arena_t * a, struct blkmem_program_t * prog)
798
{
799
  int i,block;
800
  int err;
801
  unsigned int erased = 0;
802
  unsigned long pos = file->f_pos;
803
 
804
  /* Mandatory flush of all dirty buffers */
805
  fsync_dev(inode->i_rdev);
806
  invalidate_buffers(inode->i_rdev);
807
 
808
  for(i=0;i<prog->blocks;i++) {
809
    int min= prog->block[i].pos / a->blksize;
810
    int max = (prog->block[i].pos + prog->block[i].length - 1) / a->blksize;
811
    for(block=min; block <= max; block++) {
812
      if (!test_bit(block, &erased)) {
813
        printk("Erase of sector at pos %lx of arena %d (address %p)\n", block * a->blksize, MINOR(inode->i_rdev), (void*)(a->address+block*a->blksize));
814
 
815
        /* Invoke erase function */
816
        a->erase_func(a, block * a->blksize);
817
        set_bit(block, &erased);
818
      }
819
    }
820
 
821
    printk("Write of %lu bytes at pos %lu (data at %p)\n", prog->block[i].length, prog->block[i].pos, prog->block[i].data);
822
 
823
    a->write_func(a, prog->block[i].pos, prog->block[i].length, prog->block[i].data);
824
 
825
    schedule();
826
  }
827
 
828
  if (prog->reset)
829
        HARD_RESET_NOW();
830
  return 0;
831
}
832
 
833
 
834
static void complete_request(void * data);
835
 
836
static struct tq_struct complete_tq = {0, 0, complete_request, NULL};
837
 
838
static void
839
delay_request( void )
840
{
841
  queue_task(&complete_tq, &tq_scheduler);
842
}
843
 
844
static void
845
complete_request( void * data)
846
{
847
  unsigned long start;
848
  unsigned long len;
849
  struct arena_t * a = arena + DEVICE_NR(CURRENT_DEV);
850
 
851
  for(;;) {
852
 
853
  /* sectors are 512 bytes */
854
  start = CURRENT->sector << 9;
855
  len  = CURRENT->current_nr_sectors << 9;
856
 
857
  /*printk("blkmem: re-request %d\n", CURRENT->cmd);*/
858
 
859
  if ( CURRENT->cmd == READ ) {
860
    /*printk("BMre-Read: %lx:%lx > %p\n", a->address + start, len, CURRENT->buffer);*/
861
    a->read_func(a, start, len, CURRENT->buffer);
862
  }
863
  else if (CURRENT->cmd == WRITE) {
864
    /*printk("BMre-Write: %p > %lx:%lx\n", CURRENT->buffer, a->address + start, len);*/
865
    a->write_func(a, start, len, CURRENT->buffer);
866
  }
867
  /*printk("ending blkmem request\n");*/
868
  end_request( TRUE );
869
 
870
  INIT_REQUEST;
871
  }
872
 
873
#if 0
874
  if (CURRENT)
875
    do_blkmem_request(); /* Process subsequent requests */
876
#endif
877
}
878
 
879
 
880
static void
881
do_blkmem_request( void )
882
{
883
  unsigned long start;
884
  unsigned long len;
885
  struct arena_t * a = arena + DEVICE_NR(CURRENT_DEV);
886
#if 0
887
  printk( KERN_ERR DEVICE_NAME ": request\n");
888
#endif
889
  while ( TRUE ) {
890
    INIT_REQUEST;
891
 
892
    /* sectors are 512 bytes */
893
    start = CURRENT->sector << 9;
894
    len  = CURRENT->current_nr_sectors << 9;
895
 
896
    if ((start + len) > a->length) {
897
      printk( KERN_ERR DEVICE_NAME ": bad access: block=%ld, count=%ld (pos=%lx, len=%lx)\n",
898
              CURRENT->sector,
899
              CURRENT->current_nr_sectors,
900
              start+len,
901
              a->length);
902
      end_request( FALSE );
903
      continue;
904
    }
905
 
906
    /*printk("blkmem: request %d\n", CURRENT->cmd);*/
907
 
908
    if ( ( CURRENT->cmd != READ )
909
         && ( CURRENT->cmd != WRITE )
910
         ) {
911
      printk( KERN_ERR DEVICE_NAME ": bad command: %d\n", CURRENT->cmd );
912
      end_request( FALSE );
913
      continue;
914
    }
915
 
916
    if ( CURRENT->cmd == READ ) {
917
      /*printk("BMRead %d, pid %d: %lx:%lx > %p\n", DEVICE_NR(CURRENT_DEV), current->pid, a->address + start, len, CURRENT->buffer);*/
918
      if (a->read_func) {
919
        delay_request();
920
        return;
921
        /*a->read_func(a, start, len, CURRENT->buffer);*/
922
      }
923
      else
924
        memcpy( CURRENT->buffer, (void*)(a->address + start), len );
925
    }
926
    else if (CURRENT->cmd == WRITE) {
927
      /*printk("BMWrite %d: %p > %lx:%lx\n", DEVICE_NR(CURRENT_DEV), CURRENT->buffer, a->address + start, len);*/
928
      if (a->write_func) {
929
        delay_request();
930
        return;
931
        /*a->write_func(a, start, len, CURRENT->buffer);*/
932
      } else
933
        memcpy( (void*)(a->address + start), CURRENT->buffer, len );
934
    }
935
    /*printk("ending blkmem request\n");*/
936
    end_request( TRUE );
937
  }
938
}
939
 
940
 
941
#ifdef MAGIC_ROM_PTR
942
static int
943
blkmem_romptr( struct inode *inode, struct file *filp, struct vm_area_struct * vma)
944
{
945
  struct arena_t * a = arena + MINOR(inode->i_rdev);
946
 
947
  if (a->read_func)
948
    return -ENOSYS; /* Can't do it, as this arena isn't in the main address space */
949
 
950
  vma->vm_start = a->address + vma->vm_offset;
951
  return 0;
952
}
953
#endif
954
 
955
static int blkmem_ioctl (struct inode *inode, struct file *file,
956
                         unsigned int cmd, unsigned long arg)
957
{
958
  struct arena_t * a = arena + MINOR(inode->i_rdev);
959
  int err;
960
 
961
  switch (cmd) {
962
  case BMGETSIZES:   /* Return device size in sectors */
963
 
964
    if (!arg)
965
      return -EINVAL;
966
 
967
    err = verify_area(VERIFY_WRITE, (unsigned long *) arg, sizeof(unsigned long));
968
    if (err)
969
      return err;
970
 
971
    put_user(a->blksize ? (a->length / a->blksize) : 0, (unsigned long *) arg);
972
 
973
    break;
974
 
975
  case BMGETSIZEB:   /* Return device size in bytes */
976
 
977
    if (!arg)
978
      return -EINVAL;
979
 
980
    err = verify_area(VERIFY_WRITE, (unsigned long *) arg, sizeof(unsigned long));
981
    if (err)
982
      return err;
983
 
984
    put_user(a->length, (unsigned long *) arg);
985
 
986
    break;
987
 
988
  case BMSERASE:
989
    if (a->erase_func) {
990
 
991
      printk("Erase of sector at pos %lx of arena %d (address %p)\n", arg, MINOR(inode->i_rdev), (void*)(a->address+arg));
992
 
993
      if (arg >= a->length)
994
        return -EINVAL;
995
 
996
      /* Mandatory flush of all dirty buffers */
997
      fsync_dev(inode->i_rdev);
998
 
999
      /* Invalidate any buffers pointing to the section that will be erased */
1000
      invalidate_buffers_by_byte(inode->i_rdev, arg * a->blksize, a->blksize);
1001
 
1002
      /* Invoke erase function */
1003
      a->erase_func(a, arg);
1004
    } else
1005
      return -EINVAL;
1006
    break;
1007
 
1008
  case BMSGSIZE:
1009
 
1010
    if (!arg)
1011
      return -EINVAL;
1012
 
1013
    err = verify_area(VERIFY_WRITE, (unsigned long*)arg, sizeof(unsigned long));
1014
    if (err)
1015
      return err;
1016
 
1017
    put_user(a->blksize, (unsigned long*)arg);
1018
    break;
1019
 
1020
  case BMSGERASEVALUE:
1021
    err = verify_area(VERIFY_WRITE, (unsigned char*)arg, sizeof(unsigned char));
1022
    if (err)
1023
      return err;
1024
 
1025
    *(unsigned char*)arg = a->erasevalue;
1026
    break;
1027
 
1028
  case BMPROGRAM:
1029
  {
1030
    struct blkmem_program_t * prog;
1031
    int i;
1032
    if (!arg)
1033
      return -EINVAL;
1034
 
1035
    prog = (struct blkmem_program_t*)arg;
1036
 
1037
    /* Extensive checks to verify that the programming data makes sense */
1038
 
1039
    err = verify_area(VERIFY_READ, prog, sizeof(struct blkmem_program_t));
1040
    if (err)
1041
      return err;
1042
 
1043
    if ((prog->magic1 != BMPROGRAM_MAGIC_1) ||
1044
        (prog->magic2 != BMPROGRAM_MAGIC_2))
1045
      return -EINVAL;
1046
 
1047
    err = verify_area(VERIFY_READ, prog, sizeof(struct blkmem_program_t) + sizeof(prog->block[0]) * prog->blocks);
1048
    if (err)
1049
      return err;
1050
 
1051
    for(i=0;i<prog->blocks;i++)
1052
      if(prog->block[i].magic3 != BMPROGRAM_MAGIC_3)
1053
        return -EINVAL;
1054
 
1055
    for(i=0;i<prog->blocks;i++)
1056
      if ((prog->block[i].pos > a->length) ||
1057
          ((prog->block[i].pos+prog->block[i].length-1) > a->length))
1058
        return -EINVAL;
1059
 
1060
    for(i=0;i<prog->blocks;i++) {
1061
      err = verify_area(VERIFY_READ, prog->block[i].data, prog->block[i].length);
1062
      if (err)
1063
        return err;
1064
    }
1065
 
1066
    if (a->program_func) {
1067
      a->program_func(a, prog);
1068
    } else {
1069
      return general_program_func(inode, file, a, prog);
1070
    }
1071
 
1072
    break;
1073
  }
1074
  default:
1075
    return -EINVAL;
1076
  }
1077
  return 0;
1078
}
1079
 
1080
static int
1081
blkmem_open( struct inode *inode, struct file *filp )
1082
{
1083
  int device;
1084
  struct arena_t * a;
1085
 
1086
  device = DEVICE_NR( inode->i_rdev );
1087
#if 0
1088
  printk( KERN_ERR DEVICE_NAME ": open: %d\n", device );
1089
#endif
1090
 
1091
  if ((MINOR(device) < 0) || (MINOR(device) >= arenas))  {
1092
    printk("arena open of %d failed!\n", MINOR(device));
1093
    return -ENODEV;
1094
  }
1095
 
1096
  a = &arena[MINOR(device)];
1097
 
1098
#ifdef DEBUG
1099
  printk("Open of blkmem arena %d at %lx, length %lx\n", MINOR(device), a->address, a->length);
1100
#endif
1101
 
1102
#if defined(MODULE)
1103
  MOD_INC_USE_COUNT;
1104
#endif
1105
  return 0;
1106
}
1107
 
1108
static void
1109
blkmem_release( struct inode *inode, struct file *filp )
1110
{
1111
#if 0
1112
  printk( KERN_ERR DEVICE_NAME ": release: %d\n", current_device );
1113
#endif
1114
 
1115
  fsync_dev( inode->i_rdev );
1116
 
1117
#if defined(MODULE)
1118
  MOD_DEC_USE_COUNT;
1119
#endif
1120
 
1121
  return;
1122
}
1123
 
1124
static struct file_operations blkmem_fops =
1125
{
1126
  NULL,                   /* lseek - default */
1127
  block_read,             /* read - general block-dev read */
1128
  block_write,            /* write - general block-dev write */
1129
  NULL,                   /* readdir - bad */
1130
  NULL,                   /* poll */
1131
  blkmem_ioctl,           /* ioctl */
1132
  NULL,
1133
  blkmem_open,            /* open */
1134
  blkmem_release,         /* release */
1135
  block_fsync,            /* fsync */
1136
  NULL,                   /* fasync */
1137
  NULL,                   /* check media change */
1138
  NULL,                   /* revalidate */
1139
  blkmem_romptr,          /* romptr */
1140
};
1141
 
1142
int
1143
blkmem_init( void )
1144
{
1145
  int i;
1146
  if ( register_blkdev( MAJOR_NR, DEVICE_NAME, &blkmem_fops )) {
1147
    printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n",
1148
            MAJOR_NR );
1149
    return -EBUSY;
1150
  }
1151
 
1152
#ifdef FIXUP_ARENAS
1153
  {
1154
  FIXUP_ARENAS
1155
  }
1156
#endif
1157
 
1158
  for(i=0;i<arenas;i++) {
1159
    if (arena[i].length == -1)
1160
      arena[i].length = *(volatile unsigned long *)(arena[i].address + 8);
1161
    blkmem_blocksizes[i] = 1024;
1162
    blkmem_sizes[i] = (arena[i].length + (1 << 10) - 1) >> 10; /* Round up */
1163
    arena[i].length = blkmem_sizes[i] << 10;
1164
  }
1165
  printk("Blkmem copyright 1998,1999 D. Jeff Dionne\nBlkmem copyright 1998 Kenneth Albanowski\nBlkmem %ld disk images:\n", arenas);
1166
 
1167
  for(i=0;i<arenas;i++) {
1168
    printk("%d: %lX-%lX (%s)\n", i, arena[i].address, arena[i].address+arena[i].length-1,
1169
        arena[i].rw
1170
                ? "RW"
1171
                : "RO"
1172
    );
1173
  }
1174
 
1175
  read_ahead[ MAJOR_NR ] = 0;
1176
  blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
1177
  blksize_size[ MAJOR_NR ] = blkmem_blocksizes;
1178
  blk_size[ MAJOR_NR ] = blkmem_sizes;
1179
 
1180
#ifdef ROOT_ARENA
1181
  ROOT_DEV = MKDEV(MAJOR_NR,ROOT_ARENA);
1182
#endif
1183
 
1184
  return 0;
1185
}
1186
 
1187
#if defined(MODULE)
1188
 
1189
int
1190
init_module( void )
1191
{
1192
  int error;
1193
 
1194
  error = blkmem_init();
1195
  if ( error == 0 ) {
1196
    printk( KERN_INFO DEVICE_NAME ": loaded as module\n" );
1197
  }
1198
 
1199
  return error;
1200
}
1201
 
1202
void
1203
cleanup_module( void )
1204
{
1205
  if ( unregister_blkdev( MAJOR_NR, DEVICE_NAME ) != 0 )
1206
    printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
1207
 
1208
  if ( current_device != -1 ) {
1209
    /* free whatever we resources remain here */
1210
  }
1211
 
1212
  return;
1213
}
1214
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.