Commit | Line | Data |
---|---|---|
2e73d674 | 1 | /* |
c0441c16 KB |
2 | * Copyright (c) 1988 Regents of the University of California. |
3 | * All rights reserved. | |
2e73d674 | 4 | * |
1326eec7 | 5 | * %sccs.include.redist.c% |
2e73d674 | 6 | * |
b28b3a13 | 7 | * @(#)qdcons.c 7.5 (Berkeley) %G% |
c0441c16 KB |
8 | */ |
9 | ||
10 | /* | |
2e73d674 MT |
11 | * derived from: @(#)qdcons.c 4.1 (ULTRIX 11/23/87 |
12 | */ | |
13 | ||
14 | /************************************************************************ | |
15 | * | |
16 | * ULTRIX QDSS STANDALONE BOOT DEVICE DRIVER... | |
17 | * device driver to boot system with QDSS as console | |
18 | * | |
19 | *************************************************************************/ | |
20 | /************************************************************************ | |
21 | * * | |
22 | * Copyright (c) 1985 by * | |
23 | * Digital Equipment Corporation, Maynard, MA * | |
24 | * All rights reserved. * | |
25 | * * | |
26 | * This software is furnished under a license and may be used and * | |
27 | * copied only in accordance with the terms of such license and * | |
28 | * with the inclusion of the above copyright notice. This * | |
29 | * software or any other copies thereof may not be provided or * | |
30 | * otherwise made available to any other person. No title to and * | |
31 | * ownership of the software is hereby transferred. * | |
32 | * * | |
33 | * The information in this software is subject to change without * | |
34 | * notice and should not be construed as a commitment by Digital * | |
35 | * Equipment Corporation. * | |
36 | * * | |
37 | * Digital assumes no responsibility for the use or reliability * | |
38 | * of its software on equipment which is not supplied by Digital. * | |
39 | * * | |
40 | ************************************************************************* | |
253bb020 | 41 | * revision history: (should be moved into sccs comments) |
2e73d674 MT |
42 | ************************************************************************* |
43 | * | |
44 | * 09 oct 85 longo added uVAXII console ROM cursor reset to bottom of | |
45 | * the screen. Also spruced up qdputc() & scroll_up() | |
46 | * 02 oct 85 longo changed references to ADDRESS to be ADDRESS_COMPLETE | |
47 | * 23 aug 85 longo changed I/O page CSR address to be 0x1F00 | |
48 | * 20 aug 85 longo created | |
49 | * | |
50 | ************************************************************************/ | |
51 | ||
b28b3a13 KB |
52 | #include "sys/types.h" |
53 | #include "../include/cpu.h" | |
2e73d674 | 54 | #define KERNEL |
b28b3a13 KB |
55 | #include "../uba/qdioctl.h" |
56 | #include "../uba/qevent.h" | |
57 | #include "../uba/qduser.h" | |
58 | #include "../uba/qdreg.h" | |
2e73d674 MT |
59 | #undef KERNEL |
60 | ||
61 | /*----------------------------------------------------------------------- | |
62 | * constants used to set VAX ROM's cursor to bottom the of the screen */ | |
63 | ||
64 | #define NVR_ADRS 0x200B8024 | |
65 | ||
66 | #define CURRENT_ROW 0x4C /* these are offsets to the ROM's scratch.. */ | |
67 | #define ROW_MIN 0x4D /* ..RAM start adrs as picked up out of NVR */ | |
68 | #define ROW_MAX 0x4E | |
69 | #define CURRENT_COL 0x50 | |
70 | #define COL_MIN 0x51 | |
71 | #define COL_MAX 0x52 | |
72 | ||
73 | /*---------------------------------------- | |
74 | * LK201 keyboard state tracking struct */ | |
75 | ||
76 | struct q_keyboard { | |
77 | ||
78 | int shift; /* state variables */ | |
79 | int cntrl; | |
80 | int lock; | |
81 | char last; /* last character */ | |
82 | ||
83 | } q_keyboard; | |
84 | ||
85 | int qdputc(), qdgetc(); | |
86 | ||
87 | extern (*v_putc)(),(*v_getc)(); | |
88 | ||
89 | /*---------------------------- | |
90 | * general purpose defines */ | |
91 | ||
92 | #define BAD -1 | |
93 | #define GOOD 0 | |
94 | ||
95 | /*---------------------------------------------- | |
96 | * console cursor bitmap (block cursor type) */ | |
97 | ||
98 | short cons_cursor[32] = { /* white block cursor */ | |
99 | ||
100 | /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, | |
101 | 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, | |
102 | /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, | |
103 | 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF | |
104 | ||
105 | }; | |
106 | ||
107 | /*------------------------------------- | |
108 | * constants used in font operations */ | |
109 | ||
110 | #define CHARS 95 /* # of chars in the font */ | |
111 | #define CHAR_HEIGHT 15 /* char height in pixels */ | |
112 | #define CHAR_WIDTH 8 /* char width in pixels*/ | |
113 | #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ | |
114 | #define ROWS CHAR_HEIGHT | |
115 | ||
116 | #define FONT_X 0 /* font's off screen adrs */ | |
117 | #define FONT_Y (2047 - CHAR_HEIGHT) | |
118 | /* | |
119 | #define FONT_Y 200 | |
120 | */ | |
121 | ||
122 | extern char q_font[]; /* reference font object code */ | |
123 | ||
124 | extern char q_key[]; /* reference key xlation tables */ | |
125 | extern char q_shift_key[]; | |
126 | extern char *q_special[]; | |
127 | ||
128 | /*---------------------------- | |
129 | * console cursor structure */ | |
130 | ||
131 | struct cons_cur { | |
132 | int x; | |
133 | int y; | |
134 | } cursor; | |
135 | ||
136 | /*------------------------------------------ | |
137 | * MicroVAX-II q-bus addressing constants */ | |
138 | ||
139 | #define QMEMBASE 0x30000000 | |
140 | #define QDSSCSR 0x20001F00 | |
141 | ||
142 | #define CHUNK (64 * 1024) | |
143 | #define QMEMSIZE (1024 * 1024 * 4) | |
144 | #define QDBASE (QMEMBASE + QMEMSIZE - CHUNK) | |
145 | ||
146 | /*------------------------------------------------------------------ | |
147 | * QDSS register address offsets from start of QDSS address space */ | |
148 | ||
149 | #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ | |
150 | ||
151 | #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ | |
152 | #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ | |
153 | ||
154 | #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ | |
155 | #define REGSTART 0xC000 /* offset of reg pages from base adrs */ | |
156 | ||
157 | #define ADDER (REGSTART+0x000) | |
158 | #define DGA (REGSTART+0x200) | |
159 | #define DUART (REGSTART+0x400) | |
160 | #define MEMCSR (REGSTART+0x800) | |
161 | ||
162 | #define CLRSIZE (3 * 512) /* color map size */ | |
163 | #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ | |
164 | /* 0x0C00 really */ | |
165 | #define RED (CLRSTART+0x000) | |
166 | #define BLUE (CLRSTART+0x200) | |
167 | #define GREEN (CLRSTART+0x400) | |
168 | ||
169 | /*--------------------------------------- | |
170 | * QDSS register address map structure */ | |
171 | ||
172 | struct qdmap qdmap; | |
173 | ||
174 | /************************************************************************ | |
175 | ************************************************************************* | |
176 | ************************************************************************* | |
177 | * | |
178 | * EXTERNALLY CALLED ROUTINES START HERE: | |
179 | * | |
180 | ************************************************************************* | |
181 | ************************************************************************* | |
182 | ************************************************************************/ | |
183 | ||
184 | /************************************************************************ | |
185 | * | |
186 | * qd_init()... init the QDSS into a physical memory system | |
187 | * | |
188 | ************************************************************************/ | |
189 | ||
190 | qd_init() | |
191 | { | |
192 | register char *ROM_console; | |
193 | register short *NVR; | |
194 | register int i; | |
195 | ||
196 | caddr_t qdaddr; | |
197 | struct dga *dga; | |
f6322301 | 198 | extern int cpu; |
2e73d674 MT |
199 | |
200 | qdaddr = (caddr_t) QDSSCSR; | |
201 | if (badaddr(qdaddr, sizeof(short))) | |
202 | return(0); | |
203 | ||
204 | *(short *)qdaddr = (short) (QDBASE >> 16); | |
205 | ||
206 | /*---------------------------------------------------------------------- | |
207 | * load qdmap struct with the physical addresses of the QDSS elements */ | |
208 | ||
209 | qdmap.template = (caddr_t) QDBASE + TMPSTART; | |
210 | qdmap.adder = (caddr_t) QDBASE + ADDER; | |
211 | qdmap.dga = (caddr_t) QDBASE + DGA; | |
212 | qdmap.duart = (caddr_t) QDBASE + DUART; | |
213 | qdmap.memcsr = (caddr_t) QDBASE + MEMCSR; | |
214 | qdmap.red = (caddr_t) QDBASE + RED; | |
215 | qdmap.blue = (caddr_t) QDBASE + BLUE; | |
216 | qdmap.green = (caddr_t) QDBASE + GREEN; | |
217 | ||
218 | /*-------------------------- | |
219 | * no interrupts allowed! */ | |
220 | ||
221 | dga = (struct dga *) qdmap.dga; | |
222 | dga->csr = HALT; | |
223 | dga->csr |= CURS_ENB; | |
224 | ||
225 | /*---------------------------- | |
226 | * init the default values */ | |
227 | ||
228 | q_keyboard.shift = 0; /* init keyboard state tracking */ | |
229 | q_keyboard.lock = 0; | |
230 | q_keyboard.cntrl = 0; | |
231 | q_keyboard.last = 0; | |
232 | ||
233 | cursor.x = 0; /* init cursor to top left */ | |
234 | cursor.y = 0; | |
235 | ||
236 | set_defaults(); /* setup the default device */ | |
237 | ldfont(); /* PtoB the font into off-screen */ | |
238 | ||
239 | /*-------------------------------------------------------------------- | |
240 | * tell the VAX ROM that the cursor is at the bottom of the screen */ | |
241 | ||
f6322301 TF |
242 | if (cpu == VAX_630) { |
243 | NVR = (short *) NVR_ADRS; | |
2e73d674 | 244 | |
f6322301 TF |
245 | i = *NVR++ & 0xFF; |
246 | i |= (*NVR++ & 0xFF) << 8; | |
247 | i |= (*NVR++ & 0xFF) << 16; | |
248 | i |= (*NVR++ & 0xFF) << 24; | |
2e73d674 | 249 | |
f6322301 | 250 | ROM_console = (char *) i; |
2e73d674 | 251 | |
f6322301 TF |
252 | ROM_console[CURRENT_COL] = ROM_console[COL_MIN]; |
253 | ROM_console[CURRENT_ROW] = ROM_console[ROW_MAX]; | |
254 | } | |
2e73d674 MT |
255 | |
256 | /*---------------------------------------------------------- | |
257 | * smash system virtual console service routine addresses */ | |
258 | ||
f6322301 | 259 | printf("switching console to QDSS display...\n"); |
2e73d674 MT |
260 | v_getc = qdgetc; |
261 | v_putc = qdputc; | |
262 | ||
263 | return(1); | |
264 | ||
265 | } /* qd_init */ | |
266 | ||
267 | /******************************************************************* | |
268 | * | |
269 | * qdputc()... output a character to the QDSS screen | |
270 | * | |
271 | ******************************************************************** | |
272 | * | |
273 | * calling convention: | |
274 | * | |
275 | * qdputc(chr); | |
276 | * char chr; ;character to be displayed | |
277 | * | |
278 | ********/ | |
279 | ||
280 | qdputc(chr) | |
281 | char chr; | |
282 | { | |
283 | register struct adder *adder; | |
284 | register struct dga *dga; | |
285 | register int i; | |
286 | ||
287 | short x; | |
288 | ||
289 | adder = (struct adder *) qdmap.adder; | |
290 | dga = (struct dga *) qdmap.dga; | |
291 | ||
292 | /*--------------------------- | |
293 | * non display character? */ | |
294 | ||
295 | chr &= 0x7F; | |
296 | ||
297 | switch (chr) { | |
298 | ||
299 | case '\r': /* return char */ | |
300 | cursor.x = 0; | |
301 | dga->x_cursor = TRANX(cursor.x); | |
302 | return(0); | |
303 | ||
304 | case '\t': /* tab char */ | |
305 | ||
306 | for (i = 8 - ((cursor.x >> 3) & 0x07); i > 0; --i) { | |
307 | qdputc(' '); | |
308 | } | |
309 | return(0); | |
310 | ||
311 | case '\n': /* line feed char */ | |
312 | ||
313 | if ((cursor.y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { | |
314 | cursor.y -= CHAR_HEIGHT; | |
315 | scroll_up(adder); | |
316 | } | |
317 | dga->y_cursor = TRANY(cursor.y); | |
318 | return(0); | |
319 | ||
320 | case '\b': /* backspace char */ | |
321 | if (cursor.x > 0) { | |
322 | cursor.x -= CHAR_WIDTH; | |
323 | qdputc(' '); | |
324 | cursor.x -= CHAR_WIDTH; | |
325 | dga->x_cursor = TRANX(cursor.x); | |
326 | } | |
327 | return(0); | |
328 | ||
329 | default: | |
330 | if (chr < ' ' || chr > '~') { | |
331 | return(0); | |
332 | } | |
333 | } | |
334 | ||
335 | /*------------------------------------------ | |
336 | * setup VIPER operand control registers */ | |
337 | ||
338 | write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ | |
339 | write_ID(adder, SRC1_OCR_B, | |
340 | EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); | |
341 | ||
342 | write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ | |
343 | write_ID(adder, SRC1_OCR_B, | |
344 | EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); | |
345 | ||
346 | write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ | |
347 | write_ID(adder, DST_OCR_B, | |
348 | EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); | |
349 | ||
350 | write_ID(adder, MASK_1, 0xFFFF); | |
351 | write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); | |
352 | write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); | |
353 | ||
354 | /*---------------------------------------- | |
355 | * load DESTINATION origin and vectors */ | |
356 | ||
357 | adder->fast_dest_dy = 0; | |
358 | adder->slow_dest_dx = 0; | |
359 | adder->error_1 = 0; | |
360 | adder->error_2 = 0; | |
361 | ||
362 | adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; | |
363 | ||
364 | wait_status(adder, RASTEROP_COMPLETE); | |
365 | ||
366 | adder->destination_x = cursor.x; | |
367 | adder->fast_dest_dx = CHAR_WIDTH; | |
368 | ||
369 | adder->destination_y = cursor.y; | |
370 | adder->slow_dest_dy = CHAR_HEIGHT; | |
371 | ||
372 | /*----------------------------------- | |
373 | * load SOURCE origin and vectors */ | |
374 | ||
375 | adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH); | |
376 | adder->source_1_y = FONT_Y; | |
377 | ||
378 | adder->source_1_dx = CHAR_WIDTH; | |
379 | adder->source_1_dy = CHAR_HEIGHT; | |
380 | ||
381 | write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); | |
382 | adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; | |
383 | ||
384 | /*------------------------------------- | |
385 | * update console cursor coordinates */ | |
386 | ||
387 | cursor.x += CHAR_WIDTH; | |
388 | dga->x_cursor = TRANX(cursor.x); | |
389 | ||
390 | if (cursor.x > (1024 - CHAR_WIDTH)) { | |
391 | qdputc('\r'); | |
392 | qdputc('\n'); | |
393 | } | |
394 | ||
395 | } /* qdputc */ | |
396 | ||
397 | /******************************************************************* | |
398 | * | |
399 | * qdgetc()... get a character from the LK201 | |
400 | * | |
401 | *******************************************************************/ | |
402 | ||
403 | qdgetc() | |
404 | { | |
405 | register short key; | |
406 | register char chr; | |
407 | register struct duart *duart; | |
408 | ||
409 | u_int status; | |
410 | ||
411 | duart = (struct duart *) qdmap.duart; | |
412 | ||
413 | /*-------------------------------------- | |
414 | * Get a character from the keyboard. */ | |
415 | ||
416 | LOOP: | |
417 | while (!((status = duart->statusA) & RCV_RDY)) | |
418 | ; | |
419 | ||
420 | key = duart->dataA; | |
421 | key &= 0xFF; | |
422 | ||
423 | /*-------------------------------------- | |
424 | * Check for various keyboard errors */ | |
425 | ||
426 | if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || | |
427 | key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { | |
428 | printf("Keyboard error, code = %x\n", key); | |
429 | return(0); | |
430 | } | |
431 | ||
432 | if (key < LK_LOWEST) | |
433 | return(0); | |
434 | ||
435 | /*--------------------------------- | |
436 | * See if its a state change key */ | |
437 | ||
438 | switch (key) { | |
439 | ||
440 | case LOCK: | |
441 | q_keyboard.lock ^= 0xffff; /* toggle */ | |
442 | if (q_keyboard.lock) | |
443 | led_control(LK_LED_ENABLE, LK_LED_LOCK); | |
444 | else | |
445 | led_control(LK_LED_DISABLE, LK_LED_LOCK); | |
446 | goto LOOP; | |
447 | ||
448 | case SHIFT: | |
449 | q_keyboard.shift ^= 0xFFFF; | |
450 | goto LOOP; | |
451 | ||
452 | case CNTRL: | |
453 | q_keyboard.cntrl ^= 0xFFFF; | |
454 | goto LOOP; | |
455 | ||
456 | case ALLUP: | |
457 | q_keyboard.cntrl = 0; | |
458 | q_keyboard.shift = 0; | |
459 | goto LOOP; | |
460 | ||
461 | case REPEAT: | |
462 | chr = q_keyboard.last; | |
463 | break; | |
464 | ||
465 | /*------------------------------------------------------- | |
466 | * Test for cntrl characters. If set, see if the character | |
467 | * is elligible to become a control character. */ | |
468 | ||
469 | default: | |
470 | ||
471 | if (q_keyboard.cntrl) { | |
472 | chr = q_key[key]; | |
473 | if (chr >= ' ' && chr <= '~') | |
474 | chr &= 0x1F; | |
475 | } | |
476 | else if ( q_keyboard.lock || q_keyboard.shift ) | |
477 | chr = q_shift_key[key]; | |
478 | else | |
479 | chr = q_key[key]; | |
480 | break; | |
481 | } | |
482 | ||
483 | if (chr < ' ' && chr > '~') /* if input is non-displayable */ | |
484 | return(0); /* ..then pitch it! */ | |
485 | ||
486 | q_keyboard.last = chr; | |
487 | ||
488 | /*----------------------------------- | |
489 | * Check for special function keys */ | |
490 | ||
491 | if (chr & 0x80) /* pitch the function keys */ | |
492 | return(0); | |
493 | else | |
494 | return(chr); | |
495 | ||
496 | } /* qdgetc */ | |
497 | ||
498 | /************************************************************************ | |
499 | ************************************************************************* | |
500 | ************************************************************************* | |
501 | * | |
502 | * INTERNALLY USED ROUTINES START HERE: | |
503 | * | |
504 | ************************************************************************* | |
505 | ************************************************************************* | |
506 | ************************************************************************/ | |
507 | ||
508 | /******************************************************************** | |
509 | * | |
510 | * ldcursor()... load the mouse cursor's template RAM bitmap | |
511 | * | |
512 | ********************************************************************/ | |
513 | ||
514 | ldcursor() | |
515 | { | |
516 | register struct dga *dga; | |
517 | register short *temp; | |
518 | register int i; | |
519 | ||
520 | int cursor; | |
521 | ||
522 | dga = (struct dga *) qdmap.dga; | |
523 | temp = (short *) qdmap.template; | |
524 | ||
525 | temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ | |
526 | /* ..of the 8k WORD template space */ | |
527 | for (i = 0; i < 32; ++i) | |
528 | *temp++ = cons_cursor[i]; | |
529 | ||
530 | return(0); | |
531 | ||
532 | } /* ldcursor */ | |
533 | ||
534 | /********************************************************************** | |
535 | * | |
536 | * ldfont()... put the console font in the QDSS off-screen memory | |
537 | * | |
538 | **********************************************************************/ | |
539 | ||
540 | ldfont() | |
541 | { | |
542 | register struct adder *adder; | |
543 | ||
544 | int i; /* scratch variables */ | |
545 | int j; | |
546 | int k; | |
547 | short packed; | |
548 | ||
549 | adder = (struct adder *) qdmap.adder; | |
550 | ||
551 | /*------------------------------------------ | |
552 | * setup VIPER operand control registers */ | |
553 | ||
554 | write_ID(adder, MASK_1, 0xFFFF); | |
555 | write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); | |
556 | write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); | |
557 | ||
558 | write_ID(adder, SRC1_OCR_B, | |
559 | EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); | |
560 | write_ID(adder, SRC2_OCR_B, | |
561 | EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); | |
562 | write_ID(adder, DST_OCR_B, | |
563 | EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); | |
564 | ||
565 | adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; | |
566 | ||
567 | /*-------------------------- | |
568 | * load destination data */ | |
569 | ||
570 | wait_status(adder, RASTEROP_COMPLETE); | |
571 | ||
572 | adder->destination_x = FONT_X; | |
573 | adder->destination_y = FONT_Y; | |
574 | adder->fast_dest_dx = FONT_WIDTH; | |
575 | adder->slow_dest_dy = CHAR_HEIGHT; | |
576 | ||
577 | /*--------------------------------------- | |
578 | * setup for processor to bitmap xfer */ | |
579 | ||
580 | write_ID(adder, CS_UPDATE_MASK, 0x0001); | |
581 | adder->cmd = PBT | OCRB | 2 | DTE | 2; | |
582 | ||
583 | /*----------------------------------------------- | |
584 | * iteratively do the processor to bitmap xfer */ | |
585 | ||
586 | for (i = 0; i < ROWS; ++i) { | |
587 | ||
588 | /* PTOB a scan line */ | |
589 | ||
590 | for (j = 0, k = i; j < 48; ++j) { | |
591 | ||
592 | /* PTOB one scan of a char cell */ | |
593 | ||
594 | packed = q_font[k]; | |
595 | k += ROWS; | |
596 | packed |= ((short)q_font[k] << 8); | |
597 | k += ROWS; | |
598 | ||
599 | wait_status(adder, TX_READY); | |
600 | adder->id_data = packed; | |
601 | } | |
602 | } | |
603 | ||
604 | } /* ldfont */ | |
605 | ||
606 | /********************************************************************* | |
607 | * | |
608 | * led_control()... twiddle LK-201 LED's | |
609 | * | |
610 | ********************************************************************** | |
611 | * | |
612 | * led_control(cmd, led_mask); | |
613 | * int cmd; LED enable/disable command | |
614 | * int led_mask; which LED(s) to twiddle | |
615 | * | |
616 | *************/ | |
617 | ||
618 | led_control(cmd, led_mask) | |
619 | int cmd; | |
620 | int led_mask; | |
621 | { | |
622 | register int i; | |
623 | register int status; | |
624 | register struct duart *duart; | |
625 | ||
626 | duart = (struct duart *) qdmap.duart; | |
627 | ||
628 | for (i = 1000; i > 0; --i) { | |
629 | if ((status = duart->statusA) & XMT_RDY) { | |
630 | duart->dataA = cmd; | |
631 | break; | |
632 | } | |
633 | } | |
634 | ||
635 | for (i = 1000; i > 0; --i) { | |
636 | if ((status = duart->statusA) & XMT_RDY) { | |
637 | duart->dataA = led_mask; | |
638 | break; | |
639 | } | |
640 | } | |
641 | ||
642 | if (i == 0) | |
643 | return(BAD); | |
644 | ||
645 | return(GOOD); | |
646 | ||
647 | } /* led_control */ | |
648 | ||
649 | /******************************************************************* | |
650 | * | |
651 | * scroll_up()... move the screen up one character height | |
652 | * | |
653 | ******************************************************************** | |
654 | * | |
655 | * calling convention: | |
656 | * | |
657 | * scroll_up(adder); | |
658 | * struct adder *adder; ;address of adder | |
659 | * | |
660 | ********/ | |
661 | ||
662 | scroll_up(adder) | |
663 | register struct adder *adder; | |
664 | { | |
665 | ||
666 | /*------------------------------------------ | |
667 | * setup VIPER operand control registers */ | |
668 | ||
669 | wait_status(adder, ADDRESS_COMPLETE); | |
670 | ||
671 | write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ | |
672 | ||
673 | write_ID(adder, MASK_1, 0xFFFF); | |
674 | write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); | |
675 | write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); | |
676 | ||
677 | write_ID(adder, SRC1_OCR_B, | |
678 | EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); | |
679 | write_ID(adder, DST_OCR_B, | |
680 | EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); | |
681 | ||
682 | /*---------------------------------------- | |
683 | * load DESTINATION origin and vectors */ | |
684 | ||
685 | adder->fast_dest_dy = 0; | |
686 | adder->slow_dest_dx = 0; | |
687 | adder->error_1 = 0; | |
688 | adder->error_2 = 0; | |
689 | ||
690 | adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; | |
691 | ||
692 | adder->destination_x = 0; | |
693 | adder->fast_dest_dx = 1024; | |
694 | ||
695 | adder->destination_y = 0; | |
696 | adder->slow_dest_dy = 864 - CHAR_HEIGHT; | |
697 | ||
698 | /*----------------------------------- | |
699 | * load SOURCE origin and vectors */ | |
700 | ||
701 | adder->source_1_x = 0; | |
702 | adder->source_1_dx = 1024; | |
703 | ||
704 | adder->source_1_y = 0 + CHAR_HEIGHT; | |
705 | adder->source_1_dy = 864 - CHAR_HEIGHT; | |
706 | ||
707 | write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); | |
708 | adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; | |
709 | ||
710 | /*-------------------------------------------- | |
711 | * do a rectangle clear of last screen line */ | |
712 | ||
713 | write_ID(adder, MASK_1, 0xffff); | |
714 | write_ID(adder, SOURCE, 0xffff); | |
715 | write_ID(adder,DST_OCR_B, | |
716 | (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); | |
717 | write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); | |
718 | adder->error_1 = 0; | |
719 | adder->error_2 = 0; | |
720 | adder->slow_dest_dx = 0; /* set up the width of */ | |
721 | adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ | |
722 | ||
723 | adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; | |
724 | wait_status(adder, RASTEROP_COMPLETE); | |
725 | adder->destination_x = 0; | |
726 | adder->destination_y = 864 - CHAR_HEIGHT; | |
727 | ||
728 | adder->fast_dest_dx = 1024; /* set up the height */ | |
729 | adder->fast_dest_dy = 0; /* of rectangle */ | |
730 | ||
731 | write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); | |
732 | adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; | |
733 | ||
734 | } /* scroll_up */ | |
735 | ||
736 | /********************************************************************** | |
737 | * | |
738 | * set_defaults()... init the QDSS device and driver defaults | |
739 | * | |
740 | **********************************************************************/ | |
741 | ||
742 | set_defaults() | |
743 | { | |
744 | setup_input(); /* init the DUART */ | |
745 | setup_dragon(); /* init the ADDER/VIPER stuff */ | |
746 | ldcursor(); /* load default cursor map */ | |
747 | ||
748 | } /* set_defaults */ | |
749 | ||
750 | /********************************************************************* | |
751 | * | |
752 | * setup_dragon()... init the ADDER, VIPER, bitmaps, & color map | |
753 | * | |
754 | *********************************************************************/ | |
755 | ||
756 | setup_dragon() | |
757 | { | |
758 | ||
759 | register struct adder *adder; | |
760 | register struct dga *dga; | |
761 | short *memcsr; | |
762 | ||
763 | int i; /* general purpose variables */ | |
764 | int status; | |
765 | ||
766 | short top; /* clipping/scrolling boundaries */ | |
767 | short bottom; | |
768 | short right; | |
769 | short left; | |
770 | ||
771 | short *red; /* color map pointers */ | |
772 | short *green; | |
773 | short *blue; | |
774 | ||
775 | /*------------------ | |
776 | * init for setup */ | |
777 | ||
778 | adder = (struct adder *) qdmap.adder; | |
779 | dga = (struct dga *) qdmap.dga; | |
780 | memcsr = (short *) qdmap.memcsr; | |
781 | ||
782 | *memcsr = SYNC_ON; /* blank screen and turn off LED's */ | |
783 | adder->command = CANCEL; | |
784 | ||
785 | /*---------------------- | |
786 | * set monitor timing */ | |
787 | ||
788 | adder->x_scan_count_0 = 0x2800; | |
789 | adder->x_scan_count_1 = 0x1020; | |
790 | adder->x_scan_count_2 = 0x003A; | |
791 | adder->x_scan_count_3 = 0x38F0; | |
792 | adder->x_scan_count_4 = 0x6128; | |
793 | adder->x_scan_count_5 = 0x093A; | |
794 | adder->x_scan_count_6 = 0x313C; | |
795 | adder->sync_phase_adj = 0x0100; | |
796 | adder->x_scan_conf = 0x00C8; | |
797 | ||
798 | /*--------------------------------------------------------- | |
799 | * got a bug in secound pass ADDER! lets take care of it */ | |
800 | ||
801 | /* normally, just use the code in the following bug fix code, but to | |
802 | * make repeated demos look pretty, load the registers as if there was | |
803 | * no bug and then test to see if we are getting sync */ | |
804 | ||
805 | adder->y_scan_count_0 = 0x135F; | |
806 | adder->y_scan_count_1 = 0x3363; | |
807 | adder->y_scan_count_2 = 0x2366; | |
808 | adder->y_scan_count_3 = 0x0388; | |
809 | ||
810 | /* if no sync, do the bug fix code */ | |
811 | ||
812 | if (wait_status(adder, VSYNC) == BAD) { | |
813 | ||
814 | /* first load all Y scan registers with very short frame and | |
815 | * wait for scroll service. This guarantees at least one SYNC | |
816 | * to fix the pass 2 Adder initialization bug (synchronizes | |
817 | * XCINCH with DMSEEDH) */ | |
818 | ||
819 | adder->y_scan_count_0 = 0x01; | |
820 | adder->y_scan_count_1 = 0x01; | |
821 | adder->y_scan_count_2 = 0x01; | |
822 | adder->y_scan_count_3 = 0x01; | |
823 | ||
824 | wait_status(adder, VSYNC); /* delay at least 1 full frame time */ | |
825 | wait_status(adder, VSYNC); | |
826 | ||
827 | /* now load the REAL sync values (in reverse order just to | |
828 | * be safe. */ | |
829 | ||
830 | adder->y_scan_count_3 = 0x0388; | |
831 | adder->y_scan_count_2 = 0x2366; | |
832 | adder->y_scan_count_1 = 0x3363; | |
833 | adder->y_scan_count_0 = 0x135F; | |
834 | } | |
835 | ||
836 | /*---------------------------- | |
837 | * zero the index registers */ | |
838 | ||
839 | adder->x_index_pending = 0; | |
840 | adder->y_index_pending = 0; | |
841 | adder->x_index_new = 0; | |
842 | adder->y_index_new = 0; | |
843 | adder->x_index_old = 0; | |
844 | adder->y_index_old = 0; | |
845 | ||
846 | adder->pause = 0; | |
847 | ||
848 | /*---------------------------------------- | |
849 | * set rasterop mode to normal pen down */ | |
850 | ||
851 | adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; | |
852 | ||
853 | /*-------------------------------------------------- | |
854 | * set the rasterop registers to a default values */ | |
855 | ||
856 | adder->source_1_dx = 1; | |
857 | adder->source_1_dy = 1; | |
858 | adder->source_1_x = 0; | |
859 | adder->source_1_y = 0; | |
860 | adder->destination_x = 0; | |
861 | adder->destination_y = 0; | |
862 | adder->fast_dest_dx = 1; | |
863 | adder->fast_dest_dy = 0; | |
864 | adder->slow_dest_dx = 0; | |
865 | adder->slow_dest_dy = 1; | |
866 | adder->error_1 = 0; | |
867 | adder->error_2 = 0; | |
868 | ||
869 | /*------------------------ | |
870 | * scale factor = unity */ | |
871 | ||
872 | adder->fast_scale = UNITY; | |
873 | adder->slow_scale = UNITY; | |
874 | ||
875 | /*------------------------------- | |
876 | * set the source 2 parameters */ | |
877 | ||
878 | adder->source_2_x = 0; | |
879 | adder->source_2_y = 0; | |
880 | adder->source_2_size = 0x0022; | |
881 | ||
882 | /*----------------------------------------------- | |
883 | * initialize plane addresses for eight vipers */ | |
884 | ||
885 | write_ID(adder, CS_UPDATE_MASK, 0x0001); | |
886 | write_ID(adder, PLANE_ADDRESS, 0x0000); | |
887 | ||
888 | write_ID(adder, CS_UPDATE_MASK, 0x0002); | |
889 | write_ID(adder, PLANE_ADDRESS, 0x0001); | |
890 | ||
891 | write_ID(adder, CS_UPDATE_MASK, 0x0004); | |
892 | write_ID(adder, PLANE_ADDRESS, 0x0002); | |
893 | ||
894 | write_ID(adder, CS_UPDATE_MASK, 0x0008); | |
895 | write_ID(adder, PLANE_ADDRESS, 0x0003); | |
896 | ||
897 | write_ID(adder, CS_UPDATE_MASK, 0x0010); | |
898 | write_ID(adder, PLANE_ADDRESS, 0x0004); | |
899 | ||
900 | write_ID(adder, CS_UPDATE_MASK, 0x0020); | |
901 | write_ID(adder, PLANE_ADDRESS, 0x0005); | |
902 | ||
903 | write_ID(adder, CS_UPDATE_MASK, 0x0040); | |
904 | write_ID(adder, PLANE_ADDRESS, 0x0006); | |
905 | ||
906 | write_ID(adder, CS_UPDATE_MASK, 0x0080); | |
907 | write_ID(adder, PLANE_ADDRESS, 0x0007); | |
908 | ||
909 | /* initialize the external registers. */ | |
910 | ||
911 | write_ID(adder, CS_UPDATE_MASK, 0x00FF); | |
912 | write_ID(adder, CS_SCROLL_MASK, 0x00FF); | |
913 | ||
914 | /* initialize resolution mode */ | |
915 | ||
916 | write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ | |
917 | write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ | |
918 | ||
919 | /* initialize viper registers */ | |
920 | ||
921 | write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); | |
922 | write_ID(adder, SCROLL_FILL, 0x0000); | |
923 | ||
924 | /*---------------------------------------------------- | |
925 | * set clipping and scrolling limits to full screen */ | |
926 | ||
927 | for ( i = 1000, adder->status = 0 | |
928 | ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) | |
929 | ; --i); | |
930 | ||
931 | if (i == 0) | |
932 | printf("timeout trying to setup clipping\n"); | |
933 | ||
934 | top = 0; | |
935 | bottom = 2048; | |
936 | left = 0; | |
937 | right = 1024; | |
938 | ||
939 | adder->x_clip_min = left; | |
940 | adder->x_clip_max = right; | |
941 | adder->y_clip_min = top; | |
942 | adder->y_clip_max = bottom; | |
943 | ||
944 | adder->scroll_x_min = left; | |
945 | adder->scroll_x_max = right; | |
946 | adder->scroll_y_min = top; | |
947 | adder->scroll_y_max = bottom; | |
948 | ||
949 | wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ | |
950 | wait_status(adder, VSYNC); | |
951 | ||
952 | adder->x_index_pending = left; | |
953 | adder->y_index_pending = top; | |
954 | adder->x_index_new = left; | |
955 | adder->y_index_new = top; | |
956 | adder->x_index_old = left; | |
957 | adder->y_index_old = top; | |
958 | ||
959 | for ( i = 1000, adder->status = 0 | |
960 | ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) | |
961 | ; --i); | |
962 | ||
963 | if (i == 0) | |
964 | printf("timeout waiting for ADDRESS_COMPLETE bit\n"); | |
965 | ||
966 | write_ID(adder, LEFT_SCROLL_MASK, 0x0000); | |
967 | write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); | |
968 | ||
969 | /*------------------------------------------------------------ | |
970 | * set source and the mask register to all ones (ie: white) */ | |
971 | ||
972 | write_ID(adder, SOURCE, 0xFFFF); | |
973 | write_ID(adder, MASK_1, 0xFFFF); | |
974 | write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); | |
975 | write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); | |
976 | ||
977 | /*-------------------------------------------------------------- | |
978 | * initialize Operand Control Register banks for fill command */ | |
979 | ||
980 | write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); | |
981 | write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); | |
982 | write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); | |
983 | ||
984 | write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); | |
985 | write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); | |
986 | write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); | |
987 | ||
988 | /*------------------------------------------------------------------ | |
989 | * init Logic Unit Function registers, (these are just common values, | |
990 | * and may be changed as required). */ | |
991 | ||
992 | write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); | |
993 | write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2); | |
994 | write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); | |
995 | write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); | |
996 | ||
997 | /*---------------------------------------- | |
998 | * load the color map for black & white */ | |
999 | ||
1000 | for ( i = 0, adder->status = 0 | |
1001 | ; i < 10000 && !((status = adder->status) & VSYNC) | |
1002 | ; ++i); | |
1003 | ||
1004 | if (i == 0) | |
1005 | printf("timeout waiting for VSYNC bit\n"); | |
1006 | ||
1007 | red = (short *) qdmap.red; | |
1008 | green = (short *) qdmap.green; | |
1009 | blue = (short *) qdmap.blue; | |
1010 | ||
1011 | *red++ = 0x00; /* black */ | |
1012 | *green++ = 0x00; | |
1013 | *blue++ = 0x00; | |
1014 | ||
1015 | *red-- = 0xFF; /* white */ | |
1016 | *green-- = 0xFF; | |
1017 | *blue-- = 0xFF; | |
1018 | ||
1019 | /*---------------------------------- | |
1020 | * set color map for mouse cursor */ | |
1021 | ||
1022 | red += 254; | |
1023 | green += 254; | |
1024 | blue += 254; | |
1025 | ||
1026 | *red++ = 0x00; /* black */ | |
1027 | *green++ = 0x00; | |
1028 | *blue++ = 0x00; | |
1029 | ||
1030 | *red = 0xFF; /* white */ | |
1031 | *green = 0xFF; | |
1032 | *blue = 0xFF; | |
1033 | ||
1034 | /*--------------------------------------------------------------------------- | |
1035 | * clear the bitmap a piece at a time. Since the fast scroll clear only clears | |
1036 | * the current displayed portion of the bitmap put a temporary value in the y | |
1037 | * limit register so we can access whole bitmap */ | |
1038 | ||
1039 | adder->x_limit = 1024; | |
1040 | adder->y_limit = 2048 - CHAR_HEIGHT; | |
1041 | adder->y_offset_pending = 0; | |
1042 | ||
1043 | wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ | |
1044 | wait_status(adder, VSYNC); | |
1045 | ||
1046 | adder->y_scroll_constant = SCROLL_ERASE; | |
1047 | ||
1048 | wait_status(adder, VSYNC); | |
1049 | wait_status(adder, VSYNC); | |
1050 | ||
1051 | adder->y_offset_pending = 864; | |
1052 | ||
1053 | wait_status(adder, VSYNC); | |
1054 | wait_status(adder, VSYNC); | |
1055 | ||
1056 | adder->y_scroll_constant = SCROLL_ERASE; | |
1057 | ||
1058 | wait_status(adder, VSYNC); | |
1059 | wait_status(adder, VSYNC); | |
1060 | ||
1061 | adder->y_offset_pending = 1728; | |
1062 | ||
1063 | wait_status(adder, VSYNC); | |
1064 | wait_status(adder, VSYNC); | |
1065 | ||
1066 | adder->y_scroll_constant = SCROLL_ERASE; | |
1067 | ||
1068 | wait_status(adder, VSYNC); | |
1069 | wait_status(adder, VSYNC); | |
1070 | ||
1071 | adder->y_offset_pending = 0; /* back to normal */ | |
1072 | ||
1073 | wait_status(adder, VSYNC); | |
1074 | wait_status(adder, VSYNC); | |
1075 | ||
1076 | adder->x_limit = MAX_SCREEN_X; | |
1077 | adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; | |
1078 | ||
1079 | *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ | |
1080 | return(0); | |
1081 | ||
1082 | } /* setup_dragon */ | |
1083 | ||
1084 | /****************************************************************** | |
1085 | * | |
1086 | * setup_input()... init the DUART and set defaults in input | |
1087 | * devices | |
1088 | * | |
1089 | ******************************************************************/ | |
1090 | ||
1091 | setup_input() | |
1092 | { | |
1093 | register struct duart *duart; /* DUART register structure pointer */ | |
1094 | register int bits; | |
1095 | int i, j; /* scratch variables */ | |
1096 | ||
1097 | short status; | |
1098 | ||
1099 | /*--------------- | |
1100 | * init stuff */ | |
1101 | ||
1102 | duart = (struct duart *) qdmap.duart; | |
1103 | ||
1104 | /*--------------------------------------------- | |
1105 | * setup the DUART for kbd & pointing device */ | |
1106 | ||
1107 | duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ | |
1108 | duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ | |
1109 | /* no RTS control,char error mode */ | |
1110 | duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ | |
1111 | /* no RTS control,no echo or loop */ | |
1112 | duart->auxctl = 0x00; /* baud rate set 1 */ | |
1113 | ||
1114 | duart->clkselA = 0x99; /* 4800 baud for kbd */ | |
1115 | ||
1116 | /* reset everything for keyboard */ | |
1117 | ||
1118 | for (bits = RESET_M; bits < START_BREAK; bits += 0x10) | |
1119 | duart->cmdA = bits; | |
1120 | ||
1121 | duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ | |
1122 | ||
1123 | /*-------------------------- | |
1124 | * init keyboard defaults */ | |
1125 | /* | |
1126 | for (i = 500; i > 0; --i) { | |
1127 | if ((status = duart->statusA) & XMT_RDY) { | |
1128 | duart->dataA = LK_DEFAULTS; | |
1129 | break; | |
1130 | } | |
1131 | } | |
1132 | ||
1133 | for (j = 0; j < 3; ++j) { | |
1134 | for (i = 50000; i > 0; --i) { | |
1135 | if ((status = duart->statusA) & RCV_RDY) { | |
1136 | status = duart->dataA; | |
1137 | break; | |
1138 | } | |
1139 | } | |
1140 | } | |
1141 | ||
1142 | if (i == 0) | |
1143 | printf("LK-201 init error\n"); | |
1144 | */ | |
1145 | ||
1146 | /*-------- | |
1147 | * exit */ | |
1148 | ||
1149 | return(0); | |
1150 | ||
1151 | } /* setup_input */ | |
1152 | ||
1153 | /********************************************************************** | |
1154 | * | |
1155 | * wait_status()... delay for at least one display frame time | |
1156 | * | |
1157 | *********************************************************************** | |
1158 | * | |
1159 | * calling convention: | |
1160 | * | |
1161 | * wait_status(adder, mask); | |
1162 | * struct *adder adder; | |
1163 | * int mask; | |
1164 | * | |
1165 | * return: BAD means that we timed out without ever seeing the | |
1166 | * vertical sync status bit | |
1167 | * GOOD otherwise | |
1168 | * | |
1169 | **************/ | |
1170 | ||
1171 | wait_status(adder, mask) | |
1172 | register struct adder *adder; | |
1173 | register int mask; | |
1174 | { | |
1175 | register short status; | |
1176 | int i; | |
1177 | ||
1178 | for ( i = 10000, adder->status = 0 | |
1179 | ; i > 0 && !((status = adder->status) & mask) | |
1180 | ; --i); | |
1181 | ||
1182 | if (i == 0) { | |
1183 | printf("timeout polling for 0x%x in adder->status\n", mask); | |
1184 | return(BAD); | |
1185 | } | |
1186 | ||
1187 | return(GOOD); | |
1188 | ||
1189 | } /* wait_status */ | |
1190 | ||
1191 | /********************************************************************** | |
1192 | * | |
1193 | * write_ID()... write out onto the ID bus | |
1194 | * | |
1195 | *********************************************************************** | |
1196 | * | |
1197 | * calling convention: | |
1198 | * | |
1199 | * struct *adder adder; ;pntr to ADDER structure | |
1200 | * short adrs; ;VIPER address | |
1201 | * short data; ;data to be written | |
1202 | * write_ID(adder); | |
1203 | * | |
1204 | * return: BAD means that we timed out waiting for status bits | |
1205 | * VIPER-access-specific status bits | |
1206 | * GOOD otherwise | |
1207 | * | |
1208 | **************/ | |
1209 | ||
1210 | write_ID(adder, adrs, data) | |
1211 | register struct adder *adder; | |
1212 | register short adrs; | |
1213 | register short data; | |
1214 | { | |
1215 | int i; | |
1216 | short status; | |
1217 | ||
1218 | for ( i = 100000, adder->status = 0 | |
1219 | ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) | |
1220 | ; --i); | |
1221 | ||
1222 | if (i == 0) | |
1223 | goto ERR; | |
1224 | ||
1225 | for ( i = 100000, adder->status = 0 | |
1226 | ; i > 0 && !((status = adder->status) & TX_READY) | |
1227 | ; --i); | |
1228 | ||
1229 | if (i > 0) { | |
1230 | adder->id_data = data; | |
1231 | adder->command = ID_LOAD | adrs; | |
1232 | return(GOOD); | |
1233 | } | |
1234 | ||
1235 | ERR: | |
1236 | printf("timeout trying to write to VIPER\n"); | |
1237 | return(BAD); | |
1238 | ||
1239 | } /* write_ID */ |