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