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
150typedef 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
165static const char *
166state2a(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
185typedef 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
212typedef struct _hw_eeprom_reg_spec {
213  unsigned32 base;
214  unsigned32 size;
215} hw_eeprom_reg_spec;
216
217static void
218hw_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
269static void
270invalid_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
281static void
282invalid_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
295static void
296dump_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
318static void
319start_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
349static void
350finish_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
363static void
364start_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
374static void
375finish_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
386static void
387start_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
406static void
407finish_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
425static unsigned8
426toggle(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
433static unsigned8
434read_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
516static unsigned
517hw_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
538static void
539write_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
706static unsigned
707hw_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
728typedef struct _hw_eeprom_instance {
729  unsigned_word pos;
730  hw_eeprom_device *eeprom;
731  device *me;
732} hw_eeprom_instance;
733
734static void
735hw_eeprom_instance_delete(device_instance *instance)
736{
737  hw_eeprom_instance *data = device_instance_data(instance);
738  zfree(data);
739}
740
741static int
742hw_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
757static int
758hw_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
774static int
775hw_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
787static 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
794static device_instance *
795hw_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
811static 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
823static void *
824hw_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
834const device_descriptor hw_eeprom_device_descriptor[] = {
835  { "eeprom", hw_eeprom_create, &hw_eeprom_callbacks },
836  { NULL },
837};
838
839#endif /* _HW_EEPROM_C_ */
840