123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 |
- /* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- */
- #ifndef _HW_EEPROM_C_
- #define _HW_EEPROM_C_
- #include "device_table.h"
- #ifdef HAVE_STRING_H
- #include <string.h>
- #else
- #ifdef HAVE_STRINGS_H
- #include <strings.h>
- #endif
- #endif
- /* DEVICE
- eeprom - JEDEC? compatible electricaly erasable programable device
- DESCRIPTION
- This device implements a small byte addressable EEPROM.
- Programming is performed using the same write sequences as used by
- standard modern EEPROM components. Writes occure in real time, the
- device returning a progress value until the programing has been
- completed.
- It is based on the AMD 29F040 component.
- PROPERTIES
- reg = <address> <size> (required)
- Determine where the device lives in the parents address space.
- nr-sectors = <integer> (required)
- When erasing an entire sector is cleared at a time. This specifies
- the number of sectors in the EEPROM component.
- sector-size = <integer> (required)
- The number of bytes in a sector. When erasing, memory chunks of
- this size are cleared.
- NOTE: The product nr-sectors * sector-size does not need to map the
- size specified in the reg property. If the specified size is
- smaller part of the eeprom will not be accessible while if it is
- larger the addresses will wrap.
- byte-write-delay = <integer> (required)
- Number of clock ticks before the programming of a single byte
- completes.
- sector-start-delay = <integer> (required)
- When erasing sectors, the number of clock ticks after the sector
- has been specified that the actual erase process commences.
- erase-delay = <intger> (required)
- Number of clock ticks before an erase program completes
- manufacture-code = <integer> (required)
- The one byte value returned when the auto-select manufacturer code
- is read.
- device-code = <integer> (required)
- The one byte value returned when the auto-select device code is
- read.
- input-file = <file-name> (optional)
- Initialize the eeprom using the specified binary file.
- output-file = <file-name> (optional)
- When ever the eeprom is updated, save the modified image into the
- specified file.
- EXAMPLES
- Enable tracing of the eeprom:
- | bash$ psim -t eeprom-device \
- Configure something very like the Amd Am29F040 - 512byte EEPROM
- (but a bit faster):
- | -o '/eeprom@0xfff00000/reg 0xfff00000 0x80000' \
- | -o '/eeprom@0xfff00000/nr-sectors 8' \
- | -o '/eeprom@0xfff00000/sector-size 0x10000' \
- | -o '/eeprom@0xfff00000/byte-write-delay 1000' \
- | -o '/eeprom@0xfff00000/sector-start-delay 100' \
- | -o '/eeprom@0xfff00000/erase-delay 1000' \
- | -o '/eeprom@0xfff00000/manufacture-code 0x01' \
- | -o '/eeprom@0xfff00000/device-code 0xa4' \
- Initialize the eeprom from the file <</dev/zero>>:
- | -o '/eeprom@0xfff00000/input-file /dev/zero'
- BUGS
- */
- typedef enum {
- read_reset,
- write_nr_2,
- write_nr_3,
- write_nr_4,
- write_nr_5,
- write_nr_6,
- byte_program,
- byte_programming,
- chip_erase,
- sector_erase,
- sector_erase_suspend,
- autoselect,
- } hw_eeprom_states;
- static const char *
- state2a(hw_eeprom_states state)
- {
- switch (state) {
- case read_reset: return "read_reset";
- case write_nr_2: return "write_nr_2";
- case write_nr_3: return "write_nr_3";
- case write_nr_4: return "write_nr_4";
- case write_nr_5: return "write_nr_5";
- case write_nr_6: return "write_nr_6";
- case byte_program: return "byte_program";
- case byte_programming: return "byte_programming";
- case chip_erase: return "chip_erase";
- case sector_erase: return "sector_erase";
- case sector_erase_suspend: return "sector_erase_suspend";
- case autoselect: return "autoselect";
- }
- return NULL;
- }
- typedef struct _hw_eeprom_device {
- /* general */
- hw_eeprom_states state;
- unsigned8 *memory;
- unsigned sizeof_memory;
- unsigned erase_delay;
- signed64 program_start_time;
- signed64 program_finish_time;
- unsigned8 manufacture_code;
- unsigned8 device_code;
- unsigned8 toggle_bit;
- /* initialization */
- const char *input_file_name;
- const char *output_file_name;
- /* for sector and sector programming */
- hw_eeprom_states sector_state;
- unsigned8 *sectors;
- unsigned nr_sectors;
- unsigned sizeof_sector;
- unsigned sector_start_delay;
- unsigned sector_start_time;
- /* byte and byte programming */
- unsigned byte_write_delay;
- unsigned_word byte_program_address;
- unsigned8 byte_program_byte;
- } hw_eeprom_device;
- typedef struct _hw_eeprom_reg_spec {
- unsigned32 base;
- unsigned32 size;
- } hw_eeprom_reg_spec;
- static void
- hw_eeprom_init_data(device *me)
- {
- hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
- /* have we any input or output files */
- if (device_find_property(me, "input-file") != NULL)
- eeprom->input_file_name = device_find_string_property(me, "input-file");
- if (device_find_property(me, "output-file") != NULL)
- eeprom->input_file_name = device_find_string_property(me, "output-file");
- /* figure out the sectors in the eeprom */
- if (eeprom->sectors == NULL) {
- eeprom->nr_sectors = device_find_integer_property(me, "nr-sectors");
- eeprom->sizeof_sector = device_find_integer_property(me, "sector-size");
- eeprom->sectors = zalloc(eeprom->nr_sectors);
- }
- else
- memset(eeprom->sectors, 0, eeprom->nr_sectors);
- /* initialize the eeprom */
- if (eeprom->memory == NULL) {
- eeprom->sizeof_memory = eeprom->sizeof_sector * eeprom->nr_sectors;
- eeprom->memory = zalloc(eeprom->sizeof_memory);
- }
- else
- memset(eeprom->memory, 0, eeprom->sizeof_memory);
- if (eeprom->input_file_name != NULL) {
- int i;
- FILE *input_file = fopen(eeprom->input_file_name, "r");
- if (input_file == NULL) {
- perror("eeprom");
- device_error(me, "Failed to open input file %s\n", eeprom->input_file_name);
- }
- for (i = 0; i < eeprom->sizeof_memory; i++) {
- if (fread(&eeprom->memory[i], 1, 1, input_file) != 1)
- break;
- }
- fclose(input_file);
- }
- /* timing */
- eeprom->byte_write_delay = device_find_integer_property(me, "byte-write-delay");
- eeprom->sector_start_delay = device_find_integer_property(me, "sector-start-delay");
- eeprom->erase_delay = device_find_integer_property(me, "erase-delay");
- /* misc */
- eeprom->manufacture_code = device_find_integer_property(me, "manufacture-code");
- eeprom->device_code = device_find_integer_property(me, "device-code");
- }
- static void
- invalid_read(device *me,
- hw_eeprom_states state,
- unsigned_word address,
- const char *reason)
- {
- DTRACE(eeprom, ("Invalid read to 0x%lx while in state %s (%s)\n",
- (unsigned long)address,
- state2a(state),
- reason));
- }
- static void
- invalid_write(device *me,
- hw_eeprom_states state,
- unsigned_word address,
- unsigned8 data,
- const char *reason)
- {
- DTRACE(eeprom, ("Invalid write of 0x%lx to 0x%lx while in state %s (%s)\n",
- (unsigned long)data,
- (unsigned long)address,
- state2a(state),
- reason));
- }
- static void
- dump_eeprom(device *me,
- hw_eeprom_device *eeprom)
- {
- if (eeprom->output_file_name != NULL) {
- int i;
- FILE *output_file = fopen(eeprom->output_file_name, "w");
- if (output_file == NULL) {
- perror("eeprom");
- device_error(me, "Failed to open output file %s\n",
- eeprom->output_file_name);
- }
- for (i = 0; i < eeprom->sizeof_memory; i++) {
- if (fwrite(&eeprom->memory[i], 1, 1, output_file) != 1)
- break;
- }
- fclose(output_file);
- }
- }
- /* program a single byte of eeprom */
- static void
- start_programming_byte(device *me,
- hw_eeprom_device *eeprom,
- unsigned_word address,
- unsigned8 new_byte)
- {
- unsigned8 old_byte = eeprom->memory[address];
- DTRACE(eeprom, ("start-programing-byte - address 0x%lx, new 0x%lx, old 0x%lx\n",
- (unsigned long)address,
- (unsigned long)new_byte,
- (unsigned long)old_byte));
- eeprom->byte_program_address = address;
- /* : old new : ~old : new&~old
- : 0 0 : 1 : 0
- : 0 1 : 1 : 1 -- can not set a bit
- : 1 0 : 0 : 0
- : 1 1 : 0 : 0 */
- if (~old_byte & new_byte)
- invalid_write(me, eeprom->state, address, new_byte, "setting cleared bit");
- /* : old new : old&new
- : 0 0 : 0
- : 0 1 : 0
- : 1 0 : 0
- : 1 1 : 1 */
- eeprom->byte_program_byte = new_byte & old_byte;
- eeprom->memory[address] = ~new_byte & ~0x24; /* LE-bits 5:3 zero */
- eeprom->program_start_time = device_event_queue_time(me);
- eeprom->program_finish_time = (eeprom->program_start_time
- + eeprom->byte_write_delay);
- }
- static void
- finish_programming_byte(device *me,
- hw_eeprom_device *eeprom)
- {
- DTRACE(eeprom, ("finish-programming-byte - address 0x%lx, byte 0x%lx\n",
- (unsigned long)eeprom->byte_program_address,
- (unsigned long)eeprom->byte_program_byte));
- eeprom->memory[eeprom->byte_program_address] = eeprom->byte_program_byte;
- dump_eeprom(me, eeprom);
- }
- /* erase the eeprom completly */
- static void
- start_erasing_chip(device *me,
- hw_eeprom_device *eeprom)
- {
- DTRACE(eeprom, ("start-erasing-chip\n"));
- memset(eeprom->memory, 0, eeprom->sizeof_memory);
- eeprom->program_start_time = device_event_queue_time(me);
- eeprom->program_finish_time = (eeprom->program_start_time
- + eeprom->erase_delay);
- }
- static void
- finish_erasing_chip(device *me,
- hw_eeprom_device *eeprom)
- {
- DTRACE(eeprom, ("finish-erasing-chip\n"));
- memset(eeprom->memory, 0xff, eeprom->sizeof_memory);
- dump_eeprom(me, eeprom);
- }
- /* erase a single sector of the eeprom */
- static void
- start_erasing_sector(device *me,
- hw_eeprom_device *eeprom,
- unsigned_word address)
- {
- int sector = address / eeprom->sizeof_sector;
- DTRACE(eeprom, ("start-erasing-sector - address 0x%lx, sector %d\n",
- (unsigned long)address, sector));
- ASSERT(sector < eeprom->nr_sectors);
- eeprom->sectors[sector] = 1;
- memset(eeprom->memory + sector * eeprom->sizeof_sector,
- 0x4, eeprom->sizeof_sector);
- eeprom->program_start_time = device_event_queue_time(me);
- eeprom->sector_start_time = (eeprom->program_start_time
- + eeprom->sector_start_delay);
- eeprom->program_finish_time = (eeprom->sector_start_time
- + eeprom->erase_delay);
- }
- static void
- finish_erasing_sector(device *me,
- hw_eeprom_device *eeprom)
- {
- int sector;
- DTRACE(eeprom, ("finish-erasing-sector\n"));
- for (sector = 0; sector < eeprom->nr_sectors; sector++) {
- if (eeprom->sectors[sector]) {
- eeprom->sectors[sector] = 0;
- memset(eeprom->memory + sector * eeprom->sizeof_sector,
- 0xff, eeprom->sizeof_sector);
- }
- }
- dump_eeprom(me, eeprom);
- }
- /* eeprom reads */
- static unsigned8
- toggle(hw_eeprom_device *eeprom,
- unsigned8 byte)
- {
- eeprom->toggle_bit = eeprom->toggle_bit ^ 0x40; /* le-bit 6 */
- return eeprom->toggle_bit ^ byte;
- }
- static unsigned8
- read_byte(device *me,
- hw_eeprom_device *eeprom,
- unsigned_word address)
- {
- /* may need multiple iterations of this */
- while (1) {
- switch (eeprom->state) {
- case read_reset:
- return eeprom->memory[address];
- case autoselect:
- if ((address & 0xff) == 0x00)
- return eeprom->manufacture_code;
- else if ((address & 0xff) == 0x01)
- return eeprom->device_code;
- else
- return 0; /* not certain about this */
- case byte_programming:
- if (device_event_queue_time(me) > eeprom->program_finish_time) {
- finish_programming_byte(me, eeprom);
- eeprom->state = read_reset;
- continue;
- }
- else if (address == eeprom->byte_program_address) {
- return toggle(eeprom, eeprom->memory[address]);
- }
- else {
- /* trash that memory location */
- invalid_read(me, eeprom->state, address, "not byte program address");
- eeprom->memory[address] = (eeprom->memory[address]
- & eeprom->byte_program_byte);
- return toggle(eeprom, eeprom->memory[eeprom->byte_program_address]);
- }
- case chip_erase:
- if (device_event_queue_time(me) > eeprom->program_finish_time) {
- finish_erasing_chip(me, eeprom);
- eeprom->state = read_reset;
- continue;
- }
- else {
- return toggle(eeprom, eeprom->memory[address]);
- }
- case sector_erase:
- if (device_event_queue_time(me) > eeprom->program_finish_time) {
- finish_erasing_sector(me, eeprom);
- eeprom->state = read_reset;
- continue;
- }
- else if (!eeprom->sectors[address / eeprom->sizeof_sector]) {
- /* read to wrong sector */
- invalid_read(me, eeprom->state, address, "sector not being erased");
- return toggle(eeprom, eeprom->memory[address]) & ~0x8;
- }
- else if (device_event_queue_time(me) > eeprom->sector_start_time) {
- return toggle(eeprom, eeprom->memory[address]) | 0x8;
- }
- else {
- return toggle(eeprom, eeprom->memory[address]) & ~0x8;
- }
- case sector_erase_suspend:
- if (!eeprom->sectors[address / eeprom->sizeof_sector]) {
- return eeprom->memory[address];
- }
- else {
- invalid_read(me, eeprom->state, address, "sector being erased");
- return eeprom->memory[address];
- }
- default:
- invalid_read(me, eeprom->state, address, "invalid state");
- return eeprom->memory[address];
- }
- }
- return 0;
- }
-
- static unsigned
- hw_eeprom_io_read_buffer(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
- {
- hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
- int i;
- for (i = 0; i < nr_bytes; i++) {
- unsigned_word address = (addr + i) % eeprom->sizeof_memory;
- unsigned8 byte = read_byte(me, eeprom, address);
- ((unsigned8*)dest)[i] = byte;
- }
- return nr_bytes;
- }
- /* eeprom writes */
- static void
- write_byte(device *me,
- hw_eeprom_device *eeprom,
- unsigned_word address,
- unsigned8 data)
- {
- /* may need multiple transitions to process a write */
- while (1) {
- switch (eeprom->state) {
- case read_reset:
- if (address == 0x5555 && data == 0xaa)
- eeprom->state = write_nr_2;
- else if (data == 0xf0)
- eeprom->state = read_reset;
- else {
- invalid_write(me, eeprom->state, address, data, "unexpected");
- eeprom->state = read_reset;
- }
- return;
- case write_nr_2:
- if (address == 0x2aaa && data == 0x55)
- eeprom->state = write_nr_3;
- else {
- invalid_write(me, eeprom->state, address, data, "unexpected");
- eeprom->state = read_reset;
- }
- return;
- case write_nr_3:
- if (address == 0x5555 && data == 0xf0)
- eeprom->state = read_reset;
- else if (address == 0x5555 && data == 0x90)
- eeprom->state = autoselect;
- else if (address == 0x5555 && data == 0xa0) {
- eeprom->state = byte_program;
- }
- else if (address == 0x5555 && data == 0x80)
- eeprom->state = write_nr_4;
- else {
- invalid_write(me, eeprom->state, address, data, "unexpected");
- eeprom->state = read_reset;
- }
- return;
- case write_nr_4:
- if (address == 0x5555 && data == 0xaa)
- eeprom->state = write_nr_5;
- else {
- invalid_write(me, eeprom->state, address, data, "unexpected");
- eeprom->state = read_reset;
- }
- return;
- case write_nr_5:
- if (address == 0x2aaa && data == 0x55)
- eeprom->state = write_nr_6;
- else {
- invalid_write(me, eeprom->state, address, data, "unexpected");
- eeprom->state = read_reset;
- }
- return;
- case write_nr_6:
- if (address == 0x5555 && data == 0x10) {
- start_erasing_chip(me, eeprom);
- eeprom->state = chip_erase;
- }
- else {
- start_erasing_sector(me, eeprom, address);
- eeprom->sector_state = read_reset;
- eeprom->state = sector_erase;
- }
- return;
- case autoselect:
- if (data == 0xf0)
- eeprom->state = read_reset;
- else if (address == 0x5555 && data == 0xaa)
- eeprom->state = write_nr_2;
- else {
- invalid_write(me, eeprom->state, address, data, "unsupported address");
- eeprom->state = read_reset;
- }
- return;
- case byte_program:
- start_programming_byte(me, eeprom, address, data);
- eeprom->state = byte_programming;
- return;
- case byte_programming:
- if (device_event_queue_time(me) > eeprom->program_finish_time) {
- finish_programming_byte(me, eeprom);
- eeprom->state = read_reset;
- continue;
- }
- /* ignore it */
- return;
- case chip_erase:
- if (device_event_queue_time(me) > eeprom->program_finish_time) {
- finish_erasing_chip(me, eeprom);
- eeprom->state = read_reset;
- continue;
- }
- /* ignore it */
- return;
- case sector_erase:
- if (device_event_queue_time(me) > eeprom->program_finish_time) {
- finish_erasing_sector(me, eeprom);
- eeprom->state = eeprom->sector_state;
- continue;
- }
- else if (device_event_queue_time(me) > eeprom->sector_start_time
- && data == 0xb0) {
- eeprom->sector_state = read_reset;
- eeprom->state = sector_erase_suspend;
- }
- else {
- if (eeprom->sector_state == read_reset
- && address == 0x5555 && data == 0xaa)
- eeprom->sector_state = write_nr_2;
- else if (eeprom->sector_state == write_nr_2
- && address == 0x2aaa && data == 0x55)
- eeprom->sector_state = write_nr_3;
- else if (eeprom->sector_state == write_nr_3
- && address == 0x5555 && data == 0x80)
- eeprom->sector_state = write_nr_4;
- else if (eeprom->sector_state == write_nr_4
- && address == 0x5555 && data == 0xaa)
- eeprom->sector_state = write_nr_5;
- else if (eeprom->sector_state == write_nr_5
- && address == 0x2aaa && data == 0x55)
- eeprom->sector_state = write_nr_6;
- else if (eeprom->sector_state == write_nr_6
- && address != 0x5555 && data == 0x30) {
- if (device_event_queue_time(me) > eeprom->sector_start_time) {
- DTRACE(eeprom, ("sector erase command after window closed\n"));
- eeprom->sector_state = read_reset;
- }
- else {
- start_erasing_sector(me, eeprom, address);
- eeprom->sector_state = read_reset;
- }
- }
- else {
- invalid_write(me, eeprom->state, address, data, state2a(eeprom->sector_state));
- eeprom->state = read_reset;
- }
- }
- return;
- case sector_erase_suspend:
- if (data == 0x30)
- eeprom->state = sector_erase;
- else {
- invalid_write(me, eeprom->state, address, data, "not resume command");
- eeprom->state = read_reset;
- }
- return;
- }
- }
- }
- static unsigned
- hw_eeprom_io_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
- {
- hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
- int i;
- for (i = 0; i < nr_bytes; i++) {
- unsigned_word address = (addr + i) % eeprom->sizeof_memory;
- unsigned8 byte = ((unsigned8*)source)[i];
- write_byte(me, eeprom, address, byte);
- }
- return nr_bytes;
- }
- /* An instance of the eeprom */
- typedef struct _hw_eeprom_instance {
- unsigned_word pos;
- hw_eeprom_device *eeprom;
- device *me;
- } hw_eeprom_instance;
- static void
- hw_eeprom_instance_delete(device_instance *instance)
- {
- hw_eeprom_instance *data = device_instance_data(instance);
- free(data);
- }
- static int
- hw_eeprom_instance_read(device_instance *instance,
- void *buf,
- unsigned_word len)
- {
- hw_eeprom_instance *data = device_instance_data(instance);
- int i;
- if (data->eeprom->state != read_reset)
- DITRACE(eeprom, ("eeprom not idle during instance read\n"));
- for (i = 0; i < len; i++) {
- ((unsigned8*)buf)[i] = data->eeprom->memory[data->pos];
- data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
- }
- return len;
- }
- static int
- hw_eeprom_instance_write(device_instance *instance,
- const void *buf,
- unsigned_word len)
- {
- hw_eeprom_instance *data = device_instance_data(instance);
- int i;
- if (data->eeprom->state != read_reset)
- DITRACE(eeprom, ("eeprom not idle during instance write\n"));
- for (i = 0; i < len; i++) {
- data->eeprom->memory[data->pos] = ((unsigned8*)buf)[i];
- data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
- }
- dump_eeprom(data->me, data->eeprom);
- return len;
- }
- static int
- hw_eeprom_instance_seek(device_instance *instance,
- unsigned_word pos_hi,
- unsigned_word pos_lo)
- {
- hw_eeprom_instance *data = device_instance_data(instance);
- if (pos_lo >= data->eeprom->sizeof_memory)
- device_error(data->me, "seek value 0x%lx out of range\n",
- (unsigned long)pos_lo);
- data->pos = pos_lo;
- return 0;
- }
- static const device_instance_callbacks hw_eeprom_instance_callbacks = {
- hw_eeprom_instance_delete,
- hw_eeprom_instance_read,
- hw_eeprom_instance_write,
- hw_eeprom_instance_seek,
- };
- static device_instance *
- hw_eeprom_create_instance(device *me,
- const char *path,
- const char *args)
- {
- hw_eeprom_device *eeprom = device_data(me);
- hw_eeprom_instance *data = ZALLOC(hw_eeprom_instance);
- data->eeprom = eeprom;
- data->me = me;
- return device_create_instance_from(me, NULL,
- data,
- path, args,
- &hw_eeprom_instance_callbacks);
- }
- static device_callbacks const hw_eeprom_callbacks = {
- { generic_device_init_address,
- hw_eeprom_init_data },
- { NULL, }, /* address */
- { hw_eeprom_io_read_buffer,
- hw_eeprom_io_write_buffer }, /* IO */
- { NULL, }, /* DMA */
- { NULL, }, /* interrupt */
- { NULL, }, /* unit */
- hw_eeprom_create_instance,
- };
- static void *
- hw_eeprom_create(const char *name,
- const device_unit *unit_address,
- const char *args)
- {
- hw_eeprom_device *eeprom = ZALLOC(hw_eeprom_device);
- return eeprom;
- }
- const device_descriptor hw_eeprom_device_descriptor[] = {
- { "eeprom", hw_eeprom_create, &hw_eeprom_callbacks },
- { NULL },
- };
- #endif /* _HW_EEPROM_C_ */
|