1 /* hp2100_ipl.c: HP 2000 interprocessor link simulator
3 Copyright (c) 2002-2007, Robert M Supnik
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
26 ipli, iplo 12875A interprocessor link
28 01-Mar-07 JDB IPLI EDT delays DMA completion interrupt for TSB
30 28-Dec-06 JDB Added ioCRS state to I/O decoders
31 16-Aug-05 RMS Fixed C++ declaration and cast problems
32 07-Oct-04 JDB Fixed enable/disable from either device
33 26-Apr-04 RMS Fixed SFS x,C and SFC x,C
34 Implemented DMA SRQ (follows FLG)
35 21-Dec-03 RMS Adjusted ipl_ptime for TSB (from Mike Gemeny)
36 09-May-03 RMS Added network device flag
37 31-Jan-03 RMS Links are full duplex (found by Mike Gemeny)
39 The 12875A Processor Interconnect Kit consists four 12566A Microcircuit
40 Interface cards. Two are used in each processor. One card in each system is
41 used to initiate transmissions to the other, and the second card is used to
42 receive transmissions from the other. Each pair of cards forms a
43 bidirectional link, as the sixteen data lines are cross-connected, so that
44 data sent and status returned are supported. In each processor, data is sent
45 on the lower priority card and received on the higher priority card. Two
46 sets of cards are used to support simultaneous transmission in both
50 - 12875A Processor Interconnect Kit Operating and Service Manual
51 (12875-90002, Jan-1974)
54 #include "hp2100_defs.h"
58 #define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
59 #define UNIT_V_ACTV (UNIT_V_UF + 1) /* making connection */
60 #define UNIT_V_ESTB (UNIT_V_UF + 2) /* connection established */
61 #define UNIT_V_HOLD (UNIT_V_UF + 3) /* character holding */
62 #define UNIT_DIAG (1 << UNIT_V_DIAG)
63 #define UNIT_ACTV (1 << UNIT_V_ACTV)
64 #define UNIT_ESTB (1 << UNIT_V_ESTB)
65 #define UNIT_HOLD (1 << UNIT_V_HOLD)
66 #define IBUF buf /* input buffer */
67 #define OBUF wait /* output buffer */
68 #define DSOCKET u3 /* data socket */
69 #define LSOCKET u4 /* listening socket */
73 #define DEB_CMDS (1 << 0) /* Command initiation and completion */
74 #define DEB_CPU (1 << 1) /* CPU I/O */
75 #define DEB_XFER (1 << 2) /* Socket receive and transmit */
78 extern uint32 dev_cmd
[2], dev_ctl
[2], dev_flg
[2], dev_fbf
[2], dev_srq
[2];
81 int32 ipl_edtdelay
= 1; /* EDT delay (msec) */
82 int32 ipl_ptime
= 31; /* polling interval */
83 int32 ipl_stopioe
= 0; /* stop on error */
84 int32 ipl_hold
[2] = { 0 }; /* holding character */
86 DEVICE ipli_dev
, iplo_dev
;
87 int32
ipliio (int32 inst
, int32 IR
, int32 dat
);
88 int32
iploio (int32 inst
, int32 IR
, int32 dat
);
89 int32
iplio (UNIT
*uptr
, int32 inst
, int32 IR
, int32 dat
);
90 t_stat
ipl_svc (UNIT
*uptr
);
91 t_stat
ipl_reset (DEVICE
*dptr
);
92 t_stat
ipl_attach (UNIT
*uptr
, char *cptr
);
93 t_stat
ipl_detach (UNIT
*uptr
);
94 t_stat
ipl_boot (int32 unitno
, DEVICE
*dptr
);
95 t_stat
ipl_dscln (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
96 t_stat
ipl_setdiag (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
97 t_bool
ipl_check_conn (UNIT
*uptr
);
99 /* Debug flags table */
102 { "CMDS", DEB_CMDS
},
104 { "XFER", DEB_XFER
},
107 /* IPLI data structures
109 ipli_dev IPLI device descriptor
110 ipli_unit IPLI unit descriptor
111 ipli_reg IPLI register list
115 { IPLI
, 0, 0, 0, 0, 0, &ipliio
},
116 { IPLO
, 0, 0, 0, 0, 0, &iploio
}
119 #define ipli_dib ipl_dib[0]
120 #define iplo_dib ipl_dib[1]
123 { UDATA (&ipl_svc
, UNIT_ATTABLE
, 0) },
124 { UDATA (&ipl_svc
, UNIT_ATTABLE
, 0) }
127 #define ipli_unit ipl_unit[0]
128 #define iplo_unit ipl_unit[1]
131 { ORDATA (IBUF
, ipli_unit
.IBUF
, 16) },
132 { ORDATA (OBUF
, ipli_unit
.OBUF
, 16) },
133 { FLDATA (CMD
, ipli_dib
.cmd
, 0) },
134 { FLDATA (CTL
, ipli_dib
.ctl
, 0) },
135 { FLDATA (FLG
, ipli_dib
.flg
, 0) },
136 { FLDATA (FBF
, ipli_dib
.fbf
, 0) },
137 { FLDATA (SRQ
, ipli_dib
.srq
, 0) },
138 { ORDATA (HOLD
, ipl_hold
[0], 8) },
139 { DRDATA (TIME
, ipl_ptime
, 24), PV_LEFT
},
140 { FLDATA (STOP_IOE
, ipl_stopioe
, 0) },
141 { ORDATA (DEVNO
, ipli_dib
.devno
, 6), REG_HRO
},
146 { UNIT_DIAG
, UNIT_DIAG
, "diagnostic mode", "DIAG", &ipl_setdiag
},
147 { UNIT_DIAG
, 0, "link mode", "LINK", &ipl_setdiag
},
148 { MTAB_XTD
| MTAB_VDV
, 0, NULL
, "DISCONNECT",
149 &ipl_dscln
, NULL
, NULL
},
150 { MTAB_XTD
| MTAB_VDV
, 1, "DEVNO", "DEVNO",
151 &hp_setdev
, &hp_showdev
, &ipli_dev
},
156 "IPLI", &ipli_unit
, ipli_reg
, ipl_mod
,
157 1, 10, 31, 1, 16, 16,
158 &tmxr_ex
, &tmxr_dep
, &ipl_reset
,
159 &ipl_boot
, &ipl_attach
, &ipl_detach
,
160 &ipli_dib
, DEV_NET
| DEV_DISABLE
| DEV_DIS
| DEV_DEBUG
,
161 0, ipl_deb
, NULL
, NULL
164 /* IPLO data structures
166 iplo_dev IPLO device descriptor
167 iplo_unit IPLO unit descriptor
168 iplo_reg IPLO register list
172 { ORDATA (IBUF
, iplo_unit
.IBUF
, 16) },
173 { ORDATA (OBUF
, iplo_unit
.OBUF
, 16) },
174 { FLDATA (CMD
, iplo_dib
.cmd
, 0) },
175 { FLDATA (CTL
, iplo_dib
.ctl
, 0) },
176 { FLDATA (FLG
, iplo_dib
.flg
, 0) },
177 { FLDATA (FBF
, iplo_dib
.fbf
, 0) },
178 { FLDATA (SRQ
, iplo_dib
.srq
, 0) },
179 { ORDATA (HOLD
, ipl_hold
[1], 8) },
180 { DRDATA (TIME
, ipl_ptime
, 24), PV_LEFT
},
181 { ORDATA (DEVNO
, iplo_dib
.devno
, 6), REG_HRO
},
186 "IPLO", &iplo_unit
, iplo_reg
, ipl_mod
,
187 1, 10, 31, 1, 16, 16,
188 &tmxr_ex
, &tmxr_dep
, &ipl_reset
,
189 &ipl_boot
, &ipl_attach
, &ipl_detach
,
190 &iplo_dib
, DEV_NET
| DEV_DISABLE
| DEV_DIS
| DEV_DEBUG
,
191 0, ipl_deb
, NULL
, NULL
194 /* I/O instructions */
196 int32
ipliio (int32 inst
, int32 IR
, int32 dat
)
198 return iplio (&ipli_unit
, inst
, IR
, dat
);
201 int32
iploio (int32 inst
, int32 IR
, int32 dat
)
203 return iplio (&iplo_unit
, inst
, IR
, dat
);
206 /* I/O handler for the IPLI and IPLO devices.
208 Implementation note: 2000 Access has a race condition that manifests itself
209 by an apparently normal boot and operational system console but no PLEASE LOG
210 IN response to terminals connected to the multiplexer. The frequency of
211 occurrence is higher on multiprocessor host systems, where the SP and IOP
212 instances may execute concurrently.
214 The cause is this code in the SP disc loader source (2883.asm, 7900.asm,
215 790X.asm, 79X3.asm, and 79XX.asm):
218 JSB IOPMA,I DEVICE TABLE
220 STC DMAHS,C TURN ON DMA
223 STC CH2,C SET CORRECT
224 CLC CH2 FLAG DIRECTION
226 The STC/CLC normally would cause a second "request device table" command to
227 be recognized by the IOP, except that the IOP DMA setup routine "DMAXF" (in
228 D61.asm) has specified an end-of-block CLC that holds off the IPL interrupt,
229 and the completion interrupt routine "DMACP" ends with a STC,C that clears
232 In hardware, the two CPUs are essentially interlocked by the DMA transfer,
233 and DMA completion interrupts occur almost simultaneously. Therefore, the
234 STC/CLC in the SP is guaranteed to occur before the STC,C in the IOP. Under
235 simulation, and especially on multiprocessor hosts, that guarantee does not
236 hold. If the STC/CLC occurs after the STC,C, then the IOP starts a second
237 device table DMA transfer, which the SP is not expecting. The IOP never
238 processes the subsequent "start timesharing" command, and the muxtiplexer is
241 We employ a workaround that decreases the incidence of the problem: DMA
242 output completion interrupts are delayed to allow the other SIMH instance a
243 chance to process its own DMA completion. We do this by processing the EDT
244 (End Data Transfer) I/O backplane signal and "sleep"ing for a short time if
245 the transfer was an output transfer ("dat" contains the DMA channel number
246 and direction flag for EDT signals).
249 int32
iplio (UNIT
*uptr
, int32 inst
, int32 IR
, int32 dat
)
254 DEVICE
*dbdev
; /* device ptr for debug */
255 static const char *iotype
[] = { "Status", "Command" };
257 uc
= (uptr
== &ipli_unit
) ? 'I' : 'O'; /* identify unit for debug */
258 dbdev
= (uptr
== &ipli_unit
) ? &ipli_dev
: &iplo_dev
; /* identify device for debug */
260 u
= (uptr
- ipl_unit
); /* get unit number */
261 dev
= IR
& I_DEVMASK
; /* get device no */
262 switch (inst
) { /* case on opcode */
264 case ioFLG
: /* flag clear/set */
265 if ((IR
& I_HC
) == 0) { setFSR (dev
); } /* STF */
268 case ioSFC
: /* skip flag clear */
269 if (FLG (dev
) == 0) PC
= (PC
+ 1) & VAMASK
;
272 case ioSFS
: /* skip flag set */
273 if (FLG (dev
) != 0) PC
= (PC
+ 1) & VAMASK
;
276 case ioOTX
: /* output */
279 if (DEBUG_PRJ (dbdev
, DEB_CPU
))
280 fprintf (sim_deb
, ">>IPL%c OTx: %s = %06o\n", uc
, iotype
[u
], dat
);
283 case ioLIX
: /* load */
286 case ioMIX
: /* merge */
287 dat
= dat
| uptr
->IBUF
; /* get return data */
289 if (DEBUG_PRJ (dbdev
, DEB_CPU
))
290 fprintf (sim_deb
, ">>IPL%c LIx: %s = %06o\n", uc
, iotype
[u
^ 1], dat
);
293 case ioCRS
: /* control reset */
294 clrCMD (dev
); /* clear ctl, cmd */
298 case ioCTL
: /* control clear/set */
299 if (IR
& I_CTL
) { /* CLC */
300 clrCMD (dev
); /* clear ctl, cmd */
303 if (DEBUG_PRJ (dbdev
, DEB_CMDS
))
304 fprintf (sim_deb
, ">>IPL%c CLC: Command cleared\n", uc
);
308 setCMD (dev
); /* set ctl, cmd */
311 if (DEBUG_PRJ (dbdev
, DEB_CMDS
))
312 fprintf (sim_deb
, ">>IPL%c STC: Command set\n", uc
);
314 if (uptr
->flags
& UNIT_ATT
) { /* attached? */
315 if ((uptr
->flags
& UNIT_ESTB
) == 0) { /* established? */
316 if (!ipl_check_conn (uptr
)) /* not established? */
317 return STOP_NOCONN
; /* lose */
318 uptr
->flags
= uptr
->flags
| UNIT_ESTB
;
320 msg
[0] = (uptr
->OBUF
>> 8) & 0377;
321 msg
[1] = uptr
->OBUF
& 0377;
322 sta
= sim_write_sock (uptr
->DSOCKET
, msg
, 2);
324 if (DEBUG_PRJ (dbdev
, DEB_XFER
))
326 ">>IPL%c STC: Socket write = %06o, status = %d\n",
327 uc
, uptr
->OBUF
, sta
);
329 if (sta
== SOCKET_ERROR
) {
330 printf ("IPL: socket write error\n");
335 else if (uptr
->flags
& UNIT_DIAG
) { /* diagnostic mode? */
336 u
= (uptr
- ipl_unit
) ^ 1; /* find other device */
337 ipl_unit
[u
].IBUF
= uptr
->OBUF
; /* output to other */
338 odev
= ipl_dib
[u
].devno
; /* other device no */
339 setFSR (odev
); /* set other flag */
341 else return SCPE_UNATT
; /* lose */
345 case ioEDT
: /* End of DMA data transfer */
346 if ((dat
& DMA2_OI
) == 0) { /* output transfer? */
347 if (DEBUG_PRJ (dbdev
, DEB_CMDS
))
349 ">>IPL%c EDT: Delaying DMA completion interrupt for %d msec\n",
351 sim_os_ms_sleep (ipl_edtdelay
); /* delay completion */
359 if (IR
& I_HC
) { clrFSR (dev
); } /* H/C option */
363 /* Unit service - poll for input */
365 t_stat
ipl_svc (UNIT
*uptr
)
369 DEVICE
*dbdev
; /* device ptr for debug */
371 u
= uptr
- ipl_unit
; /* get link number */
372 if ((uptr
->flags
& UNIT_ATT
) == 0) return SCPE_OK
; /* not attached? */
373 sim_activate (uptr
, ipl_ptime
); /* reactivate */
374 if ((uptr
->flags
& UNIT_ESTB
) == 0) { /* not established? */
375 if (!ipl_check_conn (uptr
)) return SCPE_OK
; /* check for conn */
376 uptr
->flags
= uptr
->flags
| UNIT_ESTB
;
378 nb
= sim_read_sock (uptr
->DSOCKET
, msg
, ((uptr
->flags
& UNIT_HOLD
)? 1: 2));
379 if (nb
< 0) { /* connection closed? */
380 printf ("IPL: socket read error\n");
383 if (nb
== 0) return SCPE_OK
; /* no data? */
384 if (uptr
->flags
& UNIT_HOLD
) { /* holdover byte? */
385 uptr
->IBUF
= (ipl_hold
[u
] << 8) | (((int32
) msg
[0]) & 0377);
386 uptr
->flags
= uptr
->flags
& ~UNIT_HOLD
;
389 ipl_hold
[u
] = ((int32
) msg
[0]) & 0377;
390 uptr
->flags
= uptr
->flags
| UNIT_HOLD
;
392 else uptr
->IBUF
= ((((int32
) msg
[0]) & 0377) << 8) |
393 (((int32
) msg
[1]) & 0377);
394 dev
= ipl_dib
[u
].devno
; /* get device number */
395 clrCMD (dev
); /* clr cmd, set flag */
398 uc
= (uptr
== &ipli_unit
) ? 'I' : 'O'; /* identify unit for debug */
399 dbdev
= (uptr
== &ipli_unit
) ? &ipli_dev
: &iplo_dev
; /* identify device for debug */
401 if (DEBUG_PRJ (dbdev
, DEB_XFER
))
402 fprintf (sim_deb
, ">>IPL%c svc: Socket read = %06o, status = %d\n",
408 t_bool
ipl_check_conn (UNIT
*uptr
)
412 if (uptr
->flags
& UNIT_ESTB
) return TRUE
; /* established? */
413 if (uptr
->flags
& UNIT_ACTV
) { /* active connect? */
414 if (sim_check_conn (uptr
->DSOCKET
, 0) <= 0) return FALSE
;
417 sock
= sim_accept_conn (uptr
->LSOCKET
, NULL
); /* poll connect */
418 if (sock
== INVALID_SOCKET
) return FALSE
; /* got a live one? */
419 uptr
->DSOCKET
= sock
; /* save data socket */
421 uptr
->flags
= uptr
->flags
| UNIT_ESTB
; /* conn established */
427 t_stat
ipl_reset (DEVICE
*dptr
)
429 DIB
*dibp
= (DIB
*) dptr
->ctxt
;
430 UNIT
*uptr
= dptr
->units
;
432 hp_enbdis_pair (dptr
, /* make pair cons */
433 (dptr
== &ipli_dev
)? &iplo_dev
: &ipli_dev
);
434 dibp
->cmd
= dibp
->ctl
= 0; /* clear cmd, ctl */
435 dibp
->flg
= dibp
->fbf
= dibp
->srq
= 1; /* set flg, fbf, srq */
436 uptr
->IBUF
= uptr
->OBUF
= 0; /* clr buffers */
437 if (uptr
->flags
& UNIT_ATT
) sim_activate (uptr
, ipl_ptime
);
438 else sim_cancel (uptr
); /* deactivate unit */
439 uptr
->flags
= uptr
->flags
& ~UNIT_HOLD
;
445 attach -l - listen for connection on port
446 attach -c - connect to ip address and port
449 t_stat
ipl_attach (UNIT
*uptr
, char *cptr
)
451 extern int32 sim_switches
;
453 uint32 i
, t
, ipa
, ipp
, oldf
;
457 r
= get_ipaddr (cptr
, &ipa
, &ipp
);
458 if ((r
!= SCPE_OK
) || (ipp
== 0)) return SCPE_ARG
;
460 if (oldf
& UNIT_ATT
) ipl_detach (uptr
);
461 if ((sim_switches
& SWMASK ('C')) ||
462 ((sim_switches
& SIM_SW_REST
) && (oldf
& UNIT_ACTV
))) {
463 if (ipa
== 0) ipa
= 0x7F000001;
464 newsock
= sim_connect_sock (ipa
, ipp
);
465 if (newsock
== INVALID_SOCKET
) return SCPE_IOERR
;
466 printf ("Connecting to IP address %d.%d.%d.%d, port %d\n",
467 (ipa
>> 24) & 0xff, (ipa
>> 16) & 0xff,
468 (ipa
>> 8) & 0xff, ipa
& 0xff, ipp
);
469 if (sim_log
) fprintf (sim_log
,
470 "Connecting to IP address %d.%d.%d.%d, port %d\n",
471 (ipa
>> 24) & 0xff, (ipa
>> 16) & 0xff,
472 (ipa
>> 8) & 0xff, ipa
& 0xff, ipp
);
473 uptr
->flags
= uptr
->flags
| UNIT_ACTV
;
475 uptr
->DSOCKET
= newsock
;
478 if (ipa
!= 0) return SCPE_ARG
;
479 newsock
= sim_master_sock (ipp
);
480 if (newsock
== INVALID_SOCKET
) return SCPE_IOERR
;
481 printf ("Listening on port %d\n", ipp
);
482 if (sim_log
) fprintf (sim_log
, "Listening on port %d\n", ipp
);
483 uptr
->flags
= uptr
->flags
& ~UNIT_ACTV
;
484 uptr
->LSOCKET
= newsock
;
487 uptr
->IBUF
= uptr
->OBUF
= 0;
488 uptr
->flags
= (uptr
->flags
| UNIT_ATT
) & ~(UNIT_ESTB
| UNIT_HOLD
);
489 tptr
= (char *) malloc (strlen (cptr
) + 1); /* get string buf */
490 if (tptr
== NULL
) { /* no memory? */
491 ipl_detach (uptr
); /* close sockets */
494 strcpy (tptr
, cptr
); /* copy ipaddr:port */
495 uptr
->filename
= tptr
; /* save */
496 sim_activate (uptr
, ipl_ptime
); /* activate poll */
497 if (sim_switches
& SWMASK ('W')) { /* wait? */
498 for (i
= 0; i
< 30; i
++) { /* check for 30 sec */
499 if (t
= ipl_check_conn (uptr
)) break; /* established? */
500 if ((i
% 10) == 0) /* status every 10 sec */
501 printf ("Waiting for connnection\n");
502 sim_os_sleep (1); /* sleep 1 sec */
504 if (t
) printf ("Connection established\n");
511 t_stat
ipl_detach (UNIT
*uptr
)
513 if (!(uptr
->flags
& UNIT_ATT
)) return SCPE_OK
; /* attached? */
514 if (uptr
->flags
& UNIT_ACTV
) sim_close_sock (uptr
->DSOCKET
, 1);
516 if (uptr
->flags
& UNIT_ESTB
) /* if established, */
517 sim_close_sock (uptr
->DSOCKET
, 0); /* close data socket */
518 sim_close_sock (uptr
->LSOCKET
, 1); /* closen listen socket */
520 free (uptr
->filename
); /* free string */
521 uptr
->filename
= NULL
;
524 uptr
->flags
= uptr
->flags
& ~(UNIT_ATT
| UNIT_ACTV
| UNIT_ESTB
);
525 sim_cancel (uptr
); /* don't poll */
529 /* Disconnect routine */
531 t_stat
ipl_dscln (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
533 if (cptr
) return SCPE_ARG
;
534 if (((uptr
->flags
& UNIT_ATT
) == 0) || (uptr
->flags
& UNIT_ACTV
) ||
535 ((uptr
->flags
& UNIT_ESTB
) == 0)) return SCPE_NOFNC
;
536 sim_close_sock (uptr
->DSOCKET
, 0);
538 uptr
->flags
= uptr
->flags
& ~UNIT_ESTB
;
542 /* Diagnostic/normal mode routine */
544 t_stat
ipl_setdiag (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
547 ipli_unit
.flags
= ipli_unit
.flags
| UNIT_DIAG
;
548 iplo_unit
.flags
= iplo_unit
.flags
| UNIT_DIAG
;
551 ipli_unit
.flags
= ipli_unit
.flags
& ~UNIT_DIAG
;
552 iplo_unit
.flags
= iplo_unit
.flags
& ~UNIT_DIAG
;
557 /* Interprocessor link bootstrap routine (HP Access Manual) */
565 static const uint32 pboot
[IBL_LNT
] = {
566 0163774, /*BBL LDA ICK,I ; IPL sel code */
567 0027751, /* JMP CFG ; go configure */
568 0107700, /*ST CLC 0,C ; intr off */
569 0002702, /* CLA,CCE,SZA ; skip in */
570 0063772, /*CN LDA M26 ; feed frame */
571 0002307, /*EOC CCE,INA,SZA,RSS ; end of file? */
572 0027760, /* JMP EOT ; yes */
573 0017736, /* JSB READ ; get #char */
574 0007307, /* CMB,CCE,INB,SZB,RSS ; 2's comp; null? */
575 0027705, /* JMP EOC ; read next */
576 0077770, /* STB WC ; word in rec */
577 0017736, /* JSB READ ; get feed frame */
578 0017736, /* JSB READ ; get address */
579 0074000, /* STB 0 ; init csum */
580 0077771, /* STB AD ; save addr */
581 0067771, /*CK LDB AD ; check addr */
582 0047773, /* ADB MAXAD ; below loader */
583 0002040, /* SEZ ; E =0 => OK */
584 0102055, /* HLT 55 */
585 0017736, /* JSB READ ; get word */
586 0040001, /* ADA 1 ; cont checksum */
587 0177771, /* STB AD,I ; store word */
588 0037771, /* ISZ AD */
589 0000040, /* CLE ; force wd read */
590 0037770, /* ISZ WC ; block done? */
591 0027717, /* JMP CK ; no */
592 0017736, /* JSB READ ; get checksum */
593 0054000, /* CPB 0 ; ok? */
594 0027704, /* JMP CN ; next block */
595 0102011, /* HLT 11 ; bad csum */
597 0006600, /* CLB,CME ; E reg byte ptr */
598 0103700, /*IO1 STC RDR,C ; start reader */
599 0102300, /*IO2 SFS RDR ; wait */
600 0027741, /* JMP *-1 */
601 0106400, /*IO3 MIB RDR ; get byte */
602 0002041, /* SEZ,RSS ; E set? */
603 0127736, /* JMP RD,I ; no, done */
604 0005767, /* BLF,CLE,BLF ; shift byte */
605 0027740, /* JMP IO1 ; again */
606 0163775, /* LDA PTR,I ; get ptr code */
607 0043765, /*CFG ADA SFS ; config IO */
608 0073741, /* STA IO2 */
609 0043766, /* ADA STC */
610 0073740, /* STA IO1 */
611 0043767, /* ADA MIB */
612 0073743, /* STA IO3 */
613 0027702, /* JMP ST */
614 0063777, /*EOT LDA PSC ; put select codes */
615 0067776, /* LDB ISC ; where xloader wants */
616 0102077, /* HLT 77 */
617 0027702, /* JMP ST */
619 0102300, /*SFS SFS 0 */
620 0001400, /*STC 1400 */
621 0002500, /*MIB 2500 */
624 0177746, /*M26 -26 */
625 0000000, /*MAX -BBL */
626 0007776, /*ICK ISC */
627 0007777, /*PTR IPT */
632 t_stat
ipl_boot (int32 unitno
, DEVICE
*dptr
)
636 extern UNIT cpu_unit
;
640 devi
= ipli_dib
.devno
; /* get device no */
641 devp
= ptr_dib
.devno
;
642 PC
= ((MEMSIZE
- 1) & ~IBL_MASK
) & VAMASK
; /* start at mem top */
643 SR
= (devi
<< IBL_V_DEV
) | devp
; /* set SR */
644 for (i
= 0; i
< IBL_LNT
; i
++) M
[PC
+ i
] = pboot
[i
]; /* copy bootstrap */
645 M
[PC
+ MAX_BASE
] = (~PC
+ 1) & DMASK
; /* fix ups */
646 M
[PC
+ IPL_PNTR
] = M
[PC
+ IPL_PNTR
] | PC
;
647 M
[PC
+ PTR_PNTR
] = M
[PC
+ PTR_PNTR
] | PC
;
648 M
[PC
+ IPL_DEVA
] = devi
;
649 M
[PC
+ PTR_DEVA
] = devp
;