First Commit of my working state
[simh.git] / HP2100 / hp2100_ipl.c
1 /* hp2100_ipl.c: HP 2000 interprocessor link simulator
2
3 Copyright (c) 2002-2007, Robert M Supnik
4
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:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
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.
21
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.
25
26 ipli, iplo 12875A interprocessor link
27
28 01-Mar-07 JDB IPLI EDT delays DMA completion interrupt for TSB
29 Added debug printouts
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)
38
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
47 directions.
48
49 Reference:
50 - 12875A Processor Interconnect Kit Operating and Service Manual
51 (12875-90002, Jan-1974)
52 */
53
54 #include "hp2100_defs.h"
55 #include "sim_sock.h"
56 #include "sim_tmxr.h"
57
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 */
70
71 /* Debug flags */
72
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 */
76
77 extern uint32 PC;
78 extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
79 extern FILE *sim_log;
80 extern FILE *sim_deb;
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 */
85
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);
98
99 /* Debug flags table */
100
101 DEBTAB ipl_deb[] = {
102 { "CMDS", DEB_CMDS },
103 { "CPU", DEB_CPU },
104 { "XFER", DEB_XFER },
105 { NULL, 0 } };
106
107 /* IPLI data structures
108
109 ipli_dev IPLI device descriptor
110 ipli_unit IPLI unit descriptor
111 ipli_reg IPLI register list
112 */
113
114 DIB ipl_dib[] = {
115 { IPLI, 0, 0, 0, 0, 0, &ipliio },
116 { IPLO, 0, 0, 0, 0, 0, &iploio }
117 };
118
119 #define ipli_dib ipl_dib[0]
120 #define iplo_dib ipl_dib[1]
121
122 UNIT ipl_unit[] = {
123 { UDATA (&ipl_svc, UNIT_ATTABLE, 0) },
124 { UDATA (&ipl_svc, UNIT_ATTABLE, 0) }
125 };
126
127 #define ipli_unit ipl_unit[0]
128 #define iplo_unit ipl_unit[1]
129
130 REG ipli_reg[] = {
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 },
142 { NULL }
143 };
144
145 MTAB ipl_mod[] = {
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 },
152 { 0 }
153 };
154
155 DEVICE 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
162 };
163
164 /* IPLO data structures
165
166 iplo_dev IPLO device descriptor
167 iplo_unit IPLO unit descriptor
168 iplo_reg IPLO register list
169 */
170
171 REG iplo_reg[] = {
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 },
182 { NULL }
183 };
184
185 DEVICE iplo_dev = {
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
192 };
193
194 /* I/O instructions */
195
196 int32 ipliio (int32 inst, int32 IR, int32 dat)
197 {
198 return iplio (&ipli_unit, inst, IR, dat);
199 }
200
201 int32 iploio (int32 inst, int32 IR, int32 dat)
202 {
203 return iplio (&iplo_unit, inst, IR, dat);
204 }
205
206 /* I/O handler for the IPLI and IPLO devices.
207
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.
213
214 The cause is this code in the SP disc loader source (2883.asm, 7900.asm,
215 790X.asm, 79X3.asm, and 79XX.asm):
216
217 LDA SDVTR REQUEST
218 JSB IOPMA,I DEVICE TABLE
219 [...]
220 STC DMAHS,C TURN ON DMA
221 SFS DMAHS WAIT FOR
222 JMP *-1 DEVICE TABLE
223 STC CH2,C SET CORRECT
224 CLC CH2 FLAG DIRECTION
225
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
230 the IPL flag.
231
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
239 non-reponsive.
240
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).
247 */
248
249 int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat)
250 {
251 uint32 u, dev, odev;
252 int32 sta;
253 char msg[2], uc;
254 DEVICE *dbdev; /* device ptr for debug */
255 static const char *iotype[] = { "Status", "Command" };
256
257 uc = (uptr == &ipli_unit) ? 'I' : 'O'; /* identify unit for debug */
258 dbdev = (uptr == &ipli_unit) ? &ipli_dev : &iplo_dev; /* identify device for debug */
259
260 u = (uptr - ipl_unit); /* get unit number */
261 dev = IR & I_DEVMASK; /* get device no */
262 switch (inst) { /* case on opcode */
263
264 case ioFLG: /* flag clear/set */
265 if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */
266 break;
267
268 case ioSFC: /* skip flag clear */
269 if (FLG (dev) == 0) PC = (PC + 1) & VAMASK;
270 break;
271
272 case ioSFS: /* skip flag set */
273 if (FLG (dev) != 0) PC = (PC + 1) & VAMASK;
274 break;
275
276 case ioOTX: /* output */
277 uptr->OBUF = dat;
278
279 if (DEBUG_PRJ (dbdev, DEB_CPU))
280 fprintf (sim_deb, ">>IPL%c OTx: %s = %06o\n", uc, iotype[u], dat);
281 break;
282
283 case ioLIX: /* load */
284 dat = 0;
285
286 case ioMIX: /* merge */
287 dat = dat | uptr->IBUF; /* get return data */
288
289 if (DEBUG_PRJ (dbdev, DEB_CPU))
290 fprintf (sim_deb, ">>IPL%c LIx: %s = %06o\n", uc, iotype[u ^ 1], dat);
291 break;
292
293 case ioCRS: /* control reset */
294 clrCMD (dev); /* clear ctl, cmd */
295 clrCTL (dev);
296 break;
297
298 case ioCTL: /* control clear/set */
299 if (IR & I_CTL) { /* CLC */
300 clrCMD (dev); /* clear ctl, cmd */
301 clrCTL (dev);
302
303 if (DEBUG_PRJ (dbdev, DEB_CMDS))
304 fprintf (sim_deb, ">>IPL%c CLC: Command cleared\n", uc);
305 }
306
307 else { /* STC */
308 setCMD (dev); /* set ctl, cmd */
309 setCTL (dev);
310
311 if (DEBUG_PRJ (dbdev, DEB_CMDS))
312 fprintf (sim_deb, ">>IPL%c STC: Command set\n", uc);
313
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;
319 }
320 msg[0] = (uptr->OBUF >> 8) & 0377;
321 msg[1] = uptr->OBUF & 0377;
322 sta = sim_write_sock (uptr->DSOCKET, msg, 2);
323
324 if (DEBUG_PRJ (dbdev, DEB_XFER))
325 fprintf (sim_deb,
326 ">>IPL%c STC: Socket write = %06o, status = %d\n",
327 uc, uptr->OBUF, sta);
328
329 if (sta == SOCKET_ERROR) {
330 printf ("IPL: socket write error\n");
331 return SCPE_IOERR;
332 }
333 sim_os_sleep (0);
334 }
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 */
340 }
341 else return SCPE_UNATT; /* lose */
342 }
343 break;
344
345 case ioEDT: /* End of DMA data transfer */
346 if ((dat & DMA2_OI) == 0) { /* output transfer? */
347 if (DEBUG_PRJ (dbdev, DEB_CMDS))
348 fprintf (sim_deb,
349 ">>IPL%c EDT: Delaying DMA completion interrupt for %d msec\n",
350 uc, ipl_edtdelay);
351 sim_os_ms_sleep (ipl_edtdelay); /* delay completion */
352 }
353 break;
354
355 default:
356 break;
357 }
358
359 if (IR & I_HC) { clrFSR (dev); } /* H/C option */
360 return dat;
361 }
362
363 /* Unit service - poll for input */
364
365 t_stat ipl_svc (UNIT *uptr)
366 {
367 int32 u, nb, dev;
368 char msg[2], uc;
369 DEVICE *dbdev; /* device ptr for debug */
370
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;
377 }
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");
381 return SCPE_IOERR;
382 }
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;
387 }
388 else if (nb == 1) {
389 ipl_hold[u] = ((int32) msg[0]) & 0377;
390 uptr->flags = uptr->flags | UNIT_HOLD;
391 }
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 */
396 setFSR (dev);
397
398 uc = (uptr == &ipli_unit) ? 'I' : 'O'; /* identify unit for debug */
399 dbdev = (uptr == &ipli_unit) ? &ipli_dev : &iplo_dev; /* identify device for debug */
400
401 if (DEBUG_PRJ (dbdev, DEB_XFER))
402 fprintf (sim_deb, ">>IPL%c svc: Socket read = %06o, status = %d\n",
403 uc, uptr->IBUF, nb);
404
405 return SCPE_OK;
406 }
407
408 t_bool ipl_check_conn (UNIT *uptr)
409 {
410 SOCKET sock;
411
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;
415 }
416 else {
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 */
420 }
421 uptr->flags = uptr->flags | UNIT_ESTB; /* conn established */
422 return TRUE;
423 }
424
425 /* Reset routine */
426
427 t_stat ipl_reset (DEVICE *dptr)
428 {
429 DIB *dibp = (DIB *) dptr->ctxt;
430 UNIT *uptr = dptr->units;
431
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;
440 return SCPE_OK;
441 }
442
443 /* Attach routine
444
445 attach -l - listen for connection on port
446 attach -c - connect to ip address and port
447 */
448
449 t_stat ipl_attach (UNIT *uptr, char *cptr)
450 {
451 extern int32 sim_switches;
452 SOCKET newsock;
453 uint32 i, t, ipa, ipp, oldf;
454 char *tptr;
455 t_stat r;
456
457 r = get_ipaddr (cptr, &ipa, &ipp);
458 if ((r != SCPE_OK) || (ipp == 0)) return SCPE_ARG;
459 oldf = uptr->flags;
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;
474 uptr->LSOCKET = 0;
475 uptr->DSOCKET = newsock;
476 }
477 else {
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;
485 uptr->DSOCKET = 0;
486 }
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 */
492 return SCPE_MEM;
493 }
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 */
503 }
504 if (t) printf ("Connection established\n");
505 }
506 return SCPE_OK;
507 }
508
509 /* Detach routine */
510
511 t_stat ipl_detach (UNIT *uptr)
512 {
513 if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
514 if (uptr->flags & UNIT_ACTV) sim_close_sock (uptr->DSOCKET, 1);
515 else {
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 */
519 }
520 free (uptr->filename); /* free string */
521 uptr->filename = NULL;
522 uptr->LSOCKET = 0;
523 uptr->DSOCKET = 0;
524 uptr->flags = uptr->flags & ~(UNIT_ATT | UNIT_ACTV | UNIT_ESTB);
525 sim_cancel (uptr); /* don't poll */
526 return SCPE_OK;
527 }
528
529 /* Disconnect routine */
530
531 t_stat ipl_dscln (UNIT *uptr, int32 val, char *cptr, void *desc)
532 {
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);
537 uptr->DSOCKET = 0;
538 uptr->flags = uptr->flags & ~UNIT_ESTB;
539 return SCPE_OK;
540 }
541
542 /* Diagnostic/normal mode routine */
543
544 t_stat ipl_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc)
545 {
546 if (val) {
547 ipli_unit.flags = ipli_unit.flags | UNIT_DIAG;
548 iplo_unit.flags = iplo_unit.flags | UNIT_DIAG;
549 }
550 else {
551 ipli_unit.flags = ipli_unit.flags & ~UNIT_DIAG;
552 iplo_unit.flags = iplo_unit.flags & ~UNIT_DIAG;
553 }
554 return SCPE_OK;
555 }
556
557 /* Interprocessor link bootstrap routine (HP Access Manual) */
558
559 #define MAX_BASE 073
560 #define IPL_PNTR 074
561 #define PTR_PNTR 075
562 #define IPL_DEVA 076
563 #define PTR_DEVA 077
564
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 */
596 0000000, /*RD 0 */
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 */
618 0000000, /* NOP */
619 0102300, /*SFS SFS 0 */
620 0001400, /*STC 1400 */
621 0002500, /*MIB 2500 */
622 0000000, /*WC 0 */
623 0000000, /*AD 0 */
624 0177746, /*M26 -26 */
625 0000000, /*MAX -BBL */
626 0007776, /*ICK ISC */
627 0007777, /*PTR IPT */
628 0000000, /*ISC 0 */
629 0000000 /*IPT 0 */
630 };
631
632 t_stat ipl_boot (int32 unitno, DEVICE *dptr)
633 {
634 int32 i, devi, devp;
635 extern DIB ptr_dib;
636 extern UNIT cpu_unit;
637 extern uint32 SR;
638 extern uint16 *M;
639
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;
650 return SCPE_OK;
651 }