1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
29 /* declared in basics.h, this object is used everywhere */
30 /* typedef struct _device device; */
35 As explained in earlier sections, the device, device instance,
36 property and interrupts lie at the heart of PSIM's device model.
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>>.
45 /* Device creation: */
48 (device
*) device_create
52 const char *unit_address
,
60 /* Device initialization: */
68 (void) device_init_static_properties
73 (void) device_init_address
78 (void) device_init_runtime_properties
83 (void) device_init_data
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).
97 (device
*) device_parent
101 (device
*) device_root
105 (device
*) device_sibling
109 (device
*) device_child
113 (const char *) device_name
117 (const char *) device_base
121 (const char *) device_path
129 (psim
*) device_system
132 typedef struct _device_unit
{
134 unsigned_cell cells
[4]; /* unused cells are zero */
138 (const device_unit
*) device_unit_address
142 (int) device_decode_unit
145 device_unit
*address
);
148 (int) device_encode_unit
150 const device_unit
*unit_address
,
155 /* Convert an Open Firmware size into a form suitable for attach
158 Return a zero result if the address should be ignored when looking
159 for attach addresses */
162 (int) device_address_to_attach_address
164 const device_unit
*address
,
166 unsigned_word
*attach_address
,
170 /* Convert an Open Firmware size into a form suitable for attach
173 Return a zero result if the address should be ignored */
176 (int) device_size_to_attach_size
178 const device_unit
*size
,
184 (unsigned) device_nr_address_cells
188 (unsigned) device_nr_size_cells
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.
200 /* The following are valid property types. The property `array' is
201 for generic untyped data. */
206 ihandle_property
, /*runtime*/
208 range_array_property
,
211 string_array_property
,
212 } device_property_type
;
214 typedef struct _device_property device_property
;
215 struct _device_property
{
218 device_property_type type
;
219 unsigned sizeof_array
;
221 const device_property
*original
;
222 object_disposition disposition
;
226 /* iterate through the properties attached to a device */
229 (const device_property
*) device_next_property
230 (const device_property
*previous
);
233 (const device_property
*) device_find_property
235 const char *property
); /* NULL for first property */
238 /* Manipulate the properties belonging to a given device.
240 SET on the other hand will force the properties value. The
241 simulation is aborted if the property was present but of a
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.
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>*)
260 (void) device_add_array_property
262 const char *property
,
267 (void) device_set_array_property
269 const char *property
,
274 (const device_property
*) device_find_array_property
276 const char *property
);
281 (void) device_add_boolean_property
283 const char *property
,
287 (int) device_find_boolean_property
289 const char *property
);
293 typedef struct _ihandle_runtime_property_spec
{
295 const char *full_path
;
297 } ihandle_runtime_property_spec
;
300 (void) device_add_ihandle_runtime_property
302 const char *property
,
303 const ihandle_runtime_property_spec
*ihandle
);
306 (void) device_find_ihandle_runtime_property
308 const char *property
,
309 ihandle_runtime_property_spec
*ihandle
);
312 (void) device_set_ihandle_property
314 const char *property
,
315 device_instance
*ihandle
);
318 (device_instance
*) device_find_ihandle_property
320 const char *property
);
325 (void) device_add_integer_property
327 const char *property
,
328 signed_cell integer
);
331 (signed_cell
) device_find_integer_property
333 const char *property
);
336 (int) device_find_integer_array_property
338 const char *property
,
340 signed_word
*integer
);
344 typedef struct _range_property_spec
{
345 device_unit child_address
;
346 device_unit parent_address
;
348 } range_property_spec
;
351 (void) device_add_range_array_property
353 const char *property
,
354 const range_property_spec
*ranges
,
358 (int) device_find_range_array_property
360 const char *property
,
362 range_property_spec
*range
);
366 typedef struct _reg_property_spec
{
372 (void) device_add_reg_array_property
374 const char *property
,
375 const reg_property_spec
*reg
,
379 (int) device_find_reg_array_property
381 const char *property
,
383 reg_property_spec
*reg
);
388 (void) device_add_string_property
390 const char *property
,
394 (const char *) device_find_string_property
396 const char *property
);
400 typedef const char *string_property_spec
;
403 (void) device_add_string_array_property
405 const char *property
,
406 const string_property_spec
*strings
,
407 unsigned nr_strings
);
410 (int) device_find_string_array_property
412 const char *property
,
414 string_property_spec
*string
);
419 (void) device_add_duplicate_property
421 const char *property
,
422 const device_property
*original
);
428 As with IEEE1275, a device can be opened, creating an instance.
429 Instances provide more abstract interfaces to the underlying
430 hardware. For example, the instance methods for a disk may include
431 code that is able to interpret file systems found on disks. Such
432 methods would there for allow the manipulation of files on the
433 disks file system. The operations would be implemented using the
434 basic block I/O model provided by the disk.
436 This model includes methods that faciliate the creation of device
437 instance and (should a given device support it) standard operations
442 typedef struct _device_instance_callbacks device_instance_callbacks
;
445 (device_instance
*) device_create_instance_from
446 (device
*me
, /*OR*/ device_instance
*parent
,
450 const device_instance_callbacks
*callbacks
);
453 (device_instance
*) device_create_instance
455 const char *full_path
,
459 (void) device_instance_delete
460 (device_instance
*instance
);
463 (int) device_instance_read
464 (device_instance
*instance
,
469 (int) device_instance_write
470 (device_instance
*instance
,
475 (int) device_instance_seek
476 (device_instance
*instance
,
477 unsigned_word pos_hi
,
478 unsigned_word pos_lo
);
481 (int) device_instance_call_method
482 (device_instance
*instance
,
485 unsigned_cell stack_args
[/*n_stack_args*/],
487 unsigned_cell stack_returns
[/*n_stack_returns*/]);
490 (device
*) device_instance_device
491 (device_instance
*instance
);
494 (const char *) device_instance_path
495 (device_instance
*instance
);
498 (void *) device_instance_data
499 (device_instance
*instance
);
508 A device drives its interrupt line using the call
513 (void) device_interrupt_event
520 /* This interrupt event will then be propogated to any attached
521 interrupt destinations.
523 Any interpretation of PORT and VALUE is model dependant. However
524 as guidelines the following are recommended: PCI interrupts a-d
525 correspond to lines 0-3; level sensative interrupts be requested
526 with a value of one and withdrawn with a value of 0; edge sensative
527 interrupts always have a value of 1, the event its self is treated
531 Interrupt Destinations
533 Attached to each interrupt line of a device can be zero or more
534 desitinations. These destinations consist of a device/port pair.
535 A destination is attached/detached to a device line using the
536 attach and detach calls. */
539 (void) device_interrupt_attach
544 object_disposition disposition
);
547 (void) device_interrupt_detach
553 typedef void (device_interrupt_traverse_function
)
561 (void) device_interrupt_traverse
563 device_interrupt_traverse_function
*handler
,
567 /* DESTINATION is attached (detached) to LINE of the device ME
572 Users refer to interrupt port numbers symbolically. For instance a
573 device may refer to its `INT' signal which is internally
574 represented by port 3.
576 To convert to/from the symbolic and internal representation of a
577 port name/number. The following functions are available. */
580 (int) device_interrupt_decode
582 const char *symbolic_name
,
583 port_direction direction
);
586 (int) device_interrupt_encode
591 port_direction direction
);
594 /* Hardware operations:
599 (unsigned) device_io_read_buffer
609 (unsigned) device_io_write_buffer
619 /* Conversly, the device pci1000,1@1 my need to perform a dma transfer
620 into the cpu/memory core. Just as I/O moves towards the leaves,
621 dma transfers move towards the core via the initiating devices
622 parent nodes. The root device (special) converts the DMA transfer
623 into reads/writes to memory */
626 (unsigned) device_dma_read_buffer
634 (unsigned) device_dma_write_buffer
640 int violate_read_only_section
);
642 /* To avoid the need for an intermediate (bridging) node to ask each
643 of its child devices in turn if an IO access is intended for them,
644 parent nodes maintain a table mapping addresses directly to
645 specific devices. When a device is `connected' to its bus it
646 attaches its self to its parent. */
648 /* Address access attributes */
649 typedef enum _access_type
{
653 access_read_write
= 3,
655 access_read_exec
= 5,
656 access_write_exec
= 6,
657 access_read_write_exec
= 7,
660 /* Address attachement types */
661 typedef enum _attach_type
{
669 (void) device_attach_address
676 device
*client
); /*callback/default*/
679 (void) device_detach_address
686 device
*client
); /*callback/default*/
694 Often devices require `out of band' operations to be performed.
695 For instance a pal device may need to notify a PCI bridge device
696 that an interrupt ack cycle needs to be performed on the PCI bus.
697 Within PSIM such operations are performed by using the generic
698 ioctl call <<device_ioctl()>>.
703 device_ioctl_break
, /* unsigned_word requested_break */
704 device_ioctl_set_trace
, /* void */
705 device_ioctl_create_stack
, /* unsigned_word *sp, char **argv, char **envp */
706 device_ioctl_change_media
, /* const char *new_image (possibly NULL) */
707 nr_device_ioctl_requests
,
708 } device_ioctl_request
;
715 device_ioctl_request request
,
721 So that errors originating from devices appear in a consistent
722 format, the <<device_error()>> function can be used. Formats and
723 outputs the error message before aborting the simulation
725 Devices should use this function to abort the simulation except
726 when the abort reason leaves the simulation in a hazardous
727 condition (for instance a failed malloc).
732 (void volatile) device_error
735 ...) __attribute__ ((format (printf
, 2, 3)));
743 /* External representation:
745 Both device nodes and device instances, in OpenBoot firmware have
746 an external representation (phandles and ihandles) and these values
747 are both stored in the device tree in property nodes and passed
748 between the client program and the simulator during emulation
751 To limit the potential risk associated with trusing `data' from the
752 client program, the following mapping operators `safely' convert
753 between the two representations
758 (device
*) external_to_device
759 (device
*tree_member
,
760 unsigned_cell phandle
);
763 (unsigned_cell
) device_to_external
767 (device_instance
*) external_to_device_instance
768 (device
*tree_member
,
769 unsigned_cell ihandle
);
772 (unsigned_cell
) device_instance_to_external
773 (device_instance
*me
);
778 The device inherets certain event queue operations from the main
781 typedef void device_event_handler(void *data
);
784 (event_entry_tag
) device_event_queue_schedule
787 device_event_handler
*handler
,
791 (void) device_event_queue_deschedule
793 event_entry_tag event_to_remove
);
796 (signed64
) device_event_queue_time
799 #endif /* _DEVICE_H_ */