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