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