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