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