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