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