First Commit of my working state
[simh.git] / VAX / vax780_uba.c
CommitLineData
196ba1fc
PH
1/* vax780_uba.c: VAX 11/780 Unibus adapter\r
2\r
3 Copyright (c) 2004-2008, 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 uba DW780 Unibus adapter\r
27\r
28 28-May-08 RMS Inlined physical memory routines\r
29 25-Jan-08 RMS Fixed declarations (from Mark Pizzolato)\r
30*/\r
31\r
32#include "vax_defs.h"\r
33\r
34/* Unibus adapter */\r
35\r
36#define UBA_NDPATH 16 /* number of data paths */\r
37#define UBA_NMAPR 496 /* number of map reg */\r
38\r
39/* Unibus configuration register */\r
40\r
41#define UBACNF_OF 0x00\r
42#define UBACNF_ADPDN 0x00800000 /* adap pdn - ni */\r
43#define UBACNF_ADPUP 0x00400000 /* adap pup - ni */\r
44#define UBACNF_UBINIT 0x00040000 /* UB INIT - ni */\r
45#define UBACNF_UBPDN 0x00020000 /* UB pdn */\r
46#define UBACNF_UBIC 0x00010000 /* UB init done */\r
47#define UBACNF_CODE 0x00000028 /* adapter code */\r
48#define UBACNF_RD (SBI_FAULTS|UBACNF_W1C)\r
49#define UBACNF_W1C 0x00C70000\r
50\r
51/* Control register */\r
52\r
53#define UBACR_OF 0x01\r
54#define UBACR_V_DSB 26 /* map disable */\r
55#define UBACR_M_DSB 0x1F\r
56#define UBACR_GETDSB(x) (((x) >> (UBACR_V_DSB - 4)) & (UBACR_M_DSB << 4))\r
57#define UBACR_IFS 0x00000040 /* SBI field intr */\r
58#define UBACR_BRIE 0x00000020 /* BR int enable */\r
59#define UBACR_USEFIE 0x00000010 /* UB to SBI int enb */\r
60#define UBACR_SUEFIE 0x00000008 /* SBI to UB int enb */\r
61#define UBACR_CNFIE 0x00000004 /* config int enb */\r
62#define UBACR_UPF 0x00000002 /* power fail UB */\r
63#define UBACR_ADINIT 0x00000001 /* adapter init */\r
64#define UBACR_RD ((UBACR_M_DSB << UBACR_V_DSB) | 0x0000007E)\r
65#define UBACR_WR (UBACR_RD)\r
66\r
67#define UBA_USEFIE_SR (UBASR_RDTO|UBASR_RDS|UBASR_CRD|UBASR_CXTER| \\r
68 UBASR_CXTO|UBASR_DPPE|UBASR_IVMR|UBASR_MRPF)\r
69#define UBA_SUEFIE_SR (UBASR_UBSTO|UBASR_UBTMO)\r
70#define UBA_CNFIE_CR (UBACNF_ADPDN|UBACNF_ADPUP|UBACNF_UBINIT|\\r
71 UBACNF_UBPDN|UBACNF_UBIC)\r
72\r
73/* Status register */\r
74\r
75#define UBASR_OF 0x02\r
76#define UBASR_V_BR4 24 /* filled br's - ni */\r
77#define UBASR_RDTO 0x00000400 /* read tmo - ni */\r
78#define UBASR_RDS 0x00000200 /* read sub - ni */\r
79#define UBASR_CRD 0x00000100 /* read crd - ni */\r
80#define UBASR_CXTER 0x00000080 /* cmd xfr err - ni */\r
81#define UBASR_CXTO 0x00000040 /* cmd xfr tmo - ni */\r
82#define UBASR_DPPE 0x00000020 /* parity err - ni */\r
83#define UBASR_IVMR 0x00000010 /* invalid map reg */\r
84#define UBASR_MRPF 0x00000008 /* map reg par - ni */\r
85#define UBASR_LEB 0x00000004 /* locked err */\r
86#define UBASR_UBSTO 0x00000002 /* UB select tmo - ni */\r
87#define UBASR_UBTMO 0x00000001 /* UB nxm */\r
88#define UBASR_RD 0x0F0007FF\r
89#define UBASR_W1C 0x000007FF\r
90\r
91/* Diagnostic register */\r
92\r
93#define UBADR_OF 0x03\r
94#define UBADR_SPARE 0x80000000 /* spare */\r
95#define UBADR_DINTR 0x40000000 /* disable intr */\r
96#define UBADR_DMP 0x20000000\r
97#define UBADR_DDPP 0x10000000\r
98#define UBADR_MICOK 0x08000000 /* microseq ok */\r
99#define UBADR_RD 0xF8000000\r
100#define UBADR_WR 0xF0000000\r
101#define UBADR_CNF_RD 0x07FFFFFF\r
102\r
103/* Failing map entry - read only */\r
104\r
105#define UBAFMER_OF 0x04\r
106#define UBAFMER_OF1 0x06\r
107#define UBAFMER_RD 0x1FF\r
108\r
109/* Failing Unibus address - read only */\r
110\r
111#define UBAFUBAR_OF 0x05\r
112#define UBAFUBAR_OF1 0x07\r
113#define UBAFUBAR_RD 0xFFFF\r
114\r
115/* Spare registers - read/write */\r
116\r
117#define UBABRSVR_OF 0x08\r
118\r
119/* Vector registers - read only */\r
120\r
121#define UBABRRVR_OF 0x0C\r
122#define UBA_UVEC 0x80000000\r
123\r
124/* Data path registers */\r
125\r
126#define UBADPR_OF 0x010\r
127#define UBADPR_BNE 0x80000000 /* buf not empty - ni */\r
128#define UBADPR_BTE 0x40000000 /* buf xfr err - ni */\r
129#define UBADPR_DIR 0x20000000 /* buf rd/wr */\r
130#define UBADPR_STATE 0x00FF0000 /* byte full state - ni */\r
131#define UBADPR_UA 0x0000FFFF /* Unibus addr<17:2> */\r
132#define UBADPR_UA 0x0000FFFF /* last UB addr */\r
133#define UBADPR_RD 0xC0FFFFFF\r
134#define UBADPR_W1C 0xC0000000\r
135\r
136/* Map registers */\r
137\r
138#define UBAMAP_OF 0x200\r
139#define UBAMAP_VLD 0x80000000 /* valid */\r
140#define UBAMAP_LWAE 0x04000000 /* LW access enb - ni */\r
141#define UBAMAP_ODD 0x02000000 /* odd byte */\r
142#define UBAMAP_V_DP 21 /* data path */\r
143#define UBAMAP_M_DP 0xF\r
144#define UBAMAP_DP (UBAMAP_M_DP << UBAMAP_V_DP)\r
145#define UBAMAP_GETDP(x) (((x) >> UBAMAP_V_DP) & UBAMAP_M_DP)\r
146#define UBAMAP_PAG 0x001FFFFF\r
147#define UBAMAP_RD (0x86000000 | UBAMAP_DP | UBAMAP_PAG)\r
148#define UBAMAP_WR (UBAMAP_RD)\r
149\r
150/* Debug switches */\r
151\r
152#define UBA_DEB_RRD 0x01 /* reg reads */\r
153#define UBA_DEB_RWR 0x02 /* reg writes */\r
154#define UBA_DEB_MRD 0x04 /* map reads */\r
155#define UBA_DEB_MWR 0x08 /* map writes */\r
156#define UBA_DEB_XFR 0x10 /* transfers */\r
157#define UBA_DEB_ERR 0x20 /* errors */\r
158\r
159int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */\r
160uint32 uba_cnf = 0; /* config reg */\r
161uint32 uba_cr = 0; /* control reg */\r
162uint32 uba_sr = 0; /* status reg */\r
163uint32 uba_dr = 0; /* diag ctrl */\r
164uint32 uba_int = 0; /* UBA interrupt */\r
165uint32 uba_fmer = 0; /* failing map reg */\r
166uint32 uba_fubar = 0; /* failing Unibus addr */\r
167uint32 uba_svr[4] = { 0 }; /* diag registers */\r
168uint32 uba_rvr[4] = { 0 }; /* vector reg */\r
169uint32 uba_dpr[UBA_NDPATH] = { 0 }; /* number data paths */\r
170uint32 uba_map[UBA_NMAPR] = { 0 }; /* map registers */\r
171uint32 uba_aiip = 0; /* adapter init in prog */\r
172uint32 uba_uiip = 0; /* Unibus init in prog */\r
173uint32 uba_aitime = 250; /* adapter init time */\r
174uint32 uba_uitime = 12250; /* Unibus init time */\r
175int32 autcon_enb = 1; /* autoconfig enable */\r
176\r
177extern int32 trpirq;\r
178extern int32 autcon_enb;\r
179extern jmp_buf save_env;\r
180extern DEVICE *sim_devices[];\r
181extern UNIT cpu_unit;\r
182extern uint32 nexus_req[NEXUS_HLVL];\r
183extern int32 sim_switches;\r
184extern FILE *sim_log, *sim_deb;\r
185\r
186t_stat uba_svc (UNIT *uptr);\r
187t_stat uba_reset (DEVICE *dptr);\r
188t_stat uba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);\r
189t_stat uba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);\r
190t_stat uba_rdreg (int32 *val, int32 pa, int32 mode);\r
191t_stat uba_wrreg (int32 val, int32 pa, int32 lnt);\r
192int32 uba_get_ubvector (int32 lvl);\r
193void uba_ub_nxm (int32 ua);\r
194void uba_inv_map (int32 ublk);\r
195void uba_eval_int (void);\r
196void uba_adap_set_int (int32 flg);\r
197void uba_adap_clr_int ();\r
198void uba_set_dpr (uint32 ua, t_bool wr);\r
199void uba_ubpdn (int32 time);\r
200t_bool uba_map_addr (uint32 ua, uint32 *ma);\r
201t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc);\r
202t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc);\r
203t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);\r
204t_stat uba_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc);\r
205\r
206extern int32 eval_int (void);\r
207extern t_stat build_dib_tab (void);\r
208\r
209/* Unibus IO page dispatches */\r
210\r
211static t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md);\r
212static t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md);\r
213static DIB *iodibp[IOPAGESIZE >> 1];\r
214\r
215/* Unibus interrupt request to interrupt action map */\r
216\r
217int32 (*int_ack[IPL_HLVL][32])(); /* int ack routines */\r
218\r
219/* Unibus interrupt request to vector map */\r
220\r
221int32 int_vec[IPL_HLVL][32]; /* int req to vector */\r
222\r
223/* Unibus adapter data structures\r
224\r
225 uba_dev UBA device descriptor\r
226 uba_unit UBA units\r
227 uba_reg UBA register list\r
228*/\r
229\r
230DIB uba_dib = { TR_UBA, 0, &uba_rdreg, &uba_wrreg, 0, 0 };\r
231\r
232UNIT uba_unit = { UDATA (&uba_svc, 0, 0) };\r
233\r
234REG uba_reg[] = {\r
235 { HRDATA (IPL14, int_req[0], 32), REG_RO },\r
236 { HRDATA (IPL15, int_req[1], 32), REG_RO },\r
237 { HRDATA (IPL16, int_req[2], 32), REG_RO },\r
238 { HRDATA (IPL17, int_req[3], 32), REG_RO },\r
239 { HRDATA (CNFR, uba_cnf, 32) },\r
240 { HRDATA (CR, uba_cr, 32) },\r
241 { HRDATA (SR, uba_sr, 32) },\r
242 { HRDATA (DR, uba_dr, 32) },\r
243 { FLDATA (INT, uba_int, 0) },\r
244 { FLDATA (NEXINT, nexus_req[IPL_UBA], TR_UBA) },\r
245 { FLDATA (AIIP, uba_aiip, 0) },\r
246 { FLDATA (UIIP, uba_uiip, 0) },\r
247 { HRDATA (FMER, uba_fmer, 32) },\r
248 { HRDATA (FUBAR, uba_fubar, 32) },\r
249 { HRDATA (BRSVR0, uba_svr[0], 32) },\r
250 { HRDATA (BRSVR1, uba_svr[1], 32) },\r
251 { HRDATA (BRSVR2, uba_svr[2], 32) },\r
252 { HRDATA (BRSVR3, uba_svr[3], 32) },\r
253 { HRDATA (BRRVR4, uba_rvr[0], 32) },\r
254 { HRDATA (BRRVR5, uba_rvr[1], 32) },\r
255 { HRDATA (BRRVR6, uba_rvr[2], 32) },\r
256 { HRDATA (BRRVR7, uba_rvr[3], 32) },\r
257 { BRDATA (DPR, uba_dpr, 16, 32, 16) },\r
258 { BRDATA (MAP, uba_map, 16, 32, 496) },\r
259 { DRDATA (AITIME, uba_aitime, 24), PV_LEFT + REG_NZ },\r
260 { DRDATA (UITIME, uba_uitime, 24), PV_LEFT + REG_NZ },\r
261 { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO },\r
262 { NULL }\r
263 };\r
264\r
265MTAB uba_mod[] = {\r
266 { MTAB_XTD|MTAB_VDV, TR_UBA, "NEXUS", NULL,\r
267 NULL, &show_nexus },\r
268 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,\r
269 NULL, &show_iospace },\r
270 { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG",\r
271 &set_autocon, &show_autocon },\r
272 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG",\r
273 &set_autocon, NULL },\r
274 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL,\r
275 NULL, &uba_show_virt },\r
276 { 0 }\r
277 };\r
278\r
279DEBTAB uba_deb[] = {\r
280 { "REGREAD", UBA_DEB_RRD },\r
281 { "REGWRITE", UBA_DEB_RWR },\r
282 { "MAPREAD", UBA_DEB_MRD },\r
283 { "MAPWRITE", UBA_DEB_MWR },\r
284 { "XFER", UBA_DEB_XFR },\r
285 { "ERROR", UBA_DEB_ERR },\r
286 { NULL, 0 }\r
287 };\r
288\r
289DEVICE uba_dev = {\r
290 "UBA", &uba_unit, uba_reg, uba_mod,\r
291 1, 16, UBADDRWIDTH, 2, 16, 16,\r
292 &uba_ex, &uba_dep, &uba_reset,\r
293 NULL, NULL, NULL,\r
294 &uba_dib, DEV_NEXUS | DEV_DEBUG, 0,\r
295 uba_deb, 0, 0\r
296 };\r
297\r
298/* Read Unibus adapter register - aligned lw only */\r
299\r
300t_stat uba_rdreg (int32 *val, int32 pa, int32 lnt)\r
301{\r
302int32 idx, ofs;\r
303\r
304if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */\r
305 printf (">>UBA: invalid adapter read mask, pa = %X, lnt = %d\r\n", pa, lnt);\r
306 sbi_set_errcnf (); /* err confirmation */\r
307 return SCPE_OK;\r
308 }\r
309ofs = NEXUS_GETOFS (pa); /* get offset */\r
310if (uba_aiip && (ofs != UBACNF_OF) /* init in prog? */\r
311 && (ofs != UBADR_OF)) return SCPE_NXM; /* only cnf, dr */\r
312if (ofs >= UBAMAP_OF) { /* map? */\r
313 idx = ofs - UBAMAP_OF;\r
314 if (idx >= UBA_NMAPR) return SCPE_NXM; /* valid? */\r
315 *val = uba_map[idx] & UBAMAP_RD;\r
316 if (DEBUG_PRI (uba_dev, UBA_DEB_MRD))\r
317 fprintf (sim_deb, ">>UBA: map %d read, value = %X\n", idx, *val);\r
318 return SCPE_OK;\r
319 }\r
320\r
321switch (ofs) { /* case on offset */\r
322\r
323 case UBACNF_OF: /* CNF */\r
324 *val = (uba_cnf & UBACNF_RD) | UBACNF_CODE;\r
325 break;\r
326\r
327 case UBACR_OF: /* CR */\r
328 *val = uba_cr & UBACR_RD;\r
329 break;\r
330\r
331 case UBASR_OF: /* SR */\r
332 *val = uba_sr & UBASR_RD;\r
333 break;\r
334\r
335 case UBADR_OF: /* DR */\r
336 *val = (uba_dr & UBADR_RD) | UBADR_MICOK |\r
337 ((uba_cnf & UBADR_CNF_RD) | UBACNF_CODE);\r
338 break;\r
339\r
340 case UBAFMER_OF: case UBAFMER_OF1: /* FMER */\r
341 *val = uba_fmer & UBAFMER_RD;\r
342 break;\r
343\r
344 case UBAFUBAR_OF: case UBAFUBAR_OF1: /* FUBAR */\r
345 *val = uba_fubar & UBAFUBAR_RD;\r
346 break;\r
347\r
348 case UBABRSVR_OF + 0: case UBABRSVR_OF + 1: /* BRSVR */\r
349 case UBABRSVR_OF + 2: case UBABRSVR_OF + 3:\r
350 idx = ofs - UBABRSVR_OF;\r
351 *val = uba_svr[idx];\r
352 break;\r
353\r
354 case UBABRRVR_OF + 0: case UBABRRVR_OF + 1: /* BRRVR */\r
355 case UBABRRVR_OF + 2: case UBABRRVR_OF + 3:\r
356 idx = ofs - UBABRRVR_OF;\r
357 uba_rvr[idx] = uba_get_ubvector (idx);\r
358 *val = uba_rvr[idx];\r
359 break;\r
360\r
361 case UBADPR_OF + 0: /* DPR */\r
362 *val = 0; /* direct */\r
363 break;\r
364\r
365 case UBADPR_OF + 1:\r
366 case UBADPR_OF + 2: case UBADPR_OF + 3:\r
367 case UBADPR_OF + 4: case UBADPR_OF + 5:\r
368 case UBADPR_OF + 6: case UBADPR_OF + 7:\r
369 case UBADPR_OF + 8: case UBADPR_OF + 9:\r
370 case UBADPR_OF + 10: case UBADPR_OF + 11:\r
371 case UBADPR_OF + 12: case UBADPR_OF + 13:\r
372 case UBADPR_OF + 14: case UBADPR_OF + 15:\r
373 idx = ofs - UBADPR_OF;\r
374 *val = uba_dpr[idx] & UBADPR_RD;\r
375 break;\r
376\r
377 default:\r
378 return SCPE_NXM;\r
379 }\r
380\r
381if (DEBUG_PRI (uba_dev, UBA_DEB_RRD))\r
382 fprintf (sim_deb, ">>UBA: reg %d read, value = %X\n", ofs, *val);\r
383return SCPE_OK;\r
384}\r
385\r
386/* Write Unibus adapter register */\r
387\r
388t_stat uba_wrreg (int32 val, int32 pa, int32 lnt)\r
389{\r
390int32 idx, ofs, old_cr;\r
391\r
392if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */\r
393 printf (">>UBA: invalid adapter write mask, pa = %X, lnt = %d\r\n", pa, lnt);\r
394 sbi_set_errcnf (); /* err confirmation */\r
395 return SCPE_OK;\r
396 }\r
397ofs = NEXUS_GETOFS (pa); /* get offset */\r
398if (uba_aiip && (ofs != UBACNF_OF) && (ofs != UBADR_OF) &&\r
399 (ofs != UBACR_OF) && (ofs != UBASR_OF)) return SCPE_NXM;\r
400if (ofs >= UBAMAP_OF) { /* map? */\r
401 idx = ofs - UBAMAP_OF;\r
402 if (idx >= UBA_NMAPR) return SCPE_NXM; /* valid? */\r
403 uba_map[idx] = val & UBAMAP_WR;\r
404 if (DEBUG_PRI (uba_dev, UBA_DEB_MWR))\r
405 fprintf (sim_deb, ">>UBA: map %d write, value = %X\n", idx, val);\r
406 return SCPE_OK;\r
407 }\r
408\r
409switch (ofs) { /* case on offset */\r
410\r
411 case UBACNF_OF: /* CNF */\r
412 uba_cnf = uba_cnf & ~(val & UBACNF_W1C); /* W1C bits */\r
413 uba_adap_clr_int (); /* possible clr int */\r
414 break;\r
415\r
416 case UBACR_OF: /* CR */\r
417 old_cr = uba_cr;\r
418 if (val & UBACR_ADINIT) { /* adapter init */\r
419 uba_reset (&uba_dev); /* reset adapter */\r
420 uba_aiip = 1; /* set init in prog */\r
421 uba_ubpdn (uba_aitime); /* power fail UB */\r
422 }\r
423 if ((val & UBACR_UPF) && !(old_cr & UBACR_UPF) /* Unibus power clear */\r
424 && !sim_is_active (&uba_unit))\r
425 uba_ubpdn (uba_aitime + uba_uitime); /* power fail UB */\r
426 uba_cr = (uba_cr & ~UBACR_WR) | (val & UBACR_WR);\r
427 uba_adap_set_int (uba_cr & ~old_cr); /* possible int set */\r
428 uba_adap_clr_int (); /* possible int clr */\r
429 break;\r
430\r
431 case UBASR_OF: /* SR */\r
432 uba_sr = uba_sr & ~(val & UBASR_W1C); /* W1C bits */\r
433 uba_adap_clr_int (); /* possible clr int */\r
434 break;\r
435\r
436 case UBADR_OF: /* DR */\r
437 uba_dr = (uba_dr & ~UBADR_WR) | (val & UBADR_WR);\r
438 uba_cnf = uba_cnf & ~(val & UBACNF_W1C);\r
439 uba_adap_clr_int (); /* possible clr int */\r
440 break;\r
441\r
442 case UBABRSVR_OF + 0: case UBABRSVR_OF + 1: /* BRSVR */\r
443 case UBABRSVR_OF + 2: case UBABRSVR_OF + 3:\r
444 idx = ofs - UBABRSVR_OF;\r
445 uba_svr[idx] = val;\r
446 break;\r
447\r
448 case UBADPR_OF + 0: /* DPR */\r
449 break; /* direct */\r
450\r
451 case UBADPR_OF + 1:\r
452 case UBADPR_OF + 2: case UBADPR_OF + 3:\r
453 case UBADPR_OF + 4: case UBADPR_OF + 5:\r
454 case UBADPR_OF + 6: case UBADPR_OF + 7:\r
455 case UBADPR_OF + 8: case UBADPR_OF + 9:\r
456 case UBADPR_OF + 10: case UBADPR_OF + 11:\r
457 case UBADPR_OF + 12: case UBADPR_OF + 13:\r
458 case UBADPR_OF + 14: case UBADPR_OF + 15:\r
459 idx = ofs - UBADPR_OF;\r
460 uba_dpr[idx] = uba_dpr[idx] & ~(val & UBADPR_W1C);\r
461 break;\r
462\r
463 default:\r
464 return SCPE_NXM;\r
465 }\r
466\r
467if (DEBUG_PRI (uba_dev, UBA_DEB_RWR))\r
468 fprintf (sim_deb, ">>UBA: reg %d write, value = %X\n", ofs, val);\r
469return SCPE_OK;\r
470}\r
471\r
472/* Read and write Unibus I/O space */\r
473\r
474int32 ReadUb (uint32 pa)\r
475{\r
476int32 idx, val;\r
477\r
478if (ADDR_IS_IOP (pa) && !uba_uiip) { /* iopage,!init */\r
479 idx = (pa & IOPAGEMASK) >> 1;\r
480 if (iodispR[idx]) {\r
481 iodispR[idx] (&val, pa, READ);\r
482 return val;\r
483 }\r
484 }\r
485uba_ub_nxm (pa); /* UB nxm */\r
486return 0;\r
487}\r
488\r
489void WriteUb (uint32 pa, int32 val, int32 mode)\r
490{\r
491int32 idx;\r
492\r
493if (ADDR_IS_IOP (pa) && !uba_uiip) { /* iopage,!init */\r
494 idx = (pa & IOPAGEMASK) >> 1;\r
495 if (iodispW[idx]) {\r
496 iodispW[idx] (val, pa, mode);\r
497 return;\r
498 }\r
499 }\r
500uba_ub_nxm (pa); /* UB nxm */\r
501return;\r
502}\r
503\r
504/* ReadIO - read from IO - UBA only responds to byte, aligned word\r
505\r
506 Inputs:\r
507 pa = physical address\r
508 lnt = length (BWLQ)\r
509 Output:\r
510 longword of data\r
511*/\r
512\r
513int32 ReadIO (uint32 pa, int32 lnt)\r
514{\r
515uint32 iod;\r
516\r
517if ((lnt == L_BYTE) || /* byte? */\r
518 ((lnt == L_WORD) && ((pa & 1) == 0))) { /* aligned word? */\r
519 iod = ReadUb (pa); /* DATI from Unibus */\r
520 if (pa & 2) iod = iod << 16; /* position */\r
521 }\r
522else {\r
523 printf (">>UBA: invalid read mask, pa = %x, lnt = %d\n", pa, lnt);\r
524 sbi_set_errcnf (); /* err confirmation */\r
525 iod = 0;\r
526 }\r
527SET_IRQL;\r
528return iod;\r
529}\r
530\r
531/* WriteIO - write to IO - UBA only responds to byte, aligned word\r
532\r
533 Inputs:\r
534 pa = physical address\r
535 val = data to write, right justified in 32b longword\r
536 lnt = length (BWL)\r
537 Outputs:\r
538 none\r
539*/\r
540\r
541void WriteIO (uint32 pa, int32 val, int32 lnt)\r
542{\r
543if (lnt == L_BYTE) WriteUb (pa, val, WRITEB); /* byte? DATOB */\r
544else if ((lnt == L_WORD) && ((pa & 1) == 0)) /* aligned word? */\r
545 WriteUb (pa, val, WRITE); /* DATO */\r
546else {\r
547 printf (">>UBA: invalid write mask, pa = %x, lnt = %d\n", pa, lnt);\r
548 sbi_set_errcnf (); /* err confirmation */\r
549 }\r
550SET_IRQL; /* update ints */\r
551return;\r
552}\r
553\r
554/* Update UBA nexus interrupts */\r
555\r
556void uba_eval_int (void)\r
557{\r
558int32 i;\r
559\r
560for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) /* clear all UBA req */\r
561 nexus_req[i] &= ~(1 << TR_UBA);\r
562if (((uba_dr & UBADR_DINTR) == 0) && !uba_uiip && /* intr enabled? */\r
563 (uba_cr & UBACR_IFS) && (uba_cr & UBACR_BRIE)) {\r
564 for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) {\r
565 if (int_req[i]) nexus_req[i] |= (1 << TR_UBA);\r
566 }\r
567 }\r
568if (uba_int) SET_NEXUS_INT (UBA); /* adapter int? */\r
569return;\r
570}\r
571\r
572/* Return vector for Unibus interrupt at relative IPL level [0-3] */\r
573\r
574int32 uba_get_ubvector (int32 lvl)\r
575{\r
576int32 i, vec;\r
577\r
578vec = 0;\r
579if ((lvl == (IPL_UBA - IPL_HMIN)) && uba_int) { /* UBA lvl, int? */\r
580 vec = UBA_UVEC; /* set flag */\r
581 uba_int = 0; /* clear int */\r
582 }\r
583if (((uba_dr & UBADR_DINTR) == 0) && !uba_uiip && /* intr enabled? */\r
584 (uba_cr & UBACR_IFS) && (uba_cr & UBACR_BRIE)) {\r
585 for (i = 0; int_req[lvl] && (i < 32); i++) {\r
586 if ((int_req[lvl] >> i) & 1) {\r
587 int_req[lvl] = int_req[lvl] & ~(1u << i);\r
588 if (int_ack[lvl][i]) return (vec | int_ack[lvl][i]());\r
589 return (vec | int_vec[lvl][i]);\r
590 }\r
591 }\r
592 }\r
593return vec;\r
594}\r
595\r
596/* Unibus I/O buffer routines\r
597\r
598 Map_ReadB - fetch byte buffer from memory\r
599 Map_ReadW - fetch word buffer from memory\r
600 Map_WriteB - store byte buffer into memory\r
601 Map_WriteW - store word buffer into memory\r
602*/\r
603\r
604int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf)\r
605{\r
606int32 i, j, pbc;\r
607uint32 ma, dat;\r
608\r
609ba = ba & UBADDRMASK; /* mask UB addr */\r
610for (i = 0; i < bc; i = i + pbc) { /* loop by pages */\r
611 if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */\r
612 pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */\r
613 if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */\r
614 if (DEBUG_PRI (uba_dev, UBA_DEB_XFR))\r
615 fprintf (sim_deb, ">>UBA: 8b read, ma = %X, bc = %X\n", ma, pbc);\r
616 if ((ma | pbc) & 3) { /* aligned LW? */\r
617 for (j = 0; j < pbc; ma++, j++) { /* no, do by bytes */\r
618 *buf++ = ReadB (ma);\r
619 }\r
620 }\r
621 else { /* yes, do by LW */\r
622 for (j = 0; j < pbc; ma = ma + 4, j = j + 4) {\r
623 dat = ReadL (ma); /* get lw */\r
624 *buf++ = dat & BMASK; /* low 8b */\r
625 *buf++ = (dat >> 8) & BMASK; /* next 8b */\r
626 *buf++ = (dat >> 16) & BMASK; /* next 8b */\r
627 *buf++ = (dat >> 24) & BMASK;\r
628 }\r
629 }\r
630 uba_set_dpr (ba + i + pbc - L_BYTE, FALSE);\r
631 }\r
632return 0;\r
633}\r
634\r
635int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf)\r
636{\r
637int32 i, j, pbc;\r
638uint32 ma, dat;\r
639\r
640ba = ba & UBADDRMASK; /* mask UB addr */\r
641bc = bc & ~01;\r
642for (i = 0; i < bc; i = i + pbc) { /* loop by pages */\r
643 if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */\r
644 pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */\r
645 if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */\r
646 if (DEBUG_PRI (uba_dev, UBA_DEB_XFR))\r
647 fprintf (sim_deb, ">>UBA: 16b read, ma = %X, bc = %X\n", ma, pbc);\r
648 if ((ma | pbc) & 1) { /* aligned word? */\r
649 for (j = 0; j < pbc; ma++, j++) { /* no, do by bytes */\r
650 if ((i + j) & 1) { /* odd byte? */\r
651 *buf = (*buf & BMASK) | (ReadB (ma) << 8);\r
652 buf++;\r
653 }\r
654 else *buf = (*buf & ~BMASK) | ReadB (ma);\r
655 }\r
656 }\r
657 else if ((ma | pbc) & 3) { /* aligned LW? */\r
658 for (j = 0; j < pbc; ma = ma + 2, j = j + 2) { /* no, words */\r
659 *buf++ = ReadW (ma); /* get word */\r
660 }\r
661 }\r
662 else { /* yes, do by LW */\r
663 for (j = 0; j < pbc; ma = ma + 4, j = j + 4) {\r
664 dat = ReadL (ma); /* get lw */\r
665 *buf++ = dat & WMASK; /* low 16b */\r
666 *buf++ = (dat >> 16) & WMASK; /* high 16b */\r
667 }\r
668 }\r
669 uba_set_dpr (ba + i + pbc - L_WORD, FALSE);\r
670 }\r
671return 0;\r
672}\r
673\r
674int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf)\r
675{\r
676int32 i, j, pbc;\r
677uint32 ma, dat;\r
678\r
679ba = ba & UBADDRMASK; /* mask UB addr */\r
680for (i = 0; i < bc; i = i + pbc) { /* loop by pages */\r
681 if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */\r
682 pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */\r
683 if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */\r
684 if (DEBUG_PRI (uba_dev, UBA_DEB_XFR))\r
685 fprintf (sim_deb, ">>UBA: 8b write, ma = %X, bc = %X\n", ma, pbc);\r
686 if ((ma | pbc) & 3) { /* aligned LW? */\r
687 for (j = 0; j < pbc; ma++, j++) { /* no, do by bytes */\r
688 WriteB (ma, *buf);\r
689 buf++;\r
690 }\r
691 }\r
692 else { /* yes, do by LW */\r
693 for (j = 0; j < pbc; ma = ma + 4, j = j + 4) {\r
694 dat = (uint32) *buf++; /* get low 8b */\r
695 dat = dat | (((uint32) *buf++) << 8); /* merge next 8b */\r
696 dat = dat | (((uint32) *buf++) << 16); /* merge next 8b */\r
697 dat = dat | (((uint32) *buf++) << 24); /* merge hi 8b */\r
698 WriteL (ma, dat); /* store lw */\r
699 }\r
700 }\r
701 uba_set_dpr (ba + i + pbc - L_BYTE, TRUE);\r
702 }\r
703return 0;\r
704}\r
705\r
706int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf)\r
707{\r
708int32 i, j, pbc;\r
709uint32 ma, dat;\r
710\r
711ba = ba & UBADDRMASK; /* mask UB addr */\r
712bc = bc & ~01;\r
713for (i = 0; i < bc; i = i + pbc) { /* loop by pages */\r
714 if (!uba_map_addr (ba + i, &ma)) return (bc - i); /* page inv or NXM? */\r
715 pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */\r
716 if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */\r
717 if (DEBUG_PRI (uba_dev, UBA_DEB_XFR))\r
718 fprintf (sim_deb, ">>UBA: 16b write, ma = %X, bc = %X\n", ma, pbc);\r
719 if ((ma | pbc) & 1) { /* aligned word? */\r
720 for (j = 0; j < pbc; ma++, j++) { /* no, bytes */\r
721 if ((i + j) & 1) {\r
722 WriteB (ma, (*buf >> 8) & BMASK);\r
723 buf++;\r
724 }\r
725 else WriteB (ma, *buf & BMASK);\r
726 }\r
727 }\r
728 else if ((ma | pbc) & 3) { /* aligned LW? */\r
729 for (j = 0; j < pbc; ma = ma + 2, j = j + 2) { /* no, words */\r
730 WriteW (ma, *buf); /* write word */\r
731 buf++;\r
732 }\r
733 }\r
734 else { /* yes, do by LW */\r
735 for (j = 0; j < pbc; ma = ma + 4, j = j + 4) {\r
736 dat = (uint32) *buf++; /* get low 16b */\r
737 dat = dat | (((uint32) *buf++) << 16); /* merge hi 16b */\r
738 WriteL (ma, dat); /* store LW */\r
739 }\r
740 }\r
741 uba_set_dpr (ba + i + pbc - L_WORD, TRUE);\r
742 }\r
743return 0;\r
744}\r
745\r
746/* Map an address via the translation map */\r
747\r
748t_bool uba_map_addr (uint32 ua, uint32 *ma)\r
749{\r
750uint32 ublk, umap;\r
751\r
752ublk = ua >> VA_V_VPN; /* Unibus blk */\r
753if ((ublk < UBACR_GETDSB (uba_cr)) || /* map disabled? */\r
754 (ublk >= UBA_NMAPR)) return FALSE; /* unimplemented? */\r
755umap = uba_map[ublk]; /* get map */\r
756if (umap & UBAMAP_VLD) { /* valid? */\r
757 *ma = ((umap & UBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (ua);\r
758 if ((umap & UBAMAP_DP) && (umap & UBAMAP_ODD)) /* buffered dp? */\r
759 *ma = *ma + 1; /* byte offset? */\r
760 return (ADDR_IS_MEM (*ma)); /* legit addr */\r
761 }\r
762uba_inv_map (ua); /* invalid map */\r
763return FALSE;\r
764}\r
765\r
766/* Map an address via the translation map - console version (no status changes) */\r
767\r
768t_bool uba_map_addr_c (uint32 ua, uint32 *ma)\r
769{\r
770uint32 ublk, umap;\r
771\r
772ublk = ua >> VA_V_VPN; /* Unibus blk */\r
773if ((ublk < UBACR_GETDSB (uba_cr)) || /* map disabled? */\r
774 (ublk >= UBA_NMAPR)) return FALSE; /* unimplemented? */\r
775umap = uba_map[ublk]; /* get map */\r
776if (umap & UBAMAP_VLD) { /* valid? */\r
777 *ma = ((umap & UBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (ua);\r
778 if ((umap & UBAMAP_DP) && (umap & UBAMAP_ODD)) /* buffered dp? */\r
779 *ma = *ma + 1; /* byte offset? */\r
780 return TRUE; /* legit addr */\r
781 }\r
782return FALSE;\r
783}\r
784\r
785/* At end of page or transfer, update DPR register, in case next page\r
786 gets an error */\r
787\r
788void uba_set_dpr (uint32 ua, t_bool wr)\r
789{\r
790uint32 ublk, umap, dpr;\r
791\r
792ublk = ua >> VA_V_VPN; /* Unibus blk */\r
793if (ublk >= UBA_NMAPR) return; /* paranoia */\r
794umap = uba_map[ublk]; /* get map */\r
795dpr = UBAMAP_GETDP (umap); /* get bdp */\r
796if (dpr) uba_dpr[dpr] = (uba_dpr[dpr] & ~(UBADPR_UA|UBADPR_DIR)) |\r
797 (wr? UBADPR_DIR: 0) |\r
798 (((ua >> 2) + ((umap & UBAMAP_ODD)? 1: 0)) & UBADPR_UA);\r
799return;\r
800}\r
801\r
802/* Error routines\r
803\r
804 uba_ub_nxm SBI read/write to nx Unibus address\r
805 uba_inv_map Unibus reference to invalid map reg\r
806*/\r
807\r
808void uba_ub_nxm (int32 ua)\r
809{\r
810if ((uba_sr & UBASR_UBTMO) == 0) {\r
811 uba_sr |= UBASR_UBTMO;\r
812 uba_adap_set_int (uba_cr & UBACR_SUEFIE);\r
813 uba_fubar = (ua >> 2) & UBAFUBAR_RD;\r
814 }\r
815else uba_sr |= UBASR_LEB;\r
816if (DEBUG_PRI (uba_dev, UBA_DEB_ERR))\r
817 fprintf (sim_deb, ">>UBA: nxm error, ua = %X\n", ua);\r
818return;\r
819}\r
820\r
821void uba_inv_map (int32 ublk)\r
822{\r
823if ((uba_sr & UBASR_IVMR) == 0) {\r
824 uba_sr |= UBASR_IVMR;\r
825 uba_adap_set_int (uba_cr & UBACR_USEFIE);\r
826 uba_fmer = ublk & UBAFMER_RD;\r
827 }\r
828else uba_sr |= UBASR_LEB;\r
829if (DEBUG_PRI (uba_dev, UBA_DEB_ERR))\r
830 fprintf (sim_deb, ">>UBA: inv map error, ublk = %X\n", ublk);\r
831return;\r
832}\r
833\r
834/* Unibus power fail routines */\r
835\r
836void uba_ubpdn (int32 time)\r
837{\r
838int32 i;\r
839DEVICE *dptr;\r
840\r
841uba_cnf = (uba_cnf & ~UBACNF_UBIC) | UBACNF_UBPDN; /* update cnf */\r
842sim_activate (&uba_unit, time); /* schedule */\r
843uba_uiip = 1; /* UB init in prog */\r
844for (i = 0; sim_devices[i] != NULL; i++) { /* reset Unibus */\r
845 dptr = sim_devices[i];\r
846 if (dptr->reset && (dptr->flags & DEV_UBUS))\r
847 dptr->reset (dptr);\r
848 }\r
849return;\r
850}\r
851\r
852/* Init timeout service routine */\r
853\r
854t_stat uba_svc (UNIT *uptr)\r
855{\r
856if (uba_aiip) { /* adapter init? */\r
857 uba_aiip = 0; /* clear in prog */\r
858 sim_activate (uptr, uba_uitime); /* schedule UB */\r
859 }\r
860else {\r
861 uba_uiip = 0; /* no, UB */\r
862 uba_cnf = (uba_cnf & ~UBACNF_UBPDN) | UBACNF_UBIC;\r
863 uba_adap_set_int (uba_cr & UBACR_CNFIE); /* possible int */\r
864 }\r
865return SCPE_OK;\r
866}\r
867\r
868/* Interrupt routines */\r
869\r
870void uba_adap_set_int (int32 flg)\r
871{\r
872if (((flg & UBACR_SUEFIE) && (uba_sr & UBA_SUEFIE_SR)) ||\r
873 ((flg & UBACR_USEFIE) && (uba_sr & UBA_USEFIE_SR)) ||\r
874 ((flg & UBACR_CNFIE) && (uba_cr & UBA_CNFIE_CR))) {\r
875 uba_int = 1;\r
876 if (DEBUG_PRI (uba_dev, UBA_DEB_ERR)) fprintf (sim_deb, \r
877 ">>UBA: adapter int req, sr = %X, cr = %X\n", uba_sr, uba_cr);\r
878 }\r
879return;\r
880}\r
881\r
882void uba_adap_clr_int ()\r
883{\r
884if ((!(uba_cr & UBACR_SUEFIE) || !(uba_sr & UBA_SUEFIE_SR)) &&\r
885 (!(uba_cr & UBACR_USEFIE) || !(uba_sr & UBA_USEFIE_SR)) &&\r
886 (!(uba_cr & UBACR_CNFIE) || !(uba_cr & UBA_CNFIE_CR)))\r
887 uba_int = 0;\r
888return;\r
889}\r
890\r
891/* Reset Unibus adapter */\r
892\r
893t_stat uba_reset (DEVICE *dptr)\r
894{\r
895int32 i;\r
896\r
897uba_int = 0;\r
898uba_aiip = uba_uiip = 0;\r
899sim_cancel (&uba_unit);\r
900for (i = 0; i < IPL_HLVL; i++) {\r
901 nexus_req[i] &= ~(1 << TR_UBA);\r
902 int_req[i] = 0;\r
903 uba_svr[i] = 0;\r
904 uba_rvr[i] = 0;\r
905 }\r
906for (i = 0; i < UBA_NMAPR; i++) uba_map[i] = 0;\r
907for (i = 0; i < UBA_NDPATH; i++) uba_dpr[i] = 0;\r
908uba_sr = 0;\r
909uba_cr = 0;\r
910uba_dr = 0;\r
911uba_cnf = UBACNF_UBIC;\r
912return SCPE_OK;\r
913}\r
914\r
915/* Memory examine via map (word only) */\r
916\r
917t_stat uba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)\r
918{\r
919uint32 ua = (uint32) exta, pa;\r
920\r
921if ((vptr == NULL) || (ua >= UBADDRSIZE)) return SCPE_ARG;\r
922if (uba_map_addr_c (ua, &pa) && ADDR_IS_MEM (pa)) {\r
923 *vptr = (uint32) ReadW (pa);\r
924 return SCPE_OK;\r
925 }\r
926return SCPE_NXM;\r
927}\r
928\r
929/* Memory deposit via map (word only) */\r
930\r
931t_stat uba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)\r
932{\r
933uint32 ua = (uint32) exta, pa;\r
934\r
935if (ua >= UBADDRSIZE) return SCPE_ARG;\r
936if (uba_map_addr_c (ua, &pa) && ADDR_IS_MEM (pa)) {\r
937 WriteW (pa, (int32) val);\r
938 return SCPE_OK;\r
939 }\r
940return SCPE_NXM;\r
941}\r
942\r
943/* Enable/disable autoconfiguration */\r
944\r
945t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc)\r
946{\r
947if (cptr != NULL) return SCPE_ARG;\r
948autcon_enb = val;\r
949return auto_config (NULL, 0);\r
950}\r
951\r
952/* Show autoconfiguration status */\r
953\r
954t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc)\r
955{\r
956fprintf (st, "autoconfiguration ");\r
957fprintf (st, autcon_enb? "enabled": "disabled");\r
958return SCPE_OK;\r
959}\r
960\r
961/* Change device address */\r
962\r
963t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc)\r
964{\r
965DEVICE *dptr;\r
966DIB *dibp;\r
967uint32 newba;\r
968t_stat r;\r
969\r
970if (cptr == NULL) return SCPE_ARG;\r
971if ((val == 0) || (uptr == NULL)) return SCPE_IERR;\r
972dptr = find_dev_from_unit (uptr);\r
973if (dptr == NULL) return SCPE_IERR;\r
974dibp = (DIB *) dptr->ctxt;\r
975if (dibp == NULL) return SCPE_IERR;\r
976newba = (uint32) get_uint (cptr, 16, IOPAGEBASE+IOPAGEMASK, &r);\r
977if (r != SCPE_OK) return r;\r
978if ((newba <= IOPAGEBASE) || /* must be > 0 */\r
979 (newba % ((uint32) val))) return SCPE_ARG; /* check modulus */\r
980dibp->ba = newba; /* store */\r
981dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */\r
982autcon_enb = 0; /* autoconfig off */\r
983return SCPE_OK;\r
984}\r
985\r
986/* Show device address */\r
987\r
988t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc)\r
989{\r
990DEVICE *dptr;\r
991DIB *dibp;\r
992\r
993if (uptr == NULL) return SCPE_IERR;\r
994dptr = find_dev_from_unit (uptr);\r
995if (dptr == NULL) return SCPE_IERR;\r
996dibp = (DIB *) dptr->ctxt;\r
997if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR;\r
998fprintf (st, "address=%08X", dibp->ba);\r
999if (dibp->lnt > 1)\r
1000 fprintf (st, "-%08X", dibp->ba + dibp->lnt - 1);\r
1001if (dptr->flags & DEV_FLTA) fprintf (st, "*");\r
1002return SCPE_OK;\r
1003}\r
1004\r
1005/* Set address floating */\r
1006\r
1007t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc)\r
1008{\r
1009DEVICE *dptr;\r
1010\r
1011if (cptr == NULL) return SCPE_ARG;\r
1012if ((val == 0) || (uptr == NULL)) return SCPE_IERR;\r
1013dptr = find_dev_from_unit (uptr);\r
1014if (dptr == NULL) return SCPE_IERR;\r
1015dptr->flags = dptr->flags | DEV_FLTA; /* floating */\r
1016return auto_config (NULL, 0); /* autoconfigure */\r
1017}\r
1018\r
1019/* Change device vector */\r
1020\r
1021t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc)\r
1022{\r
1023DEVICE *dptr;\r
1024DIB *dibp;\r
1025uint32 newvec;\r
1026t_stat r;\r
1027\r
1028if (cptr == NULL) return SCPE_ARG;\r
1029if (uptr == NULL) return SCPE_IERR;\r
1030dptr = find_dev_from_unit (uptr);\r
1031if (dptr == NULL) return SCPE_IERR;\r
1032dibp = (DIB *) dptr->ctxt;\r
1033if (dibp == NULL) return SCPE_IERR;\r
1034newvec = (uint32) get_uint (cptr, 16, 01000, &r);\r
1035if ((r != SCPE_OK) ||\r
1036 ((newvec + (dibp->vnum * 4)) >= 01000) ||\r
1037 (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG;\r
1038dibp->vec = newvec;\r
1039dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */\r
1040autcon_enb = 0; /* autoconfig off */\r
1041return SCPE_OK;\r
1042}\r
1043\r
1044/* Show device vector */\r
1045\r
1046t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc)\r
1047{\r
1048DEVICE *dptr;\r
1049DIB *dibp;\r
1050uint32 vec, numvec;\r
1051\r
1052if (uptr == NULL) return SCPE_IERR;\r
1053dptr = find_dev_from_unit (uptr);\r
1054if (dptr == NULL) return SCPE_IERR;\r
1055dibp = (DIB *) dptr->ctxt;\r
1056if (dibp == NULL) return SCPE_IERR;\r
1057vec = dibp->vec;\r
1058if (arg) numvec = arg;\r
1059else numvec = dibp->vnum;\r
1060if (vec == 0) fprintf (st, "no vector");\r
1061else {\r
1062 fprintf (st, "vector=%X", vec);\r
1063 if (numvec > 1) fprintf (st, "-%X", vec + (4 * (numvec - 1)));\r
1064 }\r
1065return SCPE_OK;\r
1066}\r
1067\r
1068/* Init Unibus tables */\r
1069\r
1070void init_ubus_tab (void)\r
1071{\r
1072int32 i, j;\r
1073\r
1074for (i = 0; i < IPL_HLVL; i++) { /* clear int tables */\r
1075 for (j = 0; j < 32; j++) {\r
1076 int_vec[i][j] = 0;\r
1077 int_ack[i][j] = NULL;\r
1078 }\r
1079 }\r
1080for (i = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */\r
1081 iodispR[i] = NULL;\r
1082 iodispW[i] = NULL;\r
1083 iodibp[i] = NULL;\r
1084 }\r
1085return;\r
1086}\r
1087\r
1088/* Build Unibus tables */\r
1089\r
1090t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp)\r
1091{\r
1092int32 i, idx, vec, ilvl, ibit;\r
1093\r
1094if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */\r
1095if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR;\r
1096for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */\r
1097 idx = dibp->vloc + i; /* vector index */\r
1098 vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */\r
1099 ilvl = idx / 32;\r
1100 ibit = idx % 32;\r
1101 if ((int_ack[ilvl][ibit] && dibp->ack[i] && /* conflict? */\r
1102 (int_ack[ilvl][ibit] != dibp->ack[i])) ||\r
1103 (int_vec[ilvl][ibit] && vec &&\r
1104 (int_vec[ilvl][ibit] != vec))) {\r
1105 printf ("Device %s interrupt slot conflict at %d\n",\r
1106 sim_dname (dptr), idx);\r
1107 if (sim_log) fprintf (sim_log,\r
1108 "Device %s interrupt slot conflict at %d\n",\r
1109 sim_dname (dptr), idx);\r
1110 return SCPE_STOP;\r
1111 }\r
1112 if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i];\r
1113 else if (vec) int_vec[ilvl][ibit] = vec;\r
1114 }\r
1115for (i = 0; i < (int32) dibp->lnt; i = i + 2) { /* create entries */\r
1116 idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */\r
1117 if ((iodispR[idx] && dibp->rd && /* conflict? */\r
1118 (iodispR[idx] != dibp->rd)) ||\r
1119 (iodispW[idx] && dibp->wr &&\r
1120 (iodispW[idx] != dibp->wr))) {\r
1121 printf ("Device %s address conflict at %08o\n",\r
1122 sim_dname (dptr), dibp->ba);\r
1123 if (sim_log) fprintf (sim_log,\r
1124 "Device %s address conflict at %08o\n",\r
1125 sim_dname (dptr), dibp->ba);\r
1126 return SCPE_STOP;\r
1127 }\r
1128 if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */\r
1129 if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */\r
1130 iodibp[idx] = dibp; /* remember DIB */\r
1131 }\r
1132return SCPE_OK;\r
1133}\r
1134\r
1135/* Show IO space */\r
1136\r
1137t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc)\r
1138{\r
1139uint32 i, j;\r
1140DEVICE *dptr;\r
1141DIB *dibp;\r
1142\r
1143if (build_dib_tab ()) return SCPE_OK; /* build IO page */\r
1144for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */\r
1145 if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */\r
1146 dibp = iodibp[i]; /* DIB for block */\r
1147 for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) {\r
1148 if (((DIB*) sim_devices[j]->ctxt) == dibp) {\r
1149 dptr = sim_devices[j]; /* locate device */\r
1150 break;\r
1151 } /* end if */\r
1152 } /* end for j */\r
1153 fprintf (st, "%08X - %08X%c\t%s\n", dibp->ba,\r
1154 dibp->ba + dibp->lnt - 1,\r
1155 (dptr && (dptr->flags & DEV_FLTA))? '*': ' ',\r
1156 dptr? sim_dname (dptr): "CPU");\r
1157 } /* end if */\r
1158 } /* end for i */\r
1159return SCPE_OK;\r
1160}\r
1161\r
1162/* Show UBA virtual address */\r
1163\r
1164t_stat uba_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc)\r
1165{\r
1166t_stat r;\r
1167char *cptr = (char *) desc;\r
1168uint32 ua, pa;\r
1169\r
1170if (cptr) {\r
1171 ua = (uint32) get_uint (cptr, 16, UBADDRSIZE - 1, &r);\r
1172 if (r == SCPE_OK) {\r
1173 if (uba_map_addr_c (ua, &pa))\r
1174 fprintf (of, "Unibus %-X = physical %-X\n", ua, pa);\r
1175 else fprintf (of, "Unibus %-X: invalid mapping\n", ua);\r
1176 return SCPE_OK;\r
1177 }\r
1178 }\r
1179fprintf (of, "Invalid argument\n");\r
1180return SCPE_OK;\r
1181}\r
1182\r
1183/* Autoconfiguration\r
1184\r
1185 The table reflects the MicroVAX 3900 microcode, with one addition - the\r
1186 number of controllers field handles devices where multiple instances\r
1187 are simulated through a single DEVICE structure (e.g., DZ, VH).\r
1188\r
1189 A minus number of vectors indicates a field that should be calculated\r
1190 but not placed in the DIB (RQ, TQ dynamic vectors) */\r
1191\r
1192#define AUTO_MAXC 4\r
1193#define AUTO_CSRBASE 0010\r
1194#define AUTO_VECBASE 0300\r
1195\r
1196typedef struct {\r
1197 char *dnam[AUTO_MAXC];\r
1198 int32 numc;\r
1199 int32 numv;\r
1200 uint32 amod;\r
1201 uint32 vmod;\r
1202 uint32 fixa[AUTO_MAXC];\r
1203 uint32 fixv[AUTO_MAXC];\r
1204 } AUTO_CON;\r
1205\r
1206AUTO_CON auto_tab[] = {\r
1207 { { NULL }, 1, 2, 0, 8, { 0 } }, /* DLV11J - fx CSRs */\r
1208 { { NULL }, 1, 2, 8, 8 }, /* DJ11 */\r
1209 { { NULL }, 1, 2, 16, 8 }, /* DH11 */\r
1210 { { NULL }, 1, 2, 8, 8 }, /* DQ11 */\r
1211 { { NULL }, 1, 2, 8, 8 }, /* DU11 */\r
1212 { { NULL }, 1, 2, 8, 8 }, /* DUP11 */\r
1213 { { NULL }, 10, 2, 8, 8 }, /* LK11A */\r
1214 { { NULL }, 1, 2, 8, 8 }, /* DMC11 */\r
1215 { { "DZ" }, DZ_MUXES, 2, 8, 8 }, /* DZ11 */\r
1216 { { NULL }, 1, 2, 8, 8 }, /* KMC11 */\r
1217 { { NULL }, 1, 2, 8, 8 }, /* LPP11 */\r
1218 { { NULL }, 1, 2, 8, 8 }, /* VMV21 */\r
1219 { { NULL }, 1, 2, 16, 8 }, /* VMV31 */\r
1220 { { NULL }, 1, 2, 8, 8 }, /* DWR70 */\r
1221 { { "RL", "RLB" }, 1, 1, 8, 4, {IOBA_RL}, {VEC_RL} }, /* RL11 */\r
1222 { { "TS", "TSB", "TSC", "TSD" }, 1, 1, 0, 4, /* TS11 */\r
1223 {IOBA_TS, IOBA_TS + 4, IOBA_TS + 8, IOBA_TS + 12},\r
1224 {VEC_TS} },\r
1225 { { NULL }, 1, 2, 16, 8 }, /* LPA11K */\r
1226 { { NULL }, 1, 2, 8, 8 }, /* KW11C */\r
1227 { { NULL }, 1, 1, 8, 8 }, /* reserved */\r
1228 { { "RX", "RY" }, 1, 1, 8, 4, {IOBA_RX} , {VEC_RX} }, /* RX11/RX211 */\r
1229 { { NULL }, 1, 1, 8, 4 }, /* DR11W */\r
1230 { { NULL }, 1, 1, 8, 4, { 0, 0 }, { 0 } }, /* DR11B - fx CSRs,vec */\r
1231 { { NULL }, 1, 2, 8, 8 }, /* DMP11 */\r
1232 { { NULL }, 1, 2, 8, 8 }, /* DPV11 */\r
1233 { { NULL }, 1, 2, 8, 8 }, /* ISB11 */\r
1234 { { NULL }, 1, 2, 16, 8 }, /* DMV11 */\r
1235 { { "XU", "XUB" }, 1, 1, 8, 4, {IOBA_XU}, {VEC_XU} }, /* DEUNA */\r
1236 { { "XQ", "XQB" }, 1, 1, 0, 4, /* DEQNA */\r
1237 {IOBA_XQ,IOBA_XQB}, {VEC_XQ} }, /* */\r
1238 { { "RQ", "RQB", "RQC", "RQD" }, 1, -1, 4, 4, /* RQDX3 */\r
1239 {IOBA_RQ}, {VEC_RQ} },\r
1240 { { NULL }, 1, 8, 32, 4 }, /* DMF32 */\r
1241 { { NULL }, 1, 2, 16, 8 }, /* KMS11 */\r
1242 { { NULL }, 1, 1, 16, 4 }, /* VS100 */\r
1243 { { "TQ", "TQB" }, 1, -1, 4, 4, {IOBA_TQ}, {VEC_TQ} }, /* TQK50 */\r
1244 { { NULL }, 1, 2, 16, 8 }, /* KMV11 */\r
1245 { { "VH" }, VH_MUXES, 2, 16, 8 }, /* DHU11/DHQ11 */\r
1246 { { NULL }, 1, 6, 32, 4 }, /* DMZ32 */\r
1247 { { NULL }, 1, 6, 32, 4 }, /* CP132 */\r
1248 { { NULL }, 1, 2, 64, 8, { 0 } }, /* QVSS - fx CSR */\r
1249 { { NULL }, 1, 1, 8, 4 }, /* VS31 */\r
1250 { { NULL }, 1, 1, 0, 4, { 0 } }, /* LNV11 - fx CSR */\r
1251 { { NULL }, 1, 1, 16, 4 }, /* LNV21/QPSS */\r
1252 { { NULL }, 1, 1, 8, 4, { 0 } }, /* QTA - fx CSR */\r
1253 { { NULL }, 1, 1, 8, 4 }, /* DSV11 */\r
1254 { { NULL }, 1, 2, 8, 8 }, /* CSAM */\r
1255 { { NULL }, 1, 2, 8, 8 }, /* ADV11C */\r
1256 { { NULL }, 1, 0, 8, 0 }, /* AAV11C */\r
1257 { { NULL }, 1, 2, 8, 8, { 0 }, { 0 } }, /* AXV11C - fx CSR,vec */\r
1258 { { NULL }, 1, 2, 4, 8, { 0 } }, /* KWV11C - fx CSR */\r
1259 { { NULL }, 1, 2, 8, 8, { 0 } }, /* ADV11D - fx CSR */\r
1260 { { NULL }, 1, 2, 8, 8, { 0 } }, /* AAV11D - fx CSR */\r
1261 { { "QDSS" }, 1, 3, 0, 16, {IOBA_QDSS} }, /* QDSS - fx CSR */\r
1262 { { NULL }, -1 } /* end table */\r
1263};\r
1264\r
1265t_stat auto_config (char *name, int32 nctrl)\r
1266{\r
1267uint32 csr = IOPAGEBASE + AUTO_CSRBASE;\r
1268uint32 vec = VEC_Q + AUTO_VECBASE;\r
1269AUTO_CON *autp;\r
1270DEVICE *dptr;\r
1271DIB *dibp;\r
1272uint32 j, k, vmask, amask;\r
1273\r
1274if (autcon_enb == 0) return SCPE_OK; /* enabled? */\r
1275if (name) { /* updating? */\r
1276 if (nctrl < 0) return SCPE_ARG;\r
1277 for (autp = auto_tab; autp->numc >= 0; autp++) {\r
1278 for (j = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) {\r
1279 if (strcmp (name, autp->dnam[j]) == 0)\r
1280 autp->numc = nctrl;\r
1281 }\r
1282 }\r
1283 }\r
1284for (autp = auto_tab; autp->numc >= 0; autp++) { /* loop thru table */\r
1285 if (autp->amod) { /* floating csr? */\r
1286 amask = autp->amod - 1;\r
1287 csr = (csr + amask) & ~amask; /* align csr */\r
1288 }\r
1289 for (j = k = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) {\r
1290 dptr = find_dev (autp->dnam[j]); /* find ctrl */\r
1291 if ((dptr == NULL) || (dptr->flags & DEV_DIS) ||\r
1292 !(dptr->flags & DEV_FLTA)) continue; /* enabled, floating? */\r
1293 dibp = (DIB *) dptr->ctxt; /* get DIB */\r
1294 if (dibp == NULL) return SCPE_IERR; /* not there??? */\r
1295 if (autp->amod) { /* dyn csr needed? */\r
1296 if (autp->fixa[k]) /* fixed csr avail? */\r
1297 dibp->ba = autp->fixa[k]; /* use it */\r
1298 else { /* no fixed left */\r
1299 dibp->ba = csr; /* set CSR */\r
1300 csr += (autp->numc * autp->amod); /* next CSR */\r
1301 } /* end else */\r
1302 } /* end if dyn csr */\r
1303 if (autp->numv && autp->vmod) { /* dyn vec needed? */\r
1304 uint32 numv = abs (autp->numv); /* get num vec */\r
1305 if (autp->fixv[k]) { /* fixed vec avail? */\r
1306 if (autp->numv > 0)\r
1307 dibp->vec = autp->fixv[k]; /* use it */\r
1308 }\r
1309 else { /* no fixed left */\r
1310 vmask = autp->vmod - 1;\r
1311 vec = (vec + vmask) & ~vmask; /* align vector */\r
1312 if (autp->numv > 0)\r
1313 dibp->vec = vec; /* set vector */\r
1314 vec += (autp->numc * numv * 4);\r
1315 } /* end else */\r
1316 } /* end if dyn vec */\r
1317 k++; /* next instance */\r
1318 } /* end for j */\r
1319 if (autp->amod) csr = csr + 2; /* flt CSR? gap */\r
1320 } /* end for i */\r
1321return SCPE_OK;\r
1322}\r