Home | History | Annotate | Line # | Download | only in ppc
      1 /*  This file is part of the program psim.
      2 
      3     Copyright (C) 1994-1996, Andrew Cagney <cagney (at) 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 3 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, see <http://www.gnu.org/licenses/>.
     17 
     18     */
     19 
     20 
     21 #ifndef _HW_CPU_C_
     22 #define _HW_CPU_C_
     23 
     24 #ifndef STATIC_INLINE_HW_CPU
     25 #define STATIC_INLINE_HW_CPU STATIC_INLINE
     26 #endif
     27 
     28 #include "device_table.h"
     29 #include "hw_cpu.h"
     30 
     31 #include "interrupts.h"
     32 #include "cpu.h"
     33 
     34 
     35 /* DEVICE
     36 
     37 
     38    cpu - Interface to a Processor
     39 
     40 
     41    DESCRIPTION
     42 
     43 
     44    The CPU device provides the connection between the interrupt net
     45    (linking the devices and the interrupt controller) and the
     46    simulated model of each processor.  This device contains interrupt
     47    ports that correspond directly to the external interrupt stimulus
     48    that can be sent to a given processor.  Sending an interrupt to one
     49    of the ports results in an interrupt being delivered to the
     50    corresponding processor.
     51 
     52    Typically, an interrupt controller would have its inputs connected
     53    to device interrupt sources and its outputs (sreset, int, et.al.)
     54    connected to this device.
     55 
     56 
     57    PROPERTIES
     58 
     59 
     60    cpu-nr = <integer> (required)
     61 
     62 
     63    Specify the processor (1..N) that this cpu device node should
     64    control.
     65 
     66 
     67    EXAMPLES
     68 
     69 
     70    Connect an OpenPIC interrupt controller interrupt ports to
     71    processor zero.
     72 
     73    | -o '/phb/opic@0 > irq0 int /cpus/cpu@0' \
     74    | -o '/phb/opic@0 > init hreset /cpus/cpu@0' \
     75 
     76 
     77    */
     78 
     79 typedef struct _hw_cpu_device {
     80   int cpu_nr;
     81   cpu *processor;
     82 } hw_cpu_device;
     83 
     84 static const device_interrupt_port_descriptor hw_cpu_interrupt_ports[] = {
     85   { "hreset", hw_cpu_hard_reset },
     86   { "sreset", hw_cpu_soft_reset },
     87   { "int", hw_cpu_external_interrupt },
     88   { "mci", hw_cpu_machine_check_interrupt },
     89   { "smi", hw_cpu_system_management_interrupt },
     90   { NULL }
     91 };
     92 
     93 
     94 static void *
     95 hw_cpu_create(const char *name,
     96 	      const device_unit *unit_address,
     97 	      const char *args)
     98 {
     99   hw_cpu_device *hw_cpu = ZALLOC(hw_cpu_device);
    100   return hw_cpu;
    101 }
    102 
    103 
    104 /* during address initialization ensure that any missing cpu
    105    properties are added to this devices node */
    106 
    107 static void
    108 hw_cpu_init_address(device *me)
    109 {
    110   hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
    111   /* populate the node with properties */
    112   /* clear our data */
    113   memset(hw_cpu, 0x0, sizeof(hw_cpu_device));
    114   hw_cpu->cpu_nr = device_find_integer_property(me, "cpu-nr");
    115   hw_cpu->processor = psim_cpu(device_system(me), hw_cpu->cpu_nr);
    116 }
    117 
    118 
    119 /* Take the interrupt and synchronize its delivery with the clock.  If
    120    we've not yet scheduled an interrupt for the next clock tick, take
    121    the opportunity to do it now */
    122 
    123 static void
    124 hw_cpu_interrupt_event(device *me,
    125 		       int my_port,
    126 		       device *source,
    127 		       int source_port,
    128 		       int level,
    129 		       cpu *processor,
    130 		       unsigned_word cia)
    131 {
    132   hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
    133   if (my_port < 0 || my_port >= hw_cpu_nr_interrupt_ports)
    134     error("hw_cpu_interrupt_event_callback: interrupt port out of range %d\n",
    135 	  my_port);
    136   switch (my_port) {
    137     /*case hw_cpu_hard_reset:*/
    138     /*case hw_cpu_soft_reset:*/
    139   case hw_cpu_external_interrupt:
    140     external_interrupt(hw_cpu->processor, level);
    141     break;
    142     /*case hw_cpu_machine_check_interrupt:*/
    143   default:
    144     error("hw_cpu_deliver_interrupt: unimplemented interrupt port %d\n",
    145 	  my_port);
    146     break;
    147   }
    148 }
    149 
    150 
    151 static device_callbacks const hw_cpu_callbacks = {
    152   { hw_cpu_init_address, }, /* init */
    153   { NULL, }, /* address */
    154   { NULL, }, /* io */
    155   { NULL, }, /* DMA */
    156   { hw_cpu_interrupt_event, NULL, hw_cpu_interrupt_ports }, /* interrupts */
    157   { NULL, NULL, },
    158 };
    159 
    160 const device_descriptor hw_cpu_device_descriptor[] = {
    161   { "hw-cpu", hw_cpu_create, &hw_cpu_callbacks },
    162   { "cpu", hw_cpu_create, &hw_cpu_callbacks },
    163   { NULL, },
    164 };
    165 
    166 #endif /* _HW_CPU_C_ */
    167