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