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