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