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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [sim/] [ppc/] [hw_eeprom.c] - Blame information for rev 106

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _HW_EEPROM_C_
23
#define _HW_EEPROM_C_
24
 
25
#include "device_table.h"
26
 
27
#ifdef HAVE_STRING_H
28
#include <string.h>
29
#else
30
#ifdef HAVE_STRINGS_H
31
#include <strings.h>
32
#endif
33
#endif
34
 
35
 
36
/* DEVICE
37
 
38
 
39
   eeprom - JEDEC? compatible electricaly erasable programable device
40
 
41
 
42
   DESCRIPTION
43
 
44
 
45
   This device implements a small byte addressable EEPROM.
46
   Programming is performed using the same write sequences as used by
47
   standard modern EEPROM components.  Writes occure in real time, the
48
   device returning a progress value until the programing has been
49
   completed.
50
 
51
   It is based on the AMD 29F040 component.
52
 
53
 
54
   PROPERTIES
55
 
56
 
57
   reg = <address> <size> (required)
58
 
59
   Determine where the device lives in the parents address space.
60
 
61
 
62
   nr-sectors = <integer> (required)
63
 
64
   When erasing an entire sector is cleared at a time.  This specifies
65
   the number of sectors in the EEPROM component.
66
 
67
 
68
   sector-size = <integer> (required)
69
 
70
   The number of bytes in a sector.  When erasing, memory chunks of
71
   this size are cleared.
72
 
73
   NOTE: The product nr-sectors * sector-size does not need to map the
74
   size specified in the reg property.  If the specified size is
75
   smaller part of the eeprom will not be accessible while if it is
76
   larger the addresses will wrap.
77
 
78
 
79
   byte-write-delay = <integer> (required)
80
 
81
   Number of clock ticks before the programming of a single byte
82
   completes.
83
 
84
 
85
   sector-start-delay = <integer> (required)
86
 
87
   When erasing sectors, the number of clock ticks after the sector
88
   has been specified that the actual erase process commences.
89
 
90
 
91
   erase-delay = <intger> (required)
92
 
93
   Number of clock ticks before an erase program completes
94
 
95
 
96
   manufacture-code = <integer> (required)
97
 
98
   The one byte value returned when the auto-select manufacturer code
99
   is read.
100
 
101
 
102
   device-code = <integer> (required)
103
 
104
   The one byte value returned when the auto-select device code is
105
   read.
106
 
107
 
108
   input-file = <file-name> (optional)
109
 
110
   Initialize the eeprom using the specified binary file.
111
 
112
 
113
   output-file = <file-name> (optional)
114
 
115
   When ever the eeprom is updated, save the modified image into the
116
   specified file.
117
 
118
 
119
   EXAMPLES
120
 
121
 
122
   Enable tracing of the eeprom:
123
 
124
   |  bash$ psim -t eeprom-device \
125
 
126
 
127
   Configure something very like the Amd Am29F040 - 512byte EEPROM
128
   (but a bit faster):
129
 
130
   |  -o '/eeprom@0xfff00000/reg 0xfff00000 0x80000' \
131
   |  -o '/eeprom@0xfff00000/nr-sectors 8' \
132
   |  -o '/eeprom@0xfff00000/sector-size 0x10000' \
133
   |  -o '/eeprom@0xfff00000/byte-write-delay 1000' \
134
   |  -o '/eeprom@0xfff00000/sector-start-delay 100' \
135
   |  -o '/eeprom@0xfff00000/erase-delay 1000' \
136
   |  -o '/eeprom@0xfff00000/manufacture-code 0x01' \
137
   |  -o '/eeprom@0xfff00000/device-code 0xa4' \
138
 
139
 
140
   Initialize the eeprom from the file <</dev/zero>>:
141
 
142
   |  -o '/eeprom@0xfff00000/input-file /dev/zero'
143
 
144
 
145
   BUGS
146
 
147
 
148
   */
149
 
150
typedef enum {
151
  read_reset,
152
  write_nr_2,
153
  write_nr_3,
154
  write_nr_4,
155
  write_nr_5,
156
  write_nr_6,
157
  byte_program,
158
  byte_programming,
159
  chip_erase,
160
  sector_erase,
161
  sector_erase_suspend,
162
  autoselect,
163
} hw_eeprom_states;
164
 
