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