1 /* dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.
2 Copyright (C) 1999, 2000, 2001, 2002, 2003 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 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"
32 m68hc11cpu - m68hc11 cpu virtual device
33 m68hc12cpu - m68hc12 cpu virtual device
37 Implements the external m68hc11/68hc12 functionality. This includes
38 the delivery of of interrupts generated from other devices and the
39 handling of device specific registers.
46 Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).
50 Frequency of the quartz used by the processor.
52 mode [single | expanded | bootstrap | test]
54 Cpu operating mode (the MODA and MODB external pins).
61 Reset the cpu and generates a cpu-reset event (used to reset
66 Deliver a non-maskable interrupt to the processor.
73 Allow an external device to set the value of port A, C or D inputs.
78 Event generated after the CPU performs a reset.
86 Event generated when the value of the output port A, B, C or D
92 When delivering an interrupt, this code assumes that there is only
93 one processor (number 0).
99 OPTION_OSC_SET
= OPTION_START
,
104 static DECLARE_OPTION_HANDLER (m68hc11_option_handler
);
106 static const OPTION m68hc11_options
[] =
108 { {"osc-set", required_argument
, NULL
, OPTION_OSC_SET
},
109 '\0', "BIT,FREQ", "Set the oscillator on input port BIT",
110 m68hc11_option_handler
},
111 { {"osc-clear", required_argument
, NULL
, OPTION_OSC_CLEAR
},
112 '\0', "BIT", "Clear oscillator on input port BIT",
113 m68hc11_option_handler
},
114 { {"osc-info", no_argument
, NULL
, OPTION_OSC_INFO
},
115 '\0', NULL
, "Print information about current input oscillators",
116 m68hc11_option_handler
},
118 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
126 struct hw_event
*event
;
133 #define NR_PORT_A_OSC (4)
134 #define NR_PORT_B_OSC (0)
135 #define NR_PORT_C_OSC (8)
136 #define NR_PORT_D_OSC (6)
137 #define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)
139 /* Pending interrupts for delivery by event handler. */
143 struct hw_event
*event
;
144 unsigned_word attach_address
;
148 struct input_osc oscillators
[NR_OSC
];
153 /* input port ID's */
172 static const struct hw_port_descriptor m68hc11cpu_ports
[] = {
174 /* Interrupt inputs. */
175 { "reset", RESET_PORT
, 0, input_port
, },
176 { "nmi", NMI_PORT
, 0, input_port
, },
177 { "irq", IRQ_PORT
, 0, input_port
, },
179 { "set-port-a", SET_PORT_A
, 0, input_port
, },
180 { "set-port-c", SET_PORT_C
, 0, input_port
, },
181 { "set-port-d", SET_PORT_D
, 0, input_port
, },
183 { "cpu-write-port", CPU_WRITE_PORT
, 0, input_port
, },
185 /* Events generated for connection to other devices. */
186 { "cpu-reset", CPU_RESET_PORT
, 0, output_port
, },
188 /* Events generated when the corresponding port is
189 changed by the program. */
190 { "port-a", PORT_A
, 0, output_port
, },
191 { "port-b", PORT_B
, 0, output_port
, },
192 { "port-c", PORT_C
, 0, output_port
, },
193 { "port-d", PORT_D
, 0, output_port
, },
195 { "capture", CAPTURE
, 0, output_port
, },
200 static hw_io_read_buffer_method m68hc11cpu_io_read_buffer
;
201 static hw_io_write_buffer_method m68hc11cpu_io_write_buffer
;
202 static hw_ioctl_method m68hc11_ioctl
;
204 /* Finish off the partially created hw device. Attach our local
205 callbacks. Wire up our port names etc. */
207 static hw_port_event_method m68hc11cpu_port_event
;
209 static void make_oscillator (struct m68hc11cpu
*controller
,
210 const char *id
, uint16 addr
, uint8 mask
);
211 static struct input_osc
*find_oscillator (struct m68hc11cpu
*controller
,
213 static void reset_oscillators (struct hw
*me
);
216 dv_m6811_attach_address_callback (struct hw
*me
,
220 address_word nr_bytes
,
223 HW_TRACE ((me
, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
224 level
, space
, (unsigned long) addr
, (unsigned long) nr_bytes
,
229 sim_core_attach (hw_system (me
),
232 access_read_write_exec
,
241 /*printf("Attach from sub device: %d\n", (long) addr);*/
242 sim_core_attach (hw_system (me
),
255 dv_m6811_detach_address_callback (struct hw
*me
,
259 address_word nr_bytes
,
262 sim_core_detach (hw_system (me
), NULL
, /*cpu*/
267 m68hc11_delete (struct hw
* me
)
269 struct m68hc11cpu
*controller
;
271 controller
= hw_data (me
);
273 reset_oscillators (me
);
274 hw_detach_address (me
, M6811_IO_LEVEL
,
275 controller
->attach_space
,
276 controller
->attach_address
,
277 controller
->attach_size
, me
);
282 attach_m68hc11_regs (struct hw
*me
,
283 struct m68hc11cpu
*controller
)
287 reg_property_spec reg
;
288 const char *cpu_mode
;
290 if (hw_find_property (me
, "reg") == NULL
)
291 hw_abort (me
, "Missing \"reg\" property");
293 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
294 hw_abort (me
, "\"reg\" property must contain one addr/size entry");
296 hw_unit_address_to_attach_address (hw_parent (me
),
298 &controller
->attach_space
,
299 &controller
->attach_address
,
301 hw_unit_size_to_attach_size (hw_parent (me
),
303 &controller
->attach_size
, me
);
305 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
306 controller
->attach_space
,
307 controller
->attach_address
,
308 controller
->attach_size
,
310 set_hw_delete (me
, m68hc11_delete
);
312 /* Get cpu frequency. */
314 cpu
= STATE_CPU (sd
, 0);
315 if (hw_find_property (me
, "clock") != NULL
)
317 cpu
->cpu_frequency
= hw_find_integer_property (me
, "clock");
321 cpu
->cpu_frequency
= 8*1000*1000;
324 if (hw_find_property (me
, "use_bank") != NULL
)
325 hw_attach_address (hw_parent (me
), 0,
328 cpu
->bank_end
- cpu
->bank_start
,
331 cpu_mode
= "expanded";
332 if (hw_find_property (me
, "mode") != NULL
)
333 cpu_mode
= hw_find_string_property (me
, "mode");
335 if (strcmp (cpu_mode
, "test") == 0)
336 cpu
->cpu_mode
= M6811_MDA
| M6811_SMOD
;
337 else if (strcmp (cpu_mode
, "bootstrap") == 0)
338 cpu
->cpu_mode
= M6811_SMOD
;
339 else if (strcmp (cpu_mode
, "single") == 0)
342 cpu
->cpu_mode
= M6811_MDA
;
344 controller
->last_oscillator
= 0;
346 /* Create oscillators for input port A. */
347 make_oscillator (controller
, "A7", M6811_PORTA
, 0x80);
348 make_oscillator (controller
, "A2", M6811_PORTA
, 0x04);
349 make_oscillator (controller
, "A1", M6811_PORTA
, 0x02);
350 make_oscillator (controller
, "A0", M6811_PORTA
, 0x01);
352 /* port B is output only. */
354 /* Create oscillators for input port C. */
355 make_oscillator (controller
, "C0", M6811_PORTC
, 0x01);
356 make_oscillator (controller
, "C1", M6811_PORTC
, 0x02);
357 make_oscillator (controller
, "C2", M6811_PORTC
, 0x04);
358 make_oscillator (controller
, "C3", M6811_PORTC
, 0x08);
359 make_oscillator (controller
, "C4", M6811_PORTC
, 0x10);
360 make_oscillator (controller
, "C5", M6811_PORTC
, 0x20);
361 make_oscillator (controller
, "C6", M6811_PORTC
, 0x40);
362 make_oscillator (controller
, "C7", M6811_PORTC
, 0x80);
364 /* Create oscillators for input port D. */
365 make_oscillator (controller
, "D0", M6811_PORTD
, 0x01);
366 make_oscillator (controller
, "D1", M6811_PORTD
, 0x02);
367 make_oscillator (controller
, "D2", M6811_PORTD
, 0x04);
368 make_oscillator (controller
, "D3", M6811_PORTD
, 0x08);
369 make_oscillator (controller
, "D4", M6811_PORTD
, 0x10);
370 make_oscillator (controller
, "D5", M6811_PORTD
, 0x20);
372 /* Add oscillator commands. */
373 sim_add_option_table (sd
, 0, m68hc11_options
);
377 m68hc11cpu_finish (struct hw
*me
)
379 struct m68hc11cpu
*controller
;
381 controller
= HW_ZALLOC (me
, struct m68hc11cpu
);
382 set_hw_data (me
, controller
);
383 set_hw_io_read_buffer (me
, m68hc11cpu_io_read_buffer
);
384 set_hw_io_write_buffer (me
, m68hc11cpu_io_write_buffer
);
385 set_hw_ports (me
, m68hc11cpu_ports
);
386 set_hw_port_event (me
, m68hc11cpu_port_event
);
387 set_hw_attach_address (me
, dv_m6811_attach_address_callback
);
388 set_hw_detach_address (me
, dv_m6811_detach_address_callback
);
390 set_hw_ioctl (me
, m68hc11_ioctl
);
392 me
->to_ioctl
= m68hc11_ioctl
;
395 /* Initialize the pending interrupt flags. */
396 controller
->pending_level
= 0;
397 controller
->pending_reset
= 0;
398 controller
->pending_nmi
= 0;
399 controller
->event
= NULL
;
401 attach_m68hc11_regs (me
, controller
);
404 /* An event arrives on an interrupt port. */
407 deliver_m68hc11cpu_interrupt (struct hw
*me
, void *data
)
412 make_oscillator (struct m68hc11cpu
*controller
, const char *name
,
413 uint16 addr
, uint8 mask
)
415 struct input_osc
*osc
;
417 if (controller
->last_oscillator
>= NR_OSC
)
418 hw_abort (0, "Too many oscillators");
420 osc
= &controller
->oscillators
[controller
->last_oscillator
];
424 controller
->last_oscillator
++;
427 /* Find the oscillator given the input port name. */
428 static struct input_osc
*
429 find_oscillator (struct m68hc11cpu
*controller
, const char *name
)
433 for (i
= 0; i
< controller
->last_oscillator
; i
++)
434 if (strcasecmp (controller
->oscillators
[i
].name
, name
) == 0)
435 return &controller
->oscillators
[i
];
441 oscillator_handler (struct hw
*me
, void *data
)
443 struct input_osc
*osc
= (struct input_osc
*) data
;
450 cpu
= STATE_CPU (sd
, 0);
452 /* Change the input bit. */
453 osc
->value
^= osc
->mask
;
454 val
= cpu
->ios
[osc
->addr
] & ~osc
->mask
;
456 m68hc11cpu_set_port (me
, cpu
, osc
->addr
, val
);
458 /* Setup event to toggle the bit. */
464 if (dt
&& --osc
->repeat
>= 0)
466 sim_events
*events
= STATE_EVENTS (sd
);
468 dt
+= events
->nr_ticks_to_process
;
469 osc
->event
= hw_event_queue_schedule (me
, dt
, oscillator_handler
, osc
);
476 reset_oscillators (struct hw
*me
)
478 struct m68hc11cpu
*controller
= hw_data (me
);
481 for (i
= 0; i
< controller
->last_oscillator
; i
++)
483 if (controller
->oscillators
[i
].event
)
485 hw_event_queue_deschedule (me
, controller
->oscillators
[i
].event
);
486 controller
->oscillators
[i
].event
= 0;
492 m68hc11cpu_port_event (struct hw
*me
,
498 struct m68hc11cpu
*controller
= hw_data (me
);
503 cpu
= STATE_CPU (sd
, 0);
507 HW_TRACE ((me
, "port-in reset"));
509 /* The reset is made in 3 steps:
510 - First, cleanup the current sim_cpu struct.
512 - Restart the cpu for the reset (get the CPU mode from the
513 CONFIG register that gets initialized by EEPROM device). */
515 reset_oscillators (me
);
516 hw_port_event (me
, CPU_RESET_PORT
, 1);
521 controller
->pending_nmi
= 1;
522 HW_TRACE ((me
, "port-in nmi"));
526 /* level == 0 means that the interrupt was cleared. */
528 controller
->pending_level
= -1; /* signal end of interrupt */
530 controller
->pending_level
= level
;
531 HW_TRACE ((me
, "port-in level=%d", level
));
535 m68hc11cpu_set_port (me
, cpu
, M6811_PORTA
, level
);
539 m68hc11cpu_set_port (me
, cpu
, M6811_PORTC
, level
);
543 m68hc11cpu_set_port (me
, cpu
, M6811_PORTD
, level
);
550 hw_abort (me
, "bad switch");
554 /* Schedule an event to be delivered immediately after current
556 if(controller
->event
!= NULL
)
557 hw_event_queue_deschedule(me
, controller
->event
);
559 hw_event_queue_schedule (me
, 0, deliver_m68hc11cpu_interrupt
, NULL
);
563 io_reg_desc config_desc
[] = {
564 { M6811_NOSEC
, "NOSEC ", "Security Mode Disable" },
565 { M6811_NOCOP
, "NOCOP ", "COP System Disable" },
566 { M6811_ROMON
, "ROMON ", "Enable On-chip Rom" },
567 { M6811_EEON
, "EEON ", "Enable On-chip EEprom" },
571 io_reg_desc hprio_desc
[] = {
572 { M6811_RBOOT
, "RBOOT ", "Read Bootstrap ROM" },
573 { M6811_SMOD
, "SMOD ", "Special Mode" },
574 { M6811_MDA
, "MDA ", "Mode Select A" },
575 { M6811_IRV
, "IRV ", "Internal Read Visibility" },
579 io_reg_desc option_desc
[] = {
580 { M6811_ADPU
, "ADPU ", "A/D Powerup" },
581 { M6811_CSEL
, "CSEL ", "A/D/EE Charge pump clock source select" },
582 { M6811_IRQE
, "IRQE ", "IRQ Edge/Level sensitive" },
583 { M6811_DLY
, "DLY ", "Stop exit turn on delay" },
584 { M6811_CME
, "CME ", "Clock Monitor Enable" },
585 { M6811_CR1
, "CR1 ", "COP timer rate select (CR1)" },
586 { M6811_CR0
, "CR0 ", "COP timer rate select (CR0)" },
591 m68hc11_info (struct hw
*me
)
596 struct m68hc11sio
*controller
;
600 cpu
= STATE_CPU (sd
, 0);
601 controller
= hw_data (me
);
603 base
= cpu_get_io_base (cpu
);
604 sim_io_printf (sd
, "M68HC11:\n");
606 val
= cpu
->ios
[M6811_HPRIO
];
607 print_io_byte (sd
, "HPRIO ", hprio_desc
, val
, base
+ M6811_HPRIO
);
608 switch (cpu
->cpu_mode
)
610 case M6811_MDA
| M6811_SMOD
:
611 sim_io_printf (sd
, "[test]\n");
614 sim_io_printf (sd
, "[bootstrap]\n");
617 sim_io_printf (sd
, "[extended]\n");
620 sim_io_printf (sd
, "[single]\n");
624 val
= cpu
->ios
[M6811_CONFIG
];
625 print_io_byte (sd
, "CONFIG", config_desc
, val
, base
+ M6811_CONFIG
);
626 sim_io_printf (sd
, "\n");
628 val
= cpu
->ios
[M6811_OPTION
];
629 print_io_byte (sd
, "OPTION", option_desc
, val
, base
+ M6811_OPTION
);
630 sim_io_printf (sd
, "\n");
632 val
= cpu
->ios
[M6811_INIT
];
633 print_io_byte (sd
, "INIT ", 0, val
, base
+ M6811_INIT
);
634 sim_io_printf (sd
, "Ram = 0x%04x IO = 0x%04x\n",
635 (((uint16
) (val
& 0xF0)) << 8),
636 (((uint16
) (val
& 0x0F)) << 12));
640 interrupts_info (sd
, &cpu
->cpu_interrupts
);
644 m68hc11_ioctl (struct hw
*me
,
645 hw_ioctl_request request
,
652 /* Setup an oscillator on an input port.
654 TON represents the time in seconds that the input port should be set to 1.
655 TOFF is the time in seconds for the input port to be set to 0.
657 The oscillator frequency is therefore 1 / (ton + toff).
659 REPEAT indicates the number of 1 <-> 0 transitions until the oscillator
662 m68hc11cpu_set_oscillator (SIM_DESC sd
, const char *port
,
663 double ton
, double toff
, signed64 repeat
)
666 struct input_osc
*osc
;
669 cpu
= STATE_CPU (sd
, 0);
671 /* Find oscillator that corresponds to the input port. */
672 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
676 /* Compute the ON time in cpu cycles. */
677 f
= (double) (cpu
->cpu_frequency
) * ton
;
678 osc
->on_time
= (signed64
) (f
/ 4.0);
679 if (osc
->on_time
< 1)
682 /* Compute the OFF time in cpu cycles. */
683 f
= (double) (cpu
->cpu_frequency
) * toff
;
684 osc
->off_time
= (signed64
) (f
/ 4.0);
685 if (osc
->off_time
< 1)
688 osc
->repeat
= repeat
;
690 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
692 osc
->event
= hw_event_queue_schedule (cpu
->hw_cpu
,
693 osc
->value
? osc
->on_time
695 oscillator_handler
, osc
);
699 /* Clear the oscillator. */
701 m68hc11cpu_clear_oscillator (SIM_DESC sd
, const char *port
)
704 struct input_osc
*osc
;
706 cpu
= STATE_CPU (sd
, 0);
707 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
712 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
719 get_frequency (const char *s
, double *f
)
729 if (strcasecmp (p
, "khz") == 0)
731 else if (strcasecmp (p
, "mhz") == 0)
733 else if (strcasecmp (p
, "hz") != 0)
740 m68hc11_option_handler (SIM_DESC sd
, sim_cpu
*cpu
,
741 int opt
, char *arg
, int is_command
)
743 struct m68hc11cpu
*controller
;
747 int title_printed
= 0;
750 cpu
= STATE_CPU (sd
, 0);
752 controller
= hw_data (cpu
->hw_cpu
);
756 p
= strchr (arg
, ',');
761 sim_io_eprintf (sd
, "No frequency specified\n");
762 else if (get_frequency (p
, &f
) < 0 || f
< 1.0e-8)
763 sim_io_eprintf (sd
, "Invalid frequency: '%s'\n", p
);
764 else if (m68hc11cpu_set_oscillator (sd
, arg
,
766 1.0 / (f
* 2.0), LONG_MAX
))
767 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
770 case OPTION_OSC_CLEAR
:
771 if (m68hc11cpu_clear_oscillator (sd
, arg
) != 0)
772 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
775 case OPTION_OSC_INFO
:
776 for (i
= 0; i
< controller
->last_oscillator
; i
++)
779 struct input_osc
*osc
;
781 osc
= &controller
->oscillators
[i
];
789 if (title_printed
== 0)
792 sim_io_printf (sd
, " PORT Frequency Current"
793 " Next Transition time\n");
796 f
= (double) (osc
->on_time
+ osc
->off_time
);
797 f
= (double) (cpu
->cpu_frequency
/ 4) / f
;
798 t
= hw_event_remain_time (cpu
->hw_cpu
, osc
->event
);
801 sprintf (freq
, "%6.2f", f
/ 1000.0);
803 sprintf (freq
, "%6.2f", f
);
804 cur_value
= osc
->value
? 1 : 0;
805 next_value
= osc
->value
? 0 : 1;
807 sim_io_printf (sd
, " %4.4s %8.8s khz"
810 cur_value
, next_value
,
811 cycle_to_string (cpu
, t
));
813 sim_io_printf (sd
, " %4.4s %8.8s hz "
816 cur_value
, next_value
,
817 cycle_to_string (cpu
, t
));
826 /* generic read/write */
829 m68hc11cpu_io_read_buffer (struct hw
*me
,
836 struct m68hc11cpu
*controller
= hw_data (me
);
841 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
844 cpu
= STATE_CPU (sd
, 0);
846 if (base
>= cpu
->bank_start
&& base
< cpu
->bank_end
)
848 address_word virt_addr
= phys_to_virt (cpu
, base
);
849 if (virt_addr
!= base
)
850 return sim_core_read_buffer (sd
, cpu
, space
, dest
,
851 virt_addr
, nr_bytes
);
854 /* Handle reads for the sub-devices. */
855 base
-= controller
->attach_address
;
856 result
= sim_core_read_buffer (sd
, cpu
,
857 io_map
, dest
, base
, nr_bytes
);
863 if (base
>= controller
->attach_size
)
866 memcpy (dest
, &cpu
->ios
[base
], 1);
867 dest
= (char*) dest
+ 1;
876 m68hc11cpu_set_port (struct hw
*me
, sim_cpu
*cpu
,
877 unsigned addr
, uint8 val
)
881 int check_interrupts
= 0;
887 if (cpu
->ios
[M6811_PACTL
] & M6811_DDRA7
)
893 val
|= cpu
->ios
[M6811_PORTA
] & ~mask
;
894 delta
= val
^ cpu
->ios
[M6811_PORTA
];
895 cpu
->ios
[M6811_PORTA
] = val
;
898 /* Pulse accumulator is enabled. */
899 if ((cpu
->ios
[M6811_PACTL
] & M6811_PAEN
)
900 && !(cpu
->ios
[M6811_PACTL
] & M6811_PAMOD
))
904 /* Increment event counter according to rising/falling edge. */
905 if (cpu
->ios
[M6811_PACTL
] & M6811_PEDGE
)
906 inc
= (val
& 0x80) ? 1 : 0;
908 inc
= (val
& 0x80) ? 0 : 1;
910 cpu
->ios
[M6811_PACNT
] += inc
;
912 /* Event counter overflowed. */
913 if (inc
&& cpu
->ios
[M6811_PACNT
] == 0)
915 cpu
->ios
[M6811_TFLG2
] |= M6811_PAOVI
;
916 check_interrupts
= 1;
921 /* Scan IC3, IC2 and IC1. Bit number is 3 - i. */
922 for (i
= 0; i
< 3; i
++)
924 uint8 mask
= (1 << i
);
931 edge
= cpu
->ios
[M6811_TCTL2
];
932 edge
= (edge
>> (2 * i
)) & 0x3;
939 captured
= (val
& mask
) != 0;
942 captured
= (val
& mask
) == 0;
950 cpu
->ios
[M6811_TFLG1
] |= (1 << i
);
951 hw_port_event (me
, CAPTURE
, M6811_TIC1
+ 3 - i
);
952 check_interrupts
= 1;
959 mask
= cpu
->ios
[M6811_DDRC
];
961 val
|= cpu
->ios
[M6811_PORTC
] & ~mask
;
962 cpu
->ios
[M6811_PORTC
] = val
;
966 mask
= cpu
->ios
[M6811_DDRD
];
968 val
|= cpu
->ios
[M6811_PORTD
] & ~mask
;
969 cpu
->ios
[M6811_PORTD
] = val
;
976 if (check_interrupts
)
977 interrupts_update_pending (&cpu
->cpu_interrupts
);
981 m68hc11cpu_io_write (struct hw
*me
, sim_cpu
*cpu
,
982 unsigned_word addr
, uint8 val
)
987 hw_port_event (me
, PORT_A
, val
);
994 hw_port_event (me
, PORT_C
, val
);
998 hw_port_event (me
, PORT_B
, val
);
1008 hw_port_event (me
, PORT_D
, val
);
1018 /* Change the RAM and I/O mapping. */
1021 uint8 old_bank
= cpu
->ios
[M6811_INIT
];
1023 cpu
->ios
[M6811_INIT
] = val
;
1025 /* Update IO mapping. Detach from the old address
1026 and attach to the new one. */
1027 if ((old_bank
& 0x0F) != (val
& 0x0F))
1029 struct m68hc11cpu
*controller
= hw_data (me
);
1031 hw_detach_address (hw_parent (me
), M6811_IO_LEVEL
,
1032 controller
->attach_space
,
1033 controller
->attach_address
,
1034 controller
->attach_size
,
1036 controller
->attach_address
= (val
& 0x0F0) << 12;
1037 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
1038 controller
->attach_space
,
1039 controller
->attach_address
,
1040 controller
->attach_size
,
1043 if ((old_bank
& 0xF0) != (val
& 0xF0))
1050 /* Writing the config is similar to programing the eeprom.
1051 The config register value is the last byte of the EEPROM.
1052 This last byte is not mapped in memory (that's why we have
1053 to add '1' to 'end_addr'). */
1062 if (val
== 0xAA && cpu
->ios
[addr
] == 0x55)
1065 /* COP reset here. */
1073 cpu
->ios
[addr
] = val
;
1077 m68hc11cpu_io_write_buffer (struct hw
*me
,
1084 struct m68hc11cpu
*controller
= hw_data (me
);
1089 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
1091 sd
= hw_system (me
);
1092 cpu
= STATE_CPU (sd
, 0);
1094 if (base
>= cpu
->bank_start
&& base
< cpu
->bank_end
)
1096 address_word virt_addr
= phys_to_virt (cpu
, base
);
1097 if (virt_addr
!= base
)
1098 return sim_core_write_buffer (sd
, cpu
, space
, source
,
1099 virt_addr
, nr_bytes
);
1101 base
-= controller
->attach_address
;
1102 result
= sim_core_write_buffer (sd
, cpu
,
1103 io_map
, source
, base
, nr_bytes
);
1111 if (base
>= controller
->attach_size
)
1114 val
= *((uint8
*) source
);
1115 m68hc11cpu_io_write (me
, cpu
, base
, val
);
1116 source
= (char*) source
+ 1;
1124 const struct hw_descriptor dv_m68hc11_descriptor
[] = {
1125 { "m68hc11", m68hc11cpu_finish
},
1126 { "m68hc12", m68hc11cpu_finish
},