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