run copyright.sh for 2011.
[external/binutils.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   zfree(data);
739 }
740
741 static int
742 hw_eeprom_instance_read(device_instance *instance,
743                         void *buf,
744                         unsigned_word len)
745 {
746   hw_eeprom_instance *data = device_instance_data(instance);
747   int i;
748   if (data->eeprom->state != read_reset)
749     DITRACE(eeprom, ("eeprom not idle during instance read\n"));
750   for (i = 0; i < len; i++) {
751     ((unsigned8*)buf)[i] = data->eeprom->memory[data->pos];
752     data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
753   }
754   return len;
755 }
756
757 static int
758 hw_eeprom_instance_write(device_instance *instance,
759                          const void *buf,
760                          unsigned_word len)
761 {
762   hw_eeprom_instance *data = device_instance_data(instance);
763   int i;
764   if (data->eeprom->state != read_reset)
765     DITRACE(eeprom, ("eeprom not idle during instance write\n"));
766   for (i = 0; i < len; i++) {
767     data->eeprom->memory[data->pos] = ((unsigned8*)buf)[i];
768     data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
769   }
770   dump_eeprom(data->me, data->eeprom);
771   return len;
772 }
773
774 static int
775 hw_eeprom_instance_seek(device_instance *instance,
776                       unsigned_word pos_hi,
777                       unsigned_word pos_lo)
778 {
779   hw_eeprom_instance *data = device_instance_data(instance);
780   if (pos_lo >= data->eeprom->sizeof_memory)
781     device_error(data->me, "seek value 0x%lx out of range\n",
782                  (unsigned long)pos_lo);
783   data->pos = pos_lo;
784   return 0;
785 }
786
787 static const device_instance_callbacks hw_eeprom_instance_callbacks = {
788   hw_eeprom_instance_delete,
789   hw_eeprom_instance_read,
790   hw_eeprom_instance_write,
791   hw_eeprom_instance_seek,
792 };
793
794 static device_instance *
795 hw_eeprom_create_instance(device *me,
796                           const char *path,
797                           const char *args)
798 {
799   hw_eeprom_device *eeprom = device_data(me);
800   hw_eeprom_instance *data = ZALLOC(hw_eeprom_instance);
801   data->eeprom = eeprom;
802   data->me = me;
803   return device_create_instance_from(me, NULL,
804                                      data,
805                                      path, args,
806                                      &hw_eeprom_instance_callbacks);
807 }
808
809
810
811 static device_callbacks const hw_eeprom_callbacks = {
812   { generic_device_init_address,
813     hw_eeprom_init_data },
814   { NULL, }, /* address */
815   { hw_eeprom_io_read_buffer,
816     hw_eeprom_io_write_buffer }, /* IO */
817   { NULL, }, /* DMA */
818   { NULL, }, /* interrupt */
819   { NULL, }, /* unit */
820   hw_eeprom_create_instance,
821 };
822
823 static void *
824 hw_eeprom_create(const char *name,
825                  const device_unit *unit_address,
826                  const char *args)
827 {
828   hw_eeprom_device *eeprom = ZALLOC(hw_eeprom_device);
829   return eeprom;
830 }
831
832
833
834 const device_descriptor hw_eeprom_device_descriptor[] = {
835   { "eeprom", hw_eeprom_create, &hw_eeprom_callbacks },
836   { NULL },
837 };
838
839 #endif /* _HW_EEPROM_C_ */