/* 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_*/ |