1212397c6Schristos /* This file is part of SIS (SPARC instruction simulator) 2212397c6Schristos 3*1f4e7eb9Schristos Copyright (C) 1995-2024 Free Software Foundation, Inc. 4212397c6Schristos Contributed by Jiri Gaisler, European Space Agency 5212397c6Schristos 6212397c6Schristos This program is free software; you can redistribute it and/or modify 7212397c6Schristos it under the terms of the GNU General Public License as published by 8212397c6Schristos the Free Software Foundation; either version 3 of the License, or 9212397c6Schristos (at your option) any later version. 10212397c6Schristos 11212397c6Schristos This program is distributed in the hope that it will be useful, 12212397c6Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 13212397c6Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14212397c6Schristos GNU General Public License for more details. 15212397c6Schristos 16212397c6Schristos You should have received a copy of the GNU General Public License 17212397c6Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 184e98e3e1Schristos 194e98e3e1Schristos /* The control space devices */ 204e98e3e1Schristos 214b169a6bSchristos /* This must come before any other includes. */ 224b169a6bSchristos #include "defs.h" 234b169a6bSchristos 244e98e3e1Schristos #include <sys/types.h> 254e98e3e1Schristos #include <stdio.h> 264e98e3e1Schristos #include <string.h> 274b169a6bSchristos #ifdef HAVE_TERMIOS_H 284e98e3e1Schristos #include <termios.h> 294b169a6bSchristos #endif 304e98e3e1Schristos #include <sys/fcntl.h> 314e98e3e1Schristos #include <sys/file.h> 324e98e3e1Schristos #include <unistd.h> 334e98e3e1Schristos #include "sis.h" 344e98e3e1Schristos #include "sim-config.h" 354e98e3e1Schristos 364e98e3e1Schristos extern int ctrl_c; 374b169a6bSchristos extern int32_t sis_verbose; 384b169a6bSchristos extern int32_t sparclite, sparclite_board; 394e98e3e1Schristos extern int rom8,wrp,uben; 404e98e3e1Schristos extern char uart_dev1[], uart_dev2[]; 414e98e3e1Schristos 424e98e3e1Schristos int dumbio = 0; /* normal, smart, terminal oriented IO by default */ 434e98e3e1Schristos 444e98e3e1Schristos /* MEC registers */ 454e98e3e1Schristos #define MEC_START 0x01f80000 464e98e3e1Schristos #define MEC_END 0x01f80100 474e98e3e1Schristos 484e98e3e1Schristos /* Memory exception waitstates */ 494e98e3e1Schristos #define MEM_EX_WS 1 504e98e3e1Schristos 514e98e3e1Schristos /* ERC32 always adds one waitstate during RAM std */ 524e98e3e1Schristos #define STD_WS 1 534e98e3e1Schristos 544e98e3e1Schristos #ifdef ERRINJ 554e98e3e1Schristos extern int errmec; 564e98e3e1Schristos #endif 574e98e3e1Schristos 584e98e3e1Schristos #define MEC_WS 0 /* Waitstates per MEC access (0 ws) */ 594e98e3e1Schristos #define MOK 0 604e98e3e1Schristos 614e98e3e1Schristos /* MEC register addresses */ 624e98e3e1Schristos 634e98e3e1Schristos #define MEC_MCR 0x000 644e98e3e1Schristos #define MEC_SFR 0x004 654e98e3e1Schristos #define MEC_PWDR 0x008 664e98e3e1Schristos #define MEC_MEMCFG 0x010 674e98e3e1Schristos #define MEC_IOCR 0x014 684e98e3e1Schristos #define MEC_WCR 0x018 694e98e3e1Schristos 704e98e3e1Schristos #define MEC_MAR0 0x020 714e98e3e1Schristos #define MEC_MAR1 0x024 724e98e3e1Schristos 734e98e3e1Schristos #define MEC_SSA1 0x020 744e98e3e1Schristos #define MEC_SEA1 0x024 754e98e3e1Schristos #define MEC_SSA2 0x028 764e98e3e1Schristos #define MEC_SEA2 0x02C 774e98e3e1Schristos #define MEC_ISR 0x044 784e98e3e1Schristos #define MEC_IPR 0x048 794e98e3e1Schristos #define MEC_IMR 0x04C 804e98e3e1Schristos #define MEC_ICR 0x050 814e98e3e1Schristos #define MEC_IFR 0x054 824e98e3e1Schristos #define MEC_WDOG 0x060 834e98e3e1Schristos #define MEC_TRAPD 0x064 844e98e3e1Schristos #define MEC_RTC_COUNTER 0x080 854e98e3e1Schristos #define MEC_RTC_RELOAD 0x080 864e98e3e1Schristos #define MEC_RTC_SCALER 0x084 874e98e3e1Schristos #define MEC_GPT_COUNTER 0x088 884e98e3e1Schristos #define MEC_GPT_RELOAD 0x088 894e98e3e1Schristos #define MEC_GPT_SCALER 0x08C 904e98e3e1Schristos #define MEC_TIMER_CTRL 0x098 914e98e3e1Schristos #define MEC_SFSR 0x0A0 924e98e3e1Schristos #define MEC_FFAR 0x0A4 934e98e3e1Schristos #define MEC_ERSR 0x0B0 944e98e3e1Schristos #define MEC_DBG 0x0C0 954e98e3e1Schristos #define MEC_TCR 0x0D0 964e98e3e1Schristos 974e98e3e1Schristos #define MEC_BRK 0x0C4 984e98e3e1Schristos #define MEC_WPR 0x0C8 994e98e3e1Schristos 1004e98e3e1Schristos #define MEC_UARTA 0x0E0 1014e98e3e1Schristos #define MEC_UARTB 0x0E4 1024e98e3e1Schristos #define MEC_UART_CTRL 0x0E8 1034e98e3e1Schristos #define SIM_LOAD 0x0F0 1044e98e3e1Schristos 1054e98e3e1Schristos /* Memory exception causes */ 1064e98e3e1Schristos #define PROT_EXC 0x3 1074e98e3e1Schristos #define UIMP_ACC 0x4 1084e98e3e1Schristos #define MEC_ACC 0x6 1094e98e3e1Schristos #define WATCH_EXC 0xa 1104e98e3e1Schristos #define BREAK_EXC 0xb 1114e98e3e1Schristos 1124e98e3e1Schristos /* Size of UART buffers (bytes) */ 1134e98e3e1Schristos #define UARTBUF 1024 1144e98e3e1Schristos 1154e98e3e1Schristos /* Number of simulator ticks between flushing the UARTS. */ 1164e98e3e1Schristos /* For good performance, keep above 1000 */ 1174e98e3e1Schristos #define UART_FLUSH_TIME 3000 1184e98e3e1Schristos 1194e98e3e1Schristos /* MEC timer control register bits */ 1204e98e3e1Schristos #define TCR_GACR 1 1214e98e3e1Schristos #define TCR_GACL 2 1224e98e3e1Schristos #define TCR_GASE 4 1234e98e3e1Schristos #define TCR_GASL 8 1244e98e3e1Schristos #define TCR_TCRCR 0x100 1254e98e3e1Schristos #define TCR_TCRCL 0x200 1264e98e3e1Schristos #define TCR_TCRSE 0x400 1274e98e3e1Schristos #define TCR_TCRSL 0x800 1284e98e3e1Schristos 1294e98e3e1Schristos /* New uart defines */ 1304e98e3e1Schristos #define UART_TX_TIME 1000 1314e98e3e1Schristos #define UART_RX_TIME 1000 1324e98e3e1Schristos #define UARTA_DR 0x1 1334e98e3e1Schristos #define UARTA_SRE 0x2 1344e98e3e1Schristos #define UARTA_HRE 0x4 1354e98e3e1Schristos #define UARTA_OR 0x40 1364e98e3e1Schristos #define UARTA_CLR 0x80 1374e98e3e1Schristos #define UARTB_DR 0x10000 1384e98e3e1Schristos #define UARTB_SRE 0x20000 1394e98e3e1Schristos #define UARTB_HRE 0x40000 1404e98e3e1Schristos #define UARTB_OR 0x400000 1414e98e3e1Schristos #define UARTB_CLR 0x800000 1424e98e3e1Schristos 1434e98e3e1Schristos #define UART_DR 0x100 1444e98e3e1Schristos #define UART_TSE 0x200 1454e98e3e1Schristos #define UART_THE 0x400 1464e98e3e1Schristos 1474e98e3e1Schristos /* MEC registers */ 1484e98e3e1Schristos 1494e98e3e1Schristos static char fname[256]; 1504b169a6bSchristos static int32_t find = 0; 1514b169a6bSchristos static uint32_t mec_ssa[2]; /* Write protection start address */ 1524b169a6bSchristos static uint32_t mec_sea[2]; /* Write protection end address */ 1534b169a6bSchristos static uint32_t mec_wpr[2]; /* Write protection control fields */ 1544b169a6bSchristos static uint32_t mec_sfsr; 1554b169a6bSchristos static uint32_t mec_ffar; 1564b169a6bSchristos static uint32_t mec_ipr; 1574b169a6bSchristos static uint32_t mec_imr; 1584b169a6bSchristos static uint32_t mec_isr; 1594b169a6bSchristos static uint32_t mec_icr; 1604b169a6bSchristos static uint32_t mec_ifr; 1614b169a6bSchristos static uint32_t mec_mcr; /* MEC control register */ 1624b169a6bSchristos static uint32_t mec_memcfg; /* Memory control register */ 1634b169a6bSchristos static uint32_t mec_wcr; /* MEC waitstate register */ 1644b169a6bSchristos static uint32_t mec_iocr; /* MEC IO control register */ 1654b169a6bSchristos static uint32_t posted_irq; 1664b169a6bSchristos static uint32_t mec_ersr; /* MEC error and status register */ 1674b169a6bSchristos static uint32_t mec_tcr; /* MEC test comtrol register */ 1684e98e3e1Schristos 1694b169a6bSchristos static uint32_t rtc_counter; 1704b169a6bSchristos static uint32_t rtc_reload; 1714b169a6bSchristos static uint32_t rtc_scaler; 1724b169a6bSchristos static uint32_t rtc_scaler_start; 1734b169a6bSchristos static uint32_t rtc_enabled; 1744b169a6bSchristos static uint32_t rtc_cr; 1754b169a6bSchristos static uint32_t rtc_se; 1764e98e3e1Schristos 1774b169a6bSchristos static uint32_t gpt_counter; 1784b169a6bSchristos static uint32_t gpt_reload; 1794b169a6bSchristos static uint32_t gpt_scaler; 1804b169a6bSchristos static uint32_t gpt_scaler_start; 1814b169a6bSchristos static uint32_t gpt_enabled; 1824b169a6bSchristos static uint32_t gpt_cr; 1834b169a6bSchristos static uint32_t gpt_se; 1844e98e3e1Schristos 1854b169a6bSchristos static uint32_t wdog_scaler; 1864b169a6bSchristos static uint32_t wdog_counter; 1874b169a6bSchristos static uint32_t wdog_rst_delay; 1884b169a6bSchristos static uint32_t wdog_rston; 1894e98e3e1Schristos 1904e98e3e1Schristos enum wdog_type { 1914e98e3e1Schristos init, disabled, enabled, stopped 1924e98e3e1Schristos }; 1934e98e3e1Schristos 1944e98e3e1Schristos static enum wdog_type wdog_status; 1954e98e3e1Schristos 1964e98e3e1Schristos 1974e98e3e1Schristos /* ROM size 1024 Kbyte */ 1984e98e3e1Schristos #define ROM_SZ 0x100000 1994e98e3e1Schristos #define ROM_MASK 0x0fffff 2004e98e3e1Schristos 2014e98e3e1Schristos /* RAM size 4 Mbyte */ 2024e98e3e1Schristos #define RAM_START 0x02000000 2034e98e3e1Schristos #define RAM_END 0x02400000 2044e98e3e1Schristos #define RAM_MASK 0x003fffff 2054e98e3e1Schristos 2064e98e3e1Schristos /* SPARClite boards all seem to have RAM at the same place. */ 2074e98e3e1Schristos #define RAM_START_SLITE 0x40000000 2084e98e3e1Schristos #define RAM_END_SLITE 0x40400000 2094e98e3e1Schristos #define RAM_MASK_SLITE 0x003fffff 2104e98e3e1Schristos 2114e98e3e1Schristos /* Memory support variables */ 2124e98e3e1Schristos 2134b169a6bSchristos static uint32_t mem_ramr_ws; /* RAM read waitstates */ 2144b169a6bSchristos static uint32_t mem_ramw_ws; /* RAM write waitstates */ 2154b169a6bSchristos static uint32_t mem_romr_ws; /* ROM read waitstates */ 2164b169a6bSchristos static uint32_t mem_romw_ws; /* ROM write waitstates */ 2174b169a6bSchristos static uint32_t mem_ramstart; /* RAM start */ 2184b169a6bSchristos static uint32_t mem_ramend; /* RAM end */ 2194b169a6bSchristos static uint32_t mem_rammask; /* RAM address mask */ 2204b169a6bSchristos static uint32_t mem_ramsz; /* RAM size */ 2214b169a6bSchristos static uint32_t mem_romsz; /* ROM size */ 2224b169a6bSchristos static uint32_t mem_accprot; /* RAM write protection enabled */ 2234b169a6bSchristos static uint32_t mem_blockprot; /* RAM block write protection enabled */ 2244e98e3e1Schristos 2254e98e3e1Schristos static unsigned char romb[ROM_SZ]; 2264e98e3e1Schristos static unsigned char ramb[RAM_END - RAM_START]; 2274e98e3e1Schristos 2284e98e3e1Schristos 2294e98e3e1Schristos /* UART support variables */ 2304e98e3e1Schristos 2314b169a6bSchristos static int32_t fd1, fd2; /* file descriptor for input file */ 2324b169a6bSchristos static int32_t Ucontrol; /* UART status register */ 2334e98e3e1Schristos static unsigned char aq[UARTBUF], bq[UARTBUF]; 2344b169a6bSchristos static int32_t anum, aind = 0; 2354b169a6bSchristos static int32_t bnum, bind = 0; 2364e98e3e1Schristos static char wbufa[UARTBUF], wbufb[UARTBUF]; 2374e98e3e1Schristos static unsigned wnuma; 2384e98e3e1Schristos static unsigned wnumb; 2394e98e3e1Schristos static FILE *f1in, *f1out, *f2in, *f2out; 2404b169a6bSchristos #ifdef HAVE_TERMIOS_H 2414e98e3e1Schristos static struct termios ioc1, ioc2, iocold1, iocold2; 2424b169a6bSchristos #endif 2434e98e3e1Schristos static int f1open = 0, f2open = 0; 2444e98e3e1Schristos 2454e98e3e1Schristos static char uarta_sreg, uarta_hreg, uartb_sreg, uartb_hreg; 2464b169a6bSchristos static uint32_t uart_stat_reg; 2474b169a6bSchristos static uint32_t uarta_data, uartb_data; 2484e98e3e1Schristos 2494e98e3e1Schristos #ifdef ERA 2504e98e3e1Schristos int era = 0; 2514e98e3e1Schristos int erareg; 2524e98e3e1Schristos #endif 2534e98e3e1Schristos 2544e98e3e1Schristos /* Forward declarations */ 2554e98e3e1Schristos 25603467a24Schristos static void decode_ersr (void); 2574e98e3e1Schristos #ifdef ERRINJ 25803467a24Schristos static void iucomperr (void); 2594e98e3e1Schristos #endif 26003467a24Schristos static void mecparerror (void); 26103467a24Schristos static void decode_memcfg (void); 26203467a24Schristos static void decode_wcr (void); 26303467a24Schristos static void decode_mcr (void); 26403467a24Schristos static void close_port (void); 26503467a24Schristos static void mec_reset (void); 2664b169a6bSchristos static void mec_intack (int32_t level); 26703467a24Schristos static void chk_irq (void); 2684b169a6bSchristos static void mec_irq (int32_t level); 2694b169a6bSchristos static void set_sfsr (uint32_t fault, uint32_t addr, 2704b169a6bSchristos uint32_t asi, uint32_t read); 2714b169a6bSchristos static int32_t mec_read (uint32_t addr, uint32_t asi, uint32_t *data); 2724b169a6bSchristos static int mec_write (uint32_t addr, uint32_t data); 27303467a24Schristos static void port_init (void); 2744b169a6bSchristos static uint32_t read_uart (uint32_t addr); 2754b169a6bSchristos static void write_uart (uint32_t addr, uint32_t data); 27603467a24Schristos static void flush_uart (void); 2774b169a6bSchristos static void uarta_tx (int32_t); 2784b169a6bSchristos static void uartb_tx (int32_t); 2794b169a6bSchristos static void uart_rx (int32_t); 2804b169a6bSchristos static void uart_intr (int32_t); 28103467a24Schristos static void uart_irq_start (void); 2824b169a6bSchristos static void wdog_intr (int32_t); 28303467a24Schristos static void wdog_start (void); 2844b169a6bSchristos static void rtc_intr (int32_t); 28503467a24Schristos static void rtc_start (void); 2864b169a6bSchristos static uint32_t rtc_counter_read (void); 2874b169a6bSchristos static void rtc_scaler_set (uint32_t val); 2884b169a6bSchristos static void rtc_reload_set (uint32_t val); 2894b169a6bSchristos static void gpt_intr (int32_t); 29003467a24Schristos static void gpt_start (void); 2914b169a6bSchristos static uint32_t gpt_counter_read (void); 2924b169a6bSchristos static void gpt_scaler_set (uint32_t val); 2934b169a6bSchristos static void gpt_reload_set (uint32_t val); 2944b169a6bSchristos static void timer_ctrl (uint32_t val); 2954b169a6bSchristos static void * get_mem_ptr (uint32_t addr, uint32_t size); 2964b169a6bSchristos static void store_bytes (unsigned char *mem, uint32_t waddr, 2974b169a6bSchristos uint32_t *data, int sz, int32_t *ws); 2984e98e3e1Schristos 2994e98e3e1Schristos extern int ext_irl; 3004e98e3e1Schristos 3014e98e3e1Schristos 3024e98e3e1Schristos /* One-time init */ 3034e98e3e1Schristos 3044e98e3e1Schristos void 3054b169a6bSchristos init_sim(void) 3064e98e3e1Schristos { 3074e98e3e1Schristos port_init(); 3084e98e3e1Schristos } 3094e98e3e1Schristos 3104e98e3e1Schristos /* Power-on reset init */ 3114e98e3e1Schristos 3124e98e3e1Schristos void 3134b169a6bSchristos reset(void) 3144e98e3e1Schristos { 3154e98e3e1Schristos mec_reset(); 3164e98e3e1Schristos uart_irq_start(); 3174e98e3e1Schristos wdog_start(); 3184e98e3e1Schristos } 3194e98e3e1Schristos 3204e98e3e1Schristos static void 3214b169a6bSchristos decode_ersr(void) 3224e98e3e1Schristos { 3234e98e3e1Schristos if (mec_ersr & 0x01) { 3244e98e3e1Schristos if (!(mec_mcr & 0x20)) { 3254e98e3e1Schristos if (mec_mcr & 0x40) { 3264e98e3e1Schristos sys_reset(); 3274e98e3e1Schristos mec_ersr = 0x8000; 3284e98e3e1Schristos if (sis_verbose) 3294e98e3e1Schristos printf("Error manager reset - IU in error mode\n"); 3304e98e3e1Schristos } else { 3314e98e3e1Schristos sys_halt(); 3324e98e3e1Schristos mec_ersr |= 0x2000; 3334e98e3e1Schristos if (sis_verbose) 3344e98e3e1Schristos printf("Error manager halt - IU in error mode\n"); 3354e98e3e1Schristos } 3364e98e3e1Schristos } else 3374e98e3e1Schristos mec_irq(1); 3384e98e3e1Schristos } 3394e98e3e1Schristos if (mec_ersr & 0x04) { 3404e98e3e1Schristos if (!(mec_mcr & 0x200)) { 3414e98e3e1Schristos if (mec_mcr & 0x400) { 3424e98e3e1Schristos sys_reset(); 3434e98e3e1Schristos mec_ersr = 0x8000; 3444e98e3e1Schristos if (sis_verbose) 3454e98e3e1Schristos printf("Error manager reset - IU comparison error\n"); 3464e98e3e1Schristos } else { 3474e98e3e1Schristos sys_halt(); 3484e98e3e1Schristos mec_ersr |= 0x2000; 3494e98e3e1Schristos if (sis_verbose) 3504e98e3e1Schristos printf("Error manager halt - IU comparison error\n"); 3514e98e3e1Schristos } 3524e98e3e1Schristos } else 3534e98e3e1Schristos mec_irq(1); 3544e98e3e1Schristos } 3554e98e3e1Schristos if (mec_ersr & 0x20) { 3564e98e3e1Schristos if (!(mec_mcr & 0x2000)) { 3574e98e3e1Schristos if (mec_mcr & 0x4000) { 3584e98e3e1Schristos sys_reset(); 3594e98e3e1Schristos mec_ersr = 0x8000; 3604e98e3e1Schristos if (sis_verbose) 3614e98e3e1Schristos printf("Error manager reset - MEC hardware error\n"); 3624e98e3e1Schristos } else { 3634e98e3e1Schristos sys_halt(); 3644e98e3e1Schristos mec_ersr |= 0x2000; 3654e98e3e1Schristos if (sis_verbose) 3664e98e3e1Schristos printf("Error manager halt - MEC hardware error\n"); 3674e98e3e1Schristos } 3684e98e3e1Schristos } else 3694e98e3e1Schristos mec_irq(1); 3704e98e3e1Schristos } 3714e98e3e1Schristos } 3724e98e3e1Schristos 3734e98e3e1Schristos #ifdef ERRINJ 3744e98e3e1Schristos static void 3754e98e3e1Schristos iucomperr() 3764e98e3e1Schristos { 3774e98e3e1Schristos mec_ersr |= 0x04; 3784e98e3e1Schristos decode_ersr(); 3794e98e3e1Schristos } 3804e98e3e1Schristos #endif 3814e98e3e1Schristos 3824e98e3e1Schristos static void 3834b169a6bSchristos mecparerror(void) 3844e98e3e1Schristos { 3854e98e3e1Schristos mec_ersr |= 0x20; 3864e98e3e1Schristos decode_ersr(); 3874e98e3e1Schristos } 3884e98e3e1Schristos 3894e98e3e1Schristos 3904e98e3e1Schristos /* IU error mode manager */ 3914e98e3e1Schristos 3924e98e3e1Schristos void 3934b169a6bSchristos error_mode(uint32_t pc) 3944e98e3e1Schristos { 3954e98e3e1Schristos 3964e98e3e1Schristos mec_ersr |= 0x1; 3974e98e3e1Schristos decode_ersr(); 3984e98e3e1Schristos } 3994e98e3e1Schristos 4004e98e3e1Schristos 4014e98e3e1Schristos /* Check memory settings */ 4024e98e3e1Schristos 4034e98e3e1Schristos static void 4044b169a6bSchristos decode_memcfg(void) 4054e98e3e1Schristos { 4064e98e3e1Schristos if (rom8) mec_memcfg &= ~0x20000; 4074e98e3e1Schristos else mec_memcfg |= 0x20000; 4084e98e3e1Schristos 4094e98e3e1Schristos mem_ramsz = (256 * 1024) << ((mec_memcfg >> 10) & 7); 4104e98e3e1Schristos mem_romsz = (128 * 1024) << ((mec_memcfg >> 18) & 7); 4114e98e3e1Schristos 4124e98e3e1Schristos if (sparclite_board) { 4134e98e3e1Schristos mem_ramstart = RAM_START_SLITE; 4144e98e3e1Schristos mem_ramend = RAM_END_SLITE; 4154e98e3e1Schristos mem_rammask = RAM_MASK_SLITE; 4164e98e3e1Schristos } 4174e98e3e1Schristos else { 4184e98e3e1Schristos mem_ramstart = RAM_START; 4194e98e3e1Schristos mem_ramend = RAM_END; 4204e98e3e1Schristos mem_rammask = RAM_MASK; 4214e98e3e1Schristos } 4224e98e3e1Schristos if (sis_verbose) 4234e98e3e1Schristos printf("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n", 4244e98e3e1Schristos mem_ramstart, mem_ramsz >> 10, mem_romsz >> 10); 4254e98e3e1Schristos } 4264e98e3e1Schristos 4274e98e3e1Schristos static void 4284b169a6bSchristos decode_wcr(void) 4294e98e3e1Schristos { 4304e98e3e1Schristos mem_ramr_ws = mec_wcr & 3; 4314e98e3e1Schristos mem_ramw_ws = (mec_wcr >> 2) & 3; 4324e98e3e1Schristos mem_romr_ws = (mec_wcr >> 4) & 0x0f; 4334e98e3e1Schristos if (rom8) { 4344e98e3e1Schristos if (mem_romr_ws > 0 ) mem_romr_ws--; 4354e98e3e1Schristos mem_romr_ws = 5 + (4*mem_romr_ws); 4364e98e3e1Schristos } 4374e98e3e1Schristos mem_romw_ws = (mec_wcr >> 8) & 0x0f; 4384e98e3e1Schristos if (sis_verbose) 4394e98e3e1Schristos printf("Waitstates = RAM read: %d, RAM write: %d, ROM read: %d, ROM write: %d\n", 4404e98e3e1Schristos mem_ramr_ws, mem_ramw_ws, mem_romr_ws, mem_romw_ws); 4414e98e3e1Schristos } 4424e98e3e1Schristos 4434e98e3e1Schristos static void 4444b169a6bSchristos decode_mcr(void) 4454e98e3e1Schristos { 4464e98e3e1Schristos mem_accprot = (mec_wpr[0] | mec_wpr[1]); 4474e98e3e1Schristos mem_blockprot = (mec_mcr >> 3) & 1; 4484e98e3e1Schristos if (sis_verbose && mem_accprot) 4494e98e3e1Schristos printf("Memory block write protection enabled\n"); 4504e98e3e1Schristos if (mec_mcr & 0x08000) { 4514e98e3e1Schristos mec_ersr |= 0x20; 4524e98e3e1Schristos decode_ersr(); 4534e98e3e1Schristos } 4544e98e3e1Schristos if (sis_verbose && (mec_mcr & 2)) 4554e98e3e1Schristos printf("Software reset enabled\n"); 4564e98e3e1Schristos if (sis_verbose && (mec_mcr & 1)) 4574e98e3e1Schristos printf("Power-down mode enabled\n"); 4584e98e3e1Schristos } 4594e98e3e1Schristos 4604e98e3e1Schristos /* Flush ports when simulator stops */ 4614e98e3e1Schristos 4624e98e3e1Schristos void 4634b169a6bSchristos sim_halt(void) 4644e98e3e1Schristos { 4654e98e3e1Schristos #ifdef FAST_UART 4664e98e3e1Schristos flush_uart(); 4674e98e3e1Schristos #endif 4684e98e3e1Schristos } 4694e98e3e1Schristos 4704e98e3e1Schristos int 4714e98e3e1Schristos sim_stop(SIM_DESC sd) 4724e98e3e1Schristos { 4734e98e3e1Schristos ctrl_c = 1; 4744e98e3e1Schristos return 1; 4754e98e3e1Schristos } 4764e98e3e1Schristos 4774e98e3e1Schristos static void 4784b169a6bSchristos close_port(void) 4794e98e3e1Schristos { 4804e98e3e1Schristos if (f1open && f1in != stdin) 4814e98e3e1Schristos fclose(f1in); 4824e98e3e1Schristos if (f2open && f2in != stdin) 4834e98e3e1Schristos fclose(f2in); 4844e98e3e1Schristos } 4854e98e3e1Schristos 4864e98e3e1Schristos void 4874b169a6bSchristos exit_sim(void) 4884e98e3e1Schristos { 4894e98e3e1Schristos close_port(); 4904e98e3e1Schristos } 4914e98e3e1Schristos 4924e98e3e1Schristos static void 4934b169a6bSchristos mec_reset(void) 4944e98e3e1Schristos { 4954e98e3e1Schristos int i; 4964e98e3e1Schristos 4974e98e3e1Schristos find = 0; 4984e98e3e1Schristos for (i = 0; i < 2; i++) 4994e98e3e1Schristos mec_ssa[i] = mec_sea[i] = mec_wpr[i] = 0; 5004e98e3e1Schristos mec_mcr = 0x01350014; 5014e98e3e1Schristos mec_iocr = 0; 5024e98e3e1Schristos mec_sfsr = 0x078; 5034e98e3e1Schristos mec_ffar = 0; 5044e98e3e1Schristos mec_ipr = 0; 5054e98e3e1Schristos mec_imr = 0x7ffe; 5064e98e3e1Schristos mec_isr = 0; 5074e98e3e1Schristos mec_icr = 0; 5084e98e3e1Schristos mec_ifr = 0; 5094e98e3e1Schristos mec_memcfg = 0x10000; 5104e98e3e1Schristos mec_wcr = -1; 5114e98e3e1Schristos mec_ersr = 0; /* MEC error and status register */ 5124e98e3e1Schristos mec_tcr = 0; /* MEC test comtrol register */ 5134e98e3e1Schristos 5144e98e3e1Schristos decode_memcfg(); 5154e98e3e1Schristos decode_wcr(); 5164e98e3e1Schristos decode_mcr(); 5174e98e3e1Schristos 5184e98e3e1Schristos posted_irq = 0; 5194e98e3e1Schristos wnuma = wnumb = 0; 5204e98e3e1Schristos anum = aind = bnum = bind = 0; 5214e98e3e1Schristos 5224e98e3e1Schristos uart_stat_reg = UARTA_SRE | UARTA_HRE | UARTB_SRE | UARTB_HRE; 5234e98e3e1Schristos uarta_data = uartb_data = UART_THE | UART_TSE; 5244e98e3e1Schristos 5254e98e3e1Schristos rtc_counter = 0xffffffff; 5264e98e3e1Schristos rtc_reload = 0xffffffff; 5274e98e3e1Schristos rtc_scaler = 0xff; 5284e98e3e1Schristos rtc_enabled = 0; 5294e98e3e1Schristos rtc_cr = 0; 5304e98e3e1Schristos rtc_se = 0; 5314e98e3e1Schristos 5324e98e3e1Schristos gpt_counter = 0xffffffff; 5334e98e3e1Schristos gpt_reload = 0xffffffff; 5344e98e3e1Schristos gpt_scaler = 0xffff; 5354e98e3e1Schristos gpt_enabled = 0; 5364e98e3e1Schristos gpt_cr = 0; 5374e98e3e1Schristos gpt_se = 0; 5384e98e3e1Schristos 5394e98e3e1Schristos wdog_scaler = 255; 5404e98e3e1Schristos wdog_rst_delay = 255; 5414e98e3e1Schristos wdog_counter = 0xffff; 5424e98e3e1Schristos wdog_rston = 0; 5434e98e3e1Schristos wdog_status = init; 5444e98e3e1Schristos 5454e98e3e1Schristos #ifdef ERA 5464e98e3e1Schristos erareg = 0; 5474e98e3e1Schristos #endif 5484e98e3e1Schristos 5494e98e3e1Schristos } 5504e98e3e1Schristos 5514e98e3e1Schristos 5524e98e3e1Schristos 5534e98e3e1Schristos static void 5544b169a6bSchristos mec_intack(int32_t level) 5554e98e3e1Schristos { 5564e98e3e1Schristos int irq_test; 5574e98e3e1Schristos 5584e98e3e1Schristos if (sis_verbose) 5594e98e3e1Schristos printf("interrupt %d acknowledged\n", level); 5604e98e3e1Schristos irq_test = mec_tcr & 0x80000; 5614e98e3e1Schristos if ((irq_test) && (mec_ifr & (1 << level))) 5624e98e3e1Schristos mec_ifr &= ~(1 << level); 5634e98e3e1Schristos else 5644e98e3e1Schristos mec_ipr &= ~(1 << level); 5654e98e3e1Schristos chk_irq(); 5664e98e3e1Schristos } 5674e98e3e1Schristos 5684e98e3e1Schristos static void 5694b169a6bSchristos chk_irq(void) 5704e98e3e1Schristos { 5714b169a6bSchristos int32_t i; 5724b169a6bSchristos uint32_t itmp; 5734e98e3e1Schristos int old_irl; 5744e98e3e1Schristos 5754e98e3e1Schristos old_irl = ext_irl; 5764e98e3e1Schristos if (mec_tcr & 0x80000) itmp = mec_ifr; 5774e98e3e1Schristos else itmp = 0; 5784e98e3e1Schristos itmp = ((mec_ipr | itmp) & ~mec_imr) & 0x0fffe; 5794e98e3e1Schristos ext_irl = 0; 5804e98e3e1Schristos if (itmp != 0) { 5814e98e3e1Schristos for (i = 15; i > 0; i--) { 5824e98e3e1Schristos if (((itmp >> i) & 1) != 0) { 5834e98e3e1Schristos if ((sis_verbose) && (i > old_irl)) 5844e98e3e1Schristos printf("IU irl: %d\n", i); 5854e98e3e1Schristos ext_irl = i; 5864e98e3e1Schristos set_int(i, mec_intack, i); 5874e98e3e1Schristos break; 5884e98e3e1Schristos } 5894e98e3e1Schristos } 5904e98e3e1Schristos } 5914e98e3e1Schristos } 5924e98e3e1Schristos 5934e98e3e1Schristos static void 5944b169a6bSchristos mec_irq(int32_t level) 5954e98e3e1Schristos { 5964e98e3e1Schristos mec_ipr |= (1 << level); 5974e98e3e1Schristos chk_irq(); 5984e98e3e1Schristos } 5994e98e3e1Schristos 6004e98e3e1Schristos static void 6014b169a6bSchristos set_sfsr(uint32_t fault, uint32_t addr, uint32_t asi, uint32_t read) 6024e98e3e1Schristos { 6034e98e3e1Schristos if ((asi == 0xa) || (asi == 0xb)) { 6044e98e3e1Schristos mec_ffar = addr; 6054e98e3e1Schristos mec_sfsr = (fault << 3) | (!read << 15); 6064e98e3e1Schristos mec_sfsr |= ((mec_sfsr & 1) ^ 1) | (mec_sfsr & 1); 6074e98e3e1Schristos switch (asi) { 6084e98e3e1Schristos case 0xa: 6094e98e3e1Schristos mec_sfsr |= 0x0004; 6104e98e3e1Schristos break; 6114e98e3e1Schristos case 0xb: 6124e98e3e1Schristos mec_sfsr |= 0x1004; 6134e98e3e1Schristos break; 6144e98e3e1Schristos } 6154e98e3e1Schristos } 6164e98e3e1Schristos } 6174e98e3e1Schristos 6184b169a6bSchristos static int32_t 6194b169a6bSchristos mec_read(uint32_t addr, uint32_t asi, uint32_t *data) 6204e98e3e1Schristos { 6214e98e3e1Schristos 6224e98e3e1Schristos switch (addr & 0x0ff) { 6234e98e3e1Schristos 6244e98e3e1Schristos case MEC_MCR: /* 0x00 */ 6254e98e3e1Schristos *data = mec_mcr; 6264e98e3e1Schristos break; 6274e98e3e1Schristos 6284e98e3e1Schristos case MEC_MEMCFG: /* 0x10 */ 6294e98e3e1Schristos *data = mec_memcfg; 6304e98e3e1Schristos break; 6314e98e3e1Schristos 6324e98e3e1Schristos case MEC_IOCR: 6334e98e3e1Schristos *data = mec_iocr; /* 0x14 */ 6344e98e3e1Schristos break; 6354e98e3e1Schristos 6364e98e3e1Schristos case MEC_SSA1: /* 0x20 */ 6374e98e3e1Schristos *data = mec_ssa[0] | (mec_wpr[0] << 23); 6384e98e3e1Schristos break; 6394e98e3e1Schristos case MEC_SEA1: /* 0x24 */ 6404e98e3e1Schristos *data = mec_sea[0]; 6414e98e3e1Schristos break; 6424e98e3e1Schristos case MEC_SSA2: /* 0x28 */ 6434e98e3e1Schristos *data = mec_ssa[1] | (mec_wpr[1] << 23); 6444e98e3e1Schristos break; 6454e98e3e1Schristos case MEC_SEA2: /* 0x2c */ 6464e98e3e1Schristos *data = mec_sea[1]; 6474e98e3e1Schristos break; 6484e98e3e1Schristos 6494e98e3e1Schristos case MEC_ISR: /* 0x44 */ 6504e98e3e1Schristos *data = mec_isr; 6514e98e3e1Schristos break; 6524e98e3e1Schristos 6534e98e3e1Schristos case MEC_IPR: /* 0x48 */ 6544e98e3e1Schristos *data = mec_ipr; 6554e98e3e1Schristos break; 6564e98e3e1Schristos 6574e98e3e1Schristos case MEC_IMR: /* 0x4c */ 6584e98e3e1Schristos *data = mec_imr; 6594e98e3e1Schristos break; 6604e98e3e1Schristos 6614e98e3e1Schristos case MEC_IFR: /* 0x54 */ 6624e98e3e1Schristos *data = mec_ifr; 6634e98e3e1Schristos break; 6644e98e3e1Schristos 6654e98e3e1Schristos case MEC_RTC_COUNTER: /* 0x80 */ 6664e98e3e1Schristos *data = rtc_counter_read(); 6674e98e3e1Schristos break; 6684e98e3e1Schristos case MEC_RTC_SCALER: /* 0x84 */ 6694e98e3e1Schristos if (rtc_enabled) 6704e98e3e1Schristos *data = rtc_scaler - (now() - rtc_scaler_start); 6714e98e3e1Schristos else 6724e98e3e1Schristos *data = rtc_scaler; 6734e98e3e1Schristos break; 6744e98e3e1Schristos 6754e98e3e1Schristos case MEC_GPT_COUNTER: /* 0x88 */ 6764e98e3e1Schristos *data = gpt_counter_read(); 6774e98e3e1Schristos break; 6784e98e3e1Schristos 6794e98e3e1Schristos case MEC_GPT_SCALER: /* 0x8c */ 6804e98e3e1Schristos if (rtc_enabled) 6814e98e3e1Schristos *data = gpt_scaler - (now() - gpt_scaler_start); 6824e98e3e1Schristos else 6834e98e3e1Schristos *data = gpt_scaler; 6844e98e3e1Schristos break; 6854e98e3e1Schristos 6864e98e3e1Schristos 6874e98e3e1Schristos case MEC_SFSR: /* 0xA0 */ 6884e98e3e1Schristos *data = mec_sfsr; 6894e98e3e1Schristos break; 6904e98e3e1Schristos 6914e98e3e1Schristos case MEC_FFAR: /* 0xA4 */ 6924e98e3e1Schristos *data = mec_ffar; 6934e98e3e1Schristos break; 6944e98e3e1Schristos 6954e98e3e1Schristos case SIM_LOAD: 6964e98e3e1Schristos fname[find] = 0; 6974e98e3e1Schristos if (find == 0) 6984e98e3e1Schristos strcpy(fname, "simload"); 6994e98e3e1Schristos find = bfd_load(fname); 7004e98e3e1Schristos if (find == -1) 7014e98e3e1Schristos *data = 0; 7024e98e3e1Schristos else 7034e98e3e1Schristos *data = 1; 7044e98e3e1Schristos find = 0; 7054e98e3e1Schristos break; 7064e98e3e1Schristos 7074e98e3e1Schristos case MEC_ERSR: /* 0xB0 */ 7084e98e3e1Schristos *data = mec_ersr; 7094e98e3e1Schristos break; 7104e98e3e1Schristos 7114e98e3e1Schristos case MEC_TCR: /* 0xD0 */ 7124e98e3e1Schristos *data = mec_tcr; 7134e98e3e1Schristos break; 7144e98e3e1Schristos 7154e98e3e1Schristos case MEC_UARTA: /* 0xE0 */ 7164e98e3e1Schristos case MEC_UARTB: /* 0xE4 */ 7174e98e3e1Schristos if (asi != 0xb) { 7184e98e3e1Schristos set_sfsr(MEC_ACC, addr, asi, 1); 719212397c6Schristos return 1; 7204e98e3e1Schristos } 7214e98e3e1Schristos *data = read_uart(addr); 7224e98e3e1Schristos break; 7234e98e3e1Schristos 7244e98e3e1Schristos case MEC_UART_CTRL: /* 0xE8 */ 7254e98e3e1Schristos 7264e98e3e1Schristos *data = read_uart(addr); 7274e98e3e1Schristos break; 7284e98e3e1Schristos 729212397c6Schristos case 0xF4: /* simulator RAM size in bytes */ 730212397c6Schristos *data = 4096*1024; 731212397c6Schristos break; 732212397c6Schristos 733212397c6Schristos case 0xF8: /* simulator ROM size in bytes */ 734212397c6Schristos *data = 1024*1024; 735212397c6Schristos break; 736212397c6Schristos 7374e98e3e1Schristos default: 7384e98e3e1Schristos set_sfsr(MEC_ACC, addr, asi, 1); 739212397c6Schristos return 1; 7404e98e3e1Schristos break; 7414e98e3e1Schristos } 742212397c6Schristos return MOK; 7434e98e3e1Schristos } 7444e98e3e1Schristos 7454e98e3e1Schristos static int 7464b169a6bSchristos mec_write(uint32_t addr, uint32_t data) 7474e98e3e1Schristos { 7484e98e3e1Schristos if (sis_verbose > 1) 7494e98e3e1Schristos printf("MEC write a: %08x, d: %08x\n",addr,data); 7504e98e3e1Schristos switch (addr & 0x0ff) { 7514e98e3e1Schristos 7524e98e3e1Schristos case MEC_MCR: 7534e98e3e1Schristos mec_mcr = data; 7544e98e3e1Schristos decode_mcr(); 7554e98e3e1Schristos if (mec_mcr & 0x08000) mecparerror(); 7564e98e3e1Schristos break; 7574e98e3e1Schristos 7584e98e3e1Schristos case MEC_SFR: 7594e98e3e1Schristos if (mec_mcr & 0x2) { 7604e98e3e1Schristos sys_reset(); 7614e98e3e1Schristos mec_ersr = 0x4000; 7624e98e3e1Schristos if (sis_verbose) 7634e98e3e1Schristos printf(" Software reset issued\n"); 7644e98e3e1Schristos } 7654e98e3e1Schristos break; 7664e98e3e1Schristos 7674e98e3e1Schristos case MEC_IOCR: 7684e98e3e1Schristos mec_iocr = data; 7694e98e3e1Schristos if (mec_iocr & 0xC0C0C0C0) mecparerror(); 7704e98e3e1Schristos break; 7714e98e3e1Schristos 7724e98e3e1Schristos case MEC_SSA1: /* 0x20 */ 7734e98e3e1Schristos if (data & 0xFE000000) mecparerror(); 7744e98e3e1Schristos mec_ssa[0] = data & 0x7fffff; 7754e98e3e1Schristos mec_wpr[0] = (data >> 23) & 0x03; 7764e98e3e1Schristos mem_accprot = mec_wpr[0] || mec_wpr[1]; 7774e98e3e1Schristos if (sis_verbose && mec_wpr[0]) 7784e98e3e1Schristos printf("Segment 1 memory protection enabled (0x02%06x - 0x02%06x)\n", 7794e98e3e1Schristos mec_ssa[0] << 2, mec_sea[0] << 2); 7804e98e3e1Schristos break; 7814e98e3e1Schristos case MEC_SEA1: /* 0x24 */ 7824e98e3e1Schristos if (data & 0xFF800000) mecparerror(); 7834e98e3e1Schristos mec_sea[0] = data & 0x7fffff; 7844e98e3e1Schristos break; 7854e98e3e1Schristos case MEC_SSA2: /* 0x28 */ 7864e98e3e1Schristos if (data & 0xFE000000) mecparerror(); 7874e98e3e1Schristos mec_ssa[1] = data & 0x7fffff; 7884e98e3e1Schristos mec_wpr[1] = (data >> 23) & 0x03; 7894e98e3e1Schristos mem_accprot = mec_wpr[0] || mec_wpr[1]; 7904e98e3e1Schristos if (sis_verbose && mec_wpr[1]) 7914e98e3e1Schristos printf("Segment 2 memory protection enabled (0x02%06x - 0x02%06x)\n", 7924e98e3e1Schristos mec_ssa[1] << 2, mec_sea[1] << 2); 7934e98e3e1Schristos break; 7944e98e3e1Schristos case MEC_SEA2: /* 0x2c */ 7954e98e3e1Schristos if (data & 0xFF800000) mecparerror(); 7964e98e3e1Schristos mec_sea[1] = data & 0x7fffff; 7974e98e3e1Schristos break; 7984e98e3e1Schristos 7994e98e3e1Schristos case MEC_UARTA: 8004e98e3e1Schristos case MEC_UARTB: 8014e98e3e1Schristos if (data & 0xFFFFFF00) mecparerror(); 802*1f4e7eb9Schristos ATTRIBUTE_FALLTHROUGH; 8034e98e3e1Schristos case MEC_UART_CTRL: 8044e98e3e1Schristos if (data & 0xFF00FF00) mecparerror(); 8054e98e3e1Schristos write_uart(addr, data); 8064e98e3e1Schristos break; 8074e98e3e1Schristos 8084e98e3e1Schristos case MEC_GPT_RELOAD: 8094e98e3e1Schristos gpt_reload_set(data); 8104e98e3e1Schristos break; 8114e98e3e1Schristos 8124e98e3e1Schristos case MEC_GPT_SCALER: 8134e98e3e1Schristos if (data & 0xFFFF0000) mecparerror(); 8144e98e3e1Schristos gpt_scaler_set(data); 8154e98e3e1Schristos break; 8164e98e3e1Schristos 8174e98e3e1Schristos case MEC_TIMER_CTRL: 8184e98e3e1Schristos if (data & 0xFFFFF0F0) mecparerror(); 8194e98e3e1Schristos timer_ctrl(data); 8204e98e3e1Schristos break; 8214e98e3e1Schristos 8224e98e3e1Schristos case MEC_RTC_RELOAD: 8234e98e3e1Schristos rtc_reload_set(data); 8244e98e3e1Schristos break; 8254e98e3e1Schristos 8264e98e3e1Schristos case MEC_RTC_SCALER: 8274e98e3e1Schristos if (data & 0xFFFFFF00) mecparerror(); 8284e98e3e1Schristos rtc_scaler_set(data); 8294e98e3e1Schristos break; 8304e98e3e1Schristos 8314e98e3e1Schristos case MEC_SFSR: /* 0xA0 */ 8324e98e3e1Schristos if (data & 0xFFFF0880) mecparerror(); 8334e98e3e1Schristos mec_sfsr = 0x78; 8344e98e3e1Schristos break; 8354e98e3e1Schristos 8364e98e3e1Schristos case MEC_ISR: 8374e98e3e1Schristos if (data & 0xFFFFE000) mecparerror(); 8384e98e3e1Schristos mec_isr = data; 8394e98e3e1Schristos break; 8404e98e3e1Schristos 8414e98e3e1Schristos case MEC_IMR: /* 0x4c */ 8424e98e3e1Schristos 8434e98e3e1Schristos if (data & 0xFFFF8001) mecparerror(); 8444e98e3e1Schristos mec_imr = data & 0x7ffe; 8454e98e3e1Schristos chk_irq(); 8464e98e3e1Schristos break; 8474e98e3e1Schristos 8484e98e3e1Schristos case MEC_ICR: /* 0x50 */ 8494e98e3e1Schristos 8504e98e3e1Schristos if (data & 0xFFFF0001) mecparerror(); 8514e98e3e1Schristos mec_ipr &= ~data & 0x0fffe; 8524e98e3e1Schristos chk_irq(); 8534e98e3e1Schristos break; 8544e98e3e1Schristos 8554e98e3e1Schristos case MEC_IFR: /* 0x54 */ 8564e98e3e1Schristos 8574e98e3e1Schristos if (mec_tcr & 0x080000) { 8584e98e3e1Schristos if (data & 0xFFFF0001) mecparerror(); 8594e98e3e1Schristos mec_ifr = data & 0xfffe; 8604e98e3e1Schristos chk_irq(); 8614e98e3e1Schristos } 8624e98e3e1Schristos break; 8634e98e3e1Schristos case SIM_LOAD: 8644e98e3e1Schristos fname[find++] = (char) data; 8654e98e3e1Schristos break; 8664e98e3e1Schristos 8674e98e3e1Schristos 8684e98e3e1Schristos case MEC_MEMCFG: /* 0x10 */ 8694e98e3e1Schristos if (data & 0xC0E08000) mecparerror(); 8704e98e3e1Schristos mec_memcfg = data; 8714e98e3e1Schristos decode_memcfg(); 8724e98e3e1Schristos if (mec_memcfg & 0xc0e08000) 8734e98e3e1Schristos mecparerror(); 8744e98e3e1Schristos break; 8754e98e3e1Schristos 8764e98e3e1Schristos case MEC_WCR: /* 0x18 */ 8774e98e3e1Schristos mec_wcr = data; 8784e98e3e1Schristos decode_wcr(); 8794e98e3e1Schristos break; 8804e98e3e1Schristos 8814e98e3e1Schristos case MEC_ERSR: /* 0xB0 */ 8824e98e3e1Schristos if (mec_tcr & 0x100000) 8834e98e3e1Schristos if (data & 0xFFFFEFC0) mecparerror(); 8844e98e3e1Schristos mec_ersr = data & 0x103f; 8854e98e3e1Schristos break; 8864e98e3e1Schristos 8874e98e3e1Schristos case MEC_TCR: /* 0xD0 */ 8884e98e3e1Schristos if (data & 0xFFE1FFC0) mecparerror(); 8894e98e3e1Schristos mec_tcr = data & 0x1e003f; 8904e98e3e1Schristos break; 8914e98e3e1Schristos 8924e98e3e1Schristos case MEC_WDOG: /* 0x60 */ 8934e98e3e1Schristos wdog_scaler = (data >> 16) & 0x0ff; 8944e98e3e1Schristos wdog_counter = data & 0x0ffff; 8954e98e3e1Schristos wdog_rst_delay = data >> 24; 8964e98e3e1Schristos wdog_rston = 0; 8974e98e3e1Schristos if (wdog_status == stopped) 8984e98e3e1Schristos wdog_start(); 8994e98e3e1Schristos wdog_status = enabled; 9004e98e3e1Schristos break; 9014e98e3e1Schristos 9024e98e3e1Schristos case MEC_TRAPD: /* 0x64 */ 9034e98e3e1Schristos if (wdog_status == init) { 9044e98e3e1Schristos wdog_status = disabled; 9054e98e3e1Schristos if (sis_verbose) 9064e98e3e1Schristos printf("Watchdog disabled\n"); 9074e98e3e1Schristos } 9084e98e3e1Schristos break; 9094e98e3e1Schristos 9104e98e3e1Schristos case MEC_PWDR: 9114e98e3e1Schristos if (mec_mcr & 1) 9124e98e3e1Schristos wait_for_irq(); 9134e98e3e1Schristos break; 9144e98e3e1Schristos 9154e98e3e1Schristos default: 9164e98e3e1Schristos set_sfsr(MEC_ACC, addr, 0xb, 0); 917212397c6Schristos return 1; 9184e98e3e1Schristos break; 9194e98e3e1Schristos } 920212397c6Schristos return MOK; 9214e98e3e1Schristos } 9224e98e3e1Schristos 9234e98e3e1Schristos 9244e98e3e1Schristos /* MEC UARTS */ 9254e98e3e1Schristos 9264e98e3e1Schristos static int ifd1 = -1, ifd2 = -1, ofd1 = -1, ofd2 = -1; 9274e98e3e1Schristos 9284e98e3e1Schristos void 9294b169a6bSchristos init_stdio(void) 9304e98e3e1Schristos { 9314e98e3e1Schristos if (dumbio) 9324e98e3e1Schristos return; /* do nothing */ 9334b169a6bSchristos #ifdef HAVE_TERMIOS_H 9344e98e3e1Schristos if (!ifd1) 9354e98e3e1Schristos tcsetattr(0, TCSANOW, &ioc1); 9364e98e3e1Schristos if (!ifd2) 9374e98e3e1Schristos tcsetattr(0, TCSANOW, &ioc2); 9384b169a6bSchristos #endif 9394e98e3e1Schristos } 9404e98e3e1Schristos 9414e98e3e1Schristos void 9424b169a6bSchristos restore_stdio(void) 9434e98e3e1Schristos { 9444e98e3e1Schristos if (dumbio) 9454e98e3e1Schristos return; /* do nothing */ 9464b169a6bSchristos #ifdef HAVE_TERMIOS_H 9474e98e3e1Schristos if (!ifd1) 9484e98e3e1Schristos tcsetattr(0, TCSANOW, &iocold1); 9494e98e3e1Schristos if (!ifd2) 9504e98e3e1Schristos tcsetattr(0, TCSANOW, &iocold2); 9514b169a6bSchristos #endif 9524e98e3e1Schristos } 9534e98e3e1Schristos 9544e98e3e1Schristos #define DO_STDIO_READ( _fd_, _buf_, _len_ ) \ 9554e98e3e1Schristos ( dumbio \ 9564e98e3e1Schristos ? (0) /* no bytes read, no delay */ \ 9574e98e3e1Schristos : read( _fd_, _buf_, _len_ ) ) 9584e98e3e1Schristos 9594e98e3e1Schristos 9604e98e3e1Schristos static void 9614b169a6bSchristos port_init(void) 9624e98e3e1Schristos { 9634e98e3e1Schristos 9644e98e3e1Schristos if (uben) { 9654e98e3e1Schristos f2in = stdin; 9664e98e3e1Schristos f1in = NULL; 9674e98e3e1Schristos f2out = stdout; 9684e98e3e1Schristos f1out = NULL; 9694e98e3e1Schristos } else { 9704e98e3e1Schristos f1in = stdin; 9714e98e3e1Schristos f2in = NULL; 9724e98e3e1Schristos f1out = stdout; 9734e98e3e1Schristos f2out = NULL; 9744e98e3e1Schristos } 9754b169a6bSchristos if (uart_dev1[0] != 0) { 9764e98e3e1Schristos if ((fd1 = open(uart_dev1, O_RDWR | O_NONBLOCK)) < 0) { 9774e98e3e1Schristos printf("Warning, couldn't open output device %s\n", uart_dev1); 9784e98e3e1Schristos } else { 9794e98e3e1Schristos if (sis_verbose) 9804e98e3e1Schristos printf("serial port A on %s\n", uart_dev1); 9814e98e3e1Schristos f1in = f1out = fdopen(fd1, "r+"); 9824e98e3e1Schristos setbuf(f1out, NULL); 9834e98e3e1Schristos f1open = 1; 9844e98e3e1Schristos } 9854b169a6bSchristos } 9864e98e3e1Schristos if (f1in) ifd1 = fileno(f1in); 9874e98e3e1Schristos if (ifd1 == 0) { 9884e98e3e1Schristos if (sis_verbose) 9894e98e3e1Schristos printf("serial port A on stdin/stdout\n"); 9904e98e3e1Schristos if (!dumbio) { 9914b169a6bSchristos #ifdef HAVE_TERMIOS_H 9924e98e3e1Schristos tcgetattr(ifd1, &ioc1); 9934e98e3e1Schristos iocold1 = ioc1; 9944e98e3e1Schristos ioc1.c_lflag &= ~(ICANON | ECHO); 9954e98e3e1Schristos ioc1.c_cc[VMIN] = 0; 9964e98e3e1Schristos ioc1.c_cc[VTIME] = 0; 9974b169a6bSchristos #endif 9984e98e3e1Schristos } 9994e98e3e1Schristos f1open = 1; 10004e98e3e1Schristos } 10014e98e3e1Schristos 10024e98e3e1Schristos if (f1out) { 10034e98e3e1Schristos ofd1 = fileno(f1out); 10044e98e3e1Schristos if (!dumbio && ofd1 == 1) setbuf(f1out, NULL); 10054e98e3e1Schristos } 10064e98e3e1Schristos 10074b169a6bSchristos if (uart_dev2[0] != 0) { 10084e98e3e1Schristos if ((fd2 = open(uart_dev2, O_RDWR | O_NONBLOCK)) < 0) { 10094e98e3e1Schristos printf("Warning, couldn't open output device %s\n", uart_dev2); 10104e98e3e1Schristos } else { 10114e98e3e1Schristos if (sis_verbose) 10124e98e3e1Schristos printf("serial port B on %s\n", uart_dev2); 10134e98e3e1Schristos f2in = f2out = fdopen(fd2, "r+"); 10144e98e3e1Schristos setbuf(f2out, NULL); 10154e98e3e1Schristos f2open = 1; 10164e98e3e1Schristos } 10174b169a6bSchristos } 10184e98e3e1Schristos if (f2in) ifd2 = fileno(f2in); 10194e98e3e1Schristos if (ifd2 == 0) { 10204e98e3e1Schristos if (sis_verbose) 10214e98e3e1Schristos printf("serial port B on stdin/stdout\n"); 10224e98e3e1Schristos if (!dumbio) { 10234b169a6bSchristos #ifdef HAVE_TERMIOS_H 10244e98e3e1Schristos tcgetattr(ifd2, &ioc2); 10254e98e3e1Schristos iocold2 = ioc2; 10264e98e3e1Schristos ioc2.c_lflag &= ~(ICANON | ECHO); 10274e98e3e1Schristos ioc2.c_cc[VMIN] = 0; 10284e98e3e1Schristos ioc2.c_cc[VTIME] = 0; 10294b169a6bSchristos #endif 10304e98e3e1Schristos } 10314e98e3e1Schristos f2open = 1; 10324e98e3e1Schristos } 10334e98e3e1Schristos 10344e98e3e1Schristos if (f2out) { 10354e98e3e1Schristos ofd2 = fileno(f2out); 10364e98e3e1Schristos if (!dumbio && ofd2 == 1) setbuf(f2out, NULL); 10374e98e3e1Schristos } 10384e98e3e1Schristos 10394e98e3e1Schristos wnuma = wnumb = 0; 10404e98e3e1Schristos 10414e98e3e1Schristos } 10424e98e3e1Schristos 10434b169a6bSchristos static uint32_t 10444b169a6bSchristos read_uart(uint32_t addr) 10454e98e3e1Schristos { 10464e98e3e1Schristos switch (addr & 0xff) { 10474e98e3e1Schristos 10484e98e3e1Schristos case 0xE0: /* UART 1 */ 10494e98e3e1Schristos #ifndef _WIN32 10504e98e3e1Schristos #ifdef FAST_UART 10514e98e3e1Schristos 10524e98e3e1Schristos if (aind < anum) { 10534e98e3e1Schristos if ((aind + 1) < anum) 10544e98e3e1Schristos mec_irq(4); 10554b169a6bSchristos return (0x700 | (uint32_t) aq[aind++]); 10564e98e3e1Schristos } else { 10574e98e3e1Schristos if (f1open) { 10584e98e3e1Schristos anum = DO_STDIO_READ(ifd1, aq, UARTBUF); 10594e98e3e1Schristos } 10604e98e3e1Schristos if (anum > 0) { 10614e98e3e1Schristos aind = 0; 10624e98e3e1Schristos if ((aind + 1) < anum) 10634e98e3e1Schristos mec_irq(4); 10644b169a6bSchristos return (0x700 | (uint32_t) aq[aind++]); 10654e98e3e1Schristos } else { 10664b169a6bSchristos return (0x600 | (uint32_t) aq[aind]); 10674e98e3e1Schristos } 10684e98e3e1Schristos 10694e98e3e1Schristos } 10704e98e3e1Schristos #else 1071*1f4e7eb9Schristos unsigned tmp = uarta_data; 10724e98e3e1Schristos uarta_data &= ~UART_DR; 10734e98e3e1Schristos uart_stat_reg &= ~UARTA_DR; 10744e98e3e1Schristos return tmp; 10754e98e3e1Schristos #endif 10764e98e3e1Schristos #else 1077212397c6Schristos return 0; 10784e98e3e1Schristos #endif 10794e98e3e1Schristos break; 10804e98e3e1Schristos 10814e98e3e1Schristos case 0xE4: /* UART 2 */ 10824e98e3e1Schristos #ifndef _WIN32 10834e98e3e1Schristos #ifdef FAST_UART 10844e98e3e1Schristos if (bind < bnum) { 10854e98e3e1Schristos if ((bind + 1) < bnum) 10864e98e3e1Schristos mec_irq(5); 10874b169a6bSchristos return (0x700 | (uint32_t) bq[bind++]); 10884e98e3e1Schristos } else { 10894e98e3e1Schristos if (f2open) { 10904e98e3e1Schristos bnum = DO_STDIO_READ(ifd2, bq, UARTBUF); 10914e98e3e1Schristos } 10924e98e3e1Schristos if (bnum > 0) { 10934e98e3e1Schristos bind = 0; 10944e98e3e1Schristos if ((bind + 1) < bnum) 10954e98e3e1Schristos mec_irq(5); 10964b169a6bSchristos return (0x700 | (uint32_t) bq[bind++]); 10974e98e3e1Schristos } else { 10984b169a6bSchristos return (0x600 | (uint32_t) bq[bind]); 10994e98e3e1Schristos } 11004e98e3e1Schristos 11014e98e3e1Schristos } 11024e98e3e1Schristos #else 1103*1f4e7eb9Schristos unsigned tmp = uartb_data; 11044e98e3e1Schristos uartb_data &= ~UART_DR; 11054e98e3e1Schristos uart_stat_reg &= ~UARTB_DR; 11064e98e3e1Schristos return tmp; 11074e98e3e1Schristos #endif 11084e98e3e1Schristos #else 1109212397c6Schristos return 0; 11104e98e3e1Schristos #endif 11114e98e3e1Schristos break; 11124e98e3e1Schristos 11134e98e3e1Schristos case 0xE8: /* UART status register */ 11144e98e3e1Schristos #ifndef _WIN32 11154e98e3e1Schristos #ifdef FAST_UART 11164e98e3e1Schristos 11174e98e3e1Schristos Ucontrol = 0; 11184e98e3e1Schristos if (aind < anum) { 11194e98e3e1Schristos Ucontrol |= 0x00000001; 11204e98e3e1Schristos } else { 11214e98e3e1Schristos if (f1open) { 11224e98e3e1Schristos anum = DO_STDIO_READ(ifd1, aq, UARTBUF); 11234e98e3e1Schristos } 11244e98e3e1Schristos if (anum > 0) { 11254e98e3e1Schristos Ucontrol |= 0x00000001; 11264e98e3e1Schristos aind = 0; 11274e98e3e1Schristos mec_irq(4); 11284e98e3e1Schristos } 11294e98e3e1Schristos } 11304e98e3e1Schristos if (bind < bnum) { 11314e98e3e1Schristos Ucontrol |= 0x00010000; 11324e98e3e1Schristos } else { 11334e98e3e1Schristos if (f2open) { 11344e98e3e1Schristos bnum = DO_STDIO_READ(ifd2, bq, UARTBUF); 11354e98e3e1Schristos } 11364e98e3e1Schristos if (bnum > 0) { 11374e98e3e1Schristos Ucontrol |= 0x00010000; 11384e98e3e1Schristos bind = 0; 11394e98e3e1Schristos mec_irq(5); 11404e98e3e1Schristos } 11414e98e3e1Schristos } 11424e98e3e1Schristos 11434e98e3e1Schristos Ucontrol |= 0x00060006; 1144212397c6Schristos return Ucontrol; 11454e98e3e1Schristos #else 1146212397c6Schristos return uart_stat_reg; 11474e98e3e1Schristos #endif 11484e98e3e1Schristos #else 1149212397c6Schristos return 0x00060006; 11504e98e3e1Schristos #endif 11514e98e3e1Schristos break; 11524e98e3e1Schristos default: 11534e98e3e1Schristos if (sis_verbose) 11544e98e3e1Schristos printf("Read from unimplemented MEC register (%x)\n", addr); 11554e98e3e1Schristos 11564e98e3e1Schristos } 1157212397c6Schristos return 0; 11584e98e3e1Schristos } 11594e98e3e1Schristos 11604e98e3e1Schristos static void 11614b169a6bSchristos write_uart(uint32_t addr, uint32_t data) 11624e98e3e1Schristos { 11634e98e3e1Schristos unsigned char c; 11644e98e3e1Schristos 11654e98e3e1Schristos c = (unsigned char) data; 11664e98e3e1Schristos switch (addr & 0xff) { 11674e98e3e1Schristos 11684e98e3e1Schristos case 0xE0: /* UART A */ 11694e98e3e1Schristos #ifdef FAST_UART 11704e98e3e1Schristos if (f1open) { 11714e98e3e1Schristos if (wnuma < UARTBUF) 11724e98e3e1Schristos wbufa[wnuma++] = c; 11734e98e3e1Schristos else { 11744e98e3e1Schristos while (wnuma) 11754e98e3e1Schristos wnuma -= fwrite(wbufa, 1, wnuma, f1out); 11764e98e3e1Schristos wbufa[wnuma++] = c; 11774e98e3e1Schristos } 11784e98e3e1Schristos } 11794e98e3e1Schristos mec_irq(4); 11804e98e3e1Schristos #else 11814e98e3e1Schristos if (uart_stat_reg & UARTA_SRE) { 11824e98e3e1Schristos uarta_sreg = c; 11834e98e3e1Schristos uart_stat_reg &= ~UARTA_SRE; 11844e98e3e1Schristos event(uarta_tx, 0, UART_TX_TIME); 11854e98e3e1Schristos } else { 11864e98e3e1Schristos uarta_hreg = c; 11874e98e3e1Schristos uart_stat_reg &= ~UARTA_HRE; 11884e98e3e1Schristos } 11894e98e3e1Schristos #endif 11904e98e3e1Schristos break; 11914e98e3e1Schristos 11924e98e3e1Schristos case 0xE4: /* UART B */ 11934e98e3e1Schristos #ifdef FAST_UART 11944e98e3e1Schristos if (f2open) { 11954e98e3e1Schristos if (wnumb < UARTBUF) 11964e98e3e1Schristos wbufb[wnumb++] = c; 11974e98e3e1Schristos else { 11984e98e3e1Schristos while (wnumb) 11994e98e3e1Schristos wnumb -= fwrite(wbufb, 1, wnumb, f2out); 12004e98e3e1Schristos wbufb[wnumb++] = c; 12014e98e3e1Schristos } 12024e98e3e1Schristos } 12034e98e3e1Schristos mec_irq(5); 12044e98e3e1Schristos #else 12054e98e3e1Schristos if (uart_stat_reg & UARTB_SRE) { 12064e98e3e1Schristos uartb_sreg = c; 12074e98e3e1Schristos uart_stat_reg &= ~UARTB_SRE; 12084e98e3e1Schristos event(uartb_tx, 0, UART_TX_TIME); 12094e98e3e1Schristos } else { 12104e98e3e1Schristos uartb_hreg = c; 12114e98e3e1Schristos uart_stat_reg &= ~UARTB_HRE; 12124e98e3e1Schristos } 12134e98e3e1Schristos #endif 12144e98e3e1Schristos break; 12154e98e3e1Schristos case 0xE8: /* UART status register */ 12164e98e3e1Schristos #ifndef FAST_UART 12174e98e3e1Schristos if (data & UARTA_CLR) { 12184e98e3e1Schristos uart_stat_reg &= 0xFFFF0000; 12194e98e3e1Schristos uart_stat_reg |= UARTA_SRE | UARTA_HRE; 12204e98e3e1Schristos } 12214e98e3e1Schristos if (data & UARTB_CLR) { 12224e98e3e1Schristos uart_stat_reg &= 0x0000FFFF; 12234e98e3e1Schristos uart_stat_reg |= UARTB_SRE | UARTB_HRE; 12244e98e3e1Schristos } 12254e98e3e1Schristos #endif 12264e98e3e1Schristos break; 12274e98e3e1Schristos default: 12284e98e3e1Schristos if (sis_verbose) 12294e98e3e1Schristos printf("Write to unimplemented MEC register (%x)\n", addr); 12304e98e3e1Schristos 12314e98e3e1Schristos } 12324e98e3e1Schristos } 12334e98e3e1Schristos 12344e98e3e1Schristos static void 12354b169a6bSchristos flush_uart(void) 12364e98e3e1Schristos { 12374e98e3e1Schristos while (wnuma && f1open) 12384e98e3e1Schristos wnuma -= fwrite(wbufa, 1, wnuma, f1out); 12394e98e3e1Schristos while (wnumb && f2open) 12404e98e3e1Schristos wnumb -= fwrite(wbufb, 1, wnumb, f2out); 12414e98e3e1Schristos } 12424e98e3e1Schristos 12434b169a6bSchristos ATTRIBUTE_UNUSED 12444e98e3e1Schristos static void 12454b169a6bSchristos uarta_tx(int32_t arg ATTRIBUTE_UNUSED) 12464e98e3e1Schristos { 12474e98e3e1Schristos 12484e98e3e1Schristos while (f1open && fwrite(&uarta_sreg, 1, 1, f1out) != 1); 12494e98e3e1Schristos if (uart_stat_reg & UARTA_HRE) { 12504e98e3e1Schristos uart_stat_reg |= UARTA_SRE; 12514e98e3e1Schristos } else { 12524e98e3e1Schristos uarta_sreg = uarta_hreg; 12534e98e3e1Schristos uart_stat_reg |= UARTA_HRE; 12544e98e3e1Schristos event(uarta_tx, 0, UART_TX_TIME); 12554e98e3e1Schristos } 12564e98e3e1Schristos mec_irq(4); 12574e98e3e1Schristos } 12584e98e3e1Schristos 12594b169a6bSchristos ATTRIBUTE_UNUSED 12604e98e3e1Schristos static void 12614b169a6bSchristos uartb_tx(int32_t arg ATTRIBUTE_UNUSED) 12624e98e3e1Schristos { 12634e98e3e1Schristos while (f2open && fwrite(&uartb_sreg, 1, 1, f2out) != 1); 12644e98e3e1Schristos if (uart_stat_reg & UARTB_HRE) { 12654e98e3e1Schristos uart_stat_reg |= UARTB_SRE; 12664e98e3e1Schristos } else { 12674e98e3e1Schristos uartb_sreg = uartb_hreg; 12684e98e3e1Schristos uart_stat_reg |= UARTB_HRE; 12694e98e3e1Schristos event(uartb_tx, 0, UART_TX_TIME); 12704e98e3e1Schristos } 12714e98e3e1Schristos mec_irq(5); 12724e98e3e1Schristos } 12734e98e3e1Schristos 12744b169a6bSchristos ATTRIBUTE_UNUSED 12754e98e3e1Schristos static void 12764b169a6bSchristos uart_rx(int32_t arg ATTRIBUTE_UNUSED) 12774e98e3e1Schristos { 12784b169a6bSchristos int32_t rsize; 12794e98e3e1Schristos char rxd; 12804e98e3e1Schristos 12814e98e3e1Schristos 12824e98e3e1Schristos rsize = 0; 12834e98e3e1Schristos if (f1open) 12844e98e3e1Schristos rsize = DO_STDIO_READ(ifd1, &rxd, 1); 12854e98e3e1Schristos if (rsize > 0) { 12864e98e3e1Schristos uarta_data = UART_DR | rxd; 12874e98e3e1Schristos if (uart_stat_reg & UARTA_HRE) 12884e98e3e1Schristos uarta_data |= UART_THE; 12894e98e3e1Schristos if (uart_stat_reg & UARTA_SRE) 12904e98e3e1Schristos uarta_data |= UART_TSE; 12914e98e3e1Schristos if (uart_stat_reg & UARTA_DR) { 12924e98e3e1Schristos uart_stat_reg |= UARTA_OR; 12934e98e3e1Schristos mec_irq(7); /* UART error interrupt */ 12944e98e3e1Schristos } 12954e98e3e1Schristos uart_stat_reg |= UARTA_DR; 12964e98e3e1Schristos mec_irq(4); 12974e98e3e1Schristos } 12984e98e3e1Schristos rsize = 0; 12994e98e3e1Schristos if (f2open) 13004e98e3e1Schristos rsize = DO_STDIO_READ(ifd2, &rxd, 1); 13014e98e3e1Schristos if (rsize) { 13024e98e3e1Schristos uartb_data = UART_DR | rxd; 13034e98e3e1Schristos if (uart_stat_reg & UARTB_HRE) 13044e98e3e1Schristos uartb_data |= UART_THE; 13054e98e3e1Schristos if (uart_stat_reg & UARTB_SRE) 13064e98e3e1Schristos uartb_data |= UART_TSE; 13074e98e3e1Schristos if (uart_stat_reg & UARTB_DR) { 13084e98e3e1Schristos uart_stat_reg |= UARTB_OR; 13094e98e3e1Schristos mec_irq(7); /* UART error interrupt */ 13104e98e3e1Schristos } 13114e98e3e1Schristos uart_stat_reg |= UARTB_DR; 13124e98e3e1Schristos mec_irq(5); 13134e98e3e1Schristos } 13144e98e3e1Schristos event(uart_rx, 0, UART_RX_TIME); 13154e98e3e1Schristos } 13164e98e3e1Schristos 13174e98e3e1Schristos static void 13184b169a6bSchristos uart_intr(int32_t arg ATTRIBUTE_UNUSED) 13194e98e3e1Schristos { 13204e98e3e1Schristos read_uart(0xE8); /* Check for UART interrupts every 1000 clk */ 13214e98e3e1Schristos flush_uart(); /* Flush UART ports */ 13224e98e3e1Schristos event(uart_intr, 0, UART_FLUSH_TIME); 13234e98e3e1Schristos } 13244e98e3e1Schristos 13254e98e3e1Schristos 13264e98e3e1Schristos static void 13274b169a6bSchristos uart_irq_start(void) 13284e98e3e1Schristos { 13294e98e3e1Schristos #ifdef FAST_UART 13304e98e3e1Schristos event(uart_intr, 0, UART_FLUSH_TIME); 13314e98e3e1Schristos #else 13324e98e3e1Schristos #ifndef _WIN32 13334e98e3e1Schristos event(uart_rx, 0, UART_RX_TIME); 13344e98e3e1Schristos #endif 13354e98e3e1Schristos #endif 13364e98e3e1Schristos } 13374e98e3e1Schristos 13384e98e3e1Schristos /* Watch-dog */ 13394e98e3e1Schristos 13404e98e3e1Schristos static void 13414b169a6bSchristos wdog_intr(int32_t arg ATTRIBUTE_UNUSED) 13424e98e3e1Schristos { 13434e98e3e1Schristos if (wdog_status == disabled) { 13444e98e3e1Schristos wdog_status = stopped; 13454e98e3e1Schristos } else { 13464e98e3e1Schristos 13474e98e3e1Schristos if (wdog_counter) { 13484e98e3e1Schristos wdog_counter--; 13494e98e3e1Schristos event(wdog_intr, 0, wdog_scaler + 1); 13504e98e3e1Schristos } else { 13514e98e3e1Schristos if (wdog_rston) { 13524e98e3e1Schristos printf("Watchdog reset!\n"); 13534e98e3e1Schristos sys_reset(); 13544e98e3e1Schristos mec_ersr = 0xC000; 13554e98e3e1Schristos } else { 13564e98e3e1Schristos mec_irq(15); 13574e98e3e1Schristos wdog_rston = 1; 13584e98e3e1Schristos wdog_counter = wdog_rst_delay; 13594e98e3e1Schristos event(wdog_intr, 0, wdog_scaler + 1); 13604e98e3e1Schristos } 13614e98e3e1Schristos } 13624e98e3e1Schristos } 13634e98e3e1Schristos } 13644e98e3e1Schristos 13654e98e3e1Schristos static void 13664b169a6bSchristos wdog_start(void) 13674e98e3e1Schristos { 13684e98e3e1Schristos event(wdog_intr, 0, wdog_scaler + 1); 13694e98e3e1Schristos if (sis_verbose) 13704e98e3e1Schristos printf("Watchdog started, scaler = %d, counter = %d\n", 13714e98e3e1Schristos wdog_scaler, wdog_counter); 13724e98e3e1Schristos } 13734e98e3e1Schristos 13744e98e3e1Schristos 13754e98e3e1Schristos /* MEC timers */ 13764e98e3e1Schristos 13774e98e3e1Schristos 13784e98e3e1Schristos static void 13794b169a6bSchristos rtc_intr(int32_t arg ATTRIBUTE_UNUSED) 13804e98e3e1Schristos { 13814e98e3e1Schristos if (rtc_counter == 0) { 13824e98e3e1Schristos 13834e98e3e1Schristos mec_irq(13); 13844e98e3e1Schristos if (rtc_cr) 13854e98e3e1Schristos rtc_counter = rtc_reload; 13864e98e3e1Schristos else 13874e98e3e1Schristos rtc_se = 0; 13884e98e3e1Schristos } else 13894e98e3e1Schristos rtc_counter -= 1; 13904e98e3e1Schristos if (rtc_se) { 13914e98e3e1Schristos event(rtc_intr, 0, rtc_scaler + 1); 13924e98e3e1Schristos rtc_scaler_start = now(); 13934e98e3e1Schristos rtc_enabled = 1; 13944e98e3e1Schristos } else { 13954e98e3e1Schristos if (sis_verbose) 13964e98e3e1Schristos printf("RTC stopped\n\r"); 13974e98e3e1Schristos rtc_enabled = 0; 13984e98e3e1Schristos } 13994e98e3e1Schristos } 14004e98e3e1Schristos 14014e98e3e1Schristos static void 14024b169a6bSchristos rtc_start(void) 14034e98e3e1Schristos { 14044e98e3e1Schristos if (sis_verbose) 14054e98e3e1Schristos printf("RTC started (period %d)\n\r", rtc_scaler + 1); 14064e98e3e1Schristos event(rtc_intr, 0, rtc_scaler + 1); 14074e98e3e1Schristos rtc_scaler_start = now(); 14084e98e3e1Schristos rtc_enabled = 1; 14094e98e3e1Schristos } 14104e98e3e1Schristos 14114b169a6bSchristos static uint32_t 14124b169a6bSchristos rtc_counter_read(void) 14134e98e3e1Schristos { 1414212397c6Schristos return rtc_counter; 14154e98e3e1Schristos } 14164e98e3e1Schristos 14174e98e3e1Schristos static void 14184b169a6bSchristos rtc_scaler_set(uint32_t val) 14194e98e3e1Schristos { 14204e98e3e1Schristos rtc_scaler = val & 0x0ff; /* eight-bit scaler only */ 14214e98e3e1Schristos } 14224e98e3e1Schristos 14234e98e3e1Schristos static void 14244b169a6bSchristos rtc_reload_set(uint32_t val) 14254e98e3e1Schristos { 14264e98e3e1Schristos rtc_reload = val; 14274e98e3e1Schristos } 14284e98e3e1Schristos 14294e98e3e1Schristos static void 14304b169a6bSchristos gpt_intr(int32_t arg ATTRIBUTE_UNUSED) 14314e98e3e1Schristos { 14324e98e3e1Schristos if (gpt_counter == 0) { 14334e98e3e1Schristos mec_irq(12); 14344e98e3e1Schristos if (gpt_cr) 14354e98e3e1Schristos gpt_counter = gpt_reload; 14364e98e3e1Schristos else 14374e98e3e1Schristos gpt_se = 0; 14384e98e3e1Schristos } else 14394e98e3e1Schristos gpt_counter -= 1; 14404e98e3e1Schristos if (gpt_se) { 14414e98e3e1Schristos event(gpt_intr, 0, gpt_scaler + 1); 14424e98e3e1Schristos gpt_scaler_start = now(); 14434e98e3e1Schristos gpt_enabled = 1; 14444e98e3e1Schristos } else { 14454e98e3e1Schristos if (sis_verbose) 14464e98e3e1Schristos printf("GPT stopped\n\r"); 14474e98e3e1Schristos gpt_enabled = 0; 14484e98e3e1Schristos } 14494e98e3e1Schristos } 14504e98e3e1Schristos 14514e98e3e1Schristos static void 14524b169a6bSchristos gpt_start(void) 14534e98e3e1Schristos { 14544e98e3e1Schristos if (sis_verbose) 14554e98e3e1Schristos printf("GPT started (period %d)\n\r", gpt_scaler + 1); 14564e98e3e1Schristos event(gpt_intr, 0, gpt_scaler + 1); 14574e98e3e1Schristos gpt_scaler_start = now(); 14584e98e3e1Schristos gpt_enabled = 1; 14594e98e3e1Schristos } 14604e98e3e1Schristos 14614b169a6bSchristos static uint32_t 14624b169a6bSchristos gpt_counter_read(void) 14634e98e3e1Schristos { 1464212397c6Schristos return gpt_counter; 14654e98e3e1Schristos } 14664e98e3e1Schristos 14674e98e3e1Schristos static void 14684b169a6bSchristos gpt_scaler_set(uint32_t val) 14694e98e3e1Schristos { 14704e98e3e1Schristos gpt_scaler = val & 0x0ffff; /* 16-bit scaler */ 14714e98e3e1Schristos } 14724e98e3e1Schristos 14734e98e3e1Schristos static void 14744b169a6bSchristos gpt_reload_set(uint32_t val) 14754e98e3e1Schristos { 14764e98e3e1Schristos gpt_reload = val; 14774e98e3e1Schristos } 14784e98e3e1Schristos 14794e98e3e1Schristos static void 14804b169a6bSchristos timer_ctrl(uint32_t val) 14814e98e3e1Schristos { 14824e98e3e1Schristos 14834e98e3e1Schristos rtc_cr = ((val & TCR_TCRCR) != 0); 14844e98e3e1Schristos if (val & TCR_TCRCL) { 14854e98e3e1Schristos rtc_counter = rtc_reload; 14864e98e3e1Schristos } 14874e98e3e1Schristos if (val & TCR_TCRSL) { 14884e98e3e1Schristos } 14894e98e3e1Schristos rtc_se = ((val & TCR_TCRSE) != 0); 14904e98e3e1Schristos if (rtc_se && (rtc_enabled == 0)) 14914e98e3e1Schristos rtc_start(); 14924e98e3e1Schristos 14934e98e3e1Schristos gpt_cr = (val & TCR_GACR); 14944e98e3e1Schristos if (val & TCR_GACL) { 14954e98e3e1Schristos gpt_counter = gpt_reload; 14964e98e3e1Schristos } 14974e98e3e1Schristos if (val & TCR_GACL) { 14984e98e3e1Schristos } 14994e98e3e1Schristos gpt_se = (val & TCR_GASE) >> 2; 15004e98e3e1Schristos if (gpt_se && (gpt_enabled == 0)) 15014e98e3e1Schristos gpt_start(); 15024e98e3e1Schristos } 15034e98e3e1Schristos 1504212397c6Schristos /* Store data in host byte order. MEM points to the beginning of the 1505212397c6Schristos emulated memory; WADDR contains the index the emulated memory, 15064e98e3e1Schristos DATA points to words in host byte order to be stored. SZ contains log(2) 15074e98e3e1Schristos of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word), 1508212397c6Schristos 2 (one word), or 3 (two words); WS should return the number of 1509212397c6Schristos wait-states. */ 15104e98e3e1Schristos 15114e98e3e1Schristos static void 15124b169a6bSchristos store_bytes (unsigned char *mem, uint32_t waddr, uint32_t *data, int32_t sz, 15134b169a6bSchristos int32_t *ws) 15144e98e3e1Schristos { 15154e98e3e1Schristos switch (sz) { 15164e98e3e1Schristos case 0: 1517212397c6Schristos waddr ^= EBT; 1518212397c6Schristos mem[waddr] = *data & 0x0ff; 1519212397c6Schristos *ws = mem_ramw_ws + 3; 15204e98e3e1Schristos break; 15214e98e3e1Schristos case 1: 1522212397c6Schristos #ifdef HOST_LITTLE_ENDIAN 1523212397c6Schristos waddr ^= 2; 1524212397c6Schristos #endif 1525212397c6Schristos memcpy (&mem[waddr], data, 2); 1526212397c6Schristos *ws = mem_ramw_ws + 3; 15274e98e3e1Schristos break; 1528212397c6Schristos case 2: 1529212397c6Schristos memcpy (&mem[waddr], data, 4); 1530212397c6Schristos *ws = mem_ramw_ws; 15314e98e3e1Schristos break; 1532212397c6Schristos case 3: 1533212397c6Schristos memcpy (&mem[waddr], data, 8); 1534212397c6Schristos *ws = 2 * mem_ramw_ws + STD_WS; 1535212397c6Schristos break; 15364e98e3e1Schristos } 15374e98e3e1Schristos } 15384e98e3e1Schristos 15394e98e3e1Schristos 15404e98e3e1Schristos /* Memory emulation */ 15414e98e3e1Schristos 15424e98e3e1Schristos int 15434b169a6bSchristos memory_iread (uint32_t addr, uint32_t *data, uint32_t *ws) 1544212397c6Schristos { 15454b169a6bSchristos uint32_t asi; 1546212397c6Schristos if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) { 1547212397c6Schristos memcpy (data, &ramb[addr & mem_rammask & ~3], 4); 1548212397c6Schristos *ws = mem_ramr_ws; 1549212397c6Schristos return 0; 1550212397c6Schristos } else if (addr < mem_romsz) { 1551212397c6Schristos memcpy (data, &romb[addr & ~3], 4); 1552212397c6Schristos *ws = mem_romr_ws; 1553212397c6Schristos return 0; 1554212397c6Schristos } 1555212397c6Schristos 1556212397c6Schristos if (sis_verbose) 1557212397c6Schristos printf ("Memory exception at %x (illegal address)\n", addr); 1558212397c6Schristos if (sregs.psr & 0x080) 1559212397c6Schristos asi = 9; 1560212397c6Schristos else 1561212397c6Schristos asi = 8; 1562212397c6Schristos set_sfsr (UIMP_ACC, addr, asi, 1); 1563212397c6Schristos *ws = MEM_EX_WS; 1564212397c6Schristos return 1; 1565212397c6Schristos } 1566212397c6Schristos 1567212397c6Schristos int 15684b169a6bSchristos memory_read(int32_t asi, uint32_t addr, void *data, int32_t sz, int32_t *ws) 15694e98e3e1Schristos { 15704b169a6bSchristos int32_t mexc; 15714e98e3e1Schristos 15724e98e3e1Schristos #ifdef ERRINJ 15734e98e3e1Schristos if (errmec) { 15744e98e3e1Schristos if (sis_verbose) 15754e98e3e1Schristos printf("Inserted MEC error %d\n",errmec); 15764e98e3e1Schristos set_sfsr(errmec, addr, asi, 1); 15774e98e3e1Schristos if (errmec == 5) mecparerror(); 15784e98e3e1Schristos if (errmec == 6) iucomperr(); 15794e98e3e1Schristos errmec = 0; 1580212397c6Schristos return 1; 15814e98e3e1Schristos } 15824e98e3e1Schristos #endif 15834e98e3e1Schristos 15844e98e3e1Schristos if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) { 1585212397c6Schristos memcpy (data, &ramb[addr & mem_rammask & ~3], 4); 15864e98e3e1Schristos *ws = mem_ramr_ws; 1587212397c6Schristos return 0; 15884e98e3e1Schristos } else if ((addr >= MEC_START) && (addr < MEC_END)) { 15894e98e3e1Schristos mexc = mec_read(addr, asi, data); 15904e98e3e1Schristos if (mexc) { 15914e98e3e1Schristos set_sfsr(MEC_ACC, addr, asi, 1); 15924e98e3e1Schristos *ws = MEM_EX_WS; 15934e98e3e1Schristos } else { 15944e98e3e1Schristos *ws = 0; 15954e98e3e1Schristos } 1596212397c6Schristos return mexc; 15974e98e3e1Schristos 15984e98e3e1Schristos #ifdef ERA 15994e98e3e1Schristos 16004e98e3e1Schristos } else if (era) { 16014e98e3e1Schristos if ((addr < 0x100000) || 16024e98e3e1Schristos ((addr>= 0x80000000) && (addr < 0x80100000))) { 1603212397c6Schristos memcpy (data, &romb[addr & ROM_MASK & ~3], 4); 16044e98e3e1Schristos *ws = 4; 1605212397c6Schristos return 0; 16064e98e3e1Schristos } else if ((addr >= 0x10000000) && 16074e98e3e1Schristos (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) && 16084e98e3e1Schristos (mec_iocr & 0x10)) { 16094b169a6bSchristos memcpy (data, &erareg, 4); 1610212397c6Schristos return 0; 16114e98e3e1Schristos } 16124e98e3e1Schristos 16134e98e3e1Schristos } else if (addr < mem_romsz) { 1614212397c6Schristos memcpy (data, &romb[addr & ~3], 4); 16154e98e3e1Schristos *ws = mem_romr_ws; 1616212397c6Schristos return 0; 16174e98e3e1Schristos #else 16184e98e3e1Schristos } else if (addr < mem_romsz) { 1619212397c6Schristos memcpy (data, &romb[addr & ~3], 4); 16204e98e3e1Schristos *ws = mem_romr_ws; 1621212397c6Schristos return 0; 16224e98e3e1Schristos #endif 16234e98e3e1Schristos 16244e98e3e1Schristos } 16254e98e3e1Schristos 1626212397c6Schristos if (sis_verbose) 16274e98e3e1Schristos printf ("Memory exception at %x (illegal address)\n", addr); 16284e98e3e1Schristos set_sfsr(UIMP_ACC, addr, asi, 1); 16294e98e3e1Schristos *ws = MEM_EX_WS; 1630212397c6Schristos return 1; 16314e98e3e1Schristos } 16324e98e3e1Schristos 16334e98e3e1Schristos int 16344b169a6bSchristos memory_write(int32_t asi, uint32_t addr, uint32_t *data, int32_t sz, int32_t *ws) 16354e98e3e1Schristos { 16364b169a6bSchristos uint32_t waddr; 16374b169a6bSchristos int32_t mexc; 16384e98e3e1Schristos int i; 16394e98e3e1Schristos int wphit[2]; 16404e98e3e1Schristos 16414e98e3e1Schristos #ifdef ERRINJ 16424e98e3e1Schristos if (errmec) { 16434e98e3e1Schristos if (sis_verbose) 16444e98e3e1Schristos printf("Inserted MEC error %d\n",errmec); 16454e98e3e1Schristos set_sfsr(errmec, addr, asi, 0); 16464e98e3e1Schristos if (errmec == 5) mecparerror(); 16474e98e3e1Schristos if (errmec == 6) iucomperr(); 16484e98e3e1Schristos errmec = 0; 1649212397c6Schristos return 1; 16504e98e3e1Schristos } 16514e98e3e1Schristos #endif 16524e98e3e1Schristos 16534e98e3e1Schristos if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) { 16544e98e3e1Schristos if (mem_accprot) { 16554e98e3e1Schristos 16564e98e3e1Schristos waddr = (addr & 0x7fffff) >> 2; 16574e98e3e1Schristos for (i = 0; i < 2; i++) 16584e98e3e1Schristos wphit[i] = 16594e98e3e1Schristos (((asi == 0xa) && (mec_wpr[i] & 1)) || 16604e98e3e1Schristos ((asi == 0xb) && (mec_wpr[i] & 2))) && 16614e98e3e1Schristos ((waddr >= mec_ssa[i]) && ((waddr | (sz == 3)) < mec_sea[i])); 16624e98e3e1Schristos 16634e98e3e1Schristos if (((mem_blockprot) && (wphit[0] || wphit[1])) || 16644e98e3e1Schristos ((!mem_blockprot) && 16654e98e3e1Schristos !((mec_wpr[0] && wphit[0]) || (mec_wpr[1] && wphit[1])) 16664e98e3e1Schristos )) { 16674e98e3e1Schristos if (sis_verbose) 16684e98e3e1Schristos printf("Memory access protection error at 0x%08x\n", addr); 16694e98e3e1Schristos set_sfsr(PROT_EXC, addr, asi, 0); 16704e98e3e1Schristos *ws = MEM_EX_WS; 1671212397c6Schristos return 1; 16724e98e3e1Schristos } 16734e98e3e1Schristos } 1674212397c6Schristos waddr = addr & mem_rammask; 1675212397c6Schristos store_bytes (ramb, waddr, data, sz, ws); 1676212397c6Schristos return 0; 16774e98e3e1Schristos } else if ((addr >= MEC_START) && (addr < MEC_END)) { 16784e98e3e1Schristos if ((sz != 2) || (asi != 0xb)) { 16794e98e3e1Schristos set_sfsr(MEC_ACC, addr, asi, 0); 16804e98e3e1Schristos *ws = MEM_EX_WS; 1681212397c6Schristos return 1; 16824e98e3e1Schristos } 16834e98e3e1Schristos mexc = mec_write(addr, *data); 16844e98e3e1Schristos if (mexc) { 16854e98e3e1Schristos set_sfsr(MEC_ACC, addr, asi, 0); 16864e98e3e1Schristos *ws = MEM_EX_WS; 16874e98e3e1Schristos } else { 16884e98e3e1Schristos *ws = 0; 16894e98e3e1Schristos } 1690212397c6Schristos return mexc; 16914e98e3e1Schristos 16924e98e3e1Schristos #ifdef ERA 16934e98e3e1Schristos 16944e98e3e1Schristos } else if (era) { 16954e98e3e1Schristos if ((erareg & 2) && 16964e98e3e1Schristos ((addr < 0x100000) || ((addr >= 0x80000000) && (addr < 0x80100000)))) { 16974e98e3e1Schristos addr &= ROM_MASK; 16984e98e3e1Schristos *ws = sz == 3 ? 8 : 4; 1699212397c6Schristos store_bytes (romb, addr, data, sz, ws); 1700212397c6Schristos return 0; 17014e98e3e1Schristos } else if ((addr >= 0x10000000) && 17024e98e3e1Schristos (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) && 17034e98e3e1Schristos (mec_iocr & 0x10)) { 17044e98e3e1Schristos erareg = *data & 0x0e; 1705212397c6Schristos return 0; 17064e98e3e1Schristos } 17074e98e3e1Schristos 17084e98e3e1Schristos } else if ((addr < mem_romsz) && (mec_memcfg & 0x10000) && (wrp) && 17094e98e3e1Schristos (((mec_memcfg & 0x20000) && (sz > 1)) || 17104e98e3e1Schristos (!(mec_memcfg & 0x20000) && (sz == 0)))) { 17114e98e3e1Schristos 17124e98e3e1Schristos *ws = mem_romw_ws + 1; 17134e98e3e1Schristos if (sz == 3) 17144e98e3e1Schristos *ws += mem_romw_ws + STD_WS; 1715212397c6Schristos store_bytes (romb, addr, data, sz, ws); 1716212397c6Schristos return 0; 17174e98e3e1Schristos 17184e98e3e1Schristos #else 17194e98e3e1Schristos } else if ((addr < mem_romsz) && (mec_memcfg & 0x10000) && (wrp) && 17204e98e3e1Schristos (((mec_memcfg & 0x20000) && (sz > 1)) || 17214e98e3e1Schristos (!(mec_memcfg & 0x20000) && (sz == 0)))) { 17224e98e3e1Schristos 17234e98e3e1Schristos *ws = mem_romw_ws + 1; 17244e98e3e1Schristos if (sz == 3) 17254e98e3e1Schristos *ws += mem_romw_ws + STD_WS; 1726212397c6Schristos store_bytes (romb, addr, data, sz, ws); 1727212397c6Schristos return 0; 17284e98e3e1Schristos 17294e98e3e1Schristos #endif 17304e98e3e1Schristos 17314e98e3e1Schristos } 17324e98e3e1Schristos 17334e98e3e1Schristos *ws = MEM_EX_WS; 17344e98e3e1Schristos set_sfsr(UIMP_ACC, addr, asi, 0); 1735212397c6Schristos return 1; 17364e98e3e1Schristos } 17374e98e3e1Schristos 17384b169a6bSchristos static void * 17394b169a6bSchristos get_mem_ptr(uint32_t addr, uint32_t size) 17404e98e3e1Schristos { 17414e98e3e1Schristos if ((addr + size) < ROM_SZ) { 1742212397c6Schristos return &romb[addr]; 17434e98e3e1Schristos } else if ((addr >= mem_ramstart) && ((addr + size) < mem_ramend)) { 1744212397c6Schristos return &ramb[addr & mem_rammask]; 17454e98e3e1Schristos } 17464e98e3e1Schristos 17474e98e3e1Schristos #ifdef ERA 17484e98e3e1Schristos else if ((era) && ((addr <0x100000) || 17494e98e3e1Schristos ((addr >= (unsigned) 0x80000000) && ((addr + size) < (unsigned) 0x80100000)))) { 1750212397c6Schristos return &romb[addr & ROM_MASK]; 17514e98e3e1Schristos } 17524e98e3e1Schristos #endif 17534e98e3e1Schristos 17544b169a6bSchristos return (void *) -1; 17554e98e3e1Schristos } 17564e98e3e1Schristos 17574e98e3e1Schristos int 17584b169a6bSchristos sis_memory_write(uint32_t addr, const void *data, uint32_t length) 17594e98e3e1Schristos { 17604b169a6bSchristos void *mem; 17614e98e3e1Schristos 17624b169a6bSchristos if ((mem = get_mem_ptr(addr, length)) == ((void *) -1)) 1763212397c6Schristos return 0; 17644e98e3e1Schristos 17654e98e3e1Schristos memcpy(mem, data, length); 1766212397c6Schristos return length; 17674e98e3e1Schristos } 17684e98e3e1Schristos 17694e98e3e1Schristos int 17704b169a6bSchristos sis_memory_read(uint32_t addr, void *data, uint32_t length) 17714e98e3e1Schristos { 17724e98e3e1Schristos char *mem; 17734e98e3e1Schristos 17744b169a6bSchristos if ((mem = get_mem_ptr(addr, length)) == ((void *) -1)) 1775212397c6Schristos return 0; 17764e98e3e1Schristos 17774e98e3e1Schristos memcpy(data, mem, length); 1778212397c6Schristos return length; 1779212397c6Schristos } 1780212397c6Schristos 1781212397c6Schristos extern struct pstate sregs; 1782212397c6Schristos 1783212397c6Schristos void 1784212397c6Schristos boot_init (void) 1785212397c6Schristos { 1786212397c6Schristos mec_write(MEC_WCR, 0); /* zero waitstates */ 1787212397c6Schristos mec_write(MEC_TRAPD, 0); /* turn off watch-dog */ 1788212397c6Schristos mec_write(MEC_RTC_SCALER, sregs.freq - 1); /* generate 1 MHz RTC tick */ 1789212397c6Schristos mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */ 1790212397c6Schristos sregs.wim = 2; 1791212397c6Schristos sregs.psr = 0x110010e0; 1792212397c6Schristos sregs.r[30] = RAM_END; 1793212397c6Schristos sregs.r[14] = sregs.r[30] - 96 * 4; 1794212397c6Schristos mec_mcr |= 1; /* power-down enabled */ 17954e98e3e1Schristos } 1796