1 /*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)qd.c 7.1 (Berkeley) 06/28/91
8 */
9
10 /************************************************************************
11 * *
12 * Copyright (c) 1985-1988 by *
13 * Digital Equipment Corporation, Maynard, MA *
14 * All rights reserved. *
15 * *
16 * This software is furnished under a license and may be used and *
17 * copied only in accordance with the terms of such license and *
18 * with the inclusion of the above copyright notice. This *
19 * software or any other copies thereof may not be provided or *
20 * otherwise made available to any other person. No title to and *
21 * ownership of the software is hereby transferred. *
22 * *
23 * The information in this software is subject to change without *
24 * notice and should not be construed as a commitment by Digital *
25 * Equipment Corporation. *
26 * *
27 * Digital assumes no responsibility for the use or reliability *
28 * of its software on equipment which is not supplied by Digital. *
29 * *
30 *************************************************************************/
31
32 /*
33 * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
34 */
35
36 #include "qd.h"
37
38 #if NQD > 0
39 #include "../include/pte.h"
40 #include "../include/mtpr.h"
41 #include "sys/param.h"
42 #include "../include/cpu.h"
43 #include "sys/conf.h"
44 #include "sys/user.h"
45 #include "qdioctl.h"
46 #include "sys/tty.h"
47 #include "sys/map.h"
48 #include "sys/buf.h"
49 #include "sys/vm.h"
50 #include "sys/clist.h"
51 #include "sys/file.h"
52 #include "sys/uio.h"
53 #include "sys/kernel.h"
54 #include "sys/exec.h"
55 #include "sys/proc.h"
56 #include "ubareg.h"
57 #include "ubavar.h"
58 #include "sys/syslog.h"
59 #include "qduser.h" /* definitions shared with user level client */
60 #include "qdreg.h" /* QDSS device register structures */
61
62 /*
63 * QDSS driver status flags for tracking operational state
64 */
65 struct qdflags {
66 u_int inuse; /* which minor dev's are in use now */
67 u_int config; /* I/O page register content */
68 u_int mapped; /* user mapping status word */
69 u_int kernel_loop; /* if kernel console is redirected */
70 u_int user_dma; /* DMA from user space in progress */
71 u_short pntr_id; /* type code of pointing device */
72 u_short duart_imask; /* shadowing for duart intrpt mask reg */
73 u_short adder_ie; /* shadowing for adder intrpt enbl reg */
74 u_short curs_acc; /* cursor acceleration factor */
75 u_short curs_thr; /* cursor acceleration threshold level */
76 u_short tab_res; /* tablet resolution factor */
77 u_short selmask; /* mask for active qd select entries */
78 };
79
80 /*
81 * bit definitions for 'inuse' entry
82 */
83 #define CONS_DEV 0x01
84 #define GRAPHIC_DEV 0x04
85
86 /*
87 * bit definitions for 'mapped' member of flag structure
88 */
89 #define MAPDEV 0x01 /* hardware is mapped */
90 #define MAPDMA 0x02 /* DMA buffer mapped */
91 #define MAPEQ 0x04 /* event queue buffer mapped */
92 #define MAPSCR 0x08 /* scroll param area mapped */
93 #define MAPCOLOR 0x10 /* color map writing buffer mapped */
94
95 /*
96 * bit definitions for 'selmask' member of qdflag structure
97 */
98 #define SEL_READ 0x01 /* read select is active */
99 #define SEL_WRITE 0x02 /* write select is active */
100
101 /*
102 * constants used in shared memory operations
103 */
104 #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */
105 #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \
106 / sizeof(struct _vs_event) )
107 #define DMA_BUFSIZ (1024 * 10)
108 #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF)
109
110 /*
111 * reference to an array of "uba_device" structures built by the auto
112 * configuration program. The uba_device structure decribes the device
113 * sufficiently for the driver to talk to it. The auto configuration code
114 * fills in the uba_device structures (located in ioconf.c) from user
115 * maintained info.
116 */
117 struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */
118 struct tty qd_tty[NQD*4]; /* teletype structures for each.. */
119 extern char qvmem[][128*NBPG];
120 extern struct pte QVmap[][128];
121 #define CHUNK (64 * 1024)
122 #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */
123
124 /*
125 * static storage used by multiple functions in this code
126 */
127 int Qbus_unmap[NQD]; /* Qbus mapper release code */
128 struct qdflags qdflags[NQD]; /* QDSS device status flags */
129 struct qdmap qdmap[NQD]; /* QDSS register map structure */
130 caddr_t qdbase[NQD]; /* base address of each QDSS unit */
131 struct buf qdbuf[NQD]; /* buf structs used by strategy */
132 short qdopened[NQD]; /* graphics device is open exclusive use */
133
134 /*
135 * the array "event_shared[]" is made up of a number of event queue buffers
136 * equal to the number of QDSS's configured into the running kernel (NQD).
137 * Each event queue buffer begins with an event queue header (struct qdinput)
138 * followed by a group of event queue entries (struct _vs_event). The array
139 * "*eq_header[]" is an array of pointers to the start of each event queue
140 * buffer in "event_shared[]".
141 */
142 #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
143
144 char event_shared[EQSIZE]; /* reserve space for event bufs */
145 struct qdinput *eq_header[NQD]; /* event queue header pntrs */
146
147 /*
148 * This allocation method reserves enough memory pages for NQD shared DMA I/O
149 * buffers. Each buffer must consume an integral number of memory pages to
150 * guarantee that a following buffer will begin on a page boundary. Also,
151 * enough space is allocated so that the FIRST I/O buffer can start at the
152 * 1st page boundary after "&DMA_shared". Page boundaries are used so that
153 * memory protections can be turned on/off for individual buffers.
154 */
155 #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512)
156
157 char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */
158 struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */
159
160 /*
161 * The driver assists a client in scroll operations by loading dragon
162 * registers from an interrupt service routine. The loading is done using
163 * parameters found in memory shrade between the driver and it's client.
164 * The scroll parameter structures are ALL loacted in the same memory page
165 * for reasons of memory economy.
166 */
167 char scroll_shared[2 * 512]; /* reserve space for scroll structs */
168 struct scroll *scroll[NQD]; /* pointers to scroll structures */
169
170 /*
171 * the driver is programmable to provide the user with color map write
172 * services at VSYNC interrupt time. At interrupt time the driver loads
173 * the color map with any user-requested load data found in shared memory
174 */
175 #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512)
176
177 char color_shared[COLOR_SHARED]; /* reserve space: color bufs */
178 struct color_buf *color_buf[NQD]; /* pointers to color bufs */
179
180 /*
181 * mouse input event structures
182 */
183 struct mouse_report last_rep[NQD];
184 struct mouse_report current_rep[NQD];
185
186 struct proc *qdrsel[NQD]; /* process waiting for select */
187 struct _vs_cursor cursor[NQD]; /* console cursor */
188 int qdcount = 0; /* count of successfully probed qd's */
189 int nNQD = NQD;
190 int DMAbuf_size = DMA_BUFSIZ;
191 int QDlast_DMAtype; /* type of the last DMA operation */
192
193 #define QDSSMAJOR 41 /* QDSS major device number */
194 /*
195 * macro to get system time. Used to time stamp event queue entries
196 */
197 #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
198
199 int qdprobe();
200 int qdattach();
201 int qddint(); /* DMA gate array intrpt service */
202 int qdaint(); /* Dragon ADDER intrpt service */
203 int qdiint();
204
205 u_short qdstd[] = { 0 };
206
207 struct uba_driver qddriver = {
208 qdprobe, /* device probe entry */
209 0, /* no slave device */
210 qdattach, /* device attach entry */
211 0, /* no "fill csr/ba to start" */
212 qdstd, /* device addresses */
213 "qd", /* device name string */
214 qdinfo /* ptr to QDSS's uba_device struct */
215 };
216
217 #define QDPRIOR (PZERO-1) /* must be negative */
218 #define FALSE 0
219 #define TRUE ~FALSE
220 #define BAD -1
221 #define GOOD 0
222
223 /*
224 * macro to create a system virtual page number from system virtual adrs
225 */
226 #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT)
227
228 /*
229 * QDSS register address offsets from start of QDSS address space
230 */
231 #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */
232 #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */
233 #define TMPSTART 0x8000 /* offset of template RAM from base adrs */
234 #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */
235 #define REGSTART 0xC000 /* offset of reg pages from base adrs */
236 #define ADDER (REGSTART+0x000)
237 #define DGA (REGSTART+0x200)
238 #define DUART (REGSTART+0x400)
239 #define MEMCSR (REGSTART+0x800)
240 #define CLRSIZE (3 * 512) /* color map size */
241 #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */
242 /* 0x0C00 really */
243 #define RED (CLRSTART+0x000)
244 #define BLUE (CLRSTART+0x200)
245 #define GREEN (CLRSTART+0x400)
246
247
248 /*
249 * QDSS minor device numbers. The *real* minor device numbers are in
250 * the bottom two bits of the major/minor device spec. Bits 2 and up are
251 * used to specify the QDSS device number (ie: which one?)
252 */
253
254 #define CONS 0
255 #define GRAPHIC 2
256
257 /*
258 * console cursor bitmap (white block cursor)
259 */
260 short cons_cursor[32] = {
261 /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
262 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
263 /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
264 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
265 };
266
267 /*
268 * constants used in font operations
269 */
270 #define CHARS 190 /* # of chars in the font */
271 #define CHAR_HEIGHT 15 /* char height in pixels */
272 #define CHAR_WIDTH 8 /* char width in pixels*/
273 #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */
274 #define ROWS CHAR_HEIGHT
275 #define FONT_X 0 /* font's off screen adrs */
276 #define FONT_Y (2048 - CHAR_HEIGHT)
277
278 /* Offset to second row characters (XXX - should remove) */
279 #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
280
281 extern char q_font[]; /* reference font object code */
282 extern u_short q_key[]; /* reference key xlation tables */
283 extern u_short q_shift_key[];
284 extern char *q_special[];
285
286 /*
287 * definitions for cursor acceleration reporting
288 */
289 #define ACC_OFF 0x01 /* acceleration is inactive */
290
291 /*
292 * virtual console support.
293 */
294 extern (*v_putc)();
295 #ifdef KADB
296 extern (*v_getc)();
297 extern (*v_poll)();
298 #endif
299 extern struct cdevsw *consops;
300 int qdputc();
301 int qdgetc();
302 int qdpoll();
303 int qdstart();
304 int qdpolling = 0;
305
306 /*
307 * LK-201 state storage for input console keyboard conversion to ASCII
308 */
309 struct q_keyboard {
310 int shift; /* state variables */
311 int cntrl;
312 int lock;
313 int lastcode; /* last keycode typed */
314 unsigned kup[8]; /* bits for each keycode*/
315 unsigned dkeys[8]; /* down/up mode keys */
316 char last; /* last character */
317 } q_keyboard;
318
319 /*
320 * tty settings on first open
321 */
322 #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
323 #define OFLAG (OPOST|OXTABS|ONLCR)
324 #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
325 #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
326
327 /*
328 * Init QDSS as console (before probe routine)
329 */
330
qdcons_init()331 qdcons_init()
332 {
333 register unit;
334 caddr_t phys_adr; /* physical QDSS base adrs */
335 u_int mapix; /* index into QVmap[] array */
336 struct percpu *pcpu; /* pointer to cpusw structure */
337 register struct qbus *qb;
338 u_short *qdaddr; /* address of QDSS IO page CSR */
339 u_short *devptr; /* vitual device space */
340 extern cnputc();
341
342 #define QDSSCSR 0x1F00
343
344 if (v_putc != cnputc)
345 return 0;
346
347 unit = 0;
348
349 /*
350 * find the cpusw entry that matches this machine.
351 */
352 for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
353 ;
354 if (pcpu == NULL)
355 return 0;
356 if (pcpu->pc_io->io_type != IO_QBUS)
357 return 0;
358
359 /*
360 * Map device registers - the last 8K of qvmem.
361 */
362 qb = (struct qbus *)pcpu->pc_io->io_details;
363 ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
364 UBAIOPAGES * NBPG);
365 devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
366 qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
367 if (badaddr((caddr_t)qdaddr, sizeof(short)))
368 return 0;
369
370 /*
371 * Map q-bus memory used by qdss. (separate map)
372 */
373 mapix = QMEMSIZE - (CHUNK * (unit + 1));
374 phys_adr = qb->qb_maddr + mapix;
375 ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
376
377 /*
378 * tell QDSS which Q memory address base to decode
379 * (shifted right 16 bits - its in 64K units)
380 */
381 *qdaddr = (u_short)((int)mapix >> 16);
382 qdflags[unit].config = *(u_short *)qdaddr;
383
384 /*
385 * load qdmap struct with the virtual addresses of the QDSS elements
386 */
387 qdbase[unit] = (caddr_t) (qvmem[0]);
388 qdmap[unit].template = qdbase[unit] + TMPSTART;
389 qdmap[unit].adder = qdbase[unit] + ADDER;
390 qdmap[unit].dga = qdbase[unit] + DGA;
391 qdmap[unit].duart = qdbase[unit] + DUART;
392 qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
393 qdmap[unit].red = qdbase[unit] + RED;
394 qdmap[unit].blue = qdbase[unit] + BLUE;
395 qdmap[unit].green = qdbase[unit] + GREEN;
396
397 qdflags[unit].duart_imask = 0; /* init shadow variables */
398
399 /*
400 * init the QDSS
401 */
402 /*
403 printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
404 (char *)qdbase[0], qdmap[0].memcsr);
405 */
406
407 *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
408
409 cursor[unit].x = 0;
410 cursor[unit].y = 0;
411 init_shared(unit); /* init shared memory */
412 setup_dragon(unit); /* init the ADDER/VIPER stuff */
413 clear_qd_screen(unit); /* clear the screen */
414 ldfont(unit); /* load the console font */
415 ldcursor(unit, cons_cursor); /* load default cursor map */
416 setup_input(unit); /* init the DUART */
417 v_putc = qdputc; /* kernel console output to qdss */
418 #ifdef KADB
419 v_getc = qdgetc; /* kernel console input from qdss */
420 v_poll = qdpoll; /* kdb hook to disable char intr */
421 #endif
422 consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */
423 return 1;
424
425 } /* qdcons_init */
426
427 /*
428 * Configure QDSS into Q memory and make it intrpt.
429 *
430 * side effects: QDSS gets mapped into Qbus memory space at the first
431 * vacant 64kb boundary counting back from the top of
432 * Qbus memory space (qvmem+4mb)
433 *
434 * return: QDSS bus request level and vector address returned in
435 * registers by UNIX convention.
436 *
437 */
qdprobe(reg)438 qdprobe(reg)
439 caddr_t reg; /* character pointer to the QDSS I/O page register */
440 {
441 register int br, cvec;
442 register int unit;
443 struct dga *dga; /* pointer to gate array structure */
444 int vector;
445 #ifdef notdef
446 int *ptep; /* page table entry pointer */
447 caddr_t phys_adr; /* physical QDSS base adrs */
448 u_int mapix;
449 #endif
450
451 #ifdef lint
452 br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
453 qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
454 #endif
455
456 /*
457 * calculate board unit number from I/O page register address
458 */
459 unit = (int) (((int)reg >> 1) & 0x0007);
460
461 /*
462 * QDSS regs must be mapped to Qbus memory space at a 64kb
463 * physical boundary. The Qbus memory space is mapped into
464 * the system memory space at config time. After config
465 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
466 * of the start of Qbus memory. The Qbus memory page table
467 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
468 * which is also loaded at config time. These are the
469 * variables used below to find a vacant 64kb boundary in
470 * Qbus memory, and load it's corresponding physical adrs
471 * into the QDSS's I/O page CSR.
472 */
473
474 /*
475 * Only if QD is the graphics device.
476 */
477
478 /* if this QDSS is NOT the console, then do init here.. */
479
480 if (unit != 0) {
481 printf("qd: can't support two qdss's (yet)\n");
482 #ifdef notdef /* can't test */
483 if (v_consputc != qdputc || unit != 0) {
484
485 /*
486 * read QDSS config info
487 */
488 qdflags[unit].config = *(u_short *)reg;
489
490 /*
491 * find an empty 64kb adrs boundary
492 */
493
494 qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
495
496 /*
497 * find the cpusw entry that matches this machine.
498 */
499 cpup = &cpusw[cpu];
500 while (!(BADADDR(qdbase[unit], sizeof(short))))
501 qdbase[unit] -= CHUNK;
502
503 /*
504 * tell QDSS which Q memory address base to decode
505 */
506 mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
507 ptep = (int *) QVmap[0] + mapix;
508 phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
509 *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
510
511 /*
512 * load QDSS adrs map with system addresses
513 * of device regs
514 */
515 qdmap[unit].template = qdbase[unit] + TMPSTART;
516 qdmap[unit].adder = qdbase[unit] + ADDER;
517 qdmap[unit].dga = qdbase[unit] + DGA;
518 qdmap[unit].duart = qdbase[unit] + DUART;
519 qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
520 qdmap[unit].red = qdbase[unit] + RED;
521 qdmap[unit].blue = qdbase[unit] + BLUE;
522 qdmap[unit].green = qdbase[unit] + GREEN;
523
524 /* device init */
525
526 cursor[unit].x = 0;
527 cursor[unit].y = 0;
528 init_shared(unit); /* init shared memory */
529 setup_dragon(unit); /* init the ADDER/VIPER stuff */
530 ldcursor(unit, cons_cursor); /* load default cursor map */
531 setup_input(unit); /* init the DUART */
532 clear_qd_screen(unit);
533 ldfont(unit); /* load the console font */
534
535 /* once only: turn on sync */
536
537 *(short *)qdmap[unit].memcsr |= SYNC_ON;
538 }
539 #endif /*notdef*/
540 }
541
542 /*
543 * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
544 * (ADDER) and xx8 (DUART). Therefore, we take three
545 * vectors from the vector pool, and then continue
546 * to take them until we get a xx0 HEX vector. The
547 * pool provides vectors in contiguous decending
548 * order.
549 */
550
551 vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */
552
553 while (vector & 0x0F) { /* if lo nibble != 0.. */
554 /* ..take another vector */
555 vector = (uba_hd[0].uh_lastiv -= 4);
556 }
557
558 /*
559 * setup DGA to do a DMA interrupt (transfer count = 0)
560 */
561 dga = (struct dga *) qdmap[unit].dga;
562 dga->csr = (short) HALT; /* disable everything */
563 dga->ivr = (short) vector; /* load intrpt base vector */
564 dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */
565 dga->bytcnt_hi = (short) 0;
566
567 /*
568 * turn on DMA interrupts
569 */
570 dga->csr &= ~SET_DONE_FIFO;
571 dga->csr |= DMA_IE | DL_ENB;
572
573 DELAY(20000); /* wait for the intrpt */
574 dga->csr = HALT; /* stop the wheels */
575
576 if (cvec != vector) /* if vector != base vector.. */
577 return(0); /* ..return = 'no device' */
578
579 /*
580 * score this as an existing qdss
581 */
582 qdcount++;
583
584 return(sizeof(short)); /* return size of QDSS I/O page reg */
585
586 } /* qdprobe */
587
588 qdattach(ui)
589 struct uba_device *ui;
590 {
591 register unit; /* QDSS module # for this call */
592
593 unit = ui->ui_unit; /* get QDSS number */
594
595 /*
596 * init "qdflags[]" for this QDSS
597 */
598 qdflags[unit].inuse = 0; /* init inuse variable EARLY! */
599 qdflags[unit].mapped = 0;
600 qdflags[unit].kernel_loop = -1;
601 qdflags[unit].user_dma = 0;
602 qdflags[unit].curs_acc = ACC_OFF;
603 qdflags[unit].curs_thr = 128;
604 qdflags[unit].tab_res = 2; /* default tablet resolution factor */
605 qdflags[unit].duart_imask = 0; /* init shadow variables */
606 qdflags[unit].adder_ie = 0;
607
608 /*
609 * init structures used in kbd/mouse interrupt service. This code must
610 * come after the "init_shared()" routine has run since that routine
611 * inits the eq_header[unit] structure used here.
612 */
613
614 /*
615 * init the "latest mouse report" structure
616 */
617 last_rep[unit].state = 0;
618 last_rep[unit].dx = 0;
619 last_rep[unit].dy = 0;
620 last_rep[unit].bytcnt = 0;
621
622 /*
623 * init the event queue (except mouse position)
624 */
625 eq_header[unit]->header.events =
626 (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
627
628 eq_header[unit]->header.size = MAXEVENTS;
629 eq_header[unit]->header.head = 0;
630 eq_header[unit]->header.tail = 0;
631
632 /*
633 * open exclusive for graphics device.
634 */
635 qdopened[unit] = 0;
636
637 } /* qdattach */
638
639 /*ARGSUSED*/
qdopen(dev,flag)640 qdopen(dev, flag)
641 dev_t dev;
642 int flag;
643 {
644 register struct uba_device *ui; /* ptr to uba structures */
645 register struct dga *dga; /* ptr to gate array struct */
646 register struct tty *tp;
647 struct duart *duart;
648 int unit;
649 int minor_dev;
650
651 minor_dev = minor(dev); /* get QDSS minor device number */
652 unit = minor_dev >> 2;
653
654 /*
655 * check for illegal conditions
656 */
657 ui = qdinfo[unit]; /* get ptr to QDSS device struct */
658 if (ui == 0 || ui->ui_alive == 0)
659 return(ENXIO); /* no such device or address */
660
661 duart = (struct duart *) qdmap[unit].duart;
662 dga = (struct dga *) qdmap[unit].dga;
663
664 if ((minor_dev & 0x03) == 2) {
665 /*
666 * this is the graphic device...
667 */
668 if (qdopened[unit] != 0)
669 return(EBUSY);
670 else
671 qdopened[unit] = 1;
672 qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */
673 /*
674 * enble kbd & mouse intrpts in DUART mask reg
675 */
676 qdflags[unit].duart_imask |= 0x22;
677 duart->imask = qdflags[unit].duart_imask;
678 } else {
679 /*
680 * this is the console
681 */
682 qdflags[unit].inuse |= CONS_DEV; /* mark console as open */
683 dga->csr |= CURS_ENB;
684 qdflags[unit].duart_imask |= 0x02;
685 duart->imask = qdflags[unit].duart_imask;
686 /*
687 * some setup for tty handling
688 */
689 tp = &qd_tty[minor_dev];
690 tp->t_addr = ui->ui_addr;
691 tp->t_oproc = qdstart;
692 if ((tp->t_state & TS_ISOPEN) == 0) {
693 ttychars(tp);
694 tp->t_ispeed = B9600;
695 tp->t_ospeed = B9600;
696 tp->t_state = TS_ISOPEN | TS_CARR_ON;
697 tp->t_iflag = TTYDEF_IFLAG;
698 tp->t_oflag = TTYDEF_OFLAG;
699 tp->t_lflag = TTYDEF_LFLAG;
700 tp->t_cflag = TTYDEF_CFLAG;
701 }
702 /*
703 * enable intrpts, open line discipline
704 */
705 dga->csr |= GLOBAL_IE; /* turn on the interrupts */
706 return ((*linesw[tp->t_line].l_open)(dev, tp));
707 }
708 dga->csr |= GLOBAL_IE; /* turn on the interrupts */
709 return(0);
710
711 } /* qdopen */
712
713 /*ARGSUSED*/
qdclose(dev,flag,mode,p)714 qdclose(dev, flag, mode, p)
715 dev_t dev;
716 int flag, mode;
717 struct proc *p;
718 {
719 register struct tty *tp;
720 register struct qdmap *qd;
721 register int *ptep;
722 struct dga *dga; /* gate array register map pointer */
723 struct duart *duart;
724 struct adder *adder;
725 int unit;
726 int minor_dev;
727 u_int mapix;
728 int i; /* SIGNED index */
729
730 minor_dev = minor(dev); /* get minor device number */
731 unit = minor_dev >> 2; /* get QDSS number */
732 qd = &qdmap[unit];
733
734 if ((minor_dev & 0x03) == 2) {
735 /*
736 * this is the graphic device...
737 */
738 if (qdopened[unit] != 1)
739 return(EBUSY);
740 else
741 qdopened[unit] = 0; /* allow it to be re-opened */
742 /*
743 * re-protect device memory
744 */
745 if (qdflags[unit].mapped & MAPDEV) {
746 /*
747 * TEMPLATE RAM
748 */
749 mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
750 ptep = (int *)(QVmap[0] + mapix);
751 for (i = 0; i < btop(TMPSIZE); i++, ptep++)
752 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
753 /*
754 * ADDER
755 */
756 mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
757 ptep = (int *)(QVmap[0] + mapix);
758 for (i = 0; i < btop(REGSIZE); i++, ptep++)
759 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
760 /*
761 * COLOR MAPS
762 */
763 mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
764 ptep = (int *)(QVmap[0] + mapix);
765 for (i = 0; i < btop(CLRSIZE); i++, ptep++)
766 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
767 }
768
769 /*
770 * re-protect DMA buffer and free the map registers
771 */
772 if (qdflags[unit].mapped & MAPDMA) {
773 dga = (struct dga *) qdmap[unit].dga;
774 adder = (struct adder *) qdmap[unit].adder;
775 dga->csr &= ~DMA_IE;
776 dga->csr &= ~0x0600; /* kill DMA */
777 adder->command = CANCEL;
778 /*
779 * if DMA was running, flush spurious intrpt
780 */
781 if (dga->bytcnt_lo != 0) {
782 dga->bytcnt_lo = 0;
783 dga->bytcnt_hi = 0;
784 DMA_SETIGNORE(DMAheader[unit]);
785 dga->csr |= DMA_IE;
786 dga->csr &= ~DMA_IE;
787 }
788 ptep = (int *)
789 ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
790 for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
791 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
792 ubarelse(0, &Qbus_unmap[unit]);
793 }
794
795 /*
796 * re-protect 1K (2 pages) event queue
797 */
798 if (qdflags[unit].mapped & MAPEQ) {
799 ptep = (int *)
800 ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
801 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
802 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
803 }
804 /*
805 * re-protect scroll param area and disable scroll intrpts
806 */
807 if (qdflags[unit].mapped & MAPSCR) {
808 ptep = (int *) ((VTOP(scroll[unit]) * 4)
809 + (mfpr(SBR) | 0x80000000));
810 /*
811 * re-protect 512 scroll param area
812 */
813 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
814 adder = (struct adder *) qdmap[unit].adder;
815 qdflags[unit].adder_ie &= ~FRAME_SYNC;
816 adder->interrupt_enable = qdflags[unit].adder_ie;
817 }
818 /*
819 * re-protect color map write buffer area and kill intrpts
820 */
821 if (qdflags[unit].mapped & MAPCOLOR) {
822 ptep = (int *) ((VTOP(color_buf[unit]) * 4)
823 + (mfpr(SBR) | 0x80000000));
824 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
825 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
826 color_buf[unit]->status = 0;
827 adder = (struct adder *) qdmap[unit].adder;
828 qdflags[unit].adder_ie &= ~VSYNC;
829 adder->interrupt_enable = qdflags[unit].adder_ie;
830 }
831 mtpr(TBIA, 0);
832 /* flag everything now unmapped */
833 qdflags[unit].mapped = 0;
834 qdflags[unit].inuse &= ~GRAPHIC_DEV;
835 qdflags[unit].curs_acc = ACC_OFF;
836 qdflags[unit].curs_thr = 128;
837 /*
838 * restore the console
839 */
840 dga = (struct dga *) qdmap[unit].dga;
841 adder = (struct adder *) qdmap[unit].adder;
842 dga->csr &= ~DMA_IE;
843 dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */
844 dga->csr |= DMA_ERR; /* clear error condition */
845 adder->command = CANCEL;
846 /*
847 * if DMA was running, flush spurious intrpt
848 */
849 if (dga->bytcnt_lo != 0) {
850 dga->bytcnt_lo = 0;
851 dga->bytcnt_hi = 0;
852 DMA_SETIGNORE(DMAheader[unit]);
853 dga->csr |= DMA_IE;
854 dga->csr &= ~DMA_IE;
855 }
856 init_shared(unit); /* init shared memory */
857 setup_dragon(unit); /* init ADDER/VIPER */
858 ldcursor(unit, cons_cursor); /* load default cursor map */
859 setup_input(unit); /* init the DUART */
860 ldfont(unit);
861 cursor[unit].x = 0;
862 cursor[unit].y = 0;
863 /*
864 * shut off the mouse rcv intrpt and turn on kbd intrpts
865 */
866 duart = (struct duart *) qdmap[unit].duart;
867 qdflags[unit].duart_imask &= ~(0x20);
868 qdflags[unit].duart_imask |= 0x02;
869 duart->imask = qdflags[unit].duart_imask;
870 /*
871 * shut off interrupts if all is closed
872 */
873 if (!(qdflags[unit].inuse & CONS_DEV)) {
874 dga = (struct dga *) qdmap[unit].dga;
875 dga->csr &= ~(GLOBAL_IE | DMA_IE);
876 }
877 } else {
878 /*
879 * this is the console
880 */
881 tp = &qd_tty[minor_dev];
882 (*linesw[tp->t_line].l_close)(tp, flag);
883 ttyclose(tp);
884 tp->t_state = 0;
885 qdflags[unit].inuse &= ~CONS_DEV;
886 /*
887 * if graphics device is closed, kill interrupts
888 */
889 if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
890 dga = (struct dga *) qdmap[unit].dga;
891 dga->csr &= ~(GLOBAL_IE | DMA_IE);
892 }
893 }
894
895 return(0);
896
897 } /* qdclose */
898
qdioctl(dev,cmd,datap,flags)899 qdioctl(dev, cmd, datap, flags)
900 dev_t dev;
901 int cmd;
902 register caddr_t datap;
903 int flags;
904 {
905 register int *ptep; /* page table entry pointer */
906 register int mapix; /* QVmap[] page table index */
907 register struct _vs_event *event;
908 register struct tty *tp;
909 register i;
910 struct qdmap *qd; /* pointer to device map struct */
911 struct dga *dga; /* Gate Array reg structure pntr */
912 struct duart *duart; /* DUART reg structure pointer */
913 struct adder *adder; /* ADDER reg structure pointer */
914 struct prgkbd *cmdbuf;
915 struct prg_cursor *curs;
916 struct _vs_cursor *pos;
917 int unit = minor(dev) >> 2; /* number of caller's QDSS */
918 u_int minor_dev = minor(dev);
919 int error;
920 int s;
921 short *temp; /* a pointer to template RAM */
922
923 /*
924 * service graphic device ioctl commands
925 */
926 switch (cmd) {
927
928 case QD_GETEVENT:
929 /*
930 * extract the oldest event from the event queue
931 */
932 if (ISEMPTY(eq_header[unit])) {
933 event = (struct _vs_event *) datap;
934 event->vse_device = VSE_NULL;
935 break;
936 }
937 event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
938 s = spl5();
939 GETEND(eq_header[unit]);
940 splx(s);
941 bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
942 break;
943
944 case QD_RESET:
945 /*
946 * init the dragon stuff, DUART, and driver variables
947 */
948 init_shared(unit); /* init shared memory */
949 setup_dragon(unit); /* init the ADDER/VIPER stuff */
950 clear_qd_screen(unit);
951 ldcursor(unit, cons_cursor); /* load default cursor map */
952 ldfont(unit); /* load the console font */
953 setup_input(unit); /* init the DUART */
954 break;
955
956 case QD_SET:
957 /*
958 * init the DUART and driver variables
959 */
960 init_shared(unit);
961 setup_input(unit);
962 break;
963
964 case QD_CLRSCRN:
965 /*
966 * clear the QDSS screen. (NOTE that this reinits the dragon)
967 */
968 #ifdef notdef /* has caused problems and isn't necessary */
969 setup_dragon(unit);
970 clear_qd_screen(unit);
971 #endif
972 break;
973
974 case QD_WTCURSOR:
975 /*
976 * load a cursor into template RAM
977 */
978 ldcursor(unit, (short *)datap);
979 break;
980
981 case QD_RDCURSOR:
982
983 temp = (short *) qdmap[unit].template;
984 /*
985 * cursor is 32 WORDS from the end of the 8k WORD...
986 * ...template space
987 */
988 temp += (8 * 1024) - 32;
989 for (i = 0; i < 32; ++i, datap += sizeof(short))
990 *(short *)datap = *temp++;
991 break;
992
993 case QD_POSCURSOR:
994 /*
995 * position the mouse cursor
996 */
997 dga = (struct dga *) qdmap[unit].dga;
998 pos = (struct _vs_cursor *) datap;
999 s = spl5();
1000 dga->x_cursor = TRANX(pos->x);
1001 dga->y_cursor = TRANY(pos->y);
1002 eq_header[unit]->curs_pos.x = pos->x;
1003 eq_header[unit]->curs_pos.y = pos->y;
1004 splx(s);
1005 break;
1006
1007 case QD_PRGCURSOR:
1008 /*
1009 * set the cursor acceleration factor
1010 */
1011 curs = (struct prg_cursor *) datap;
1012 s = spl5();
1013 qdflags[unit].curs_acc = curs->acc_factor;
1014 qdflags[unit].curs_thr = curs->threshold;
1015 splx(s);
1016 break;
1017
1018 case QD_MAPDEVICE:
1019 /*
1020 * enable 'user write' to device pages
1021 */
1022 qdflags[unit].mapped |= MAPDEV;
1023 qd = (struct qdmap *) &qdmap[unit];
1024 /*
1025 * enable user write to template RAM
1026 */
1027 mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
1028 ptep = (int *)(QVmap[0] + mapix);
1029 for (i = 0; i < btop(TMPSIZE); i++, ptep++)
1030 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1031 /*
1032 * enable user write to registers
1033 */
1034 mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
1035 ptep = (int *)(QVmap[0] + mapix);
1036 for (i = 0; i < btop(REGSIZE); i++, ptep++)
1037 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1038 /*
1039 * enable user write to color maps
1040 */
1041 mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
1042 ptep = (int *)(QVmap[0] + mapix);
1043 for (i = 0; i < btop(CLRSIZE); i++, ptep++)
1044 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1045 /*
1046 * enable user write to DUART
1047 */
1048 mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
1049 ptep = (int *)(QVmap[0] + mapix);
1050 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
1051
1052 mtpr(TBIA, 0); /* invalidate translation buffer */
1053
1054 /*
1055 * stuff qdmap structure in return buffer
1056 */
1057 bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
1058 break;
1059
1060 case QD_MAPIOBUF:
1061 /*
1062 * do setup for DMA by user process
1063 *
1064 * set 'user write enable' bits for DMA buffer
1065 */
1066 qdflags[unit].mapped |= MAPDMA;
1067 ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
1068 + (mfpr(SBR) | 0x80000000));
1069 for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
1070 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1071 mtpr(TBIA, 0); /* invalidate translation buffer */
1072 /*
1073 * set up QBUS map registers for DMA
1074 */
1075 DMAheader[unit]->QBAreg =
1076 uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
1077 if (DMAheader[unit]->QBAreg == 0)
1078 printf("qd%d: qdioctl: QBA setup error\n", unit);
1079 Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
1080 DMAheader[unit]->QBAreg &= 0x3FFFF;
1081 /*
1082 * return I/O buf adr
1083 */
1084 *(int *)datap = (int) DMAheader[unit];
1085 break;
1086
1087 case QD_MAPSCROLL:
1088 /*
1089 * map the shared scroll param area and enable scroll interpts
1090 */
1091 qdflags[unit].mapped |= MAPSCR;
1092 ptep = (int *) ((VTOP(scroll[unit]) * 4)
1093 + (mfpr(SBR) | 0x80000000));
1094 /*
1095 * allow user write to scroll area
1096 */
1097 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1098 mtpr(TBIA, 0); /* invalidate translation buf */
1099 scroll[unit]->status = 0;
1100 adder = (struct adder *) qdmap[unit].adder;
1101 qdflags[unit].adder_ie |= FRAME_SYNC;
1102 adder->interrupt_enable = qdflags[unit].adder_ie;
1103 *(int *)datap = (int) scroll[unit]; /* return scroll area */
1104 break;
1105
1106 case QD_UNMAPSCROLL:
1107 /*
1108 * unmap shared scroll param area and disable scroll intrpts
1109 */
1110 if (qdflags[unit].mapped & MAPSCR) {
1111 qdflags[unit].mapped &= ~MAPSCR;
1112 ptep = (int *) ((VTOP(scroll[unit]) * 4)
1113 + (mfpr(SBR) | 0x80000000));
1114 /*
1115 * re-protect 512 scroll param area
1116 */
1117 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1118 mtpr(TBIA, 0); /* smash CPU's translation buf */
1119 adder = (struct adder *) qdmap[unit].adder;
1120 qdflags[unit].adder_ie &= ~FRAME_SYNC;
1121 adder->interrupt_enable = qdflags[unit].adder_ie;
1122 }
1123 break;
1124
1125 case QD_MAPCOLOR:
1126 /*
1127 * map shared color map write buf and turn on vsync intrpt
1128 */
1129 qdflags[unit].mapped |= MAPCOLOR;
1130 ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1131 + (mfpr(SBR) | 0x80000000));
1132 /*
1133 * allow user write to color map write buffer
1134 */
1135 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
1136 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1137 mtpr(TBIA, 0); /* clr CPU translation buf */
1138 adder = (struct adder *) qdmap[unit].adder;
1139 qdflags[unit].adder_ie |= VSYNC;
1140 adder->interrupt_enable = qdflags[unit].adder_ie;
1141 /*
1142 * return color area address
1143 */
1144 *(int *)datap = (int) color_buf[unit];
1145 break;
1146
1147 case QD_UNMAPCOLOR:
1148 /*
1149 * unmap shared color map write buffer and kill VSYNC intrpts
1150 */
1151 if (qdflags[unit].mapped & MAPCOLOR) {
1152 qdflags[unit].mapped &= ~MAPCOLOR;
1153 ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1154 + (mfpr(SBR) | 0x80000000));
1155 /*
1156 * re-protect color map write buffer
1157 */
1158 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
1159 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1160 mtpr(TBIA, 0);
1161 adder = (struct adder *) qdmap[unit].adder;
1162 qdflags[unit].adder_ie &= ~VSYNC;
1163 adder->interrupt_enable = qdflags[unit].adder_ie;
1164 }
1165 break;
1166
1167 case QD_MAPEVENT:
1168 /*
1169 * give user write access to the event queue
1170 */
1171 qdflags[unit].mapped |= MAPEQ;
1172 ptep = (int *) ((VTOP(eq_header[unit]) * 4)
1173 + (mfpr(SBR) | 0x80000000));
1174 /*
1175 * allow user write to 1K event queue
1176 */
1177 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
1178 *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1179 mtpr(TBIA, 0); /* clr CPU translation buf */
1180 /*
1181 * return event queue address
1182 */
1183 *(int *)datap = (int)eq_header[unit];
1184 break;
1185
1186 case QD_PRGKBD:
1187 /*
1188 * pass caller's programming commands to LK201
1189 */
1190 duart = (struct duart *)qdmap[unit].duart;
1191 cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */
1192 /*
1193 * send command
1194 */
1195 for (i = 1000; i > 0; --i) {
1196 if (duart->statusA&XMT_RDY) {
1197 duart->dataA = cmdbuf->cmd;
1198 break;
1199 }
1200 }
1201 if (i == 0) {
1202 printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
1203 break;
1204 }
1205 /*
1206 * send param1?
1207 */
1208 if (cmdbuf->cmd & LAST_PARAM)
1209 break;
1210 for (i = 1000; i > 0; --i) {
1211 if (duart->statusA&XMT_RDY) {
1212 duart->dataA = cmdbuf->param1;
1213 break;
1214 }
1215 }
1216 if (i == 0) {
1217 printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
1218 break;
1219 }
1220 /*
1221 * send param2?
1222 */
1223 if (cmdbuf->param1 & LAST_PARAM)
1224 break;
1225 for (i = 1000; i > 0; --i) {
1226 if (duart->statusA&XMT_RDY) {
1227 duart->dataA = cmdbuf->param2;
1228 break;
1229 }
1230 }
1231 if (i == 0) {
1232 printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
1233 break;
1234 }
1235 break;
1236
1237 case QD_PRGMOUSE:
1238 /*
1239 * pass caller's programming commands to the mouse
1240 */
1241 duart = (struct duart *) qdmap[unit].duart;
1242 for (i = 1000; i > 0; --i) {
1243 if (duart->statusB&XMT_RDY) {
1244 duart->dataB = *datap;
1245 break;
1246 }
1247 }
1248 if (i == 0) {
1249 printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
1250 }
1251 break;
1252
1253 case QD_RDCONFIG:
1254 /*
1255 * get QDSS configuration word and return it
1256 */
1257 *(short *)datap = qdflags[unit].config;
1258 break;
1259
1260 case QD_KERN_LOOP:
1261 case QD_KERN_UNLOOP:
1262 /*
1263 * vestige from ultrix. BSD uses TIOCCONS to redirect
1264 * kernel console output.
1265 */
1266 break;
1267
1268 case QD_PRGTABLET:
1269 /*
1270 * program the tablet
1271 */
1272 duart = (struct duart *) qdmap[unit].duart;
1273 for (i = 1000; i > 0; --i) {
1274 if (duart->statusB&XMT_RDY) {
1275 duart->dataB = *datap;
1276 break;
1277 }
1278 }
1279 if (i == 0) {
1280 printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
1281 }
1282 break;
1283
1284 case QD_PRGTABRES:
1285 /*
1286 * program the tablet report resolution factor
1287 */
1288 qdflags[unit].tab_res = *(short *)datap;
1289 break;
1290
1291 default:
1292 /*
1293 * service tty ioctl's
1294 */
1295 if (!(minor_dev & 0x02)) {
1296 tp = &qd_tty[minor_dev];
1297 error =
1298 (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
1299 if (error >= 0) {
1300 return(error);
1301 }
1302 error = ttioctl(tp, cmd, datap, flags);
1303 if (error >= 0) {
1304 return(error);
1305 }
1306 }
1307 break;
1308 }
1309
1310 return(0);
1311
1312 } /* qdioctl */
1313
qdselect(dev,rw)1314 qdselect(dev, rw)
1315 dev_t dev;
1316 int rw;
1317 {
1318 register s;
1319 register unit;
1320 register struct tty *tp;
1321 u_int minor_dev = minor(dev);
1322
1323 s = spl5();
1324 unit = minor_dev >> 2;
1325
1326 switch (rw) {
1327 case FREAD:
1328 if ((minor_dev & 0x03) == 2) {
1329 /*
1330 * this is a graphics device, so check for events
1331 */
1332 if(!(ISEMPTY(eq_header[unit]))) {
1333 splx(s);
1334 return(1);
1335 }
1336 qdrsel[unit] = u.u_procp;
1337 qdflags[unit].selmask |= SEL_READ;
1338 splx(s);
1339 return(0);
1340 } else {
1341 /*
1342 * this is a tty device
1343 */
1344 tp = &qd_tty[minor_dev];
1345 if (ttnread(tp))
1346 return(1);
1347 tp->t_rsel = u.u_procp;
1348 splx(s);
1349 return(0);
1350 }
1351
1352 case FWRITE:
1353 if ((minor(dev) & 0x03) == 2) {
1354 /*
1355 * this is a graphics device, so check for dma buffers
1356 */
1357 if (DMA_ISEMPTY(DMAheader[unit]))
1358 {
1359 splx(s);
1360 return(1);
1361 }
1362 qdrsel[unit] = u.u_procp;
1363 qdflags[unit].selmask |= SEL_WRITE;
1364 splx(s);
1365 return(0);
1366 } else {
1367 /*
1368 * this is a tty device
1369 */
1370 tp = &qd_tty[minor_dev];
1371 if (tp->t_outq.c_cc <= tp->t_lowat)
1372 return(1);
1373 tp->t_wsel = u.u_procp;
1374 splx(s);
1375 return(0);
1376 }
1377 }
1378 splx(s);
1379 return(0);
1380
1381 } /* qdselect() */
1382
1383 extern qd_strategy();
1384
qdwrite(dev,uio)1385 qdwrite(dev, uio)
1386 dev_t dev;
1387 struct uio *uio;
1388 {
1389 register struct tty *tp;
1390 register minor_dev;
1391 register unit;
1392
1393 minor_dev = minor(dev);
1394 unit = (minor_dev >> 2) & 0x07;
1395
1396 if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
1397 /*
1398 * this is the console...
1399 */
1400 tp = &qd_tty[minor_dev];
1401 return ((*linesw[tp->t_line].l_write)(tp, uio));
1402 } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1403 /*
1404 * this is a DMA xfer from user space
1405 */
1406 return (physio(qd_strategy, &qdbuf[unit],
1407 dev, B_WRITE, minphys, uio));
1408 }
1409 return (ENXIO);
1410 }
1411
qdread(dev,uio)1412 qdread(dev, uio)
1413 dev_t dev;
1414 struct uio *uio;
1415 {
1416 register struct tty *tp;
1417 register minor_dev;
1418 register unit;
1419
1420 minor_dev = minor(dev);
1421 unit = (minor_dev >> 2) & 0x07;
1422
1423 if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
1424 /*
1425 * this is the console
1426 */
1427 tp = &qd_tty[minor_dev];
1428 return ((*linesw[tp->t_line].l_read)(tp, uio));
1429 } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1430 /*
1431 * this is a bitmap-to-processor xfer
1432 */
1433 return (physio(qd_strategy, &qdbuf[unit],
1434 dev, B_READ, minphys, uio));
1435 }
1436 return (ENXIO);
1437 }
1438
1439 /***************************************************************
1440 *
1441 * qd_strategy()... strategy routine to do DMA
1442 *
1443 ***************************************************************/
1444
qd_strategy(bp)1445 qd_strategy(bp)
1446 register struct buf *bp;
1447 {
1448 register struct dga *dga;
1449 register struct adder *adder;
1450 register unit;
1451 int QBAreg;
1452 int s;
1453 int cookie;
1454
1455 unit = (minor(bp->b_dev) >> 2) & 0x07;
1456
1457 /*
1458 * init pointers
1459 */
1460 if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
1461 printf("qd%d: qd_strategy: QBA setup error\n", unit);
1462 goto STRAT_ERR;
1463 }
1464 dga = (struct dga *) qdmap[unit].dga;
1465 s = spl5();
1466 qdflags[unit].user_dma = -1;
1467 dga->csr |= DMA_IE;
1468 cookie = QBAreg & 0x3FFFF;
1469 dga->adrs_lo = (short) cookie;
1470 dga->adrs_hi = (short) (cookie >> 16);
1471 dga->bytcnt_lo = (short) bp->b_bcount;
1472 dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
1473
1474 while (qdflags[unit].user_dma) {
1475 sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
1476 }
1477 splx(s);
1478 ubarelse(0, &QBAreg);
1479 if (!(dga->csr & DMA_ERR)) {
1480 iodone(bp);
1481 return;
1482 }
1483
1484 STRAT_ERR:
1485 adder = (struct adder *) qdmap[unit].adder;
1486 adder->command = CANCEL; /* cancel adder activity */
1487 dga->csr &= ~DMA_IE;
1488 dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
1489 dga->csr |= DMA_ERR; /* clear error condition */
1490 bp->b_flags |= B_ERROR; /* flag an error to physio() */
1491
1492 /*
1493 * if DMA was running, flush spurious intrpt
1494 */
1495 if (dga->bytcnt_lo != 0) {
1496 dga->bytcnt_lo = 0;
1497 dga->bytcnt_hi = 0;
1498 DMA_SETIGNORE(DMAheader[unit]);
1499 dga->csr |= DMA_IE;
1500 }
1501 iodone(bp);
1502
1503 } /* qd_strategy */
1504
1505 /*
1506 * Start output to the console screen
1507 */
qdstart(tp)1508 qdstart(tp)
1509 register struct tty *tp;
1510 {
1511 register which_unit, unit, c;
1512 int s;
1513
1514 unit = minor(tp->t_dev);
1515 which_unit = (unit >> 2) & 0x3;
1516 unit &= 0x03;
1517
1518 s = spl5();
1519
1520 /*
1521 * If it's currently active, or delaying, no need to do anything.
1522 */
1523 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1524 goto out;
1525
1526 /*
1527 * Display chars until the queue is empty.
1528 * Drop input from anything but the console
1529 * device on the floor.
1530 *
1531 * XXX - this loop is done at spltty.
1532 *
1533 */
1534 while (tp->t_outq.c_cc) {
1535 c = getc(&tp->t_outq);
1536 if (unit == 0)
1537 blitc(which_unit, (u_char)c);
1538 }
1539 /*
1540 * If there are sleepers, and output has drained below low
1541 * water mark, wake up the sleepers.
1542 */
1543 if (tp->t_outq.c_cc <= tp->t_lowat) {
1544 if (tp->t_state & TS_ASLEEP){
1545 tp->t_state &= ~TS_ASLEEP;
1546 wakeup((caddr_t) &tp->t_outq);
1547 }
1548 }
1549
1550 tp->t_state &= ~TS_BUSY;
1551
1552 out:
1553 splx(s);
1554
1555 } /* qdstart */
1556
1557 /*ARGSUSED*/
qdstop(tp,flag)1558 qdstop(tp, flag)
1559 register struct tty *tp;
1560 int flag;
1561 {
1562 register int s;
1563
1564 s = spl5(); /* block intrpts during state modification */
1565 if (tp->t_state & TS_BUSY)
1566 if ((tp->t_state & TS_TTSTOP) == 0)
1567 tp->t_state |= TS_FLUSH;
1568 else
1569 tp->t_state &= ~TS_BUSY;
1570 splx(s);
1571 }
1572
1573 /*
1574 * Output a character to the QDSS screen
1575 */
1576
blitc(unit,chr)1577 blitc(unit, chr)
1578 register unit;
1579 register u_char chr;
1580 {
1581 register struct adder *adder;
1582 register struct dga *dga;
1583 register int i;
1584 int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
1585 static short inescape[NQD];
1586
1587 adder = (struct adder *)qdmap[unit].adder;
1588 dga = (struct dga *) qdmap[unit].dga;
1589 /*
1590 * BSD comment: this (&=0177) defeats the extended character
1591 * set code for the glass tty, but if i had the time i would
1592 * spend it ripping out the code completely. This driver
1593 * is too big for its own good.
1594 */
1595 chr &= 0177;
1596 /*
1597 * Cursor addressing (so vi will work).
1598 * Decode for "\E=%.%." cursor motion description.
1599 * Corresponds to type "qdcons" in /etc/termcap:
1600 *
1601 * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
1602 * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
1603 *
1604 */
1605 if (inescape[unit] && nograph) {
1606 switch (inescape[unit]++) {
1607 case 1:
1608 if (chr != '=') {
1609 /* abort escape sequence */
1610 inescape[unit] = 0;
1611 blitc(unit, chr);
1612 }
1613 return;
1614 case 2:
1615 /* position row */
1616 cursor[unit].y = CHAR_HEIGHT * chr;
1617 if (cursor[unit].y > 863 - CHAR_HEIGHT)
1618 cursor[unit].y = 863 - CHAR_HEIGHT;
1619 dga->y_cursor = TRANY(cursor[unit].y);
1620 return;
1621 case 3:
1622 /* position column */
1623 cursor[unit].x = CHAR_WIDTH * chr;
1624 if (cursor[unit].x > 1024 - CHAR_WIDTH)
1625 cursor[unit].x = 1023 - CHAR_WIDTH;
1626 dga->x_cursor = TRANX(cursor[unit].x);
1627 inescape[unit] = 0;
1628 return;
1629 default:
1630 inescape[unit] = 0;
1631 blitc(unit, chr);
1632 }
1633 }
1634
1635 switch (chr) {
1636 case '\r': /* return char */
1637 cursor[unit].x = 0;
1638 if (nograph)
1639 dga->x_cursor = TRANX(cursor[unit].x);
1640 return;
1641
1642 case '\t': /* tab char */
1643 for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
1644 blitc(unit, ' ');
1645 }
1646 return;
1647
1648 case '\n': /* line feed char */
1649 if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1650 if (nograph) {
1651 cursor[unit].y -= CHAR_HEIGHT;
1652 scroll_up(adder);
1653 } else
1654 cursor[unit].y = 0;
1655 }
1656 if (nograph)
1657 dga->y_cursor = TRANY(cursor[unit].y);
1658 return;
1659
1660 case '\b': /* backspace char */
1661 if (cursor[unit].x > 0) {
1662 cursor[unit].x -= CHAR_WIDTH;
1663 if (nograph)
1664 dga->x_cursor = TRANX(cursor[unit].x);
1665 }
1666 return;
1667 case CTRL('k'): /* cursor up */
1668 if (nograph && cursor[unit].y > 0) {
1669 cursor[unit].y -= CHAR_HEIGHT;
1670 dga->y_cursor = TRANY(cursor[unit].y);
1671 }
1672 return;
1673
1674 case CTRL('^'): /* home cursor */
1675 if (nograph) {
1676 cursor[unit].x = 0;
1677 dga->x_cursor = TRANX(cursor[unit].x);
1678 cursor[unit].y = 0;
1679 dga->y_cursor = TRANY(cursor[unit].y);
1680 }
1681 return;
1682
1683 case CTRL('l'): /* cursor right */
1684 if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
1685 cursor[unit].x += CHAR_WIDTH;
1686 dga->x_cursor = TRANX(cursor[unit].x);
1687 }
1688 return;
1689
1690 case CTRL('z'): /* clear screen */
1691 if (nograph) {
1692 setup_dragon(unit);
1693 clear_qd_screen(unit);
1694 /* home cursor - termcap seems to assume this */
1695 cursor[unit].x = 0;
1696 dga->x_cursor = TRANX(cursor[unit].x);
1697 cursor[unit].y = 0;
1698 dga->y_cursor = TRANY(cursor[unit].y);
1699 }
1700 return;
1701
1702 case '\033': /* start escape sequence */
1703 if (nograph)
1704 inescape[unit] = 1;
1705 return;
1706
1707 default:
1708 if ((chr < ' ') || (chr > '~'))
1709 return;
1710 }
1711 /*
1712 * setup VIPER operand control registers
1713 */
1714 write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */
1715 write_ID(adder, SRC1_OCR_B,
1716 EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
1717 write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */
1718 write_ID(adder, SRC1_OCR_B,
1719 EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
1720 write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
1721 write_ID(adder, DST_OCR_B,
1722 EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
1723 write_ID(adder, MASK_1, 0xFFFF);
1724 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
1725 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1726 adder->x_clip_min = 0;
1727 adder->x_clip_max = 1024;
1728 adder->y_clip_min = 0;
1729 adder->y_clip_max = 864;
1730 /*
1731 * load DESTINATION origin and vectors
1732 */
1733 adder->fast_dest_dy = 0;
1734 adder->slow_dest_dx = 0;
1735 adder->error_1 = 0;
1736 adder->error_2 = 0;
1737 adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
1738 (void)wait_status(adder, RASTEROP_COMPLETE);
1739 adder->destination_x = cursor[unit].x;
1740 adder->fast_dest_dx = CHAR_WIDTH;
1741 adder->destination_y = cursor[unit].y;
1742 adder->slow_dest_dy = CHAR_HEIGHT;
1743 /*
1744 * load SOURCE origin and vectors
1745 */
1746 if ((chr - ' ') > (CHARS - 1)) {
1747 printf("Invalid character (x)%x in blitc\n",chr);
1748 chr = ' ';
1749 }
1750 /*
1751 * X position is modulo the number of characters per line
1752 */
1753 adder->source_1_x = FONT_X +
1754 (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
1755 /*
1756 * Point to either first or second row
1757 */
1758 adder->source_1_y = 2048 - 15 *
1759 (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
1760 adder->source_1_dx = CHAR_WIDTH;
1761 adder->source_1_dy = CHAR_HEIGHT;
1762 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
1763 adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1764 /*
1765 * update console cursor coordinates
1766 */
1767 cursor[unit].x += CHAR_WIDTH;
1768 if (nograph)
1769 dga->x_cursor = TRANX(cursor[unit].x);
1770 if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
1771 blitc(unit, '\r');
1772 blitc(unit, '\n');
1773 }
1774
1775 } /* blitc */
1776
qdreset()1777 qdreset() { }
1778
1779 /*
1780 * INTERRUPT SERVICE ROUTINES
1781 */
1782
1783 /*
1784 * Service "DMA DONE" interrupt condition
1785 */
qddint(qd)1786 qddint(qd)
1787 register qd;
1788 {
1789 register struct DMAreq_header *header;
1790 register struct DMAreq *request;
1791 register struct dga *dga;
1792 struct adder *adder;
1793 int cookie; /* DMA adrs for QDSS */
1794
1795 (void)spl4(); /* allow interval timer in */
1796
1797 /*
1798 * init pointers
1799 */
1800 header = DMAheader[qd]; /* register for optimization */
1801 dga = (struct dga *) qdmap[qd].dga;
1802 adder = (struct adder *) qdmap[qd].adder;
1803
1804 /*
1805 * if this interrupt flagged as bogus for interrupt flushing purposes..
1806 */
1807 if (DMA_ISIGNORE(header)) {
1808 DMA_CLRIGNORE(header);
1809 return;
1810 }
1811
1812 /*
1813 * dump a DMA hardware error message if appropriate
1814 */
1815 if (dga->csr & DMA_ERR) {
1816
1817 if (dga->csr & PARITY_ERR)
1818 printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
1819
1820 if (dga->csr & BUS_ERR)
1821 printf("qd%d: qddint: DMA hardware bus error.\n", qd);
1822 }
1823
1824 /*
1825 * if this was a DMA from user space...
1826 */
1827 if (qdflags[qd].user_dma) {
1828 qdflags[qd].user_dma = 0;
1829 wakeup((caddr_t)&qdflags[qd].user_dma);
1830 return;
1831 }
1832
1833 /*
1834 * if we're doing DMA request queue services, field the error condition
1835 */
1836 if (dga->csr & DMA_ERR) {
1837
1838 dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
1839 dga->csr |= DMA_ERR; /* clear error condition */
1840 adder->command = CANCEL; /* cancel adder activity */
1841
1842 DMA_SETERROR(header); /* flag error in header status word */
1843 DMA_CLRACTIVE(header);
1844 header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
1845 header->newest = header->oldest;
1846 header->used = 0;
1847
1848 if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
1849 selwakeup(qdrsel[qd], 0);
1850 qdrsel[qd] = 0;
1851 qdflags[qd].selmask &= ~SEL_WRITE;
1852 }
1853
1854 if (dga->bytcnt_lo != 0) {
1855 dga->bytcnt_lo = 0;
1856 dga->bytcnt_hi = 0;
1857 DMA_SETIGNORE(header);
1858 }
1859 return;
1860 }
1861
1862 /*
1863 * if the DMA request queue is now becoming non-full,
1864 * wakeup "select" client.
1865 */
1866 if (DMA_ISFULL(header)) {
1867 if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
1868 selwakeup(qdrsel[qd], 0);
1869 qdrsel[qd] = 0;
1870 qdflags[qd].selmask &= ~SEL_WRITE;
1871 }
1872 }
1873
1874 header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
1875 QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
1876
1877 /* check for unexpected interrupt */
1878 if (DMA_ISEMPTY(header))
1879 return;
1880
1881 DMA_GETEND(header); /* update request queue indices */
1882
1883 /*
1884 * if no more DMA pending, wake up "select" client and exit
1885 */
1886 if (DMA_ISEMPTY(header)) {
1887
1888 if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
1889 selwakeup(qdrsel[qd], 0);
1890 qdrsel[qd] = 0;
1891 qdflags[qd].selmask &= ~SEL_WRITE;
1892 }
1893
1894 DMA_CLRACTIVE(header); /* flag DMA done */
1895 return;
1896 }
1897
1898 /*
1899 * initiate next DMA xfer
1900 */
1901 request = DMA_GETBEGIN(header);
1902 if (request->DMAtype != QDlast_DMAtype) {
1903 dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
1904 adder->command = CANCEL; /* cancel adder activity */
1905 }
1906
1907
1908 switch (request->DMAtype) {
1909
1910 case DISPLIST:
1911 if (request->DMAtype != QDlast_DMAtype) {
1912 dga->csr |= DL_ENB;
1913 dga->csr &= ~(BTOP_ENB | BYTE_DMA);
1914 }
1915 break;
1916
1917 case PTOB:
1918 if (request->DMAtype != QDlast_DMAtype) {
1919 if (request->DMAdone & BYTE_PACK)
1920 dga->csr |= (PTOB_ENB | BYTE_DMA);
1921 else {
1922 dga->csr |= PTOB_ENB;
1923 dga->csr &= ~BYTE_DMA;
1924 }
1925 }
1926 break;
1927
1928 case BTOP:
1929 if (request->DMAtype != QDlast_DMAtype) {
1930 if (request->DMAdone & BYTE_PACK) {
1931 dga->csr &= ~DL_ENB;
1932 dga->csr |= (BTOP_ENB | BYTE_DMA);
1933 }
1934 else {
1935 dga->csr |= BTOP_ENB;
1936 dga->csr &= ~(BYTE_DMA | DL_ENB);
1937 }
1938 }
1939 break;
1940 default:
1941 printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
1942 DMA_CLRACTIVE(header); /* flag DMA done */
1943 return;
1944 }
1945
1946 if (request->DMAdone & COUNT_ZERO) {
1947 dga->csr &= ~SET_DONE_FIFO;
1948 }
1949 else if (request->DMAdone & FIFO_EMPTY) {
1950 dga->csr |= SET_DONE_FIFO;
1951 }
1952
1953 if (request->DMAdone & WORD_PACK)
1954 dga->csr &= ~BYTE_DMA;
1955 else if (request->DMAdone & BYTE_PACK)
1956 dga->csr |= BYTE_DMA;
1957
1958 dga->csr |= DMA_IE;
1959 QDlast_DMAtype = request->DMAtype;
1960
1961 cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
1962
1963 dga->adrs_lo = (short) cookie;
1964 dga->adrs_hi = (short) (cookie >> 16);
1965
1966 dga->bytcnt_lo = (short) request->length;
1967 dga->bytcnt_hi = (short) (request->length >> 16);
1968
1969 return;
1970 }
1971
1972 /*
1973 * ADDER interrupt service routine
1974 */
qdaint(qd)1975 qdaint(qd)
1976 register qd;
1977 {
1978 register struct adder *adder;
1979 struct color_buf *cbuf;
1980 int i;
1981 register struct rgb *rgbp;
1982 register short *red;
1983 register short *green;
1984 register short *blue;
1985
1986 (void)spl4(); /* allow interval timer in */
1987
1988 adder = (struct adder *) qdmap[qd].adder;
1989
1990 /*
1991 * service the vertical blank interrupt (VSYNC bit) by loading
1992 * any pending color map load request
1993 */
1994 if (adder->status & VSYNC) {
1995 adder->status &= ~VSYNC; /* clear the interrupt */
1996 cbuf = color_buf[qd];
1997 if (cbuf->status & LOAD_COLOR_MAP) {
1998
1999 red = (short *) qdmap[qd].red;
2000 green = (short *) qdmap[qd].green;
2001 blue = (short *) qdmap[qd].blue;
2002
2003 for (i = cbuf->count, rgbp = cbuf->rgb;
2004 --i >= 0; rgbp++) {
2005 red[rgbp->offset] = (short) rgbp->red;
2006 green[rgbp->offset] = (short) rgbp->green;
2007 blue[rgbp->offset] = (short) rgbp->blue;
2008 }
2009
2010 cbuf->status &= ~LOAD_COLOR_MAP;
2011 }
2012 }
2013
2014 /*
2015 * service the scroll interrupt (FRAME_SYNC bit)
2016 */
2017 if (adder->status & FRAME_SYNC) {
2018 adder->status &= ~FRAME_SYNC; /* clear the interrupt */
2019
2020 if (scroll[qd]->status & LOAD_REGS) {
2021
2022 for (i = 1000, adder->status = 0; i > 0 &&
2023 !(adder->status&ID_SCROLL_READY); --i)
2024 ;
2025
2026 if (i == 0) {
2027 printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
2028 qd);
2029 return;
2030 }
2031
2032 adder->ID_scroll_data = scroll[qd]->viper_constant;
2033 adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
2034
2035 adder->y_scroll_constant =
2036 scroll[qd]->y_scroll_constant;
2037 adder->y_offset_pending = scroll[qd]->y_offset;
2038
2039 if (scroll[qd]->status & LOAD_INDEX) {
2040
2041 adder->x_index_pending =
2042 scroll[qd]->x_index_pending;
2043 adder->y_index_pending =
2044 scroll[qd]->y_index_pending;
2045 }
2046
2047 scroll[qd]->status = 0x00;
2048 }
2049 }
2050 }
2051
2052 /*
2053 * DUART input interrupt service routine
2054 *
2055 * XXX - this routine should be broken out - it is essentially
2056 * straight line code.
2057 */
2058
qdiint(qd)2059 qdiint(qd)
2060 register qd;
2061 {
2062 register struct _vs_event *event;
2063 register struct qdinput *eqh;
2064 struct dga *dga;
2065 struct duart *duart;
2066 struct mouse_report *new_rep;
2067 struct uba_device *ui;
2068 struct tty *tp;
2069 u_short chr;
2070 u_short status;
2071 u_short data;
2072 u_short key;
2073 char do_wakeup = 0; /* flag to do a select wakeup call */
2074 char a, b, c; /* mouse button test variables */
2075
2076 (void)spl4(); /* allow interval timer in */
2077
2078 eqh = eq_header[qd]; /* optimized as a register */
2079 new_rep = ¤t_rep[qd];
2080 duart = (struct duart *) qdmap[qd].duart;
2081
2082 /*
2083 * if the graphic device is turned on..
2084 */
2085 if (qdflags[qd].inuse & GRAPHIC_DEV) {
2086 /*
2087 * empty DUART
2088 */
2089 while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
2090 /*
2091 * pick up LK-201 input (if any)
2092 */
2093 if (duart->statusA&RCV_RDY) {
2094
2095 /* if error condition, then reset it */
2096
2097 if (duart->statusA&0x70) {
2098 duart->cmdA = 0x40;
2099 continue;
2100 }
2101
2102 /* event queue full now? (overflow condition) */
2103
2104 if (ISFULL(eqh) == TRUE) {
2105 printf(
2106 "qd%d: qdiint: event queue overflow\n",
2107 qd);
2108 break;
2109 }
2110
2111 /*
2112 * Check for various keyboard errors */
2113
2114 key = duart->dataA & 0xFF;
2115
2116 if (key==LK_POWER_ERROR ||
2117 key==LK_KDOWN_ERROR ||
2118 key == LK_INPUT_ERROR ||
2119 key == LK_OUTPUT_ERROR) {
2120 printf(
2121 "qd%d: qdiint: keyboard error, code = %x\n",
2122 qd,key);
2123 return;
2124 }
2125
2126 if (key < LK_LOWEST)
2127 return;
2128
2129 ++do_wakeup; /* request a select wakeup call */
2130
2131 event = PUTBEGIN(eqh);
2132 PUTEND(eqh);
2133
2134 event->vse_key = key;
2135 event->vse_key &= 0x00FF;
2136 event->vse_x = eqh->curs_pos.x;
2137 event->vse_y = eqh->curs_pos.y;
2138 event->vse_time = TOY;
2139 event->vse_type = VSE_BUTTON;
2140 event->vse_direction = VSE_KBTRAW;
2141 event->vse_device = VSE_DKB;
2142 }
2143
2144 /*
2145 * pick up the mouse input (if any) */
2146
2147 if ((status = duart->statusB) & RCV_RDY &&
2148 qdflags[qd].pntr_id == MOUSE_ID) {
2149
2150 if (status & 0x70) {
2151 duart->cmdB = 0x40;
2152 continue;
2153 }
2154
2155 /* event queue full now? (overflow condition) */
2156
2157 if (ISFULL(eqh) == TRUE) {
2158 printf(
2159 "qd%d: qdiint: event queue overflow\n",
2160 qd);
2161 break;
2162 }
2163
2164 data = duart->dataB; /* get report byte */
2165 ++new_rep->bytcnt; /* bump report byte count */
2166
2167 /*
2168 * if 1st byte of report.. */
2169
2170 if ( data & START_FRAME) {
2171 new_rep->state = data;
2172 if (new_rep->bytcnt > 1) {
2173 /* start of new frame */
2174 new_rep->bytcnt = 1;
2175 /* ..continue looking */
2176 continue;
2177 }
2178 }
2179
2180 /*
2181 * if 2nd byte of report.. */
2182
2183 else if (new_rep->bytcnt == 2) {
2184 new_rep->dx = data & 0x00FF;
2185 }
2186
2187 /*
2188 * if 3rd byte of report, load input event queue */
2189
2190 else if (new_rep->bytcnt == 3) {
2191
2192 new_rep->dy = data & 0x00FF;
2193 new_rep->bytcnt = 0;
2194
2195 /*
2196 * if mouse position has changed.. */
2197
2198 if (new_rep->dx != 0 || new_rep->dy != 0) {
2199
2200 /*
2201 * calculate acceleration factor, if needed */
2202
2203 if (qdflags[qd].curs_acc > ACC_OFF) {
2204
2205 if (qdflags[qd].curs_thr <= new_rep->dx)
2206 new_rep->dx +=
2207 (new_rep->dx - qdflags[qd].curs_thr)
2208 * qdflags[qd].curs_acc;
2209
2210 if (qdflags[qd].curs_thr <= new_rep->dy)
2211 new_rep->dy +=
2212 (new_rep->dy - qdflags[qd].curs_thr)
2213 * qdflags[qd].curs_acc;
2214 }
2215
2216 /*
2217 * update cursor position coordinates */
2218
2219 if (new_rep->state & X_SIGN) {
2220 eqh->curs_pos.x += new_rep->dx;
2221 if (eqh->curs_pos.x > 1023)
2222 eqh->curs_pos.x = 1023;
2223 }
2224 else {
2225 eqh->curs_pos.x -= new_rep->dx;
2226 if (eqh->curs_pos.x < -15)
2227 eqh->curs_pos.x = -15;
2228 }
2229
2230 if (new_rep->state & Y_SIGN) {
2231 eqh->curs_pos.y -= new_rep->dy;
2232 if (eqh->curs_pos.y < -15)
2233 eqh->curs_pos.y = -15;
2234 }
2235 else {
2236 eqh->curs_pos.y += new_rep->dy;
2237 if (eqh->curs_pos.y > 863)
2238 eqh->curs_pos.y = 863;
2239 }
2240
2241 /*
2242 * update cursor screen position */
2243
2244 dga = (struct dga *) qdmap[qd].dga;
2245 dga->x_cursor = TRANX(eqh->curs_pos.x);
2246 dga->y_cursor = TRANY(eqh->curs_pos.y);
2247
2248 /*
2249 * if cursor is in the box, no event report */
2250
2251 if (eqh->curs_pos.x <= eqh->curs_box.right &&
2252 eqh->curs_pos.x >= eqh->curs_box.left &&
2253 eqh->curs_pos.y >= eqh->curs_box.top &&
2254 eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2255 goto GET_MBUTTON;
2256 }
2257
2258 /*
2259 * report the mouse motion event */
2260
2261 event = PUTBEGIN(eqh);
2262 PUTEND(eqh);
2263
2264 ++do_wakeup; /* request a select wakeup call */
2265
2266 event->vse_x = eqh->curs_pos.x;
2267 event->vse_y = eqh->curs_pos.y;
2268
2269 event->vse_device = VSE_MOUSE; /* mouse */
2270 event->vse_type = VSE_MMOTION; /* pos changed */
2271 event->vse_key = 0;
2272 event->vse_direction = 0;
2273 event->vse_time = TOY; /* time stamp */
2274 }
2275
2276 GET_MBUTTON:
2277 /*
2278 * if button state has changed */
2279
2280 a = new_rep->state & 0x07; /*mask nonbutton bits */
2281 b = last_rep[qd].state & 0x07;
2282
2283 if (a ^ b) {
2284
2285 for ( c = 1; c < 8; c <<= 1) {
2286
2287 if (!( c & (a ^ b))) /* this button change? */
2288 continue;
2289
2290 /* event queue full? (overflow condition) */
2291
2292 if (ISFULL(eqh) == TRUE) {
2293 printf("qd%d: qdiint: event queue overflow\n", qd);
2294 break;
2295 }
2296
2297 event = PUTBEGIN(eqh); /* get new event */
2298 PUTEND(eqh);
2299
2300 ++do_wakeup; /* request select wakeup */
2301
2302 event->vse_x = eqh->curs_pos.x;
2303 event->vse_y = eqh->curs_pos.y;
2304
2305 event->vse_device = VSE_MOUSE; /* mouse */
2306 event->vse_type = VSE_BUTTON; /* new button */
2307 event->vse_time = TOY; /* time stamp */
2308
2309 /* flag changed button and if up or down */
2310
2311 if (c == RIGHT_BUTTON)
2312 event->vse_key = VSE_RIGHT_BUTTON;
2313 else if (c == MIDDLE_BUTTON)
2314 event->vse_key = VSE_MIDDLE_BUTTON;
2315 else if (c == LEFT_BUTTON)
2316 event->vse_key = VSE_LEFT_BUTTON;
2317
2318 /* set bit = button depressed */
2319
2320 if (c & a)
2321 event->vse_direction = VSE_KBTDOWN;
2322 else
2323 event->vse_direction = VSE_KBTUP;
2324 }
2325 }
2326
2327 /* refresh last report */
2328
2329 last_rep[qd] = current_rep[qd];
2330
2331 } /* get last byte of report */
2332 } else if ((status = duart->statusB)&RCV_RDY &&
2333 qdflags[qd].pntr_id == TABLET_ID) {
2334 /*
2335 * pickup tablet input, if any
2336 */
2337 if (status&0x70) {
2338 duart->cmdB = 0x40;
2339 continue;
2340 }
2341 /*
2342 * event queue full now? (overflow condition)
2343 */
2344 if (ISFULL(eqh) == TRUE) {
2345 printf("qd%d: qdiint: event queue overflow\n", qd);
2346 break;
2347 }
2348
2349 data = duart->dataB; /* get report byte */
2350 ++new_rep->bytcnt; /* bump report byte count */
2351
2352 /*
2353 * if 1st byte of report.. */
2354
2355 if (data & START_FRAME) {
2356 new_rep->state = data;
2357 if (new_rep->bytcnt > 1) {
2358 new_rep->bytcnt = 1; /* start of new frame */
2359 continue; /* ..continue looking */
2360 }
2361 }
2362
2363 /*
2364 * if 2nd byte of report.. */
2365
2366 else if (new_rep->bytcnt == 2) {
2367 new_rep->dx = data & 0x3F;
2368 }
2369
2370 /*
2371 * if 3rd byte of report.. */
2372
2373 else if (new_rep->bytcnt == 3) {
2374 new_rep->dx |= (data & 0x3F) << 6;
2375 }
2376
2377 /*
2378 * if 4th byte of report.. */
2379
2380 else if (new_rep->bytcnt == 4) {
2381 new_rep->dy = data & 0x3F;
2382 }
2383
2384 /*
2385 * if 5th byte of report, load input event queue */
2386
2387 else if (new_rep->bytcnt == 5) {
2388
2389 new_rep->dy |= (data & 0x3F) << 6;
2390 new_rep->bytcnt = 0;
2391
2392 /*
2393 * update cursor position coordinates */
2394
2395 new_rep->dx /= qdflags[qd].tab_res;
2396 new_rep->dy = (2200 - new_rep->dy)
2397 / qdflags[qd].tab_res;
2398
2399 if (new_rep->dx > 1023) {
2400 new_rep->dx = 1023;
2401 }
2402 if (new_rep->dy > 863) {
2403 new_rep->dy = 863;
2404 }
2405
2406 /*
2407 * report an event if the puck/stylus has moved
2408 */
2409
2410 if (eqh->curs_pos.x != new_rep->dx ||
2411 eqh->curs_pos.y != new_rep->dy) {
2412
2413 eqh->curs_pos.x = new_rep->dx;
2414 eqh->curs_pos.y = new_rep->dy;
2415
2416 /*
2417 * update cursor screen position */
2418
2419 dga = (struct dga *) qdmap[qd].dga;
2420 dga->x_cursor = TRANX(eqh->curs_pos.x);
2421 dga->y_cursor = TRANY(eqh->curs_pos.y);
2422
2423 /*
2424 * if cursor is in the box, no event report
2425 */
2426
2427 if (eqh->curs_pos.x <= eqh->curs_box.right &&
2428 eqh->curs_pos.x >= eqh->curs_box.left &&
2429 eqh->curs_pos.y >= eqh->curs_box.top &&
2430 eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2431 goto GET_TBUTTON;
2432 }
2433
2434 /*
2435 * report the tablet motion event */
2436
2437 event = PUTBEGIN(eqh);
2438 PUTEND(eqh);
2439
2440 ++do_wakeup; /* request a select wakeup call */
2441
2442 event->vse_x = eqh->curs_pos.x;
2443 event->vse_y = eqh->curs_pos.y;
2444
2445 event->vse_device = VSE_TABLET; /* tablet */
2446 /*
2447 * right now, X handles tablet motion the same
2448 * as mouse motion
2449 */
2450 event->vse_type = VSE_MMOTION; /* pos changed */
2451 event->vse_key = 0;
2452 event->vse_direction = 0;
2453 event->vse_time = TOY; /* time stamp */
2454 }
2455 GET_TBUTTON:
2456 /*
2457 * if button state has changed */
2458
2459 a = new_rep->state & 0x1E; /* mask nonbutton bits */
2460 b = last_rep[qd].state & 0x1E;
2461
2462 if (a ^ b) {
2463
2464 /* event queue full now? (overflow condition) */
2465
2466 if (ISFULL(eqh) == TRUE) {
2467 printf("qd%d: qdiint: event queue overflow\n",qd);
2468 break;
2469 }
2470
2471 event = PUTBEGIN(eqh); /* get new event */
2472 PUTEND(eqh);
2473
2474 ++do_wakeup; /* request a select wakeup call */
2475
2476 event->vse_x = eqh->curs_pos.x;
2477 event->vse_y = eqh->curs_pos.y;
2478
2479 event->vse_device = VSE_TABLET; /* tablet */
2480 event->vse_type = VSE_BUTTON; /* button changed */
2481 event->vse_time = TOY; /* time stamp */
2482
2483 /* define the changed button and if up or down */
2484
2485 for ( c = 1; c <= 0x10; c <<= 1) {
2486 if (c & (a ^ b)) {
2487 if (c == T_LEFT_BUTTON)
2488 event->vse_key = VSE_T_LEFT_BUTTON;
2489 else if (c == T_FRONT_BUTTON)
2490 event->vse_key = VSE_T_FRONT_BUTTON;
2491 else if (c == T_RIGHT_BUTTON)
2492 event->vse_key = VSE_T_RIGHT_BUTTON;
2493 else if (c == T_BACK_BUTTON)
2494 event->vse_key = VSE_T_BACK_BUTTON;
2495 break;
2496 }
2497 }
2498
2499 /* set bit = button depressed */
2500
2501 if (c & a)
2502 event->vse_direction = VSE_KBTDOWN;
2503 else
2504 event->vse_direction = VSE_KBTUP;
2505 }
2506
2507 /* refresh last report */
2508
2509 last_rep[qd] = current_rep[qd];
2510
2511 } /* get last byte of report */
2512 } /* pick up tablet input */
2513
2514 } /* while input available.. */
2515
2516 /*
2517 * do select wakeup
2518 */
2519 if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
2520 selwakeup(qdrsel[qd], 0);
2521 qdrsel[qd] = 0;
2522 qdflags[qd].selmask &= ~SEL_READ;
2523 do_wakeup = 0;
2524 }
2525 } else {
2526 /*
2527 * if the graphic device is not turned on, this is console input
2528 */
2529 if (qdpolling)
2530 return;
2531 ui = qdinfo[qd];
2532 if (ui == 0 || ui->ui_alive == 0)
2533 return;
2534
2535 tp = &qd_tty[qd << 2];
2536
2537 /*
2538 * Get a character from the keyboard.
2539 */
2540 while (duart->statusA&RCV_RDY) {
2541 key = duart->dataA;
2542 key &= 0xFF;
2543 /*
2544 * Check for various keyboard errors
2545 */
2546 if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2547 key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2548 printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
2549 return;
2550 }
2551
2552 if (key < LK_LOWEST)
2553 return;
2554
2555 /*
2556 * See if its a state change key */
2557
2558 switch (key) {
2559
2560 case LOCK:
2561 q_keyboard.lock ^= 0xffff; /* toggle */
2562 if (q_keyboard.lock)
2563 (void)led_control(qd, LK_LED_ENABLE,
2564 LK_LED_LOCK);
2565 else
2566 (void)led_control(qd, LK_LED_DISABLE,
2567 LK_LED_LOCK);
2568 return;
2569
2570 case SHIFT:
2571 q_keyboard.shift ^= 0xFFFF;
2572 return;
2573
2574 case CNTRL:
2575 q_keyboard.cntrl ^= 0xFFFF;
2576 return;
2577
2578 case ALLUP:
2579 q_keyboard.cntrl = 0;
2580 q_keyboard.shift = 0;
2581 return;
2582
2583 case REPEAT:
2584 chr = q_keyboard.last;
2585 break;
2586
2587 /*
2588 * Test for cntrl characters. If set, see if the character
2589 * is elligible to become a control character. */
2590
2591 default:
2592
2593 if (q_keyboard.cntrl) {
2594 chr = q_key[key];
2595 if (chr >= ' ' && chr <= '~')
2596 chr &= 0x1F;
2597 else if (chr >= 0xA1 && chr <= 0xFE)
2598 chr &= 0x9F;
2599 }
2600 else if( q_keyboard.lock || q_keyboard.shift )
2601 chr = q_shift_key[key];
2602 else
2603 chr = q_key[key];
2604 break;
2605 }
2606
2607 q_keyboard.last = chr;
2608
2609 /*
2610 * Check for special function keys */
2611
2612 if (chr & 0x100) {
2613 char *string;
2614 string = q_special[chr & 0x7F];
2615 while(*string)
2616 (*linesw[tp->t_line].l_rint)(*string++, tp);
2617 }
2618 else {
2619 #ifdef KADB
2620 if (!kdbrintr(chr&0177, tp))
2621 #endif
2622 (*linesw[tp->t_line].l_rint)(chr&0177, tp);
2623 }
2624 }
2625 }
2626 } /* qdiint */
2627
2628 /*
2629 *
2630 * Clear the QDSS screen
2631 *
2632 * >>> NOTE <<<
2633 *
2634 * This code requires that certain adder initialization be valid. To
2635 * assure that this requirement is satisfied, this routine should be
2636 * called only after calling the "setup_dragon()" function.
2637 *
2638 * Clear the bitmap a piece at a time. Since the fast scroll clear
2639 * only clears the current displayed portion of the bitmap put a
2640 * temporary value in the y limit register so we can access whole
2641 * bitmap
2642 *
2643 */
clear_qd_screen(unit)2644 clear_qd_screen(unit)
2645 int unit;
2646 {
2647 register struct adder *adder;
2648 adder = (struct adder *) qdmap[unit].adder;
2649
2650 adder->x_limit = 1024;
2651 adder->y_limit = 2048 - CHAR_HEIGHT;
2652 adder->y_offset_pending = 0;
2653 #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
2654 WSV;
2655 adder->y_scroll_constant = SCROLL_ERASE;
2656 WSV;
2657 adder->y_offset_pending = 864;
2658 WSV;
2659 adder->y_scroll_constant = SCROLL_ERASE;
2660 WSV;
2661 adder->y_offset_pending = 1728;
2662 WSV;
2663 adder->y_scroll_constant = SCROLL_ERASE;
2664 WSV;
2665 adder->y_offset_pending = 0; /* back to normal */
2666 WSV;
2667 adder->x_limit = MAX_SCREEN_X;
2668 adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2669 #undef WSV
2670
2671 } /* clear_qd_screen */
2672
2673 /*
2674 * kernel console output to the glass tty
2675 */
qdputc(chr)2676 qdputc(chr)
2677 register char chr;
2678 {
2679
2680 /*
2681 * if system is now physical, forget it (ie: crash DUMP)
2682 */
2683 if ((mfpr(MAPEN) & 1) == 0)
2684 return;
2685
2686 blitc(0, (u_char)(chr & 0xff));
2687 if ((chr & 0177) == '\n')
2688 blitc(0, '\r');
2689
2690 } /* qdputc */
2691
2692 /*
2693 * load the mouse cursor's template RAM bitmap
2694 */
ldcursor(unit,bitmap)2695 ldcursor(unit, bitmap)
2696 int unit;
2697 register short *bitmap;
2698 {
2699 register struct dga *dga;
2700 register short *temp;
2701 register int i;
2702 int curs;
2703
2704 dga = (struct dga *) qdmap[unit].dga;
2705 temp = (short *) qdmap[unit].template;
2706
2707 if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */
2708 curs = -1; /* ..note that.. */
2709 dga->csr &= ~CURS_ENB; /* ..and shut it off */
2710 } else
2711 curs = 0;
2712
2713 dga->csr &= ~CURS_ENB; /* shut off the cursor */
2714
2715 temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */
2716 /* ..of the 8k WORD template space */
2717 for (i = 0; i < 32; ++i)
2718 *temp++ = *bitmap++;
2719
2720 if (curs) { /* if cursor was enabled.. */
2721 dga->csr |= CURS_ENB; /* ..turn it back on */
2722 }
2723
2724 } /* ldcursor */
2725
2726 /*
2727 * Put the console font in the QDSS off-screen memory
2728 */
ldfont(unit)2729 ldfont(unit)
2730 int unit;
2731 {
2732 register struct adder *adder;
2733
2734 register i, j, k, max_chars_line;
2735 register short packed;
2736
2737 adder = (struct adder *) qdmap[unit].adder;
2738
2739 /*
2740 * setup VIPER operand control registers
2741 */
2742 write_ID(adder, MASK_1, 0xFFFF);
2743 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
2744 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
2745
2746 write_ID(adder, SRC1_OCR_B,
2747 EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
2748 write_ID(adder, SRC2_OCR_B,
2749 EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
2750 write_ID(adder, DST_OCR_B,
2751 EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
2752
2753 adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
2754
2755 /*
2756 * load destination data
2757 */
2758 (void)wait_status(adder, RASTEROP_COMPLETE);
2759
2760 adder->destination_x = FONT_X;
2761 adder->destination_y = FONT_Y;
2762 #if FONT_WIDTH > MAX_SCREEN_X
2763 adder->fast_dest_dx = MAX_SCREEN_X;
2764 #else
2765 adder->fast_dest_dx = FONT_WIDTH;
2766 #endif
2767 adder->slow_dest_dy = CHAR_HEIGHT;
2768
2769 /*
2770 * setup for processor to bitmap xfer */
2771
2772 write_ID(adder, CS_UPDATE_MASK, 0x0001);
2773 adder->cmd = PBT | OCRB | 2 | DTE | 2;
2774
2775 /*
2776 * Figure out how many characters can be stored on one "line" of
2777 * offscreen memory.
2778 */
2779 max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2780 if ((CHARS/2 + CHARS%2) < max_chars_line)
2781 max_chars_line = CHARS/2 + CHARS%2;
2782
2783 /*
2784 * iteratively do the processor to bitmap xfer */
2785
2786 for (i = 0; i < ROWS; ++i) {
2787
2788 /* PTOB a scan line */
2789
2790 for (j = 0, k = i; j < max_chars_line; ++j) {
2791 /* PTOB one scan of a char cell */
2792
2793 packed = q_font[k];
2794 k += ROWS;
2795 packed |= ((short)q_font[k] << 8);
2796 k += ROWS;
2797
2798 (void)wait_status(adder, TX_READY);
2799 adder->id_data = packed;
2800 }
2801 }
2802
2803 /*
2804 * (XXX XXX XXX - should remove)
2805 *
2806 * Copy the second row of characters. Subtract the first
2807 * row from the total number. Divide this quantity by 2
2808 * because 2 chars are stored in a short in the PTOB loop
2809 * below. Figure out how many characters can be stored on
2810 * one "line" of offscreen memory
2811 */
2812
2813 max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2814 if ((CHARS/2 + CHARS%2) < max_chars_line)
2815 return;
2816 max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
2817 /* Paranoia check to see if 3rd row may be needed */
2818 if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
2819 max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2820
2821 adder->destination_x = FONT_X;
2822 adder->destination_y = FONT_Y - CHAR_HEIGHT;
2823 adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
2824 adder->slow_dest_dy = CHAR_HEIGHT;
2825
2826 /*
2827 * setup for processor to bitmap xfer
2828 */
2829 write_ID(adder, CS_UPDATE_MASK, 0x0001);
2830 adder->cmd = PBT | OCRB | 2 | DTE | 2;
2831
2832 /*
2833 * iteratively do the processor to bitmap xfer
2834 */
2835 for (i = 0; i < ROWS; ++i) {
2836 /*
2837 * PTOB a scan line
2838 */
2839 for (j = 0, k = i; j < max_chars_line; ++j) {
2840 /*
2841 * PTOB one scan of a char cell
2842 */
2843 packed = q_font[k + FONT_OFFSET];
2844 k += ROWS;
2845 packed |= ((short)q_font[k + FONT_OFFSET] << 8);
2846 k += ROWS;
2847 (void)wait_status(adder, TX_READY);
2848 adder->id_data = packed;
2849 }
2850 }
2851
2852 } /* ldfont */
2853
qdpoll(onoff)2854 qdpoll(onoff)
2855 {
2856 qdpolling = onoff;
2857 }
2858
2859 /*
2860 * Get a character from the LK201 (polled)
2861 */
qdgetc()2862 qdgetc()
2863 {
2864 register short key;
2865 register char chr;
2866 register struct duart *duart;
2867
2868 duart = (struct duart *) qdmap[0].duart;
2869
2870 /*
2871 * Get a character from the keyboard.
2872 */
2873 LOOP:
2874 while (!(duart->statusA&RCV_RDY))
2875 ;
2876
2877 key = duart->dataA;
2878 key &= 0xFF;
2879
2880 /*
2881 * Check for various keyboard errors */
2882
2883 if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2884 key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2885 printf("Keyboard error, code = %x\n", key);
2886 return(0);
2887 }
2888
2889 if (key < LK_LOWEST)
2890 return(0);
2891
2892 /*
2893 * See if its a state change key
2894 */
2895 switch (key) {
2896
2897 case LOCK:
2898 q_keyboard.lock ^= 0xffff; /* toggle */
2899 if (q_keyboard.lock)
2900 (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
2901 else
2902 (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
2903 goto LOOP;
2904
2905 case SHIFT:
2906 q_keyboard.shift ^= 0xFFFF;
2907 goto LOOP;
2908
2909 case CNTRL:
2910 q_keyboard.cntrl ^= 0xFFFF;
2911 goto LOOP;
2912
2913 case ALLUP:
2914 q_keyboard.cntrl = 0;
2915 q_keyboard.shift = 0;
2916 goto LOOP;
2917
2918 case REPEAT:
2919 chr = q_keyboard.last;
2920 break;
2921
2922 /*
2923 * Test for cntrl characters. If set, see if the character
2924 * is elligible to become a control character.
2925 */
2926 default:
2927
2928 if (q_keyboard.cntrl) {
2929 chr = q_key[key];
2930 if (chr >= ' ' && chr <= '~')
2931 chr &= 0x1F;
2932 }
2933 else if ( q_keyboard.lock || q_keyboard.shift )
2934 chr = q_shift_key[key];
2935 else
2936 chr = q_key[key];
2937 break;
2938 }
2939
2940 if (chr < ' ' && chr > '~') /* if input is non-displayable */
2941 return(0); /* ..then pitch it! */
2942
2943 q_keyboard.last = chr;
2944
2945 /*
2946 * Check for special function keys */
2947
2948 if (chr & 0x80) /* pitch the function keys */
2949 return(0);
2950 else
2951 return(chr);
2952
2953 } /* qdgetc */
2954
2955 /*
2956 * led_control()... twiddle LK-201 LED's
2957 */
led_control(unit,cmd,led_mask)2958 led_control(unit, cmd, led_mask)
2959 int unit, cmd, led_mask;
2960 {
2961 register i;
2962 register struct duart *duart;
2963
2964 duart = (struct duart *)qdmap[unit].duart;
2965
2966 for (i = 1000; i > 0; --i) {
2967 if (duart->statusA&XMT_RDY) {
2968 duart->dataA = cmd;
2969 break;
2970 }
2971 }
2972 for (i = 1000; i > 0; --i) {
2973 if (duart->statusA&XMT_RDY) {
2974 duart->dataA = led_mask;
2975 break;
2976 }
2977 }
2978 if (i == 0)
2979 return(BAD);
2980 return(GOOD);
2981
2982 } /* led_control */
2983
2984 /*
2985 * scroll_up()... move the screen up one character height
2986 */
scroll_up(adder)2987 scroll_up(adder)
2988 register struct adder *adder;
2989 {
2990 /*
2991 * setup VIPER operand control registers
2992 */
2993 (void)wait_status(adder, ADDRESS_COMPLETE);
2994 write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
2995 write_ID(adder, MASK_1, 0xFFFF);
2996 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
2997 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
2998 write_ID(adder, SRC1_OCR_B,
2999 EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
3000 write_ID(adder, DST_OCR_B,
3001 EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3002 /*
3003 * load DESTINATION origin and vectors
3004 */
3005 adder->fast_dest_dy = 0;
3006 adder->slow_dest_dx = 0;
3007 adder->error_1 = 0;
3008 adder->error_2 = 0;
3009 adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
3010 adder->destination_x = 0;
3011 adder->fast_dest_dx = 1024;
3012 adder->destination_y = 0;
3013 adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3014 /*
3015 * load SOURCE origin and vectors
3016 */
3017 adder->source_1_x = 0;
3018 adder->source_1_dx = 1024;
3019 adder->source_1_y = 0 + CHAR_HEIGHT;
3020 adder->source_1_dy = 864 - CHAR_HEIGHT;
3021 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3022 adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3023 /*
3024 * do a rectangle clear of last screen line
3025 */
3026 write_ID(adder, MASK_1, 0xffff);
3027 write_ID(adder, SOURCE, 0xffff);
3028 write_ID(adder,DST_OCR_B,
3029 (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
3030 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
3031 adder->error_1 = 0;
3032 adder->error_2 = 0;
3033 adder->slow_dest_dx = 0; /* set up the width of */
3034 adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */
3035 adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
3036 (void)wait_status(adder, RASTEROP_COMPLETE);
3037 adder->destination_x = 0;
3038 adder->destination_y = 864 - CHAR_HEIGHT;
3039 adder->fast_dest_dx = 1024; /* set up the height */
3040 adder->fast_dest_dy = 0; /* of rectangle */
3041 write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
3042 adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
3043
3044 } /* scroll_up */
3045
3046 /*
3047 * init shared memory pointers and structures
3048 */
init_shared(unit)3049 init_shared(unit)
3050 register unit;
3051 {
3052 register struct dga *dga;
3053
3054 dga = (struct dga *) qdmap[unit].dga;
3055
3056 /*
3057 * initialize the event queue pointers and header */
3058
3059 eq_header[unit] = (struct qdinput *)
3060 ((((int)event_shared & ~(0x01FF)) + 512)
3061 + (EVENT_BUFSIZE * unit));
3062 eq_header[unit]->curs_pos.x = 0;
3063 eq_header[unit]->curs_pos.y = 0;
3064 dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
3065 dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
3066 eq_header[unit]->curs_box.left = 0;
3067 eq_header[unit]->curs_box.right = 0;
3068 eq_header[unit]->curs_box.top = 0;
3069 eq_header[unit]->curs_box.bottom = 0;
3070 /*
3071 * assign a pointer to the DMA I/O buffer for this QDSS.
3072 */
3073 DMAheader[unit] = (struct DMAreq_header *)
3074 (((int)(&DMA_shared[0] + 512) & ~0x1FF)
3075 + (DMAbuf_size * unit));
3076 DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
3077 + sizeof(struct DMAreq_header));
3078 DMAheader[unit]->QBAreg = 0;
3079 DMAheader[unit]->status = 0;
3080 DMAheader[unit]->shared_size = DMAbuf_size;
3081 DMAheader[unit]->used = 0;
3082 DMAheader[unit]->size = 10; /* default = 10 requests */
3083 DMAheader[unit]->oldest = 0;
3084 DMAheader[unit]->newest = 0;
3085 /*
3086 * assign a pointer to the scroll structure for this QDSS.
3087 */
3088 scroll[unit] = (struct scroll *)
3089 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
3090 + (sizeof(struct scroll) * unit));
3091 scroll[unit]->status = 0;
3092 scroll[unit]->viper_constant = 0;
3093 scroll[unit]->y_scroll_constant = 0;
3094 scroll[unit]->y_offset = 0;
3095 scroll[unit]->x_index_pending = 0;
3096 scroll[unit]->y_index_pending = 0;
3097 /*
3098 * assign a pointer to the color map write buffer for this QDSS
3099 */
3100 color_buf[unit] = (struct color_buf *)
3101 (((int)(&color_shared[0] + 512) & ~0x1FF)
3102 + (COLOR_BUFSIZ * unit));
3103 color_buf[unit]->status = 0;
3104 color_buf[unit]->count = 0;
3105
3106 } /* init_shared */
3107
3108 /*
3109 * init the ADDER, VIPER, bitmaps, & color map
3110 */
setup_dragon(unit)3111 setup_dragon(unit)
3112 int unit;
3113 {
3114
3115 register struct adder *adder;
3116 register struct dga *dga;
3117 short *memcsr;
3118 register i;
3119 short top; /* clipping/scrolling boundaries */
3120 short bottom;
3121 short right;
3122 short left;
3123 short *red; /* color map pointers */
3124 short *green;
3125 short *blue;
3126
3127 /*
3128 * init for setup
3129 */
3130 adder = (struct adder *) qdmap[unit].adder;
3131 dga = (struct dga *) qdmap[unit].dga;
3132 memcsr = (short *) qdmap[unit].memcsr;
3133 dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */
3134 *memcsr = SYNC_ON; /* blank screen and turn off LED's */
3135 adder->command = CANCEL;
3136 /*
3137 * set monitor timing
3138 */
3139 adder->x_scan_count_0 = 0x2800;
3140 adder->x_scan_count_1 = 0x1020;
3141 adder->x_scan_count_2 = 0x003A;
3142 adder->x_scan_count_3 = 0x38F0;
3143 adder->x_scan_count_4 = 0x6128;
3144 adder->x_scan_count_5 = 0x093A;
3145 adder->x_scan_count_6 = 0x313C;
3146 adder->sync_phase_adj = 0x0100;
3147 adder->x_scan_conf = 0x00C8;
3148 /*
3149 * got a bug in secound pass ADDER! lets take care of it
3150 *
3151 * normally, just use the code in the following bug fix code, but to
3152 * make repeated demos look pretty, load the registers as if there was
3153 * no bug and then test to see if we are getting sync
3154 */
3155 adder->y_scan_count_0 = 0x135F;
3156 adder->y_scan_count_1 = 0x3363;
3157 adder->y_scan_count_2 = 0x2366;
3158 adder->y_scan_count_3 = 0x0388;
3159 /*
3160 * if no sync, do the bug fix code
3161 */
3162 if (wait_status(adder, VSYNC) == BAD) {
3163 /* first load all Y scan registers with very short frame and
3164 * wait for scroll service. This guarantees at least one SYNC
3165 * to fix the pass 2 Adder initialization bug (synchronizes
3166 * XCINCH with DMSEEDH)
3167 */
3168 adder->y_scan_count_0 = 0x01;
3169 adder->y_scan_count_1 = 0x01;
3170 adder->y_scan_count_2 = 0x01;
3171 adder->y_scan_count_3 = 0x01;
3172 /*
3173 * delay at least 1 full frame time
3174 */
3175 (void)wait_status(adder, VSYNC);
3176 (void)wait_status(adder, VSYNC);
3177 /*
3178 * now load the REAL sync values (in reverse order just to
3179 * be safe.
3180 */
3181 adder->y_scan_count_3 = 0x0388;
3182 adder->y_scan_count_2 = 0x2366;
3183 adder->y_scan_count_1 = 0x3363;
3184 adder->y_scan_count_0 = 0x135F;
3185 }
3186 *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */
3187 /*
3188 * zero the index registers
3189 */
3190 adder->x_index_pending = 0;
3191 adder->y_index_pending = 0;
3192 adder->x_index_new = 0;
3193 adder->y_index_new = 0;
3194 adder->x_index_old = 0;
3195 adder->y_index_old = 0;
3196 adder->pause = 0;
3197 /*
3198 * set rasterop mode to normal pen down
3199 */
3200 adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3201 /*
3202 * set the rasterop registers to a default values
3203 */
3204 adder->source_1_dx = 1;
3205 adder->source_1_dy = 1;
3206 adder->source_1_x = 0;
3207 adder->source_1_y = 0;
3208 adder->destination_x = 0;
3209 adder->destination_y = 0;
3210 adder->fast_dest_dx = 1;
3211 adder->fast_dest_dy = 0;
3212 adder->slow_dest_dx = 0;
3213 adder->slow_dest_dy = 1;
3214 adder->error_1 = 0;
3215 adder->error_2 = 0;
3216 /*
3217 * scale factor = UNITY
3218 */
3219 adder->fast_scale = UNITY;
3220 adder->slow_scale = UNITY;
3221 /*
3222 * set the source 2 parameters
3223 */
3224 adder->source_2_x = 0;
3225 adder->source_2_y = 0;
3226 adder->source_2_size = 0x0022;
3227 /*
3228 * initialize plane addresses for eight vipers
3229 */
3230 write_ID(adder, CS_UPDATE_MASK, 0x0001);
3231 write_ID(adder, PLANE_ADDRESS, 0x0000);
3232 write_ID(adder, CS_UPDATE_MASK, 0x0002);
3233 write_ID(adder, PLANE_ADDRESS, 0x0001);
3234 write_ID(adder, CS_UPDATE_MASK, 0x0004);
3235 write_ID(adder, PLANE_ADDRESS, 0x0002);
3236 write_ID(adder, CS_UPDATE_MASK, 0x0008);
3237 write_ID(adder, PLANE_ADDRESS, 0x0003);
3238 write_ID(adder, CS_UPDATE_MASK, 0x0010);
3239 write_ID(adder, PLANE_ADDRESS, 0x0004);
3240 write_ID(adder, CS_UPDATE_MASK, 0x0020);
3241 write_ID(adder, PLANE_ADDRESS, 0x0005);
3242 write_ID(adder, CS_UPDATE_MASK, 0x0040);
3243 write_ID(adder, PLANE_ADDRESS, 0x0006);
3244 write_ID(adder, CS_UPDATE_MASK, 0x0080);
3245 write_ID(adder, PLANE_ADDRESS, 0x0007);
3246 /*
3247 * initialize the external registers.
3248 */
3249 write_ID(adder, CS_UPDATE_MASK, 0x00FF);
3250 write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3251 /*
3252 * initialize resolution mode
3253 */
3254 write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */
3255 write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */
3256 /*
3257 * initialize viper registers
3258 */
3259 write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
3260 write_ID(adder, SCROLL_FILL, 0x0000);
3261 /*
3262 * set clipping and scrolling limits to full screen
3263 */
3264 for (i = 1000, adder->status = 0;
3265 i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
3266 ;
3267 if (i == 0)
3268 printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
3269 top = 0;
3270 bottom = 2048;
3271 left = 0;
3272 right = 1024;
3273 adder->x_clip_min = left;
3274 adder->x_clip_max = right;
3275 adder->y_clip_min = top;
3276 adder->y_clip_max = bottom;
3277 adder->scroll_x_min = left;
3278 adder->scroll_x_max = right;
3279 adder->scroll_y_min = top;
3280 adder->scroll_y_max = bottom;
3281 (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */
3282 (void)wait_status(adder, VSYNC);
3283 adder->x_index_pending = left;
3284 adder->y_index_pending = top;
3285 adder->x_index_new = left;
3286 adder->y_index_new = top;
3287 adder->x_index_old = left;
3288 adder->y_index_old = top;
3289
3290 for (i = 1000, adder->status = 0; i > 0 &&
3291 !(adder->status&ADDRESS_COMPLETE) ; --i)
3292 ;
3293 if (i == 0)
3294 printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
3295
3296 write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
3297 write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3298 /*
3299 * set source and the mask register to all ones (ie: white) o
3300 */
3301 write_ID(adder, SOURCE, 0xFFFF);
3302 write_ID(adder, MASK_1, 0xFFFF);
3303 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3304 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3305 /*
3306 * initialize Operand Control Register banks for fill command
3307 */
3308 write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT);
3309 write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
3310 write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3311 write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
3312 write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT);
3313 write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3314 /*
3315 * init Logic Unit Function registers, (these are just common values,
3316 * and may be changed as required).
3317 */
3318 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3319 write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
3320 INV_M1_M2);
3321 write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
3322 write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3323 /*
3324 * load the color map for black & white
3325 */
3326 for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
3327 ;
3328
3329 if (i == 0)
3330 printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
3331
3332 red = (short *) qdmap[unit].red;
3333 green = (short *) qdmap[unit].green;
3334 blue = (short *) qdmap[unit].blue;
3335
3336 *red++ = 0x00; /* black */
3337 *green++ = 0x00;
3338 *blue++ = 0x00;
3339
3340 *red-- = 0xFF; /* white */
3341 *green-- = 0xFF;
3342 *blue-- = 0xFF;
3343
3344 /*
3345 * set color map for mouse cursor
3346 */
3347
3348 red += 254;
3349 green += 254;
3350 blue += 254;
3351
3352 *red++ = 0x00; /* black */
3353 *green++ = 0x00;
3354 *blue++ = 0x00;
3355
3356 *red = 0xFF; /* white */
3357 *green = 0xFF;
3358 *blue = 0xFF;
3359
3360 } /* setup_dragon */
3361
3362 /*
3363 * Init the DUART and set defaults in input
3364 */
setup_input(unit)3365 setup_input(unit)
3366 int unit;
3367 {
3368 register struct duart *duart; /* DUART register structure pointer */
3369 register i, bits;
3370 char id_byte;
3371
3372 duart = (struct duart *) qdmap[unit].duart;
3373 duart->imask = 0;
3374
3375 /*
3376 * setup the DUART for kbd & pointing device
3377 */
3378 duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */
3379 duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */
3380 /* no RTS control,char error mode */
3381 duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */
3382 /* no RTS control,no echo or loop */
3383 duart->cmdB = RESET_M; /* reset mode reg pntr for host */
3384 duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */
3385 /* ..no RTS cntrl, char error mode */
3386 duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */
3387 /* no RTS control,no echo or loop */
3388 duart->auxctl = 0x00; /* baud rate set 1 */
3389 duart->clkselA = 0x99; /* 4800 baud for kbd */
3390 duart->clkselB = 0x99; /* 4800 baud for mouse */
3391
3392 /* reset everything for keyboard */
3393
3394 for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3395 duart->cmdA = bits;
3396
3397 /* reset everything for host */
3398
3399 for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3400 duart->cmdB = bits;
3401
3402 duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
3403 duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
3404
3405 /*
3406 * init keyboard defaults (DUART channel A)
3407 */
3408 for (i = 500; i > 0; --i) {
3409 if (duart->statusA&XMT_RDY) {
3410 duart->dataA = LK_DEFAULTS;
3411 break;
3412 }
3413 }
3414
3415 for (i = 100000; i > 0; --i) {
3416 if (duart->statusA&RCV_RDY) {
3417 break;
3418 }
3419 }
3420
3421 if (duart->dataA) /* flush the ACK */
3422 ;
3423
3424 /*
3425 * identify the pointing device
3426 */
3427 for (i = 500; i > 0; --i) {
3428 if (duart->statusB&XMT_RDY) {
3429 duart->dataB = SELF_TEST;
3430 break;
3431 }
3432 }
3433
3434 /*
3435 * wait for 1st byte of self test report */
3436
3437 for (i = 100000; i > 0; --i) {
3438 if (duart->statusB&RCV_RDY) {
3439 break;
3440 }
3441 }
3442
3443 if (i == 0) {
3444 printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
3445 ,unit);
3446 goto OUT;
3447 }
3448
3449 if (duart->dataB)
3450 ;
3451
3452 /*
3453 * wait for ID byte of self test report
3454 */
3455 for (i = 100000; i > 0; --i) {
3456 if (duart->statusB&RCV_RDY) {
3457 break;
3458 }
3459 }
3460
3461 if (i == 0) {
3462 printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
3463 goto OUT;
3464 }
3465
3466 id_byte = duart->dataB;
3467
3468 /*
3469 * wait for other bytes to come in
3470 */
3471 for (i = 100000; i > 0; --i) {
3472 if (duart->statusB & RCV_RDY) {
3473 if (duart->dataB)
3474 ;
3475 break;
3476 }
3477 }
3478 if (i == 0) {
3479 printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
3480 goto OUT;
3481 }
3482 for (i = 100000; i > 0; --i) {
3483 if (duart->statusB&RCV_RDY) {
3484 if (duart->dataB)
3485 ;
3486 break;
3487 }
3488 }
3489 if (i == 0) {
3490 printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
3491 goto OUT;
3492 }
3493 /*
3494 * flag pointing device type and set defaults
3495 */
3496 for (i=100000; i>0; --i)
3497 ; /*XXX*/
3498
3499 if ((id_byte & 0x0F) != TABLET_ID) {
3500 qdflags[unit].pntr_id = MOUSE_ID;
3501
3502 for (i = 500; i > 0; --i) {
3503 if (duart->statusB&XMT_RDY) {
3504 duart->dataB = INC_STREAM_MODE;
3505 break;
3506 }
3507 }
3508 }
3509 else {
3510 qdflags[unit].pntr_id = TABLET_ID;
3511
3512 for (i = 500; i > 0; --i) {
3513 if (duart->statusB&XMT_RDY) {
3514 duart->dataB = T_STREAM;
3515 break;
3516 }
3517 }
3518 }
3519 OUT:
3520 duart->imask = qdflags[unit].duart_imask;
3521
3522 } /* setup_input */
3523
3524 /*
3525 * delay for at least one display frame time
3526 *
3527 * return: BAD means that we timed out without ever seeing the
3528 * vertical sync status bit
3529 * GOOD otherwise
3530 */
wait_status(adder,mask)3531 wait_status(adder, mask)
3532 register struct adder *adder;
3533 register int mask;
3534 {
3535 register i;
3536
3537 for (i = 10000, adder->status = 0 ; i > 0 &&
3538 !(adder->status&mask) ; --i)
3539 ;
3540
3541 if (i == 0) {
3542 printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
3543 return(BAD);
3544 }
3545
3546 return(GOOD);
3547
3548 } /* wait_status */
3549
3550 /*
3551 * write out onto the ID bus
3552 */
write_ID(adder,adrs,data)3553 write_ID(adder, adrs, data)
3554 register struct adder *adder;
3555 register short adrs;
3556 register short data;
3557 {
3558 register i;
3559
3560 for (i = 100000, adder->status = 0 ;
3561 i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i)
3562 ;
3563
3564 if (i == 0)
3565 goto ERR;
3566
3567 for (i = 100000, adder->status = 0 ;
3568 i > 0 && !(adder->status&TX_READY) ; --i)
3569 ;
3570
3571 if (i > 0) {
3572 adder->id_data = data;
3573 adder->command = ID_LOAD | adrs;
3574 return ;
3575 }
3576
3577 ERR:
3578 printf("write_ID: timeout trying to write to VIPER\n");
3579 return ;
3580
3581 } /* write_ID */
3582 #endif
3583