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 *
state2a(hw_eeprom_states state)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
hw_eeprom_init_data(device * me)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
invalid_read(device * me,hw_eeprom_states state,unsigned_word address,const char * reason)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
invalid_write(device * me,hw_eeprom_states state,unsigned_word address,unsigned8 data,const char * reason)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
dump_eeprom(device * me,hw_eeprom_device * eeprom)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
start_programming_byte(device * me,hw_eeprom_device * eeprom,unsigned_word address,unsigned8 new_byte)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
finish_programming_byte(device * me,hw_eeprom_device * eeprom)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
start_erasing_chip(device * me,hw_eeprom_device * eeprom)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
finish_erasing_chip(device * me,hw_eeprom_device * eeprom)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
start_erasing_sector(device * me,hw_eeprom_device * eeprom,unsigned_word address)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
finish_erasing_sector(device * me,hw_eeprom_device * eeprom)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
toggle(hw_eeprom_device * eeprom,unsigned8 byte)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
read_byte(device * me,hw_eeprom_device * eeprom,unsigned_word address)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
hw_eeprom_io_read_buffer(device * me,void * dest,int space,unsigned_word addr,unsigned nr_bytes,cpu * processor,unsigned_word cia)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
write_byte(device * me,hw_eeprom_device * eeprom,unsigned_word address,unsigned8 data)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
hw_eeprom_io_write_buffer(device * me,const void * source,int space,unsigned_word addr,unsigned nr_bytes,cpu * processor,unsigned_word cia)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
hw_eeprom_instance_delete(device_instance * instance)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
hw_eeprom_instance_read(device_instance * instance,void * buf,unsigned_word len)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
hw_eeprom_instance_write(device_instance * instance,const void * buf,unsigned_word len)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
hw_eeprom_instance_seek(device_instance * instance,unsigned_word pos_hi,unsigned_word pos_lo)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 *
hw_eeprom_create_instance(device * me,const char * path,const char * args)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 *
hw_eeprom_create(const char * name,const device_unit * unit_address,const char * args)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_ */
840