]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/ppc/hw_eeprom.c
069103b5ff84cbc0bfc420c9715facbe82b90b40
[thirdparty/binutils-gdb.git] / sim / ppc / hw_eeprom.c
1 /* 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 free(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_ */