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