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