165
static const char *
166
state2a(hw_eeprom_states state)
167
{
168
  switch (state) {
169
  case read_reset: return "read_reset";
170
  case write_nr_2: return "write_nr_2";
171
  case write_nr_3: return "write_nr_3";
172
  case write_nr_4: return "write_nr_4";
173
  case write_nr_5: return "write_nr_5";
174
  case write_nr_6: return "write_nr_6";
175
  case byte_program: return "byte_program";
176
  case byte_programming: return "byte_programming";
177
  case chip_erase: return "chip_erase";
178
  case sector_erase: return "sector_erase";
179
  case sector_erase_suspend: return "sector_erase_suspend";
180
  case autoselect: return "autoselect";
181
  }
182
  return NULL;
183
}
184
 
185
typedef struct _hw_eeprom_device {
186
  /* general */
187
  hw_eeprom_states state;
188
  unsigned8 *memory;
189
  unsigned sizeof_memory;
190
  unsigned erase_delay;
191
  signed64 program_start_time;
192
  signed64 program_finish_time;
193
  unsigned8 manufacture_code;
194
  unsigned8 device_code;
195
  unsigned8 toggle_bit;
196
  /* initialization */
197
  const char *input_file_name;
198
  const char *output_file_name;
199
  /* for sector and sector programming */
200
  hw_eeprom_states sector_state;
201
  unsigned8 *sectors;
202
  unsigned nr_sectors;
203
  unsigned sizeof_sector;
204
  unsigned sector_start_delay;
205
  unsigned sector_start_time;
206
  /* byte and byte programming */
207
  unsigned byte_write_delay;
208
  unsigned_word byte_program_address;
209
  unsigned8 byte_program_byte;
210
} hw_eeprom_device;
211
 
212
typedef struct _hw_eeprom_reg_spec {
213
  unsigned32 base;
214
  unsigned32 size;
215
} hw_eeprom_reg_spec;
216
 
217
static void
218
hw_eeprom_init_data(device *me)
219
{
220
  hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
221
 
222
  /* have we any input or output files */
223
  if (device_find_property(me, "input-file") != NULL)
224
    eeprom->input_file_name = device_find_string_property(me, "input-file");
225
  if (device_find_property(me, "output-file") != NULL)
226
    eeprom->input_file_name = device_find_string_property(me, "output-file");
227
 
228
  /* figure out the sectors in the eeprom */
229
  if (eeprom->sectors == NULL) {
230
    eeprom->nr_sectors = device_find_integer_property(me, "nr-sectors");
231
    eeprom->sizeof_sector = device_find_integer_property(me, "sector-size");
232
    eeprom->sectors = zalloc(eeprom->nr_sectors);
233
  }
234
  else
235
    memset(eeprom->sectors, 0, eeprom->nr_sectors);
236
 
237
  /* initialize the eeprom */
238
  if (eeprom->memory == NULL) {
239
    eeprom->sizeof_memory = eeprom->sizeof_sector * eeprom->nr_sectors;
240
    eeprom->memory = zalloc(eeprom->sizeof_memory);
241
  }
242
  else
243
    memset(eeprom->memory, 0, eeprom->sizeof_memory);
244
  if (eeprom->input_file_name != NULL) {
245
    int i;
246
    FILE *input_file = fopen(eeprom->input_file_name, "r");
247
    if (input_file == NULL) {
248
      perror("eeprom");
249
      device_error(me, "Failed to open input file %s\n", eeprom->input_file_name);
250
    }
251
    for (i = 0; i < eeprom->sizeof_memory; i++) {
252
      if (fread(&eeprom->memory[i], 1, 1, input_file) != 1)
253
        break;
254
    }
255
    fclose(input_file);
256
  }
257
 
258
  /* timing */
259
  eeprom->byte_write_delay = device_find_integer_property(me, "byte-write-delay");
260
  eeprom->sector_start_delay = device_find_integer_property(me, "sector-start-delay");
261
  eeprom->erase_delay = device_find_integer_property(me, "erase-delay");
262
 
263
  /* misc */
264
  eeprom->manufacture_code = device_find_integer_property(me, "manufacture-code");
265
  eeprom->device_code = device_find_integer_property(me, "device-code");
266
}
267
 
