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