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
80typedef struct _hw_cpu_device {
81  int cpu_nr;
82  cpu *processor;
83} hw_cpu_device;
84
85static 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
95static void *
96hw_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
108static void
109hw_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
124static void
125hw_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
152static 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
161const 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_ */
168