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