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