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 sim_io_printf (sd
, "\n");
596 val
= cpu
->ios
[M6811_CONFIG
];
597 print_io_byte (sd
, "CONFIG", config_desc
, val
, base
+ M6811_CONFIG
);
598 sim_io_printf (sd
, "\n");
600 val
= cpu
->ios
[M6811_OPTION
];
601 print_io_byte (sd
, "OPTION", option_desc
, val
, base
+ M6811_OPTION
);
602 sim_io_printf (sd
, "\n");
604 val
= cpu
->ios
[M6811_INIT
];
605 print_io_byte (sd
, "INIT ", 0, val
, base
+ M6811_INIT
);
606 sim_io_printf (sd
, "Ram = 0x%04x IO = 0x%04x\n",
607 (((uint16
) (val
& 0xF0)) << 8),
608 (((uint16
) (val
& 0x0F)) << 12));
612 interrupts_info (sd
, &cpu
->cpu_interrupts
);
616 m68hc11_ioctl (struct hw
*me
,
617 hw_ioctl_request request
,
624 /* Setup an oscillator on an input port.
626 TON represents the time in seconds that the input port should be set to 1.
627 TOFF is the time in seconds for the input port to be set to 0.
629 The oscillator frequency is therefore 1 / (ton + toff).
631 REPEAT indicates the number of 1 <-> 0 transitions until the oscillator
634 m68hc11cpu_set_oscillator (SIM_DESC sd
, const char *port
,
635 double ton
, double toff
, signed64 repeat
)
638 struct input_osc
*osc
;
641 cpu
= STATE_CPU (sd
, 0);
643 /* Find oscillator that corresponds to the input port. */
644 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
648 /* Compute the ON time in cpu cycles. */
649 f
= (double) (cpu
->cpu_frequency
) * ton
;
650 osc
->on_time
= (signed64
) (f
/ 4.0);
651 if (osc
->on_time
< 1)
654 /* Compute the OFF time in cpu cycles. */
655 f
= (double) (cpu
->cpu_frequency
) * toff
;
656 osc
->off_time
= (signed64
) (f
/ 4.0);
657 if (osc
->off_time
< 1)
660 osc
->repeat
= repeat
;
662 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
664 osc
->event
= hw_event_queue_schedule (cpu
->hw_cpu
,
665 osc
->value
? osc
->on_time
667 oscillator_handler
, osc
);
671 /* Clear the oscillator. */
673 m68hc11cpu_clear_oscillator (SIM_DESC sd
, const char *port
)
676 struct input_osc
*osc
;
678 cpu
= STATE_CPU (sd
, 0);
679 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
684 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
691 get_frequency (const char *s
, double *f
)
701 if (strcasecmp (p
, "khz") == 0)
703 else if (strcasecmp (p
, "mhz") == 0)
705 else if (strcasecmp (p
, "hz") != 0)
712 m68hc11_option_handler (SIM_DESC sd
, sim_cpu
*cpu
,
713 int opt
, char *arg
, int is_command
)
715 struct m68hc11cpu
*controller
;
719 int title_printed
= 0;
722 cpu
= STATE_CPU (sd
, 0);
724 controller
= hw_data (cpu
->hw_cpu
);
728 p
= strchr (arg
, ',');
733 sim_io_eprintf (sd
, "No frequency specified\n");
734 else if (get_frequency (p
, &f
) < 0 || f
< 1.0e-8)
735 sim_io_eprintf (sd
, "Invalid frequency: '%s'\n", p
);
736 else if (m68hc11cpu_set_oscillator (sd
, arg
,
738 1.0 / (f
* 2.0), LONG_MAX
))
739 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
742 case OPTION_OSC_CLEAR
:
743 if (m68hc11cpu_clear_oscillator (sd
, arg
) != 0)
744 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
747 case OPTION_OSC_INFO
:
748 for (i
= 0; i
< controller
->last_oscillator
; i
++)
751 struct input_osc
*osc
;
753 osc
= &controller
->oscillators
[i
];
761 if (title_printed
== 0)
764 sim_io_printf (sd
, " PORT Frequency Current"
765 " Next Transition time\n");
768 f
= (double) (osc
->on_time
+ osc
->off_time
);
769 f
= (double) (cpu
->cpu_frequency
/ 4) / f
;
770 t
= hw_event_remain_time (cpu
->hw_cpu
, osc
->event
);
773 sprintf (freq
, "%6.2f", f
/ 1000.0);
775 sprintf (freq
, "%6.2f", f
);
776 cur_value
= osc
->value
? 1 : 0;
777 next_value
= osc
->value
? 0 : 1;
779 sim_io_printf (sd
, " %4.4s %8.8s khz"
782 cur_value
, next_value
,
783 cycle_to_string (cpu
, t
));
785 sim_io_printf (sd
, " %4.4s %8.8s hz "
788 cur_value
, next_value
,
789 cycle_to_string (cpu
, t
));
798 /* generic read/write */
801 m68hc11cpu_io_read_buffer (struct hw
*me
,
808 struct m68hc11cpu
*controller
= hw_data (me
);
813 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
816 cpu
= STATE_CPU (sd
, 0);
818 /* Handle reads for the sub-devices. */
819 base
-= controller
->attach_address
;
820 result
= sim_core_read_buffer (sd
, cpu
,
821 io_map
, dest
, base
, nr_bytes
);
827 if (base
>= controller
->attach_size
)
830 memcpy (dest
, &cpu
->ios
[base
], 1);
840 m68hc11cpu_set_port (struct hw
*me
, sim_cpu
*cpu
,
841 unsigned addr
, uint8 val
)
845 int check_interrupts
= 0;
851 if (cpu
->ios
[M6811_PACTL
] & M6811_DDRA7
)
857 val
|= cpu
->ios
[M6811_PORTA
] & ~mask
;
858 delta
= val
^ cpu
->ios
[M6811_PORTA
];
859 cpu
->ios
[M6811_PORTA
] = val
;
862 /* Pulse accumulator is enabled. */
863 if ((cpu
->ios
[M6811_PACTL
] & M6811_PAEN
)
864 && !(cpu
->ios
[M6811_PACTL
] & M6811_PAMOD
))
868 /* Increment event counter according to rising/falling edge. */
869 if (cpu
->ios
[M6811_PACTL
] & M6811_PEDGE
)
870 inc
= (val
& 0x80) ? 1 : 0;
872 inc
= (val
& 0x80) ? 0 : 1;
874 cpu
->ios
[M6811_PACNT
] += inc
;
876 /* Event counter overflowed. */
877 if (inc
&& cpu
->ios
[M6811_PACNT
] == 0)
879 cpu
->ios
[M6811_TFLG2
] |= M6811_PAOVI
;
880 check_interrupts
= 1;
885 /* Scan IC3, IC2 and IC1. Bit number is 3 - i. */
886 for (i
= 0; i
< 3; i
++)
888 uint8 mask
= (1 << i
);
895 edge
= cpu
->ios
[M6811_TCTL2
];
896 edge
= (edge
>> (2 * i
)) & 0x3;
903 captured
= (val
& mask
) != 0;
906 captured
= (val
& mask
) == 0;
914 cpu
->ios
[M6811_TFLG1
] |= (1 << i
);
915 hw_port_event (me
, CAPTURE
, M6811_TIC1
+ 3 - i
);
916 check_interrupts
= 1;
923 mask
= cpu
->ios
[M6811_DDRC
];
925 val
|= cpu
->ios
[M6811_PORTC
] & ~mask
;
926 cpu
->ios
[M6811_PORTC
] = val
;
930 mask
= cpu
->ios
[M6811_DDRD
];
932 val
|= cpu
->ios
[M6811_PORTD
] & ~mask
;
933 cpu
->ios
[M6811_PORTD
] = val
;
940 if (check_interrupts
)
941 interrupts_update_pending (&cpu
->cpu_interrupts
);
945 m68hc11cpu_io_write (struct hw
*me
, sim_cpu
*cpu
,
946 unsigned_word addr
, uint8 val
)
951 hw_port_event (me
, PORT_A
, val
);
958 hw_port_event (me
, PORT_C
, val
);
962 hw_port_event (me
, PORT_B
, val
);
972 hw_port_event (me
, PORT_D
, val
);
982 /* Change the RAM and I/O mapping. */
985 uint8 old_bank
= cpu
->ios
[M6811_INIT
];
987 cpu
->ios
[M6811_INIT
] = val
;
989 /* Update IO mapping. Detach from the old address
990 and attach to the new one. */
991 if ((old_bank
& 0xF0) != (val
& 0xF0))
993 struct m68hc11cpu
*controller
= hw_data (me
);
995 hw_detach_address (hw_parent (me
), M6811_IO_LEVEL
,
996 controller
->attach_space
,
997 controller
->attach_address
,
998 controller
->attach_size
,
1000 controller
->attach_address
= (val
& 0x0F0) << 12;
1001 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
1002 controller
->attach_space
,
1003 controller
->attach_address
,
1004 controller
->attach_size
,
1007 if ((old_bank
& 0x0F) != (val
& 0x0F))
1014 /* Writing the config is similar to programing the eeprom.
1015 The config register value is the last byte of the EEPROM.
1016 This last byte is not mapped in memory (that's why we have
1017 to add '1' to 'end_addr'). */
1026 if (val
== 0xAA && cpu
->ios
[addr
] == 0x55)
1029 /* COP reset here. */
1037 cpu
->ios
[addr
] = val
;
1041 m68hc11cpu_io_write_buffer (struct hw
*me
,
1048 struct m68hc11cpu
*controller
= hw_data (me
);
1053 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
1055 sd
= hw_system (me
);
1056 cpu
= STATE_CPU (sd
, 0);
1057 base
-= controller
->attach_address
;
1058 result
= sim_core_write_buffer (sd
, cpu
,
1059 io_map
, source
, base
, nr_bytes
);
1067 if (base
>= controller
->attach_size
)
1070 val
= *((uint8
*) source
);
1071 m68hc11cpu_io_write (me
, cpu
, base
, val
);
1080 const struct hw_descriptor dv_m68hc11_descriptor
[] = {
1081 { "m68hc11", m68hc11cpu_finish
},
1082 { "m68hc12", m68hc11cpu_finish
},