268
 
269
static void
270
invalid_read(device *me,
271
             hw_eeprom_states state,
272
             unsigned_word address,
273
             const char *reason)
274
{
275
  DTRACE(eeprom, ("Invalid read to 0x%lx while in state %s (%s)\n",
276
                  (unsigned long)address,
277
                  state2a(state),
278
                  reason));
279
}
280
 
281
static void
282
invalid_write(device *me,
283
              hw_eeprom_states state,
284
              unsigned_word address,
285
              unsigned8 data,
286
              const char *reason)
287
{
288
  DTRACE(eeprom, ("Invalid write of 0x%lx to 0x%lx while in state %s (%s)\n",
289
                  (unsigned long)data,
290
                  (unsigned long)address,
291
                  state2a(state),
292
                  reason));
293
}
294
 
295
static void
296
dump_eeprom(device *me,
297
            hw_eeprom_device *eeprom)
298
{
299
  if (eeprom->output_file_name != NULL) {
300
    int i;
301
    FILE *output_file = fopen(eeprom->output_file_name, "w");
302
    if (output_file == NULL) {
303
      perror("eeprom");
304
      device_error(me, "Failed to open output file %s\n",
305
                   eeprom->output_file_name);
306
    }
307
    for (i = 0; i < eeprom->sizeof_memory; i++) {
308
      if (fwrite(&eeprom->memory[i], 1, 1, output_file) != 1)
309
        break;
310
    }
311
    fclose(output_file);
312
  }
313
}
314
 
315
 
316
/* program a single byte of eeprom */
317
 
318
static void
319
start_programming_byte(device *me,
320
                       hw_eeprom_device *eeprom,
321
                       unsigned_word address,
322
                       unsigned8 new_byte)
323
{
324
  unsigned8 old_byte = eeprom->memory[address];
325
  DTRACE(eeprom, ("start-programing-byte - address 0x%lx, new 0x%lx, old 0x%lx\n",
326
                  (unsigned long)address,
327
                  (unsigned long)new_byte,
328
                  (unsigned long)old_byte));
329
  eeprom->byte_program_address = address;
330
  /* : old new : ~old : new&~old
331
     :  0   0  :   1  :    0
332
     :  0   1  :   1  :    1     -- can not set a bit
333
     :  1   0  :   0  :    0
334
     :  1   1  :   0  :    0 */
335
  if (~old_byte & new_byte)
336
    invalid_write(me, eeprom->state, address, new_byte, "setting cleared bit");
337
  /* : old new : old&new
338
     :  0   0  :    0
339
     :  0   1  :    0
340
     :  1   0  :    0
341
     :  1   1  :    1 */
342
  eeprom->byte_program_byte = new_byte & old_byte;
343
  eeprom->memory[address] = ~new_byte & ~0x24; /* LE-bits 5:3 zero */
344
  eeprom->program_start_time = device_event_queue_time(me);
345
  eeprom->program_finish_time = (eeprom->program_start_time
346
                                 + eeprom->byte_write_delay);
347
}
348
 
349
static void
350
finish_programming_byte(device *me,
351
                        hw_eeprom_device *eeprom)
352
{
353
  DTRACE(eeprom, ("finish-programming-byte - address 0x%lx, byte 0x%lx\n",
354
                  (unsigned long)eeprom->byte_program_address,
355
                  (unsigned long)eeprom->byte_program_byte));
356
  eeprom->memory[eeprom->byte_program_address] = eeprom->byte_program_byte;
357
  dump_eeprom(me, eeprom);
358
}
359
 
360
 
361
/* erase the eeprom completly */
362
 
363
static void
364
start_erasing_chip(device *me,
365
                   hw_eeprom_device *eeprom)
366
{
367
  DTRACE(eeprom, ("start-erasing-chip\n"));
368
  memset(eeprom->memory, 0, eeprom->sizeof_memory);
369
  eeprom->program_start_time = device_event_queue_time(me);
370
  eeprom->program_finish_time = (eeprom->program_start_time
371
                                 + eeprom->erase_delay);
372
}
373
 
