1006e9885Smarc /*
2537afb73Sbostic * Copyright (c) 1988 Regents of the University of California.
3537afb73Sbostic * All rights reserved.
4006e9885Smarc *
59c395af7Sbostic * %sccs.include.redist.c%
6006e9885Smarc *
7*61ab9802Skarels * @(#)qd.c 7.1 (Berkeley) 06/28/91
8006e9885Smarc */
9b2b69f49Smarc
107e911b15Skarels /************************************************************************
117e911b15Skarels * *
12e977faadSmarc * Copyright (c) 1985-1988 by *
137e911b15Skarels * Digital Equipment Corporation, Maynard, MA *
147e911b15Skarels * All rights reserved. *
157e911b15Skarels * *
167e911b15Skarels * This software is furnished under a license and may be used and *
177e911b15Skarels * copied only in accordance with the terms of such license and *
187e911b15Skarels * with the inclusion of the above copyright notice. This *
197e911b15Skarels * software or any other copies thereof may not be provided or *
207e911b15Skarels * otherwise made available to any other person. No title to and *
217e911b15Skarels * ownership of the software is hereby transferred. *
227e911b15Skarels * *
237e911b15Skarels * The information in this software is subject to change without *
247e911b15Skarels * notice and should not be construed as a commitment by Digital *
257e911b15Skarels * Equipment Corporation. *
267e911b15Skarels * *
277e911b15Skarels * Digital assumes no responsibility for the use or reliability *
287e911b15Skarels * of its software on equipment which is not supplied by Digital. *
297e911b15Skarels * *
307e911b15Skarels *************************************************************************/
31e977faadSmarc
327e911b15Skarels /*
33b2b69f49Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
347e911b15Skarels */
357e911b15Skarels
36b2b69f49Smarc #include "qd.h"
37e977faadSmarc
38006e9885Smarc #if NQD > 0
3939bdaf89Sbostic #include "../include/pte.h"
4039bdaf89Sbostic #include "../include/mtpr.h"
4139bdaf89Sbostic #include "sys/param.h"
4239bdaf89Sbostic #include "../include/cpu.h"
4339bdaf89Sbostic #include "sys/conf.h"
4439bdaf89Sbostic #include "sys/user.h"
45b2b69f49Smarc #include "qdioctl.h"
4639bdaf89Sbostic #include "sys/tty.h"
4739bdaf89Sbostic #include "sys/map.h"
4839bdaf89Sbostic #include "sys/buf.h"
4939bdaf89Sbostic #include "sys/vm.h"
5039bdaf89Sbostic #include "sys/clist.h"
5139bdaf89Sbostic #include "sys/file.h"
5239bdaf89Sbostic #include "sys/uio.h"
5339bdaf89Sbostic #include "sys/kernel.h"
5439bdaf89Sbostic #include "sys/exec.h"
5539bdaf89Sbostic #include "sys/proc.h"
56b2b69f49Smarc #include "ubareg.h"
57b2b69f49Smarc #include "ubavar.h"
5839bdaf89Sbostic #include "sys/syslog.h"
59b2b69f49Smarc #include "qduser.h" /* definitions shared with user level client */
60e977faadSmarc #include "qdreg.h" /* QDSS device register structures */
6124f67f6bSmarc
62b2b69f49Smarc /*
63b2b69f49Smarc * QDSS driver status flags for tracking operational state
64b2b69f49Smarc */
6524f67f6bSmarc struct qdflags {
6624f67f6bSmarc u_int inuse; /* which minor dev's are in use now */
6724f67f6bSmarc u_int config; /* I/O page register content */
6824f67f6bSmarc u_int mapped; /* user mapping status word */
69e977faadSmarc u_int kernel_loop; /* if kernel console is redirected */
7024f67f6bSmarc u_int user_dma; /* DMA from user space in progress */
7124f67f6bSmarc u_short pntr_id; /* type code of pointing device */
7224f67f6bSmarc u_short duart_imask; /* shadowing for duart intrpt mask reg */
7324f67f6bSmarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */
7424f67f6bSmarc u_short curs_acc; /* cursor acceleration factor */
7524f67f6bSmarc u_short curs_thr; /* cursor acceleration threshold level */
7624f67f6bSmarc u_short tab_res; /* tablet resolution factor */
7724f67f6bSmarc u_short selmask; /* mask for active qd select entries */
7824f67f6bSmarc };
7924f67f6bSmarc
80b2b69f49Smarc /*
81b2b69f49Smarc * bit definitions for 'inuse' entry
82b2b69f49Smarc */
8324f67f6bSmarc #define CONS_DEV 0x01
8424f67f6bSmarc #define GRAPHIC_DEV 0x04
8524f67f6bSmarc
86b2b69f49Smarc /*
87b2b69f49Smarc * bit definitions for 'mapped' member of flag structure
88b2b69f49Smarc */
8924f67f6bSmarc #define MAPDEV 0x01 /* hardware is mapped */
9024f67f6bSmarc #define MAPDMA 0x02 /* DMA buffer mapped */
9124f67f6bSmarc #define MAPEQ 0x04 /* event queue buffer mapped */
9224f67f6bSmarc #define MAPSCR 0x08 /* scroll param area mapped */
9324f67f6bSmarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */
9424f67f6bSmarc
95b2b69f49Smarc /*
96b2b69f49Smarc * bit definitions for 'selmask' member of qdflag structure
97b2b69f49Smarc */
9824f67f6bSmarc #define SEL_READ 0x01 /* read select is active */
9924f67f6bSmarc #define SEL_WRITE 0x02 /* write select is active */
10024f67f6bSmarc
101b2b69f49Smarc /*
102b2b69f49Smarc * constants used in shared memory operations
103b2b69f49Smarc */
10424f67f6bSmarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */
10524f67f6bSmarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \
10624f67f6bSmarc / sizeof(struct _vs_event) )
1070d59d4d6Smarc #define DMA_BUFSIZ (1024 * 10)
10824f67f6bSmarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF)
10924f67f6bSmarc
110b2b69f49Smarc /*
11124f67f6bSmarc * reference to an array of "uba_device" structures built by the auto
11224f67f6bSmarc * configuration program. The uba_device structure decribes the device
11324f67f6bSmarc * sufficiently for the driver to talk to it. The auto configuration code
11424f67f6bSmarc * fills in the uba_device structures (located in ioconf.c) from user
115b2b69f49Smarc * maintained info.
116b2b69f49Smarc */
11724f67f6bSmarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */
11824f67f6bSmarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */
1197881ece5Smarc extern char qvmem[][128*NBPG];
120b2b69f49Smarc extern struct pte QVmap[][128];
121b2b69f49Smarc #define CHUNK (64 * 1024)
122b2b69f49Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */
12324f67f6bSmarc
124b2b69f49Smarc /*
125b2b69f49Smarc * static storage used by multiple functions in this code
126b2b69f49Smarc */
12724f67f6bSmarc int Qbus_unmap[NQD]; /* Qbus mapper release code */
12824f67f6bSmarc struct qdflags qdflags[NQD]; /* QDSS device status flags */
12924f67f6bSmarc struct qdmap qdmap[NQD]; /* QDSS register map structure */
13024f67f6bSmarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */
13124f67f6bSmarc struct buf qdbuf[NQD]; /* buf structs used by strategy */
132b2b69f49Smarc short qdopened[NQD]; /* graphics device is open exclusive use */
13324f67f6bSmarc
134b2b69f49Smarc /*
135e977faadSmarc * the array "event_shared[]" is made up of a number of event queue buffers
13624f67f6bSmarc * equal to the number of QDSS's configured into the running kernel (NQD).
13724f67f6bSmarc * Each event queue buffer begins with an event queue header (struct qdinput)
13824f67f6bSmarc * followed by a group of event queue entries (struct _vs_event). The array
13924f67f6bSmarc * "*eq_header[]" is an array of pointers to the start of each event queue
140b2b69f49Smarc * buffer in "event_shared[]".
141b2b69f49Smarc */
14224f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
14324f67f6bSmarc
14424f67f6bSmarc char event_shared[EQSIZE]; /* reserve space for event bufs */
14524f67f6bSmarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */
14624f67f6bSmarc
147b2b69f49Smarc /*
14824f67f6bSmarc * This allocation method reserves enough memory pages for NQD shared DMA I/O
14924f67f6bSmarc * buffers. Each buffer must consume an integral number of memory pages to
15024f67f6bSmarc * guarantee that a following buffer will begin on a page boundary. Also,
15124f67f6bSmarc * enough space is allocated so that the FIRST I/O buffer can start at the
15224f67f6bSmarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that
153b2b69f49Smarc * memory protections can be turned on/off for individual buffers.
154b2b69f49Smarc */
15524f67f6bSmarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512)
15624f67f6bSmarc
15724f67f6bSmarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */
15824f67f6bSmarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */
15924f67f6bSmarc
160b2b69f49Smarc /*
16124f67f6bSmarc * The driver assists a client in scroll operations by loading dragon
16224f67f6bSmarc * registers from an interrupt service routine. The loading is done using
16324f67f6bSmarc * parameters found in memory shrade between the driver and it's client.
16424f67f6bSmarc * The scroll parameter structures are ALL loacted in the same memory page
165b2b69f49Smarc * for reasons of memory economy.
166b2b69f49Smarc */
16724f67f6bSmarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */
16824f67f6bSmarc struct scroll *scroll[NQD]; /* pointers to scroll structures */
16924f67f6bSmarc
170b2b69f49Smarc /*
17124f67f6bSmarc * the driver is programmable to provide the user with color map write
17224f67f6bSmarc * services at VSYNC interrupt time. At interrupt time the driver loads
173b2b69f49Smarc * the color map with any user-requested load data found in shared memory
174b2b69f49Smarc */
17524f67f6bSmarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512)
17624f67f6bSmarc
177e977faadSmarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */
17824f67f6bSmarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */
17924f67f6bSmarc
180b2b69f49Smarc /*
181b2b69f49Smarc * mouse input event structures
182b2b69f49Smarc */
18324f67f6bSmarc struct mouse_report last_rep[NQD];
18424f67f6bSmarc struct mouse_report current_rep[NQD];
18524f67f6bSmarc
1867881ece5Smarc struct proc *qdrsel[NQD]; /* process waiting for select */
187b2b69f49Smarc struct _vs_cursor cursor[NQD]; /* console cursor */
188b2b69f49Smarc int qdcount = 0; /* count of successfully probed qd's */
18924f67f6bSmarc int nNQD = NQD;
19024f67f6bSmarc int DMAbuf_size = DMA_BUFSIZ;
191e977faadSmarc int QDlast_DMAtype; /* type of the last DMA operation */
192e977faadSmarc
193b2b69f49Smarc #define QDSSMAJOR 41 /* QDSS major device number */
194b2b69f49Smarc /*
195b2b69f49Smarc * macro to get system time. Used to time stamp event queue entries
196b2b69f49Smarc */
1977e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
1987e911b15Skarels
1997e911b15Skarels int qdprobe();
2007e911b15Skarels int qdattach();
2017e911b15Skarels int qddint(); /* DMA gate array intrpt service */
2027e911b15Skarels int qdaint(); /* Dragon ADDER intrpt service */
2037e911b15Skarels int qdiint();
2047e911b15Skarels
2057e911b15Skarels u_short qdstd[] = { 0 };
2067e911b15Skarels
207b2b69f49Smarc struct uba_driver qddriver = {
2087e911b15Skarels qdprobe, /* device probe entry */
2097e911b15Skarels 0, /* no slave device */
2107e911b15Skarels qdattach, /* device attach entry */
2117e911b15Skarels 0, /* no "fill csr/ba to start" */
2127e911b15Skarels qdstd, /* device addresses */
2137e911b15Skarels "qd", /* device name string */
2147e911b15Skarels qdinfo /* ptr to QDSS's uba_device struct */
2157e911b15Skarels };
2167e911b15Skarels
217e977faadSmarc #define QDPRIOR (PZERO-1) /* must be negative */
2187e911b15Skarels #define FALSE 0
2197e911b15Skarels #define TRUE ~FALSE
2207e911b15Skarels #define BAD -1
2217e911b15Skarels #define GOOD 0
2227e911b15Skarels
223b2b69f49Smarc /*
224b2b69f49Smarc * macro to create a system virtual page number from system virtual adrs
225b2b69f49Smarc */
226b2b69f49Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT)
2277e911b15Skarels
228b2b69f49Smarc /*
229b2b69f49Smarc * QDSS register address offsets from start of QDSS address space
230b2b69f49Smarc */
2317e911b15Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */
2327e911b15Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */
2337e911b15Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */
2347e911b15Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */
2357e911b15Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */
2367e911b15Skarels #define ADDER (REGSTART+0x000)
2377e911b15Skarels #define DGA (REGSTART+0x200)
2387e911b15Skarels #define DUART (REGSTART+0x400)
2397e911b15Skarels #define MEMCSR (REGSTART+0x800)
2407e911b15Skarels #define CLRSIZE (3 * 512) /* color map size */
2417e911b15Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */
2427e911b15Skarels /* 0x0C00 really */
2437e911b15Skarels #define RED (CLRSTART+0x000)
2447e911b15Skarels #define BLUE (CLRSTART+0x200)
2457e911b15Skarels #define GREEN (CLRSTART+0x400)
2467e911b15Skarels
2477e911b15Skarels
248b2b69f49Smarc /*
2497e911b15Skarels * QDSS minor device numbers. The *real* minor device numbers are in
2507e911b15Skarels * the bottom two bits of the major/minor device spec. Bits 2 and up are
251b2b69f49Smarc * used to specify the QDSS device number (ie: which one?)
252b2b69f49Smarc */
2537e911b15Skarels
2547e911b15Skarels #define CONS 0
2557e911b15Skarels #define GRAPHIC 2
2567e911b15Skarels
257b2b69f49Smarc /*
258b2b69f49Smarc * console cursor bitmap (white block cursor)
259b2b69f49Smarc */
260b2b69f49Smarc short cons_cursor[32] = {
2617e911b15Skarels /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2627e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2637e911b15Skarels /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2647e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
2657e911b15Skarels };
2667e911b15Skarels
267b2b69f49Smarc /*
268b2b69f49Smarc * constants used in font operations
269b2b69f49Smarc */
270e977faadSmarc #define CHARS 190 /* # of chars in the font */
2717e911b15Skarels #define CHAR_HEIGHT 15 /* char height in pixels */
2727e911b15Skarels #define CHAR_WIDTH 8 /* char width in pixels*/
2737e911b15Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */
2747e911b15Skarels #define ROWS CHAR_HEIGHT
2757e911b15Skarels #define FONT_X 0 /* font's off screen adrs */
2767e911b15Skarels #define FONT_Y (2048 - CHAR_HEIGHT)
277e977faadSmarc
278b2b69f49Smarc /* Offset to second row characters (XXX - should remove) */
279e977faadSmarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
2807e911b15Skarels
2817e911b15Skarels extern char q_font[]; /* reference font object code */
282e977faadSmarc extern u_short q_key[]; /* reference key xlation tables */
283e977faadSmarc extern u_short q_shift_key[];
2847e911b15Skarels extern char *q_special[];
2857e911b15Skarels
286b2b69f49Smarc /*
287b2b69f49Smarc * definitions for cursor acceleration reporting
288b2b69f49Smarc */
2897e911b15Skarels #define ACC_OFF 0x01 /* acceleration is inactive */
2907e911b15Skarels
291b2b69f49Smarc /*
292b2b69f49Smarc * virtual console support.
2937e911b15Skarels */
294e977faadSmarc extern (*v_putc)();
295f79d7b48Smarc #ifdef KADB
296f79d7b48Smarc extern (*v_getc)();
297f79d7b48Smarc extern (*v_poll)();
298f79d7b48Smarc #endif
299e977faadSmarc extern struct cdevsw *consops;
300e977faadSmarc int qdputc();
301f79d7b48Smarc int qdgetc();
302f79d7b48Smarc int qdpoll();
303e977faadSmarc int qdstart();
304f79d7b48Smarc int qdpolling = 0;
305e977faadSmarc
306b2b69f49Smarc /*
307b2b69f49Smarc * LK-201 state storage for input console keyboard conversion to ASCII
308b2b69f49Smarc */
3097e911b15Skarels struct q_keyboard {
3107e911b15Skarels int shift; /* state variables */
3117e911b15Skarels int cntrl;
3127e911b15Skarels int lock;
3137e911b15Skarels int lastcode; /* last keycode typed */
3147e911b15Skarels unsigned kup[8]; /* bits for each keycode*/
3157e911b15Skarels unsigned dkeys[8]; /* down/up mode keys */
3167e911b15Skarels char last; /* last character */
3177e911b15Skarels } q_keyboard;
3187e911b15Skarels
319b2b69f49Smarc /*
320b2b69f49Smarc * tty settings on first open
321b2b69f49Smarc */
322f79d7b48Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
323e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR)
324f79d7b48Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
325e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
326e977faadSmarc
3277881ece5Smarc /*
3287881ece5Smarc * Init QDSS as console (before probe routine)
3297881ece5Smarc */
3307e911b15Skarels
qdcons_init()3317e911b15Skarels qdcons_init()
3327e911b15Skarels {
3337881ece5Smarc register unit;
3347e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */
335e977faadSmarc u_int mapix; /* index into QVmap[] array */
336e977faadSmarc struct percpu *pcpu; /* pointer to cpusw structure */
337e977faadSmarc register struct qbus *qb;
3387e911b15Skarels u_short *qdaddr; /* address of QDSS IO page CSR */
3397e911b15Skarels u_short *devptr; /* vitual device space */
340e977faadSmarc extern cnputc();
3417e911b15Skarels
3427e911b15Skarels #define QDSSCSR 0x1F00
3437e911b15Skarels
34424f67f6bSmarc if (v_putc != cnputc)
3457881ece5Smarc return 0;
34624f67f6bSmarc
3477e911b15Skarels unit = 0;
3487e911b15Skarels
349b2b69f49Smarc /*
350b2b69f49Smarc * find the cpusw entry that matches this machine.
351b2b69f49Smarc */
35224f67f6bSmarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
3537e911b15Skarels ;
35424f67f6bSmarc if (pcpu == NULL)
3557881ece5Smarc return 0;
3562b86b1e4Stef if (pcpu->pc_io->io_type != IO_QBUS)
3572b86b1e4Stef return 0;
35824f67f6bSmarc
35924f67f6bSmarc /*
360e977faadSmarc * Map device registers - the last 8K of qvmem.
36124f67f6bSmarc */
36224f67f6bSmarc qb = (struct qbus *)pcpu->pc_io->io_details;
36324f67f6bSmarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
36424f67f6bSmarc UBAIOPAGES * NBPG);
36524f67f6bSmarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
36624f67f6bSmarc qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
3677881ece5Smarc if (badaddr((caddr_t)qdaddr, sizeof(short)))
3687881ece5Smarc return 0;
369e977faadSmarc
37024f67f6bSmarc /*
37124f67f6bSmarc * Map q-bus memory used by qdss. (separate map)
37224f67f6bSmarc */
37324f67f6bSmarc mapix = QMEMSIZE - (CHUNK * (unit + 1));
37424f67f6bSmarc phys_adr = qb->qb_maddr + mapix;
37524f67f6bSmarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
3767e911b15Skarels
37724f67f6bSmarc /*
37824f67f6bSmarc * tell QDSS which Q memory address base to decode
379b2b69f49Smarc * (shifted right 16 bits - its in 64K units)
38024f67f6bSmarc */
38124f67f6bSmarc *qdaddr = (u_short)((int)mapix >> 16);
3827e911b15Skarels qdflags[unit].config = *(u_short *)qdaddr;
3837e911b15Skarels
384b2b69f49Smarc /*
385b2b69f49Smarc * load qdmap struct with the virtual addresses of the QDSS elements
386b2b69f49Smarc */
387e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0]);
3887e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART;
3897e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER;
3907e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA;
3917e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART;
3927e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
3937e911b15Skarels qdmap[unit].red = qdbase[unit] + RED;
3947e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE;
3957e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN;
3967e911b15Skarels
3977e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */
3987e911b15Skarels
399b2b69f49Smarc /*
400b2b69f49Smarc * init the QDSS
401b2b69f49Smarc */
402b2b69f49Smarc /*
40324f67f6bSmarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
40424f67f6bSmarc (char *)qdbase[0], qdmap[0].memcsr);
405b2b69f49Smarc */
4067e911b15Skarels
4077e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
4087e911b15Skarels
4097e911b15Skarels cursor[unit].x = 0;
4107e911b15Skarels cursor[unit].y = 0;
4117e911b15Skarels init_shared(unit); /* init shared memory */
4127e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */
4137e911b15Skarels clear_qd_screen(unit); /* clear the screen */
4147e911b15Skarels ldfont(unit); /* load the console font */
4157e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */
4167e911b15Skarels setup_input(unit); /* init the DUART */
417b2b69f49Smarc v_putc = qdputc; /* kernel console output to qdss */
418f79d7b48Smarc #ifdef KADB
419f79d7b48Smarc v_getc = qdgetc; /* kernel console input from qdss */
420f79d7b48Smarc v_poll = qdpoll; /* kdb hook to disable char intr */
421f79d7b48Smarc #endif
422b2b69f49Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */
4237881ece5Smarc return 1;
4247e911b15Skarels
4257e911b15Skarels } /* qdcons_init */
4267e911b15Skarels
4277881ece5Smarc /*
4287881ece5Smarc * Configure QDSS into Q memory and make it intrpt.
4297e911b15Skarels *
4307e911b15Skarels * side effects: QDSS gets mapped into Qbus memory space at the first
4317e911b15Skarels * vacant 64kb boundary counting back from the top of
432e977faadSmarc * Qbus memory space (qvmem+4mb)
4337e911b15Skarels *
4347e911b15Skarels * return: QDSS bus request level and vector address returned in
4357e911b15Skarels * registers by UNIX convention.
4367e911b15Skarels *
4377881ece5Smarc */
qdprobe(reg)4387e911b15Skarels qdprobe(reg)
4397881ece5Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */
4407e911b15Skarels {
441f79d7b48Smarc register int br, cvec;
4427e911b15Skarels register int unit;
4437e911b15Skarels struct dga *dga; /* pointer to gate array structure */
4447e911b15Skarels int vector;
4457881ece5Smarc #ifdef notdef
4467881ece5Smarc int *ptep; /* page table entry pointer */
4477e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */
4487e911b15Skarels u_int mapix;
4497881ece5Smarc #endif
4507881ece5Smarc
4517881ece5Smarc #ifdef lint
4527881ece5Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
4537881ece5Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
4547881ece5Smarc #endif
4557e911b15Skarels
456b2b69f49Smarc /*
457b2b69f49Smarc * calculate board unit number from I/O page register address
458b2b69f49Smarc */
4597e911b15Skarels unit = (int) (((int)reg >> 1) & 0x0007);
4607e911b15Skarels
461b2b69f49Smarc /*
462b2b69f49Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb
463b2b69f49Smarc * physical boundary. The Qbus memory space is mapped into
464b2b69f49Smarc * the system memory space at config time. After config
465b2b69f49Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
466b2b69f49Smarc * of the start of Qbus memory. The Qbus memory page table
467b2b69f49Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
468b2b69f49Smarc * which is also loaded at config time. These are the
469b2b69f49Smarc * variables used below to find a vacant 64kb boundary in
470b2b69f49Smarc * Qbus memory, and load it's corresponding physical adrs
471b2b69f49Smarc * into the QDSS's I/O page CSR.
472b2b69f49Smarc */
473e977faadSmarc
474e977faadSmarc /*
475e977faadSmarc * Only if QD is the graphics device.
47624f67f6bSmarc */
4777e911b15Skarels
4787e911b15Skarels /* if this QDSS is NOT the console, then do init here.. */
4797e911b15Skarels
480e977faadSmarc if (unit != 0) {
481e977faadSmarc printf("qd: can't support two qdss's (yet)\n");
4827881ece5Smarc #ifdef notdef /* can't test */
4837e911b15Skarels if (v_consputc != qdputc || unit != 0) {
4847e911b15Skarels
485b2b69f49Smarc /*
486b2b69f49Smarc * read QDSS config info
487b2b69f49Smarc */
4887e911b15Skarels qdflags[unit].config = *(u_short *)reg;
4897e911b15Skarels
490b2b69f49Smarc /*
491b2b69f49Smarc * find an empty 64kb adrs boundary
492b2b69f49Smarc */
4937e911b15Skarels
494e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
495e977faadSmarc
496b2b69f49Smarc /*
4977881ece5Smarc * find the cpusw entry that matches this machine.
4987881ece5Smarc */
4997e911b15Skarels cpup = &cpusw[cpu];
5007e911b15Skarels while (!(BADADDR(qdbase[unit], sizeof(short))))
5017e911b15Skarels qdbase[unit] -= CHUNK;
5027e911b15Skarels
503b2b69f49Smarc /*
5047881ece5Smarc * tell QDSS which Q memory address base to decode
5057881ece5Smarc */
506e977faadSmarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
507e977faadSmarc ptep = (int *) QVmap[0] + mapix;
5087e911b15Skarels phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
5097e911b15Skarels *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
5107e911b15Skarels
511b2b69f49Smarc /*
512b2b69f49Smarc * load QDSS adrs map with system addresses
513b2b69f49Smarc * of device regs
514b2b69f49Smarc */
5157e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART;
5167e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER;
5177e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA;
5187e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART;
5197e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
5207e911b15Skarels qdmap[unit].red = qdbase[unit] + RED;
5217e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE;
5227e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN;
5237e911b15Skarels
5247e911b15Skarels /* device init */
5257e911b15Skarels
5267e911b15Skarels cursor[unit].x = 0;
5277e911b15Skarels cursor[unit].y = 0;
5287e911b15Skarels init_shared(unit); /* init shared memory */
5297e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */
5307e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */
5317e911b15Skarels setup_input(unit); /* init the DUART */
5327e911b15Skarels clear_qd_screen(unit);
5337e911b15Skarels ldfont(unit); /* load the console font */
5347e911b15Skarels
5357e911b15Skarels /* once only: turn on sync */
5367e911b15Skarels
5377e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON;
538b2b69f49Smarc }
539006e9885Smarc #endif /*notdef*/
540e977faadSmarc }
5417e911b15Skarels
542b2b69f49Smarc /*
543b2b69f49Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
544b2b69f49Smarc * (ADDER) and xx8 (DUART). Therefore, we take three
545b2b69f49Smarc * vectors from the vector pool, and then continue
546b2b69f49Smarc * to take them until we get a xx0 HEX vector. The
547b2b69f49Smarc * pool provides vectors in contiguous decending
548b2b69f49Smarc * order.
549b2b69f49Smarc */
5507e911b15Skarels
5517e911b15Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */
5527e911b15Skarels
5537e911b15Skarels while (vector & 0x0F) { /* if lo nibble != 0.. */
554b2b69f49Smarc /* ..take another vector */
555b2b69f49Smarc vector = (uba_hd[0].uh_lastiv -= 4);
5567e911b15Skarels }
5577e911b15Skarels
558b2b69f49Smarc /*
559b2b69f49Smarc * setup DGA to do a DMA interrupt (transfer count = 0)
560b2b69f49Smarc */
5617e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
5627e911b15Skarels dga->csr = (short) HALT; /* disable everything */
5637e911b15Skarels dga->ivr = (short) vector; /* load intrpt base vector */
5647e911b15Skarels dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */
5657e911b15Skarels dga->bytcnt_hi = (short) 0;
5667e911b15Skarels
567b2b69f49Smarc /*
568b2b69f49Smarc * turn on DMA interrupts
569b2b69f49Smarc */
5707e911b15Skarels dga->csr &= ~SET_DONE_FIFO;
5717e911b15Skarels dga->csr |= DMA_IE | DL_ENB;
5727e911b15Skarels
5737e911b15Skarels DELAY(20000); /* wait for the intrpt */
5747e911b15Skarels dga->csr = HALT; /* stop the wheels */
5757e911b15Skarels
5767e911b15Skarels if (cvec != vector) /* if vector != base vector.. */
5777e911b15Skarels return(0); /* ..return = 'no device' */
5787e911b15Skarels
579e977faadSmarc /*
580e977faadSmarc * score this as an existing qdss
581e977faadSmarc */
582e977faadSmarc qdcount++;
583e977faadSmarc
5847e911b15Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */
5857e911b15Skarels
5867e911b15Skarels } /* qdprobe */
5877e911b15Skarels
5887e911b15Skarels qdattach(ui)
5897e911b15Skarels struct uba_device *ui;
5907e911b15Skarels {
5917881ece5Smarc register unit; /* QDSS module # for this call */
5927e911b15Skarels
5937e911b15Skarels unit = ui->ui_unit; /* get QDSS number */
5947e911b15Skarels
595b2b69f49Smarc /*
596b2b69f49Smarc * init "qdflags[]" for this QDSS
597b2b69f49Smarc */
5987e911b15Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */
5997e911b15Skarels qdflags[unit].mapped = 0;
600e977faadSmarc qdflags[unit].kernel_loop = -1;
6017e911b15Skarels qdflags[unit].user_dma = 0;
6027e911b15Skarels qdflags[unit].curs_acc = ACC_OFF;
6037e911b15Skarels qdflags[unit].curs_thr = 128;
6047e911b15Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */
6057e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */
6067e911b15Skarels qdflags[unit].adder_ie = 0;
6077e911b15Skarels
608b2b69f49Smarc /*
6097e911b15Skarels * init structures used in kbd/mouse interrupt service. This code must
610b2b69f49Smarc * come after the "init_shared()" routine has run since that routine
611b2b69f49Smarc * inits the eq_header[unit] structure used here.
612b2b69f49Smarc */
6137e911b15Skarels
614b2b69f49Smarc /*
615b2b69f49Smarc * init the "latest mouse report" structure
616b2b69f49Smarc */
6177e911b15Skarels last_rep[unit].state = 0;
6187e911b15Skarels last_rep[unit].dx = 0;
6197e911b15Skarels last_rep[unit].dy = 0;
6207e911b15Skarels last_rep[unit].bytcnt = 0;
6217e911b15Skarels
622b2b69f49Smarc /*
6237881ece5Smarc * init the event queue (except mouse position)
6247881ece5Smarc */
6257881ece5Smarc eq_header[unit]->header.events =
6267881ece5Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
6277e911b15Skarels
6287e911b15Skarels eq_header[unit]->header.size = MAXEVENTS;
6297e911b15Skarels eq_header[unit]->header.head = 0;
6307e911b15Skarels eq_header[unit]->header.tail = 0;
6317e911b15Skarels
632b2b69f49Smarc /*
633b2b69f49Smarc * open exclusive for graphics device.
634b2b69f49Smarc */
635b2b69f49Smarc qdopened[unit] = 0;
6367e911b15Skarels
6377e911b15Skarels } /* qdattach */
6387e911b15Skarels
6397881ece5Smarc /*ARGSUSED*/
qdopen(dev,flag)6407e911b15Skarels qdopen(dev, flag)
6417e911b15Skarels dev_t dev;
6427e911b15Skarels int flag;
6437e911b15Skarels {
6447e911b15Skarels register struct uba_device *ui; /* ptr to uba structures */
6457e911b15Skarels register struct dga *dga; /* ptr to gate array struct */
6467e911b15Skarels register struct tty *tp;
6477e911b15Skarels struct duart *duart;
6487881ece5Smarc int unit;
6497881ece5Smarc int minor_dev;
6507e911b15Skarels
6517e911b15Skarels minor_dev = minor(dev); /* get QDSS minor device number */
6527e911b15Skarels unit = minor_dev >> 2;
6537e911b15Skarels
654b2b69f49Smarc /*
655b2b69f49Smarc * check for illegal conditions
656b2b69f49Smarc */
6577e911b15Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */
6587e911b15Skarels if (ui == 0 || ui->ui_alive == 0)
6597e911b15Skarels return(ENXIO); /* no such device or address */
6607e911b15Skarels
6617e911b15Skarels duart = (struct duart *) qdmap[unit].duart;
6627e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
6637e911b15Skarels
6647e911b15Skarels if ((minor_dev & 0x03) == 2) {
665b2b69f49Smarc /*
666b2b69f49Smarc * this is the graphic device...
667b2b69f49Smarc */
668b2b69f49Smarc if (qdopened[unit] != 0)
6697e911b15Skarels return(EBUSY);
6707e911b15Skarels else
671b2b69f49Smarc qdopened[unit] = 1;
6727e911b15Skarels qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */
673b2b69f49Smarc /*
674b2b69f49Smarc * enble kbd & mouse intrpts in DUART mask reg
675b2b69f49Smarc */
6767e911b15Skarels qdflags[unit].duart_imask |= 0x22;
6777e911b15Skarels duart->imask = qdflags[unit].duart_imask;
678b2b69f49Smarc } else {
679b2b69f49Smarc /*
680b2b69f49Smarc * this is the console
681b2b69f49Smarc */
6827e911b15Skarels qdflags[unit].inuse |= CONS_DEV; /* mark console as open */
6837e911b15Skarels dga->csr |= CURS_ENB;
6847e911b15Skarels qdflags[unit].duart_imask |= 0x02;
6857e911b15Skarels duart->imask = qdflags[unit].duart_imask;
686b2b69f49Smarc /*
687b2b69f49Smarc * some setup for tty handling
688b2b69f49Smarc */
6897e911b15Skarels tp = &qd_tty[minor_dev];
6907e911b15Skarels tp->t_addr = ui->ui_addr;
6917e911b15Skarels tp->t_oproc = qdstart;
6927e911b15Skarels if ((tp->t_state & TS_ISOPEN) == 0) {
6937e911b15Skarels ttychars(tp);
6947e911b15Skarels tp->t_ispeed = B9600;
6957e911b15Skarels tp->t_ospeed = B9600;
696e977faadSmarc tp->t_state = TS_ISOPEN | TS_CARR_ON;
697b2b69f49Smarc tp->t_iflag = TTYDEF_IFLAG;
698b2b69f49Smarc tp->t_oflag = TTYDEF_OFLAG;
699b2b69f49Smarc tp->t_lflag = TTYDEF_LFLAG;
700b2b69f49Smarc tp->t_cflag = TTYDEF_CFLAG;
701e977faadSmarc }
702b2b69f49Smarc /*
703b2b69f49Smarc * enable intrpts, open line discipline
704b2b69f49Smarc */
7057e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */
7067e911b15Skarels return ((*linesw[tp->t_line].l_open)(dev, tp));
7077e911b15Skarels }
7087e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */
7097e911b15Skarels return(0);
7107e911b15Skarels
7117e911b15Skarels } /* qdopen */
7127e911b15Skarels
7137881ece5Smarc /*ARGSUSED*/
qdclose(dev,flag,mode,p)7149e5284e4Smarc qdclose(dev, flag, mode, p)
7157e911b15Skarels dev_t dev;
7169e5284e4Smarc int flag, mode;
7179e5284e4Smarc struct proc *p;
7187e911b15Skarels {
7197e911b15Skarels register struct tty *tp;
7207e911b15Skarels register struct qdmap *qd;
7217e911b15Skarels register int *ptep;
7227e911b15Skarels struct dga *dga; /* gate array register map pointer */
7237e911b15Skarels struct duart *duart;
7247e911b15Skarels struct adder *adder;
7257881ece5Smarc int unit;
7267881ece5Smarc int minor_dev;
7277e911b15Skarels u_int mapix;
728b2b69f49Smarc int i; /* SIGNED index */
7297e911b15Skarels
7307e911b15Skarels minor_dev = minor(dev); /* get minor device number */
7317e911b15Skarels unit = minor_dev >> 2; /* get QDSS number */
7327e911b15Skarels qd = &qdmap[unit];
7337e911b15Skarels
7347e911b15Skarels if ((minor_dev & 0x03) == 2) {
735b2b69f49Smarc /*
736b2b69f49Smarc * this is the graphic device...
737b2b69f49Smarc */
738b2b69f49Smarc if (qdopened[unit] != 1)
7397e911b15Skarels return(EBUSY);
7407e911b15Skarels else
741b2b69f49Smarc qdopened[unit] = 0; /* allow it to be re-opened */
742b2b69f49Smarc /*
743b2b69f49Smarc * re-protect device memory
744b2b69f49Smarc */
7457e911b15Skarels if (qdflags[unit].mapped & MAPDEV) {
746b2b69f49Smarc /*
747b2b69f49Smarc * TEMPLATE RAM
748b2b69f49Smarc */
74924f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
75024f67f6bSmarc ptep = (int *)(QVmap[0] + mapix);
7517881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++)
7527881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
753b2b69f49Smarc /*
754b2b69f49Smarc * ADDER
755b2b69f49Smarc */
75624f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
75724f67f6bSmarc ptep = (int *)(QVmap[0] + mapix);
7587881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++)
7597881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
760b2b69f49Smarc /*
761b2b69f49Smarc * COLOR MAPS
762b2b69f49Smarc */
76324f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
76424f67f6bSmarc ptep = (int *)(QVmap[0] + mapix);
7657881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++)
7667881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
7677e911b15Skarels }
7687e911b15Skarels
769b2b69f49Smarc /*
770b2b69f49Smarc * re-protect DMA buffer and free the map registers
771b2b69f49Smarc */
7727e911b15Skarels if (qdflags[unit].mapped & MAPDMA) {
7737e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
7747e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
7757e911b15Skarels dga->csr &= ~DMA_IE;
7767e911b15Skarels dga->csr &= ~0x0600; /* kill DMA */
7777e911b15Skarels adder->command = CANCEL;
778b2b69f49Smarc /*
779b2b69f49Smarc * if DMA was running, flush spurious intrpt
780b2b69f49Smarc */
7817e911b15Skarels if (dga->bytcnt_lo != 0) {
7827e911b15Skarels dga->bytcnt_lo = 0;
7837e911b15Skarels dga->bytcnt_hi = 0;
7847e911b15Skarels DMA_SETIGNORE(DMAheader[unit]);
7857e911b15Skarels dga->csr |= DMA_IE;
7867e911b15Skarels dga->csr &= ~DMA_IE;
7877e911b15Skarels }
7887e911b15Skarels ptep = (int *)
7897e911b15Skarels ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
7907881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
7917881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
7927e911b15Skarels ubarelse(0, &Qbus_unmap[unit]);
7937e911b15Skarels }
7947e911b15Skarels
795b2b69f49Smarc /*
796b2b69f49Smarc * re-protect 1K (2 pages) event queue
797b2b69f49Smarc */
7987e911b15Skarels if (qdflags[unit].mapped & MAPEQ) {
7997e911b15Skarels ptep = (int *)
8007e911b15Skarels ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
8017881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8027e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8037e911b15Skarels }
804b2b69f49Smarc /*
805b2b69f49Smarc * re-protect scroll param area and disable scroll intrpts
806b2b69f49Smarc */
8077e911b15Skarels if (qdflags[unit].mapped & MAPSCR) {
8087e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4)
8097e911b15Skarels + (mfpr(SBR) | 0x80000000));
810b2b69f49Smarc /*
811b2b69f49Smarc * re-protect 512 scroll param area
812b2b69f49Smarc */
8137e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8147e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
8157e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC;
8167e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
8177e911b15Skarels }
818b2b69f49Smarc /*
819b2b69f49Smarc * re-protect color map write buffer area and kill intrpts
820b2b69f49Smarc */
8217e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) {
8227e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4)
8237e911b15Skarels + (mfpr(SBR) | 0x80000000));
8247881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8257e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8267e911b15Skarels color_buf[unit]->status = 0;
8277e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
8287e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC;
8297e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
8307e911b15Skarels }
831b2b69f49Smarc mtpr(TBIA, 0);
832b2b69f49Smarc /* flag everything now unmapped */
833b2b69f49Smarc qdflags[unit].mapped = 0;
8347e911b15Skarels qdflags[unit].inuse &= ~GRAPHIC_DEV;
8357e911b15Skarels qdflags[unit].curs_acc = ACC_OFF;
8367e911b15Skarels qdflags[unit].curs_thr = 128;
837b2b69f49Smarc /*
838b2b69f49Smarc * restore the console
839b2b69f49Smarc */
8407e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
8417e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
8427e911b15Skarels dga->csr &= ~DMA_IE;
8437e911b15Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */
8447e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */
8457e911b15Skarels adder->command = CANCEL;
846b2b69f49Smarc /*
847b2b69f49Smarc * if DMA was running, flush spurious intrpt
848b2b69f49Smarc */
8497e911b15Skarels if (dga->bytcnt_lo != 0) {
8507e911b15Skarels dga->bytcnt_lo = 0;
8517e911b15Skarels dga->bytcnt_hi = 0;
8527e911b15Skarels DMA_SETIGNORE(DMAheader[unit]);
8537e911b15Skarels dga->csr |= DMA_IE;
8547e911b15Skarels dga->csr &= ~DMA_IE;
8557e911b15Skarels }
8567e911b15Skarels init_shared(unit); /* init shared memory */
8577e911b15Skarels setup_dragon(unit); /* init ADDER/VIPER */
8587e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */
8597e911b15Skarels setup_input(unit); /* init the DUART */
8607e911b15Skarels ldfont(unit);
8617e911b15Skarels cursor[unit].x = 0;
8627e911b15Skarels cursor[unit].y = 0;
863b2b69f49Smarc /*
864b2b69f49Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts
865b2b69f49Smarc */
8667e911b15Skarels duart = (struct duart *) qdmap[unit].duart;
8677e911b15Skarels qdflags[unit].duart_imask &= ~(0x20);
8687e911b15Skarels qdflags[unit].duart_imask |= 0x02;
8697e911b15Skarels duart->imask = qdflags[unit].duart_imask;
870b2b69f49Smarc /*
871b2b69f49Smarc * shut off interrupts if all is closed
872b2b69f49Smarc */
873b2b69f49Smarc if (!(qdflags[unit].inuse & CONS_DEV)) {
8747e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
8757e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE);
8767e911b15Skarels }
877b2b69f49Smarc } else {
878b2b69f49Smarc /*
879b2b69f49Smarc * this is the console
880b2b69f49Smarc */
8817e911b15Skarels tp = &qd_tty[minor_dev];
8829e5284e4Smarc (*linesw[tp->t_line].l_close)(tp, flag);
8837e911b15Skarels ttyclose(tp);
8847e911b15Skarels tp->t_state = 0;
8857e911b15Skarels qdflags[unit].inuse &= ~CONS_DEV;
886b2b69f49Smarc /*
887b2b69f49Smarc * if graphics device is closed, kill interrupts
888b2b69f49Smarc */
8897e911b15Skarels if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
8907e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
8917e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE);
8927e911b15Skarels }
8937e911b15Skarels }
8947e911b15Skarels
8957e911b15Skarels return(0);
8967e911b15Skarels
8977e911b15Skarels } /* qdclose */
8987e911b15Skarels
qdioctl(dev,cmd,datap,flags)8997e911b15Skarels qdioctl(dev, cmd, datap, flags)
9007e911b15Skarels dev_t dev;
9017e911b15Skarels int cmd;
9027881ece5Smarc register caddr_t datap;
9037e911b15Skarels int flags;
9047e911b15Skarels {
9057e911b15Skarels register int *ptep; /* page table entry pointer */
90624f67f6bSmarc register int mapix; /* QVmap[] page table index */
9077e911b15Skarels register struct _vs_event *event;
9087e911b15Skarels register struct tty *tp;
9097881ece5Smarc register i;
9107e911b15Skarels struct qdmap *qd; /* pointer to device map struct */
9117e911b15Skarels struct dga *dga; /* Gate Array reg structure pntr */
9127e911b15Skarels struct duart *duart; /* DUART reg structure pointer */
9137e911b15Skarels struct adder *adder; /* ADDER reg structure pointer */
9147e911b15Skarels struct prgkbd *cmdbuf;
9157e911b15Skarels struct prg_cursor *curs;
9167e911b15Skarels struct _vs_cursor *pos;
9177881ece5Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */
9187e911b15Skarels u_int minor_dev = minor(dev);
9197e911b15Skarels int error;
9207e911b15Skarels int s;
9217e911b15Skarels short *temp; /* a pointer to template RAM */
9227e911b15Skarels
923b2b69f49Smarc /*
924b2b69f49Smarc * service graphic device ioctl commands
925b2b69f49Smarc */
9267e911b15Skarels switch (cmd) {
927e977faadSmarc
9287e911b15Skarels case QD_GETEVENT:
929b2b69f49Smarc /*
930b2b69f49Smarc * extract the oldest event from the event queue
931b2b69f49Smarc */
9327e911b15Skarels if (ISEMPTY(eq_header[unit])) {
9337e911b15Skarels event = (struct _vs_event *) datap;
9347e911b15Skarels event->vse_device = VSE_NULL;
9357e911b15Skarels break;
9367e911b15Skarels }
9377e911b15Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
938e977faadSmarc s = spl5();
9397e911b15Skarels GETEND(eq_header[unit]);
9407e911b15Skarels splx(s);
9417881ece5Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
9427e911b15Skarels break;
9437e911b15Skarels
9447e911b15Skarels case QD_RESET:
945b2b69f49Smarc /*
946b2b69f49Smarc * init the dragon stuff, DUART, and driver variables
947b2b69f49Smarc */
9487e911b15Skarels init_shared(unit); /* init shared memory */
9497e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */
9507e911b15Skarels clear_qd_screen(unit);
9517e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */
9527e911b15Skarels ldfont(unit); /* load the console font */
9537e911b15Skarels setup_input(unit); /* init the DUART */
9547e911b15Skarels break;
9557e911b15Skarels
9567e911b15Skarels case QD_SET:
957b2b69f49Smarc /*
958b2b69f49Smarc * init the DUART and driver variables
959b2b69f49Smarc */
9607e911b15Skarels init_shared(unit);
9617e911b15Skarels setup_input(unit);
9627e911b15Skarels break;
9637e911b15Skarels
9647e911b15Skarels case QD_CLRSCRN:
965b2b69f49Smarc /*
966b2b69f49Smarc * clear the QDSS screen. (NOTE that this reinits the dragon)
967b2b69f49Smarc */
9687881ece5Smarc #ifdef notdef /* has caused problems and isn't necessary */
9697e911b15Skarels setup_dragon(unit);
9707e911b15Skarels clear_qd_screen(unit);
971e977faadSmarc #endif
9727e911b15Skarels break;
9737e911b15Skarels
9747e911b15Skarels case QD_WTCURSOR:
975b2b69f49Smarc /*
976b2b69f49Smarc * load a cursor into template RAM
977b2b69f49Smarc */
9787881ece5Smarc ldcursor(unit, (short *)datap);
9797e911b15Skarels break;
9807e911b15Skarels
9817e911b15Skarels case QD_RDCURSOR:
9827e911b15Skarels
9837e911b15Skarels temp = (short *) qdmap[unit].template;
984b2b69f49Smarc /*
985b2b69f49Smarc * cursor is 32 WORDS from the end of the 8k WORD...
986b2b69f49Smarc * ...template space
987b2b69f49Smarc */
9887e911b15Skarels temp += (8 * 1024) - 32;
9897e911b15Skarels for (i = 0; i < 32; ++i, datap += sizeof(short))
9907e911b15Skarels *(short *)datap = *temp++;
9917e911b15Skarels break;
9927e911b15Skarels
9937e911b15Skarels case QD_POSCURSOR:
994b2b69f49Smarc /*
995b2b69f49Smarc * position the mouse cursor
996b2b69f49Smarc */
9977e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
9987e911b15Skarels pos = (struct _vs_cursor *) datap;
999e977faadSmarc s = spl5();
10007e911b15Skarels dga->x_cursor = TRANX(pos->x);
10017e911b15Skarels dga->y_cursor = TRANY(pos->y);
10027e911b15Skarels eq_header[unit]->curs_pos.x = pos->x;
10037e911b15Skarels eq_header[unit]->curs_pos.y = pos->y;
10047e911b15Skarels splx(s);
10057e911b15Skarels break;
10067e911b15Skarels
10077e911b15Skarels case QD_PRGCURSOR:
1008b2b69f49Smarc /*
1009b2b69f49Smarc * set the cursor acceleration factor
1010b2b69f49Smarc */
10117e911b15Skarels curs = (struct prg_cursor *) datap;
1012e977faadSmarc s = spl5();
10137e911b15Skarels qdflags[unit].curs_acc = curs->acc_factor;
10147e911b15Skarels qdflags[unit].curs_thr = curs->threshold;
10157e911b15Skarels splx(s);
10167e911b15Skarels break;
10177e911b15Skarels
10187e911b15Skarels case QD_MAPDEVICE:
1019b2b69f49Smarc /*
1020b2b69f49Smarc * enable 'user write' to device pages
1021b2b69f49Smarc */
10227e911b15Skarels qdflags[unit].mapped |= MAPDEV;
10237e911b15Skarels qd = (struct qdmap *) &qdmap[unit];
1024b2b69f49Smarc /*
1025b2b69f49Smarc * enable user write to template RAM
1026b2b69f49Smarc */
102724f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
102824f67f6bSmarc ptep = (int *)(QVmap[0] + mapix);
10297881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++)
10307881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1031b2b69f49Smarc /*
1032b2b69f49Smarc * enable user write to registers
1033b2b69f49Smarc */
103424f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
103524f67f6bSmarc ptep = (int *)(QVmap[0] + mapix);
10367881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++)
10377881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1038b2b69f49Smarc /*
1039b2b69f49Smarc * enable user write to color maps
1040b2b69f49Smarc */
104124f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
104224f67f6bSmarc ptep = (int *)(QVmap[0] + mapix);
10437881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++)
10447881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1045b2b69f49Smarc /*
1046b2b69f49Smarc * enable user write to DUART
1047b2b69f49Smarc */
104824f67f6bSmarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
104924f67f6bSmarc ptep = (int *)(QVmap[0] + mapix);
10507e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
10517e911b15Skarels
10527881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */
10537e911b15Skarels
1054b2b69f49Smarc /*
1055b2b69f49Smarc * stuff qdmap structure in return buffer
1056b2b69f49Smarc */
10577881ece5Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
10587e911b15Skarels break;
10597e911b15Skarels
10607e911b15Skarels case QD_MAPIOBUF:
1061b2b69f49Smarc /*
1062b2b69f49Smarc * do setup for DMA by user process
1063b2b69f49Smarc *
1064b2b69f49Smarc * set 'user write enable' bits for DMA buffer
1065b2b69f49Smarc */
10667e911b15Skarels qdflags[unit].mapped |= MAPDMA;
10677e911b15Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
10687e911b15Skarels + (mfpr(SBR) | 0x80000000));
10697881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
10707881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
10717881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */
1072b2b69f49Smarc /*
1073b2b69f49Smarc * set up QBUS map registers for DMA
1074b2b69f49Smarc */
10757e911b15Skarels DMAheader[unit]->QBAreg =
10767881ece5Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
10777e911b15Skarels if (DMAheader[unit]->QBAreg == 0)
10787881ece5Smarc printf("qd%d: qdioctl: QBA setup error\n", unit);
10797e911b15Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
10807e911b15Skarels DMAheader[unit]->QBAreg &= 0x3FFFF;
1081b2b69f49Smarc /*
1082b2b69f49Smarc * return I/O buf adr
1083b2b69f49Smarc */
10847e911b15Skarels *(int *)datap = (int) DMAheader[unit];
10857e911b15Skarels break;
10867e911b15Skarels
10877e911b15Skarels case QD_MAPSCROLL:
1088b2b69f49Smarc /*
1089b2b69f49Smarc * map the shared scroll param area and enable scroll interpts
1090b2b69f49Smarc */
10917e911b15Skarels qdflags[unit].mapped |= MAPSCR;
10927e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4)
10937e911b15Skarels + (mfpr(SBR) | 0x80000000));
1094b2b69f49Smarc /*
1095b2b69f49Smarc * allow user write to scroll area
1096b2b69f49Smarc */
10977e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
10987881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buf */
10997e911b15Skarels scroll[unit]->status = 0;
11007e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
11017e911b15Skarels qdflags[unit].adder_ie |= FRAME_SYNC;
11027e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
1103b2b69f49Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */
11047e911b15Skarels break;
11057e911b15Skarels
11067e911b15Skarels case QD_UNMAPSCROLL:
1107b2b69f49Smarc /*
1108b2b69f49Smarc * unmap shared scroll param area and disable scroll intrpts
1109b2b69f49Smarc */
11107e911b15Skarels if (qdflags[unit].mapped & MAPSCR) {
11117e911b15Skarels qdflags[unit].mapped &= ~MAPSCR;
11127e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4)
11137e911b15Skarels + (mfpr(SBR) | 0x80000000));
1114b2b69f49Smarc /*
1115b2b69f49Smarc * re-protect 512 scroll param area
1116b2b69f49Smarc */
11177e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11187e911b15Skarels mtpr(TBIA, 0); /* smash CPU's translation buf */
11197e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
11207e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC;
11217e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
11227e911b15Skarels }
11237e911b15Skarels break;
11247e911b15Skarels
11257e911b15Skarels case QD_MAPCOLOR:
1126b2b69f49Smarc /*
1127b2b69f49Smarc * map shared color map write buf and turn on vsync intrpt
1128b2b69f49Smarc */
11297e911b15Skarels qdflags[unit].mapped |= MAPCOLOR;
11307e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11317e911b15Skarels + (mfpr(SBR) | 0x80000000));
11327881ece5Smarc /*
11337881ece5Smarc * allow user write to color map write buffer
11347881ece5Smarc */
11357881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11367e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11377e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */
1138b2b69f49Smarc adder = (struct adder *) qdmap[unit].adder;
11397e911b15Skarels qdflags[unit].adder_ie |= VSYNC;
11407e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
11417881ece5Smarc /*
11427881ece5Smarc * return color area address
11437881ece5Smarc */
11447e911b15Skarels *(int *)datap = (int) color_buf[unit];
11457e911b15Skarels break;
11467e911b15Skarels
11477e911b15Skarels case QD_UNMAPCOLOR:
1148b2b69f49Smarc /*
1149b2b69f49Smarc * unmap shared color map write buffer and kill VSYNC intrpts
1150b2b69f49Smarc */
11517e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) {
11527e911b15Skarels qdflags[unit].mapped &= ~MAPCOLOR;
11537e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11547e911b15Skarels + (mfpr(SBR) | 0x80000000));
11557881ece5Smarc /*
11567881ece5Smarc * re-protect color map write buffer
11577881ece5Smarc */
11587881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
11597e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11607881ece5Smarc mtpr(TBIA, 0);
11617e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
11627e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC;
11637e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
11647e911b15Skarels }
11657e911b15Skarels break;
11667e911b15Skarels
11677e911b15Skarels case QD_MAPEVENT:
1168b2b69f49Smarc /*
1169b2b69f49Smarc * give user write access to the event queue
1170b2b69f49Smarc */
11717e911b15Skarels qdflags[unit].mapped |= MAPEQ;
11727e911b15Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4)
11737e911b15Skarels + (mfpr(SBR) | 0x80000000));
11747881ece5Smarc /*
11757881ece5Smarc * allow user write to 1K event queue
11767881ece5Smarc */
11777881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11787e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11797e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */
11807881ece5Smarc /*
11817881ece5Smarc * return event queue address
11827881ece5Smarc */
11837e911b15Skarels *(int *)datap = (int)eq_header[unit];
11847e911b15Skarels break;
11857e911b15Skarels
11867e911b15Skarels case QD_PRGKBD:
1187b2b69f49Smarc /*
1188b2b69f49Smarc * pass caller's programming commands to LK201
1189b2b69f49Smarc */
11907e911b15Skarels duart = (struct duart *)qdmap[unit].duart;
11917e911b15Skarels cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */
1192b2b69f49Smarc /*
1193b2b69f49Smarc * send command
1194b2b69f49Smarc */
11957e911b15Skarels for (i = 1000; i > 0; --i) {
11967881ece5Smarc if (duart->statusA&XMT_RDY) {
11977e911b15Skarels duart->dataA = cmdbuf->cmd;
11987e911b15Skarels break;
11997e911b15Skarels }
12007e911b15Skarels }
12017e911b15Skarels if (i == 0) {
12027881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
12037e911b15Skarels break;
12047e911b15Skarels }
1205b2b69f49Smarc /*
1206b2b69f49Smarc * send param1?
1207b2b69f49Smarc */
12087e911b15Skarels if (cmdbuf->cmd & LAST_PARAM)
12097e911b15Skarels break;
12107e911b15Skarels for (i = 1000; i > 0; --i) {
12117881ece5Smarc if (duart->statusA&XMT_RDY) {
12127e911b15Skarels duart->dataA = cmdbuf->param1;
12137e911b15Skarels break;
12147e911b15Skarels }
12157e911b15Skarels }
12167e911b15Skarels if (i == 0) {
12177881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
12187e911b15Skarels break;
12197e911b15Skarels }
1220b2b69f49Smarc /*
1221b2b69f49Smarc * send param2?
1222b2b69f49Smarc */
12237e911b15Skarels if (cmdbuf->param1 & LAST_PARAM)
12247e911b15Skarels break;
12257e911b15Skarels for (i = 1000; i > 0; --i) {
12267881ece5Smarc if (duart->statusA&XMT_RDY) {
12277e911b15Skarels duart->dataA = cmdbuf->param2;
12287e911b15Skarels break;
12297e911b15Skarels }
12307e911b15Skarels }
12317e911b15Skarels if (i == 0) {
12327881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
12337e911b15Skarels break;
12347e911b15Skarels }
12357e911b15Skarels break;
12367e911b15Skarels
12377e911b15Skarels case QD_PRGMOUSE:
1238b2b69f49Smarc /*
1239b2b69f49Smarc * pass caller's programming commands to the mouse
1240b2b69f49Smarc */
12417e911b15Skarels duart = (struct duart *) qdmap[unit].duart;
12427e911b15Skarels for (i = 1000; i > 0; --i) {
12437881ece5Smarc if (duart->statusB&XMT_RDY) {
12447e911b15Skarels duart->dataB = *datap;
12457e911b15Skarels break;
12467e911b15Skarels }
12477e911b15Skarels }
12487e911b15Skarels if (i == 0) {
12497881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
12507e911b15Skarels }
12517e911b15Skarels break;
12527e911b15Skarels
12537e911b15Skarels case QD_RDCONFIG:
1254b2b69f49Smarc /*
1255b2b69f49Smarc * get QDSS configuration word and return it
1256b2b69f49Smarc */
12577e911b15Skarels *(short *)datap = qdflags[unit].config;
12587e911b15Skarels break;
12597e911b15Skarels
1260e977faadSmarc case QD_KERN_LOOP:
1261e977faadSmarc case QD_KERN_UNLOOP:
1262b2b69f49Smarc /*
1263b2b69f49Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect
1264b2b69f49Smarc * kernel console output.
1265b2b69f49Smarc */
1266e977faadSmarc break;
1267e977faadSmarc
12687e911b15Skarels case QD_PRGTABLET:
1269b2b69f49Smarc /*
1270b2b69f49Smarc * program the tablet
1271b2b69f49Smarc */
12727e911b15Skarels duart = (struct duart *) qdmap[unit].duart;
12737e911b15Skarels for (i = 1000; i > 0; --i) {
12747881ece5Smarc if (duart->statusB&XMT_RDY) {
12757e911b15Skarels duart->dataB = *datap;
12767e911b15Skarels break;
12777e911b15Skarels }
12787e911b15Skarels }
12797e911b15Skarels if (i == 0) {
12807881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
12817e911b15Skarels }
12827e911b15Skarels break;
12837e911b15Skarels
12847e911b15Skarels case QD_PRGTABRES:
1285b2b69f49Smarc /*
1286b2b69f49Smarc * program the tablet report resolution factor
1287b2b69f49Smarc */
12887e911b15Skarels qdflags[unit].tab_res = *(short *)datap;
12897e911b15Skarels break;
12908a2bf9b0Smarc
12917e911b15Skarels default:
1292b2b69f49Smarc /*
1293b2b69f49Smarc * service tty ioctl's
1294b2b69f49Smarc */
12957e911b15Skarels if (!(minor_dev & 0x02)) {
12967e911b15Skarels tp = &qd_tty[minor_dev];
1297b2b69f49Smarc error =
1298b2b69f49Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
12997e911b15Skarels if (error >= 0) {
13007e911b15Skarels return(error);
13017e911b15Skarels }
13027e911b15Skarels error = ttioctl(tp, cmd, datap, flags);
13037e911b15Skarels if (error >= 0) {
13047e911b15Skarels return(error);
13057e911b15Skarels }
13067e911b15Skarels }
13077e911b15Skarels break;
13087e911b15Skarels }
13097e911b15Skarels
13107e911b15Skarels return(0);
13117e911b15Skarels
13127e911b15Skarels } /* qdioctl */
13137e911b15Skarels
qdselect(dev,rw)13147e911b15Skarels qdselect(dev, rw)
13157e911b15Skarels dev_t dev;
13167e911b15Skarels int rw;
13177e911b15Skarels {
13187881ece5Smarc register s;
13197881ece5Smarc register unit;
1320e977faadSmarc register struct tty *tp;
1321e977faadSmarc u_int minor_dev = minor(dev);
13227e911b15Skarels
1323e977faadSmarc s = spl5();
1324e977faadSmarc unit = minor_dev >> 2;
13257e911b15Skarels
13267e911b15Skarels switch (rw) {
1327e977faadSmarc case FREAD:
1328b2b69f49Smarc if ((minor_dev & 0x03) == 2) {
1329e977faadSmarc /*
1330e977faadSmarc * this is a graphics device, so check for events
1331e977faadSmarc */
13327881ece5Smarc if(!(ISEMPTY(eq_header[unit]))) {
13337e911b15Skarels splx(s);
1334e977faadSmarc return(1);
13357e911b15Skarels }
13367881ece5Smarc qdrsel[unit] = u.u_procp;
13377e911b15Skarels qdflags[unit].selmask |= SEL_READ;
13387e911b15Skarels splx(s);
13397e911b15Skarels return(0);
1340b2b69f49Smarc } else {
1341e977faadSmarc /*
1342e977faadSmarc * this is a tty device
1343e977faadSmarc */
1344e977faadSmarc tp = &qd_tty[minor_dev];
1345e977faadSmarc if (ttnread(tp))
1346e977faadSmarc return(1);
1347e977faadSmarc tp->t_rsel = u.u_procp;
13487e911b15Skarels splx(s);
1349e977faadSmarc return(0);
1350e977faadSmarc }
1351e977faadSmarc
1352e977faadSmarc case FWRITE:
1353b2b69f49Smarc if ((minor(dev) & 0x03) == 2) {
1354e977faadSmarc /*
1355e977faadSmarc * this is a graphics device, so check for dma buffers
1356e977faadSmarc */
1357e977faadSmarc if (DMA_ISEMPTY(DMAheader[unit]))
1358e977faadSmarc {
1359e977faadSmarc splx(s);
1360e977faadSmarc return(1);
13617e911b15Skarels }
13627881ece5Smarc qdrsel[unit] = u.u_procp;
13637e911b15Skarels qdflags[unit].selmask |= SEL_WRITE;
13647e911b15Skarels splx(s);
13657e911b15Skarels return(0);
1366b2b69f49Smarc } else {
1367e977faadSmarc /*
1368e977faadSmarc * this is a tty device
1369e977faadSmarc */
1370e977faadSmarc tp = &qd_tty[minor_dev];
1371f5319004Smarc if (tp->t_outq.c_cc <= tp->t_lowat)
1372e977faadSmarc return(1);
1373e977faadSmarc tp->t_wsel = u.u_procp;
1374e977faadSmarc splx(s);
1375e977faadSmarc return(0);
1376e977faadSmarc }
1377e977faadSmarc }
13787881ece5Smarc splx(s);
13797881ece5Smarc return(0);
13807e911b15Skarels
13817e911b15Skarels } /* qdselect() */
13827e911b15Skarels
13837e911b15Skarels extern qd_strategy();
13847e911b15Skarels
qdwrite(dev,uio)13857e911b15Skarels qdwrite(dev, uio)
13867e911b15Skarels dev_t dev;
13877e911b15Skarels struct uio *uio;
13887e911b15Skarels {
13897e911b15Skarels register struct tty *tp;
13907881ece5Smarc register minor_dev;
13917881ece5Smarc register unit;
13927e911b15Skarels
13937e911b15Skarels minor_dev = minor(dev);
13947e911b15Skarels unit = (minor_dev >> 2) & 0x07;
13957e911b15Skarels
1396b2b69f49Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
1397b2b69f49Smarc /*
1398b2b69f49Smarc * this is the console...
1399b2b69f49Smarc */
14007e911b15Skarels tp = &qd_tty[minor_dev];
14017e911b15Skarels return ((*linesw[tp->t_line].l_write)(tp, uio));
1402b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1403b2b69f49Smarc /*
1404b2b69f49Smarc * this is a DMA xfer from user space
1405b2b69f49Smarc */
14067e911b15Skarels return (physio(qd_strategy, &qdbuf[unit],
14077e911b15Skarels dev, B_WRITE, minphys, uio));
14087e911b15Skarels }
14097881ece5Smarc return (ENXIO);
14107e911b15Skarels }
14117e911b15Skarels
qdread(dev,uio)14127e911b15Skarels qdread(dev, uio)
14137e911b15Skarels dev_t dev;
14147e911b15Skarels struct uio *uio;
14157e911b15Skarels {
14167e911b15Skarels register struct tty *tp;
14177881ece5Smarc register minor_dev;
14187881ece5Smarc register unit;
14197e911b15Skarels
14207e911b15Skarels minor_dev = minor(dev);
14217e911b15Skarels unit = (minor_dev >> 2) & 0x07;
14227e911b15Skarels
1423b2b69f49Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
1424b2b69f49Smarc /*
1425b2b69f49Smarc * this is the console
1426b2b69f49Smarc */
14277e911b15Skarels tp = &qd_tty[minor_dev];
14287e911b15Skarels return ((*linesw[tp->t_line].l_read)(tp, uio));
1429b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1430b2b69f49Smarc /*
1431b2b69f49Smarc * this is a bitmap-to-processor xfer
1432b2b69f49Smarc */
14337e911b15Skarels return (physio(qd_strategy, &qdbuf[unit],
14347e911b15Skarels dev, B_READ, minphys, uio));
14357e911b15Skarels }
14367881ece5Smarc return (ENXIO);
14377e911b15Skarels }
14387e911b15Skarels
14397e911b15Skarels /***************************************************************
14407e911b15Skarels *
14417e911b15Skarels * qd_strategy()... strategy routine to do DMA
14427e911b15Skarels *
14437e911b15Skarels ***************************************************************/
14447e911b15Skarels
qd_strategy(bp)14457e911b15Skarels qd_strategy(bp)
14467e911b15Skarels register struct buf *bp;
14477e911b15Skarels {
14487e911b15Skarels register struct dga *dga;
14497e911b15Skarels register struct adder *adder;
14507881ece5Smarc register unit;
14517e911b15Skarels int QBAreg;
14527e911b15Skarels int s;
14537e911b15Skarels int cookie;
14547e911b15Skarels
14557e911b15Skarels unit = (minor(bp->b_dev) >> 2) & 0x07;
14567e911b15Skarels
1457b2b69f49Smarc /*
1458b2b69f49Smarc * init pointers
1459b2b69f49Smarc */
14607e911b15Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
14617881ece5Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit);
14627e911b15Skarels goto STRAT_ERR;
14637e911b15Skarels }
14647e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
1465e977faadSmarc s = spl5();
14667e911b15Skarels qdflags[unit].user_dma = -1;
14677e911b15Skarels dga->csr |= DMA_IE;
14687e911b15Skarels cookie = QBAreg & 0x3FFFF;
14697e911b15Skarels dga->adrs_lo = (short) cookie;
14707e911b15Skarels dga->adrs_hi = (short) (cookie >> 16);
14717e911b15Skarels dga->bytcnt_lo = (short) bp->b_bcount;
14727e911b15Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
14737e911b15Skarels
14747e911b15Skarels while (qdflags[unit].user_dma) {
14757e911b15Skarels sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
14767e911b15Skarels }
14777e911b15Skarels splx(s);
14787e911b15Skarels ubarelse(0, &QBAreg);
14797e911b15Skarels if (!(dga->csr & DMA_ERR)) {
14807e911b15Skarels iodone(bp);
14817e911b15Skarels return;
14827e911b15Skarels }
14837e911b15Skarels
14847e911b15Skarels STRAT_ERR:
14857e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
14867e911b15Skarels adder->command = CANCEL; /* cancel adder activity */
14877e911b15Skarels dga->csr &= ~DMA_IE;
14887e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
14897e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */
14907e911b15Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */
14917e911b15Skarels
1492b2b69f49Smarc /*
1493b2b69f49Smarc * if DMA was running, flush spurious intrpt
1494b2b69f49Smarc */
14957e911b15Skarels if (dga->bytcnt_lo != 0) {
14967e911b15Skarels dga->bytcnt_lo = 0;
14977e911b15Skarels dga->bytcnt_hi = 0;
14987e911b15Skarels DMA_SETIGNORE(DMAheader[unit]);
14997e911b15Skarels dga->csr |= DMA_IE;
15007e911b15Skarels }
15017e911b15Skarels iodone(bp);
15027e911b15Skarels
15037e911b15Skarels } /* qd_strategy */
15047e911b15Skarels
15057881ece5Smarc /*
15067881ece5Smarc * Start output to the console screen
15077881ece5Smarc */
qdstart(tp)15087e911b15Skarels qdstart(tp)
15097e911b15Skarels register struct tty *tp;
15107e911b15Skarels {
15117881ece5Smarc register which_unit, unit, c;
15127e911b15Skarels int s;
15137e911b15Skarels
1514e977faadSmarc unit = minor(tp->t_dev);
1515e977faadSmarc which_unit = (unit >> 2) & 0x3;
1516e977faadSmarc unit &= 0x03;
1517e977faadSmarc
1518e977faadSmarc s = spl5();
1519e977faadSmarc
1520b2b69f49Smarc /*
1521b2b69f49Smarc * If it's currently active, or delaying, no need to do anything.
1522b2b69f49Smarc */
15237e911b15Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
15247e911b15Skarels goto out;
15257e911b15Skarels
1526b2b69f49Smarc /*
1527b2b69f49Smarc * Display chars until the queue is empty.
1528b2b69f49Smarc * Drop input from anything but the console
1529b2b69f49Smarc * device on the floor.
1530b2b69f49Smarc *
1531b2b69f49Smarc * XXX - this loop is done at spltty.
1532b2b69f49Smarc *
1533b2b69f49Smarc */
15347e911b15Skarels while (tp->t_outq.c_cc) {
15357e911b15Skarels c = getc(&tp->t_outq);
1536e977faadSmarc if (unit == 0)
15377881ece5Smarc blitc(which_unit, (u_char)c);
15387e911b15Skarels }
1539b2b69f49Smarc /*
1540e977faadSmarc * If there are sleepers, and output has drained below low
1541b2b69f49Smarc * water mark, wake up the sleepers.
1542b2b69f49Smarc */
1543f5319004Smarc if (tp->t_outq.c_cc <= tp->t_lowat) {
15447e911b15Skarels if (tp->t_state & TS_ASLEEP){
15457e911b15Skarels tp->t_state &= ~TS_ASLEEP;
15467e911b15Skarels wakeup((caddr_t) &tp->t_outq);
15477e911b15Skarels }
1548e977faadSmarc }
1549e977faadSmarc
1550e977faadSmarc tp->t_state &= ~TS_BUSY;
15517e911b15Skarels
15527e911b15Skarels out:
15537e911b15Skarels splx(s);
15547e911b15Skarels
15557e911b15Skarels } /* qdstart */
15567e911b15Skarels
15577881ece5Smarc /*ARGSUSED*/
qdstop(tp,flag)15587e911b15Skarels qdstop(tp, flag)
15597e911b15Skarels register struct tty *tp;
15607e911b15Skarels int flag;
15617e911b15Skarels {
15627e911b15Skarels register int s;
15637e911b15Skarels
1564e977faadSmarc s = spl5(); /* block intrpts during state modification */
15657881ece5Smarc if (tp->t_state & TS_BUSY)
15667881ece5Smarc if ((tp->t_state & TS_TTSTOP) == 0)
15677e911b15Skarels tp->t_state |= TS_FLUSH;
1568b2b69f49Smarc else
15697e911b15Skarels tp->t_state &= ~TS_BUSY;
15707e911b15Skarels splx(s);
15717e911b15Skarels }
15727e911b15Skarels
15737881ece5Smarc /*
15747881ece5Smarc * Output a character to the QDSS screen
15757881ece5Smarc */
15767e911b15Skarels
blitc(unit,chr)15777e911b15Skarels blitc(unit, chr)
15787881ece5Smarc register unit;
15797881ece5Smarc register u_char chr;
15807e911b15Skarels {
15817e911b15Skarels register struct adder *adder;
15827e911b15Skarels register struct dga *dga;
15837e911b15Skarels register int i;
1584b2b69f49Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
1585b2b69f49Smarc static short inescape[NQD];
15867e911b15Skarels
15877e911b15Skarels adder = (struct adder *)qdmap[unit].adder;
15887e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
1589b2b69f49Smarc /*
1590b2b69f49Smarc * BSD comment: this (&=0177) defeats the extended character
1591b2b69f49Smarc * set code for the glass tty, but if i had the time i would
1592b2b69f49Smarc * spend it ripping out the code completely. This driver
1593b2b69f49Smarc * is too big for its own good.
1594b2b69f49Smarc */
1595b2b69f49Smarc chr &= 0177;
1596b2b69f49Smarc /*
15977881ece5Smarc * Cursor addressing (so vi will work).
1598b2b69f49Smarc * Decode for "\E=%.%." cursor motion description.
15997881ece5Smarc * Corresponds to type "qdcons" in /etc/termcap:
1600b2b69f49Smarc *
1601b2b69f49Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
1602b2b69f49Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
1603b2b69f49Smarc *
1604b2b69f49Smarc */
1605b2b69f49Smarc if (inescape[unit] && nograph) {
1606b2b69f49Smarc switch (inescape[unit]++) {
1607b2b69f49Smarc case 1:
1608b2b69f49Smarc if (chr != '=') {
1609b2b69f49Smarc /* abort escape sequence */
1610b2b69f49Smarc inescape[unit] = 0;
1611b2b69f49Smarc blitc(unit, chr);
1612b2b69f49Smarc }
16137881ece5Smarc return;
1614b2b69f49Smarc case 2:
1615b2b69f49Smarc /* position row */
1616b2b69f49Smarc cursor[unit].y = CHAR_HEIGHT * chr;
1617b2b69f49Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT)
1618b2b69f49Smarc cursor[unit].y = 863 - CHAR_HEIGHT;
1619b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y);
16207881ece5Smarc return;
1621b2b69f49Smarc case 3:
1622b2b69f49Smarc /* position column */
1623b2b69f49Smarc cursor[unit].x = CHAR_WIDTH * chr;
1624b2b69f49Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH)
1625b2b69f49Smarc cursor[unit].x = 1023 - CHAR_WIDTH;
1626b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x);
1627b2b69f49Smarc inescape[unit] = 0;
16287881ece5Smarc return;
1629b2b69f49Smarc default:
1630b2b69f49Smarc inescape[unit] = 0;
1631b2b69f49Smarc blitc(unit, chr);
1632b2b69f49Smarc }
1633b2b69f49Smarc }
163424f67f6bSmarc
16357e911b15Skarels switch (chr) {
16367e911b15Skarels case '\r': /* return char */
16377e911b15Skarels cursor[unit].x = 0;
1638b2b69f49Smarc if (nograph)
16397e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x);
16407881ece5Smarc return;
16417e911b15Skarels
16427e911b15Skarels case '\t': /* tab char */
16437e911b15Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
16447e911b15Skarels blitc(unit, ' ');
16457e911b15Skarels }
16467881ece5Smarc return;
16477e911b15Skarels
16487e911b15Skarels case '\n': /* line feed char */
16497e911b15Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1650b2b69f49Smarc if (nograph) {
16517e911b15Skarels cursor[unit].y -= CHAR_HEIGHT;
16527e911b15Skarels scroll_up(adder);
1653b2b69f49Smarc } else
1654b2b69f49Smarc cursor[unit].y = 0;
16557e911b15Skarels }
1656b2b69f49Smarc if (nograph)
16577e911b15Skarels dga->y_cursor = TRANY(cursor[unit].y);
16587881ece5Smarc return;
16597e911b15Skarels
16607e911b15Skarels case '\b': /* backspace char */
16617e911b15Skarels if (cursor[unit].x > 0) {
16627e911b15Skarels cursor[unit].x -= CHAR_WIDTH;
1663b2b69f49Smarc if (nograph)
1664b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x);
1665b2b69f49Smarc }
16667881ece5Smarc return;
1667b2b69f49Smarc case CTRL('k'): /* cursor up */
1668b2b69f49Smarc if (nograph && cursor[unit].y > 0) {
1669b2b69f49Smarc cursor[unit].y -= CHAR_HEIGHT;
1670b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y);
1671b2b69f49Smarc }
16727881ece5Smarc return;
1673b2b69f49Smarc
1674b2b69f49Smarc case CTRL('^'): /* home cursor */
1675b2b69f49Smarc if (nograph) {
1676b2b69f49Smarc cursor[unit].x = 0;
1677b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x);
1678b2b69f49Smarc cursor[unit].y = 0;
1679b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y);
1680b2b69f49Smarc }
16817881ece5Smarc return;
1682b2b69f49Smarc
1683b2b69f49Smarc case CTRL('l'): /* cursor right */
1684b2b69f49Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
1685b2b69f49Smarc cursor[unit].x += CHAR_WIDTH;
16867e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x);
16877e911b15Skarels }
16887881ece5Smarc return;
16897e911b15Skarels
1690b2b69f49Smarc case CTRL('z'): /* clear screen */
1691b2b69f49Smarc if (nograph) {
1692b2b69f49Smarc setup_dragon(unit);
1693b2b69f49Smarc clear_qd_screen(unit);
1694b2b69f49Smarc /* home cursor - termcap seems to assume this */
1695b2b69f49Smarc cursor[unit].x = 0;
1696b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x);
1697b2b69f49Smarc cursor[unit].y = 0;
1698b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y);
1699b2b69f49Smarc }
17007881ece5Smarc return;
1701e977faadSmarc
1702b2b69f49Smarc case '\033': /* start escape sequence */
1703b2b69f49Smarc if (nograph)
1704b2b69f49Smarc inescape[unit] = 1;
17057881ece5Smarc return;
1706b2b69f49Smarc
1707b2b69f49Smarc default:
1708b2b69f49Smarc if ((chr < ' ') || (chr > '~'))
17097881ece5Smarc return;
17107e911b15Skarels }
1711b2b69f49Smarc /*
1712b2b69f49Smarc * setup VIPER operand control registers
1713b2b69f49Smarc */
17147e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */
17157e911b15Skarels write_ID(adder, SRC1_OCR_B,
17167e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
17177e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */
17187e911b15Skarels write_ID(adder, SRC1_OCR_B,
17197e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
17207e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
17217e911b15Skarels write_ID(adder, DST_OCR_B,
17227e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
17237e911b15Skarels write_ID(adder, MASK_1, 0xFFFF);
17247e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
17257e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1726e977faadSmarc adder->x_clip_min = 0;
1727e977faadSmarc adder->x_clip_max = 1024;
1728e977faadSmarc adder->y_clip_min = 0;
1729e977faadSmarc adder->y_clip_max = 864;
1730b2b69f49Smarc /*
1731b2b69f49Smarc * load DESTINATION origin and vectors
1732b2b69f49Smarc */
17337e911b15Skarels adder->fast_dest_dy = 0;
17347e911b15Skarels adder->slow_dest_dx = 0;
17357e911b15Skarels adder->error_1 = 0;
17367e911b15Skarels adder->error_2 = 0;
17377e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
17387881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE);
17397e911b15Skarels adder->destination_x = cursor[unit].x;
17407e911b15Skarels adder->fast_dest_dx = CHAR_WIDTH;
17417e911b15Skarels adder->destination_y = cursor[unit].y;
17427e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT;
1743b2b69f49Smarc /*
1744b2b69f49Smarc * load SOURCE origin and vectors
1745b2b69f49Smarc */
1746e977faadSmarc if ((chr - ' ') > (CHARS - 1)) {
1747e977faadSmarc printf("Invalid character (x)%x in blitc\n",chr);
1748e977faadSmarc chr = ' ';
1749e977faadSmarc }
1750b2b69f49Smarc /*
1751b2b69f49Smarc * X position is modulo the number of characters per line
1752b2b69f49Smarc */
1753e977faadSmarc adder->source_1_x = FONT_X +
1754e977faadSmarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
1755b2b69f49Smarc /*
1756b2b69f49Smarc * Point to either first or second row
1757b2b69f49Smarc */
1758e977faadSmarc adder->source_1_y = 2048 - 15 *
1759e977faadSmarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
17607e911b15Skarels adder->source_1_dx = CHAR_WIDTH;
17617e911b15Skarels adder->source_1_dy = CHAR_HEIGHT;
17627e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
17637e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1764b2b69f49Smarc /*
1765b2b69f49Smarc * update console cursor coordinates
1766b2b69f49Smarc */
17677e911b15Skarels cursor[unit].x += CHAR_WIDTH;
1768b2b69f49Smarc if (nograph)
17697e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x);
17707e911b15Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
17717e911b15Skarels blitc(unit, '\r');
17727e911b15Skarels blitc(unit, '\n');
17737e911b15Skarels }
17747e911b15Skarels
17757e911b15Skarels } /* blitc */
17767e911b15Skarels
qdreset()17777881ece5Smarc qdreset() { }
17787e911b15Skarels
17797881ece5Smarc /*
1780b2b69f49Smarc * INTERRUPT SERVICE ROUTINES
17817881ece5Smarc */
17827e911b15Skarels
17837881ece5Smarc /*
17847881ece5Smarc * Service "DMA DONE" interrupt condition
17857881ece5Smarc */
qddint(qd)17867e911b15Skarels qddint(qd)
17877881ece5Smarc register qd;
17887e911b15Skarels {
17897e911b15Skarels register struct DMAreq_header *header;
17907e911b15Skarels register struct DMAreq *request;
17917e911b15Skarels register struct dga *dga;
17927e911b15Skarels struct adder *adder;
17937e911b15Skarels int cookie; /* DMA adrs for QDSS */
17947e911b15Skarels
17957881ece5Smarc (void)spl4(); /* allow interval timer in */
17967e911b15Skarels
1797b2b69f49Smarc /*
1798b2b69f49Smarc * init pointers
1799b2b69f49Smarc */
18007e911b15Skarels header = DMAheader[qd]; /* register for optimization */
18017e911b15Skarels dga = (struct dga *) qdmap[qd].dga;
18027e911b15Skarels adder = (struct adder *) qdmap[qd].adder;
18037e911b15Skarels
1804b2b69f49Smarc /*
1805b2b69f49Smarc * if this interrupt flagged as bogus for interrupt flushing purposes..
1806b2b69f49Smarc */
18077e911b15Skarels if (DMA_ISIGNORE(header)) {
18087e911b15Skarels DMA_CLRIGNORE(header);
18097e911b15Skarels return;
18107e911b15Skarels }
18117e911b15Skarels
1812b2b69f49Smarc /*
1813b2b69f49Smarc * dump a DMA hardware error message if appropriate
1814b2b69f49Smarc */
18157e911b15Skarels if (dga->csr & DMA_ERR) {
18167e911b15Skarels
18177e911b15Skarels if (dga->csr & PARITY_ERR)
18187881ece5Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
18197e911b15Skarels
18207e911b15Skarels if (dga->csr & BUS_ERR)
18217881ece5Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd);
18227e911b15Skarels }
18237e911b15Skarels
1824b2b69f49Smarc /*
1825b2b69f49Smarc * if this was a DMA from user space...
1826b2b69f49Smarc */
18277e911b15Skarels if (qdflags[qd].user_dma) {
18287e911b15Skarels qdflags[qd].user_dma = 0;
18297e911b15Skarels wakeup((caddr_t)&qdflags[qd].user_dma);
18307e911b15Skarels return;
18317e911b15Skarels }
18327e911b15Skarels
1833b2b69f49Smarc /*
1834b2b69f49Smarc * if we're doing DMA request queue services, field the error condition
1835b2b69f49Smarc */
18367e911b15Skarels if (dga->csr & DMA_ERR) {
18377e911b15Skarels
18387e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
18397e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */
18407e911b15Skarels adder->command = CANCEL; /* cancel adder activity */
18417e911b15Skarels
18427e911b15Skarels DMA_SETERROR(header); /* flag error in header status word */
18437e911b15Skarels DMA_CLRACTIVE(header);
18447e911b15Skarels header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
18457e911b15Skarels header->newest = header->oldest;
18467e911b15Skarels header->used = 0;
18477e911b15Skarels
18487881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18497881ece5Smarc selwakeup(qdrsel[qd], 0);
18507881ece5Smarc qdrsel[qd] = 0;
18517e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE;
18527e911b15Skarels }
18537e911b15Skarels
18547e911b15Skarels if (dga->bytcnt_lo != 0) {
18557e911b15Skarels dga->bytcnt_lo = 0;
18567e911b15Skarels dga->bytcnt_hi = 0;
18577e911b15Skarels DMA_SETIGNORE(header);
18587e911b15Skarels }
18597e911b15Skarels return;
18607e911b15Skarels }
18617e911b15Skarels
1862b2b69f49Smarc /*
1863b2b69f49Smarc * if the DMA request queue is now becoming non-full,
1864b2b69f49Smarc * wakeup "select" client.
1865b2b69f49Smarc */
18667e911b15Skarels if (DMA_ISFULL(header)) {
18677881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18687881ece5Smarc selwakeup(qdrsel[qd], 0);
18697881ece5Smarc qdrsel[qd] = 0;
18707e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE;
18717e911b15Skarels }
18727e911b15Skarels }
18737e911b15Skarels
18747e911b15Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
1875e977faadSmarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
18767e911b15Skarels
1877e977faadSmarc /* check for unexpected interrupt */
1878e977faadSmarc if (DMA_ISEMPTY(header))
18797e911b15Skarels return;
18807e911b15Skarels
18817e911b15Skarels DMA_GETEND(header); /* update request queue indices */
18827e911b15Skarels
1883b2b69f49Smarc /*
18847881ece5Smarc * if no more DMA pending, wake up "select" client and exit
18857881ece5Smarc */
18867e911b15Skarels if (DMA_ISEMPTY(header)) {
18877e911b15Skarels
18887881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18897881ece5Smarc selwakeup(qdrsel[qd], 0);
18907881ece5Smarc qdrsel[qd] = 0;
18917e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE;
18927e911b15Skarels }
18937e911b15Skarels
18947e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */
18957e911b15Skarels return;
18967e911b15Skarels }
18977e911b15Skarels
1898b2b69f49Smarc /*
18997881ece5Smarc * initiate next DMA xfer
19007881ece5Smarc */
19017e911b15Skarels request = DMA_GETBEGIN(header);
1902e977faadSmarc if (request->DMAtype != QDlast_DMAtype) {
1903e977faadSmarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
1904e977faadSmarc adder->command = CANCEL; /* cancel adder activity */
1905e977faadSmarc }
1906e977faadSmarc
19077e911b15Skarels
19087e911b15Skarels switch (request->DMAtype) {
19097e911b15Skarels
19107e911b15Skarels case DISPLIST:
1911e977faadSmarc if (request->DMAtype != QDlast_DMAtype) {
19127e911b15Skarels dga->csr |= DL_ENB;
1913e977faadSmarc dga->csr &= ~(BTOP_ENB | BYTE_DMA);
1914e977faadSmarc }
19157e911b15Skarels break;
19167e911b15Skarels
19177e911b15Skarels case PTOB:
1918e977faadSmarc if (request->DMAtype != QDlast_DMAtype) {
1919e977faadSmarc if (request->DMAdone & BYTE_PACK)
1920e977faadSmarc dga->csr |= (PTOB_ENB | BYTE_DMA);
1921e977faadSmarc else {
19227e911b15Skarels dga->csr |= PTOB_ENB;
1923e977faadSmarc dga->csr &= ~BYTE_DMA;
1924e977faadSmarc }
1925e977faadSmarc }
19267e911b15Skarels break;
19277e911b15Skarels
19287e911b15Skarels case BTOP:
1929e977faadSmarc if (request->DMAtype != QDlast_DMAtype) {
1930e977faadSmarc if (request->DMAdone & BYTE_PACK) {
1931e977faadSmarc dga->csr &= ~DL_ENB;
1932e977faadSmarc dga->csr |= (BTOP_ENB | BYTE_DMA);
1933e977faadSmarc }
1934e977faadSmarc else {
19357e911b15Skarels dga->csr |= BTOP_ENB;
1936e977faadSmarc dga->csr &= ~(BYTE_DMA | DL_ENB);
1937e977faadSmarc }
1938e977faadSmarc }
19397e911b15Skarels break;
19407e911b15Skarels default:
19417881ece5Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
19427e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */
19437e911b15Skarels return;
19447e911b15Skarels }
19457e911b15Skarels
19467e911b15Skarels if (request->DMAdone & COUNT_ZERO) {
19477e911b15Skarels dga->csr &= ~SET_DONE_FIFO;
1948b2b69f49Smarc }
1949b2b69f49Smarc else if (request->DMAdone & FIFO_EMPTY) {
19507e911b15Skarels dga->csr |= SET_DONE_FIFO;
19517e911b15Skarels }
19527e911b15Skarels
19537e911b15Skarels if (request->DMAdone & WORD_PACK)
19547e911b15Skarels dga->csr &= ~BYTE_DMA;
19557e911b15Skarels else if (request->DMAdone & BYTE_PACK)
19567e911b15Skarels dga->csr |= BYTE_DMA;
19577e911b15Skarels
19587e911b15Skarels dga->csr |= DMA_IE;
1959e977faadSmarc QDlast_DMAtype = request->DMAtype;
19607e911b15Skarels
19617e911b15Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
19627e911b15Skarels
19637e911b15Skarels dga->adrs_lo = (short) cookie;
19647e911b15Skarels dga->adrs_hi = (short) (cookie >> 16);
19657e911b15Skarels
19667e911b15Skarels dga->bytcnt_lo = (short) request->length;
19677e911b15Skarels dga->bytcnt_hi = (short) (request->length >> 16);
19687e911b15Skarels
19697e911b15Skarels return;
19707e911b15Skarels }
19717e911b15Skarels
19727881ece5Smarc /*
19737881ece5Smarc * ADDER interrupt service routine
19747881ece5Smarc */
qdaint(qd)19757e911b15Skarels qdaint(qd)
19767881ece5Smarc register qd;
19777e911b15Skarels {
19787e911b15Skarels register struct adder *adder;
19797e911b15Skarels struct color_buf *cbuf;
19807e911b15Skarels int i;
19817e911b15Skarels register struct rgb *rgbp;
19827e911b15Skarels register short *red;
19837e911b15Skarels register short *green;
19847e911b15Skarels register short *blue;
19857e911b15Skarels
19867881ece5Smarc (void)spl4(); /* allow interval timer in */
19877e911b15Skarels
19887e911b15Skarels adder = (struct adder *) qdmap[qd].adder;
19897e911b15Skarels
1990b2b69f49Smarc /*
1991b2b69f49Smarc * service the vertical blank interrupt (VSYNC bit) by loading
1992b2b69f49Smarc * any pending color map load request
1993b2b69f49Smarc */
19947e911b15Skarels if (adder->status & VSYNC) {
19957e911b15Skarels adder->status &= ~VSYNC; /* clear the interrupt */
19967e911b15Skarels cbuf = color_buf[qd];
19977e911b15Skarels if (cbuf->status & LOAD_COLOR_MAP) {
19987e911b15Skarels
19997e911b15Skarels red = (short *) qdmap[qd].red;
20007e911b15Skarels green = (short *) qdmap[qd].green;
20017e911b15Skarels blue = (short *) qdmap[qd].blue;
20027e911b15Skarels
2003b2b69f49Smarc for (i = cbuf->count, rgbp = cbuf->rgb;
2004b2b69f49Smarc --i >= 0; rgbp++) {
20057e911b15Skarels red[rgbp->offset] = (short) rgbp->red;
20067e911b15Skarels green[rgbp->offset] = (short) rgbp->green;
20077e911b15Skarels blue[rgbp->offset] = (short) rgbp->blue;
20087e911b15Skarels }
20097e911b15Skarels
20107e911b15Skarels cbuf->status &= ~LOAD_COLOR_MAP;
20117e911b15Skarels }
20127e911b15Skarels }
20137e911b15Skarels
2014b2b69f49Smarc /*
2015b2b69f49Smarc * service the scroll interrupt (FRAME_SYNC bit)
2016b2b69f49Smarc */
20177e911b15Skarels if (adder->status & FRAME_SYNC) {
20187e911b15Skarels adder->status &= ~FRAME_SYNC; /* clear the interrupt */
20197e911b15Skarels
20207e911b15Skarels if (scroll[qd]->status & LOAD_REGS) {
20217e911b15Skarels
20227881ece5Smarc for (i = 1000, adder->status = 0; i > 0 &&
20237881ece5Smarc !(adder->status&ID_SCROLL_READY); --i)
2024b2b69f49Smarc ;
20257e911b15Skarels
20267e911b15Skarels if (i == 0) {
20277881ece5Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
2028b2b69f49Smarc qd);
20297e911b15Skarels return;
20307e911b15Skarels }
20317e911b15Skarels
20327e911b15Skarels adder->ID_scroll_data = scroll[qd]->viper_constant;
20337e911b15Skarels adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
20347e911b15Skarels
2035b2b69f49Smarc adder->y_scroll_constant =
2036b2b69f49Smarc scroll[qd]->y_scroll_constant;
20377e911b15Skarels adder->y_offset_pending = scroll[qd]->y_offset;
20387e911b15Skarels
20397e911b15Skarels if (scroll[qd]->status & LOAD_INDEX) {
20407e911b15Skarels
2041b2b69f49Smarc adder->x_index_pending =
2042b2b69f49Smarc scroll[qd]->x_index_pending;
2043b2b69f49Smarc adder->y_index_pending =
2044b2b69f49Smarc scroll[qd]->y_index_pending;
20457e911b15Skarels }
20467e911b15Skarels
20477e911b15Skarels scroll[qd]->status = 0x00;
20487e911b15Skarels }
20497e911b15Skarels }
20507e911b15Skarels }
20517e911b15Skarels
20527881ece5Smarc /*
20537881ece5Smarc * DUART input interrupt service routine
20547e911b15Skarels *
2055b2b69f49Smarc * XXX - this routine should be broken out - it is essentially
2056b2b69f49Smarc * straight line code.
20577881ece5Smarc */
20587e911b15Skarels
qdiint(qd)20597e911b15Skarels qdiint(qd)
20607881ece5Smarc register qd;
20617e911b15Skarels {
20627e911b15Skarels register struct _vs_event *event;
20637e911b15Skarels register struct qdinput *eqh;
20647e911b15Skarels struct dga *dga;
20657e911b15Skarels struct duart *duart;
20667e911b15Skarels struct mouse_report *new_rep;
20677e911b15Skarels struct uba_device *ui;
20687e911b15Skarels struct tty *tp;
2069e977faadSmarc u_short chr;
20707e911b15Skarels u_short status;
20717e911b15Skarels u_short data;
20727e911b15Skarels u_short key;
20737e911b15Skarels char do_wakeup = 0; /* flag to do a select wakeup call */
20747e911b15Skarels char a, b, c; /* mouse button test variables */
20757e911b15Skarels
20767881ece5Smarc (void)spl4(); /* allow interval timer in */
20777e911b15Skarels
20787e911b15Skarels eqh = eq_header[qd]; /* optimized as a register */
20797e911b15Skarels new_rep = ¤t_rep[qd];
20807e911b15Skarels duart = (struct duart *) qdmap[qd].duart;
20817e911b15Skarels
2082b2b69f49Smarc /*
20837881ece5Smarc * if the graphic device is turned on..
20847881ece5Smarc */
20857e911b15Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) {
2086b2b69f49Smarc /*
2087b2b69f49Smarc * empty DUART
2088b2b69f49Smarc */
20897881ece5Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
2090b2b69f49Smarc /*
20917881ece5Smarc * pick up LK-201 input (if any)
20927881ece5Smarc */
20937881ece5Smarc if (duart->statusA&RCV_RDY) {
20947e911b15Skarels
20957e911b15Skarels /* if error condition, then reset it */
20967e911b15Skarels
20977881ece5Smarc if (duart->statusA&0x70) {
20987e911b15Skarels duart->cmdA = 0x40;
20997e911b15Skarels continue;
21007e911b15Skarels }
21017e911b15Skarels
21027e911b15Skarels /* event queue full now? (overflow condition) */
21037e911b15Skarels
21047e911b15Skarels if (ISFULL(eqh) == TRUE) {
2105b2b69f49Smarc printf(
21067881ece5Smarc "qd%d: qdiint: event queue overflow\n",
2107b2b69f49Smarc qd);
21087e911b15Skarels break;
21097e911b15Skarels }
21107e911b15Skarels
2111b2b69f49Smarc /*
21127e911b15Skarels * Check for various keyboard errors */
21137e911b15Skarels
21147e911b15Skarels key = duart->dataA & 0xFF;
21157e911b15Skarels
2116b2b69f49Smarc if (key==LK_POWER_ERROR ||
2117b2b69f49Smarc key==LK_KDOWN_ERROR ||
2118b2b69f49Smarc key == LK_INPUT_ERROR ||
2119b2b69f49Smarc key == LK_OUTPUT_ERROR) {
2120b2b69f49Smarc printf(
21217881ece5Smarc "qd%d: qdiint: keyboard error, code = %x\n",
2122b2b69f49Smarc qd,key);
21237881ece5Smarc return;
21247e911b15Skarels }
21257e911b15Skarels
21267e911b15Skarels if (key < LK_LOWEST)
21277881ece5Smarc return;
21287e911b15Skarels
21297e911b15Skarels ++do_wakeup; /* request a select wakeup call */
21307e911b15Skarels
21317e911b15Skarels event = PUTBEGIN(eqh);
21327e911b15Skarels PUTEND(eqh);
21337e911b15Skarels
21347e911b15Skarels event->vse_key = key;
21357e911b15Skarels event->vse_key &= 0x00FF;
21367e911b15Skarels event->vse_x = eqh->curs_pos.x;
21377e911b15Skarels event->vse_y = eqh->curs_pos.y;
21387e911b15Skarels event->vse_time = TOY;
21397e911b15Skarels event->vse_type = VSE_BUTTON;
21407e911b15Skarels event->vse_direction = VSE_KBTRAW;
21417e911b15Skarels event->vse_device = VSE_DKB;
21427e911b15Skarels }
21437e911b15Skarels
2144b2b69f49Smarc /*
21457e911b15Skarels * pick up the mouse input (if any) */
21467e911b15Skarels
21477e911b15Skarels if ((status = duart->statusB) & RCV_RDY &&
21487e911b15Skarels qdflags[qd].pntr_id == MOUSE_ID) {
21497e911b15Skarels
21507e911b15Skarels if (status & 0x70) {
21517e911b15Skarels duart->cmdB = 0x40;
21527e911b15Skarels continue;
21537e911b15Skarels }
21547e911b15Skarels
21557e911b15Skarels /* event queue full now? (overflow condition) */
21567e911b15Skarels
21577e911b15Skarels if (ISFULL(eqh) == TRUE) {
2158b2b69f49Smarc printf(
21597881ece5Smarc "qd%d: qdiint: event queue overflow\n",
2160b2b69f49Smarc qd);
21617e911b15Skarels break;
21627e911b15Skarels }
21637e911b15Skarels
21647e911b15Skarels data = duart->dataB; /* get report byte */
21657e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */
21667e911b15Skarels
2167b2b69f49Smarc /*
21687e911b15Skarels * if 1st byte of report.. */
21697e911b15Skarels
21707e911b15Skarels if ( data & START_FRAME) {
21717e911b15Skarels new_rep->state = data;
21727e911b15Skarels if (new_rep->bytcnt > 1) {
2173b2b69f49Smarc /* start of new frame */
2174b2b69f49Smarc new_rep->bytcnt = 1;
2175b2b69f49Smarc /* ..continue looking */
2176b2b69f49Smarc continue;
21777e911b15Skarels }
21787e911b15Skarels }
21797e911b15Skarels
2180b2b69f49Smarc /*
21817e911b15Skarels * if 2nd byte of report.. */
21827e911b15Skarels
21837e911b15Skarels else if (new_rep->bytcnt == 2) {
21847e911b15Skarels new_rep->dx = data & 0x00FF;
21857e911b15Skarels }
21867e911b15Skarels
2187b2b69f49Smarc /*
21887e911b15Skarels * if 3rd byte of report, load input event queue */
21897e911b15Skarels
21907e911b15Skarels else if (new_rep->bytcnt == 3) {
21917e911b15Skarels
21927e911b15Skarels new_rep->dy = data & 0x00FF;
21937e911b15Skarels new_rep->bytcnt = 0;
21947e911b15Skarels
2195b2b69f49Smarc /*
21967e911b15Skarels * if mouse position has changed.. */
21977e911b15Skarels
21987e911b15Skarels if (new_rep->dx != 0 || new_rep->dy != 0) {
21997e911b15Skarels
2200b2b69f49Smarc /*
22017e911b15Skarels * calculate acceleration factor, if needed */
22027e911b15Skarels
22037e911b15Skarels if (qdflags[qd].curs_acc > ACC_OFF) {
22047e911b15Skarels
22057e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dx)
22067e911b15Skarels new_rep->dx +=
22077e911b15Skarels (new_rep->dx - qdflags[qd].curs_thr)
22087e911b15Skarels * qdflags[qd].curs_acc;
22097e911b15Skarels
22107e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dy)
22117e911b15Skarels new_rep->dy +=
22127e911b15Skarels (new_rep->dy - qdflags[qd].curs_thr)
22137e911b15Skarels * qdflags[qd].curs_acc;
22147e911b15Skarels }
22157e911b15Skarels
2216b2b69f49Smarc /*
22177e911b15Skarels * update cursor position coordinates */
22187e911b15Skarels
22197e911b15Skarels if (new_rep->state & X_SIGN) {
22207e911b15Skarels eqh->curs_pos.x += new_rep->dx;
22217e911b15Skarels if (eqh->curs_pos.x > 1023)
22227e911b15Skarels eqh->curs_pos.x = 1023;
22237e911b15Skarels }
22247e911b15Skarels else {
22257e911b15Skarels eqh->curs_pos.x -= new_rep->dx;
22267e911b15Skarels if (eqh->curs_pos.x < -15)
22277e911b15Skarels eqh->curs_pos.x = -15;
22287e911b15Skarels }
22297e911b15Skarels
22307e911b15Skarels if (new_rep->state & Y_SIGN) {
22317e911b15Skarels eqh->curs_pos.y -= new_rep->dy;
22327e911b15Skarels if (eqh->curs_pos.y < -15)
22337e911b15Skarels eqh->curs_pos.y = -15;
22347e911b15Skarels }
22357e911b15Skarels else {
22367e911b15Skarels eqh->curs_pos.y += new_rep->dy;
22377e911b15Skarels if (eqh->curs_pos.y > 863)
22387e911b15Skarels eqh->curs_pos.y = 863;
22397e911b15Skarels }
22407e911b15Skarels
2241b2b69f49Smarc /*
22427e911b15Skarels * update cursor screen position */
22437e911b15Skarels
22447e911b15Skarels dga = (struct dga *) qdmap[qd].dga;
22457e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x);
22467e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y);
22477e911b15Skarels
2248b2b69f49Smarc /*
22497e911b15Skarels * if cursor is in the box, no event report */
22507e911b15Skarels
22517e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right &&
22527e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left &&
22537e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top &&
22547e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) {
22557e911b15Skarels goto GET_MBUTTON;
22567e911b15Skarels }
22577e911b15Skarels
2258b2b69f49Smarc /*
22597e911b15Skarels * report the mouse motion event */
22607e911b15Skarels
22617e911b15Skarels event = PUTBEGIN(eqh);
22627e911b15Skarels PUTEND(eqh);
22637e911b15Skarels
22647e911b15Skarels ++do_wakeup; /* request a select wakeup call */
22657e911b15Skarels
22667e911b15Skarels event->vse_x = eqh->curs_pos.x;
22677e911b15Skarels event->vse_y = eqh->curs_pos.y;
22687e911b15Skarels
22697e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */
22707e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */
22717e911b15Skarels event->vse_key = 0;
22727e911b15Skarels event->vse_direction = 0;
22737e911b15Skarels event->vse_time = TOY; /* time stamp */
22747e911b15Skarels }
22757e911b15Skarels
22767e911b15Skarels GET_MBUTTON:
2277b2b69f49Smarc /*
22787e911b15Skarels * if button state has changed */
22797e911b15Skarels
22807e911b15Skarels a = new_rep->state & 0x07; /*mask nonbutton bits */
22817e911b15Skarels b = last_rep[qd].state & 0x07;
22827e911b15Skarels
22837e911b15Skarels if (a ^ b) {
22847e911b15Skarels
22857e911b15Skarels for ( c = 1; c < 8; c <<= 1) {
22867e911b15Skarels
22877e911b15Skarels if (!( c & (a ^ b))) /* this button change? */
22887e911b15Skarels continue;
22897e911b15Skarels
22907e911b15Skarels /* event queue full? (overflow condition) */
22917e911b15Skarels
22927e911b15Skarels if (ISFULL(eqh) == TRUE) {
22937881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd);
22947e911b15Skarels break;
22957e911b15Skarels }
22967e911b15Skarels
22977e911b15Skarels event = PUTBEGIN(eqh); /* get new event */
22987e911b15Skarels PUTEND(eqh);
22997e911b15Skarels
23007e911b15Skarels ++do_wakeup; /* request select wakeup */
23017e911b15Skarels
23027e911b15Skarels event->vse_x = eqh->curs_pos.x;
23037e911b15Skarels event->vse_y = eqh->curs_pos.y;
23047e911b15Skarels
23057e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */
23067e911b15Skarels event->vse_type = VSE_BUTTON; /* new button */
23077e911b15Skarels event->vse_time = TOY; /* time stamp */
23087e911b15Skarels
23097e911b15Skarels /* flag changed button and if up or down */
23107e911b15Skarels
23117e911b15Skarels if (c == RIGHT_BUTTON)
23127e911b15Skarels event->vse_key = VSE_RIGHT_BUTTON;
23137e911b15Skarels else if (c == MIDDLE_BUTTON)
23147e911b15Skarels event->vse_key = VSE_MIDDLE_BUTTON;
23157e911b15Skarels else if (c == LEFT_BUTTON)
23167e911b15Skarels event->vse_key = VSE_LEFT_BUTTON;
23177e911b15Skarels
23187e911b15Skarels /* set bit = button depressed */
23197e911b15Skarels
23207e911b15Skarels if (c & a)
23217e911b15Skarels event->vse_direction = VSE_KBTDOWN;
23227e911b15Skarels else
23237e911b15Skarels event->vse_direction = VSE_KBTUP;
23247e911b15Skarels }
23257e911b15Skarels }
23267e911b15Skarels
23277e911b15Skarels /* refresh last report */
23287e911b15Skarels
23297e911b15Skarels last_rep[qd] = current_rep[qd];
23307e911b15Skarels
23317e911b15Skarels } /* get last byte of report */
23327881ece5Smarc } else if ((status = duart->statusB)&RCV_RDY &&
23337e911b15Skarels qdflags[qd].pntr_id == TABLET_ID) {
23347881ece5Smarc /*
23357881ece5Smarc * pickup tablet input, if any
23367881ece5Smarc */
23377e911b15Skarels if (status&0x70) {
23387e911b15Skarels duart->cmdB = 0x40;
23397e911b15Skarels continue;
23407e911b15Skarels }
23417881ece5Smarc /*
23427881ece5Smarc * event queue full now? (overflow condition)
23437881ece5Smarc */
23447e911b15Skarels if (ISFULL(eqh) == TRUE) {
23457881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd);
23467e911b15Skarels break;
23477e911b15Skarels }
23487e911b15Skarels
23497e911b15Skarels data = duart->dataB; /* get report byte */
23507e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */
23517e911b15Skarels
2352b2b69f49Smarc /*
23537e911b15Skarels * if 1st byte of report.. */
23547e911b15Skarels
23557e911b15Skarels if (data & START_FRAME) {
23567e911b15Skarels new_rep->state = data;
23577e911b15Skarels if (new_rep->bytcnt > 1) {
23587e911b15Skarels new_rep->bytcnt = 1; /* start of new frame */
23597e911b15Skarels continue; /* ..continue looking */
23607e911b15Skarels }
23617e911b15Skarels }
23627e911b15Skarels
2363b2b69f49Smarc /*
23647e911b15Skarels * if 2nd byte of report.. */
23657e911b15Skarels
23667e911b15Skarels else if (new_rep->bytcnt == 2) {
23677e911b15Skarels new_rep->dx = data & 0x3F;
23687e911b15Skarels }
23697e911b15Skarels
2370b2b69f49Smarc /*
23717e911b15Skarels * if 3rd byte of report.. */
23727e911b15Skarels
23737e911b15Skarels else if (new_rep->bytcnt == 3) {
23747e911b15Skarels new_rep->dx |= (data & 0x3F) << 6;
23757e911b15Skarels }
23767e911b15Skarels
2377b2b69f49Smarc /*
23787e911b15Skarels * if 4th byte of report.. */
23797e911b15Skarels
23807e911b15Skarels else if (new_rep->bytcnt == 4) {
23817e911b15Skarels new_rep->dy = data & 0x3F;
23827e911b15Skarels }
23837e911b15Skarels
2384b2b69f49Smarc /*
23857e911b15Skarels * if 5th byte of report, load input event queue */
23867e911b15Skarels
23877e911b15Skarels else if (new_rep->bytcnt == 5) {
23887e911b15Skarels
23897e911b15Skarels new_rep->dy |= (data & 0x3F) << 6;
23907e911b15Skarels new_rep->bytcnt = 0;
23917e911b15Skarels
2392b2b69f49Smarc /*
23937e911b15Skarels * update cursor position coordinates */
23947e911b15Skarels
23957e911b15Skarels new_rep->dx /= qdflags[qd].tab_res;
23967e911b15Skarels new_rep->dy = (2200 - new_rep->dy)
23977e911b15Skarels / qdflags[qd].tab_res;
23987e911b15Skarels
23997e911b15Skarels if (new_rep->dx > 1023) {
24007e911b15Skarels new_rep->dx = 1023;
24017e911b15Skarels }
24027e911b15Skarels if (new_rep->dy > 863) {
24037e911b15Skarels new_rep->dy = 863;
24047e911b15Skarels }
24057e911b15Skarels
24067e911b15Skarels /*
24077e911b15Skarels * report an event if the puck/stylus has moved
24087e911b15Skarels */
24097e911b15Skarels
24107e911b15Skarels if (eqh->curs_pos.x != new_rep->dx ||
24117e911b15Skarels eqh->curs_pos.y != new_rep->dy) {
24127e911b15Skarels
24137e911b15Skarels eqh->curs_pos.x = new_rep->dx;
24147e911b15Skarels eqh->curs_pos.y = new_rep->dy;
24157e911b15Skarels
2416b2b69f49Smarc /*
24177e911b15Skarels * update cursor screen position */
24187e911b15Skarels
24197e911b15Skarels dga = (struct dga *) qdmap[qd].dga;
24207e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x);
24217e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y);
24227e911b15Skarels
24237e911b15Skarels /*
24247e911b15Skarels * if cursor is in the box, no event report
24257e911b15Skarels */
24267e911b15Skarels
24277e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right &&
24287e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left &&
24297e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top &&
24307e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) {
24317e911b15Skarels goto GET_TBUTTON;
24327e911b15Skarels }
24337e911b15Skarels
2434b2b69f49Smarc /*
24357e911b15Skarels * report the tablet motion event */
24367e911b15Skarels
24377e911b15Skarels event = PUTBEGIN(eqh);
24387e911b15Skarels PUTEND(eqh);
24397e911b15Skarels
24407e911b15Skarels ++do_wakeup; /* request a select wakeup call */
24417e911b15Skarels
24427e911b15Skarels event->vse_x = eqh->curs_pos.x;
24437e911b15Skarels event->vse_y = eqh->curs_pos.y;
24447e911b15Skarels
24457e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */
24467e911b15Skarels /*
24477e911b15Skarels * right now, X handles tablet motion the same
24487e911b15Skarels * as mouse motion
24497e911b15Skarels */
24507e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */
24517e911b15Skarels event->vse_key = 0;
24527e911b15Skarels event->vse_direction = 0;
24537e911b15Skarels event->vse_time = TOY; /* time stamp */
24547e911b15Skarels }
24557e911b15Skarels GET_TBUTTON:
2456b2b69f49Smarc /*
24577e911b15Skarels * if button state has changed */
24587e911b15Skarels
24597e911b15Skarels a = new_rep->state & 0x1E; /* mask nonbutton bits */
24607e911b15Skarels b = last_rep[qd].state & 0x1E;
24617e911b15Skarels
24627e911b15Skarels if (a ^ b) {
24637e911b15Skarels
24647e911b15Skarels /* event queue full now? (overflow condition) */
24657e911b15Skarels
24667e911b15Skarels if (ISFULL(eqh) == TRUE) {
24677881ece5Smarc printf("qd%d: qdiint: event queue overflow\n",qd);
24687e911b15Skarels break;
24697e911b15Skarels }
24707e911b15Skarels
24717e911b15Skarels event = PUTBEGIN(eqh); /* get new event */
24727e911b15Skarels PUTEND(eqh);
24737e911b15Skarels
24747e911b15Skarels ++do_wakeup; /* request a select wakeup call */
24757e911b15Skarels
24767e911b15Skarels event->vse_x = eqh->curs_pos.x;
24777e911b15Skarels event->vse_y = eqh->curs_pos.y;
24787e911b15Skarels
24797e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */
24807e911b15Skarels event->vse_type = VSE_BUTTON; /* button changed */
24817e911b15Skarels event->vse_time = TOY; /* time stamp */
24827e911b15Skarels
24837e911b15Skarels /* define the changed button and if up or down */
24847e911b15Skarels
24857e911b15Skarels for ( c = 1; c <= 0x10; c <<= 1) {
24867e911b15Skarels if (c & (a ^ b)) {
24877e911b15Skarels if (c == T_LEFT_BUTTON)
24887e911b15Skarels event->vse_key = VSE_T_LEFT_BUTTON;
24897e911b15Skarels else if (c == T_FRONT_BUTTON)
24907e911b15Skarels event->vse_key = VSE_T_FRONT_BUTTON;
24917e911b15Skarels else if (c == T_RIGHT_BUTTON)
24927e911b15Skarels event->vse_key = VSE_T_RIGHT_BUTTON;
24937e911b15Skarels else if (c == T_BACK_BUTTON)
24947e911b15Skarels event->vse_key = VSE_T_BACK_BUTTON;
24957e911b15Skarels break;
24967e911b15Skarels }
24977e911b15Skarels }
24987e911b15Skarels
24997e911b15Skarels /* set bit = button depressed */
25007e911b15Skarels
25017e911b15Skarels if (c & a)
25027e911b15Skarels event->vse_direction = VSE_KBTDOWN;
25037e911b15Skarels else
25047e911b15Skarels event->vse_direction = VSE_KBTUP;
25057e911b15Skarels }
25067e911b15Skarels
25077e911b15Skarels /* refresh last report */
25087e911b15Skarels
25097e911b15Skarels last_rep[qd] = current_rep[qd];
25107e911b15Skarels
25117e911b15Skarels } /* get last byte of report */
25127e911b15Skarels } /* pick up tablet input */
25137e911b15Skarels
25147e911b15Skarels } /* while input available.. */
25157e911b15Skarels
2516b2b69f49Smarc /*
2517b2b69f49Smarc * do select wakeup
2518b2b69f49Smarc */
25197881ece5Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
25207881ece5Smarc selwakeup(qdrsel[qd], 0);
25217881ece5Smarc qdrsel[qd] = 0;
25227e911b15Skarels qdflags[qd].selmask &= ~SEL_READ;
25237e911b15Skarels do_wakeup = 0;
25247e911b15Skarels }
25257881ece5Smarc } else {
2526b2b69f49Smarc /*
25277881ece5Smarc * if the graphic device is not turned on, this is console input
25287881ece5Smarc */
2529f79d7b48Smarc if (qdpolling)
2530f79d7b48Smarc return;
25317e911b15Skarels ui = qdinfo[qd];
25327e911b15Skarels if (ui == 0 || ui->ui_alive == 0)
25337881ece5Smarc return;
25347e911b15Skarels
25357e911b15Skarels tp = &qd_tty[qd << 2];
25367e911b15Skarels
2537b2b69f49Smarc /*
25387881ece5Smarc * Get a character from the keyboard.
25397881ece5Smarc */
25407881ece5Smarc while (duart->statusA&RCV_RDY) {
25417e911b15Skarels key = duart->dataA;
25427e911b15Skarels key &= 0xFF;
2543b2b69f49Smarc /*
25447881ece5Smarc * Check for various keyboard errors
25457881ece5Smarc */
25467e911b15Skarels if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
25477e911b15Skarels key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
25487881ece5Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
25497881ece5Smarc return;
25507e911b15Skarels }
25517e911b15Skarels
25527e911b15Skarels if (key < LK_LOWEST)
25537881ece5Smarc return;
25547e911b15Skarels
2555b2b69f49Smarc /*
25567e911b15Skarels * See if its a state change key */
25577e911b15Skarels
25587e911b15Skarels switch (key) {
25597e911b15Skarels
25607e911b15Skarels case LOCK:
25617e911b15Skarels q_keyboard.lock ^= 0xffff; /* toggle */
25627e911b15Skarels if (q_keyboard.lock)
25637881ece5Smarc (void)led_control(qd, LK_LED_ENABLE,
25647881ece5Smarc LK_LED_LOCK);
25657e911b15Skarels else
25667881ece5Smarc (void)led_control(qd, LK_LED_DISABLE,
25677881ece5Smarc LK_LED_LOCK);
25687e911b15Skarels return;
25697e911b15Skarels
25707e911b15Skarels case SHIFT:
25717e911b15Skarels q_keyboard.shift ^= 0xFFFF;
25727e911b15Skarels return;
25737e911b15Skarels
25747e911b15Skarels case CNTRL:
25757e911b15Skarels q_keyboard.cntrl ^= 0xFFFF;
25767e911b15Skarels return;
25777e911b15Skarels
25787e911b15Skarels case ALLUP:
25797e911b15Skarels q_keyboard.cntrl = 0;
25807e911b15Skarels q_keyboard.shift = 0;
25817e911b15Skarels return;
25827e911b15Skarels
25837e911b15Skarels case REPEAT:
25847e911b15Skarels chr = q_keyboard.last;
25857e911b15Skarels break;
25867e911b15Skarels
2587b2b69f49Smarc /*
25887e911b15Skarels * Test for cntrl characters. If set, see if the character
25897e911b15Skarels * is elligible to become a control character. */
25907e911b15Skarels
25917e911b15Skarels default:
25927e911b15Skarels
25937e911b15Skarels if (q_keyboard.cntrl) {
25947e911b15Skarels chr = q_key[key];
25957e911b15Skarels if (chr >= ' ' && chr <= '~')
25967e911b15Skarels chr &= 0x1F;
2597e977faadSmarc else if (chr >= 0xA1 && chr <= 0xFE)
2598e977faadSmarc chr &= 0x9F;
25997e911b15Skarels }
26007e911b15Skarels else if( q_keyboard.lock || q_keyboard.shift )
26017e911b15Skarels chr = q_shift_key[key];
26027e911b15Skarels else
26037e911b15Skarels chr = q_key[key];
26047e911b15Skarels break;
26057e911b15Skarels }
26067e911b15Skarels
26077e911b15Skarels q_keyboard.last = chr;
26087e911b15Skarels
2609b2b69f49Smarc /*
26107e911b15Skarels * Check for special function keys */
26117e911b15Skarels
2612e977faadSmarc if (chr & 0x100) {
26137e911b15Skarels char *string;
26147e911b15Skarels string = q_special[chr & 0x7F];
26157e911b15Skarels while(*string)
26167e911b15Skarels (*linesw[tp->t_line].l_rint)(*string++, tp);
26177e911b15Skarels }
26187e911b15Skarels else {
2619f79d7b48Smarc #ifdef KADB
2620f79d7b48Smarc if (!kdbrintr(chr&0177, tp))
2621f79d7b48Smarc #endif
2622b2b69f49Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp);
26237e911b15Skarels }
26247e911b15Skarels }
26257e911b15Skarels }
26267e911b15Skarels } /* qdiint */
26277e911b15Skarels
26287881ece5Smarc /*
26297e911b15Skarels *
26307881ece5Smarc * Clear the QDSS screen
26317e911b15Skarels *
26327e911b15Skarels * >>> NOTE <<<
26337e911b15Skarels *
26347e911b15Skarels * This code requires that certain adder initialization be valid. To
26357e911b15Skarels * assure that this requirement is satisfied, this routine should be
26367e911b15Skarels * called only after calling the "setup_dragon()" function.
26377e911b15Skarels *
26387e911b15Skarels * Clear the bitmap a piece at a time. Since the fast scroll clear
26397e911b15Skarels * only clears the current displayed portion of the bitmap put a
26407e911b15Skarels * temporary value in the y limit register so we can access whole
26417e911b15Skarels * bitmap
26427e911b15Skarels *
26437881ece5Smarc */
clear_qd_screen(unit)26447e911b15Skarels clear_qd_screen(unit)
26457e911b15Skarels int unit;
26467e911b15Skarels {
26477e911b15Skarels register struct adder *adder;
26487e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
26497e911b15Skarels
26507e911b15Skarels adder->x_limit = 1024;
26517e911b15Skarels adder->y_limit = 2048 - CHAR_HEIGHT;
26527e911b15Skarels adder->y_offset_pending = 0;
26537881ece5Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
2654b2b69f49Smarc WSV;
26557e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE;
2656b2b69f49Smarc WSV;
26577e911b15Skarels adder->y_offset_pending = 864;
2658b2b69f49Smarc WSV;
26597e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE;
2660b2b69f49Smarc WSV;
26617e911b15Skarels adder->y_offset_pending = 1728;
2662b2b69f49Smarc WSV;
26637e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE;
2664b2b69f49Smarc WSV;
26657e911b15Skarels adder->y_offset_pending = 0; /* back to normal */
2666b2b69f49Smarc WSV;
26677e911b15Skarels adder->x_limit = MAX_SCREEN_X;
26687e911b15Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2669b2b69f49Smarc #undef WSV
26707e911b15Skarels
26717e911b15Skarels } /* clear_qd_screen */
26727e911b15Skarels
26737881ece5Smarc /*
26747881ece5Smarc * kernel console output to the glass tty
26757881ece5Smarc */
qdputc(chr)26767e911b15Skarels qdputc(chr)
26777e911b15Skarels register char chr;
26787e911b15Skarels {
26797e911b15Skarels
2680b2b69f49Smarc /*
2681b2b69f49Smarc * if system is now physical, forget it (ie: crash DUMP)
2682b2b69f49Smarc */
26837e911b15Skarels if ((mfpr(MAPEN) & 1) == 0)
26847e911b15Skarels return;
26857e911b15Skarels
26867881ece5Smarc blitc(0, (u_char)(chr & 0xff));
268724f67f6bSmarc if ((chr & 0177) == '\n')
268824f67f6bSmarc blitc(0, '\r');
268924f67f6bSmarc
26907e911b15Skarels } /* qdputc */
26917e911b15Skarels
2692b2b69f49Smarc /*
26937881ece5Smarc * load the mouse cursor's template RAM bitmap
26947881ece5Smarc */
ldcursor(unit,bitmap)26957e911b15Skarels ldcursor(unit, bitmap)
26967881ece5Smarc int unit;
26977881ece5Smarc register short *bitmap;
26987e911b15Skarels {
26997e911b15Skarels register struct dga *dga;
27007e911b15Skarels register short *temp;
27017e911b15Skarels register int i;
27027881ece5Smarc int curs;
27037e911b15Skarels
27047e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
27057e911b15Skarels temp = (short *) qdmap[unit].template;
27067e911b15Skarels
27077e911b15Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */
27087881ece5Smarc curs = -1; /* ..note that.. */
27097e911b15Skarels dga->csr &= ~CURS_ENB; /* ..and shut it off */
27107881ece5Smarc } else
27117881ece5Smarc curs = 0;
27127e911b15Skarels
27137e911b15Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */
27147e911b15Skarels
27157e911b15Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */
27167e911b15Skarels /* ..of the 8k WORD template space */
27177e911b15Skarels for (i = 0; i < 32; ++i)
27187e911b15Skarels *temp++ = *bitmap++;
27197e911b15Skarels
27207881ece5Smarc if (curs) { /* if cursor was enabled.. */
27217e911b15Skarels dga->csr |= CURS_ENB; /* ..turn it back on */
27227e911b15Skarels }
27237e911b15Skarels
27247e911b15Skarels } /* ldcursor */
27257e911b15Skarels
27267881ece5Smarc /*
27277881ece5Smarc * Put the console font in the QDSS off-screen memory
27287881ece5Smarc */
ldfont(unit)27297e911b15Skarels ldfont(unit)
27307881ece5Smarc int unit;
27317e911b15Skarels {
27327e911b15Skarels register struct adder *adder;
27337e911b15Skarels
27347881ece5Smarc register i, j, k, max_chars_line;
27357881ece5Smarc register short packed;
27367e911b15Skarels
27377e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
27387e911b15Skarels
2739b2b69f49Smarc /*
27407881ece5Smarc * setup VIPER operand control registers
27417881ece5Smarc */
27427e911b15Skarels write_ID(adder, MASK_1, 0xFFFF);
27437e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
27447e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
27457e911b15Skarels
27467e911b15Skarels write_ID(adder, SRC1_OCR_B,
27477e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27487e911b15Skarels write_ID(adder, SRC2_OCR_B,
27497e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27507e911b15Skarels write_ID(adder, DST_OCR_B,
27517e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
27527e911b15Skarels
27537e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
27547e911b15Skarels
2755b2b69f49Smarc /*
27567881ece5Smarc * load destination data
27577881ece5Smarc */
27587881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE);
27597e911b15Skarels
27607e911b15Skarels adder->destination_x = FONT_X;
27617e911b15Skarels adder->destination_y = FONT_Y;
27627881ece5Smarc #if FONT_WIDTH > MAX_SCREEN_X
2763e977faadSmarc adder->fast_dest_dx = MAX_SCREEN_X;
27647881ece5Smarc #else
27657e911b15Skarels adder->fast_dest_dx = FONT_WIDTH;
27667881ece5Smarc #endif
27677e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT;
27687e911b15Skarels
2769b2b69f49Smarc /*
27707e911b15Skarels * setup for processor to bitmap xfer */
27717e911b15Skarels
27727e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001);
27737e911b15Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2;
27747e911b15Skarels
2775b2b69f49Smarc /*
2776b2b69f49Smarc * Figure out how many characters can be stored on one "line" of
2777b2b69f49Smarc * offscreen memory.
2778e977faadSmarc */
2779e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2780e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line)
2781e977faadSmarc max_chars_line = CHARS/2 + CHARS%2;
2782e977faadSmarc
2783b2b69f49Smarc /*
2784e977faadSmarc * iteratively do the processor to bitmap xfer */
2785e977faadSmarc
2786e977faadSmarc for (i = 0; i < ROWS; ++i) {
2787e977faadSmarc
2788e977faadSmarc /* PTOB a scan line */
2789e977faadSmarc
2790e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) {
2791e977faadSmarc /* PTOB one scan of a char cell */
2792e977faadSmarc
2793e977faadSmarc packed = q_font[k];
2794e977faadSmarc k += ROWS;
2795e977faadSmarc packed |= ((short)q_font[k] << 8);
2796e977faadSmarc k += ROWS;
2797e977faadSmarc
27987881ece5Smarc (void)wait_status(adder, TX_READY);
2799e977faadSmarc adder->id_data = packed;
2800e977faadSmarc }
2801e977faadSmarc }
2802e977faadSmarc
2803b2b69f49Smarc /*
2804b2b69f49Smarc * (XXX XXX XXX - should remove)
2805b2b69f49Smarc *
2806b2b69f49Smarc * Copy the second row of characters. Subtract the first
2807b2b69f49Smarc * row from the total number. Divide this quantity by 2
2808b2b69f49Smarc * because 2 chars are stored in a short in the PTOB loop
2809b2b69f49Smarc * below. Figure out how many characters can be stored on
2810b2b69f49Smarc * one "line" of offscreen memory
2811e977faadSmarc */
2812b2b69f49Smarc
2813e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2814e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line)
2815e977faadSmarc return;
2816e977faadSmarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
2817e977faadSmarc /* Paranoia check to see if 3rd row may be needed */
2818e977faadSmarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
2819e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2820e977faadSmarc
2821e977faadSmarc adder->destination_x = FONT_X;
2822e977faadSmarc adder->destination_y = FONT_Y - CHAR_HEIGHT;
2823e977faadSmarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
2824e977faadSmarc adder->slow_dest_dy = CHAR_HEIGHT;
2825e977faadSmarc
2826b2b69f49Smarc /*
2827b2b69f49Smarc * setup for processor to bitmap xfer
2828b2b69f49Smarc */
2829e977faadSmarc write_ID(adder, CS_UPDATE_MASK, 0x0001);
2830e977faadSmarc adder->cmd = PBT | OCRB | 2 | DTE | 2;
2831e977faadSmarc
2832b2b69f49Smarc /*
2833b2b69f49Smarc * iteratively do the processor to bitmap xfer
2834b2b69f49Smarc */
28357e911b15Skarels for (i = 0; i < ROWS; ++i) {
2836b2b69f49Smarc /*
2837b2b69f49Smarc * PTOB a scan line
2838b2b69f49Smarc */
2839e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) {
2840b2b69f49Smarc /*
2841b2b69f49Smarc * PTOB one scan of a char cell
2842b2b69f49Smarc */
2843e977faadSmarc packed = q_font[k + FONT_OFFSET];
28447e911b15Skarels k += ROWS;
2845e977faadSmarc packed |= ((short)q_font[k + FONT_OFFSET] << 8);
28467e911b15Skarels k += ROWS;
28477881ece5Smarc (void)wait_status(adder, TX_READY);
28487e911b15Skarels adder->id_data = packed;
28497e911b15Skarels }
28507e911b15Skarels }
28517e911b15Skarels
28527e911b15Skarels } /* ldfont */
28537e911b15Skarels
qdpoll(onoff)2854f79d7b48Smarc qdpoll(onoff)
2855f79d7b48Smarc {
2856f79d7b48Smarc qdpolling = onoff;
2857f79d7b48Smarc }
2858f79d7b48Smarc
28597881ece5Smarc /*
28607881ece5Smarc * Get a character from the LK201 (polled)
28617881ece5Smarc */
qdgetc()28627881ece5Smarc qdgetc()
28637e911b15Skarels {
28647881ece5Smarc register short key;
28657881ece5Smarc register char chr;
28667881ece5Smarc register struct duart *duart;
28677881ece5Smarc
28687881ece5Smarc duart = (struct duart *) qdmap[0].duart;
28697881ece5Smarc
28707881ece5Smarc /*
28717881ece5Smarc * Get a character from the keyboard.
28727881ece5Smarc */
28737881ece5Smarc LOOP:
28747881ece5Smarc while (!(duart->statusA&RCV_RDY))
28757881ece5Smarc ;
28767881ece5Smarc
28777881ece5Smarc key = duart->dataA;
28787881ece5Smarc key &= 0xFF;
28797881ece5Smarc
28807881ece5Smarc /*
28817881ece5Smarc * Check for various keyboard errors */
28827881ece5Smarc
28837881ece5Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
28847881ece5Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
28857881ece5Smarc printf("Keyboard error, code = %x\n", key);
28867881ece5Smarc return(0);
28877881ece5Smarc }
28887881ece5Smarc
28897881ece5Smarc if (key < LK_LOWEST)
28907881ece5Smarc return(0);
28917881ece5Smarc
28927881ece5Smarc /*
28937881ece5Smarc * See if its a state change key
28947881ece5Smarc */
28957881ece5Smarc switch (key) {
28967881ece5Smarc
28977881ece5Smarc case LOCK:
28987881ece5Smarc q_keyboard.lock ^= 0xffff; /* toggle */
28997881ece5Smarc if (q_keyboard.lock)
29007881ece5Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
29017881ece5Smarc else
29027881ece5Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
29037881ece5Smarc goto LOOP;
29047881ece5Smarc
29057881ece5Smarc case SHIFT:
29067881ece5Smarc q_keyboard.shift ^= 0xFFFF;
29077881ece5Smarc goto LOOP;
29087881ece5Smarc
29097881ece5Smarc case CNTRL:
29107881ece5Smarc q_keyboard.cntrl ^= 0xFFFF;
29117881ece5Smarc goto LOOP;
29127881ece5Smarc
29137881ece5Smarc case ALLUP:
29147881ece5Smarc q_keyboard.cntrl = 0;
29157881ece5Smarc q_keyboard.shift = 0;
29167881ece5Smarc goto LOOP;
29177881ece5Smarc
29187881ece5Smarc case REPEAT:
29197881ece5Smarc chr = q_keyboard.last;
29207881ece5Smarc break;
29217881ece5Smarc
29227881ece5Smarc /*
29237881ece5Smarc * Test for cntrl characters. If set, see if the character
29247881ece5Smarc * is elligible to become a control character.
29257881ece5Smarc */
29267881ece5Smarc default:
29277881ece5Smarc
29287881ece5Smarc if (q_keyboard.cntrl) {
29297881ece5Smarc chr = q_key[key];
29307881ece5Smarc if (chr >= ' ' && chr <= '~')
29317881ece5Smarc chr &= 0x1F;
29327881ece5Smarc }
29337881ece5Smarc else if ( q_keyboard.lock || q_keyboard.shift )
29347881ece5Smarc chr = q_shift_key[key];
29357881ece5Smarc else
29367881ece5Smarc chr = q_key[key];
29377881ece5Smarc break;
29387881ece5Smarc }
29397881ece5Smarc
29407881ece5Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */
29417881ece5Smarc return(0); /* ..then pitch it! */
29427881ece5Smarc
29437881ece5Smarc q_keyboard.last = chr;
29447881ece5Smarc
29457881ece5Smarc /*
29467881ece5Smarc * Check for special function keys */
29477881ece5Smarc
29487881ece5Smarc if (chr & 0x80) /* pitch the function keys */
29497881ece5Smarc return(0);
29507881ece5Smarc else
29517881ece5Smarc return(chr);
29527881ece5Smarc
29537881ece5Smarc } /* qdgetc */
29547881ece5Smarc
29557881ece5Smarc /*
29567881ece5Smarc * led_control()... twiddle LK-201 LED's
29577881ece5Smarc */
led_control(unit,cmd,led_mask)29587881ece5Smarc led_control(unit, cmd, led_mask)
29597881ece5Smarc int unit, cmd, led_mask;
29607881ece5Smarc {
29617881ece5Smarc register i;
29627e911b15Skarels register struct duart *duart;
29637e911b15Skarels
29647e911b15Skarels duart = (struct duart *)qdmap[unit].duart;
29657e911b15Skarels
29667e911b15Skarels for (i = 1000; i > 0; --i) {
29677881ece5Smarc if (duart->statusA&XMT_RDY) {
29687e911b15Skarels duart->dataA = cmd;
29697e911b15Skarels break;
29707e911b15Skarels }
29717e911b15Skarels }
29727e911b15Skarels for (i = 1000; i > 0; --i) {
29737881ece5Smarc if (duart->statusA&XMT_RDY) {
29747e911b15Skarels duart->dataA = led_mask;
29757e911b15Skarels break;
29767e911b15Skarels }
29777e911b15Skarels }
29787e911b15Skarels if (i == 0)
29797e911b15Skarels return(BAD);
29807e911b15Skarels return(GOOD);
29817e911b15Skarels
29827e911b15Skarels } /* led_control */
29837e911b15Skarels
29847881ece5Smarc /*
29857e911b15Skarels * scroll_up()... move the screen up one character height
29867881ece5Smarc */
scroll_up(adder)29877e911b15Skarels scroll_up(adder)
29887e911b15Skarels register struct adder *adder;
29897e911b15Skarels {
2990b2b69f49Smarc /*
2991b2b69f49Smarc * setup VIPER operand control registers
2992b2b69f49Smarc */
29937881ece5Smarc (void)wait_status(adder, ADDRESS_COMPLETE);
29947e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
29957e911b15Skarels write_ID(adder, MASK_1, 0xFFFF);
29967e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
29977e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
29987e911b15Skarels write_ID(adder, SRC1_OCR_B,
29997e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
30007e911b15Skarels write_ID(adder, DST_OCR_B,
30017e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3002b2b69f49Smarc /*
3003b2b69f49Smarc * load DESTINATION origin and vectors
3004b2b69f49Smarc */
30057e911b15Skarels adder->fast_dest_dy = 0;
30067e911b15Skarels adder->slow_dest_dx = 0;
30077e911b15Skarels adder->error_1 = 0;
30087e911b15Skarels adder->error_2 = 0;
30097e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
30107e911b15Skarels adder->destination_x = 0;
30117e911b15Skarels adder->fast_dest_dx = 1024;
30127e911b15Skarels adder->destination_y = 0;
30137e911b15Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3014b2b69f49Smarc /*
3015b2b69f49Smarc * load SOURCE origin and vectors
3016b2b69f49Smarc */
30177e911b15Skarels adder->source_1_x = 0;
30187e911b15Skarels adder->source_1_dx = 1024;
30197e911b15Skarels adder->source_1_y = 0 + CHAR_HEIGHT;
30207e911b15Skarels adder->source_1_dy = 864 - CHAR_HEIGHT;
30217e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
30227e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3023b2b69f49Smarc /*
3024b2b69f49Smarc * do a rectangle clear of last screen line
3025b2b69f49Smarc */
30267e911b15Skarels write_ID(adder, MASK_1, 0xffff);
30277e911b15Skarels write_ID(adder, SOURCE, 0xffff);
30287e911b15Skarels write_ID(adder,DST_OCR_B,
30297e911b15Skarels (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
30307e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
30317e911b15Skarels adder->error_1 = 0;
30327e911b15Skarels adder->error_2 = 0;
30337e911b15Skarels adder->slow_dest_dx = 0; /* set up the width of */
30347e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */
30357e911b15Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
30367881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE);
30377e911b15Skarels adder->destination_x = 0;
30387e911b15Skarels adder->destination_y = 864 - CHAR_HEIGHT;
30397e911b15Skarels adder->fast_dest_dx = 1024; /* set up the height */
30407e911b15Skarels adder->fast_dest_dy = 0; /* of rectangle */
30417e911b15Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
30427e911b15Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
30437e911b15Skarels
30447e911b15Skarels } /* scroll_up */
30457e911b15Skarels
30467881ece5Smarc /*
30477881ece5Smarc * init shared memory pointers and structures
30487881ece5Smarc */
init_shared(unit)30497e911b15Skarels init_shared(unit)
30507881ece5Smarc register unit;
30517e911b15Skarels {
30527e911b15Skarels register struct dga *dga;
30537e911b15Skarels
30547e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
30557e911b15Skarels
3056b2b69f49Smarc /*
30577e911b15Skarels * initialize the event queue pointers and header */
30587e911b15Skarels
30597e911b15Skarels eq_header[unit] = (struct qdinput *)
30607e911b15Skarels ((((int)event_shared & ~(0x01FF)) + 512)
30617e911b15Skarels + (EVENT_BUFSIZE * unit));
30627e911b15Skarels eq_header[unit]->curs_pos.x = 0;
30637e911b15Skarels eq_header[unit]->curs_pos.y = 0;
30647e911b15Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
30657e911b15Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
30667e911b15Skarels eq_header[unit]->curs_box.left = 0;
30677e911b15Skarels eq_header[unit]->curs_box.right = 0;
30687e911b15Skarels eq_header[unit]->curs_box.top = 0;
30697e911b15Skarels eq_header[unit]->curs_box.bottom = 0;
3070b2b69f49Smarc /*
3071b2b69f49Smarc * assign a pointer to the DMA I/O buffer for this QDSS.
3072b2b69f49Smarc */
30737e911b15Skarels DMAheader[unit] = (struct DMAreq_header *)
30747e911b15Skarels (((int)(&DMA_shared[0] + 512) & ~0x1FF)
30757e911b15Skarels + (DMAbuf_size * unit));
30767e911b15Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
30777e911b15Skarels + sizeof(struct DMAreq_header));
30787e911b15Skarels DMAheader[unit]->QBAreg = 0;
30797e911b15Skarels DMAheader[unit]->status = 0;
30807e911b15Skarels DMAheader[unit]->shared_size = DMAbuf_size;
30817e911b15Skarels DMAheader[unit]->used = 0;
30827e911b15Skarels DMAheader[unit]->size = 10; /* default = 10 requests */
30837e911b15Skarels DMAheader[unit]->oldest = 0;
30847e911b15Skarels DMAheader[unit]->newest = 0;
3085b2b69f49Smarc /*
3086b2b69f49Smarc * assign a pointer to the scroll structure for this QDSS.
3087b2b69f49Smarc */
30887e911b15Skarels scroll[unit] = (struct scroll *)
30897e911b15Skarels (((int)(&scroll_shared[0] + 512) & ~0x1FF)
30907e911b15Skarels + (sizeof(struct scroll) * unit));
30917e911b15Skarels scroll[unit]->status = 0;
30927e911b15Skarels scroll[unit]->viper_constant = 0;
30937e911b15Skarels scroll[unit]->y_scroll_constant = 0;
30947e911b15Skarels scroll[unit]->y_offset = 0;
30957e911b15Skarels scroll[unit]->x_index_pending = 0;
30967e911b15Skarels scroll[unit]->y_index_pending = 0;
3097b2b69f49Smarc /*
3098b2b69f49Smarc * assign a pointer to the color map write buffer for this QDSS
3099b2b69f49Smarc */
31007e911b15Skarels color_buf[unit] = (struct color_buf *)
31017e911b15Skarels (((int)(&color_shared[0] + 512) & ~0x1FF)
31027e911b15Skarels + (COLOR_BUFSIZ * unit));
31037e911b15Skarels color_buf[unit]->status = 0;
31047e911b15Skarels color_buf[unit]->count = 0;
31057e911b15Skarels
31067e911b15Skarels } /* init_shared */
31077e911b15Skarels
31087881ece5Smarc /*
31097881ece5Smarc * init the ADDER, VIPER, bitmaps, & color map
31107881ece5Smarc */
setup_dragon(unit)31117e911b15Skarels setup_dragon(unit)
31127881ece5Smarc int unit;
31137e911b15Skarels {
31147e911b15Skarels
31157e911b15Skarels register struct adder *adder;
31167e911b15Skarels register struct dga *dga;
31177e911b15Skarels short *memcsr;
31187881ece5Smarc register i;
31197e911b15Skarels short top; /* clipping/scrolling boundaries */
31207e911b15Skarels short bottom;
31217e911b15Skarels short right;
31227e911b15Skarels short left;
31237e911b15Skarels short *red; /* color map pointers */
31247e911b15Skarels short *green;
31257e911b15Skarels short *blue;
31267e911b15Skarels
3127b2b69f49Smarc /*
3128b2b69f49Smarc * init for setup
3129b2b69f49Smarc */
31307e911b15Skarels adder = (struct adder *) qdmap[unit].adder;
31317e911b15Skarels dga = (struct dga *) qdmap[unit].dga;
31327e911b15Skarels memcsr = (short *) qdmap[unit].memcsr;
31337e911b15Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */
31347e911b15Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */
31357e911b15Skarels adder->command = CANCEL;
3136b2b69f49Smarc /*
3137b2b69f49Smarc * set monitor timing
3138b2b69f49Smarc */
31397e911b15Skarels adder->x_scan_count_0 = 0x2800;
31407e911b15Skarels adder->x_scan_count_1 = 0x1020;
31417e911b15Skarels adder->x_scan_count_2 = 0x003A;
31427e911b15Skarels adder->x_scan_count_3 = 0x38F0;
31437e911b15Skarels adder->x_scan_count_4 = 0x6128;
31447e911b15Skarels adder->x_scan_count_5 = 0x093A;
31457e911b15Skarels adder->x_scan_count_6 = 0x313C;
31467e911b15Skarels adder->sync_phase_adj = 0x0100;
31477e911b15Skarels adder->x_scan_conf = 0x00C8;
3148b2b69f49Smarc /*
3149b2b69f49Smarc * got a bug in secound pass ADDER! lets take care of it
3150b2b69f49Smarc *
3151b2b69f49Smarc * normally, just use the code in the following bug fix code, but to
31527e911b15Skarels * make repeated demos look pretty, load the registers as if there was
3153b2b69f49Smarc * no bug and then test to see if we are getting sync
3154b2b69f49Smarc */
31557e911b15Skarels adder->y_scan_count_0 = 0x135F;
31567e911b15Skarels adder->y_scan_count_1 = 0x3363;
31577e911b15Skarels adder->y_scan_count_2 = 0x2366;
31587e911b15Skarels adder->y_scan_count_3 = 0x0388;
3159b2b69f49Smarc /*
3160b2b69f49Smarc * if no sync, do the bug fix code
3161b2b69f49Smarc */
31627e911b15Skarels if (wait_status(adder, VSYNC) == BAD) {
31637e911b15Skarels /* first load all Y scan registers with very short frame and
31647e911b15Skarels * wait for scroll service. This guarantees at least one SYNC
31657e911b15Skarels * to fix the pass 2 Adder initialization bug (synchronizes
3166b2b69f49Smarc * XCINCH with DMSEEDH)
3167b2b69f49Smarc */
31687e911b15Skarels adder->y_scan_count_0 = 0x01;
31697e911b15Skarels adder->y_scan_count_1 = 0x01;
31707e911b15Skarels adder->y_scan_count_2 = 0x01;
31717e911b15Skarels adder->y_scan_count_3 = 0x01;
3172b2b69f49Smarc /*
3173b2b69f49Smarc * delay at least 1 full frame time
3174b2b69f49Smarc */
31757881ece5Smarc (void)wait_status(adder, VSYNC);
31767881ece5Smarc (void)wait_status(adder, VSYNC);
3177b2b69f49Smarc /*
3178b2b69f49Smarc * now load the REAL sync values (in reverse order just to
3179b2b69f49Smarc * be safe.
3180b2b69f49Smarc */
31817e911b15Skarels adder->y_scan_count_3 = 0x0388;
31827e911b15Skarels adder->y_scan_count_2 = 0x2366;
31837e911b15Skarels adder->y_scan_count_1 = 0x3363;
31847e911b15Skarels adder->y_scan_count_0 = 0x135F;
31857e911b15Skarels }
31867e911b15Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */
3187b2b69f49Smarc /*
3188b2b69f49Smarc * zero the index registers
3189b2b69f49Smarc */
31907e911b15Skarels adder->x_index_pending = 0;
31917e911b15Skarels adder->y_index_pending = 0;
31927e911b15Skarels adder->x_index_new = 0;
31937e911b15Skarels adder->y_index_new = 0;
31947e911b15Skarels adder->x_index_old = 0;
31957e911b15Skarels adder->y_index_old = 0;
31967e911b15Skarels adder->pause = 0;
3197b2b69f49Smarc /*
3198b2b69f49Smarc * set rasterop mode to normal pen down
3199b2b69f49Smarc */
32007e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3201b2b69f49Smarc /*
3202b2b69f49Smarc * set the rasterop registers to a default values
3203b2b69f49Smarc */
32047e911b15Skarels adder->source_1_dx = 1;
32057e911b15Skarels adder->source_1_dy = 1;
32067e911b15Skarels adder->source_1_x = 0;
32077e911b15Skarels adder->source_1_y = 0;
32087e911b15Skarels adder->destination_x = 0;
32097e911b15Skarels adder->destination_y = 0;
32107e911b15Skarels adder->fast_dest_dx = 1;
32117e911b15Skarels adder->fast_dest_dy = 0;
32127e911b15Skarels adder->slow_dest_dx = 0;
32137e911b15Skarels adder->slow_dest_dy = 1;
32147e911b15Skarels adder->error_1 = 0;
32157e911b15Skarels adder->error_2 = 0;
3216b2b69f49Smarc /*
32177881ece5Smarc * scale factor = UNITY
3218b2b69f49Smarc */
32197e911b15Skarels adder->fast_scale = UNITY;
32207e911b15Skarels adder->slow_scale = UNITY;
3221b2b69f49Smarc /*
3222b2b69f49Smarc * set the source 2 parameters
3223b2b69f49Smarc */
32247e911b15Skarels adder->source_2_x = 0;
32257e911b15Skarels adder->source_2_y = 0;
32267e911b15Skarels adder->source_2_size = 0x0022;
3227b2b69f49Smarc /*
3228b2b69f49Smarc * initialize plane addresses for eight vipers
3229b2b69f49Smarc */
32307e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001);
32317e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0000);
32327e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002);
32337e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0001);
32347e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004);
32357e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0002);
32367e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008);
32377e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0003);
32387e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010);
32397e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0004);
32407e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020);
32417e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0005);
32427e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040);
32437e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0006);
32447e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080);
32457e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0007);
3246b2b69f49Smarc /*
3247b2b69f49Smarc * initialize the external registers.
3248b2b69f49Smarc */
32497e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF);
32507e911b15Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3251b2b69f49Smarc /*
3252b2b69f49Smarc * initialize resolution mode
3253b2b69f49Smarc */
32547e911b15Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */
32557e911b15Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */
3256b2b69f49Smarc /*
3257b2b69f49Smarc * initialize viper registers
3258b2b69f49Smarc */
32597e911b15Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
32607e911b15Skarels write_ID(adder, SCROLL_FILL, 0x0000);
3261b2b69f49Smarc /*
3262b2b69f49Smarc * set clipping and scrolling limits to full screen
3263b2b69f49Smarc */
3264b2b69f49Smarc for (i = 1000, adder->status = 0;
32657881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
3266b2b69f49Smarc ;
32677e911b15Skarels if (i == 0)
32687881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
32697e911b15Skarels top = 0;
32707e911b15Skarels bottom = 2048;
32717e911b15Skarels left = 0;
32727e911b15Skarels right = 1024;
32737e911b15Skarels adder->x_clip_min = left;
32747e911b15Skarels adder->x_clip_max = right;
32757e911b15Skarels adder->y_clip_min = top;
32767e911b15Skarels adder->y_clip_max = bottom;
32777e911b15Skarels adder->scroll_x_min = left;
32787e911b15Skarels adder->scroll_x_max = right;
32797e911b15Skarels adder->scroll_y_min = top;
32807e911b15Skarels adder->scroll_y_max = bottom;
32817881ece5Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */
32827881ece5Smarc (void)wait_status(adder, VSYNC);
32837e911b15Skarels adder->x_index_pending = left;
32847e911b15Skarels adder->y_index_pending = top;
32857e911b15Skarels adder->x_index_new = left;
32867e911b15Skarels adder->y_index_new = top;
32877e911b15Skarels adder->x_index_old = left;
32887e911b15Skarels adder->y_index_old = top;
32897e911b15Skarels
32907881ece5Smarc for (i = 1000, adder->status = 0; i > 0 &&
32917881ece5Smarc !(adder->status&ADDRESS_COMPLETE) ; --i)
3292b2b69f49Smarc ;
32937e911b15Skarels if (i == 0)
32947881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
32957e911b15Skarels
32967e911b15Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
32977e911b15Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3298b2b69f49Smarc /*
3299b2b69f49Smarc * set source and the mask register to all ones (ie: white) o
3300b2b69f49Smarc */
33017e911b15Skarels write_ID(adder, SOURCE, 0xFFFF);
33027e911b15Skarels write_ID(adder, MASK_1, 0xFFFF);
33037e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
33047e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3305b2b69f49Smarc /*
3306b2b69f49Smarc * initialize Operand Control Register banks for fill command
3307b2b69f49Smarc */
33087e911b15Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT);
33097e911b15Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
33107e911b15Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
33117e911b15Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
33127e911b15Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT);
33137e911b15Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3314b2b69f49Smarc /*
33157e911b15Skarels * init Logic Unit Function registers, (these are just common values,
3316b2b69f49Smarc * and may be changed as required).
3317b2b69f49Smarc */
33187e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3319b2b69f49Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
3320b2b69f49Smarc INV_M1_M2);
33217e911b15Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
33227e911b15Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3323b2b69f49Smarc /*
3324b2b69f49Smarc * load the color map for black & white
3325b2b69f49Smarc */
33267881ece5Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
3327b2b69f49Smarc ;
33287e911b15Skarels
33297e911b15Skarels if (i == 0)
33307881ece5Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
33317e911b15Skarels
33327e911b15Skarels red = (short *) qdmap[unit].red;
33337e911b15Skarels green = (short *) qdmap[unit].green;
33347e911b15Skarels blue = (short *) qdmap[unit].blue;
33357e911b15Skarels
33367e911b15Skarels *red++ = 0x00; /* black */
33377e911b15Skarels *green++ = 0x00;
33387e911b15Skarels *blue++ = 0x00;
33397e911b15Skarels
33407e911b15Skarels *red-- = 0xFF; /* white */
33417e911b15Skarels *green-- = 0xFF;
33427e911b15Skarels *blue-- = 0xFF;
33437e911b15Skarels
3344b2b69f49Smarc /*
33457881ece5Smarc * set color map for mouse cursor
33467881ece5Smarc */
33477e911b15Skarels
33487e911b15Skarels red += 254;
33497e911b15Skarels green += 254;
33507e911b15Skarels blue += 254;
33517e911b15Skarels
33527e911b15Skarels *red++ = 0x00; /* black */
33537e911b15Skarels *green++ = 0x00;
33547e911b15Skarels *blue++ = 0x00;
33557e911b15Skarels
33567e911b15Skarels *red = 0xFF; /* white */
33577e911b15Skarels *green = 0xFF;
33587e911b15Skarels *blue = 0xFF;
33597e911b15Skarels
33607e911b15Skarels } /* setup_dragon */
33617e911b15Skarels
33627881ece5Smarc /*
33637881ece5Smarc * Init the DUART and set defaults in input
33647881ece5Smarc */
setup_input(unit)33657e911b15Skarels setup_input(unit)
33667881ece5Smarc int unit;
33677e911b15Skarels {
33687e911b15Skarels register struct duart *duart; /* DUART register structure pointer */
33697881ece5Smarc register i, bits;
33707e911b15Skarels char id_byte;
33717e911b15Skarels
33727e911b15Skarels duart = (struct duart *) qdmap[unit].duart;
33737e911b15Skarels duart->imask = 0;
33747e911b15Skarels
3375b2b69f49Smarc /*
3376b2b69f49Smarc * setup the DUART for kbd & pointing device
3377b2b69f49Smarc */
33787e911b15Skarels duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */
33797e911b15Skarels duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */
33807e911b15Skarels /* no RTS control,char error mode */
33817e911b15Skarels duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */
33827e911b15Skarels /* no RTS control,no echo or loop */
33837e911b15Skarels duart->cmdB = RESET_M; /* reset mode reg pntr for host */
33847e911b15Skarels duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */
33857e911b15Skarels /* ..no RTS cntrl, char error mode */
33867e911b15Skarels duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */
33877e911b15Skarels /* no RTS control,no echo or loop */
33887e911b15Skarels duart->auxctl = 0x00; /* baud rate set 1 */
33897e911b15Skarels duart->clkselA = 0x99; /* 4800 baud for kbd */
33907e911b15Skarels duart->clkselB = 0x99; /* 4800 baud for mouse */
33917e911b15Skarels
33927e911b15Skarels /* reset everything for keyboard */
33937e911b15Skarels
33947e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
33957e911b15Skarels duart->cmdA = bits;
33967e911b15Skarels
33977e911b15Skarels /* reset everything for host */
33987e911b15Skarels
33997e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
34007e911b15Skarels duart->cmdB = bits;
34017e911b15Skarels
34027e911b15Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
34037e911b15Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
34047e911b15Skarels
3405b2b69f49Smarc /*
34067881ece5Smarc * init keyboard defaults (DUART channel A)
34077881ece5Smarc */
34087e911b15Skarels for (i = 500; i > 0; --i) {
34097881ece5Smarc if (duart->statusA&XMT_RDY) {
34107e911b15Skarels duart->dataA = LK_DEFAULTS;
34117e911b15Skarels break;
34127e911b15Skarels }
34137e911b15Skarels }
34147e911b15Skarels
34157e911b15Skarels for (i = 100000; i > 0; --i) {
34167881ece5Smarc if (duart->statusA&RCV_RDY) {
34177e911b15Skarels break;
34187e911b15Skarels }
34197e911b15Skarels }
34207e911b15Skarels
34217881ece5Smarc if (duart->dataA) /* flush the ACK */
34227881ece5Smarc ;
34237e911b15Skarels
3424b2b69f49Smarc /*
34257881ece5Smarc * identify the pointing device
34267881ece5Smarc */
34277e911b15Skarels for (i = 500; i > 0; --i) {
34287881ece5Smarc if (duart->statusB&XMT_RDY) {
34297e911b15Skarels duart->dataB = SELF_TEST;
34307e911b15Skarels break;
34317e911b15Skarels }
34327e911b15Skarels }
34337e911b15Skarels
3434b2b69f49Smarc /*
34357e911b15Skarels * wait for 1st byte of self test report */
34367e911b15Skarels
34377e911b15Skarels for (i = 100000; i > 0; --i) {
34387881ece5Smarc if (duart->statusB&RCV_RDY) {
34397e911b15Skarels break;
34407e911b15Skarels }
34417e911b15Skarels }
34427e911b15Skarels
34437e911b15Skarels if (i == 0) {
34447881ece5Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
3445b2b69f49Smarc ,unit);
34467e911b15Skarels goto OUT;
34477e911b15Skarels }
34487e911b15Skarels
34497881ece5Smarc if (duart->dataB)
34507881ece5Smarc ;
34517e911b15Skarels
3452b2b69f49Smarc /*
34537881ece5Smarc * wait for ID byte of self test report
34547881ece5Smarc */
34557e911b15Skarels for (i = 100000; i > 0; --i) {
34567881ece5Smarc if (duart->statusB&RCV_RDY) {
34577e911b15Skarels break;
34587e911b15Skarels }
34597e911b15Skarels }
34607e911b15Skarels
34617e911b15Skarels if (i == 0) {
34627881ece5Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
34637e911b15Skarels goto OUT;
34647e911b15Skarels }
34657e911b15Skarels
34667e911b15Skarels id_byte = duart->dataB;
34677e911b15Skarels
3468b2b69f49Smarc /*
34697881ece5Smarc * wait for other bytes to come in
34707881ece5Smarc */
34717e911b15Skarels for (i = 100000; i > 0; --i) {
34727881ece5Smarc if (duart->statusB & RCV_RDY) {
34737881ece5Smarc if (duart->dataB)
34747881ece5Smarc ;
34757e911b15Skarels break;
34767e911b15Skarels }
34777e911b15Skarels }
34787e911b15Skarels if (i == 0) {
34797881ece5Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
34807e911b15Skarels goto OUT;
34817e911b15Skarels }
34827e911b15Skarels for (i = 100000; i > 0; --i) {
34837881ece5Smarc if (duart->statusB&RCV_RDY) {
34847881ece5Smarc if (duart->dataB)
34857881ece5Smarc ;
34867e911b15Skarels break;
34877e911b15Skarels }
34887e911b15Skarels }
34897e911b15Skarels if (i == 0) {
34907881ece5Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
34917e911b15Skarels goto OUT;
34927e911b15Skarels }
3493b2b69f49Smarc /*
34947881ece5Smarc * flag pointing device type and set defaults
34957881ece5Smarc */
34967881ece5Smarc for (i=100000; i>0; --i)
34977881ece5Smarc ; /*XXX*/
34987e911b15Skarels
34997e911b15Skarels if ((id_byte & 0x0F) != TABLET_ID) {
35007e911b15Skarels qdflags[unit].pntr_id = MOUSE_ID;
35017e911b15Skarels
35027e911b15Skarels for (i = 500; i > 0; --i) {
35037881ece5Smarc if (duart->statusB&XMT_RDY) {
35047e911b15Skarels duart->dataB = INC_STREAM_MODE;
35057e911b15Skarels break;
35067e911b15Skarels }
35077e911b15Skarels }
3508b2b69f49Smarc }
3509b2b69f49Smarc else {
35107e911b15Skarels qdflags[unit].pntr_id = TABLET_ID;
35117e911b15Skarels
35127e911b15Skarels for (i = 500; i > 0; --i) {
35137881ece5Smarc if (duart->statusB&XMT_RDY) {
35147e911b15Skarels duart->dataB = T_STREAM;
35157e911b15Skarels break;
35167e911b15Skarels }
35177e911b15Skarels }
35187e911b15Skarels }
35197e911b15Skarels OUT:
35207e911b15Skarels duart->imask = qdflags[unit].duart_imask;
35217e911b15Skarels
35227e911b15Skarels } /* setup_input */
35237e911b15Skarels
35247881ece5Smarc /*
35257881ece5Smarc * delay for at least one display frame time
35267e911b15Skarels *
35277e911b15Skarels * return: BAD means that we timed out without ever seeing the
35287e911b15Skarels * vertical sync status bit
35297e911b15Skarels * GOOD otherwise
35307881ece5Smarc */
wait_status(adder,mask)35317e911b15Skarels wait_status(adder, mask)
35327e911b15Skarels register struct adder *adder;
35337e911b15Skarels register int mask;
35347e911b15Skarels {
35357881ece5Smarc register i;
35367e911b15Skarels
3537b2b69f49Smarc for (i = 10000, adder->status = 0 ; i > 0 &&
35387881ece5Smarc !(adder->status&mask) ; --i)
3539b2b69f49Smarc ;
35407e911b15Skarels
35417e911b15Skarels if (i == 0) {
35427881ece5Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
35437e911b15Skarels return(BAD);
35447e911b15Skarels }
35457e911b15Skarels
35467e911b15Skarels return(GOOD);
35477e911b15Skarels
35487e911b15Skarels } /* wait_status */
35497e911b15Skarels
35507881ece5Smarc /*
35517881ece5Smarc * write out onto the ID bus
35527881ece5Smarc */
write_ID(adder,adrs,data)35537e911b15Skarels write_ID(adder, adrs, data)
35547e911b15Skarels register struct adder *adder;
35557e911b15Skarels register short adrs;
35567e911b15Skarels register short data;
35577e911b15Skarels {
35587881ece5Smarc register i;
35597e911b15Skarels
3560b2b69f49Smarc for (i = 100000, adder->status = 0 ;
35617881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i)
3562b2b69f49Smarc ;
35637e911b15Skarels
35647e911b15Skarels if (i == 0)
35657e911b15Skarels goto ERR;
35667e911b15Skarels
3567b2b69f49Smarc for (i = 100000, adder->status = 0 ;
35687881ece5Smarc i > 0 && !(adder->status&TX_READY) ; --i)
3569b2b69f49Smarc ;
35707e911b15Skarels
35717e911b15Skarels if (i > 0) {
35727e911b15Skarels adder->id_data = data;
35737e911b15Skarels adder->command = ID_LOAD | adrs;
35747881ece5Smarc return ;
35757e911b15Skarels }
35767e911b15Skarels
35777e911b15Skarels ERR:
35787881ece5Smarc printf("write_ID: timeout trying to write to VIPER\n");
35797881ece5Smarc return ;
35807e911b15Skarels
35817e911b15Skarels } /* write_ID */
3582006e9885Smarc #endif
3583