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