374
static void
375
finish_erasing_chip(device *me,
376
                    hw_eeprom_device *eeprom)
377
{
378
  DTRACE(eeprom, ("finish-erasing-chip\n"));
379
  memset(eeprom->memory, 0xff, eeprom->sizeof_memory);
380
  dump_eeprom(me, eeprom);
381
}
382
 
383
 
384
/* erase a single sector of the eeprom */
385
 
386
static void
387
start_erasing_sector(device *me,
388
                     hw_eeprom_device *eeprom,
389
                     unsigned_word address)
390
{
391
  int sector = address / eeprom->sizeof_sector;
392
  DTRACE(eeprom, ("start-erasing-sector - address 0x%lx, sector %d\n",
393
                  (unsigned long)address, sector));
394
  ASSERT(sector < eeprom->nr_sectors);
395
  eeprom->sectors[sector] = 1;
396
  memset(eeprom->memory + sector * eeprom->sizeof_sector,
397
         0x4, eeprom->sizeof_sector);
398
  eeprom->program_start_time = device_event_queue_time(me);
399
  eeprom->sector_start_time = (eeprom->program_start_time
400
                               + eeprom->sector_start_delay);
401
  eeprom->program_finish_time = (eeprom->sector_start_time
402
                                 + eeprom->erase_delay);
403
 
404
}
405
 
406
static void
407
finish_erasing_sector(device *me,
408
                      hw_eeprom_device *eeprom)
409
{
410
  int sector;
411
  DTRACE(eeprom, ("finish-erasing-sector\n"));
412
  for (sector = 0; sector < eeprom->nr_sectors; sector++) {
413
    if (eeprom->sectors[sector]) {
414
      eeprom->sectors[sector] = 0;
415
      memset(eeprom->memory + sector * eeprom->sizeof_sector,
416
             0xff, eeprom->sizeof_sector);
417
    }
418
  }
419
  dump_eeprom(me, eeprom);
420
}
421
 
422
 
423
/* eeprom reads */
424
 
425
static unsigned8
426
toggle(hw_eeprom_device *eeprom,
427
       unsigned8 byte)
428
{
429
  eeprom->toggle_bit = eeprom->toggle_bit ^ 0x40; /* le-bit 6 */
430
  return eeprom->toggle_bit ^ byte;
431
}
432
 
433
static unsigned8
434
read_byte(device *me,
435
          hw_eeprom_device *eeprom,
436
          unsigned_word address)
437
{
438
  /* may need multiple iterations of this */
439
  while (1) {
440
    switch (eeprom->state) {
441
 
442
    case read_reset:
443
      return eeprom->memory[address];
444
 
445
    case autoselect:
446
      if ((address & 0xff) == 0x00)
447
        return eeprom->manufacture_code;
448
      else if ((address & 0xff) == 0x01)
449
        return eeprom->device_code;
450
      else
451
        return 0; /* not certain about this */
452
 
453
    case byte_programming:
454
      if (device_event_queue_time(me) > eeprom->program_finish_time) {
455
        finish_programming_byte(me, eeprom);
456
        eeprom->state = read_reset;
457
        continue;
458
      }
459
      else if (address == eeprom->byte_program_address) {
460
        return toggle(eeprom, eeprom->memory[address]);
461
      }
462
      else {
463
        /* trash that memory location */
464
        invalid_read(me, eeprom->state, address, "not byte program address");
465
        eeprom->memory[address] = (eeprom->memory[address]
466
                                   & eeprom->byte_program_byte);
467
        return toggle(eeprom, eeprom->memory[eeprom->byte_program_address]);
468
      }
469
 
470
    case chip_erase:
471
      if (device_event_queue_time(me) > eeprom->program_finish_time) {
472
        finish_erasing_chip(me, eeprom);
473
        eeprom->state = read_reset;
474
        continue;
475
      }
476
      else {
477
        return toggle(eeprom, eeprom->memory[address]);
478
      }
479
 
480
    case sector_erase:
481
      if (device_event_queue_time(me) > eeprom->program_finish_time) {
482
        finish_erasing_sector(me, eeprom);
483
        eeprom->state = read_reset;
484
        continue;
485
      }
486
      else if (!eeprom->sectors[address / eeprom->sizeof_sector]) {
487
        /* read to wrong sector */
488
        invalid_read(me, eeprom->state, address, "sector not being erased");
489
        return toggle(eeprom, eeprom->memory[address]) & ~0x8;
490
      }
491
      else if (device_event_queue_time(me) > eeprom->sector_start_time) {
492
        return toggle(eeprom, eeprom->memory[address]) | 0x8;
493
      }
494
      else {
495
        return toggle(eeprom, eeprom->memory[address]) & ~0x8;
496
      }
497
 
498
    case sector_erase_suspend:
499
      if (!eeprom->sectors[address / eeprom->sizeof_sector]) {
500
        return eeprom->memory[address];
501
      }
502
      else {
503
        invalid_read(me, eeprom->state, address, "sector being erased");
504
        return eeprom->memory[address];
505
      }
506
 
507
    default:
508
      invalid_read(me, eeprom->state, address, "invalid state");
509
      return eeprom->memory[address];
510
 
511
    }
512
  }
513
  return 0;
514
}
515
 
