New changes from Andrew
[deliverable/binutils-gdb.git] / sim / ppc / devices.h
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, 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 _DEVICES_H_
23 #define _DEVICES_H_
24
25 #ifndef INLINE_DEVICES
26 #define INLINE_DEVICES
27 #endif
28
29 #ifndef STATIC_DEVICES
30 #define STATIC_DEVICES
31 #endif
32
33
34 /* forward declaration of types */
35 /* typedef struct _device device; -- in devices.h */
36
37
38 /* Address access attributes that can be attached to a devices address
39 range */
40 typedef enum _access_type {
41 access_invalid = 0,
42 access_read = 1,
43 access_write = 2,
44 access_read_write = 3,
45 access_exec = 4,
46 access_read_exec = 5,
47 access_write_exec = 6,
48 access_read_write_exec = 7,
49 } access_type;
50
51 /* Address attachement types */
52 typedef enum _attach_type {
53 attach_invalid,
54 attach_callback,
55 attach_default,
56 attach_raw_memory,
57 } attach_type;
58
59
60 /* Operators on devices: */
61
62
63 /* Initialization:
64
65 A device is made fully functional in two stages.
66
67 1. It is created. A device is created _before_ it is entered into
68 the device tree. During creation any permenant structures needed
69 by the device should be created/initialized.
70
71 2. It is initialized. Before a simulation run, each device in the
72 device tree is initialized in prefix order. As part of this
73 initialization, a device should (re)attach its self to its parent
74 as needed.
75
76 */
77
78 typedef void (device_init_callback)
79 (const device *me,
80 psim *system);
81
82 #define DTRACE_INIT(OBJECT) \
83 DTRACE(OBJECT, \
84 (#OBJECT "_init(me=0x%x:%s system=0x%x)\n", \
85 me, me->full_name, system))
86
87 /* Data transfers:
88
89 A device may permit the reading/writing (IO) of its registers in
90 one or more address spaces. For instance, a PCI device may have
91 config registers in its config space and control registers in both
92 the io and memory spaces of a PCI bus.
93
94 Similarly, a device may initiate a data transfer (DMA) by passing
95 such a request up to its parent.
96
97 Init:
98
99 As part of its initialization (not creation) and possibly also as a
100 consequence of IO a device may attach its self to one or more of
101 the address spaces of its parent device.
102
103 For instance, a PCI device, during initialization would attach its
104 config registers (space=0?, base=0, nr_bytes=64) to its parent PCI
105 bridge. Later, due to a write to this config space, the same
106 device may in turn find it necessary to also attach its self to
107 it's parent's `memory' or `io' space.
108
109 To perform these operations, a device will call upon its parent
110 using either device_attach_address or device_detach_address.
111
112 * Any address specified is according to what the device expects to
113 see.
114
115 * Any detach operation must exactly match a previous attach.
116
117 * included with the attach or detach is the devices name, the
118 parent may use this as part of determining how to map map between a
119 child's address + space and its own.
120
121 * at any time, at most one device can have a default mapping
122 registered.
123
124
125 IO:
126
127 A device receives requests to perform reads/writes to its registers
128 or memory either A. from a processor or B. from a parent device.
129
130 The device may then in turn either A. resolve the IO request
131 locally by processing the data or trigering an exception or
132 B. re-mapping the access onto one of its local address spaces and
133 then in turn passing that on to one of its children.
134
135 * Any address passed is relative to the local device. Eg for PCI
136 config registers, the address would (normally) be in the range of 0
137 to 63.
138
139 * Any exception situtation triggered by an IO operation (processor
140 != NULL) is handled in one of the following ways: 1. Machine check
141 (and similar): issued immediatly by restarting the cpu; 2. External
142 exception: issue delayed (using events.h) until the current
143 instruction execution cycle is completed; 3. Slave device (and
144 similar): the need for the interrupt is passed on to the devices
145 parent (which being an interrupt control unit will in turn take one
146 of the actions described here); 4. Forget it.
147
148 * Any exception situtation trigered by a non IO operation
149 (processor == NULL) is handled buy returning 0.
150
151 * Transfers of size <= 8 and of a power of 2 *must* be correctly
152 aligned and should be treated as a `single cycle' transfer.
153
154 DMA:
155
156 A device initiates a DMA transfer by calling its parent with the
157 request. At the top level (if not done earlier) this is reflected
158 back down the tree as io read/writes to the target device.
159
160 This function is subject to change ...
161
162 */
163
164 typedef void (device_config_address_callback)
165 (const device *me,
166 const char *name,
167 attach_type attach,
168 int space,
169 unsigned_word addr,
170 unsigned nr_bytes,
171 access_type access,
172 const device *who); /*callback/default*/
173
174 #define DTRACE_ATTACH_ADDRESS(OBJECT) \
175 DTRACE(OBJECT, \
176 (#OBJECT "_attach_address(me=0x%x:%s, name=%s, attach=%d, space=%d, addr=0x%x, nr_bytes=%d, access=%d, who=0x%x)\n", \
177 me, me->full_name, name, attach, space, addr, nr_bytes, access, who))
178 #define DTRACE_DETACH_ADDRESS(OBJECT) \
179 DTRACE(OBJECT, \
180 (#OBJECT "_detach_address(me=0x%x:%s, name=%s, attach=%d, space=%d, addr=0x%x, nr_bytes=%d, access=%d, who=0x%x)\n", \
181 me, me->full_name, name, attach, space, addr, nr_bytes, access, who))
182
183
184 typedef unsigned (device_io_read_buffer_callback)
185 (const device *me,
186 void *dest,
187 int space,
188 unsigned_word addr,
189 unsigned nr_bytes,
190 cpu *processor,
191 unsigned_word cia);
192
193 typedef unsigned (device_io_write_buffer_callback)
194 (const device *me,
195 const void *source,
196 int space,
197 unsigned_word addr,
198 unsigned nr_bytes,
199 cpu *processor,
200 unsigned_word cia);
201
202 #define DTRACE_IO_READ_BUFFER(OBJECT) \
203 DTRACE(OBJECT, \
204 (#OBJECT "_io_read_buffer(me=0x%x:%s dest=0x%x space=%d addr=0x%x nr_bytes=%d processor=0x%x cia=0x%x)\n", \
205 me, me->full_name, dest, space, addr, nr_bytes, processor, cia))
206 #define DTRACE_IO_WRITE_BUFFER(OBJECT) \
207 DTRACE(OBJECT, \
208 (#OBJECT "_io_write_buffer(me=0x%x:%s source=0x%x space=%d addr=0x%x nr_bytes=%d processor=0x%x cia=0x%x)\n", \
209 me, me->full_name, source, space, addr, nr_bytes, processor, cia))
210
211
212 typedef unsigned (device_dma_read_buffer_callback)
213 (const device *me,
214 void *dest,
215 int space,
216 unsigned_word addr,
217 unsigned nr_bytes);
218
219 typedef unsigned (device_dma_write_buffer_callback)
220 (const device *me,
221 const void *source,
222 int space,
223 unsigned_word addr,
224 unsigned nr_bytes,
225 int violate_read_only_section);
226
227 #define DTRACE_DMA_READ_BUFFER(OBJECT) \
228 DTRACE(OBJECT, \
229 (#OBJECT "_dma_read_buffer(me=0x%x:%s dest=0x%x space=%d addr=0x%x nr_bytes=%d)\n", \
230 me, me->full_name, dest, space, addr, nr_bytes))
231 #define DTRACE_DMA_WRITE_BUFFER(OBJECT) \
232 DTRACE(OBJECT, \
233 (#OBJECT "_dma_write_buffer(me=0x%x:%s source=0x%x space=%d addr=0x%x nr_bytes=%d)\n", \
234 me, me->full_name, source, space, addr, nr_bytes))
235
236
237 /* Interrupts:
238
239 As mentioned above. Instead of handling an interrupt directly, a
240 device may instead pass the need to interrupt on to its parent.
241
242 Init:
243
244 Before passing interrupts up to is parent, a device must first
245 attach its interrupt lines to the parent device. To do this, the
246 device uses the parents attach/detach calls.
247
248 Interrupts:
249
250 A child notifies a parent of a change in an interrupt lines status
251 using the interrupt call. Similarly, a parent may notify a child
252 of any `interrupt ack' sequence using the interrupt_ack call.
253
254 */
255
256 typedef void (device_config_interrupt_callback)
257 (const device *me,
258 const device *who,
259 int interrupt_line,
260 const char *name);
261
262 typedef void (device_interrupt_ack_callback)
263 (const device *me,
264 int interrupt_line,
265 int interrupt_status);
266
267 typedef void (device_interrupt_callback)
268 (const device *me,
269 const device *who,
270 int interrupt_line,
271 int interrupt_status,
272 cpu *processor,
273 unsigned_word cia);
274
275
276 /* IOCTL:
277
278 Very simply, a catch all for any thing that turns up that until now
279 either hasn't been thought of or doesn't justify an extra function. */
280
281
282 typedef void (device_ioctl_callback)
283 (const device *me,
284 psim *system,
285 cpu *processor,
286 unsigned_word cia,
287 ...);
288
289
290
291 /* the callbacks */
292
293 typedef struct _device_callbacks {
294 /* initialization */
295 device_init_callback *init;
296 /* address/data config - from child */
297 device_config_address_callback *attach_address;
298 device_config_address_callback *detach_address;
299 /* address/data transfer - to child */
300 device_io_read_buffer_callback *io_read_buffer;
301 device_io_write_buffer_callback *io_write_buffer;
302 /* address/data transfer - from child */
303 device_dma_read_buffer_callback *dma_read_buffer;
304 device_dma_write_buffer_callback *dma_write_buffer;
305 /* interrupt config - from child */
306 device_config_interrupt_callback *attach_interrupt;
307 device_config_interrupt_callback *detach_interrupt;
308 /* interrupt transfer - from child */
309 device_interrupt_callback *interrupt;
310 /* interrupt transfer - to child */
311 device_interrupt_ack_callback *interrupt_ack;
312 /* back door to anything we've forgot */
313 device_ioctl_callback *ioctl;
314 } device_callbacks;
315
316 /* A device */
317 struct _device {
318 const char *name; /* eg rom@0x1234,0x400 */
319 const char *full_name; /* eg /isa/rom@0x1234,0x400 */
320 void *data; /* device specific data */
321 const device_callbacks *callback;
322 const device *parent;
323 };
324
325
326 /* Create a new device, finding it in the builtin device table */
327
328 INLINE_DEVICES const device *device_create
329 (const char *name,
330 const char *full_name,
331 const device *parent);
332
333 /* create a new device using the parameterized data */
334
335 INLINE_DEVICES const device *device_create_from
336 (const char *name,
337 const char *full_name,
338 void *data,
339 const device_callbacks *callback,
340 const device *parent);
341
342
343 /* Unimplemented call back functions. These abort the simulation */
344
345 INLINE_DEVICES device_init_callback unimp_device_init;
346 INLINE_DEVICES device_config_address_callback unimp_device_attach_address;
347 INLINE_DEVICES device_config_address_callback unimp_device_detach_address;
348 INLINE_DEVICES device_io_read_buffer_callback unimp_device_io_read_buffer;
349 INLINE_DEVICES device_io_write_buffer_callback unimp_device_io_write_buffer;
350 INLINE_DEVICES device_dma_read_buffer_callback unimp_device_dma_read_buffer;
351 INLINE_DEVICES device_dma_write_buffer_callback unimp_device_dma_write_buffer;
352 INLINE_DEVICES device_config_interrupt_callback unimp_device_attach_interrupt;
353 INLINE_DEVICES device_config_interrupt_callback unimp_device_detach_interrupt;
354 INLINE_DEVICES device_interrupt_callback unimp_device_interrupt;
355 INLINE_DEVICES device_interrupt_ack_callback unimp_device_interrupt_ack;
356 STATIC_DEVICES device_ioctl_callback unimp_device_ioctl;
357
358 /* Pass through and ignore callback functions. A call going towards
359 the root device are passed on up, local calls are ignored and call
360 downs abort */
361
362 INLINE_DEVICES device_init_callback ignore_device_init;
363 INLINE_DEVICES device_config_address_callback pass_device_attach_address;
364 INLINE_DEVICES device_config_address_callback pass_device_detach_address;
365 INLINE_DEVICES device_dma_read_buffer_callback pass_device_dma_read_buffer;
366 INLINE_DEVICES device_dma_write_buffer_callback pass_device_dma_write_buffer;
367 INLINE_DEVICES device_config_interrupt_callback pass_device_attach_interrupt;
368 INLINE_DEVICES device_config_interrupt_callback pass_device_detach_interrupt;
369 INLINE_DEVICES device_interrupt_callback pass_device_interrupt;
370
371 INLINE_DEVICES const device_callbacks *passthrough_device_callbacks
372 (void);
373
374
375
376 #endif /* _DEVICES_H_ */
This page took 0.038203 seconds and 4 git commands to generate.