1 /* dv-m68hc11eepr.c -- Simulation of the 68HC11 Internal EEPROM.
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.fr)
4 (From a driver model Contributed by Cygnus Solutions.)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /* This must come before any other includes. */
26 #include "sim-assert.h"
27 #include "sim-events.h"
37 m68hc11eepr - m68hc11 EEPROM
42 Implements the 68HC11 eeprom device described in the m68hc11
43 user guide (Chapter 4 in the pink book).
50 Base of eeprom and its length.
54 Path of the EEPROM file. The default is 'm6811.eeprom'.
65 /* static functions */
76 static const struct hw_port_descriptor m68hc11eepr_ports
[] =
78 { "reset", RESET_PORT
, 0, input_port
, },
84 /* The timer/counter register internal state. Note that we store
85 state using the control register images, in host endian order. */
89 address_word base_address
; /* control register base */
94 /* Current state of the eeprom programing:
95 - eeprom_wmode indicates whether the EEPROM address and byte have
97 - eeprom_waddr indicates the EEPROM address that was latched
98 and eeprom_wbyte is the byte that was latched.
99 - eeprom_wcycle indicates the CPU absolute cycle type when
100 the high voltage was applied (successfully) on the EEPROM.
102 These data members are setup only when we detect good EEPROM programing
103 conditions (see Motorola EEPROM Programming and PPROG register usage).
104 When the high voltage is switched off, we look at the CPU absolute
105 cycle time to see if the EEPROM command must succeeds or not.
106 The EEPROM content is updated and saved only at that time.
107 (EEPROM command is: byte zero bits program, byte erase, row erase
110 The CONFIG register is programmed in the same way. It is physically
111 located at the end of the EEPROM (eeprom size + 1). It is not mapped
112 in memory but it's saved in the EEPROM file. */
113 unsigned long eeprom_wcycle
;
120 /* Minimum time in CPU cycles for programming the EEPROM. */
121 unsigned long eeprom_min_cycles
;
123 const char* file_name
;
128 /* Finish off the partially created hw device. Attach our local
129 callbacks. Wire up our port names etc. */
131 static hw_io_read_buffer_method m68hc11eepr_io_read_buffer
;
132 static hw_io_write_buffer_method m68hc11eepr_io_write_buffer
;
133 static hw_ioctl_method m68hc11eepr_ioctl
;
135 /* Read or write the memory bank content from/to a file.
136 Returns 0 if the operation succeeded and -1 if it failed. */
138 m6811eepr_memory_rw (struct m68hc11eepr
*controller
, int mode
)
140 const char *name
= controller
->file_name
;
144 size
= controller
->size
;
145 fd
= open (name
, mode
, 0644);
148 if (mode
== O_RDONLY
)
150 memset (controller
->eeprom
, 0xFF, size
);
151 /* Default value for CONFIG register (0xFF should be ok):
152 controller->eeprom[size - 1] = M6811_NOSEC | M6811_NOCOP
153 | M6811_ROMON | M6811_EEON; */
159 if (mode
== O_RDONLY
)
161 if (read (fd
, controller
->eeprom
, size
) != size
)
169 if (write (fd
, controller
->eeprom
, size
) != size
)
184 attach_m68hc11eepr_regs (struct hw
*me
,
185 struct m68hc11eepr
*controller
)
187 unsigned_word attach_address
;
189 unsigned attach_size
;
190 reg_property_spec reg
;
192 if (hw_find_property (me
, "reg") == NULL
)
193 hw_abort (me
, "Missing \"reg\" property");
195 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
196 hw_abort (me
, "\"reg\" property must contain one addr/size entry");
198 hw_unit_address_to_attach_address (hw_parent (me
),
203 hw_unit_size_to_attach_size (hw_parent (me
),
207 /* Attach the two IO registers that control the EEPROM.
208 The EEPROM is only attached at reset time because it may
209 be enabled/disabled by the EEON bit in the CONFIG register. */
210 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
211 io_map
, M6811_PPROG
, 1, me
);
212 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
213 io_map
, M6811_CONFIG
, 1, me
);
215 if (hw_find_property (me
, "file") == NULL
)
216 controller
->file_name
= "m6811.eeprom";
218 controller
->file_name
= hw_find_string_property (me
, "file");
220 controller
->attach_space
= attach_space
;
221 controller
->base_address
= attach_address
;
222 controller
->eeprom
= hw_malloc (me
, attach_size
+ 1);
223 controller
->eeprom_min_cycles
= 10000;
224 controller
->size
= attach_size
+ 1;
225 controller
->mapped
= 0;
227 m6811eepr_memory_rw (controller
, O_RDONLY
);
231 /* An event arrives on an interrupt port. */
234 m68hc11eepr_port_event (struct hw
*me
,
241 struct m68hc11eepr
*controller
;
244 controller
= hw_data (me
);
246 cpu
= STATE_CPU (sd
, 0);
251 HW_TRACE ((me
, "EEPROM reset"));
253 /* Re-read the EEPROM from the file. This gives the chance
254 to users to erase this file before doing a reset and have
255 a fresh EEPROM taken into account. */
256 m6811eepr_memory_rw (controller
, O_RDONLY
);
258 /* Reset the state of EEPROM programmer. The CONFIG register
259 is also initialized from the EEPROM/file content. */
260 cpu
->ios
[M6811_PPROG
] = 0;
261 if (cpu
->cpu_use_local_config
)
262 cpu
->ios
[M6811_CONFIG
] = cpu
->cpu_config
;
264 cpu
->ios
[M6811_CONFIG
] = controller
->eeprom
[controller
->size
-1];
265 controller
->eeprom_wmode
= 0;
266 controller
->eeprom_waddr
= 0;
267 controller
->eeprom_wbyte
= 0;
269 /* Attach or detach to the bus depending on the EEPROM enable bit.
270 The EEPROM CONFIG register is still enabled and can be programmed
271 for a next configuration (taken into account only after a reset,
272 see Motorola spec). */
273 if (!(cpu
->ios
[M6811_CONFIG
] & M6811_EEON
))
275 if (controller
->mapped
)
276 hw_detach_address (hw_parent (me
), M6811_EEPROM_LEVEL
,
277 controller
->attach_space
,
278 controller
->base_address
,
279 controller
->size
- 1,
281 controller
->mapped
= 0;
285 if (!controller
->mapped
)
286 hw_attach_address (hw_parent (me
), M6811_EEPROM_LEVEL
,
287 controller
->attach_space
,
288 controller
->base_address
,
289 controller
->size
- 1,
291 controller
->mapped
= 1;
297 hw_abort (me
, "Event on unknown port %d", my_port
);
304 m68hc11eepr_finish (struct hw
*me
)
306 struct m68hc11eepr
*controller
;
308 controller
= HW_ZALLOC (me
, struct m68hc11eepr
);
309 set_hw_data (me
, controller
);
310 set_hw_io_read_buffer (me
, m68hc11eepr_io_read_buffer
);
311 set_hw_io_write_buffer (me
, m68hc11eepr_io_write_buffer
);
312 set_hw_ports (me
, m68hc11eepr_ports
);
313 set_hw_port_event (me
, m68hc11eepr_port_event
);
315 set_hw_ioctl (me
, m68hc11eepr_ioctl
);
317 me
->to_ioctl
= m68hc11eepr_ioctl
;
320 attach_m68hc11eepr_regs (me
, controller
);
325 static io_reg_desc pprog_desc
[] = {
326 { M6811_BYTE
, "BYTE ", "Byte Program Mode" },
327 { M6811_ROW
, "ROW ", "Row Program Mode" },
328 { M6811_ERASE
, "ERASE ", "Erase Mode" },
329 { M6811_EELAT
, "EELAT ", "EEProm Latch Control" },
330 { M6811_EEPGM
, "EEPGM ", "EEProm Programming Voltable Enable" },
333 extern io_reg_desc config_desc
[];
336 /* Describe the state of the EEPROM device. */
338 m68hc11eepr_info (struct hw
*me
)
343 struct m68hc11eepr
*controller
;
347 cpu
= STATE_CPU (sd
, 0);
348 controller
= hw_data (me
);
349 base
= cpu_get_io_base (cpu
);
351 sim_io_printf (sd
, "M68HC11 EEprom:\n");
353 val
= cpu
->ios
[M6811_PPROG
];
354 print_io_byte (sd
, "PPROG ", pprog_desc
, val
, base
+ M6811_PPROG
);
355 sim_io_printf (sd
, "\n");
357 val
= cpu
->ios
[M6811_CONFIG
];
358 print_io_byte (sd
, "CONFIG ", config_desc
, val
, base
+ M6811_CONFIG
);
359 sim_io_printf (sd
, "\n");
361 val
= controller
->eeprom
[controller
->size
- 1];
362 print_io_byte (sd
, "(*NEXT*) ", config_desc
, val
, base
+ M6811_CONFIG
);
363 sim_io_printf (sd
, "\n");
365 /* Describe internal state of EEPROM. */
366 if (controller
->eeprom_wmode
)
368 if (controller
->eeprom_waddr
== controller
->size
- 1)
369 sim_io_printf (sd
, " Programming CONFIG register ");
371 sim_io_printf (sd
, " Programming: 0x%04x ",
372 controller
->eeprom_waddr
+ controller
->base_address
);
374 sim_io_printf (sd
, "with 0x%02x\n",
375 controller
->eeprom_wbyte
);
378 sim_io_printf (sd
, " EEProm file: %s\n",
379 controller
->file_name
);
383 m68hc11eepr_ioctl (struct hw
*me
,
384 hw_ioctl_request request
,
387 m68hc11eepr_info (me
);
391 /* generic read/write */
394 m68hc11eepr_io_read_buffer (struct hw
*me
,
401 struct m68hc11eepr
*controller
;
404 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
407 controller
= hw_data (me
);
408 cpu
= STATE_CPU (sd
, 0);
414 while (nr_bytes
!= 0)
420 *((uint8
*) dest
) = cpu
->ios
[base
];
424 hw_abort (me
, "reading wrong register 0x%04x", base
);
426 dest
= (uint8
*) (dest
) + 1;
434 /* In theory, we can't read the EEPROM when it's being programmed. */
435 if ((cpu
->ios
[M6811_PPROG
] & M6811_EELAT
) != 0
436 && cpu_is_running (cpu
))
438 sim_memory_error (cpu
, SIM_SIGBUS
, base
,
439 "EEprom not configured for reading");
442 base
= base
- controller
->base_address
;
443 memcpy (dest
, &controller
->eeprom
[base
], nr_bytes
);
449 m68hc11eepr_io_write_buffer (struct hw
*me
,
456 struct m68hc11eepr
*controller
;
460 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
463 controller
= hw_data (me
);
464 cpu
= STATE_CPU (sd
, 0);
466 /* Programming several bytes at a time is not possible. */
467 if (space
!= io_map
&& nr_bytes
!= 1)
469 sim_memory_error (cpu
, SIM_SIGBUS
, base
,
470 "EEprom write error (only 1 byte can be programmed)");
475 hw_abort (me
, "Cannot write more than 1 byte to EEPROM device at a time");
477 val
= *((const uint8
*) source
);
479 /* Write to the EEPROM control register. */
480 if (space
== io_map
&& base
== M6811_PPROG
)
485 addr
= base
+ cpu_get_io_base (cpu
);
487 /* Setting EELAT and EEPGM at the same time is an error.
488 Clearing them both is ok. */
489 wrong_bits
= (cpu
->ios
[M6811_PPROG
] ^ val
) & val
;
490 wrong_bits
&= (M6811_EELAT
| M6811_EEPGM
);
492 if (wrong_bits
== (M6811_EEPGM
|M6811_EELAT
))
494 sim_memory_error (cpu
, SIM_SIGBUS
, addr
,
495 "Wrong eeprom programing value");
499 if ((val
& M6811_EELAT
) == 0)
503 if ((val
& M6811_EEPGM
) && !(cpu
->ios
[M6811_PPROG
] & M6811_EELAT
))
505 sim_memory_error (cpu
, SIM_SIGBUS
, addr
,
506 "EEProm high voltage applied after EELAT");
508 if ((val
& M6811_EEPGM
) && controller
->eeprom_wmode
== 0)
510 sim_memory_error (cpu
, SIM_SIGSEGV
, addr
,
511 "EEProm high voltage applied without address");
513 if (val
& M6811_EEPGM
)
515 controller
->eeprom_wcycle
= cpu_current_cycle (cpu
);
517 else if (cpu
->ios
[M6811_PPROG
] & M6811_PPROG
)
520 unsigned long t
= cpu_current_cycle (cpu
);
522 t
-= controller
->eeprom_wcycle
;
523 if (t
< controller
->eeprom_min_cycles
)
525 sim_memory_error (cpu
, SIM_SIGILL
, addr
,
526 "EEprom programmed only for %lu cycles",
530 /* Program the byte by clearing some bits. */
531 if (!(cpu
->ios
[M6811_PPROG
] & M6811_ERASE
))
533 controller
->eeprom
[controller
->eeprom_waddr
]
534 &= controller
->eeprom_wbyte
;
537 /* Erase a byte, row or the complete eeprom. Erased value is 0xFF.
538 Ignore row or complete eeprom erase when we are programming the
539 CONFIG register (last EEPROM byte). */
540 else if ((cpu
->ios
[M6811_PPROG
] & M6811_BYTE
)
541 || controller
->eeprom_waddr
== controller
->size
- 1)
543 controller
->eeprom
[controller
->eeprom_waddr
] = 0xff;
545 else if (cpu
->ios
[M6811_BYTE
] & M6811_ROW
)
549 /* Size of EEPROM (-1 because the last byte is the
551 max_size
= controller
->size
;
552 controller
->eeprom_waddr
&= 0xFFF0;
554 && controller
->eeprom_waddr
< max_size
; i
++)
556 controller
->eeprom
[controller
->eeprom_waddr
] = 0xff;
557 controller
->eeprom_waddr
++;
564 max_size
= controller
->size
;
565 for (i
= 0; i
< max_size
; i
++)
567 controller
->eeprom
[i
] = 0xff;
571 /* Save the eeprom in a file. We have to save after each
572 change because the simulator can be stopped or crash... */
573 if (m6811eepr_memory_rw (controller
, O_WRONLY
| O_CREAT
) != 0)
575 sim_memory_error (cpu
, SIM_SIGABRT
, addr
,
576 "EEPROM programing failed: errno=%d", errno
);
578 controller
->eeprom_wmode
= 0;
580 cpu
->ios
[M6811_PPROG
] = val
;
584 /* The CONFIG IO register is mapped at end of EEPROM.
586 if (space
== io_map
&& base
== M6811_CONFIG
)
588 base
= controller
->size
- 1;
592 base
= base
- controller
->base_address
;
595 /* Writing the memory is allowed for the Debugger or simulator
596 (cpu not running). */
597 if (cpu_is_running (cpu
))
599 if ((cpu
->ios
[M6811_PPROG
] & M6811_EELAT
) == 0)
601 sim_memory_error (cpu
, SIM_SIGSEGV
, base
,
602 "EEprom not configured for writing");
605 if (controller
->eeprom_wmode
!= 0)
607 sim_memory_error (cpu
, SIM_SIGSEGV
, base
,
608 "EEprom write error");
611 controller
->eeprom_wmode
= 1;
612 controller
->eeprom_waddr
= base
;
613 controller
->eeprom_wbyte
= val
;
617 controller
->eeprom
[base
] = val
;
618 m6811eepr_memory_rw (controller
, O_WRONLY
);
624 const struct hw_descriptor dv_m68hc11eepr_descriptor
[] = {
625 { "m68hc11eepr", m68hc11eepr_finish
},
626 { "m68hc12eepr", m68hc11eepr_finish
},