516
static unsigned
517
hw_eeprom_io_read_buffer(device *me,
518
                         void *dest,
519
                         int space,
520
                         unsigned_word addr,
521
                         unsigned nr_bytes,
522
                         cpu *processor,
523
                         unsigned_word cia)
524
{
525
  hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
526
  int i;
527
  for (i = 0; i < nr_bytes; i++) {
528
    unsigned_word address = (addr + i) % eeprom->sizeof_memory;
529
    unsigned8 byte = read_byte(me, eeprom, address);
530
    ((unsigned8*)dest)[i] = byte;
531
  }
532
  return nr_bytes;
533
}
534
 
535
 
536
/* eeprom writes */
537
 
538
static void
539
write_byte(device *me,
540
           hw_eeprom_device *eeprom,
541
           unsigned_word address,
542
           unsigned8 data)
543
{
544
  /* may need multiple transitions to process a write */
545
  while (1) {
546
    switch (eeprom->state) {
547
 
548
    case read_reset:
549
      if (address == 0x5555 && data == 0xaa)
550
        eeprom->state = write_nr_2;
551
      else if (data == 0xf0)
552
        eeprom->state = read_reset;
553
      else {
554
        invalid_write(me, eeprom->state, address, data, "unexpected");
555
        eeprom->state = read_reset;
556
      }
557
      return;
558
 
559
    case write_nr_2:
560
      if (address == 0x2aaa && data == 0x55)
561
        eeprom->state = write_nr_3;
562
      else {
563
        invalid_write(me, eeprom->state, address, data, "unexpected");
564
        eeprom->state = read_reset;
565
      }
566
      return;
567
 
568
    case write_nr_3:
569
      if (address == 0x5555 && data == 0xf0)
570
        eeprom->state = read_reset;
571
      else if (address == 0x5555 && data == 0x90)
572
        eeprom->state = autoselect;
573
      else if (address == 0x5555 && data == 0xa0) {
574
        eeprom->state = byte_program;
575
      }
576
      else if (address == 0x5555 && data == 0x80)
577
        eeprom->state = write_nr_4;
578
      else {
579
        invalid_write(me, eeprom->state, address, data, "unexpected");
580
        eeprom->state = read_reset;
581
      }
582
      return;
583
 
584
    case write_nr_4:
585
      if (address == 0x5555 && data == 0xaa)
586
        eeprom->state = write_nr_5;
587
      else {
588
        invalid_write(me, eeprom->state, address, data, "unexpected");
589
        eeprom->state = read_reset;
590
      }
591
      return;
592
 
593
    case write_nr_5:
594
      if (address == 0x2aaa && data == 0x55)
595
        eeprom->state = write_nr_6;
596
      else {
597
        invalid_write(me, eeprom->state, address, data, "unexpected");
598
        eeprom->state = read_reset;
599
      }
600
      return;
601
 
602
    case write_nr_6:
603
      if (address == 0x5555 && data == 0x10) {
604
        start_erasing_chip(me, eeprom);
605
        eeprom->state = chip_erase;
606
      }
607
      else {
608
        start_erasing_sector(me, eeprom, address);
609
        eeprom->sector_state = read_reset;
610
        eeprom->state = sector_erase;
611
      }
612
      return;
613
 
614
    case autoselect:
615
      if (data == 0xf0)
616
        eeprom->state = read_reset;
617
      else if (address == 0x5555 && data == 0xaa)
618
        eeprom->state = write_nr_2;
619
      else {
620
        invalid_write(me, eeprom->state, address, data, "unsupported address");
621
        eeprom->state = read_reset;
622
      }
623
      return;
624
 
625
    case byte_program:
626
      start_programming_byte(me, eeprom, address, data);
627
      eeprom->state = byte_programming;
628
      return;
629
 
630
    case byte_programming:
631
      if (device_event_queue_time(me) > eeprom->program_finish_time) {
632
        finish_programming_byte(me, eeprom);
633
        eeprom->state = read_reset;
634
        continue;
635
      }
636
      /* ignore it */
637
      return;
638
 
639
    case chip_erase:
640
      if (device_event_queue_time(me) > eeprom->program_finish_time) {
641
        finish_erasing_chip(me, eeprom);
642
        eeprom->state = read_reset;
643
        continue;
644
      }
645
      /* ignore it */
646
      return;
647
 
648
    case sector_erase:
649
      if (device_event_queue_time(me) > eeprom->program_finish_time) {
650
        finish_erasing_sector(me, eeprom);
651
        eeprom->state = eeprom->sector_state;
652
        continue;
653
      }
654
      else if (device_event_queue_time(me) > eeprom->sector_start_time
655
               && data == 0xb0) {
656
        eeprom->sector_state = read_reset;
657
        eeprom->state = sector_erase_suspend;
658
      }
659
      else {
660
        if (eeprom->sector_state == read_reset
661
            && address == 0x5555 && data == 0xaa)
662
          eeprom->sector_state = write_nr_2;
663
        else if (eeprom->sector_state == write_nr_2
664
                 && address == 0x2aaa && data == 0x55)
665
          eeprom->sector_state = write_nr_3;
666
        else if (eeprom->sector_state == write_nr_3
667
                 && address == 0x5555 && data == 0x80)
668
          eeprom->sector_state = write_nr_4;
669
        else if (eeprom->sector_state == write_nr_4
670
                 && address == 0x5555 && data == 0xaa)
671
          eeprom->sector_state = write_nr_5;
672
        else if (eeprom->sector_state == write_nr_5
673
                 && address == 0x2aaa && data == 0x55)
674
          eeprom->sector_state = write_nr_6;
675
        else if (eeprom->sector_state == write_nr_6
676
                 && address != 0x5555 && data == 0x30) {
677
          if (device_event_queue_time(me) > eeprom->sector_start_time) {
678
            DTRACE(eeprom, ("sector erase command after window closed\n"));
679
            eeprom->sector_state = read_reset;
680
          }
681
          else {
682
            start_erasing_sector(me, eeprom, address);
683
            eeprom->sector_state = read_reset;
684
          }
685
        }
686
        else {
687
          invalid_write(me, eeprom->state, address, data, state2a(eeprom->sector_state));
688
          eeprom->state = read_reset;
689
        }
690
      }
691
      return;
692
 
693
    case sector_erase_suspend:
694
      if (data == 0x30)
695
        eeprom->state = sector_erase;
696
      else {
697
        invalid_write(me, eeprom->state, address, data, "not resume command");
698
        eeprom->state = read_reset;
699
      }
700
      return;
701
 
702
    }
703
  }
704
}
705
 
