Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1997, 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 _DEVICE_H_ | |
23 | #define _DEVICE_H_ | |
24 | ||
25 | #ifndef INLINE_DEVICE | |
26 | #define INLINE_DEVICE | |
27 | #endif | |
28 | ||
29 | /* declared in basics.h, this object is used everywhere */ | |
30 | /* typedef struct _device device; */ | |
31 | ||
32 | ||
33 | /* Introduction: | |
34 | ||
35 | As explained in earlier sections, the device, device instance, | |
36 | property and interrupts lie at the heart of PSIM's device model. | |
37 | ||
38 | In the below a synopsis of the device object and the operations it | |
39 | supports are given. Details of this object can be found in the | |
40 | files <<device.h>> and <<device.c>>. | |
41 | ||
42 | */ | |
43 | ||
44 | ||
45 | /* Device creation: */ | |
46 | ||
47 | INLINE_DEVICE\ | |
48 | (device *) device_create | |
49 | (device *parent, | |
50 | const char *base, | |
51 | const char *name, | |
52 | const char *unit_address, | |
53 | const char *args); | |
54 | ||
55 | INLINE_DEVICE\ | |
56 | (void) device_usage | |
57 | (int verbose); | |
58 | ||
59 | ||
60 | /* Device initialization: */ | |
61 | ||
62 | INLINE_DEVICE\ | |
63 | (void) device_clean | |
64 | (device *root, | |
65 | void *data); | |
66 | ||
67 | INLINE_DEVICE\ | |
68 | (void) device_init_static_properties | |
69 | (device *me, | |
70 | void *data); | |
71 | ||
72 | INLINE_DEVICE\ | |
73 | (void) device_init_address | |
74 | (device *me, | |
75 | void *data); | |
76 | ||
77 | INLINE_DEVICE\ | |
78 | (void) device_init_runtime_properties | |
79 | (device *me, | |
80 | void *data); | |
81 | ||
82 | INLINE_DEVICE\ | |
83 | (void) device_init_data | |
84 | (device *me, | |
85 | void *data); | |
86 | ||
87 | ||
88 | /* Relationships: | |
89 | ||
90 | A device is able to determine its relationship to other devices | |
91 | within the tree. Operations include querying for a devices parent, | |
92 | sibling, child, name, and path (from the root). | |
93 | ||
94 | */ | |
95 | ||
96 | INLINE_DEVICE\ | |
97 | (device *) device_parent | |
98 | (device *me); | |
99 | ||
100 | INLINE_DEVICE\ | |
101 | (device *) device_root | |
102 | (device *me); | |
103 | ||
104 | INLINE_DEVICE\ | |
105 | (device *) device_sibling | |
106 | (device *me); | |
107 | ||
108 | INLINE_DEVICE\ | |
109 | (device *) device_child | |
110 | (device *me); | |
111 | ||
112 | INLINE_DEVICE\ | |
113 | (const char *) device_name | |
114 | (device *me); | |
115 | ||
116 | INLINE_DEVICE\ | |
117 | (const char *) device_base | |
118 | (device *me); | |
119 | ||
120 | INLINE_DEVICE\ | |
121 | (const char *) device_path | |
122 | (device *me); | |
123 | ||
124 | INLINE_DEVICE\ | |
125 | (void *) device_data | |
126 | (device *me); | |
127 | ||
128 | INLINE_DEVICE\ | |
129 | (psim *) device_system | |
130 | (device *me); | |
131 | ||
132 | typedef struct _device_unit { | |
133 | int nr_cells; | |
134 | unsigned_cell cells[4]; /* unused cells are zero */ | |
135 | } device_unit; | |
136 | ||
137 | INLINE_DEVICE\ | |
138 | (const device_unit *) device_unit_address | |
139 | (device *me); | |
140 | ||
141 | INLINE_DEVICE\ | |
142 | (int) device_decode_unit | |
143 | (device *bus, | |
144 | const char *unit, | |
145 | device_unit *address); | |
146 | ||
147 | INLINE_DEVICE\ | |
148 | (int) device_encode_unit | |
149 | (device *bus, | |
150 | const device_unit *unit_address, | |
151 | char *buf, | |
152 | int sizeof_buf); | |
153 | ||
154 | ||
155 | /* Convert an Open Firmware size into a form suitable for attach | |
156 | address calls. | |
157 | ||
158 | Return a zero result if the address should be ignored when looking | |
159 | for attach addresses */ | |
160 | ||
161 | INLINE_DEVICE\ | |
162 | (int) device_address_to_attach_address | |
163 | (device *me, | |
164 | const device_unit *address, | |
165 | int *attach_space, | |
166 | unsigned_word *attach_address, | |
167 | device *client); | |
168 | ||
169 | ||
170 | /* Convert an Open Firmware size into a form suitable for attach | |
171 | address calls | |
172 | ||
173 | Return a zero result if the address should be ignored */ | |
174 | ||
175 | INLINE_DEVICE\ | |
176 | (int) device_size_to_attach_size | |
177 | (device *me, | |
178 | const device_unit *size, | |
179 | unsigned *nr_bytes, | |
180 | device *client); | |
181 | ||
182 | ||
183 | INLINE_DEVICE\ | |
184 | (unsigned) device_nr_address_cells | |
185 | (device *me); | |
186 | ||
187 | INLINE_DEVICE\ | |
188 | (unsigned) device_nr_size_cells | |
189 | (device *me); | |
190 | ||
191 | ||
192 | /* Properties: | |
193 | ||
194 | Attached to a device are a number of properties. Each property has | |
195 | a size and type (both of which can be queried). A device is able | |
196 | to iterate over or query and set a properties value. | |
197 | ||
198 | */ | |
199 | ||
200 | /* The following are valid property types. The property `array' is | |
201 | for generic untyped data. */ | |
202 | ||
203 | typedef enum { | |
204 | array_property, | |
205 | boolean_property, | |
206 | ihandle_property, /*runtime*/ | |
207 | integer_property, | |
208 | range_array_property, | |
209 | reg_array_property, | |
210 | string_property, | |
211 | string_array_property, | |
212 | } device_property_type; | |
213 | ||
214 | typedef struct _device_property device_property; | |
215 | struct _device_property { | |
216 | device *owner; | |
217 | const char *name; | |
218 | device_property_type type; | |
219 | unsigned sizeof_array; | |
220 | const void *array; | |
221 | const device_property *original; | |
222 | object_disposition disposition; | |
223 | }; | |
224 | ||
225 | ||
226 | /* iterate through the properties attached to a device */ | |
227 | ||
228 | INLINE_DEVICE\ | |
229 | (const device_property *) device_next_property | |
230 | (const device_property *previous); | |
231 | ||
232 | INLINE_DEVICE\ | |
233 | (const device_property *) device_find_property | |
234 | (device *me, | |
235 | const char *property); /* NULL for first property */ | |
236 | ||
237 | ||
238 | /* Manipulate the properties belonging to a given device. | |
239 | ||
240 | SET on the other hand will force the properties value. The | |
241 | simulation is aborted if the property was present but of a | |
242 | conflicting type. | |
243 | ||
244 | FIND returns the specified properties value, aborting the | |
245 | simulation if the property is missing. Code locating a property | |
246 | should first check its type (using device_find_property above) and | |
247 | then obtain its value using the below. | |
248 | ||
249 | void device_add_<type>_property(device *, const char *, <type>) | |
250 | void device_add_*_array_property(device *, const char *, const <type>*, int) | |
251 | void device_set_*_property(device *, const char *, <type>) | |
252 | void device_set_*_array_property(device *, const char *, const <type>*, int) | |
253 | <type> device_find_*_property(device *, const char *) | |
254 | int device_find_*_array_property(device *, const char *, int, <type>*) | |
255 | ||
256 | */ | |
257 | ||
258 | ||
259 | INLINE_DEVICE\ | |
260 | (void) device_add_array_property | |
261 | (device *me, | |
262 | const char *property, | |
263 | const void *array, | |
264 | int sizeof_array); | |
265 | ||
266 | INLINE_DEVICE\ | |
267 | (void) device_set_array_property | |
268 | (device *me, | |
269 | const char *property, | |
270 | const void *array, | |
271 | int sizeof_array); | |
272 | ||
273 | INLINE_DEVICE\ | |
274 | (const device_property *) device_find_array_property | |
275 | (device *me, | |
276 | const char *property); | |
277 | ||
278 | ||
279 | ||
280 | INLINE_DEVICE\ | |
281 | (void) device_add_boolean_property | |
282 | (device *me, | |
283 | const char *property, | |
284 | int bool); | |
285 | ||
286 | INLINE_DEVICE\ | |
287 | (int) device_find_boolean_property | |
288 | (device *me, | |
289 | const char *property); | |
290 | ||
291 | ||
292 | ||
293 | typedef struct _ihandle_runtime_property_spec { | |
294 | const char *full_path; | |
295 | } ihandle_runtime_property_spec; | |
296 | ||
297 | INLINE_DEVICE\ | |
298 | (void) device_add_ihandle_runtime_property | |
299 | (device *me, | |
300 | const char *property, | |
301 | const ihandle_runtime_property_spec *ihandle); | |
302 | ||
303 | INLINE_DEVICE\ | |
304 | (void) device_find_ihandle_runtime_property | |
305 | (device *me, | |
306 | const char *property, | |
307 | ihandle_runtime_property_spec *ihandle); | |
308 | ||
309 | INLINE_DEVICE\ | |
310 | (void) device_set_ihandle_property | |
311 | (device *me, | |
312 | const char *property, | |
313 | device_instance *ihandle); | |
314 | ||
315 | INLINE_DEVICE\ | |
316 | (device_instance *) device_find_ihandle_property | |
317 | (device *me, | |
318 | const char *property); | |
319 | ||
320 | ||
321 | ||
322 | INLINE_DEVICE\ | |
323 | (void) device_add_integer_property | |
324 | (device *me, | |
325 | const char *property, | |
326 | signed_cell integer); | |
327 | ||
328 | INLINE_DEVICE\ | |
329 | (signed_cell) device_find_integer_property | |
330 | (device *me, | |
331 | const char *property); | |
332 | ||
333 | INLINE_DEVICE\ | |
334 | (int) device_find_integer_array_property | |
335 | (device *me, | |
336 | const char *property, | |
337 | unsigned index, | |
d29d5195 | 338 | signed_cell *integer); |
c906108c SS |
339 | |
340 | ||
341 | ||
342 | typedef struct _range_property_spec { | |
343 | device_unit child_address; | |
344 | device_unit parent_address; | |
345 | device_unit size; | |
346 | } range_property_spec; | |
347 | ||
348 | INLINE_DEVICE\ | |
349 | (void) device_add_range_array_property | |
350 | (device *me, | |
351 | const char *property, | |
352 | const range_property_spec *ranges, | |
353 | unsigned nr_ranges); | |
354 | ||
355 | INLINE_DEVICE\ | |
356 | (int) device_find_range_array_property | |
357 | (device *me, | |
358 | const char *property, | |
359 | unsigned index, | |
360 | range_property_spec *range); | |
361 | ||
362 | ||
363 | ||
364 | typedef struct _reg_property_spec { | |
365 | device_unit address; | |
366 | device_unit size; | |
367 | } reg_property_spec; | |
368 | ||
369 | INLINE_DEVICE\ | |
370 | (void) device_add_reg_array_property | |
371 | (device *me, | |
372 | const char *property, | |
373 | const reg_property_spec *reg, | |
374 | unsigned nr_regs); | |
375 | ||
376 | INLINE_DEVICE\ | |
377 | (int) device_find_reg_array_property | |
378 | (device *me, | |
379 | const char *property, | |
380 | unsigned index, | |
381 | reg_property_spec *reg); | |
382 | ||
383 | ||
384 | ||
385 | INLINE_DEVICE\ | |
386 | (void) device_add_string_property | |
387 | (device *me, | |
388 | const char *property, | |
389 | const char *string); | |
390 | ||
391 | INLINE_DEVICE\ | |
392 | (const char *) device_find_string_property | |
393 | (device *me, | |
394 | const char *property); | |
395 | ||
396 | ||
397 | ||
398 | typedef const char *string_property_spec; | |
399 | ||
400 | INLINE_DEVICE\ | |
401 | (void) device_add_string_array_property | |
402 | (device *me, | |
403 | const char *property, | |
404 | const string_property_spec *strings, | |
405 | unsigned nr_strings); | |
406 | ||
407 | INLINE_DEVICE\ | |
408 | (int) device_find_string_array_property | |
409 | (device *me, | |
410 | const char *property, | |
411 | unsigned index, | |
412 | string_property_spec *string); | |
413 | ||
414 | ||
415 | ||
416 | INLINE_DEVICE\ | |
417 | (void) device_add_duplicate_property | |
418 | (device *me, | |
419 | const char *property, | |
420 | const device_property *original); | |
421 | ||
422 | ||
423 | ||
424 | /* Instances: | |
425 | ||
426 | As with IEEE1275, a device can be opened, creating an instance. | |
427 | Instances provide more abstract interfaces to the underlying | |
428 | hardware. For example, the instance methods for a disk may include | |
429 | code that is able to interpret file systems found on disks. Such | |
430 | methods would there for allow the manipulation of files on the | |
431 | disks file system. The operations would be implemented using the | |
432 | basic block I/O model provided by the disk. | |
433 | ||
434 | This model includes methods that faciliate the creation of device | |
435 | instance and (should a given device support it) standard operations | |
436 | on those instances. | |
437 | ||
438 | */ | |
439 | ||
440 | typedef struct _device_instance_callbacks device_instance_callbacks; | |
441 | ||
442 | INLINE_DEVICE\ | |
443 | (device_instance *) device_create_instance_from | |
444 | (device *me, /*OR*/ device_instance *parent, | |
445 | void *data, | |
446 | const char *path, | |
447 | const char *args, | |
448 | const device_instance_callbacks *callbacks); | |
449 | ||
450 | INLINE_DEVICE\ | |
451 | (device_instance *) device_create_instance | |
452 | (device *me, | |
453 | const char *full_path, | |
454 | const char *args); | |
455 | ||
456 | INLINE_DEVICE\ | |
457 | (void) device_instance_delete | |
458 | (device_instance *instance); | |
459 | ||
460 | INLINE_DEVICE\ | |
461 | (int) device_instance_read | |
462 | (device_instance *instance, | |
463 | void *addr, | |
464 | unsigned_word len); | |
465 | ||
466 | INLINE_DEVICE\ | |
467 | (int) device_instance_write | |
468 | (device_instance *instance, | |
469 | const void *addr, | |
470 | unsigned_word len); | |
471 | ||
472 | INLINE_DEVICE\ | |
473 | (int) device_instance_seek | |
474 | (device_instance *instance, | |
475 | unsigned_word pos_hi, | |
476 | unsigned_word pos_lo); | |
477 | ||
478 | INLINE_DEVICE\ | |
479 | (int) device_instance_call_method | |
480 | (device_instance *instance, | |
481 | const char *method, | |
482 | int n_stack_args, | |
483 | unsigned_cell stack_args[/*n_stack_args*/], | |
484 | int n_stack_returns, | |
485 | unsigned_cell stack_returns[/*n_stack_returns*/]); | |
486 | ||
487 | INLINE_DEVICE\ | |
488 | (device *) device_instance_device | |
489 | (device_instance *instance); | |
490 | ||
491 | INLINE_DEVICE\ | |
492 | (const char *) device_instance_path | |
493 | (device_instance *instance); | |
494 | ||
495 | INLINE_DEVICE\ | |
496 | (void *) device_instance_data | |
497 | (device_instance *instance); | |
498 | ||
499 | ||
500 | /* Interrupts: | |
501 | ||
502 | */ | |
503 | ||
504 | /* Interrupt Source | |
505 | ||
506 | A device drives its interrupt line using the call | |
507 | ||
508 | */ | |
509 | ||
510 | INLINE_DEVICE\ | |
511 | (void) device_interrupt_event | |
512 | (device *me, | |
513 | int my_port, | |
514 | int value, | |
515 | cpu *processor, | |
516 | unsigned_word cia); | |
517 | ||
518 | /* This interrupt event will then be propogated to any attached | |
519 | interrupt destinations. | |
520 | ||
521 | Any interpretation of PORT and VALUE is model dependant. However | |
522 | as guidelines the following are recommended: PCI interrupts a-d | |
523 | correspond to lines 0-3; level sensative interrupts be requested | |
524 | with a value of one and withdrawn with a value of 0; edge sensative | |
525 | interrupts always have a value of 1, the event its self is treated | |
526 | as the interrupt. | |
527 | ||
528 | ||
529 | Interrupt Destinations | |
530 | ||
531 | Attached to each interrupt line of a device can be zero or more | |
532 | desitinations. These destinations consist of a device/port pair. | |
533 | A destination is attached/detached to a device line using the | |
534 | attach and detach calls. */ | |
535 | ||
536 | INLINE_DEVICE\ | |
537 | (void) device_interrupt_attach | |
538 | (device *me, | |
539 | int my_port, | |
540 | device *dest, | |
541 | int dest_port, | |
542 | object_disposition disposition); | |
543 | ||
544 | INLINE_DEVICE\ | |
545 | (void) device_interrupt_detach | |
546 | (device *me, | |
547 | int my_port, | |
548 | device *dest, | |
549 | int dest_port); | |
550 | ||
551 | typedef void (device_interrupt_traverse_function) | |
552 | (device *me, | |
553 | int my_port, | |
554 | device *dest, | |
555 | int my_dest, | |
556 | void *data); | |
557 | ||
558 | INLINE_DEVICE\ | |
559 | (void) device_interrupt_traverse | |
560 | (device *me, | |
561 | device_interrupt_traverse_function *handler, | |
562 | void *data); | |
563 | ||
564 | ||
565 | /* DESTINATION is attached (detached) to LINE of the device ME | |
566 | ||
567 | ||
568 | Interrupt conversion | |
569 | ||
570 | Users refer to interrupt port numbers symbolically. For instance a | |
571 | device may refer to its `INT' signal which is internally | |
572 | represented by port 3. | |
573 | ||
574 | To convert to/from the symbolic and internal representation of a | |
575 | port name/number. The following functions are available. */ | |
576 | ||
577 | INLINE_DEVICE\ | |
578 | (int) device_interrupt_decode | |
579 | (device *me, | |
580 | const char *symbolic_name, | |
581 | port_direction direction); | |
582 | ||
583 | INLINE_DEVICE\ | |
584 | (int) device_interrupt_encode | |
585 | (device *me, | |
586 | int port_number, | |
587 | char *buf, | |
588 | int sizeof_buf, | |
589 | port_direction direction); | |
590 | ||
591 | ||
592 | /* Hardware operations: | |
593 | ||
594 | */ | |
595 | ||
596 | INLINE_DEVICE\ | |
597 | (unsigned) device_io_read_buffer | |
598 | (device *me, | |
599 | void *dest, | |
600 | int space, | |
601 | unsigned_word addr, | |
602 | unsigned nr_bytes, | |
603 | cpu *processor, | |
604 | unsigned_word cia); | |
605 | ||
606 | INLINE_DEVICE\ | |
607 | (unsigned) device_io_write_buffer | |
608 | (device *me, | |
609 | const void *source, | |
610 | int space, | |
611 | unsigned_word addr, | |
612 | unsigned nr_bytes, | |
613 | cpu *processor, | |
614 | unsigned_word cia); | |
615 | ||
616 | ||
617 | /* Conversly, the device pci1000,1@1 my need to perform a dma transfer | |
618 | into the cpu/memory core. Just as I/O moves towards the leaves, | |
619 | dma transfers move towards the core via the initiating devices | |
620 | parent nodes. The root device (special) converts the DMA transfer | |
621 | into reads/writes to memory */ | |
622 | ||
623 | INLINE_DEVICE\ | |
624 | (unsigned) device_dma_read_buffer | |
625 | (device *me, | |
626 | void *dest, | |
627 | int space, | |
628 | unsigned_word addr, | |
629 | unsigned nr_bytes); | |
630 | ||
631 | INLINE_DEVICE\ | |
632 | (unsigned) device_dma_write_buffer | |
633 | (device *me, | |
634 | const void *source, | |
635 | int space, | |
636 | unsigned_word addr, | |
637 | unsigned nr_bytes, | |
638 | int violate_read_only_section); | |
639 | ||
640 | /* To avoid the need for an intermediate (bridging) node to ask each | |
641 | of its child devices in turn if an IO access is intended for them, | |
642 | parent nodes maintain a table mapping addresses directly to | |
643 | specific devices. When a device is `connected' to its bus it | |
644 | attaches its self to its parent. */ | |
645 | ||
646 | /* Address access attributes */ | |
647 | typedef enum _access_type { | |
648 | access_invalid = 0, | |
649 | access_read = 1, | |
650 | access_write = 2, | |
651 | access_read_write = 3, | |
652 | access_exec = 4, | |
653 | access_read_exec = 5, | |
654 | access_write_exec = 6, | |
655 | access_read_write_exec = 7, | |
656 | } access_type; | |
657 | ||
658 | /* Address attachement types */ | |
659 | typedef enum _attach_type { | |
660 | attach_invalid, | |
661 | attach_raw_memory, | |
662 | attach_callback, | |
663 | /* ... */ | |
664 | } attach_type; | |
665 | ||
666 | INLINE_DEVICE\ | |
667 | (void) device_attach_address | |
668 | (device *me, | |
669 | attach_type attach, | |
670 | int space, | |
671 | unsigned_word addr, | |
672 | unsigned nr_bytes, | |
673 | access_type access, | |
674 | device *client); /*callback/default*/ | |
675 | ||
676 | INLINE_DEVICE\ | |
677 | (void) device_detach_address | |
678 | (device *me, | |
679 | attach_type attach, | |
680 | int space, | |
681 | unsigned_word addr, | |
682 | unsigned nr_bytes, | |
683 | access_type access, | |
684 | device *client); /*callback/default*/ | |
685 | ||
686 | /* Utilities: | |
687 | ||
688 | */ | |
689 | ||
690 | /* IOCTL:: | |
691 | ||
692 | Often devices require `out of band' operations to be performed. | |
693 | For instance a pal device may need to notify a PCI bridge device | |
694 | that an interrupt ack cycle needs to be performed on the PCI bus. | |
695 | Within PSIM such operations are performed by using the generic | |
696 | ioctl call <<device_ioctl()>>. | |
697 | ||
698 | */ | |
699 | ||
700 | typedef enum { | |
701 | device_ioctl_break, /* unsigned_word requested_break */ | |
702 | device_ioctl_set_trace, /* void */ | |
703 | device_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */ | |
704 | device_ioctl_change_media, /* const char *new_image (possibly NULL) */ | |
705 | nr_device_ioctl_requests, | |
706 | } device_ioctl_request; | |
707 | ||
708 | EXTERN_DEVICE\ | |
709 | (int) device_ioctl | |
710 | (device *me, | |
711 | cpu *processor, | |
712 | unsigned_word cia, | |
713 | device_ioctl_request request, | |
714 | ...); | |
715 | ||
716 | ||
717 | /* Error reporting:: | |
718 | ||
719 | So that errors originating from devices appear in a consistent | |
720 | format, the <<device_error()>> function can be used. Formats and | |
721 | outputs the error message before aborting the simulation | |
722 | ||
723 | Devices should use this function to abort the simulation except | |
724 | when the abort reason leaves the simulation in a hazardous | |
725 | condition (for instance a failed malloc). | |
726 | ||
727 | */ | |
728 | ||
729 | EXTERN_DEVICE\ | |
730 | (void volatile) device_error | |
731 | (device *me, | |
732 | const char *fmt, | |
733 | ...) __attribute__ ((format (printf, 2, 3))); | |
734 | ||
735 | INLINE_DEVICE\ | |
736 | (int) device_trace | |
737 | (device *me); | |
738 | ||
739 | ||
740 | ||
741 | /* External representation: | |
742 | ||
743 | Both device nodes and device instances, in OpenBoot firmware have | |
744 | an external representation (phandles and ihandles) and these values | |
745 | are both stored in the device tree in property nodes and passed | |
746 | between the client program and the simulator during emulation | |
747 | calls. | |
748 | ||
749 | To limit the potential risk associated with trusing `data' from the | |
750 | client program, the following mapping operators `safely' convert | |
751 | between the two representations | |
752 | ||
753 | */ | |
754 | ||
755 | INLINE_DEVICE\ | |
756 | (device *) external_to_device | |
757 | (device *tree_member, | |
758 | unsigned_cell phandle); | |
759 | ||
760 | INLINE_DEVICE\ | |
761 | (unsigned_cell) device_to_external | |
762 | (device *me); | |
763 | ||
764 | INLINE_DEVICE\ | |
765 | (device_instance *) external_to_device_instance | |
766 | (device *tree_member, | |
767 | unsigned_cell ihandle); | |
768 | ||
769 | INLINE_DEVICE\ | |
770 | (unsigned_cell) device_instance_to_external | |
771 | (device_instance *me); | |
772 | ||
773 | ||
774 | /* Event queue: | |
775 | ||
776 | The device inherets certain event queue operations from the main | |
777 | simulation. */ | |
778 | ||
779 | typedef void device_event_handler(void *data); | |
780 | ||
781 | INLINE_DEVICE\ | |
782 | (event_entry_tag) device_event_queue_schedule | |
783 | (device *me, | |
784 | signed64 delta_time, | |
785 | device_event_handler *handler, | |
786 | void *data); | |
787 | ||
788 | INLINE_EVENTS\ | |
789 | (void) device_event_queue_deschedule | |
790 | (device *me, | |
791 | event_entry_tag event_to_remove); | |
792 | ||
793 | INLINE_EVENTS\ | |
794 | (signed64) device_event_queue_time | |
795 | (device *me); | |
796 | ||
797 | #endif /* _DEVICE_H_ */ |