1 /* dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.
2 Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.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 2 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, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include "sim-options.h"
31 m68hc11cpu - m68hc11 cpu virtual device
32 m68hc12cpu - m68hc12 cpu virtual device
36 Implements the external m68hc11/68hc12 functionality. This includes
37 the delivery of of interrupts generated from other devices and the
38 handling of device specific registers.
45 Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).
49 Frequency of the quartz used by the processor.
51 mode [single | expanded | bootstrap | test]
53 Cpu operating mode (the MODA and MODB external pins).
60 Reset the cpu and generates a cpu-reset event (used to reset
65 Deliver a non-maskable interrupt to the processor.
72 Allow an external device to set the value of port A, C or D inputs.
77 Event generated after the CPU performs a reset.
85 Event generated when the value of the output port A, B, C or D
91 When delivering an interrupt, this code assumes that there is only
92 one processor (number 0).
98 OPTION_OSC_SET
= OPTION_START
,
103 static DECLARE_OPTION_HANDLER (m68hc11_option_handler
);
105 static const OPTION m68hc11_options
[] =
107 { {"osc-set", required_argument
, NULL
, OPTION_OSC_SET
},
108 '\0', "BIT,FREQ", "Set the oscillator on input port BIT",
109 m68hc11_option_handler
},
110 { {"osc-clear", required_argument
, NULL
, OPTION_OSC_CLEAR
},
111 '\0', "BIT", "Clear oscillator on input port BIT",
112 m68hc11_option_handler
},
113 { {"osc-info", no_argument
, NULL
, OPTION_OSC_INFO
},
114 '\0', NULL
, "Print information about current input oscillators",
115 m68hc11_option_handler
},
117 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
125 struct hw_event
*event
;
132 #define NR_PORT_A_OSC (4)
133 #define NR_PORT_B_OSC (0)
134 #define NR_PORT_C_OSC (8)
135 #define NR_PORT_D_OSC (6)
136 #define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)
138 /* Pending interrupts for delivery by event handler. */
142 struct hw_event
*event
;
143 unsigned_word attach_address
;
147 struct input_osc oscillators
[NR_OSC
];
152 /* input port ID's */
170 static const struct hw_port_descriptor m68hc11cpu_ports
[] = {
172 /* Interrupt inputs. */
173 { "reset", RESET_PORT
, 0, input_port
, },
174 { "nmi", NMI_PORT
, 0, input_port
, },
175 { "irq", IRQ_PORT
, 0, input_port
, },
177 { "set-port-a", SET_PORT_A
, 0, input_port
, },
178 { "set-port-c", SET_PORT_C
, 0, input_port
, },
179 { "set-port-d", SET_PORT_D
, 0, input_port
, },
181 /* Events generated for connection to other devices. */
182 { "cpu-reset", CPU_RESET_PORT
, 0, output_port
, },
184 /* Events generated when the corresponding port is
185 changed by the program. */
186 { "port-a", PORT_A
, 0, output_port
, },
187 { "port-b", PORT_B
, 0, output_port
, },
188 { "port-c", PORT_C
, 0, output_port
, },
189 { "port-d", PORT_D
, 0, output_port
, },
191 { "capture", CAPTURE
, 0, output_port
, },
196 static hw_io_read_buffer_method m68hc11cpu_io_read_buffer
;
197 static hw_io_write_buffer_method m68hc11cpu_io_write_buffer
;
198 static hw_ioctl_method m68hc11_ioctl
;
200 /* Finish off the partially created hw device. Attach our local
201 callbacks. Wire up our port names etc. */
203 static hw_port_event_method m68hc11cpu_port_event
;
205 static void make_oscillator (struct m68hc11cpu
*controller
,
206 const char *id
, uint16 addr
, uint8 mask
);
207 static struct input_osc
*find_oscillator (struct m68hc11cpu
*controller
,
209 static void reset_oscillators (struct hw
*me
);
212 dv_m6811_attach_address_callback (struct hw
*me
,
216 address_word nr_bytes
,
219 HW_TRACE ((me
, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
220 level
, space
, (unsigned long) addr
, (unsigned long) nr_bytes
,
225 sim_core_attach (hw_system (me
),
228 access_read_write_exec
,
237 /*printf("Attach from sub device: %d\n", (long) addr);*/
238 sim_core_attach (hw_system (me
),
251 dv_m6811_detach_address_callback (struct hw
*me
,
255 address_word nr_bytes
,
258 sim_core_detach (hw_system (me
), NULL
, /*cpu*/
263 m68hc11_delete (struct hw
* me
)
265 struct m68hc11cpu
*controller
;
267 controller
= hw_data (me
);
269 reset_oscillators (me
);
270 hw_detach_address (me
, M6811_IO_LEVEL
,
271 controller
->attach_space
,
272 controller
->attach_address
,
273 controller
->attach_size
, me
);
278 attach_m68hc11_regs (struct hw
*me
,
279 struct m68hc11cpu
*controller
)
283 reg_property_spec reg
;
284 const char *cpu_mode
;
286 if (hw_find_property (me
, "reg") == NULL
)
287 hw_abort (me
, "Missing \"reg\" property");
289 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
290 hw_abort (me
, "\"reg\" property must contain one addr/size entry");
292 hw_unit_address_to_attach_address (hw_parent (me
),
294 &controller
->attach_space
,
295 &controller
->attach_address
,
297 hw_unit_size_to_attach_size (hw_parent (me
),
299 &controller
->attach_size
, me
);
301 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
302 controller
->attach_space
,
303 controller
->attach_address
,
304 controller
->attach_size
,
306 set_hw_delete (me
, m68hc11_delete
);
308 /* Get cpu frequency. */
310 cpu
= STATE_CPU (sd
, 0);
311 if (hw_find_property (me
, "clock") != NULL
)
313 cpu
->cpu_frequency
= hw_find_integer_property (me
, "clock");
317 cpu
->cpu_frequency
= 8*1000*1000;
320 cpu_mode
= "expanded";
321 if (hw_find_property (me
, "mode") != NULL
)
322 cpu_mode
= hw_find_string_property (me
, "mode");
324 if (strcmp (cpu_mode
, "test") == 0)
325 cpu
->cpu_mode
= M6811_MDA
| M6811_SMOD
;
326 else if (strcmp (cpu_mode
, "bootstrap") == 0)
327 cpu
->cpu_mode
= M6811_SMOD
;
328 else if (strcmp (cpu_mode
, "single") == 0)
331 cpu
->cpu_mode
= M6811_MDA
;
333 controller
->last_oscillator
= 0;
335 /* Create oscillators for input port A. */
336 make_oscillator (controller
, "A7", M6811_PORTA
, 0x80);
337 make_oscillator (controller
, "A2", M6811_PORTA
, 0x04);
338 make_oscillator (controller
, "A1", M6811_PORTA
, 0x02);
339 make_oscillator (controller
, "A0", M6811_PORTA
, 0x01);
341 /* port B is output only. */
343 /* Create oscillators for input port C. */
344 make_oscillator (controller
, "C0", M6811_PORTC
, 0x01);
345 make_oscillator (controller
, "C1", M6811_PORTC
, 0x02);
346 make_oscillator (controller
, "C2", M6811_PORTC
, 0x04);
347 make_oscillator (controller
, "C3", M6811_PORTC
, 0x08);
348 make_oscillator (controller
, "C4", M6811_PORTC
, 0x10);
349 make_oscillator (controller
, "C5", M6811_PORTC
, 0x20);
350 make_oscillator (controller
, "C6", M6811_PORTC
, 0x40);
351 make_oscillator (controller
, "C7", M6811_PORTC
, 0x80);
353 /* Create oscillators for input port D. */
354 make_oscillator (controller
, "D0", M6811_PORTD
, 0x01);
355 make_oscillator (controller
, "D1", M6811_PORTD
, 0x02);
356 make_oscillator (controller
, "D2", M6811_PORTD
, 0x04);
357 make_oscillator (controller
, "D3", M6811_PORTD
, 0x08);
358 make_oscillator (controller
, "D4", M6811_PORTD
, 0x10);
359 make_oscillator (controller
, "D5", M6811_PORTD
, 0x20);
361 /* Add oscillator commands. */
362 sim_add_option_table (sd
, 0, m68hc11_options
);
366 m68hc11cpu_finish (struct hw
*me
)
368 struct m68hc11cpu
*controller
;
370 controller
= HW_ZALLOC (me
, struct m68hc11cpu
);
371 set_hw_data (me
, controller
);
372 set_hw_io_read_buffer (me
, m68hc11cpu_io_read_buffer
);
373 set_hw_io_write_buffer (me
, m68hc11cpu_io_write_buffer
);
374 set_hw_ports (me
, m68hc11cpu_ports
);
375 set_hw_port_event (me
, m68hc11cpu_port_event
);
376 set_hw_attach_address (me
, dv_m6811_attach_address_callback
);
377 set_hw_detach_address (me
, dv_m6811_detach_address_callback
);
379 set_hw_ioctl (me
, m68hc11_ioctl
);
381 me
->to_ioctl
= m68hc11_ioctl
;
384 /* Initialize the pending interrupt flags. */
385 controller
->pending_level
= 0;
386 controller
->pending_reset
= 0;
387 controller
->pending_nmi
= 0;
388 controller
->event
= NULL
;
390 attach_m68hc11_regs (me
, controller
);
393 /* An event arrives on an interrupt port. */
396 deliver_m68hc11cpu_interrupt (struct hw
*me
, void *data
)
401 make_oscillator (struct m68hc11cpu
*controller
, const char *name
,
402 uint16 addr
, uint8 mask
)
404 struct input_osc
*osc
;
406 if (controller
->last_oscillator
>= NR_OSC
)
407 hw_abort (0, "Too many oscillators");
409 osc
= &controller
->oscillators
[controller
->last_oscillator
];
413 controller
->last_oscillator
++;
416 /* Find the oscillator given the input port name. */
417 static struct input_osc
*
418 find_oscillator (struct m68hc11cpu
*controller
, const char *name
)
422 for (i
= 0; i
< controller
->last_oscillator
; i
++)
423 if (strcasecmp (controller
->oscillators
[i
].name
, name
) == 0)
424 return &controller
->oscillators
[i
];
430 oscillator_handler (struct hw
*me
, void *data
)
432 struct input_osc
*osc
= (struct input_osc
*) data
;
439 cpu
= STATE_CPU (sd
, 0);
441 /* Change the input bit. */
442 osc
->value
^= osc
->mask
;
443 val
= cpu
->ios
[osc
->addr
] & ~osc
->mask
;
445 m68hc11cpu_set_port (me
, cpu
, osc
->addr
, val
);
447 /* Setup event to toggle the bit. */
453 if (dt
&& --osc
->repeat
>= 0)
455 sim_events
*events
= STATE_EVENTS (sd
);
457 dt
+= events
->nr_ticks_to_process
;
458 osc
->event
= hw_event_queue_schedule (me
, dt
, oscillator_handler
, osc
);
465 reset_oscillators (struct hw
*me
)
467 struct m68hc11cpu
*controller
= hw_data (me
);
470 for (i
= 0; i
< controller
->last_oscillator
; i
++)
472 if (controller
->oscillators
[i
].event
)
474 hw_event_queue_deschedule (me
, controller
->oscillators
[i
].event
);
475 controller
->oscillators
[i
].event
= 0;
481 m68hc11cpu_port_event (struct hw
*me
,
487 struct m68hc11cpu
*controller
= hw_data (me
);
492 cpu
= STATE_CPU (sd
, 0);
496 HW_TRACE ((me
, "port-in reset"));
498 /* The reset is made in 3 steps:
499 - First, cleanup the current sim_cpu struct.
501 - Restart the cpu for the reset (get the CPU mode from the
502 CONFIG register that gets initialized by EEPROM device). */
504 reset_oscillators (me
);
505 hw_port_event (me
, CPU_RESET_PORT
, 1);
510 controller
->pending_nmi
= 1;
511 HW_TRACE ((me
, "port-in nmi"));
515 /* level == 0 means that the interrupt was cleared. */
517 controller
->pending_level
= -1; /* signal end of interrupt */
519 controller
->pending_level
= level
;
520 HW_TRACE ((me
, "port-in level=%d", level
));
524 m68hc11cpu_set_port (me
, cpu
, M6811_PORTA
, level
);
528 m68hc11cpu_set_port (me
, cpu
, M6811_PORTC
, level
);
532 m68hc11cpu_set_port (me
, cpu
, M6811_PORTD
, level
);
536 hw_abort (me
, "bad switch");
540 /* Schedule an event to be delivered immediately after current
542 if(controller
->event
!= NULL
)
543 hw_event_queue_deschedule(me
, controller
->event
);
545 hw_event_queue_schedule (me
, 0, deliver_m68hc11cpu_interrupt
, NULL
);
549 io_reg_desc config_desc
[] = {
550 { M6811_NOSEC
, "NOSEC ", "Security Mode Disable" },
551 { M6811_NOCOP
, "NOCOP ", "COP System Disable" },
552 { M6811_ROMON
, "ROMON ", "Enable On-chip Rom" },
553 { M6811_EEON
, "EEON ", "Enable On-chip EEprom" },
557 io_reg_desc hprio_desc
[] = {
558 { M6811_RBOOT
, "RBOOT ", "Read Bootstrap ROM" },
559 { M6811_SMOD
, "SMOD ", "Special Mode" },
560 { M6811_MDA
, "MDA ", "Mode Select A" },
561 { M6811_IRV
, "IRV ", "Internal Read Visibility" },
565 io_reg_desc option_desc
[] = {
566 { M6811_ADPU
, "ADPU ", "A/D Powerup" },
567 { M6811_CSEL
, "CSEL ", "A/D/EE Charge pump clock source select" },
568 { M6811_IRQE
, "IRQE ", "IRQ Edge/Level sensitive" },
569 { M6811_DLY
, "DLY ", "Stop exit turn on delay" },
570 { M6811_CME
, "CME ", "Clock Monitor Enable" },
571 { M6811_CR1
, "CR1 ", "COP timer rate select (CR1)" },
572 { M6811_CR0
, "CR0 ", "COP timer rate select (CR0)" },
577 m68hc11_info (struct hw
*me
)
582 struct m68hc11sio
*controller
;
586 cpu
= STATE_CPU (sd
, 0);
587 controller
= hw_data (me
);
589 base
= cpu_get_io_base (cpu
);
590 sim_io_printf (sd
, "M68HC11:\n");
592 val
= cpu
->ios
[M6811_HPRIO
];
593 print_io_byte (sd
, "HPRIO ", hprio_desc
, val
, base
+ M6811_HPRIO
);
594 switch (cpu
->cpu_mode
)
596 case M6811_MDA
| M6811_SMOD
:
597 sim_io_printf (sd
, "[test]\n");
600 sim_io_printf (sd
, "[bootstrap]\n");
603 sim_io_printf (sd
, "[extended]\n");
606 sim_io_printf (sd
, "[single]\n");
610 val
= cpu
->ios
[M6811_CONFIG
];
611 print_io_byte (sd
, "CONFIG", config_desc
, val
, base
+ M6811_CONFIG
);
612 sim_io_printf (sd
, "\n");
614 val
= cpu
->ios
[M6811_OPTION
];
615 print_io_byte (sd
, "OPTION", option_desc
, val
, base
+ M6811_OPTION
);
616 sim_io_printf (sd
, "\n");
618 val
= cpu
->ios
[M6811_INIT
];
619 print_io_byte (sd
, "INIT ", 0, val
, base
+ M6811_INIT
);
620 sim_io_printf (sd
, "Ram = 0x%04x IO = 0x%04x\n",
621 (((uint16
) (val
& 0xF0)) << 8),
622 (((uint16
) (val
& 0x0F)) << 12));
626 interrupts_info (sd
, &cpu
->cpu_interrupts
);
630 m68hc11_ioctl (struct hw
*me
,
631 hw_ioctl_request request
,
638 /* Setup an oscillator on an input port.
640 TON represents the time in seconds that the input port should be set to 1.
641 TOFF is the time in seconds for the input port to be set to 0.
643 The oscillator frequency is therefore 1 / (ton + toff).
645 REPEAT indicates the number of 1 <-> 0 transitions until the oscillator
648 m68hc11cpu_set_oscillator (SIM_DESC sd
, const char *port
,
649 double ton
, double toff
, signed64 repeat
)
652 struct input_osc
*osc
;
655 cpu
= STATE_CPU (sd
, 0);
657 /* Find oscillator that corresponds to the input port. */
658 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
662 /* Compute the ON time in cpu cycles. */
663 f
= (double) (cpu
->cpu_frequency
) * ton
;
664 osc
->on_time
= (signed64
) (f
/ 4.0);
665 if (osc
->on_time
< 1)
668 /* Compute the OFF time in cpu cycles. */
669 f
= (double) (cpu
->cpu_frequency
) * toff
;
670 osc
->off_time
= (signed64
) (f
/ 4.0);
671 if (osc
->off_time
< 1)
674 osc
->repeat
= repeat
;
676 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
678 osc
->event
= hw_event_queue_schedule (cpu
->hw_cpu
,
679 osc
->value
? osc
->on_time
681 oscillator_handler
, osc
);
685 /* Clear the oscillator. */
687 m68hc11cpu_clear_oscillator (SIM_DESC sd
, const char *port
)
690 struct input_osc
*osc
;
692 cpu
= STATE_CPU (sd
, 0);
693 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
698 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
705 get_frequency (const char *s
, double *f
)
715 if (strcasecmp (p
, "khz") == 0)
717 else if (strcasecmp (p
, "mhz") == 0)
719 else if (strcasecmp (p
, "hz") != 0)
726 m68hc11_option_handler (SIM_DESC sd
, sim_cpu
*cpu
,
727 int opt
, char *arg
, int is_command
)
729 struct m68hc11cpu
*controller
;
733 int title_printed
= 0;
736 cpu
= STATE_CPU (sd
, 0);
738 controller
= hw_data (cpu
->hw_cpu
);
742 p
= strchr (arg
, ',');
747 sim_io_eprintf (sd
, "No frequency specified\n");
748 else if (get_frequency (p
, &f
) < 0 || f
< 1.0e-8)
749 sim_io_eprintf (sd
, "Invalid frequency: '%s'\n", p
);
750 else if (m68hc11cpu_set_oscillator (sd
, arg
,
752 1.0 / (f
* 2.0), LONG_MAX
))
753 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
756 case OPTION_OSC_CLEAR
:
757 if (m68hc11cpu_clear_oscillator (sd
, arg
) != 0)
758 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
761 case OPTION_OSC_INFO
:
762 for (i
= 0; i
< controller
->last_oscillator
; i
++)
765 struct input_osc
*osc
;
767 osc
= &controller
->oscillators
[i
];
775 if (title_printed
== 0)
778 sim_io_printf (sd
, " PORT Frequency Current"
779 " Next Transition time\n");
782 f
= (double) (osc
->on_time
+ osc
->off_time
);
783 f
= (double) (cpu
->cpu_frequency
/ 4) / f
;
784 t
= hw_event_remain_time (cpu
->hw_cpu
, osc
->event
);
787 sprintf (freq
, "%6.2f", f
/ 1000.0);
789 sprintf (freq
, "%6.2f", f
);
790 cur_value
= osc
->value
? 1 : 0;
791 next_value
= osc
->value
? 0 : 1;
793 sim_io_printf (sd
, " %4.4s %8.8s khz"
796 cur_value
, next_value
,
797 cycle_to_string (cpu
, t
));
799 sim_io_printf (sd
, " %4.4s %8.8s hz "
802 cur_value
, next_value
,
803 cycle_to_string (cpu
, t
));
812 /* generic read/write */
815 m68hc11cpu_io_read_buffer (struct hw
*me
,
822 struct m68hc11cpu
*controller
= hw_data (me
);
827 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
830 cpu
= STATE_CPU (sd
, 0);
832 /* Handle reads for the sub-devices. */
833 base
-= controller
->attach_address
;
834 result
= sim_core_read_buffer (sd
, cpu
,
835 io_map
, dest
, base
, nr_bytes
);
841 if (base
>= controller
->attach_size
)
844 memcpy (dest
, &cpu
->ios
[base
], 1);
854 m68hc11cpu_set_port (struct hw
*me
, sim_cpu
*cpu
,
855 unsigned addr
, uint8 val
)
859 int check_interrupts
= 0;
865 if (cpu
->ios
[M6811_PACTL
] & M6811_DDRA7
)
871 val
|= cpu
->ios
[M6811_PORTA
] & ~mask
;
872 delta
= val
^ cpu
->ios
[M6811_PORTA
];
873 cpu
->ios
[M6811_PORTA
] = val
;
876 /* Pulse accumulator is enabled. */
877 if ((cpu
->ios
[M6811_PACTL
] & M6811_PAEN
)
878 && !(cpu
->ios
[M6811_PACTL
] & M6811_PAMOD
))
882 /* Increment event counter according to rising/falling edge. */
883 if (cpu
->ios
[M6811_PACTL
] & M6811_PEDGE
)
884 inc
= (val
& 0x80) ? 1 : 0;
886 inc
= (val
& 0x80) ? 0 : 1;
888 cpu
->ios
[M6811_PACNT
] += inc
;
890 /* Event counter overflowed. */
891 if (inc
&& cpu
->ios
[M6811_PACNT
] == 0)
893 cpu
->ios
[M6811_TFLG2
] |= M6811_PAOVI
;
894 check_interrupts
= 1;
899 /* Scan IC3, IC2 and IC1. Bit number is 3 - i. */
900 for (i
= 0; i
< 3; i
++)
902 uint8 mask
= (1 << i
);
909 edge
= cpu
->ios
[M6811_TCTL2
];
910 edge
= (edge
>> (2 * i
)) & 0x3;
917 captured
= (val
& mask
) != 0;
920 captured
= (val
& mask
) == 0;
928 cpu
->ios
[M6811_TFLG1
] |= (1 << i
);
929 hw_port_event (me
, CAPTURE
, M6811_TIC1
+ 3 - i
);
930 check_interrupts
= 1;
937 mask
= cpu
->ios
[M6811_DDRC
];
939 val
|= cpu
->ios
[M6811_PORTC
] & ~mask
;
940 cpu
->ios
[M6811_PORTC
] = val
;
944 mask
= cpu
->ios
[M6811_DDRD
];
946 val
|= cpu
->ios
[M6811_PORTD
] & ~mask
;
947 cpu
->ios
[M6811_PORTD
] = val
;
954 if (check_interrupts
)
955 interrupts_update_pending (&cpu
->cpu_interrupts
);
959 m68hc11cpu_io_write (struct hw
*me
, sim_cpu
*cpu
,
960 unsigned_word addr
, uint8 val
)
965 hw_port_event (me
, PORT_A
, val
);
972 hw_port_event (me
, PORT_C
, val
);
976 hw_port_event (me
, PORT_B
, val
);
986 hw_port_event (me
, PORT_D
, val
);
996 /* Change the RAM and I/O mapping. */
999 uint8 old_bank
= cpu
->ios
[M6811_INIT
];
1001 cpu
->ios
[M6811_INIT
] = val
;
1003 /* Update IO mapping. Detach from the old address
1004 and attach to the new one. */
1005 if ((old_bank
& 0x0F) != (val
& 0x0F))
1007 struct m68hc11cpu
*controller
= hw_data (me
);
1009 hw_detach_address (hw_parent (me
), M6811_IO_LEVEL
,
1010 controller
->attach_space
,
1011 controller
->attach_address
,
1012 controller
->attach_size
,
1014 controller
->attach_address
= (val
& 0x0F0) << 12;
1015 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
1016 controller
->attach_space
,
1017 controller
->attach_address
,
1018 controller
->attach_size
,
1021 if ((old_bank
& 0xF0) != (val
& 0xF0))
1028 /* Writing the config is similar to programing the eeprom.
1029 The config register value is the last byte of the EEPROM.
1030 This last byte is not mapped in memory (that's why we have
1031 to add '1' to 'end_addr'). */
1040 if (val
== 0xAA && cpu
->ios
[addr
] == 0x55)
1043 /* COP reset here. */
1051 cpu
->ios
[addr
] = val
;
1055 m68hc11cpu_io_write_buffer (struct hw
*me
,
1062 struct m68hc11cpu
*controller
= hw_data (me
);
1067 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
1069 sd
= hw_system (me
);
1070 cpu
= STATE_CPU (sd
, 0);
1071 base
-= controller
->attach_address
;
1072 result
= sim_core_write_buffer (sd
, cpu
,
1073 io_map
, source
, base
, nr_bytes
);
1081 if (base
>= controller
->attach_size
)
1084 val
= *((uint8
*) source
);
1085 m68hc11cpu_io_write (me
, cpu
, base
, val
);
1094 const struct hw_descriptor dv_m68hc11_descriptor
[] = {
1095 { "m68hc11", m68hc11cpu_finish
},
1096 { "m68hc12", m68hc11cpu_finish
},