Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / qbus / qd.c
blob9edccb896f3812719d2943775dbe6566f32b7924
1 /* $NetBSD: qd.c,v 1.49 2009/04/18 14:58:03 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 1988 Regents of the University of California.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
31 * @(#)qd.c 7.1 (Berkeley) 6/28/91
34 /************************************************************************
35 * *
36 * Copyright (c) 1985-1988 by *
37 * Digital Equipment Corporation, Maynard, MA *
38 * All rights reserved. *
39 * *
40 * This software is furnished under a license and may be used and *
41 * copied only in accordance with the terms of such license and *
42 * with the inclusion of the above copyright notice. This *
43 * software or any other copies thereof may not be provided or *
44 * otherwise made available to any other person. No title to and *
45 * ownership of the software is hereby transferred. *
46 * *
47 * The information in this software is subject to change without *
48 * notice and should not be construed as a commitment by Digital *
49 * Equipment Corporation. *
50 * *
51 * Digital assumes no responsibility for the use or reliability *
52 * of its software on equipment which is not supplied by Digital. *
53 * *
54 *************************************************************************/
57 * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
60 #include <sys/cdefs.h>
61 __KERNEL_RCSID(0, "$NetBSD: qd.c,v 1.49 2009/04/18 14:58:03 tsutsui Exp $");
63 #include "opt_ddb.h"
65 #include "qd.h"
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/conf.h>
70 #include <sys/tty.h>
71 #include <sys/kernel.h>
72 #include <sys/device.h>
73 #include <sys/poll.h>
74 #include <sys/buf.h>
76 #include <uvm/uvm_extern.h>
78 #include <dev/cons.h>
80 #include <sys/bus.h>
81 #include <machine/scb.h>
83 #ifdef __vax__
84 #include <machine/sid.h>
85 #include <sys/cpu.h>
86 #include <machine/pte.h>
87 #endif
89 #include <dev/qbus/ubavar.h>
91 #include <dev/qbus/qduser.h>
92 #include <dev/qbus/qdreg.h>
93 #include <dev/qbus/qdioctl.h>
95 #include "ioconf.h"
98 * QDSS driver status flags for tracking operational state
100 struct qdflags {
101 u_int inuse; /* which minor dev's are in use now */
102 u_int config; /* I/O page register content */
103 u_int mapped; /* user mapping status word */
104 u_int kernel_loop; /* if kernel console is redirected */
105 u_int user_dma; /* DMA from user space in progress */
106 u_short pntr_id; /* type code of pointing device */
107 u_short duart_imask; /* shadowing for duart intrpt mask reg */
108 u_short adder_ie; /* shadowing for adder intrpt enbl reg */
109 u_short curs_acc; /* cursor acceleration factor */
110 u_short curs_thr; /* cursor acceleration threshold level */
111 u_short tab_res; /* tablet resolution factor */
112 u_short selmask; /* mask for active qd select entries */
116 * Softc struct to keep track of all states in this driver.
118 struct qd_softc {
119 struct device sc_dev;
120 bus_space_tag_t sc_iot;
121 bus_space_handle_t sc_ioh;
122 bus_dma_tag_t sc_dmat;
126 * bit definitions for 'inuse' entry
128 #define CONS_DEV 0x01
129 #define GRAPHIC_DEV 0x04
132 * bit definitions for 'mapped' member of flag structure
134 #define MAPDEV 0x01 /* hardware is mapped */
135 #define MAPDMA 0x02 /* DMA buffer mapped */
136 #define MAPEQ 0x04 /* event queue buffer mapped */
137 #define MAPSCR 0x08 /* scroll param area mapped */
138 #define MAPCOLOR 0x10 /* color map writing buffer mapped */
141 * constants used in shared memory operations
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)
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.
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 struct pte *QVmap[NQD];
160 #define CHUNK (64 * 1024)
161 #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */
164 * static storage used by multiple functions in this code
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 void *qdbase[NQD]; /* base address of each QDSS unit */
170 short qdopened[NQD]; /* graphics device is open exclusive use */
173 * the array "event_shared[]" is made up of a number of event queue buffers
174 * equal to the number of QDSS's configured into the running kernel (NQD).
175 * Each event queue buffer begins with an event queue header (struct qdinput)
176 * followed by a group of event queue entries (struct _vs_event). The array
177 * "*eq_header[]" is an array of pointers to the start of each event queue
178 * buffer in "event_shared[]".
180 #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
182 char event_shared[EQSIZE]; /* reserve space for event bufs */
183 struct qdinput *eq_header[NQD]; /* event queue header pntrs */
186 * This allocation method reserves enough memory pages for NQD shared DMA I/O
187 * buffers. Each buffer must consume an integral number of memory pages to
188 * guarantee that a following buffer will begin on a page boundary. Also,
189 * enough space is allocated so that the FIRST I/O buffer can start at the
190 * 1st page boundary after "&DMA_shared". Page boundaries are used so that
191 * memory protections can be turned on/off for individual buffers.
193 #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512)
195 char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */
196 struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */
199 * The driver assists a client in scroll operations by loading dragon
200 * registers from an interrupt service routine. The loading is done using
201 * parameters found in memory shrade between the driver and it's client.
202 * The scroll parameter structures are ALL loacted in the same memory page
203 * for reasons of memory economy.
205 char scroll_shared[2 * 512]; /* reserve space for scroll structs */
206 struct scroll *scroll[NQD]; /* pointers to scroll structures */
209 * the driver is programmable to provide the user with color map write
210 * services at VSYNC interrupt time. At interrupt time the driver loads
211 * the color map with any user-requested load data found in shared memory
213 #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512)
215 char color_shared[COLOR_SHARED]; /* reserve space: color bufs */
216 struct color_buf *color_buf[NQD]; /* pointers to color bufs */
219 * mouse input event structures
221 struct mouse_report last_rep[NQD];
222 struct mouse_report current_rep[NQD];
224 struct selinfo qdrsel[NQD]; /* process waiting for select */
225 struct _vs_cursor cursor[NQD]; /* console cursor */
226 int qdcount = 0; /* count of successfully probed qd's */
227 int nNQD = NQD;
228 int DMAbuf_size = DMA_BUFSIZ;
229 int QDlast_DMAtype; /* type of the last DMA operation */
232 * macro to get system time. Used to time stamp event queue entries
234 #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
236 void qd_attach(device_t, device_t, void *);
237 static int qd_match(device_t, cfdata_t, void *);
239 static void qddint(void *); /* DMA gate array intrpt service */
240 static void qdaint(void *); /* Dragon ADDER intrpt service */
241 static void qdiint(void *);
243 #define QDPRIOR (PZERO-1) /* must be negative */
244 #define FALSE 0
245 #ifdef TRUE
246 #undef TRUE
247 #endif
248 #define TRUE ~FALSE
249 #define BAD -1
250 #define GOOD 0
253 * macro to create a system virtual page number from system virtual adrs
255 #define VTOP(x) (((int)x & ~0xC0000000) >> VAX_PGSHIFT)
258 * QDSS register address offsets from start of QDSS address space
260 #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */
261 #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */
262 #define TMPSTART 0x8000 /* offset of template RAM from base adrs */
263 #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */
264 #define REGSTART 0xC000 /* offset of reg pages from base adrs */
265 #define ADDER (REGSTART+0x000)
266 #define DGA (REGSTART+0x200)
267 #define DUART (REGSTART+0x400)
268 #define MEMCSR (REGSTART+0x800)
269 #define CLRSIZE (3 * 512) /* color map size */
270 #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */
271 /* 0x0C00 really */
272 #define RED (CLRSTART+0x000)
273 #define BLUE (CLRSTART+0x200)
274 #define GREEN (CLRSTART+0x400)
278 * QDSS minor device numbers. The *real* minor device numbers are in
279 * the bottom two bits of the major/minor device spec. Bits 2 and up are
280 * used to specify the QDSS device number (ie: which one?)
283 #define CONS 0
284 #define GRAPHIC 2
287 * console cursor bitmap (white block cursor)
289 short cons_cursor[32] = {
290 /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
291 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
292 /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
293 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
297 * constants used in font operations
299 #define CHARS 190 /* # of chars in the font */
300 #define CHAR_HEIGHT 15 /* char height in pixels */
301 #define CHAR_WIDTH 8 /* char width in pixels*/
302 #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */
303 #define ROWS CHAR_HEIGHT
304 #define FONT_X 0 /* font's off screen adrs */
305 #define FONT_Y (2048 - CHAR_HEIGHT)
307 /* Offset to second row characters (XXX - should remove) */
308 #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
310 extern char q_font[]; /* reference font object code */
311 extern u_short q_key[]; /* reference key xlation tables */
312 extern u_short q_shift_key[];
313 extern char *q_special[];
316 * definitions for cursor acceleration reporting
318 #define ACC_OFF 0x01 /* acceleration is inactive */
321 * virtual console support.
323 extern struct cdevsw *consops;
324 cons_decl(qd);
325 void setup_dragon(int);
326 void init_shared(int);
327 void clear_qd_screen(int);
328 void ldfont(int);
329 void ldcursor(int, short *);
330 void setup_input(int);
331 void blitc(int, u_char);
332 void scroll_up(volatile struct adder *);
333 void write_ID(volatile struct adder *, short, short);
334 int wait_status(volatile struct adder *, int);
335 void led_control(int, int, int);
336 void qdstart(struct tty *);
337 void qdearly(void);
338 int qdpolling = 0;
340 dev_type_open(qdopen);
341 dev_type_close(qdclose);
342 dev_type_read(qdread);
343 dev_type_write(qdwrite);
344 dev_type_ioctl(qdioctl);
345 dev_type_stop(qdstop);
346 dev_type_poll(qdpoll);
347 dev_type_kqfilter(qdkqfilter);
349 const struct cdevsw qd_cdevsw = {
350 qdopen, qdclose, qdread, qdwrite, qdioctl,
351 qdstop, notty, qdpoll, nommap, qdkqfilter,
355 * LK-201 state storage for input console keyboard conversion to ASCII
357 struct q_keyboard {
358 int shift; /* state variables */
359 int cntrl;
360 int lock;
361 int lastcode; /* last keycode typed */
362 unsigned kup[8]; /* bits for each keycode*/
363 unsigned dkeys[8]; /* down/up mode keys */
364 char last; /* last character */
365 } q_keyboard;
368 * tty settings on first open
370 #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
371 #define OFLAG (OPOST|OXTABS|ONLCR)
372 #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
373 #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
376 * Kernel virtual addresses where we can map in the QBUS io page and the
377 * QDSS memory during qdcninit. pmap_bootstrap fills this in.
379 void *qd_ubaio;
381 /* This is the QDSS unit 0 CSR. It is hard-coded in here so that the
382 * QDSS can be used as the console. The console routines don't get
383 * any config info. The ROM also autodetects at this address, so
384 * the console QDSS should be at this address. Furthermore, nothing
385 * else shuld be at this address instead because that would confuse the
386 * ROM and this driver.
388 #define QDSSCSR 0x1F00
390 volatile u_short *qdaddr; /* Virtual address for QDSS CSR */
393 * This flag is set to 1 if the console initialization (qdcninit)
394 * has been performed on qd0. That initialization is required and must
395 * be done before the device probe routine.
397 int qd0cninited = 0, qd0iscons = 0;
400 * Do early check if the qdss is console. If not; don't allocate
401 * any memory for it in bootstrap.
403 void
404 qdearly(void)
406 extern vaddr_t virtual_avail;
407 int tmp;
409 /* Make sure we're running on a system that can have a QDSS */
410 if (vax_boardtype == VAX_BTYP_630) {
411 /* Now check some undocumented flag */
412 if ((*(int *)(0x200B801E) & 0x60) == 0)
413 /* The KA630 isn't using a QDSS as the console,
414 * so we won't either */
415 return;
416 } else if (vax_boardtype != VAX_BTYP_650)
417 return;
419 /* How to check for console on KA650? We assume that if there is a
420 * QDSS, it is console.
422 #define QIOPAGE 0x20000000 /* XXX */
423 #define UBAIOPAGES 16
424 tmp = QIOPAGE + ubdevreg(QDSSCSR);
425 if (badaddr((void *)tmp, sizeof(short)))
426 return;
428 MAPVIRT(qvmem[0], 64 * 1024 * NQD / VAX_NBPG);
429 MAPVIRT(qd_ubaio, 16);
430 pmap_map((int)qd_ubaio, QIOPAGE, QIOPAGE + UBAIOPAGES * VAX_NBPG,
431 VM_PROT_READ|VM_PROT_WRITE);
432 qdaddr = (u_short *)((u_int)qd_ubaio + ubdevreg(QDSSCSR));
433 qd0iscons = 1;
436 void
437 qdcnprobe(struct consdev *cndev)
439 int i;
441 cndev->cn_pri = CN_DEAD;
443 if (mfpr(PR_MAPEN) == 0)
444 return; /* Cannot use qd if vm system is OFF */
446 if (!qd0iscons)
447 return;
449 /* Find the console device corresponding to the console QDSS */
450 cndev->cn_dev = makedev(cdevsw_lookup_major(&qd_cdevsw), 0);
451 cndev->cn_pri = CN_INTERNAL;
452 return;
457 * Init QDSS as console (before probe routine)
459 void
460 qdcninit(struct consdev *cndev)
462 void *phys_adr; /* physical QDSS base adrs */
463 u_int mapix; /* index into QVmap[] array */
464 int unit;
466 /* qdaddr must point to CSR for this unit! */
468 /* The console QDSS is QDSS unit 0 */
469 unit = 0;
472 * Map q-bus memory used by qdss. (separate map)
474 mapix = QMEMSIZE - (CHUNK * (unit + 1));
475 #define QMEM 0x30000000
476 (int)phys_adr = QMEM + mapix;
477 pmap_map((int)(qvmem[0]), (int)phys_adr, (int)(phys_adr + (CHUNK*NQD)),
478 VM_PROT_READ|VM_PROT_WRITE);
481 * Set QVmap to point to page table entries for what we just
482 * mapped.
484 QVmap[0] = (struct pte *)kvtopte(qvmem[0]);
487 * tell QDSS which Q memory address base to decode
488 * (shifted right 16 bits - its in 64K units)
490 *qdaddr = (u_short)((int)mapix >> 16);
491 qdflags[unit].config = *(u_short *)qdaddr;
494 * load qdmap struct with the virtual addresses of the QDSS elements
496 qdbase[unit] = (void *) (qvmem[0]);
497 qdmap[unit].template = qdbase[unit] + TMPSTART;
498 qdmap[unit].adder = qdbase[unit] + ADDER;
499 qdmap[unit].dga = qdbase[unit] + DGA;
500 qdmap[unit].duart = qdbase[unit] + DUART;
501 qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
502 qdmap[unit].red = qdbase[unit] + RED;
503 qdmap[unit].blue = qdbase[unit] + BLUE;
504 qdmap[unit].green = qdbase[unit] + GREEN;
506 qdflags[unit].duart_imask = 0; /* init shadow variables */
509 * init the QDSS
512 *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
514 cursor[unit].x = 0;
515 cursor[unit].y = 0;
516 init_shared(unit); /* init shared memory */
517 setup_dragon(unit); /* init the ADDER/VIPER stuff */
518 clear_qd_screen(unit); /* clear the screen */
519 ldfont(unit); /* load the console font */
520 ldcursor(unit, cons_cursor); /* load default cursor map */
521 setup_input(unit); /* init the DUART */
522 selinit(&qdrsel[unit]);
524 /* Set flag so probe knows */
525 qd0cninited = 1;
526 } /* qdcninit */
528 /* see <sys/device.h> */
529 CFATTACH_DECL(qd, sizeof(struct qd_softc),
530 qd_match, qd_attach, NULL, NULL);
532 #define QD_RCSR(reg) \
533 bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
534 #define QD_WCSR(reg, val) \
535 bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
538 * Configure QDSS into Q memory and make it intrpt.
540 * side effects: QDSS gets mapped into Qbus memory space at the first
541 * vacant 64kb boundary counting back from the top of
542 * Qbus memory space (qvmem+4mb)
544 * return: QDSS bus request level and vector address returned in
545 * registers by UNIX convention.
548 static int
549 qd_match(device_t parent, cfdata_t match, void *aux)
551 struct qd_softc ssc;
552 struct qd_softc *sc = &ssc;
553 struct uba_attach_args *ua = aux;
554 struct uba_softc *uh = (void *)parent;
555 int unit;
556 volatile struct dga *dga; /* pointer to gate array structure */
557 int vector;
558 #ifdef notdef
559 int *ptep; /* page table entry pointer */
560 void *phys_adr; /* physical QDSS base adrs */
561 u_int mapix;
562 #endif
564 /* Create a "fake" softc with only a few fields used. */
565 sc->sc_iot = ua->ua_iot;
566 sc->sc_ioh = ua->ua_ioh;
567 sc->sc_dmat = ua->ua_dmat;
569 * calculate board unit number from I/O page register address
571 unit = (int) (((int)sc->sc_ioh >> 1) & 0x0007);
574 * QDSS regs must be mapped to Qbus memory space at a 64kb
575 * physical boundary. The Qbus memory space is mapped into
576 * the system memory space at config time. After config
577 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
578 * of the start of Qbus memory. The Qbus memory page table
579 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
580 * which is also loaded at config time. These are the
581 * variables used below to find a vacant 64kb boundary in
582 * Qbus memory, and load it's corresponding physical adrs
583 * into the QDSS's I/O page CSR.
587 * Only if QD is the graphics device.
590 /* if this QDSS is NOT the console, then do init here.. */
592 if (unit != 0) {
593 printf("qd: can't support two qdss's (yet)\n");
594 #ifdef notdef /* can't test */
595 if (v_consputc != qdputc || unit != 0) {
598 * read QDSS config info
600 qdflags[unit].config = *(u_short *)reg;
603 * find an empty 64kb adrs boundary
606 qdbase[unit] = (void *) (qvmem[0] + QMEMSIZE - CHUNK);
609 * find the cpusw entry that matches this machine.
611 cpup = &cpusw[cpu];
612 while (!(BADADDR(qdbase[unit], sizeof(short))))
613 qdbase[unit] -= CHUNK;
616 * tell QDSS which Q memory address base to decode
618 mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
619 ptep = (int *) QVmap[0] + mapix;
620 phys_adr = (void *)(((int)*ptep&0x001FFFFF)<<VAX_PGSHIFT);
621 *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
624 * load QDSS adrs map with system addresses
625 * of device regs
627 qdmap[unit].template = qdbase[unit] + TMPSTART;
628 qdmap[unit].adder = qdbase[unit] + ADDER;
629 qdmap[unit].dga = qdbase[unit] + DGA;
630 qdmap[unit].duart = qdbase[unit] + DUART;
631 qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
632 qdmap[unit].red = qdbase[unit] + RED;
633 qdmap[unit].blue = qdbase[unit] + BLUE;
634 qdmap[unit].green = qdbase[unit] + GREEN;
636 /* device init */
638 cursor[unit].x = 0;
639 cursor[unit].y = 0;
640 init_shared(unit); /* init shared memory */
641 setup_dragon(unit); /* init the ADDER/VIPER stuff */
642 ldcursor(unit, cons_cursor); /* load default cursor map */
643 setup_input(unit); /* init the DUART */
644 clear_qd_screen(unit);
645 ldfont(unit); /* load the console font */
647 /* once only: turn on sync */
649 *(short *)qdmap[unit].memcsr |= SYNC_ON;
651 #endif /*notdef*/
652 } else {
653 /* We are dealing with qd0 */
655 if (!qd0cninited) {
657 * qd0 has not been initiallized as the console.
658 * We need to do some initialization now
660 * XXX
661 * However, if the QDSS is not the console then
662 * that stupid undocumented bit (see qdcnprobe)
663 * is cleared. Then the QDSS refuses to work.
664 * (What did the ROM do to it!?)
665 * XXX
667 return 0;
669 #if 0
670 qdaddr = (void *)reg;
672 /* Lame probe for QDSS. Should be ok for qd0 */
673 if (badaddr((void *)qdaddr, sizeof(short)))
674 return 0;
676 qdcninit(NULL);
677 #endif
683 * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
684 * (ADDER) and xx8 (DUART). Therefore, we take three
685 * vectors from the vector pool, and then continue
686 * to take them until we get a xx0 HEX vector. The
687 * pool provides vectors in contiguous decending
688 * order.
691 vector = (uh->uh_lastiv -= 4*3); /* take three vectors */
693 while (vector & 0x0F) { /* if lo nibble != 0.. */
694 /* ..take another vector */
695 vector = (uh->uh_lastiv -= 4);
699 * setup DGA to do a DMA interrupt (transfer count = 0)
701 dga = (struct dga *) qdmap[unit].dga;
702 dga->csr = (short) HALT; /* disable everything */
703 dga->ivr = (short) vector; /* load intrpt base vector */
704 dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */
705 dga->bytcnt_hi = (short) 0;
708 * turn on DMA interrupts
710 dga->csr &= ~SET_DONE_FIFO;
711 dga->csr |= DMA_IE | DL_ENB;
713 DELAY(20000); /* wait for the intrpt */
714 dga->csr = HALT; /* stop the wheels */
717 * score this as an existing qdss
719 qdcount++;
721 return 1;
722 } /* qdprobe */
725 void qd_attach(parent, self, aux)
726 device_t parent, *self;
727 void *aux;
729 struct uba_attach_args *ua = aux;
730 int unit; /* QDSS module # for this call */
732 printf("\n");
734 unit = device_unit(self); /* get QDSS number */
736 /* Set interrupt vectors for interrupt handlers */
738 uba_intr_establish(ua->ua_icookie, ua->ua_cvec , qddint, self);
739 uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, qdaint, self);
740 uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 8, qdiint, self);
743 * init "qdflags[]" for this QDSS
745 qdflags[unit].inuse = 0; /* init inuse variable EARLY! */
746 qdflags[unit].mapped = 0;
747 qdflags[unit].kernel_loop = -1;
748 qdflags[unit].user_dma = 0;
749 qdflags[unit].curs_acc = ACC_OFF;
750 qdflags[unit].curs_thr = 128;
751 qdflags[unit].tab_res = 2; /* default tablet resolution factor */
752 qdflags[unit].duart_imask = 0; /* init shadow variables */
753 qdflags[unit].adder_ie = 0;
756 * init structures used in kbd/mouse interrupt service. This code must
757 * come after the "init_shared()" routine has run since that routine
758 * inits the eq_header[unit] structure used here.
762 * init the "latest mouse report" structure
764 last_rep[unit].state = 0;
765 last_rep[unit].dx = 0;
766 last_rep[unit].dy = 0;
767 last_rep[unit].bytcnt = 0;
770 * init the event queue (except mouse position)
772 eq_header[unit]->header.events =
773 (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
775 eq_header[unit]->header.size = MAXEVENTS;
776 eq_header[unit]->header.head = 0;
777 eq_header[unit]->header.tail = 0;
780 * open exclusive for graphics device.
782 qdopened[unit] = 0;
784 } /* qdattach */
787 /*ARGSUSED*/
789 qdopen(dev_t dev, int flag, int mode, struct proc *p)
791 volatile struct dga *dga; /* ptr to gate array struct */
792 struct tty *tp;
793 volatile struct duart *duart;
794 struct uba_softc *sc;
795 int unit;
796 int minor_dev;
798 minor_dev = minor(dev); /* get QDSS minor device number */
799 unit = minor_dev >> 2;
802 * check for illegal conditions
804 sc = device_lookup_private(&qd_cd, unit);
805 if (sc == NULL)
806 return ENXIO;
808 duart = (struct duart *) qdmap[unit].duart;
809 dga = (struct dga *) qdmap[unit].dga;
811 if ((minor_dev & 0x03) == 2) {
813 * this is the graphic device...
815 if (qdopened[unit] != 0)
816 return(EBUSY);
817 else
818 qdopened[unit] = 1;
819 qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */
821 * enble kbd & mouse intrpts in DUART mask reg
823 qdflags[unit].duart_imask |= 0x22;
824 duart->imask = qdflags[unit].duart_imask;
825 } else {
826 /* Only one console */
827 if (minor_dev) return ENXIO;
829 /* If not done already, allocate tty structure */
830 if (qd_tty[minor_dev] == NULL)
831 qd_tty[minor_dev] = ttymalloc();
833 if (qd_tty[minor_dev] == NULL)
834 return ENXIO;
837 * this is the console
839 qdflags[unit].inuse |= CONS_DEV; /* mark console as open */
840 dga->csr |= CURS_ENB;
841 qdflags[unit].duart_imask |= 0x02;
842 duart->imask = qdflags[unit].duart_imask;
844 * some setup for tty handling
846 tp = qd_tty[minor_dev];
847 /* tp->t_addr = ui->ui_addr; */
848 tp->t_oproc = qdstart;
849 tp->t_dev = dev;
850 if ((tp->t_state & TS_ISOPEN) == 0) {
851 ttychars(tp);
852 tp->t_ispeed = B9600;
853 tp->t_ospeed = B9600;
854 tp->t_state = TS_ISOPEN | TS_CARR_ON;
855 tp->t_iflag = TTYDEF_IFLAG;
856 tp->t_oflag = TTYDEF_OFLAG;
857 tp->t_lflag = TTYDEF_LFLAG;
858 tp->t_cflag = TTYDEF_CFLAG;
859 ttsetwater(tp);
862 * enable intrpts, open line discipline
864 dga->csr |= GLOBAL_IE; /* turn on the interrupts */
865 return ((*tp->t_linesw->l_open)(dev, tp));
867 dga->csr |= GLOBAL_IE; /* turn on the interrupts */
868 return(0);
870 } /* qdopen */
872 /*ARGSUSED*/
874 qdclose(dev_t dev, int flag, int mode, struct proc *p)
876 struct tty *tp;
877 struct qdmap *qd;
878 volatile int *ptep;
879 volatile struct dga *dga; /* gate array register map pointer */
880 volatile struct duart *duart;
881 volatile struct adder *adder;
882 int unit;
883 int minor_dev;
884 u_int mapix;
885 int i; /* SIGNED index */
886 struct uba_softc *uh;
888 minor_dev = minor(dev); /* get minor device number */
889 unit = minor_dev >> 2; /* get QDSS number */
890 qd = &qdmap[unit];
892 uh = device_private(device_parent(device_lookup(&qd_cd, unit)));
895 if ((minor_dev & 0x03) == 2) {
897 * this is the graphic device...
899 if (qdopened[unit] != 1)
900 return(EBUSY);
901 else
902 qdopened[unit] = 0; /* allow it to be re-opened */
904 * re-protect device memory
906 if (qdflags[unit].mapped & MAPDEV) {
908 * TEMPLATE RAM
910 mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
911 ptep = (int *)(QVmap[0] + mapix);
912 for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++)
913 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
915 * ADDER
917 mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
918 ptep = (int *)(QVmap[0] + mapix);
919 for (i = 0; i < vax_btop(REGSIZE); i++, ptep++)
920 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
922 * COLOR MAPS
924 mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
925 ptep = (int *)(QVmap[0] + mapix);
926 for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
927 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
931 * re-protect DMA buffer and free the map registers
933 if (qdflags[unit].mapped & MAPDMA) {
934 panic("Unmapping unmapped buffer");
935 #ifdef notyet
937 * Ragge 990620:
938 * Can't happen because the buffer can't be mapped.
940 dga = (struct dga *) qdmap[unit].dga;
941 adder = (struct adder *) qdmap[unit].adder;
942 dga->csr &= ~DMA_IE;
943 dga->csr &= ~0x0600; /* kill DMA */
944 adder->command = CANCEL;
946 * if DMA was running, flush spurious intrpt
948 if (dga->bytcnt_lo != 0) {
949 dga->bytcnt_lo = 0;
950 dga->bytcnt_hi = 0;
951 DMA_SETIGNORE(DMAheader[unit]);
952 dga->csr |= DMA_IE;
953 dga->csr &= ~DMA_IE;
955 ptep = (int *)
956 ((VTOP(DMAheader[unit]*4)) + (mfpr(PR_SBR)|0x80000000));
957 for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
958 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
959 ubarelse(uh, &Qbus_unmap[unit]);
960 #endif
964 * re-protect 1K (2 pages) event queue
966 if (qdflags[unit].mapped & MAPEQ) {
967 ptep = (int *)
968 ((VTOP(eq_header[unit])*4) + (mfpr(PR_SBR)|0x80000000));
969 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
970 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
973 * re-protect scroll param area and disable scroll intrpts
975 if (qdflags[unit].mapped & MAPSCR) {
976 ptep = (int *) ((VTOP(scroll[unit]) * 4)
977 + (mfpr(PR_SBR) | 0x80000000));
979 * re-protect 512 scroll param area
981 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
982 adder = (struct adder *) qdmap[unit].adder;
983 qdflags[unit].adder_ie &= ~FRAME_SYNC;
984 adder->interrupt_enable = qdflags[unit].adder_ie;
987 * re-protect color map write buffer area and kill intrpts
989 if (qdflags[unit].mapped & MAPCOLOR) {
990 ptep = (int *) ((VTOP(color_buf[unit]) * 4)
991 + (mfpr(PR_SBR) | 0x80000000));
992 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
993 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
994 color_buf[unit]->status = 0;
995 adder = (struct adder *) qdmap[unit].adder;
996 qdflags[unit].adder_ie &= ~VSYNC;
997 adder->interrupt_enable = qdflags[unit].adder_ie;
999 mtpr(0, PR_TBIA);
1000 /* flag everything now unmapped */
1001 qdflags[unit].mapped = 0;
1002 qdflags[unit].inuse &= ~GRAPHIC_DEV;
1003 qdflags[unit].curs_acc = ACC_OFF;
1004 qdflags[unit].curs_thr = 128;
1006 * restore the console
1008 dga = (struct dga *) qdmap[unit].dga;
1009 adder = (struct adder *) qdmap[unit].adder;
1010 dga->csr &= ~DMA_IE;
1011 dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */
1012 dga->csr |= DMA_ERR; /* clear error condition */
1013 adder->command = CANCEL;
1015 * if DMA was running, flush spurious intrpt
1017 if (dga->bytcnt_lo != 0) {
1018 dga->bytcnt_lo = 0;
1019 dga->bytcnt_hi = 0;
1020 DMA_SETIGNORE(DMAheader[unit]);
1021 dga->csr |= DMA_IE;
1022 dga->csr &= ~DMA_IE;
1024 init_shared(unit); /* init shared memory */
1025 setup_dragon(unit); /* init ADDER/VIPER */
1026 ldcursor(unit, cons_cursor); /* load default cursor map */
1027 setup_input(unit); /* init the DUART */
1028 ldfont(unit);
1029 cursor[unit].x = 0;
1030 cursor[unit].y = 0;
1032 * shut off the mouse rcv intrpt and turn on kbd intrpts
1034 duart = (struct duart *) qdmap[unit].duart;
1035 qdflags[unit].duart_imask &= ~(0x20);
1036 qdflags[unit].duart_imask |= 0x02;
1037 duart->imask = qdflags[unit].duart_imask;
1039 * shut off interrupts if all is closed
1041 if (!(qdflags[unit].inuse & CONS_DEV)) {
1042 dga = (struct dga *) qdmap[unit].dga;
1043 dga->csr &= ~(GLOBAL_IE | DMA_IE);
1045 } else {
1047 * this is the console
1049 tp = qd_tty[minor_dev];
1050 (*tp->t_linesw->l_close)(tp, flag);
1051 ttyclose(tp);
1052 tp->t_state = 0;
1053 qdflags[unit].inuse &= ~CONS_DEV;
1055 * if graphics device is closed, kill interrupts
1057 if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
1058 dga = (struct dga *) qdmap[unit].dga;
1059 dga->csr &= ~(GLOBAL_IE | DMA_IE);
1063 return(0);
1065 } /* qdclose */
1068 qdioctl(dev_t dev, u_long cmd, void *datap, int flags, struct proc *p)
1070 volatile int *ptep; /* page table entry pointer */
1071 int mapix; /* QVmap[] page table index */
1072 struct _vs_event *event;
1073 struct tty *tp;
1074 int i;
1075 struct qdmap *qd; /* pointer to device map struct */
1076 volatile struct dga *dga; /* Gate Array reg structure pntr */
1077 volatile struct duart *duart; /* DUART reg structure pointer */
1078 volatile struct adder *adder; /* ADDER reg structure pointer */
1079 struct prgkbd *cmdbuf;
1080 struct prg_cursor *curs;
1081 struct _vs_cursor *pos;
1082 int unit = minor(dev) >> 2; /* number of caller's QDSS */
1083 u_int minor_dev = minor(dev);
1084 int error;
1085 int s;
1086 short *temp; /* a pointer to template RAM */
1087 struct uba_softc *uh;
1089 uh = device_private(device_parent(device_lookup(&qd_cd, unit)));
1092 * service graphic device ioctl commands
1094 switch (cmd) {
1096 case QD_GETEVENT:
1098 * extract the oldest event from the event queue
1100 if (ISEMPTY(eq_header[unit])) {
1101 event = (struct _vs_event *) datap;
1102 event->vse_device = VSE_NULL;
1103 break;
1105 event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
1106 s = spl5();
1107 GETEND(eq_header[unit]);
1108 splx(s);
1109 memcpy(datap, (void *)event, sizeof(struct _vs_event));
1110 break;
1112 case QD_RESET:
1114 * init the dragon stuff, DUART, and driver variables
1116 init_shared(unit); /* init shared memory */
1117 setup_dragon(unit); /* init the ADDER/VIPER stuff */
1118 clear_qd_screen(unit);
1119 ldcursor(unit, cons_cursor); /* load default cursor map */
1120 ldfont(unit); /* load the console font */
1121 setup_input(unit); /* init the DUART */
1122 break;
1124 case QD_SET:
1126 * init the DUART and driver variables
1128 init_shared(unit);
1129 setup_input(unit);
1130 break;
1132 case QD_CLRSCRN:
1134 * clear the QDSS screen. (NOTE that this reinits the dragon)
1136 #ifdef notdef /* has caused problems and isn't necessary */
1137 setup_dragon(unit);
1138 clear_qd_screen(unit);
1139 #endif
1140 break;
1142 case QD_WTCURSOR:
1144 * load a cursor into template RAM
1146 ldcursor(unit, (short *)datap);
1147 break;
1149 case QD_RDCURSOR:
1151 temp = (short *) qdmap[unit].template;
1153 * cursor is 32 WORDS from the end of the 8k WORD...
1154 * ...template space
1156 temp += (8 * 1024) - 32;
1157 for (i = 0; i < 32; ++i, datap += sizeof(short))
1158 *(short *)datap = *temp++;
1159 break;
1161 case QD_POSCURSOR:
1163 * position the mouse cursor
1165 dga = (struct dga *) qdmap[unit].dga;
1166 pos = (struct _vs_cursor *) datap;
1167 s = spl5();
1168 dga->x_cursor = TRANX(pos->x);
1169 dga->y_cursor = TRANY(pos->y);
1170 eq_header[unit]->curs_pos.x = pos->x;
1171 eq_header[unit]->curs_pos.y = pos->y;
1172 splx(s);
1173 break;
1175 case QD_PRGCURSOR:
1177 * set the cursor acceleration factor
1179 curs = (struct prg_cursor *) datap;
1180 s = spl5();
1181 qdflags[unit].curs_acc = curs->acc_factor;
1182 qdflags[unit].curs_thr = curs->threshold;
1183 splx(s);
1184 break;
1186 case QD_MAPDEVICE:
1188 * enable 'user write' to device pages
1190 qdflags[unit].mapped |= MAPDEV;
1191 qd = (struct qdmap *) &qdmap[unit];
1193 * enable user write to template RAM
1195 mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
1196 ptep = (int *)(QVmap[0] + mapix);
1197 for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++)
1198 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
1201 * enable user write to registers
1203 mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
1204 ptep = (int *)(QVmap[0] + mapix);
1205 for (i = 0; i < vax_btop(REGSIZE); i++, ptep++)
1206 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
1209 * enable user write to color maps
1211 mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
1212 ptep = (int *)(QVmap[0] + mapix);
1213 for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
1214 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
1217 * enable user write to DUART
1219 mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
1220 ptep = (int *)(QVmap[0] + mapix);
1221 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; /* duart page */
1223 mtpr(0, PR_TBIA); /* invalidate translation buffer */
1226 * stuff qdmap structure in return buffer
1228 memcpy(datap, (void *)qd, sizeof(struct qdmap));
1230 break;
1232 #ifdef notyet
1234 * Ragge 999620:
1235 * Can't map in the graphic buffer into user space for now.
1236 * The best way to fix this is to convert this driver to wscons.
1238 case QD_MAPIOBUF:
1240 * do setup for DMA by user process
1242 * set 'user write enable' bits for DMA buffer
1244 qdflags[unit].mapped |= MAPDMA;
1245 ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
1246 + (mfpr(PR_SBR) | 0x80000000));
1247 for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
1248 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
1249 mtpr(0, PR_TBIA); /* invalidate translation buffer */
1251 * set up QBUS map registers for DMA
1253 DMAheader[unit]->QBAreg =
1254 uballoc(uh, (void *)DMAheader[unit], DMAbuf_size, 0);
1255 if (DMAheader[unit]->QBAreg == 0)
1256 printf("qd%d: qdioctl: QBA setup error\n", unit);
1257 Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
1258 DMAheader[unit]->QBAreg &= 0x3FFFF;
1260 * return I/O buf adr
1262 *(int *)datap = (int) DMAheader[unit];
1263 break;
1264 #endif
1266 case QD_MAPSCROLL:
1268 * map the shared scroll param area and enable scroll interpts
1270 qdflags[unit].mapped |= MAPSCR;
1271 ptep = (int *) ((VTOP(scroll[unit]) * 4)
1272 + (mfpr(PR_SBR) | 0x80000000));
1274 * allow user write to scroll area
1276 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
1277 mtpr(0, PR_TBIA); /* invalidate translation buf */
1278 scroll[unit]->status = 0;
1279 adder = (struct adder *) qdmap[unit].adder;
1280 qdflags[unit].adder_ie |= FRAME_SYNC;
1281 adder->interrupt_enable = qdflags[unit].adder_ie;
1282 *(int *)datap = (int) scroll[unit]; /* return scroll area */
1283 break;
1285 case QD_UNMAPSCROLL:
1287 * unmap shared scroll param area and disable scroll intrpts
1289 if (qdflags[unit].mapped & MAPSCR) {
1290 qdflags[unit].mapped &= ~MAPSCR;
1291 ptep = (int *) ((VTOP(scroll[unit]) * 4)
1292 + (mfpr(PR_SBR) | 0x80000000));
1294 * re-protect 512 scroll param area
1296 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1297 mtpr(0, PR_TBIA); /* smash CPU's translation buf */
1298 adder = (struct adder *) qdmap[unit].adder;
1299 qdflags[unit].adder_ie &= ~FRAME_SYNC;
1300 adder->interrupt_enable = qdflags[unit].adder_ie;
1302 break;
1304 case QD_MAPCOLOR:
1306 * map shared color map write buf and turn on vsync intrpt
1308 qdflags[unit].mapped |= MAPCOLOR;
1309 ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1310 + (mfpr(PR_SBR) | 0x80000000));
1312 * allow user write to color map write buffer
1314 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
1315 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
1316 mtpr(0, PR_TBIA); /* clr CPU translation buf */
1317 adder = (struct adder *) qdmap[unit].adder;
1318 qdflags[unit].adder_ie |= VSYNC;
1319 adder->interrupt_enable = qdflags[unit].adder_ie;
1321 * return color area address
1323 *(int *)datap = (int) color_buf[unit];
1324 break;
1326 case QD_UNMAPCOLOR:
1328 * unmap shared color map write buffer and kill VSYNC intrpts
1330 if (qdflags[unit].mapped & MAPCOLOR) {
1331 qdflags[unit].mapped &= ~MAPCOLOR;
1332 ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1333 + (mfpr(PR_SBR) | 0x80000000));
1335 * re-protect color map write buffer
1337 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
1338 *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1339 mtpr(0, PR_TBIA);
1340 adder = (struct adder *) qdmap[unit].adder;
1341 qdflags[unit].adder_ie &= ~VSYNC;
1342 adder->interrupt_enable = qdflags[unit].adder_ie;
1344 break;
1346 case QD_MAPEVENT:
1348 * give user write access to the event queue
1350 qdflags[unit].mapped |= MAPEQ;
1351 ptep = (int *) ((VTOP(eq_header[unit]) * 4)
1352 + (mfpr(PR_SBR) | 0x80000000));
1354 * allow user write to 1K event queue
1356 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
1357 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
1358 mtpr(0, PR_TBIA); /* clr CPU translation buf */
1360 * return event queue address
1362 *(int *)datap = (int)eq_header[unit];
1363 break;
1365 case QD_PRGKBD:
1367 * pass caller's programming commands to LK201
1369 duart = (struct duart *)qdmap[unit].duart;
1370 cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */
1372 * send command
1374 for (i = 1000; i > 0; --i) {
1375 if (duart->statusA&XMT_RDY) {
1376 duart->dataA = cmdbuf->cmd;
1377 break;
1380 if (i == 0) {
1381 printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
1382 break;
1385 * send param1?
1387 if (cmdbuf->cmd & LAST_PARAM)
1388 break;
1389 for (i = 1000; i > 0; --i) {
1390 if (duart->statusA&XMT_RDY) {
1391 duart->dataA = cmdbuf->param1;
1392 break;
1395 if (i == 0) {
1396 printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
1397 break;
1400 * send param2?
1402 if (cmdbuf->param1 & LAST_PARAM)
1403 break;
1404 for (i = 1000; i > 0; --i) {
1405 if (duart->statusA&XMT_RDY) {
1406 duart->dataA = cmdbuf->param2;
1407 break;
1410 if (i == 0) {
1411 printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
1412 break;
1414 break;
1416 case QD_PRGMOUSE:
1418 * pass caller's programming commands to the mouse
1420 duart = (struct duart *) qdmap[unit].duart;
1421 for (i = 1000; i > 0; --i) {
1422 if (duart->statusB&XMT_RDY) {
1423 duart->dataB = *datap;
1424 break;
1427 if (i == 0) {
1428 printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
1430 break;
1432 case QD_RDCONFIG:
1434 * get QDSS configuration word and return it
1436 *(short *)datap = qdflags[unit].config;
1437 break;
1439 case QD_KERN_LOOP:
1440 case QD_KERN_UNLOOP:
1442 * vestige from ultrix. BSD uses TIOCCONS to redirect
1443 * kernel console output.
1445 break;
1447 case QD_PRGTABLET:
1449 * program the tablet
1451 duart = (struct duart *) qdmap[unit].duart;
1452 for (i = 1000; i > 0; --i) {
1453 if (duart->statusB&XMT_RDY) {
1454 duart->dataB = *datap;
1455 break;
1458 if (i == 0) {
1459 printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
1461 break;
1463 case QD_PRGTABRES:
1465 * program the tablet report resolution factor
1467 qdflags[unit].tab_res = *(short *)datap;
1468 break;
1470 default:
1472 * service tty ioctl's
1474 if (!(minor_dev & 0x02)) {
1475 tp = qd_tty[minor_dev];
1476 error =
1478 (*tp->t_linesw->l_ioctl)(tp, cmd, datap, flags, p);
1479 if (error != EPASSTHROUGH) {
1480 return(error);
1482 return ttioctl(tp, cmd, datap, flags, p);
1484 break;
1487 return(0);
1489 } /* qdioctl */
1493 qdpoll(dev_t dev, int events, struct proc *p)
1495 int s;
1496 int unit;
1497 struct tty *tp;
1498 u_int minor_dev = minor(dev);
1499 int revents = 0;
1501 s = spl5();
1502 unit = minor_dev >> 2;
1504 if ((minor_dev & 0x03) == 2) {
1506 * This is a graphics device, so check for events.
1509 if (events & (POLLIN | POLLRDNORM))
1510 if(!(ISEMPTY(eq_header[unit])))
1511 revents |= events & (POLLIN | POLLRDNORM);
1513 if (events & (POLLOUT | POLLWRNORM))
1514 if (DMA_ISEMPTY(DMAheader[unit]))
1515 revents |= events & (POLLOUT | POLLWRNORM);
1517 if (revents == 0) {
1518 if (events & (POLLIN | POLLRDNORM))
1519 selrecord(p, &qdrsel[unit]);
1521 if (events & (POLLOUT | POLLWRNORM))
1522 selrecord(p, &qdrsel[unit]);
1524 } else {
1526 * this is a tty device
1528 tp = qd_tty[minor_dev];
1529 revents = (*tp->t_linesw->l_poll)(tp, events, p);
1532 splx(s);
1533 return (revents);
1534 } /* qdpoll() */
1536 static void
1537 filt_qdrdetach(struct knote *kn)
1539 dev_t dev = (intptr_t) kn->kn_hook;
1540 u_int minor_dev = minor(dev);
1541 int unit = minor_dev >> 2;
1542 int s;
1544 s = spl5();
1545 SLIST_REMOVE(&qdrsel[unit].sel_klist, kn, knote, kn_selnext);
1546 splx(s);
1549 static int
1550 filt_qdread(struct knote *kn, long hint)
1552 dev_t dev = (intptr_t) kn->kn_hook;
1553 u_int minor_dev = minor(dev);
1554 int unit = minor_dev >> 2;
1556 if (ISEMPTY(eq_header[unit]))
1557 return (0);
1559 kn->kn_data = 0; /* XXXLUKEM (thorpej): what to put here? */
1560 return (1);
1563 static int
1564 filt_qdwrite(struct knote *kn, long hint)
1566 dev_t dev = (intptr_t) kn->kn_hook;
1567 u_int minor_dev = minor(dev);
1568 int unit = minor_dev >> 2;
1570 if (! DMA_ISEMPTY(DMAheader[unit]))
1571 return (0);
1573 kn->kn_data = 0; /* XXXLUKEM (thorpej): what to put here? */
1574 return (1);
1577 static const struct filterops qdread_filtops =
1578 { 1, NULL, filt_qdrdetach, filt_qdread };
1580 static const struct filterops qdwrite_filtops =
1581 { 1, NULL, filt_qdrdetach, filt_qdwrite };
1584 qdkqfilter(dev_t dev, struct knote *kn)
1586 struct klist *klist;
1587 u_int minor_dev = minor(dev);
1588 int s, unit = minor_dev >> 2;
1590 if ((minor_dev & 0x03) != 2) {
1591 /* TTY device. */
1592 return (ttykqfilter(dev, kn));
1595 switch (kn->kn_filter) {
1596 case EVFILT_READ:
1597 klist = &qdrsel[unit].sel_klist;
1598 kn->kn_fop = &qdread_filtops;
1599 break;
1601 case EVFILT_WRITE:
1602 klist = &qdrsel[unit].sel_klist;
1603 kn->kn_fop = &qdwrite_filtops;
1604 break;
1606 default:
1607 return (EINVAL);
1610 kn->kn_hook = (void *)(intptr_t) dev;
1612 s = spl5();
1613 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1614 splx(s);
1616 return (0);
1619 void qd_strategy(struct buf *bp);
1621 /*ARGSUSED*/
1623 qdwrite(dev_t dev, struct uio *uio, int flag)
1625 struct tty *tp;
1626 int minor_dev;
1627 int unit;
1629 minor_dev = minor(dev);
1630 unit = (minor_dev >> 2) & 0x07;
1632 if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
1634 * this is the console...
1636 tp = qd_tty[minor_dev];
1637 return ((*tp->t_linesw->l_write)(tp, uio, flag));
1638 } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1640 * this is a DMA xfer from user space
1642 return (physio(qd_strategy, NULL, dev, B_WRITE, minphys, uio));
1644 return (ENXIO);
1647 /*ARGSUSED*/
1649 qdread(dev_t dev, struct uio *uio, int flag)
1651 struct tty *tp;
1652 int minor_dev;
1653 int unit;
1655 minor_dev = minor(dev);
1656 unit = (minor_dev >> 2) & 0x07;
1658 if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
1660 * this is the console
1662 tp = qd_tty[minor_dev];
1663 return ((*tp->t_linesw->l_read)(tp, uio, flag));
1664 } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1666 * this is a bitmap-to-processor xfer
1668 return (physio(qd_strategy, NULL, dev, B_READ, minphys, uio));
1670 return (ENXIO);
1673 /***************************************************************
1675 * qd_strategy()... strategy routine to do DMA
1677 ***************************************************************/
1679 void
1680 qd_strategy(struct buf *bp)
1682 volatile struct dga *dga;
1683 volatile struct adder *adder;
1684 int unit;
1685 int QBAreg;
1686 int s;
1687 int cookie;
1688 struct uba_softc *uh;
1690 unit = (minor(bp->b_dev) >> 2) & 0x07;
1692 uh = device_private(device_parent(device_lookup(&qd_cd, unit)));
1695 * init pointers
1697 dga = (struct dga *) qdmap[unit].dga;
1698 panic("qd_strategy");
1699 #ifdef notyet
1700 if ((QBAreg = ubasetup(uh, bp, 0)) == 0) {
1701 printf("qd%d: qd_strategy: QBA setup error\n", unit);
1702 goto STRAT_ERR;
1704 #endif
1705 s = spl5();
1706 qdflags[unit].user_dma = -1;
1707 dga->csr |= DMA_IE;
1708 cookie = QBAreg & 0x3FFFF;
1709 dga->adrs_lo = (short) cookie;
1710 dga->adrs_hi = (short) (cookie >> 16);
1711 dga->bytcnt_lo = (short) bp->b_bcount;
1712 dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
1714 while (qdflags[unit].user_dma) {
1715 (void) tsleep(&qdflags[unit].user_dma, QSPRIOR,
1716 "qdstrat", 0);
1718 splx(s);
1719 #ifdef notyet
1720 ubarelse(uh, &QBAreg);
1721 #endif
1722 if (!(dga->csr & DMA_ERR)) {
1723 biodone(bp);
1724 return;
1727 /* STRAT_ERR: */
1728 adder = (struct adder *) qdmap[unit].adder;
1729 adder->command = CANCEL; /* cancel adder activity */
1730 dga->csr &= ~DMA_IE;
1731 dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
1732 dga->csr |= DMA_ERR; /* clear error condition */
1733 bp->b_error = EIO; /* flag an error to physio() */
1736 * if DMA was running, flush spurious intrpt
1738 if (dga->bytcnt_lo != 0) {
1739 dga->bytcnt_lo = 0;
1740 dga->bytcnt_hi = 0;
1741 DMA_SETIGNORE(DMAheader[unit]);
1742 dga->csr |= DMA_IE;
1744 biodone(bp);
1745 } /* qd_strategy */
1749 * Start output to the console screen
1751 void qdstart(tp)
1752 struct tty *tp;
1754 int which_unit, unit, c;
1755 int s;
1757 unit = minor(tp->t_dev);
1758 which_unit = (unit >> 2) & 0x3;
1759 unit &= 0x03;
1761 s = spl5();
1764 * If it's currently active, or delaying, no need to do anything.
1766 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1767 goto out;
1770 * Display chars until the queue is empty.
1771 * Drop input from anything but the console
1772 * device on the floor.
1774 * XXX - this loop is done at spltty.
1777 while (tp->t_outq.c_cc) {
1778 c = getc(&tp->t_outq);
1779 if (unit == 0)
1780 blitc(which_unit, (u_char)c);
1782 ttypull(tp);
1783 tp->t_state &= ~TS_BUSY;
1785 out:
1786 splx(s);
1788 } /* qdstart */
1790 /*ARGSUSED*/
1791 void
1792 qdstop(struct tty *tp, int flag)
1794 int s;
1796 s = spl5(); /* block intrpts during state modification */
1797 if (tp->t_state & TS_BUSY) {
1798 if ((tp->t_state & TS_TTSTOP) == 0)
1799 tp->t_state |= TS_FLUSH;
1800 else
1801 tp->t_state &= ~TS_BUSY;
1803 splx(s);
1807 * Output a character to the QDSS screen
1809 void
1810 blitc(int unit, u_char chr)
1812 volatile struct adder *adder;
1813 volatile struct dga *dga;
1814 int i;
1815 int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
1816 static short inescape[NQD];
1818 adder = (struct adder *)qdmap[unit].adder;
1819 dga = (struct dga *) qdmap[unit].dga;
1821 * BSD comment: this (&=0177) defeats the extended character
1822 * set code for the glass tty, but if i had the time i would
1823 * spend it ripping out the code completely. This driver
1824 * is too big for its own good.
1826 chr &= 0177;
1828 * Cursor addressing (so vi will work).
1829 * Decode for "\E=%.%." cursor motion description.
1830 * Corresponds to type "qdcons" in /etc/termcap:
1832 * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
1833 * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
1836 if (inescape[unit] && nograph) {
1837 switch (inescape[unit]++) {
1838 case 1:
1839 if (chr != '=') {
1840 /* abort escape sequence */
1841 inescape[unit] = 0;
1842 blitc(unit, chr);
1844 return;
1845 case 2:
1846 /* position row */
1847 cursor[unit].y = CHAR_HEIGHT * chr;
1848 if (cursor[unit].y > 863 - CHAR_HEIGHT)
1849 cursor[unit].y = 863 - CHAR_HEIGHT;
1850 dga->y_cursor = TRANY(cursor[unit].y);
1851 return;
1852 case 3:
1853 /* position column */
1854 cursor[unit].x = CHAR_WIDTH * chr;
1855 if (cursor[unit].x > 1024 - CHAR_WIDTH)
1856 cursor[unit].x = 1023 - CHAR_WIDTH;
1857 dga->x_cursor = TRANX(cursor[unit].x);
1858 inescape[unit] = 0;
1859 return;
1860 default:
1861 inescape[unit] = 0;
1862 blitc(unit, chr);
1866 switch (chr) {
1867 case '\r': /* return char */
1868 cursor[unit].x = 0;
1869 if (nograph)
1870 dga->x_cursor = TRANX(cursor[unit].x);
1871 return;
1873 case '\t': /* tab char */
1874 for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
1875 blitc(unit, ' ');
1877 return;
1879 case '\n': /* line feed char */
1880 if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1881 if (nograph) {
1882 cursor[unit].y -= CHAR_HEIGHT;
1883 scroll_up(adder);
1884 } else
1885 cursor[unit].y = 0;
1887 if (nograph)
1888 dga->y_cursor = TRANY(cursor[unit].y);
1889 return;
1891 case '\b': /* backspace char */
1892 if (cursor[unit].x > 0) {
1893 cursor[unit].x -= CHAR_WIDTH;
1894 if (nograph)
1895 dga->x_cursor = TRANX(cursor[unit].x);
1897 return;
1898 case CTRL('k'): /* cursor up */
1899 if (nograph && cursor[unit].y > 0) {
1900 cursor[unit].y -= CHAR_HEIGHT;
1901 dga->y_cursor = TRANY(cursor[unit].y);
1903 return;
1905 case CTRL('^'): /* home cursor */
1906 if (nograph) {
1907 cursor[unit].x = 0;
1908 dga->x_cursor = TRANX(cursor[unit].x);
1909 cursor[unit].y = 0;
1910 dga->y_cursor = TRANY(cursor[unit].y);
1912 return;
1914 case CTRL('l'): /* cursor right */
1915 if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
1916 cursor[unit].x += CHAR_WIDTH;
1917 dga->x_cursor = TRANX(cursor[unit].x);
1919 return;
1921 case CTRL('z'): /* clear screen */
1922 if (nograph) {
1923 setup_dragon(unit);
1924 clear_qd_screen(unit);
1925 /* home cursor - termcap seems to assume this */
1926 cursor[unit].x = 0;
1927 dga->x_cursor = TRANX(cursor[unit].x);
1928 cursor[unit].y = 0;
1929 dga->y_cursor = TRANY(cursor[unit].y);
1931 return;
1933 case '\033': /* start escape sequence */
1934 if (nograph)
1935 inescape[unit] = 1;
1936 return;
1938 default:
1939 if ((chr < ' ') || (chr > '~'))
1940 return;
1943 * setup VIPER operand control registers
1945 write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */
1946 write_ID(adder, SRC1_OCR_B,
1947 EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
1948 write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */
1949 write_ID(adder, SRC1_OCR_B,
1950 EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
1951 write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
1952 write_ID(adder, DST_OCR_B,
1953 EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
1954 write_ID(adder, MASK_1, 0xFFFF);
1955 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
1956 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1957 adder->x_clip_min = 0;
1958 adder->x_clip_max = 1024;
1959 adder->y_clip_min = 0;
1960 adder->y_clip_max = 864;
1962 * load DESTINATION origin and vectors
1964 adder->fast_dest_dy = 0;
1965 adder->slow_dest_dx = 0;
1966 adder->error_1 = 0;
1967 adder->error_2 = 0;
1968 adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
1969 (void)wait_status(adder, RASTEROP_COMPLETE);
1970 adder->destination_x = cursor[unit].x;
1971 adder->fast_dest_dx = CHAR_WIDTH;
1972 adder->destination_y = cursor[unit].y;
1973 adder->slow_dest_dy = CHAR_HEIGHT;
1975 * load SOURCE origin and vectors
1977 if ((chr - ' ') > (CHARS - 1)) {
1978 printf("Invalid character (x)%x in blitc\n",chr);
1979 chr = ' ';
1982 * X position is modulo the number of characters per line
1984 adder->source_1_x = FONT_X +
1985 (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
1987 * Point to either first or second row
1989 adder->source_1_y = 2048 - 15 *
1990 (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
1991 adder->source_1_dx = CHAR_WIDTH;
1992 adder->source_1_dy = CHAR_HEIGHT;
1993 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
1994 adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1996 * update console cursor coordinates
1998 cursor[unit].x += CHAR_WIDTH;
1999 if (nograph)
2000 dga->x_cursor = TRANX(cursor[unit].x);
2001 if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
2002 blitc(unit, '\r');
2003 blitc(unit, '\n');
2006 } /* blitc */
2009 * INTERRUPT SERVICE ROUTINES
2013 * Service "DMA DONE" interrupt condition
2016 static void
2017 qddint(void *arg)
2019 device_t dv = arg;
2020 struct DMAreq_header *header;
2021 struct DMAreq *request;
2022 volatile struct dga *dga;
2023 volatile struct adder *adder;
2024 int cookie; /* DMA adrs for QDSS */
2025 int unit = device_unit(dv);
2027 (void)spl4(); /* allow interval timer in */
2030 * init pointers
2032 header = DMAheader[unit]; /* register for optimization */
2033 dga = (struct dga *) qdmap[unit].dga;
2034 adder = (struct adder *) qdmap[unit].adder;
2037 * if this interrupt flagged as bogus for interrupt flushing purposes..
2039 if (DMA_ISIGNORE(header)) {
2040 DMA_CLRIGNORE(header);
2041 return;
2045 * dump a DMA hardware error message if appropriate
2047 if (dga->csr & DMA_ERR) {
2049 if (dga->csr & PARITY_ERR)
2050 printf("qd%d: qddint: DMA hardware parity fault.\n", unit);
2052 if (dga->csr & BUS_ERR)
2053 printf("qd%d: qddint: DMA hardware bus error.\n", unit);
2057 * if this was a DMA from user space...
2059 if (qdflags[unit].user_dma) {
2060 qdflags[unit].user_dma = 0;
2061 wakeup((void *)&qdflags[unit].user_dma);
2062 return;
2066 * if we're doing DMA request queue services, field the error condition
2068 if (dga->csr & DMA_ERR) {
2070 dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
2071 dga->csr |= DMA_ERR; /* clear error condition */
2072 adder->command = CANCEL; /* cancel adder activity */
2074 DMA_SETERROR(header); /* flag error in header status word */
2075 DMA_CLRACTIVE(header);
2076 header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
2077 header->newest = header->oldest;
2078 header->used = 0;
2080 selnotify(&qdrsel[unit], 0, 0);
2082 if (dga->bytcnt_lo != 0) {
2083 dga->bytcnt_lo = 0;
2084 dga->bytcnt_hi = 0;
2085 DMA_SETIGNORE(header);
2087 return;
2091 * if the DMA request queue is now becoming non-full,
2092 * wakeup "select" client.
2094 if (DMA_ISFULL(header)) {
2095 selnotify(&qdrsel[unit], 0, 0);
2098 header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
2099 QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
2101 /* check for unexpected interrupt */
2102 if (DMA_ISEMPTY(header))
2103 return;
2105 DMA_GETEND(header); /* update request queue indices */
2108 * if no more DMA pending, wake up "select" client and exit
2110 if (DMA_ISEMPTY(header)) {
2111 selnotify(&qdrsel[unit], 0, 0);
2112 DMA_CLRACTIVE(header); /* flag DMA done */
2113 return;
2117 * initiate next DMA xfer
2119 request = DMA_GETBEGIN(header);
2120 if (request->DMAtype != QDlast_DMAtype) {
2121 dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
2122 adder->command = CANCEL; /* cancel adder activity */
2126 switch (request->DMAtype) {
2128 case DISPLIST:
2129 if (request->DMAtype != QDlast_DMAtype) {
2130 dga->csr |= DL_ENB;
2131 dga->csr &= ~(BTOP_ENB | BYTE_DMA);
2133 break;
2135 case PTOB:
2136 if (request->DMAtype != QDlast_DMAtype) {
2137 if (request->DMAdone & BYTE_PACK)
2138 dga->csr |= (PTOB_ENB | BYTE_DMA);
2139 else {
2140 dga->csr |= PTOB_ENB;
2141 dga->csr &= ~BYTE_DMA;
2144 break;
2146 case BTOP:
2147 if (request->DMAtype != QDlast_DMAtype) {
2148 if (request->DMAdone & BYTE_PACK) {
2149 dga->csr &= ~DL_ENB;
2150 dga->csr |= (BTOP_ENB | BYTE_DMA);
2152 else {
2153 dga->csr |= BTOP_ENB;
2154 dga->csr &= ~(BYTE_DMA | DL_ENB);
2157 break;
2158 default:
2159 printf("qd%d: qddint: illegal DMAtype parameter.\n", unit);
2160 DMA_CLRACTIVE(header); /* flag DMA done */
2161 return;
2164 if (request->DMAdone & COUNT_ZERO) {
2165 dga->csr &= ~SET_DONE_FIFO;
2167 else if (request->DMAdone & FIFO_EMPTY) {
2168 dga->csr |= SET_DONE_FIFO;
2171 if (request->DMAdone & WORD_PACK)
2172 dga->csr &= ~BYTE_DMA;
2173 else if (request->DMAdone & BYTE_PACK)
2174 dga->csr |= BYTE_DMA;
2176 dga->csr |= DMA_IE;
2177 QDlast_DMAtype = request->DMAtype;
2179 cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
2181 dga->adrs_lo = (short) cookie;
2182 dga->adrs_hi = (short) (cookie >> 16);
2184 dga->bytcnt_lo = (short) request->length;
2185 dga->bytcnt_hi = (short) (request->length >> 16);
2187 return;
2191 * ADDER interrupt service routine
2193 static void
2194 qdaint(void *arg)
2196 device_t dv = arg;
2197 volatile struct adder *adder;
2198 struct color_buf *cbuf;
2199 int i;
2200 struct rgb *rgbp;
2201 volatile short *red;
2202 volatile short *green;
2203 volatile short *blue;
2204 int unit = device_unit(dv);
2206 (void)spl4(); /* allow interval timer in */
2208 adder = (struct adder *) qdmap[unit].adder;
2211 * service the vertical blank interrupt (VSYNC bit) by loading
2212 * any pending color map load request
2214 if (adder->status & VSYNC) {
2215 adder->status &= ~VSYNC; /* clear the interrupt */
2216 cbuf = color_buf[unit];
2217 if (cbuf->status & LOAD_COLOR_MAP) {
2219 red = (short *) qdmap[unit].red;
2220 green = (short *) qdmap[unit].green;
2221 blue = (short *) qdmap[unit].blue;
2223 for (i = cbuf->count, rgbp = cbuf->rgb;
2224 --i >= 0; rgbp++) {
2225 red[rgbp->offset] = (short) rgbp->red;
2226 green[rgbp->offset] = (short) rgbp->green;
2227 blue[rgbp->offset] = (short) rgbp->blue;
2230 cbuf->status &= ~LOAD_COLOR_MAP;
2235 * service the scroll interrupt (FRAME_SYNC bit)
2237 if (adder->status & FRAME_SYNC) {
2238 adder->status &= ~FRAME_SYNC; /* clear the interrupt */
2240 if (scroll[unit]->status & LOAD_REGS) {
2242 for (i = 1000, adder->status = 0; i > 0 &&
2243 !(adder->status&ID_SCROLL_READY); --i)
2246 if (i == 0) {
2247 printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
2248 qd);
2249 return;
2252 adder->ID_scroll_data = scroll[unit]->viper_constant;
2253 adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
2255 adder->y_scroll_constant =
2256 scroll[unit]->y_scroll_constant;
2257 adder->y_offset_pending = scroll[unit]->y_offset;
2259 if (scroll[unit]->status & LOAD_INDEX) {
2261 adder->x_index_pending =
2262 scroll[unit]->x_index_pending;
2263 adder->y_index_pending =
2264 scroll[unit]->y_index_pending;
2267 scroll[unit]->status = 0x00;
2273 * DUART input interrupt service routine
2275 * XXX - this routine should be broken out - it is essentially
2276 * straight line code.
2279 static void
2280 qdiint(void *arg)
2282 device_t dv = arg;
2283 struct _vs_event *event;
2284 struct qdinput *eqh;
2285 volatile struct dga *dga;
2286 volatile struct duart *duart;
2287 struct mouse_report *new_rep;
2288 struct tty *tp;
2289 u_short chr;
2290 u_short status;
2291 u_short data;
2292 u_short key;
2293 char do_wakeup = 0; /* flag to do a select wakeup call */
2294 char a, b, c; /* mouse button test variables */
2295 int unit = device_unit(dv);
2297 (void)spl4(); /* allow interval timer in */
2299 eqh = eq_header[unit]; /* optimized as a register */
2300 new_rep = &current_rep[unit];
2301 duart = (struct duart *) qdmap[unit].duart;
2304 * if the graphic device is turned on..
2306 if (qdflags[unit].inuse & GRAPHIC_DEV) {
2308 * empty DUART
2310 while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
2312 * pick up LK-201 input (if any)
2314 if (duart->statusA&RCV_RDY) {
2316 /* if error condition, then reset it */
2318 if (duart->statusA&0x70) {
2319 duart->cmdA = 0x40;
2320 continue;
2323 /* event queue full now? (overflow condition) */
2325 if (ISFULL(eqh) == TRUE) {
2326 printf(
2327 "qd%d: qdiint: event queue overflow\n",
2328 qd);
2329 break;
2333 * Check for various keyboard errors */
2335 key = duart->dataA & 0xFF;
2337 if (key==LK_POWER_ERROR ||
2338 key==LK_KDOWN_ERROR ||
2339 key == LK_INPUT_ERROR ||
2340 key == LK_OUTPUT_ERROR) {
2341 printf(
2342 "qd%d: qdiint: keyboard error, code = %x\n",
2343 qd,key);
2344 return;
2347 if (key < LK_LOWEST)
2348 return;
2350 ++do_wakeup; /* request a select wakeup call */
2352 event = PUTBEGIN(eqh);
2353 PUTEND(eqh);
2355 event->vse_key = key;
2356 event->vse_key &= 0x00FF;
2357 event->vse_x = eqh->curs_pos.x;
2358 event->vse_y = eqh->curs_pos.y;
2359 event->vse_time = TOY;
2360 event->vse_type = VSE_BUTTON;
2361 event->vse_direction = VSE_KBTRAW;
2362 event->vse_device = VSE_DKB;
2366 * pick up the mouse input (if any) */
2368 if ((status = duart->statusB) & RCV_RDY &&
2369 qdflags[unit].pntr_id == MOUSE_ID) {
2371 if (status & 0x70) {
2372 duart->cmdB = 0x40;
2373 continue;
2376 /* event queue full now? (overflow condition) */
2378 if (ISFULL(eqh) == TRUE) {
2379 printf(
2380 "qd%d: qdiint: event queue overflow\n",
2381 qd);
2382 break;
2385 data = duart->dataB; /* get report byte */
2386 ++new_rep->bytcnt; /* bump report byte count */
2389 * if 1st byte of report.. */
2391 if ( data & START_FRAME) {
2392 new_rep->state = data;
2393 if (new_rep->bytcnt > 1) {
2394 /* start of new frame */
2395 new_rep->bytcnt = 1;
2396 /* ..continue looking */
2397 continue;
2402 * if 2nd byte of report.. */
2404 else if (new_rep->bytcnt == 2) {
2405 new_rep->dx = data & 0x00FF;
2409 * if 3rd byte of report, load input event queue */
2411 else if (new_rep->bytcnt == 3) {
2413 new_rep->dy = data & 0x00FF;
2414 new_rep->bytcnt = 0;
2417 * if mouse position has changed.. */
2419 if (new_rep->dx != 0 || new_rep->dy != 0) {
2422 * calculate acceleration factor, if needed */
2424 if (qdflags[unit].curs_acc > ACC_OFF) {
2426 if (qdflags[unit].curs_thr <= new_rep->dx)
2427 new_rep->dx +=
2428 (new_rep->dx - qdflags[unit].curs_thr)
2429 * qdflags[unit].curs_acc;
2431 if (qdflags[unit].curs_thr <= new_rep->dy)
2432 new_rep->dy +=
2433 (new_rep->dy - qdflags[unit].curs_thr)
2434 * qdflags[unit].curs_acc;
2438 * update cursor position coordinates */
2440 if (new_rep->state & X_SIGN) {
2441 eqh->curs_pos.x += new_rep->dx;
2442 if (eqh->curs_pos.x > 1023)
2443 eqh->curs_pos.x = 1023;
2445 else {
2446 eqh->curs_pos.x -= new_rep->dx;
2447 if (eqh->curs_pos.x < -15)
2448 eqh->curs_pos.x = -15;
2451 if (new_rep->state & Y_SIGN) {
2452 eqh->curs_pos.y -= new_rep->dy;
2453 if (eqh->curs_pos.y < -15)
2454 eqh->curs_pos.y = -15;
2456 else {
2457 eqh->curs_pos.y += new_rep->dy;
2458 if (eqh->curs_pos.y > 863)
2459 eqh->curs_pos.y = 863;
2463 * update cursor screen position */
2465 dga = (struct dga *) qdmap[unit].dga;
2466 dga->x_cursor = TRANX(eqh->curs_pos.x);
2467 dga->y_cursor = TRANY(eqh->curs_pos.y);
2470 * if cursor is in the box, no event report */
2472 if (eqh->curs_pos.x <= eqh->curs_box.right &&
2473 eqh->curs_pos.x >= eqh->curs_box.left &&
2474 eqh->curs_pos.y >= eqh->curs_box.top &&
2475 eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2476 goto GET_MBUTTON;
2480 * report the mouse motion event */
2482 event = PUTBEGIN(eqh);
2483 PUTEND(eqh);
2485 ++do_wakeup; /* request a select wakeup call */
2487 event->vse_x = eqh->curs_pos.x;
2488 event->vse_y = eqh->curs_pos.y;
2490 event->vse_device = VSE_MOUSE; /* mouse */
2491 event->vse_type = VSE_MMOTION; /* pos changed */
2492 event->vse_key = 0;
2493 event->vse_direction = 0;
2494 event->vse_time = TOY; /* time stamp */
2497 GET_MBUTTON:
2499 * if button state has changed */
2501 a = new_rep->state & 0x07; /*mask nonbutton bits */
2502 b = last_rep[unit].state & 0x07;
2504 if (a ^ b) {
2506 for ( c = 1; c < 8; c <<= 1) {
2508 if (!( c & (a ^ b))) /* this button change? */
2509 continue;
2511 /* event queue full? (overflow condition) */
2513 if (ISFULL(eqh) == TRUE) {
2514 printf("qd%d: qdiint: event queue overflow\n", qd);
2515 break;
2518 event = PUTBEGIN(eqh); /* get new event */
2519 PUTEND(eqh);
2521 ++do_wakeup; /* request select wakeup */
2523 event->vse_x = eqh->curs_pos.x;
2524 event->vse_y = eqh->curs_pos.y;
2526 event->vse_device = VSE_MOUSE; /* mouse */
2527 event->vse_type = VSE_BUTTON; /* new button */
2528 event->vse_time = TOY; /* time stamp */
2530 /* flag changed button and if up or down */
2532 if (c == RIGHT_BUTTON)
2533 event->vse_key = VSE_RIGHT_BUTTON;
2534 else if (c == MIDDLE_BUTTON)
2535 event->vse_key = VSE_MIDDLE_BUTTON;
2536 else if (c == LEFT_BUTTON)
2537 event->vse_key = VSE_LEFT_BUTTON;
2539 /* set bit = button depressed */
2541 if (c & a)
2542 event->vse_direction = VSE_KBTDOWN;
2543 else
2544 event->vse_direction = VSE_KBTUP;
2548 /* refresh last report */
2550 last_rep[unit] = current_rep[unit];
2552 } /* get last byte of report */
2553 } else if ((status = duart->statusB)&RCV_RDY &&
2554 qdflags[unit].pntr_id == TABLET_ID) {
2556 * pickup tablet input, if any
2558 if (status&0x70) {
2559 duart->cmdB = 0x40;
2560 continue;
2563 * event queue full now? (overflow condition)
2565 if (ISFULL(eqh) == TRUE) {
2566 printf("qd%d: qdiint: event queue overflow\n", qd);
2567 break;
2570 data = duart->dataB; /* get report byte */
2571 ++new_rep->bytcnt; /* bump report byte count */
2574 * if 1st byte of report.. */
2576 if (data & START_FRAME) {
2577 new_rep->state = data;
2578 if (new_rep->bytcnt > 1) {
2579 new_rep->bytcnt = 1; /* start of new frame */
2580 continue; /* ..continue looking */
2585 * if 2nd byte of report.. */
2587 else if (new_rep->bytcnt == 2) {
2588 new_rep->dx = data & 0x3F;
2592 * if 3rd byte of report.. */
2594 else if (new_rep->bytcnt == 3) {
2595 new_rep->dx |= (data & 0x3F) << 6;
2599 * if 4th byte of report.. */
2601 else if (new_rep->bytcnt == 4) {
2602 new_rep->dy = data & 0x3F;
2606 * if 5th byte of report, load input event queue */
2608 else if (new_rep->bytcnt == 5) {
2610 new_rep->dy |= (data & 0x3F) << 6;
2611 new_rep->bytcnt = 0;
2614 * update cursor position coordinates */
2616 new_rep->dx /= qdflags[unit].tab_res;
2617 new_rep->dy = (2200 - new_rep->dy)
2618 / qdflags[unit].tab_res;
2620 if (new_rep->dx > 1023) {
2621 new_rep->dx = 1023;
2623 if (new_rep->dy > 863) {
2624 new_rep->dy = 863;
2628 * report an event if the puck/stylus has moved
2631 if (eqh->curs_pos.x != new_rep->dx ||
2632 eqh->curs_pos.y != new_rep->dy) {
2634 eqh->curs_pos.x = new_rep->dx;
2635 eqh->curs_pos.y = new_rep->dy;
2638 * update cursor screen position */
2640 dga = (struct dga *) qdmap[unit].dga;
2641 dga->x_cursor = TRANX(eqh->curs_pos.x);
2642 dga->y_cursor = TRANY(eqh->curs_pos.y);
2645 * if cursor is in the box, no event report
2648 if (eqh->curs_pos.x <= eqh->curs_box.right &&
2649 eqh->curs_pos.x >= eqh->curs_box.left &&
2650 eqh->curs_pos.y >= eqh->curs_box.top &&
2651 eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2652 goto GET_TBUTTON;
2656 * report the tablet motion event */
2658 event = PUTBEGIN(eqh);
2659 PUTEND(eqh);
2661 ++do_wakeup; /* request a select wakeup call */
2663 event->vse_x = eqh->curs_pos.x;
2664 event->vse_y = eqh->curs_pos.y;
2666 event->vse_device = VSE_TABLET; /* tablet */
2668 * right now, X handles tablet motion the same
2669 * as mouse motion
2671 event->vse_type = VSE_MMOTION; /* pos changed */
2672 event->vse_key = 0;
2673 event->vse_direction = 0;
2674 event->vse_time = TOY; /* time stamp */
2676 GET_TBUTTON:
2678 * if button state has changed */
2680 a = new_rep->state & 0x1E; /* mask nonbutton bits */
2681 b = last_rep[unit].state & 0x1E;
2683 if (a ^ b) {
2685 /* event queue full now? (overflow condition) */
2687 if (ISFULL(eqh) == TRUE) {
2688 printf("qd%d: qdiint: event queue overflow\n",qd);
2689 break;
2692 event = PUTBEGIN(eqh); /* get new event */
2693 PUTEND(eqh);
2695 ++do_wakeup; /* request a select wakeup call */
2697 event->vse_x = eqh->curs_pos.x;
2698 event->vse_y = eqh->curs_pos.y;
2700 event->vse_device = VSE_TABLET; /* tablet */
2701 event->vse_type = VSE_BUTTON; /* button changed */
2702 event->vse_time = TOY; /* time stamp */
2704 /* define the changed button and if up or down */
2706 for ( c = 1; c <= 0x10; c <<= 1) {
2707 if (c & (a ^ b)) {
2708 if (c == T_LEFT_BUTTON)
2709 event->vse_key = VSE_T_LEFT_BUTTON;
2710 else if (c == T_FRONT_BUTTON)
2711 event->vse_key = VSE_T_FRONT_BUTTON;
2712 else if (c == T_RIGHT_BUTTON)
2713 event->vse_key = VSE_T_RIGHT_BUTTON;
2714 else if (c == T_BACK_BUTTON)
2715 event->vse_key = VSE_T_BACK_BUTTON;
2716 break;
2720 /* set bit = button depressed */
2722 if (c & a)
2723 event->vse_direction = VSE_KBTDOWN;
2724 else
2725 event->vse_direction = VSE_KBTUP;
2728 /* refresh last report */
2730 last_rep[unit] = current_rep[unit];
2732 } /* get last byte of report */
2733 } /* pick up tablet input */
2735 } /* while input available.. */
2738 * do select wakeup
2740 if (do_wakeup) {
2741 selnotify(&qdrsel[unit], 0, 0);
2742 do_wakeup = 0;
2744 } else {
2746 * if the graphic device is not turned on, this is console input
2748 if (qdpolling)
2749 return;
2751 if (unit >= qd_cd.cd_ndevs || device_lookup(&qd_cd, unit) == NULL)
2752 return; /* no such device or address */
2754 tp = qd_tty[unit << 2];
2757 * Get a character from the keyboard.
2759 while (duart->statusA&RCV_RDY) {
2760 key = duart->dataA;
2761 key &= 0xFF;
2763 * Check for various keyboard errors
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;
2771 if (key < LK_LOWEST)
2772 return;
2775 * See if its a state change key */
2777 switch (key) {
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;
2789 case SHIFT:
2790 q_keyboard.shift ^= 0xFFFF;
2791 return;
2793 case CNTRL:
2794 q_keyboard.cntrl ^= 0xFFFF;
2795 return;
2797 case ALLUP:
2798 q_keyboard.cntrl = 0;
2799 q_keyboard.shift = 0;
2800 return;
2802 case REPEAT:
2803 chr = q_keyboard.last;
2804 break;
2807 * Test for cntrl characters. If set, see if the character
2808 * is elligible to become a control character. */
2810 default:
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;
2819 else if( q_keyboard.lock || q_keyboard.shift )
2820 chr = q_shift_key[key];
2821 else
2822 chr = q_key[key];
2823 break;
2826 q_keyboard.last = chr;
2829 * Check for special function keys */
2831 if (chr & 0x100) {
2832 char *string;
2833 string = q_special[chr & 0x7F];
2834 while(*string)
2835 (*tp->t_linesw->l_rint)(*string++, tp);
2837 else {
2838 #ifdef DDB
2839 /* Check for kernel debugger escape here */
2840 int j;
2842 j = kdbrint(chr&0177);
2844 if (j == 1) /* Escape received, just return */
2845 return;
2847 if (j == 2) /* Second char wasn't 'D' */
2848 (*tp->t_linesw->l_rint)(27, tp);
2849 #endif
2850 (*tp->t_linesw->l_rint)(chr&0177, tp);
2854 } /* qdiint */
2858 * Clear the QDSS screen
2860 * >>> NOTE <<<
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.
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
2872 void
2873 clear_qd_screen(int unit)
2875 volatile struct adder *adder;
2876 adder = (struct adder *) qdmap[unit].adder;
2878 adder->x_limit = 1024;
2879 adder->y_limit = 2048 - CHAR_HEIGHT;
2880 adder->y_offset_pending = 0;
2881 #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
2882 WSV;
2883 adder->y_scroll_constant = SCROLL_ERASE;
2884 WSV;
2885 adder->y_offset_pending = 864;
2886 WSV;
2887 adder->y_scroll_constant = SCROLL_ERASE;
2888 WSV;
2889 adder->y_offset_pending = 1728;
2890 WSV;
2891 adder->y_scroll_constant = SCROLL_ERASE;
2892 WSV;
2893 adder->y_offset_pending = 0; /* back to normal */
2894 WSV;
2895 adder->x_limit = MAX_SCREEN_X;
2896 adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2897 #undef WSV
2899 } /* clear_qd_screen */
2902 * kernel console output to the glass tty
2904 void
2905 qdcnputc(dev_t dev, int chr)
2909 * if system is now physical, forget it (ie: crash DUMP)
2911 if ((mfpr(PR_MAPEN) & 1) == 0)
2912 return;
2914 blitc(0, (u_char)(chr & 0xff));
2915 if ((chr & 0177) == '\n')
2916 blitc(0, '\r');
2918 } /* qdputc */
2921 * load the mouse cursor's template RAM bitmap
2923 void
2924 ldcursor(int unit, short *bitmap)
2926 volatile struct dga *dga;
2927 volatile short *temp;
2928 int i;
2929 int curs;
2931 dga = (struct dga *) qdmap[unit].dga;
2932 temp = (short *) qdmap[unit].template;
2934 if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */
2935 curs = -1; /* ..note that.. */
2936 dga->csr &= ~CURS_ENB; /* ..and shut it off */
2937 } else
2938 curs = 0;
2940 dga->csr &= ~CURS_ENB; /* shut off the cursor */
2942 temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */
2943 /* ..of the 8k WORD template space */
2944 for (i = 0; i < 32; ++i)
2945 *temp++ = *bitmap++;
2947 if (curs) { /* if cursor was enabled.. */
2948 dga->csr |= CURS_ENB; /* ..turn it back on */
2951 } /* ldcursor */
2954 * Put the console font in the QDSS off-screen memory
2956 void
2957 ldfont(int unit)
2959 volatile struct adder *adder;
2961 int i, j, k, max_chars_line;
2962 short packed;
2964 adder = (struct adder *) qdmap[unit].adder;
2967 * setup VIPER operand control registers
2969 write_ID(adder, MASK_1, 0xFFFF);
2970 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
2971 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
2973 write_ID(adder, SRC1_OCR_B,
2974 EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
2975 write_ID(adder, SRC2_OCR_B,
2976 EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
2977 write_ID(adder, DST_OCR_B,
2978 EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
2980 adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
2983 * load destination data
2985 (void)wait_status(adder, RASTEROP_COMPLETE);
2987 adder->destination_x = FONT_X;
2988 adder->destination_y = FONT_Y;
2989 #if FONT_WIDTH > MAX_SCREEN_X
2990 adder->fast_dest_dx = MAX_SCREEN_X;
2991 #else
2992 adder->fast_dest_dx = FONT_WIDTH;
2993 #endif
2994 adder->slow_dest_dy = CHAR_HEIGHT;
2997 * setup for processor to bitmap xfer */
2999 write_ID(adder, CS_UPDATE_MASK, 0x0001);
3000 adder->cmd = PBT | OCRB | 2 | DTE | 2;
3003 * Figure out how many characters can be stored on one "line" of
3004 * offscreen memory.
3006 max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3007 if ((CHARS/2 + CHARS%2) < max_chars_line)
3008 max_chars_line = CHARS/2 + CHARS%2;
3011 * iteratively do the processor to bitmap xfer */
3013 for (i = 0; i < ROWS; ++i) {
3015 /* PTOB a scan line */
3017 for (j = 0, k = i; j < max_chars_line; ++j) {
3018 /* PTOB one scan of a char cell */
3020 packed = q_font[k];
3021 k += ROWS;
3022 packed |= ((short)q_font[k] << 8);
3023 k += ROWS;
3025 (void)wait_status(adder, TX_READY);
3026 adder->id_data = packed;
3031 * (XXX XXX XXX - should remove)
3033 * Copy the second row of characters. Subtract the first
3034 * row from the total number. Divide this quantity by 2
3035 * because 2 chars are stored in a short in the PTOB loop
3036 * below. Figure out how many characters can be stored on
3037 * one "line" of offscreen memory
3040 max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3041 if ((CHARS/2 + CHARS%2) < max_chars_line)
3042 return;
3043 max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
3044 /* Paranoia check to see if 3rd row may be needed */
3045 if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
3046 max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3048 adder->destination_x = FONT_X;
3049 adder->destination_y = FONT_Y - CHAR_HEIGHT;
3050 adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
3051 adder->slow_dest_dy = CHAR_HEIGHT;
3054 * setup for processor to bitmap xfer
3056 write_ID(adder, CS_UPDATE_MASK, 0x0001);
3057 adder->cmd = PBT | OCRB | 2 | DTE | 2;
3060 * iteratively do the processor to bitmap xfer
3062 for (i = 0; i < ROWS; ++i) {
3064 * PTOB a scan line
3066 for (j = 0, k = i; j < max_chars_line; ++j) {
3068 * PTOB one scan of a char cell
3070 packed = q_font[k + FONT_OFFSET];
3071 k += ROWS;
3072 packed |= ((short)q_font[k + FONT_OFFSET] << 8);
3073 k += ROWS;
3074 (void)wait_status(adder, TX_READY);
3075 adder->id_data = packed;
3079 } /* ldfont */
3083 * Disable or enable polling. This is used when entering or leaving the
3084 * kernel debugger.
3086 void
3087 qdcnpollc(dev_t dev, int onoff)
3089 qdpolling = onoff;
3094 * Get a character from the LK201 (polled)
3097 qdcngetc(dev_t dev)
3099 short key;
3100 char chr;
3101 volatile struct duart *duart;
3103 duart = (struct duart *) qdmap[0].duart;
3106 * Get a character from the keyboard.
3108 LOOP:
3109 while (!(duart->statusA&RCV_RDY))
3112 key = duart->dataA;
3113 key &= 0xFF;
3116 * Check for various keyboard errors */
3118 if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
3119 key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
3120 printf("Keyboard error, code = %x\n", key);
3121 return(0);
3124 if (key < LK_LOWEST)
3125 return(0);
3128 * See if its a state change key
3130 switch (key) {
3132 case LOCK:
3133 q_keyboard.lock ^= 0xffff; /* toggle */
3134 if (q_keyboard.lock)
3135 led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
3136 else
3137 led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
3138 goto LOOP;
3140 case SHIFT:
3141 q_keyboard.shift ^= 0xFFFF;
3142 goto LOOP;
3144 case CNTRL:
3145 q_keyboard.cntrl ^= 0xFFFF;
3146 goto LOOP;
3148 case ALLUP:
3149 q_keyboard.cntrl = 0;
3150 q_keyboard.shift = 0;
3151 goto LOOP;
3153 case REPEAT:
3154 chr = q_keyboard.last;
3155 break;
3158 * Test for cntrl characters. If set, see if the character
3159 * is elligible to become a control character.
3161 default:
3163 if (q_keyboard.cntrl) {
3164 chr = q_key[key];
3165 if (chr >= ' ' && chr <= '~')
3166 chr &= 0x1F;
3168 else if ( q_keyboard.lock || q_keyboard.shift )
3169 chr = q_shift_key[key];
3170 else
3171 chr = q_key[key];
3172 break;
3175 if (chr < ' ' && chr > '~') /* if input is non-displayable */
3176 return(0); /* ..then pitch it! */
3178 q_keyboard.last = chr;
3181 * Check for special function keys */
3183 if (chr & 0x80) /* pitch the function keys */
3184 return(0);
3185 else
3186 return(chr);
3188 } /* qdgetc */
3191 * led_control()... twiddle LK-201 LED's
3193 void
3194 led_control(int unit, int cmd, int led_mask)
3196 int i;
3197 volatile struct duart *duart;
3199 duart = (struct duart *)qdmap[unit].duart;
3201 for (i = 1000; i > 0; --i) {
3202 if (duart->statusA&XMT_RDY) {
3203 duart->dataA = cmd;
3204 break;
3207 for (i = 1000; i > 0; --i) {
3208 if (duart->statusA&XMT_RDY) {
3209 duart->dataA = led_mask;
3210 break;
3213 return;
3215 } /* led_control */
3218 * scroll_up()... move the screen up one character height
3220 void
3221 scroll_up(volatile struct adder *adder)
3224 * setup VIPER operand control registers
3226 (void)wait_status(adder, ADDRESS_COMPLETE);
3227 write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
3228 write_ID(adder, MASK_1, 0xFFFF);
3229 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3230 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3231 write_ID(adder, SRC1_OCR_B,
3232 EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
3233 write_ID(adder, DST_OCR_B,
3234 EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3236 * load DESTINATION origin and vectors
3238 adder->fast_dest_dy = 0;
3239 adder->slow_dest_dx = 0;
3240 adder->error_1 = 0;
3241 adder->error_2 = 0;
3242 adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
3243 adder->destination_x = 0;
3244 adder->fast_dest_dx = 1024;
3245 adder->destination_y = 0;
3246 adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3248 * load SOURCE origin and vectors
3250 adder->source_1_x = 0;
3251 adder->source_1_dx = 1024;
3252 adder->source_1_y = 0 + CHAR_HEIGHT;
3253 adder->source_1_dy = 864 - CHAR_HEIGHT;
3254 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3255 adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3257 * do a rectangle clear of last screen line
3259 write_ID(adder, MASK_1, 0xffff);
3260 write_ID(adder, SOURCE, 0xffff);
3261 write_ID(adder,DST_OCR_B,
3262 (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
3263 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
3264 adder->error_1 = 0;
3265 adder->error_2 = 0;
3266 adder->slow_dest_dx = 0; /* set up the width of */
3267 adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */
3268 adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
3269 (void)wait_status(adder, RASTEROP_COMPLETE);
3270 adder->destination_x = 0;
3271 adder->destination_y = 864 - CHAR_HEIGHT;
3272 adder->fast_dest_dx = 1024; /* set up the height */
3273 adder->fast_dest_dy = 0; /* of rectangle */
3274 write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
3275 adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
3277 } /* scroll_up */
3280 * init shared memory pointers and structures
3282 void
3283 init_shared(int unit)
3285 volatile struct dga *dga;
3287 dga = (struct dga *) qdmap[unit].dga;
3290 * initialize the event queue pointers and header */
3292 eq_header[unit] = (struct qdinput *)
3293 ((((int)event_shared & ~(0x01FF)) + 512)
3294 + (EVENT_BUFSIZE * unit));
3295 eq_header[unit]->curs_pos.x = 0;
3296 eq_header[unit]->curs_pos.y = 0;
3297 dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
3298 dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
3299 eq_header[unit]->curs_box.left = 0;
3300 eq_header[unit]->curs_box.right = 0;
3301 eq_header[unit]->curs_box.top = 0;
3302 eq_header[unit]->curs_box.bottom = 0;
3304 * assign a pointer to the DMA I/O buffer for this QDSS.
3306 DMAheader[unit] = (struct DMAreq_header *)
3307 (((int)(&DMA_shared[0] + 512) & ~0x1FF)
3308 + (DMAbuf_size * unit));
3309 DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
3310 + sizeof(struct DMAreq_header));
3311 DMAheader[unit]->QBAreg = 0;
3312 DMAheader[unit]->status = 0;
3313 DMAheader[unit]->shared_size = DMAbuf_size;
3314 DMAheader[unit]->used = 0;
3315 DMAheader[unit]->size = 10; /* default = 10 requests */
3316 DMAheader[unit]->oldest = 0;
3317 DMAheader[unit]->newest = 0;
3319 * assign a pointer to the scroll structure for this QDSS.
3321 scroll[unit] = (struct scroll *)
3322 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
3323 + (sizeof(struct scroll) * unit));
3324 scroll[unit]->status = 0;
3325 scroll[unit]->viper_constant = 0;
3326 scroll[unit]->y_scroll_constant = 0;
3327 scroll[unit]->y_offset = 0;
3328 scroll[unit]->x_index_pending = 0;
3329 scroll[unit]->y_index_pending = 0;
3331 * assign a pointer to the color map write buffer for this QDSS
3333 color_buf[unit] = (struct color_buf *)
3334 (((int)(&color_shared[0] + 512) & ~0x1FF)
3335 + (COLOR_BUFSIZ * unit));
3336 color_buf[unit]->status = 0;
3337 color_buf[unit]->count = 0;
3339 } /* init_shared */
3342 * init the ADDER, VIPER, bitmaps, & color map
3344 void
3345 setup_dragon(int unit)
3348 volatile struct adder *adder;
3349 volatile struct dga *dga;
3350 volatile short *memcsr;
3351 int i;
3352 short top; /* clipping/scrolling boundaries */
3353 short bottom;
3354 short right;
3355 short left;
3356 volatile short *red; /* color map pointers */
3357 volatile short *green;
3358 volatile short *blue;
3361 * init for setup
3363 adder = (struct adder *) qdmap[unit].adder;
3364 dga = (struct dga *) qdmap[unit].dga;
3365 memcsr = (short *) qdmap[unit].memcsr;
3366 dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */
3367 *memcsr = SYNC_ON; /* blank screen and turn off LED's */
3368 adder->command = CANCEL;
3370 * set monitor timing
3372 adder->x_scan_count_0 = 0x2800;
3373 adder->x_scan_count_1 = 0x1020;
3374 adder->x_scan_count_2 = 0x003A;
3375 adder->x_scan_count_3 = 0x38F0;
3376 adder->x_scan_count_4 = 0x6128;
3377 adder->x_scan_count_5 = 0x093A;
3378 adder->x_scan_count_6 = 0x313C;
3379 adder->sync_phase_adj = 0x0100;
3380 adder->x_scan_conf = 0x00C8;
3382 * got a bug in secound pass ADDER! lets take care of it
3384 * normally, just use the code in the following bug fix code, but to
3385 * make repeated demos look pretty, load the registers as if there was
3386 * no bug and then test to see if we are getting sync
3388 adder->y_scan_count_0 = 0x135F;
3389 adder->y_scan_count_1 = 0x3363;
3390 adder->y_scan_count_2 = 0x2366;
3391 adder->y_scan_count_3 = 0x0388;
3393 * if no sync, do the bug fix code
3395 if (wait_status(adder, VSYNC) == BAD) {
3396 /* first load all Y scan registers with very short frame and
3397 * wait for scroll service. This guarantees at least one SYNC
3398 * to fix the pass 2 Adder initialization bug (synchronizes
3399 * XCINCH with DMSEEDH)
3401 adder->y_scan_count_0 = 0x01;
3402 adder->y_scan_count_1 = 0x01;
3403 adder->y_scan_count_2 = 0x01;
3404 adder->y_scan_count_3 = 0x01;
3406 * delay at least 1 full frame time
3408 (void)wait_status(adder, VSYNC);
3409 (void)wait_status(adder, VSYNC);
3411 * now load the REAL sync values (in reverse order just to
3412 * be safe.
3414 adder->y_scan_count_3 = 0x0388;
3415 adder->y_scan_count_2 = 0x2366;
3416 adder->y_scan_count_1 = 0x3363;
3417 adder->y_scan_count_0 = 0x135F;
3419 *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */
3421 * zero the index registers
3423 adder->x_index_pending = 0;
3424 adder->y_index_pending = 0;
3425 adder->x_index_new = 0;
3426 adder->y_index_new = 0;
3427 adder->x_index_old = 0;
3428 adder->y_index_old = 0;
3429 adder->pause = 0;
3431 * set rasterop mode to normal pen down
3433 adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3435 * set the rasterop registers to a default values
3437 adder->source_1_dx = 1;
3438 adder->source_1_dy = 1;
3439 adder->source_1_x = 0;
3440 adder->source_1_y = 0;
3441 adder->destination_x = 0;
3442 adder->destination_y = 0;
3443 adder->fast_dest_dx = 1;
3444 adder->fast_dest_dy = 0;
3445 adder->slow_dest_dx = 0;
3446 adder->slow_dest_dy = 1;
3447 adder->error_1 = 0;
3448 adder->error_2 = 0;
3450 * scale factor = UNITY
3452 adder->fast_scale = UNITY;
3453 adder->slow_scale = UNITY;
3455 * set the source 2 parameters
3457 adder->source_2_x = 0;
3458 adder->source_2_y = 0;
3459 adder->source_2_size = 0x0022;
3461 * initialize plane addresses for eight vipers
3463 write_ID(adder, CS_UPDATE_MASK, 0x0001);
3464 write_ID(adder, PLANE_ADDRESS, 0x0000);
3465 write_ID(adder, CS_UPDATE_MASK, 0x0002);
3466 write_ID(adder, PLANE_ADDRESS, 0x0001);
3467 write_ID(adder, CS_UPDATE_MASK, 0x0004);
3468 write_ID(adder, PLANE_ADDRESS, 0x0002);
3469 write_ID(adder, CS_UPDATE_MASK, 0x0008);
3470 write_ID(adder, PLANE_ADDRESS, 0x0003);
3471 write_ID(adder, CS_UPDATE_MASK, 0x0010);
3472 write_ID(adder, PLANE_ADDRESS, 0x0004);
3473 write_ID(adder, CS_UPDATE_MASK, 0x0020);
3474 write_ID(adder, PLANE_ADDRESS, 0x0005);
3475 write_ID(adder, CS_UPDATE_MASK, 0x0040);
3476 write_ID(adder, PLANE_ADDRESS, 0x0006);
3477 write_ID(adder, CS_UPDATE_MASK, 0x0080);
3478 write_ID(adder, PLANE_ADDRESS, 0x0007);
3480 * initialize the external registers.
3482 write_ID(adder, CS_UPDATE_MASK, 0x00FF);
3483 write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3485 * initialize resolution mode
3487 write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */
3488 write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */
3490 * initialize viper registers
3492 write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
3493 write_ID(adder, SCROLL_FILL, 0x0000);
3495 * set clipping and scrolling limits to full screen
3497 for (i = 1000, adder->status = 0;
3498 i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
3500 if (i == 0)
3501 printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
3502 top = 0;
3503 bottom = 2048;
3504 left = 0;
3505 right = 1024;
3506 adder->x_clip_min = left;
3507 adder->x_clip_max = right;
3508 adder->y_clip_min = top;
3509 adder->y_clip_max = bottom;
3510 adder->scroll_x_min = left;
3511 adder->scroll_x_max = right;
3512 adder->scroll_y_min = top;
3513 adder->scroll_y_max = bottom;
3514 (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */
3515 (void)wait_status(adder, VSYNC);
3516 adder->x_index_pending = left;
3517 adder->y_index_pending = top;
3518 adder->x_index_new = left;
3519 adder->y_index_new = top;
3520 adder->x_index_old = left;
3521 adder->y_index_old = top;
3523 for (i = 1000, adder->status = 0; i > 0 &&
3524 !(adder->status&ADDRESS_COMPLETE) ; --i)
3526 if (i == 0)
3527 printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
3529 write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
3530 write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3532 * set source and the mask register to all ones (ie: white) o
3534 write_ID(adder, SOURCE, 0xFFFF);
3535 write_ID(adder, MASK_1, 0xFFFF);
3536 write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3537 write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3539 * initialize Operand Control Register banks for fill command
3541 write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT);
3542 write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
3543 write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3544 write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
3545 write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT);
3546 write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3548 * init Logic Unit Function registers, (these are just common values,
3549 * and may be changed as required).
3551 write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3552 write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
3553 INV_M1_M2);
3554 write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
3555 write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3557 * load the color map for black & white
3559 for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
3562 if (i == 0)
3563 printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
3565 red = (short *) qdmap[unit].red;
3566 green = (short *) qdmap[unit].green;
3567 blue = (short *) qdmap[unit].blue;
3569 *red++ = 0x00; /* black */
3570 *green++ = 0x00;
3571 *blue++ = 0x00;
3573 *red-- = 0xFF; /* white */
3574 *green-- = 0xFF;
3575 *blue-- = 0xFF;
3578 * set color map for mouse cursor
3581 red += 254;
3582 green += 254;
3583 blue += 254;
3585 *red++ = 0x00; /* black */
3586 *green++ = 0x00;
3587 *blue++ = 0x00;
3589 *red = 0xFF; /* white */
3590 *green = 0xFF;
3591 *blue = 0xFF;
3593 } /* setup_dragon */
3596 * Init the DUART and set defaults in input
3598 void
3599 setup_input(int unit)
3601 volatile struct duart *duart; /* DUART register structure pointer */
3602 int i, bits;
3603 char id_byte;
3605 duart = (struct duart *) qdmap[unit].duart;
3606 duart->imask = 0;
3609 * setup the DUART for kbd & pointing device
3611 duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */
3612 duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */
3613 /* no RTS control,char error mode */
3614 duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */
3615 /* no RTS control,no echo or loop */
3616 duart->cmdB = RESET_M; /* reset mode reg pntr for host */
3617 duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */
3618 /* ..no RTS cntrl, char error mode */
3619 duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */
3620 /* no RTS control,no echo or loop */
3621 duart->auxctl = 0x00; /* baud rate set 1 */
3622 duart->clkselA = 0x99; /* 4800 baud for kbd */
3623 duart->clkselB = 0x99; /* 4800 baud for mouse */
3625 /* reset everything for keyboard */
3627 for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3628 duart->cmdA = bits;
3630 /* reset everything for host */
3632 for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3633 duart->cmdB = bits;
3635 duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
3636 duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
3639 * init keyboard defaults (DUART channel A)
3641 for (i = 500; i > 0; --i) {
3642 if (duart->statusA&XMT_RDY) {
3643 duart->dataA = LK_DEFAULTS;
3644 break;
3648 for (i = 100000; i > 0; --i) {
3649 if (duart->statusA&RCV_RDY) {
3650 break;
3654 if (duart->dataA) /* flush the ACK */
3658 * identify the pointing device
3660 for (i = 500; i > 0; --i) {
3661 if (duart->statusB&XMT_RDY) {
3662 duart->dataB = SELF_TEST;
3663 break;
3668 * wait for 1st byte of self test report */
3670 for (i = 100000; i > 0; --i) {
3671 if (duart->statusB&RCV_RDY) {
3672 break;
3676 if (i == 0) {
3677 printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
3678 ,unit);
3679 goto OUT;
3682 if (duart->dataB)
3686 * wait for ID byte of self test report
3688 for (i = 100000; i > 0; --i) {
3689 if (duart->statusB&RCV_RDY) {
3690 break;
3694 if (i == 0) {
3695 printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
3696 goto OUT;
3699 id_byte = duart->dataB;
3702 * wait for other bytes to come in
3704 for (i = 100000; i > 0; --i) {
3705 if (duart->statusB & RCV_RDY) {
3706 if (duart->dataB)
3708 break;
3711 if (i == 0) {
3712 printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
3713 goto OUT;
3715 for (i = 100000; i > 0; --i) {
3716 if (duart->statusB&RCV_RDY) {
3717 if (duart->dataB)
3719 break;
3722 if (i == 0) {
3723 printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
3724 goto OUT;
3727 * flag pointing device type and set defaults
3729 for (i=100000; i>0; --i)
3730 ; /*XXX*/
3732 if ((id_byte & 0x0F) != TABLET_ID) {
3733 qdflags[unit].pntr_id = MOUSE_ID;
3735 for (i = 500; i > 0; --i) {
3736 if (duart->statusB&XMT_RDY) {
3737 duart->dataB = INC_STREAM_MODE;
3738 break;
3742 else {
3743 qdflags[unit].pntr_id = TABLET_ID;
3745 for (i = 500; i > 0; --i) {
3746 if (duart->statusB&XMT_RDY) {
3747 duart->dataB = T_STREAM;
3748 break;
3752 OUT:
3753 duart->imask = qdflags[unit].duart_imask;
3755 } /* setup_input */
3758 * delay for at least one display frame time
3760 * return: BAD means that we timed out without ever seeing the
3761 * vertical sync status bit
3762 * GOOD otherwise
3765 wait_status(volatile struct adder *adder, int mask)
3767 int i;
3769 for (i = 10000, adder->status = 0 ; i > 0 &&
3770 !(adder->status&mask) ; --i)
3773 if (i == 0) {
3774 printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
3775 return(BAD);
3778 return(GOOD);
3780 } /* wait_status */
3783 * write out onto the ID bus
3785 void
3786 write_ID(volatile struct adder *adder, short adrs, short data)
3788 int i;
3790 for (i = 100000, adder->status = 0 ;
3791 i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i)
3794 if (i == 0)
3795 goto ERR;
3797 for (i = 100000, adder->status = 0 ;
3798 i > 0 && !(adder->status&TX_READY) ; --i)
3801 if (i > 0) {
3802 adder->id_data = data;
3803 adder->command = ID_LOAD | adrs;
3804 return ;
3807 ERR:
3808 printf("write_ID: timeout trying to write to VIPER\n");
3809 return ;
3811 } /* write_ID */