Commit | Line | Data |
---|---|---|
b85e4829 AC |
1 | /* The common simulator framework for GDB, the GNU Debugger. |
2 | ||
e2882c85 | 3 | Copyright 2002-2018 Free Software Foundation, Inc. |
b85e4829 AC |
4 | |
5 | Contributed by Andrew Cagney and Red Hat. | |
6 | ||
7 | This file is part of GDB. | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
4744ac1b | 11 | the Free Software Foundation; either version 3 of the License, or |
b85e4829 AC |
12 | (at your option) any later version. |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
4744ac1b | 20 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
c906108c SS |
21 | |
22 | ||
23 | #ifndef HW_DEVICE_H | |
24 | #define HW_DEVICE_H | |
25 | ||
c906108c SS |
26 | |
27 | /* Introduction: | |
28 | ||
29 | As explained in earlier sections, the device, device instance, | |
30 | property and ports lie at the heart of PSIM's device model. | |
31 | ||
32 | In the below a synopsis of the device object and the operations it | |
33 | supports are given. | |
34 | */ | |
35 | ||
36 | ||
37 | /* Creation: | |
38 | ||
39 | The devices are created using a sequence of steps. In particular: | |
40 | ||
41 | o A tree framework is created. | |
42 | ||
43 | At this point, properties can be modified and extra | |
44 | devices inserted (or removed?). | |
45 | ||
46 | #if LATER | |
47 | ||
48 | Any properties that have a run-time value (eg ihandle | |
49 | or device instance pointer properties) are entered | |
50 | into the device tree using a named reference to the | |
51 | corresponding runtime object that is to be created. | |
52 | ||
53 | #endif | |
54 | ||
55 | o Real devices are created for all the dummy devices. | |
56 | ||
57 | A device can assume that all of its parents have been | |
58 | initialized. | |
59 | ||
60 | A device can assume that all non run-time properties | |
61 | have been initialized. | |
62 | ||
63 | As part of being created, the device normally attaches | |
64 | itself to its parent bus. | |
65 | ||
66 | #if LATER | |
67 | ||
68 | Device instance data is initialized. | |
69 | ||
70 | #endif | |
71 | ||
72 | #if LATER | |
73 | ||
74 | o Any run-time properties are created. | |
75 | ||
76 | #endif | |
77 | ||
78 | #if MUCH_MUCH_LATER | |
79 | ||
80 | o Some devices, as part of their initialization | |
81 | might want to refer to ihandle properties | |
82 | in the device tree. | |
83 | ||
84 | #endif | |
85 | ||
86 | NOTES: | |
87 | ||
88 | o It is important to separate the creation | |
89 | of an actual device from the creation | |
90 | of the tree. The alternative creating | |
91 | the device in two stages: As a separate | |
92 | entity and then as a part of the tree. | |
93 | ||
94 | #if LATER | |
95 | o Run-time properties can not be created | |
96 | until after the devices in the tree | |
97 | have been created. Hence an extra pass | |
98 | for handling them. | |
99 | #endif | |
100 | ||
101 | */ | |
102 | ||
103 | /* Relationships: | |
104 | ||
105 | A device is able to determine its relationship to other devices | |
106 | within the tree. Operations include querying for a devices parent, | |
107 | sibling, child, name, and path (from the root). | |
108 | ||
109 | */ | |
110 | ||
111 | ||
112 | #define hw_parent(hw) ((hw)->parent_of_hw + 0) | |
113 | ||
114 | #define hw_sibling(hw) ((hw)->sibling_of_hw + 0) | |
115 | ||
116 | #define hw_child(hw) ((hw)->child_of_hw + 0) | |
117 | ||
118 | ||
119 | ||
120 | /* Herritage: | |
121 | ||
122 | */ | |
123 | ||
124 | #define hw_family(hw) ((hw)->family_of_hw + 0) | |
125 | ||
126 | #define hw_name(hw) ((hw)->name_of_hw + 0) | |
127 | ||
128 | #define hw_args(hw) ((hw)->args_of_hw + 0) | |
129 | ||
130 | #define hw_path(hw) ((hw)->path_of_hw + 0) | |
131 | ||
132 | ||
133 | ||
134 | /* Short cut to the root node of the tree */ | |
135 | ||
136 | #define hw_root(hw) ((hw)->root_of_hw + 0) | |
137 | ||
138 | /* Short cut back to the simulator object */ | |
139 | ||
140 | #define hw_system(hw) ((hw)->system_of_hw) | |
141 | ||
142 | /* For requests initiated by a CPU the cpu that initiated the request */ | |
143 | ||
144 | struct _sim_cpu *hw_system_cpu (struct hw *hw); | |
145 | ||
146 | ||
147 | /* Device private data */ | |
148 | ||
149 | #define hw_data(hw) ((hw)->data_of_hw) | |
150 | ||
151 | #define set_hw_data(hw, value) \ | |
152 | ((hw)->data_of_hw = (value)) | |
153 | ||
154 | ||
155 | \f | |
156 | /* Perform a soft reset of the device */ | |
157 | ||
158 | typedef unsigned (hw_reset_method) | |
159 | (struct hw *me); | |
160 | ||
161 | #define hw_reset(hw) ((hw)->to_reset (hw)) | |
162 | ||
163 | #define set_hw_reset(hw, method) \ | |
164 | ((hw)->to_reset = method) | |
165 | ||
166 | \f | |
167 | /* Hardware operations: | |
168 | ||
169 | Connecting a parent to its children is a common bus. The parent | |
170 | node is described as the bus owner and is responisble for | |
171 | co-ordinating bus operations. On the bus, a SPACE:ADDR pair is used | |
172 | to specify an address. A device that is both a bus owner (parent) | |
6439295f | 173 | and bus client (child) are referred to as a bridging device. |
c906108c SS |
174 | |
175 | A child performing a data (DMA) transfer will pass its request to | |
176 | the bus owner (the devices parent). The bus owner will then either | |
177 | reflect the request to one of the other devices attached to the bus | |
178 | (a child of the bus owner) or bridge the request up the tree to the | |
179 | next bus. */ | |
180 | ||
181 | ||
182 | /* Children attached to a bus can register (attach) themselves to | |
183 | specific addresses on their attached bus. | |
184 | ||
185 | (A device may also be implicitly attached to certain bus | |
186 | addresses). | |
187 | ||
188 | The SPACE:ADDR pair specify an address on the common bus that | |
189 | connects the parent and child devices. */ | |
190 | ||
191 | typedef void (hw_attach_address_method) | |
192 | (struct hw *me, | |
193 | int level, | |
194 | int space, | |
195 | address_word addr, | |
196 | address_word nr_bytes, | |
197 | struct hw *client); /*callback/default*/ | |
198 | ||
199 | #define hw_attach_address(me, level, space, addr, nr_bytes, client) \ | |
200 | ((me)->to_attach_address (me, level, space, addr, nr_bytes, client)) | |
201 | ||
202 | #define set_hw_attach_address(hw, method) \ | |
203 | ((hw)->to_attach_address = (method)) | |
204 | ||
205 | typedef void (hw_detach_address_method) | |
206 | (struct hw *me, | |
207 | int level, | |
208 | int space, | |
209 | address_word addr, | |
210 | address_word nr_bytes, | |
211 | struct hw *client); /*callback/default*/ | |
212 | ||
213 | #define hw_detach_address(me, level, space, addr, nr_bytes, client) \ | |
214 | ((me)->to_detach_address (me, level, space, addr, nr_bytes, client)) | |
215 | ||
216 | #define set_hw_detach_address(hw, method) \ | |
217 | ((hw)->to_detach_address = (method)) | |
218 | ||
219 | ||
220 | /* An IO operation from a parent to a child via the conecting bus. | |
221 | ||
222 | The SPACE:ADDR pair specify an address on the bus shared between | |
223 | the parent and child devices. */ | |
224 | ||
225 | typedef unsigned (hw_io_read_buffer_method) | |
226 | (struct hw *me, | |
227 | void *dest, | |
228 | int space, | |
229 | unsigned_word addr, | |
230 | unsigned nr_bytes); | |
231 | ||
232 | #define hw_io_read_buffer(hw, dest, space, addr, nr_bytes) \ | |
233 | ((hw)->to_io_read_buffer (hw, dest, space, addr, nr_bytes)) | |
234 | ||
235 | #define set_hw_io_read_buffer(hw, method) \ | |
236 | ((hw)->to_io_read_buffer = (method)) | |
237 | ||
238 | typedef unsigned (hw_io_write_buffer_method) | |
239 | (struct hw *me, | |
240 | const void *source, | |
241 | int space, | |
242 | unsigned_word addr, | |
243 | unsigned nr_bytes); | |
244 | ||
245 | #define hw_io_write_buffer(hw, src, space, addr, nr_bytes) \ | |
246 | ((hw)->to_io_write_buffer (hw, src, space, addr, nr_bytes)) | |
247 | ||
248 | #define set_hw_io_write_buffer(hw, method) \ | |
249 | ((hw)->to_io_write_buffer = (method)) | |
250 | ||
251 | ||
252 | /* Conversly, the device pci1000,1@1 may need to perform a dma transfer | |
253 | into the cpu/memory core. Just as I/O moves towards the leaves, | |
254 | dma transfers move towards the core via the initiating devices | |
255 | parent nodes. The root device (special) converts the DMA transfer | |
256 | into reads/writes to memory. | |
257 | ||
258 | The SPACE:ADDR pair specify an address on the common bus connecting | |
259 | the parent and child devices. */ | |
260 | ||
261 | typedef unsigned (hw_dma_read_buffer_method) | |
262 | (struct hw *bus, | |
263 | void *dest, | |
264 | int space, | |
265 | unsigned_word addr, | |
266 | unsigned nr_bytes); | |
267 | ||
268 | #define hw_dma_read_buffer(bus, dest, space, addr, nr_bytes) \ | |
269 | ((bus)->to_dma_read_buffer (bus, dest, space, addr, nr_bytes)) | |
270 | ||
271 | #define set_hw_dma_read_buffer(me, method) \ | |
272 | ((me)->to_dma_read_buffer = (method)) | |
273 | ||
274 | typedef unsigned (hw_dma_write_buffer_method) | |
275 | (struct hw *bus, | |
276 | const void *source, | |
277 | int space, | |
278 | unsigned_word addr, | |
279 | unsigned nr_bytes, | |
280 | int violate_read_only_section); | |
281 | ||
282 | #define hw_dma_write_buffer(bus, src, space, addr, nr_bytes, violate_ro) \ | |
283 | ((bus)->to_dma_write_buffer (bus, src, space, addr, nr_bytes, violate_ro)) | |
284 | ||
285 | #define set_hw_dma_write_buffer(me, method) \ | |
286 | ((me)->to_dma_write_buffer = (method)) | |
287 | \f | |
288 | /* Address/size specs for devices are encoded following a convention | |
289 | similar to that used by OpenFirmware. In particular, an | |
290 | address/size is packed into a sequence of up to four cell words. | |
291 | The number of words determined by the number of {address,size} | |
292 | cells attributes of the device. */ | |
293 | ||
12c4cbd5 MF |
294 | typedef struct _hw_unit |
295 | { | |
c906108c SS |
296 | int nr_cells; |
297 | unsigned_cell cells[4]; /* unused cells are zero */ | |
298 | } hw_unit; | |
299 | ||
300 | ||
301 | /* For the given bus, the number of address and size cells used in a | |
302 | hw_unit. */ | |
303 | ||
304 | #define hw_unit_nr_address_cells(bus) ((bus)->nr_address_cells_of_hw_unit + 0) | |
305 | ||
306 | #define hw_unit_nr_size_cells(bus) ((bus)->nr_size_cells_of_hw_unit + 0) | |
307 | ||
308 | ||
309 | /* For the given device, its identifying hw_unit address. | |
310 | ||
311 | Each device has an identifying hw_unit address. That address is | |
312 | used when identifying one of a number of identical devices on a | |
313 | common controller bus. ex fd0&fd1. */ | |
314 | ||
315 | const hw_unit *hw_unit_address | |
316 | (struct hw *me); | |
317 | ||
318 | ||
319 | /* Convert between a textual and the internal representation of a | |
320 | hw_unit address/size. | |
321 | ||
322 | NOTE: A device asks its parent to translate between a hw_unit and | |
323 | textual representation. This is because the textual address of a | |
324 | device is specified using the parent busses notation. */ | |
325 | ||
326 | typedef int (hw_unit_decode_method) | |
327 | (struct hw *bus, | |
328 | const char *encoded, | |
329 | hw_unit *unit); | |
330 | ||
331 | #define hw_unit_decode(bus, encoded, unit) \ | |
332 | ((bus)->to_unit_decode (bus, encoded, unit)) | |
333 | ||
334 | #define set_hw_unit_decode(hw, method) \ | |
335 | ((hw)->to_unit_decode = (method)) | |
336 | ||
337 | typedef int (hw_unit_encode_method) | |
338 | (struct hw *bus, | |
339 | const hw_unit *unit, | |
340 | char *encoded, | |
341 | int sizeof_buf); | |
028f6515 | 342 | |
c906108c SS |
343 | #define hw_unit_encode(bus, unit, encoded, sizeof_encoded) \ |
344 | ((bus)->to_unit_encode (bus, unit, encoded, sizeof_encoded)) | |
345 | ||
346 | #define set_hw_unit_encode(hw, method) \ | |
347 | ((hw)->to_unit_encode = (method)) | |
348 | ||
349 | ||
350 | /* As the bus that the device is attached too, to translate a devices | |
351 | hw_unit address/size into a form suitable for an attach address | |
352 | call. | |
353 | ||
354 | Return a zero result if the address should be ignored when looking | |
355 | for attach addresses. */ | |
356 | ||
357 | typedef int (hw_unit_address_to_attach_address_method) | |
358 | (struct hw *bus, | |
359 | const hw_unit *unit_addr, | |
360 | int *attach_space, | |
361 | unsigned_word *attach_addr, | |
362 | struct hw *client); | |
363 | ||
364 | #define hw_unit_address_to_attach_address(bus, unit_addr, attach_space, attach_addr, client) \ | |
365 | ((bus)->to_unit_address_to_attach_address (bus, unit_addr, attach_space, attach_addr, client)) | |
366 | ||
367 | #define set_hw_unit_address_to_attach_address(hw, method) \ | |
368 | ((hw)->to_unit_address_to_attach_address = (method)) | |
369 | ||
370 | typedef int (hw_unit_size_to_attach_size_method) | |
371 | (struct hw *bus, | |
372 | const hw_unit *unit_size, | |
373 | unsigned *attach_size, | |
374 | struct hw *client); | |
375 | ||
376 | #define hw_unit_size_to_attach_size(bus, unit_size, attach_size, client) \ | |
377 | ((bus)->to_unit_size_to_attach_size (bus, unit_size, attach_size, client)) | |
378 | ||
379 | #define set_hw_unit_size_to_attach_size(hw, method) \ | |
380 | ((hw)->to_unit_size_to_attach_size = (method)) | |
381 | ||
382 | \f | |
383 | extern char *hw_strdup (struct hw *me, const char *str); | |
384 | ||
385 | \f | |
386 | /* Utilities: | |
387 | ||
388 | */ | |
389 | ||
390 | /* IOCTL:: | |
391 | ||
392 | Often devices require `out of band' operations to be performed. | |
393 | For instance a pal device may need to notify a PCI bridge device | |
394 | that an interrupt ack cycle needs to be performed on the PCI bus. | |
395 | Within PSIM such operations are performed by using the generic | |
396 | ioctl call <<hw_ioctl()>>. | |
397 | ||
398 | */ | |
399 | ||
12c4cbd5 MF |
400 | typedef enum |
401 | { | |
c906108c SS |
402 | hw_ioctl_break, /* unsigned_word requested_break */ |
403 | hw_ioctl_set_trace, /* void */ | |
404 | hw_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */ | |
405 | hw_ioctl_change_media, /* const char *new_image (possibly NULL) */ | |
406 | nr_hw_ioctl_requests, | |
407 | } hw_ioctl_request; | |
408 | ||
409 | typedef int (hw_ioctl_method) | |
410 | (struct hw *me, | |
411 | hw_ioctl_request request, | |
412 | va_list ap); | |
413 | ||
414 | int hw_ioctl | |
415 | (struct hw *me, | |
416 | hw_ioctl_request request, | |
417 | ...); | |
418 | ||
419 | ||
420 | /* Error reporting:: | |
421 | ||
422 | So that errors originating from devices appear in a consistent | |
423 | format, the <<hw_abort()>> function can be used. Formats and | |
424 | outputs the error message before aborting the simulation | |
425 | ||
426 | Devices should use this function to abort the simulation except | |
427 | when the abort reason leaves the simulation in a hazardous | |
428 | condition (for instance a failed malloc). | |
429 | ||
430 | */ | |
431 | ||
432 | void hw_abort | |
433 | (struct hw *me, | |
434 | const char *fmt, | |
5f78776a | 435 | ...) __attribute__ ((format (printf, 2, 3), noreturn)); |
c906108c SS |
436 | |
437 | void hw_vabort | |
438 | (struct hw *me, | |
439 | const char *fmt, | |
5f78776a | 440 | va_list ap) __attribute__ ((noreturn)); |
c906108c SS |
441 | |
442 | void hw_halt | |
443 | (struct hw *me, | |
444 | int reason, | |
5f78776a | 445 | int status) __attribute__ ((noreturn)); |
c906108c SS |
446 | |
447 | ||
448 | #define hw_trace_p(hw) ((hw)->trace_of_hw_p + 0) | |
449 | ||
450 | void hw_trace | |
451 | (struct hw *me, | |
452 | const char *fmt, | |
453 | ...) __attribute__ ((format (printf, 2, 3))); | |
454 | ||
455 | #define HW_TRACE(ARGS) \ | |
456 | do { \ | |
457 | if (hw_trace_p (me)) \ | |
458 | { \ | |
459 | hw_trace ARGS; \ | |
460 | } \ | |
461 | } while (0) | |
462 | ||
463 | ||
464 | /* Some of the related functions require specific types */ | |
465 | ||
466 | struct hw_property_data; | |
467 | struct hw_port_data; | |
468 | struct hw_base_data; | |
469 | struct hw_alloc_data; | |
470 | struct hw_event_data; | |
471 | struct hw_handle_data; | |
472 | struct hw_instance_data; | |
473 | ||
474 | /* Finally the hardware device - keep your grubby little mits off of | |
475 | these internals! :-) */ | |
476 | ||
12c4cbd5 MF |
477 | struct hw |
478 | { | |
c906108c SS |
479 | |
480 | /* our relatives */ | |
481 | struct hw *parent_of_hw; | |
482 | struct hw *sibling_of_hw; | |
483 | struct hw *child_of_hw; | |
484 | ||
485 | /* our identity */ | |
486 | const char *name_of_hw; | |
487 | const char *family_of_hw; | |
488 | const char *args_of_hw; | |
489 | const char *path_of_hw; | |
490 | ||
491 | /* our data */ | |
492 | void *data_of_hw; | |
493 | ||
494 | /* hot links */ | |
495 | struct hw *root_of_hw; | |
496 | struct sim_state *system_of_hw; | |
497 | ||
498 | /* identifying data */ | |
499 | hw_unit unit_address_of_hw; | |
500 | int nr_address_cells_of_hw_unit; | |
501 | int nr_size_cells_of_hw_unit; | |
502 | ||
503 | /* Soft reset */ | |
504 | hw_reset_method *to_reset; | |
505 | ||
506 | /* Basic callbacks */ | |
507 | hw_io_read_buffer_method *to_io_read_buffer; | |
508 | hw_io_write_buffer_method *to_io_write_buffer; | |
509 | hw_dma_read_buffer_method *to_dma_read_buffer; | |
510 | hw_dma_write_buffer_method *to_dma_write_buffer; | |
511 | hw_attach_address_method *to_attach_address; | |
512 | hw_detach_address_method *to_detach_address; | |
513 | ||
514 | /* More complicated callbacks */ | |
515 | hw_ioctl_method *to_ioctl; | |
516 | int trace_of_hw_p; | |
517 | ||
518 | /* address callbacks */ | |
519 | hw_unit_decode_method *to_unit_decode; | |
520 | hw_unit_encode_method *to_unit_encode; | |
521 | hw_unit_address_to_attach_address_method *to_unit_address_to_attach_address; | |
522 | hw_unit_size_to_attach_size_method *to_unit_size_to_attach_size; | |
523 | ||
524 | /* related data */ | |
525 | struct hw_property_data *properties_of_hw; | |
526 | struct hw_port_data *ports_of_hw; | |
527 | struct hw_base_data *base_of_hw; | |
528 | struct hw_alloc_data *alloc_of_hw; | |
529 | struct hw_event_data *events_of_hw; | |
530 | struct hw_handle_data *handles_of_hw; | |
531 | struct hw_instance_data *instances_of_hw; | |
532 | ||
533 | }; | |
534 | ||
535 | ||
536 | #endif |