1*52891Sbostic /*- 2*52891Sbostic * Copyright (c) 1992 The Regents of the University of California. 3*52891Sbostic * All rights reserved. 4*52891Sbostic * 5*52891Sbostic * This code is derived from software contributed to Berkeley by 6*52891Sbostic * Ralph Campbell. 7*52891Sbostic * 8*52891Sbostic * %sccs.include.redist.c% 9*52891Sbostic * 10*52891Sbostic * @(#)cfb.c 7.1 (Berkeley) 03/09/92 11*52891Sbostic */ 12*52891Sbostic 13*52891Sbostic /* 14*52891Sbostic * devGraphics.c -- 15*52891Sbostic * 16*52891Sbostic * This file contains machine-dependent routines for the graphics device. 17*52891Sbostic * 18*52891Sbostic * Copyright (C) 1989 Digital Equipment Corporation. 19*52891Sbostic * Permission to use, copy, modify, and distribute this software and 20*52891Sbostic * its documentation for any purpose and without fee is hereby granted, 21*52891Sbostic * provided that the above copyright notice appears in all copies. 22*52891Sbostic * Digital Equipment Corporation makes no representations about the 23*52891Sbostic * suitability of this software for any purpose. It is provided "as is" 24*52891Sbostic * without express or implied warranty. 25*52891Sbostic * 26*52891Sbostic * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c, 27*52891Sbostic * v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)"; 28*52891Sbostic */ 29*52891Sbostic /* 30*52891Sbostic * Mach Operating System 31*52891Sbostic * Copyright (c) 1991,1990,1989 Carnegie Mellon University 32*52891Sbostic * All Rights Reserved. 33*52891Sbostic * 34*52891Sbostic * Permission to use, copy, modify and distribute this software and its 35*52891Sbostic * documentation is hereby granted, provided that both the copyright 36*52891Sbostic * notice and this permission notice appear in all copies of the 37*52891Sbostic * software, derivative works or modified versions, and any portions 38*52891Sbostic * thereof, and that both notices appear in supporting documentation. 39*52891Sbostic * 40*52891Sbostic * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 41*52891Sbostic * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 42*52891Sbostic * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 43*52891Sbostic * 44*52891Sbostic * Carnegie Mellon requests users of this software to return to 45*52891Sbostic * 46*52891Sbostic * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 47*52891Sbostic * School of Computer Science 48*52891Sbostic * Carnegie Mellon University 49*52891Sbostic * Pittsburgh PA 15213-3890 50*52891Sbostic * 51*52891Sbostic * any improvements or extensions that they make and grant Carnegie the 52*52891Sbostic * rights to redistribute these changes. 53*52891Sbostic */ 54*52891Sbostic 55*52891Sbostic #include "cfb.h" 56*52891Sbostic #if NCFB > 0 57*52891Sbostic 58*52891Sbostic /* 59*52891Sbostic * This is a device driver for the PMAG-BA color frame buffer 60*52891Sbostic * on the TURBOchannel. 61*52891Sbostic * XXX This is just to get a console working; 62*52891Sbostic * it will need changes to work with X11R5. 63*52891Sbostic */ 64*52891Sbostic 65*52891Sbostic #include "param.h" 66*52891Sbostic #include "time.h" 67*52891Sbostic #include "kernel.h" 68*52891Sbostic #include "ioctl.h" 69*52891Sbostic #include "file.h" 70*52891Sbostic #include "errno.h" 71*52891Sbostic #include "proc.h" 72*52891Sbostic #include "mman.h" 73*52891Sbostic #include "vm/vm.h" 74*52891Sbostic 75*52891Sbostic #include "machine/machConst.h" 76*52891Sbostic #include "machine/machMon.h" 77*52891Sbostic #include "machine/dc7085cons.h" 78*52891Sbostic #include "machine/pmioctl.h" 79*52891Sbostic 80*52891Sbostic #include "device.h" 81*52891Sbostic #include "cfbreg.h" 82*52891Sbostic #include "font.c" 83*52891Sbostic 84*52891Sbostic #define MAX_ROW 56 85*52891Sbostic #define MAX_COL 80 86*52891Sbostic 87*52891Sbostic /* 88*52891Sbostic * Macro to translate from a time struct to milliseconds. 89*52891Sbostic */ 90*52891Sbostic #define TO_MS(tv) ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)) 91*52891Sbostic 92*52891Sbostic static int isMono; /* true if B&W frame buffer */ 93*52891Sbostic static int initialized; /* true if 'probe' was successful */ 94*52891Sbostic static int GraphicsOpen; /* true if the graphics device is open */ 95*52891Sbostic static int row, col; /* row and col for console cursor */ 96*52891Sbostic static struct selinfo cfb_selp; /* process waiting for select */ 97*52891Sbostic static unsigned fb_addr; /* frame buffer kernel virtual address */ 98*52891Sbostic static unsigned planemask_addr; /* plane mask kernel virtual address */ 99*52891Sbostic 100*52891Sbostic /* 101*52891Sbostic * These need to be mapped into user space. 102*52891Sbostic */ 103*52891Sbostic static struct pmuaccess { 104*52891Sbostic PM_Info scrInfo; 105*52891Sbostic pmEvent events[PM_MAXEVQ]; 106*52891Sbostic pmTimeCoord tcs[MOTION_BUFFER_SIZE]; 107*52891Sbostic } pmu; 108*52891Sbostic 109*52891Sbostic /* 110*52891Sbostic * Font mask bits used by Blitc(). 111*52891Sbostic */ 112*52891Sbostic static unsigned int fontmaskBits[16] = { 113*52891Sbostic 0x00000000, 114*52891Sbostic 0x00000001, 115*52891Sbostic 0x00000100, 116*52891Sbostic 0x00000101, 117*52891Sbostic 0x00010000, 118*52891Sbostic 0x00010001, 119*52891Sbostic 0x00010100, 120*52891Sbostic 0x00010101, 121*52891Sbostic 0x01000000, 122*52891Sbostic 0x01000001, 123*52891Sbostic 0x01000100, 124*52891Sbostic 0x01000101, 125*52891Sbostic 0x01010000, 126*52891Sbostic 0x01010001, 127*52891Sbostic 0x01010100, 128*52891Sbostic 0x01010101 129*52891Sbostic }; 130*52891Sbostic 131*52891Sbostic /* 132*52891Sbostic * Forward references. 133*52891Sbostic */ 134*52891Sbostic static void Scroll(); 135*52891Sbostic static void Blitc(); 136*52891Sbostic 137*52891Sbostic static void ScreenInit(); 138*52891Sbostic static void LoadCursor(); 139*52891Sbostic static void RestoreCursorColor(); 140*52891Sbostic static void CursorColor(); 141*52891Sbostic static void PosCursor(); 142*52891Sbostic static void InitColorMap(); 143*52891Sbostic static void LoadColorMap(); 144*52891Sbostic static void EnableVideo(); 145*52891Sbostic static void DisableVideo(); 146*52891Sbostic 147*52891Sbostic extern void dcKBDPutc(); 148*52891Sbostic extern void (*dcDivertXInput)(); 149*52891Sbostic extern void (*dcMouseEvent)(); 150*52891Sbostic extern void (*dcMouseButtons)(); 151*52891Sbostic 152*52891Sbostic int cfbprobe(); 153*52891Sbostic struct driver cfbdriver = { 154*52891Sbostic "cfb", cfbprobe, 0, 0, 155*52891Sbostic }; 156*52891Sbostic 157*52891Sbostic /* 158*52891Sbostic * Test to see if device is present. 159*52891Sbostic * Return true if found and initialized ok. 160*52891Sbostic */ 161*52891Sbostic cfbprobe(cp) 162*52891Sbostic register struct pmax_ctlr *cp; 163*52891Sbostic { 164*52891Sbostic 165*52891Sbostic if (!initialized) { 166*52891Sbostic if (!cfb_init(cp)) 167*52891Sbostic return (0); 168*52891Sbostic } 169*52891Sbostic printf("cfb%d at nexus0 csr 0x%x priority %d\n", 170*52891Sbostic cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 171*52891Sbostic return (1); 172*52891Sbostic } 173*52891Sbostic 174*52891Sbostic /* 175*52891Sbostic *---------------------------------------------------------------------- 176*52891Sbostic * 177*52891Sbostic * cfbKbdEvent -- 178*52891Sbostic * 179*52891Sbostic * Process a received character. 180*52891Sbostic * 181*52891Sbostic * Results: 182*52891Sbostic * None. 183*52891Sbostic * 184*52891Sbostic * Side effects: 185*52891Sbostic * Events added to the queue. 186*52891Sbostic * 187*52891Sbostic *---------------------------------------------------------------------- 188*52891Sbostic */ 189*52891Sbostic void 190*52891Sbostic cfbKbdEvent(ch) 191*52891Sbostic int ch; 192*52891Sbostic { 193*52891Sbostic register pmEvent *eventPtr; 194*52891Sbostic int i; 195*52891Sbostic 196*52891Sbostic if (!GraphicsOpen) 197*52891Sbostic return; 198*52891Sbostic 199*52891Sbostic /* 200*52891Sbostic * See if there is room in the queue. 201*52891Sbostic */ 202*52891Sbostic i = PM_EVROUND(pmu.scrInfo.qe.eTail + 1); 203*52891Sbostic if (i == pmu.scrInfo.qe.eHead) 204*52891Sbostic return; 205*52891Sbostic 206*52891Sbostic /* 207*52891Sbostic * Add the event to the queue. 208*52891Sbostic */ 209*52891Sbostic eventPtr = &pmu.events[pmu.scrInfo.qe.eTail]; 210*52891Sbostic eventPtr->type = BUTTON_RAW_TYPE; 211*52891Sbostic eventPtr->device = KEYBOARD_DEVICE; 212*52891Sbostic eventPtr->x = pmu.scrInfo.mouse.x; 213*52891Sbostic eventPtr->y = pmu.scrInfo.mouse.y; 214*52891Sbostic eventPtr->time = TO_MS(time); 215*52891Sbostic eventPtr->key = ch; 216*52891Sbostic pmu.scrInfo.qe.eTail = i; 217*52891Sbostic selwakeup(&cfb_selp); 218*52891Sbostic } 219*52891Sbostic 220*52891Sbostic /* 221*52891Sbostic *---------------------------------------------------------------------- 222*52891Sbostic * 223*52891Sbostic * cfbMouseEvent -- 224*52891Sbostic * 225*52891Sbostic * Process a mouse event. 226*52891Sbostic * 227*52891Sbostic * Results: 228*52891Sbostic * None. 229*52891Sbostic * 230*52891Sbostic * Side effects: 231*52891Sbostic * An event is added to the event queue. 232*52891Sbostic * 233*52891Sbostic *---------------------------------------------------------------------- 234*52891Sbostic */ 235*52891Sbostic void 236*52891Sbostic cfbMouseEvent(newRepPtr) 237*52891Sbostic register MouseReport *newRepPtr; 238*52891Sbostic { 239*52891Sbostic unsigned milliSec; 240*52891Sbostic int i; 241*52891Sbostic pmEvent *eventPtr; 242*52891Sbostic 243*52891Sbostic if (!GraphicsOpen) 244*52891Sbostic return; 245*52891Sbostic 246*52891Sbostic milliSec = TO_MS(time); 247*52891Sbostic 248*52891Sbostic /* 249*52891Sbostic * Check to see if we have to accelerate the mouse 250*52891Sbostic */ 251*52891Sbostic if (pmu.scrInfo.mscale >= 0) { 252*52891Sbostic if (newRepPtr->dx >= pmu.scrInfo.mthreshold) { 253*52891Sbostic newRepPtr->dx += 254*52891Sbostic (newRepPtr->dx - pmu.scrInfo.mthreshold) * 255*52891Sbostic pmu.scrInfo.mscale; 256*52891Sbostic } 257*52891Sbostic if (newRepPtr->dy >= pmu.scrInfo.mthreshold) { 258*52891Sbostic newRepPtr->dy += 259*52891Sbostic (newRepPtr->dy - pmu.scrInfo.mthreshold) * 260*52891Sbostic pmu.scrInfo.mscale; 261*52891Sbostic } 262*52891Sbostic } 263*52891Sbostic 264*52891Sbostic /* 265*52891Sbostic * Update mouse position 266*52891Sbostic */ 267*52891Sbostic if (newRepPtr->state & MOUSE_X_SIGN) { 268*52891Sbostic pmu.scrInfo.mouse.x += newRepPtr->dx; 269*52891Sbostic if (pmu.scrInfo.mouse.x > pmu.scrInfo.max_cur_x) 270*52891Sbostic pmu.scrInfo.mouse.x = pmu.scrInfo.max_cur_x; 271*52891Sbostic } else { 272*52891Sbostic pmu.scrInfo.mouse.x -= newRepPtr->dx; 273*52891Sbostic if (pmu.scrInfo.mouse.x < pmu.scrInfo.min_cur_x) 274*52891Sbostic pmu.scrInfo.mouse.x = pmu.scrInfo.min_cur_x; 275*52891Sbostic } 276*52891Sbostic if (newRepPtr->state & MOUSE_Y_SIGN) { 277*52891Sbostic pmu.scrInfo.mouse.y -= newRepPtr->dy; 278*52891Sbostic if (pmu.scrInfo.mouse.y < pmu.scrInfo.min_cur_y) 279*52891Sbostic pmu.scrInfo.mouse.y = pmu.scrInfo.min_cur_y; 280*52891Sbostic } else { 281*52891Sbostic pmu.scrInfo.mouse.y += newRepPtr->dy; 282*52891Sbostic if (pmu.scrInfo.mouse.y > pmu.scrInfo.max_cur_y) 283*52891Sbostic pmu.scrInfo.mouse.y = pmu.scrInfo.max_cur_y; 284*52891Sbostic } 285*52891Sbostic 286*52891Sbostic /* 287*52891Sbostic * Move the hardware cursor. 288*52891Sbostic */ 289*52891Sbostic PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y); 290*52891Sbostic 291*52891Sbostic /* 292*52891Sbostic * Store the motion event in the motion buffer. 293*52891Sbostic */ 294*52891Sbostic pmu.tcs[pmu.scrInfo.qe.tcNext].time = milliSec; 295*52891Sbostic pmu.tcs[pmu.scrInfo.qe.tcNext].x = pmu.scrInfo.mouse.x; 296*52891Sbostic pmu.tcs[pmu.scrInfo.qe.tcNext].y = pmu.scrInfo.mouse.y; 297*52891Sbostic if (++pmu.scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE) 298*52891Sbostic pmu.scrInfo.qe.tcNext = 0; 299*52891Sbostic if (pmu.scrInfo.mouse.y < pmu.scrInfo.mbox.bottom && 300*52891Sbostic pmu.scrInfo.mouse.y >= pmu.scrInfo.mbox.top && 301*52891Sbostic pmu.scrInfo.mouse.x < pmu.scrInfo.mbox.right && 302*52891Sbostic pmu.scrInfo.mouse.x >= pmu.scrInfo.mbox.left) 303*52891Sbostic return; 304*52891Sbostic 305*52891Sbostic pmu.scrInfo.mbox.bottom = 0; 306*52891Sbostic if (PM_EVROUND(pmu.scrInfo.qe.eTail + 1) == pmu.scrInfo.qe.eHead) 307*52891Sbostic return; 308*52891Sbostic 309*52891Sbostic i = PM_EVROUND(pmu.scrInfo.qe.eTail - 1); 310*52891Sbostic if ((pmu.scrInfo.qe.eTail != pmu.scrInfo.qe.eHead) && 311*52891Sbostic (i != pmu.scrInfo.qe.eHead)) { 312*52891Sbostic pmEvent *eventPtr; 313*52891Sbostic 314*52891Sbostic eventPtr = &pmu.events[i]; 315*52891Sbostic if (eventPtr->type == MOTION_TYPE) { 316*52891Sbostic eventPtr->x = pmu.scrInfo.mouse.x; 317*52891Sbostic eventPtr->y = pmu.scrInfo.mouse.y; 318*52891Sbostic eventPtr->time = milliSec; 319*52891Sbostic eventPtr->device = MOUSE_DEVICE; 320*52891Sbostic return; 321*52891Sbostic } 322*52891Sbostic } 323*52891Sbostic /* 324*52891Sbostic * Put event into queue and wakeup any waiters. 325*52891Sbostic */ 326*52891Sbostic eventPtr = &pmu.events[pmu.scrInfo.qe.eTail]; 327*52891Sbostic eventPtr->type = MOTION_TYPE; 328*52891Sbostic eventPtr->time = milliSec; 329*52891Sbostic eventPtr->x = pmu.scrInfo.mouse.x; 330*52891Sbostic eventPtr->y = pmu.scrInfo.mouse.y; 331*52891Sbostic eventPtr->device = MOUSE_DEVICE; 332*52891Sbostic pmu.scrInfo.qe.eTail = PM_EVROUND(pmu.scrInfo.qe.eTail + 1); 333*52891Sbostic selwakeup(&cfb_selp); 334*52891Sbostic } 335*52891Sbostic 336*52891Sbostic /* 337*52891Sbostic *---------------------------------------------------------------------- 338*52891Sbostic * 339*52891Sbostic * cfbMouseButtons -- 340*52891Sbostic * 341*52891Sbostic * Process mouse buttons. 342*52891Sbostic * 343*52891Sbostic * Results: 344*52891Sbostic * None. 345*52891Sbostic * 346*52891Sbostic * Side effects: 347*52891Sbostic * None. 348*52891Sbostic * 349*52891Sbostic *---------------------------------------------------------------------- 350*52891Sbostic */ 351*52891Sbostic void 352*52891Sbostic cfbMouseButtons(newRepPtr) 353*52891Sbostic MouseReport *newRepPtr; 354*52891Sbostic { 355*52891Sbostic static char temp, oldSwitch, newSwitch; 356*52891Sbostic int i, j; 357*52891Sbostic pmEvent *eventPtr; 358*52891Sbostic static MouseReport lastRep; 359*52891Sbostic 360*52891Sbostic if (!GraphicsOpen) 361*52891Sbostic return; 362*52891Sbostic 363*52891Sbostic newSwitch = newRepPtr->state & 0x07; 364*52891Sbostic oldSwitch = lastRep.state & 0x07; 365*52891Sbostic 366*52891Sbostic temp = oldSwitch ^ newSwitch; 367*52891Sbostic if (temp == 0) 368*52891Sbostic return; 369*52891Sbostic for (j = 1; j < 8; j <<= 1) { 370*52891Sbostic if ((j & temp) == 0) 371*52891Sbostic continue; 372*52891Sbostic 373*52891Sbostic /* 374*52891Sbostic * Check for room in the queue 375*52891Sbostic */ 376*52891Sbostic i = PM_EVROUND(pmu.scrInfo.qe.eTail+1); 377*52891Sbostic if (i == pmu.scrInfo.qe.eHead) 378*52891Sbostic return; 379*52891Sbostic 380*52891Sbostic /* 381*52891Sbostic * Put event into queue. 382*52891Sbostic */ 383*52891Sbostic eventPtr = &pmu.events[pmu.scrInfo.qe.eTail]; 384*52891Sbostic 385*52891Sbostic switch (j) { 386*52891Sbostic case RIGHT_BUTTON: 387*52891Sbostic eventPtr->key = EVENT_RIGHT_BUTTON; 388*52891Sbostic break; 389*52891Sbostic 390*52891Sbostic case MIDDLE_BUTTON: 391*52891Sbostic eventPtr->key = EVENT_MIDDLE_BUTTON; 392*52891Sbostic break; 393*52891Sbostic 394*52891Sbostic case LEFT_BUTTON: 395*52891Sbostic eventPtr->key = EVENT_LEFT_BUTTON; 396*52891Sbostic } 397*52891Sbostic if (newSwitch & j) 398*52891Sbostic eventPtr->type = BUTTON_DOWN_TYPE; 399*52891Sbostic else 400*52891Sbostic eventPtr->type = BUTTON_UP_TYPE; 401*52891Sbostic eventPtr->device = MOUSE_DEVICE; 402*52891Sbostic 403*52891Sbostic eventPtr->time = TO_MS(time); 404*52891Sbostic eventPtr->x = pmu.scrInfo.mouse.x; 405*52891Sbostic eventPtr->y = pmu.scrInfo.mouse.y; 406*52891Sbostic } 407*52891Sbostic pmu.scrInfo.qe.eTail = i; 408*52891Sbostic selwakeup(&cfb_selp); 409*52891Sbostic 410*52891Sbostic lastRep = *newRepPtr; 411*52891Sbostic pmu.scrInfo.mswitches = newSwitch; 412*52891Sbostic } 413*52891Sbostic 414*52891Sbostic /* 415*52891Sbostic *---------------------------------------------------------------------- 416*52891Sbostic * 417*52891Sbostic * Scroll -- 418*52891Sbostic * 419*52891Sbostic * Scroll the screen. 420*52891Sbostic * 421*52891Sbostic * Results: 422*52891Sbostic * None. 423*52891Sbostic * 424*52891Sbostic * Side effects: 425*52891Sbostic * None. 426*52891Sbostic * 427*52891Sbostic *---------------------------------------------------------------------- 428*52891Sbostic */ 429*52891Sbostic static void 430*52891Sbostic Scroll() 431*52891Sbostic { 432*52891Sbostic register int *dest, *src; 433*52891Sbostic register int *end; 434*52891Sbostic register int temp0, temp1, temp2, temp3; 435*52891Sbostic register int i, scanInc, lineCount; 436*52891Sbostic int line; 437*52891Sbostic 438*52891Sbostic /* 439*52891Sbostic * If the mouse is on we don't scroll so that the bit map remains sane. 440*52891Sbostic */ 441*52891Sbostic if (GraphicsOpen) { 442*52891Sbostic row = 0; 443*52891Sbostic return; 444*52891Sbostic } 445*52891Sbostic 446*52891Sbostic /* 447*52891Sbostic * The following is an optimization to cause the scrolling 448*52891Sbostic * of text to be memory limited. Basically the writebuffer is 449*52891Sbostic * 4 words (32 bits ea.) long so to achieve maximum speed we 450*52891Sbostic * read and write in multiples of 4 words. We also limit the 451*52891Sbostic * size to be MAX_COL characters for more speed. 452*52891Sbostic */ 453*52891Sbostic if (isMono) { 454*52891Sbostic lineCount = 5; 455*52891Sbostic line = 1920 * 2; 456*52891Sbostic scanInc = 44; 457*52891Sbostic } else { 458*52891Sbostic lineCount = 40; 459*52891Sbostic scanInc = 96; 460*52891Sbostic line = 1920 * 8; 461*52891Sbostic } 462*52891Sbostic src = (int *)(fb_addr + line); 463*52891Sbostic dest = (int *)(fb_addr); 464*52891Sbostic end = (int *)(fb_addr + (60 * line) - line); 465*52891Sbostic do { 466*52891Sbostic i = 0; 467*52891Sbostic do { 468*52891Sbostic temp0 = src[0]; 469*52891Sbostic temp1 = src[1]; 470*52891Sbostic temp2 = src[2]; 471*52891Sbostic temp3 = src[3]; 472*52891Sbostic dest[0] = temp0; 473*52891Sbostic dest[1] = temp1; 474*52891Sbostic dest[2] = temp2; 475*52891Sbostic dest[3] = temp3; 476*52891Sbostic dest += 4; 477*52891Sbostic src += 4; 478*52891Sbostic i++; 479*52891Sbostic } while (i < lineCount); 480*52891Sbostic src += scanInc; 481*52891Sbostic dest += scanInc; 482*52891Sbostic } while (src < end); 483*52891Sbostic 484*52891Sbostic /* 485*52891Sbostic * Now zero out the last two lines 486*52891Sbostic */ 487*52891Sbostic bzero(fb_addr + (row * line), 3 * line); 488*52891Sbostic } 489*52891Sbostic 490*52891Sbostic /* 491*52891Sbostic *---------------------------------------------------------------------- 492*52891Sbostic * 493*52891Sbostic * cfbPutc -- 494*52891Sbostic * 495*52891Sbostic * Write a character to the console. 496*52891Sbostic * 497*52891Sbostic * Results: 498*52891Sbostic * None. 499*52891Sbostic * 500*52891Sbostic * Side effects: 501*52891Sbostic * None. 502*52891Sbostic * 503*52891Sbostic *---------------------------------------------------------------------- 504*52891Sbostic */ 505*52891Sbostic cfbPutc(c) 506*52891Sbostic register int c; 507*52891Sbostic { 508*52891Sbostic int s; 509*52891Sbostic 510*52891Sbostic s = splhigh(); /* in case we do any printf's at interrupt time */ 511*52891Sbostic if (initialized) { 512*52891Sbostic #ifdef DEBUG 513*52891Sbostic /* 514*52891Sbostic * If the HELP key is pressed, wait for another 515*52891Sbostic * HELP key press to start/stop output. 516*52891Sbostic */ 517*52891Sbostic if (dcDebugGetc() == LK_HELP) { 518*52891Sbostic while (dcDebugGetc() != LK_HELP) 519*52891Sbostic ; 520*52891Sbostic } 521*52891Sbostic #endif 522*52891Sbostic Blitc(c); 523*52891Sbostic } else { 524*52891Sbostic void (*f)() = (void (*)())MACH_MON_PUTCHAR; 525*52891Sbostic 526*52891Sbostic (*f)(c); 527*52891Sbostic } 528*52891Sbostic splx(s); 529*52891Sbostic } 530*52891Sbostic 531*52891Sbostic /* 532*52891Sbostic *---------------------------------------------------------------------- 533*52891Sbostic * 534*52891Sbostic * Blitc -- 535*52891Sbostic * 536*52891Sbostic * Write a character to the screen. 537*52891Sbostic * 538*52891Sbostic * Results: 539*52891Sbostic * None. 540*52891Sbostic * 541*52891Sbostic * Side effects: 542*52891Sbostic * None. 543*52891Sbostic * 544*52891Sbostic *---------------------------------------------------------------------- 545*52891Sbostic */ 546*52891Sbostic static void 547*52891Sbostic Blitc(c) 548*52891Sbostic register int c; 549*52891Sbostic { 550*52891Sbostic register char *bRow, *fRow; 551*52891Sbostic register int i; 552*52891Sbostic register int ote = isMono ? 256 : 1024; /* offset to table entry */ 553*52891Sbostic int colMult = isMono ? 1 : 8; 554*52891Sbostic 555*52891Sbostic c &= 0xff; 556*52891Sbostic 557*52891Sbostic switch (c) { 558*52891Sbostic case '\t': 559*52891Sbostic for (i = 8 - (col & 0x7); i > 0; i--) 560*52891Sbostic Blitc(' '); 561*52891Sbostic break; 562*52891Sbostic 563*52891Sbostic case '\r': 564*52891Sbostic col = 0; 565*52891Sbostic break; 566*52891Sbostic 567*52891Sbostic case '\b': 568*52891Sbostic col--; 569*52891Sbostic if (col < 0) 570*52891Sbostic col = 0; 571*52891Sbostic break; 572*52891Sbostic 573*52891Sbostic case '\n': 574*52891Sbostic if (row + 1 >= MAX_ROW) 575*52891Sbostic Scroll(); 576*52891Sbostic else 577*52891Sbostic row++; 578*52891Sbostic col = 0; 579*52891Sbostic break; 580*52891Sbostic 581*52891Sbostic case '\007': 582*52891Sbostic dcKBDPutc(LK_RING_BELL); 583*52891Sbostic break; 584*52891Sbostic 585*52891Sbostic default: 586*52891Sbostic /* 587*52891Sbostic * 0xA1 to 0xFD are the printable characters added with 8-bit 588*52891Sbostic * support. 589*52891Sbostic */ 590*52891Sbostic if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD) 591*52891Sbostic break; 592*52891Sbostic /* 593*52891Sbostic * If the next character will wrap around then 594*52891Sbostic * increment row counter or scroll screen. 595*52891Sbostic */ 596*52891Sbostic if (col >= MAX_COL) { 597*52891Sbostic col = 0; 598*52891Sbostic if (row + 1 >= MAX_ROW) 599*52891Sbostic Scroll(); 600*52891Sbostic else 601*52891Sbostic row++; 602*52891Sbostic } 603*52891Sbostic bRow = (char *)(fb_addr + 604*52891Sbostic (row * 15 & 0x3ff) * ote + col * colMult); 605*52891Sbostic i = c - ' '; 606*52891Sbostic /* 607*52891Sbostic * This is to skip the (32) 8-bit 608*52891Sbostic * control chars, as well as DEL 609*52891Sbostic * and 0xA0 which aren't printable 610*52891Sbostic */ 611*52891Sbostic if (c > '~') 612*52891Sbostic i -= 34; 613*52891Sbostic i *= 15; 614*52891Sbostic fRow = (char *)((int)pmFont + i); 615*52891Sbostic 616*52891Sbostic /* inline expansion for speed */ 617*52891Sbostic if (isMono) { 618*52891Sbostic *bRow = *fRow++; bRow += ote; 619*52891Sbostic *bRow = *fRow++; bRow += ote; 620*52891Sbostic *bRow = *fRow++; bRow += ote; 621*52891Sbostic *bRow = *fRow++; bRow += ote; 622*52891Sbostic *bRow = *fRow++; bRow += ote; 623*52891Sbostic *bRow = *fRow++; bRow += ote; 624*52891Sbostic *bRow = *fRow++; bRow += ote; 625*52891Sbostic *bRow = *fRow++; bRow += ote; 626*52891Sbostic *bRow = *fRow++; bRow += ote; 627*52891Sbostic *bRow = *fRow++; bRow += ote; 628*52891Sbostic *bRow = *fRow++; bRow += ote; 629*52891Sbostic *bRow = *fRow++; bRow += ote; 630*52891Sbostic *bRow = *fRow++; bRow += ote; 631*52891Sbostic *bRow = *fRow++; bRow += ote; 632*52891Sbostic *bRow = *fRow++; bRow += ote; 633*52891Sbostic } else { 634*52891Sbostic register int j; 635*52891Sbostic register unsigned int *pInt; 636*52891Sbostic 637*52891Sbostic pInt = (unsigned int *)bRow; 638*52891Sbostic for (j = 0; j < 15; j++) { 639*52891Sbostic /* 640*52891Sbostic * fontmaskBits converts a nibble 641*52891Sbostic * (4 bytes) to a long word 642*52891Sbostic * containing 4 pixels corresponding 643*52891Sbostic * to each bit in the nibble. Thus 644*52891Sbostic * we write two longwords for each 645*52891Sbostic * byte in font. 646*52891Sbostic * 647*52891Sbostic * Remember the font is 8 bits wide 648*52891Sbostic * and 15 bits high. 649*52891Sbostic * 650*52891Sbostic * We add 256 to the pointer to 651*52891Sbostic * point to the pixel on the 652*52891Sbostic * next scan line 653*52891Sbostic * directly below the current 654*52891Sbostic * pixel. 655*52891Sbostic */ 656*52891Sbostic pInt[0] = fontmaskBits[(*fRow) & 0xf]; 657*52891Sbostic pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf]; 658*52891Sbostic fRow++; 659*52891Sbostic pInt += 256; 660*52891Sbostic } 661*52891Sbostic } 662*52891Sbostic col++; /* increment column counter */ 663*52891Sbostic } 664*52891Sbostic if (!GraphicsOpen) 665*52891Sbostic PosCursor(col * 8, row * 15); 666*52891Sbostic } 667*52891Sbostic 668*52891Sbostic /*ARGSUSED*/ 669*52891Sbostic cfbopen(dev, flag) 670*52891Sbostic dev_t dev; 671*52891Sbostic int flag; 672*52891Sbostic { 673*52891Sbostic 674*52891Sbostic if (!initialized) 675*52891Sbostic return (ENXIO); 676*52891Sbostic if (GraphicsOpen) 677*52891Sbostic return (EBUSY); 678*52891Sbostic 679*52891Sbostic GraphicsOpen = 1; 680*52891Sbostic if (!isMono) 681*52891Sbostic InitColorMap(); 682*52891Sbostic /* 683*52891Sbostic * Set up event queue for later 684*52891Sbostic */ 685*52891Sbostic pmu.scrInfo.qe.eSize = PM_MAXEVQ; 686*52891Sbostic pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0; 687*52891Sbostic pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE; 688*52891Sbostic pmu.scrInfo.qe.tcNext = 0; 689*52891Sbostic pmu.scrInfo.qe.timestamp_ms = TO_MS(time); 690*52891Sbostic return (0); 691*52891Sbostic } 692*52891Sbostic 693*52891Sbostic /*ARGSUSED*/ 694*52891Sbostic cfbclose(dev, flag) 695*52891Sbostic dev_t dev; 696*52891Sbostic int flag; 697*52891Sbostic { 698*52891Sbostic 699*52891Sbostic if (!GraphicsOpen) 700*52891Sbostic return (EBADF); 701*52891Sbostic 702*52891Sbostic GraphicsOpen = 0; 703*52891Sbostic if (!isMono) 704*52891Sbostic InitColorMap(); 705*52891Sbostic ScreenInit(); 706*52891Sbostic vmUserUnmap(); 707*52891Sbostic bzero(fb_addr, (isMono ? 1024 / 8 : 1024) * 864); 708*52891Sbostic PosCursor(col * 8, row * 15); 709*52891Sbostic return (0); 710*52891Sbostic } 711*52891Sbostic 712*52891Sbostic /*ARGSUSED*/ 713*52891Sbostic cfbioctl(dev, cmd, data, flag) 714*52891Sbostic dev_t dev; 715*52891Sbostic caddr_t data; 716*52891Sbostic { 717*52891Sbostic 718*52891Sbostic switch (cmd) { 719*52891Sbostic case QIOCGINFO: 720*52891Sbostic { 721*52891Sbostic caddr_t addr; 722*52891Sbostic extern caddr_t vmUserMap(); 723*52891Sbostic 724*52891Sbostic /* 725*52891Sbostic * Map the all the data the user needs access to into 726*52891Sbostic * user space. 727*52891Sbostic */ 728*52891Sbostic addr = vmUserMap(sizeof(pmu), (unsigned)&pmu); 729*52891Sbostic if (addr == (caddr_t)0) 730*52891Sbostic goto mapError; 731*52891Sbostic *(PM_Info **)data = &((struct pmuaccess *)addr)->scrInfo; 732*52891Sbostic pmu.scrInfo.qe.events = ((struct pmuaccess *)addr)->events; 733*52891Sbostic pmu.scrInfo.qe.tcs = ((struct pmuaccess *)addr)->tcs; 734*52891Sbostic /* 735*52891Sbostic * Map the plane mask into the user's address space. 736*52891Sbostic */ 737*52891Sbostic addr = vmUserMap(4, planemask_addr); 738*52891Sbostic if (addr == (caddr_t)0) 739*52891Sbostic goto mapError; 740*52891Sbostic pmu.scrInfo.planemask = (char *)addr; 741*52891Sbostic /* 742*52891Sbostic * Map the frame buffer into the user's address space. 743*52891Sbostic */ 744*52891Sbostic addr = vmUserMap(isMono ? 256*1024 : 1024*1024, fb_addr); 745*52891Sbostic if (addr == (caddr_t)0) 746*52891Sbostic goto mapError; 747*52891Sbostic pmu.scrInfo.bitmap = (char *)addr; 748*52891Sbostic break; 749*52891Sbostic 750*52891Sbostic mapError: 751*52891Sbostic vmUserUnmap(); 752*52891Sbostic printf("Cannot map shared data structures\n"); 753*52891Sbostic return (EIO); 754*52891Sbostic } 755*52891Sbostic 756*52891Sbostic case QIOCPMSTATE: 757*52891Sbostic /* 758*52891Sbostic * Set mouse state. 759*52891Sbostic */ 760*52891Sbostic pmu.scrInfo.mouse = *(pmCursor *)data; 761*52891Sbostic PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y); 762*52891Sbostic break; 763*52891Sbostic 764*52891Sbostic case QIOCINIT: 765*52891Sbostic /* 766*52891Sbostic * Initialize the screen. 767*52891Sbostic */ 768*52891Sbostic ScreenInit(); 769*52891Sbostic break; 770*52891Sbostic 771*52891Sbostic case QIOCKPCMD: 772*52891Sbostic { 773*52891Sbostic pmKpCmd *kpCmdPtr; 774*52891Sbostic unsigned char *cp; 775*52891Sbostic 776*52891Sbostic kpCmdPtr = (pmKpCmd *)data; 777*52891Sbostic if (kpCmdPtr->nbytes == 0) 778*52891Sbostic kpCmdPtr->cmd |= 0x80; 779*52891Sbostic if (!GraphicsOpen) 780*52891Sbostic kpCmdPtr->cmd |= 1; 781*52891Sbostic dcKBDPutc((int)kpCmdPtr->cmd); 782*52891Sbostic cp = &kpCmdPtr->par[0]; 783*52891Sbostic for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) { 784*52891Sbostic if (kpCmdPtr->nbytes == 1) 785*52891Sbostic *cp |= 0x80; 786*52891Sbostic dcKBDPutc((int)*cp); 787*52891Sbostic } 788*52891Sbostic break; 789*52891Sbostic } 790*52891Sbostic 791*52891Sbostic case QIOCADDR: 792*52891Sbostic *(PM_Info **)data = &pmu.scrInfo; 793*52891Sbostic break; 794*52891Sbostic 795*52891Sbostic case QIOWCURSOR: 796*52891Sbostic LoadCursor((unsigned short *)data); 797*52891Sbostic break; 798*52891Sbostic 799*52891Sbostic case QIOWCURSORCOLOR: 800*52891Sbostic CursorColor((unsigned int *)data); 801*52891Sbostic break; 802*52891Sbostic 803*52891Sbostic case QIOSETCMAP: 804*52891Sbostic LoadColorMap((ColorMap *)data); 805*52891Sbostic break; 806*52891Sbostic 807*52891Sbostic case QIOKERNLOOP: 808*52891Sbostic dcDivertXInput = cfbKbdEvent; 809*52891Sbostic dcMouseEvent = cfbMouseEvent; 810*52891Sbostic dcMouseButtons = cfbMouseButtons; 811*52891Sbostic break; 812*52891Sbostic 813*52891Sbostic case QIOKERNUNLOOP: 814*52891Sbostic dcDivertXInput = (void (*)())0; 815*52891Sbostic dcMouseEvent = (void (*)())0; 816*52891Sbostic dcMouseButtons = (void (*)())0; 817*52891Sbostic break; 818*52891Sbostic 819*52891Sbostic case QIOVIDEOON: 820*52891Sbostic EnableVideo(); 821*52891Sbostic break; 822*52891Sbostic 823*52891Sbostic case QIOVIDEOOFF: 824*52891Sbostic DisableVideo(); 825*52891Sbostic break; 826*52891Sbostic 827*52891Sbostic default: 828*52891Sbostic printf("cfb0: Unknown ioctl command %x\n", cmd); 829*52891Sbostic return (EINVAL); 830*52891Sbostic } 831*52891Sbostic return (0); 832*52891Sbostic } 833*52891Sbostic 834*52891Sbostic cfbselect(dev, flag, p) 835*52891Sbostic dev_t dev; 836*52891Sbostic int flag; 837*52891Sbostic struct proc *p; 838*52891Sbostic { 839*52891Sbostic 840*52891Sbostic switch (flag) { 841*52891Sbostic case FREAD: 842*52891Sbostic if (pmu.scrInfo.qe.eHead != pmu.scrInfo.qe.eTail) 843*52891Sbostic return (1); 844*52891Sbostic selrecord(p, &cfb_selp); 845*52891Sbostic break; 846*52891Sbostic } 847*52891Sbostic 848*52891Sbostic return (0); 849*52891Sbostic } 850*52891Sbostic 851*52891Sbostic static u_char cursor_RGB[6]; /* cursor color 2 & 3 */ 852*52891Sbostic 853*52891Sbostic /* 854*52891Sbostic * The default cursor. 855*52891Sbostic */ 856*52891Sbostic static unsigned short defCursor[1024] = { 857*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 858*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 859*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 860*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 861*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 862*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 863*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 864*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 865*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 866*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 867*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 868*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 869*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 870*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 871*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 872*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 873*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 874*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 875*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 876*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 877*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 878*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 879*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 880*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 881*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 882*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 883*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 884*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 885*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 886*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 887*52891Sbostic 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 888*52891Sbostic 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 889*52891Sbostic }; 890*52891Sbostic 891*52891Sbostic #define CFB_OFFSET_VRAM 0x0 /* from module's base */ 892*52891Sbostic /* Replicated at x100000 */ 893*52891Sbostic #define CFB_OFFSET_BT459 0x200000 /* Bt459 registers */ 894*52891Sbostic #define CFB_OFFSET_IREQ 0x300000 /* Interrupt req. control */ 895*52891Sbostic #define CFB_OFFSET_ROM 0x380000 /* Diagnostic ROM */ 896*52891Sbostic #define CFB_OFFSET_RESET 0x3c0000 /* Bt459 resets on writes */ 897*52891Sbostic 898*52891Sbostic /* 899*52891Sbostic * Generic register access 900*52891Sbostic */ 901*52891Sbostic void 902*52891Sbostic bt459_select_reg(regs, regno) 903*52891Sbostic bt459_regmap_t *regs; 904*52891Sbostic { 905*52891Sbostic regs->addr_lo = regno; 906*52891Sbostic regs->addr_hi = regno >> 8; 907*52891Sbostic MachEmptyWriteBuffer(); 908*52891Sbostic } 909*52891Sbostic 910*52891Sbostic void 911*52891Sbostic bt459_write_reg(regs, regno, val) 912*52891Sbostic bt459_regmap_t *regs; 913*52891Sbostic { 914*52891Sbostic regs->addr_lo = regno; 915*52891Sbostic regs->addr_hi = regno >> 8; 916*52891Sbostic MachEmptyWriteBuffer(); 917*52891Sbostic regs->addr_reg = val; 918*52891Sbostic MachEmptyWriteBuffer(); 919*52891Sbostic } 920*52891Sbostic 921*52891Sbostic unsigned char 922*52891Sbostic bt459_read_reg(regs, regno) 923*52891Sbostic bt459_regmap_t *regs; 924*52891Sbostic { 925*52891Sbostic regs->addr_lo = regno; 926*52891Sbostic regs->addr_hi = regno >> 8; 927*52891Sbostic MachEmptyWriteBuffer(); 928*52891Sbostic return regs->addr_reg; 929*52891Sbostic } 930*52891Sbostic 931*52891Sbostic #ifdef DEBUG 932*52891Sbostic bt459_print_colormap(regs) 933*52891Sbostic bt459_regmap_t *regs; 934*52891Sbostic { 935*52891Sbostic register int i; 936*52891Sbostic 937*52891Sbostic bt459_select_reg(regs, 0); 938*52891Sbostic for (i = 0; i < 256; i++) { 939*52891Sbostic register unsigned red, green, blue; 940*52891Sbostic 941*52891Sbostic red = regs->addr_cmap; 942*52891Sbostic green = regs->addr_cmap; 943*52891Sbostic blue = regs->addr_cmap; 944*52891Sbostic printf("%x->[x%x x%x x%x]\n", i, red, green, blue); 945*52891Sbostic } 946*52891Sbostic } 947*52891Sbostic #endif 948*52891Sbostic 949*52891Sbostic /* 950*52891Sbostic * Test to see if device is present. 951*52891Sbostic * Return true if found and initialized ok. 952*52891Sbostic */ 953*52891Sbostic cfb_init(cp) 954*52891Sbostic register struct pmax_ctlr *cp; 955*52891Sbostic { 956*52891Sbostic bt459_regmap_t *regs; 957*52891Sbostic 958*52891Sbostic /* check for no frame buffer */ 959*52891Sbostic if (badaddr(cp->pmax_addr, 4)) 960*52891Sbostic return (0); 961*52891Sbostic 962*52891Sbostic fb_addr = (unsigned)cp->pmax_addr + CFB_OFFSET_VRAM; 963*52891Sbostic planemask_addr = 0; /* XXX */ 964*52891Sbostic regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 965*52891Sbostic 966*52891Sbostic if (bt459_read_reg(regs, BT459_REG_ID) != 0x4a) 967*52891Sbostic return (0); 968*52891Sbostic 969*52891Sbostic *(int *)(fb_addr + CFB_OFFSET_RESET) = 0; /* force chip reset */ 970*52891Sbostic DELAY(2000); /* ???? check right time on specs! ???? */ 971*52891Sbostic 972*52891Sbostic /* use 4:1 input mux */ 973*52891Sbostic bt459_write_reg(regs, BT459_REG_CMD0, 0x40); 974*52891Sbostic 975*52891Sbostic /* no zooming, no panning */ 976*52891Sbostic bt459_write_reg(regs, BT459_REG_CMD1, 0x00); 977*52891Sbostic 978*52891Sbostic /* 979*52891Sbostic * signature test, X-windows cursor, no overlays, SYNC* PLL, 980*52891Sbostic * normal RAM select, 7.5 IRE pedestal, do sync 981*52891Sbostic */ 982*52891Sbostic bt459_write_reg(regs, BT459_REG_CMD2, 0xc2); 983*52891Sbostic 984*52891Sbostic /* get all pixel bits */ 985*52891Sbostic bt459_write_reg(regs, BT459_REG_PRM, 0xff); 986*52891Sbostic 987*52891Sbostic /* no blinking */ 988*52891Sbostic bt459_write_reg(regs, BT459_REG_PBM, 0x00); 989*52891Sbostic 990*52891Sbostic /* no overlay */ 991*52891Sbostic bt459_write_reg(regs, BT459_REG_ORM, 0x00); 992*52891Sbostic 993*52891Sbostic /* no overlay blink */ 994*52891Sbostic bt459_write_reg(regs, BT459_REG_OBM, 0x00); 995*52891Sbostic 996*52891Sbostic /* no interleave, no underlay */ 997*52891Sbostic bt459_write_reg(regs, BT459_REG_ILV, 0x00); 998*52891Sbostic 999*52891Sbostic /* normal operation, no signature analysis */ 1000*52891Sbostic bt459_write_reg(regs, BT459_REG_TEST, 0x00); 1001*52891Sbostic 1002*52891Sbostic /* 1003*52891Sbostic * no blinking, 1bit cross hair, XOR reg&crosshair, 1004*52891Sbostic * no crosshair on either plane 0 or 1, 1005*52891Sbostic * regular cursor on both planes. 1006*52891Sbostic */ 1007*52891Sbostic bt459_write_reg(regs, BT459_REG_CCR, 0xc0); 1008*52891Sbostic 1009*52891Sbostic /* home cursor */ 1010*52891Sbostic bt459_write_reg(regs, BT459_REG_CXLO, 0x00); 1011*52891Sbostic bt459_write_reg(regs, BT459_REG_CXHI, 0x00); 1012*52891Sbostic bt459_write_reg(regs, BT459_REG_CYLO, 0x00); 1013*52891Sbostic bt459_write_reg(regs, BT459_REG_CYHI, 0x00); 1014*52891Sbostic 1015*52891Sbostic /* no crosshair window */ 1016*52891Sbostic bt459_write_reg(regs, BT459_REG_WXLO, 0x00); 1017*52891Sbostic bt459_write_reg(regs, BT459_REG_WXHI, 0x00); 1018*52891Sbostic bt459_write_reg(regs, BT459_REG_WYLO, 0x00); 1019*52891Sbostic bt459_write_reg(regs, BT459_REG_WYHI, 0x00); 1020*52891Sbostic bt459_write_reg(regs, BT459_REG_WWLO, 0x00); 1021*52891Sbostic bt459_write_reg(regs, BT459_REG_WWHI, 0x00); 1022*52891Sbostic bt459_write_reg(regs, BT459_REG_WHLO, 0x00); 1023*52891Sbostic bt459_write_reg(regs, BT459_REG_WHHI, 0x00); 1024*52891Sbostic 1025*52891Sbostic /* 1026*52891Sbostic * Initialize screen info. 1027*52891Sbostic */ 1028*52891Sbostic pmu.scrInfo.max_row = MAX_ROW; 1029*52891Sbostic pmu.scrInfo.max_col = MAX_COL; 1030*52891Sbostic pmu.scrInfo.max_x = 1024; 1031*52891Sbostic pmu.scrInfo.max_y = 864; 1032*52891Sbostic pmu.scrInfo.max_cur_x = 1023; 1033*52891Sbostic pmu.scrInfo.max_cur_y = 863; 1034*52891Sbostic pmu.scrInfo.version = 11; 1035*52891Sbostic pmu.scrInfo.mthreshold = 4; 1036*52891Sbostic pmu.scrInfo.mscale = 2; 1037*52891Sbostic pmu.scrInfo.min_cur_x = 0; 1038*52891Sbostic pmu.scrInfo.min_cur_y = 0; 1039*52891Sbostic pmu.scrInfo.qe.timestamp_ms = TO_MS(time); 1040*52891Sbostic pmu.scrInfo.qe.eSize = PM_MAXEVQ; 1041*52891Sbostic pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0; 1042*52891Sbostic pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE; 1043*52891Sbostic pmu.scrInfo.qe.tcNext = 0; 1044*52891Sbostic 1045*52891Sbostic /* 1046*52891Sbostic * Initialize the color map, the screen, and the mouse. 1047*52891Sbostic */ 1048*52891Sbostic InitColorMap(); 1049*52891Sbostic ScreenInit(); 1050*52891Sbostic Scroll(); 1051*52891Sbostic 1052*52891Sbostic initialized = 1; 1053*52891Sbostic return (1); 1054*52891Sbostic } 1055*52891Sbostic 1056*52891Sbostic /* 1057*52891Sbostic * ---------------------------------------------------------------------------- 1058*52891Sbostic * 1059*52891Sbostic * ScreenInit -- 1060*52891Sbostic * 1061*52891Sbostic * Initialize the screen. 1062*52891Sbostic * 1063*52891Sbostic * Results: 1064*52891Sbostic * None. 1065*52891Sbostic * 1066*52891Sbostic * Side effects: 1067*52891Sbostic * The screen is initialized. 1068*52891Sbostic * 1069*52891Sbostic * ---------------------------------------------------------------------------- 1070*52891Sbostic */ 1071*52891Sbostic static void 1072*52891Sbostic ScreenInit() 1073*52891Sbostic { 1074*52891Sbostic 1075*52891Sbostic /* 1076*52891Sbostic * Home the cursor. 1077*52891Sbostic * We want an LSI terminal emulation. We want the graphics 1078*52891Sbostic * terminal to scroll from the bottom. So start at the bottom. 1079*52891Sbostic */ 1080*52891Sbostic row = 55; 1081*52891Sbostic col = 0; 1082*52891Sbostic 1083*52891Sbostic /* 1084*52891Sbostic * Load the cursor with the default values 1085*52891Sbostic * 1086*52891Sbostic */ 1087*52891Sbostic LoadCursor(defCursor); 1088*52891Sbostic } 1089*52891Sbostic 1090*52891Sbostic /* 1091*52891Sbostic * ---------------------------------------------------------------------------- 1092*52891Sbostic * 1093*52891Sbostic * LoadCursor -- 1094*52891Sbostic * 1095*52891Sbostic * Routine to load the cursor Sprite pattern. 1096*52891Sbostic * 1097*52891Sbostic * Results: 1098*52891Sbostic * None. 1099*52891Sbostic * 1100*52891Sbostic * Side effects: 1101*52891Sbostic * The cursor is loaded into the hardware cursor. 1102*52891Sbostic * 1103*52891Sbostic * ---------------------------------------------------------------------------- 1104*52891Sbostic */ 1105*52891Sbostic static void 1106*52891Sbostic LoadCursor(cur) 1107*52891Sbostic unsigned short *cur; 1108*52891Sbostic { 1109*52891Sbostic bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 1110*52891Sbostic register int i, j; 1111*52891Sbostic 1112*52891Sbostic /* 1113*52891Sbostic * As per specs, must run a check to see if we 1114*52891Sbostic * had contention. If so, re-write the cursor. 1115*52891Sbostic */ 1116*52891Sbostic for (j = 0; j < 2; j++) { 1117*52891Sbostic /* loop once to write */ 1118*52891Sbostic bt459_select_reg(regs, BT459_REG_CRAM_BASE); 1119*52891Sbostic for (i = 0; i < 1024; i++) { 1120*52891Sbostic regs->addr_reg = cur[i]; 1121*52891Sbostic MachEmptyWriteBuffer(); 1122*52891Sbostic } 1123*52891Sbostic 1124*52891Sbostic /* loop to check, if fail write again */ 1125*52891Sbostic bt459_select_reg(regs, BT459_REG_CRAM_BASE); 1126*52891Sbostic for (i = 0; i < 1024; i++) 1127*52891Sbostic if (regs->addr_reg != cur[i]) 1128*52891Sbostic break; 1129*52891Sbostic if (i == 1024) 1130*52891Sbostic break; /* all went well first shot */ 1131*52891Sbostic } 1132*52891Sbostic } 1133*52891Sbostic 1134*52891Sbostic /* 1135*52891Sbostic * ---------------------------------------------------------------------------- 1136*52891Sbostic * 1137*52891Sbostic * RestoreCursorColor -- 1138*52891Sbostic * 1139*52891Sbostic * Routine to restore the color of the cursor. 1140*52891Sbostic * 1141*52891Sbostic * Results: 1142*52891Sbostic * None. 1143*52891Sbostic * 1144*52891Sbostic * Side effects: 1145*52891Sbostic * None. 1146*52891Sbostic * 1147*52891Sbostic * ---------------------------------------------------------------------------- 1148*52891Sbostic */ 1149*52891Sbostic static void 1150*52891Sbostic RestoreCursorColor() 1151*52891Sbostic { 1152*52891Sbostic bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 1153*52891Sbostic register int i; 1154*52891Sbostic 1155*52891Sbostic bt459_select_reg(regs, BT459_REG_CCOLOR_2); 1156*52891Sbostic for (i = 0; i < 6; i++) { 1157*52891Sbostic regs->addr_reg = cursor_RGB[i]; 1158*52891Sbostic MachEmptyWriteBuffer(); 1159*52891Sbostic } 1160*52891Sbostic } 1161*52891Sbostic 1162*52891Sbostic /* 1163*52891Sbostic * ---------------------------------------------------------------------------- 1164*52891Sbostic * 1165*52891Sbostic * CursorColor -- 1166*52891Sbostic * 1167*52891Sbostic * Set the color of the cursor. 1168*52891Sbostic * 1169*52891Sbostic * Results: 1170*52891Sbostic * None. 1171*52891Sbostic * 1172*52891Sbostic * Side effects: 1173*52891Sbostic * None. 1174*52891Sbostic * 1175*52891Sbostic * ---------------------------------------------------------------------------- 1176*52891Sbostic */ 1177*52891Sbostic static void 1178*52891Sbostic CursorColor(color) 1179*52891Sbostic unsigned int color[]; 1180*52891Sbostic { 1181*52891Sbostic register int i, j; 1182*52891Sbostic 1183*52891Sbostic for (i = 0; i < 6; i++) 1184*52891Sbostic cursor_RGB[i] = (u_char)(color[i] >> 8); 1185*52891Sbostic 1186*52891Sbostic RestoreCursorColor(); 1187*52891Sbostic } 1188*52891Sbostic 1189*52891Sbostic /* 1190*52891Sbostic *---------------------------------------------------------------------- 1191*52891Sbostic * 1192*52891Sbostic * PosCursor -- 1193*52891Sbostic * 1194*52891Sbostic * Postion the cursor. 1195*52891Sbostic * 1196*52891Sbostic * Results: 1197*52891Sbostic * None. 1198*52891Sbostic * 1199*52891Sbostic * Side effects: 1200*52891Sbostic * None. 1201*52891Sbostic * 1202*52891Sbostic *---------------------------------------------------------------------- 1203*52891Sbostic */ 1204*52891Sbostic static void 1205*52891Sbostic PosCursor(x, y) 1206*52891Sbostic register int x, y; 1207*52891Sbostic { 1208*52891Sbostic bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 1209*52891Sbostic 1210*52891Sbostic if (y < pmu.scrInfo.min_cur_y || y > pmu.scrInfo.max_cur_y) 1211*52891Sbostic y = pmu.scrInfo.max_cur_y; 1212*52891Sbostic if (x < pmu.scrInfo.min_cur_x || x > pmu.scrInfo.max_cur_x) 1213*52891Sbostic x = pmu.scrInfo.max_cur_x; 1214*52891Sbostic pmu.scrInfo.cursor.x = x; /* keep track of real cursor */ 1215*52891Sbostic pmu.scrInfo.cursor.y = y; /* position, indep. of mouse */ 1216*52891Sbostic 1217*52891Sbostic x += 219; 1218*52891Sbostic y += 34; 1219*52891Sbostic 1220*52891Sbostic bt459_select_reg(regs, BT459_REG_CXLO); 1221*52891Sbostic regs->addr_reg = x; 1222*52891Sbostic MachEmptyWriteBuffer(); 1223*52891Sbostic regs->addr_reg = x >> 8; 1224*52891Sbostic MachEmptyWriteBuffer(); 1225*52891Sbostic regs->addr_reg = y; 1226*52891Sbostic MachEmptyWriteBuffer(); 1227*52891Sbostic regs->addr_reg = y >> 8; 1228*52891Sbostic MachEmptyWriteBuffer(); 1229*52891Sbostic } 1230*52891Sbostic 1231*52891Sbostic /* 1232*52891Sbostic * ---------------------------------------------------------------------------- 1233*52891Sbostic * 1234*52891Sbostic * InitColorMap -- 1235*52891Sbostic * 1236*52891Sbostic * Initialize the color map. 1237*52891Sbostic * 1238*52891Sbostic * Results: 1239*52891Sbostic * None. 1240*52891Sbostic * 1241*52891Sbostic * Side effects: 1242*52891Sbostic * The colormap is initialized appropriately. 1243*52891Sbostic * 1244*52891Sbostic * ---------------------------------------------------------------------------- 1245*52891Sbostic */ 1246*52891Sbostic static void 1247*52891Sbostic InitColorMap() 1248*52891Sbostic { 1249*52891Sbostic bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 1250*52891Sbostic register int i; 1251*52891Sbostic 1252*52891Sbostic bt459_select_reg(regs, 0); 1253*52891Sbostic regs->addr_cmap = 0; MachEmptyWriteBuffer(); 1254*52891Sbostic regs->addr_cmap = 0; MachEmptyWriteBuffer(); 1255*52891Sbostic regs->addr_cmap = 0; MachEmptyWriteBuffer(); 1256*52891Sbostic 1257*52891Sbostic for (i = 1; i < 256; i++) { 1258*52891Sbostic regs->addr_cmap = 0xff; MachEmptyWriteBuffer(); 1259*52891Sbostic regs->addr_cmap = 0xff; MachEmptyWriteBuffer(); 1260*52891Sbostic regs->addr_cmap = 0xff; MachEmptyWriteBuffer(); 1261*52891Sbostic } 1262*52891Sbostic 1263*52891Sbostic for (i = 0; i < 3; i++) { 1264*52891Sbostic cursor_RGB[i] = 0x00; 1265*52891Sbostic cursor_RGB[i + 3] = 0xff; 1266*52891Sbostic } 1267*52891Sbostic RestoreCursorColor(); 1268*52891Sbostic } 1269*52891Sbostic 1270*52891Sbostic /* 1271*52891Sbostic * ---------------------------------------------------------------------------- 1272*52891Sbostic * 1273*52891Sbostic * LoadColorMap -- 1274*52891Sbostic * 1275*52891Sbostic * Load the color map. 1276*52891Sbostic * 1277*52891Sbostic * Results: 1278*52891Sbostic * None. 1279*52891Sbostic * 1280*52891Sbostic * Side effects: 1281*52891Sbostic * The color map is loaded. 1282*52891Sbostic * 1283*52891Sbostic * ---------------------------------------------------------------------------- 1284*52891Sbostic */ 1285*52891Sbostic static void 1286*52891Sbostic LoadColorMap(ptr) 1287*52891Sbostic ColorMap *ptr; 1288*52891Sbostic { 1289*52891Sbostic bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 1290*52891Sbostic 1291*52891Sbostic if (ptr->index > 256) 1292*52891Sbostic return; 1293*52891Sbostic 1294*52891Sbostic bt459_select_reg(regs, ptr->index); 1295*52891Sbostic 1296*52891Sbostic regs->addr_cmap = ptr->Entry.red; MachEmptyWriteBuffer(); 1297*52891Sbostic regs->addr_cmap = ptr->Entry.green; MachEmptyWriteBuffer(); 1298*52891Sbostic regs->addr_cmap = ptr->Entry.blue; MachEmptyWriteBuffer(); 1299*52891Sbostic } 1300*52891Sbostic 1301*52891Sbostic /* 1302*52891Sbostic * Video on/off state. 1303*52891Sbostic */ 1304*52891Sbostic struct vstate { 1305*52891Sbostic u_char color0[3]; /* saved color map entry zero */ 1306*52891Sbostic u_char off; /* TRUE if display is off */ 1307*52891Sbostic } vstate; 1308*52891Sbostic 1309*52891Sbostic /* 1310*52891Sbostic * ---------------------------------------------------------------------------- 1311*52891Sbostic * 1312*52891Sbostic * EnableVideo -- 1313*52891Sbostic * 1314*52891Sbostic * Enable the video display. 1315*52891Sbostic * 1316*52891Sbostic * Results: 1317*52891Sbostic * None. 1318*52891Sbostic * 1319*52891Sbostic * Side effects: 1320*52891Sbostic * The display is enabled. 1321*52891Sbostic * 1322*52891Sbostic * ---------------------------------------------------------------------------- 1323*52891Sbostic */ 1324*52891Sbostic static void 1325*52891Sbostic EnableVideo() 1326*52891Sbostic { 1327*52891Sbostic bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 1328*52891Sbostic 1329*52891Sbostic if (!vstate.off) 1330*52891Sbostic return; 1331*52891Sbostic 1332*52891Sbostic /* restore old color map entry zero */ 1333*52891Sbostic bt459_select_reg(regs, 0); 1334*52891Sbostic regs->addr_cmap = vstate.color0[0]; 1335*52891Sbostic MachEmptyWriteBuffer(); 1336*52891Sbostic regs->addr_cmap = vstate.color0[1]; 1337*52891Sbostic MachEmptyWriteBuffer(); 1338*52891Sbostic regs->addr_cmap = vstate.color0[2]; 1339*52891Sbostic MachEmptyWriteBuffer(); 1340*52891Sbostic 1341*52891Sbostic /* enable normal display */ 1342*52891Sbostic bt459_write_reg(regs, BT459_REG_PRM, 0xff); 1343*52891Sbostic bt459_write_reg(regs, BT459_REG_CCR, 0xc0); 1344*52891Sbostic 1345*52891Sbostic vstate.off = 0; 1346*52891Sbostic } 1347*52891Sbostic 1348*52891Sbostic /* 1349*52891Sbostic * ---------------------------------------------------------------------------- 1350*52891Sbostic * 1351*52891Sbostic * DisableVideo -- 1352*52891Sbostic * 1353*52891Sbostic * Disable the video display. 1354*52891Sbostic * 1355*52891Sbostic * Results: 1356*52891Sbostic * None. 1357*52891Sbostic * 1358*52891Sbostic * Side effects: 1359*52891Sbostic * The display is disabled. 1360*52891Sbostic * 1361*52891Sbostic * ---------------------------------------------------------------------------- 1362*52891Sbostic */ 1363*52891Sbostic static void 1364*52891Sbostic DisableVideo() 1365*52891Sbostic { 1366*52891Sbostic bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459); 1367*52891Sbostic 1368*52891Sbostic if (vstate.off) 1369*52891Sbostic return; 1370*52891Sbostic 1371*52891Sbostic /* save old color map entry zero */ 1372*52891Sbostic bt459_select_reg(regs, 0); 1373*52891Sbostic vstate.color0[0] = regs->addr_cmap; 1374*52891Sbostic vstate.color0[1] = regs->addr_cmap; 1375*52891Sbostic vstate.color0[2] = regs->addr_cmap; 1376*52891Sbostic 1377*52891Sbostic /* set color map entry zero to zero */ 1378*52891Sbostic bt459_select_reg(regs, 0); 1379*52891Sbostic regs->addr_cmap = 0; 1380*52891Sbostic MachEmptyWriteBuffer(); 1381*52891Sbostic regs->addr_cmap = 0; 1382*52891Sbostic MachEmptyWriteBuffer(); 1383*52891Sbostic regs->addr_cmap = 0; 1384*52891Sbostic MachEmptyWriteBuffer(); 1385*52891Sbostic 1386*52891Sbostic /* disable display */ 1387*52891Sbostic bt459_write_reg(regs, BT459_REG_PRM, 0); 1388*52891Sbostic bt459_write_reg(regs, BT459_REG_CCR, 0); 1389*52891Sbostic 1390*52891Sbostic vstate.off = 1; 1391*52891Sbostic } 1392*52891Sbostic #endif 1393