706
static unsigned
707
hw_eeprom_io_write_buffer(device *me,
708
                          const void *source,
709
                          int space,
710
                          unsigned_word addr,
711
                          unsigned nr_bytes,
712
                          cpu *processor,
713
                          unsigned_word cia)
714
{
715
  hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
716
  int i;
717
  for (i = 0; i < nr_bytes; i++) {
718
    unsigned_word address = (addr + i) % eeprom->sizeof_memory;
719
    unsigned8 byte = ((unsigned8*)source)[i];
720
    write_byte(me, eeprom, address, byte);
721
  }
722
  return nr_bytes;
723
}
724
 
725
 
726
/* An instance of the eeprom */
727
 
728
typedef struct _hw_eeprom_instance {
729
  unsigned_word pos;
730
  hw_eeprom_device *eeprom;
731
  device *me;
732
} hw_eeprom_instance;
733
 
734
static void
735
hw_eeprom_instance_delete(device_instance *instance)
736
{
737
  hw_eeprom_instance *data = device_instance_data(instance);
738
  zfree(data);
739
}
740
 
741
static int
742
hw_eeprom_instance_read(device_instance *instance,
743
                        void *buf,
744
                        unsigned_word len)
745
{
746
  hw_eeprom_instance *data = device_instance_data(instance);
747
  int i;
748
  if (data->eeprom->state != read_reset)
749
    DITRACE(eeprom, ("eeprom not idle during instance read\n"));
750
  for (i = 0; i < len; i++) {
751
    ((unsigned8*)buf)[i] = data->eeprom->memory[data->pos];
752
    data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
753
  }
754
  return len;
755
}
756
 
