Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au> | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | */ | |
20 | ||
21 | ||
22 | #ifndef _HW_CPU_C_ | |
23 | #define _HW_CPU_C_ | |
24 | ||
25 | #ifndef STATIC_INLINE_HW_CPU | |
26 | #define STATIC_INLINE_HW_CPU STATIC_INLINE | |
27 | #endif | |
28 | ||
29 | #include "device_table.h" | |
30 | #include "hw_cpu.h" | |
31 | ||
32 | #include "interrupts.h" | |
33 | #include "cpu.h" | |
34 | ||
35 | ||
36 | /* DEVICE | |
37 | ||
38 | ||
39 | cpu - Interface to a Processor | |
40 | ||
41 | ||
42 | DESCRIPTION | |
43 | ||
44 | ||
45 | The CPU device provides the connection between the interrupt net | |
46 | (linking the devices and the interrupt controller) and the | |
47 | simulated model of each processor. This device contains interrupt | |
48 | ports that correspond directly to the external interrupt stimulus | |
49 | that can be sent to a given processor. Sending an interrupt to one | |
50 | of the ports results in an interrupt being delivered to the | |
51 | corresponding processor. | |
52 | ||
53 | Typically, an interrupt controller would have its inputs connected | |
54 | to device interrupt sources and its outputs (sreset, int, et.al.) | |
55 | connected to this device. | |
56 | ||
57 | ||
58 | PROPERTIES | |
59 | ||
60 | ||
61 | cpu-nr = <integer> (required) | |
62 | ||
63 | ||
64 | Specify the processor (1..N) that this cpu device node should | |
65 | control. | |
66 | ||
67 | ||
68 | EXAMPLES | |
69 | ||
70 | ||
71 | Connect an OpenPIC interrupt controller interrupt ports to | |
72 | processor zero. | |
73 | ||
74 | | -o '/phb/opic@0 > irq0 int /cpus/cpu@0' \ | |
75 | | -o '/phb/opic@0 > init hreset /cpus/cpu@0' \ | |
76 | ||
77 | ||
78 | */ | |
79 | ||
80 | typedef struct _hw_cpu_device { | |
81 | int cpu_nr; | |
82 | cpu *processor; | |
83 | } hw_cpu_device; | |
84 | ||
85 | static const device_interrupt_port_descriptor hw_cpu_interrupt_ports[] = { | |
86 | { "hreset", hw_cpu_hard_reset }, | |
87 | { "sreset", hw_cpu_soft_reset }, | |
88 | { "int", hw_cpu_external_interrupt }, | |
89 | { "mci", hw_cpu_machine_check_interrupt }, | |
90 | { "smi", hw_cpu_system_management_interrupt }, | |
91 | { NULL } | |
92 | }; | |
93 | ||
94 | ||
95 | static void * | |
96 | hw_cpu_create(const char *name, | |
97 | const device_unit *unit_address, | |
98 | const char *args) | |
99 | { | |
100 | hw_cpu_device *hw_cpu = ZALLOC(hw_cpu_device); | |
101 | return hw_cpu; | |
102 | } | |
103 | ||
104 | ||
105 | /* during address initialization ensure that any missing cpu | |
106 | properties are added to this devices node */ | |
107 | ||
108 | static void | |
109 | hw_cpu_init_address(device *me) | |
110 | { | |
111 | hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me); | |
112 | /* populate the node with properties */ | |
113 | /* clear our data */ | |
114 | memset(hw_cpu, 0x0, sizeof(hw_cpu_device)); | |
115 | hw_cpu->cpu_nr = device_find_integer_property(me, "cpu-nr"); | |
116 | hw_cpu->processor = psim_cpu(device_system(me), hw_cpu->cpu_nr); | |
117 | } | |
118 | ||
119 | ||
120 | /* Take the interrupt and synchronize its delivery with the clock. If | |
121 | we've not yet scheduled an interrupt for the next clock tick, take | |
122 | the oportunity to do it now */ | |
123 | ||
124 | static void | |
125 | hw_cpu_interrupt_event(device *me, | |
126 | int my_port, | |
127 | device *source, | |
128 | int source_port, | |
129 | int level, | |
130 | cpu *processor, | |
131 | unsigned_word cia) | |
132 | { | |
133 | hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me); | |
134 | if (my_port < 0 || my_port >= hw_cpu_nr_interrupt_ports) | |
135 | error("hw_cpu_interrupt_event_callback: interrupt port out of range %d\n", | |
136 | my_port); | |
137 | switch (my_port) { | |
138 | /*case hw_cpu_hard_reset:*/ | |
139 | /*case hw_cpu_soft_reset:*/ | |
140 | case hw_cpu_external_interrupt: | |
141 | external_interrupt(hw_cpu->processor, level); | |
142 | break; | |
143 | /*case hw_cpu_machine_check_interrupt:*/ | |
144 | default: | |
145 | error("hw_cpu_deliver_interrupt: unimplemented interrupt port %d\n", | |
146 | my_port); | |
147 | break; | |
148 | } | |
149 | } | |
150 | ||
151 | ||
152 | static device_callbacks const hw_cpu_callbacks = { | |
153 | { hw_cpu_init_address, }, /* init */ | |
154 | { NULL, }, /* address */ | |
155 | { NULL, }, /* io */ | |
156 | { NULL, }, /* DMA */ | |
157 | { hw_cpu_interrupt_event, NULL, hw_cpu_interrupt_ports }, /* interrupts */ | |
158 | { NULL, NULL, }, | |
159 | }; | |
160 | ||
161 | const device_descriptor hw_cpu_device_descriptor[] = { | |
162 | { "hw-cpu", hw_cpu_create, &hw_cpu_callbacks }, | |
163 | { "cpu", hw_cpu_create, &hw_cpu_callbacks }, | |
164 | { NULL, }, | |
165 | }; | |
166 | ||
167 | #endif /* _HW_CPU_C_ */ |