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