diff options
Diffstat (limited to 'sim/m68hc11/dv-m68hc11eepr.c')
-rw-r--r-- | sim/m68hc11/dv-m68hc11eepr.c | 628 |
1 files changed, 0 insertions, 628 deletions
diff --git a/sim/m68hc11/dv-m68hc11eepr.c b/sim/m68hc11/dv-m68hc11eepr.c deleted file mode 100644 index fb99068fe87..00000000000 --- a/sim/m68hc11/dv-m68hc11eepr.c +++ /dev/null @@ -1,628 +0,0 @@ -/* dv-m68hc11eepr.c -- Simulation of the 68HC11 Internal EEPROM. - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. - Written by Stephane Carrez (stcarrez@worldnet.fr) - (From a driver model Contributed by Cygnus Solutions.) - - 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 2 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, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - - -#include "sim-main.h" -#include "hw-main.h" -#include "sim-assert.h" -#include "sim-events.h" - -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> - - - -/* DEVICE - - m68hc11eepr - m68hc11 EEPROM - - - DESCRIPTION - - Implements the 68HC11 eeprom device described in the m68hc11 - user guide (Chapter 4 in the pink book). - - - PROPERTIES - - reg <base> <length> - - Base of eeprom and its length. - - file <path> - - Path of the EEPROM file. The default is 'm6811.eeprom'. - - - PORTS - - None - - */ - - - -/* static functions */ - - -/* port ID's */ - -enum -{ - RESET_PORT -}; - - -static const struct hw_port_descriptor m68hc11eepr_ports[] = -{ - { "reset", RESET_PORT, 0, input_port, }, - { NULL, }, -}; - - - -/* The timer/counter register internal state. Note that we store - state using the control register images, in host endian order. */ - -struct m68hc11eepr -{ - address_word base_address; /* control register base */ - int attach_space; - unsigned size; - int mapped; - - /* Current state of the eeprom programing: - - eeprom_wmode indicates whether the EEPROM address and byte have - been latched. - - eeprom_waddr indicates the EEPROM address that was latched - and eeprom_wbyte is the byte that was latched. - - eeprom_wcycle indicates the CPU absolute cycle type when - the high voltage was applied (successfully) on the EEPROM. - - These data members are setup only when we detect good EEPROM programing - conditions (see Motorola EEPROM Programming and PPROG register usage). - When the high voltage is switched off, we look at the CPU absolute - cycle time to see if the EEPROM command must succeeds or not. - The EEPROM content is updated and saved only at that time. - (EEPROM command is: byte zero bits program, byte erase, row erase - and bulk erase). - - The CONFIG register is programmed in the same way. It is physically - located at the end of the EEPROM (eeprom size + 1). It is not mapped - in memory but it's saved in the EEPROM file. */ - unsigned long eeprom_wcycle; - uint16 eeprom_waddr; - uint8 eeprom_wbyte; - uint8 eeprom_wmode; - - uint8* eeprom; - - /* Minimum time in CPU cycles for programming the EEPROM. */ - unsigned long eeprom_min_cycles; - - char* file_name; -}; - - - -/* Finish off the partially created hw device. Attach our local - callbacks. Wire up our port names etc. */ - -static hw_io_read_buffer_method m68hc11eepr_io_read_buffer; -static hw_io_write_buffer_method m68hc11eepr_io_write_buffer; -static hw_ioctl_method m68hc11eepr_ioctl; - -/* Read or write the memory bank content from/to a file. - Returns 0 if the operation succeeded and -1 if it failed. */ -static int -m6811eepr_memory_rw (struct m68hc11eepr *controller, int mode) -{ - const char *name = controller->file_name; - int fd; - size_t size; - - size = controller->size; - fd = open (name, mode, 0644); - if (fd < 0) - { - if (mode == O_RDONLY) - { - memset (controller->eeprom, 0xFF, size); - /* Default value for CONFIG register (0xFF should be ok): - controller->eeprom[size - 1] = M6811_NOSEC | M6811_NOCOP - | M6811_ROMON | M6811_EEON; */ - return 0; - } - return -1; - } - - if (mode == O_RDONLY) - { - if (read (fd, controller->eeprom, size) != size) - { - close (fd); - return -1; - } - } - else - { - if (write (fd, controller->eeprom, size) != size) - { - close (fd); - return -1; - } - } - close (fd); - - return 0; -} - - - - -static void -attach_m68hc11eepr_regs (struct hw *me, - struct m68hc11eepr *controller) -{ - unsigned_word attach_address; - int attach_space; - unsigned attach_size; - reg_property_spec reg; - - if (hw_find_property (me, "reg") == NULL) - hw_abort (me, "Missing \"reg\" property"); - - if (!hw_find_reg_array_property (me, "reg", 0, ®)) - hw_abort (me, "\"reg\" property must contain one addr/size entry"); - - hw_unit_address_to_attach_address (hw_parent (me), - ®.address, - &attach_space, - &attach_address, - me); - hw_unit_size_to_attach_size (hw_parent (me), - ®.size, - &attach_size, me); - - /* Attach the two IO registers that control the EEPROM. - The EEPROM is only attached at reset time because it may - be enabled/disabled by the EEON bit in the CONFIG register. */ - hw_attach_address (hw_parent (me), M6811_IO_LEVEL, - io_map, M6811_PPROG, 1, me); - hw_attach_address (hw_parent (me), M6811_IO_LEVEL, - io_map, M6811_CONFIG, 1, me); - - if (hw_find_property (me, "file") == NULL) - controller->file_name = "m6811.eeprom"; - else - controller->file_name = hw_find_string_property (me, "file"); - - controller->attach_space = attach_space; - controller->base_address = attach_address; - controller->eeprom = (char*) hw_malloc (me, attach_size + 1); - controller->eeprom_min_cycles = 10000; - controller->size = attach_size + 1; - controller->mapped = 0; - - m6811eepr_memory_rw (controller, O_RDONLY); -} - - -/* An event arrives on an interrupt port. */ - -static void -m68hc11eepr_port_event (struct hw *me, - int my_port, - struct hw *source, - int source_port, - int level) -{ - SIM_DESC sd; - struct m68hc11eepr *controller; - sim_cpu *cpu; - - controller = hw_data (me); - sd = hw_system (me); - cpu = STATE_CPU (sd, 0); - switch (my_port) - { - case RESET_PORT: - { - HW_TRACE ((me, "EEPROM reset")); - - /* Re-read the EEPROM from the file. This gives the chance - to users to erase this file before doing a reset and have - a fresh EEPROM taken into account. */ - m6811eepr_memory_rw (controller, O_RDONLY); - - /* Reset the state of EEPROM programmer. The CONFIG register - is also initialized from the EEPROM/file content. */ - cpu->ios[M6811_PPROG] = 0; - if (cpu->cpu_use_local_config) - cpu->ios[M6811_CONFIG] = cpu->cpu_config; - else - cpu->ios[M6811_CONFIG] = controller->eeprom[controller->size-1]; - controller->eeprom_wmode = 0; - controller->eeprom_waddr = 0; - controller->eeprom_wbyte = 0; - - /* Attach or detach to the bus depending on the EEPROM enable bit. - The EEPROM CONFIG register is still enabled and can be programmed - for a next configuration (taken into account only after a reset, - see Motorola spec). */ - if (!(cpu->ios[M6811_CONFIG] & M6811_EEON)) - { - if (controller->mapped) - hw_detach_address (hw_parent (me), M6811_EEPROM_LEVEL, - controller->attach_space, - controller->base_address, - controller->size - 1, - me); - controller->mapped = 0; - } - else - { - if (!controller->mapped) - hw_attach_address (hw_parent (me), M6811_EEPROM_LEVEL, - controller->attach_space, - controller->base_address, - controller->size - 1, - me); - controller->mapped = 1; - } - break; - } - - default: - hw_abort (me, "Event on unknown port %d", my_port); - break; - } -} - - -static void -m68hc11eepr_finish (struct hw *me) -{ - struct m68hc11eepr *controller; - - controller = HW_ZALLOC (me, struct m68hc11eepr); - set_hw_data (me, controller); - set_hw_io_read_buffer (me, m68hc11eepr_io_read_buffer); - set_hw_io_write_buffer (me, m68hc11eepr_io_write_buffer); - set_hw_ports (me, m68hc11eepr_ports); - set_hw_port_event (me, m68hc11eepr_port_event); -#ifdef set_hw_ioctl - set_hw_ioctl (me, m68hc11eepr_ioctl); -#else - me->to_ioctl = m68hc11eepr_ioctl; -#endif - - attach_m68hc11eepr_regs (me, controller); -} - - - -static io_reg_desc pprog_desc[] = { - { M6811_BYTE, "BYTE ", "Byte Program Mode" }, - { M6811_ROW, "ROW ", "Row Program Mode" }, - { M6811_ERASE, "ERASE ", "Erase Mode" }, - { M6811_EELAT, "EELAT ", "EEProm Latch Control" }, - { M6811_EEPGM, "EEPGM ", "EEProm Programming Voltable Enable" }, - { 0, 0, 0 } -}; -extern io_reg_desc config_desc[]; - - -/* Describe the state of the EEPROM device. */ -static void -m68hc11eepr_info (struct hw *me) -{ - SIM_DESC sd; - uint16 base = 0; - sim_cpu *cpu; - struct m68hc11eepr *controller; - uint8 val; - - sd = hw_system (me); - cpu = STATE_CPU (sd, 0); - controller = hw_data (me); - base = cpu_get_io_base (cpu); - - sim_io_printf (sd, "M68HC11 EEprom:\n"); - - val = cpu->ios[M6811_PPROG]; - print_io_byte (sd, "PPROG ", pprog_desc, val, base + M6811_PPROG); - sim_io_printf (sd, "\n"); - - val = cpu->ios[M6811_CONFIG]; - print_io_byte (sd, "CONFIG ", config_desc, val, base + M6811_CONFIG); - sim_io_printf (sd, "\n"); - - val = controller->eeprom[controller->size - 1]; - print_io_byte (sd, "(*NEXT*) ", config_desc, val, base + M6811_CONFIG); - sim_io_printf (sd, "\n"); - - /* Describe internal state of EEPROM. */ - if (controller->eeprom_wmode) - { - if (controller->eeprom_waddr == controller->size - 1) - sim_io_printf (sd, " Programming CONFIG register "); - else - sim_io_printf (sd, " Programming: 0x%04x ", - controller->eeprom_waddr + controller->base_address); - - sim_io_printf (sd, "with 0x%02x\n", - controller->eeprom_wbyte); - } - - sim_io_printf (sd, " EEProm file: %s\n", - controller->file_name); -} - -static int -m68hc11eepr_ioctl (struct hw *me, - hw_ioctl_request request, - va_list ap) -{ - m68hc11eepr_info (me); - return 0; -} - -/* generic read/write */ - -static unsigned -m68hc11eepr_io_read_buffer (struct hw *me, - void *dest, - int space, - unsigned_word base, - unsigned nr_bytes) -{ - SIM_DESC sd; - struct m68hc11eepr *controller; - sim_cpu *cpu; - - HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); - - sd = hw_system (me); - controller = hw_data (me); - cpu = STATE_CPU (sd, 0); - - if (space == io_map) - { - unsigned cnt = 0; - - while (nr_bytes != 0) - { - switch (base) - { - case M6811_PPROG: - case M6811_CONFIG: - *((uint8*) dest) = cpu->ios[base]; - break; - - default: - hw_abort (me, "reading wrong register 0x%04x", base); - } - dest = (uint8*) (dest) + 1; - base++; - nr_bytes--; - cnt++; - } - return cnt; - } - - /* In theory, we can't read the EEPROM when it's being programmed. */ - if ((cpu->ios[M6811_PPROG] & M6811_EELAT) != 0 - && cpu_is_running (cpu)) - { - sim_memory_error (cpu, SIM_SIGBUS, base, - "EEprom not configured for reading"); - } - - base = base - controller->base_address; - memcpy (dest, &controller->eeprom[base], nr_bytes); - return nr_bytes; -} - - -static unsigned -m68hc11eepr_io_write_buffer (struct hw *me, - const void *source, - int space, - unsigned_word base, - unsigned nr_bytes) -{ - SIM_DESC sd; - struct m68hc11eepr *controller; - sim_cpu *cpu; - uint8 val; - - HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); - - sd = hw_system (me); - controller = hw_data (me); - cpu = STATE_CPU (sd, 0); - - /* Programming several bytes at a time is not possible. */ - if (space != io_map && nr_bytes != 1) - { - sim_memory_error (cpu, SIM_SIGBUS, base, - "EEprom write error (only 1 byte can be programmed)"); - return 0; - } - - if (nr_bytes != 1) - hw_abort (me, "Cannot write more than 1 byte to EEPROM device at a time"); - - val = *((const uint8*) source); - - /* Write to the EEPROM control register. */ - if (space == io_map && base == M6811_PPROG) - { - uint8 wrong_bits; - uint16 addr; - - addr = base + cpu_get_io_base (cpu); - - /* Setting EELAT and EEPGM at the same time is an error. - Clearing them both is ok. */ - wrong_bits = (cpu->ios[M6811_PPROG] ^ val) & val; - wrong_bits &= (M6811_EELAT | M6811_EEPGM); - - if (wrong_bits == (M6811_EEPGM|M6811_EELAT)) - { - sim_memory_error (cpu, SIM_SIGBUS, addr, - "Wrong eeprom programing value"); - return 0; - } - - if ((val & M6811_EELAT) == 0) - { - val = 0; - } - if ((val & M6811_EEPGM) && !(cpu->ios[M6811_PPROG] & M6811_EELAT)) - { - sim_memory_error (cpu, SIM_SIGBUS, addr, - "EEProm high voltage applied after EELAT"); - } - if ((val & M6811_EEPGM) && controller->eeprom_wmode == 0) - { - sim_memory_error (cpu, SIM_SIGSEGV, addr, - "EEProm high voltage applied without address"); - } - if (val & M6811_EEPGM) - { - controller->eeprom_wcycle = cpu_current_cycle (cpu); - } - else if (cpu->ios[M6811_PPROG] & M6811_PPROG) - { - int i; - unsigned long t = cpu_current_cycle (cpu); - - t -= controller->eeprom_wcycle; - if (t < controller->eeprom_min_cycles) - { - sim_memory_error (cpu, SIM_SIGILL, addr, - "EEprom programmed only for %lu cycles", - t); - } - - /* Program the byte by clearing some bits. */ - if (!(cpu->ios[M6811_PPROG] & M6811_ERASE)) - { - controller->eeprom[controller->eeprom_waddr] - &= controller->eeprom_wbyte; - } - - /* Erase a byte, row or the complete eeprom. Erased value is 0xFF. - Ignore row or complete eeprom erase when we are programming the - CONFIG register (last EEPROM byte). */ - else if ((cpu->ios[M6811_PPROG] & M6811_BYTE) - || controller->eeprom_waddr == controller->size - 1) - { - controller->eeprom[controller->eeprom_waddr] = 0xff; - } - else if (cpu->ios[M6811_BYTE] & M6811_ROW) - { - size_t max_size; - - /* Size of EEPROM (-1 because the last byte is the - CONFIG register. */ - max_size = controller->size; - controller->eeprom_waddr &= 0xFFF0; - for (i = 0; i < 16 - && controller->eeprom_waddr < max_size; i++) - { - controller->eeprom[controller->eeprom_waddr] = 0xff; - controller->eeprom_waddr ++; - } - } - else - { - size_t max_size; - - max_size = controller->size; - for (i = 0; i < max_size; i++) - { - controller->eeprom[i] = 0xff; - } - } - - /* Save the eeprom in a file. We have to save after each - change because the simulator can be stopped or crash... */ - if (m6811eepr_memory_rw (controller, O_WRONLY | O_CREAT) != 0) - { - sim_memory_error (cpu, SIM_SIGABRT, addr, - "EEPROM programing failed: errno=%d", errno); - } - controller->eeprom_wmode = 0; - } - cpu->ios[M6811_PPROG] = val; - return 1; - } - - /* The CONFIG IO register is mapped at end of EEPROM. - It's not visible. */ - if (space == io_map && base == M6811_CONFIG) - { - base = controller->size - 1; - } - else - { - base = base - controller->base_address; - } - - /* Writing the memory is allowed for the Debugger or simulator - (cpu not running). */ - if (cpu_is_running (cpu)) - { - if ((cpu->ios[M6811_PPROG] & M6811_EELAT) == 0) - { - sim_memory_error (cpu, SIM_SIGSEGV, base, - "EEprom not configured for writing"); - return 0; - } - if (controller->eeprom_wmode != 0) - { - sim_memory_error (cpu, SIM_SIGSEGV, base, - "EEprom write error"); - return 0; - } - controller->eeprom_wmode = 1; - controller->eeprom_waddr = base; - controller->eeprom_wbyte = val; - } - else - { - controller->eeprom[base] = val; - m6811eepr_memory_rw (controller, O_WRONLY); - } - - return 1; -} - -const struct hw_descriptor dv_m68hc11eepr_descriptor[] = { - { "m68hc11eepr", m68hc11eepr_finish }, - { "m68hc12eepr", m68hc11eepr_finish }, - { NULL }, -}; - |