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 *** THIS SECTION DESCRIBES HOW A DEVICE HAS A STATIC AND DYNAMIC
36 COMPONENT ** on the device in the tree is dynamic. *****
38 A device node is created from its template. The only valid
39 operation on a template is to create a device node from it: */
42 (device *) device_template_create_device
45 const char *unit_address,
48 /* The create is paramaterized by both the devices unit address (a
49 string that is converted into numeric form by the devices parent)
50 and optionally extra argument information.
52 The actual device node is constructed by a number of pieces provided
53 by the template function: */
55 typedef struct _device_callbacks device_callbacks;
58 (device *) device_create_from
60 const device_unit *unit_address,
62 const device_callbacks *callbacks,
65 /* OpenBoot discusses the creation of packages (devices). */
70 As with OpenBoot, all nodes in the device tree are considered to be
71 devices. Each node then has associated with it a number of methods
72 and properties (duscussed later).
74 OpenBoot documentation refers to devices, device nodes, packages,
75 package instances, methods, static methods and properties. This
76 device implementation uses its own termonology. Where ever it
77 exists, the notes will indicate a correspondance between PSIM terms
78 and those found in OpenBoot.
82 A device is the basic building block in this model. A device can
83 be further categorized into one of three classes - template, node
86 device-node (aka device):
88 The device tree is constructed from device-nodes. Each node has
89 both local state (data), a relationship with the device nodes
90 around it and an address (unit-address) on the parents bus `bus' */
93 (device *) device_parent
97 (device *) device_sibling
101 (device *) device_child
105 (const char *) device_name
109 (const char *) device_path
117 (psim *) device_system
120 typedef struct _device_unit {
122 unsigned32 cells[4]; /* unused cells are zero */
126 (const device_unit *) device_unit_address
129 /* Each device-node normally corresponds to a hardware component of
130 the system being modeled. Leaf nodes matching external devices and
131 intermediate nodes matching bridges and controllers.
133 Device nodes also support methods that are an abstraction of the
134 transactions that occure in real hardware. These operations
135 (io/dma read/writes and interrupts) are discussed separatly.
137 OpenBoot refers to device nodes by many names. The most common are
138 device, device node and package. */
143 In IEEE1275 many of the the characteristics of a device are stored
144 in the device tree as properties. Each property consists of a name
145 and an associated (implicitly typed) value. A device will have a
146 list of properties attached to it. The user is able to manipulate
147 the list, adding and removing properties and set/modify the value
150 PSIM's device tree follows this model but with the addition of
151 strongly typing each property's value. The simulator will detect
152 at run time, the incorrect use of a property.
154 In addition to the standard use of properties, Both PSIM and
155 individual devices will use properties to record simulation
156 configuration information. For instance, a disk device might store
157 in a string property called <<file>> the name of the file that
158 contains the disk image to use. */
160 /* The following are valid property types. The property `array' is a
161 for generic untyped data. */
169 } device_property_type;
171 typedef struct _device_property device_property;
172 struct _device_property {
175 device_property_type type;
176 unsigned sizeof_array;
178 const device_property *original;
179 object_disposition disposition;
183 /* iterate through the properties attached to a device */
186 (const device_property *) device_next_property
187 (const device_property *previous);
190 (const device_property *) device_find_property
192 const char *property); /* NULL for first property */
195 /* Manipulate the properties belonging to a given device.
197 SET on the other hand will force the properties value. The
198 simulation is aborted if the property was present but of a
201 FIND returns the specified properties value, aborting the
202 simulation if the property is missing. Code locating a property
203 should first check its type (using device_find_property above) and
204 then obtain its value using the below. */
208 (void) device_set_array_property
210 const char *property,
215 (const device_property *) device_find_array_property
217 const char *property);
222 (void) device_set_boolean_property
224 const char *property,
229 (int) device_find_boolean_property
231 const char *property);
236 (void) device_set_ihandle_property
238 const char *property,
239 device_instance *ihandle);
243 (device_instance *) device_find_ihandle_property
245 const char *property);
250 (void) device_set_integer_property
252 const char *property,
253 signed_word integer);
257 (signed_word) device_find_integer_property
259 const char *property);
264 (void) device_set_string_property
266 const char *property,
271 (const char *) device_find_string_property
273 const char *property);
278 As with IEEE1275, a device can be opened, creating an instance.
279 Instances provide more abstract interfaces to the underlying
280 hardware. For example, the instance methods for a disk may include
281 code that is able to interpret file systems found on disks. Such
282 methods would there for allow the manipulation of files on the
283 disks file system. The operations would be implemented using the
284 basic block I/O model provided by the disk.
286 This model includes methods that faciliate the creation of device
287 instance and (should a given device support it) standard operations
288 on those instances. */
290 *** device-instance ***
292 Devices support an abstract I/O model. A unique I/O instance can be
293 created from a device node and then this instance used to perform
294 I/O that is independant of other instances. */
296 typedef struct _device_instance_callbacks device_instance_callbacks;
299 (device_instance *) device_create_instance_from
300 (device *me, /*OR*/ device_instance *parent,
304 const device_instance_callbacks *callbacks);
307 (device_instance *) device_create_instance
309 const char *device_specifier);
312 (void) device_instance_delete
313 (device_instance *instance);
316 (int) device_instance_read
317 (device_instance *instance,
322 (int) device_instance_write
323 (device_instance *instance,
328 (int) device_instance_seek
329 (device_instance *instance,
330 unsigned_word pos_hi,
331 unsigned_word pos_lo);
334 (unsigned_word) device_instance_claim
335 (device_instance *instance,
336 unsigned_word address,
337 unsigned_word length,
338 unsigned_word alignment);
341 (void) device_instance_release
342 (device_instance *instance,
343 unsigned_word address,
344 unsigned_word length);
347 (device *) device_instance_device
348 (device_instance *instance);
351 (const char *) device_instance_path
352 (device_instance *instance);
355 (void *) device_instance_data
356 (device_instance *instance);
358 /* A device instance can be marked (when created) as being permenant.
359 Such instances are assigned a reserved address and are *not*
360 deleted between simulation runs.
362 OpenBoot refers to a device instace as a package instance */
367 *** DESCRIBE HERE WHAT A PIO OPERATION IS and how, broadly it is
371 During initialization, each device attaches its self to is parent
372 registering the address spaces that it is interested in:
374 a. The <<com>> device attaches its self to its parent <<phb>>
375 device at address <<0x3f8>> through to address <<0x3f8 + 16>>.
377 b. The <<phb>> has in turn attached its self to addresses
378 <<0xf0000000 .. 0xf0100000>>.
380 During the execution of the simulation propper, the following then
383 1. After any virtual to physical translation, the processor
384 passes the address to be read (or written to the core device).
385 (eg address 0xf00003f8).
387 2. The core device then looks up the specified addresses in its
388 address to device map, determines that in this case the address
389 belongs to the phb and passes it down.
391 3. The <<phb>> in turn determines that the address belongs to the
392 serial port and passes to that device the request for an access
393 to location <<0x3f8>>.
401 This model assumes that the data paths of the system being modeled
402 have a tree topology. That is, one or more processors sit at the
403 top of a tree. That tree containing leaf nodes (real devices) and
404 branch nodes (bridges).
406 For instance, consider the tree:
408 /pci # PCI-HOST bridge
409 /pci/pci1000,1@1 # A pci controller
410 /pci/isa8086 # PCI-ISA bridge
411 /pci/isa8086/fdc@300 # floppy disk controller on ISA bus
413 A processor needing to access the device fdc@300 on the ISA bus
414 would do so using a data path that goes through the pci-host bridge
415 (pci)and the isa-pci bridge (isa8086) to finally reach the device
416 fdc@300. As the data transfer passes through each intermediate
417 bridging node that bridge device is able to (just like with real
418 hardware) manipulate either the address or data involved in the
422 (unsigned) device_io_read_buffer
432 (unsigned) device_io_write_buffer
441 /* To avoid the need for an intermediate (bridging) node to ask each
442 of its child devices in turn if an IO access is intended for them,
443 parent nodes maintain a table mapping addresses directly to
444 specific devices. When a device is `connected' to its bus it
445 attaches its self to its parent. */
447 /* Address access attributes */
448 typedef enum _access_type {
452 access_read_write = 3,
454 access_read_exec = 5,
455 access_write_exec = 6,
456 access_read_write_exec = 7,
459 /* Address attachement types */
460 typedef enum _attach_type {
468 (void) device_attach_address
476 device *who); /*callback/default*/
479 (void) device_detach_address
487 device *who); /*callback/default*/
489 /* where the attached address space can be any of
491 callback - all accesses to that range of addresses are past on to
492 the attached child device. The callback addresses are ordered
493 according to the callback level (attach_callback, .. + 1, .. + 2,
494 ...). Lower levels are searched first. This facilitates the
495 implementation of more unusual addressing schema such as
496 subtractive decoding (as seen on the PCI bus). Within a given
497 callback level addresses must not overlap.
499 memory - the specified address space contains RAM, the node that is
500 having the ram attached is responsible for allocating space for and
501 maintaining that space. The device initiating the attach will not
502 be notified of accesses to such an attachement.
504 The memory attachment is very important. By giving the parent node
505 the responsability (and freedom) of managing the RAM, that node is
506 able to implement memory spaces more efficiently. For instance it
507 could `cache' accesses or merge adjacent memory areas.
510 In addition to I/O and DMA, devices interact with the rest of the
511 system via interrupts. Interrupts are discussed separatly. */
516 *** DESCRIBE HERE WHAT A DMA OPERATION IS AND HOW IT IS MODELED,
517 include an interation of an access being reflected back down ***
521 /* Conversly, the device pci1000,1@1 my need to perform a dma transfer
522 into the cpu/memory core. Just as I/O moves towards the leaves,
523 dma transfers move towards the core via the initiating devices
524 parent nodes. The root device (special) converts the DMA transfer
525 into reads/writes to memory */
528 (unsigned) device_dma_read_buffer
536 (unsigned) device_dma_write_buffer
542 int violate_read_only_section);
547 *** DESCRIBE HERE THE INTERRUPT NETWORK ***
549 PSIM models interrupts and their wiring as a directed graph of
550 connections between interrupt sources and destinations. The source
551 and destination are both a tupple consisting of a port number and
552 device. Both multiple destinations attached to a single source and
553 multiple sources attached to a single destination are allowed.
555 When a device drives an interrupt port with multiple destinations a
556 broadcast of that interrupt event (message to all destinations)
557 occures. Each of those destination (device/port) are able to
558 further propogate the interrupt until it reaches its ultimate
561 Normally an interrupt source would be a model of a real device
562 (such as a keyboard) while an interrupt destination would be an
563 interrupt controller. The facility that allows an interrupt to be
564 delivered to multiple devices and to be propogated from device to
565 device was designed to support the requirements specified by
566 OpenPIC (ISA interrupts go to both OpenPIC and 8259), CHRP (8259
567 connected to OpenPIC) and hardware designs such as PCI-PCI
571 /* Interrupting a processor
573 The cpu object provides methods for delivering external interrupts
574 to a given processor.
576 The problem of synchronizing external interrupt delivery with the
577 execution of the cpu is handled internally by the processor object. */
583 A device drives its interrupt line using the call: */
586 (void) device_interrupt_event
593 /* This interrupt event will then be propogated to any attached
594 interrupt destinations.
596 Any interpretation of PORT and VALUE is model dependant. However
597 as guidelines the following are recommended: PCI interrupts a-d
598 correspond to lines 0-3; level sensative interrupts be requested
599 with a value of one and withdrawn with a value of 0; edge sensative
600 interrupts always have a value of 1, the event its self is treated
604 Interrupt Destinations
606 Attached to each interrupt line of a device can be zero or more
607 desitinations. These destinations consist of a device/port pair.
608 A destination is attached/detached to a device line using the
609 attach and detach calls. */
612 (void) device_interrupt_attach
617 object_disposition disposition);
620 (void) device_interrupt_detach
626 /* DESTINATION is attached (detached) to LINE of the device ME
631 Users refer to interrupt port numbers symbolically. For instance a
632 device may refer to its `INT' signal which is internally
633 represented by port 3.
635 To convert to/from the symbolic and internal representation of a
636 port name/number. The following functions are available. */
639 (int) device_interrupt_decode
641 const char *symbolic_name);
644 (int) device_interrupt_encode
654 In PSIM, the device tree is created and then initialized in stages.
655 When using devices it is important to be clear what initialization
656 the simulator assumes is being performed during each of these
659 Firstly, each device is created in isolation (using the create from
660 template method). Only after it has been created will a device be
661 inserted into the tree ready for initialization.
663 Once the tree is created, it is initialized as follows:
665 1. All properties (apart from those containing instances)
668 2. Any interrupts addeded as part of the simulation run
671 4. The initialize address method of each device (in top
672 down order) is called. At this stage the device
675 o Clear address maps and delete allocated memory
676 associated with the devices children.
678 o (Re)attach its own addresses to its parent device.
680 o Ensure that it is otherwize sufficiently
681 initialized such that it is ready for a
682 device instance create call.
684 5. All properties containing an instance of
685 a device are (re)initialized
687 6. The initialize data method for each device is called (in
688 top down) order. At this stage the device is expected to:
690 o Perform any needed data transfers. Such
691 transfers would include the initialization
692 of memory created during the address initialization
698 (void) device_tree_init
706 Very simply, a catch all for any thing that turns up that until now
707 either hasn't been thought of or doesn't justify an extra function. */
717 /* External communcation:
719 Devices interface to the external environment */
721 /* device_error() reports the problem to the console and aborts the
722 simulation. The error message is prefixed with the name of the
726 (void volatile) device_error
729 ...) __attribute__ ((format (printf, 2, 3)));
734 In addition to the standard method of creating a device from a
735 device template, the following sortcuts can be used.
737 Create a device or property from a textual representation */
740 (device *) device_tree_add_parsed
743 ...) __attribute__ ((format (printf, 2, 3)));
745 /* where FMT,... once formatted (using vsprintf) is used to locate and
746 create either a device or property. Its syntax is almost identical
747 to that used in OpenBoot documentation - the only extension is in
748 allowing properties and their values to be specified vis:
750 "/pci/pci1000,1@1/disk@0,0"
754 The path to a device or property can either be absolute (leading
755 `/') or relative (leading `.' or `..'). Relative paths start from
756 the CURRENT node. The new current node is returned as the result.
757 In addition, a path may start with a leading alias (resolved by
758 looking in /aliases).
762 <name> "@" <unit> [ ":" <args> ]
764 Where <name> is the name of the template device, <unit> is a
765 textual specification of the devices unit address (that is
766 converted into a numeric form by the devices parent) and <args> are
767 optional additional information to be passed to the device-template
768 when it creates the device.
772 Properties are specified in a similar way to devices except that
773 the last element on the path (which would have been the device) is
774 the property name. This path is then followed by the property
775 value. Unlike OpenBoot, the property values in the device tree are
780 <property-name> " " <text>
781 <property-name> " " "\"" <text>
785 <property-name> " " [ "true" | "false" ]
786 Integer property or integer array property:
788 <property-name> " " <number> { <number> }
792 <property-name> " " "&" <path-to-device>
796 <property-name> " " "*" <path-to-device-to-open>
798 Duplicate existing property:
800 <property-name> " " "!" <path-to-original-property>
803 In addition to properties, the wiring of interrupts can be
806 Attach interrupt <line> of <device> to <controller>:
808 <device> " " ">" <my-port> <dest-port> <dest-device>
811 Once created, a device tree can be traversed in various orders: */
813 typedef void (device_tree_traverse_function)
818 (void) device_tree_traverse
820 device_tree_traverse_function *prefix,
821 device_tree_traverse_function *postfix,
824 /* Or dumped out in a format that can be read back in using
825 device_add_parsed() */
828 (void) device_tree_print_device
830 void *ignore_data_argument);
832 /* Individual nodes can be located using */
835 (device *) device_tree_find_device
839 /* And the current list of devices can be listed */
846 /* ihandles and phandles:
848 Both device nodes and device instances, in OpenBoot firmware have
849 an external representation (phandles and ihandles) and these values
850 are both stored in the device tree in property nodes and passed
851 between the client program and the simulator during emulation
854 To limit the potential risk associated with trusing `data' from the
855 client program, the following mapping operators `safely' convert
856 between the two representations: */
859 (device *) external_to_device
860 (device *tree_member,
864 (unsigned32) device_to_external
868 (device_instance *) external_to_device_instance
869 (device *tree_member,
873 (unsigned32) device_instance_to_external
874 (device_instance *me);
876 #endif /* _DEVICE_H_ */