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