134511Smarc /*
235353Sbostic * Copyright (c) 1988 Regents of the University of California.
335353Sbostic * All rights reserved.
435353Sbostic *
544551Sbostic * %sccs.include.redist.c%
635353Sbostic *
7*50260Skarels * @(#)qd.c 7.1 (Berkeley) 06/28/91
835353Sbostic */
934642Smarc
1030391Skarels /************************************************************************
1134511Smarc * *
1234615Smarc * Copyright (c) 1985-1988 by *
1330391Skarels * Digital Equipment Corporation, Maynard, MA *
1430391Skarels * All rights reserved. *
1530391Skarels * *
1630391Skarels * This software is furnished under a license and may be used and *
1730391Skarels * copied only in accordance with the terms of such license and *
1830391Skarels * with the inclusion of the above copyright notice. This *
1930391Skarels * software or any other copies thereof may not be provided or *
2030391Skarels * otherwise made available to any other person. No title to and *
2130391Skarels * ownership of the software is hereby transferred. *
2230391Skarels * *
2330391Skarels * The information in this software is subject to change without *
2430391Skarels * notice and should not be construed as a commitment by Digital *
2530391Skarels * Equipment Corporation. *
2630391Skarels * *
2730391Skarels * Digital assumes no responsibility for the use or reliability *
2830391Skarels * of its software on equipment which is not supplied by Digital. *
2930391Skarels * *
3030391Skarels *************************************************************************/
3134615Smarc
3230391Skarels /*
3334642Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
3430391Skarels */
3530391Skarels
3634642Smarc #include "qd.h"
3734615Smarc
3834511Smarc #if NQD > 0
3945804Sbostic #include "../include/pte.h"
4045804Sbostic #include "../include/mtpr.h"
4145804Sbostic #include "sys/param.h"
4245804Sbostic #include "../include/cpu.h"
4345804Sbostic #include "sys/conf.h"
4445804Sbostic #include "sys/user.h"
4534642Smarc #include "qdioctl.h"
4645804Sbostic #include "sys/tty.h"
4745804Sbostic #include "sys/map.h"
4845804Sbostic #include "sys/buf.h"
4945804Sbostic #include "sys/vm.h"
5045804Sbostic #include "sys/clist.h"
5145804Sbostic #include "sys/file.h"
5245804Sbostic #include "sys/uio.h"
5345804Sbostic #include "sys/kernel.h"
5445804Sbostic #include "sys/exec.h"
5545804Sbostic #include "sys/proc.h"
5634642Smarc #include "ubareg.h"
5734642Smarc #include "ubavar.h"
5845804Sbostic #include "sys/syslog.h"
5934642Smarc #include "qduser.h" /* definitions shared with user level client */
6034615Smarc #include "qdreg.h" /* QDSS device register structures */
6132012Smarc
6234642Smarc /*
6334642Smarc * QDSS driver status flags for tracking operational state
6434642Smarc */
6534642Smarc struct qdflags {
6634642Smarc u_int inuse; /* which minor dev's are in use now */
6734642Smarc u_int config; /* I/O page register content */
6834642Smarc u_int mapped; /* user mapping status word */
6934642Smarc u_int kernel_loop; /* if kernel console is redirected */
7034642Smarc u_int user_dma; /* DMA from user space in progress */
7134642Smarc u_short pntr_id; /* type code of pointing device */
7234642Smarc u_short duart_imask; /* shadowing for duart intrpt mask reg */
7334642Smarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */
7434642Smarc u_short curs_acc; /* cursor acceleration factor */
7534642Smarc u_short curs_thr; /* cursor acceleration threshold level */
7634642Smarc u_short tab_res; /* tablet resolution factor */
7734642Smarc u_short selmask; /* mask for active qd select entries */
7834642Smarc };
7932012Smarc
8034642Smarc /*
8134642Smarc * bit definitions for 'inuse' entry
8234642Smarc */
8332012Smarc #define CONS_DEV 0x01
8432012Smarc #define GRAPHIC_DEV 0x04
8532012Smarc
8634642Smarc /*
8734642Smarc * bit definitions for 'mapped' member of flag structure
8834642Smarc */
8932012Smarc #define MAPDEV 0x01 /* hardware is mapped */
9032012Smarc #define MAPDMA 0x02 /* DMA buffer mapped */
9132012Smarc #define MAPEQ 0x04 /* event queue buffer mapped */
9232012Smarc #define MAPSCR 0x08 /* scroll param area mapped */
9332012Smarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */
9432012Smarc
9534642Smarc /*
9634642Smarc * bit definitions for 'selmask' member of qdflag structure
9734642Smarc */
9832012Smarc #define SEL_READ 0x01 /* read select is active */
9932012Smarc #define SEL_WRITE 0x02 /* write select is active */
10032012Smarc
10134642Smarc /*
10234732Smarc * constants used in shared memory operations
10334732Smarc */
10432012Smarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */
10532012Smarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \
10634642Smarc / sizeof(struct _vs_event) )
10734527Smarc #define DMA_BUFSIZ (1024 * 10)
10832012Smarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF)
10932012Smarc
11034642Smarc /*
11134732Smarc * reference to an array of "uba_device" structures built by the auto
11234732Smarc * configuration program. The uba_device structure decribes the device
11334732Smarc * sufficiently for the driver to talk to it. The auto configuration code
11434732Smarc * fills in the uba_device structures (located in ioconf.c) from user
11534732Smarc * maintained info.
11634732Smarc */
11734642Smarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */
11834642Smarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */
11934732Smarc extern char qvmem[][128*NBPG];
12034642Smarc extern struct pte QVmap[][128];
12134642Smarc #define CHUNK (64 * 1024)
12234642Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */
12332012Smarc
12434642Smarc /*
12534642Smarc * static storage used by multiple functions in this code
12634642Smarc */
12734642Smarc int Qbus_unmap[NQD]; /* Qbus mapper release code */
12834642Smarc struct qdflags qdflags[NQD]; /* QDSS device status flags */
12934642Smarc struct qdmap qdmap[NQD]; /* QDSS register map structure */
13034642Smarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */
13134642Smarc struct buf qdbuf[NQD]; /* buf structs used by strategy */
13234642Smarc short qdopened[NQD]; /* graphics device is open exclusive use */
13332012Smarc
13434642Smarc /*
13534732Smarc * the array "event_shared[]" is made up of a number of event queue buffers
13634732Smarc * equal to the number of QDSS's configured into the running kernel (NQD).
13734732Smarc * Each event queue buffer begins with an event queue header (struct qdinput)
13834732Smarc * followed by a group of event queue entries (struct _vs_event). The array
13934732Smarc * "*eq_header[]" is an array of pointers to the start of each event queue
14034732Smarc * buffer in "event_shared[]".
14134732Smarc */
14232012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
14332012Smarc
14434642Smarc char event_shared[EQSIZE]; /* reserve space for event bufs */
14534642Smarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */
14632012Smarc
14734642Smarc /*
14834732Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O
14934732Smarc * buffers. Each buffer must consume an integral number of memory pages to
15034732Smarc * guarantee that a following buffer will begin on a page boundary. Also,
15134732Smarc * enough space is allocated so that the FIRST I/O buffer can start at the
15234732Smarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that
15334732Smarc * memory protections can be turned on/off for individual buffers.
15434732Smarc */
15532012Smarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512)
15632012Smarc
15734642Smarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */
15834642Smarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */
15932012Smarc
16034642Smarc /*
16134732Smarc * The driver assists a client in scroll operations by loading dragon
16234732Smarc * registers from an interrupt service routine. The loading is done using
16334732Smarc * parameters found in memory shrade between the driver and it's client.
16434732Smarc * The scroll parameter structures are ALL loacted in the same memory page
16534732Smarc * for reasons of memory economy.
16634732Smarc */
16734642Smarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */
16834642Smarc struct scroll *scroll[NQD]; /* pointers to scroll structures */
16932012Smarc
17034642Smarc /*
17134732Smarc * the driver is programmable to provide the user with color map write
17234732Smarc * services at VSYNC interrupt time. At interrupt time the driver loads
17334732Smarc * the color map with any user-requested load data found in shared memory
17434732Smarc */
17532012Smarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512)
17632012Smarc
17734642Smarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */
17834642Smarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */
17932012Smarc
18034642Smarc /*
18134732Smarc * mouse input event structures
18234732Smarc */
18334642Smarc struct mouse_report last_rep[NQD];
18434642Smarc struct mouse_report current_rep[NQD];
18532012Smarc
18634732Smarc struct proc *qdrsel[NQD]; /* process waiting for select */
18734642Smarc struct _vs_cursor cursor[NQD]; /* console cursor */
18834642Smarc int qdcount = 0; /* count of successfully probed qd's */
18934642Smarc int nNQD = NQD;
19034642Smarc int DMAbuf_size = DMA_BUFSIZ;
19134642Smarc int QDlast_DMAtype; /* type of the last DMA operation */
19232012Smarc
19334642Smarc #define QDSSMAJOR 41 /* QDSS major device number */
19434642Smarc /*
19534732Smarc * macro to get system time. Used to time stamp event queue entries
19634732Smarc */
19730391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
19830391Skarels
19934642Smarc int qdprobe();
20034642Smarc int qdattach();
20134642Smarc int qddint(); /* DMA gate array intrpt service */
20234642Smarc int qdaint(); /* Dragon ADDER intrpt service */
20334642Smarc int qdiint();
20430391Skarels
20534642Smarc u_short qdstd[] = { 0 };
20630391Skarels
20734642Smarc struct uba_driver qddriver = {
20834732Smarc qdprobe, /* device probe entry */
20934732Smarc 0, /* no slave device */
21034732Smarc qdattach, /* device attach entry */
21134732Smarc 0, /* no "fill csr/ba to start" */
21234642Smarc qdstd, /* device addresses */
21334642Smarc "qd", /* device name string */
21434642Smarc qdinfo /* ptr to QDSS's uba_device struct */
21534642Smarc };
21630391Skarels
21734615Smarc #define QDPRIOR (PZERO-1) /* must be negative */
21830391Skarels #define FALSE 0
21930391Skarels #define TRUE ~FALSE
22030391Skarels #define BAD -1
22130391Skarels #define GOOD 0
22230391Skarels
22334642Smarc /*
22434642Smarc * macro to create a system virtual page number from system virtual adrs
22534642Smarc */
22634642Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT)
22730391Skarels
22834642Smarc /*
22934642Smarc * QDSS register address offsets from start of QDSS address space
23034642Smarc */
23130391Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */
23230391Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */
23330391Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */
23430391Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */
23530391Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */
23630391Skarels #define ADDER (REGSTART+0x000)
23730391Skarels #define DGA (REGSTART+0x200)
23830391Skarels #define DUART (REGSTART+0x400)
23930391Skarels #define MEMCSR (REGSTART+0x800)
24030391Skarels #define CLRSIZE (3 * 512) /* color map size */
24130391Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */
24234642Smarc /* 0x0C00 really */
24330391Skarels #define RED (CLRSTART+0x000)
24430391Skarels #define BLUE (CLRSTART+0x200)
24530391Skarels #define GREEN (CLRSTART+0x400)
24630391Skarels
24730391Skarels
24834642Smarc /*
24934642Smarc * QDSS minor device numbers. The *real* minor device numbers are in
25034642Smarc * the bottom two bits of the major/minor device spec. Bits 2 and up are
25134642Smarc * used to specify the QDSS device number (ie: which one?)
25234642Smarc */
25330391Skarels
25430391Skarels #define CONS 0
25530391Skarels #define GRAPHIC 2
25630391Skarels
25734642Smarc /*
25834642Smarc * console cursor bitmap (white block cursor)
25934642Smarc */
26034642Smarc short cons_cursor[32] = {
26134642Smarc /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
26234642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
26334642Smarc /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
26434642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
26534642Smarc };
26630391Skarels
26734642Smarc /*
26834642Smarc * constants used in font operations
26934642Smarc */
27034615Smarc #define CHARS 190 /* # of chars in the font */
27130391Skarels #define CHAR_HEIGHT 15 /* char height in pixels */
27230391Skarels #define CHAR_WIDTH 8 /* char width in pixels*/
27330391Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */
27430391Skarels #define ROWS CHAR_HEIGHT
27530391Skarels #define FONT_X 0 /* font's off screen adrs */
27630391Skarels #define FONT_Y (2048 - CHAR_HEIGHT)
27730391Skarels
27834642Smarc /* Offset to second row characters (XXX - should remove) */
27934615Smarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
28030391Skarels
28134642Smarc extern char q_font[]; /* reference font object code */
28234642Smarc extern u_short q_key[]; /* reference key xlation tables */
28334642Smarc extern u_short q_shift_key[];
28434642Smarc extern char *q_special[];
28530391Skarels
28634642Smarc /*
28734642Smarc * definitions for cursor acceleration reporting
28834642Smarc */
28930391Skarels #define ACC_OFF 0x01 /* acceleration is inactive */
29030391Skarels
29134642Smarc /*
29234642Smarc * virtual console support.
29334642Smarc */
29434642Smarc extern (*v_putc)();
29540817Smarc #ifdef KADB
29640817Smarc extern (*v_getc)();
29740817Smarc extern (*v_poll)();
29840817Smarc #endif
29934642Smarc extern struct cdevsw *consops;
30034642Smarc int qdputc();
30140817Smarc int qdgetc();
30240817Smarc int qdpoll();
30334642Smarc int qdstart();
30440817Smarc int qdpolling = 0;
30530391Skarels
30634642Smarc /*
30734642Smarc * LK-201 state storage for input console keyboard conversion to ASCII
30834642Smarc */
30934642Smarc struct q_keyboard {
31034642Smarc int shift; /* state variables */
31134642Smarc int cntrl;
31234642Smarc int lock;
31334642Smarc int lastcode; /* last keycode typed */
31434642Smarc unsigned kup[8]; /* bits for each keycode*/
31534642Smarc unsigned dkeys[8]; /* down/up mode keys */
31634642Smarc char last; /* last character */
31734642Smarc } q_keyboard;
31830391Skarels
31934642Smarc /*
32034642Smarc * tty settings on first open
32134642Smarc */
32240817Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
32334615Smarc #define OFLAG (OPOST|OXTABS|ONLCR)
32440817Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
32534615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
32634615Smarc
32734732Smarc /*
32834732Smarc * Init QDSS as console (before probe routine)
32934732Smarc */
33030391Skarels
qdcons_init()33130391Skarels qdcons_init()
33230391Skarels {
33334732Smarc register unit;
33430391Skarels caddr_t phys_adr; /* physical QDSS base adrs */
33534615Smarc u_int mapix; /* index into QVmap[] array */
33634615Smarc struct percpu *pcpu; /* pointer to cpusw structure */
33734615Smarc register struct qbus *qb;
33830391Skarels u_short *qdaddr; /* address of QDSS IO page CSR */
33930391Skarels u_short *devptr; /* vitual device space */
34034615Smarc extern cnputc();
34130391Skarels
34230391Skarels #define QDSSCSR 0x1F00
34330391Skarels
34432012Smarc if (v_putc != cnputc)
34534732Smarc return 0;
34632012Smarc
34730391Skarels unit = 0;
34830391Skarels
34934642Smarc /*
35034642Smarc * find the cpusw entry that matches this machine.
35134642Smarc */
35232012Smarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
35332012Smarc ;
35432012Smarc if (pcpu == NULL)
35534732Smarc return 0;
35636705Stef if (pcpu->pc_io->io_type != IO_QBUS)
35736705Stef return 0;
35830391Skarels
35932012Smarc /*
36034615Smarc * Map device registers - the last 8K of qvmem.
36132012Smarc */
36232012Smarc qb = (struct qbus *)pcpu->pc_io->io_details;
36332012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
36434732Smarc UBAIOPAGES * NBPG);
36532012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
36630391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
36734732Smarc if (badaddr((caddr_t)qdaddr, sizeof(short)))
36834732Smarc return 0;
36934615Smarc
37032012Smarc /*
37132012Smarc * Map q-bus memory used by qdss. (separate map)
37232012Smarc */
37332012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1));
37432012Smarc phys_adr = qb->qb_maddr + mapix;
37532012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
37630391Skarels
37732012Smarc /*
37832012Smarc * tell QDSS which Q memory address base to decode
37934642Smarc * (shifted right 16 bits - its in 64K units)
38032012Smarc */
38132012Smarc *qdaddr = (u_short)((int)mapix >> 16);
38230391Skarels qdflags[unit].config = *(u_short *)qdaddr;
38330391Skarels
38434642Smarc /*
38534642Smarc * load qdmap struct with the virtual addresses of the QDSS elements
38634642Smarc */
38734615Smarc qdbase[unit] = (caddr_t) (qvmem[0]);
38830391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART;
38930391Skarels qdmap[unit].adder = qdbase[unit] + ADDER;
39030391Skarels qdmap[unit].dga = qdbase[unit] + DGA;
39130391Skarels qdmap[unit].duart = qdbase[unit] + DUART;
39230391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
39330391Skarels qdmap[unit].red = qdbase[unit] + RED;
39430391Skarels qdmap[unit].blue = qdbase[unit] + BLUE;
39530391Skarels qdmap[unit].green = qdbase[unit] + GREEN;
39630391Skarels
39730391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */
39830391Skarels
39934642Smarc /*
40034642Smarc * init the QDSS
40134642Smarc */
40234642Smarc /*
40332012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
40434642Smarc (char *)qdbase[0], qdmap[0].memcsr);
40534642Smarc */
40632012Smarc
40730391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
40830391Skarels
40930391Skarels cursor[unit].x = 0;
41030391Skarels cursor[unit].y = 0;
41130391Skarels init_shared(unit); /* init shared memory */
41230391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */
41330391Skarels clear_qd_screen(unit); /* clear the screen */
41430391Skarels ldfont(unit); /* load the console font */
41530391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */
41630391Skarels setup_input(unit); /* init the DUART */
41734642Smarc v_putc = qdputc; /* kernel console output to qdss */
41840817Smarc #ifdef KADB
41940817Smarc v_getc = qdgetc; /* kernel console input from qdss */
42040817Smarc v_poll = qdpoll; /* kdb hook to disable char intr */
42140817Smarc #endif
42234642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */
42334732Smarc return 1;
42430391Skarels
42530391Skarels } /* qdcons_init */
42630391Skarels
42734732Smarc /*
42834732Smarc * Configure QDSS into Q memory and make it intrpt.
42934732Smarc *
43034732Smarc * side effects: QDSS gets mapped into Qbus memory space at the first
43134732Smarc * vacant 64kb boundary counting back from the top of
43234732Smarc * Qbus memory space (qvmem+4mb)
43334732Smarc *
43434732Smarc * return: QDSS bus request level and vector address returned in
43534732Smarc * registers by UNIX convention.
43634732Smarc *
43734732Smarc */
qdprobe(reg)43830391Skarels qdprobe(reg)
43934732Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */
44030391Skarels {
44140817Smarc register int br, cvec;
44230391Skarels register int unit;
44330391Skarels struct dga *dga; /* pointer to gate array structure */
44434732Smarc int vector;
44534732Smarc #ifdef notdef
44630391Skarels int *ptep; /* page table entry pointer */
44730391Skarels caddr_t phys_adr; /* physical QDSS base adrs */
44830391Skarels u_int mapix;
44934732Smarc #endif
45030391Skarels
45134732Smarc #ifdef lint
45234732Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
45334732Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
45434732Smarc #endif
45534732Smarc
45634642Smarc /*
45734642Smarc * calculate board unit number from I/O page register address
45834642Smarc */
45930391Skarels unit = (int) (((int)reg >> 1) & 0x0007);
46030391Skarels
46134642Smarc /*
46234642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb
46334642Smarc * physical boundary. The Qbus memory space is mapped into
46434642Smarc * the system memory space at config time. After config
46534642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
46634642Smarc * of the start of Qbus memory. The Qbus memory page table
46734642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
46834642Smarc * which is also loaded at config time. These are the
46934642Smarc * variables used below to find a vacant 64kb boundary in
47034642Smarc * Qbus memory, and load it's corresponding physical adrs
47134642Smarc * into the QDSS's I/O page CSR.
47234642Smarc */
47330391Skarels
47434615Smarc /*
47534615Smarc * Only if QD is the graphics device.
47634615Smarc */
47734615Smarc
47830391Skarels /* if this QDSS is NOT the console, then do init here.. */
47930391Skarels
48034615Smarc if (unit != 0) {
48134615Smarc printf("qd: can't support two qdss's (yet)\n");
48234732Smarc #ifdef notdef /* can't test */
48334642Smarc if (v_consputc != qdputc || unit != 0) {
48430391Skarels
48534642Smarc /*
48634642Smarc * read QDSS config info
48734642Smarc */
48834642Smarc qdflags[unit].config = *(u_short *)reg;
48934615Smarc
49034642Smarc /*
49134642Smarc * find an empty 64kb adrs boundary
49234642Smarc */
49330391Skarels
49434642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
49530391Skarels
49634642Smarc /*
49734732Smarc * find the cpusw entry that matches this machine.
49834732Smarc */
49934642Smarc cpup = &cpusw[cpu];
50034732Smarc while (!(BADADDR(qdbase[unit], sizeof(short))))
50134732Smarc qdbase[unit] -= CHUNK;
50234615Smarc
50334642Smarc /*
50434732Smarc * tell QDSS which Q memory address base to decode
50534732Smarc */
50634642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
50734642Smarc ptep = (int *) QVmap[0] + mapix;
50834642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
50934642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
51034615Smarc
51134642Smarc /*
51234642Smarc * load QDSS adrs map with system addresses
51334642Smarc * of device regs
51434642Smarc */
51534642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART;
51634642Smarc qdmap[unit].adder = qdbase[unit] + ADDER;
51734642Smarc qdmap[unit].dga = qdbase[unit] + DGA;
51834642Smarc qdmap[unit].duart = qdbase[unit] + DUART;
51934642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
52034642Smarc qdmap[unit].red = qdbase[unit] + RED;
52134642Smarc qdmap[unit].blue = qdbase[unit] + BLUE;
52234642Smarc qdmap[unit].green = qdbase[unit] + GREEN;
52330391Skarels
52434642Smarc /* device init */
52534615Smarc
52634642Smarc cursor[unit].x = 0;
52734642Smarc cursor[unit].y = 0;
52834642Smarc init_shared(unit); /* init shared memory */
52934642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */
53034642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */
53134642Smarc setup_input(unit); /* init the DUART */
53234642Smarc clear_qd_screen(unit);
53334642Smarc ldfont(unit); /* load the console font */
53430391Skarels
53534642Smarc /* once only: turn on sync */
53630391Skarels
53734642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON;
53834642Smarc }
53934615Smarc #endif /*notdef*/
54030391Skarels }
54130391Skarels
54234642Smarc /*
54334642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
54434642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three
54534642Smarc * vectors from the vector pool, and then continue
54634642Smarc * to take them until we get a xx0 HEX vector. The
54734642Smarc * pool provides vectors in contiguous decending
54834642Smarc * order.
54934642Smarc */
55030391Skarels
55130391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */
55230391Skarels
55334642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */
55434642Smarc /* ..take another vector */
55534642Smarc vector = (uba_hd[0].uh_lastiv -= 4);
55630391Skarels }
55730391Skarels
55834642Smarc /*
55934642Smarc * setup DGA to do a DMA interrupt (transfer count = 0)
56034642Smarc */
56130391Skarels dga = (struct dga *) qdmap[unit].dga;
56234642Smarc dga->csr = (short) HALT; /* disable everything */
56334642Smarc dga->ivr = (short) vector; /* load intrpt base vector */
56434642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */
56530391Skarels dga->bytcnt_hi = (short) 0;
56630391Skarels
56734642Smarc /*
56834642Smarc * turn on DMA interrupts
56934642Smarc */
57030391Skarels dga->csr &= ~SET_DONE_FIFO;
57130391Skarels dga->csr |= DMA_IE | DL_ENB;
57230391Skarels
57330391Skarels DELAY(20000); /* wait for the intrpt */
57430391Skarels dga->csr = HALT; /* stop the wheels */
57530391Skarels
57630391Skarels if (cvec != vector) /* if vector != base vector.. */
57734732Smarc return(0); /* ..return = 'no device' */
57830391Skarels
57934615Smarc /*
58034642Smarc * score this as an existing qdss
58134642Smarc */
58234615Smarc qdcount++;
58334615Smarc
58430391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */
58530391Skarels
58630391Skarels } /* qdprobe */
58730391Skarels
58830391Skarels qdattach(ui)
58934642Smarc struct uba_device *ui;
59030391Skarels {
59134732Smarc register unit; /* QDSS module # for this call */
59230391Skarels
59330391Skarels unit = ui->ui_unit; /* get QDSS number */
59430391Skarels
59534642Smarc /*
59634642Smarc * init "qdflags[]" for this QDSS
59734642Smarc */
59830391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */
59930391Skarels qdflags[unit].mapped = 0;
60034615Smarc qdflags[unit].kernel_loop = -1;
60130391Skarels qdflags[unit].user_dma = 0;
60230391Skarels qdflags[unit].curs_acc = ACC_OFF;
60330391Skarels qdflags[unit].curs_thr = 128;
60430391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */
60530391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */
60630391Skarels qdflags[unit].adder_ie = 0;
60730391Skarels
60834642Smarc /*
60934642Smarc * init structures used in kbd/mouse interrupt service. This code must
61034642Smarc * come after the "init_shared()" routine has run since that routine
61134642Smarc * inits the eq_header[unit] structure used here.
61234642Smarc */
61330391Skarels
61434642Smarc /*
61534642Smarc * init the "latest mouse report" structure
61634642Smarc */
61730391Skarels last_rep[unit].state = 0;
61830391Skarels last_rep[unit].dx = 0;
61930391Skarels last_rep[unit].dy = 0;
62030391Skarels last_rep[unit].bytcnt = 0;
62130391Skarels
62234642Smarc /*
62334732Smarc * init the event queue (except mouse position)
62434732Smarc */
62534732Smarc eq_header[unit]->header.events =
62634732Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
62730391Skarels
62830391Skarels eq_header[unit]->header.size = MAXEVENTS;
62930391Skarels eq_header[unit]->header.head = 0;
63030391Skarels eq_header[unit]->header.tail = 0;
63130391Skarels
63234642Smarc /*
63334642Smarc * open exclusive for graphics device.
63434642Smarc */
63534642Smarc qdopened[unit] = 0;
63630391Skarels
63730391Skarels } /* qdattach */
63830391Skarels
63934732Smarc /*ARGSUSED*/
qdopen(dev,flag)64030391Skarels qdopen(dev, flag)
64134642Smarc dev_t dev;
64234642Smarc int flag;
64330391Skarels {
64430391Skarels register struct uba_device *ui; /* ptr to uba structures */
64530391Skarels register struct dga *dga; /* ptr to gate array struct */
64630391Skarels register struct tty *tp;
64730391Skarels struct duart *duart;
64834732Smarc int unit;
64934732Smarc int minor_dev;
65030391Skarels
65130391Skarels minor_dev = minor(dev); /* get QDSS minor device number */
65230391Skarels unit = minor_dev >> 2;
65330391Skarels
65434642Smarc /*
65534642Smarc * check for illegal conditions
65634642Smarc */
65730391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */
65830391Skarels if (ui == 0 || ui->ui_alive == 0)
65934642Smarc return(ENXIO); /* no such device or address */
66030391Skarels
66130391Skarels duart = (struct duart *) qdmap[unit].duart;
66230391Skarels dga = (struct dga *) qdmap[unit].dga;
66330391Skarels
66430391Skarels if ((minor_dev & 0x03) == 2) {
66534642Smarc /*
66634642Smarc * this is the graphic device...
66734642Smarc */
66834642Smarc if (qdopened[unit] != 0)
66934732Smarc return(EBUSY);
67034642Smarc else
67134642Smarc qdopened[unit] = 1;
67234642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */
67334642Smarc /*
67434642Smarc * enble kbd & mouse intrpts in DUART mask reg
67534642Smarc */
67634642Smarc qdflags[unit].duart_imask |= 0x22;
67734642Smarc duart->imask = qdflags[unit].duart_imask;
67834642Smarc } else {
67934642Smarc /*
68034642Smarc * this is the console
68134642Smarc */
68234642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */
68334642Smarc dga->csr |= CURS_ENB;
68434642Smarc qdflags[unit].duart_imask |= 0x02;
68534642Smarc duart->imask = qdflags[unit].duart_imask;
68634642Smarc /*
68734642Smarc * some setup for tty handling
68834642Smarc */
68934642Smarc tp = &qd_tty[minor_dev];
69034642Smarc tp->t_addr = ui->ui_addr;
69134642Smarc tp->t_oproc = qdstart;
69234642Smarc if ((tp->t_state & TS_ISOPEN) == 0) {
69334642Smarc ttychars(tp);
69434642Smarc tp->t_ispeed = B9600;
69534642Smarc tp->t_ospeed = B9600;
69634642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON;
69734642Smarc tp->t_iflag = TTYDEF_IFLAG;
69834642Smarc tp->t_oflag = TTYDEF_OFLAG;
69934642Smarc tp->t_lflag = TTYDEF_LFLAG;
70034642Smarc tp->t_cflag = TTYDEF_CFLAG;
70132012Smarc }
70234642Smarc /*
70334642Smarc * enable intrpts, open line discipline
70434642Smarc */
70534642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */
70634642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp));
70730391Skarels }
70830391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */
70930391Skarels return(0);
71030391Skarels
71130391Skarels } /* qdopen */
71230391Skarels
71334732Smarc /*ARGSUSED*/
qdclose(dev,flag,mode,p)71449759Smarc qdclose(dev, flag, mode, p)
71534642Smarc dev_t dev;
71649759Smarc int flag, mode;
71749759Smarc struct proc *p;
71830391Skarels {
71930391Skarels register struct tty *tp;
72030391Skarels register struct qdmap *qd;
72130391Skarels register int *ptep;
72230391Skarels struct dga *dga; /* gate array register map pointer */
72330391Skarels struct duart *duart;
72430391Skarels struct adder *adder;
72534732Smarc int unit;
72634732Smarc int minor_dev;
72730391Skarels u_int mapix;
72834642Smarc int i; /* SIGNED index */
72930391Skarels
73030391Skarels minor_dev = minor(dev); /* get minor device number */
73130391Skarels unit = minor_dev >> 2; /* get QDSS number */
73230391Skarels qd = &qdmap[unit];
73330391Skarels
73430391Skarels if ((minor_dev & 0x03) == 2) {
73534642Smarc /*
73634642Smarc * this is the graphic device...
73734642Smarc */
73834642Smarc if (qdopened[unit] != 1)
73934732Smarc return(EBUSY);
74034642Smarc else
74134642Smarc qdopened[unit] = 0; /* allow it to be re-opened */
74234642Smarc /*
74334642Smarc * re-protect device memory
74434642Smarc */
74534642Smarc if (qdflags[unit].mapped & MAPDEV) {
74634642Smarc /*
74734642Smarc * TEMPLATE RAM
74834642Smarc */
74934642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
75034642Smarc ptep = (int *)(QVmap[0] + mapix);
75134732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++)
75234732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
75334642Smarc /*
75434642Smarc * ADDER
75534642Smarc */
75634642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
75734642Smarc ptep = (int *)(QVmap[0] + mapix);
75834732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++)
75934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
76034642Smarc /*
76134642Smarc * COLOR MAPS
76234642Smarc */
76334642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
76434642Smarc ptep = (int *)(QVmap[0] + mapix);
76534732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++)
76634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
76734642Smarc }
76834615Smarc
76934642Smarc /*
77034642Smarc * re-protect DMA buffer and free the map registers
77134642Smarc */
77234642Smarc if (qdflags[unit].mapped & MAPDMA) {
77334642Smarc dga = (struct dga *) qdmap[unit].dga;
77434642Smarc adder = (struct adder *) qdmap[unit].adder;
77534642Smarc dga->csr &= ~DMA_IE;
77634642Smarc dga->csr &= ~0x0600; /* kill DMA */
77734642Smarc adder->command = CANCEL;
77834642Smarc /*
77934642Smarc * if DMA was running, flush spurious intrpt
78034642Smarc */
78134642Smarc if (dga->bytcnt_lo != 0) {
78234642Smarc dga->bytcnt_lo = 0;
78334642Smarc dga->bytcnt_hi = 0;
78434642Smarc DMA_SETIGNORE(DMAheader[unit]);
78534642Smarc dga->csr |= DMA_IE;
78634642Smarc dga->csr &= ~DMA_IE;
78734642Smarc }
78834642Smarc ptep = (int *)
78934642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
79034732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
79134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
79234642Smarc ubarelse(0, &Qbus_unmap[unit]);
79334642Smarc }
79434615Smarc
79534642Smarc /*
79634642Smarc * re-protect 1K (2 pages) event queue
79734642Smarc */
79834642Smarc if (qdflags[unit].mapped & MAPEQ) {
79934642Smarc ptep = (int *)
80034642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
80134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
80234642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
80330391Skarels }
80434642Smarc /*
80534642Smarc * re-protect scroll param area and disable scroll intrpts
80634642Smarc */
80734642Smarc if (qdflags[unit].mapped & MAPSCR) {
80834642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4)
80934642Smarc + (mfpr(SBR) | 0x80000000));
81034642Smarc /*
81134642Smarc * re-protect 512 scroll param area
81234642Smarc */
81334642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
81434642Smarc adder = (struct adder *) qdmap[unit].adder;
81534642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC;
81634642Smarc adder->interrupt_enable = qdflags[unit].adder_ie;
81734642Smarc }
81834642Smarc /*
81934642Smarc * re-protect color map write buffer area and kill intrpts
82034642Smarc */
82134642Smarc if (qdflags[unit].mapped & MAPCOLOR) {
82234642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4)
82334642Smarc + (mfpr(SBR) | 0x80000000));
82434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
82534642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
82634642Smarc color_buf[unit]->status = 0;
82734642Smarc adder = (struct adder *) qdmap[unit].adder;
82834642Smarc qdflags[unit].adder_ie &= ~VSYNC;
82934642Smarc adder->interrupt_enable = qdflags[unit].adder_ie;
83034642Smarc }
83134642Smarc mtpr(TBIA, 0);
83234642Smarc /* flag everything now unmapped */
83334642Smarc qdflags[unit].mapped = 0;
83434642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV;
83534642Smarc qdflags[unit].curs_acc = ACC_OFF;
83634642Smarc qdflags[unit].curs_thr = 128;
83734642Smarc /*
83834642Smarc * restore the console
83934642Smarc */
84030391Skarels dga = (struct dga *) qdmap[unit].dga;
84130391Skarels adder = (struct adder *) qdmap[unit].adder;
84230391Skarels dga->csr &= ~DMA_IE;
84330391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */
84430391Skarels dga->csr |= DMA_ERR; /* clear error condition */
84530391Skarels adder->command = CANCEL;
84634642Smarc /*
84734642Smarc * if DMA was running, flush spurious intrpt
84834642Smarc */
84930391Skarels if (dga->bytcnt_lo != 0) {
85034642Smarc dga->bytcnt_lo = 0;
85134642Smarc dga->bytcnt_hi = 0;
85234642Smarc DMA_SETIGNORE(DMAheader[unit]);
85334642Smarc dga->csr |= DMA_IE;
85434642Smarc dga->csr &= ~DMA_IE;
85530391Skarels }
85630391Skarels init_shared(unit); /* init shared memory */
85730391Skarels setup_dragon(unit); /* init ADDER/VIPER */
85830391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */
85930391Skarels setup_input(unit); /* init the DUART */
86030391Skarels ldfont(unit);
86130391Skarels cursor[unit].x = 0;
86230391Skarels cursor[unit].y = 0;
86334642Smarc /*
86434642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts
86534642Smarc */
86634642Smarc duart = (struct duart *) qdmap[unit].duart;
86734642Smarc qdflags[unit].duart_imask &= ~(0x20);
86834642Smarc qdflags[unit].duart_imask |= 0x02;
86934642Smarc duart->imask = qdflags[unit].duart_imask;
87034642Smarc /*
87134642Smarc * shut off interrupts if all is closed
87234642Smarc */
87334642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) {
87434642Smarc dga = (struct dga *) qdmap[unit].dga;
87534642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE);
87634642Smarc }
87734642Smarc } else {
87834642Smarc /*
87934642Smarc * this is the console
88034642Smarc */
88134642Smarc tp = &qd_tty[minor_dev];
88249759Smarc (*linesw[tp->t_line].l_close)(tp, flag);
88334642Smarc ttyclose(tp);
88434642Smarc tp->t_state = 0;
88534642Smarc qdflags[unit].inuse &= ~CONS_DEV;
88634642Smarc /*
88734642Smarc * if graphics device is closed, kill interrupts
88834642Smarc */
88934642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
89034642Smarc dga = (struct dga *) qdmap[unit].dga;
89134642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE);
89234642Smarc }
89330391Skarels }
89434615Smarc
89530391Skarels return(0);
89630391Skarels
89730391Skarels } /* qdclose */
89830391Skarels
qdioctl(dev,cmd,datap,flags)89930391Skarels qdioctl(dev, cmd, datap, flags)
90034642Smarc dev_t dev;
90134642Smarc int cmd;
90234732Smarc register caddr_t datap;
90334642Smarc int flags;
90430391Skarels {
90530391Skarels register int *ptep; /* page table entry pointer */
90632012Smarc register int mapix; /* QVmap[] page table index */
90730391Skarels register struct _vs_event *event;
90830391Skarels register struct tty *tp;
90934732Smarc register i;
91030391Skarels struct qdmap *qd; /* pointer to device map struct */
91130391Skarels struct dga *dga; /* Gate Array reg structure pntr */
91230391Skarels struct duart *duart; /* DUART reg structure pointer */
91330391Skarels struct adder *adder; /* ADDER reg structure pointer */
91430391Skarels struct prgkbd *cmdbuf;
91530391Skarels struct prg_cursor *curs;
91630391Skarels struct _vs_cursor *pos;
91734732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */
91830391Skarels u_int minor_dev = minor(dev);
91930391Skarels int error;
92030391Skarels int s;
92130391Skarels short *temp; /* a pointer to template RAM */
92230391Skarels
92334642Smarc /*
92434642Smarc * service graphic device ioctl commands
92534642Smarc */
92630391Skarels switch (cmd) {
92734615Smarc
92834642Smarc case QD_GETEVENT:
92934642Smarc /*
93034642Smarc * extract the oldest event from the event queue
93134642Smarc */
93230391Skarels if (ISEMPTY(eq_header[unit])) {
93334642Smarc event = (struct _vs_event *) datap;
93434642Smarc event->vse_device = VSE_NULL;
93534642Smarc break;
93630391Skarels }
93730391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
93834615Smarc s = spl5();
93930391Skarels GETEND(eq_header[unit]);
94030391Skarels splx(s);
94134732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
94230391Skarels break;
94330391Skarels
94434642Smarc case QD_RESET:
94534642Smarc /*
94634642Smarc * init the dragon stuff, DUART, and driver variables
94734642Smarc */
94830391Skarels init_shared(unit); /* init shared memory */
94930391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */
95030391Skarels clear_qd_screen(unit);
95130391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */
95230391Skarels ldfont(unit); /* load the console font */
95330391Skarels setup_input(unit); /* init the DUART */
95430391Skarels break;
95530391Skarels
95634642Smarc case QD_SET:
95734642Smarc /*
95834642Smarc * init the DUART and driver variables
95934642Smarc */
96030391Skarels init_shared(unit);
96130391Skarels setup_input(unit);
96230391Skarels break;
96330391Skarels
96434642Smarc case QD_CLRSCRN:
96534642Smarc /*
96634642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon)
96734642Smarc */
96834732Smarc #ifdef notdef /* has caused problems and isn't necessary */
96930391Skarels setup_dragon(unit);
97030391Skarels clear_qd_screen(unit);
97134615Smarc #endif
97230391Skarels break;
97330391Skarels
97434642Smarc case QD_WTCURSOR:
97534642Smarc /*
97634642Smarc * load a cursor into template RAM
97734642Smarc */
97834732Smarc ldcursor(unit, (short *)datap);
97930391Skarels break;
98030391Skarels
98134642Smarc case QD_RDCURSOR:
98230391Skarels
98330391Skarels temp = (short *) qdmap[unit].template;
98434642Smarc /*
98534642Smarc * cursor is 32 WORDS from the end of the 8k WORD...
98634642Smarc * ...template space
98734642Smarc */
98830391Skarels temp += (8 * 1024) - 32;
98930391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short))
99034642Smarc *(short *)datap = *temp++;
99130391Skarels break;
99230391Skarels
99334642Smarc case QD_POSCURSOR:
99434642Smarc /*
99534642Smarc * position the mouse cursor
99634642Smarc */
99730391Skarels dga = (struct dga *) qdmap[unit].dga;
99830391Skarels pos = (struct _vs_cursor *) datap;
99934615Smarc s = spl5();
100030391Skarels dga->x_cursor = TRANX(pos->x);
100130391Skarels dga->y_cursor = TRANY(pos->y);
100230391Skarels eq_header[unit]->curs_pos.x = pos->x;
100330391Skarels eq_header[unit]->curs_pos.y = pos->y;
100430391Skarels splx(s);
100530391Skarels break;
100630391Skarels
100734642Smarc case QD_PRGCURSOR:
100834642Smarc /*
100934642Smarc * set the cursor acceleration factor
101034642Smarc */
101130391Skarels curs = (struct prg_cursor *) datap;
101234615Smarc s = spl5();
101330391Skarels qdflags[unit].curs_acc = curs->acc_factor;
101430391Skarels qdflags[unit].curs_thr = curs->threshold;
101530391Skarels splx(s);
101630391Skarels break;
101730391Skarels
101834642Smarc case QD_MAPDEVICE:
101934642Smarc /*
102034642Smarc * enable 'user write' to device pages
102134642Smarc */
102230391Skarels qdflags[unit].mapped |= MAPDEV;
102330391Skarels qd = (struct qdmap *) &qdmap[unit];
102434642Smarc /*
102534642Smarc * enable user write to template RAM
102634642Smarc */
102732012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
102832012Smarc ptep = (int *)(QVmap[0] + mapix);
102934732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++)
103034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
103134642Smarc /*
103234642Smarc * enable user write to registers
103334642Smarc */
103432012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
103532012Smarc ptep = (int *)(QVmap[0] + mapix);
103634732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++)
103734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
103834642Smarc /*
103934642Smarc * enable user write to color maps
104034642Smarc */
104132012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
104232012Smarc ptep = (int *)(QVmap[0] + mapix);
104334732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++)
104434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
104534642Smarc /*
104634642Smarc * enable user write to DUART
104734642Smarc */
104832012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
104932012Smarc ptep = (int *)(QVmap[0] + mapix);
105030391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
105130391Skarels
105234732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */
105330391Skarels
105434642Smarc /*
105534732Smarc * stuff qdmap structure in return buffer
105634732Smarc */
105734732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
105830391Skarels break;
105930391Skarels
106034642Smarc case QD_MAPIOBUF:
106134642Smarc /*
106234642Smarc * do setup for DMA by user process
106334642Smarc *
106434642Smarc * set 'user write enable' bits for DMA buffer
106534642Smarc */
106630391Skarels qdflags[unit].mapped |= MAPDMA;
106730391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
106834642Smarc + (mfpr(SBR) | 0x80000000));
106934732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
107034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
107134732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */
107234642Smarc /*
107334642Smarc * set up QBUS map registers for DMA
107434642Smarc */
107530391Skarels DMAheader[unit]->QBAreg =
107634732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
107730391Skarels if (DMAheader[unit]->QBAreg == 0)
107834732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit);
107930391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
108030391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF;
108134642Smarc /*
108234642Smarc * return I/O buf adr
108334642Smarc */
108430391Skarels *(int *)datap = (int) DMAheader[unit];
108530391Skarels break;
108630391Skarels
108734642Smarc case QD_MAPSCROLL:
108834642Smarc /*
108934642Smarc * map the shared scroll param area and enable scroll interpts
109034642Smarc */
109130391Skarels qdflags[unit].mapped |= MAPSCR;
109230391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4)
109334642Smarc + (mfpr(SBR) | 0x80000000));
109434642Smarc /*
109534642Smarc * allow user write to scroll area
109634642Smarc */
109730391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
109834732Smarc mtpr(TBIA, 0); /* invalidate translation buf */
109930391Skarels scroll[unit]->status = 0;
110030391Skarels adder = (struct adder *) qdmap[unit].adder;
110130391Skarels qdflags[unit].adder_ie |= FRAME_SYNC;
110230391Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
110334642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */
110430391Skarels break;
110530391Skarels
110634642Smarc case QD_UNMAPSCROLL:
110734642Smarc /*
110834642Smarc * unmap shared scroll param area and disable scroll intrpts
110934642Smarc */
111030391Skarels if (qdflags[unit].mapped & MAPSCR) {
111134642Smarc qdflags[unit].mapped &= ~MAPSCR;
111234642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4)
111334642Smarc + (mfpr(SBR) | 0x80000000));
111434642Smarc /*
111534642Smarc * re-protect 512 scroll param area
111634642Smarc */
111734642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
111834642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */
111934642Smarc adder = (struct adder *) qdmap[unit].adder;
112034642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC;
112134642Smarc adder->interrupt_enable = qdflags[unit].adder_ie;
112230391Skarels }
112330391Skarels break;
112430391Skarels
112534642Smarc case QD_MAPCOLOR:
112634642Smarc /*
112734642Smarc * map shared color map write buf and turn on vsync intrpt
112834642Smarc */
112930391Skarels qdflags[unit].mapped |= MAPCOLOR;
113030391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4)
113134642Smarc + (mfpr(SBR) | 0x80000000));
113234732Smarc /*
113334732Smarc * allow user write to color map write buffer
113434732Smarc */
113534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
113630391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
113730391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */
113834642Smarc adder = (struct adder *) qdmap[unit].adder;
113930391Skarels qdflags[unit].adder_ie |= VSYNC;
114030391Skarels adder->interrupt_enable = qdflags[unit].adder_ie;
114134732Smarc /*
114234732Smarc * return color area address
114334732Smarc */
114430391Skarels *(int *)datap = (int) color_buf[unit];
114530391Skarels break;
114630391Skarels
114734642Smarc case QD_UNMAPCOLOR:
114834642Smarc /*
114934732Smarc * unmap shared color map write buffer and kill VSYNC intrpts
115034732Smarc */
115130391Skarels if (qdflags[unit].mapped & MAPCOLOR) {
115234642Smarc qdflags[unit].mapped &= ~MAPCOLOR;
115334642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4)
115434642Smarc + (mfpr(SBR) | 0x80000000));
115534732Smarc /*
115634732Smarc * re-protect color map write buffer
115734732Smarc */
115834732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
115934642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
116034732Smarc mtpr(TBIA, 0);
116134642Smarc adder = (struct adder *) qdmap[unit].adder;
116234642Smarc qdflags[unit].adder_ie &= ~VSYNC;
116334642Smarc adder->interrupt_enable = qdflags[unit].adder_ie;
116430391Skarels }
116530391Skarels break;
116630391Skarels
116734642Smarc case QD_MAPEVENT:
116834642Smarc /*
116934642Smarc * give user write access to the event queue
117034642Smarc */
117130391Skarels qdflags[unit].mapped |= MAPEQ;
117230391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4)
117334642Smarc + (mfpr(SBR) | 0x80000000));
117434732Smarc /*
117534732Smarc * allow user write to 1K event queue
117634732Smarc */
117734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
117830391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
117930391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */
118034732Smarc /*
118134732Smarc * return event queue address
118234732Smarc */
118334732Smarc *(int *)datap = (int)eq_header[unit];
118430391Skarels break;
118530391Skarels
118634642Smarc case QD_PRGKBD:
118734642Smarc /*
118834642Smarc * pass caller's programming commands to LK201
118934642Smarc */
119034732Smarc duart = (struct duart *)qdmap[unit].duart;
119134732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */
119234642Smarc /*
119334642Smarc * send command
119434642Smarc */
119530391Skarels for (i = 1000; i > 0; --i) {
119634732Smarc if (duart->statusA&XMT_RDY) {
119734642Smarc duart->dataA = cmdbuf->cmd;
119834642Smarc break;
119934642Smarc }
120030391Skarels }
120130391Skarels if (i == 0) {
120234732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
120334642Smarc break;
120430391Skarels }
120534642Smarc /*
120634642Smarc * send param1?
120734642Smarc */
120830391Skarels if (cmdbuf->cmd & LAST_PARAM)
120934642Smarc break;
121030391Skarels for (i = 1000; i > 0; --i) {
121134732Smarc if (duart->statusA&XMT_RDY) {
121234642Smarc duart->dataA = cmdbuf->param1;
121334642Smarc break;
121434642Smarc }
121530391Skarels }
121630391Skarels if (i == 0) {
121734732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
121834642Smarc break;
121930391Skarels }
122034642Smarc /*
122134642Smarc * send param2?
122234642Smarc */
122330391Skarels if (cmdbuf->param1 & LAST_PARAM)
122430391Skarels break;
122530391Skarels for (i = 1000; i > 0; --i) {
122634732Smarc if (duart->statusA&XMT_RDY) {
122734642Smarc duart->dataA = cmdbuf->param2;
122834642Smarc break;
122934642Smarc }
123030391Skarels }
123130391Skarels if (i == 0) {
123234732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
123334642Smarc break;
123430391Skarels }
123530391Skarels break;
123630391Skarels
123734642Smarc case QD_PRGMOUSE:
123834642Smarc /*
123934642Smarc * pass caller's programming commands to the mouse
124034642Smarc */
124130391Skarels duart = (struct duart *) qdmap[unit].duart;
124230391Skarels for (i = 1000; i > 0; --i) {
124334732Smarc if (duart->statusB&XMT_RDY) {
124434642Smarc duart->dataB = *datap;
124534642Smarc break;
124634642Smarc }
124730391Skarels }
124830391Skarels if (i == 0) {
124934732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
125030391Skarels }
125130391Skarels break;
125230391Skarels
125334642Smarc case QD_RDCONFIG:
125434642Smarc /*
125534642Smarc * get QDSS configuration word and return it
125634642Smarc */
125730391Skarels *(short *)datap = qdflags[unit].config;
125830391Skarels break;
125930391Skarels
126034642Smarc case QD_KERN_LOOP:
126134642Smarc case QD_KERN_UNLOOP:
126234642Smarc /*
126334642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect
126434642Smarc * kernel console output.
126534642Smarc */
126634615Smarc break;
126734615Smarc
126834642Smarc case QD_PRGTABLET:
126934642Smarc /*
127034642Smarc * program the tablet
127134642Smarc */
127230391Skarels duart = (struct duart *) qdmap[unit].duart;
127330391Skarels for (i = 1000; i > 0; --i) {
127434732Smarc if (duart->statusB&XMT_RDY) {
127534642Smarc duart->dataB = *datap;
127634642Smarc break;
127734642Smarc }
127830391Skarels }
127930391Skarels if (i == 0) {
128034732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
128130391Skarels }
128230391Skarels break;
128330391Skarels
128434642Smarc case QD_PRGTABRES:
128534642Smarc /*
128634642Smarc * program the tablet report resolution factor
128734642Smarc */
128830391Skarels qdflags[unit].tab_res = *(short *)datap;
128930391Skarels break;
129030391Skarels
129134642Smarc default:
129234642Smarc /*
129334642Smarc * service tty ioctl's
129434642Smarc */
129534642Smarc if (!(minor_dev & 0x02)) {
129630391Skarels tp = &qd_tty[minor_dev];
129734642Smarc error =
129834642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
129930391Skarels if (error >= 0) {
130034642Smarc return(error);
130130391Skarels }
130230391Skarels error = ttioctl(tp, cmd, datap, flags);
130330391Skarels if (error >= 0) {
130434642Smarc return(error);
130530391Skarels }
130634642Smarc }
130734642Smarc break;
130830391Skarels }
130930391Skarels
131030391Skarels return(0);
131130391Skarels
131230391Skarels } /* qdioctl */
131330391Skarels
qdselect(dev,rw)131430391Skarels qdselect(dev, rw)
131534642Smarc dev_t dev;
131634642Smarc int rw;
131730391Skarels {
131834732Smarc register s;
131934732Smarc register unit;
132034615Smarc register struct tty *tp;
132134615Smarc u_int minor_dev = minor(dev);
132230391Skarels
132334615Smarc s = spl5();
132434615Smarc unit = minor_dev >> 2;
132530391Skarels
132630391Skarels switch (rw) {
132734642Smarc case FREAD:
132834642Smarc if ((minor_dev & 0x03) == 2) {
132934642Smarc /*
133034642Smarc * this is a graphics device, so check for events
133134642Smarc */
133234732Smarc if(!(ISEMPTY(eq_header[unit]))) {
133334642Smarc splx(s);
133434642Smarc return(1);
133534642Smarc }
133634732Smarc qdrsel[unit] = u.u_procp;
133734642Smarc qdflags[unit].selmask |= SEL_READ;
133834642Smarc splx(s);
133934642Smarc return(0);
134034642Smarc } else {
134134642Smarc /*
134234642Smarc * this is a tty device
134334642Smarc */
134434642Smarc tp = &qd_tty[minor_dev];
134534642Smarc if (ttnread(tp))
134634642Smarc return(1);
134734642Smarc tp->t_rsel = u.u_procp;
134834642Smarc splx(s);
134934642Smarc return(0);
135030391Skarels }
135130391Skarels
135234642Smarc case FWRITE:
135334642Smarc if ((minor(dev) & 0x03) == 2) {
135434642Smarc /*
135534642Smarc * this is a graphics device, so check for dma buffers
135634642Smarc */
135734642Smarc if (DMA_ISEMPTY(DMAheader[unit]))
135834642Smarc {
135934642Smarc splx(s);
136034642Smarc return(1);
136134642Smarc }
136234732Smarc qdrsel[unit] = u.u_procp;
136334642Smarc qdflags[unit].selmask |= SEL_WRITE;
136434642Smarc splx(s);
136534642Smarc return(0);
136634642Smarc } else {
136734642Smarc /*
136834642Smarc * this is a tty device
136934642Smarc */
137034642Smarc tp = &qd_tty[minor_dev];
137137605Smarc if (tp->t_outq.c_cc <= tp->t_lowat)
137234642Smarc return(1);
137334642Smarc tp->t_wsel = u.u_procp;
137434642Smarc splx(s);
137534642Smarc return(0);
137630391Skarels }
137730391Skarels }
137834732Smarc splx(s);
137934732Smarc return(0);
138030391Skarels
138130391Skarels } /* qdselect() */
138230391Skarels
138330391Skarels extern qd_strategy();
138430391Skarels
qdwrite(dev,uio)138530391Skarels qdwrite(dev, uio)
138634642Smarc dev_t dev;
138734642Smarc struct uio *uio;
138830391Skarels {
138930391Skarels register struct tty *tp;
139034732Smarc register minor_dev;
139134732Smarc register unit;
139230391Skarels
139330391Skarels minor_dev = minor(dev);
139430391Skarels unit = (minor_dev >> 2) & 0x07;
139530391Skarels
139634642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
139734642Smarc /*
139834642Smarc * this is the console...
139934642Smarc */
140034642Smarc tp = &qd_tty[minor_dev];
140134642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio));
140234642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
140334642Smarc /*
140434642Smarc * this is a DMA xfer from user space
140534642Smarc */
140634642Smarc return (physio(qd_strategy, &qdbuf[unit],
140734642Smarc dev, B_WRITE, minphys, uio));
140830391Skarels }
140934732Smarc return (ENXIO);
141030391Skarels }
141130391Skarels
qdread(dev,uio)141230391Skarels qdread(dev, uio)
141334642Smarc dev_t dev;
141434642Smarc struct uio *uio;
141530391Skarels {
141630391Skarels register struct tty *tp;
141734732Smarc register minor_dev;
141834732Smarc register unit;
141930391Skarels
142030391Skarels minor_dev = minor(dev);
142130391Skarels unit = (minor_dev >> 2) & 0x07;
142230391Skarels
142334642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
142434642Smarc /*
142534642Smarc * this is the console
142634642Smarc */
142734642Smarc tp = &qd_tty[minor_dev];
142834642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio));
142934642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
143034642Smarc /*
143134642Smarc * this is a bitmap-to-processor xfer
143234642Smarc */
143334642Smarc return (physio(qd_strategy, &qdbuf[unit],
143434642Smarc dev, B_READ, minphys, uio));
143530391Skarels }
143634732Smarc return (ENXIO);
143730391Skarels }
143830391Skarels
143930391Skarels /***************************************************************
144030391Skarels *
144130391Skarels * qd_strategy()... strategy routine to do DMA
144230391Skarels *
144330391Skarels ***************************************************************/
144430391Skarels
qd_strategy(bp)144530391Skarels qd_strategy(bp)
144634642Smarc register struct buf *bp;
144730391Skarels {
144830391Skarels register struct dga *dga;
144930391Skarels register struct adder *adder;
145034732Smarc register unit;
145130391Skarels int QBAreg;
145230391Skarels int s;
145330391Skarels int cookie;
145430391Skarels
145530391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07;
145630391Skarels
145734642Smarc /*
145834642Smarc * init pointers
145934642Smarc */
146030391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
146134732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit);
146234642Smarc goto STRAT_ERR;
146330391Skarels }
146430391Skarels dga = (struct dga *) qdmap[unit].dga;
146534615Smarc s = spl5();
146630391Skarels qdflags[unit].user_dma = -1;
146730391Skarels dga->csr |= DMA_IE;
146830391Skarels cookie = QBAreg & 0x3FFFF;
146930391Skarels dga->adrs_lo = (short) cookie;
147030391Skarels dga->adrs_hi = (short) (cookie >> 16);
147130391Skarels dga->bytcnt_lo = (short) bp->b_bcount;
147230391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
147330391Skarels
147430391Skarels while (qdflags[unit].user_dma) {
147534642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
147630391Skarels }
147730391Skarels splx(s);
147830391Skarels ubarelse(0, &QBAreg);
147930391Skarels if (!(dga->csr & DMA_ERR)) {
148034642Smarc iodone(bp);
148134642Smarc return;
148230391Skarels }
148330391Skarels
148430391Skarels STRAT_ERR:
148530391Skarels adder = (struct adder *) qdmap[unit].adder;
148634642Smarc adder->command = CANCEL; /* cancel adder activity */
148730391Skarels dga->csr &= ~DMA_IE;
148830391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
148930391Skarels dga->csr |= DMA_ERR; /* clear error condition */
149030391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */
149130391Skarels
149234642Smarc /*
149334642Smarc * if DMA was running, flush spurious intrpt
149434642Smarc */
149530391Skarels if (dga->bytcnt_lo != 0) {
149634642Smarc dga->bytcnt_lo = 0;
149734642Smarc dga->bytcnt_hi = 0;
149834642Smarc DMA_SETIGNORE(DMAheader[unit]);
149934642Smarc dga->csr |= DMA_IE;
150030391Skarels }
150130391Skarels iodone(bp);
150230391Skarels
150330391Skarels } /* qd_strategy */
150430391Skarels
150534732Smarc /*
150634732Smarc * Start output to the console screen
150734732Smarc */
qdstart(tp)150830391Skarels qdstart(tp)
150934642Smarc register struct tty *tp;
151030391Skarels {
151134732Smarc register which_unit, unit, c;
151230391Skarels int s;
151334615Smarc
151430391Skarels unit = minor(tp->t_dev);
151530391Skarels which_unit = (unit >> 2) & 0x3;
151634615Smarc unit &= 0x03;
151730391Skarels
151834615Smarc s = spl5();
151934615Smarc
152034642Smarc /*
152134642Smarc * If it's currently active, or delaying, no need to do anything.
152234642Smarc */
152330391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
152430391Skarels goto out;
152530391Skarels
152634642Smarc /*
152734642Smarc * Display chars until the queue is empty.
152834642Smarc * Drop input from anything but the console
152934642Smarc * device on the floor.
153034642Smarc *
153134642Smarc * XXX - this loop is done at spltty.
153234642Smarc *
153334642Smarc */
153434642Smarc while (tp->t_outq.c_cc) {
153534511Smarc c = getc(&tp->t_outq);
153634615Smarc if (unit == 0)
153734732Smarc blitc(which_unit, (u_char)c);
153830391Skarels }
153934642Smarc /*
154034642Smarc * If there are sleepers, and output has drained below low
154134642Smarc * water mark, wake up the sleepers.
154234642Smarc */
154337605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) {
154434615Smarc if (tp->t_state & TS_ASLEEP){
154534615Smarc tp->t_state &= ~TS_ASLEEP;
154634615Smarc wakeup((caddr_t) &tp->t_outq);
154734615Smarc }
154830391Skarels }
154930391Skarels
155034615Smarc tp->t_state &= ~TS_BUSY;
155134615Smarc
155230391Skarels out:
155330391Skarels splx(s);
155430391Skarels
155530391Skarels } /* qdstart */
155630391Skarels
155734732Smarc /*ARGSUSED*/
qdstop(tp,flag)155830391Skarels qdstop(tp, flag)
155934642Smarc register struct tty *tp;
156034642Smarc int flag;
156130391Skarels {
156230391Skarels register int s;
156330391Skarels
156434615Smarc s = spl5(); /* block intrpts during state modification */
156534732Smarc if (tp->t_state & TS_BUSY)
156634732Smarc if ((tp->t_state & TS_TTSTOP) == 0)
156734642Smarc tp->t_state |= TS_FLUSH;
156834642Smarc else
156934642Smarc tp->t_state &= ~TS_BUSY;
157030391Skarels splx(s);
157130391Skarels }
157230391Skarels
157334732Smarc /*
157434732Smarc * Output a character to the QDSS screen
157534732Smarc */
157630391Skarels
blitc(unit,chr)157730391Skarels blitc(unit, chr)
157834732Smarc register unit;
157934732Smarc register u_char chr;
158030391Skarels {
158130391Skarels register struct adder *adder;
158230391Skarels register struct dga *dga;
158330391Skarels register int i;
158434642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
158534642Smarc static short inescape[NQD];
158630391Skarels
158734732Smarc adder = (struct adder *)qdmap[unit].adder;
158830391Skarels dga = (struct dga *) qdmap[unit].dga;
158934642Smarc /*
159034642Smarc * BSD comment: this (&=0177) defeats the extended character
159134642Smarc * set code for the glass tty, but if i had the time i would
159234642Smarc * spend it ripping out the code completely. This driver
159334642Smarc * is too big for its own good.
159434642Smarc */
159534642Smarc chr &= 0177;
159634642Smarc /*
159734732Smarc * Cursor addressing (so vi will work).
159834642Smarc * Decode for "\E=%.%." cursor motion description.
159934732Smarc * Corresponds to type "qdcons" in /etc/termcap:
160034642Smarc *
160134642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
160234642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
160334642Smarc *
160434642Smarc */
160534642Smarc if (inescape[unit] && nograph) {
160634642Smarc switch (inescape[unit]++) {
160734642Smarc case 1:
160834642Smarc if (chr != '=') {
160934642Smarc /* abort escape sequence */
161034642Smarc inescape[unit] = 0;
161134642Smarc blitc(unit, chr);
161234642Smarc }
161334732Smarc return;
161434642Smarc case 2:
161534642Smarc /* position row */
161634642Smarc cursor[unit].y = CHAR_HEIGHT * chr;
161734642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT)
161834642Smarc cursor[unit].y = 863 - CHAR_HEIGHT;
161934642Smarc dga->y_cursor = TRANY(cursor[unit].y);
162034732Smarc return;
162134642Smarc case 3:
162234642Smarc /* position column */
162334642Smarc cursor[unit].x = CHAR_WIDTH * chr;
162434642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH)
162534642Smarc cursor[unit].x = 1023 - CHAR_WIDTH;
162634642Smarc dga->x_cursor = TRANX(cursor[unit].x);
162734642Smarc inescape[unit] = 0;
162834732Smarc return;
162934642Smarc default:
163034642Smarc inescape[unit] = 0;
163134642Smarc blitc(unit, chr);
163234642Smarc }
163334642Smarc }
163430391Skarels
163530391Skarels switch (chr) {
163634642Smarc case '\r': /* return char */
163730391Skarels cursor[unit].x = 0;
163834642Smarc if (nograph)
163934642Smarc dga->x_cursor = TRANX(cursor[unit].x);
164034732Smarc return;
164130391Skarels
164234642Smarc case '\t': /* tab char */
164330391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
164434642Smarc blitc(unit, ' ');
164530391Skarels }
164634732Smarc return;
164730391Skarels
164834642Smarc case '\n': /* line feed char */
164930391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
165034642Smarc if (nograph) {
165134642Smarc cursor[unit].y -= CHAR_HEIGHT;
165234642Smarc scroll_up(adder);
165334642Smarc } else
165434642Smarc cursor[unit].y = 0;
165530391Skarels }
165634642Smarc if (nograph)
165734642Smarc dga->y_cursor = TRANY(cursor[unit].y);
165834732Smarc return;
165930391Skarels
166034642Smarc case '\b': /* backspace char */
166130391Skarels if (cursor[unit].x > 0) {
166234642Smarc cursor[unit].x -= CHAR_WIDTH;
166334642Smarc if (nograph)
166434642Smarc dga->x_cursor = TRANX(cursor[unit].x);
166530391Skarels }
166634732Smarc return;
166734642Smarc case CTRL('k'): /* cursor up */
166834642Smarc if (nograph && cursor[unit].y > 0) {
166934642Smarc cursor[unit].y -= CHAR_HEIGHT;
167034642Smarc dga->y_cursor = TRANY(cursor[unit].y);
167134642Smarc }
167234732Smarc return;
167330391Skarels
167434642Smarc case CTRL('^'): /* home cursor */
167534642Smarc if (nograph) {
167634642Smarc cursor[unit].x = 0;
167734642Smarc dga->x_cursor = TRANX(cursor[unit].x);
167834642Smarc cursor[unit].y = 0;
167934642Smarc dga->y_cursor = TRANY(cursor[unit].y);
168034642Smarc }
168134732Smarc return;
168232012Smarc
168334642Smarc case CTRL('l'): /* cursor right */
168434642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
168534642Smarc cursor[unit].x += CHAR_WIDTH;
168634642Smarc dga->x_cursor = TRANX(cursor[unit].x);
168734642Smarc }
168834732Smarc return;
168930391Skarels
169034642Smarc case CTRL('z'): /* clear screen */
169134642Smarc if (nograph) {
169234642Smarc setup_dragon(unit);
169334642Smarc clear_qd_screen(unit);
169434642Smarc /* home cursor - termcap seems to assume this */
169534642Smarc cursor[unit].x = 0;
169634642Smarc dga->x_cursor = TRANX(cursor[unit].x);
169734642Smarc cursor[unit].y = 0;
169834642Smarc dga->y_cursor = TRANY(cursor[unit].y);
169934642Smarc }
170034732Smarc return;
170130391Skarels
170234642Smarc case '\033': /* start escape sequence */
170334642Smarc if (nograph)
170434642Smarc inescape[unit] = 1;
170534732Smarc return;
170634642Smarc
170734642Smarc default:
170834642Smarc if ((chr < ' ') || (chr > '~'))
170934732Smarc return;
171034642Smarc }
171134642Smarc /*
171234642Smarc * setup VIPER operand control registers
171334642Smarc */
171430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */
171530391Skarels write_ID(adder, SRC1_OCR_B,
171634642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
171730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */
171830391Skarels write_ID(adder, SRC1_OCR_B,
171934642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
172030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
172130391Skarels write_ID(adder, DST_OCR_B,
172234642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
172330391Skarels write_ID(adder, MASK_1, 0xFFFF);
172430391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
172530391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
172634642Smarc adder->x_clip_min = 0;
172734642Smarc adder->x_clip_max = 1024;
172834642Smarc adder->y_clip_min = 0;
172934642Smarc adder->y_clip_max = 864;
173034642Smarc /*
173134642Smarc * load DESTINATION origin and vectors
173234642Smarc */
173330391Skarels adder->fast_dest_dy = 0;
173430391Skarels adder->slow_dest_dx = 0;
173530391Skarels adder->error_1 = 0;
173630391Skarels adder->error_2 = 0;
173730391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
173834732Smarc (void)wait_status(adder, RASTEROP_COMPLETE);
173930391Skarels adder->destination_x = cursor[unit].x;
174030391Skarels adder->fast_dest_dx = CHAR_WIDTH;
174130391Skarels adder->destination_y = cursor[unit].y;
174230391Skarels adder->slow_dest_dy = CHAR_HEIGHT;
174334642Smarc /*
174434642Smarc * load SOURCE origin and vectors
174534642Smarc */
174634615Smarc if ((chr - ' ') > (CHARS - 1)) {
174734615Smarc printf("Invalid character (x)%x in blitc\n",chr);
174834615Smarc chr = ' ';
174934615Smarc }
175034642Smarc /*
175134642Smarc * X position is modulo the number of characters per line
175234642Smarc */
175334615Smarc adder->source_1_x = FONT_X +
175434642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
175534642Smarc /*
175634642Smarc * Point to either first or second row
175734642Smarc */
175834615Smarc adder->source_1_y = 2048 - 15 *
175934642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
176030391Skarels adder->source_1_dx = CHAR_WIDTH;
176130391Skarels adder->source_1_dy = CHAR_HEIGHT;
176230391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
176330391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
176434642Smarc /*
176534642Smarc * update console cursor coordinates
176634642Smarc */
176730391Skarels cursor[unit].x += CHAR_WIDTH;
176834642Smarc if (nograph)
176934642Smarc dga->x_cursor = TRANX(cursor[unit].x);
177030391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
177134642Smarc blitc(unit, '\r');
177234642Smarc blitc(unit, '\n');
177330391Skarels }
177430391Skarels
177530391Skarels } /* blitc */
177630391Skarels
qdreset()177734732Smarc qdreset() { }
177830391Skarels
177934732Smarc /*
178034732Smarc * INTERRUPT SERVICE ROUTINES
178134732Smarc */
178230391Skarels
178334732Smarc /*
178434732Smarc * Service "DMA DONE" interrupt condition
178534732Smarc */
qddint(qd)178630391Skarels qddint(qd)
178734732Smarc register qd;
178830391Skarels {
178930391Skarels register struct DMAreq_header *header;
179030391Skarels register struct DMAreq *request;
179130391Skarels register struct dga *dga;
179230391Skarels struct adder *adder;
179330391Skarels int cookie; /* DMA adrs for QDSS */
179430391Skarels
179534732Smarc (void)spl4(); /* allow interval timer in */
179630391Skarels
179734642Smarc /*
179834642Smarc * init pointers
179934642Smarc */
180030391Skarels header = DMAheader[qd]; /* register for optimization */
180130391Skarels dga = (struct dga *) qdmap[qd].dga;
180230391Skarels adder = (struct adder *) qdmap[qd].adder;
180330391Skarels
180434642Smarc /*
180534642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes..
180634642Smarc */
180730391Skarels if (DMA_ISIGNORE(header)) {
180834642Smarc DMA_CLRIGNORE(header);
180934642Smarc return;
181030391Skarels }
181130391Skarels
181234642Smarc /*
181334642Smarc * dump a DMA hardware error message if appropriate
181434642Smarc */
181530391Skarels if (dga->csr & DMA_ERR) {
181630391Skarels
181734642Smarc if (dga->csr & PARITY_ERR)
181834732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
181930391Skarels
182034642Smarc if (dga->csr & BUS_ERR)
182134732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd);
182230391Skarels }
182330391Skarels
182434642Smarc /*
182534642Smarc * if this was a DMA from user space...
182634642Smarc */
182730391Skarels if (qdflags[qd].user_dma) {
182834642Smarc qdflags[qd].user_dma = 0;
182934642Smarc wakeup((caddr_t)&qdflags[qd].user_dma);
183034642Smarc return;
183130391Skarels }
183230391Skarels
183334642Smarc /*
183434642Smarc * if we're doing DMA request queue services, field the error condition
183534642Smarc */
183630391Skarels if (dga->csr & DMA_ERR) {
183730391Skarels
183834642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
183934642Smarc dga->csr |= DMA_ERR; /* clear error condition */
184034642Smarc adder->command = CANCEL; /* cancel adder activity */
184130391Skarels
184234642Smarc DMA_SETERROR(header); /* flag error in header status word */
184334642Smarc DMA_CLRACTIVE(header);
184434642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
184534642Smarc header->newest = header->oldest;
184634642Smarc header->used = 0;
184730391Skarels
184834732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
184934732Smarc selwakeup(qdrsel[qd], 0);
185034732Smarc qdrsel[qd] = 0;
185134642Smarc qdflags[qd].selmask &= ~SEL_WRITE;
185234642Smarc }
185330391Skarels
185434642Smarc if (dga->bytcnt_lo != 0) {
185534642Smarc dga->bytcnt_lo = 0;
185634642Smarc dga->bytcnt_hi = 0;
185734642Smarc DMA_SETIGNORE(header);
185834642Smarc }
185934642Smarc return;
186030391Skarels }
186130391Skarels
186234642Smarc /*
186334642Smarc * if the DMA request queue is now becoming non-full,
186434642Smarc * wakeup "select" client.
186534642Smarc */
186630391Skarels if (DMA_ISFULL(header)) {
186734732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
186834732Smarc selwakeup(qdrsel[qd], 0);
186934732Smarc qdrsel[qd] = 0;
187034642Smarc qdflags[qd].selmask &= ~SEL_WRITE;
187134642Smarc }
187230391Skarels }
187330391Skarels
187430391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
187534642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
187630391Skarels
187734615Smarc /* check for unexpected interrupt */
187834615Smarc if (DMA_ISEMPTY(header))
187930391Skarels return;
188030391Skarels
188130391Skarels DMA_GETEND(header); /* update request queue indices */
188230391Skarels
188334642Smarc /*
188434732Smarc * if no more DMA pending, wake up "select" client and exit
188534732Smarc */
188630391Skarels if (DMA_ISEMPTY(header)) {
188730391Skarels
188834732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
188934732Smarc selwakeup(qdrsel[qd], 0);
189034732Smarc qdrsel[qd] = 0;
189134642Smarc qdflags[qd].selmask &= ~SEL_WRITE;
189234642Smarc }
189330391Skarels
189434642Smarc DMA_CLRACTIVE(header); /* flag DMA done */
189534642Smarc return;
189630391Skarels }
189730391Skarels
189834642Smarc /*
189934732Smarc * initiate next DMA xfer
190034732Smarc */
190130391Skarels request = DMA_GETBEGIN(header);
190234615Smarc if (request->DMAtype != QDlast_DMAtype) {
190334642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
190434642Smarc adder->command = CANCEL; /* cancel adder activity */
190534615Smarc }
190630391Skarels
190734615Smarc
190830391Skarels switch (request->DMAtype) {
190930391Skarels
191034642Smarc case DISPLIST:
191134615Smarc if (request->DMAtype != QDlast_DMAtype) {
191234615Smarc dga->csr |= DL_ENB;
191334615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA);
191434615Smarc }
191530391Skarels break;
191630391Skarels
191734642Smarc case PTOB:
191834615Smarc if (request->DMAtype != QDlast_DMAtype) {
191934615Smarc if (request->DMAdone & BYTE_PACK)
192034642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA);
192134615Smarc else {
192234615Smarc dga->csr |= PTOB_ENB;
192334615Smarc dga->csr &= ~BYTE_DMA;
192434615Smarc }
192534615Smarc }
192630391Skarels break;
192730391Skarels
192834642Smarc case BTOP:
192934615Smarc if (request->DMAtype != QDlast_DMAtype) {
193034615Smarc if (request->DMAdone & BYTE_PACK) {
193134615Smarc dga->csr &= ~DL_ENB;
193234615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA);
193334615Smarc }
193434615Smarc else {
193534615Smarc dga->csr |= BTOP_ENB;
193634615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB);
193734615Smarc }
193834615Smarc }
193930391Skarels break;
194034642Smarc default:
194134732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
194230391Skarels DMA_CLRACTIVE(header); /* flag DMA done */
194330391Skarels return;
194430391Skarels }
194530391Skarels
194630391Skarels if (request->DMAdone & COUNT_ZERO) {
194734642Smarc dga->csr &= ~SET_DONE_FIFO;
194834642Smarc }
194934642Smarc else if (request->DMAdone & FIFO_EMPTY) {
195034642Smarc dga->csr |= SET_DONE_FIFO;
195130391Skarels }
195230391Skarels
195330391Skarels if (request->DMAdone & WORD_PACK)
195430391Skarels dga->csr &= ~BYTE_DMA;
195530391Skarels else if (request->DMAdone & BYTE_PACK)
195630391Skarels dga->csr |= BYTE_DMA;
195730391Skarels
195830391Skarels dga->csr |= DMA_IE;
195934642Smarc QDlast_DMAtype = request->DMAtype;
196030391Skarels
196130391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
196230391Skarels
196330391Skarels dga->adrs_lo = (short) cookie;
196430391Skarels dga->adrs_hi = (short) (cookie >> 16);
196530391Skarels
196630391Skarels dga->bytcnt_lo = (short) request->length;
196730391Skarels dga->bytcnt_hi = (short) (request->length >> 16);
196830391Skarels
196930391Skarels return;
197030391Skarels }
197130391Skarels
197234732Smarc /*
197334732Smarc * ADDER interrupt service routine
197434732Smarc */
qdaint(qd)197530391Skarels qdaint(qd)
197634732Smarc register qd;
197730391Skarels {
197830391Skarels register struct adder *adder;
197930391Skarels struct color_buf *cbuf;
198030391Skarels int i;
198130391Skarels register struct rgb *rgbp;
198230391Skarels register short *red;
198330391Skarels register short *green;
198430391Skarels register short *blue;
198530391Skarels
198634732Smarc (void)spl4(); /* allow interval timer in */
198730391Skarels
198830391Skarels adder = (struct adder *) qdmap[qd].adder;
198930391Skarels
199034642Smarc /*
199134642Smarc * service the vertical blank interrupt (VSYNC bit) by loading
199234642Smarc * any pending color map load request
199334642Smarc */
199430391Skarels if (adder->status & VSYNC) {
199534642Smarc adder->status &= ~VSYNC; /* clear the interrupt */
199634642Smarc cbuf = color_buf[qd];
199734642Smarc if (cbuf->status & LOAD_COLOR_MAP) {
199830391Skarels
199934642Smarc red = (short *) qdmap[qd].red;
200034642Smarc green = (short *) qdmap[qd].green;
200134642Smarc blue = (short *) qdmap[qd].blue;
200230391Skarels
200334642Smarc for (i = cbuf->count, rgbp = cbuf->rgb;
200434642Smarc --i >= 0; rgbp++) {
200534642Smarc red[rgbp->offset] = (short) rgbp->red;
200634642Smarc green[rgbp->offset] = (short) rgbp->green;
200734642Smarc blue[rgbp->offset] = (short) rgbp->blue;
200834642Smarc }
200930391Skarels
201034642Smarc cbuf->status &= ~LOAD_COLOR_MAP;
201130391Skarels }
201230391Skarels }
201330391Skarels
201434642Smarc /*
201534642Smarc * service the scroll interrupt (FRAME_SYNC bit)
201634642Smarc */
201730391Skarels if (adder->status & FRAME_SYNC) {
201834642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */
201930391Skarels
202034642Smarc if (scroll[qd]->status & LOAD_REGS) {
202130391Skarels
202234732Smarc for (i = 1000, adder->status = 0; i > 0 &&
202334732Smarc !(adder->status&ID_SCROLL_READY); --i)
202434642Smarc ;
202530391Skarels
202634642Smarc if (i == 0) {
202734732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
202834642Smarc qd);
202934642Smarc return;
203034642Smarc }
203130391Skarels
203234642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant;
203334642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
203430391Skarels
203534642Smarc adder->y_scroll_constant =
203634642Smarc scroll[qd]->y_scroll_constant;
203734642Smarc adder->y_offset_pending = scroll[qd]->y_offset;
203830391Skarels
203934642Smarc if (scroll[qd]->status & LOAD_INDEX) {
204030391Skarels
204134642Smarc adder->x_index_pending =
204234642Smarc scroll[qd]->x_index_pending;
204334642Smarc adder->y_index_pending =
204434642Smarc scroll[qd]->y_index_pending;
204534642Smarc }
204634642Smarc
204734642Smarc scroll[qd]->status = 0x00;
204830391Skarels }
204930391Skarels }
205030391Skarels }
205130391Skarels
205234732Smarc /*
205334732Smarc * DUART input interrupt service routine
205434732Smarc *
205534732Smarc * XXX - this routine should be broken out - it is essentially
205634732Smarc * straight line code.
205734732Smarc */
205830391Skarels
qdiint(qd)205930391Skarels qdiint(qd)
206034732Smarc register qd;
206130391Skarels {
206230391Skarels register struct _vs_event *event;
206330391Skarels register struct qdinput *eqh;
206430391Skarels struct dga *dga;
206530391Skarels struct duart *duart;
206630391Skarels struct mouse_report *new_rep;
206730391Skarels struct uba_device *ui;
206830391Skarels struct tty *tp;
206934615Smarc u_short chr;
207030391Skarels u_short status;
207130391Skarels u_short data;
207230391Skarels u_short key;
207330391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */
207430391Skarels char a, b, c; /* mouse button test variables */
207530391Skarels
207634732Smarc (void)spl4(); /* allow interval timer in */
207730391Skarels
207830391Skarels eqh = eq_header[qd]; /* optimized as a register */
207930391Skarels new_rep = ¤t_rep[qd];
208030391Skarels duart = (struct duart *) qdmap[qd].duart;
208130391Skarels
208234642Smarc /*
208334732Smarc * if the graphic device is turned on..
208434732Smarc */
208530391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) {
208634642Smarc /*
208734642Smarc * empty DUART
208834642Smarc */
208934732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
209034642Smarc /*
209134732Smarc * pick up LK-201 input (if any)
209234732Smarc */
209334732Smarc if (duart->statusA&RCV_RDY) {
209430391Skarels
209534642Smarc /* if error condition, then reset it */
209630391Skarels
209734732Smarc if (duart->statusA&0x70) {
209834642Smarc duart->cmdA = 0x40;
209934642Smarc continue;
210034642Smarc }
210130391Skarels
210234642Smarc /* event queue full now? (overflow condition) */
210330391Skarels
210434642Smarc if (ISFULL(eqh) == TRUE) {
210534642Smarc printf(
210634732Smarc "qd%d: qdiint: event queue overflow\n",
210734642Smarc qd);
210834642Smarc break;
210934642Smarc }
211030391Skarels
211134642Smarc /*
211234642Smarc * Check for various keyboard errors */
211330391Skarels
211434642Smarc key = duart->dataA & 0xFF;
211530391Skarels
211634642Smarc if (key==LK_POWER_ERROR ||
211734642Smarc key==LK_KDOWN_ERROR ||
211834642Smarc key == LK_INPUT_ERROR ||
211934642Smarc key == LK_OUTPUT_ERROR) {
212034642Smarc printf(
212134732Smarc "qd%d: qdiint: keyboard error, code = %x\n",
212234642Smarc qd,key);
212334732Smarc return;
212434642Smarc }
212530391Skarels
212634642Smarc if (key < LK_LOWEST)
212734732Smarc return;
212830391Skarels
212934642Smarc ++do_wakeup; /* request a select wakeup call */
213030391Skarels
213134642Smarc event = PUTBEGIN(eqh);
213234642Smarc PUTEND(eqh);
213330391Skarels
213434642Smarc event->vse_key = key;
213534642Smarc event->vse_key &= 0x00FF;
213634642Smarc event->vse_x = eqh->curs_pos.x;
213734642Smarc event->vse_y = eqh->curs_pos.y;
213834642Smarc event->vse_time = TOY;
213934642Smarc event->vse_type = VSE_BUTTON;
214034642Smarc event->vse_direction = VSE_KBTRAW;
214134642Smarc event->vse_device = VSE_DKB;
214234642Smarc }
214330391Skarels
214434642Smarc /*
214534642Smarc * pick up the mouse input (if any) */
214630391Skarels
214734642Smarc if ((status = duart->statusB) & RCV_RDY &&
214834642Smarc qdflags[qd].pntr_id == MOUSE_ID) {
214930391Skarels
215034642Smarc if (status & 0x70) {
215134642Smarc duart->cmdB = 0x40;
215234642Smarc continue;
215334642Smarc }
215430391Skarels
215534642Smarc /* event queue full now? (overflow condition) */
215630391Skarels
215734642Smarc if (ISFULL(eqh) == TRUE) {
215834642Smarc printf(
215934732Smarc "qd%d: qdiint: event queue overflow\n",
216034642Smarc qd);
216134642Smarc break;
216234642Smarc }
216330391Skarels
216434642Smarc data = duart->dataB; /* get report byte */
216534642Smarc ++new_rep->bytcnt; /* bump report byte count */
216630391Skarels
216734642Smarc /*
216834642Smarc * if 1st byte of report.. */
216930391Skarels
217034642Smarc if ( data & START_FRAME) {
217134642Smarc new_rep->state = data;
217234642Smarc if (new_rep->bytcnt > 1) {
217334642Smarc /* start of new frame */
217434642Smarc new_rep->bytcnt = 1;
217534642Smarc /* ..continue looking */
217634642Smarc continue;
217734642Smarc }
217834642Smarc }
217930391Skarels
218034642Smarc /*
218134642Smarc * if 2nd byte of report.. */
218230391Skarels
218334642Smarc else if (new_rep->bytcnt == 2) {
218434642Smarc new_rep->dx = data & 0x00FF;
218534642Smarc }
218630391Skarels
218734642Smarc /*
218834642Smarc * if 3rd byte of report, load input event queue */
218930391Skarels
219034642Smarc else if (new_rep->bytcnt == 3) {
219130391Skarels
219234642Smarc new_rep->dy = data & 0x00FF;
219334642Smarc new_rep->bytcnt = 0;
219430391Skarels
219534642Smarc /*
219634642Smarc * if mouse position has changed.. */
219730391Skarels
219834642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) {
219930391Skarels
220034642Smarc /*
220134642Smarc * calculate acceleration factor, if needed */
220230391Skarels
220334642Smarc if (qdflags[qd].curs_acc > ACC_OFF) {
220430391Skarels
220534642Smarc if (qdflags[qd].curs_thr <= new_rep->dx)
220634642Smarc new_rep->dx +=
220734642Smarc (new_rep->dx - qdflags[qd].curs_thr)
220834642Smarc * qdflags[qd].curs_acc;
220930391Skarels
221034642Smarc if (qdflags[qd].curs_thr <= new_rep->dy)
221134642Smarc new_rep->dy +=
221234642Smarc (new_rep->dy - qdflags[qd].curs_thr)
221334642Smarc * qdflags[qd].curs_acc;
221434642Smarc }
221530391Skarels
221634642Smarc /*
221734642Smarc * update cursor position coordinates */
221830391Skarels
221934642Smarc if (new_rep->state & X_SIGN) {
222034642Smarc eqh->curs_pos.x += new_rep->dx;
222134642Smarc if (eqh->curs_pos.x > 1023)
222234642Smarc eqh->curs_pos.x = 1023;
222334642Smarc }
222434642Smarc else {
222534642Smarc eqh->curs_pos.x -= new_rep->dx;
222634642Smarc if (eqh->curs_pos.x < -15)
222734642Smarc eqh->curs_pos.x = -15;
222834642Smarc }
222930391Skarels
223034642Smarc if (new_rep->state & Y_SIGN) {
223134642Smarc eqh->curs_pos.y -= new_rep->dy;
223234642Smarc if (eqh->curs_pos.y < -15)
223334642Smarc eqh->curs_pos.y = -15;
223434642Smarc }
223534642Smarc else {
223634642Smarc eqh->curs_pos.y += new_rep->dy;
223734642Smarc if (eqh->curs_pos.y > 863)
223834642Smarc eqh->curs_pos.y = 863;
223934642Smarc }
224030391Skarels
224134642Smarc /*
224234642Smarc * update cursor screen position */
224330391Skarels
224434642Smarc dga = (struct dga *) qdmap[qd].dga;
224534642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x);
224634642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y);
224730391Skarels
224834642Smarc /*
224934642Smarc * if cursor is in the box, no event report */
225030391Skarels
225134642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right &&
225234642Smarc eqh->curs_pos.x >= eqh->curs_box.left &&
225334642Smarc eqh->curs_pos.y >= eqh->curs_box.top &&
225434642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) {
225534642Smarc goto GET_MBUTTON;
225634642Smarc }
225730391Skarels
225834642Smarc /*
225934642Smarc * report the mouse motion event */
226030391Skarels
226134642Smarc event = PUTBEGIN(eqh);
226234642Smarc PUTEND(eqh);
226330391Skarels
226434642Smarc ++do_wakeup; /* request a select wakeup call */
226530391Skarels
226634642Smarc event->vse_x = eqh->curs_pos.x;
226734642Smarc event->vse_y = eqh->curs_pos.y;
226830391Skarels
226934642Smarc event->vse_device = VSE_MOUSE; /* mouse */
227034642Smarc event->vse_type = VSE_MMOTION; /* pos changed */
227134642Smarc event->vse_key = 0;
227234642Smarc event->vse_direction = 0;
227334642Smarc event->vse_time = TOY; /* time stamp */
227434642Smarc }
227530391Skarels
227630391Skarels GET_MBUTTON:
227734642Smarc /*
227834642Smarc * if button state has changed */
227930391Skarels
228034642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */
228134642Smarc b = last_rep[qd].state & 0x07;
228230391Skarels
228334642Smarc if (a ^ b) {
228430391Skarels
228534642Smarc for ( c = 1; c < 8; c <<= 1) {
228630391Skarels
228734642Smarc if (!( c & (a ^ b))) /* this button change? */
228834642Smarc continue;
228930391Skarels
229034642Smarc /* event queue full? (overflow condition) */
229130391Skarels
229234642Smarc if (ISFULL(eqh) == TRUE) {
229334732Smarc printf("qd%d: qdiint: event queue overflow\n", qd);
229434642Smarc break;
229534642Smarc }
229630391Skarels
229734642Smarc event = PUTBEGIN(eqh); /* get new event */
229834642Smarc PUTEND(eqh);
229930391Skarels
230034642Smarc ++do_wakeup; /* request select wakeup */
230130391Skarels
230234642Smarc event->vse_x = eqh->curs_pos.x;
230334642Smarc event->vse_y = eqh->curs_pos.y;
230430391Skarels
230534642Smarc event->vse_device = VSE_MOUSE; /* mouse */
230634642Smarc event->vse_type = VSE_BUTTON; /* new button */
230734642Smarc event->vse_time = TOY; /* time stamp */
230830391Skarels
230934642Smarc /* flag changed button and if up or down */
231030391Skarels
231134642Smarc if (c == RIGHT_BUTTON)
231234642Smarc event->vse_key = VSE_RIGHT_BUTTON;
231334642Smarc else if (c == MIDDLE_BUTTON)
231434642Smarc event->vse_key = VSE_MIDDLE_BUTTON;
231534642Smarc else if (c == LEFT_BUTTON)
231634642Smarc event->vse_key = VSE_LEFT_BUTTON;
231730391Skarels
231834642Smarc /* set bit = button depressed */
231930391Skarels
232034642Smarc if (c & a)
232134642Smarc event->vse_direction = VSE_KBTDOWN;
232234642Smarc else
232334642Smarc event->vse_direction = VSE_KBTUP;
232434642Smarc }
232534642Smarc }
232630391Skarels
232734642Smarc /* refresh last report */
232830391Skarels
232934642Smarc last_rep[qd] = current_rep[qd];
233030391Skarels
233134642Smarc } /* get last byte of report */
233234732Smarc } else if ((status = duart->statusB)&RCV_RDY &&
233334732Smarc qdflags[qd].pntr_id == TABLET_ID) {
233434732Smarc /*
233534732Smarc * pickup tablet input, if any
233634732Smarc */
233734732Smarc if (status&0x70) {
233834642Smarc duart->cmdB = 0x40;
233934642Smarc continue;
234034642Smarc }
234134732Smarc /*
234234732Smarc * event queue full now? (overflow condition)
234334732Smarc */
234434642Smarc if (ISFULL(eqh) == TRUE) {
234534732Smarc printf("qd%d: qdiint: event queue overflow\n", qd);
234634642Smarc break;
234734642Smarc }
234830391Skarels
234934642Smarc data = duart->dataB; /* get report byte */
235034642Smarc ++new_rep->bytcnt; /* bump report byte count */
235130391Skarels
235234642Smarc /*
235334642Smarc * if 1st byte of report.. */
235430391Skarels
235534642Smarc if (data & START_FRAME) {
235634642Smarc new_rep->state = data;
235734642Smarc if (new_rep->bytcnt > 1) {
235834642Smarc new_rep->bytcnt = 1; /* start of new frame */
235934642Smarc continue; /* ..continue looking */
236034642Smarc }
236134642Smarc }
236230391Skarels
236334642Smarc /*
236434642Smarc * if 2nd byte of report.. */
236530391Skarels
236634642Smarc else if (new_rep->bytcnt == 2) {
236734642Smarc new_rep->dx = data & 0x3F;
236834642Smarc }
236930391Skarels
237034642Smarc /*
237134642Smarc * if 3rd byte of report.. */
237230391Skarels
237334642Smarc else if (new_rep->bytcnt == 3) {
237434642Smarc new_rep->dx |= (data & 0x3F) << 6;
237534642Smarc }
237630391Skarels
237734642Smarc /*
237834642Smarc * if 4th byte of report.. */
237930391Skarels
238034642Smarc else if (new_rep->bytcnt == 4) {
238134642Smarc new_rep->dy = data & 0x3F;
238234642Smarc }
238330391Skarels
238434642Smarc /*
238534642Smarc * if 5th byte of report, load input event queue */
238630391Skarels
238734642Smarc else if (new_rep->bytcnt == 5) {
238830391Skarels
238934642Smarc new_rep->dy |= (data & 0x3F) << 6;
239034642Smarc new_rep->bytcnt = 0;
239130391Skarels
239234642Smarc /*
239334642Smarc * update cursor position coordinates */
239430391Skarels
239534642Smarc new_rep->dx /= qdflags[qd].tab_res;
239634642Smarc new_rep->dy = (2200 - new_rep->dy)
239734642Smarc / qdflags[qd].tab_res;
239830391Skarels
239934642Smarc if (new_rep->dx > 1023) {
240034642Smarc new_rep->dx = 1023;
240134642Smarc }
240234642Smarc if (new_rep->dy > 863) {
240334642Smarc new_rep->dy = 863;
240434642Smarc }
240530391Skarels
240634642Smarc /*
240734642Smarc * report an event if the puck/stylus has moved
240834642Smarc */
240930391Skarels
241034642Smarc if (eqh->curs_pos.x != new_rep->dx ||
241134642Smarc eqh->curs_pos.y != new_rep->dy) {
241230391Skarels
241334642Smarc eqh->curs_pos.x = new_rep->dx;
241434642Smarc eqh->curs_pos.y = new_rep->dy;
241530391Skarels
241634642Smarc /*
241734642Smarc * update cursor screen position */
241830391Skarels
241934642Smarc dga = (struct dga *) qdmap[qd].dga;
242034642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x);
242134642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y);
242230391Skarels
242334642Smarc /*
242434642Smarc * if cursor is in the box, no event report
242534642Smarc */
242630391Skarels
242734642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right &&
242834642Smarc eqh->curs_pos.x >= eqh->curs_box.left &&
242934642Smarc eqh->curs_pos.y >= eqh->curs_box.top &&
243034642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) {
243134642Smarc goto GET_TBUTTON;
243234642Smarc }
243330391Skarels
243434642Smarc /*
243534642Smarc * report the tablet motion event */
243630391Skarels
243734642Smarc event = PUTBEGIN(eqh);
243834642Smarc PUTEND(eqh);
243930391Skarels
244034642Smarc ++do_wakeup; /* request a select wakeup call */
244130391Skarels
244234642Smarc event->vse_x = eqh->curs_pos.x;
244334642Smarc event->vse_y = eqh->curs_pos.y;
244430391Skarels
244534642Smarc event->vse_device = VSE_TABLET; /* tablet */
244634642Smarc /*
244734642Smarc * right now, X handles tablet motion the same
244834642Smarc * as mouse motion
244934642Smarc */
245034642Smarc event->vse_type = VSE_MMOTION; /* pos changed */
245134642Smarc event->vse_key = 0;
245234642Smarc event->vse_direction = 0;
245334642Smarc event->vse_time = TOY; /* time stamp */
245434642Smarc }
245530391Skarels GET_TBUTTON:
245634642Smarc /*
245734642Smarc * if button state has changed */
245830391Skarels
245934642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */
246034642Smarc b = last_rep[qd].state & 0x1E;
246130391Skarels
246234642Smarc if (a ^ b) {
246330391Skarels
246434642Smarc /* event queue full now? (overflow condition) */
246530391Skarels
246634642Smarc if (ISFULL(eqh) == TRUE) {
246734732Smarc printf("qd%d: qdiint: event queue overflow\n",qd);
246834642Smarc break;
246934642Smarc }
247030391Skarels
247134642Smarc event = PUTBEGIN(eqh); /* get new event */
247234642Smarc PUTEND(eqh);
247330391Skarels
247434642Smarc ++do_wakeup; /* request a select wakeup call */
247530391Skarels
247634642Smarc event->vse_x = eqh->curs_pos.x;
247734642Smarc event->vse_y = eqh->curs_pos.y;
247830391Skarels
247934642Smarc event->vse_device = VSE_TABLET; /* tablet */
248034642Smarc event->vse_type = VSE_BUTTON; /* button changed */
248134642Smarc event->vse_time = TOY; /* time stamp */
248230391Skarels
248334642Smarc /* define the changed button and if up or down */
248430391Skarels
248534642Smarc for ( c = 1; c <= 0x10; c <<= 1) {
248634642Smarc if (c & (a ^ b)) {
248734642Smarc if (c == T_LEFT_BUTTON)
248834642Smarc event->vse_key = VSE_T_LEFT_BUTTON;
248934642Smarc else if (c == T_FRONT_BUTTON)
249034642Smarc event->vse_key = VSE_T_FRONT_BUTTON;
249134642Smarc else if (c == T_RIGHT_BUTTON)
249234642Smarc event->vse_key = VSE_T_RIGHT_BUTTON;
249334642Smarc else if (c == T_BACK_BUTTON)
249434642Smarc event->vse_key = VSE_T_BACK_BUTTON;
249534642Smarc break;
249634642Smarc }
249734642Smarc }
249830391Skarels
249934642Smarc /* set bit = button depressed */
250030391Skarels
250134642Smarc if (c & a)
250234642Smarc event->vse_direction = VSE_KBTDOWN;
250334642Smarc else
250434642Smarc event->vse_direction = VSE_KBTUP;
250534642Smarc }
250630391Skarels
250734642Smarc /* refresh last report */
250830391Skarels
250934642Smarc last_rep[qd] = current_rep[qd];
251030391Skarels
251134642Smarc } /* get last byte of report */
251234642Smarc } /* pick up tablet input */
251330391Skarels
251434642Smarc } /* while input available.. */
251530391Skarels
251634642Smarc /*
251734642Smarc * do select wakeup
251834642Smarc */
251934732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
252034732Smarc selwakeup(qdrsel[qd], 0);
252134732Smarc qdrsel[qd] = 0;
252234642Smarc qdflags[qd].selmask &= ~SEL_READ;
252334642Smarc do_wakeup = 0;
252434642Smarc }
252534732Smarc } else {
252634732Smarc /*
252734732Smarc * if the graphic device is not turned on, this is console input
252834732Smarc */
252940817Smarc if (qdpolling)
253040817Smarc return;
253134642Smarc ui = qdinfo[qd];
253234642Smarc if (ui == 0 || ui->ui_alive == 0)
253334732Smarc return;
253430391Skarels
253534642Smarc tp = &qd_tty[qd << 2];
253630391Skarels
253734642Smarc /*
253834732Smarc * Get a character from the keyboard.
253934732Smarc */
254034732Smarc while (duart->statusA&RCV_RDY) {
254134642Smarc key = duart->dataA;
254234642Smarc key &= 0xFF;
254334642Smarc /*
254434732Smarc * Check for various keyboard errors
254534732Smarc */
254634732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
254734642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
254834732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
254934732Smarc return;
255034642Smarc }
255130391Skarels
255234642Smarc if (key < LK_LOWEST)
255334732Smarc return;
255430391Skarels
255534642Smarc /*
255634642Smarc * See if its a state change key */
255730391Skarels
255834642Smarc switch (key) {
255930391Skarels
256034642Smarc case LOCK:
256134642Smarc q_keyboard.lock ^= 0xffff; /* toggle */
256234642Smarc if (q_keyboard.lock)
256334732Smarc (void)led_control(qd, LK_LED_ENABLE,
256434732Smarc LK_LED_LOCK);
256534642Smarc else
256634732Smarc (void)led_control(qd, LK_LED_DISABLE,
256734732Smarc LK_LED_LOCK);
256834642Smarc return;
256930391Skarels
257034642Smarc case SHIFT:
257134642Smarc q_keyboard.shift ^= 0xFFFF;
257234642Smarc return;
257330391Skarels
257434642Smarc case CNTRL:
257534642Smarc q_keyboard.cntrl ^= 0xFFFF;
257634642Smarc return;
257730391Skarels
257834642Smarc case ALLUP:
257934642Smarc q_keyboard.cntrl = 0;
258034642Smarc q_keyboard.shift = 0;
258134642Smarc return;
258230391Skarels
258334642Smarc case REPEAT:
258434642Smarc chr = q_keyboard.last;
258534642Smarc break;
258630391Skarels
258734642Smarc /*
258834642Smarc * Test for cntrl characters. If set, see if the character
258934642Smarc * is elligible to become a control character. */
259030391Skarels
259134642Smarc default:
259230391Skarels
259334642Smarc if (q_keyboard.cntrl) {
259434642Smarc chr = q_key[key];
259534642Smarc if (chr >= ' ' && chr <= '~')
259634642Smarc chr &= 0x1F;
259734642Smarc else if (chr >= 0xA1 && chr <= 0xFE)
259834642Smarc chr &= 0x9F;
259934642Smarc }
260034642Smarc else if( q_keyboard.lock || q_keyboard.shift )
260134642Smarc chr = q_shift_key[key];
260234642Smarc else
260334642Smarc chr = q_key[key];
260434642Smarc break;
260530391Skarels }
260630391Skarels
260734642Smarc q_keyboard.last = chr;
260830391Skarels
260934642Smarc /*
261034642Smarc * Check for special function keys */
261130391Skarels
261234642Smarc if (chr & 0x100) {
261334642Smarc char *string;
261434642Smarc string = q_special[chr & 0x7F];
261534642Smarc while(*string)
261634642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp);
261734615Smarc }
261834642Smarc else {
261940817Smarc #ifdef KADB
262040817Smarc if (!kdbrintr(chr&0177, tp))
262140817Smarc #endif
262234642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp);
262334642Smarc }
262430391Skarels }
262530391Skarels }
262630391Skarels } /* qdiint */
262730391Skarels
262834732Smarc /*
262934732Smarc *
263034732Smarc * Clear the QDSS screen
263134732Smarc *
263234732Smarc * >>> NOTE <<<
263334732Smarc *
263434732Smarc * This code requires that certain adder initialization be valid. To
263534732Smarc * assure that this requirement is satisfied, this routine should be
263634732Smarc * called only after calling the "setup_dragon()" function.
263734732Smarc *
263834732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear
263934732Smarc * only clears the current displayed portion of the bitmap put a
264034732Smarc * temporary value in the y limit register so we can access whole
264134732Smarc * bitmap
264234732Smarc *
264334732Smarc */
clear_qd_screen(unit)264430391Skarels clear_qd_screen(unit)
264534732Smarc int unit;
264630391Skarels {
264730391Skarels register struct adder *adder;
264830391Skarels adder = (struct adder *) qdmap[unit].adder;
264930391Skarels
265030391Skarels adder->x_limit = 1024;
265130391Skarels adder->y_limit = 2048 - CHAR_HEIGHT;
265230391Skarels adder->y_offset_pending = 0;
265334732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
265434642Smarc WSV;
265530391Skarels adder->y_scroll_constant = SCROLL_ERASE;
265634642Smarc WSV;
265730391Skarels adder->y_offset_pending = 864;
265834642Smarc WSV;
265930391Skarels adder->y_scroll_constant = SCROLL_ERASE;
266034642Smarc WSV;
266130391Skarels adder->y_offset_pending = 1728;
266234642Smarc WSV;
266330391Skarels adder->y_scroll_constant = SCROLL_ERASE;
266434642Smarc WSV;
266530391Skarels adder->y_offset_pending = 0; /* back to normal */
266634642Smarc WSV;
266730391Skarels adder->x_limit = MAX_SCREEN_X;
266830391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
266934642Smarc #undef WSV
267030391Skarels
267130391Skarels } /* clear_qd_screen */
267230391Skarels
267334732Smarc /*
267434732Smarc * kernel console output to the glass tty
267534732Smarc */
qdputc(chr)267630391Skarels qdputc(chr)
267734642Smarc register char chr;
267830391Skarels {
267930391Skarels
268034642Smarc /*
268134642Smarc * if system is now physical, forget it (ie: crash DUMP)
268234642Smarc */
268334642Smarc if ((mfpr(MAPEN) & 1) == 0)
268434642Smarc return;
268534615Smarc
268634732Smarc blitc(0, (u_char)(chr & 0xff));
268732012Smarc if ((chr & 0177) == '\n')
268832012Smarc blitc(0, '\r');
268930391Skarels
269030391Skarels } /* qdputc */
269130391Skarels
269234732Smarc /*
269334732Smarc * load the mouse cursor's template RAM bitmap
269434732Smarc */
ldcursor(unit,bitmap)269530391Skarels ldcursor(unit, bitmap)
269634732Smarc int unit;
269734732Smarc register short *bitmap;
269830391Skarels {
269930391Skarels register struct dga *dga;
270030391Skarels register short *temp;
270130391Skarels register int i;
270234732Smarc int curs;
270330391Skarels
270430391Skarels dga = (struct dga *) qdmap[unit].dga;
270530391Skarels temp = (short *) qdmap[unit].template;
270630391Skarels
270730391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */
270834732Smarc curs = -1; /* ..note that.. */
270934642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */
271034732Smarc } else
271134732Smarc curs = 0;
271230391Skarels
271330391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */
271430391Skarels
271530391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */
271634642Smarc /* ..of the 8k WORD template space */
271730391Skarels for (i = 0; i < 32; ++i)
271834642Smarc *temp++ = *bitmap++;
271930391Skarels
272034732Smarc if (curs) { /* if cursor was enabled.. */
272134642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */
272230391Skarels }
272330391Skarels
272430391Skarels } /* ldcursor */
272530391Skarels
272634732Smarc /*
272734732Smarc * Put the console font in the QDSS off-screen memory
272834732Smarc */
ldfont(unit)272930391Skarels ldfont(unit)
273034732Smarc int unit;
273130391Skarels {
273230391Skarels register struct adder *adder;
273330391Skarels
273434732Smarc register i, j, k, max_chars_line;
273534732Smarc register short packed;
273630391Skarels
273730391Skarels adder = (struct adder *) qdmap[unit].adder;
273830391Skarels
273934642Smarc /*
274034732Smarc * setup VIPER operand control registers
274134732Smarc */
274230391Skarels write_ID(adder, MASK_1, 0xFFFF);
274330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
274430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
274530391Skarels
274630391Skarels write_ID(adder, SRC1_OCR_B,
274734642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
274830391Skarels write_ID(adder, SRC2_OCR_B,
274934642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
275030391Skarels write_ID(adder, DST_OCR_B,
275134642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
275230391Skarels
275330391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
275430391Skarels
275534642Smarc /*
275634732Smarc * load destination data
275734732Smarc */
275834732Smarc (void)wait_status(adder, RASTEROP_COMPLETE);
275930391Skarels
276030391Skarels adder->destination_x = FONT_X;
276130391Skarels adder->destination_y = FONT_Y;
276234732Smarc #if FONT_WIDTH > MAX_SCREEN_X
276334732Smarc adder->fast_dest_dx = MAX_SCREEN_X;
276434732Smarc #else
276534732Smarc adder->fast_dest_dx = FONT_WIDTH;
276634732Smarc #endif
276730391Skarels adder->slow_dest_dy = CHAR_HEIGHT;
276830391Skarels
276934642Smarc /*
277034642Smarc * setup for processor to bitmap xfer */
277130391Skarels
277230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001);
277330391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2;
277430391Skarels
277534642Smarc /*
277634642Smarc * Figure out how many characters can be stored on one "line" of
277734642Smarc * offscreen memory.
277834642Smarc */
277934642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
278034642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line)
278134642Smarc max_chars_line = CHARS/2 + CHARS%2;
278230391Skarels
278334642Smarc /*
278434642Smarc * iteratively do the processor to bitmap xfer */
278534615Smarc
278630391Skarels for (i = 0; i < ROWS; ++i) {
278730391Skarels
278834642Smarc /* PTOB a scan line */
278930391Skarels
279034642Smarc for (j = 0, k = i; j < max_chars_line; ++j) {
279134642Smarc /* PTOB one scan of a char cell */
279230391Skarels
279334642Smarc packed = q_font[k];
279434642Smarc k += ROWS;
279534642Smarc packed |= ((short)q_font[k] << 8);
279634642Smarc k += ROWS;
279730391Skarels
279834732Smarc (void)wait_status(adder, TX_READY);
279934642Smarc adder->id_data = packed;
280034642Smarc }
280130391Skarels }
280230391Skarels
280334642Smarc /*
280434642Smarc * (XXX XXX XXX - should remove)
280534642Smarc *
280634642Smarc * Copy the second row of characters. Subtract the first
280734642Smarc * row from the total number. Divide this quantity by 2
280834642Smarc * because 2 chars are stored in a short in the PTOB loop
280934642Smarc * below. Figure out how many characters can be stored on
281034642Smarc * one "line" of offscreen memory
281134642Smarc */
281234642Smarc
281334642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
281434642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line)
281534642Smarc return;
281634642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
281734642Smarc /* Paranoia check to see if 3rd row may be needed */
281834642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
281934615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
282034615Smarc
282134615Smarc adder->destination_x = FONT_X;
282234615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT;
282334615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
282434615Smarc adder->slow_dest_dy = CHAR_HEIGHT;
282534615Smarc
282634642Smarc /*
282734642Smarc * setup for processor to bitmap xfer
282834642Smarc */
282934615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001);
283034615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2;
283134615Smarc
283234642Smarc /*
283334642Smarc * iteratively do the processor to bitmap xfer
283434642Smarc */
283534615Smarc for (i = 0; i < ROWS; ++i) {
283634642Smarc /*
283734642Smarc * PTOB a scan line
283834642Smarc */
283934642Smarc for (j = 0, k = i; j < max_chars_line; ++j) {
284034642Smarc /*
284134642Smarc * PTOB one scan of a char cell
284234642Smarc */
284334642Smarc packed = q_font[k + FONT_OFFSET];
284434642Smarc k += ROWS;
284534642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8);
284634642Smarc k += ROWS;
284734732Smarc (void)wait_status(adder, TX_READY);
284834642Smarc adder->id_data = packed;
284934642Smarc }
285034615Smarc }
285134615Smarc
285230391Skarels } /* ldfont */
285330391Skarels
qdpoll(onoff)285440817Smarc qdpoll(onoff)
285540817Smarc {
285640817Smarc qdpolling = onoff;
285740817Smarc }
285840817Smarc
285934732Smarc /*
286034732Smarc * Get a character from the LK201 (polled)
286134732Smarc */
qdgetc()286234732Smarc qdgetc()
286334732Smarc {
286434732Smarc register short key;
286534732Smarc register char chr;
286634732Smarc register struct duart *duart;
286730391Skarels
286834732Smarc duart = (struct duart *) qdmap[0].duart;
286934732Smarc
287034732Smarc /*
287134732Smarc * Get a character from the keyboard.
287234732Smarc */
287334732Smarc LOOP:
287434732Smarc while (!(duart->statusA&RCV_RDY))
287534732Smarc ;
287634732Smarc
287734732Smarc key = duart->dataA;
287834732Smarc key &= 0xFF;
287934732Smarc
288034732Smarc /*
288134732Smarc * Check for various keyboard errors */
288234732Smarc
288334732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
288434732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
288534732Smarc printf("Keyboard error, code = %x\n", key);
288634732Smarc return(0);
288734732Smarc }
288834732Smarc
288934732Smarc if (key < LK_LOWEST)
289034732Smarc return(0);
289134732Smarc
289234732Smarc /*
289334732Smarc * See if its a state change key
289434732Smarc */
289534732Smarc switch (key) {
289634732Smarc
289734732Smarc case LOCK:
289834732Smarc q_keyboard.lock ^= 0xffff; /* toggle */
289934732Smarc if (q_keyboard.lock)
290034732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
290134732Smarc else
290234732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
290334732Smarc goto LOOP;
290434732Smarc
290534732Smarc case SHIFT:
290634732Smarc q_keyboard.shift ^= 0xFFFF;
290734732Smarc goto LOOP;
290834732Smarc
290934732Smarc case CNTRL:
291034732Smarc q_keyboard.cntrl ^= 0xFFFF;
291134732Smarc goto LOOP;
291234732Smarc
291334732Smarc case ALLUP:
291434732Smarc q_keyboard.cntrl = 0;
291534732Smarc q_keyboard.shift = 0;
291634732Smarc goto LOOP;
291734732Smarc
291834732Smarc case REPEAT:
291934732Smarc chr = q_keyboard.last;
292034732Smarc break;
292134732Smarc
292234732Smarc /*
292334732Smarc * Test for cntrl characters. If set, see if the character
292434732Smarc * is elligible to become a control character.
292534732Smarc */
292634732Smarc default:
292734732Smarc
292834732Smarc if (q_keyboard.cntrl) {
292934732Smarc chr = q_key[key];
293034732Smarc if (chr >= ' ' && chr <= '~')
293134732Smarc chr &= 0x1F;
293234732Smarc }
293334732Smarc else if ( q_keyboard.lock || q_keyboard.shift )
293434732Smarc chr = q_shift_key[key];
293534732Smarc else
293634732Smarc chr = q_key[key];
293734732Smarc break;
293834732Smarc }
293934732Smarc
294034732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */
294134732Smarc return(0); /* ..then pitch it! */
294234732Smarc
294334732Smarc q_keyboard.last = chr;
294434732Smarc
294534732Smarc /*
294634732Smarc * Check for special function keys */
294734732Smarc
294834732Smarc if (chr & 0x80) /* pitch the function keys */
294934732Smarc return(0);
295034732Smarc else
295134732Smarc return(chr);
295234732Smarc
295334732Smarc } /* qdgetc */
295434732Smarc
295534732Smarc /*
295634732Smarc * led_control()... twiddle LK-201 LED's
295734732Smarc */
led_control(unit,cmd,led_mask)295830391Skarels led_control(unit, cmd, led_mask)
295934732Smarc int unit, cmd, led_mask;
296030391Skarels {
296134732Smarc register i;
296230391Skarels register struct duart *duart;
296330391Skarels
296434732Smarc duart = (struct duart *)qdmap[unit].duart;
296530391Skarels
296630391Skarels for (i = 1000; i > 0; --i) {
296734732Smarc if (duart->statusA&XMT_RDY) {
296834642Smarc duart->dataA = cmd;
296934642Smarc break;
297034642Smarc }
297130391Skarels }
297230391Skarels for (i = 1000; i > 0; --i) {
297334732Smarc if (duart->statusA&XMT_RDY) {
297434642Smarc duart->dataA = led_mask;
297534642Smarc break;
297634642Smarc }
297730391Skarels }
297830391Skarels if (i == 0)
297934642Smarc return(BAD);
298030391Skarels return(GOOD);
298130391Skarels
298230391Skarels } /* led_control */
298330391Skarels
298434732Smarc /*
298534732Smarc * scroll_up()... move the screen up one character height
298634732Smarc */
scroll_up(adder)298730391Skarels scroll_up(adder)
298834642Smarc register struct adder *adder;
298930391Skarels {
299034642Smarc /*
299134642Smarc * setup VIPER operand control registers
299234642Smarc */
299334732Smarc (void)wait_status(adder, ADDRESS_COMPLETE);
299430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
299530391Skarels write_ID(adder, MASK_1, 0xFFFF);
299630391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
299730391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
299830391Skarels write_ID(adder, SRC1_OCR_B,
299934642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
300030391Skarels write_ID(adder, DST_OCR_B,
300134642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
300234642Smarc /*
300334642Smarc * load DESTINATION origin and vectors
300434642Smarc */
300530391Skarels adder->fast_dest_dy = 0;
300630391Skarels adder->slow_dest_dx = 0;
300730391Skarels adder->error_1 = 0;
300830391Skarels adder->error_2 = 0;
300930391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
301030391Skarels adder->destination_x = 0;
301130391Skarels adder->fast_dest_dx = 1024;
301230391Skarels adder->destination_y = 0;
301330391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT;
301434642Smarc /*
301534642Smarc * load SOURCE origin and vectors
301634642Smarc */
301730391Skarels adder->source_1_x = 0;
301830391Skarels adder->source_1_dx = 1024;
301930391Skarels adder->source_1_y = 0 + CHAR_HEIGHT;
302030391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT;
302130391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
302230391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
302334642Smarc /*
302434642Smarc * do a rectangle clear of last screen line
302534642Smarc */
302630391Skarels write_ID(adder, MASK_1, 0xffff);
302730391Skarels write_ID(adder, SOURCE, 0xffff);
302830391Skarels write_ID(adder,DST_OCR_B,
302934642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
303030391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
303130391Skarels adder->error_1 = 0;
303230391Skarels adder->error_2 = 0;
303334642Smarc adder->slow_dest_dx = 0; /* set up the width of */
303430391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */
303530391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
303634732Smarc (void)wait_status(adder, RASTEROP_COMPLETE);
303730391Skarels adder->destination_x = 0;
303830391Skarels adder->destination_y = 864 - CHAR_HEIGHT;
303930391Skarels adder->fast_dest_dx = 1024; /* set up the height */
304030391Skarels adder->fast_dest_dy = 0; /* of rectangle */
304130391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
304230391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
304330391Skarels
304430391Skarels } /* scroll_up */
304530391Skarels
304634732Smarc /*
304734732Smarc * init shared memory pointers and structures
304834732Smarc */
init_shared(unit)304930391Skarels init_shared(unit)
305034732Smarc register unit;
305130391Skarels {
305230391Skarels register struct dga *dga;
305330391Skarels
305430391Skarels dga = (struct dga *) qdmap[unit].dga;
305530391Skarels
305634642Smarc /*
305734642Smarc * initialize the event queue pointers and header */
305830391Skarels
305930391Skarels eq_header[unit] = (struct qdinput *)
306034642Smarc ((((int)event_shared & ~(0x01FF)) + 512)
306134642Smarc + (EVENT_BUFSIZE * unit));
306230391Skarels eq_header[unit]->curs_pos.x = 0;
306330391Skarels eq_header[unit]->curs_pos.y = 0;
306430391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
306530391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
306630391Skarels eq_header[unit]->curs_box.left = 0;
306730391Skarels eq_header[unit]->curs_box.right = 0;
306830391Skarels eq_header[unit]->curs_box.top = 0;
306930391Skarels eq_header[unit]->curs_box.bottom = 0;
307034642Smarc /*
307134642Smarc * assign a pointer to the DMA I/O buffer for this QDSS.
307234642Smarc */
307330391Skarels DMAheader[unit] = (struct DMAreq_header *)
307434642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF)
307534642Smarc + (DMAbuf_size * unit));
307630391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
307734642Smarc + sizeof(struct DMAreq_header));
307830391Skarels DMAheader[unit]->QBAreg = 0;
307930391Skarels DMAheader[unit]->status = 0;
308030391Skarels DMAheader[unit]->shared_size = DMAbuf_size;
308130391Skarels DMAheader[unit]->used = 0;
308230391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */
308330391Skarels DMAheader[unit]->oldest = 0;
308430391Skarels DMAheader[unit]->newest = 0;
308534642Smarc /*
308634642Smarc * assign a pointer to the scroll structure for this QDSS.
308734642Smarc */
308830391Skarels scroll[unit] = (struct scroll *)
308934642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF)
309034642Smarc + (sizeof(struct scroll) * unit));
309130391Skarels scroll[unit]->status = 0;
309230391Skarels scroll[unit]->viper_constant = 0;
309330391Skarels scroll[unit]->y_scroll_constant = 0;
309430391Skarels scroll[unit]->y_offset = 0;
309530391Skarels scroll[unit]->x_index_pending = 0;
309630391Skarels scroll[unit]->y_index_pending = 0;
309734642Smarc /*
309834642Smarc * assign a pointer to the color map write buffer for this QDSS
309934642Smarc */
310030391Skarels color_buf[unit] = (struct color_buf *)
310134642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF)
310234642Smarc + (COLOR_BUFSIZ * unit));
310330391Skarels color_buf[unit]->status = 0;
310430391Skarels color_buf[unit]->count = 0;
310530391Skarels
310630391Skarels } /* init_shared */
310730391Skarels
310834732Smarc /*
310934732Smarc * init the ADDER, VIPER, bitmaps, & color map
311034732Smarc */
setup_dragon(unit)311130391Skarels setup_dragon(unit)
311234732Smarc int unit;
311330391Skarels {
311430391Skarels
311530391Skarels register struct adder *adder;
311630391Skarels register struct dga *dga;
311730391Skarels short *memcsr;
311834732Smarc register i;
311930391Skarels short top; /* clipping/scrolling boundaries */
312030391Skarels short bottom;
312130391Skarels short right;
312230391Skarels short left;
312330391Skarels short *red; /* color map pointers */
312430391Skarels short *green;
312530391Skarels short *blue;
312630391Skarels
312734642Smarc /*
312834642Smarc * init for setup
312934642Smarc */
313030391Skarels adder = (struct adder *) qdmap[unit].adder;
313130391Skarels dga = (struct dga *) qdmap[unit].dga;
313230391Skarels memcsr = (short *) qdmap[unit].memcsr;
313330391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */
313430391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */
313530391Skarels adder->command = CANCEL;
313634642Smarc /*
313734642Smarc * set monitor timing
313834642Smarc */
313930391Skarels adder->x_scan_count_0 = 0x2800;
314030391Skarels adder->x_scan_count_1 = 0x1020;
314130391Skarels adder->x_scan_count_2 = 0x003A;
314230391Skarels adder->x_scan_count_3 = 0x38F0;
314330391Skarels adder->x_scan_count_4 = 0x6128;
314430391Skarels adder->x_scan_count_5 = 0x093A;
314530391Skarels adder->x_scan_count_6 = 0x313C;
314630391Skarels adder->sync_phase_adj = 0x0100;
314730391Skarels adder->x_scan_conf = 0x00C8;
314834642Smarc /*
314934642Smarc * got a bug in secound pass ADDER! lets take care of it
315034642Smarc *
315134642Smarc * normally, just use the code in the following bug fix code, but to
315234642Smarc * make repeated demos look pretty, load the registers as if there was
315334642Smarc * no bug and then test to see if we are getting sync
315434642Smarc */
315530391Skarels adder->y_scan_count_0 = 0x135F;
315630391Skarels adder->y_scan_count_1 = 0x3363;
315730391Skarels adder->y_scan_count_2 = 0x2366;
315830391Skarels adder->y_scan_count_3 = 0x0388;
315934642Smarc /*
316034642Smarc * if no sync, do the bug fix code
316134642Smarc */
316230391Skarels if (wait_status(adder, VSYNC) == BAD) {
316334642Smarc /* first load all Y scan registers with very short frame and
316434642Smarc * wait for scroll service. This guarantees at least one SYNC
316534642Smarc * to fix the pass 2 Adder initialization bug (synchronizes
316634642Smarc * XCINCH with DMSEEDH)
316734642Smarc */
316834642Smarc adder->y_scan_count_0 = 0x01;
316934642Smarc adder->y_scan_count_1 = 0x01;
317034642Smarc adder->y_scan_count_2 = 0x01;
317134642Smarc adder->y_scan_count_3 = 0x01;
317234642Smarc /*
317334642Smarc * delay at least 1 full frame time
317434642Smarc */
317534732Smarc (void)wait_status(adder, VSYNC);
317634732Smarc (void)wait_status(adder, VSYNC);
317734642Smarc /*
317834642Smarc * now load the REAL sync values (in reverse order just to
317934642Smarc * be safe.
318034642Smarc */
318134642Smarc adder->y_scan_count_3 = 0x0388;
318234642Smarc adder->y_scan_count_2 = 0x2366;
318334642Smarc adder->y_scan_count_1 = 0x3363;
318434642Smarc adder->y_scan_count_0 = 0x135F;
318530391Skarels }
318630391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */
318734642Smarc /*
318834642Smarc * zero the index registers
318934642Smarc */
319030391Skarels adder->x_index_pending = 0;
319130391Skarels adder->y_index_pending = 0;
319230391Skarels adder->x_index_new = 0;
319330391Skarels adder->y_index_new = 0;
319430391Skarels adder->x_index_old = 0;
319530391Skarels adder->y_index_old = 0;
319630391Skarels adder->pause = 0;
319734642Smarc /*
319834642Smarc * set rasterop mode to normal pen down
319934642Smarc */
320030391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
320134642Smarc /*
320234642Smarc * set the rasterop registers to a default values
320334642Smarc */
320430391Skarels adder->source_1_dx = 1;
320530391Skarels adder->source_1_dy = 1;
320630391Skarels adder->source_1_x = 0;
320730391Skarels adder->source_1_y = 0;
320830391Skarels adder->destination_x = 0;
320930391Skarels adder->destination_y = 0;
321030391Skarels adder->fast_dest_dx = 1;
321130391Skarels adder->fast_dest_dy = 0;
321230391Skarels adder->slow_dest_dx = 0;
321330391Skarels adder->slow_dest_dy = 1;
321430391Skarels adder->error_1 = 0;
321530391Skarels adder->error_2 = 0;
321634642Smarc /*
321734732Smarc * scale factor = UNITY
321834642Smarc */
321930391Skarels adder->fast_scale = UNITY;
322030391Skarels adder->slow_scale = UNITY;
322134642Smarc /*
322234642Smarc * set the source 2 parameters
322334642Smarc */
322430391Skarels adder->source_2_x = 0;
322530391Skarels adder->source_2_y = 0;
322630391Skarels adder->source_2_size = 0x0022;
322734642Smarc /*
322834642Smarc * initialize plane addresses for eight vipers
322934642Smarc */
323030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001);
323130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000);
323230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002);
323330391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001);
323430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004);
323530391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002);
323630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008);
323730391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003);
323830391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010);
323930391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004);
324030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020);
324130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005);
324230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040);
324330391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006);
324430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080);
324530391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007);
324634642Smarc /*
324734642Smarc * initialize the external registers.
324834642Smarc */
324930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF);
325030391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF);
325134642Smarc /*
325234642Smarc * initialize resolution mode
325334642Smarc */
325430391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */
325530391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */
325634642Smarc /*
325734642Smarc * initialize viper registers
325834642Smarc */
325930391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
326030391Skarels write_ID(adder, SCROLL_FILL, 0x0000);
326134642Smarc /*
326234642Smarc * set clipping and scrolling limits to full screen
326334642Smarc */
326434732Smarc for (i = 1000, adder->status = 0;
326534732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
326634642Smarc ;
326730391Skarels if (i == 0)
326834732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
326930391Skarels top = 0;
327030391Skarels bottom = 2048;
327130391Skarels left = 0;
327230391Skarels right = 1024;
327330391Skarels adder->x_clip_min = left;
327430391Skarels adder->x_clip_max = right;
327530391Skarels adder->y_clip_min = top;
327630391Skarels adder->y_clip_max = bottom;
327730391Skarels adder->scroll_x_min = left;
327830391Skarels adder->scroll_x_max = right;
327930391Skarels adder->scroll_y_min = top;
328030391Skarels adder->scroll_y_max = bottom;
328134732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */
328234732Smarc (void)wait_status(adder, VSYNC);
328330391Skarels adder->x_index_pending = left;
328430391Skarels adder->y_index_pending = top;
328530391Skarels adder->x_index_new = left;
328630391Skarels adder->y_index_new = top;
328730391Skarels adder->x_index_old = left;
328830391Skarels adder->y_index_old = top;
328930391Skarels
329034732Smarc for (i = 1000, adder->status = 0; i > 0 &&
329134732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i)
329234642Smarc ;
329330391Skarels if (i == 0)
329434732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
329530391Skarels
329630391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
329730391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
329834642Smarc /*
329934642Smarc * set source and the mask register to all ones (ie: white) o
330034642Smarc */
330130391Skarels write_ID(adder, SOURCE, 0xFFFF);
330230391Skarels write_ID(adder, MASK_1, 0xFFFF);
330330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
330430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
330534642Smarc /*
330634642Smarc * initialize Operand Control Register banks for fill command
330734642Smarc */
330830391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT);
330930391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
331030391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
331130391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
331230391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT);
331330391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
331434642Smarc /*
331534642Smarc * init Logic Unit Function registers, (these are just common values,
331634642Smarc * and may be changed as required).
331734642Smarc */
331830391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
331934642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
332034642Smarc INV_M1_M2);
332130391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
332230391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
332334642Smarc /*
332434642Smarc * load the color map for black & white
332534642Smarc */
332634732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
332734642Smarc ;
332830391Skarels
332930391Skarels if (i == 0)
333034732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
333130391Skarels
333230391Skarels red = (short *) qdmap[unit].red;
333330391Skarels green = (short *) qdmap[unit].green;
333430391Skarels blue = (short *) qdmap[unit].blue;
333530391Skarels
333630391Skarels *red++ = 0x00; /* black */
333730391Skarels *green++ = 0x00;
333830391Skarels *blue++ = 0x00;
333930391Skarels
334030391Skarels *red-- = 0xFF; /* white */
334130391Skarels *green-- = 0xFF;
334230391Skarels *blue-- = 0xFF;
334330391Skarels
334434642Smarc /*
334534732Smarc * set color map for mouse cursor
334634732Smarc */
334730391Skarels
334830391Skarels red += 254;
334930391Skarels green += 254;
335030391Skarels blue += 254;
335130391Skarels
335230391Skarels *red++ = 0x00; /* black */
335330391Skarels *green++ = 0x00;
335430391Skarels *blue++ = 0x00;
335530391Skarels
335630391Skarels *red = 0xFF; /* white */
335730391Skarels *green = 0xFF;
335830391Skarels *blue = 0xFF;
335930391Skarels
336030391Skarels } /* setup_dragon */
336130391Skarels
336234732Smarc /*
336334732Smarc * Init the DUART and set defaults in input
336434732Smarc */
setup_input(unit)336530391Skarels setup_input(unit)
336634732Smarc int unit;
336730391Skarels {
336830391Skarels register struct duart *duart; /* DUART register structure pointer */
336934732Smarc register i, bits;
337030391Skarels char id_byte;
337130391Skarels
337230391Skarels duart = (struct duart *) qdmap[unit].duart;
337330391Skarels duart->imask = 0;
337430391Skarels
337534642Smarc /*
337634642Smarc * setup the DUART for kbd & pointing device
337734642Smarc */
337834732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */
337934732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */
338034732Smarc /* no RTS control,char error mode */
338134732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */
338234732Smarc /* no RTS control,no echo or loop */
338334732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */
338434732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */
338534732Smarc /* ..no RTS cntrl, char error mode */
338634732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */
338734732Smarc /* no RTS control,no echo or loop */
338834732Smarc duart->auxctl = 0x00; /* baud rate set 1 */
338934732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */
339034732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */
339130391Skarels
339230391Skarels /* reset everything for keyboard */
339330391Skarels
339430391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
339534642Smarc duart->cmdA = bits;
339630391Skarels
339730391Skarels /* reset everything for host */
339830391Skarels
339930391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
340034642Smarc duart->cmdB = bits;
340130391Skarels
340230391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
340330391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
340430391Skarels
340534642Smarc /*
340634732Smarc * init keyboard defaults (DUART channel A)
340734732Smarc */
340830391Skarels for (i = 500; i > 0; --i) {
340934732Smarc if (duart->statusA&XMT_RDY) {
341034642Smarc duart->dataA = LK_DEFAULTS;
341134642Smarc break;
341234642Smarc }
341330391Skarels }
341430391Skarels
341530391Skarels for (i = 100000; i > 0; --i) {
341634732Smarc if (duart->statusA&RCV_RDY) {
341734642Smarc break;
341834642Smarc }
341930391Skarels }
342030391Skarels
342134732Smarc if (duart->dataA) /* flush the ACK */
342234732Smarc ;
342330391Skarels
342434642Smarc /*
342534732Smarc * identify the pointing device
342634732Smarc */
342730391Skarels for (i = 500; i > 0; --i) {
342834732Smarc if (duart->statusB&XMT_RDY) {
342934642Smarc duart->dataB = SELF_TEST;
343034642Smarc break;
343134642Smarc }
343230391Skarels }
343330391Skarels
343434642Smarc /*
343530391Skarels * wait for 1st byte of self test report */
343630391Skarels
343730391Skarels for (i = 100000; i > 0; --i) {
343834732Smarc if (duart->statusB&RCV_RDY) {
343934642Smarc break;
344034642Smarc }
344130391Skarels }
344230391Skarels
344330391Skarels if (i == 0) {
344434732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
344534642Smarc ,unit);
344634642Smarc goto OUT;
344730391Skarels }
344830391Skarels
344934732Smarc if (duart->dataB)
345034732Smarc ;
345130391Skarels
345234642Smarc /*
345334732Smarc * wait for ID byte of self test report
345434732Smarc */
345530391Skarels for (i = 100000; i > 0; --i) {
345634732Smarc if (duart->statusB&RCV_RDY) {
345734642Smarc break;
345834642Smarc }
345930391Skarels }
346030391Skarels
346130391Skarels if (i == 0) {
346234732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
346334642Smarc goto OUT;
346430391Skarels }
346530391Skarels
346630391Skarels id_byte = duart->dataB;
346730391Skarels
346834642Smarc /*
346934732Smarc * wait for other bytes to come in
347034732Smarc */
347130391Skarels for (i = 100000; i > 0; --i) {
347234732Smarc if (duart->statusB & RCV_RDY) {
347334732Smarc if (duart->dataB)
347434732Smarc ;
347534642Smarc break;
347634642Smarc }
347730391Skarels }
347830391Skarels if (i == 0) {
347934732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
348034642Smarc goto OUT;
348130391Skarels }
348230391Skarels for (i = 100000; i > 0; --i) {
348334732Smarc if (duart->statusB&RCV_RDY) {
348434732Smarc if (duart->dataB)
348534732Smarc ;
348634642Smarc break;
348734642Smarc }
348830391Skarels }
348930391Skarels if (i == 0) {
349034732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
349134642Smarc goto OUT;
349230391Skarels }
349334642Smarc /*
349434732Smarc * flag pointing device type and set defaults
349534732Smarc */
349634732Smarc for (i=100000; i>0; --i)
349734732Smarc ; /*XXX*/
349830391Skarels
349930391Skarels if ((id_byte & 0x0F) != TABLET_ID) {
350034642Smarc qdflags[unit].pntr_id = MOUSE_ID;
350130391Skarels
350234642Smarc for (i = 500; i > 0; --i) {
350334732Smarc if (duart->statusB&XMT_RDY) {
350434642Smarc duart->dataB = INC_STREAM_MODE;
350534642Smarc break;
350634642Smarc }
350730391Skarels }
350834642Smarc }
350934642Smarc else {
351034642Smarc qdflags[unit].pntr_id = TABLET_ID;
351130391Skarels
351234642Smarc for (i = 500; i > 0; --i) {
351334732Smarc if (duart->statusB&XMT_RDY) {
351434642Smarc duart->dataB = T_STREAM;
351534642Smarc break;
351634642Smarc }
351730391Skarels }
351830391Skarels }
351930391Skarels OUT:
352030391Skarels duart->imask = qdflags[unit].duart_imask;
352130391Skarels
352230391Skarels } /* setup_input */
352330391Skarels
352434732Smarc /*
352534732Smarc * delay for at least one display frame time
352634732Smarc *
352734732Smarc * return: BAD means that we timed out without ever seeing the
352834732Smarc * vertical sync status bit
352934732Smarc * GOOD otherwise
353034732Smarc */
wait_status(adder,mask)353130391Skarels wait_status(adder, mask)
353234642Smarc register struct adder *adder;
353334642Smarc register int mask;
353430391Skarels {
353534732Smarc register i;
353630391Skarels
353734732Smarc for (i = 10000, adder->status = 0 ; i > 0 &&
353834732Smarc !(adder->status&mask) ; --i)
353934642Smarc ;
354030391Skarels
354130391Skarels if (i == 0) {
354234732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
354334642Smarc return(BAD);
354430391Skarels }
354530391Skarels
354630391Skarels return(GOOD);
354730391Skarels
354830391Skarels } /* wait_status */
354930391Skarels
355034732Smarc /*
355134732Smarc * write out onto the ID bus
355234732Smarc */
write_ID(adder,adrs,data)355330391Skarels write_ID(adder, adrs, data)
355434642Smarc register struct adder *adder;
355534642Smarc register short adrs;
355634642Smarc register short data;
355730391Skarels {
355834732Smarc register i;
355930391Skarels
356034732Smarc for (i = 100000, adder->status = 0 ;
356134732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i)
356234642Smarc ;
356330391Skarels
356430391Skarels if (i == 0)
356534732Smarc goto ERR;
356630391Skarels
356734732Smarc for (i = 100000, adder->status = 0 ;
356834732Smarc i > 0 && !(adder->status&TX_READY) ; --i)
356934642Smarc ;
357030391Skarels
357130391Skarels if (i > 0) {
357234642Smarc adder->id_data = data;
357334642Smarc adder->command = ID_LOAD | adrs;
357434732Smarc return ;
357530391Skarels }
357630391Skarels
357730391Skarels ERR:
357834732Smarc printf("write_ID: timeout trying to write to VIPER\n");
357934732Smarc return ;
358030391Skarels
358130391Skarels } /* write_ID */
358234511Smarc #endif
3583