First Commit of my working state
[simh.git] / Interdata / id_io.c
1 /* id_io.c: Interdata CPU-independent I/O routines
2
3 Copyright (c) 2001-2006, 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 30-Mar-06 RMS Fixed bug, GO preserves EXA and SSTA (found by Davis Johnson)
27 21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
28
29 Interdata I/O devices are defined by a device information block:
30
31 dno base device number
32 sch selector channel, -1 if none
33 irq interrupt request flag
34 tplte device number template, NULL if one device number
35 iot I/O processing routine
36 ini initialization routine
37
38 Interdata I/O uses the following interconnected tables:
39
40 dev_tab[dev] Indexed by device number, points to the I/O instruction
41 processing routine for the device.
42
43 sch_tab[dev] Indexed by device number, if non-zero, the number + 1
44 of the selector channel used by the device.
45
46 int_req[level] Indexed by interrupt level, device interrupt flags.
47
48 int_enb[level] Indexed by interrupt level, device interrupt enable flags.
49
50 int_tab[idx] Indexed by ((interrupt level * 32) + interrupt number),
51 maps bit positions in int_req to device numbers.
52 */
53
54 #include "id_defs.h"
55
56 /* Selector channel */
57
58 #define SCHC_EXA 0x40 /* read ext addr */
59 #define SCHC_RD 0x20 /* read */
60 #define SCHC_GO 0x10 /* go */
61 #define SCHC_STOP 0x08 /* stop */
62 #define SCHC_SSTA 0x04 /* sel ch status */
63 #define SCHC_EXM 0x03 /* ext mem */
64
65 extern uint32 int_req[INTSZ], int_enb[INTSZ];
66 extern uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout);
67 extern uint32 pawidth;
68 extern UNIT cpu_unit;
69 extern FILE *sim_log;
70 extern DEVICE *sim_devices[];
71
72 uint32 sch_max = 2; /* sch count */
73 uint32 sch_sa[SCH_NUMCH] = { 0 }; /* start addr */
74 uint32 sch_ea[SCH_NUMCH] = { 0 }; /* end addr */
75 uint8 sch_sdv[SCH_NUMCH] = { 0 }; /* device */
76 uint8 sch_cmd[SCH_NUMCH] = { 0 }; /* command */
77 uint8 sch_rdp[SCH_NUMCH] = { 0 }; /* read ptr */
78 uint8 sch_wdc[SCH_NUMCH] = { 0 }; /* write ctr */
79 uint32 sch_tab[DEVNO] = { 0 }; /* dev to sch map */
80 uint32 int_tab[INTSZ * 32] = { 0 }; /* int to dev map */
81 uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */
82
83 uint32 sch (uint32 dev, uint32 op, uint32 dat);
84 void sch_ini (t_bool dtpl);
85 t_stat sch_reset (DEVICE *dptr);
86 t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc);
87 t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc);
88
89 /* Selector channel data structures
90
91 sch_dev channel device descriptor
92 sch_unit channel unit descriptor
93 sch_mod channel modifiers list
94 sch_reg channel register list
95 */
96
97 DIB sch_dib = { d_SCH, -1, v_SCH, sch_tplte, &sch, &sch_ini };
98
99 UNIT sch_unit = { UDATA (NULL, 0, 0) };
100
101 REG sch_reg[] = {
102 { HRDATA (CHAN, sch_max, 3), REG_HRO },
103 { BRDATA (SA, sch_sa, 16, 20, SCH_NUMCH) },
104 { BRDATA (EA, sch_ea, 16, 20, SCH_NUMCH) },
105 { BRDATA (CMD, sch_cmd, 16, 8, SCH_NUMCH) },
106 { BRDATA (DEV, sch_sdv, 16, 8, SCH_NUMCH) },
107 { BRDATA (RDP, sch_rdp, 16, 2, SCH_NUMCH) },
108 { BRDATA (WDC, sch_wdc, 16, 3, SCH_NUMCH) },
109 { GRDATA (IREQ, int_req[l_SCH], 16, SCH_NUMCH, i_SCH) },
110 { GRDATA (IENB, int_enb[l_SCH], 16, SCH_NUMCH, i_SCH) },
111 { HRDATA (DEVNO, sch_dib.dno, 8), REG_HRO },
112 { NULL }
113 };
114
115 MTAB sch_mod[] = {
116 { MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS",
117 &sch_set_nchan, NULL, &sch_reg[0] },
118 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL,
119 NULL, &sch_show_reg, NULL },
120 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL,
121 NULL, &sch_show_reg, NULL },
122 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "2", NULL,
123 NULL, &sch_show_reg, NULL },
124 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "3", NULL,
125 NULL, &sch_show_reg, NULL },
126 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
127 &set_dev, &show_dev, &sch_dib },
128 { 0 }
129 };
130
131 DEVICE sch_dev = {
132 "SELCH", &sch_unit, sch_reg, sch_mod,
133 1, 16, 8, 1, 16, 8,
134 NULL, NULL, &sch_reset,
135 NULL, NULL, NULL,
136 &sch_dib, 0
137 };
138
139 /* (Extended) selector channel
140
141 There are really three different selector channels:
142 - 16b selector channel (max 4B of data)
143 - 18b selector channel (max 4B of data)
144 - 20b selector channel (max 6B of data)
145 The algorithm for loading the start and end addresses is taken
146 from the maintenance manual for the Extended Selector Channel.
147 */
148
149 #define SCH_EXR(ch) ((sch_cmd[ch] & SCHC_EXA) && (pawidth == PAWIDTH32))
150
151 uint32 sch (uint32 dev, uint32 op, uint32 dat)
152 {
153 uint32 t, bank, sdv, ch = dev - sch_dib.dno;
154
155 switch (op) { /* case IO op */
156
157 case IO_ADR: /* select */
158 return BY; /* byte only */
159
160 case IO_RD: /* read data */
161 t = (sch_sa[ch] >> (sch_rdp[ch] * 8)) & DMASK8; /* get sa byte */
162 if (sch_rdp[ch] == 0) sch_rdp[ch] = /* wrap? */
163 SCH_EXR (ch)? 2: 1;
164 else sch_rdp[ch] = sch_rdp[ch] - 1; /* dec byte ptr */
165 return t;
166
167 case IO_WD: /* write data */
168 if (pawidth != PAWIDTH32) { /* 16b? max 4 */
169 if (sch_wdc[ch] >= 4) break; /* stop at 4 */
170 sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea to sa */
171 (sch_ea[ch] >> 8)) & DMASK16;
172 sch_ea[ch] = ((sch_ea[ch] << 8) | /* ripple ea low */
173 dat) & DMASK16; /* insert byte */
174 }
175 else { /* 32b? max 6 */
176 if (sch_wdc[ch] >= 6) break; /* stop at 6 */
177 if (sch_wdc[ch] != 5) { /* if not last */
178 sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea<15:8> to sa */
179 ((sch_ea[ch] >> 8) & DMASK8)) & PAMASK32;
180 sch_ea[ch] = /* ripple ea<7:0> */
181 (((sch_ea[ch] & DMASK8) << 8) | dat) & PAMASK32;
182 }
183 else sch_ea[ch] = ((sch_ea[ch] << 8) | dat) & PAMASK32;
184 }
185 sch_wdc[ch] = sch_wdc[ch] + 1; /* adv sequencer */
186 break;
187
188 case IO_SS: /* status */
189 if (sch_cmd[ch] & SCHC_GO) return STA_BSY; /* test busy */
190 if (sch_cmd[ch] & SCHC_SSTA) return 0; /* test sch sta */
191 else {
192 sdv = sch_sdv[ch]; /* get dev */
193 if (dev_tab[sdv] == 0) return CC_V; /* not there? */
194 dev_tab[sdv] (sdv, IO_ADR, 0); /* select dev */
195 t = dev_tab[sdv] (sdv, IO_SS, 0); /* get status */
196 return t & ~STA_BSY; /* clr busy */
197 }
198
199 case IO_OC: /* command */
200 bank = 0; /* assume no bank */
201 if (pawidth != PAWIDTH32) { /* 16b/18b proc? */
202 dat = dat & ~(SCHC_EXA | SCHC_SSTA); /* clr ext func */
203 if (pawidth == PAWIDTH16E) /* 18b proc? */
204 bank = (dat & SCHC_EXM) << 16;
205 }
206 if (dat & SCHC_STOP) { /* stop? */
207 sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA); /* clr go */
208 CLR_INT (v_SCH + ch); /* clr intr */
209 sch_rdp[ch] = SCH_EXR (ch)? 2: 1; /* init sequencers */
210 sch_wdc[ch] = 0;
211 }
212 else if (dat & SCHC_GO) { /* go? */
213 sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA| SCHC_GO | SCHC_RD);
214 if (sch_wdc[ch] <= 4) { /* 4 bytes? */
215 sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */
216 sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank;
217 }
218 sch_sa[ch] = sch_sa[ch] & ~1;
219 if (sch_ea[ch] <= sch_sa[ch]) /* wrap? */
220 sch_ea[ch] = sch_ea[ch] | /* modify end addr */
221 ((pawidth == PAWIDTH32)? PAMASK32: PAMASK16);
222 }
223 break;
224 }
225
226 return 0;
227 }
228
229 /* CPU call to test if channel blocks access to device */
230
231 t_bool sch_blk (uint32 dev)
232 {
233 uint32 ch = sch_tab[dev] - 1;
234
235 if ((ch < sch_max) && (sch_cmd[ch] & SCHC_GO)) return TRUE;
236 return FALSE;
237 }
238
239 /* Device call to 'remember' last dev on channel */
240
241 void sch_adr (uint32 ch, uint32 dev)
242 {
243 if (ch < sch_max) sch_sdv[ch] = dev;
244 return;
245 }
246
247 /* Device call to see if selector channel is active for device */
248
249 t_bool sch_actv (uint32 ch, uint32 dev)
250 {
251 if ((ch < sch_max) && /* chan valid, */
252 (sch_cmd[ch] & SCHC_GO) && /* on, and */
253 (sch_sdv[ch] == dev)) return TRUE; /* set for dev? */
254 return FALSE; /* no */
255 }
256
257 /* Device call to read a block of memory */
258
259 uint32 sch_rdmem (uint32 ch, uint8 *buf, uint32 cnt)
260 {
261 uint32 addr, end, xfr, inc;
262
263 if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0;
264 addr = sch_sa[ch]; /* start */
265 end = sch_ea[ch]; /* end */
266 xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
267 inc = IOReadBlk (addr, xfr, buf); /* read mem */
268 if ((addr + inc) > end) { /* end? */
269 SET_INT (v_SCH + ch); /* interrupt */
270 sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
271 sch_sa[ch] = sch_sa[ch] + inc - 1; /* end addr */
272 }
273 else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
274 return inc;
275 }
276
277 /* Device call to write a block of memory */
278
279 uint32 sch_wrmem (uint32 ch, uint8 *buf, uint32 cnt)
280 {
281 uint32 addr, end, xfr, inc;
282
283 if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0;
284 addr = sch_sa[ch]; /* start */
285 end = sch_ea[ch]; /* end */
286 xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
287 inc = IOWriteBlk (addr, xfr, buf); /* write mem */
288 if ((addr + inc) > end) { /* end? */
289 SET_INT (v_SCH + ch); /* interrupt */
290 sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
291 sch_sa[ch] = sch_sa[ch] + inc - 1; /* end addr */
292 }
293 else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
294 return inc;
295 }
296
297 /* Device call to stop a selector channel */
298
299 void sch_stop (uint32 ch)
300 {
301 if (ch < sch_max) {
302 SET_INT (v_SCH + ch); /* interrupt */
303 sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
304 }
305 return;
306 }
307
308 /* Reset */
309
310 void sch_reset_ch (uint32 rst_lim)
311 {
312 uint32 ch;
313
314 for (ch = 0; ch < SCH_NUMCH; ch++) {
315 if (ch >= rst_lim) {
316 CLR_INT (v_SCH + ch);
317 SET_ENB (v_SCH + ch);
318 sch_sa[ch] = sch_ea[ch] = 0;
319 sch_cmd[ch] = sch_sdv[ch] = 0;
320 sch_wdc[ch] = 0;
321 sch_rdp[ch] = 1;
322 }
323 }
324 return;
325 }
326
327 t_stat sch_reset (DEVICE *dptr)
328 {
329 sch_reset_ch (0); /* reset all chan */
330 return SCPE_OK;
331 }
332
333 /* Set number of channels */
334
335 t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc)
336 {
337 DEVICE *dptr;
338 DIB *dibp;
339 uint32 i, newmax;
340 t_stat r;
341
342 if (cptr == NULL) return SCPE_ARG;
343 newmax = get_uint (cptr, 10, SCH_NUMCH, &r); /* get new max */
344 if ((r != SCPE_OK) || (newmax == sch_max)) return r; /* err or no chg? */
345 if (newmax == 0) return SCPE_ARG; /* must be > 0 */
346 if (newmax < sch_max) { /* reducing? */
347 for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */
348 dibp = (DIB *) dptr->ctxt; /* get DIB */
349 if (dibp && (dibp->sch >= (int32) newmax)) { /* dev using chan? */
350 printf ("Device %02X uses channel %d\n",
351 dibp->dno, dibp->sch);
352 if (sim_log) fprintf (sim_log, "Device %02X uses channel %d\n",
353 dibp->dno, dibp->sch);
354 return SCPE_OK;
355 }
356 }
357 }
358 sch_max = newmax; /* set new max */
359 sch_reset_ch (sch_max); /* reset chan */
360 return SCPE_OK;
361 }
362
363 /* Show channel registers */
364
365 t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc)
366 {
367 if (val < 0) return SCPE_IERR;
368 if (val >= (int32) sch_max) fprintf (st, "Channel %d disabled\n", val);
369 else {
370 fprintf (st, "SA: %05X\n", sch_sa[val]);
371 fprintf (st, "EA: %05X\n", sch_ea[val]);
372 fprintf (st, "CMD: %02X\n", sch_cmd[val]);
373 fprintf (st, "DEV: %02X\n", sch_sdv[val]);
374 fprintf (st, "RDP: %X\n", sch_rdp[val]);
375 fprintf (st, "WDC: %X\n", sch_wdc[val]);
376 }
377 return SCPE_OK;
378 }
379
380 /* Initialize template */
381
382 void sch_ini (t_bool dtpl)
383 {
384 uint32 i;
385
386 for (i = 0; i < sch_max; i++) sch_tplte[i] = i;
387 sch_tplte[sch_max] = TPL_END;
388 return;
389 }
390
391 /* Evaluate interrupt */
392
393 void int_eval (void)
394 {
395 int i;
396 extern uint32 qevent;
397
398 for (i = 0; i < INTSZ; i++) {
399 if (int_req[i] & int_enb[i]) {
400 qevent = qevent | EV_INT;
401 return;
402 }
403 }
404 qevent = qevent & ~EV_INT;
405 return;
406 }
407
408 /* Return interrupting device */
409
410 uint32 int_getdev (void)
411 {
412 int32 i, j, t;
413 uint32 r;
414
415 for (i = t = 0; i < INTSZ; i++) { /* loop thru array */
416 if (r = int_req[i] & int_enb[i]) { /* find nz int wd */
417 for (j = 0; j < 32; t++, j++) {
418 if (r & (1u << j)) {
419 int_req[i] = int_req[i] & ~(1u << j); /* clr request */
420 return int_tab[t];
421 }
422 }
423 }
424 else t = t + 32;
425 }
426 return 0;
427 }
428
429 /* Update device interrupt status */
430
431 int32 int_chg (uint32 irq, int32 dat, int32 armdis)
432 {
433 int32 t = CMD_GETINT (dat); /* get int ctrl */
434
435 if (t == CMD_IENB) { /* enable? */
436 SET_ENB (irq);
437 return 1;
438 }
439 else if (t == CMD_IDIS) { /* disable? */
440 CLR_ENB (irq);
441 return 1;
442 }
443 if (t == CMD_IDSA) { /* disarm? */
444 CLR_ENB (irq);
445 CLR_INT (irq);
446 return 0;
447 }
448 return armdis;
449 }
450
451 /* Process a 2b field and return unchanged, set, clear, complement */
452
453 int32 io_2b (int32 val, int32 pos, int32 old)
454 {
455 int32 t = (val >> pos) & 3;
456 if (t == 0) return old;
457 if (t == 1) return 1;
458 if (t == 2) return 0;
459 return old ^1;
460 }
461
462 /* Block transfer routines */
463
464 uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf)
465 {
466 uint32 i;
467
468 if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0;
469 if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc;
470 for (i = 0; i < cnt; i++) buf[i] = IOReadB (loc + i);
471 return cnt;
472 }
473
474 uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf)
475 {
476 uint32 i;
477
478 if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0;
479 if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc;
480 for (i = 0; i < cnt; i++) IOWriteB (loc + i, buf[i]);
481 return cnt;
482 }
483
484 /* Change selector channel for a device */
485
486 t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc)
487 {
488 DEVICE *dptr;
489 DIB *dibp;
490 uint32 newch;
491 t_stat r;
492
493 if (cptr == NULL) return SCPE_ARG;
494 if (uptr == NULL) return SCPE_IERR;
495 dptr = find_dev_from_unit (uptr);
496 if (dptr == NULL) return SCPE_IERR;
497 dibp = (DIB *) dptr->ctxt;
498 if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR;
499 newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */
500 if (r != SCPE_OK) return r;
501 dibp->sch = newch; /* store */
502 return SCPE_OK;
503 }
504
505 /* Show selector channel for a device */
506
507 t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc)
508 {
509 DEVICE *dptr;
510 DIB *dibp;
511
512 if (uptr == NULL) return SCPE_IERR;
513 dptr = find_dev_from_unit (uptr);
514 if (dptr == NULL) return SCPE_IERR;
515 dibp = (DIB *) dptr->ctxt;
516 if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR;
517 fprintf (st, "selch=%X", dibp->sch);
518 return SCPE_OK;
519 }
520
521 /* Change device number for a device */
522
523 t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc)
524 {
525 DEVICE *dptr;
526 DIB *dibp;
527 uint32 newdev;
528 t_stat r;
529
530 if (cptr == NULL) return SCPE_ARG;
531 if (uptr == NULL) return SCPE_IERR;
532 dptr = find_dev_from_unit (uptr);
533 if (dptr == NULL) return SCPE_IERR;
534 dibp = (DIB *) dptr->ctxt;
535 if (dibp == NULL) return SCPE_IERR;
536 newdev = get_uint (cptr, 16, DEV_MAX, &r); /* get new */
537 if ((r != SCPE_OK) || (newdev == dibp->dno)) return r;
538 if (newdev == 0) return SCPE_ARG; /* must be > 0 */
539 dibp->dno = newdev; /* store */
540 return SCPE_OK;
541 }
542
543 /* Show device number for a device */
544
545 t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc)
546 {
547 DEVICE *dptr;
548 DIB *dibp;
549
550 if (uptr == NULL) return SCPE_IERR;
551 dptr = find_dev_from_unit (uptr);
552 if (dptr == NULL) return SCPE_IERR;
553 dibp = (DIB *) dptr->ctxt;
554 if ((dibp == NULL) || (dibp->dno == 0)) return SCPE_IERR;
555 fprintf (st, "devno=%02X", dibp->dno);
556 return SCPE_OK;
557 }
558
559 /* Init device tables */
560
561 t_bool devtab_init (void)
562 {
563 DEVICE *dptr;
564 DIB *dibp;
565 uint32 i, j, dno, dmsk, doff, t, dmap[DEVNO / 32];
566 uint8 *tplte, dflt_tplte[] = { 0, TPL_END };
567
568 /* Clear tables, device map */
569
570 for (i = 0; i < DEVNO; i++) {
571 dev_tab[i] = NULL;
572 sch_tab[i] = 0;
573 }
574 for (i = 0; i < (INTSZ * 32); i++) int_tab[i] = 0;
575 for (i = 0; i < (DEVNO / 32); i++) dmap[i] = 0;
576
577 /* Test each device for conflict; add to map; init tables */
578
579 for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */
580 dibp = (DIB *) dptr->ctxt; /* get DIB */
581 if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */
582 dno = dibp->dno; /* get device num */
583 if (dibp->ini) dibp->ini (TRUE); /* gen dno template */
584 tplte = dibp->tplte; /* get template */
585 if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
586 for ( ; *tplte != TPL_END; tplte++) { /* loop thru template */
587 t = (dno + *tplte) & DEV_MAX; /* loop thru template */
588 dmsk = 1u << (t & 0x1F); /* bit to test */
589 doff = t / 32; /* word to test */
590 if (dmap[doff] & dmsk) { /* in use? */
591 printf ("Device number conflict, devno = %02X\n", t);
592 if (sim_log) fprintf (sim_log,
593 "Device number conflict, devno = %02X\n", t);
594 return TRUE;
595 }
596 dmap[doff] = dmap[doff] | dmsk;
597 if (dibp->sch >= 0) sch_tab[t] = dibp->sch + 1;
598 dev_tab[t] = dibp->iot;
599 }
600 if (dibp->ini) dibp->ini (FALSE); /* gen int template */
601 tplte = dibp->tplte; /* get template */
602 if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
603 for (j = dibp->irq; *tplte != TPL_END; j++, tplte++)
604 int_tab[j] = (dno + *tplte) & DEV_MAX;
605 } /* end for i */
606 return FALSE;
607 }