summaryrefslogtreecommitdiff
path: root/sim/m68hc11/dv-m68hc11.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/m68hc11/dv-m68hc11.c')
-rw-r--r--sim/m68hc11/dv-m68hc11.c593
1 files changed, 0 insertions, 593 deletions
diff --git a/sim/m68hc11/dv-m68hc11.c b/sim/m68hc11/dv-m68hc11.c
deleted file mode 100644
index f300297331a..00000000000
--- a/sim/m68hc11/dv-m68hc11.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/* dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.
- Copyright (C) 1999, 2000 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"
-
-/* DEVICE
-
- m68hc11cpu - m68hc11 cpu virtual device
- m68hc12cpu - m68hc12 cpu virtual device
-
- DESCRIPTION
-
- Implements the external m68hc11/68hc12 functionality. This includes
- the delivery of of interrupts generated from other devices and the
- handling of device specific registers.
-
-
- PROPERTIES
-
- reg <base> <size>
-
- Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).
-
- clock <hz>
-
- Frequency of the quartz used by the processor.
-
- mode [single | expanded | bootstrap | test]
-
- Cpu operating mode (the MODA and MODB external pins).
-
-
- PORTS
-
- reset (input)
-
- Reset the cpu and generates a cpu-reset event (used to reset
- other devices).
-
- nmi (input)
-
- Deliver a non-maskable interrupt to the processor.
-
-
- cpu-reset (output)
-
- Event generated after the CPU performs a reset.
-
-
- BUGS
-
- When delivering an interrupt, this code assumes that there is only
- one processor (number 0).
-
- */
-
-
-
-struct m68hc11cpu {
- /* Pending interrupts for delivery by event handler. */
- int pending_reset;
- int pending_nmi;
- int pending_level;
- struct hw_event *event;
- unsigned_word attach_address;
- int attach_size;
- int attach_space;
-};
-
-
-
-/* input port ID's */
-
-enum {
- RESET_PORT,
- NMI_PORT,
- IRQ_PORT,
- CPU_RESET_PORT
-};
-
-
-static const struct hw_port_descriptor m68hc11cpu_ports[] = {
-
- /* Interrupt inputs. */
- { "reset", RESET_PORT, 0, input_port, },
- { "nmi", NMI_PORT, 0, input_port, },
- { "irq", IRQ_PORT, 0, input_port, },
-
- /* Events generated for connection to other devices. */
- { "cpu-reset", CPU_RESET_PORT, 0, output_port, },
-
- { NULL, },
-};
-
-static hw_io_read_buffer_method m68hc11cpu_io_read_buffer;
-static hw_io_write_buffer_method m68hc11cpu_io_write_buffer;
-static hw_ioctl_method m68hc11_ioctl;
-
-/* Finish off the partially created hw device. Attach our local
- callbacks. Wire up our port names etc. */
-
-static hw_port_event_method m68hc11cpu_port_event;
-
-
-static void
-dv_m6811_attach_address_callback (struct hw *me,
- int level,
- int space,
- address_word addr,
- address_word nr_bytes,
- struct hw *client)
-{
- HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
- level, space, (unsigned long) addr, (unsigned long) nr_bytes,
- hw_path (client)));
-
- if (space != io_map)
- {
- sim_core_attach (hw_system (me),
- NULL, /*cpu*/
- level,
- access_read_write_exec,
- space, addr,
- nr_bytes,
- 0, /* modulo */
- client,
- NULL);
- }
- else
- {
- /*printf("Attach from sub device: %d\n", (long) addr);*/
- sim_core_attach (hw_system (me),
- NULL, /*cpu*/
- level,
- access_io,
- space, addr,
- nr_bytes,
- 0, /* modulo */
- client,
- NULL);
- }
-}
-
-static void
-dv_m6811_detach_address_callback (struct hw *me,
- int level,
- int space,
- address_word addr,
- address_word nr_bytes,
- struct hw *client)
-{
- sim_core_detach (hw_system (me), NULL, /*cpu*/
- level, space, addr);
-}
-
-static void
-m68hc11_delete (struct hw* me)
-{
- struct m68hc11cpu *controller;
-
- controller = hw_data (me);
-
- hw_detach_address (me, M6811_IO_LEVEL,
- controller->attach_space,
- controller->attach_address,
- controller->attach_size, me);
-}
-
-
-static void
-attach_m68hc11_regs (struct hw *me,
- struct m68hc11cpu *controller)
-{
- SIM_DESC sd;
- sim_cpu *cpu;
- reg_property_spec reg;
- const char *cpu_mode;
-
- if (hw_find_property (me, "reg") == NULL)
- hw_abort (me, "Missing \"reg\" property");
-
- if (!hw_find_reg_array_property (me, "reg", 0, &reg))
- hw_abort (me, "\"reg\" property must contain one addr/size entry");
-
- hw_unit_address_to_attach_address (hw_parent (me),
- &reg.address,
- &controller->attach_space,
- &controller->attach_address,
- me);
- hw_unit_size_to_attach_size (hw_parent (me),
- &reg.size,
- &controller->attach_size, me);
-
- hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
- controller->attach_space,
- controller->attach_address,
- controller->attach_size,
- me);
- set_hw_delete (me, m68hc11_delete);
-
- /* Get cpu frequency. */
- sd = hw_system (me);
- cpu = STATE_CPU (sd, 0);
- if (hw_find_property (me, "clock") != NULL)
- {
- cpu->cpu_frequency = hw_find_integer_property (me, "clock");
- }
- else
- {
- cpu->cpu_frequency = 8*1000*1000;
- }
-
- cpu_mode = "expanded";
- if (hw_find_property (me, "mode") != NULL)
- cpu_mode = hw_find_string_property (me, "mode");
-
- if (strcmp (cpu_mode, "test") == 0)
- cpu->cpu_mode = M6811_MDA | M6811_SMOD;
- else if (strcmp (cpu_mode, "bootstrap") == 0)
- cpu->cpu_mode = M6811_SMOD;
- else if (strcmp (cpu_mode, "single") == 0)
- cpu->cpu_mode = 0;
- else
- cpu->cpu_mode = M6811_MDA;
-}
-
-static void
-m68hc11cpu_finish (struct hw *me)
-{
- struct m68hc11cpu *controller;
-
- controller = HW_ZALLOC (me, struct m68hc11cpu);
- set_hw_data (me, controller);
- set_hw_io_read_buffer (me, m68hc11cpu_io_read_buffer);
- set_hw_io_write_buffer (me, m68hc11cpu_io_write_buffer);
- set_hw_ports (me, m68hc11cpu_ports);
- set_hw_port_event (me, m68hc11cpu_port_event);
- set_hw_attach_address (me, dv_m6811_attach_address_callback);
- set_hw_detach_address (me, dv_m6811_detach_address_callback);
-#ifdef set_hw_ioctl
- set_hw_ioctl (me, m68hc11_ioctl);
-#else
- me->to_ioctl = m68hc11_ioctl;
-#endif
-
- /* Initialize the pending interrupt flags. */
- controller->pending_level = 0;
- controller->pending_reset = 0;
- controller->pending_nmi = 0;
- controller->event = NULL;
-
- attach_m68hc11_regs (me, controller);
-}
-
-/* An event arrives on an interrupt port. */
-
-static void
-deliver_m68hc11cpu_interrupt (struct hw *me, void *data)
-{
-}
-
-
-static void
-m68hc11cpu_port_event (struct hw *me,
- int my_port,
- struct hw *source,
- int source_port,
- int level)
-{
- struct m68hc11cpu *controller = hw_data (me);
- SIM_DESC sd;
- sim_cpu* cpu;
-
- sd = hw_system (me);
- cpu = STATE_CPU (sd, 0);
- switch (my_port)
- {
- case RESET_PORT:
- HW_TRACE ((me, "port-in reset"));
-
- /* The reset is made in 3 steps:
- - First, cleanup the current sim_cpu struct.
- - Reset the devices.
- - Restart the cpu for the reset (get the CPU mode from the
- CONFIG register that gets initialized by EEPROM device). */
- cpu_reset (cpu);
- hw_port_event (me, CPU_RESET_PORT, 1);
- cpu_restart (cpu);
- break;
-
- case NMI_PORT:
- controller->pending_nmi = 1;
- HW_TRACE ((me, "port-in nmi"));
- break;
-
- case IRQ_PORT:
- /* level == 0 means that the interrupt was cleared. */
- if(level == 0)
- controller->pending_level = -1; /* signal end of interrupt */
- else
- controller->pending_level = level;
- HW_TRACE ((me, "port-in level=%d", level));
- break;
-
- default:
- hw_abort (me, "bad switch");
- break;
- }
-
- /* Schedule an event to be delivered immediately after current
- instruction. */
- if(controller->event != NULL)
- hw_event_queue_deschedule(me, controller->event);
- controller->event =
- hw_event_queue_schedule (me, 0, deliver_m68hc11cpu_interrupt, NULL);
-}
-
-
-io_reg_desc config_desc[] = {
- { M6811_NOSEC, "NOSEC ", "Security Mode Disable" },
- { M6811_NOCOP, "NOCOP ", "COP System Disable" },
- { M6811_ROMON, "ROMON ", "Enable On-chip Rom" },
- { M6811_EEON, "EEON ", "Enable On-chip EEprom" },
- { 0, 0, 0 }
-};
-
-io_reg_desc hprio_desc[] = {
- { M6811_RBOOT, "RBOOT ", "Read Bootstrap ROM" },
- { M6811_SMOD, "SMOD ", "Special Mode" },
- { M6811_MDA, "MDA ", "Mode Select A" },
- { M6811_IRV, "IRV ", "Internal Read Visibility" },
- { 0, 0, 0 }
-};
-
-io_reg_desc option_desc[] = {
- { M6811_ADPU, "ADPU ", "A/D Powerup" },
- { M6811_CSEL, "CSEL ", "A/D/EE Charge pump clock source select" },
- { M6811_IRQE, "IRQE ", "IRQ Edge/Level sensitive" },
- { M6811_DLY, "DLY ", "Stop exit turn on delay" },
- { M6811_CME, "CME ", "Clock Monitor Enable" },
- { M6811_CR1, "CR1 ", "COP timer rate select (CR1)" },
- { M6811_CR0, "CR0 ", "COP timer rate select (CR0)" },
- { 0, 0, 0 }
-};
-
-static void
-m68hc11_info (struct hw *me)
-{
- SIM_DESC sd;
- uint16 base = 0;
- sim_cpu *cpu;
- struct m68hc11sio *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:\n");
-
- val = cpu->ios[M6811_HPRIO];
- print_io_byte (sd, "HPRIO ", hprio_desc, val, base + M6811_HPRIO);
- 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 = cpu->ios[M6811_OPTION];
- print_io_byte (sd, "OPTION", option_desc, val, base + M6811_OPTION);
- sim_io_printf (sd, "\n");
-
- val = cpu->ios[M6811_INIT];
- print_io_byte (sd, "INIT ", 0, val, base + M6811_INIT);
- sim_io_printf (sd, "Ram = 0x%04x IO = 0x%04x\n",
- (((uint16) (val & 0xF0)) << 8),
- (((uint16) (val & 0x0F)) << 12));
-
-
- cpu_info (sd, cpu);
- interrupts_info (sd, &cpu->cpu_interrupts);
-}
-
-static int
-m68hc11_ioctl (struct hw *me,
- hw_ioctl_request request,
- va_list ap)
-{
- m68hc11_info (me);
- return 0;
-}
-
-/* generic read/write */
-
-static unsigned
-m68hc11cpu_io_read_buffer (struct hw *me,
- void *dest,
- int space,
- unsigned_word base,
- unsigned nr_bytes)
-{
- SIM_DESC sd;
- struct m68hc11cpu *controller = hw_data (me);
- sim_cpu *cpu;
- unsigned byte = 0;
- int result;
-
- HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
-
- sd = hw_system (me);
- cpu = STATE_CPU (sd, 0);
-
- /* Handle reads for the sub-devices. */
- base -= controller->attach_address;
- result = sim_core_read_buffer (sd, cpu,
- io_map, dest, base, nr_bytes);
- if (result > 0)
- return result;
-
- while (nr_bytes)
- {
- if (base >= controller->attach_size)
- break;
-
- memcpy (dest, &cpu->ios[base], 1);
- dest++;
- base++;
- byte++;
- nr_bytes--;
- }
- return byte;
-}
-
-
-static void
-m68hc11cpu_io_write (struct hw *me, sim_cpu *cpu,
- unsigned_word addr, uint8 val)
-{
- switch (addr)
- {
- case M6811_PORTA:
- break;
-
- case M6811_PIOC:
- break;
-
- case M6811_PORTC:
- break;
-
- case M6811_PORTB:
- break;
-
- case M6811_PORTCL:
- break;
-
- case M6811_DDRC:
- break;
-
- case M6811_PORTD:
- break;
-
- case M6811_DDRD:
- break;
-
- case M6811_TMSK2:
-
- break;
-
- /* Change the RAM and I/O mapping. */
- case M6811_INIT:
- {
- uint8 old_bank = cpu->ios[M6811_INIT];
-
- cpu->ios[M6811_INIT] = val;
-
- /* Update IO mapping. Detach from the old address
- and attach to the new one. */
- if ((old_bank & 0xF0) != (val & 0xF0))
- {
- struct m68hc11cpu *controller = hw_data (me);
-
- hw_detach_address (hw_parent (me), M6811_IO_LEVEL,
- controller->attach_space,
- controller->attach_address,
- controller->attach_size,
- me);
- controller->attach_address = (val & 0x0F0) << 12;
- hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
- controller->attach_space,
- controller->attach_address,
- controller->attach_size,
- me);
- }
- if ((old_bank & 0x0F) != (val & 0x0F))
- {
- ;
- }
- return;
- }
-
- /* Writing the config is similar to programing the eeprom.
- The config register value is the last byte of the EEPROM.
- This last byte is not mapped in memory (that's why we have
- to add '1' to 'end_addr'). */
- case M6811_CONFIG:
- {
- return;
- }
-
-
- /* COP reset. */
- case M6811_COPRST:
- if (val == 0xAA && cpu->ios[addr] == 0x55)
- {
- val = 0;
- /* COP reset here. */
- }
- break;
-
- default:
- break;
-
- }
- cpu->ios[addr] = val;
-}
-
-static unsigned
-m68hc11cpu_io_write_buffer (struct hw *me,
- const void *source,
- int space,
- unsigned_word base,
- unsigned nr_bytes)
-{
- SIM_DESC sd;
- struct m68hc11cpu *controller = hw_data (me);
- unsigned byte;
- sim_cpu *cpu;
- int result;
-
- HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
-
- sd = hw_system (me);
- cpu = STATE_CPU (sd, 0);
- base -= controller->attach_address;
- result = sim_core_write_buffer (sd, cpu,
- io_map, source, base, nr_bytes);
- if (result > 0)
- return result;
-
- byte = 0;
- while (nr_bytes)
- {
- uint8 val;
- if (base >= controller->attach_size)
- break;
-
- val = *((uint8*) source);
- m68hc11cpu_io_write (me, cpu, base, val);
- source++;
- base++;
- byte++;
- nr_bytes--;
- }
- return byte;
-}
-
-const struct hw_descriptor dv_m68hc11_descriptor[] = {
- { "m68hc11", m68hc11cpu_finish },
- { "m68hc12", m68hc11cpu_finish },
- { NULL },
-};
-