|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)qv.c 1.7 Berkeley 6/14/88 ! 7: * ! 8: * derived from: @(#)qv.c 1.8 (ULTRIX) 8/21/85 ! 9: */ ! 10: ! 11: /************************************************************************ ! 12: * * ! 13: * Copyright (c) 1985 by * ! 14: * Digital Equipment Corporation, Maynard, MA * ! 15: * All rights reserved. * ! 16: * * ! 17: * This software is furnished under a license and may be used and * ! 18: * copied only in accordance with the terms of such license and * ! 19: * with the inclusion of the above copyright notice. This * ! 20: * software or any other copies thereof may not be provided or * ! 21: * otherwise made available to any other person. No title to and * ! 22: * ownership of the software is hereby transferred. * ! 23: * * ! 24: * This software is derived from software received from the * ! 25: * University of California, Berkeley, and from Bell * ! 26: * Laboratories. Use, duplication, or disclosure is subject to * ! 27: * restrictions under license agreements with University of * ! 28: * California and with AT&T. * ! 29: * * ! 30: * The information in this software is subject to change without * ! 31: * notice and should not be construed as a commitment by Digital * ! 32: * Equipment Corporation. * ! 33: * * ! 34: * Digital assumes no responsibility for the use or reliability * ! 35: * of its software on equipment which is not supplied by Digital. * ! 36: * * ! 37: ************************************************************************ ! 38: * ! 39: * This driver provides glass tty functionality to the qvss. It is a strange ! 40: * device in that it supports three subchannels. The first being the asr, ! 41: * the second being a channel that intercepts the chars headed for the screen ! 42: * ( like a pseudo tty ) and the third being a source of mouse state changes. ! 43: * NOTE: the second is conditional on #ifdef CONS_HACK in this version ! 44: * of the driver, as it's a total crock. ! 45: * ! 46: * There may be one and only one qvss in the system. This restriction is based ! 47: * on the inability to map more than one at a time. This restriction will ! 48: * exist until the kernel has shared memory services. This driver therefore ! 49: * support a single unit. No attempt was made to have it service more. ! 50: * ! 51: * (this belongs in sccs - not here) ! 52: * ! 53: * 02 Aug 85 -- rjl ! 54: * Changed the names of the special setup routines so that the system ! 55: * can have a qvss or a qdss system console. ! 56: * ! 57: * 03 Jul 85 -- rjl ! 58: * Added a check for virtual mode in qvputc so that the driver ! 59: * doesn't crash while in a dump which is done in physical mode. ! 60: * ! 61: * 10 Apr 85 -- jg ! 62: * Well, our theory about keyboard handling was wrong; most of the ! 63: * keyboard is in autorepeat, down mode. These changes are to make ! 64: * the qvss work the same as the Vs100, which is not necessarily ! 65: * completely correct, as some chord usage may fail. But since we ! 66: * can't easily change the Vs100, we might as well propagate the ! 67: * problem to another device. There are also changes for screen and ! 68: * mouse accellaration. ! 69: * ! 70: * 27 Mar 85 -- rjl ! 71: * MicroVAX-II systems have interval timers that interrupt at ipl4. ! 72: * Everything else is higher and thus causes us to miss clock ticks. The ! 73: * problem isn't severe except in the case of a device like this one that ! 74: * generates lots of interrupts. We aren't willing to make this change to ! 75: * all device drivers but it seems acceptable in this case. ! 76: * ! 77: * 3 Dec 84 -- jg ! 78: * To continue the tradition of building a better mouse trap, this ! 79: * driver has been extended to form Vs100 style event queues. If the ! 80: * mouse device is open, the keyboard events are intercepted and put ! 81: * into the shared memory queue. Unfortunately, we are ending up with ! 82: * one of the longest Unix device drivers. Sigh.... ! 83: * ! 84: * 20 Nov 84 -- rjl ! 85: * As a further complication this driver is required to function as the ! 86: * virtual system console. This code runs before and during auto- ! 87: * configuration and therefore is require to have a second path for setup. ! 88: * It is futher constrained to have a character output routine that ! 89: * is not dependant on the interrupt system. ! 90: * ! 91: */ ! 92: ! 93: ! 94: #include "qv.h" ! 95: #if NQV > 0 ! 96: ! 97: #include "../machine/pte.h" ! 98: ! 99: #include "param.h" ! 100: #include "conf.h" ! 101: #include "dir.h" ! 102: #include "user.h" ! 103: #include "qvioctl.h" ! 104: #include "tty.h" ! 105: #include "map.h" ! 106: #include "buf.h" ! 107: #include "vm.h" ! 108: #include "bk.h" ! 109: #include "clist.h" ! 110: #include "file.h" ! 111: #include "uio.h" ! 112: #include "kernel.h" ! 113: #include "syslog.h" ! 114: #include "../machine/cpu.h" ! 115: #include "../machine/mtpr.h" ! 116: #include "ubareg.h" ! 117: #include "ubavar.h" ! 118: ! 119: #define CONS_HACK ! 120: ! 121: struct uba_device *qvinfo[NQV]; ! 122: ! 123: struct tty qv_tty[NQV*4]; ! 124: ! 125: #define nNQV NQV ! 126: int nqv = NQV*4; ! 127: ! 128: /* ! 129: * Definition of the driver for the auto-configuration program. ! 130: */ ! 131: int qvprobe(), qvattach(), qvkint(), qvvint(); ! 132: u_short qvstd[] = { 0 }; ! 133: struct uba_driver qvdriver = ! 134: { qvprobe, 0, qvattach, 0, qvstd, "qv", qvinfo }; ! 135: ! 136: extern char qvmem[][512*NBPG]; ! 137: extern struct pte QVmap[][512]; ! 138: ! 139: /* ! 140: * Local variables for the driver. Initialized for 15' screen ! 141: * so that it can be used during the boot process. ! 142: */ ! 143: ! 144: #define QVWAITPRI (PZERO+1) ! 145: #define QVSSMAJOR 40 ! 146: ! 147: #define QVKEYBOARD 0 /* minor 0, keyboard/glass tty */ ! 148: #define QVPCONS 1 /* minor 1, console interceptor XXX */ ! 149: #define QVMOUSECHAN 2 /* minor 2, mouse */ ! 150: #define QVSPARE 3 /* unused */ ! 151: #define QVCHAN(unit) ((unit) & 03) ! 152: /* ! 153: * v_putc is the switch that is used to redirect the console cnputc to the ! 154: * virtual console vputc. consops is used to redirect the console ! 155: * device to the qvss console. ! 156: */ ! 157: extern (*v_putc)(); ! 158: extern struct cdevsw *consops; ! 159: /* ! 160: * qv_def_scrn is used to select the appropriate tables. 0=15 inch 1=19 inch, ! 161: * 2 = uVAXII. ! 162: */ ! 163: int qv_def_scrn = 2; ! 164: ! 165: #define QVMAXEVQ 64 /* must be power of 2 */ ! 166: #define EVROUND(x) ((x) & (QVMAXEVQ - 1)) ! 167: ! 168: /* ! 169: * Screen parameters 15 & 19 inch monitors. These determine the max size in ! 170: * pixel and character units for the display and cursor positions. ! 171: * Notice that the mouse defaults to original square algorithm, but X ! 172: * will change to its defaults once implemented. ! 173: */ ! 174: struct qv_info *qv_scn; ! 175: struct qv_info qv_scn_defaults[] = { ! 176: {0, {0, 0}, 0, {0, 0}, 0, 0, 30, 80, 768, 480, 768-16, 480-16, ! 177: 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4}, ! 178: {0, {0, 0}, 0, {0, 0}, 0, 0, 55, 120, 960, 864, 960-16, 864-16, ! 179: 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4}, ! 180: {0, {0, 0}, 0, {0, 0}, 0, 0, 56, 120,1024, 864,1024-16, 864-16, ! 181: 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4} ! 182: }; ! 183: ! 184: /* ! 185: * Screen controller initialization parameters. The definations and use ! 186: * of these parameters can be found in the Motorola 68045 crtc specs. In ! 187: * essence they set the display parameters for the chip. The first set is ! 188: * for the 15" screen and the second is for the 19" seperate sync. There ! 189: * is also a third set for a 19" composite sync monitor which we have not ! 190: * tested and which is not supported. ! 191: */ ! 192: static short qv_crt_parms[][16] = { ! 193: { 31, 25, 27, 0142, 31, 13, 30, 31, 4, 15, 040, 0, 0, 0, 0, 0 }, ! 194: /* VR100*/ { 39, 30, 32, 0262, 55, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0 }, ! 195: /* VR260*/ { 39, 32, 33, 0264, 56, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0}, ! 196: }; ! 197: ! 198: /* ! 199: * Screen parameters ! 200: */ ! 201: struct qv_info *qv_scn; ! 202: int maxqvmem = 254*1024 - sizeof(struct qv_info) - QVMAXEVQ*sizeof(vsEvent); ! 203: ! 204: /* ! 205: * Keyboard state ! 206: */ ! 207: struct qv_keyboard { ! 208: int shift; /* state variables */ ! 209: int cntrl; ! 210: int lock; ! 211: char last; /* last character */ ! 212: } qv_keyboard; ! 213: ! 214: short divdefaults[15] = { LK_DOWN, /* 0 doesn't exist */ ! 215: LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, LK_DOWN, ! 216: LK_UPDOWN, LK_UPDOWN, LK_AUTODOWN, LK_AUTODOWN, ! 217: LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, LK_AUTODOWN, ! 218: LK_DOWN, LK_AUTODOWN }; ! 219: ! 220: short kbdinitstring[] = { /* reset any random keyboard stuff */ ! 221: LK_AR_ENABLE, /* we want autorepeat by default */ ! 222: LK_CL_ENABLE, /* keyclick */ ! 223: 0x84, /* keyclick volume */ ! 224: LK_KBD_ENABLE, /* the keyboard itself */ ! 225: LK_BELL_ENABLE, /* keyboard bell */ ! 226: 0x84, /* bell volume */ ! 227: LK_LED_DISABLE, /* keyboard leds */ ! 228: LED_ALL }; ! 229: #define KBD_INIT_LENGTH sizeof(kbdinitstring)/sizeof(short) ! 230: ! 231: #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) ! 232: ! 233: int qv_ipl_lo = 1; /* IPL low flag */ ! 234: int mouseon = 0; /* mouse channel is enabled when 1*/ ! 235: struct proc *qvrsel; /* process waiting for select */ ! 236: ! 237: int qvstart(), qvputc(), ttrstrt(); ! 238: ! 239: /* ! 240: * Keyboard translation and font tables ! 241: */ ! 242: extern u_short q_key[], q_shift_key[], q_cursor[]; ! 243: extern char *q_special[], q_font[]; ! 244: ! 245: /* ! 246: * See if the qvss will interrupt. ! 247: */ ! 248: ! 249: /*ARGSUSED*/ ! 250: qvprobe(reg, ctlr) ! 251: caddr_t reg; ! 252: int ctlr; ! 253: { ! 254: register int br, cvec; /* these are ``value-result'' */ ! 255: register struct qvdevice *qvaddr = (struct qvdevice *)reg; ! 256: static int tvec, ovec; ! 257: ! 258: #ifdef lint ! 259: br = 0; cvec = br; br = cvec; ! 260: qvkint(0); qvvint(0); ! 261: #endif ! 262: /* ! 263: * Allocate the next two vectors ! 264: */ ! 265: tvec = 0360; ! 266: ovec = cvec; ! 267: /* ! 268: * Turn on the keyboard and vertical interrupt vectors. ! 269: */ ! 270: qvaddr->qv_intcsr = 0; /* init the interrupt controler */ ! 271: qvaddr->qv_intcsr = 0x40; /* reset irr */ ! 272: qvaddr->qv_intcsr = 0x80; /* specify individual vectors */ ! 273: qvaddr->qv_intcsr = 0xc0; /* preset autoclear data */ ! 274: qvaddr->qv_intdata = 0xff; /* all setup as autoclear */ ! 275: ! 276: qvaddr->qv_intcsr = 0xe0; /* preset vector address 1 */ ! 277: qvaddr->qv_intdata = tvec; /* give it the keyboard vector */ ! 278: qvaddr->qv_intcsr = 0x28; /* enable tx/rx interrupt */ ! 279: ! 280: qvaddr->qv_intcsr = 0xe1; /* preset vector address 2 */ ! 281: qvaddr->qv_intdata = tvec+4; /* give it the vertical sysnc */ ! 282: qvaddr->qv_intcsr = 0x29; /* enable */ ! 283: ! 284: qvaddr->qv_intcsr = 0xa1; /* arm the interrupt ctrl */ ! 285: ! 286: qvaddr->qv_uartcmd = 0x15; /* set mode pntr/enable rx/tx */ ! 287: qvaddr->qv_uartmode = 0x17; /* noparity, 8-bit */ ! 288: qvaddr->qv_uartmode = 0x07; /* 1 stop bit */ ! 289: qvaddr->qv_uartstatus = 0x99; /* 4800 baud xmit/recv */ ! 290: qvaddr->qv_uartintstatus = 2; /* enable recv interrupts */ ! 291: ! 292: qvaddr->qv_csr |= QV_INT_ENABLE | QV_CUR_MODE; ! 293: ! 294: DELAY(10000); ! 295: ! 296: qvaddr->qv_csr &= ~QV_INT_ENABLE; ! 297: ! 298: /* ! 299: * If the qvss did interrupt it was the second vector not ! 300: * the first so we have to return the first so that they ! 301: * will be setup properly ! 302: */ ! 303: if( ovec == cvec ) { ! 304: return 0; ! 305: } else ! 306: cvec -= 4; ! 307: return (sizeof (struct qvdevice)); ! 308: } ! 309: ! 310: /* ! 311: * Routine called to attach a qv. ! 312: */ ! 313: qvattach(ui) ! 314: struct uba_device *ui; ! 315: { ! 316: ! 317: /* ! 318: * If not the console then we have to setup the screen ! 319: */ ! 320: if (v_putc != qvputc || ui->ui_unit != 0) ! 321: (void)qv_setup((struct qvdevice *)ui->ui_addr, ui->ui_unit, 1); ! 322: else ! 323: qv_scn->qvaddr = (struct qvdevice *)ui->ui_addr; ! 324: } ! 325: ! 326: ! 327: /*ARGSUSED*/ ! 328: qvopen(dev, flag) ! 329: dev_t dev; ! 330: { ! 331: register struct tty *tp; ! 332: register int unit, qv; ! 333: register struct qvdevice *qvaddr; ! 334: register struct uba_device *ui; ! 335: register struct qv_info *qp = qv_scn; ! 336: ! 337: unit = minor(dev); ! 338: qv = unit >> 2; ! 339: if (unit >= nqv || (ui = qvinfo[qv])== 0 || ui->ui_alive == 0) ! 340: return (ENXIO); ! 341: if (QVCHAN(unit) == QVSPARE ! 342: #ifndef CONS_HACK ! 343: || QVCHAN(unit) == QVPCONS ! 344: #endif ! 345: ) ! 346: return (ENODEV); ! 347: tp = &qv_tty[unit]; ! 348: if (tp->t_state&TS_XCLUDE && u.u_uid!=0) ! 349: return (EBUSY); ! 350: qvaddr = (struct qvdevice *)ui->ui_addr; ! 351: qv_scn->qvaddr = qvaddr; ! 352: tp->t_addr = (caddr_t)qvaddr; ! 353: tp->t_oproc = qvstart; ! 354: ! 355: if ((tp->t_state&TS_ISOPEN) == 0) { ! 356: ttychars(tp); ! 357: tp->t_state = TS_ISOPEN|TS_CARR_ON; ! 358: tp->t_ispeed = B9600; ! 359: tp->t_ospeed = B9600; ! 360: if( QVCHAN(unit) == QVKEYBOARD ) { ! 361: /* make sure keyboard is always back to default */ ! 362: qvkbdreset(); ! 363: qvaddr->qv_csr |= QV_INT_ENABLE; ! 364: tp->t_flags = XTABS|EVENP|ECHO|CRMOD; ! 365: } else ! 366: tp->t_flags = RAW; ! 367: } ! 368: /* ! 369: * Process line discipline specific open if its not the ! 370: * mouse channel. For the mouse we init the ring ptr's. ! 371: */ ! 372: if( QVCHAN(unit) != QVMOUSECHAN ) ! 373: return ((*linesw[tp->t_line].l_open)(dev, tp)); ! 374: else { ! 375: mouseon = 1; ! 376: /* set up event queue for later */ ! 377: qp->ibuff = (vsEvent *)qp - QVMAXEVQ; ! 378: qp->iqsize = QVMAXEVQ; ! 379: qp->ihead = qp->itail = 0; ! 380: return 0; ! 381: } ! 382: } ! 383: ! 384: /* ! 385: * Close a QVSS line. ! 386: */ ! 387: /*ARGSUSED*/ ! 388: qvclose(dev, flag) ! 389: dev_t dev; ! 390: int flag; ! 391: { ! 392: register struct tty *tp; ! 393: register unit; ! 394: register struct qvdevice *qvaddr; ! 395: ! 396: unit = minor(dev); ! 397: tp = &qv_tty[unit]; ! 398: ! 399: /* ! 400: * If this is the keyboard unit (0) shutdown the ! 401: * interface. ! 402: */ ! 403: qvaddr = (struct qvdevice *)tp->t_addr; ! 404: if (QVCHAN(unit) == QVKEYBOARD ) ! 405: qvaddr->qv_csr &= ~QV_INT_ENABLE; ! 406: ! 407: /* ! 408: * If unit is not the mouse channel call the line disc. ! 409: * otherwise clear the state flag, and put the keyboard into down/up. ! 410: */ ! 411: if (QVCHAN(unit) != QVMOUSECHAN) { ! 412: (*linesw[tp->t_line].l_close)(tp); ! 413: ttyclose(tp); ! 414: } else { ! 415: mouseon = 0; ! 416: qv_init( qvaddr ); ! 417: } ! 418: tp->t_state = 0; ! 419: } ! 420: ! 421: qvread(dev, uio) ! 422: dev_t dev; ! 423: struct uio *uio; ! 424: { ! 425: register struct tty *tp; ! 426: int unit = minor( dev ); ! 427: ! 428: if (QVCHAN(unit) != QVMOUSECHAN) { ! 429: tp = &qv_tty[unit]; ! 430: return ((*linesw[tp->t_line].l_read)(tp, uio)); ! 431: } ! 432: return (ENXIO); ! 433: } ! 434: ! 435: qvwrite(dev, uio) ! 436: dev_t dev; ! 437: struct uio *uio; ! 438: { ! 439: register struct tty *tp; ! 440: int unit = minor( dev ); ! 441: ! 442: /* ! 443: * If this is the mouse we simply fake the i/o, otherwise ! 444: * we let the line disp. handle it. ! 445: */ ! 446: if (QVCHAN(unit) == QVMOUSECHAN) { ! 447: uio->uio_offset = uio->uio_resid; ! 448: uio->uio_resid = 0; ! 449: return 0; ! 450: } ! 451: tp = &qv_tty[unit]; ! 452: return ((*linesw[tp->t_line].l_write)(tp, uio)); ! 453: } ! 454: ! 455: ! 456: /* ! 457: * Mouse activity select routine ! 458: */ ! 459: qvselect(dev, rw) ! 460: dev_t dev; ! 461: { ! 462: register int s = spl5(); ! 463: register struct qv_info *qp = qv_scn; ! 464: ! 465: if( QVCHAN(minor(dev)) == QVMOUSECHAN ) ! 466: switch(rw) { ! 467: case FREAD: /* if events okay */ ! 468: if(qp->ihead != qp->itail) { ! 469: splx(s); ! 470: return(1); ! 471: } ! 472: qvrsel = u.u_procp; ! 473: splx(s); ! 474: return(0); ! 475: default: /* can never write */ ! 476: splx(s); ! 477: return(0); ! 478: } ! 479: else { ! 480: splx(s); ! 481: return( ttselect(dev, rw) ); ! 482: } ! 483: /*NOTREACHED*/ ! 484: } ! 485: ! 486: /* ! 487: * QVSS keyboard interrupt. ! 488: */ ! 489: qvkint(qv) ! 490: int qv; ! 491: { ! 492: struct tty *tp; ! 493: register c; ! 494: struct uba_device *ui; ! 495: register int key; ! 496: register int i; ! 497: ! 498: ui = qvinfo[qv]; ! 499: if (ui == 0 || ui->ui_alive == 0) ! 500: return; ! 501: tp = &qv_tty[qv<<2]; ! 502: /* ! 503: * Get a character from the keyboard. ! 504: */ ! 505: key = ((struct qvdevice *)ui->ui_addr)->qv_uartdata & 0xff; ! 506: if( mouseon == 0) { ! 507: /* ! 508: * Check for various keyboard errors ! 509: */ ! 510: if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || ! 511: key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { ! 512: log(LOG_ERR, ! 513: "qv%d: Keyboard error, code = %x\n",qv,key); ! 514: return; ! 515: } ! 516: if( key < LK_LOWEST ) return; ! 517: /* ! 518: * See if its a state change key ! 519: */ ! 520: switch ( key ) { ! 521: case LOCK: ! 522: qv_keyboard.lock ^= 0xffff; /* toggle */ ! 523: if( qv_keyboard.lock ) ! 524: qv_key_out( LK_LED_ENABLE ); ! 525: else ! 526: qv_key_out( LK_LED_DISABLE ); ! 527: qv_key_out( LED_3 ); ! 528: return; ! 529: case SHIFT: ! 530: qv_keyboard.shift ^= 0xffff; ! 531: return; ! 532: case CNTRL: ! 533: qv_keyboard.cntrl ^= 0xffff; ! 534: return; ! 535: case ALLUP: ! 536: qv_keyboard.cntrl = qv_keyboard.shift = 0; ! 537: return; ! 538: case REPEAT: ! 539: c = qv_keyboard.last; ! 540: break; ! 541: default: ! 542: /* ! 543: * Test for control characters. If set, see if the character ! 544: * is elligible to become a control character. ! 545: */ ! 546: if( qv_keyboard.cntrl ) { ! 547: c = q_key[ key ]; ! 548: if( c >= ' ' && c <= '~' ) ! 549: c &= 0x1f; ! 550: } else if( qv_keyboard.lock || qv_keyboard.shift ) ! 551: c = q_shift_key[ key ]; ! 552: else ! 553: c = q_key[ key ]; ! 554: break; ! 555: } ! 556: ! 557: qv_keyboard.last = c; ! 558: ! 559: /* ! 560: * Check for special function keys ! 561: */ ! 562: if( c & 0x80 ) { ! 563: register char *string; ! 564: string = q_special[ c & 0x7f ]; ! 565: while( *string ) ! 566: (*linesw[tp->t_line].l_rint)(*string++, tp); ! 567: } else ! 568: (*linesw[tp->t_line].l_rint)(c, tp); ! 569: } else { ! 570: /* ! 571: * Mouse channel is open put it into the event queue ! 572: * instead. ! 573: */ ! 574: register struct qv_info *qp = qv_scn; ! 575: register vsEvent *vep; ! 576: ! 577: if ((i = EVROUND(qp->itail+1)) == qp->ihead) ! 578: return; ! 579: vep = &qp->ibuff[qp->itail]; ! 580: vep->vse_direction = VSE_KBTRAW; ! 581: vep->vse_type = VSE_BUTTON; ! 582: vep->vse_device = VSE_DKB; ! 583: vep->vse_x = qp->mouse.x; ! 584: vep->vse_y = qp->mouse.y; ! 585: vep->vse_time = TOY; ! 586: vep->vse_key = key; ! 587: qp->itail = i; ! 588: if(qvrsel) { ! 589: selwakeup(qvrsel,0); ! 590: qvrsel = 0; ! 591: } ! 592: } ! 593: } ! 594: ! 595: /* ! 596: * Ioctl for QVSS. ! 597: */ ! 598: /*ARGSUSED*/ ! 599: qvioctl(dev, cmd, data, flag) ! 600: dev_t dev; ! 601: register caddr_t data; ! 602: { ! 603: register struct tty *tp; ! 604: register int unit = minor(dev); ! 605: register struct qv_info *qp = qv_scn; ! 606: register struct qv_kpcmd *qk; ! 607: register unsigned char *cp; ! 608: int error; ! 609: ! 610: /* ! 611: * Check for and process qvss specific ioctl's ! 612: */ ! 613: switch( cmd ) { ! 614: case QIOCGINFO: /* return screen info */ ! 615: bcopy((caddr_t)qp, data, sizeof (struct qv_info)); ! 616: break; ! 617: ! 618: case QIOCSMSTATE: /* set mouse state */ ! 619: qp->mouse = *((vsCursor *)data); ! 620: qv_pos_cur( qp->mouse.x, qp->mouse.y ); ! 621: break; ! 622: ! 623: case QIOCINIT: /* init screen */ ! 624: qv_init( qp->qvaddr ); ! 625: break; ! 626: ! 627: case QIOCKPCMD: ! 628: qk = (struct qv_kpcmd *)data; ! 629: if(qk->nbytes == 0) qk->cmd |= 0200; ! 630: if(mouseon == 0) qk->cmd |= 1; /* no mode changes */ ! 631: qv_key_out(qk->cmd); ! 632: cp = &qk->par[0]; ! 633: while(qk->nbytes-- > 0) { /* terminate parameters */ ! 634: if(qk->nbytes <= 0) *cp |= 0200; ! 635: qv_key_out(*cp++); ! 636: } ! 637: break; ! 638: case QIOCADDR: /* get struct addr */ ! 639: *(struct qv_info **) data = qp; ! 640: break; ! 641: default: /* not ours ?? */ ! 642: tp = &qv_tty[unit]; ! 643: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 644: if (error >= 0) ! 645: return (error); ! 646: error = ttioctl(tp, cmd, data, flag); ! 647: if (error >= 0) { ! 648: return (error); ! 649: } ! 650: break; ! 651: } ! 652: return (0); ! 653: } ! 654: /* ! 655: * Initialize the screen and the scanmap ! 656: */ ! 657: qv_init(qvaddr) ! 658: struct qvdevice *qvaddr; ! 659: { ! 660: register short *scanline; ! 661: register int i; ! 662: register short scan; ! 663: register char *ptr; ! 664: register struct qv_info *qp = qv_scn; ! 665: ! 666: /* ! 667: * Clear the bit map ! 668: */ ! 669: for( i=0 , ptr = qp->bitmap ; i<240 ; i += 2 , ptr += 2048) ! 670: bzero( ptr, 2048 ); ! 671: /* ! 672: * Reinitialize the scanmap ! 673: */ ! 674: scan = qvaddr->qv_csr & QV_MEM_BANK; ! 675: scanline = qp->scanmap; ! 676: for(i = 0 ; i < qp->max_y ; i++ ) ! 677: *scanline++ = scan++; ! 678: ! 679: /* ! 680: * Home the cursor ! 681: */ ! 682: qp->row = qp->col = 0; ! 683: ! 684: /* ! 685: * Reset the cursor to the default type. ! 686: */ ! 687: for( i=0 ; i<16 ; i++ ) ! 688: qp->cursorbits[i] = q_cursor[i]; ! 689: qvaddr->qv_csr |= QV_CUR_MODE; ! 690: /* ! 691: * Reset keyboard to default state. ! 692: */ ! 693: qvkbdreset(); ! 694: } ! 695: ! 696: qvreset() ! 697: { ! 698: } ! 699: qvkbdreset() ! 700: { ! 701: register int i; ! 702: qv_key_out(LK_DEFAULTS); ! 703: for( i=1 ; i < 15 ; i++ ) ! 704: qv_key_out( divdefaults[i] | (i<<3)); ! 705: for (i = 0; i < KBD_INIT_LENGTH; i++) ! 706: qv_key_out(kbdinitstring[i]); ! 707: } ! 708: ! 709: #define abs(x) (((x) > 0) ? (x) : (-(x))) ! 710: /* ! 711: * QVSS vertical sync interrupt ! 712: */ ! 713: qvvint(qv) ! 714: int qv; ! 715: { ! 716: extern int selwait; ! 717: register struct qvdevice *qvaddr; ! 718: struct uba_device *ui; ! 719: register struct qv_info *qp = qv_scn; ! 720: int unit; ! 721: struct tty *tp0; ! 722: int i; ! 723: register int j; ! 724: /* ! 725: * Mouse state info ! 726: */ ! 727: static ushort omouse = 0, nmouse = 0; ! 728: static char omx=0, omy=0, mx=0, my=0, om_switch=0, m_switch=0; ! 729: register int dx, dy; ! 730: ! 731: /* ! 732: * Test and set the qv_ipl_lo flag. If the result is not zero then ! 733: * someone else must have already gotten here. ! 734: */ ! 735: if( --qv_ipl_lo ) ! 736: return; ! 737: (void)spl4(); ! 738: ui = qvinfo[qv]; ! 739: unit = qv<<2; ! 740: qvaddr = (struct qvdevice *)ui->ui_addr; ! 741: tp0 = &qv_tty[QVCHAN(unit) + QVMOUSECHAN]; ! 742: /* ! 743: * See if the mouse has moved. ! 744: */ ! 745: if( omouse != (nmouse = qvaddr->qv_mouse) ) { ! 746: omouse = nmouse; ! 747: mx = nmouse & 0xff; ! 748: my = nmouse >> 8; ! 749: dy = my - omy; omy = my; ! 750: dx = mx - omx; omx = mx; ! 751: if( dy < 50 && dy > -50 && dx < 50 && dx > -50 ) { ! 752: register vsEvent *vep; ! 753: if( qp->mscale < 0 ) { /* Ray Lanza's original */ ! 754: if( dy < 0 ) ! 755: dy = -( dy * dy ); ! 756: else ! 757: dy *= dy; ! 758: if( dx < 0 ) ! 759: dx = -( dx * dx ); ! 760: else ! 761: dx *= dx; ! 762: } ! 763: else { /* Vs100 style, see WGA spec */ ! 764: int thresh = qp->mthreshold; ! 765: int scale = qp->mscale; ! 766: if( abs(dx) > thresh ) { ! 767: if ( dx < 0 ) ! 768: dx = (dx + thresh)*scale - thresh; ! 769: else ! 770: dx = (dx - thresh)*scale + thresh; ! 771: } ! 772: if( abs(dy) > thresh ) { ! 773: if ( dy < 0 ) ! 774: dy = (dy + thresh)*scale - thresh; ! 775: else ! 776: dy = (dy - thresh)*scale + thresh; ! 777: } ! 778: } ! 779: qp->mouse.x += dx; ! 780: qp->mouse.y -= dy; ! 781: if( qp->mouse.x < 0 ) ! 782: qp->mouse.x = 0; ! 783: if( qp->mouse.y < 0 ) ! 784: qp->mouse.y = 0; ! 785: if( qp->mouse.x > qp->max_cur_x ) ! 786: qp->mouse.x = qp->max_cur_x; ! 787: if( qp->mouse.y > qp->max_cur_y ) ! 788: qp->mouse.y = qp->max_cur_y; ! 789: if( tp0->t_state & TS_ISOPEN ) ! 790: qv_pos_cur( qp->mouse.x, qp->mouse.y ); ! 791: if (qp->mouse.y < qp->mbox.bottom && ! 792: qp->mouse.y >= qp->mbox.top && ! 793: qp->mouse.x < qp->mbox.right && ! 794: qp->mouse.x >= qp->mbox.left) goto switches; ! 795: qp->mbox.bottom = 0; /* trash box */ ! 796: if (EVROUND(qp->itail+1) == qp->ihead) ! 797: goto switches; ! 798: i = EVROUND(qp->itail - 1); ! 799: if ((qp->itail != qp->ihead) && (i != qp->ihead)) { ! 800: vep = & qp->ibuff[i]; ! 801: if(vep->vse_type == VSE_MMOTION) { ! 802: vep->vse_x = qp->mouse.x; ! 803: vep->vse_y = qp->mouse.y; ! 804: goto switches; ! 805: } ! 806: } ! 807: /* put event into queue and do select */ ! 808: vep = & qp->ibuff[qp->itail]; ! 809: vep->vse_type = VSE_MMOTION; ! 810: vep->vse_time = TOY; ! 811: vep->vse_x = qp->mouse.x; ! 812: vep->vse_y = qp->mouse.y; ! 813: qp->itail = EVROUND(qp->itail+1); ! 814: } ! 815: } ! 816: /* ! 817: * See if mouse switches have changed. ! 818: */ ! 819: switches:if( om_switch != ( m_switch = (qvaddr->qv_csr & QV_MOUSE_ANY) >> 8 ) ) { ! 820: qp->mswitches = ~m_switch & 0x7; ! 821: for (j = 0; j < 3; j++) { /* check each switch */ ! 822: register vsEvent *vep; ! 823: if ( ((om_switch>>j) & 1) == ((m_switch>>j) & 1) ) ! 824: continue; ! 825: /* check for room in the queue */ ! 826: if ((i = EVROUND(qp->itail+1)) == qp->ihead) return; ! 827: /* put event into queue and do select */ ! 828: vep = &qp->ibuff[qp->itail]; ! 829: vep->vse_type = VSE_BUTTON; ! 830: vep->vse_key = 2 - j; ! 831: vep->vse_direction = VSE_KBTDOWN; ! 832: if ( (m_switch >> j) & 1) ! 833: vep->vse_direction = VSE_KBTUP; ! 834: vep->vse_device = VSE_MOUSE; ! 835: vep->vse_time = TOY; ! 836: vep->vse_x = qp->mouse.x; ! 837: vep->vse_y = qp->mouse.y; ! 838: } ! 839: qp->itail = i; ! 840: om_switch = m_switch; ! 841: qp->mswitches = m_switch; ! 842: } ! 843: /* if we have proc waiting, and event has happened, wake him up */ ! 844: if(qvrsel && (qp->ihead != qp->itail)) { ! 845: selwakeup(qvrsel,0); ! 846: qvrsel = 0; ! 847: } ! 848: /* ! 849: * Okay we can take another hit now ! 850: */ ! 851: qv_ipl_lo = 1; ! 852: } ! 853: ! 854: /* ! 855: * Start transmission ! 856: */ ! 857: qvstart(tp) ! 858: register struct tty *tp; ! 859: { ! 860: register int unit, c; ! 861: register struct tty *tp0; ! 862: int s; ! 863: ! 864: unit = minor(tp->t_dev); ! 865: #ifdef CONS_HACK ! 866: tp0 = &qv_tty[(unit&0xfc)+QVPCONS]; ! 867: #endif ! 868: unit = QVCHAN(unit); ! 869: ! 870: s = spl5(); ! 871: /* ! 872: * If it's currently active, or delaying, no need to do anything. ! 873: */ ! 874: if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) ! 875: goto out; ! 876: /* ! 877: * Display chars until the queue is empty, if the second subchannel ! 878: * is open direct them there. Drop characters from subchannels other ! 879: * than 0 on the floor. ! 880: */ ! 881: ! 882: while( tp->t_outq.c_cc ) { ! 883: c = getc(&tp->t_outq); ! 884: if (unit == QVKEYBOARD) ! 885: #ifdef CONS_HACK ! 886: if( tp0->t_state & TS_ISOPEN ){ ! 887: (*linesw[tp0->t_line].l_rint)(c, tp0); ! 888: } else ! 889: #endif ! 890: qvputchar( c & 0xff ); ! 891: } ! 892: /* ! 893: * Position the cursor to the next character location. ! 894: */ ! 895: qv_pos_cur( qv_scn->col*8, qv_scn->row*15 ); ! 896: ! 897: /* ! 898: * If there are sleepers, and output has drained below low ! 899: * water mark, wake up the sleepers. ! 900: */ ! 901: if ( tp->t_outq.c_cc<=TTLOWAT(tp) ) { ! 902: if (tp->t_state&TS_ASLEEP){ ! 903: tp->t_state &= ~TS_ASLEEP; ! 904: wakeup((caddr_t)&tp->t_outq); ! 905: } ! 906: } ! 907: tp->t_state &= ~TS_BUSY; ! 908: out: ! 909: splx(s); ! 910: } ! 911: ! 912: /* ! 913: * Stop output on a line, e.g. for ^S/^Q or output flush. ! 914: */ ! 915: /*ARGSUSED*/ ! 916: qvstop(tp, flag) ! 917: register struct tty *tp; ! 918: { ! 919: register int s; ! 920: ! 921: /* ! 922: * Block input/output interrupts while messing with state. ! 923: */ ! 924: s = spl5(); ! 925: if (tp->t_state & TS_BUSY) { ! 926: if ((tp->t_state&TS_TTSTOP)==0) { ! 927: tp->t_state |= TS_FLUSH; ! 928: } else ! 929: tp->t_state &= ~TS_BUSY; ! 930: } ! 931: splx(s); ! 932: } ! 933: ! 934: qvputc(c) ! 935: char c; ! 936: { ! 937: qvputchar(c); ! 938: if (c == '\n') ! 939: qvputchar('\r'); ! 940: } ! 941: ! 942: /* ! 943: * Routine to display a character on the screen. The model used is a ! 944: * glass tty. It is assummed that the user will only use this emulation ! 945: * during system boot and that the screen will be eventually controlled ! 946: * by a window manager. ! 947: * ! 948: */ ! 949: qvputchar( c ) ! 950: register char c; ! 951: { ! 952: ! 953: register char *b_row, *f_row; ! 954: register int i; ! 955: register short *scanline; ! 956: register int ote = 128; ! 957: register struct qv_info *qp = qv_scn; ! 958: ! 959: /* ! 960: * This routine may be called in physical mode by the dump code ! 961: * so we check and punt if that's the case. ! 962: */ ! 963: if( (mfpr(MAPEN) & 1) == 0 ) ! 964: return; ! 965: ! 966: c &= 0x7f; ! 967: ! 968: switch ( c ) { ! 969: case '\t': /* tab */ ! 970: for( i = 8 - (qp->col & 0x7) ; i > 0 ; i-- ) ! 971: qvputchar( ' ' ); ! 972: break; ! 973: ! 974: case '\r': /* return */ ! 975: qp->col = 0; ! 976: break; ! 977: ! 978: case '\010': /* backspace */ ! 979: if( --qp->col < 0 ) ! 980: qp->col = 0; ! 981: break; ! 982: ! 983: case '\n': /* linefeed */ ! 984: if( qp->row+1 >= qp->max_row ) ! 985: qvscroll(); ! 986: else ! 987: qp->row++; ! 988: /* ! 989: * Position the cursor to the next character location. ! 990: */ ! 991: qv_pos_cur( qp->col*8, qp->row*15 ); ! 992: break; ! 993: ! 994: case '\007': /* bell */ ! 995: /* ! 996: * We don't do anything to the keyboard until after ! 997: * autoconfigure. ! 998: */ ! 999: if( qp->qvaddr ) ! 1000: qv_key_out( LK_RING_BELL ); ! 1001: return; ! 1002: ! 1003: default: ! 1004: if( c >= ' ' && c <= '~' ) { ! 1005: scanline = qp->scanmap; ! 1006: b_row = qp->bitmap+(scanline[qp->row*15]&0x3ff)*128+qp->col; ! 1007: i = c - ' '; ! 1008: if( i < 0 || i > 95 ) ! 1009: i = 0; ! 1010: else ! 1011: i *= 15; ! 1012: f_row = (char *)((int)q_font + i); ! 1013: ! 1014: /* for( i=0 ; i<15 ; i++ , b_row += 128, f_row++ ) ! 1015: *b_row = *f_row;*/ ! 1016: /* inline expansion for speed */ ! 1017: *b_row = *f_row++; b_row += ote; ! 1018: *b_row = *f_row++; b_row += ote; ! 1019: *b_row = *f_row++; b_row += ote; ! 1020: *b_row = *f_row++; b_row += ote; ! 1021: *b_row = *f_row++; b_row += ote; ! 1022: *b_row = *f_row++; b_row += ote; ! 1023: *b_row = *f_row++; b_row += ote; ! 1024: *b_row = *f_row++; b_row += ote; ! 1025: *b_row = *f_row++; b_row += ote; ! 1026: *b_row = *f_row++; b_row += ote; ! 1027: *b_row = *f_row++; b_row += ote; ! 1028: *b_row = *f_row++; b_row += ote; ! 1029: *b_row = *f_row++; b_row += ote; ! 1030: *b_row = *f_row++; b_row += ote; ! 1031: *b_row = *f_row++; b_row += ote; ! 1032: ! 1033: if( ++qp->col >= qp->max_col ) { ! 1034: qp->col = 0 ; ! 1035: if( qp->row+1 >= qp->max_row ) ! 1036: qvscroll(); ! 1037: else ! 1038: qp->row++; ! 1039: } ! 1040: } ! 1041: break; ! 1042: } ! 1043: } ! 1044: ! 1045: /* ! 1046: * Position the cursor to a particular spot. ! 1047: */ ! 1048: qv_pos_cur( x, y) ! 1049: register int x,y; ! 1050: { ! 1051: register struct qvdevice *qvaddr; ! 1052: register struct qv_info *qp = qv_scn; ! 1053: register index; ! 1054: ! 1055: if( qvaddr = qp->qvaddr ) { ! 1056: if( y < 0 || y > qp->max_cur_y ) ! 1057: y = qp->max_cur_y; ! 1058: if( x < 0 || x > qp->max_cur_x ) ! 1059: x = qp->max_cur_x; ! 1060: qp->cursor.x = x; /* keep track of real cursor*/ ! 1061: qp->cursor.y = y; /* position, indep. of mouse*/ ! 1062: ! 1063: qvaddr->qv_crtaddr = 10; /* select cursor start reg */ ! 1064: qvaddr->qv_crtdata = y & 0xf; ! 1065: qvaddr->qv_crtaddr = 11; /* select cursor end reg */ ! 1066: qvaddr->qv_crtdata = y & 0xf; ! 1067: qvaddr->qv_crtaddr = 14; /* select cursor y pos. */ ! 1068: qvaddr->qv_crtdata = y >> 4; ! 1069: qvaddr->qv_xcur = x; /* pos x axis */ ! 1070: /* ! 1071: * If the mouse is being used then we change the mode of ! 1072: * cursor display based on the pixels under the cursor ! 1073: */ ! 1074: if( mouseon ) { ! 1075: index = y*128 + x/8; ! 1076: if( qp->bitmap[ index ] && qp->bitmap[ index+128 ] ) ! 1077: qvaddr->qv_csr &= ~QV_CUR_MODE; ! 1078: else ! 1079: qvaddr->qv_csr |= QV_CUR_MODE; ! 1080: } ! 1081: } ! 1082: } ! 1083: /* ! 1084: * Scroll the bitmap by moving the scanline map words. This could ! 1085: * be done by moving the bitmap but it's much too slow for a full screen. ! 1086: * The only drawback is that the scanline map must be reset when the user ! 1087: * wants to do graphics. ! 1088: */ ! 1089: qvscroll() ! 1090: { ! 1091: short tmpscanlines[15]; ! 1092: register char *b_row; ! 1093: register short *scanline; ! 1094: register struct qv_info *qp = qv_scn; ! 1095: ! 1096: /* ! 1097: * If the mouse is on we don't scroll so that the bit map ! 1098: * remains sane. ! 1099: */ ! 1100: if( mouseon ) { ! 1101: qp->row = 0; ! 1102: return; ! 1103: } ! 1104: /* ! 1105: * Save the first 15 scanlines so that we can put them at ! 1106: * the bottom when done. ! 1107: */ ! 1108: bcopy((caddr_t)qp->scanmap, (caddr_t)tmpscanlines, sizeof tmpscanlines); ! 1109: ! 1110: /* ! 1111: * Clear the wrapping line so that it won't flash on the bottom ! 1112: * of the screen. ! 1113: */ ! 1114: scanline = qp->scanmap; ! 1115: b_row = qp->bitmap+(*scanline&0x3ff)*128; ! 1116: bzero( b_row, 1920 ); ! 1117: ! 1118: /* ! 1119: * Now move the scanlines down ! 1120: */ ! 1121: bcopy((caddr_t)(qp->scanmap+15), (caddr_t)qp->scanmap, ! 1122: (qp->row * 15) * sizeof (short) ); ! 1123: ! 1124: /* ! 1125: * Now put the other lines back ! 1126: */ ! 1127: bcopy((caddr_t)tmpscanlines, (caddr_t)(qp->scanmap+(qp->row * 15)), ! 1128: sizeof (tmpscanlines) ); ! 1129: ! 1130: } ! 1131: ! 1132: /* ! 1133: * Output to the keyboard. This routine status polls the transmitter on the ! 1134: * keyboard to output a code. The timer is to avoid hanging on a bad device. ! 1135: */ ! 1136: qv_key_out(c) ! 1137: u_short c; ! 1138: { ! 1139: int timer = 30000; ! 1140: register struct qv_info *qp = qv_scn; ! 1141: ! 1142: if (qp->qvaddr) { ! 1143: while ((qp->qvaddr->qv_uartstatus & 0x4) == 0 && timer--) ! 1144: ; ! 1145: qp->qvaddr->qv_uartdata = c; ! 1146: } ! 1147: } ! 1148: /* ! 1149: * Virtual console initialization. This routine sets up the qvss so that it can ! 1150: * be used as the system console. It is invoked before autoconfig and has to do ! 1151: * everything necessary to allow the device to serve as the system console. ! 1152: * In this case it must map the q-bus and device areas and initialize the qvss ! 1153: * screen. ! 1154: */ ! 1155: qvcons_init() ! 1156: { ! 1157: struct percpu *pcpu; /* pointer to percpu structure */ ! 1158: register struct qbus *qb; ! 1159: struct qvdevice *qvaddr; /* device pointer */ ! 1160: short *devptr; /* virtual device space */ ! 1161: extern cnputc(); /* standard serial console putc */ ! 1162: #define QVSSCSR 017200 ! 1163: ! 1164: /* ! 1165: * If secondary console already configured, ! 1166: * don't override the previous one. ! 1167: */ ! 1168: if (v_putc != cnputc) ! 1169: return 0; ! 1170: /* ! 1171: * find the percpu entry that matches this machine. ! 1172: */ ! 1173: for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ ) ! 1174: ; ! 1175: if( pcpu == NULL ) ! 1176: return 0; ! 1177: ! 1178: /* ! 1179: * Found an entry for this cpu. Because this device is Microvax specific ! 1180: * we assume that there is a single q-bus and don't have to worry about ! 1181: * multiple adapters. ! 1182: * ! 1183: * Map the device registers. ! 1184: */ ! 1185: qb = (struct qbus *)pcpu->pc_io->io_details; ! 1186: ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, UBAIOPAGES * NBPG); ! 1187: ! 1188: /* ! 1189: * See if the qvss is there. ! 1190: */ ! 1191: devptr = (short *)((char *)umem[0] + (qb->qb_memsize * NBPG)); ! 1192: qvaddr = (struct qvdevice *)((u_int)devptr + ubdevreg(QVSSCSR)); ! 1193: if (badaddr((caddr_t)qvaddr, sizeof(short))) ! 1194: return 0; ! 1195: /* ! 1196: * Okay the device is there lets set it up ! 1197: */ ! 1198: if (!qv_setup(qvaddr, 0, 0)) ! 1199: return 0; ! 1200: v_putc = qvputc; ! 1201: consops = &cdevsw[QVSSMAJOR]; ! 1202: return 1; ! 1203: } ! 1204: /* ! 1205: * Do the board specific setup ! 1206: */ ! 1207: qv_setup(qvaddr, unit, probed) ! 1208: struct qvdevice *qvaddr; ! 1209: int unit; ! 1210: int probed; ! 1211: { ! 1212: caddr_t qvssmem; /* pointer to the display mem */ ! 1213: register i; /* simple index */ ! 1214: register struct qv_info *qp; ! 1215: register int *pte; ! 1216: struct percpu *pcpu; /* pointer to percpu structure */ ! 1217: register struct qbus *qb; ! 1218: ! 1219: /* ! 1220: * find the percpu entry that matches this machine. ! 1221: */ ! 1222: for( pcpu = percpu ; pcpu && pcpu->pc_cputype != cpu ; pcpu++ ) ! 1223: ; ! 1224: if( pcpu == NULL ) ! 1225: return(0); ! 1226: ! 1227: /* ! 1228: * Found an entry for this cpu. Because this device is Microvax specific ! 1229: * we assume that there is a single q-bus and don't have to worry about ! 1230: * multiple adapters. ! 1231: * ! 1232: * Map the device memory. ! 1233: */ ! 1234: qb = (struct qbus *)pcpu->pc_io->io_details; ! 1235: ! 1236: i = (u_int)(qvaddr->qv_csr & QV_MEM_BANK) << 7; ! 1237: ioaccess(qb->qb_maddr + i, QVmap[unit], 512 * NBPG); ! 1238: qvssmem = qvmem[unit]; ! 1239: pte = (int *)(QVmap[unit]); ! 1240: for (i=0; i < 512; i++, pte++) ! 1241: *pte = (*pte & ~PG_PROT) | PG_UW | PG_V; ! 1242: ! 1243: qv_scn = (struct qv_info *)((u_int)qvssmem + 251*1024); ! 1244: qp = qv_scn; ! 1245: if( (qvaddr->qv_csr & QV_19INCH) && qv_def_scrn == 0) ! 1246: qv_def_scrn = 1; ! 1247: *qv_scn = qv_scn_defaults[ qv_def_scrn ]; ! 1248: if (probed) ! 1249: qp->qvaddr = qvaddr; ! 1250: qp->bitmap = qvssmem; ! 1251: qp->scanmap = (short *)((u_int)qvssmem + 254*1024); ! 1252: qp->cursorbits = (short *)((u_int)qvssmem + 256*1024-32); ! 1253: /* set up event queue for later */ ! 1254: qp->ibuff = (vsEvent *)qp - QVMAXEVQ; ! 1255: qp->iqsize = QVMAXEVQ; ! 1256: qp->ihead = qp->itail = 0; ! 1257: ! 1258: /* ! 1259: * Setup the crt controller chip. ! 1260: */ ! 1261: for( i=0 ; i<16 ; i++ ) { ! 1262: qvaddr->qv_crtaddr = i; ! 1263: qvaddr->qv_crtdata = qv_crt_parms[ qv_def_scrn ][ i ]; ! 1264: } ! 1265: /* ! 1266: * Setup the display. ! 1267: */ ! 1268: qv_init( qvaddr ); ! 1269: ! 1270: /* ! 1271: * Turn on the video ! 1272: */ ! 1273: qvaddr->qv_csr |= QV_VIDEO_ENA ; ! 1274: return 1; ! 1275: } ! 1276: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.