1 1.1 christos /* dv-m68hc11eepr.c -- Simulation of the 68HC11 Internal EEPROM. 2 1.1.1.10 christos Copyright (C) 1999-2024 Free Software Foundation, Inc. 3 1.1 christos Written by Stephane Carrez (stcarrez (at) nerim.fr) 4 1.1 christos (From a driver model Contributed by Cygnus Solutions.) 5 1.1 christos 6 1.1 christos This program is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3 of the License, or 9 1.1 christos (at your option) any later version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. 18 1.1 christos 19 1.1 christos */ 20 1.1 christos 21 1.1.1.9 christos /* This must come before any other includes. */ 22 1.1.1.9 christos #include "defs.h" 23 1.1 christos 24 1.1 christos #include "sim-main.h" 25 1.1 christos #include "hw-main.h" 26 1.1 christos #include "sim-assert.h" 27 1.1 christos #include "sim-events.h" 28 1.1.1.9 christos #include "sim-signal.h" 29 1.1 christos 30 1.1 christos #include <unistd.h> 31 1.1 christos #include <fcntl.h> 32 1.1 christos #include <errno.h> 33 1.1 christos 34 1.1.1.10 christos #include "m68hc11-sim.h" 35 1.1 christos 36 1.1 christos /* DEVICE 37 1.1 christos 38 1.1 christos m68hc11eepr - m68hc11 EEPROM 39 1.1 christos 40 1.1 christos 41 1.1 christos DESCRIPTION 42 1.1 christos 43 1.1 christos Implements the 68HC11 eeprom device described in the m68hc11 44 1.1 christos user guide (Chapter 4 in the pink book). 45 1.1 christos 46 1.1 christos 47 1.1 christos PROPERTIES 48 1.1 christos 49 1.1 christos reg <base> <length> 50 1.1 christos 51 1.1 christos Base of eeprom and its length. 52 1.1 christos 53 1.1 christos file <path> 54 1.1 christos 55 1.1 christos Path of the EEPROM file. The default is 'm6811.eeprom'. 56 1.1 christos 57 1.1 christos 58 1.1 christos PORTS 59 1.1 christos 60 1.1 christos None 61 1.1 christos 62 1.1 christos */ 63 1.1 christos 64 1.1 christos 65 1.1 christos 66 1.1 christos /* static functions */ 67 1.1 christos 68 1.1 christos 69 1.1 christos /* port ID's */ 70 1.1 christos 71 1.1 christos enum 72 1.1 christos { 73 1.1 christos RESET_PORT 74 1.1 christos }; 75 1.1 christos 76 1.1 christos 77 1.1 christos static const struct hw_port_descriptor m68hc11eepr_ports[] = 78 1.1 christos { 79 1.1 christos { "reset", RESET_PORT, 0, input_port, }, 80 1.1 christos { NULL, }, 81 1.1 christos }; 82 1.1 christos 83 1.1 christos 84 1.1 christos 85 1.1 christos /* The timer/counter register internal state. Note that we store 86 1.1 christos state using the control register images, in host endian order. */ 87 1.1 christos 88 1.1 christos struct m68hc11eepr 89 1.1 christos { 90 1.1 christos address_word base_address; /* control register base */ 91 1.1 christos int attach_space; 92 1.1 christos unsigned size; 93 1.1 christos int mapped; 94 1.1 christos 95 1.1 christos /* Current state of the eeprom programing: 96 1.1 christos - eeprom_wmode indicates whether the EEPROM address and byte have 97 1.1 christos been latched. 98 1.1 christos - eeprom_waddr indicates the EEPROM address that was latched 99 1.1 christos and eeprom_wbyte is the byte that was latched. 100 1.1 christos - eeprom_wcycle indicates the CPU absolute cycle type when 101 1.1 christos the high voltage was applied (successfully) on the EEPROM. 102 1.1 christos 103 1.1 christos These data members are setup only when we detect good EEPROM programing 104 1.1 christos conditions (see Motorola EEPROM Programming and PPROG register usage). 105 1.1 christos When the high voltage is switched off, we look at the CPU absolute 106 1.1 christos cycle time to see if the EEPROM command must succeeds or not. 107 1.1 christos The EEPROM content is updated and saved only at that time. 108 1.1 christos (EEPROM command is: byte zero bits program, byte erase, row erase 109 1.1 christos and bulk erase). 110 1.1 christos 111 1.1 christos The CONFIG register is programmed in the same way. It is physically 112 1.1 christos located at the end of the EEPROM (eeprom size + 1). It is not mapped 113 1.1 christos in memory but it's saved in the EEPROM file. */ 114 1.1 christos unsigned long eeprom_wcycle; 115 1.1.1.9 christos uint16_t eeprom_waddr; 116 1.1.1.9 christos uint8_t eeprom_wbyte; 117 1.1.1.9 christos uint8_t eeprom_wmode; 118 1.1 christos 119 1.1.1.9 christos uint8_t* eeprom; 120 1.1 christos 121 1.1 christos /* Minimum time in CPU cycles for programming the EEPROM. */ 122 1.1 christos unsigned long eeprom_min_cycles; 123 1.1 christos 124 1.1 christos const char* file_name; 125 1.1 christos }; 126 1.1 christos 127 1.1 christos 128 1.1 christos 129 1.1 christos /* Finish off the partially created hw device. Attach our local 130 1.1 christos callbacks. Wire up our port names etc. */ 131 1.1 christos 132 1.1 christos static hw_io_read_buffer_method m68hc11eepr_io_read_buffer; 133 1.1 christos static hw_io_write_buffer_method m68hc11eepr_io_write_buffer; 134 1.1 christos static hw_ioctl_method m68hc11eepr_ioctl; 135 1.1 christos 136 1.1 christos /* Read or write the memory bank content from/to a file. 137 1.1 christos Returns 0 if the operation succeeded and -1 if it failed. */ 138 1.1 christos static int 139 1.1 christos m6811eepr_memory_rw (struct m68hc11eepr *controller, int mode) 140 1.1 christos { 141 1.1 christos const char *name = controller->file_name; 142 1.1 christos int fd; 143 1.1 christos size_t size; 144 1.1 christos 145 1.1 christos size = controller->size; 146 1.1 christos fd = open (name, mode, 0644); 147 1.1 christos if (fd < 0) 148 1.1 christos { 149 1.1 christos if (mode == O_RDONLY) 150 1.1 christos { 151 1.1 christos memset (controller->eeprom, 0xFF, size); 152 1.1 christos /* Default value for CONFIG register (0xFF should be ok): 153 1.1 christos controller->eeprom[size - 1] = M6811_NOSEC | M6811_NOCOP 154 1.1 christos | M6811_ROMON | M6811_EEON; */ 155 1.1 christos return 0; 156 1.1 christos } 157 1.1 christos return -1; 158 1.1 christos } 159 1.1 christos 160 1.1 christos if (mode == O_RDONLY) 161 1.1 christos { 162 1.1 christos if (read (fd, controller->eeprom, size) != size) 163 1.1 christos { 164 1.1 christos close (fd); 165 1.1 christos return -1; 166 1.1 christos } 167 1.1 christos } 168 1.1 christos else 169 1.1 christos { 170 1.1 christos if (write (fd, controller->eeprom, size) != size) 171 1.1 christos { 172 1.1 christos close (fd); 173 1.1 christos return -1; 174 1.1 christos } 175 1.1 christos } 176 1.1 christos close (fd); 177 1.1 christos 178 1.1 christos return 0; 179 1.1 christos } 180 1.1 christos 181 1.1 christos 182 1.1 christos 183 1.1 christos 184 1.1 christos static void 185 1.1 christos attach_m68hc11eepr_regs (struct hw *me, 186 1.1 christos struct m68hc11eepr *controller) 187 1.1 christos { 188 1.1 christos unsigned_word attach_address; 189 1.1 christos int attach_space; 190 1.1 christos unsigned attach_size; 191 1.1 christos reg_property_spec reg; 192 1.1 christos 193 1.1 christos if (hw_find_property (me, "reg") == NULL) 194 1.1 christos hw_abort (me, "Missing \"reg\" property"); 195 1.1 christos 196 1.1 christos if (!hw_find_reg_array_property (me, "reg", 0, ®)) 197 1.1 christos hw_abort (me, "\"reg\" property must contain one addr/size entry"); 198 1.1 christos 199 1.1 christos hw_unit_address_to_attach_address (hw_parent (me), 200 1.1 christos ®.address, 201 1.1 christos &attach_space, 202 1.1 christos &attach_address, 203 1.1 christos me); 204 1.1 christos hw_unit_size_to_attach_size (hw_parent (me), 205 1.1 christos ®.size, 206 1.1 christos &attach_size, me); 207 1.1 christos 208 1.1 christos /* Attach the two IO registers that control the EEPROM. 209 1.1 christos The EEPROM is only attached at reset time because it may 210 1.1 christos be enabled/disabled by the EEON bit in the CONFIG register. */ 211 1.1 christos hw_attach_address (hw_parent (me), M6811_IO_LEVEL, 212 1.1 christos io_map, M6811_PPROG, 1, me); 213 1.1 christos hw_attach_address (hw_parent (me), M6811_IO_LEVEL, 214 1.1 christos io_map, M6811_CONFIG, 1, me); 215 1.1 christos 216 1.1 christos if (hw_find_property (me, "file") == NULL) 217 1.1 christos controller->file_name = "m6811.eeprom"; 218 1.1 christos else 219 1.1 christos controller->file_name = hw_find_string_property (me, "file"); 220 1.1 christos 221 1.1 christos controller->attach_space = attach_space; 222 1.1 christos controller->base_address = attach_address; 223 1.1.1.6 christos controller->eeprom = hw_malloc (me, attach_size + 1); 224 1.1 christos controller->eeprom_min_cycles = 10000; 225 1.1 christos controller->size = attach_size + 1; 226 1.1 christos controller->mapped = 0; 227 1.1 christos 228 1.1 christos m6811eepr_memory_rw (controller, O_RDONLY); 229 1.1 christos } 230 1.1 christos 231 1.1 christos 232 1.1 christos /* An event arrives on an interrupt port. */ 233 1.1 christos 234 1.1 christos static void 235 1.1 christos m68hc11eepr_port_event (struct hw *me, 236 1.1 christos int my_port, 237 1.1 christos struct hw *source, 238 1.1 christos int source_port, 239 1.1 christos int level) 240 1.1 christos { 241 1.1 christos SIM_DESC sd; 242 1.1 christos struct m68hc11eepr *controller; 243 1.1 christos sim_cpu *cpu; 244 1.1.1.10 christos struct m68hc11_sim_cpu *m68hc11_cpu; 245 1.1 christos 246 1.1 christos controller = hw_data (me); 247 1.1 christos sd = hw_system (me); 248 1.1 christos cpu = STATE_CPU (sd, 0); 249 1.1.1.10 christos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 250 1.1 christos switch (my_port) 251 1.1 christos { 252 1.1 christos case RESET_PORT: 253 1.1 christos { 254 1.1 christos HW_TRACE ((me, "EEPROM reset")); 255 1.1 christos 256 1.1 christos /* Re-read the EEPROM from the file. This gives the chance 257 1.1 christos to users to erase this file before doing a reset and have 258 1.1 christos a fresh EEPROM taken into account. */ 259 1.1 christos m6811eepr_memory_rw (controller, O_RDONLY); 260 1.1 christos 261 1.1 christos /* Reset the state of EEPROM programmer. The CONFIG register 262 1.1 christos is also initialized from the EEPROM/file content. */ 263 1.1.1.10 christos m68hc11_cpu->ios[M6811_PPROG] = 0; 264 1.1.1.10 christos if (m68hc11_cpu->cpu_use_local_config) 265 1.1.1.10 christos m68hc11_cpu->ios[M6811_CONFIG] = m68hc11_cpu->cpu_config; 266 1.1 christos else 267 1.1.1.10 christos m68hc11_cpu->ios[M6811_CONFIG] = controller->eeprom[controller->size-1]; 268 1.1 christos controller->eeprom_wmode = 0; 269 1.1 christos controller->eeprom_waddr = 0; 270 1.1 christos controller->eeprom_wbyte = 0; 271 1.1 christos 272 1.1 christos /* Attach or detach to the bus depending on the EEPROM enable bit. 273 1.1 christos The EEPROM CONFIG register is still enabled and can be programmed 274 1.1 christos for a next configuration (taken into account only after a reset, 275 1.1 christos see Motorola spec). */ 276 1.1.1.10 christos if (!(m68hc11_cpu->ios[M6811_CONFIG] & M6811_EEON)) 277 1.1 christos { 278 1.1 christos if (controller->mapped) 279 1.1 christos hw_detach_address (hw_parent (me), M6811_EEPROM_LEVEL, 280 1.1 christos controller->attach_space, 281 1.1 christos controller->base_address, 282 1.1 christos controller->size - 1, 283 1.1 christos me); 284 1.1 christos controller->mapped = 0; 285 1.1 christos } 286 1.1 christos else 287 1.1 christos { 288 1.1 christos if (!controller->mapped) 289 1.1 christos hw_attach_address (hw_parent (me), M6811_EEPROM_LEVEL, 290 1.1 christos controller->attach_space, 291 1.1 christos controller->base_address, 292 1.1 christos controller->size - 1, 293 1.1 christos me); 294 1.1 christos controller->mapped = 1; 295 1.1 christos } 296 1.1 christos break; 297 1.1 christos } 298 1.1 christos 299 1.1 christos default: 300 1.1 christos hw_abort (me, "Event on unknown port %d", my_port); 301 1.1 christos break; 302 1.1 christos } 303 1.1 christos } 304 1.1 christos 305 1.1 christos 306 1.1 christos static void 307 1.1 christos m68hc11eepr_finish (struct hw *me) 308 1.1 christos { 309 1.1 christos struct m68hc11eepr *controller; 310 1.1 christos 311 1.1 christos controller = HW_ZALLOC (me, struct m68hc11eepr); 312 1.1 christos set_hw_data (me, controller); 313 1.1 christos set_hw_io_read_buffer (me, m68hc11eepr_io_read_buffer); 314 1.1 christos set_hw_io_write_buffer (me, m68hc11eepr_io_write_buffer); 315 1.1 christos set_hw_ports (me, m68hc11eepr_ports); 316 1.1 christos set_hw_port_event (me, m68hc11eepr_port_event); 317 1.1 christos #ifdef set_hw_ioctl 318 1.1 christos set_hw_ioctl (me, m68hc11eepr_ioctl); 319 1.1 christos #else 320 1.1 christos me->to_ioctl = m68hc11eepr_ioctl; 321 1.1 christos #endif 322 1.1 christos 323 1.1 christos attach_m68hc11eepr_regs (me, controller); 324 1.1 christos } 325 1.1 christos 326 1.1 christos 327 1.1 christos 328 1.1 christos static io_reg_desc pprog_desc[] = { 329 1.1 christos { M6811_BYTE, "BYTE ", "Byte Program Mode" }, 330 1.1 christos { M6811_ROW, "ROW ", "Row Program Mode" }, 331 1.1 christos { M6811_ERASE, "ERASE ", "Erase Mode" }, 332 1.1 christos { M6811_EELAT, "EELAT ", "EEProm Latch Control" }, 333 1.1 christos { M6811_EEPGM, "EEPGM ", "EEProm Programming Voltable Enable" }, 334 1.1 christos { 0, 0, 0 } 335 1.1 christos }; 336 1.1 christos extern io_reg_desc config_desc[]; 337 1.1 christos 338 1.1 christos 339 1.1 christos /* Describe the state of the EEPROM device. */ 340 1.1 christos static void 341 1.1 christos m68hc11eepr_info (struct hw *me) 342 1.1 christos { 343 1.1 christos SIM_DESC sd; 344 1.1.1.9 christos uint16_t base = 0; 345 1.1 christos sim_cpu *cpu; 346 1.1.1.10 christos struct m68hc11_sim_cpu *m68hc11_cpu; 347 1.1 christos struct m68hc11eepr *controller; 348 1.1.1.9 christos uint8_t val; 349 1.1 christos 350 1.1 christos sd = hw_system (me); 351 1.1 christos cpu = STATE_CPU (sd, 0); 352 1.1.1.10 christos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 353 1.1 christos controller = hw_data (me); 354 1.1 christos base = cpu_get_io_base (cpu); 355 1.1 christos 356 1.1 christos sim_io_printf (sd, "M68HC11 EEprom:\n"); 357 1.1 christos 358 1.1.1.10 christos val = m68hc11_cpu->ios[M6811_PPROG]; 359 1.1 christos print_io_byte (sd, "PPROG ", pprog_desc, val, base + M6811_PPROG); 360 1.1 christos sim_io_printf (sd, "\n"); 361 1.1 christos 362 1.1.1.10 christos val = m68hc11_cpu->ios[M6811_CONFIG]; 363 1.1 christos print_io_byte (sd, "CONFIG ", config_desc, val, base + M6811_CONFIG); 364 1.1 christos sim_io_printf (sd, "\n"); 365 1.1 christos 366 1.1 christos val = controller->eeprom[controller->size - 1]; 367 1.1 christos print_io_byte (sd, "(*NEXT*) ", config_desc, val, base + M6811_CONFIG); 368 1.1 christos sim_io_printf (sd, "\n"); 369 1.1 christos 370 1.1 christos /* Describe internal state of EEPROM. */ 371 1.1 christos if (controller->eeprom_wmode) 372 1.1 christos { 373 1.1 christos if (controller->eeprom_waddr == controller->size - 1) 374 1.1 christos sim_io_printf (sd, " Programming CONFIG register "); 375 1.1 christos else 376 1.1 christos sim_io_printf (sd, " Programming: 0x%04x ", 377 1.1 christos controller->eeprom_waddr + controller->base_address); 378 1.1 christos 379 1.1 christos sim_io_printf (sd, "with 0x%02x\n", 380 1.1 christos controller->eeprom_wbyte); 381 1.1 christos } 382 1.1 christos 383 1.1 christos sim_io_printf (sd, " EEProm file: %s\n", 384 1.1 christos controller->file_name); 385 1.1 christos } 386 1.1 christos 387 1.1 christos static int 388 1.1 christos m68hc11eepr_ioctl (struct hw *me, 389 1.1 christos hw_ioctl_request request, 390 1.1 christos va_list ap) 391 1.1 christos { 392 1.1 christos m68hc11eepr_info (me); 393 1.1 christos return 0; 394 1.1 christos } 395 1.1 christos 396 1.1 christos /* generic read/write */ 397 1.1 christos 398 1.1 christos static unsigned 399 1.1 christos m68hc11eepr_io_read_buffer (struct hw *me, 400 1.1 christos void *dest, 401 1.1 christos int space, 402 1.1 christos unsigned_word base, 403 1.1 christos unsigned nr_bytes) 404 1.1 christos { 405 1.1 christos SIM_DESC sd; 406 1.1 christos struct m68hc11eepr *controller; 407 1.1 christos sim_cpu *cpu; 408 1.1.1.10 christos struct m68hc11_sim_cpu *m68hc11_cpu; 409 1.1 christos 410 1.1 christos HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); 411 1.1 christos 412 1.1 christos sd = hw_system (me); 413 1.1 christos controller = hw_data (me); 414 1.1 christos cpu = STATE_CPU (sd, 0); 415 1.1.1.10 christos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 416 1.1 christos 417 1.1 christos if (space == io_map) 418 1.1 christos { 419 1.1 christos unsigned cnt = 0; 420 1.1 christos 421 1.1 christos while (nr_bytes != 0) 422 1.1 christos { 423 1.1 christos switch (base) 424 1.1 christos { 425 1.1 christos case M6811_PPROG: 426 1.1 christos case M6811_CONFIG: 427 1.1.1.10 christos *((uint8_t*) dest) = m68hc11_cpu->ios[base]; 428 1.1 christos break; 429 1.1 christos 430 1.1 christos default: 431 1.1 christos hw_abort (me, "reading wrong register 0x%04x", base); 432 1.1 christos } 433 1.1.1.9 christos dest = (uint8_t*) (dest) + 1; 434 1.1 christos base++; 435 1.1 christos nr_bytes--; 436 1.1 christos cnt++; 437 1.1 christos } 438 1.1 christos return cnt; 439 1.1 christos } 440 1.1 christos 441 1.1 christos /* In theory, we can't read the EEPROM when it's being programmed. */ 442 1.1.1.10 christos if ((m68hc11_cpu->ios[M6811_PPROG] & M6811_EELAT) != 0 443 1.1 christos && cpu_is_running (cpu)) 444 1.1 christos { 445 1.1 christos sim_memory_error (cpu, SIM_SIGBUS, base, 446 1.1 christos "EEprom not configured for reading"); 447 1.1 christos } 448 1.1 christos 449 1.1 christos base = base - controller->base_address; 450 1.1 christos memcpy (dest, &controller->eeprom[base], nr_bytes); 451 1.1 christos return nr_bytes; 452 1.1 christos } 453 1.1 christos 454 1.1 christos 455 1.1 christos static unsigned 456 1.1 christos m68hc11eepr_io_write_buffer (struct hw *me, 457 1.1 christos const void *source, 458 1.1 christos int space, 459 1.1 christos unsigned_word base, 460 1.1 christos unsigned nr_bytes) 461 1.1 christos { 462 1.1 christos SIM_DESC sd; 463 1.1 christos struct m68hc11eepr *controller; 464 1.1 christos sim_cpu *cpu; 465 1.1.1.10 christos struct m68hc11_sim_cpu *m68hc11_cpu; 466 1.1.1.9 christos uint8_t val; 467 1.1 christos 468 1.1 christos HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); 469 1.1 christos 470 1.1 christos sd = hw_system (me); 471 1.1 christos controller = hw_data (me); 472 1.1 christos cpu = STATE_CPU (sd, 0); 473 1.1.1.10 christos m68hc11_cpu = M68HC11_SIM_CPU (cpu); 474 1.1 christos 475 1.1 christos /* Programming several bytes at a time is not possible. */ 476 1.1 christos if (space != io_map && nr_bytes != 1) 477 1.1 christos { 478 1.1 christos sim_memory_error (cpu, SIM_SIGBUS, base, 479 1.1 christos "EEprom write error (only 1 byte can be programmed)"); 480 1.1 christos return 0; 481 1.1 christos } 482 1.1 christos 483 1.1 christos if (nr_bytes != 1) 484 1.1 christos hw_abort (me, "Cannot write more than 1 byte to EEPROM device at a time"); 485 1.1 christos 486 1.1.1.9 christos val = *((const uint8_t*) source); 487 1.1 christos 488 1.1 christos /* Write to the EEPROM control register. */ 489 1.1 christos if (space == io_map && base == M6811_PPROG) 490 1.1 christos { 491 1.1.1.9 christos uint8_t wrong_bits; 492 1.1.1.9 christos uint16_t addr; 493 1.1 christos 494 1.1 christos addr = base + cpu_get_io_base (cpu); 495 1.1 christos 496 1.1 christos /* Setting EELAT and EEPGM at the same time is an error. 497 1.1 christos Clearing them both is ok. */ 498 1.1.1.10 christos wrong_bits = (m68hc11_cpu->ios[M6811_PPROG] ^ val) & val; 499 1.1 christos wrong_bits &= (M6811_EELAT | M6811_EEPGM); 500 1.1 christos 501 1.1 christos if (wrong_bits == (M6811_EEPGM|M6811_EELAT)) 502 1.1 christos { 503 1.1 christos sim_memory_error (cpu, SIM_SIGBUS, addr, 504 1.1 christos "Wrong eeprom programing value"); 505 1.1 christos return 0; 506 1.1 christos } 507 1.1 christos 508 1.1 christos if ((val & M6811_EELAT) == 0) 509 1.1 christos { 510 1.1 christos val = 0; 511 1.1 christos } 512 1.1.1.10 christos if ((val & M6811_EEPGM) && !(m68hc11_cpu->ios[M6811_PPROG] & M6811_EELAT)) 513 1.1 christos { 514 1.1 christos sim_memory_error (cpu, SIM_SIGBUS, addr, 515 1.1 christos "EEProm high voltage applied after EELAT"); 516 1.1 christos } 517 1.1 christos if ((val & M6811_EEPGM) && controller->eeprom_wmode == 0) 518 1.1 christos { 519 1.1 christos sim_memory_error (cpu, SIM_SIGSEGV, addr, 520 1.1 christos "EEProm high voltage applied without address"); 521 1.1 christos } 522 1.1 christos if (val & M6811_EEPGM) 523 1.1 christos { 524 1.1 christos controller->eeprom_wcycle = cpu_current_cycle (cpu); 525 1.1 christos } 526 1.1.1.10 christos else if (m68hc11_cpu->ios[M6811_PPROG] & M6811_PPROG) 527 1.1 christos { 528 1.1 christos int i; 529 1.1 christos unsigned long t = cpu_current_cycle (cpu); 530 1.1 christos 531 1.1 christos t -= controller->eeprom_wcycle; 532 1.1 christos if (t < controller->eeprom_min_cycles) 533 1.1 christos { 534 1.1 christos sim_memory_error (cpu, SIM_SIGILL, addr, 535 1.1 christos "EEprom programmed only for %lu cycles", 536 1.1 christos t); 537 1.1 christos } 538 1.1 christos 539 1.1 christos /* Program the byte by clearing some bits. */ 540 1.1.1.10 christos if (!(m68hc11_cpu->ios[M6811_PPROG] & M6811_ERASE)) 541 1.1 christos { 542 1.1 christos controller->eeprom[controller->eeprom_waddr] 543 1.1 christos &= controller->eeprom_wbyte; 544 1.1 christos } 545 1.1 christos 546 1.1 christos /* Erase a byte, row or the complete eeprom. Erased value is 0xFF. 547 1.1 christos Ignore row or complete eeprom erase when we are programming the 548 1.1 christos CONFIG register (last EEPROM byte). */ 549 1.1.1.10 christos else if ((m68hc11_cpu->ios[M6811_PPROG] & M6811_BYTE) 550 1.1 christos || controller->eeprom_waddr == controller->size - 1) 551 1.1 christos { 552 1.1 christos controller->eeprom[controller->eeprom_waddr] = 0xff; 553 1.1 christos } 554 1.1.1.10 christos else if (m68hc11_cpu->ios[M6811_BYTE] & M6811_ROW) 555 1.1 christos { 556 1.1 christos size_t max_size; 557 1.1 christos 558 1.1 christos /* Size of EEPROM (-1 because the last byte is the 559 1.1 christos CONFIG register. */ 560 1.1 christos max_size = controller->size; 561 1.1 christos controller->eeprom_waddr &= 0xFFF0; 562 1.1 christos for (i = 0; i < 16 563 1.1 christos && controller->eeprom_waddr < max_size; i++) 564 1.1 christos { 565 1.1 christos controller->eeprom[controller->eeprom_waddr] = 0xff; 566 1.1 christos controller->eeprom_waddr ++; 567 1.1 christos } 568 1.1 christos } 569 1.1 christos else 570 1.1 christos { 571 1.1 christos size_t max_size; 572 1.1 christos 573 1.1 christos max_size = controller->size; 574 1.1 christos for (i = 0; i < max_size; i++) 575 1.1 christos { 576 1.1 christos controller->eeprom[i] = 0xff; 577 1.1 christos } 578 1.1 christos } 579 1.1 christos 580 1.1 christos /* Save the eeprom in a file. We have to save after each 581 1.1 christos change because the simulator can be stopped or crash... */ 582 1.1 christos if (m6811eepr_memory_rw (controller, O_WRONLY | O_CREAT) != 0) 583 1.1 christos { 584 1.1 christos sim_memory_error (cpu, SIM_SIGABRT, addr, 585 1.1 christos "EEPROM programing failed: errno=%d", errno); 586 1.1 christos } 587 1.1 christos controller->eeprom_wmode = 0; 588 1.1 christos } 589 1.1.1.10 christos m68hc11_cpu->ios[M6811_PPROG] = val; 590 1.1 christos return 1; 591 1.1 christos } 592 1.1 christos 593 1.1 christos /* The CONFIG IO register is mapped at end of EEPROM. 594 1.1 christos It's not visible. */ 595 1.1 christos if (space == io_map && base == M6811_CONFIG) 596 1.1 christos { 597 1.1 christos base = controller->size - 1; 598 1.1 christos } 599 1.1 christos else 600 1.1 christos { 601 1.1 christos base = base - controller->base_address; 602 1.1 christos } 603 1.1 christos 604 1.1 christos /* Writing the memory is allowed for the Debugger or simulator 605 1.1 christos (cpu not running). */ 606 1.1 christos if (cpu_is_running (cpu)) 607 1.1 christos { 608 1.1.1.10 christos if ((m68hc11_cpu->ios[M6811_PPROG] & M6811_EELAT) == 0) 609 1.1 christos { 610 1.1 christos sim_memory_error (cpu, SIM_SIGSEGV, base, 611 1.1 christos "EEprom not configured for writing"); 612 1.1 christos return 0; 613 1.1 christos } 614 1.1 christos if (controller->eeprom_wmode != 0) 615 1.1 christos { 616 1.1 christos sim_memory_error (cpu, SIM_SIGSEGV, base, 617 1.1 christos "EEprom write error"); 618 1.1 christos return 0; 619 1.1 christos } 620 1.1 christos controller->eeprom_wmode = 1; 621 1.1 christos controller->eeprom_waddr = base; 622 1.1 christos controller->eeprom_wbyte = val; 623 1.1 christos } 624 1.1 christos else 625 1.1 christos { 626 1.1 christos controller->eeprom[base] = val; 627 1.1 christos m6811eepr_memory_rw (controller, O_WRONLY); 628 1.1 christos } 629 1.1 christos 630 1.1 christos return 1; 631 1.1 christos } 632 1.1 christos 633 1.1 christos const struct hw_descriptor dv_m68hc11eepr_descriptor[] = { 634 1.1 christos { "m68hc11eepr", m68hc11eepr_finish }, 635 1.1 christos { "m68hc12eepr", m68hc11eepr_finish }, 636 1.1 christos { NULL }, 637 1.1 christos }; 638 1.1 christos 639