These changes facilitate more robust parameter type checking and helps to identify unexpected coding errors. Most simulators can now also be compiled with a C++ compiler without warnings. Additionally, these changes have also been configured to facilitate easier backporting of simulator and device simulation modules to run under the simh v3.9+ SCP framework.
434 lines
16 KiB
C
434 lines
16 KiB
C
/* chip_defs.h: definitions for several chips
|
|
|
|
Copyright (c) 2009-2010 Holger Veit
|
|
|
|
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
|
|
Holger Veit 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 Holger Veit et al shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from Holger Veit et al.
|
|
|
|
22-Jan-10 HV Initial version
|
|
*/
|
|
#ifndef CHIP_DEFS_H_
|
|
#define CHIP_DEFS_H_
|
|
|
|
#include "sim_imd.h"
|
|
#include "sim_sock.h"
|
|
#include "sim_tmxr.h"
|
|
|
|
/*****************************************************************************************
|
|
* General implementation note:
|
|
*
|
|
* Each chip device is implemented through a specific data structure, e.g. struct i8251
|
|
* The address of this data structure MUST be passed to the device->ctxt variable.
|
|
* The data structure MUST contain a PNP_INFO attribute at the beginning.
|
|
*
|
|
* In case each unit of a complex device has an own chip, device->ctxt points to an array
|
|
* of as much elements as there are units.
|
|
* The device reset routine MUST call add_iohandler and del_iohandler depending on
|
|
* enable or disable of the device. add_iohandler and del_iohandler will be passed
|
|
* the corresponding address of the data structure for the chip (device->ctxt).
|
|
*
|
|
*****************************************************************************************/
|
|
|
|
/* set this to 0 to remove debug messages */
|
|
#ifndef DBG_MSG
|
|
#define DBG_MSG 1
|
|
#endif
|
|
|
|
/* generic debug tracing support */
|
|
#if DBG_MSG==1
|
|
|
|
#define ADDRESS_FORMAT "[0x%08x]"
|
|
#if UNIX_PLATFORM
|
|
#define NLP "\r\n"
|
|
#else
|
|
#define NLP "\n"
|
|
#endif
|
|
|
|
#define TRACE_PRINT(level,args)\
|
|
if(sim_deb && chip->dev->dctrl & level) { \
|
|
fprintf(sim_deb,"%-4s: " ADDRESS_FORMAT " ", chip->dev->name, PCX); \
|
|
fprintf args; fputs(NLP,sim_deb); }
|
|
#define TRACE_PRINT0(level,fmt)\
|
|
if(sim_deb && chip->dev->dctrl & level) { \
|
|
fprintf(sim_deb,"%-4s: " ADDRESS_FORMAT " ", chip->dev->name, PCX); \
|
|
fprintf(sim_deb,fmt NLP); }
|
|
#define TRACE_PRINT1(level,fmt,arg1)\
|
|
if(sim_deb && chip->dev->dctrl & level) { \
|
|
fprintf(sim_deb,"%-4s: " ADDRESS_FORMAT " ", chip->dev->name, PCX); \
|
|
fprintf(sim_deb,fmt NLP,arg1); }
|
|
#define TRACE_PRINT2(level,fmt,arg1,arg2)\
|
|
if(sim_deb && chip->dev->dctrl & level) { \
|
|
fprintf(sim_deb,"%-4s: " ADDRESS_FORMAT " ", chip->dev->name, PCX); \
|
|
fprintf(sim_deb,fmt NLP,arg1,arg2); }
|
|
#else
|
|
#define TRACE_PRINT(level,args)
|
|
#define TRACE_PRINT0(level,fmt)
|
|
#define TRACE_PRINT1(level,fmt,arg1)
|
|
#define TRACE_PRINT2(level,fmt,arg1,arg2)
|
|
#endif
|
|
|
|
/*****************************************************************************************
|
|
* general terminal multiplexer/socket support
|
|
*****************************************************************************************/
|
|
|
|
typedef struct {
|
|
int pfirst;
|
|
int prate;
|
|
TMLN ldsc;
|
|
TMXR desc;
|
|
UNIT* term;
|
|
UNIT* poll;
|
|
} SERMUX;
|
|
t_stat mux_attach(UNIT*,CONST char*,SERMUX*);
|
|
t_stat mux_detach(UNIT*,SERMUX*);
|
|
|
|
/*****************************************************************************************
|
|
* 8259 PIC
|
|
*****************************************************************************************/
|
|
#define I8259_ICW1 0x10
|
|
#define I8259_ICW1_A765 0xe0
|
|
#define I8259_ICW1_LTIM 0x08
|
|
#define I8259_ICW1_ADI 0x04
|
|
#define I8259_ICW1_SNGL 0x02
|
|
#define I8259_ICW1_IC4 0x01
|
|
#define I8259_ICW4_SFNM 0x10
|
|
#define I8259_ICW4_BUF 0x08
|
|
#define I8259_ICW4_MS 0x04
|
|
#define I8259_ICW4_AEOI 0x02
|
|
#define I8259_ICW4_UPM 0x01
|
|
#define I8259_OCW2_MODE 0xe0
|
|
#define I8259_OCW2_LEVEL 0x07
|
|
#define I8259_OCW3_ESMM 0x40
|
|
#define I8259_OCW3_SMM 0x20
|
|
#define I8259_OCW3 0x08
|
|
#define I8259_OCW3_POLL 0x04
|
|
#define I8259_OCW3_RR 0x02
|
|
#define I8259_OCW3_RIS 0x01
|
|
|
|
typedef struct i8259 {
|
|
PNP_INFO pnp;
|
|
DEVICE* dev; /* backlink to device */
|
|
t_stat (*write)(struct i8259* chip,int port,uint32 value);
|
|
t_stat (*read)(struct i8259* chip,int port,uint32* value);
|
|
t_stat (*reset)(struct i8259* chip);
|
|
int state;
|
|
int rmode;
|
|
int32 imr;
|
|
int32 isr;
|
|
int32 irr;
|
|
int32 icw1;
|
|
int32 icw2;
|
|
int32 icw4;
|
|
int32 prio; /* which IR* has prio 7? */
|
|
t_bool autoint;
|
|
int intlevel;
|
|
int intvector;
|
|
} I8259;
|
|
|
|
extern t_stat i8259_io(IOHANDLER* ioh,uint32* value,uint32 rw,uint32 mask);
|
|
extern t_stat i8259_read(I8259* pic,int addr,uint32* value);
|
|
extern t_stat i8259_write(I8259* pic,int addr, uint32 value);
|
|
extern t_stat i8259_reset(I8259* chip);
|
|
extern t_stat i8259_raiseint(I8259* chip,int level);
|
|
|
|
/* Debug flags */
|
|
#define DBG_PIC_RD (1 << 0)
|
|
#define DBG_PIC_WR (1 << 1)
|
|
#define DBG_PIC_II (1 << 2)
|
|
#define DBG_PIC_IO (1 << 3)
|
|
extern DEBTAB i8259_dt[];
|
|
|
|
/*****************************************************************************************
|
|
* 8251 USART
|
|
*****************************************************************************************/
|
|
#define I8251_AMODE_STOP 0xc0
|
|
#define I8251_AMODE_S1 0x40
|
|
#define I8251_AMODE_S15 0x80
|
|
#define I8251_AMODE_S2 0xc0
|
|
#define I8251_MODE_EP 0x20
|
|
#define I8251_MODE_PEN 0x10
|
|
#define I8251_AMODE_BITS 0x0c
|
|
#define I8251_AMODE_BITS5 0x00
|
|
#define I8251_AMODE_BITS6 0x04
|
|
#define I8251_AMODE_BITS7 0x08
|
|
#define I8251_AMODE_BITS8 0x0c
|
|
#define I8251_MODE_BAUD 0x03
|
|
#define I8251_MODE_SYNC 0x00
|
|
#define I8251_AMODE_BAUD1 0x01
|
|
#define I8251_AMODE_BAUD16 0x02
|
|
#define I8251_AMODE_BAUD64 0x03
|
|
#define I8251_SMODE_ESD 0x40
|
|
#define I8251_SMODE_SCS 0x80
|
|
#define I8251_CMD_EH 0x80
|
|
#define I8251_CMD_IR 0x40
|
|
#define I8251_CMD_RTS 0x20
|
|
#define I8251_CMD_ER 0x10
|
|
#define I8251_CMD_SBRK 0x08
|
|
#define I8251_CMD_RXE 0x04
|
|
#define I8251_CMD_DTR 0x02
|
|
#define I8251_CMD_TXEN 0x01
|
|
#define I8251_ST_DSR 0x80
|
|
#define I8251_ST_SYNBRK 0x40
|
|
#define I8251_ST_FE 0x20
|
|
#define I8251_ST_OE 0x10
|
|
#define I8251_ST_PE 0x08
|
|
#define I8251_ST_TXEMPTY 0x04
|
|
#define I8251_ST_RXRDY 0x02
|
|
#define I8251_ST_TXRDY 0x01
|
|
|
|
typedef struct i8251 {
|
|
PNP_INFO pnp;
|
|
DEVICE* dev; /* backlink to device */
|
|
t_stat (*write)(struct i8251* chip,int port,uint32 value);
|
|
t_stat (*read)(struct i8251* chip,int port,uint32* value);
|
|
t_stat (*reset)(struct i8251* chip);
|
|
t_stat (*txint)(struct i8251* chip);
|
|
t_stat (*rxint)(struct i8251* chip);
|
|
UNIT* in;
|
|
UNIT* out;
|
|
SERMUX* mux;
|
|
int init;
|
|
int mode;
|
|
int sync1;
|
|
int sync2;
|
|
int cmd;
|
|
int ibuf;
|
|
int obuf;
|
|
int status;
|
|
int bitmask;
|
|
t_bool oob; /* out-of-band=1 will allow a console to receive CTRL-E even when receiver is disabled */
|
|
int crlf; /* CRLF state machine to suppress NUL bytes */
|
|
} I8251;
|
|
|
|
/* default handlers */
|
|
extern t_stat i8251_io(IOHANDLER* ioh,uint32* value,uint32 rw,uint32 mask);
|
|
extern t_stat i8251_write(I8251* chip,int port,uint32 value);
|
|
extern t_stat i8251_read(I8251* chip,int port,uint32* value);
|
|
extern t_stat i8251_reset(I8251* chip);
|
|
|
|
/* Debug flags */
|
|
#define DBG_UART_RD (1 << 0)
|
|
#define DBG_UART_WR (1 << 1)
|
|
#define DBG_UART_IRQ (1 << 2)
|
|
extern DEBTAB i8251_dt[];
|
|
|
|
|
|
/*****************************************************************************************
|
|
* 8253 TIMER
|
|
*****************************************************************************************/
|
|
/*forward*/ struct i8253;
|
|
typedef struct {
|
|
t_stat (*call)(struct i8253* chip,int rw,uint32* src);
|
|
int state; /* the current output state (latching, MSB/LSB out */
|
|
int mode; /* programmed mode */
|
|
int32 latch; /* the latched value of count */
|
|
int32 divider; /* programmed divider value */
|
|
int32 count; /* the real count value as calculated by rcall callback */
|
|
} I8253CNTR;
|
|
|
|
typedef struct i8253 {
|
|
PNP_INFO pnp;
|
|
DEVICE* dev; /* backlink to device */
|
|
UNIT* unit; /* backlink to unit */
|
|
t_stat (*reset)(struct i8253* chip);
|
|
t_stat (*ckmode)(struct i8253* chip, uint32 value);
|
|
I8253CNTR cntr[3];
|
|
int init;
|
|
} I8253;
|
|
|
|
#define I8253_SCMASK 0xc0
|
|
#define I8253_SC0 0x00
|
|
#define I8253_SC1 0x40
|
|
#define I8253_SC2 0x80
|
|
#define I8253_RLMASK 0x30
|
|
#define I8253_LATCH 0x00
|
|
#define I8253_LSB 0x10
|
|
#define I8253_MSB 0x20
|
|
#define I8253_BOTH 0x30
|
|
#define I8253_MODEMASK 0xe0
|
|
#define I8253_MODE0 0x00
|
|
#define I8253_MODE1 0x02
|
|
#define I8253_MODE2 0x04
|
|
#define I8253_MODE2a 0x0c
|
|
#define I8253_MODE3 0x06
|
|
#define I8253_MODE3a 0x0e
|
|
#define I8253_MODE4 0x08
|
|
#define I8253_MODE5 0x0a
|
|
#define I8253_MODEBIN 0x00
|
|
#define I8253_MODEBCD 0x01
|
|
|
|
#define I8253_ST_LSBNEXT 0x01
|
|
#define I8253_ST_MSBNEXT 0x02
|
|
#define I8253_ST_LATCH 0x08
|
|
|
|
/* default handlers */
|
|
extern t_stat i8253_io(IOHANDLER* ioh,uint32* value,uint32 rw,uint32 mask);
|
|
extern t_stat i8253_reset(I8253* chip);
|
|
|
|
/* Debug flags */
|
|
#define DBG_TMR_RD (1 << 0)
|
|
#define DBG_TMR_WR (1 << 1)
|
|
extern DEBTAB i8253_dt[];
|
|
|
|
/****************************************************************************************
|
|
* upd765 FDC chip
|
|
***************************************************************************************/
|
|
#define I8272_MAX_DRIVES 4
|
|
#define I8272_MAX_SECTOR 26
|
|
#define I8272_MAX_SECTOR_SZ 8192
|
|
/* 2^(7 + I8272_MAX_N) == I8272_MAX_SECTOR_SZ */
|
|
#define I8272_MAX_N 6
|
|
|
|
#define I8272_FDC_MSR 0 /* R=FDC Main Status Register, W=Drive Select Register */
|
|
#define I8272_FDC_DATA 1 /* R/W FDC Data Register */
|
|
|
|
typedef struct {
|
|
UNIT *uptr;
|
|
DISK_INFO *imd;
|
|
uint8 ntracks; /* number of tracks */
|
|
uint8 nheads; /* number of heads */
|
|
uint32 sectsize; /* sector size, not including pre/postamble */
|
|
uint8 track; /* Current Track */
|
|
uint8 ready; /* Is drive ready? */
|
|
} I8272_DRIVE_INFO;
|
|
|
|
typedef enum i8272state {
|
|
S_CMD=1, S_CMDREAD, S_EXEC, S_DATAWRITE, S_SECWRITE, S_SECREAD, S_DATAREAD, S_RESULT
|
|
} I8272_STATE;
|
|
|
|
typedef struct i8272 {
|
|
PNP_INFO pnp; /* Plug-n-Play Information */
|
|
DEVICE* dev; /* backlink to device */
|
|
t_stat (*write)(struct i8272* chip,int port,uint32 data);
|
|
t_stat (*read)(struct i8272* chip,int port,uint32* data);
|
|
t_stat (*reset)(struct i8272* chip);
|
|
void (*seldrv)(struct i8272* chip,int seldrv);
|
|
void (*irq)(struct i8272* chip,int delay);
|
|
|
|
I8272_STATE fdc_state; /* internal state machine */
|
|
uint32 fdc_dma_addr;/* DMA Transfer Address */
|
|
uint8 fdc_msr; /* 8272 Main Status Register */
|
|
uint8 fdc_nd; /* Non-DMA Mode 1=Non-DMA, 0=DMA */
|
|
uint8 fdc_head; /* H Head Number */
|
|
uint8 fdc_sector; /* R Record (Sector) */
|
|
uint8 fdc_sec_len; /* N Sector Length in controller units (2^(7+fdc_sec_len)) */
|
|
uint8 fdc_eot; /* EOT End of Track (Final sector number of cyl) */
|
|
uint8 fdc_gap; /* GAP Length */
|
|
uint8 fdc_dtl; /* DTL Data Length */
|
|
uint8 fdc_mt; /* Multiple sectors */
|
|
uint8 fdc_mfm; /* MFM mode */
|
|
uint8 fdc_sk; /* Skip Deleted Data */
|
|
uint8 fdc_hds; /* Head Select */
|
|
uint8 fdc_seek_end; /* Seek was executed successfully */
|
|
int fdc_secsz; /* N Sector Length in bytes: 2^(7 + fdc_sec_len), fdc_sec_len <= I8272_MAX_N */
|
|
int fdc_nd_cnt; /* read/write count in non-DMA mode, -1 if start read */
|
|
uint8 fdc_sdata[I8272_MAX_SECTOR_SZ]; /* sector buffer */
|
|
uint8 fdc_fault; /* error code passed from some commands to sense_int */
|
|
|
|
uint8 cmd_cnt; /* command read count */
|
|
uint8 cmd[10]; /* Storage for current command */
|
|
uint8 cmd_len; /* FDC Command Length */
|
|
|
|
uint8 result_cnt; /* result emit count */
|
|
uint8 result[10]; /* Result data */
|
|
uint8 result_len; /* FDC Result Length */
|
|
|
|
uint8 idcount; /* used to cycle sector numbers during ReadID */
|
|
uint8 irqflag; /* set by interrupt, cleared by I8272_SENSE_INTERRUPT */
|
|
|
|
uint8 fdc_curdrv; /* Currently selected drive */
|
|
I8272_DRIVE_INFO drive[I8272_MAX_DRIVES];
|
|
} I8272;
|
|
|
|
extern t_stat i8272_io(IOHANDLER* ioh,uint32* value,uint32 rw,uint32 mask);
|
|
extern t_stat i8272_write(I8272* chip, int addr, uint32 value);
|
|
extern t_stat i8272_read(I8272* chip,int addr,uint32* value);
|
|
extern t_stat i8272_reset(I8272* chip);
|
|
extern void i8272_seldrv(I8272* chip,int drvnum);
|
|
extern t_stat i8272_abortio(I8272* chip);
|
|
extern t_stat i8272_finish(I8272* chip);
|
|
extern t_stat i8272_attach(UNIT *uptr, CONST char *cptr);
|
|
extern t_stat i8272_detach(UNIT *uptr);
|
|
extern t_stat i8272_setDMA(I8272* chip, uint32 dma_addr);
|
|
|
|
/* Debug flags */
|
|
#define DBG_FD_ERROR (1 << 0)
|
|
#define DBG_FD_SEEK (1 << 1)
|
|
#define DBG_FD_CMD (1 << 2)
|
|
#define DBG_FD_RDDATA (1 << 3)
|
|
#define DBG_FD_WRDATA (1 << 4)
|
|
#define DBG_FD_STATUS (1 << 5)
|
|
#define DBG_FD_FMT (1 << 6)
|
|
#define DBG_FD_VERBOSE (1 << 7)
|
|
#define DBG_FD_IRQ (1 << 8)
|
|
#define DBG_FD_STATE (1 << 9)
|
|
#define DBG_FD_IMD (1 << 10)
|
|
#define DBG_FD_DATA (1 << 11)
|
|
extern DEBTAB i8272_dt[];
|
|
extern DEVICE* i8272_dev;
|
|
|
|
/* moved from i8272.c */
|
|
#define UNIT_V_I8272_WLK (UNIT_V_UF + 0) /* write locked */
|
|
#define UNIT_I8272_WLK (1 << UNIT_V_I8272_WLK)
|
|
#define UNIT_V_I8272_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
|
#define UNIT_I8272_VERBOSE (1 << UNIT_V_I8272_VERBOSE)
|
|
#define I8272_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */
|
|
#define I8272_CAPACITY_SSSD (77*1*26*128) /* Single-sided Single Density IBM Diskette1 */
|
|
|
|
/*****************************************************************************************
|
|
* 8255 PARPORT
|
|
*****************************************************************************************/
|
|
typedef struct i8255 {
|
|
PNP_INFO pnp;
|
|
DEVICE* dev; /* backlink to device */
|
|
t_stat (*write)(struct i8255* chip,int port,uint32 data);
|
|
t_stat (*read)(struct i8255* chip,int port,uint32* data);
|
|
t_stat (*reset)(struct i8255* chip);
|
|
t_stat (*calla)(struct i8255* chip,int rw);
|
|
t_stat (*callb)(struct i8255* chip,int rw);
|
|
t_stat (*callc)(struct i8255* chip,int rw);
|
|
t_stat (*ckmode)(struct i8255* chip,uint32 data);
|
|
uint32 porta;
|
|
uint32 last_porta; /* for edge detection */
|
|
uint32 portb;
|
|
uint32 last_portb; /* for edge detection */
|
|
uint32 portc;
|
|
uint32 last_portc; /* for edge detection */
|
|
uint32 ctrl;
|
|
} I8255;
|
|
extern t_stat i8255_io(IOHANDLER* ioh,uint32* value,uint32 rw,uint32 mask);
|
|
extern t_stat i8255_read(I8255* chip,int port,uint32* data);
|
|
extern t_stat i8255_write(I8255* chip,int port,uint32 data);
|
|
#define I8255_RISEEDGE(port,bit) ((chip->last_##port & bit)==0 && (chip->port & bit))
|
|
#define I8255_FALLEDGE(port,bit) ((chip->last_##port & bit) && (chip->port & bit)==0)
|
|
#define I8255_ISSET(port,bit) ((chip->port & (bit))==(bit))
|
|
#define I8255_ISCLR(port,bit) ((chip->port & (bit))==0)
|
|
|
|
/* debug flags */
|
|
#define DBG_PP_WRA (1<<0)
|
|
#define DBG_PP_WRB (1<<1)
|
|
#define DBG_PP_WRC (1<<2)
|
|
#define DBG_PP_RDA (1<<3)
|
|
#define DBG_PP_RDB (1<<4)
|
|
#define DBG_PP_RDC (1<<5)
|
|
#define DBG_PP_MODE (1<<6)
|
|
|
|
#endif /*CHIP_DEFS_H_*/
|