1 /* vax780_mba.c: VAX 11/780 Massbus adapter
3 Copyright (c) 2004-2008, 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 mba0, mba1 RH780 Massbus adapter
28 28-May-08 RMS Inlined physical memory routines
35 #define MBA_NMAPR 256 /* number of map reg */
36 #define MBA_V_RTYPE 10 /* nexus addr: reg type */
37 #define MBA_M_RTYPE 0x3
38 #define MBART_INT 0x0 /* internal */
39 #define MBART_EXT 0x1 /* external */
40 #define MBART_MAP 0x2 /* map */
41 #define MBA_V_INTOFS 2 /* int reg: reg ofs */
42 #define MBA_M_INTOFS 0xFF
43 #define MBA_V_DRV 7 /* ext reg: drive num */
45 #define MBA_V_DEVOFS 2 /* ext reg: reg ofs */
46 #define MBA_M_DEVOFS 0x1F
47 #define MBA_RTYPE(x) (((x) >> MBA_V_RTYPE) & MBA_M_RTYPE)
48 #define MBA_INTOFS(x) (((x) >> MBA_V_INTOFS) & MBA_M_INTOFS)
49 #define MBA_EXTDRV(x) (((x) >> MBA_V_DRV) & MBA_M_DRV)
50 #define MBA_EXTOFS(x) (((x) >> MBA_V_DEVOFS) & MBA_M_DEVOFS)
52 /* Massbus configuration register */
55 #define MBACNF_ADPDN 0x00800000 /* adap pdn - ni */
56 #define MBACNF_ADPUP 0x00400000 /* adap pup - ni */
57 #define MBACNF_CODE 0x00000020
58 #define MBACNF_RD (SBI_FAULTS|MBACNF_W1C)
59 #define MBACNF_W1C 0x00C00000
61 /* Control register */
64 #define MBACR_MNT 0x00000008 /* maint */
65 #define MBACR_IE 0x00000004 /* int enable */
66 #define MBACR_ABORT 0x00000002 /* abort */
67 #define MBACR_INIT 0x00000001
68 #define MBACR_RD 0x0000000E
69 #define MBACR_WR 0x0000000E
74 #define MBASR_DTBUSY 0x80000000 /* DT busy RO */
75 #define MBASR_NRCONF 0x40000000 /* no conf - ni W1C */
76 #define MBASR_CRD 0x20000000 /* CRD - ni W1C */
77 #define MBASR_CBH 0x00800000 /* CBHUNG - ni W1C */
78 #define MBASR_PGE 0x00080000 /* prog err - W1C int */
79 #define MBASR_NFD 0x00040000 /* nx drive - W1C int */
80 #define MBASR_MCPE 0x00020000 /* ctl perr - ni W1C int */
81 #define MBASR_ATA 0x00010000 /* attn - W1C int */
82 #define MBASR_SPE 0x00004000 /* silo perr - ni W1C int */
83 #define MBASR_DTCMP 0x00002000 /* xfr done - W1C int */
84 #define MBASR_DTABT 0x00001000 /* abort - W1C int */
85 #define MBASR_DLT 0x00000800 /* dat late - ni W1C abt */
86 #define MBASR_WCEU 0x00000400 /* wrchk upper - W1C abt */
87 #define MBASR_WCEL 0x00000200 /* wrchk lower - W1C abt */
88 #define MBASR_MXF 0x00000100 /* miss xfr - ni W1C abt */
89 #define MBASR_MBEXC 0x00000080 /* except - ni W1C abt */
90 #define MBASR_MBDPE 0x00000040 /* dat perr - ni W1C abt */
91 #define MBASR_MAPPE 0x00000020 /* map perr - ni W1C abt */
92 #define MBASR_INVM 0x00000010 /* inv map - W1C abt */
93 #define MBASR_ERCONF 0x00000008 /* err conf - ni W1C abt */
94 #define MBASR_RDS 0x00000004 /* RDS - ni W1C abt */
95 #define MBASR_ITMO 0x00000002 /* timeout - W1C abt */
96 #define MBASR_RTMO 0x00000001 /* rd timeout - W1C abt */
97 #define MBASR_RD 0xE08F7FFF
98 #define MBASR_W1C 0x608F7FFF
99 #define MBASR_ABORTS 0x00000FFF
100 #define MBASR_ERRORS 0x608E49FF
101 #define MBASR_INTR 0x000F7000
103 /* Virtual address register */
106 #define MBAVA_RD 0x0001FFFF
107 #define MBAVA_WR (MBAVA_RD)
112 #define MBABC_WR 0x0000FFFF
113 #define MBABC_V_MBC 16 /* MB count */
115 /* Diagnostic register */
118 #define MBADR_RD 0xFFFFFFFF
119 #define MBADR_WR 0xFFC00000
121 /* Selected map entry - read only */
123 #define MBASMR_OF 0x6
124 #define MBASMR_RD (MBAMAP_RD)
126 /* Command register (SBI) - read only */
128 #define MBACMD_OF 0x7
130 /* External registers */
132 #define MBA_CS1 0x00 /* device CSR1 */
133 #define MBA_CS1_WR 0x3F /* writeable bits */
134 #define MBA_CS1_DT 0x28 /* >= for data xfr */
138 #define MBAMAP_VLD 0x80000000 /* valid */
139 #define MBAMAP_PAG 0x001FFFFF
140 #define MBAMAP_RD (MBAMAP_VLD | MBAMAP_PAG)
141 #define MBAMAP_WR (MBAMAP_RD)
145 #define MBA_DEB_RRD 0x01 /* reg reads */
146 #define MBA_DEB_RWR 0x02 /* reg writes */
147 #define MBA_DEB_MRD 0x04 /* map reads */
148 #define MBA_DEB_MWR 0x08 /* map writes */
149 #define MBA_DEB_XFR 0x10 /* transfers */
150 #define MBA_DEB_ERR 0x20 /* errors */
152 uint32 mba_cnf
[MBA_NUM
]; /* config reg */
153 uint32 mba_cr
[MBA_NUM
]; /* control reg */
154 uint32 mba_sr
[MBA_NUM
]; /* status reg */
155 uint32 mba_va
[MBA_NUM
]; /* virt addr */
156 uint32 mba_bc
[MBA_NUM
]; /* byte count */
157 uint32 mba_dr
[MBA_NUM
]; /* diag reg */
158 uint32 mba_smr
[MBA_NUM
]; /* sel map reg */
159 uint32 mba_map
[MBA_NUM
][MBA_NMAPR
]; /* map */
161 extern uint32 nexus_req
[NEXUS_HLVL
];
162 extern UNIT cpu_unit
;
163 extern FILE *sim_log
;
164 extern FILE *sim_deb
;
165 extern int32 sim_switches
;
167 t_stat
mba_reset (DEVICE
*dptr
);
168 t_stat
mba_rdreg (int32
*val
, int32 pa
, int32 mode
);
169 t_stat
mba_wrreg (int32 val
, int32 pa
, int32 lnt
);
170 t_bool
mba_map_addr (uint32 va
, uint32
*ma
, uint32 mb
);
171 void mba_set_int (uint32 mb
);
172 void mba_clr_int (uint32 mb
);
173 void mba_upd_sr (uint32 set
, uint32 clr
, uint32 mb
);
174 DIB mba0_dib
, mba1_dib
;
176 /* Massbus register dispatches */
178 static t_stat (*mbregR
[MBA_NUM
])(int32
*dat
, int32 ad
, int32 md
);
179 static t_stat (*mbregW
[MBA_NUM
])(int32 dat
, int32 ad
, int32 md
);
180 static int32 (*mbabort
[MBA_NUM
])(void);
182 /* Massbus adapter data structures
184 mba_dev MBA device descriptors
186 mbax_reg MBA register list
189 DIB mba0_dib
= { TR_MBA0
, 0, &mba_rdreg
, &mba_wrreg
, 0, NVCL (MBA0
) };
191 UNIT mba0_unit
= { UDATA (NULL
, 0, 0) };
194 { HRDATA (CNFR
, mba_cnf
[0], 32) },
195 { HRDATA (CR
, mba_cr
[0], 4) },
196 { HRDATA (SR
, mba_sr
[0], 32) },
197 { HRDATA (VA
, mba_va
[0], 17) },
198 { HRDATA (BC
, mba_bc
[0], 16) },
199 { HRDATA (DR
, mba_dr
[0], 32) },
200 { HRDATA (SMR
, mba_dr
[0], 32) },
201 { BRDATA (MAP
, mba_map
[0], 16, 32, MBA_NMAPR
) },
202 { FLDATA (NEXINT
, nexus_req
[IPL_MBA0
], TR_MBA0
) },
207 { MTAB_XTD
|MTAB_VDV
, TR_MBA0
, "NEXUS", NULL
,
212 DIB mba1_dib
= { TR_MBA1
, 0, &mba_rdreg
, &mba_wrreg
, 0, NVCL (MBA1
) };
214 UNIT mba1_unit
= { UDATA (NULL
, 0, 0) };
217 { MTAB_XTD
|MTAB_VDV
, TR_MBA1
, "NEXUS", NULL
,
223 { HRDATA (CNFR
, mba_cnf
[1], 32) },
224 { HRDATA (CR
, mba_cr
[1], 4) },
225 { HRDATA (SR
, mba_sr
[1], 32) },
226 { HRDATA (VA
, mba_va
[1], 17) },
227 { HRDATA (BC
, mba_bc
[1], 16) },
228 { HRDATA (DR
, mba_dr
[1], 32) },
229 { HRDATA (SMR
, mba_dr
[1], 32) },
230 { BRDATA (MAP
, mba_map
[1], 16, 32, MBA_NMAPR
) },
231 { FLDATA (NEXINT
, nexus_req
[IPL_MBA1
], TR_MBA1
) },
236 { "REGREAD", MBA_DEB_RRD
},
237 { "REGWRITE", MBA_DEB_RWR
},
238 { "MAPREAD", MBA_DEB_MRD
},
239 { "MAPWRITE", MBA_DEB_MWR
},
240 { "XFER", MBA_DEB_XFR
},
241 { "ERROR", MBA_DEB_ERR
},
247 "MBA0", &mba0_unit
, mba0_reg
, mba0_mod
,
249 NULL
, NULL
, &mba_reset
,
251 &mba0_dib
, DEV_NEXUS
| DEV_DEBUG
, 0,
255 "MBA1", &mba1_unit
, mba1_reg
, mba1_mod
,
257 NULL
, NULL
, &mba_reset
,
259 &mba1_dib
, DEV_NEXUS
| DEV_DEBUG
, 0,
264 /* Read Massbus adapter register */
266 t_stat
mba_rdreg (int32
*val
, int32 pa
, int32 lnt
)
268 int32 mb
, ofs
, drv
, rtype
;
272 mb
= NEXUS_GETNEX (pa
) - TR_MBA0
; /* get MBA */
273 if ((pa
& 3) || (lnt
!= L_LONG
)) { /* unaligned or not lw? */
274 printf (">>MBA%d: invalid adapter read mask, pa = %X, lnt = %d\r\n", mb
, pa
, lnt
);
275 sbi_set_errcnf (); /* err confirmation */
278 if (mb
>= MBA_NUM
) return SCPE_NXM
; /* valid? */
279 rtype
= MBA_RTYPE (pa
); /* get reg type */
281 switch (rtype
) { /* case on type */
283 case MBART_INT
: /* internal */
284 ofs
= MBA_INTOFS (pa
); /* check range */
287 case MBACNF_OF
: /* CNF */
288 *val
= (mba_cnf
[mb
] & MBACNF_RD
) | MBACNF_CODE
;
291 case MBACR_OF
: /* CR */
292 *val
= mba_cr
[mb
] & MBACR_RD
;
295 case MBASR_OF
: /* SR */
296 *val
= mba_sr
[mb
] & MBASR_RD
;
299 case MBAVA_OF
: /* VA */
300 *val
= mba_va
[mb
] & MBAVA_RD
;
303 case MBABC_OF
: /* BC */
304 t
= mba_bc
[mb
] & MBABC_WR
;
305 *val
= (t
<< MBABC_V_MBC
) | t
;
308 case MBADR_OF
: /* DR */
309 *val
= mba_dr
[mb
] & MBADR_RD
;
312 case MBASMR_OF
: /* SMR */
313 *val
= mba_smr
[mb
] & MBASMR_RD
;
316 case MBACMD_OF
: /* CMD */
323 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_RRD
))
324 fprintf (sim_deb
, ">>MBA%d: int reg %d read, value = %X\n", mb
, ofs
, *val
);
327 case MBART_EXT
: /* external */
328 if (!mbregR
[mb
]) return SCPE_NXM
; /* device there? */
329 drv
= MBA_EXTDRV (pa
); /* get dev num */
330 ofs
= MBA_EXTOFS (pa
); /* get reg offs */
331 r
= mbregR
[mb
] (val
, ofs
, drv
); /* call device */
332 if (r
== MBE_NXD
) mba_upd_sr (MBASR_NFD
, 0, mb
);/* nx drive? */
333 else if (r
== MBE_NXR
) return SCPE_NXM
; /* nx reg? */
334 *val
|= (mba_sr
[mb
] & ~WMASK
); /* upper 16b from SR */
335 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_RRD
))
336 fprintf (sim_deb
, ">>MBA%d: drv %d ext reg %d read, value = %X\n", mb
, drv
, ofs
, *val
);
339 case MBART_MAP
: /* map */
340 ofs
= MBA_INTOFS (pa
);
341 *val
= mba_map
[mb
][ofs
] & MBAMAP_RD
;
342 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_MRD
))
343 fprintf (sim_deb
, ">>MBA%d: map %d read, value = %X\n", mb
, ofs
, *val
);
353 /* Write Massbus adapter register */
355 t_stat
mba_wrreg (int32 val
, int32 pa
, int32 lnt
)
357 int32 mb
, ofs
, drv
, rtype
;
361 mb
= NEXUS_GETNEX (pa
) - TR_MBA0
; /* get MBA */
362 if ((pa
& 3) || (lnt
!= L_LONG
)) { /* unaligned or not lw? */
363 printf (">>MBA%d: invalid adapter write mask, pa = %X, lnt = %d\r\n", mb
, pa
, lnt
);
364 sbi_set_errcnf (); /* err confirmation */
367 if (mb
>= MBA_NUM
) return SCPE_NXM
; /* valid? */
368 rtype
= MBA_RTYPE (pa
); /* get reg type */
370 switch (rtype
) { /* case on type */
372 case MBART_INT
: /* internal */
373 ofs
= MBA_INTOFS (pa
); /* check range */
376 case MBACNF_OF
: /* CNF */
377 mba_cnf
[mb
] &= ~(val
& MBACNF_W1C
);
380 case MBACR_OF
: /* CR */
381 if (val
& MBACR_INIT
) /* init? */
382 mba_reset (&mba_dev
[mb
]); /* reset MBA */
383 if ((val
& MBACR_ABORT
) &&
384 (mba_sr
[mb
] & MBASR_DTBUSY
)) {
385 if (mbabort
[mb
]) mbabort
[mb
] (); /* abort? */
386 mba_upd_sr (MBASR_DTABT
, 0, mb
);
388 if ((val
& MBACR_MNT
) &&
389 (mba_sr
[mb
] & MBASR_DTBUSY
)) {
390 mba_upd_sr (MBASR_PGE
, 0, mb
); /* mnt & xfer? */
391 val
= val
& ~MBACR_MNT
;
393 if ((val
& MBACR_IE
) == 0) mba_clr_int (mb
);
394 mba_cr
[mb
] = (mba_cr
[mb
] & ~MBACR_WR
) |
398 case MBASR_OF
: /* SR */
399 mba_sr
[mb
] = mba_sr
[mb
] & ~(val
& MBASR_W1C
);
402 case MBAVA_OF
: /* VA */
403 if (mba_sr
[mb
] & MBASR_DTBUSY
) /* err if xfr */
404 mba_upd_sr (MBASR_PGE
, 0, mb
);
405 else mba_va
[mb
] = val
& MBAVA_WR
;
408 case MBABC_OF
: /* BC */
409 if (mba_sr
[mb
] & MBASR_DTBUSY
) /* err if xfr */
410 mba_upd_sr (MBASR_PGE
, 0, mb
);
411 else mba_bc
[mb
] = val
& MBABC_WR
;
414 case MBADR_OF
: /* DR */
415 mba_dr
[mb
] = (mba_dr
[mb
] & ~MBADR_WR
) |
422 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_RWR
))
423 fprintf (sim_deb
, ">>MBA%d: int reg %d write, value = %X\n", mb
, ofs
, val
);
426 case MBART_EXT
: /* external */
427 if (!mbregW
[mb
]) return SCPE_NXM
; /* device there? */
428 drv
= MBA_EXTDRV (pa
); /* get dev num */
429 ofs
= MBA_EXTOFS (pa
); /* get reg offs */
430 cs1dt
= (ofs
== MBA_CS1
) && (val
& CSR_GO
) && /* starting xfr? */
431 ((val
& MBA_CS1_WR
) >= MBA_CS1_DT
);
432 if (cs1dt
&& (mba_sr
[mb
] & MBASR_DTBUSY
)) { /* xfr while busy? */
433 mba_upd_sr (MBASR_PGE
, 0, mb
); /* prog error */
436 r
= mbregW
[mb
] (val
& WMASK
, ofs
, drv
); /* write dev reg */
437 if (r
== MBE_NXD
) mba_upd_sr (MBASR_NFD
, 0, mb
);/* nx drive? */
438 else if (r
== MBE_NXR
) return SCPE_NXM
; /* nx reg? */
439 if (cs1dt
&& (r
== SCPE_OK
)) /* did dt start? */
440 mba_sr
[mb
] = (mba_sr
[mb
] | MBASR_DTBUSY
) & ~MBASR_W1C
;
441 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_RWR
))
442 fprintf (sim_deb
, ">>MBA%d: drv %d ext reg %d write, value = %X\n", mb
, drv
, ofs
, val
);
445 case MBART_MAP
: /* map */
446 ofs
= MBA_INTOFS (pa
);
447 mba_map
[mb
][ofs
] = val
& MBAMAP_WR
;
448 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_MWR
))
449 fprintf (sim_deb
, ">>MBA%d: map %d write, value = %X\n", mb
, ofs
, val
);
459 /* Massbus I/O routine
461 mb_rdbufW - fetch word buffer from memory
462 mb_wrbufW - store word buffer into memory
463 mb_chbufW - compare word buffer with memory
465 Returns number of bytes successfully transferred/checked
468 int32
mba_rdbufW (uint32 mb
, int32 bc
, uint16
*buf
)
470 int32 i
, j
, ba
, mbc
, pbc
;
473 if (mb
>= MBA_NUM
) return 0; /* valid MBA? */
474 ba
= mba_va
[mb
]; /* get virt addr */
475 mbc
= (MBABC_WR
+ 1) - mba_bc
[mb
]; /* get Mbus bc */
476 if (bc
> mbc
) bc
= mbc
; /* use smaller */
477 for (i
= 0; i
< bc
; i
= i
+ pbc
) { /* loop by pages */
478 if (!mba_map_addr (ba
+ i
, &pa
, mb
)) break; /* page inv? */
479 if (!ADDR_IS_MEM (pa
)) { /* NXM? */
480 mba_upd_sr (MBASR_RTMO
, 0, mb
);
483 pbc
= VA_PAGSIZE
- VA_GETOFF (pa
); /* left in page */
484 if (pbc
> (bc
- i
)) pbc
= bc
- i
; /* limit to rem xfr */
485 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_XFR
))
486 fprintf (sim_deb
, ">>MBA%d: read, pa = %X, bc = %X\n", mb
, pa
, pbc
);
487 if ((pa
| pbc
) & 1) { /* aligned word? */
488 for (j
= 0; j
< pbc
; pa
++, j
++) { /* no, bytes */
489 if ((i
+ j
) & 1) { /* odd byte? */
490 *buf
= (*buf
& BMASK
) | (ReadB (pa
) << 8);
493 else *buf
= (*buf
& ~BMASK
) | ReadB (pa
);
496 else if ((pa
| pbc
) & 3) { /* aligned LW? */
497 for (j
= 0; j
< pbc
; pa
= pa
+ 2, j
= j
+ 2) { /* no, words */
498 *buf
++ = ReadW (pa
); /* get word */
501 else { /* yes, do by LW */
502 for (j
= 0; j
< pbc
; pa
= pa
+ 4, j
= j
+ 4) {
503 dat
= ReadL (pa
); /* get lw */
504 *buf
++ = dat
& WMASK
; /* low 16b */
505 *buf
++ = (dat
>> 16) & WMASK
; /* high 16b */
509 mba_bc
[mb
] = (mba_bc
[mb
] + i
) & MBABC_WR
;
510 mba_va
[mb
] = (mba_va
[mb
] + i
) & MBAVA_WR
;
514 int32
mba_wrbufW (uint32 mb
, int32 bc
, uint16
*buf
)
516 int32 i
, j
, ba
, mbc
, pbc
;
519 if (mb
>= MBA_NUM
) return 0; /* valid MBA? */
520 ba
= mba_va
[mb
]; /* get virt addr */
521 mbc
= (MBABC_WR
+ 1) - mba_bc
[mb
]; /* get Mbus bc */
522 if (bc
> mbc
) bc
= mbc
; /* use smaller */
523 for (i
= 0; i
< bc
; i
= i
+ pbc
) { /* loop by pages */
524 if (!mba_map_addr (ba
+ i
, &pa
, mb
)) break; /* page inv? */
525 if (!ADDR_IS_MEM (pa
)) { /* NXM? */
526 mba_upd_sr (MBASR_RTMO
, 0, mb
);
529 pbc
= VA_PAGSIZE
- VA_GETOFF (pa
); /* left in page */
530 if (pbc
> (bc
- i
)) pbc
= bc
- i
; /* limit to rem xfr */
531 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_XFR
))
532 fprintf (sim_deb
, ">>MBA%d: write, pa = %X, bc = %X\n", mb
, pa
, pbc
);
533 if ((pa
| pbc
) & 1) { /* aligned word? */
534 for (j
= 0; j
< pbc
; pa
++, j
++) { /* no, bytes */
536 WriteB (pa
, (*buf
>> 8) & BMASK
);
539 else WriteB (pa
, *buf
& BMASK
);
542 else if ((pa
| pbc
) & 3) { /* aligned LW? */
543 for (j
= 0; j
< pbc
; pa
= pa
+ 2, j
= j
+ 2) { /* no, words */
544 WriteW (pa
, *buf
); /* write word */
548 else { /* yes, do by LW */
549 for (j
= 0; j
< pbc
; pa
= pa
+ 4, j
= j
+ 4) {
550 dat
= (uint32
) *buf
++; /* get low 16b */
551 dat
= dat
| (((uint32
) *buf
++) << 16); /* merge hi 16b */
552 WriteL (pa
, dat
); /* store LW */
556 mba_bc
[mb
] = (mba_bc
[mb
] + i
) & MBABC_WR
;
557 mba_va
[mb
] = (mba_va
[mb
] + i
) & MBAVA_WR
;
561 int32
mba_chbufW (uint32 mb
, int32 bc
, uint16
*buf
)
563 int32 i
, j
, ba
, mbc
, pbc
;
566 if (mb
>= MBA_NUM
) return 0; /* valid MBA? */
567 ba
= mba_va
[mb
]; /* get virt addr */
568 mbc
= (MBABC_WR
+ 1) - mba_bc
[mb
]; /* get Mbus bc */
569 if (bc
> mbc
) bc
= mbc
; /* use smaller */
570 for (i
= 0; i
< bc
; i
= i
+ pbc
) { /* loop by pages */
571 if (!mba_map_addr (ba
+ i
, &pa
, mb
)) break; /* page inv? */
572 if (!ADDR_IS_MEM (pa
)) { /* NXM? */
573 mba_upd_sr (MBASR_RTMO
, 0, mb
);
576 pbc
= VA_PAGSIZE
- VA_GETOFF (pa
); /* left in page */
577 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_XFR
))
578 fprintf (sim_deb
, ">>MBA%d: check, pa = %X, bc = %X\n", mb
, pa
, pbc
);
579 if (pbc
> (bc
- i
)) pbc
= bc
- i
; /* limit to rem xfr */
580 for (j
= 0; j
< pbc
; j
++, pa
++) { /* byte by byte */
582 if ((i
+ j
) & 1) dat
= (*buf
++ >> 8) & BMASK
;
583 else dat
= *buf
& BMASK
;
585 mba_upd_sr ((j
& 1)? MBASR_WCEU
: MBASR_WCEL
, 0, mb
);
590 mba_bc
[mb
] = (mba_bc
[mb
] + i
) & MBABC_WR
;
591 mba_va
[mb
] = (mba_va
[mb
] + i
) & MBAVA_WR
;
595 /* Map an address via the translation map */
597 t_bool
mba_map_addr (uint32 va
, uint32
*ma
, uint32 mb
)
599 uint32 vblk
= (va
>> VA_V_VPN
); /* map index */
600 uint32 mmap
= mba_map
[mb
][vblk
]; /* get map */
602 mba_smr
[mb
] = mmap
; /* save map reg */
603 if (mmap
& MBAMAP_VLD
) { /* valid? */
604 *ma
= ((mmap
& MBAMAP_PAG
) << VA_V_VPN
) + VA_GETOFF (va
);
605 return 1; /* legit addr */
607 mba_upd_sr (MBASR_INVM
, 0, mb
); /* invalid map */
611 /* Device access, status, and interrupt routines */
613 void mba_set_don (uint32 mb
)
615 mba_upd_sr (MBASR_DTCMP
, 0, mb
);
619 void mba_upd_ata (uint32 mb
, uint32 val
)
621 if (val
) mba_upd_sr (MBASR_ATA
, 0, mb
);
622 else mba_upd_sr (0, MBASR_ATA
, mb
);
626 void mba_set_exc (uint32 mb
)
628 mba_upd_sr (MBASR_MBEXC
, 0, mb
);
629 if (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_ERR
))
630 fprintf (sim_deb
, ">>MBA%d: EXC write\n", mb
);
634 int32
mba_get_bc (uint32 mb
)
636 if (mb
>= MBA_NUM
) return 0;
637 return (MBABC_WR
+ 1) - mba_bc
[mb
];
640 void mba_set_int (uint32 mb
)
644 if (mb
>= MBA_NUM
) return;
645 dibp
= (DIB
*) mba_dev
[mb
].ctxt
;
647 nexus_req
[dibp
->vloc
>> 5] |= (1u << (dibp
->vloc
& 0x1F));
651 void mba_clr_int (uint32 mb
)
655 if (mb
>= MBA_NUM
) return;
656 dibp
= (DIB
*) mba_dev
[mb
].ctxt
;
658 nexus_req
[dibp
->vloc
>> 5] &= ~(1u << (dibp
->vloc
& 0x1F));
662 void mba_upd_sr (uint32 set
, uint32 clr
, uint32 mb
)
664 if (mb
>= MBA_NUM
) return;
665 if (set
& MBASR_ABORTS
) set
|= (MBASR_DTCMP
|MBASR_DTABT
);
666 if (set
& (MBASR_DTCMP
|MBASR_DTABT
)) mba_sr
[mb
] &= ~MBASR_DTBUSY
;
667 mba_sr
[mb
] = (mba_sr
[mb
] | set
) & ~clr
;
668 if ((set
& MBASR_INTR
) && (mba_cr
[mb
] & MBACR_IE
))
670 if ((set
& MBASR_ERRORS
) && (DEBUG_PRI (mba_dev
[mb
], MBA_DEB_ERR
)))
671 fprintf (sim_deb
, ">>MBA%d: CS error = %X\n", mb
, mba_sr
[mb
]);
675 /* Reset Massbus adapter */
677 t_stat
mba_reset (DEVICE
*dptr
)
682 dibp
= (DIB
*) dptr
->ctxt
;
683 if (dibp
== NULL
) return SCPE_IERR
;
684 mb
= dibp
->ba
- TR_MBA0
;
685 if ((mb
< 0) || (mb
>= MBA_NUM
)) return SCPE_IERR
;
687 mba_cr
[mb
] &= MBACR_MNT
;
693 if (sim_switches
& SWMASK ('P')) {
694 for (i
= 0; i
< MBA_NMAPR
; i
++) mba_map
[mb
][i
] = 0;
696 if (mbabort
[mb
]) mbabort
[mb
] (); /* reset device */
700 /* Show Massbus adapter number */
702 t_stat
mba_show_num (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
704 DEVICE
*dptr
= find_dev_from_unit (uptr
);
707 if (dptr
== NULL
) return SCPE_IERR
;
708 dibp
= (DIB
*) dptr
->ctxt
;
709 if (dibp
== NULL
) return SCPE_IERR
;
710 fprintf (st
, "Massbus adapter %d", dibp
->ba
);
714 /* Enable/disable Massbus adapter */
716 void mba_set_enbdis (uint32 mb
, t_bool dis
)
718 if (mb
>= MBA_NUM
) return; /* valid MBA? */
719 if (dis
) mba_dev
[mb
].flags
|= DEV_DIS
;
720 else mba_dev
[mb
].flags
&= ~DEV_DIS
;
724 /* Init Mbus tables */
726 void init_mbus_tab (void)
730 for (i
= 0; i
< MBA_NUM
; i
++) {
738 /* Build dispatch tables */
740 t_stat
build_mbus_tab (DEVICE
*dptr
, DIB
*dibp
)
744 if ((dptr
== NULL
) || (dibp
== NULL
)) return SCPE_IERR
; /* validate args */
745 idx
= dibp
->ba
; /* Mbus # */
746 if (idx
>= MBA_NUM
) return SCPE_STOP
;
747 if ((mbregR
[idx
] && dibp
->rd
&& /* conflict? */
748 (mbregR
[idx
] != dibp
->rd
)) ||
749 (mbregW
[idx
] && dibp
->wr
&&
750 (mbregW
[idx
] != dibp
->wr
)) ||
751 (mbabort
[idx
] && dibp
->ack
[0] &&
752 (mbabort
[idx
] != dibp
->ack
[0]))) {
753 printf ("Massbus %s assignment conflict at %d\n",
754 sim_dname (dptr
), dibp
->ba
);
755 if (sim_log
) fprintf (sim_log
,
756 "Massbus %s assignment conflict at %d\n",
757 sim_dname (dptr
), dibp
->ba
);
760 if (dibp
->rd
) mbregR
[idx
] = dibp
->rd
; /* set rd dispatch */
761 if (dibp
->wr
) mbregW
[idx
] = dibp
->wr
; /* set wr dispatch */
762 if (dibp
->ack
[0]) mbabort
[idx
] = dibp
->ack
[0]; /* set abort dispatch */