757
static int
758
hw_eeprom_instance_write(device_instance *instance,
759
                         const void *buf,
760
                         unsigned_word len)
761
{
762
  hw_eeprom_instance *data = device_instance_data(instance);
763
  int i;
764
  if (data->eeprom->state != read_reset)
765
    DITRACE(eeprom, ("eeprom not idle during instance write\n"));
766
  for (i = 0; i < len; i++) {
767
    data->eeprom->memory[data->pos] = ((unsigned8*)buf)[i];
768
    data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
769
  }
770
  dump_eeprom(data->me, data->eeprom);
771
  return len;
772
}
773
 
774
static int
775
hw_eeprom_instance_seek(device_instance *instance,
776
                      unsigned_word pos_hi,
777
                      unsigned_word pos_lo)
778
{
779
  hw_eeprom_instance *data = device_instance_data(instance);
780
  if (pos_lo >= data->eeprom->sizeof_memory)
781
    device_error(data->me, "seek value 0x%lx out of range\n",
782
                 (unsigned long)pos_lo);
783
  data->pos = pos_lo;
784
  return 0;
785
}
786
 
787
static const device_instance_callbacks hw_eeprom_instance_callbacks = {
788
  hw_eeprom_instance_delete,
789
  hw_eeprom_instance_read,
790
  hw_eeprom_instance_write,
791
  hw_eeprom_instance_seek,
792
};
793
 
794
static device_instance *
795
hw_eeprom_create_instance(device *me,
796
                          const char *path,
797
                          const char *args)
798
{
799
  hw_eeprom_device *eeprom = device_data(me);
800
  hw_eeprom_instance *data = ZALLOC(hw_eeprom_instance);
801
  data->eeprom = eeprom;
802
  data->me = me;
803
  return device_create_instance_from(me, NULL,
804
                                     data,
805
                                     path, args,
806
                                     &hw_eeprom_instance_callbacks);
807
}
808
 
809
 
810
 
811
static device_callbacks const hw_eeprom_callbacks = {
812
  { generic_device_init_address,
813
    hw_eeprom_init_data },
814
  { NULL, }, /* address */
815
  { hw_eeprom_io_read_buffer,
816
    hw_eeprom_io_write_buffer }, /* IO */
817
  { NULL, }, /* DMA */
818
  { NULL, }, /* interrupt */
819
  { NULL, }, /* unit */
820
  hw_eeprom_create_instance,
821
};
822
 
823
static void *
824
hw_eeprom_create(const char *name,
825
                 const device_unit *unit_address,
826
                 const char *args)
827
{
828
  hw_eeprom_device *eeprom = ZALLOC(hw_eeprom_device);
829
  return eeprom;
830
}
831
 
832
 
833
 
834
const device_descriptor hw_eeprom_device_descriptor[] = {
835
  { "eeprom", hw_eeprom_create, &hw_eeprom_callbacks },
836
  { NULL },
837
};
838
 
839
#endif /* _HW_EEPROM_C_ */

powered by: WebSVN 2.1.0

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