/* This file is part of the program GDB, the GNU debugger.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998-2020 Free Software Foundation, Inc.
Contributed by Cygnus Solutions.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sim-main.h"
-#include "hw-base.h"
+#include "hw-main.h"
/* DEVICE
Implements the tx3904 interrupt controller described in the tx3904
user guide. It does not include the interrupt detection circuit
- that preprocesses the eight external interrupts.
+ that preprocesses the eight external interrupts, so assumes that
+ each event on an input interrupt port signals a new interrupt.
+ That is, it implements edge- rather than level-triggered
+ interrupts.
+
+ This implementation does not support multiple concurrent
+ interrupts.
PROPERTIES
that even though INT[0] is tied externally to IP[5], we simulate
it as passing through the controller.
+ An output level of zero signals the clearing of a level interrupt.
+
int0-7 (input)
- External interrupts.
+ External interrupts. Level = 0 -> level interrupt cleared.
dmac0-3 (input)
- DMA internal interrupts, correspond to DMA channels 0-3.
+ DMA internal interrupts, correspond to DMA channels 0-3. Level = 0 -> level interrupt cleared.
sio0-1 (input)
- SIO internal interrupts.
+ SIO internal interrupts. Level = 0 -> level interrupt cleared.
tmr0-2 (input)
- Timer internal interrupts.
+ Timer internal interrupts. Level = 0 -> level interrupt cleared.
*/
+
+
+/* register numbers; each is one word long */
+enum
+{
+ ISR_REG = 0,
+ IMR_REG = 1,
+ ILR0_REG = 4,
+ ILR1_REG = 5,
+ ILR2_REG = 6,
+ ILR3_REG = 7,
+};
+
+
/* port ID's */
-enum {
+enum
+{
/* inputs, ordered to correspond to interrupt sources 0..15 */
INT1_PORT = 0, INT2_PORT, INT3_PORT, INT4_PORT, INT5_PORT, INT6_PORT, INT7_PORT,
DMAC3_PORT, DMAC2_PORT, DMAC1_PORT, DMAC0_PORT, SIO0_PORT, SIO1_PORT,
};
-/* register numbers; each is one word long */
-enum {
- ISR_REG = 0,
- IMR_REG = 1,
- ILR0_REG = 4,
- ILR1_REG = 5,
- ILR2_REG = 6,
- ILR3_REG = 7,
-};
-
-
-
static const struct hw_port_descriptor tx3904irc_ports[] = {
/* interrupt output */
/* Finish off the partially created hw device. Attach our local
callbacks. Wire up our port names etc */
-static hw_io_read_buffer_callback tx3904irc_io_read_buffer;
-static hw_io_write_buffer_callback tx3904irc_io_write_buffer;
-static hw_port_event_callback tx3904irc_port_event;
+static hw_io_read_buffer_method tx3904irc_io_read_buffer;
+static hw_io_write_buffer_method tx3904irc_io_write_buffer;
+static hw_port_event_method tx3904irc_port_event;
static void
attach_tx3904irc_regs (struct hw *me,
static void
tx3904irc_finish (struct hw *me)
{
- int i;
struct tx3904irc *controller;
controller = HW_ZALLOC (me, struct tx3904irc);
static void
tx3904irc_port_event (struct hw *me,
int my_port,
- struct hw *source,
+ struct hw *source_dev,
int source_port,
int level)
{
struct tx3904irc *controller = hw_data (me);
+ /* handle deactivated interrupt */
+ if(level == 0)
+ {
+ HW_TRACE ((me, "interrupt cleared on port %d", my_port));
+ hw_port_event(me, IP_PORT, 0);
+ return;
+ }
+
switch (my_port)
{
case INT0_PORT:
{
int source = my_port - INT1_PORT;
- HW_TRACE ((me, "port-event interrupt source %d", source));
+ HW_TRACE ((me, "interrupt asserted on port %d", source));
ISR_SET(controller, source);
if(ILR_GET(controller, source) > IMR_GET(controller))
{
}
/* write requested byte out */
- memcpy(dest+byte, ((char*)& register_value)+reg_offset, 1);
+ register_value = H2T_4(register_value);
+ memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1);
}
return nr_bytes;
default: register_ptr = & register_value; /* used as a dummy */
}
- HW_TRACE ((me, "reg %d pre: %08lx", reg_number, (long) *register_ptr));
+ /* HW_TRACE ((me, "reg %d pre: %08lx", reg_number, (long) *register_ptr)); */
/* overwrite requested byte */
- memcpy(((char*)register_ptr)+reg_offset, source+byte, 1);
+ register_value = H2T_4(* register_ptr);
+ memcpy (((char*)®ister_value)+reg_offset, (const char*)source + byte, 1);
+ * register_ptr = T2H_4(register_value);
- HW_TRACE ((me, "post: %08lx", (long) *register_ptr));
+ /* HW_TRACE ((me, "post: %08lx", (long) *register_ptr)); */
}
return nr_bytes;
}
-const struct hw_device_descriptor dv_tx3904irc_descriptor[] = {
+const struct hw_descriptor dv_tx3904irc_descriptor[] = {
{ "tx3904irc", tx3904irc_finish, },
{ NULL },
};