home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / sim / ppc / device.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-22  |  19.9 KB  |  708 lines

  1. /*  This file is part of the program psim.
  2.  
  3.     Copyright (C) 1994-1996, 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. /* Devices:
  34.  
  35.    OpenBoot documentation refers to devices, device nodes, packages,
  36.    package instances, methods, static methods and properties.  This
  37.    device implementation uses its own termonology. Where ever it
  38.    exists, the notes will indicate a correspondance between PSIM terms
  39.    and those found in OpenBoot.
  40.  
  41.    device:
  42.  
  43.    A device is the basic building block in this model.  A device can
  44.    be further categorized into one of three classes - template, node
  45.    and instance.
  46.  
  47.    device-node (aka device):
  48.  
  49.    The device tree is constructed from device-nodes.  Each node has
  50.    both local state (data), a relationship with the device nodes
  51.    around it and an address (unit-address) on the parents bus `bus' */
  52.  
  53. INLINE_DEVICE(device *) device_parent
  54. (device *me);
  55.  
  56. INLINE_DEVICE(device *) device_sibling
  57. (device *me);
  58.  
  59. INLINE_DEVICE(device *) device_child
  60. (device *me);
  61.  
  62. INLINE_DEVICE(const char *) device_name
  63. (device *me);
  64.  
  65. INLINE_DEVICE(const char *) device_path
  66. (device *me);
  67.  
  68. INLINE_DEVICE(void *) device_data
  69. (device *me);
  70.  
  71. typedef struct _device_unit {
  72.   int nr_cells;
  73.   unsigned32 cells[4]; /* unused cells are zero */
  74. } device_unit;
  75.  
  76. INLINE_DEVICE(const device_unit *) device_unit_address
  77. (device *me);
  78.  
  79. /* Each device-node normally corresponds to a hardware component of
  80.    the system being modeled.  Leaf nodes matching external devices and
  81.    intermediate nodes matching bridges and controllers.
  82.    
  83.    Device nodes also support methods that are an abstraction of the
  84.    transactions that occure in real hardware.  These operations
  85.    (io/dma read/writes and interrupts) are discussed separatly later.
  86.  
  87.    OpenBoot refers to device nodes by many names.  The most common are
  88.    device, device node and package.
  89.  
  90.  
  91.    device-template:
  92.  
  93.    A device node is created from its template.  The only valid
  94.    operation on a template is to create a device node from it: */
  95.  
  96. INLINE_DEVICE(device *) device_template_create_device
  97. (device *parent,
  98.  const char *name,
  99.  const char *unit_address,
  100.  const char *args);
  101.  
  102. /* The create is paramaterized by both the devices unit address (a
  103.    string that is converted into numeric form by the devices parent)
  104.    and optionally extra argument information.
  105.  
  106.    The actual device node is constructed by a number of pieces provided
  107.    by the template function: */
  108.  
  109. typedef struct _device_callbacks device_callbacks;
  110.  
  111. INLINE_DEVICE(device *) device_create_from
  112. (const char *name,
  113.  const device_unit *unit_address,
  114.  void *data,
  115.  const device_callbacks *callbacks,
  116.  device *parent);
  117.  
  118. /* OpenBoot discusses the creation of packages (devices).
  119.  
  120.  
  121.  
  122.  
  123.    device-instance:
  124.  
  125.    Devices support an abstract I/O model. A unique I/O instance can be
  126.    created from a device node and then this instance used to perform
  127.    I/O that is independant of other instances. */
  128.  
  129. INLINE_DEVICE(device_instance *)device_instance_create
  130. (device *me,
  131.  const char *device_specifier,
  132.  int permanant);
  133.  
  134. INLINE_DEVICE(void) device_instance_delete
  135. (device_instance *instance);
  136.  
  137. INLINE_DEVICE(int) device_instance_read
  138. (device_instance *instance,
  139.  void *addr,
  140.  unsigned_word len);
  141.  
  142. INLINE_DEVICE(int) device_instance_write
  143. (device_instance *instance,
  144.  const void *addr,
  145.  unsigned_word len);
  146.  
  147. INLINE_DEVICE(int) device_instance_seek
  148. (device_instance *instance,
  149.  unsigned_word pos_hi,
  150.  unsigned_word pos_lo);
  151.  
  152. INLINE_DEVICE(device *) device_instance_device
  153. (device_instance *instance);
  154.  
  155. INLINE_DEVICE(const char *) device_instance_name
  156. (device_instance *instance);
  157.  
  158. INLINE_DEVICE(const char *) device_instance_path
  159. (device_instance *instance);
  160.  
  161. INLINE_DEVICE(void *) device_instance_data
  162. (device_instance *instance);
  163.  
  164. /* A device instance can be marked (when created) as being permenant.
  165.    Such instances are assigned a reserved address and are *not*
  166.    deleted between simulation runs.
  167.  
  168.    OpenBoot refers to a device instace as a package instance */
  169.  
  170.  
  171. /* Device initialization:
  172.  
  173.    A device is created once (from its template) but initialized at the
  174.    start of every simulation run.  This initialization is performed in
  175.    stages:
  176.  
  177.     o    All attached addresses are detached
  178.         Any non-permenant interrupts are detached
  179.         Any non-permemant device instances are deleted
  180.  
  181.     o    the devices all initialize their address spaces
  182.     
  183.     o    the devices all initialize their data areas
  184.  
  185.    */
  186.  
  187. INLINE_DEVICE(void) device_init_address
  188. (device *me,
  189.  psim *system);
  190.  
  191. INLINE_DEVICE(void) device_init_data
  192. (device *me,
  193.  psim *system);
  194.  
  195. INLINE_DEVICE(void) device_tree_init
  196. (device *root,
  197.  psim *system);
  198.  
  199.  
  200.  
  201. /* Device Properties:
  202.  
  203.    Attached to a device node are its properties.  Properties describe
  204.    the devices characteristics, for instance the address of its
  205.    configuration and contrll registers. Unlike OpenBoot PSIM strictly
  206.    types all properties.properties that profile the devices features.
  207.    The below allow the manipulation of device properties */
  208.  
  209. typedef enum {
  210.   array_property,
  211.   boolean_property,
  212.   ihandle_property,
  213.   integer_property,
  214.   phandle_property,
  215.   string_property,
  216. } device_property_type;
  217.  
  218. typedef struct _device_property device_property;
  219. struct _device_property {
  220.   device *owner;
  221.   const char *name;
  222.   device_property_type type;
  223.   unsigned sizeof_array;
  224.   const void *array;
  225.   const device_property *original;
  226. };
  227.  
  228.  
  229. /* Locate a devices properties */
  230.  
  231. INLINE_DEVICE(const device_property *) device_next_property
  232. (const device_property *previous);
  233.  
  234. INLINE_DEVICE(const device_property *) device_find_property
  235. (device *me,
  236.  const char *property); /* NULL for first property */
  237.  
  238.  
  239. /* Similar to above except that the property *must* be in the device
  240.    tree and *must* be of the specified type.
  241.  
  242.    If this isn't the case each function indicates is fail action */
  243.  
  244. INLINE_DEVICE(const device_property *) device_find_array_property
  245. (device *me,
  246.  const char *property);
  247.  
  248. INLINE_DEVICE(int) device_find_boolean_property
  249. (device *me,
  250.  const char *property);
  251.  
  252. INLINE_DEVICE(device_instance *) device_find_ihandle_property
  253. (device *me,
  254.  const char *property);
  255.  
  256. INLINE_DEVICE(signed_word) device_find_integer_property
  257. (device *me,
  258.  const char *property);
  259.  
  260. INLINE_DEVICE(device *) device_find_phandle_property
  261. (device *me,
  262.  const char *property);
  263.  
  264. INLINE_DEVICE(const char *) device_find_string_property
  265. (device *me,
  266.  const char *property);
  267.  
  268.  
  269. /* INLINE_DEVICE void device_add_property
  270.    No such external function, all properties, when added are explictly
  271.    typed */
  272.  
  273. INLINE_DEVICE(void) device_add_duplicate_property
  274. (device *me,
  275.  const char *property,
  276.  const device_property *original);
  277.  
  278. INLINE_DEVICE(void) device_add_array_property
  279. (device *me,
  280.  const char *property,
  281.  const void *array,
  282.  int sizeof_array);
  283.  
  284. INLINE_DEVICE(void) device_add_boolean_property
  285. (device *me,
  286.  const char *property,
  287.  int bool);
  288.  
  289. INLINE_DEVICE(void) device_add_ihandle_property
  290. (device *me,
  291.  const char *property,
  292.  device_instance *ihandle);
  293.  
  294. INLINE_DEVICE(void) device_add_integer_property
  295. (device *me,
  296.  const char *property,
  297.  signed_word integer);
  298.  
  299. INLINE_DEVICE(void) device_add_phandle_property
  300. (device *me,
  301.  const char *property,
  302.  device *phandle);
  303.  
  304. INLINE_DEVICE(void) device_add_string_property
  305. (device *me,
  306.  const char *property,
  307.  const char *string);
  308.  
  309.  
  310.  
  311. /* Device Hardware:
  312.  
  313.    This model assumes that the data paths of the system being modeled
  314.    have a tree topology.  That is, one or more processors sit at the
  315.    top of a tree.  That tree containing leaf nodes (real devices) and
  316.    branch nodes (bridges).
  317.  
  318.    For instance, consider the tree:
  319.  
  320.    /pci                    # PCI-HOST bridge
  321.    /pci/pci1000,1@1        # A pci controller
  322.    /pci/isa8086            # PCI-ISA bridge
  323.    /pci/isa8086/fdc@300    # floppy disk controller on ISA bus
  324.  
  325.    A processor needing to access the device fdc@300 on the ISA bus
  326.    would do so using a data path that goes through the pci-host bridge
  327.    (pci)and the isa-pci bridge (isa8086) to finally reach the device
  328.    fdc@300.  As the data transfer passes through each intermediate
  329.    bridging node that bridge device is able to (just like with real
  330.    hardware) manipulate either the address or data involved in the
  331.    transfer. */
  332.  
  333. INLINE_DEVICE(unsigned) device_io_read_buffer
  334. (device *me,
  335.  void *dest,
  336.  int space,
  337.  unsigned_word addr,
  338.  unsigned nr_bytes,
  339.  cpu *processor,
  340.  unsigned_word cia);
  341.  
  342. INLINE_DEVICE(unsigned) device_io_write_buffer
  343. (device *me,
  344.  const void *source,
  345.  int space,
  346.  unsigned_word addr,
  347.  unsigned nr_bytes,
  348.  cpu *processor,
  349.  unsigned_word cia);
  350.  
  351.  
  352. /* Conversly, the device pci1000,1@1 my need to perform a dma transfer
  353.    into the cpu/memory core.  Just as I/O moves towards the leaves,
  354.    dma transfers move towards the core via the initiating devices
  355.    parent nodes.  The root device (special) converts the DMA transfer
  356.    into reads/writes to memory */
  357.  
  358. INLINE_DEVICE(unsigned) device_dma_read_buffer
  359. (device *me,
  360.  void *dest,
  361.  int space,
  362.  unsigned_word addr,
  363.  unsigned nr_bytes);
  364.  
  365. INLINE_DEVICE(unsigned) device_dma_write_buffer
  366. (device *me,
  367.  const void *source,
  368.  int space,
  369.  unsigned_word addr,
  370.  unsigned nr_bytes,
  371.  int violate_read_only_section);
  372.  
  373. /* To avoid the need for an intermediate (bridging) node to ask each
  374.    of its child devices in turn if an IO access is intended for them,
  375.    parent nodes maintain a table mapping addresses directly to
  376.    specific devices.  When a device is `connected' to its bus it
  377.    attaches its self to its parent. */
  378.  
  379. /* Address access attributes */
  380. typedef enum _access_type {
  381.   access_invalid = 0,
  382.   access_read = 1,
  383.   access_write = 2,
  384.   access_read_write = 3,
  385.   access_exec = 4,
  386.   access_read_exec = 5,
  387.   access_write_exec = 6,
  388.   access_read_write_exec = 7,
  389. } access_type;
  390.  
  391. /* Address attachement types */
  392. typedef enum _attach_type {
  393.   attach_invalid,
  394.   attach_callback,
  395.   attach_default,
  396.   attach_raw_memory,
  397. } attach_type;
  398.  
  399. INLINE_DEVICE(void) device_attach_address
  400. (device *me,
  401.  const char *name,
  402.  attach_type attach,
  403.  int space,
  404.  unsigned_word addr,
  405.  unsigned nr_bytes,
  406.  access_type access,
  407.  device *who); /*callback/default*/
  408.  
  409. INLINE_DEVICE(void) device_detach_address
  410. (device *me,
  411.  const char *name,
  412.  attach_type attach,
  413.  int space,
  414.  unsigned_word addr,
  415.  unsigned nr_bytes,
  416.  access_type access,
  417.  device *who); /*callback/default*/
  418.  
  419. /* where the attached address space can be any of:
  420.  
  421.    callback - all accesses to that range of addresses are past on to
  422.    the attached child device.
  423.  
  424.    default - if no other device claims the access, it is passed on to
  425.    this child device (giving subtractive decoding).
  426.  
  427.    memory - the specified address space contains RAM, the node that is
  428.    having the ram attached is responsible for allocating space for and
  429.    maintaining that space.  The device initiating the attach will not
  430.    be notified of accesses to such an attachement.
  431.  
  432.    The last type of attachement is very important.  By giving the
  433.    parent node the responsability (and freedom) of managing RAM, that
  434.    node is able to implement memory spaces more efficiently.  For
  435.    instance it could `cache' accesses or merge adjacent memory areas.
  436.  
  437.  
  438.    In addition to I/O and DMA, devices interact with the rest of the
  439.    system via interrupts.  Interrupts are discussed in the next
  440.    section. */
  441.  
  442.  
  443. /* Interrupts
  444.  
  445.    PSIM models interrupts and their wiring as a directed graph of
  446.    connections between interrupt sources and destinations.  The source
  447.    and destination are both a tupple consisting of a port number and
  448.    device.  Both multiple destinations attached to a single source and
  449.    multiple sources attached to a single destination are allowed.
  450.  
  451.    When a device drives an interrupt port with multiple destinations a
  452.    broadcast of that interrupt event (message to all destinations)
  453.    occures.  Each of those destination (device/port) are able to
  454.    further propogate the interrupt until it reaches its ultimate
  455.    destination.
  456.  
  457.    Normally an interrupt source would be a model of a real device
  458.    (such as a keyboard) while an interrupt destination would be an
  459.    interrupt controller.  The facility that allows an interrupt to be
  460.    delivered to multiple devices and to be propogated from device to
  461.    device was designed so that requirements specified by OpenPIC (ISA
  462.    interrupts go to both OpenPIC and 8259), CHRP (8259 connected to
  463.    OpenPIC) and hardware designs such as PCI-PCI bridges.
  464.  
  465.  
  466.    Interrupt Source
  467.  
  468.    A device drives its interrupt line using the call: */
  469.  
  470. INLINE_DEVICE(void) device_interrupt_event
  471. (device *me,
  472.  int my_port,
  473.  int value,
  474.  cpu *processor,
  475.  unsigned_word cia);
  476.  
  477. /* This interrupt event will then be propogated to any attached
  478.    interrupt destinations.
  479.  
  480.    Any interpretation of PORT and VALUE is model dependant.  However
  481.    as guidelines the following are recommended: PCI interrupts a-d
  482.    correspond to lines 0-3; level sensative interrupts be requested
  483.    with a value of one and withdrawn with a value of 0; edge sensative
  484.    interrupts always have a value of 1, the event its self is treated
  485.    as the interrupt.
  486.  
  487.  
  488.    Interrupt Destinations
  489.  
  490.    Attached to each interrupt line of a device can be zero or more
  491.    desitinations.  These destinations consist of a device/port pair.
  492.    A destination is attached/detached to a device line using the
  493.    attach and detach calls. */
  494.  
  495. INLINE_DEVICE(void) device_interrupt_attach
  496. (device *me,
  497.  int my_port,
  498.  device *dest,
  499.  int dest_port,
  500.  int permenant);
  501.  
  502. INLINE_DEVICE(void) device_interrupt_detach
  503. (device *me,
  504.  int my_port,
  505.  device *dest,
  506.  int dest_port);
  507.  
  508. /* DESTINATION is attached (detached) to LINE of the device ME
  509.  
  510.    Should no destination be attached to a given devices interrupt line
  511.    then that interrupt is propogated up the device tree (through
  512.    parent nodes) until a parent that has an interrupt destination
  513.    attached to its special child-interrupt line.  These are attached
  514.    with: */
  515.  
  516. INLINE_DEVICE(void) device_child_interrupt_attach
  517. (device *me,
  518.  device *destination,
  519.  int permenant);
  520.  
  521. INLINE_DEVICE(void) device_child_interrupt_detach
  522. (device *me,
  523.  device *destination);
  524.  
  525. /* It is an error for an interrupt to be propogated past the root node
  526.  
  527.  
  528.    Interrupting a processor
  529.  
  530.    While it is possible for an interrupt destination device to
  531.    directly interrupt a processor (using interrupt.h calls) it is not
  532.    the norm.  Interrupting a processor midway through the cpu cycle
  533.    would result in a simulation restart.  This restart may result in
  534.    the interrupt not being delivered to all the intended destinations.
  535.  
  536.    Instead, an interrupt controller, when it has been determined that
  537.    a processor should be interrupted should:
  538.  
  539.        o   Schedule an immediate timer event (using events.h)
  540.            These events occure at the end of the cpu cycle.
  541.  
  542.        o   When this timer event is delivered (at the end of the
  543.            cpu cycle) the interrupt controller can then deliver
  544.        its interrupt.
  545.  
  546.    It should be noted that interrupts can be delivered to an interrupt
  547.    controller either during the middle of the cpu cycle or at the end.
  548.    Further an interrupt could be delivered at the end of a cycle
  549.    before and after an interrupt controller receives its own timer
  550.    events.  An interrupt controller must be able to handle these cases
  551.    gracefully. */
  552.  
  553.  
  554. /* IOCTL:
  555.  
  556.    Very simply, a catch all for any thing that turns up that until now
  557.    either hasn't been thought of or doesn't justify an extra function. */
  558.  
  559. EXTERN_DEVICE\
  560. (void) device_ioctl
  561. (device *me,
  562.  psim *system,
  563.  cpu *processor,
  564.  unsigned_word cia,
  565.  ...);
  566.  
  567.  
  568. /* Tree utilities:
  569.  
  570.    In addition to the standard method of creating a device from a
  571.    device template, the following sortcuts can be used.
  572.  
  573.    Create a device or property from a textual representation */
  574.  
  575. EXTERN_DEVICE(device *) device_tree_add_parsed
  576. (device *current,
  577.  const char *fmt,
  578.  ...) __attribute__ ((format (printf, 2, 3)));
  579.  
  580. /* where FMT,... once formatted (using vsprintf) is used to locate and
  581.    create either a device or property.  Its syntax is almost identical
  582.    to that used in OpenBoot documentation - the only extension is in
  583.    allowing properties and their values to be specified vis:
  584.  
  585.    "/pci/pci1000,1@1/disk@0,0"
  586.  
  587.    Path:
  588.  
  589.    The path to a device or property can either be absolute (leading
  590.    `/') or relative (leading `.' or `..').  Relative paths start from
  591.    the CURRENT node.  The new current node is returned as the result.
  592.    In addition, a path may start with a leading alias (resolved by
  593.    looking in /aliases).
  594.  
  595.    Device name:
  596.  
  597.    <name> "@" <unit> [ ":" <args> ]
  598.  
  599.    Where <name> is the name of the template device, <unit> is a
  600.    textual specification of the devices unit address (that is
  601.    converted into a numeric form by the devices parent) and <args> are
  602.    optional additional information to be passed to the device-template
  603.    when it creates the device.
  604.  
  605.    Properties:
  606.  
  607.    Properties are specified in a similar way to devices except that
  608.    the last element on the path (which would have been the device) is
  609.    the property name. This path is then followed by the property
  610.    value. Unlike OpenBoot, the property values in the device tree are
  611.    strongly typed.
  612.  
  613.    String property:
  614.  
  615.      <property-name> " " <text>
  616.      <property-name> " " "\"" <text>
  617.    
  618.    Boolean property:
  619.  
  620.      <property-name> " " [ "true" | "false" ]
  621.    Integer property or integer array property:
  622.  
  623.      <property-name> " " <number> { <number> }
  624.  
  625.    Phandle property:
  626.  
  627.      <property-name> " " "&" <path-to-device>
  628.  
  629.    Ihandle property:
  630.  
  631.      <property-name> " " "*" <path-to-device-to-open>
  632.  
  633.    Duplicate existing property:
  634.  
  635.      <property-name> " " "!" <path-to-original-property>
  636.  
  637.  
  638.    In addition to properties, the wiring of interrupts can be
  639.    specified:
  640.  
  641.    Attach interrupt <line> of <device> to <controller>:
  642.  
  643.      <device> " " ">" <my-port>  <dest-port> <dest-device>
  644.  
  645.    Attach child interrupt of <device> to <controller>:
  646.  
  647.      <device> " " "<" <controller>
  648.  
  649.  
  650.    Once created, a device tree can be traversed in various orders: */
  651.  
  652. typedef void (device_tree_traverse_function)
  653.      (device *device,
  654.       void *data);
  655.  
  656. INLINE_DEVICE(void) device_tree_traverse
  657. (device *root,
  658.  device_tree_traverse_function *prefix,
  659.  device_tree_traverse_function *postfix,
  660.  void *data);
  661.  
  662. /* Or dumped out in a format that can be read back in using
  663.    device_add_parsed() */
  664.  
  665. INLINE_DEVICE(void) device_tree_print_device
  666. (device *device,
  667.  void *ignore_data_argument);
  668.  
  669. /* Individual nodes can be located using */
  670.  
  671. INLINE_DEVICE(device *) device_tree_find_device
  672. (device *root,
  673.  const char *path);
  674.  
  675. /* And the current list of devices can be listed */
  676.  
  677. INLINE_DEVICE(void) device_usage
  678. (int verbose);
  679.  
  680.  
  681. /* External representation
  682.  
  683.    Both device nodes and device instances, in OpenBoot firmware have
  684.    an external representation (phandles and ihandles) and these values
  685.    are both stored in the device tree in property nodes and passed
  686.    between the client program and the simulator during emulation
  687.    calls.
  688.  
  689.    To limit the potential risk associated with trusing `data' from the
  690.    client program, the following mapping operators `safely' convert
  691.    between the two representations: */
  692.  
  693. INLINE_DEVICE(device *) external_to_device
  694. (device *tree_member,
  695.  unsigned32 phandle);
  696.  
  697. INLINE_DEVICE(unsigned32) device_to_external
  698. (device *me);
  699.  
  700. INLINE_DEVICE(device_instance *) external_to_device_instance
  701. (device *tree_member,
  702.  unsigned32 ihandle);
  703.  
  704. INLINE_DEVICE(unsigned32) device_instance_to_external
  705. (device_instance *me);
  706.  
  707. #endif /* _DEVICE_H_ */
  708.