diff --git a/3B2/3b2_cpu.c b/3B2/3b2_cpu.c index 807c303c..c16b637b 100644 --- a/3B2/3b2_cpu.c +++ b/3B2/3b2_cpu.c @@ -932,7 +932,7 @@ t_stat fprint_sym_m(FILE *of, t_addr addr, t_value *val) fprintf(of, "&0x%x", w); break; default: - fprintf(of, "%d(%%fp)", reg); + fprintf(of, "%d(%%fp)", (int8) reg); break; } break; @@ -943,7 +943,7 @@ t_stat fprint_sym_m(FILE *of, t_addr addr, t_value *val) fprintf(of, "$0x%x", w); break; default: - fprintf(of, "%d(%%ap)", reg); + fprintf(of, "%d(%%ap)", (int8) reg); break; } break; @@ -970,12 +970,12 @@ t_stat fprint_sym_m(FILE *of, t_addr addr, t_value *val) case 12: /* Byte Displacement */ OP_R_B(w, val, vp); cpu_register_name(reg, reg_name, 8); - fprintf(of, "%d(%s)", w, reg_name); + fprintf(of, "%d(%s)", (int8) w, reg_name); break; case 13: /* Byte Displacement Deferred */ OP_R_B(w, val, vp); cpu_register_name(reg, reg_name, 8); - fprintf(of, "*%d(%s)", w, reg_name); + fprintf(of, "*%d(%s)", (int8) w, reg_name); break; case 14: if (reg == 15) { diff --git a/3B2/3b2_ctc.c b/3B2/3b2_ctc.c index e7d0f58c..0f6f086b 100644 --- a/3B2/3b2_ctc.c +++ b/3B2/3b2_ctc.c @@ -50,6 +50,9 @@ extern UNIT cio_unit; #define DELAY_UNK 1000 #define DELAY_CATCHUP 10000 +#define CTC_DIAG_CRC1 0xa4a5752f +#define CTC_DIAG_CRC2 0xd3d20eb3 + #define TAPE_DEV 0 /* CTAPE device */ #define XMF_DEV 1 /* XM Floppy device */ @@ -61,6 +64,7 @@ extern UNIT cio_unit; static uint8 int_cid; /* Interrupting card ID */ static uint8 int_subdev; /* Interrupting subdevice */ static t_bool ctc_conf = FALSE; /* Has a CTC card been configured? */ +static uint32 ctc_crc; /* CRC32 of downloaded memory */ struct partition vtoc_table[VTOC_PART] = { { 2, 0, 5272, 8928 }, /* 00 */ @@ -256,7 +260,7 @@ static void ctc_cmd(uint8 cid, uint32 maxpass, blkno, delay; uint8 dev; uint8 sec_buf[512]; - int32 b, j; + int32 b, i, j; t_seccnt secrw = 0; struct vtoc vtoc = {0}; struct pdinfo pdinfo = {0}; @@ -271,11 +275,14 @@ static void ctc_cmd(uint8 cid, switch(rqe->opcode) { case CIO_DLM: + for (i = 0; i < rqe->byte_count; i++) { + ctc_crc = cio_crc32_shift(ctc_crc, pread_b(rqe->address + i)); + } sim_debug(TRACE_DBG, &ctc_dev, "[ctc_cmd] CIO Download Memory: bytecnt=%04x " - "addr=%08x return_addr=%08x subdev=%02x\n", + "addr=%08x return_addr=%08x subdev=%02x (CRC=%08x)\n", rqe->byte_count, rqe->address, - rqe->address, rqe->subdevice); + rqe->address, rqe->subdevice, ctc_crc); delay = DELAY_DLM; cqe->address = rqe->address + rqe->byte_count; cqe->opcode = CTC_SUCCESS; @@ -288,18 +295,20 @@ static void ctc_cmd(uint8 cid, break; case CIO_FCF: sim_debug(TRACE_DBG, &ctc_dev, - "[ctc_cmd] CIO Force Function Call: return opcode 0\n"); + "[ctc_cmd] CIO Force Function Call (CRC=%08x)\n", ctc_crc); delay = DELAY_FCF; - /* This is to pass diagnostics. TODO: Figure out how to parse - * the given test x86 code and determine how to respond - * correctly */ - pwrite_h(0x200f000, 0x1); /* Test success */ - pwrite_h(0x200f002, 0x0); /* Test Number */ - pwrite_h(0x200f004, 0x0); /* Actual */ - pwrite_h(0x200f006, 0x0); /* Expected */ - pwrite_b(0x200f008, 0x1); /* Success flag again */ - pwrite_b(0x200f009, 0x30); /* ??? */ + /* If the currently running program is a diagnostic program, + * we are expected to write results into memory at address + * 0x200f000 */ + if (ctc_crc == CTC_DIAG_CRC1 || + ctc_crc == CTC_DIAG_CRC2) { + pwrite_h(0x200f000, 0x1); /* Test success */ + pwrite_h(0x200f002, 0x0); /* Test Number */ + pwrite_h(0x200f004, 0x0); /* Actual */ + pwrite_h(0x200f006, 0x0); /* Expected */ + pwrite_b(0x200f008, 0x1); /* Success flag again */ + } /* An interesting (?) side-effect of FORCE FUNCTION CALL is * that it resets the card state such that a new SYSGEN is @@ -571,6 +580,8 @@ void ctc_sysgen(uint8 cid) cio_entry cqe = {0}; uint8 rapp_data[12] = {0}; + ctc_crc = 0; + sim_debug(TRACE_DBG, &ctc_dev, "[ctc_sysgen] Handling Sysgen.\n"); sim_debug(TRACE_DBG, &ctc_dev, "[ctc_sysgen] rqp=%08x\n", cio[cid].rqp); sim_debug(TRACE_DBG, &ctc_dev, "[ctc_sysgen] cqp=%08x\n", cio[cid].cqp); @@ -624,6 +635,8 @@ t_stat ctc_reset(DEVICE *dptr) { uint8 cid; + ctc_crc = 0; + sim_debug(TRACE_DBG, &ctc_dev, "[ctc_reset] Resetting CTC device\n"); diff --git a/3B2/3b2_io.c b/3B2/3b2_io.c index 233ea5e0..48a27b73 100644 --- a/3B2/3b2_io.c +++ b/3B2/3b2_io.c @@ -30,6 +30,8 @@ #include "3b2_io.h" +#define CRC_POLYNOMIAL 0xEDB88320 + CIO_STATE cio[CIO_SLOTS] = { 0 }; struct iolink iotable[] = { @@ -68,6 +70,31 @@ void cio_clear(uint8 cid) cio[cid].op = 0; } +/* + * A braindead CRC32 calculator. + * + * This is overkill for what we need: A simple way to tag the contents + * of a block of memory uploaded to a CIO card (so we can + * differentiate between desired functions without actually having to + * disassemble and understand 80186 code!) + */ +uint32 cio_crc32_shift(uint32 crc, uint8 data) +{ + uint8 i; + + crc = ~crc; + crc ^= data; + for (i = 0; i < 8; i++) { + if (crc & 1) { + crc = (crc >> 1) ^ CRC_POLYNOMIAL; + } else { + crc = crc >> 1; + } + } + + return ~crc; +} + void cio_sysgen(uint8 cid) { uint32 sysgen_p; diff --git a/3B2/3b2_io.h b/3B2/3b2_io.h index 8818f755..6dd572ff 100644 --- a/3B2/3b2_io.h +++ b/3B2/3b2_io.h @@ -220,6 +220,7 @@ t_stat cio_reset(DEVICE *dptr); t_stat cio_svc(UNIT *uptr); void cio_clear(uint8 cid); +uint32 cio_crc32_shift(uint32 crc, uint8 data); void cio_cexpress(uint8 cid, uint16 esize, cio_entry *cqe, uint8 *app_data); void cio_cqueue(uint8 cid, uint8 cmd_stat, uint16 esize, cio_entry *cqe, uint8 *app_data); void cio_rexpress(uint8 cid, uint16 esize, cio_entry *rqe, uint8 *app_data); diff --git a/3B2/3b2_iu.c b/3B2/3b2_iu.c index eacb1e11..ee524129 100644 --- a/3B2/3b2_iu.c +++ b/3B2/3b2_iu.c @@ -751,7 +751,6 @@ void iu_write(uint32 pa, uint32 val, size_t size) t_stat iu_tx(uint8 portno, uint8 val) { IU_PORT *p = (portno == PORT_A) ? &iu_console : &iu_contty; - UNIT *uptr = (portno == PORT_A) ? &tto_unit : contty_xmt_unit; uint8 ists = (portno == PORT_A) ? ISTS_RAI : ISTS_RBI; uint8 imr_mask = (portno == PORT_A) ? IMR_RXRA : IMR_RXRB; int32 c; diff --git a/3B2/3b2_ports.c b/3B2/3b2_ports.c index fc388210..56a06272 100644 --- a/3B2/3b2_ports.c +++ b/3B2/3b2_ports.c @@ -71,7 +71,10 @@ extern UNIT cio_unit; */ +#ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + #define PPQESIZE 12 #define DELAY_ASYNC 25 #define DELAY_DLM 100 @@ -87,6 +90,10 @@ extern UNIT cio_unit; #define DELAY_DEVICE 25 #define DELAY_STD 100 +#define PORTS_DIAG_CRC1 0x7ceec900 +#define PORTS_DIAG_CRC2 0x77a1ea56 +#define PORTS_DIAG_CRC3 0x84cf938b + #define LN(cid,port) ((PORTS_LINES * ((cid) - base_cid)) + (port)) #define LCID(ln) (((ln) / PORTS_LINES) + base_cid) #define LPORT(ln) ((ln) % PORTS_LINES) @@ -95,6 +102,7 @@ t_bool ports_conf = FALSE; /* Have PORTS cards been configured? */ int8 base_cid; /* First cid in our contiguous block */ uint8 int_cid; /* Interrupting card ID */ uint8 int_subdev; /* Interrupting subdevice */ +uint32 ports_crc; /* CRC32 of downloaded memory */ /* PORTS-specific state for each slot */ PORTS_LINE_STATE *ports_state = NULL; @@ -247,7 +255,7 @@ t_stat ports_setnl(UNIT *uptr, int32 val, CONST char *cptr, void *desc) static void ports_cmd(uint8 cid, cio_entry *rentry, uint8 *rapp_data) { cio_entry centry = {0}; - uint32 ln; + uint32 ln, i; PORTS_OPTIONS opts; char line_config[16]; uint8 app_data[4] = {0}; @@ -258,13 +266,16 @@ static void ports_cmd(uint8 cid, cio_entry *rentry, uint8 *rapp_data) switch(rentry->opcode) { case CIO_DLM: - centry.address = rentry->address + rentry->byte_count; + for (i = 0; i < rentry->byte_count; i++) { + ports_crc = cio_crc32_shift(ports_crc, pread_b(rentry->address + i)); + } sim_debug(TRACE_DBG, &ports_dev, "[%08x] [ports_cmd] CIO Download Memory: bytecnt=%04x " - "addr=%08x return_addr=%08x subdev=%02x\n", + "addr=%08x return_addr=%08x subdev=%02x (CRC=%08x)\n", R[NUM_PC], rentry->byte_count, rentry->address, - centry.address, centry.subdevice); + centry.address, centry.subdevice, ports_crc); + centry.address = rentry->address + rentry->byte_count; cio_cexpress(cid, PPQESIZE, ¢ry, app_data); cio_irq(cid, rentry->subdevice, DELAY_DLM); break; @@ -277,25 +288,27 @@ static void ports_cmd(uint8 cid, cio_entry *rentry, uint8 *rapp_data) break; case CIO_FCF: sim_debug(TRACE_DBG, &ports_dev, - "[%08x] [ports_cmd] CIO Force Function Call\n", - R[NUM_PC]); + "[%08x] [ports_cmd] CIO Force Function Call (CRC=%08x)\n", + R[NUM_PC], ports_crc); - /* This is to pass diagnostics. TODO: Figure out how to parse the - * given test x86 code and determine how to respond correctly */ - - pwrite_h(0x200f000, 0x1); /* Test success */ - pwrite_h(0x200f002, 0x0); /* Test Number */ - pwrite_h(0x200f004, 0x0); /* Actual */ - pwrite_h(0x200f006, 0x0); /* Expected */ - pwrite_b(0x200f008, 0x1); /* Success flag again */ - pwrite_b(0x200f009, 0x30); /* ??? */ + /* If the currently running program is a diagnostics program, + * we are expected to write results into memory at address + * 0x200f000 */ + if (ports_crc == PORTS_DIAG_CRC1 || + ports_crc == PORTS_DIAG_CRC2 || + ports_crc == PORTS_DIAG_CRC3) { + pwrite_h(0x200f000, 0x1); /* Test success */ + pwrite_h(0x200f002, 0x0); /* Test Number */ + pwrite_h(0x200f004, 0x0); /* Actual */ + pwrite_h(0x200f006, 0x0); /* Expected */ + pwrite_b(0x200f008, 0x1); /* Success flag again */ + } /* An interesting (?) side-effect of FORCE FUNCTION CALL is * that it resets the card state such that a new SYSGEN is * required in order for new commands to work. In fact, an * INT0/INT1 combo _without_ a RESET can sysgen the board. So, * we reset the command bits here. */ - cio[cid].sysgen_s = 0; cio_cexpress(cid, PPQESIZE, ¢ry, app_data); cio_irq(cid, rentry->subdevice, DELAY_FCF); @@ -502,6 +515,8 @@ void ports_sysgen(uint8 cid) cio_entry cqe = {0}; uint8 app_data[4] = {0}; + ports_crc = 0; + cqe.opcode = 3; /* Sysgen success! */ /* It's not clear why we put a response in both the express @@ -540,6 +555,8 @@ t_stat ports_reset(DEVICE *dptr) uint8 cid, line, ln, end_slot; TMLN *lp; + ports_crc = 0; + sim_debug(TRACE_DBG, &ports_dev, "[ports_reset] Resetting PORTS device\n");