/* 3b2_iu.h: SCN2681A Dual UART Header | |
Copyright (c) 2017, Seth J. Morabito | |
Permission is hereby granted, free of charge, to any person | |
obtaining a copy of this software and associated documentation | |
files (the "Software"), to deal in the Software without | |
restriction, including without limitation the rights to use, copy, | |
modify, merge, publish, distribute, sublicense, and/or sell copies | |
of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be | |
included in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
SOFTWARE. | |
Except as contained in this notice, the name of the author shall | |
not be used in advertising or otherwise to promote the sale, use or | |
other dealings in this Software without prior written authorization | |
from the author. | |
*/ | |
#ifndef __3B2_IU_H__ | |
#define __3B2_IU_H__ | |
#include "3b2_defs.h" | |
#include "3b2_sysdev.h" | |
#define CMD_ERX 0x01 /* Enable receiver */ | |
#define CMD_DRX 0x02 /* Disable receiver */ | |
#define CMD_ETX 0x04 /* Enable transmitter */ | |
#define CMD_DTX 0x08 /* Disable transmitter */ | |
#define CMD_MISC_SHIFT 4 /* Command */ | |
#define CMD_MISC_MASK 0x7 | |
#define IU_SPEED_REGS 2 /* Two speed select registers, */ | |
#define IU_SPEEDS 16 /* with 16 speeds each */ | |
#define IU_PARITY_ODD 0 | |
#define IU_PARITY_EVEN 1 | |
#define IU_PARITY_NONE 2 | |
#define STS_RXR 0x01 /* Receiver ready */ | |
#define STS_FFL 0x02 /* FIFO full */ | |
#define STS_TXR 0x04 /* Transmitter ready */ | |
#define STS_TXE 0x08 /* Transmitter empty */ | |
#define STS_OER 0x10 /* Overrun error */ | |
#define STS_PER 0x20 /* Parity error */ | |
#define STS_FER 0x40 /* Framing error */ | |
#define STS_RXB 0x80 /* Received break */ | |
#define ISTS_TAI 0x01 /* Transmitter ready A */ | |
#define ISTS_RAI 0x02 /* Receiver ready A */ | |
#define ISTS_CBA 0x04 /* Change in break A */ | |
#define ISTS_CRI 0x08 /* Counter ready */ | |
#define ISTS_TBI 0x10 /* Transmitter ready B */ | |
#define ISTS_RBI 0x20 /* Receiver ready B */ | |
#define ISTS_CBB 0x40 /* Change in break B */ | |
#define ISTS_IPC 0x80 /* Interrupt port change */ | |
#define MODE_V_CHM 6 /* Channel mode */ | |
#define MODE_M_CHM 0x3 | |
/* Used by the DMAC */ | |
#define IUA_DATA_REG 3 | |
#define IUB_DATA_REG 11 | |
/* Registers - Read */ | |
#define SRA 1 | |
#define RHRA 3 | |
#define IPCR 4 | |
#define ISR 5 | |
#define CTU 6 | |
#define CTL 7 | |
#define SRB 9 | |
#define RHRB 11 | |
#define INPRT 13 /* Input port data */ | |
#define START_CTR 14 | |
#define STOP_CTR 15 | |
/* Registers - Write */ | |
#define CSRA 1 | |
#define CRA 2 | |
#define THRA 3 | |
#define ACR 4 | |
#define IMR 5 | |
#define CTUR 6 | |
#define CTLR 7 | |
#define CSRB 9 | |
#define CRB 10 | |
#define THRB 11 | |
#define OPCR 13 | |
#define SOPR 14 | |
#define ROPR 15 | |
/* Registers - R/W */ | |
#define MR12A 0 | |
#define MR12B 8 | |
/* Port configuration */ | |
#define TX_EN 1 | |
#define RX_EN 2 | |
#define UM_CTR_EXT 0 | |
#define UM_CTR_TXCA 1 | |
#define UM_CTR_TXCB 2 | |
#define UM_CTR_DIV16 3 | |
#define UM_TMR_EXT 4 | |
#define UM_TMR_EXT16 5 | |
#define UM_TMR_XTL 6 | |
#define UM_TMR_XTL16 7 | |
#define UM_MASK 0x70 | |
#define UM_SHIFT 4 | |
/* IMR bits */ | |
#define IMR_TXRA 0x01 | |
#define IMR_RXRA 0x02 | |
#define IMR_CTR 0x08 | |
#define IMR_TXRB 0x10 | |
#define IMR_RXRB 0x20 | |
/* Power-off bit */ | |
#define IU_KILLPWR 0x04 | |
#define PORT_A 0 | |
#define PORT_B 1 | |
#define IU_MODE(x) ((x & UM_MASK) >> UM_SHIFT) | |
extern DEVICE tti_dev; | |
extern DEVICE tto_dev; | |
extern DEVICE contty_dev; | |
extern DEVICE iu_timer_dev; | |
#define IUBASE 0x49000 | |
#define IUSIZE 0x100 | |
/* The UART is driven by a 3.6864 MHz crystal. This is divided by 16 | |
to clock the timer. (One peculiarity: 3.6864 MHz /16 is 230400 Hz, | |
but the SVR3 source code claims the /16 clock is actually 230525 | |
Hz. So, we'll go with 230525 Hz until proven otherwise.) | |
UART clock period = 4338ns | |
System clock period = 100ns | |
That means the system ticks 43.3792 times for every one tick of the | |
UART clock. | |
But this is a simulated system, where each simulator step is | |
CYCLES_PER_INST long. So we take that into account. | |
*/ | |
#define IU_TIMER_STP 4.33792 | |
#define IU_BUF_SIZE 3 | |
#define IU_DCDA 0x01 | |
#define IU_DCDB 0x02 | |
#define IU_DTRA 0x01 | |
#define IU_DTRB 0x02 | |
/* Default baud rate generator (9600 baud) */ | |
#define BRG_DEFAULT 11 | |
typedef struct iu_port { | |
uint8 stat; /* Port Status */ | |
uint8 cmd; /* Command */ | |
uint8 mode[2]; /* Two mode buffers */ | |
uint8 modep; /* Point to mode[0] or mode[1] */ | |
uint8 conf; /* Configuration bits */ | |
uint8 txbuf; /* Transmit Holding Register */ | |
uint8 rxbuf[IU_BUF_SIZE]; /* Receive Holding Register (3 bytes) */ | |
uint8 w_p; /* Buffer Write Pointer */ | |
uint8 r_p; /* Buffer Read Pointer */ | |
t_bool drq; /* DRQ enabled */ | |
} IU_PORT; | |
typedef struct iu_state { | |
uint8 istat; /* Interrupt Status */ | |
uint8 imr; /* Interrupt Mask Register */ | |
uint8 acr; | |
uint8 opcr; /* Output Port Configuration */ | |
uint8 inprt; /* Input Port Data */ | |
uint8 ipcr; /* Input Port Change Register */ | |
} IU_STATE; | |
typedef struct iu_timer_state { | |
uint16 c_set; | |
t_bool c_en; | |
} IU_TIMER_STATE; | |
extern IU_PORT iu_console; | |
extern IU_PORT iu_contty; | |
/* Function prototypes */ | |
t_stat contty_attach(UNIT *uptr, CONST char *cptr); | |
t_stat contty_detach(UNIT *uptr); | |
t_stat tti_reset(DEVICE *dptr); | |
t_stat contty_reset(DEVICE *dptr); | |
t_stat iu_timer_reset(DEVICE *dptr); | |
t_stat iu_svc_tti(UNIT *uptr); | |
t_stat iu_svc_tto(UNIT *uptr); | |
t_stat iu_svc_contty_rcv(UNIT *uptr); | |
t_stat iu_svc_contty_xmt(UNIT *uptr); | |
t_stat iu_svc_timer(UNIT *uptr); | |
uint32 iu_read(uint32 pa, size_t size); | |
void iu_write(uint32 pa, uint32 val, size_t size); | |
void iua_drq_handled(); | |
void iub_drq_handled(); | |
void iu_txrdy_a_irq(); | |
void iu_txrdy_b_irq(); | |
static SIM_INLINE void iu_tx(uint8 portno, uint8 val); | |
static SIM_INLINE void iu_w_buf(uint8 portno, uint8 val); | |
static SIM_INLINE void iu_w_cmd(uint8 portno, uint8 val); | |
static SIM_INLINE void iu_update_rxi(uint8 c); | |
static SIM_INLINE void iu_update_txi(); | |
#endif |