Home | History | Annotate | Line # | Download | only in erc32
      1   1.5  christos /* This file is part of SIS (SPARC instruction simulator)
      2   1.5  christos 
      3  1.11  christos    Copyright (C) 1995-2024 Free Software Foundation, Inc.
      4   1.5  christos    Contributed by Jiri Gaisler, European Space Agency
      5   1.5  christos 
      6   1.5  christos    This program is free software; you can redistribute it and/or modify
      7   1.5  christos    it under the terms of the GNU General Public License as published by
      8   1.5  christos    the Free Software Foundation; either version 3 of the License, or
      9   1.5  christos    (at your option) any later version.
     10   1.5  christos 
     11   1.5  christos    This program is distributed in the hope that it will be useful,
     12   1.5  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.5  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.5  christos    GNU General Public License for more details.
     15   1.5  christos 
     16   1.5  christos    You should have received a copy of the GNU General Public License
     17   1.5  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18   1.1  christos 
     19   1.1  christos /* The control space devices */
     20   1.1  christos 
     21  1.10  christos /* This must come before any other includes.  */
     22  1.10  christos #include "defs.h"
     23  1.10  christos 
     24   1.1  christos #include <sys/types.h>
     25   1.1  christos #include <stdio.h>
     26   1.1  christos #include <string.h>
     27  1.10  christos #ifdef HAVE_TERMIOS_H
     28   1.1  christos #include <termios.h>
     29  1.10  christos #endif
     30   1.1  christos #include <sys/fcntl.h>
     31   1.1  christos #include <sys/file.h>
     32   1.1  christos #include <unistd.h>
     33   1.1  christos #include "sis.h"
     34   1.1  christos #include "sim-config.h"
     35   1.1  christos 
     36   1.1  christos extern int      ctrl_c;
     37  1.10  christos extern int32_t    sis_verbose;
     38  1.10  christos extern int32_t    sparclite, sparclite_board;
     39   1.1  christos extern int      rom8,wrp,uben;
     40   1.1  christos extern char     uart_dev1[], uart_dev2[];
     41   1.1  christos 
     42   1.1  christos int dumbio = 0; /* normal, smart, terminal oriented IO by default */
     43   1.1  christos 
     44   1.1  christos /* MEC registers */
     45   1.1  christos #define MEC_START 	0x01f80000
     46   1.1  christos #define MEC_END 	0x01f80100
     47   1.1  christos 
     48   1.1  christos /* Memory exception waitstates */
     49   1.1  christos #define MEM_EX_WS 	1
     50   1.1  christos 
     51   1.1  christos /* ERC32 always adds one waitstate during RAM std */
     52   1.1  christos #define STD_WS 1
     53   1.1  christos 
     54   1.1  christos #ifdef ERRINJ
     55   1.1  christos extern int errmec;
     56   1.1  christos #endif
     57   1.1  christos 
     58   1.1  christos #define MEC_WS	0		/* Waitstates per MEC access (0 ws) */
     59   1.1  christos #define MOK	0
     60   1.1  christos 
     61   1.1  christos /* MEC register addresses */
     62   1.1  christos 
     63   1.1  christos #define MEC_MCR		0x000
     64   1.1  christos #define MEC_SFR  	0x004
     65   1.1  christos #define MEC_PWDR  	0x008
     66   1.1  christos #define MEC_MEMCFG	0x010
     67   1.1  christos #define MEC_IOCR	0x014
     68   1.1  christos #define MEC_WCR		0x018
     69   1.1  christos 
     70   1.1  christos #define MEC_MAR0  	0x020
     71   1.1  christos #define MEC_MAR1  	0x024
     72   1.1  christos 
     73   1.1  christos #define MEC_SSA1 	0x020
     74   1.1  christos #define MEC_SEA1 	0x024
     75   1.1  christos #define MEC_SSA2 	0x028
     76   1.1  christos #define MEC_SEA2 	0x02C
     77   1.1  christos #define MEC_ISR		0x044
     78   1.1  christos #define MEC_IPR		0x048
     79   1.1  christos #define MEC_IMR 	0x04C
     80   1.1  christos #define MEC_ICR 	0x050
     81   1.1  christos #define MEC_IFR 	0x054
     82   1.1  christos #define MEC_WDOG  	0x060
     83   1.1  christos #define MEC_TRAPD  	0x064
     84   1.1  christos #define MEC_RTC_COUNTER	0x080
     85   1.1  christos #define MEC_RTC_RELOAD	0x080
     86   1.1  christos #define MEC_RTC_SCALER	0x084
     87   1.1  christos #define MEC_GPT_COUNTER	0x088
     88   1.1  christos #define MEC_GPT_RELOAD	0x088
     89   1.1  christos #define MEC_GPT_SCALER	0x08C
     90   1.1  christos #define MEC_TIMER_CTRL	0x098
     91   1.1  christos #define MEC_SFSR	0x0A0
     92   1.1  christos #define MEC_FFAR	0x0A4
     93   1.1  christos #define MEC_ERSR	0x0B0
     94   1.1  christos #define MEC_DBG		0x0C0
     95   1.1  christos #define MEC_TCR		0x0D0
     96   1.1  christos 
     97   1.1  christos #define MEC_BRK		0x0C4
     98   1.1  christos #define MEC_WPR		0x0C8
     99   1.1  christos 
    100   1.1  christos #define MEC_UARTA	0x0E0
    101   1.1  christos #define MEC_UARTB	0x0E4
    102   1.1  christos #define MEC_UART_CTRL	0x0E8
    103   1.1  christos #define SIM_LOAD	0x0F0
    104   1.1  christos 
    105   1.1  christos /* Memory exception causes */
    106   1.1  christos #define PROT_EXC	0x3
    107   1.1  christos #define UIMP_ACC	0x4
    108   1.1  christos #define MEC_ACC		0x6
    109   1.1  christos #define WATCH_EXC	0xa
    110   1.1  christos #define BREAK_EXC	0xb
    111   1.1  christos 
    112   1.1  christos /* Size of UART buffers (bytes) */
    113   1.1  christos #define UARTBUF	1024
    114   1.1  christos 
    115   1.1  christos /* Number of simulator ticks between flushing the UARTS. 	 */
    116   1.1  christos /* For good performance, keep above 1000			 */
    117   1.1  christos #define UART_FLUSH_TIME	  3000
    118   1.1  christos 
    119   1.1  christos /* MEC timer control register bits */
    120   1.1  christos #define TCR_GACR 1
    121   1.1  christos #define TCR_GACL 2
    122   1.1  christos #define TCR_GASE 4
    123   1.1  christos #define TCR_GASL 8
    124   1.1  christos #define TCR_TCRCR 0x100
    125   1.1  christos #define TCR_TCRCL 0x200
    126   1.1  christos #define TCR_TCRSE 0x400
    127   1.1  christos #define TCR_TCRSL 0x800
    128   1.1  christos 
    129   1.1  christos /* New uart defines */
    130   1.1  christos #define UART_TX_TIME	1000
    131   1.1  christos #define UART_RX_TIME	1000
    132   1.1  christos #define UARTA_DR	0x1
    133   1.1  christos #define UARTA_SRE	0x2
    134   1.1  christos #define UARTA_HRE	0x4
    135   1.1  christos #define UARTA_OR	0x40
    136   1.1  christos #define UARTA_CLR	0x80
    137   1.1  christos #define UARTB_DR	0x10000
    138   1.1  christos #define UARTB_SRE	0x20000
    139   1.1  christos #define UARTB_HRE	0x40000
    140   1.1  christos #define UARTB_OR	0x400000
    141   1.1  christos #define UARTB_CLR	0x800000
    142   1.1  christos 
    143   1.1  christos #define UART_DR		0x100
    144   1.1  christos #define UART_TSE	0x200
    145   1.1  christos #define UART_THE	0x400
    146   1.1  christos 
    147   1.1  christos /* MEC registers */
    148   1.1  christos 
    149   1.1  christos static char     fname[256];
    150  1.10  christos static int32_t    find = 0;
    151  1.10  christos static uint32_t   mec_ssa[2];	/* Write protection start address */
    152  1.10  christos static uint32_t   mec_sea[2];	/* Write protection end address */
    153  1.10  christos static uint32_t   mec_wpr[2];	/* Write protection control fields */
    154  1.10  christos static uint32_t   mec_sfsr;
    155  1.10  christos static uint32_t   mec_ffar;
    156  1.10  christos static uint32_t   mec_ipr;
    157  1.10  christos static uint32_t   mec_imr;
    158  1.10  christos static uint32_t   mec_isr;
    159  1.10  christos static uint32_t   mec_icr;
    160  1.10  christos static uint32_t   mec_ifr;
    161  1.10  christos static uint32_t   mec_mcr;	/* MEC control register */
    162  1.10  christos static uint32_t   mec_memcfg;	/* Memory control register */
    163  1.10  christos static uint32_t   mec_wcr;	/* MEC waitstate register */
    164  1.10  christos static uint32_t   mec_iocr;	/* MEC IO control register */
    165  1.10  christos static uint32_t   posted_irq;
    166  1.10  christos static uint32_t   mec_ersr;	/* MEC error and status register */
    167  1.10  christos static uint32_t   mec_tcr;	/* MEC test comtrol register */
    168  1.10  christos 
    169  1.10  christos static uint32_t   rtc_counter;
    170  1.10  christos static uint32_t   rtc_reload;
    171  1.10  christos static uint32_t   rtc_scaler;
    172  1.10  christos static uint32_t   rtc_scaler_start;
    173  1.10  christos static uint32_t   rtc_enabled;
    174  1.10  christos static uint32_t   rtc_cr;
    175  1.10  christos static uint32_t   rtc_se;
    176  1.10  christos 
    177  1.10  christos static uint32_t   gpt_counter;
    178  1.10  christos static uint32_t   gpt_reload;
    179  1.10  christos static uint32_t   gpt_scaler;
    180  1.10  christos static uint32_t   gpt_scaler_start;
    181  1.10  christos static uint32_t   gpt_enabled;
    182  1.10  christos static uint32_t   gpt_cr;
    183  1.10  christos static uint32_t   gpt_se;
    184  1.10  christos 
    185  1.10  christos static uint32_t   wdog_scaler;
    186  1.10  christos static uint32_t   wdog_counter;
    187  1.10  christos static uint32_t   wdog_rst_delay;
    188  1.10  christos static uint32_t   wdog_rston;
    189   1.1  christos 
    190   1.1  christos enum wdog_type {
    191   1.1  christos     init, disabled, enabled, stopped
    192   1.1  christos };
    193   1.1  christos 
    194   1.1  christos static enum wdog_type wdog_status;
    195   1.1  christos 
    196   1.1  christos 
    197   1.1  christos /* ROM size 1024 Kbyte */
    198   1.1  christos #define ROM_SZ	 	0x100000
    199   1.1  christos #define ROM_MASK 	0x0fffff
    200   1.1  christos 
    201   1.1  christos /* RAM size 4 Mbyte */
    202   1.1  christos #define RAM_START 	0x02000000
    203   1.1  christos #define RAM_END 	0x02400000
    204   1.1  christos #define RAM_MASK 	0x003fffff
    205   1.1  christos 
    206   1.1  christos /* SPARClite boards all seem to have RAM at the same place. */
    207   1.1  christos #define RAM_START_SLITE	0x40000000
    208   1.1  christos #define RAM_END_SLITE 	0x40400000
    209   1.1  christos #define RAM_MASK_SLITE 	0x003fffff
    210   1.1  christos 
    211   1.1  christos /* Memory support variables */
    212   1.1  christos 
    213  1.10  christos static uint32_t   mem_ramr_ws;	/* RAM read waitstates */
    214  1.10  christos static uint32_t   mem_ramw_ws;	/* RAM write waitstates */
    215  1.10  christos static uint32_t   mem_romr_ws;	/* ROM read waitstates */
    216  1.10  christos static uint32_t   mem_romw_ws;	/* ROM write waitstates */
    217  1.10  christos static uint32_t	mem_ramstart;	/* RAM start */
    218  1.10  christos static uint32_t	mem_ramend;	/* RAM end */
    219  1.10  christos static uint32_t	mem_rammask;	/* RAM address mask */
    220  1.10  christos static uint32_t   mem_ramsz;	/* RAM size */
    221  1.10  christos static uint32_t   mem_romsz;	/* ROM size */
    222  1.10  christos static uint32_t   mem_accprot;	/* RAM write protection enabled */
    223  1.10  christos static uint32_t   mem_blockprot;	/* RAM block write protection enabled */
    224   1.1  christos 
    225   1.1  christos static unsigned char	romb[ROM_SZ];
    226   1.1  christos static unsigned char	ramb[RAM_END - RAM_START];
    227   1.1  christos 
    228   1.1  christos 
    229   1.1  christos /* UART support variables */
    230   1.1  christos 
    231  1.10  christos static int32_t    fd1, fd2;	/* file descriptor for input file */
    232  1.10  christos static int32_t    Ucontrol;	/* UART status register */
    233   1.1  christos static unsigned char aq[UARTBUF], bq[UARTBUF];
    234  1.10  christos static int32_t    anum, aind = 0;
    235  1.10  christos static int32_t    bnum, bind = 0;
    236   1.1  christos static char     wbufa[UARTBUF], wbufb[UARTBUF];
    237   1.1  christos static unsigned wnuma;
    238   1.1  christos static unsigned wnumb;
    239   1.1  christos static FILE    *f1in, *f1out, *f2in, *f2out;
    240  1.10  christos #ifdef HAVE_TERMIOS_H
    241   1.1  christos static struct termios ioc1, ioc2, iocold1, iocold2;
    242  1.10  christos #endif
    243   1.1  christos static int      f1open = 0, f2open = 0;
    244   1.1  christos 
    245   1.1  christos static char     uarta_sreg, uarta_hreg, uartb_sreg, uartb_hreg;
    246  1.10  christos static uint32_t   uart_stat_reg;
    247  1.10  christos static uint32_t   uarta_data, uartb_data;
    248   1.1  christos 
    249   1.1  christos #ifdef ERA
    250   1.1  christos int era = 0;
    251   1.1  christos int erareg;
    252   1.1  christos #endif
    253   1.1  christos 
    254   1.1  christos /* Forward declarations */
    255   1.1  christos 
    256   1.1  christos static void	decode_ersr (void);
    257   1.1  christos #ifdef ERRINJ
    258   1.1  christos static void	iucomperr (void);
    259   1.1  christos #endif
    260   1.1  christos static void	mecparerror (void);
    261   1.1  christos static void	decode_memcfg (void);
    262   1.1  christos static void	decode_wcr (void);
    263   1.1  christos static void	decode_mcr (void);
    264   1.1  christos static void	close_port (void);
    265   1.1  christos static void	mec_reset (void);
    266  1.10  christos static void	mec_intack (int32_t level);
    267   1.1  christos static void	chk_irq (void);
    268  1.10  christos static void	mec_irq (int32_t level);
    269  1.10  christos static void	set_sfsr (uint32_t fault, uint32_t addr,
    270  1.10  christos 			  uint32_t asi, uint32_t read);
    271  1.10  christos static int32_t	mec_read (uint32_t addr, uint32_t asi, uint32_t *data);
    272  1.10  christos static int	mec_write (uint32_t addr, uint32_t data);
    273   1.1  christos static void	port_init (void);
    274  1.10  christos static uint32_t	read_uart (uint32_t addr);
    275  1.10  christos static void	write_uart (uint32_t addr, uint32_t data);
    276   1.1  christos static void	flush_uart (void);
    277  1.10  christos static void	uarta_tx (int32_t);
    278  1.10  christos static void	uartb_tx (int32_t);
    279  1.10  christos static void	uart_rx (int32_t);
    280  1.10  christos static void	uart_intr (int32_t);
    281   1.1  christos static void	uart_irq_start (void);
    282  1.10  christos static void	wdog_intr (int32_t);
    283   1.1  christos static void	wdog_start (void);
    284  1.10  christos static void	rtc_intr (int32_t);
    285   1.1  christos static void	rtc_start (void);
    286  1.10  christos static uint32_t	rtc_counter_read (void);
    287  1.10  christos static void	rtc_scaler_set (uint32_t val);
    288  1.10  christos static void	rtc_reload_set (uint32_t val);
    289  1.10  christos static void	gpt_intr (int32_t);
    290   1.1  christos static void	gpt_start (void);
    291  1.10  christos static uint32_t	gpt_counter_read (void);
    292  1.10  christos static void	gpt_scaler_set (uint32_t val);
    293  1.10  christos static void	gpt_reload_set (uint32_t val);
    294  1.10  christos static void	timer_ctrl (uint32_t val);
    295  1.10  christos static void *	get_mem_ptr (uint32_t addr, uint32_t size);
    296  1.10  christos static void	store_bytes (unsigned char *mem, uint32_t waddr,
    297  1.10  christos 			uint32_t *data, int sz, int32_t *ws);
    298   1.1  christos 
    299   1.1  christos extern int	ext_irl;
    300   1.1  christos 
    301   1.1  christos 
    302   1.1  christos /* One-time init */
    303   1.1  christos 
    304   1.1  christos void
    305  1.10  christos init_sim(void)
    306   1.1  christos {
    307   1.1  christos     port_init();
    308   1.1  christos }
    309   1.1  christos 
    310   1.1  christos /* Power-on reset init */
    311   1.1  christos 
    312   1.1  christos void
    313  1.10  christos reset(void)
    314   1.1  christos {
    315   1.1  christos     mec_reset();
    316   1.1  christos     uart_irq_start();
    317   1.1  christos     wdog_start();
    318   1.1  christos }
    319   1.1  christos 
    320   1.1  christos static void
    321  1.10  christos decode_ersr(void)
    322   1.1  christos {
    323   1.1  christos     if (mec_ersr & 0x01) {
    324   1.1  christos 	if (!(mec_mcr & 0x20)) {
    325   1.1  christos 	    if (mec_mcr & 0x40) {
    326   1.1  christos 	        sys_reset();
    327   1.1  christos 	        mec_ersr = 0x8000;
    328   1.1  christos 	        if (sis_verbose)
    329   1.1  christos 	            printf("Error manager reset - IU in error mode\n");
    330   1.1  christos 	    } else {
    331   1.1  christos 	        sys_halt();
    332   1.1  christos 	        mec_ersr |= 0x2000;
    333   1.1  christos 	        if (sis_verbose)
    334   1.1  christos 	            printf("Error manager halt - IU in error mode\n");
    335   1.1  christos 	    }
    336   1.1  christos 	} else
    337   1.1  christos 	    mec_irq(1);
    338   1.1  christos     }
    339   1.1  christos     if (mec_ersr & 0x04) {
    340   1.1  christos 	if (!(mec_mcr & 0x200)) {
    341   1.1  christos 	    if (mec_mcr & 0x400) {
    342   1.1  christos 	        sys_reset();
    343   1.1  christos 	        mec_ersr = 0x8000;
    344   1.1  christos 	        if (sis_verbose)
    345   1.1  christos 	            printf("Error manager reset - IU comparison error\n");
    346   1.1  christos 	    } else {
    347   1.1  christos 	        sys_halt();
    348   1.1  christos 	        mec_ersr |= 0x2000;
    349   1.1  christos 	        if (sis_verbose)
    350   1.1  christos 	            printf("Error manager halt - IU comparison error\n");
    351   1.1  christos 	    }
    352   1.1  christos 	} else
    353   1.1  christos 	    mec_irq(1);
    354   1.1  christos     }
    355   1.1  christos     if (mec_ersr & 0x20) {
    356   1.1  christos 	if (!(mec_mcr & 0x2000)) {
    357   1.1  christos 	    if (mec_mcr & 0x4000) {
    358   1.1  christos 	        sys_reset();
    359   1.1  christos 	        mec_ersr = 0x8000;
    360   1.1  christos 	        if (sis_verbose)
    361   1.1  christos 	            printf("Error manager reset - MEC hardware error\n");
    362   1.1  christos 	    } else {
    363   1.1  christos 	        sys_halt();
    364   1.1  christos 	        mec_ersr |= 0x2000;
    365   1.1  christos 	        if (sis_verbose)
    366   1.1  christos 	            printf("Error manager halt - MEC hardware error\n");
    367   1.1  christos 	    }
    368   1.1  christos 	} else
    369   1.1  christos 	    mec_irq(1);
    370   1.1  christos     }
    371   1.1  christos }
    372   1.1  christos 
    373   1.1  christos #ifdef ERRINJ
    374   1.1  christos static void
    375   1.1  christos iucomperr()
    376   1.1  christos {
    377   1.1  christos     mec_ersr |= 0x04;
    378   1.1  christos     decode_ersr();
    379   1.1  christos }
    380   1.1  christos #endif
    381   1.1  christos 
    382   1.1  christos static void
    383  1.10  christos mecparerror(void)
    384   1.1  christos {
    385   1.1  christos     mec_ersr |= 0x20;
    386   1.1  christos     decode_ersr();
    387   1.1  christos }
    388   1.1  christos 
    389   1.1  christos 
    390   1.1  christos /* IU error mode manager */
    391   1.1  christos 
    392   1.1  christos void
    393  1.10  christos error_mode(uint32_t pc)
    394   1.1  christos {
    395   1.1  christos 
    396   1.1  christos     mec_ersr |= 0x1;
    397   1.1  christos     decode_ersr();
    398   1.1  christos }
    399   1.1  christos 
    400   1.1  christos 
    401   1.1  christos /* Check memory settings */
    402   1.1  christos 
    403   1.1  christos static void
    404  1.10  christos decode_memcfg(void)
    405   1.1  christos {
    406   1.1  christos     if (rom8) mec_memcfg &= ~0x20000;
    407   1.1  christos     else mec_memcfg |= 0x20000;
    408   1.1  christos 
    409   1.1  christos     mem_ramsz = (256 * 1024) << ((mec_memcfg >> 10) & 7);
    410   1.1  christos     mem_romsz = (128 * 1024) << ((mec_memcfg >> 18) & 7);
    411   1.1  christos 
    412   1.1  christos     if (sparclite_board) {
    413   1.1  christos 	mem_ramstart = RAM_START_SLITE;
    414   1.1  christos 	mem_ramend = RAM_END_SLITE;
    415   1.1  christos 	mem_rammask = RAM_MASK_SLITE;
    416   1.1  christos     }
    417   1.1  christos     else {
    418   1.1  christos 	mem_ramstart = RAM_START;
    419   1.1  christos 	mem_ramend = RAM_END;
    420   1.1  christos 	mem_rammask = RAM_MASK;
    421   1.1  christos     }
    422   1.1  christos     if (sis_verbose)
    423   1.1  christos 	printf("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
    424   1.1  christos 	       mem_ramstart, mem_ramsz >> 10, mem_romsz >> 10);
    425   1.1  christos }
    426   1.1  christos 
    427   1.1  christos static void
    428  1.10  christos decode_wcr(void)
    429   1.1  christos {
    430   1.1  christos     mem_ramr_ws = mec_wcr & 3;
    431   1.1  christos     mem_ramw_ws = (mec_wcr >> 2) & 3;
    432   1.1  christos     mem_romr_ws = (mec_wcr >> 4) & 0x0f;
    433   1.1  christos     if (rom8) {
    434   1.1  christos     	if (mem_romr_ws > 0 )  mem_romr_ws--;
    435   1.1  christos 	mem_romr_ws = 5 + (4*mem_romr_ws);
    436   1.1  christos     }
    437   1.1  christos     mem_romw_ws = (mec_wcr >> 8) & 0x0f;
    438   1.1  christos     if (sis_verbose)
    439   1.1  christos 	printf("Waitstates = RAM read: %d, RAM write: %d, ROM read: %d, ROM write: %d\n",
    440   1.1  christos 	       mem_ramr_ws, mem_ramw_ws, mem_romr_ws, mem_romw_ws);
    441   1.1  christos }
    442   1.1  christos 
    443   1.1  christos static void
    444  1.10  christos decode_mcr(void)
    445   1.1  christos {
    446   1.1  christos     mem_accprot = (mec_wpr[0] | mec_wpr[1]);
    447   1.1  christos     mem_blockprot = (mec_mcr >> 3) & 1;
    448   1.1  christos     if (sis_verbose && mem_accprot)
    449   1.1  christos 	printf("Memory block write protection enabled\n");
    450   1.1  christos     if (mec_mcr & 0x08000) {
    451   1.1  christos 	mec_ersr |= 0x20;
    452   1.1  christos 	decode_ersr();
    453   1.1  christos     }
    454   1.1  christos     if (sis_verbose && (mec_mcr & 2))
    455   1.1  christos 	printf("Software reset enabled\n");
    456   1.1  christos     if (sis_verbose && (mec_mcr & 1))
    457   1.1  christos 	printf("Power-down mode enabled\n");
    458   1.1  christos }
    459   1.1  christos 
    460   1.1  christos /* Flush ports when simulator stops */
    461   1.1  christos 
    462   1.1  christos void
    463  1.10  christos sim_halt(void)
    464   1.1  christos {
    465   1.1  christos #ifdef FAST_UART
    466   1.1  christos     flush_uart();
    467   1.1  christos #endif
    468   1.1  christos }
    469   1.1  christos 
    470   1.1  christos int
    471   1.1  christos sim_stop(SIM_DESC sd)
    472   1.1  christos {
    473   1.1  christos   ctrl_c = 1;
    474   1.1  christos   return 1;
    475   1.1  christos }
    476   1.1  christos 
    477   1.1  christos static void
    478  1.10  christos close_port(void)
    479   1.1  christos {
    480   1.1  christos     if (f1open && f1in != stdin)
    481   1.1  christos 	fclose(f1in);
    482   1.1  christos     if (f2open && f2in != stdin)
    483   1.1  christos 	fclose(f2in);
    484   1.1  christos }
    485   1.1  christos 
    486   1.1  christos void
    487  1.10  christos exit_sim(void)
    488   1.1  christos {
    489   1.1  christos     close_port();
    490   1.1  christos }
    491   1.1  christos 
    492   1.1  christos static void
    493  1.10  christos mec_reset(void)
    494   1.1  christos {
    495   1.1  christos     int             i;
    496   1.1  christos 
    497   1.1  christos     find = 0;
    498   1.1  christos     for (i = 0; i < 2; i++)
    499   1.1  christos 	mec_ssa[i] = mec_sea[i] = mec_wpr[i] = 0;
    500   1.1  christos     mec_mcr = 0x01350014;
    501   1.1  christos     mec_iocr = 0;
    502   1.1  christos     mec_sfsr = 0x078;
    503   1.1  christos     mec_ffar = 0;
    504   1.1  christos     mec_ipr = 0;
    505   1.1  christos     mec_imr = 0x7ffe;
    506   1.1  christos     mec_isr = 0;
    507   1.1  christos     mec_icr = 0;
    508   1.1  christos     mec_ifr = 0;
    509   1.1  christos     mec_memcfg = 0x10000;
    510   1.1  christos     mec_wcr = -1;
    511   1.1  christos     mec_ersr = 0;		/* MEC error and status register */
    512   1.1  christos     mec_tcr = 0;		/* MEC test comtrol register */
    513   1.1  christos 
    514   1.1  christos     decode_memcfg();
    515   1.1  christos     decode_wcr();
    516   1.1  christos     decode_mcr();
    517   1.1  christos 
    518   1.1  christos     posted_irq = 0;
    519   1.1  christos     wnuma = wnumb = 0;
    520   1.1  christos     anum = aind = bnum = bind = 0;
    521   1.1  christos 
    522   1.1  christos     uart_stat_reg = UARTA_SRE | UARTA_HRE | UARTB_SRE | UARTB_HRE;
    523   1.1  christos     uarta_data = uartb_data = UART_THE | UART_TSE;
    524   1.1  christos 
    525   1.1  christos     rtc_counter = 0xffffffff;
    526   1.1  christos     rtc_reload = 0xffffffff;
    527   1.1  christos     rtc_scaler = 0xff;
    528   1.1  christos     rtc_enabled = 0;
    529   1.1  christos     rtc_cr = 0;
    530   1.1  christos     rtc_se = 0;
    531   1.1  christos 
    532   1.1  christos     gpt_counter = 0xffffffff;
    533   1.1  christos     gpt_reload = 0xffffffff;
    534   1.1  christos     gpt_scaler = 0xffff;
    535   1.1  christos     gpt_enabled = 0;
    536   1.1  christos     gpt_cr = 0;
    537   1.1  christos     gpt_se = 0;
    538   1.1  christos 
    539   1.1  christos     wdog_scaler = 255;
    540   1.1  christos     wdog_rst_delay = 255;
    541   1.1  christos     wdog_counter = 0xffff;
    542   1.1  christos     wdog_rston = 0;
    543   1.1  christos     wdog_status = init;
    544   1.1  christos 
    545   1.1  christos #ifdef ERA
    546   1.1  christos     erareg = 0;
    547   1.1  christos #endif
    548   1.1  christos 
    549   1.1  christos }
    550   1.1  christos 
    551   1.1  christos 
    552   1.1  christos 
    553   1.1  christos static void
    554  1.10  christos mec_intack(int32_t level)
    555   1.1  christos {
    556   1.1  christos     int             irq_test;
    557   1.1  christos 
    558   1.1  christos     if (sis_verbose)
    559   1.1  christos 	printf("interrupt %d acknowledged\n", level);
    560   1.1  christos     irq_test = mec_tcr & 0x80000;
    561   1.1  christos     if ((irq_test) && (mec_ifr & (1 << level)))
    562   1.1  christos 	mec_ifr &= ~(1 << level);
    563   1.1  christos     else
    564   1.1  christos 	mec_ipr &= ~(1 << level);
    565   1.1  christos    chk_irq();
    566   1.1  christos }
    567   1.1  christos 
    568   1.1  christos static void
    569  1.10  christos chk_irq(void)
    570   1.1  christos {
    571  1.10  christos     int32_t           i;
    572  1.10  christos     uint32_t          itmp;
    573   1.1  christos     int		    old_irl;
    574   1.1  christos 
    575   1.1  christos     old_irl = ext_irl;
    576   1.1  christos     if (mec_tcr & 0x80000) itmp = mec_ifr;
    577   1.1  christos     else itmp  = 0;
    578   1.1  christos     itmp = ((mec_ipr | itmp) & ~mec_imr) & 0x0fffe;
    579   1.1  christos     ext_irl = 0;
    580   1.1  christos     if (itmp != 0) {
    581   1.1  christos 	for (i = 15; i > 0; i--) {
    582   1.1  christos 	    if (((itmp >> i) & 1) != 0) {
    583   1.1  christos 		if ((sis_verbose) && (i > old_irl))
    584   1.1  christos 		    printf("IU irl: %d\n", i);
    585   1.1  christos 		ext_irl = i;
    586   1.1  christos 	        set_int(i, mec_intack, i);
    587   1.1  christos 		break;
    588   1.1  christos 	    }
    589   1.1  christos 	}
    590   1.1  christos     }
    591   1.1  christos }
    592   1.1  christos 
    593   1.1  christos static void
    594  1.10  christos mec_irq(int32_t level)
    595   1.1  christos {
    596   1.1  christos     mec_ipr |= (1 << level);
    597   1.1  christos     chk_irq();
    598   1.1  christos }
    599   1.1  christos 
    600   1.1  christos static void
    601  1.10  christos set_sfsr(uint32_t fault, uint32_t addr, uint32_t asi, uint32_t read)
    602   1.1  christos {
    603   1.1  christos     if ((asi == 0xa) || (asi == 0xb)) {
    604   1.1  christos 	mec_ffar = addr;
    605   1.1  christos 	mec_sfsr = (fault << 3) | (!read << 15);
    606   1.1  christos 	mec_sfsr |= ((mec_sfsr & 1) ^ 1) | (mec_sfsr & 1);
    607   1.1  christos 	switch (asi) {
    608   1.1  christos 	case 0xa:
    609   1.1  christos 	    mec_sfsr |= 0x0004;
    610   1.1  christos 	    break;
    611   1.1  christos 	case 0xb:
    612   1.1  christos 	    mec_sfsr |= 0x1004;
    613   1.1  christos 	    break;
    614   1.1  christos 	}
    615   1.1  christos     }
    616   1.1  christos }
    617   1.1  christos 
    618  1.10  christos static int32_t
    619  1.10  christos mec_read(uint32_t addr, uint32_t asi, uint32_t *data)
    620   1.1  christos {
    621   1.1  christos 
    622   1.1  christos     switch (addr & 0x0ff) {
    623   1.1  christos 
    624   1.1  christos     case MEC_MCR:		/* 0x00 */
    625   1.1  christos 	*data = mec_mcr;
    626   1.1  christos 	break;
    627   1.1  christos 
    628   1.1  christos     case MEC_MEMCFG:		/* 0x10 */
    629   1.1  christos 	*data = mec_memcfg;
    630   1.1  christos 	break;
    631   1.1  christos 
    632   1.1  christos     case MEC_IOCR:
    633   1.1  christos 	*data = mec_iocr;	/* 0x14 */
    634   1.1  christos 	break;
    635   1.1  christos 
    636   1.1  christos     case MEC_SSA1:		/* 0x20 */
    637   1.1  christos 	*data = mec_ssa[0] | (mec_wpr[0] << 23);
    638   1.1  christos 	break;
    639   1.1  christos     case MEC_SEA1:		/* 0x24 */
    640   1.1  christos 	*data = mec_sea[0];
    641   1.1  christos 	break;
    642   1.1  christos     case MEC_SSA2:		/* 0x28 */
    643   1.1  christos 	*data = mec_ssa[1] | (mec_wpr[1] << 23);
    644   1.1  christos 	break;
    645   1.1  christos     case MEC_SEA2:		/* 0x2c */
    646   1.1  christos 	*data = mec_sea[1];
    647   1.1  christos 	break;
    648   1.1  christos 
    649   1.1  christos     case MEC_ISR:		/* 0x44 */
    650   1.1  christos 	*data = mec_isr;
    651   1.1  christos 	break;
    652   1.1  christos 
    653   1.1  christos     case MEC_IPR:		/* 0x48 */
    654   1.1  christos 	*data = mec_ipr;
    655   1.1  christos 	break;
    656   1.1  christos 
    657   1.1  christos     case MEC_IMR:		/* 0x4c */
    658   1.1  christos 	*data = mec_imr;
    659   1.1  christos 	break;
    660   1.1  christos 
    661   1.1  christos     case MEC_IFR:		/* 0x54 */
    662   1.1  christos 	*data = mec_ifr;
    663   1.1  christos 	break;
    664   1.1  christos 
    665   1.1  christos     case MEC_RTC_COUNTER:	/* 0x80 */
    666   1.1  christos 	*data = rtc_counter_read();
    667   1.1  christos 	break;
    668   1.1  christos     case MEC_RTC_SCALER:	/* 0x84 */
    669   1.1  christos 	if (rtc_enabled)
    670   1.1  christos 	    *data = rtc_scaler - (now() - rtc_scaler_start);
    671   1.1  christos 	else
    672   1.1  christos 	    *data = rtc_scaler;
    673   1.1  christos 	break;
    674   1.1  christos 
    675   1.1  christos     case MEC_GPT_COUNTER:	/* 0x88 */
    676   1.1  christos 	*data = gpt_counter_read();
    677   1.1  christos 	break;
    678   1.1  christos 
    679   1.1  christos     case MEC_GPT_SCALER:	/* 0x8c */
    680   1.1  christos 	if (rtc_enabled)
    681   1.1  christos 	    *data = gpt_scaler - (now() - gpt_scaler_start);
    682   1.1  christos 	else
    683   1.1  christos 	    *data = gpt_scaler;
    684   1.1  christos 	break;
    685   1.1  christos 
    686   1.1  christos 
    687   1.1  christos     case MEC_SFSR:		/* 0xA0 */
    688   1.1  christos 	*data = mec_sfsr;
    689   1.1  christos 	break;
    690   1.1  christos 
    691   1.1  christos     case MEC_FFAR:		/* 0xA4 */
    692   1.1  christos 	*data = mec_ffar;
    693   1.1  christos 	break;
    694   1.1  christos 
    695   1.1  christos     case SIM_LOAD:
    696   1.1  christos 	fname[find] = 0;
    697   1.1  christos 	if (find == 0)
    698   1.1  christos 	    strcpy(fname, "simload");
    699   1.1  christos 	find = bfd_load(fname);
    700   1.1  christos  	if (find == -1)
    701   1.1  christos 	    *data = 0;
    702   1.1  christos 	else
    703   1.1  christos 	    *data = 1;
    704   1.1  christos 	find = 0;
    705   1.1  christos 	break;
    706   1.1  christos 
    707   1.1  christos     case MEC_ERSR:		/* 0xB0 */
    708   1.1  christos 	*data = mec_ersr;
    709   1.1  christos 	break;
    710   1.1  christos 
    711   1.1  christos     case MEC_TCR:		/* 0xD0 */
    712   1.1  christos 	*data = mec_tcr;
    713   1.1  christos 	break;
    714   1.1  christos 
    715   1.1  christos     case MEC_UARTA:		/* 0xE0 */
    716   1.1  christos     case MEC_UARTB:		/* 0xE4 */
    717   1.1  christos 	if (asi != 0xb) {
    718   1.1  christos 	    set_sfsr(MEC_ACC, addr, asi, 1);
    719   1.5  christos 	    return 1;
    720   1.1  christos 	}
    721   1.1  christos 	*data = read_uart(addr);
    722   1.1  christos 	break;
    723   1.1  christos 
    724   1.1  christos     case MEC_UART_CTRL:		/* 0xE8 */
    725   1.1  christos 
    726   1.1  christos 	*data = read_uart(addr);
    727   1.1  christos 	break;
    728   1.1  christos 
    729   1.5  christos     case 0xF4:		/* simulator RAM size in bytes */
    730   1.5  christos 	*data = 4096*1024;
    731   1.5  christos 	break;
    732   1.5  christos 
    733   1.5  christos     case 0xF8:		/* simulator ROM size in bytes */
    734   1.5  christos 	*data = 1024*1024;
    735   1.5  christos 	break;
    736   1.5  christos 
    737   1.1  christos     default:
    738   1.1  christos 	set_sfsr(MEC_ACC, addr, asi, 1);
    739   1.5  christos 	return 1;
    740   1.1  christos 	break;
    741   1.1  christos     }
    742   1.5  christos     return MOK;
    743   1.1  christos }
    744   1.1  christos 
    745   1.1  christos static int
    746  1.10  christos mec_write(uint32_t addr, uint32_t data)
    747   1.1  christos {
    748   1.1  christos     if (sis_verbose > 1)
    749   1.1  christos 	printf("MEC write a: %08x, d: %08x\n",addr,data);
    750   1.1  christos     switch (addr & 0x0ff) {
    751   1.1  christos 
    752   1.1  christos     case MEC_MCR:
    753   1.1  christos 	mec_mcr = data;
    754   1.1  christos 	decode_mcr();
    755   1.1  christos         if (mec_mcr & 0x08000) mecparerror();
    756   1.1  christos 	break;
    757   1.1  christos 
    758   1.1  christos     case MEC_SFR:
    759   1.1  christos 	if (mec_mcr & 0x2) {
    760   1.1  christos 	    sys_reset();
    761   1.1  christos 	    mec_ersr = 0x4000;
    762   1.1  christos     	    if (sis_verbose)
    763   1.1  christos 	    	printf(" Software reset issued\n");
    764   1.1  christos 	}
    765   1.1  christos 	break;
    766   1.1  christos 
    767   1.1  christos     case MEC_IOCR:
    768   1.1  christos 	mec_iocr = data;
    769   1.1  christos         if (mec_iocr & 0xC0C0C0C0) mecparerror();
    770   1.1  christos 	break;
    771   1.1  christos 
    772   1.1  christos     case MEC_SSA1:		/* 0x20 */
    773   1.1  christos         if (data & 0xFE000000) mecparerror();
    774   1.1  christos 	mec_ssa[0] = data & 0x7fffff;
    775   1.1  christos 	mec_wpr[0] = (data >> 23) & 0x03;
    776   1.1  christos 	mem_accprot = mec_wpr[0] || mec_wpr[1];
    777   1.1  christos 	if (sis_verbose && mec_wpr[0])
    778   1.1  christos 	    printf("Segment 1 memory protection enabled (0x02%06x - 0x02%06x)\n",
    779   1.1  christos 		   mec_ssa[0] << 2, mec_sea[0] << 2);
    780   1.1  christos 	break;
    781   1.1  christos     case MEC_SEA1:		/* 0x24 */
    782   1.1  christos         if (data & 0xFF800000) mecparerror();
    783   1.1  christos 	mec_sea[0] = data & 0x7fffff;
    784   1.1  christos 	break;
    785   1.1  christos     case MEC_SSA2:		/* 0x28 */
    786   1.1  christos         if (data & 0xFE000000) mecparerror();
    787   1.1  christos 	mec_ssa[1] = data & 0x7fffff;
    788   1.1  christos 	mec_wpr[1] = (data >> 23) & 0x03;
    789   1.1  christos 	mem_accprot = mec_wpr[0] || mec_wpr[1];
    790   1.1  christos 	if (sis_verbose && mec_wpr[1])
    791   1.1  christos 	    printf("Segment 2 memory protection enabled (0x02%06x - 0x02%06x)\n",
    792   1.1  christos 		   mec_ssa[1] << 2, mec_sea[1] << 2);
    793   1.1  christos 	break;
    794   1.1  christos     case MEC_SEA2:		/* 0x2c */
    795   1.1  christos         if (data & 0xFF800000) mecparerror();
    796   1.1  christos 	mec_sea[1] = data & 0x7fffff;
    797   1.1  christos 	break;
    798   1.1  christos 
    799   1.1  christos     case MEC_UARTA:
    800   1.1  christos     case MEC_UARTB:
    801   1.1  christos         if (data & 0xFFFFFF00) mecparerror();
    802  1.11  christos         ATTRIBUTE_FALLTHROUGH;
    803   1.1  christos     case MEC_UART_CTRL:
    804   1.1  christos         if (data & 0xFF00FF00) mecparerror();
    805   1.1  christos 	write_uart(addr, data);
    806   1.1  christos 	break;
    807   1.1  christos 
    808   1.1  christos     case MEC_GPT_RELOAD:
    809   1.1  christos 	gpt_reload_set(data);
    810   1.1  christos 	break;
    811   1.1  christos 
    812   1.1  christos     case MEC_GPT_SCALER:
    813   1.1  christos         if (data & 0xFFFF0000) mecparerror();
    814   1.1  christos 	gpt_scaler_set(data);
    815   1.1  christos 	break;
    816   1.1  christos 
    817   1.1  christos     case MEC_TIMER_CTRL:
    818   1.1  christos         if (data & 0xFFFFF0F0) mecparerror();
    819   1.1  christos 	timer_ctrl(data);
    820   1.1  christos 	break;
    821   1.1  christos 
    822   1.1  christos     case MEC_RTC_RELOAD:
    823   1.1  christos 	rtc_reload_set(data);
    824   1.1  christos 	break;
    825   1.1  christos 
    826   1.1  christos     case MEC_RTC_SCALER:
    827   1.1  christos         if (data & 0xFFFFFF00) mecparerror();
    828   1.1  christos 	rtc_scaler_set(data);
    829   1.1  christos 	break;
    830   1.1  christos 
    831   1.1  christos     case MEC_SFSR:		/* 0xA0 */
    832   1.1  christos         if (data & 0xFFFF0880) mecparerror();
    833   1.1  christos 	mec_sfsr = 0x78;
    834   1.1  christos 	break;
    835   1.1  christos 
    836   1.1  christos     case MEC_ISR:
    837   1.1  christos         if (data & 0xFFFFE000) mecparerror();
    838   1.1  christos 	mec_isr = data;
    839   1.1  christos 	break;
    840   1.1  christos 
    841   1.1  christos     case MEC_IMR:		/* 0x4c */
    842   1.1  christos 
    843   1.1  christos         if (data & 0xFFFF8001) mecparerror();
    844   1.1  christos 	mec_imr = data & 0x7ffe;
    845   1.1  christos 	chk_irq();
    846   1.1  christos 	break;
    847   1.1  christos 
    848   1.1  christos     case MEC_ICR:		/* 0x50 */
    849   1.1  christos 
    850   1.1  christos         if (data & 0xFFFF0001) mecparerror();
    851   1.1  christos 	mec_ipr &= ~data & 0x0fffe;
    852   1.1  christos 	chk_irq();
    853   1.1  christos 	break;
    854   1.1  christos 
    855   1.1  christos     case MEC_IFR:		/* 0x54 */
    856   1.1  christos 
    857   1.1  christos         if (mec_tcr & 0x080000) {
    858   1.1  christos             if (data & 0xFFFF0001) mecparerror();
    859   1.1  christos 	    mec_ifr = data & 0xfffe;
    860   1.1  christos 	    chk_irq();
    861   1.1  christos 	}
    862   1.1  christos 	break;
    863   1.1  christos     case SIM_LOAD:
    864   1.1  christos 	fname[find++] = (char) data;
    865   1.1  christos 	break;
    866   1.1  christos 
    867   1.1  christos 
    868   1.1  christos     case MEC_MEMCFG:		/* 0x10 */
    869   1.1  christos         if (data & 0xC0E08000) mecparerror();
    870   1.1  christos 	mec_memcfg = data;
    871   1.1  christos 	decode_memcfg();
    872   1.1  christos 	if (mec_memcfg & 0xc0e08000)
    873   1.1  christos 	    mecparerror();
    874   1.1  christos 	break;
    875   1.1  christos 
    876   1.1  christos     case MEC_WCR:		/* 0x18 */
    877   1.1  christos 	mec_wcr = data;
    878   1.1  christos 	decode_wcr();
    879   1.1  christos 	break;
    880   1.1  christos 
    881   1.1  christos     case MEC_ERSR:		/* 0xB0 */
    882   1.1  christos 	if (mec_tcr & 0x100000)
    883  1.10  christos 	  if (data & 0xFFFFEFC0) mecparerror();
    884   1.1  christos 	    mec_ersr = data & 0x103f;
    885   1.1  christos 	break;
    886   1.1  christos 
    887   1.1  christos     case MEC_TCR:		/* 0xD0 */
    888   1.1  christos         if (data & 0xFFE1FFC0) mecparerror();
    889   1.1  christos 	mec_tcr = data & 0x1e003f;
    890   1.1  christos 	break;
    891   1.1  christos 
    892   1.1  christos     case MEC_WDOG:		/* 0x60 */
    893   1.1  christos 	wdog_scaler = (data >> 16) & 0x0ff;
    894   1.1  christos 	wdog_counter = data & 0x0ffff;
    895   1.1  christos 	wdog_rst_delay = data >> 24;
    896   1.1  christos 	wdog_rston = 0;
    897   1.1  christos 	if (wdog_status == stopped)
    898   1.1  christos 	    wdog_start();
    899   1.1  christos 	wdog_status = enabled;
    900   1.1  christos 	break;
    901   1.1  christos 
    902   1.1  christos     case MEC_TRAPD:		/* 0x64 */
    903   1.1  christos 	if (wdog_status == init) {
    904   1.1  christos 	    wdog_status = disabled;
    905   1.1  christos 	    if (sis_verbose)
    906   1.1  christos 		printf("Watchdog disabled\n");
    907   1.1  christos 	}
    908   1.1  christos 	break;
    909   1.1  christos 
    910   1.1  christos     case MEC_PWDR:
    911   1.1  christos 	if (mec_mcr & 1)
    912   1.1  christos 	    wait_for_irq();
    913   1.1  christos 	break;
    914   1.1  christos 
    915   1.1  christos     default:
    916   1.1  christos 	set_sfsr(MEC_ACC, addr, 0xb, 0);
    917   1.5  christos 	return 1;
    918   1.1  christos 	break;
    919   1.1  christos     }
    920   1.5  christos     return MOK;
    921   1.1  christos }
    922   1.1  christos 
    923   1.1  christos 
    924   1.1  christos /* MEC UARTS */
    925   1.1  christos 
    926   1.1  christos static int      ifd1 = -1, ifd2 = -1, ofd1 = -1, ofd2 = -1;
    927   1.1  christos 
    928   1.1  christos void
    929  1.10  christos init_stdio(void)
    930   1.1  christos {
    931   1.1  christos     if (dumbio)
    932   1.1  christos         return; /* do nothing */
    933  1.10  christos #ifdef HAVE_TERMIOS_H
    934   1.1  christos     if (!ifd1)
    935   1.1  christos 	tcsetattr(0, TCSANOW, &ioc1);
    936   1.1  christos     if (!ifd2)
    937   1.1  christos 	tcsetattr(0, TCSANOW, &ioc2);
    938  1.10  christos #endif
    939   1.1  christos }
    940   1.1  christos 
    941   1.1  christos void
    942  1.10  christos restore_stdio(void)
    943   1.1  christos {
    944   1.1  christos     if (dumbio)
    945   1.1  christos         return; /* do nothing */
    946  1.10  christos #ifdef HAVE_TERMIOS_H
    947   1.1  christos     if (!ifd1)
    948   1.1  christos 	tcsetattr(0, TCSANOW, &iocold1);
    949   1.1  christos     if (!ifd2)
    950   1.1  christos 	tcsetattr(0, TCSANOW, &iocold2);
    951  1.10  christos #endif
    952   1.1  christos }
    953   1.1  christos 
    954   1.1  christos #define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
    955   1.1  christos              ( dumbio                                \
    956   1.1  christos                ? (0) /* no bytes read, no delay */   \
    957   1.1  christos                : read( _fd_, _buf_, _len_ ) )
    958   1.1  christos 
    959   1.1  christos 
    960   1.1  christos static void
    961  1.10  christos port_init(void)
    962   1.1  christos {
    963   1.1  christos 
    964   1.1  christos     if (uben) {
    965   1.1  christos     f2in = stdin;
    966   1.1  christos     f1in = NULL;
    967   1.1  christos     f2out = stdout;
    968   1.1  christos     f1out = NULL;
    969   1.1  christos     } else {
    970   1.1  christos     f1in = stdin;
    971   1.1  christos     f2in = NULL;
    972   1.1  christos     f1out = stdout;
    973   1.1  christos     f2out = NULL;
    974   1.1  christos     }
    975  1.10  christos     if (uart_dev1[0] != 0) {
    976   1.1  christos 	if ((fd1 = open(uart_dev1, O_RDWR | O_NONBLOCK)) < 0) {
    977   1.1  christos 	    printf("Warning, couldn't open output device %s\n", uart_dev1);
    978   1.1  christos 	} else {
    979   1.1  christos 	    if (sis_verbose)
    980   1.1  christos 		printf("serial port A on %s\n", uart_dev1);
    981   1.1  christos 	    f1in = f1out = fdopen(fd1, "r+");
    982   1.1  christos 	    setbuf(f1out, NULL);
    983   1.1  christos 	    f1open = 1;
    984   1.1  christos 	}
    985  1.10  christos     }
    986   1.1  christos     if (f1in) ifd1 = fileno(f1in);
    987   1.1  christos     if (ifd1 == 0) {
    988   1.1  christos 	if (sis_verbose)
    989   1.1  christos 	    printf("serial port A on stdin/stdout\n");
    990   1.1  christos         if (!dumbio) {
    991  1.10  christos #ifdef HAVE_TERMIOS_H
    992   1.1  christos             tcgetattr(ifd1, &ioc1);
    993   1.1  christos             iocold1 = ioc1;
    994   1.1  christos             ioc1.c_lflag &= ~(ICANON | ECHO);
    995   1.1  christos             ioc1.c_cc[VMIN] = 0;
    996   1.1  christos             ioc1.c_cc[VTIME] = 0;
    997  1.10  christos #endif
    998   1.1  christos         }
    999   1.1  christos 	f1open = 1;
   1000   1.1  christos     }
   1001   1.1  christos 
   1002   1.1  christos     if (f1out) {
   1003   1.1  christos 	ofd1 = fileno(f1out);
   1004   1.1  christos     	if (!dumbio && ofd1 == 1) setbuf(f1out, NULL);
   1005   1.1  christos     }
   1006   1.1  christos 
   1007  1.10  christos     if (uart_dev2[0] != 0) {
   1008   1.1  christos 	if ((fd2 = open(uart_dev2, O_RDWR | O_NONBLOCK)) < 0) {
   1009   1.1  christos 	    printf("Warning, couldn't open output device %s\n", uart_dev2);
   1010   1.1  christos 	} else {
   1011   1.1  christos 	    if (sis_verbose)
   1012   1.1  christos 		printf("serial port B on %s\n", uart_dev2);
   1013   1.1  christos 	    f2in = f2out = fdopen(fd2, "r+");
   1014   1.1  christos 	    setbuf(f2out, NULL);
   1015   1.1  christos 	    f2open = 1;
   1016   1.1  christos 	}
   1017  1.10  christos     }
   1018   1.1  christos     if (f2in)  ifd2 = fileno(f2in);
   1019   1.1  christos     if (ifd2 == 0) {
   1020   1.1  christos 	if (sis_verbose)
   1021   1.1  christos 	    printf("serial port B on stdin/stdout\n");
   1022   1.1  christos         if (!dumbio) {
   1023  1.10  christos #ifdef HAVE_TERMIOS_H
   1024   1.1  christos             tcgetattr(ifd2, &ioc2);
   1025   1.1  christos             iocold2 = ioc2;
   1026   1.1  christos             ioc2.c_lflag &= ~(ICANON | ECHO);
   1027   1.1  christos             ioc2.c_cc[VMIN] = 0;
   1028   1.1  christos             ioc2.c_cc[VTIME] = 0;
   1029  1.10  christos #endif
   1030   1.1  christos         }
   1031   1.1  christos 	f2open = 1;
   1032   1.1  christos     }
   1033   1.1  christos 
   1034   1.1  christos     if (f2out) {
   1035   1.1  christos 	ofd2 = fileno(f2out);
   1036   1.1  christos         if (!dumbio && ofd2 == 1) setbuf(f2out, NULL);
   1037   1.1  christos     }
   1038   1.1  christos 
   1039   1.1  christos     wnuma = wnumb = 0;
   1040   1.1  christos 
   1041   1.1  christos }
   1042   1.1  christos 
   1043  1.10  christos static uint32_t
   1044  1.10  christos read_uart(uint32_t addr)
   1045   1.1  christos {
   1046   1.1  christos     switch (addr & 0xff) {
   1047   1.1  christos 
   1048   1.1  christos     case 0xE0:			/* UART 1 */
   1049   1.1  christos #ifndef _WIN32
   1050   1.1  christos #ifdef FAST_UART
   1051   1.1  christos 
   1052   1.1  christos 	if (aind < anum) {
   1053   1.1  christos 	    if ((aind + 1) < anum)
   1054   1.1  christos 		mec_irq(4);
   1055  1.10  christos 	    return (0x700 | (uint32_t) aq[aind++]);
   1056   1.1  christos 	} else {
   1057   1.1  christos 	    if (f1open) {
   1058   1.1  christos 	        anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
   1059   1.1  christos 	    }
   1060   1.1  christos 	    if (anum > 0) {
   1061   1.1  christos 		aind = 0;
   1062   1.1  christos 		if ((aind + 1) < anum)
   1063   1.1  christos 		    mec_irq(4);
   1064  1.10  christos 		return (0x700 | (uint32_t) aq[aind++]);
   1065   1.1  christos 	    } else {
   1066  1.10  christos 		return (0x600 | (uint32_t) aq[aind]);
   1067   1.1  christos 	    }
   1068   1.1  christos 
   1069   1.1  christos 	}
   1070   1.1  christos #else
   1071  1.11  christos 	unsigned tmp = uarta_data;
   1072   1.1  christos 	uarta_data &= ~UART_DR;
   1073   1.1  christos 	uart_stat_reg &= ~UARTA_DR;
   1074   1.1  christos 	return tmp;
   1075   1.1  christos #endif
   1076   1.1  christos #else
   1077   1.5  christos 	return 0;
   1078   1.1  christos #endif
   1079   1.1  christos 	break;
   1080   1.1  christos 
   1081   1.1  christos     case 0xE4:			/* UART 2 */
   1082   1.1  christos #ifndef _WIN32
   1083   1.1  christos #ifdef FAST_UART
   1084   1.1  christos 	if (bind < bnum) {
   1085   1.1  christos 	    if ((bind + 1) < bnum)
   1086   1.1  christos 		mec_irq(5);
   1087  1.10  christos 	    return (0x700 | (uint32_t) bq[bind++]);
   1088   1.1  christos 	} else {
   1089   1.1  christos 	    if (f2open) {
   1090   1.1  christos 		bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
   1091   1.1  christos 	    }
   1092   1.1  christos 	    if (bnum > 0) {
   1093   1.1  christos 		bind = 0;
   1094   1.1  christos 		if ((bind + 1) < bnum)
   1095   1.1  christos 		    mec_irq(5);
   1096  1.10  christos 		return (0x700 | (uint32_t) bq[bind++]);
   1097   1.1  christos 	    } else {
   1098  1.10  christos 		return (0x600 | (uint32_t) bq[bind]);
   1099   1.1  christos 	    }
   1100   1.1  christos 
   1101   1.1  christos 	}
   1102   1.1  christos #else
   1103  1.11  christos 	unsigned tmp = uartb_data;
   1104   1.1  christos 	uartb_data &= ~UART_DR;
   1105   1.1  christos 	uart_stat_reg &= ~UARTB_DR;
   1106   1.1  christos 	return tmp;
   1107   1.1  christos #endif
   1108   1.1  christos #else
   1109   1.5  christos 	return 0;
   1110   1.1  christos #endif
   1111   1.1  christos 	break;
   1112   1.1  christos 
   1113   1.1  christos     case 0xE8:			/* UART status register	 */
   1114   1.1  christos #ifndef _WIN32
   1115   1.1  christos #ifdef FAST_UART
   1116   1.1  christos 
   1117   1.1  christos 	Ucontrol = 0;
   1118   1.1  christos 	if (aind < anum) {
   1119   1.1  christos 	    Ucontrol |= 0x00000001;
   1120   1.1  christos 	} else {
   1121   1.1  christos 	    if (f1open) {
   1122   1.1  christos 	        anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
   1123   1.1  christos             }
   1124   1.1  christos 	    if (anum > 0) {
   1125   1.1  christos 		Ucontrol |= 0x00000001;
   1126   1.1  christos 		aind = 0;
   1127   1.1  christos 		mec_irq(4);
   1128   1.1  christos 	    }
   1129   1.1  christos 	}
   1130   1.1  christos 	if (bind < bnum) {
   1131   1.1  christos 	    Ucontrol |= 0x00010000;
   1132   1.1  christos 	} else {
   1133   1.1  christos 	    if (f2open) {
   1134   1.1  christos 		bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
   1135   1.1  christos 	    }
   1136   1.1  christos 	    if (bnum > 0) {
   1137   1.1  christos 		Ucontrol |= 0x00010000;
   1138   1.1  christos 		bind = 0;
   1139   1.1  christos 		mec_irq(5);
   1140   1.1  christos 	    }
   1141   1.1  christos 	}
   1142   1.1  christos 
   1143   1.1  christos 	Ucontrol |= 0x00060006;
   1144   1.5  christos 	return Ucontrol;
   1145   1.1  christos #else
   1146   1.5  christos 	return uart_stat_reg;
   1147   1.1  christos #endif
   1148   1.1  christos #else
   1149   1.5  christos 	return 0x00060006;
   1150   1.1  christos #endif
   1151   1.1  christos 	break;
   1152   1.1  christos     default:
   1153   1.1  christos 	if (sis_verbose)
   1154   1.1  christos 	    printf("Read from unimplemented MEC register (%x)\n", addr);
   1155   1.1  christos 
   1156   1.1  christos     }
   1157   1.5  christos     return 0;
   1158   1.1  christos }
   1159   1.1  christos 
   1160   1.1  christos static void
   1161  1.10  christos write_uart(uint32_t addr, uint32_t data)
   1162   1.1  christos {
   1163   1.1  christos     unsigned char   c;
   1164   1.1  christos 
   1165   1.1  christos     c = (unsigned char) data;
   1166   1.1  christos     switch (addr & 0xff) {
   1167   1.1  christos 
   1168   1.1  christos     case 0xE0:			/* UART A */
   1169   1.1  christos #ifdef FAST_UART
   1170   1.1  christos 	if (f1open) {
   1171   1.1  christos 	    if (wnuma < UARTBUF)
   1172   1.1  christos 	        wbufa[wnuma++] = c;
   1173   1.1  christos 	    else {
   1174   1.1  christos 	        while (wnuma)
   1175   1.1  christos 		    wnuma -= fwrite(wbufa, 1, wnuma, f1out);
   1176   1.1  christos 	        wbufa[wnuma++] = c;
   1177   1.1  christos 	    }
   1178   1.1  christos 	}
   1179   1.1  christos 	mec_irq(4);
   1180   1.1  christos #else
   1181   1.1  christos 	if (uart_stat_reg & UARTA_SRE) {
   1182   1.1  christos 	    uarta_sreg = c;
   1183   1.1  christos 	    uart_stat_reg &= ~UARTA_SRE;
   1184   1.1  christos 	    event(uarta_tx, 0, UART_TX_TIME);
   1185   1.1  christos 	} else {
   1186   1.1  christos 	    uarta_hreg = c;
   1187   1.1  christos 	    uart_stat_reg &= ~UARTA_HRE;
   1188   1.1  christos 	}
   1189   1.1  christos #endif
   1190   1.1  christos 	break;
   1191   1.1  christos 
   1192   1.1  christos     case 0xE4:			/* UART B */
   1193   1.1  christos #ifdef FAST_UART
   1194   1.1  christos 	if (f2open) {
   1195   1.1  christos 	    if (wnumb < UARTBUF)
   1196   1.1  christos 		wbufb[wnumb++] = c;
   1197   1.1  christos 	    else {
   1198   1.1  christos 		while (wnumb)
   1199   1.1  christos 		    wnumb -= fwrite(wbufb, 1, wnumb, f2out);
   1200   1.1  christos 		wbufb[wnumb++] = c;
   1201   1.1  christos 	    }
   1202   1.1  christos 	}
   1203   1.1  christos 	mec_irq(5);
   1204   1.1  christos #else
   1205   1.1  christos 	if (uart_stat_reg & UARTB_SRE) {
   1206   1.1  christos 	    uartb_sreg = c;
   1207   1.1  christos 	    uart_stat_reg &= ~UARTB_SRE;
   1208   1.1  christos 	    event(uartb_tx, 0, UART_TX_TIME);
   1209   1.1  christos 	} else {
   1210   1.1  christos 	    uartb_hreg = c;
   1211   1.1  christos 	    uart_stat_reg &= ~UARTB_HRE;
   1212   1.1  christos 	}
   1213   1.1  christos #endif
   1214   1.1  christos 	break;
   1215   1.1  christos     case 0xE8:			/* UART status register */
   1216   1.1  christos #ifndef FAST_UART
   1217   1.1  christos 	if (data & UARTA_CLR) {
   1218   1.1  christos 	    uart_stat_reg &= 0xFFFF0000;
   1219   1.1  christos 	    uart_stat_reg |= UARTA_SRE | UARTA_HRE;
   1220   1.1  christos 	}
   1221   1.1  christos 	if (data & UARTB_CLR) {
   1222   1.1  christos 	    uart_stat_reg &= 0x0000FFFF;
   1223   1.1  christos 	    uart_stat_reg |= UARTB_SRE | UARTB_HRE;
   1224   1.1  christos 	}
   1225   1.1  christos #endif
   1226   1.1  christos 	break;
   1227   1.1  christos     default:
   1228   1.1  christos 	if (sis_verbose)
   1229   1.1  christos 	    printf("Write to unimplemented MEC register (%x)\n", addr);
   1230   1.1  christos 
   1231   1.1  christos     }
   1232   1.1  christos }
   1233   1.1  christos 
   1234   1.1  christos static void
   1235  1.10  christos flush_uart(void)
   1236   1.1  christos {
   1237   1.1  christos     while (wnuma && f1open)
   1238   1.1  christos 	wnuma -= fwrite(wbufa, 1, wnuma, f1out);
   1239   1.1  christos     while (wnumb && f2open)
   1240   1.1  christos 	wnumb -= fwrite(wbufb, 1, wnumb, f2out);
   1241   1.1  christos }
   1242   1.1  christos 
   1243  1.10  christos ATTRIBUTE_UNUSED
   1244   1.1  christos static void
   1245  1.10  christos uarta_tx(int32_t arg ATTRIBUTE_UNUSED)
   1246   1.1  christos {
   1247   1.1  christos 
   1248   1.1  christos     while (f1open && fwrite(&uarta_sreg, 1, 1, f1out) != 1);
   1249   1.1  christos     if (uart_stat_reg & UARTA_HRE) {
   1250   1.1  christos 	uart_stat_reg |= UARTA_SRE;
   1251   1.1  christos     } else {
   1252   1.1  christos 	uarta_sreg = uarta_hreg;
   1253   1.1  christos 	uart_stat_reg |= UARTA_HRE;
   1254   1.1  christos 	event(uarta_tx, 0, UART_TX_TIME);
   1255   1.1  christos     }
   1256   1.1  christos     mec_irq(4);
   1257   1.1  christos }
   1258   1.1  christos 
   1259  1.10  christos ATTRIBUTE_UNUSED
   1260   1.1  christos static void
   1261  1.10  christos uartb_tx(int32_t arg ATTRIBUTE_UNUSED)
   1262   1.1  christos {
   1263   1.1  christos     while (f2open && fwrite(&uartb_sreg, 1, 1, f2out) != 1);
   1264   1.1  christos     if (uart_stat_reg & UARTB_HRE) {
   1265   1.1  christos 	uart_stat_reg |= UARTB_SRE;
   1266   1.1  christos     } else {
   1267   1.1  christos 	uartb_sreg = uartb_hreg;
   1268   1.1  christos 	uart_stat_reg |= UARTB_HRE;
   1269   1.1  christos 	event(uartb_tx, 0, UART_TX_TIME);
   1270   1.1  christos     }
   1271   1.1  christos     mec_irq(5);
   1272   1.1  christos }
   1273   1.1  christos 
   1274  1.10  christos ATTRIBUTE_UNUSED
   1275   1.1  christos static void
   1276  1.10  christos uart_rx(int32_t arg ATTRIBUTE_UNUSED)
   1277   1.1  christos {
   1278  1.10  christos     int32_t           rsize;
   1279   1.1  christos     char            rxd;
   1280   1.1  christos 
   1281   1.1  christos 
   1282   1.1  christos     rsize = 0;
   1283   1.1  christos     if (f1open)
   1284   1.1  christos         rsize = DO_STDIO_READ(ifd1, &rxd, 1);
   1285   1.1  christos     if (rsize > 0) {
   1286   1.1  christos 	uarta_data = UART_DR | rxd;
   1287   1.1  christos 	if (uart_stat_reg & UARTA_HRE)
   1288   1.1  christos 	    uarta_data |= UART_THE;
   1289   1.1  christos 	if (uart_stat_reg & UARTA_SRE)
   1290   1.1  christos 	    uarta_data |= UART_TSE;
   1291   1.1  christos 	if (uart_stat_reg & UARTA_DR) {
   1292   1.1  christos 	    uart_stat_reg |= UARTA_OR;
   1293   1.1  christos 	    mec_irq(7);		/* UART error interrupt */
   1294   1.1  christos 	}
   1295   1.1  christos 	uart_stat_reg |= UARTA_DR;
   1296   1.1  christos 	mec_irq(4);
   1297   1.1  christos     }
   1298   1.1  christos     rsize = 0;
   1299   1.1  christos     if (f2open)
   1300   1.1  christos         rsize = DO_STDIO_READ(ifd2, &rxd, 1);
   1301   1.1  christos     if (rsize) {
   1302   1.1  christos 	uartb_data = UART_DR | rxd;
   1303   1.1  christos 	if (uart_stat_reg & UARTB_HRE)
   1304   1.1  christos 	    uartb_data |= UART_THE;
   1305   1.1  christos 	if (uart_stat_reg & UARTB_SRE)
   1306   1.1  christos 	    uartb_data |= UART_TSE;
   1307   1.1  christos 	if (uart_stat_reg & UARTB_DR) {
   1308   1.1  christos 	    uart_stat_reg |= UARTB_OR;
   1309   1.1  christos 	    mec_irq(7);		/* UART error interrupt */
   1310   1.1  christos 	}
   1311   1.1  christos 	uart_stat_reg |= UARTB_DR;
   1312   1.1  christos 	mec_irq(5);
   1313   1.1  christos     }
   1314   1.1  christos     event(uart_rx, 0, UART_RX_TIME);
   1315   1.1  christos }
   1316   1.1  christos 
   1317   1.1  christos static void
   1318  1.10  christos uart_intr(int32_t arg ATTRIBUTE_UNUSED)
   1319   1.1  christos {
   1320   1.1  christos     read_uart(0xE8);		/* Check for UART interrupts every 1000 clk */
   1321   1.1  christos     flush_uart();		/* Flush UART ports      */
   1322   1.1  christos     event(uart_intr, 0, UART_FLUSH_TIME);
   1323   1.1  christos }
   1324   1.1  christos 
   1325   1.1  christos 
   1326   1.1  christos static void
   1327  1.10  christos uart_irq_start(void)
   1328   1.1  christos {
   1329   1.1  christos #ifdef FAST_UART
   1330   1.1  christos     event(uart_intr, 0, UART_FLUSH_TIME);
   1331   1.1  christos #else
   1332   1.1  christos #ifndef _WIN32
   1333   1.1  christos     event(uart_rx, 0, UART_RX_TIME);
   1334   1.1  christos #endif
   1335   1.1  christos #endif
   1336   1.1  christos }
   1337   1.1  christos 
   1338   1.1  christos /* Watch-dog */
   1339   1.1  christos 
   1340   1.1  christos static void
   1341  1.10  christos wdog_intr(int32_t arg ATTRIBUTE_UNUSED)
   1342   1.1  christos {
   1343   1.1  christos     if (wdog_status == disabled) {
   1344   1.1  christos 	wdog_status = stopped;
   1345   1.1  christos     } else {
   1346   1.1  christos 
   1347   1.1  christos 	if (wdog_counter) {
   1348   1.1  christos 	    wdog_counter--;
   1349   1.1  christos 	    event(wdog_intr, 0, wdog_scaler + 1);
   1350   1.1  christos 	} else {
   1351   1.1  christos 	    if (wdog_rston) {
   1352   1.1  christos 		printf("Watchdog reset!\n");
   1353   1.1  christos 		sys_reset();
   1354   1.1  christos 		mec_ersr = 0xC000;
   1355   1.1  christos 	    } else {
   1356   1.1  christos 		mec_irq(15);
   1357   1.1  christos 		wdog_rston = 1;
   1358   1.1  christos 		wdog_counter = wdog_rst_delay;
   1359   1.1  christos 		event(wdog_intr, 0, wdog_scaler + 1);
   1360   1.1  christos 	    }
   1361   1.1  christos 	}
   1362   1.1  christos     }
   1363   1.1  christos }
   1364   1.1  christos 
   1365   1.1  christos static void
   1366  1.10  christos wdog_start(void)
   1367   1.1  christos {
   1368   1.1  christos     event(wdog_intr, 0, wdog_scaler + 1);
   1369   1.1  christos     if (sis_verbose)
   1370   1.1  christos 	printf("Watchdog started, scaler = %d, counter = %d\n",
   1371   1.1  christos 	       wdog_scaler, wdog_counter);
   1372   1.1  christos }
   1373   1.1  christos 
   1374   1.1  christos 
   1375   1.1  christos /* MEC timers */
   1376   1.1  christos 
   1377   1.1  christos 
   1378   1.1  christos static void
   1379  1.10  christos rtc_intr(int32_t arg ATTRIBUTE_UNUSED)
   1380   1.1  christos {
   1381   1.1  christos     if (rtc_counter == 0) {
   1382   1.1  christos 
   1383   1.1  christos 	mec_irq(13);
   1384   1.1  christos 	if (rtc_cr)
   1385   1.1  christos 	    rtc_counter = rtc_reload;
   1386   1.1  christos 	else
   1387   1.1  christos 	    rtc_se = 0;
   1388   1.1  christos     } else
   1389   1.1  christos 	rtc_counter -= 1;
   1390   1.1  christos     if (rtc_se) {
   1391   1.1  christos 	event(rtc_intr, 0, rtc_scaler + 1);
   1392   1.1  christos 	rtc_scaler_start = now();
   1393   1.1  christos 	rtc_enabled = 1;
   1394   1.1  christos     } else {
   1395   1.1  christos 	if (sis_verbose)
   1396   1.1  christos 	    printf("RTC stopped\n\r");
   1397   1.1  christos 	rtc_enabled = 0;
   1398   1.1  christos     }
   1399   1.1  christos }
   1400   1.1  christos 
   1401   1.1  christos static void
   1402  1.10  christos rtc_start(void)
   1403   1.1  christos {
   1404   1.1  christos     if (sis_verbose)
   1405   1.1  christos 	printf("RTC started (period %d)\n\r", rtc_scaler + 1);
   1406   1.1  christos     event(rtc_intr, 0, rtc_scaler + 1);
   1407   1.1  christos     rtc_scaler_start = now();
   1408   1.1  christos     rtc_enabled = 1;
   1409   1.1  christos }
   1410   1.1  christos 
   1411  1.10  christos static uint32_t
   1412  1.10  christos rtc_counter_read(void)
   1413   1.1  christos {
   1414   1.5  christos     return rtc_counter;
   1415   1.1  christos }
   1416   1.1  christos 
   1417   1.1  christos static void
   1418  1.10  christos rtc_scaler_set(uint32_t val)
   1419   1.1  christos {
   1420   1.1  christos     rtc_scaler = val & 0x0ff;	/* eight-bit scaler only */
   1421   1.1  christos }
   1422   1.1  christos 
   1423   1.1  christos static void
   1424  1.10  christos rtc_reload_set(uint32_t val)
   1425   1.1  christos {
   1426   1.1  christos     rtc_reload = val;
   1427   1.1  christos }
   1428   1.1  christos 
   1429   1.1  christos static void
   1430  1.10  christos gpt_intr(int32_t arg ATTRIBUTE_UNUSED)
   1431   1.1  christos {
   1432   1.1  christos     if (gpt_counter == 0) {
   1433   1.1  christos 	mec_irq(12);
   1434   1.1  christos 	if (gpt_cr)
   1435   1.1  christos 	    gpt_counter = gpt_reload;
   1436   1.1  christos 	else
   1437   1.1  christos 	    gpt_se = 0;
   1438   1.1  christos     } else
   1439   1.1  christos 	gpt_counter -= 1;
   1440   1.1  christos     if (gpt_se) {
   1441   1.1  christos 	event(gpt_intr, 0, gpt_scaler + 1);
   1442   1.1  christos 	gpt_scaler_start = now();
   1443   1.1  christos 	gpt_enabled = 1;
   1444   1.1  christos     } else {
   1445   1.1  christos 	if (sis_verbose)
   1446   1.1  christos 	    printf("GPT stopped\n\r");
   1447   1.1  christos 	gpt_enabled = 0;
   1448   1.1  christos     }
   1449   1.1  christos }
   1450   1.1  christos 
   1451   1.1  christos static void
   1452  1.10  christos gpt_start(void)
   1453   1.1  christos {
   1454   1.1  christos     if (sis_verbose)
   1455   1.1  christos 	printf("GPT started (period %d)\n\r", gpt_scaler + 1);
   1456   1.1  christos     event(gpt_intr, 0, gpt_scaler + 1);
   1457   1.1  christos     gpt_scaler_start = now();
   1458   1.1  christos     gpt_enabled = 1;
   1459   1.1  christos }
   1460   1.1  christos 
   1461  1.10  christos static uint32_t
   1462  1.10  christos gpt_counter_read(void)
   1463   1.1  christos {
   1464   1.5  christos     return gpt_counter;
   1465   1.1  christos }
   1466   1.1  christos 
   1467   1.1  christos static void
   1468  1.10  christos gpt_scaler_set(uint32_t val)
   1469   1.1  christos {
   1470   1.1  christos     gpt_scaler = val & 0x0ffff;	/* 16-bit scaler */
   1471   1.1  christos }
   1472   1.1  christos 
   1473   1.1  christos static void
   1474  1.10  christos gpt_reload_set(uint32_t val)
   1475   1.1  christos {
   1476   1.1  christos     gpt_reload = val;
   1477   1.1  christos }
   1478   1.1  christos 
   1479   1.1  christos static void
   1480  1.10  christos timer_ctrl(uint32_t val)
   1481   1.1  christos {
   1482   1.1  christos 
   1483   1.1  christos     rtc_cr = ((val & TCR_TCRCR) != 0);
   1484   1.1  christos     if (val & TCR_TCRCL) {
   1485   1.1  christos 	rtc_counter = rtc_reload;
   1486   1.1  christos     }
   1487   1.1  christos     if (val & TCR_TCRSL) {
   1488   1.1  christos     }
   1489   1.1  christos     rtc_se = ((val & TCR_TCRSE) != 0);
   1490   1.1  christos     if (rtc_se && (rtc_enabled == 0))
   1491   1.1  christos 	rtc_start();
   1492   1.1  christos 
   1493   1.1  christos     gpt_cr = (val & TCR_GACR);
   1494   1.1  christos     if (val & TCR_GACL) {
   1495   1.1  christos 	gpt_counter = gpt_reload;
   1496   1.1  christos     }
   1497   1.1  christos     if (val & TCR_GACL) {
   1498   1.1  christos     }
   1499   1.1  christos     gpt_se = (val & TCR_GASE) >> 2;
   1500   1.1  christos     if (gpt_se && (gpt_enabled == 0))
   1501   1.1  christos 	gpt_start();
   1502   1.1  christos }
   1503   1.1  christos 
   1504   1.5  christos /* Store data in host byte order.  MEM points to the beginning of the
   1505   1.5  christos    emulated memory; WADDR contains the index the emulated memory,
   1506   1.5  christos    DATA points to words in host byte order to be stored.  SZ contains log(2)
   1507   1.5  christos    of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word),
   1508   1.5  christos    2 (one word), or 3 (two words); WS should return the number of
   1509   1.5  christos    wait-states.  */
   1510   1.1  christos 
   1511   1.5  christos static void
   1512  1.10  christos store_bytes (unsigned char *mem, uint32_t waddr, uint32_t *data, int32_t sz,
   1513  1.10  christos 	     int32_t *ws)
   1514   1.5  christos {
   1515   1.5  christos     switch (sz) {
   1516   1.5  christos 	case 0:
   1517   1.5  christos 	    waddr ^= EBT;
   1518   1.5  christos 	    mem[waddr] = *data & 0x0ff;
   1519   1.5  christos 	    *ws = mem_ramw_ws + 3;
   1520   1.1  christos 	    break;
   1521   1.1  christos 	case 1:
   1522   1.5  christos #ifdef HOST_LITTLE_ENDIAN
   1523   1.5  christos 	    waddr ^= 2;
   1524   1.5  christos #endif
   1525   1.5  christos 	    memcpy (&mem[waddr], data, 2);
   1526   1.5  christos 	    *ws = mem_ramw_ws + 3;
   1527   1.1  christos 	    break;
   1528   1.5  christos 	case 2:
   1529   1.5  christos 	    memcpy (&mem[waddr], data, 4);
   1530   1.5  christos 	    *ws = mem_ramw_ws;
   1531   1.1  christos 	    break;
   1532   1.1  christos 	case 3:
   1533   1.5  christos 	    memcpy (&mem[waddr], data, 8);
   1534   1.5  christos 	    *ws = 2 * mem_ramw_ws + STD_WS;
   1535   1.1  christos 	    break;
   1536   1.1  christos     }
   1537   1.1  christos }
   1538   1.1  christos 
   1539   1.1  christos 
   1540   1.5  christos /* Memory emulation */
   1541   1.1  christos 
   1542   1.5  christos int
   1543  1.10  christos memory_iread (uint32_t addr, uint32_t *data, uint32_t *ws)
   1544   1.1  christos {
   1545  1.10  christos     uint32_t          asi;
   1546   1.5  christos     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
   1547   1.5  christos 	memcpy (data, &ramb[addr & mem_rammask & ~3], 4);
   1548   1.5  christos 	*ws = mem_ramr_ws;
   1549   1.5  christos 	return 0;
   1550   1.5  christos     } else if (addr < mem_romsz) {
   1551   1.5  christos 	memcpy (data, &romb[addr & ~3], 4);
   1552   1.5  christos 	*ws = mem_romr_ws;
   1553   1.5  christos 	return 0;
   1554   1.1  christos     }
   1555   1.5  christos 
   1556   1.5  christos     if (sis_verbose)
   1557   1.5  christos 	printf ("Memory exception at %x (illegal address)\n", addr);
   1558   1.5  christos     if (sregs.psr & 0x080)
   1559   1.5  christos         asi = 9;
   1560   1.5  christos     else
   1561   1.5  christos         asi = 8;
   1562   1.5  christos     set_sfsr (UIMP_ACC, addr, asi, 1);
   1563   1.5  christos     *ws = MEM_EX_WS;
   1564   1.5  christos     return 1;
   1565   1.1  christos }
   1566   1.1  christos 
   1567   1.1  christos int
   1568  1.10  christos memory_read(int32_t asi, uint32_t addr, void *data, int32_t sz, int32_t *ws)
   1569   1.1  christos {
   1570  1.10  christos     int32_t           mexc;
   1571   1.1  christos 
   1572   1.1  christos #ifdef ERRINJ
   1573   1.1  christos     if (errmec) {
   1574   1.1  christos 	if (sis_verbose)
   1575   1.1  christos 	    printf("Inserted MEC error %d\n",errmec);
   1576   1.1  christos 	set_sfsr(errmec, addr, asi, 1);
   1577   1.1  christos 	if (errmec == 5) mecparerror();
   1578   1.1  christos 	if (errmec == 6) iucomperr();
   1579   1.1  christos 	errmec = 0;
   1580   1.5  christos 	return 1;
   1581   1.1  christos     }
   1582   1.1  christos #endif
   1583   1.1  christos 
   1584   1.1  christos     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
   1585   1.5  christos 	memcpy (data, &ramb[addr & mem_rammask & ~3], 4);
   1586   1.1  christos 	*ws = mem_ramr_ws;
   1587   1.5  christos 	return 0;
   1588   1.1  christos     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
   1589   1.1  christos 	mexc = mec_read(addr, asi, data);
   1590   1.1  christos 	if (mexc) {
   1591   1.1  christos 	    set_sfsr(MEC_ACC, addr, asi, 1);
   1592   1.1  christos 	    *ws = MEM_EX_WS;
   1593   1.1  christos 	} else {
   1594   1.1  christos 	    *ws = 0;
   1595   1.1  christos 	}
   1596   1.5  christos 	return mexc;
   1597   1.1  christos 
   1598   1.1  christos #ifdef ERA
   1599   1.1  christos 
   1600   1.1  christos     } else if (era) {
   1601   1.1  christos     	if ((addr < 0x100000) ||
   1602   1.1  christos 	    ((addr>= 0x80000000) && (addr < 0x80100000))) {
   1603   1.5  christos 	    memcpy (data, &romb[addr & ROM_MASK & ~3], 4);
   1604   1.1  christos 	    *ws = 4;
   1605   1.5  christos 	    return 0;
   1606   1.1  christos 	} else if ((addr >= 0x10000000) &&
   1607   1.1  christos 		   (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) &&
   1608   1.1  christos 		   (mec_iocr & 0x10))  {
   1609  1.10  christos 	    memcpy (data, &erareg, 4);
   1610   1.5  christos 	    return 0;
   1611   1.1  christos 	}
   1612   1.1  christos 
   1613   1.1  christos     } else  if (addr < mem_romsz) {
   1614   1.5  christos 	memcpy (data, &romb[addr & ~3], 4);
   1615   1.5  christos 	*ws = mem_romr_ws;
   1616   1.5  christos 	return 0;
   1617   1.1  christos #else
   1618   1.1  christos     } else if (addr < mem_romsz) {
   1619   1.5  christos 	memcpy (data, &romb[addr & ~3], 4);
   1620   1.1  christos 	*ws = mem_romr_ws;
   1621   1.5  christos 	return 0;
   1622   1.1  christos #endif
   1623   1.1  christos 
   1624   1.1  christos     }
   1625   1.1  christos 
   1626   1.5  christos     if (sis_verbose)
   1627   1.5  christos 	printf ("Memory exception at %x (illegal address)\n", addr);
   1628   1.1  christos     set_sfsr(UIMP_ACC, addr, asi, 1);
   1629   1.1  christos     *ws = MEM_EX_WS;
   1630   1.5  christos     return 1;
   1631   1.1  christos }
   1632   1.1  christos 
   1633   1.1  christos int
   1634  1.10  christos memory_write(int32_t asi, uint32_t addr, uint32_t *data, int32_t sz, int32_t *ws)
   1635  1.10  christos {
   1636  1.10  christos     uint32_t          waddr;
   1637  1.10  christos     int32_t           mexc;
   1638   1.1  christos     int             i;
   1639   1.1  christos     int             wphit[2];
   1640   1.1  christos 
   1641   1.1  christos #ifdef ERRINJ
   1642   1.1  christos     if (errmec) {
   1643   1.1  christos 	if (sis_verbose)
   1644   1.1  christos 	    printf("Inserted MEC error %d\n",errmec);
   1645   1.1  christos 	set_sfsr(errmec, addr, asi, 0);
   1646   1.1  christos 	if (errmec == 5) mecparerror();
   1647   1.1  christos 	if (errmec == 6) iucomperr();
   1648   1.1  christos 	errmec = 0;
   1649   1.5  christos 	return 1;
   1650   1.1  christos     }
   1651   1.1  christos #endif
   1652   1.1  christos 
   1653   1.1  christos     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
   1654   1.1  christos 	if (mem_accprot) {
   1655   1.1  christos 
   1656   1.1  christos 	    waddr = (addr & 0x7fffff) >> 2;
   1657   1.1  christos 	    for (i = 0; i < 2; i++)
   1658   1.1  christos 		wphit[i] =
   1659   1.1  christos 		    (((asi == 0xa) && (mec_wpr[i] & 1)) ||
   1660   1.1  christos 		     ((asi == 0xb) && (mec_wpr[i] & 2))) &&
   1661   1.1  christos 		    ((waddr >= mec_ssa[i]) && ((waddr | (sz == 3)) < mec_sea[i]));
   1662   1.1  christos 
   1663   1.1  christos 	    if (((mem_blockprot) && (wphit[0] || wphit[1])) ||
   1664   1.1  christos 		((!mem_blockprot) &&
   1665   1.1  christos 		 !((mec_wpr[0] && wphit[0]) || (mec_wpr[1] && wphit[1]))
   1666   1.1  christos 		 )) {
   1667   1.1  christos 		if (sis_verbose)
   1668   1.1  christos 		    printf("Memory access protection error at 0x%08x\n", addr);
   1669   1.1  christos 		set_sfsr(PROT_EXC, addr, asi, 0);
   1670   1.1  christos 		*ws = MEM_EX_WS;
   1671   1.5  christos 		return 1;
   1672   1.1  christos 	    }
   1673   1.1  christos 	}
   1674   1.5  christos 	waddr = addr & mem_rammask;
   1675   1.5  christos 	store_bytes (ramb, waddr, data, sz, ws);
   1676   1.5  christos 	return 0;
   1677   1.1  christos     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
   1678   1.1  christos 	if ((sz != 2) || (asi != 0xb)) {
   1679   1.1  christos 	    set_sfsr(MEC_ACC, addr, asi, 0);
   1680   1.1  christos 	    *ws = MEM_EX_WS;
   1681   1.5  christos 	    return 1;
   1682   1.1  christos 	}
   1683   1.1  christos 	mexc = mec_write(addr, *data);
   1684   1.1  christos 	if (mexc) {
   1685   1.1  christos 	    set_sfsr(MEC_ACC, addr, asi, 0);
   1686   1.1  christos 	    *ws = MEM_EX_WS;
   1687   1.1  christos 	} else {
   1688   1.1  christos 	    *ws = 0;
   1689   1.1  christos 	}
   1690   1.5  christos 	return mexc;
   1691   1.1  christos 
   1692   1.1  christos #ifdef ERA
   1693   1.1  christos 
   1694   1.1  christos     } else if (era) {
   1695   1.1  christos     	if ((erareg & 2) &&
   1696   1.1  christos 	((addr < 0x100000) || ((addr >= 0x80000000) && (addr < 0x80100000)))) {
   1697   1.1  christos 	    addr &= ROM_MASK;
   1698   1.1  christos 	    *ws = sz == 3 ? 8 : 4;
   1699   1.5  christos 	    store_bytes (romb, addr, data, sz, ws);
   1700   1.5  christos             return 0;
   1701   1.1  christos 	} else if ((addr >= 0x10000000) &&
   1702   1.1  christos 		   (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) &&
   1703   1.1  christos 		   (mec_iocr & 0x10))  {
   1704   1.1  christos 	    erareg = *data & 0x0e;
   1705   1.5  christos 	    return 0;
   1706   1.1  christos 	}
   1707   1.1  christos 
   1708   1.1  christos     } else if ((addr < mem_romsz) && (mec_memcfg & 0x10000) && (wrp) &&
   1709   1.1  christos                (((mec_memcfg & 0x20000) && (sz > 1)) ||
   1710   1.1  christos 		(!(mec_memcfg & 0x20000) && (sz == 0)))) {
   1711   1.1  christos 
   1712   1.1  christos 	*ws = mem_romw_ws + 1;
   1713   1.1  christos 	if (sz == 3)
   1714   1.1  christos 	    *ws += mem_romw_ws + STD_WS;
   1715   1.5  christos 	store_bytes (romb, addr, data, sz, ws);
   1716   1.5  christos         return 0;
   1717   1.1  christos 
   1718   1.1  christos #else
   1719   1.1  christos     } else if ((addr < mem_romsz) && (mec_memcfg & 0x10000) && (wrp) &&
   1720   1.1  christos                (((mec_memcfg & 0x20000) && (sz > 1)) ||
   1721   1.1  christos 		(!(mec_memcfg & 0x20000) && (sz == 0)))) {
   1722   1.1  christos 
   1723   1.1  christos 	*ws = mem_romw_ws + 1;
   1724   1.1  christos 	if (sz == 3)
   1725   1.1  christos             *ws += mem_romw_ws + STD_WS;
   1726   1.5  christos 	store_bytes (romb, addr, data, sz, ws);
   1727   1.5  christos         return 0;
   1728   1.1  christos 
   1729   1.1  christos #endif
   1730   1.1  christos 
   1731   1.1  christos     }
   1732   1.1  christos 
   1733   1.1  christos     *ws = MEM_EX_WS;
   1734   1.1  christos     set_sfsr(UIMP_ACC, addr, asi, 0);
   1735   1.5  christos     return 1;
   1736   1.1  christos }
   1737   1.1  christos 
   1738  1.10  christos static void  *
   1739  1.10  christos get_mem_ptr(uint32_t addr, uint32_t size)
   1740   1.1  christos {
   1741   1.1  christos     if ((addr + size) < ROM_SZ) {
   1742   1.5  christos 	return &romb[addr];
   1743   1.1  christos     } else if ((addr >= mem_ramstart) && ((addr + size) < mem_ramend)) {
   1744   1.5  christos 	return &ramb[addr & mem_rammask];
   1745   1.1  christos     }
   1746   1.1  christos 
   1747   1.1  christos #ifdef ERA
   1748   1.1  christos       else if ((era) && ((addr <0x100000) ||
   1749   1.1  christos 	((addr >= (unsigned) 0x80000000) && ((addr + size) < (unsigned) 0x80100000)))) {
   1750   1.5  christos 	return &romb[addr & ROM_MASK];
   1751   1.1  christos     }
   1752   1.1  christos #endif
   1753   1.1  christos 
   1754  1.10  christos     return (void *) -1;
   1755   1.1  christos }
   1756   1.1  christos 
   1757   1.1  christos int
   1758  1.10  christos sis_memory_write(uint32_t addr, const void *data, uint32_t length)
   1759   1.1  christos {
   1760  1.10  christos     void           *mem;
   1761   1.1  christos 
   1762  1.10  christos     if ((mem = get_mem_ptr(addr, length)) == ((void *) -1))
   1763   1.5  christos 	return 0;
   1764   1.1  christos 
   1765   1.1  christos     memcpy(mem, data, length);
   1766   1.5  christos     return length;
   1767   1.1  christos }
   1768   1.1  christos 
   1769   1.1  christos int
   1770  1.10  christos sis_memory_read(uint32_t addr, void *data, uint32_t length)
   1771   1.1  christos {
   1772   1.1  christos     char           *mem;
   1773   1.1  christos 
   1774  1.10  christos     if ((mem = get_mem_ptr(addr, length)) == ((void *) -1))
   1775   1.5  christos 	return 0;
   1776   1.1  christos 
   1777   1.1  christos     memcpy(data, mem, length);
   1778   1.5  christos     return length;
   1779   1.5  christos }
   1780   1.5  christos 
   1781   1.5  christos extern struct pstate sregs;
   1782   1.5  christos 
   1783   1.5  christos void
   1784   1.5  christos boot_init (void)
   1785   1.5  christos {
   1786   1.5  christos     mec_write(MEC_WCR, 0);	/* zero waitstates */
   1787   1.5  christos     mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
   1788   1.5  christos     mec_write(MEC_RTC_SCALER, sregs.freq - 1); /* generate 1 MHz RTC tick */
   1789   1.5  christos     mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
   1790   1.5  christos     sregs.wim = 2;
   1791   1.5  christos     sregs.psr = 0x110010e0;
   1792   1.5  christos     sregs.r[30] = RAM_END;
   1793   1.5  christos     sregs.r[14] = sregs.r[30] - 96 * 4;
   1794   1.5  christos     mec_mcr |= 1;		/* power-down enabled */
   1795   1.1  christos }
   1796