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