diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c index fa8d81c0..9cce494f 100644 --- a/PDP11/pdp11_xq.c +++ b/PDP11/pdp11_xq.c @@ -47,9 +47,8 @@ seen by the simulated cpu since there are no minimum response times. Known Bugs or Unsupported features, in priority order: - 1) PDP11 bootstrap - 2) MOP functionality not implemented - 3) Local packet processing not implemented + 1) MOP functionality not implemented + 2) Local packet processing not implemented Regression Tests: VAX: 1. Console SHOW DEVICE @@ -617,7 +616,6 @@ CTLR* xq_pa2ctlr(uint32 PA) t_stat xq_ex (t_value* vptr, t_addr addr, UNIT* uptr, int32 sw) { /* on PDP-11, allow EX command to look at bootrom */ -#ifdef VM_PDP11 CTLR* xq = xq_unit2ctlr(uptr); uint16 *bootrom = NULL; @@ -634,9 +632,6 @@ t_stat xq_ex (t_value* vptr, t_addr addr, UNIT* uptr, int32 sw) else *vptr = 0; return SCPE_OK; -#else - return SCPE_NOFNC; -#endif } /* stop simh from writing non-existant unit data stream */ @@ -854,7 +849,7 @@ t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc) { CTLR* xq = xq_unit2ctlr(uptr); - fprintf(st, "sanity=%s", (xq->var->sanity.enabled == 2) ? "ON" : "OFF"); + fprintf(st, "sanity=%s", (xq->var->sanity.enabled & XQ_SAN_HW_SW) ? "ON" : "OFF"); return SCPE_OK; } @@ -865,7 +860,7 @@ t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc) if (uptr->flags & UNIT_ATT) return SCPE_ALATT; /* this assumes that the parameter has already been upcased */ - if (!strcmp(cptr, "ON")) xq->var->sanity.enabled = 2; + if (!strcmp(cptr, "ON")) xq->var->sanity.enabled = XQ_SAN_HW_SW; else if (!strcmp(cptr, "OFF")) xq->var->sanity.enabled = 0; else return SCPE_ARG; @@ -1110,35 +1105,38 @@ t_stat xq_process_rbdl(CTLR* xq) /* process buffer descriptors */ while(1) { - /* DEQNA stops processing if nothing in read queue while loading boot code */ - if ((xq->var->type == XQ_T_DEQNA) && (!xq->var->ReadQ.count) && (xq->var->csr & XQ_CSR_BD)) break; + /* get receive bdl flags and descriptor bits from memory */ + rstatus = Map_ReadW (xq->var->rbdl_ba, 4, &xq->var->rbdl_buf[0]); + if (rstatus) return xq_nxm_error(xq); + + /* DEQNA stops processing if nothing in read queue */ + if ((xq->var->type == XQ_T_DEQNA) && (!xq->var->ReadQ.count)) break; - /* get receive bdl from memory */ + /* set descriptor processed flag */ xq->var->rbdl_buf[0] = 0xFFFF; wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* DEQNA stops normal processing if nothing in read queue */ - if ((xq->var->type == XQ_T_DEQNA) && (!xq->var->ReadQ.count)) break; + if (wstatus) return xq_nxm_error(xq); /* invalid buffer? */ if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { xq_csr_set_clr(xq, XQ_CSR_RL, 0); return SCPE_OK; - } - - /* DELQA stops processing if nothing in read queue */ - if (!xq->var->ReadQ.count) break; + } /* explicit chain buffer? */ if (xq->var->rbdl_buf[1] & XQ_DSC_C) { + /* get low part of chain address */ + rstatus = Map_ReadW (xq->var->rbdl_ba + 4, 2, &xq->var->rbdl_buf[2]); + if (rstatus) return xq_nxm_error(xq); xq->var->rbdl_ba = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; continue; - } + } - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]); + /* stop if nothing in read queue */ + if (!xq->var->ReadQ.count) break; + + /* get address, length and status words */ + rstatus = Map_ReadW(xq->var->rbdl_ba + 4, 8, &xq->var->rbdl_buf[2]); if (rstatus) return xq_nxm_error(xq); /* get host memory address */ @@ -1150,9 +1148,12 @@ t_stat xq_process_rbdl(CTLR* xq) if (xq->var->rbdl_buf[1] & XQ_DSC_H) { b_length -= 1; address += 1; - } + } if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1; + sim_debug(DBG_TRC, xq->dev, "Using receive descriptor=0x%X, flags=0x%04X, bits=0x%04X, addr=0x%X, len=0x%X, st1=0x%04X, st2=0x%04X\n", + xq->var->rbdl_ba, xq->var->rbdl_buf[0], xq->var->rbdl_buf[1] & 0xFFC0, address, b_length, xq->var->rbdl_buf[4], xq->var->rbdl_buf[5]); + item = &xq->var->ReadQ.item[xq->var->ReadQ.head]; rbl = (uint16)item->packet.len; rbuf = item->packet.msg; @@ -1164,7 +1165,7 @@ t_stat xq_process_rbdl(CTLR* xq) uint16 used = (uint16)item->packet.used; rbl -= used; rbuf = &rbuf[used]; - } else { + } else { /* there should be no need to adjust runt packets the physical layer (sim_ether) won't deliver any short packets via eth_read, so the only short packets which get here are loopback @@ -1176,7 +1177,7 @@ t_stat xq_process_rbdl(CTLR* xq) processing of those weird short ARP packets that seem to occur occasionally */ memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET-rbl); rbl = ETH_MIN_PACKET; - }; + } /* adjust oversized non-loopback packets */ if ((item->type != ETH_ITM_LOOPBACK) && (rbl > ETH_FRAME_SIZE)) { @@ -1187,8 +1188,8 @@ t_stat xq_process_rbdl(CTLR* xq) item->packet.len = XQ_MAX_RCV_PACKET; rbl = XQ_MAX_RCV_PACKET; } - }; - }; + } + } /* make sure entire packet fits in buffer - if not, will need to split into multiple buffers */ if (rbl > b_length) @@ -1213,8 +1214,8 @@ t_stat xq_process_rbdl(CTLR* xq) if (b_length <= rbl + 2) { wstatus = Map_WriteW(address + rbl, 2, &qdtc_chip_extra); if (wstatus) return xq_nxm_error(xq); + } } - } break; case ETH_ITM_LOOPBACK: /* loopback packet */ xq->var->stats.loop += 1; @@ -1232,7 +1233,7 @@ t_stat xq_process_rbdl(CTLR* xq) xq->var->rbdl_buf[4] = (rbl & 0x0700); /* high bits of rbl */ xq->var->rbdl_buf[4] |= 0x00f8; /* set reserved bits to 1 */ break; - } + } if (item->packet.used < item->packet.len) xq->var->rbdl_buf[4] |= XQ_RST_LASTNOT; /* not last segment */ xq->var->rbdl_buf[5] = ((rbl & 0x00FF) << 8) | (rbl & 0x00FF); @@ -1261,7 +1262,7 @@ t_stat xq_process_rbdl(CTLR* xq) /* signal reception complete */ xq_csr_set_clr(xq, XQ_CSR_RI, 0); - } + } /* set to next bdl (implicit chain) */ xq->var->rbdl_ba += 12; @@ -1414,11 +1415,11 @@ t_stat xq_process_setup(CTLR* xq) } /* finalize sanity timer state */ - if (xq->var->sanity.enabled != 2) { + if (xq->var->sanity.enabled & XQ_SAN_HW_SW) { if (xq->var->csr & XQ_CSR_SE) - xq->var->sanity.enabled = 1; + xq->var->sanity.enabled |= XQ_SAN_ENABLE; else - xq->var->sanity.enabled = 0; + xq->var->sanity.enabled &= ~XQ_SAN_ENABLE; } xq_reset_santmr(xq); @@ -1635,35 +1636,20 @@ void xq_show_debug_bdl(CTLR* xq, uint32 bdl_ba) t_stat xq_dispatch_rbdl(CTLR* xq) { - int i; - int32 rstatus, wstatus; - sim_debug(DBG_TRC, xq->dev, "xq_dispatch_rbdl()\n"); /* mark receive bdl valid */ xq_csr_set_clr(xq, 0, XQ_CSR_RL); - /* init receive bdl buffer */ - for (i=0; i<6; i++) - xq->var->rbdl_buf[i] = 0; - /* get address of first receive buffer */ xq->var->rbdl_ba = ((xq->var->rbdl[1] & 0x3F) << 16) | (xq->var->rbdl[0] & ~01); /* When debugging, walk and display the buffer descriptor list */ xq_show_debug_bdl(xq, xq->var->rbdl_ba); - /* get first receive buffer */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* is buffer valid? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq_csr_set_clr(xq, XQ_CSR_RL, 0); - return SCPE_OK; - } + /* get receive bdl flags and descriptor bits from memory */ + if (Map_ReadW (xq->var->rbdl_ba, 4, &xq->var->rbdl_buf[0])) + return xq_nxm_error(xq); /* process any waiting packets in receive queue */ if (xq->var->ReadQ.count) @@ -2199,7 +2185,6 @@ t_stat xq_wr_var(CTLR* xq, int32 data) return SCPE_OK; } -#ifdef VM_PDP11 t_stat xq_process_bootrom (CTLR* xq) { /* @@ -2258,7 +2243,6 @@ t_stat xq_process_bootrom (CTLR* xq) return SCPE_OK; } -#endif /* ifdef VM_PDP11 */ t_stat xq_wr_csr(CTLR* xq, int32 data) { @@ -2294,11 +2278,9 @@ t_stat xq_wr_csr(CTLR* xq, int32 data) /* update CSR bits */ xq_csr_set_clr (xq, set_bits, clr_bits); -#ifdef VM_PDP11 /* request boot/diagnostic rom? [PDP-11 only] */ if ((xq->var->csr & XQ_CSR_BP) == XQ_CSR_BP) /* all bits must be on */ xq_process_bootrom(xq); -#endif return SCPE_OK; } @@ -2371,7 +2353,7 @@ t_stat xq_wr_srqr(CTLR* xq, int32 data) xq->dib->vec = xq->var->init.vector; xq->var->tbindx = xq->var->rbindx = 0; - if ((xq->var->sanity.enabled) && (xq->var->init.options & XQ_IN_OP_HIT)) { + if ((xq->var->sanity.enabled & XQ_SAN_HW_SW) && (xq->var->init.options & XQ_IN_OP_HIT)) { xq->var->sanity.quarter_secs = 4*xq->var->init.hit_timeout; } xq->var->icr = xq->var->init.options & XQ_IN_OP_INT; @@ -2537,7 +2519,7 @@ t_stat xq_reset(DEVICE* dptr) break; case XQ_T_DELQA: case XQ_T_DELQA_PLUS: - xq->var->var = (xq->var->lockmode ? 0 : XQ_VEC_MS) | ((xq->var->sanity.enabled == 2) ? XQ_VEC_OS : 0); + xq->var->var = (xq->var->lockmode ? 0 : XQ_VEC_MS) | ((xq->var->sanity.enabled & XQ_SAN_HW_SW) ? XQ_VEC_OS : 0); xq->var->mode = (xq->var->lockmode ? XQ_T_DEQNA : XQ_T_DELQA); break; } @@ -2575,9 +2557,8 @@ t_stat xq_reset(DEVICE* dptr) sim_cancel(&xq->unit[2]); /* set hardware sanity controls */ - if (xq->var->sanity.enabled) { + if (xq->var->sanity.enabled & XQ_SAN_HW_SW) xq->var->sanity.quarter_secs = XQ_HW_SANITY_SECS * 4/*qsec*/; - } if (sim_switches & SWMASK ('P')) { /* Powerup? */ memset (&xq->var->setup, 0, sizeof(xq->var->setup)); @@ -2592,8 +2573,8 @@ t_stat xq_reset(DEVICE* dptr) void xq_reset_santmr(CTLR* xq) { - sim_debug(DBG_TRC, xq->dev, "xq_reset_santmr(enable=%d, qsecs=%d)\n", (xq->var->sanity.enabled ? 1 : 0), xq->var->sanity.quarter_secs); - if (xq->var->sanity.enabled) { + sim_debug(DBG_TRC, xq->dev, "xq_reset_santmr(enable=%d, qsecs=%d)\n", ((xq->var->sanity.enabled & XQ_SAN_ENABLE) ? 1 : 0), xq->var->sanity.quarter_secs); + if (xq->var->sanity.enabled & XQ_SAN_ENABLE) { sim_debug(DBG_SAN, xq->dev, "SANITY TIMER RESETTING, qsecs: %d\n", xq->var->sanity.quarter_secs); /* reset sanity countdown timer to max count */ @@ -2736,18 +2717,21 @@ t_stat xq_tmrsvc(UNIT* uptr) { CTLR* xq = xq_unit2ctlr(uptr); - /* has sanity timer expired? if so, reboot */ - if (xq->var->sanity.enabled) + /* is sanity timer running and has it expired? if so, reboot */ + if (xq->var->sanity.enabled & XQ_SAN_ENABLE) { + sim_debug(DBG_SAN, xq->dev, "SANITY TIMER TICK, %d qsecs remaining out of %d qsecs\n", xq->var->sanity.timer-1, xq->var->sanity.quarter_secs); if (--xq->var->sanity.timer <= 0) { + sim_debug(DBG_SAN, xq->dev, "SANITY TIMER EXPIRED, after %d qsecs\n", xq->var->sanity.quarter_secs); if (xq->var->mode != XQ_T_DELQA_PLUS) return xq_boot_host(xq); else { /* DELQA-T Host Inactivity Timer expiration means switch out of DELQA-T mode */ sim_debug(DBG_TRC, xq->dev, "xq_tmrsvc(DELQA-PLUS Host Inactivity Expired\n"); xq->var->mode = XQ_T_DELQA; xq->var->iba = xq->var->srr = 0; - xq->var->var = (xq->var->lockmode ? 0 : XQ_VEC_MS) | ((xq->var->sanity.enabled == 2) ? XQ_VEC_OS : 0); + xq->var->var = (xq->var->lockmode ? 0 : XQ_VEC_MS) | ((xq->var->sanity.enabled & XQ_SAN_HW_SW) ? XQ_VEC_OS : 0); } } + } /* has system id timer expired? if so, do system id */ if (--xq->var->idtmr <= 0) { @@ -3078,25 +3062,13 @@ t_stat xq_boot (int32 unitno, DEVICE *dptr) #ifdef VM_PDP11 size_t i; DIB *dib = (DIB *)dptr->ctxt; -CTLR *xq = xq_unit2ctlr(&dptr->units[unitno]); -uint16 *bootrom = NULL; extern int32 REGFILE[6][2]; /* R0-R5, two sets */ extern uint16 *M; /* Memory */ -if (xq->var->type == XQ_T_DEQNA) - bootrom = xq_bootrom_deqna; -else - if (xq->var->type == XQ_T_DELQA) - bootrom = xq_bootrom_delqa; - else - if (xq->var->type == XQ_T_DELQA_PLUS) - bootrom = xq_bootrom_delqat; - for (i = 0; i < BOOT_LEN; i++) - M[(BOOT_START >> 1) + i] = bootrom[i]; + M[(BOOT_START >> 1) + i] = boot_rom[i]; cpu_set_boot (BOOT_ENTRY); -REGFILE[0][0] = 0; -REGFILE[1][0] = dib->ba; +REGFILE[0][0] = ((dptr == &xq_dev) ? 4 : 5); return SCPE_OK; #else return SCPE_NOFNC; diff --git a/PDP11/pdp11_xq.h b/PDP11/pdp11_xq.h index 21be50ce..3038db07 100644 --- a/PDP11/pdp11_xq.h +++ b/PDP11/pdp11_xq.h @@ -104,6 +104,8 @@ enum xq_type {XQ_T_DEQNA, XQ_T_DELQA, XQ_T_DELQA_PLUS}; struct xq_sanity { int enabled; /* sanity timer enabled? 2=HW, 1=SW, 0=off */ +#define XQ_SAN_HW_SW 2 +#define XQ_SAN_ENABLE 1 int quarter_secs; /* sanity timer value in 1/4 seconds */ int timer; /* countdown timer */ }; diff --git a/PDP11/pdp11_xq_bootrom.h b/PDP11/pdp11_xq_bootrom.h index 454fc0a8..3f92653b 100644 --- a/PDP11/pdp11_xq_bootrom.h +++ b/PDP11/pdp11_xq_bootrom.h @@ -37,7 +37,6 @@ #ifndef PDP11_XQ_BOOTROM_H #define PDP11_XQ_BOOTROM_H -#ifdef VM_PDP11 /* Word 0: NOP Word 1: Branch to extended primary boot (EPB) @@ -50,11 +49,6 @@ which are being simulated (DEQNA, DELQA and DELQA-T) */ -#define BOOT_LEN 512 /* EPB Code size */ -#define BOOT_START 0 /* Initial load Address of the EPB code */ -#define BOOT_ENTRY 0 /* Start address of EPB code */ -#define BOOT_XSUM_OFFSET 6 /* Location containing checksum offset */ - /* Bootrom code is from executing a Boot Diagnostic load command to a real DEQNA (M7504) board (thus loading the ROM contents to RAM) and using ODT @@ -1112,6 +1106,192 @@ uint16 xq_bootrom_delqat[2048] = { 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, /* 0FE0 (0007740) */ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x84D2, /* 0FF0 (0007760) */ }; + +#ifdef VM_PDP11 +#if 0 +Tim Shoppa said: + +Hopefully better late than never, but I finally got to digging and +found that the CIQNDC0 sources give an example bootstrap: + + IDENTIFICATION + -------------- + +PRODUCT CODE: AC-T612A-MC + +PRODUCT NAME: CIQNDC0 DEQNA ROM RESIDENT CODE + +PRODUCT DATE: 29 June 1984 + +MAINTAINER: DIAGNOSTIC ENGINEERING + +[...] + +4.1 PRIMARY BOOT PROCESS + +The primary boot, resident in the host, normally checks for the existence +of the device it is going to boot from, boots 512. bytes from the device, +verifies the operation, sets parameters and transfers to the "booted" code. + +A suggested method for "checking" for a QNA is as follows: + + Write a "2" (a module reset) into the QNA's CSR at location + 17774456 or 17774476. + + Read back the CSR and compare against an octal 000062. + + If equal then there is most likely a QNA there. + + If not equal (Bus time-out?) then "sniff" elsewhere. + + Write a "0" back into the CSR to "reset" the reset bit. + +If a QNA is present and it is to be used for the boot the first thing +then: + + A descriptor for a 256. word "receive" is validated in the QNA. + + Data is read into the host starting at location 0 + The descriptor is 8 words long, words 0, 4, 5 and 6 will + contain operation status. Words 1, 2, 3, and 7 are constant. + + Write a "1010" into the CSR to move the boot code into the QNA's + internal receive buffer and delay for approximately one second. + + Write a "1000" into the CSR to move the data in the internal + receive buffer into host memory and delay for approximately one + second. + + Reset the QNA and check the CSR for proper status. + + Checked the receive descriptor for nominal states. + + The Data transfer is verified. + + If the QNA primary boot code detects a failure at this point the + host boot is re-entered. + + Transfer is made to the first location of the freshly loaded + portion of the QNA BD ROM. + + R1 contains the I/O Page address of the QNA (174440) + + R0 contains a "000000" if the DECnet boot resident on the + QNA is to be used. + - or - + If R0 is greater than "000777" an effective JMP (R0) is + executed in lieu of the DECnet boot. + + + Location 12 contains a "000000" if the EPB is to halt when + an error is detected. + - or - + If loaction 12 is greater than "000000" an effective JMP @12 + is executed in lieu of a "HALT". + +4.1.1 EXPECTED VALUES FOR VERIFICATION + +CSR is checked for a nominal state as are the status words in the receive +descriptor. + + Status Nominal + --------------- + CSR 000060 or 010060 + FLAG 14xxxx + BSW1 14xxxx + BSW2 14xxxx + CSW0 177777 + + x - don't care bits + +Next the actual data transfer is verified by checking the first three bytes +of the data transferred for standard values. These first locations and their +expected contents are: + + Location Contents + -------------------------- + 0000-1 000240 (NOP) + 0002 001 (a BR instruction) + 0003 xxx + + 0004 + .. The QNA Extended Primary Boot (EPB) code + 0777 + +4.1.2 SAMPLE PRIMARY BOOT CODE + +Below is an example of how a primary boot could be implemented on a typical +PDP-11 based host. + +Upon entry R0 is coded to indicate which QNA is to be used for the boot. +The first 32K bytes of the host memory is assumed to be mapped 1 to 1 +physical to logical. The I/O page is mapped to the last 4K. + +Assume settings for R0 as follows: + + R0 - Contains a "4" for QNA#1 @ 174440 + Contains a "5" for QNA#2 @ 174460 +PDP-11 code for booting the DEQNA EPB might be as follows: +#endif + +#define BOOT_LEN (sizeof(boot_rom)/sizeof(uint16))/* Code size */ +#define BOOT_START 020000 /* Initial load Address of the Boot code */ +#define BOOT_ENTRY (BOOT_START+0) /* Start address of Boot code */ + +static const uint16 boot_rom[] = { + // DESC = 4000 ; Descriptor List Address + // DECnet = 0 ; MOP boot request + 0012701, 0174440, // 0000 mov #174440,r1 ; assume device is DEQNA #1 + 0022700, 0000004, // 0004 cmp #4,r0 + 0001402, // 0010 beq 10$ ; good assumption + 0012701, 0177460, // 0012 mov #174460,r1 ; select device at DEQNA #2 + + 0012761, 0000002, 0000016, // 0016 10$: mov #SR,16(r1) ; assert QNA software reset + 0032761, 0000062, 0000016, // 0024 bit #,16(r1); "nominal" status during reset + 0001466, // 0032 beq 90$ ;? not a proper response, halt + 0005061, 0000016, // 0034 clr 16(r1) ; clear reset state and all others + + 0012703, 0004000, // 0040 mov #DESC,r3 ; pick an address for descriptor + 0010304, // 0044 mov r3,r4 + 0012724, 0100000, // 0046 mov #100000,(r4)+ ; Flag word, changed to -1 + 0011324, // 0052 mov (r3),(r4)+ ; Valid buffer descriptor, receive + 0005024, // 0054 clr (r4)+ ; location zero + 0012724, 0177400, // 0056 mov #-400,(r4)+ ; 256. words or 512. bytes + 0005024, // 0062 clr (r4)+ ; Descriptor status 1, changed to -1 + 0005024, // 0064 clr (r4)+ ; Descriptor status 2, changed to -1 + 0011324, // 0066 mov (r3),(r4)+ ; Another flag word, changed to -1 + 0012714, 0020000, // 0070 mov #020000,(r4) ; end descriptor code + 0010361, 0000004, // 0074 mov r3,04(r1) ; receive descriptor low address + 0005061, 0000006, // 0100 clr 06(r1) ; validate a receive descriptor + + 0012761, 0001010, 0000016, // 0104 mov #,16(r1) ; Instruct QNA to unload the EPB code + 0005000, // 0112 clr r0 ; delay about 60 ms for transfer of + 0077001, // 0114 sob r0,. ; i8051 contents to receive FIFO + 0012761, 0001000, 0000016, // 0116 mov #,16(r1) ; Complete the EPB unload + 0005000, // 0124 clr r0 ; delay about 60 ms for transfer of + 0077001, // 0126 sob r0,. ; receive FIFO to host memory + 0012761, 0000002, 0000016, // 0130 mov #SR,16(r1) ; reset + 0005061, 0000016, // 0136 clr 16(r1) ; Final reset to complete operation + + 0012704, 0004014, // 0142 mov #,r4 + 0042714, 0037777, // 0146 bic #037777,(r4) ; check if last status word was updated + 0022714, 0140000, // 0152 cmp #140000,(r4) ; + 0001014, // 0156 bne 90$ ; + + 0022737, 0000240, 0000000, // 0160 cmp #240,@#0 ; check for QNA boot block + 0001010, // 0166 bne 90$ ;? operation data check + 0122737, 0000001, 0000003, // 0170 cmpb #001,@#3 ; check for "BR" opcode + 0001004, // 0176 bne 90$ ;? operation data check + + 0012700, 0000000, // 0200 mov #DECnet,r0 ; Load DECnet code (or other code into R0) + 0000137, 0000000, // 0204 jmp @#0 ; go to extended primary boot + + // ; R0 - set to zero for DECnet boot + // ; R1 - has address of QNA #1 or #2 + + 0000000, // 0210 90$: halt ;? QNA error, get back to host boot control? + 0000776, // 0212 br 90$ + }; #endif /* VM_PDP11 */ #endif /* _PDP11_XQ_BOOTROM_H */