134511Smarc /* 2*34642Smarc * Copyright (c) 1982, 1986 Regents of the University of California. 3*34642Smarc * All rights reserved. The Berkeley software License Agreement 4*34642Smarc * specifies the terms and conditions for redistribution. 5*34642Smarc * 6*34642Smarc * @(#)qd.c 1.8 Berkeley 06/05/88 7*34642Smarc * 8*34642Smarc */ 9*34642Smarc 1030391Skarels /************************************************************************ 1134511Smarc * * 1234615Smarc * Copyright (c) 1985-1988 by * 1330391Skarels * Digital Equipment Corporation, Maynard, MA * 1430391Skarels * All rights reserved. * 1530391Skarels * * 1630391Skarels * This software is furnished under a license and may be used and * 1730391Skarels * copied only in accordance with the terms of such license and * 1830391Skarels * with the inclusion of the above copyright notice. This * 1930391Skarels * software or any other copies thereof may not be provided or * 2030391Skarels * otherwise made available to any other person. No title to and * 2130391Skarels * ownership of the software is hereby transferred. * 2230391Skarels * * 2330391Skarels * The information in this software is subject to change without * 2430391Skarels * notice and should not be construed as a commitment by Digital * 2530391Skarels * Equipment Corporation. * 2630391Skarels * * 2730391Skarels * Digital assumes no responsibility for the use or reliability * 2830391Skarels * of its software on equipment which is not supplied by Digital. * 2930391Skarels * * 3030391Skarels *************************************************************************/ 3134615Smarc 3230391Skarels /* 33*34642Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation 3430391Skarels */ 3530391Skarels 36*34642Smarc #include "qd.h" 3734615Smarc 3834511Smarc #if NQD > 0 3934615Smarc #include "types.h" 40*34642Smarc #include "../machine/pte.h" 41*34642Smarc #include "../machine/mtpr.h" 4234511Smarc #include "../machine/cpu.h" 43*34642Smarc #include "param.h" 44*34642Smarc #include "conf.h" 45*34642Smarc #include "dir.h" 46*34642Smarc #include "user.h" 47*34642Smarc #include "qdioctl.h" 4834511Smarc #include "tty.h" 49*34642Smarc #include "map.h" 50*34642Smarc #include "buf.h" 51*34642Smarc #include "vm.h" 52*34642Smarc #include "bk.h" 53*34642Smarc #include "clist.h" 54*34642Smarc #include "file.h" 55*34642Smarc #include "uio.h" 56*34642Smarc #include "kernel.h" 5734615Smarc #include "exec.h" 5834615Smarc #include "proc.h" 59*34642Smarc #include "ubareg.h" 60*34642Smarc #include "ubavar.h" 6134511Smarc #include "syslog.h" 62*34642Smarc #include "qduser.h" /* definitions shared with user level client */ 6334615Smarc #include "qdreg.h" /* QDSS device register structures */ 6432012Smarc 65*34642Smarc /* 66*34642Smarc * QDSS driver status flags for tracking operational state 67*34642Smarc */ 68*34642Smarc struct qdflags { 69*34642Smarc u_int inuse; /* which minor dev's are in use now */ 70*34642Smarc u_int config; /* I/O page register content */ 71*34642Smarc u_int mapped; /* user mapping status word */ 72*34642Smarc u_int kernel_loop; /* if kernel console is redirected */ 73*34642Smarc u_int user_dma; /* DMA from user space in progress */ 74*34642Smarc u_short pntr_id; /* type code of pointing device */ 75*34642Smarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 76*34642Smarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 77*34642Smarc u_short curs_acc; /* cursor acceleration factor */ 78*34642Smarc u_short curs_thr; /* cursor acceleration threshold level */ 79*34642Smarc u_short tab_res; /* tablet resolution factor */ 80*34642Smarc u_short selmask; /* mask for active qd select entries */ 81*34642Smarc }; 8232012Smarc 83*34642Smarc /* 84*34642Smarc * bit definitions for 'inuse' entry 85*34642Smarc */ 8632012Smarc #define CONS_DEV 0x01 8732012Smarc #define GRAPHIC_DEV 0x04 8832012Smarc 89*34642Smarc /* 90*34642Smarc * bit definitions for 'mapped' member of flag structure 91*34642Smarc */ 9232012Smarc #define MAPDEV 0x01 /* hardware is mapped */ 9332012Smarc #define MAPDMA 0x02 /* DMA buffer mapped */ 9432012Smarc #define MAPEQ 0x04 /* event queue buffer mapped */ 9532012Smarc #define MAPSCR 0x08 /* scroll param area mapped */ 9632012Smarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 9732012Smarc 98*34642Smarc /* 99*34642Smarc * bit definitions for 'selmask' member of qdflag structure 100*34642Smarc */ 10132012Smarc #define SEL_READ 0x01 /* read select is active */ 10232012Smarc #define SEL_WRITE 0x02 /* write select is active */ 10332012Smarc 104*34642Smarc /* 105*34642Smarc * constants used in shared memory operations 106*34642Smarc */ 10732012Smarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 10832012Smarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 109*34642Smarc / sizeof(struct _vs_event) ) 11034527Smarc #define DMA_BUFSIZ (1024 * 10) 11132012Smarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 11232012Smarc 113*34642Smarc /* 11432012Smarc * reference to an array of "uba_device" structures built by the auto 11532012Smarc * configuration program. The uba_device structure decribes the device 11632012Smarc * sufficiently for the driver to talk to it. The auto configuration code 11732012Smarc * fills in the uba_device structures (located in ioconf.c) from user 118*34642Smarc * maintained info. 119*34642Smarc */ 120*34642Smarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 121*34642Smarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 122*34642Smarc struct qd_softc qd_softc[NQD]; 123*34642Smarc extern char qvmem[][128*NBPG]; /* XXX - *NQD - but can't test it */ 124*34642Smarc extern struct pte QVmap[][128]; 125*34642Smarc #define CHUNK (64 * 1024) 126*34642Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 12732012Smarc 128*34642Smarc /* 129*34642Smarc * static storage used by multiple functions in this code 130*34642Smarc */ 131*34642Smarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 132*34642Smarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 133*34642Smarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 134*34642Smarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 135*34642Smarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 136*34642Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 13732012Smarc 138*34642Smarc /* 13934615Smarc * the array "event_shared[]" is made up of a number of event queue buffers 14032012Smarc * equal to the number of QDSS's configured into the running kernel (NQD). 14132012Smarc * Each event queue buffer begins with an event queue header (struct qdinput) 14232012Smarc * followed by a group of event queue entries (struct _vs_event). The array 14332012Smarc * "*eq_header[]" is an array of pointers to the start of each event queue 144*34642Smarc * buffer in "event_shared[]". 145*34642Smarc */ 14632012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 14732012Smarc 148*34642Smarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 149*34642Smarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 15032012Smarc 151*34642Smarc /* 15232012Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 15332012Smarc * buffers. Each buffer must consume an integral number of memory pages to 15432012Smarc * guarantee that a following buffer will begin on a page boundary. Also, 15532012Smarc * enough space is allocated so that the FIRST I/O buffer can start at the 15632012Smarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 157*34642Smarc * memory protections can be turned on/off for individual buffers. 158*34642Smarc */ 15932012Smarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 16032012Smarc 161*34642Smarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 162*34642Smarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 16332012Smarc 164*34642Smarc /* 16532012Smarc * The driver assists a client in scroll operations by loading dragon 16632012Smarc * registers from an interrupt service routine. The loading is done using 16732012Smarc * parameters found in memory shrade between the driver and it's client. 16832012Smarc * The scroll parameter structures are ALL loacted in the same memory page 169*34642Smarc * for reasons of memory economy. 170*34642Smarc */ 171*34642Smarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 172*34642Smarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 17332012Smarc 174*34642Smarc /* 17532012Smarc * the driver is programmable to provide the user with color map write 17632012Smarc * services at VSYNC interrupt time. At interrupt time the driver loads 177*34642Smarc * the color map with any user-requested load data found in shared memory 178*34642Smarc */ 17932012Smarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 18032012Smarc 181*34642Smarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 182*34642Smarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 18332012Smarc 184*34642Smarc /* 185*34642Smarc * mouse input event structures 186*34642Smarc */ 187*34642Smarc struct mouse_report last_rep[NQD]; 188*34642Smarc struct mouse_report current_rep[NQD]; 18932012Smarc 190*34642Smarc struct proc *rsel[NQD]; /* process waiting for select */ 191*34642Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 192*34642Smarc int qdcount = 0; /* count of successfully probed qd's */ 193*34642Smarc int nNQD = NQD; 194*34642Smarc int DMAbuf_size = DMA_BUFSIZ; 195*34642Smarc int QDlast_DMAtype; /* type of the last DMA operation */ 19632012Smarc 197*34642Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 198*34642Smarc /* 199*34642Smarc * macro to get system time. Used to time stamp event queue entries 200*34642Smarc */ 20130391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 20230391Skarels 203*34642Smarc int qdprobe(); 204*34642Smarc int qdattach(); 205*34642Smarc int qddint(); /* DMA gate array intrpt service */ 206*34642Smarc int qdaint(); /* Dragon ADDER intrpt service */ 207*34642Smarc int qdiint(); 20830391Skarels 209*34642Smarc u_short qdstd[] = { 0 }; 21030391Skarels 211*34642Smarc struct uba_driver qddriver = { 212*34642Smarc qdprobe, /* device probe entry */ 213*34642Smarc 0, /* no slave device */ 214*34642Smarc qdattach, /* device attach entry */ 215*34642Smarc 0, /* no "fill csr/ba to start" */ 216*34642Smarc qdstd, /* device addresses */ 217*34642Smarc "qd", /* device name string */ 218*34642Smarc qdinfo /* ptr to QDSS's uba_device struct */ 219*34642Smarc }; 22030391Skarels 22134615Smarc #define QDPRIOR (PZERO-1) /* must be negative */ 22230391Skarels #define FALSE 0 22330391Skarels #define TRUE ~FALSE 22430391Skarels #define BAD -1 22530391Skarels #define GOOD 0 22630391Skarels 227*34642Smarc /* 228*34642Smarc * macro to create a system virtual page number from system virtual adrs 229*34642Smarc */ 230*34642Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 23130391Skarels 232*34642Smarc /* 233*34642Smarc * QDSS register address offsets from start of QDSS address space 234*34642Smarc */ 23530391Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 23630391Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 23730391Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 23830391Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 23930391Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 24030391Skarels #define ADDER (REGSTART+0x000) 24130391Skarels #define DGA (REGSTART+0x200) 24230391Skarels #define DUART (REGSTART+0x400) 24330391Skarels #define MEMCSR (REGSTART+0x800) 24430391Skarels #define CLRSIZE (3 * 512) /* color map size */ 24530391Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 246*34642Smarc /* 0x0C00 really */ 24730391Skarels #define RED (CLRSTART+0x000) 24830391Skarels #define BLUE (CLRSTART+0x200) 24930391Skarels #define GREEN (CLRSTART+0x400) 25030391Skarels 25130391Skarels 252*34642Smarc /* 253*34642Smarc * QDSS minor device numbers. The *real* minor device numbers are in 254*34642Smarc * the bottom two bits of the major/minor device spec. Bits 2 and up are 255*34642Smarc * used to specify the QDSS device number (ie: which one?) 256*34642Smarc */ 25730391Skarels 25830391Skarels #define CONS 0 25930391Skarels #define GRAPHIC 2 26030391Skarels 261*34642Smarc /* 262*34642Smarc * console cursor bitmap (white block cursor) 263*34642Smarc */ 264*34642Smarc short cons_cursor[32] = { 265*34642Smarc /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 266*34642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 267*34642Smarc /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 268*34642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 269*34642Smarc }; 27030391Skarels 271*34642Smarc /* 272*34642Smarc * constants used in font operations 273*34642Smarc */ 27434615Smarc #define CHARS 190 /* # of chars in the font */ 27530391Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 27630391Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 27730391Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 27830391Skarels #define ROWS CHAR_HEIGHT 27930391Skarels #define FONT_X 0 /* font's off screen adrs */ 28030391Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 28130391Skarels 282*34642Smarc /* Offset to second row characters (XXX - should remove) */ 28334615Smarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 28430391Skarels 285*34642Smarc extern char q_font[]; /* reference font object code */ 286*34642Smarc extern u_short q_key[]; /* reference key xlation tables */ 287*34642Smarc extern u_short q_shift_key[]; 288*34642Smarc extern char *q_special[]; 28930391Skarels 290*34642Smarc /* 291*34642Smarc * definitions for cursor acceleration reporting 292*34642Smarc */ 29330391Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 29430391Skarels 295*34642Smarc /* 296*34642Smarc * virtual console support. 297*34642Smarc */ 298*34642Smarc extern (*v_putc)(); 299*34642Smarc extern struct cdevsw *consops; 300*34642Smarc int qdputc(); 301*34642Smarc int qdstart(); 30230391Skarels 303*34642Smarc /* 304*34642Smarc * LK-201 state storage for input console keyboard conversion to ASCII 305*34642Smarc */ 306*34642Smarc struct q_keyboard { 307*34642Smarc int shift; /* state variables */ 308*34642Smarc int cntrl; 309*34642Smarc int lock; 310*34642Smarc int lastcode; /* last keycode typed */ 311*34642Smarc unsigned kup[8]; /* bits for each keycode*/ 312*34642Smarc unsigned dkeys[8]; /* down/up mode keys */ 313*34642Smarc char last; /* last character */ 314*34642Smarc } q_keyboard; 31530391Skarels 316*34642Smarc /* 317*34642Smarc * tty settings on first open 318*34642Smarc */ 31934615Smarc #define IFLAGS (EVENP|ECHO|XTABS|CRMOD) 32034615Smarc #ifdef POSIXTTY 32134615Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL) 32234615Smarc #define OFLAG (OPOST|OXTABS|ONLCR) 32334615Smarc #define LFLAG (ISIG|ICANON|ECHO) 32434615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 32534615Smarc #endif 32634615Smarc 32730391Skarels /********************************************************************* 32830391Skarels * 32934615Smarc * qdcons_init()... init QDSS as console (before probe routine) 33030391Skarels * 33130391Skarels *********************************************************************/ 33230391Skarels 33330391Skarels qdcons_init() 33430391Skarels { 33530391Skarels register u_int unit; 33630391Skarels int *ptep; /* page table entry pointer */ 33730391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 33834615Smarc u_int mapix; /* index into QVmap[] array */ 33934615Smarc struct percpu *pcpu; /* pointer to cpusw structure */ 34034615Smarc register struct qbus *qb; 34130391Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 34230391Skarels u_short *devptr; /* vitual device space */ 34334615Smarc extern cnputc(); 34430391Skarels 34530391Skarels #define QDSSCSR 0x1F00 34630391Skarels 34732012Smarc if (v_putc != cnputc) 348*34642Smarc return; 34932012Smarc 35030391Skarels unit = 0; 35130391Skarels 352*34642Smarc /* 353*34642Smarc * find the cpusw entry that matches this machine. 354*34642Smarc */ 35532012Smarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 35632012Smarc ; 35732012Smarc if (pcpu == NULL) 358*34642Smarc return; 35930391Skarels 36032012Smarc /* 36134615Smarc * Map device registers - the last 8K of qvmem. 36232012Smarc */ 36332012Smarc qb = (struct qbus *)pcpu->pc_io->io_details; 36432012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 365*34642Smarc UBAIOPAGES * NBPG); 36632012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 36730391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 36832012Smarc if (badaddr(qdaddr, sizeof(short))) { 36934615Smarc printf("Can't find qdss (badaddr)\n"); /* debug */ 37030391Skarels return(0); 37132012Smarc } 37234615Smarc 37332012Smarc /* 37432012Smarc * Map q-bus memory used by qdss. (separate map) 37532012Smarc */ 37632012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 37732012Smarc phys_adr = qb->qb_maddr + mapix; 37832012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 37930391Skarels 38032012Smarc /* 38132012Smarc * tell QDSS which Q memory address base to decode 382*34642Smarc * (shifted right 16 bits - its in 64K units) 38332012Smarc */ 38432012Smarc *qdaddr = (u_short)((int)mapix >> 16); 38530391Skarels qdflags[unit].config = *(u_short *)qdaddr; 38630391Skarels 387*34642Smarc /* 388*34642Smarc * load qdmap struct with the virtual addresses of the QDSS elements 389*34642Smarc */ 39034615Smarc qdbase[unit] = (caddr_t) (qvmem[0]); 39130391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 39230391Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 39330391Skarels qdmap[unit].dga = qdbase[unit] + DGA; 39430391Skarels qdmap[unit].duart = qdbase[unit] + DUART; 39530391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 39630391Skarels qdmap[unit].red = qdbase[unit] + RED; 39730391Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 39830391Skarels qdmap[unit].green = qdbase[unit] + GREEN; 39930391Skarels 40030391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 40130391Skarels 402*34642Smarc /* 403*34642Smarc * init the QDSS 404*34642Smarc */ 405*34642Smarc /* 40632012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 407*34642Smarc (char *)qdbase[0], qdmap[0].memcsr); 408*34642Smarc */ 40932012Smarc 41030391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 41130391Skarels 41230391Skarels cursor[unit].x = 0; 41330391Skarels cursor[unit].y = 0; 41430391Skarels init_shared(unit); /* init shared memory */ 41530391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 41630391Skarels clear_qd_screen(unit); /* clear the screen */ 41730391Skarels ldfont(unit); /* load the console font */ 41830391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 41930391Skarels setup_input(unit); /* init the DUART */ 420*34642Smarc v_putc = qdputc; /* kernel console output to qdss */ 421*34642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 42230391Skarels return(1); 42330391Skarels 42430391Skarels } /* qdcons_init */ 42530391Skarels 42630391Skarels /********************************************************************* 42730391Skarels * 42830391Skarels * qdprobe()... configure QDSS into Q memory and make it intrpt 42930391Skarels * 43030391Skarels ********************************************************************** 43130391Skarels * 43230391Skarels * calling convention: 43330391Skarels * qdprobe(reg, ctlr); 43430391Skarels * caddr_t reg; 43530391Skarels * int ctlr; 43630391Skarels * 43730391Skarels * where: reg - a character pointer to the QDSS I/O page register 43830391Skarels * ctlr - controller number (?) 43930391Skarels * 44030391Skarels * side effects: QDSS gets mapped into Qbus memory space at the first 44130391Skarels * vacant 64kb boundary counting back from the top of 44234615Smarc * Qbus memory space (qvmem+4mb) 44330391Skarels * 44430391Skarels * return: QDSS bus request level and vector address returned in 44530391Skarels * registers by UNIX convention. 44630391Skarels * 44730391Skarels *****************/ 44830391Skarels 44930391Skarels qdprobe(reg) 450*34642Smarc caddr_t reg; 45130391Skarels { 452*34642Smarc register int br, cvec; /* value-result */ 45330391Skarels register int unit; 45430391Skarels struct dga *dga; /* pointer to gate array structure */ 45530391Skarels struct cpusw *cpup; /* pointer to the cpusw structure */ 45630391Skarels int *ptep; /* page table entry pointer */ 45730391Skarels int vector; 45830391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 45930391Skarels u_int mapix; 46030391Skarels 461*34642Smarc /* 462*34642Smarc * calculate board unit number from I/O page register address 463*34642Smarc */ 46430391Skarels unit = (int) (((int)reg >> 1) & 0x0007); 46530391Skarels 466*34642Smarc /* 467*34642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 468*34642Smarc * physical boundary. The Qbus memory space is mapped into 469*34642Smarc * the system memory space at config time. After config 470*34642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 471*34642Smarc * of the start of Qbus memory. The Qbus memory page table 472*34642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 473*34642Smarc * which is also loaded at config time. These are the 474*34642Smarc * variables used below to find a vacant 64kb boundary in 475*34642Smarc * Qbus memory, and load it's corresponding physical adrs 476*34642Smarc * into the QDSS's I/O page CSR. 477*34642Smarc */ 47830391Skarels 47934615Smarc /* 48034615Smarc * Only if QD is the graphics device. 48134615Smarc */ 48234615Smarc 48330391Skarels /* if this QDSS is NOT the console, then do init here.. */ 48430391Skarels 48534615Smarc if (unit != 0) { 48634615Smarc printf("qd: can't support two qdss's (yet)\n"); 487*34642Smarc #ifdef notdef /* notyet - don't have two qd's so i can't test it */ 488*34642Smarc if (v_consputc != qdputc || unit != 0) { 48930391Skarels 490*34642Smarc /* 491*34642Smarc * read QDSS config info 492*34642Smarc */ 493*34642Smarc qdflags[unit].config = *(u_short *)reg; 49434615Smarc 495*34642Smarc /* 496*34642Smarc * find an empty 64kb adrs boundary 497*34642Smarc */ 49830391Skarels 499*34642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 50030391Skarels 501*34642Smarc /* 502*34642Smarc * find the cpusw entry that matches this machine. */ 50334615Smarc 504*34642Smarc cpup = &cpusw[cpu]; 505*34642Smarc while ( !(BADADDR(qdbase[unit], sizeof(short))) ) 506*34642Smarc qdbase[unit] -= CHUNK; 50734615Smarc 508*34642Smarc /* 509*34642Smarc * tell QDSS which Q memory address base to decode */ 51030391Skarels 511*34642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 512*34642Smarc ptep = (int *) QVmap[0] + mapix; 513*34642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 514*34642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 51534615Smarc 516*34642Smarc /* 517*34642Smarc * load QDSS adrs map with system addresses 518*34642Smarc * of device regs 519*34642Smarc */ 520*34642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART; 521*34642Smarc qdmap[unit].adder = qdbase[unit] + ADDER; 522*34642Smarc qdmap[unit].dga = qdbase[unit] + DGA; 523*34642Smarc qdmap[unit].duart = qdbase[unit] + DUART; 524*34642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 525*34642Smarc qdmap[unit].red = qdbase[unit] + RED; 526*34642Smarc qdmap[unit].blue = qdbase[unit] + BLUE; 527*34642Smarc qdmap[unit].green = qdbase[unit] + GREEN; 52830391Skarels 529*34642Smarc /* device init */ 53034615Smarc 531*34642Smarc cursor[unit].x = 0; 532*34642Smarc cursor[unit].y = 0; 533*34642Smarc init_shared(unit); /* init shared memory */ 534*34642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */ 535*34642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */ 536*34642Smarc setup_input(unit); /* init the DUART */ 537*34642Smarc clear_qd_screen(unit); 538*34642Smarc ldfont(unit); /* load the console font */ 53930391Skarels 540*34642Smarc /* once only: turn on sync */ 54130391Skarels 542*34642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON; 543*34642Smarc } 54434615Smarc #endif /*notdef*/ 54530391Skarels } 54630391Skarels 547*34642Smarc /* 548*34642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 549*34642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 550*34642Smarc * vectors from the vector pool, and then continue 551*34642Smarc * to take them until we get a xx0 HEX vector. The 552*34642Smarc * pool provides vectors in contiguous decending 553*34642Smarc * order. 554*34642Smarc */ 55530391Skarels 55630391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 55730391Skarels 558*34642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */ 559*34642Smarc /* ..take another vector */ 560*34642Smarc vector = (uba_hd[0].uh_lastiv -= 4); 56130391Skarels } 56230391Skarels 563*34642Smarc /* 564*34642Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 565*34642Smarc */ 56630391Skarels dga = (struct dga *) qdmap[unit].dga; 567*34642Smarc dga->csr = (short) HALT; /* disable everything */ 568*34642Smarc dga->ivr = (short) vector; /* load intrpt base vector */ 569*34642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 57030391Skarels dga->bytcnt_hi = (short) 0; 57130391Skarels 572*34642Smarc /* 573*34642Smarc * turn on DMA interrupts 574*34642Smarc */ 57530391Skarels dga->csr &= ~SET_DONE_FIFO; 57630391Skarels dga->csr |= DMA_IE | DL_ENB; 57730391Skarels 57830391Skarels DELAY(20000); /* wait for the intrpt */ 57930391Skarels dga->csr = HALT; /* stop the wheels */ 58030391Skarels 58130391Skarels if (cvec != vector) /* if vector != base vector.. */ 58230391Skarels return(0); /* ..return = 'no device' */ 58330391Skarels 58434615Smarc /* 585*34642Smarc * score this as an existing qdss 586*34642Smarc */ 58734615Smarc qdcount++; 58834615Smarc 58930391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 59030391Skarels 59130391Skarels } /* qdprobe */ 59230391Skarels 59330391Skarels /***************************************************************** 59430391Skarels * 59534615Smarc * qdattach()... do the one-time initialization 59630391Skarels * 59730391Skarels ****************************************************************** 59830391Skarels * 59930391Skarels * calling convention: 60030391Skarels * qdattach(ui); 60130391Skarels * struct uba_device *ui; 60230391Skarels * 60330391Skarels * where: ui - pointer to the QDSS's uba_device structure 60430391Skarels * 60530391Skarels * side effects: none 60630391Skarels * return: none 60730391Skarels * 60830391Skarels *************************/ 60930391Skarels 61030391Skarels qdattach(ui) 611*34642Smarc struct uba_device *ui; 61230391Skarels { 61330391Skarels register u_int unit; /* QDSS module # for this call */ 61430391Skarels 61530391Skarels unit = ui->ui_unit; /* get QDSS number */ 61630391Skarels 617*34642Smarc /* 618*34642Smarc * init "qdflags[]" for this QDSS 619*34642Smarc */ 62030391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 62130391Skarels qdflags[unit].mapped = 0; 62234615Smarc qdflags[unit].kernel_loop = -1; 62330391Skarels qdflags[unit].user_dma = 0; 62430391Skarels qdflags[unit].curs_acc = ACC_OFF; 62530391Skarels qdflags[unit].curs_thr = 128; 62630391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 62730391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 62830391Skarels qdflags[unit].adder_ie = 0; 62930391Skarels 630*34642Smarc /* 631*34642Smarc * init structures used in kbd/mouse interrupt service. This code must 632*34642Smarc * come after the "init_shared()" routine has run since that routine 633*34642Smarc * inits the eq_header[unit] structure used here. 634*34642Smarc */ 63530391Skarels 636*34642Smarc /* 637*34642Smarc * init the "latest mouse report" structure 638*34642Smarc */ 63930391Skarels last_rep[unit].state = 0; 64030391Skarels last_rep[unit].dx = 0; 64130391Skarels last_rep[unit].dy = 0; 64230391Skarels last_rep[unit].bytcnt = 0; 64330391Skarels 644*34642Smarc /* 64534615Smarc * init the event queue (except mouse position) */ 64630391Skarels 64730391Skarels eq_header[unit]->header.events = (struct _vs_event *) 648*34642Smarc ((int)eq_header[unit] 649*34642Smarc + sizeof(struct qdinput)); 65030391Skarels 65130391Skarels eq_header[unit]->header.size = MAXEVENTS; 65230391Skarels eq_header[unit]->header.head = 0; 65330391Skarels eq_header[unit]->header.tail = 0; 65430391Skarels 655*34642Smarc /* 656*34642Smarc * open exclusive for graphics device. 657*34642Smarc */ 658*34642Smarc qdopened[unit] = 0; 65930391Skarels 66030391Skarels } /* qdattach */ 66130391Skarels 66230391Skarels /*************************************************************** 66330391Skarels * 66434615Smarc * qdopen()... open a minor device 66530391Skarels * 66630391Skarels **************************************************************** 66730391Skarels * 66830391Skarels * calling convention: qdopen(dev, flag); 66930391Skarels * dev_t dev; 67030391Skarels * int flag; 67130391Skarels * 67230391Skarels * side effects: none 67330391Skarels * 67430391Skarels *********************/ 67530391Skarels 67630391Skarels qdopen(dev, flag) 677*34642Smarc dev_t dev; 678*34642Smarc int flag; 67930391Skarels { 68030391Skarels register struct uba_device *ui; /* ptr to uba structures */ 68130391Skarels register struct dga *dga; /* ptr to gate array struct */ 68230391Skarels register struct tty *tp; 68330391Skarels struct adder *adder; 68430391Skarels struct duart *duart; 68530391Skarels u_int unit; 68630391Skarels u_int minor_dev; 68730391Skarels int s; 68830391Skarels 68930391Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 69030391Skarels unit = minor_dev >> 2; 69130391Skarels 692*34642Smarc /* 693*34642Smarc * check for illegal conditions 694*34642Smarc */ 69530391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 69630391Skarels if (ui == 0 || ui->ui_alive == 0) 697*34642Smarc return(ENXIO); /* no such device or address */ 69830391Skarels 69930391Skarels adder = (struct adder *) qdmap[unit].adder; 70030391Skarels duart = (struct duart *) qdmap[unit].duart; 70130391Skarels dga = (struct dga *) qdmap[unit].dga; 70230391Skarels 70330391Skarels if ((minor_dev & 0x03) == 2) { 704*34642Smarc /* 705*34642Smarc * this is the graphic device... 706*34642Smarc */ 707*34642Smarc if (qdopened[unit] != 0) 708*34642Smarc return(EBUSY); 709*34642Smarc else 710*34642Smarc qdopened[unit] = 1; 711*34642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 712*34642Smarc /* 713*34642Smarc * enble kbd & mouse intrpts in DUART mask reg 714*34642Smarc */ 715*34642Smarc qdflags[unit].duart_imask |= 0x22; 716*34642Smarc duart->imask = qdflags[unit].duart_imask; 717*34642Smarc } else { 718*34642Smarc /* 719*34642Smarc * this is the console 720*34642Smarc */ 721*34642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 722*34642Smarc dga->csr |= CURS_ENB; 723*34642Smarc qdflags[unit].duart_imask |= 0x02; 724*34642Smarc duart->imask = qdflags[unit].duart_imask; 725*34642Smarc /* 726*34642Smarc * some setup for tty handling 727*34642Smarc */ 728*34642Smarc tp = &qd_tty[minor_dev]; 729*34642Smarc tp->t_addr = ui->ui_addr; 730*34642Smarc tp->t_oproc = qdstart; 731*34642Smarc if ((tp->t_state & TS_ISOPEN) == 0) { 732*34642Smarc ttychars(tp); 733*34642Smarc tp->t_flags = IFLAGS; 734*34642Smarc tp->t_ispeed = B9600; 735*34642Smarc tp->t_ospeed = B9600; 736*34642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 737*34642Smarc #ifdef POSIXTTY 738*34642Smarc tp->t_iflag = TTYDEF_IFLAG; 739*34642Smarc tp->t_oflag = TTYDEF_OFLAG; 740*34642Smarc tp->t_lflag = TTYDEF_LFLAG; 741*34642Smarc tp->t_cflag = TTYDEF_CFLAG; 742*34642Smarc #endif 74332012Smarc } 744*34642Smarc /* 745*34642Smarc * enable intrpts, open line discipline 746*34642Smarc */ 747*34642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 748*34642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp)); 74930391Skarels } 75030391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 75130391Skarels return(0); 75230391Skarels 75330391Skarels } /* qdopen */ 75430391Skarels 75530391Skarels /*************************************************************** 75630391Skarels * 75734615Smarc * qdclose()... clean up on the way out 75830391Skarels * 75930391Skarels **************************************************************** 76030391Skarels * 76130391Skarels * calling convention: qdclose(); 76230391Skarels * 76330391Skarels * side effects: none 76430391Skarels * 76530391Skarels * return: none 76630391Skarels * 76730391Skarels *********************/ 76830391Skarels 76930391Skarels qdclose(dev, flag) 770*34642Smarc dev_t dev; 771*34642Smarc int flag; 77230391Skarels { 77330391Skarels register struct tty *tp; 77430391Skarels register struct qdmap *qd; 77530391Skarels register int *ptep; 77630391Skarels struct dga *dga; /* gate array register map pointer */ 77730391Skarels struct duart *duart; 77830391Skarels struct adder *adder; 77930391Skarels u_int unit; 78030391Skarels u_int minor_dev; 78130391Skarels u_int mapix; 782*34642Smarc int i; /* SIGNED index */ 78330391Skarels 78430391Skarels minor_dev = minor(dev); /* get minor device number */ 78530391Skarels unit = minor_dev >> 2; /* get QDSS number */ 78630391Skarels qd = &qdmap[unit]; 78730391Skarels 78830391Skarels if ((minor_dev & 0x03) == 2) { 789*34642Smarc /* 790*34642Smarc * this is the graphic device... 791*34642Smarc */ 792*34642Smarc if (qdopened[unit] != 1) 793*34642Smarc return(EBUSY); 794*34642Smarc else 795*34642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 796*34642Smarc /* 797*34642Smarc * re-protect device memory 798*34642Smarc */ 799*34642Smarc if (qdflags[unit].mapped & MAPDEV) { 800*34642Smarc /* 801*34642Smarc * TEMPLATE RAM 802*34642Smarc */ 803*34642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 804*34642Smarc ptep = (int *)(QVmap[0] + mapix); 805*34642Smarc for (i = VTOP(TMPSIZE); i > 0; --i) 806*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW; 807*34642Smarc /* 808*34642Smarc * ADDER 809*34642Smarc */ 810*34642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 811*34642Smarc ptep = (int *)(QVmap[0] + mapix); 812*34642Smarc for (i = VTOP(REGSIZE); i > 0; --i) 813*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW; 814*34642Smarc /* 815*34642Smarc * COLOR MAPS 816*34642Smarc */ 817*34642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 818*34642Smarc ptep = (int *)(QVmap[0] + mapix); 819*34642Smarc for (i = VTOP(CLRSIZE); i > 0; --i) 820*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW; 821*34642Smarc } 82234615Smarc 823*34642Smarc /* 824*34642Smarc * re-protect DMA buffer and free the map registers 825*34642Smarc */ 826*34642Smarc if (qdflags[unit].mapped & MAPDMA) { 827*34642Smarc dga = (struct dga *) qdmap[unit].dga; 828*34642Smarc adder = (struct adder *) qdmap[unit].adder; 829*34642Smarc dga->csr &= ~DMA_IE; 830*34642Smarc dga->csr &= ~0x0600; /* kill DMA */ 831*34642Smarc adder->command = CANCEL; 832*34642Smarc /* 833*34642Smarc * if DMA was running, flush spurious intrpt 834*34642Smarc */ 835*34642Smarc if (dga->bytcnt_lo != 0) { 836*34642Smarc dga->bytcnt_lo = 0; 837*34642Smarc dga->bytcnt_hi = 0; 838*34642Smarc DMA_SETIGNORE(DMAheader[unit]); 839*34642Smarc dga->csr |= DMA_IE; 840*34642Smarc dga->csr &= ~DMA_IE; 841*34642Smarc } 842*34642Smarc ptep = (int *) 843*34642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 844*34642Smarc for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i) 845*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW; 846*34642Smarc ubarelse(0, &Qbus_unmap[unit]); 847*34642Smarc } 84834615Smarc 849*34642Smarc /* 850*34642Smarc * re-protect 1K (2 pages) event queue 851*34642Smarc */ 852*34642Smarc if (qdflags[unit].mapped & MAPEQ) { 853*34642Smarc ptep = (int *) 854*34642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 85530391Skarels 856*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V; 857*34642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 85830391Skarels } 859*34642Smarc /* 860*34642Smarc * re-protect scroll param area and disable scroll intrpts 861*34642Smarc */ 862*34642Smarc if (qdflags[unit].mapped & MAPSCR) { 863*34642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 864*34642Smarc + (mfpr(SBR) | 0x80000000)); 865*34642Smarc /* 866*34642Smarc * re-protect 512 scroll param area 867*34642Smarc */ 868*34642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 869*34642Smarc adder = (struct adder *) qdmap[unit].adder; 870*34642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 871*34642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 872*34642Smarc } 873*34642Smarc /* 874*34642Smarc * re-protect color map write buffer area and kill intrpts 875*34642Smarc */ 876*34642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 877*34642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 878*34642Smarc + (mfpr(SBR) | 0x80000000)); 879*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V; 880*34642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 881*34642Smarc color_buf[unit]->status = 0; 882*34642Smarc adder = (struct adder *) qdmap[unit].adder; 883*34642Smarc qdflags[unit].adder_ie &= ~VSYNC; 884*34642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 885*34642Smarc } 886*34642Smarc mtpr(TBIA, 0); 887*34642Smarc /* flag everything now unmapped */ 888*34642Smarc qdflags[unit].mapped = 0; 889*34642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 890*34642Smarc qdflags[unit].curs_acc = ACC_OFF; 891*34642Smarc qdflags[unit].curs_thr = 128; 892*34642Smarc /* 893*34642Smarc * restore the console 894*34642Smarc */ 89530391Skarels dga = (struct dga *) qdmap[unit].dga; 89630391Skarels adder = (struct adder *) qdmap[unit].adder; 89730391Skarels dga->csr &= ~DMA_IE; 89830391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 89930391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 90030391Skarels adder->command = CANCEL; 901*34642Smarc /* 902*34642Smarc * if DMA was running, flush spurious intrpt 903*34642Smarc */ 90430391Skarels if (dga->bytcnt_lo != 0) { 905*34642Smarc dga->bytcnt_lo = 0; 906*34642Smarc dga->bytcnt_hi = 0; 907*34642Smarc DMA_SETIGNORE(DMAheader[unit]); 908*34642Smarc dga->csr |= DMA_IE; 909*34642Smarc dga->csr &= ~DMA_IE; 91030391Skarels } 91130391Skarels init_shared(unit); /* init shared memory */ 91230391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 91330391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 91430391Skarels setup_input(unit); /* init the DUART */ 91530391Skarels ldfont(unit); 91630391Skarels cursor[unit].x = 0; 91730391Skarels cursor[unit].y = 0; 918*34642Smarc /* 919*34642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 920*34642Smarc */ 921*34642Smarc duart = (struct duart *) qdmap[unit].duart; 922*34642Smarc qdflags[unit].duart_imask &= ~(0x20); 923*34642Smarc qdflags[unit].duart_imask |= 0x02; 924*34642Smarc duart->imask = qdflags[unit].duart_imask; 925*34642Smarc /* 926*34642Smarc * shut off interrupts if all is closed 927*34642Smarc */ 928*34642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 929*34642Smarc dga = (struct dga *) qdmap[unit].dga; 930*34642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 931*34642Smarc } 932*34642Smarc } else { 933*34642Smarc /* 934*34642Smarc * this is the console 935*34642Smarc */ 936*34642Smarc tp = &qd_tty[minor_dev]; 937*34642Smarc (*linesw[tp->t_line].l_close)(tp); 938*34642Smarc ttyclose(tp); 939*34642Smarc tp->t_state = 0; 940*34642Smarc qdflags[unit].inuse &= ~CONS_DEV; 941*34642Smarc /* 942*34642Smarc * if graphics device is closed, kill interrupts 943*34642Smarc */ 944*34642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 945*34642Smarc dga = (struct dga *) qdmap[unit].dga; 946*34642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 947*34642Smarc } 94830391Skarels } 94934615Smarc 95030391Skarels return(0); 95130391Skarels 95230391Skarels } /* qdclose */ 95330391Skarels 95430391Skarels /*************************************************************** 95530391Skarels * 95634615Smarc * qdioctl()... provide QDSS control services 95730391Skarels * 95830391Skarels **************************************************************** 95930391Skarels * 96030391Skarels * calling convention: qdioctl(dev, cmd, datap, flags); 96130391Skarels * 96230391Skarels * where: dev - the major/minor device number 96330391Skarels * cmd - the user-passed command argument 96430391Skarels * datap - ptr to user input buff (128 bytes max) 96530391Skarels * flags - "f_flags" from "struct file" in file.h 96630391Skarels * 96730391Skarels * 96830391Skarels * - here is the format for the input "cmd" argument 96930391Skarels * 97030391Skarels * 31 29 28 23 22 16 15 8 7 0 97130391Skarels * +----------------------------------------------------------------+ 97230391Skarels * |I/O type| | buff length | device ID char | user command | 97330391Skarels * +----------------------------------------------------------------+ 97430391Skarels * 97530391Skarels * Return data is in the data buffer pointed to by "datap" input spec 97630391Skarels * 97730391Skarels *********************/ 97830391Skarels 97930391Skarels qdioctl(dev, cmd, datap, flags) 980*34642Smarc dev_t dev; 981*34642Smarc int cmd; 982*34642Smarc caddr_t datap; 983*34642Smarc int flags; 98430391Skarels { 98530391Skarels register int *ptep; /* page table entry pointer */ 98632012Smarc register int mapix; /* QVmap[] page table index */ 98730391Skarels register struct _vs_event *event; 98830391Skarels register struct tty *tp; 98930391Skarels struct qdmap *qd; /* pointer to device map struct */ 99030391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 99130391Skarels struct duart *duart; /* DUART reg structure pointer */ 99230391Skarels struct adder *adder; /* ADDER reg structure pointer */ 99330391Skarels struct prgkbd *cmdbuf; 99430391Skarels struct prg_cursor *curs; 99530391Skarels struct _vs_cursor *pos; 99630391Skarels u_int unit = minor(dev) >> 2; /* number of caller's QDSS */ 99730391Skarels u_int minor_dev = minor(dev); 99830391Skarels struct uba_device *ui = qdinfo[unit]; 99930391Skarels struct qd_softc *sc = &qd_softc[ui->ui_unit]; 100030391Skarels int error; 100130391Skarels int s; 100230391Skarels int i; /* SIGNED index */ 100330391Skarels int sbr; /* SBR variable (you silly boy) */ 100430391Skarels u_int ix; 100530391Skarels short status; 100630391Skarels short *shortp; /* generic pointer to a short */ 100730391Skarels char *chrp; /* generic character pointer */ 100830391Skarels short *temp; /* a pointer to template RAM */ 100930391Skarels 1010*34642Smarc /* 1011*34642Smarc * service graphic device ioctl commands 1012*34642Smarc */ 101330391Skarels switch (cmd) { 101434615Smarc 1015*34642Smarc case QD_GETEVENT: 1016*34642Smarc /* 1017*34642Smarc * extract the oldest event from the event queue 1018*34642Smarc */ 101930391Skarels if (ISEMPTY(eq_header[unit])) { 1020*34642Smarc event = (struct _vs_event *) datap; 1021*34642Smarc event->vse_device = VSE_NULL; 1022*34642Smarc break; 102330391Skarels } 102430391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 102534615Smarc s = spl5(); 102630391Skarels GETEND(eq_header[unit]); 102730391Skarels splx(s); 102830391Skarels bcopy(event, datap, sizeof(struct _vs_event)); 102930391Skarels break; 103030391Skarels 1031*34642Smarc case QD_RESET: 1032*34642Smarc /* 1033*34642Smarc * init the dragon stuff, DUART, and driver variables 1034*34642Smarc */ 103530391Skarels init_shared(unit); /* init shared memory */ 103630391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 103730391Skarels clear_qd_screen(unit); 103830391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 103930391Skarels ldfont(unit); /* load the console font */ 104030391Skarels setup_input(unit); /* init the DUART */ 104130391Skarels break; 104230391Skarels 1043*34642Smarc case QD_SET: 1044*34642Smarc /* 1045*34642Smarc * init the DUART and driver variables 1046*34642Smarc */ 104730391Skarels init_shared(unit); 104830391Skarels setup_input(unit); 104930391Skarels break; 105030391Skarels 1051*34642Smarc case QD_CLRSCRN: 1052*34642Smarc /* 1053*34642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 1054*34642Smarc */ 105534615Smarc #ifdef notdef /* has caused problems and is not necessary */ 105630391Skarels setup_dragon(unit); 105730391Skarels clear_qd_screen(unit); 105834615Smarc #endif 105930391Skarels break; 106030391Skarels 1061*34642Smarc case QD_WTCURSOR: 1062*34642Smarc /* 1063*34642Smarc * load a cursor into template RAM 1064*34642Smarc */ 106530391Skarels ldcursor(unit, datap); 106630391Skarels break; 106730391Skarels 1068*34642Smarc case QD_RDCURSOR: 106930391Skarels 107030391Skarels temp = (short *) qdmap[unit].template; 1071*34642Smarc /* 1072*34642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 1073*34642Smarc * ...template space 1074*34642Smarc */ 107530391Skarels temp += (8 * 1024) - 32; 107630391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 1077*34642Smarc *(short *)datap = *temp++; 107830391Skarels break; 107930391Skarels 1080*34642Smarc case QD_POSCURSOR: 1081*34642Smarc /* 1082*34642Smarc * position the mouse cursor 1083*34642Smarc */ 108430391Skarels dga = (struct dga *) qdmap[unit].dga; 108530391Skarels pos = (struct _vs_cursor *) datap; 108634615Smarc s = spl5(); 108730391Skarels dga->x_cursor = TRANX(pos->x); 108830391Skarels dga->y_cursor = TRANY(pos->y); 108930391Skarels eq_header[unit]->curs_pos.x = pos->x; 109030391Skarels eq_header[unit]->curs_pos.y = pos->y; 109130391Skarels splx(s); 109230391Skarels break; 109330391Skarels 1094*34642Smarc case QD_PRGCURSOR: 1095*34642Smarc /* 1096*34642Smarc * set the cursor acceleration factor 1097*34642Smarc */ 109830391Skarels curs = (struct prg_cursor *) datap; 109934615Smarc s = spl5(); 110030391Skarels qdflags[unit].curs_acc = curs->acc_factor; 110130391Skarels qdflags[unit].curs_thr = curs->threshold; 110230391Skarels splx(s); 110330391Skarels break; 110430391Skarels 1105*34642Smarc case QD_MAPDEVICE: 1106*34642Smarc /* 1107*34642Smarc * enable 'user write' to device pages 1108*34642Smarc */ 110930391Skarels qdflags[unit].mapped |= MAPDEV; 111030391Skarels qd = (struct qdmap *) &qdmap[unit]; 1111*34642Smarc /* 1112*34642Smarc * enable user write to template RAM 1113*34642Smarc */ 111432012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 111532012Smarc ptep = (int *)(QVmap[0] + mapix); 111630391Skarels for (i = VTOP(TMPSIZE); i > 0; --i) 1117*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1118*34642Smarc /* 1119*34642Smarc * enable user write to registers 1120*34642Smarc */ 112132012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 112232012Smarc ptep = (int *)(QVmap[0] + mapix); 112330391Skarels 112430391Skarels for (i = VTOP(REGSIZE); i > 0; --i) 1125*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1126*34642Smarc /* 1127*34642Smarc * enable user write to color maps 1128*34642Smarc */ 112932012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 113032012Smarc ptep = (int *)(QVmap[0] + mapix); 113130391Skarels for (i = VTOP(CLRSIZE); i > 0; --i) 1132*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1133*34642Smarc /* 1134*34642Smarc * enable user write to DUART 1135*34642Smarc */ 113632012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 113732012Smarc ptep = (int *)(QVmap[0] + mapix); 113830391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 113930391Skarels 114030391Skarels mtpr(TBIA, 0); /* smash CPU's translation buffer */ 114130391Skarels 1142*34642Smarc /* 1143*34642Smarc * stuff qdmap structure in return buffer 1144*34642Smarc */ 114530391Skarels bcopy(qd, datap, sizeof(struct qdmap)); 114630391Skarels break; 114730391Skarels 1148*34642Smarc case QD_MAPIOBUF: 1149*34642Smarc /* 1150*34642Smarc * do setup for DMA by user process 1151*34642Smarc * 1152*34642Smarc * set 'user write enable' bits for DMA buffer 1153*34642Smarc */ 115430391Skarels qdflags[unit].mapped |= MAPDMA; 115530391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 1156*34642Smarc + (mfpr(SBR) | 0x80000000)); 115730391Skarels for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i) 1158*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V; 115930391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 1160*34642Smarc /* 1161*34642Smarc * set up QBUS map registers for DMA 1162*34642Smarc */ 116330391Skarels DMAheader[unit]->QBAreg = 1164*34642Smarc uballoc(0, DMAheader[unit], DMAbuf_size, 0); 116530391Skarels if (DMAheader[unit]->QBAreg == 0) 116634615Smarc printf("\nqd%d: qdioctl: QBA setup error", unit); 116730391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 116830391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 1169*34642Smarc /* 1170*34642Smarc * return I/O buf adr 1171*34642Smarc */ 117230391Skarels *(int *)datap = (int) DMAheader[unit]; 117330391Skarels break; 117430391Skarels 1175*34642Smarc case QD_MAPSCROLL: 1176*34642Smarc /* 1177*34642Smarc * map the shared scroll param area and enable scroll interpts 1178*34642Smarc */ 117930391Skarels qdflags[unit].mapped |= MAPSCR; 118030391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 1181*34642Smarc + (mfpr(SBR) | 0x80000000)); 1182*34642Smarc /* 1183*34642Smarc * allow user write to scroll area 1184*34642Smarc */ 118530391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 118630391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 118730391Skarels scroll[unit]->status = 0; 118830391Skarels adder = (struct adder *) qdmap[unit].adder; 118930391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 119030391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 1191*34642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 119230391Skarels break; 119330391Skarels 1194*34642Smarc case QD_UNMAPSCROLL: 1195*34642Smarc /* 1196*34642Smarc * unmap shared scroll param area and disable scroll intrpts 1197*34642Smarc */ 119830391Skarels if (qdflags[unit].mapped & MAPSCR) { 1199*34642Smarc qdflags[unit].mapped &= ~MAPSCR; 1200*34642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 1201*34642Smarc + (mfpr(SBR) | 0x80000000)); 1202*34642Smarc /* 1203*34642Smarc * re-protect 512 scroll param area 1204*34642Smarc */ 1205*34642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 1206*34642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 1207*34642Smarc adder = (struct adder *) qdmap[unit].adder; 1208*34642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 1209*34642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 121030391Skarels } 121130391Skarels break; 121230391Skarels 1213*34642Smarc case QD_MAPCOLOR: 1214*34642Smarc /* 1215*34642Smarc * map shared color map write buf and turn on vsync intrpt 1216*34642Smarc */ 121730391Skarels qdflags[unit].mapped |= MAPCOLOR; 121830391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 1219*34642Smarc + (mfpr(SBR) | 0x80000000)); 122030391Skarels 122130391Skarels /* allow user write to color map write buffer */ 122230391Skarels 122330391Skarels *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V; 122430391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 122530391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 1226*34642Smarc adder = (struct adder *) qdmap[unit].adder; 122730391Skarels qdflags[unit].adder_ie |= VSYNC; 122830391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 122934615Smarc /* return color area address */ 123030391Skarels *(int *)datap = (int) color_buf[unit]; 123130391Skarels break; 123230391Skarels 1233*34642Smarc case QD_UNMAPCOLOR: 1234*34642Smarc /* 1235*34642Smarc * unmap shared color map write buffer and kill VSYNC intrpts 1236*34642Smarc */ 123730391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 1238*34642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 1239*34642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 1240*34642Smarc + (mfpr(SBR) | 0x80000000)); 1241*34642Smarc /* re-protect color map write buffer */ 1242*34642Smarc *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V; 1243*34642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 1244*34642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 1245*34642Smarc adder = (struct adder *) qdmap[unit].adder; 1246*34642Smarc qdflags[unit].adder_ie &= ~VSYNC; 1247*34642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 124830391Skarels } 124930391Skarels break; 125030391Skarels 1251*34642Smarc case QD_MAPEVENT: 1252*34642Smarc /* 1253*34642Smarc * give user write access to the event queue 1254*34642Smarc */ 125530391Skarels qdflags[unit].mapped |= MAPEQ; 125630391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 1257*34642Smarc + (mfpr(SBR) | 0x80000000)); 125830391Skarels /* allow user write to 1K event queue */ 125930391Skarels *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V; 126030391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 126130391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 126230391Skarels /* return event queue address */ 126330391Skarels *(int *)datap = (int) eq_header[unit]; 126430391Skarels break; 126530391Skarels 1266*34642Smarc case QD_PRGKBD: 1267*34642Smarc /* 1268*34642Smarc * pass caller's programming commands to LK201 1269*34642Smarc */ 127030391Skarels duart = (struct duart *) qdmap[unit].duart; 127130391Skarels cmdbuf = (struct prgkbd *) datap; /* pnt to kbd cmd buf */ 1272*34642Smarc /* 1273*34642Smarc * send command 1274*34642Smarc */ 127530391Skarels for (i = 1000; i > 0; --i) { 1276*34642Smarc if ((status = duart->statusA) & XMT_RDY) { 1277*34642Smarc duart->dataA = cmdbuf->cmd; 1278*34642Smarc break; 1279*34642Smarc } 128030391Skarels } 128130391Skarels if (i == 0) { 1282*34642Smarc printf("\nqd%d: qdioctl: timeout on XMT_RDY [1]", unit); 1283*34642Smarc break; 128430391Skarels } 1285*34642Smarc /* 1286*34642Smarc * send param1? 1287*34642Smarc */ 128830391Skarels if (cmdbuf->cmd & LAST_PARAM) 1289*34642Smarc break; 129030391Skarels for (i = 1000; i > 0; --i) { 1291*34642Smarc if ((status = duart->statusA) & XMT_RDY) { 1292*34642Smarc duart->dataA = cmdbuf->param1; 1293*34642Smarc break; 1294*34642Smarc } 129530391Skarels } 129630391Skarels if (i == 0) { 1297*34642Smarc printf("\nqd%d: qdioctl: timeout on XMT_RDY [2]", unit); 1298*34642Smarc break; 129930391Skarels } 1300*34642Smarc /* 1301*34642Smarc * send param2? 1302*34642Smarc */ 130330391Skarels if (cmdbuf->param1 & LAST_PARAM) 130430391Skarels break; 130530391Skarels for (i = 1000; i > 0; --i) { 1306*34642Smarc if ((status = duart->statusA) & XMT_RDY) { 1307*34642Smarc duart->dataA = cmdbuf->param2; 1308*34642Smarc break; 1309*34642Smarc } 131030391Skarels } 131130391Skarels if (i == 0) { 1312*34642Smarc printf("\nqd%d: qdioctl: timeout on XMT_RDY [3]", unit); 1313*34642Smarc break; 131430391Skarels } 131530391Skarels break; 131630391Skarels 1317*34642Smarc case QD_PRGMOUSE: 1318*34642Smarc /* 1319*34642Smarc * pass caller's programming commands to the mouse 1320*34642Smarc */ 132130391Skarels duart = (struct duart *) qdmap[unit].duart; 132230391Skarels for (i = 1000; i > 0; --i) { 1323*34642Smarc if ((status = duart->statusB) & XMT_RDY) { 1324*34642Smarc duart->dataB = *datap; 1325*34642Smarc break; 1326*34642Smarc } 132730391Skarels } 132830391Skarels if (i == 0) { 1329*34642Smarc printf("\nqd%d: qdioctl: timeout on XMT_RDY [4]", unit); 133030391Skarels } 133130391Skarels break; 133230391Skarels 1333*34642Smarc case QD_RDCONFIG: 1334*34642Smarc /* 1335*34642Smarc * get QDSS configuration word and return it 1336*34642Smarc */ 133730391Skarels *(short *)datap = qdflags[unit].config; 133830391Skarels break; 133930391Skarels 1340*34642Smarc case QD_KERN_LOOP: 1341*34642Smarc case QD_KERN_UNLOOP: 1342*34642Smarc /* 1343*34642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 1344*34642Smarc * kernel console output. 1345*34642Smarc */ 134634615Smarc break; 134734615Smarc 1348*34642Smarc case QD_PRGTABLET: 1349*34642Smarc /* 1350*34642Smarc * program the tablet 1351*34642Smarc */ 135230391Skarels duart = (struct duart *) qdmap[unit].duart; 135330391Skarels for (i = 1000; i > 0; --i) { 1354*34642Smarc if ((status = duart->statusB) & XMT_RDY) { 1355*34642Smarc duart->dataB = *datap; 1356*34642Smarc break; 1357*34642Smarc } 135830391Skarels } 135930391Skarels if (i == 0) { 1360*34642Smarc printf("\nqd%d: qdioctl: timeout on XMT_RDY [5]", unit); 136130391Skarels } 136230391Skarels break; 136330391Skarels 1364*34642Smarc case QD_PRGTABRES: 1365*34642Smarc /* 1366*34642Smarc * program the tablet report resolution factor 1367*34642Smarc */ 136830391Skarels qdflags[unit].tab_res = *(short *)datap; 136930391Skarels break; 137030391Skarels 1371*34642Smarc default: 1372*34642Smarc /* 1373*34642Smarc * service tty ioctl's 1374*34642Smarc */ 1375*34642Smarc if (!(minor_dev & 0x02)) { 137630391Skarels tp = &qd_tty[minor_dev]; 1377*34642Smarc error = 1378*34642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 137930391Skarels if (error >= 0) { 1380*34642Smarc return(error); 138130391Skarels } 138230391Skarels error = ttioctl(tp, cmd, datap, flags); 138330391Skarels if (error >= 0) { 1384*34642Smarc return(error); 138530391Skarels } 1386*34642Smarc } 1387*34642Smarc break; 138830391Skarels } 138930391Skarels 139030391Skarels return(0); 139130391Skarels 139230391Skarels } /* qdioctl */ 139330391Skarels 139430391Skarels /********************************************************************** 139530391Skarels * 139630391Skarels * qdselect()... service select call for event queue input 139730391Skarels * 139830391Skarels **********************************************************************/ 139930391Skarels 140030391Skarels qdselect(dev, rw) 1401*34642Smarc dev_t dev; 1402*34642Smarc int rw; 140330391Skarels { 140430391Skarels register int s; 140530391Skarels register int unit; 140634615Smarc register struct tty *tp; 140734615Smarc u_int minor_dev = minor(dev); 140830391Skarels 140934615Smarc s = spl5(); 141034615Smarc unit = minor_dev >> 2; 141130391Skarels 141230391Skarels switch (rw) { 1413*34642Smarc case FREAD: 1414*34642Smarc if ((minor_dev & 0x03) == 2) { 1415*34642Smarc /* 1416*34642Smarc * this is a graphics device, so check for events 1417*34642Smarc */ 1418*34642Smarc if(!(ISEMPTY(eq_header[unit]))) 1419*34642Smarc { 1420*34642Smarc splx(s); 1421*34642Smarc return(1); 1422*34642Smarc } 1423*34642Smarc rsel[unit] = u.u_procp; 1424*34642Smarc qdflags[unit].selmask |= SEL_READ; 1425*34642Smarc splx(s); 1426*34642Smarc return(0); 1427*34642Smarc } else { 1428*34642Smarc /* 1429*34642Smarc * this is a tty device 1430*34642Smarc */ 1431*34642Smarc tp = &qd_tty[minor_dev]; 1432*34642Smarc if (ttnread(tp)) 1433*34642Smarc return(1); 1434*34642Smarc tp->t_rsel = u.u_procp; 1435*34642Smarc splx(s); 1436*34642Smarc return(0); 143730391Skarels } 143830391Skarels 1439*34642Smarc case FWRITE: 1440*34642Smarc if ((minor(dev) & 0x03) == 2) { 1441*34642Smarc /* 1442*34642Smarc * this is a graphics device, so check for dma buffers 1443*34642Smarc */ 1444*34642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 1445*34642Smarc { 1446*34642Smarc splx(s); 1447*34642Smarc return(1); 1448*34642Smarc } 1449*34642Smarc rsel[unit] = u.u_procp; 1450*34642Smarc qdflags[unit].selmask |= SEL_WRITE; 1451*34642Smarc splx(s); 1452*34642Smarc return(0); 1453*34642Smarc } else { 1454*34642Smarc /* 1455*34642Smarc * this is a tty device 1456*34642Smarc */ 1457*34642Smarc tp = &qd_tty[minor_dev]; 1458*34642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) 1459*34642Smarc return(1); 1460*34642Smarc tp->t_wsel = u.u_procp; 1461*34642Smarc splx(s); 1462*34642Smarc return(0); 146330391Skarels } 146430391Skarels } 146530391Skarels 146630391Skarels } /* qdselect() */ 146730391Skarels 146830391Skarels /*************************************************************** 146930391Skarels * 147030391Skarels * qdwrite()... output to the QDSS screen as a TTY 147130391Skarels * 147230391Skarels ***************************************************************/ 147330391Skarels 147430391Skarels extern qd_strategy(); 147530391Skarels 147630391Skarels qdwrite(dev, uio) 1477*34642Smarc dev_t dev; 1478*34642Smarc struct uio *uio; 147930391Skarels { 148030391Skarels register struct tty *tp; 148130391Skarels register int minor_dev; 148230391Skarels register int unit; 148330391Skarels 148430391Skarels minor_dev = minor(dev); 148530391Skarels unit = (minor_dev >> 2) & 0x07; 148630391Skarels 1487*34642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 1488*34642Smarc /* 1489*34642Smarc * this is the console... 1490*34642Smarc */ 1491*34642Smarc tp = &qd_tty[minor_dev]; 1492*34642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 1493*34642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1494*34642Smarc /* 1495*34642Smarc * this is a DMA xfer from user space 1496*34642Smarc */ 1497*34642Smarc return (physio(qd_strategy, &qdbuf[unit], 1498*34642Smarc dev, B_WRITE, minphys, uio)); 149930391Skarels } 150030391Skarels } 150130391Skarels 150230391Skarels /*************************************************************** 150330391Skarels * 150430391Skarels * qdread()... read from QDSS keyboard as a TTY 150530391Skarels * 150630391Skarels ***************************************************************/ 150730391Skarels 150830391Skarels qdread(dev, uio) 1509*34642Smarc dev_t dev; 1510*34642Smarc struct uio *uio; 151130391Skarels { 151230391Skarels register struct tty *tp; 151330391Skarels register int minor_dev; 151430391Skarels register int unit; 151530391Skarels 151630391Skarels minor_dev = minor(dev); 151730391Skarels unit = (minor_dev >> 2) & 0x07; 151830391Skarels 1519*34642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 1520*34642Smarc /* 1521*34642Smarc * this is the console 1522*34642Smarc */ 1523*34642Smarc tp = &qd_tty[minor_dev]; 1524*34642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 1525*34642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1526*34642Smarc /* 1527*34642Smarc * this is a bitmap-to-processor xfer 1528*34642Smarc */ 1529*34642Smarc return (physio(qd_strategy, &qdbuf[unit], 1530*34642Smarc dev, B_READ, minphys, uio)); 153130391Skarels } 153230391Skarels } 153330391Skarels 153430391Skarels /*************************************************************** 153530391Skarels * 153630391Skarels * qd_strategy()... strategy routine to do DMA 153730391Skarels * 153830391Skarels ***************************************************************/ 153930391Skarels 154030391Skarels qd_strategy(bp) 1541*34642Smarc register struct buf *bp; 154230391Skarels { 154330391Skarels register struct dga *dga; 154430391Skarels register struct adder *adder; 154530391Skarels char *DMAbufp; 154630391Skarels int QBAreg; 154730391Skarels int bytcnt; 154830391Skarels int s; 154930391Skarels int unit; 155030391Skarels int cookie; 155130391Skarels int i,j,k; 155230391Skarels 155330391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 155430391Skarels 1555*34642Smarc /* 1556*34642Smarc * init pointers 1557*34642Smarc */ 155830391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 1559*34642Smarc printf("\nqd%d: qd_strategy: QBA setup error", unit); 1560*34642Smarc goto STRAT_ERR; 156130391Skarels } 156230391Skarels dga = (struct dga *) qdmap[unit].dga; 156334615Smarc s = spl5(); 156430391Skarels qdflags[unit].user_dma = -1; 156530391Skarels dga->csr |= DMA_IE; 156630391Skarels cookie = QBAreg & 0x3FFFF; 156730391Skarels dga->adrs_lo = (short) cookie; 156830391Skarels dga->adrs_hi = (short) (cookie >> 16); 156930391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 157030391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 157130391Skarels 157230391Skarels while (qdflags[unit].user_dma) { 1573*34642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 157430391Skarels } 157530391Skarels splx(s); 157630391Skarels ubarelse(0, &QBAreg); 157730391Skarels if (!(dga->csr & DMA_ERR)) { 1578*34642Smarc iodone(bp); 1579*34642Smarc return; 158030391Skarels } 158130391Skarels 158230391Skarels STRAT_ERR: 158330391Skarels adder = (struct adder *) qdmap[unit].adder; 1584*34642Smarc adder->command = CANCEL; /* cancel adder activity */ 158530391Skarels dga->csr &= ~DMA_IE; 158630391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 158730391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 158830391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 158930391Skarels 1590*34642Smarc /* 1591*34642Smarc * if DMA was running, flush spurious intrpt 1592*34642Smarc */ 159330391Skarels if (dga->bytcnt_lo != 0) { 1594*34642Smarc dga->bytcnt_lo = 0; 1595*34642Smarc dga->bytcnt_hi = 0; 1596*34642Smarc DMA_SETIGNORE(DMAheader[unit]); 1597*34642Smarc dga->csr |= DMA_IE; 159830391Skarels } 159930391Skarels iodone(bp); 160030391Skarels 160130391Skarels } /* qd_strategy */ 160230391Skarels 160330391Skarels /******************************************************************* 160430391Skarels * 160530391Skarels * qdstart()... startup output to the console screen 160630391Skarels * 160730391Skarels ******************************************************************** 160830391Skarels * 160930391Skarels * calling convention: 161030391Skarels * 161130391Skarels * qdstart(tp); 161234615Smarc * struct tty *tp; ;pointer to tty structure 161330391Skarels * 161430391Skarels ********/ 161530391Skarels 161630391Skarels qdstart(tp) 1617*34642Smarc register struct tty *tp; 161830391Skarels { 161930391Skarels register int which_unit, unit, c; 162030391Skarels int s; 162134615Smarc int curs_on; 162234615Smarc struct dga *dga; 162334615Smarc 162430391Skarels unit = minor(tp->t_dev); 162530391Skarels which_unit = (unit >> 2) & 0x3; 162634615Smarc unit &= 0x03; 162730391Skarels 162834615Smarc s = spl5(); 162934615Smarc 1630*34642Smarc /* 1631*34642Smarc * If it's currently active, or delaying, no need to do anything. 1632*34642Smarc */ 163330391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 163430391Skarels goto out; 163530391Skarels 1636*34642Smarc /* 1637*34642Smarc * Display chars until the queue is empty. 1638*34642Smarc * Drop input from anything but the console 1639*34642Smarc * device on the floor. 1640*34642Smarc * 1641*34642Smarc * XXX - this loop is done at spltty. 1642*34642Smarc * 1643*34642Smarc */ 1644*34642Smarc while (tp->t_outq.c_cc) { 164534511Smarc c = getc(&tp->t_outq); 164634615Smarc if (unit == 0) 1647*34642Smarc blitc(which_unit, (char)(c & 0xFF)); 164830391Skarels } 1649*34642Smarc /* 1650*34642Smarc * If there are sleepers, and output has drained below low 1651*34642Smarc * water mark, wake up the sleepers. 1652*34642Smarc */ 1653*34642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 165434615Smarc if (tp->t_state & TS_ASLEEP){ 165534615Smarc tp->t_state &= ~TS_ASLEEP; 165634615Smarc wakeup((caddr_t) &tp->t_outq); 165734615Smarc } 165830391Skarels } 165930391Skarels 166034615Smarc tp->t_state &= ~TS_BUSY; 166134615Smarc 166230391Skarels out: 166330391Skarels splx(s); 166430391Skarels 166530391Skarels } /* qdstart */ 166630391Skarels 166730391Skarels 166830391Skarels /******************************************************************* 166930391Skarels * 167030391Skarels * qdstop()... stop the tty 167130391Skarels * 167230391Skarels *******************************************************************/ 167330391Skarels 167430391Skarels qdstop(tp, flag) 1675*34642Smarc register struct tty *tp; 1676*34642Smarc int flag; 167730391Skarels { 167830391Skarels register int s; 167930391Skarels 168034615Smarc s = spl5(); /* block intrpts during state modification */ 168130391Skarels if (tp->t_state & TS_BUSY) { 1682*34642Smarc if ((tp->t_state & TS_TTSTOP) == 0) { 1683*34642Smarc tp->t_state |= TS_FLUSH; 1684*34642Smarc } 1685*34642Smarc else 1686*34642Smarc tp->t_state &= ~TS_BUSY; 168730391Skarels } 168830391Skarels splx(s); 168930391Skarels } 169030391Skarels 169130391Skarels /******************************************************************* 169230391Skarels * 169330391Skarels * blitc()... output a character to the QDSS screen 169430391Skarels * 169530391Skarels ******************************************************************** 169630391Skarels * 169730391Skarels * calling convention: 169830391Skarels * 169930391Skarels * blitc(chr); 1700*34642Smarc * char chr; # character to be displayed 170130391Skarels * 170230391Skarels ********/ 170330391Skarels 170430391Skarels blitc(unit, chr) 1705*34642Smarc int unit; 1706*34642Smarc unsigned char chr; 170730391Skarels { 170830391Skarels register struct adder *adder; 170930391Skarels register struct dga *dga; 171030391Skarels register int i; 1711*34642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 1712*34642Smarc unsigned char savechar; 171330391Skarels short x; 1714*34642Smarc static short inescape[NQD]; 171530391Skarels 171630391Skarels adder = (struct adder *) qdmap[unit].adder; 171730391Skarels dga = (struct dga *) qdmap[unit].dga; 1718*34642Smarc /* 1719*34642Smarc * BSD comment: this (&=0177) defeats the extended character 1720*34642Smarc * set code for the glass tty, but if i had the time i would 1721*34642Smarc * spend it ripping out the code completely. This driver 1722*34642Smarc * is too big for its own good. 1723*34642Smarc */ 1724*34642Smarc chr &= 0177; 1725*34642Smarc /* 1726*34642Smarc * Cursor addressing (so vi will work when i really need it). 1727*34642Smarc * Decode for "\E=%.%." cursor motion description. 1728*34642Smarc * Corresponds to type "qdcons" in /etc/termcap, or if you 1729*34642Smarc * don't have it: 1730*34642Smarc * 1731*34642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 1732*34642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 1733*34642Smarc * 1734*34642Smarc */ 1735*34642Smarc if (inescape[unit] && nograph) { 1736*34642Smarc switch (inescape[unit]++) { 1737*34642Smarc case 1: 1738*34642Smarc if (chr != '=') { 1739*34642Smarc /* abort escape sequence */ 1740*34642Smarc inescape[unit] = 0; 1741*34642Smarc blitc(unit, chr); 1742*34642Smarc } 1743*34642Smarc return(0); 1744*34642Smarc case 2: 1745*34642Smarc /* position row */ 1746*34642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 1747*34642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 1748*34642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 1749*34642Smarc dga->y_cursor = TRANY(cursor[unit].y); 1750*34642Smarc return(0); 1751*34642Smarc case 3: 1752*34642Smarc /* position column */ 1753*34642Smarc cursor[unit].x = CHAR_WIDTH * chr; 1754*34642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 1755*34642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 1756*34642Smarc dga->x_cursor = TRANX(cursor[unit].x); 1757*34642Smarc inescape[unit] = 0; 1758*34642Smarc return(0); 1759*34642Smarc default: 1760*34642Smarc inescape[unit] = 0; 1761*34642Smarc blitc(unit, chr); 1762*34642Smarc } 1763*34642Smarc } 176430391Skarels 176530391Skarels switch (chr) { 1766*34642Smarc case '\r': /* return char */ 176730391Skarels cursor[unit].x = 0; 1768*34642Smarc if (nograph) 1769*34642Smarc dga->x_cursor = TRANX(cursor[unit].x); 177030391Skarels return(0); 177130391Skarels 1772*34642Smarc case '\t': /* tab char */ 177330391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 1774*34642Smarc blitc(unit, ' '); 177530391Skarels } 177630391Skarels return(0); 177730391Skarels 1778*34642Smarc case '\n': /* line feed char */ 177930391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 1780*34642Smarc if (nograph) { 1781*34642Smarc cursor[unit].y -= CHAR_HEIGHT; 1782*34642Smarc scroll_up(adder); 1783*34642Smarc } else 1784*34642Smarc cursor[unit].y = 0; 178530391Skarels } 1786*34642Smarc if (nograph) 1787*34642Smarc dga->y_cursor = TRANY(cursor[unit].y); 178830391Skarels return(0); 178930391Skarels 1790*34642Smarc case '\b': /* backspace char */ 179130391Skarels if (cursor[unit].x > 0) { 1792*34642Smarc cursor[unit].x -= CHAR_WIDTH; 1793*34642Smarc if (nograph) 1794*34642Smarc dga->x_cursor = TRANX(cursor[unit].x); 179530391Skarels } 179630391Skarels return(0); 1797*34642Smarc case CTRL('k'): /* cursor up */ 1798*34642Smarc if (nograph && cursor[unit].y > 0) { 1799*34642Smarc cursor[unit].y -= CHAR_HEIGHT; 1800*34642Smarc dga->y_cursor = TRANY(cursor[unit].y); 1801*34642Smarc } 1802*34642Smarc return(0); 180330391Skarels 1804*34642Smarc case CTRL('^'): /* home cursor */ 1805*34642Smarc if (nograph) { 1806*34642Smarc cursor[unit].x = 0; 1807*34642Smarc dga->x_cursor = TRANX(cursor[unit].x); 1808*34642Smarc cursor[unit].y = 0; 1809*34642Smarc dga->y_cursor = TRANY(cursor[unit].y); 1810*34642Smarc } 1811*34642Smarc return(0); 181232012Smarc 1813*34642Smarc case CTRL('l'): /* cursor right */ 1814*34642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 1815*34642Smarc cursor[unit].x += CHAR_WIDTH; 1816*34642Smarc dga->x_cursor = TRANX(cursor[unit].x); 1817*34642Smarc } 1818*34642Smarc return(0); 181930391Skarels 1820*34642Smarc case CTRL('z'): /* clear screen */ 1821*34642Smarc if (nograph) { 1822*34642Smarc setup_dragon(unit); 1823*34642Smarc clear_qd_screen(unit); 1824*34642Smarc /* home cursor - termcap seems to assume this */ 1825*34642Smarc cursor[unit].x = 0; 1826*34642Smarc dga->x_cursor = TRANX(cursor[unit].x); 1827*34642Smarc cursor[unit].y = 0; 1828*34642Smarc dga->y_cursor = TRANY(cursor[unit].y); 1829*34642Smarc } 1830*34642Smarc return(0); 183130391Skarels 1832*34642Smarc case '\033': /* start escape sequence */ 1833*34642Smarc if (nograph) 1834*34642Smarc inescape[unit] = 1; 1835*34642Smarc return(0); 1836*34642Smarc 1837*34642Smarc default: 1838*34642Smarc if ((chr < ' ') || (chr > '~')) 1839*34642Smarc return(0); 1840*34642Smarc } 1841*34642Smarc /* 1842*34642Smarc * setup VIPER operand control registers 1843*34642Smarc */ 184430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 184530391Skarels write_ID(adder, SRC1_OCR_B, 1846*34642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 184730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 184830391Skarels write_ID(adder, SRC1_OCR_B, 1849*34642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 185030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 185130391Skarels write_ID(adder, DST_OCR_B, 1852*34642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 185330391Skarels write_ID(adder, MASK_1, 0xFFFF); 185430391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 185530391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 1856*34642Smarc adder->x_clip_min = 0; 1857*34642Smarc adder->x_clip_max = 1024; 1858*34642Smarc adder->y_clip_min = 0; 1859*34642Smarc adder->y_clip_max = 864; 1860*34642Smarc /* 1861*34642Smarc * load DESTINATION origin and vectors 1862*34642Smarc */ 186330391Skarels adder->fast_dest_dy = 0; 186430391Skarels adder->slow_dest_dx = 0; 186530391Skarels adder->error_1 = 0; 186630391Skarels adder->error_2 = 0; 186730391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 186830391Skarels wait_status(adder, RASTEROP_COMPLETE); 186930391Skarels adder->destination_x = cursor[unit].x; 187030391Skarels adder->fast_dest_dx = CHAR_WIDTH; 187130391Skarels adder->destination_y = cursor[unit].y; 187230391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 1873*34642Smarc /* 1874*34642Smarc * load SOURCE origin and vectors 1875*34642Smarc */ 187634615Smarc if ((chr - ' ') > (CHARS - 1)) { 187734615Smarc printf("Invalid character (x)%x in blitc\n",chr); 187834615Smarc chr = ' '; 187934615Smarc } 1880*34642Smarc /* 1881*34642Smarc * X position is modulo the number of characters per line 1882*34642Smarc */ 188334615Smarc adder->source_1_x = FONT_X + 1884*34642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 1885*34642Smarc /* 1886*34642Smarc * Point to either first or second row 1887*34642Smarc */ 188834615Smarc adder->source_1_y = 2048 - 15 * 1889*34642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 189030391Skarels adder->source_1_dx = CHAR_WIDTH; 189130391Skarels adder->source_1_dy = CHAR_HEIGHT; 189230391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 189330391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 1894*34642Smarc /* 1895*34642Smarc * update console cursor coordinates 1896*34642Smarc */ 189730391Skarels cursor[unit].x += CHAR_WIDTH; 1898*34642Smarc if (nograph) 1899*34642Smarc dga->x_cursor = TRANX(cursor[unit].x); 190030391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 1901*34642Smarc blitc(unit, '\r'); 1902*34642Smarc blitc(unit, '\n'); 190330391Skarels } 190430391Skarels 190530391Skarels } /* blitc */ 190630391Skarels 1907*34642Smarc qdreset() 1908*34642Smarc { 1909*34642Smarc } 1910*34642Smarc qd_init() 1911*34642Smarc { 1912*34642Smarc } 191330391Skarels 191430391Skarels /****************************************************************** 191534615Smarc ******************************************************************* 191634615Smarc ******************************************************************* 191730391Skarels * 1918*34642Smarc * INTERRUPT SERVICE ROUTINES 191930391Skarels * 192034615Smarc ******************************************************************* 192134615Smarc ******************************************************************* 192230391Skarels ******************************************************************/ 192330391Skarels 192430391Skarels /***************************************************************** 192530391Skarels * 192630391Skarels * qddint()... service "DMA DONE" interrupt condition 192730391Skarels * 192830391Skarels *****************************************************************/ 192930391Skarels 193030391Skarels qddint(qd) 1931*34642Smarc int qd; 193230391Skarels { 193330391Skarels register struct DMAreq_header *header; 193430391Skarels register struct DMAreq *request; 193530391Skarels register struct dga *dga; 193630391Skarels struct adder *adder; 193730391Skarels 193830391Skarels int cookie; /* DMA adrs for QDSS */ 193930391Skarels int i; 194030391Skarels 194130391Skarels spl4(); /* allow interval timer in */ 194230391Skarels 1943*34642Smarc /* 1944*34642Smarc * init pointers 1945*34642Smarc */ 194630391Skarels header = DMAheader[qd]; /* register for optimization */ 194730391Skarels dga = (struct dga *) qdmap[qd].dga; 194830391Skarels adder = (struct adder *) qdmap[qd].adder; 194930391Skarels 1950*34642Smarc /* 1951*34642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 1952*34642Smarc */ 195330391Skarels if (DMA_ISIGNORE(header)) { 1954*34642Smarc DMA_CLRIGNORE(header); 1955*34642Smarc return; 195630391Skarels } 195730391Skarels 1958*34642Smarc /* 1959*34642Smarc * dump a DMA hardware error message if appropriate 1960*34642Smarc */ 196130391Skarels if (dga->csr & DMA_ERR) { 196230391Skarels 1963*34642Smarc if (dga->csr & PARITY_ERR) 1964*34642Smarc printf("\nqd%d: qddint: DMA hardware parity fault.", qd); 196530391Skarels 1966*34642Smarc if (dga->csr & BUS_ERR) 1967*34642Smarc printf("\nqd%d: qddint: DMA hardware bus error.", qd); 196830391Skarels } 196930391Skarels 1970*34642Smarc /* 1971*34642Smarc * if this was a DMA from user space... 1972*34642Smarc */ 197330391Skarels if (qdflags[qd].user_dma) { 1974*34642Smarc qdflags[qd].user_dma = 0; 1975*34642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 1976*34642Smarc return; 197730391Skarels } 197830391Skarels 1979*34642Smarc /* 1980*34642Smarc * if we're doing DMA request queue services, field the error condition 1981*34642Smarc */ 198230391Skarels if (dga->csr & DMA_ERR) { 198330391Skarels 1984*34642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 1985*34642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 1986*34642Smarc adder->command = CANCEL; /* cancel adder activity */ 198730391Skarels 1988*34642Smarc DMA_SETERROR(header); /* flag error in header status word */ 1989*34642Smarc DMA_CLRACTIVE(header); 1990*34642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 1991*34642Smarc header->newest = header->oldest; 1992*34642Smarc header->used = 0; 199330391Skarels 1994*34642Smarc if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 1995*34642Smarc selwakeup(rsel[qd], 0); 1996*34642Smarc rsel[qd] = 0; 1997*34642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 1998*34642Smarc } 199930391Skarels 2000*34642Smarc if (dga->bytcnt_lo != 0) { 2001*34642Smarc dga->bytcnt_lo = 0; 2002*34642Smarc dga->bytcnt_hi = 0; 2003*34642Smarc DMA_SETIGNORE(header); 2004*34642Smarc } 2005*34642Smarc return; 200630391Skarels } 200730391Skarels 2008*34642Smarc /* 2009*34642Smarc * if the DMA request queue is now becoming non-full, 2010*34642Smarc * wakeup "select" client. 2011*34642Smarc */ 201230391Skarels if (DMA_ISFULL(header)) { 201330391Skarels 2014*34642Smarc if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 2015*34642Smarc selwakeup(rsel[qd], 0); 2016*34642Smarc rsel[qd] = 0; 2017*34642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 2018*34642Smarc } 201930391Skarels } 202030391Skarels 202130391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 2022*34642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 202330391Skarels 202434615Smarc /* check for unexpected interrupt */ 202534615Smarc if (DMA_ISEMPTY(header)) 202630391Skarels return; 202730391Skarels 202830391Skarels DMA_GETEND(header); /* update request queue indices */ 202930391Skarels 2030*34642Smarc /* 2031*34642Smarc * if no more DMA pending, wake up "select" client and exit */ 203230391Skarels 203330391Skarels if (DMA_ISEMPTY(header)) { 203430391Skarels 2035*34642Smarc if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 2036*34642Smarc selwakeup(rsel[qd], 0); 2037*34642Smarc rsel[qd] = 0; 2038*34642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 2039*34642Smarc } 204030391Skarels 2041*34642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 2042*34642Smarc return; 204330391Skarels } 204430391Skarels 2045*34642Smarc /* 2046*34642Smarc * initiate next DMA xfer */ 204730391Skarels 204830391Skarels request = DMA_GETBEGIN(header); 204934615Smarc if (request->DMAtype != QDlast_DMAtype) { 2050*34642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 2051*34642Smarc adder->command = CANCEL; /* cancel adder activity */ 205234615Smarc } 205330391Skarels 205434615Smarc 205530391Skarels switch (request->DMAtype) { 205630391Skarels 2057*34642Smarc case DISPLIST: 205834615Smarc if (request->DMAtype != QDlast_DMAtype) { 205934615Smarc dga->csr |= DL_ENB; 206034615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 206134615Smarc } 206230391Skarels break; 206330391Skarels 2064*34642Smarc case PTOB: 206534615Smarc if (request->DMAtype != QDlast_DMAtype) { 206634615Smarc if (request->DMAdone & BYTE_PACK) 2067*34642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 206834615Smarc else { 206934615Smarc dga->csr |= PTOB_ENB; 207034615Smarc dga->csr &= ~BYTE_DMA; 207134615Smarc } 207234615Smarc } 207330391Skarels break; 207430391Skarels 2075*34642Smarc case BTOP: 207634615Smarc if (request->DMAtype != QDlast_DMAtype) { 207734615Smarc if (request->DMAdone & BYTE_PACK) { 207834615Smarc dga->csr &= ~DL_ENB; 207934615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 208034615Smarc } 208134615Smarc else { 208234615Smarc dga->csr |= BTOP_ENB; 208334615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 208434615Smarc } 208534615Smarc } 208630391Skarels break; 2087*34642Smarc default: 208834615Smarc printf("\nqd%d: qddint: illegal DMAtype parameter.", qd); 208930391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 209030391Skarels return; 209130391Skarels } 209230391Skarels 209330391Skarels if (request->DMAdone & COUNT_ZERO) { 2094*34642Smarc dga->csr &= ~SET_DONE_FIFO; 2095*34642Smarc } 2096*34642Smarc else if (request->DMAdone & FIFO_EMPTY) { 2097*34642Smarc dga->csr |= SET_DONE_FIFO; 209830391Skarels } 209930391Skarels 210030391Skarels if (request->DMAdone & WORD_PACK) 210130391Skarels dga->csr &= ~BYTE_DMA; 210230391Skarels else if (request->DMAdone & BYTE_PACK) 210330391Skarels dga->csr |= BYTE_DMA; 210430391Skarels 210530391Skarels dga->csr |= DMA_IE; 2106*34642Smarc QDlast_DMAtype = request->DMAtype; 210730391Skarels 210830391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 210930391Skarels 211030391Skarels dga->adrs_lo = (short) cookie; 211130391Skarels dga->adrs_hi = (short) (cookie >> 16); 211230391Skarels 211330391Skarels dga->bytcnt_lo = (short) request->length; 211430391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 211530391Skarels 211630391Skarels return; 211730391Skarels } 211830391Skarels 211930391Skarels /***************************************************************** 212030391Skarels * 212130391Skarels * qdaint()... ADDER interrupt service 212230391Skarels * 212330391Skarels *****************************************************************/ 212434615Smarc int Nqdaint; 212530391Skarels 212630391Skarels qdaint(qd) 2127*34642Smarc register int qd; 212830391Skarels { 212930391Skarels register struct adder *adder; 213030391Skarels struct color_buf *cbuf; 213130391Skarels 213230391Skarels short stat; 213330391Skarels int i; 213430391Skarels register struct rgb *rgbp; 213530391Skarels register short *red; 213630391Skarels register short *green; 213730391Skarels register short *blue; 213830391Skarels 213930391Skarels spl4(); /* allow interval timer in */ 214034615Smarc Nqdaint++; /* debug */ 214130391Skarels 214230391Skarels adder = (struct adder *) qdmap[qd].adder; 214330391Skarels 2144*34642Smarc /* 2145*34642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 2146*34642Smarc * any pending color map load request 2147*34642Smarc */ 214830391Skarels if (adder->status & VSYNC) { 2149*34642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 2150*34642Smarc cbuf = color_buf[qd]; 2151*34642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 215230391Skarels 2153*34642Smarc red = (short *) qdmap[qd].red; 2154*34642Smarc green = (short *) qdmap[qd].green; 2155*34642Smarc blue = (short *) qdmap[qd].blue; 215630391Skarels 2157*34642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 2158*34642Smarc --i >= 0; rgbp++) { 2159*34642Smarc red[rgbp->offset] = (short) rgbp->red; 2160*34642Smarc green[rgbp->offset] = (short) rgbp->green; 2161*34642Smarc blue[rgbp->offset] = (short) rgbp->blue; 2162*34642Smarc } 216330391Skarels 2164*34642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 216530391Skarels } 216630391Skarels } 216730391Skarels 2168*34642Smarc /* 2169*34642Smarc * service the scroll interrupt (FRAME_SYNC bit) 2170*34642Smarc */ 217130391Skarels if (adder->status & FRAME_SYNC) { 2172*34642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 217330391Skarels 2174*34642Smarc if (scroll[qd]->status & LOAD_REGS) { 217530391Skarels 2176*34642Smarc for ( i = 1000, adder->status = 0; i > 0 2177*34642Smarc && !((stat = adder->status) & ID_SCROLL_READY); 2178*34642Smarc --i) 2179*34642Smarc ; 218030391Skarels 2181*34642Smarc if (i == 0) { 2182*34642Smarc printf("\nqd%d: qdaint: timeout on ID_SCROLL_READY", 2183*34642Smarc qd); 2184*34642Smarc return; 2185*34642Smarc } 218630391Skarels 2187*34642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 2188*34642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 218930391Skarels 2190*34642Smarc adder->y_scroll_constant = 2191*34642Smarc scroll[qd]->y_scroll_constant; 2192*34642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 219330391Skarels 2194*34642Smarc if (scroll[qd]->status & LOAD_INDEX) { 219530391Skarels 2196*34642Smarc adder->x_index_pending = 2197*34642Smarc scroll[qd]->x_index_pending; 2198*34642Smarc adder->y_index_pending = 2199*34642Smarc scroll[qd]->y_index_pending; 2200*34642Smarc } 2201*34642Smarc 2202*34642Smarc scroll[qd]->status = 0x00; 220330391Skarels } 220430391Skarels } 220530391Skarels } 220630391Skarels 220730391Skarels /***************************************************************** 220830391Skarels * 220930391Skarels * qdiint()... DUART input interrupt service routine 221030391Skarels * 2211*34642Smarc * XXX - this routine should be broken out - it is essentially 2212*34642Smarc * straight line code. 2213*34642Smarc * 221430391Skarels *****************************************************************/ 221530391Skarels 221630391Skarels qdiint(qd) 2217*34642Smarc register int qd; 221830391Skarels { 221930391Skarels register struct _vs_event *event; 222030391Skarels register struct qdinput *eqh; 222130391Skarels 222230391Skarels struct dga *dga; 222330391Skarels struct duart *duart; 222430391Skarels struct mouse_report *new_rep; 222530391Skarels 222630391Skarels struct uba_device *ui; 222730391Skarels struct tty *tp; 222830391Skarels 222934615Smarc u_short chr; 223030391Skarels int i,j; 223130391Skarels int k,l; 223230391Skarels 223330391Skarels u_short status; 223430391Skarels u_short data; 223530391Skarels u_short key; 223630391Skarels 223730391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 223830391Skarels char a, b, c; /* mouse button test variables */ 223930391Skarels 224030391Skarels spl4(); /* allow interval timer in */ 224130391Skarels 224230391Skarels eqh = eq_header[qd]; /* optimized as a register */ 224330391Skarels new_rep = ¤t_rep[qd]; 224430391Skarels duart = (struct duart *) qdmap[qd].duart; 224530391Skarels 2246*34642Smarc /* 2247*34642Smarc * if the graphic device is turned on.. */ 224830391Skarels 224930391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 225030391Skarels 2251*34642Smarc /* 2252*34642Smarc * empty DUART 2253*34642Smarc */ 2254*34642Smarc while ((status = duart->statusA) & RCV_RDY || 2255*34642Smarc (status = duart->statusB) & RCV_RDY) { 225630391Skarels 2257*34642Smarc /* 2258*34642Smarc * pick up LK-201 input (if any) */ 225930391Skarels 2260*34642Smarc if ((status = duart->statusA) & RCV_RDY) { 226130391Skarels 2262*34642Smarc /* if error condition, then reset it */ 226330391Skarels 2264*34642Smarc if ((status = duart->statusA) & 0x70) { 2265*34642Smarc duart->cmdA = 0x40; 2266*34642Smarc continue; 2267*34642Smarc } 226830391Skarels 2269*34642Smarc /* event queue full now? (overflow condition) */ 227030391Skarels 2271*34642Smarc if (ISFULL(eqh) == TRUE) { 2272*34642Smarc printf( 2273*34642Smarc "\nqd%d: qdiint: event queue overflow", 2274*34642Smarc qd); 2275*34642Smarc break; 2276*34642Smarc } 227730391Skarels 2278*34642Smarc /* 2279*34642Smarc * Check for various keyboard errors */ 228030391Skarels 2281*34642Smarc key = duart->dataA & 0xFF; 228230391Skarels 2283*34642Smarc if (key==LK_POWER_ERROR || 2284*34642Smarc key==LK_KDOWN_ERROR || 2285*34642Smarc key == LK_INPUT_ERROR || 2286*34642Smarc key == LK_OUTPUT_ERROR) { 2287*34642Smarc printf( 2288*34642Smarc "\nqd%d: qdiint: keyboard error, code = %x", 2289*34642Smarc qd,key); 2290*34642Smarc return(0); 2291*34642Smarc } 229230391Skarels 2293*34642Smarc if (key < LK_LOWEST) 2294*34642Smarc return(0); 229530391Skarels 2296*34642Smarc ++do_wakeup; /* request a select wakeup call */ 229730391Skarels 2298*34642Smarc event = PUTBEGIN(eqh); 2299*34642Smarc PUTEND(eqh); 230030391Skarels 2301*34642Smarc event->vse_key = key; 2302*34642Smarc event->vse_key &= 0x00FF; 2303*34642Smarc event->vse_x = eqh->curs_pos.x; 2304*34642Smarc event->vse_y = eqh->curs_pos.y; 2305*34642Smarc event->vse_time = TOY; 2306*34642Smarc event->vse_type = VSE_BUTTON; 2307*34642Smarc event->vse_direction = VSE_KBTRAW; 2308*34642Smarc event->vse_device = VSE_DKB; 2309*34642Smarc } 231030391Skarels 2311*34642Smarc /* 2312*34642Smarc * pick up the mouse input (if any) */ 231330391Skarels 2314*34642Smarc if ((status = duart->statusB) & RCV_RDY && 2315*34642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 231630391Skarels 2317*34642Smarc if (status & 0x70) { 2318*34642Smarc duart->cmdB = 0x40; 2319*34642Smarc continue; 2320*34642Smarc } 232130391Skarels 2322*34642Smarc /* event queue full now? (overflow condition) */ 232330391Skarels 2324*34642Smarc if (ISFULL(eqh) == TRUE) { 2325*34642Smarc printf( 2326*34642Smarc "\nqd%d: qdiint: event queue overflow", 2327*34642Smarc qd); 2328*34642Smarc break; 2329*34642Smarc } 233030391Skarels 2331*34642Smarc data = duart->dataB; /* get report byte */ 2332*34642Smarc ++new_rep->bytcnt; /* bump report byte count */ 233330391Skarels 2334*34642Smarc /* 2335*34642Smarc * if 1st byte of report.. */ 233630391Skarels 2337*34642Smarc if ( data & START_FRAME) { 2338*34642Smarc new_rep->state = data; 2339*34642Smarc if (new_rep->bytcnt > 1) { 2340*34642Smarc /* start of new frame */ 2341*34642Smarc new_rep->bytcnt = 1; 2342*34642Smarc /* ..continue looking */ 2343*34642Smarc continue; 2344*34642Smarc } 2345*34642Smarc } 234630391Skarels 2347*34642Smarc /* 2348*34642Smarc * if 2nd byte of report.. */ 234930391Skarels 2350*34642Smarc else if (new_rep->bytcnt == 2) { 2351*34642Smarc new_rep->dx = data & 0x00FF; 2352*34642Smarc } 235330391Skarels 2354*34642Smarc /* 2355*34642Smarc * if 3rd byte of report, load input event queue */ 235630391Skarels 2357*34642Smarc else if (new_rep->bytcnt == 3) { 235830391Skarels 2359*34642Smarc new_rep->dy = data & 0x00FF; 2360*34642Smarc new_rep->bytcnt = 0; 236130391Skarels 2362*34642Smarc /* 2363*34642Smarc * if mouse position has changed.. */ 236430391Skarels 2365*34642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 236630391Skarels 2367*34642Smarc /* 2368*34642Smarc * calculate acceleration factor, if needed */ 236930391Skarels 2370*34642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 237130391Skarels 2372*34642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 2373*34642Smarc new_rep->dx += 2374*34642Smarc (new_rep->dx - qdflags[qd].curs_thr) 2375*34642Smarc * qdflags[qd].curs_acc; 237630391Skarels 2377*34642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 2378*34642Smarc new_rep->dy += 2379*34642Smarc (new_rep->dy - qdflags[qd].curs_thr) 2380*34642Smarc * qdflags[qd].curs_acc; 2381*34642Smarc } 238230391Skarels 2383*34642Smarc /* 2384*34642Smarc * update cursor position coordinates */ 238530391Skarels 2386*34642Smarc if (new_rep->state & X_SIGN) { 2387*34642Smarc eqh->curs_pos.x += new_rep->dx; 2388*34642Smarc if (eqh->curs_pos.x > 1023) 2389*34642Smarc eqh->curs_pos.x = 1023; 2390*34642Smarc } 2391*34642Smarc else { 2392*34642Smarc eqh->curs_pos.x -= new_rep->dx; 2393*34642Smarc if (eqh->curs_pos.x < -15) 2394*34642Smarc eqh->curs_pos.x = -15; 2395*34642Smarc } 239630391Skarels 2397*34642Smarc if (new_rep->state & Y_SIGN) { 2398*34642Smarc eqh->curs_pos.y -= new_rep->dy; 2399*34642Smarc if (eqh->curs_pos.y < -15) 2400*34642Smarc eqh->curs_pos.y = -15; 2401*34642Smarc } 2402*34642Smarc else { 2403*34642Smarc eqh->curs_pos.y += new_rep->dy; 2404*34642Smarc if (eqh->curs_pos.y > 863) 2405*34642Smarc eqh->curs_pos.y = 863; 2406*34642Smarc } 240730391Skarels 2408*34642Smarc /* 2409*34642Smarc * update cursor screen position */ 241030391Skarels 2411*34642Smarc dga = (struct dga *) qdmap[qd].dga; 2412*34642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 2413*34642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 241430391Skarels 2415*34642Smarc /* 2416*34642Smarc * if cursor is in the box, no event report */ 241730391Skarels 2418*34642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 2419*34642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 2420*34642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 2421*34642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 2422*34642Smarc goto GET_MBUTTON; 2423*34642Smarc } 242430391Skarels 2425*34642Smarc /* 2426*34642Smarc * report the mouse motion event */ 242730391Skarels 2428*34642Smarc event = PUTBEGIN(eqh); 2429*34642Smarc PUTEND(eqh); 243030391Skarels 2431*34642Smarc ++do_wakeup; /* request a select wakeup call */ 243230391Skarels 2433*34642Smarc event->vse_x = eqh->curs_pos.x; 2434*34642Smarc event->vse_y = eqh->curs_pos.y; 243530391Skarels 2436*34642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 2437*34642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 2438*34642Smarc event->vse_key = 0; 2439*34642Smarc event->vse_direction = 0; 2440*34642Smarc event->vse_time = TOY; /* time stamp */ 2441*34642Smarc } 244230391Skarels 244330391Skarels GET_MBUTTON: 2444*34642Smarc /* 2445*34642Smarc * if button state has changed */ 244630391Skarels 2447*34642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 2448*34642Smarc b = last_rep[qd].state & 0x07; 244930391Skarels 2450*34642Smarc if (a ^ b) { 245130391Skarels 2452*34642Smarc for ( c = 1; c < 8; c <<= 1) { 245330391Skarels 2454*34642Smarc if (!( c & (a ^ b))) /* this button change? */ 2455*34642Smarc continue; 245630391Skarels 2457*34642Smarc /* event queue full? (overflow condition) */ 245830391Skarels 2459*34642Smarc if (ISFULL(eqh) == TRUE) { 2460*34642Smarc printf("\nqd%d: qdiint: event queue overflow", qd); 2461*34642Smarc break; 2462*34642Smarc } 246330391Skarels 2464*34642Smarc event = PUTBEGIN(eqh); /* get new event */ 2465*34642Smarc PUTEND(eqh); 246630391Skarels 2467*34642Smarc ++do_wakeup; /* request select wakeup */ 246830391Skarels 2469*34642Smarc event->vse_x = eqh->curs_pos.x; 2470*34642Smarc event->vse_y = eqh->curs_pos.y; 247130391Skarels 2472*34642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 2473*34642Smarc event->vse_type = VSE_BUTTON; /* new button */ 2474*34642Smarc event->vse_time = TOY; /* time stamp */ 247530391Skarels 2476*34642Smarc /* flag changed button and if up or down */ 247730391Skarels 2478*34642Smarc if (c == RIGHT_BUTTON) 2479*34642Smarc event->vse_key = VSE_RIGHT_BUTTON; 2480*34642Smarc else if (c == MIDDLE_BUTTON) 2481*34642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 2482*34642Smarc else if (c == LEFT_BUTTON) 2483*34642Smarc event->vse_key = VSE_LEFT_BUTTON; 248430391Skarels 2485*34642Smarc /* set bit = button depressed */ 248630391Skarels 2487*34642Smarc if (c & a) 2488*34642Smarc event->vse_direction = VSE_KBTDOWN; 2489*34642Smarc else 2490*34642Smarc event->vse_direction = VSE_KBTUP; 2491*34642Smarc } 2492*34642Smarc } 249330391Skarels 2494*34642Smarc /* refresh last report */ 249530391Skarels 2496*34642Smarc last_rep[qd] = current_rep[qd]; 249730391Skarels 2498*34642Smarc } /* get last byte of report */ 2499*34642Smarc } /* pickup mouse input */ 250030391Skarels 2501*34642Smarc /* 2502*34642Smarc * pickup tablet input, if any */ 250330391Skarels 2504*34642Smarc else if ((status = duart->statusB) & RCV_RDY && 2505*34642Smarc qdflags[qd].pntr_id == TABLET_ID) { 250630391Skarels 2507*34642Smarc if (status & 0x70) { 2508*34642Smarc duart->cmdB = 0x40; 2509*34642Smarc continue; 2510*34642Smarc } 251130391Skarels 2512*34642Smarc /* event queue full now? (overflow condition) */ 251330391Skarels 2514*34642Smarc if (ISFULL(eqh) == TRUE) { 2515*34642Smarc printf("\nqd%d: qdiint: event queue overflow", qd); 2516*34642Smarc break; 2517*34642Smarc } 251830391Skarels 2519*34642Smarc data = duart->dataB; /* get report byte */ 2520*34642Smarc ++new_rep->bytcnt; /* bump report byte count */ 252130391Skarels 2522*34642Smarc /* 2523*34642Smarc * if 1st byte of report.. */ 252430391Skarels 2525*34642Smarc if (data & START_FRAME) { 2526*34642Smarc new_rep->state = data; 2527*34642Smarc if (new_rep->bytcnt > 1) { 2528*34642Smarc new_rep->bytcnt = 1; /* start of new frame */ 2529*34642Smarc continue; /* ..continue looking */ 2530*34642Smarc } 2531*34642Smarc } 253230391Skarels 2533*34642Smarc /* 2534*34642Smarc * if 2nd byte of report.. */ 253530391Skarels 2536*34642Smarc else if (new_rep->bytcnt == 2) { 2537*34642Smarc new_rep->dx = data & 0x3F; 2538*34642Smarc } 253930391Skarels 2540*34642Smarc /* 2541*34642Smarc * if 3rd byte of report.. */ 254230391Skarels 2543*34642Smarc else if (new_rep->bytcnt == 3) { 2544*34642Smarc new_rep->dx |= (data & 0x3F) << 6; 2545*34642Smarc } 254630391Skarels 2547*34642Smarc /* 2548*34642Smarc * if 4th byte of report.. */ 254930391Skarels 2550*34642Smarc else if (new_rep->bytcnt == 4) { 2551*34642Smarc new_rep->dy = data & 0x3F; 2552*34642Smarc } 255330391Skarels 2554*34642Smarc /* 2555*34642Smarc * if 5th byte of report, load input event queue */ 255630391Skarels 2557*34642Smarc else if (new_rep->bytcnt == 5) { 255830391Skarels 2559*34642Smarc new_rep->dy |= (data & 0x3F) << 6; 2560*34642Smarc new_rep->bytcnt = 0; 256130391Skarels 2562*34642Smarc /* 2563*34642Smarc * update cursor position coordinates */ 256430391Skarels 2565*34642Smarc new_rep->dx /= qdflags[qd].tab_res; 2566*34642Smarc new_rep->dy = (2200 - new_rep->dy) 2567*34642Smarc / qdflags[qd].tab_res; 256830391Skarels 2569*34642Smarc if (new_rep->dx > 1023) { 2570*34642Smarc new_rep->dx = 1023; 2571*34642Smarc } 2572*34642Smarc if (new_rep->dy > 863) { 2573*34642Smarc new_rep->dy = 863; 2574*34642Smarc } 257530391Skarels 2576*34642Smarc /* 2577*34642Smarc * report an event if the puck/stylus has moved 2578*34642Smarc */ 257930391Skarels 2580*34642Smarc if (eqh->curs_pos.x != new_rep->dx || 2581*34642Smarc eqh->curs_pos.y != new_rep->dy) { 258230391Skarels 2583*34642Smarc eqh->curs_pos.x = new_rep->dx; 2584*34642Smarc eqh->curs_pos.y = new_rep->dy; 258530391Skarels 2586*34642Smarc /* 2587*34642Smarc * update cursor screen position */ 258830391Skarels 2589*34642Smarc dga = (struct dga *) qdmap[qd].dga; 2590*34642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 2591*34642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 259230391Skarels 2593*34642Smarc /* 2594*34642Smarc * if cursor is in the box, no event report 2595*34642Smarc */ 259630391Skarels 2597*34642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 2598*34642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 2599*34642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 2600*34642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 2601*34642Smarc goto GET_TBUTTON; 2602*34642Smarc } 260330391Skarels 2604*34642Smarc /* 2605*34642Smarc * report the tablet motion event */ 260630391Skarels 2607*34642Smarc event = PUTBEGIN(eqh); 2608*34642Smarc PUTEND(eqh); 260930391Skarels 2610*34642Smarc ++do_wakeup; /* request a select wakeup call */ 261130391Skarels 2612*34642Smarc event->vse_x = eqh->curs_pos.x; 2613*34642Smarc event->vse_y = eqh->curs_pos.y; 261430391Skarels 2615*34642Smarc event->vse_device = VSE_TABLET; /* tablet */ 2616*34642Smarc /* 2617*34642Smarc * right now, X handles tablet motion the same 2618*34642Smarc * as mouse motion 2619*34642Smarc */ 2620*34642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 2621*34642Smarc event->vse_key = 0; 2622*34642Smarc event->vse_direction = 0; 2623*34642Smarc event->vse_time = TOY; /* time stamp */ 2624*34642Smarc } 262530391Skarels GET_TBUTTON: 2626*34642Smarc /* 2627*34642Smarc * if button state has changed */ 262830391Skarels 2629*34642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 2630*34642Smarc b = last_rep[qd].state & 0x1E; 263130391Skarels 2632*34642Smarc if (a ^ b) { 263330391Skarels 2634*34642Smarc /* event queue full now? (overflow condition) */ 263530391Skarels 2636*34642Smarc if (ISFULL(eqh) == TRUE) { 2637*34642Smarc printf("\nqd%d: qdiint: event queue overflow",qd); 2638*34642Smarc break; 2639*34642Smarc } 264030391Skarels 2641*34642Smarc event = PUTBEGIN(eqh); /* get new event */ 2642*34642Smarc PUTEND(eqh); 264330391Skarels 2644*34642Smarc ++do_wakeup; /* request a select wakeup call */ 264530391Skarels 2646*34642Smarc event->vse_x = eqh->curs_pos.x; 2647*34642Smarc event->vse_y = eqh->curs_pos.y; 264830391Skarels 2649*34642Smarc event->vse_device = VSE_TABLET; /* tablet */ 2650*34642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 2651*34642Smarc event->vse_time = TOY; /* time stamp */ 265230391Skarels 2653*34642Smarc /* define the changed button and if up or down */ 265430391Skarels 2655*34642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 2656*34642Smarc if (c & (a ^ b)) { 2657*34642Smarc if (c == T_LEFT_BUTTON) 2658*34642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 2659*34642Smarc else if (c == T_FRONT_BUTTON) 2660*34642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 2661*34642Smarc else if (c == T_RIGHT_BUTTON) 2662*34642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 2663*34642Smarc else if (c == T_BACK_BUTTON) 2664*34642Smarc event->vse_key = VSE_T_BACK_BUTTON; 2665*34642Smarc break; 2666*34642Smarc } 2667*34642Smarc } 266830391Skarels 2669*34642Smarc /* set bit = button depressed */ 267030391Skarels 2671*34642Smarc if (c & a) 2672*34642Smarc event->vse_direction = VSE_KBTDOWN; 2673*34642Smarc else 2674*34642Smarc event->vse_direction = VSE_KBTUP; 2675*34642Smarc } 267630391Skarels 2677*34642Smarc /* refresh last report */ 267830391Skarels 2679*34642Smarc last_rep[qd] = current_rep[qd]; 268030391Skarels 2681*34642Smarc } /* get last byte of report */ 2682*34642Smarc } /* pick up tablet input */ 268330391Skarels 2684*34642Smarc } /* while input available.. */ 268530391Skarels 2686*34642Smarc /* 2687*34642Smarc * do select wakeup 2688*34642Smarc */ 2689*34642Smarc if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 2690*34642Smarc selwakeup(rsel[qd], 0); 2691*34642Smarc rsel[qd] = 0; 2692*34642Smarc qdflags[qd].selmask &= ~SEL_READ; 2693*34642Smarc do_wakeup = 0; 2694*34642Smarc } 269530391Skarels } 269630391Skarels 2697*34642Smarc /* 2698*34642Smarc * if the graphic device is not turned on, this is console input */ 269930391Skarels 270030391Skarels else { 270130391Skarels 2702*34642Smarc ui = qdinfo[qd]; 2703*34642Smarc if (ui == 0 || ui->ui_alive == 0) 2704*34642Smarc return(0); 270530391Skarels 2706*34642Smarc tp = &qd_tty[qd << 2]; 270730391Skarels 2708*34642Smarc /* 2709*34642Smarc * Get a character from the keyboard. */ 271030391Skarels 2711*34642Smarc while ((status = duart->statusA) & RCV_RDY) { 271230391Skarels 2713*34642Smarc key = duart->dataA; 2714*34642Smarc key &= 0xFF; 271530391Skarels 2716*34642Smarc /* 2717*34642Smarc * Check for various keyboard errors */ 271830391Skarels 2719*34642Smarc if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 2720*34642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 2721*34642Smarc printf("\nqd%d: qdiint: Keyboard error, code = %x",qd,key); 2722*34642Smarc return(0); 2723*34642Smarc } 272430391Skarels 2725*34642Smarc if (key < LK_LOWEST) 2726*34642Smarc return(0); 272730391Skarels 2728*34642Smarc /* 2729*34642Smarc * See if its a state change key */ 273030391Skarels 2731*34642Smarc switch (key) { 273230391Skarels 2733*34642Smarc case LOCK: 2734*34642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 2735*34642Smarc if (q_keyboard.lock) 2736*34642Smarc led_control(qd, LK_LED_ENABLE, LK_LED_LOCK); 2737*34642Smarc else 2738*34642Smarc led_control(qd, LK_LED_DISABLE, LK_LED_LOCK); 2739*34642Smarc return; 274030391Skarels 2741*34642Smarc case SHIFT: 2742*34642Smarc q_keyboard.shift ^= 0xFFFF; 2743*34642Smarc return; 274430391Skarels 2745*34642Smarc case CNTRL: 2746*34642Smarc q_keyboard.cntrl ^= 0xFFFF; 2747*34642Smarc return; 274830391Skarels 2749*34642Smarc case ALLUP: 2750*34642Smarc q_keyboard.cntrl = 0; 2751*34642Smarc q_keyboard.shift = 0; 2752*34642Smarc return; 275330391Skarels 2754*34642Smarc case REPEAT: 2755*34642Smarc chr = q_keyboard.last; 2756*34642Smarc break; 275730391Skarels 2758*34642Smarc /* 2759*34642Smarc * Test for cntrl characters. If set, see if the character 2760*34642Smarc * is elligible to become a control character. */ 276130391Skarels 2762*34642Smarc default: 276330391Skarels 2764*34642Smarc if (q_keyboard.cntrl) { 2765*34642Smarc chr = q_key[key]; 2766*34642Smarc if (chr >= ' ' && chr <= '~') 2767*34642Smarc chr &= 0x1F; 2768*34642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 2769*34642Smarc chr &= 0x9F; 2770*34642Smarc } 2771*34642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 2772*34642Smarc chr = q_shift_key[key]; 2773*34642Smarc else 2774*34642Smarc chr = q_key[key]; 2775*34642Smarc break; 277630391Skarels } 277730391Skarels 2778*34642Smarc q_keyboard.last = chr; 277930391Skarels 2780*34642Smarc /* 2781*34642Smarc * Check for special function keys */ 278230391Skarels 2783*34642Smarc if (chr & 0x100) { 2784*34642Smarc char *string; 2785*34642Smarc string = q_special[chr & 0x7F]; 2786*34642Smarc while(*string) 2787*34642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 278834615Smarc } 2789*34642Smarc else { 2790*34642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 2791*34642Smarc } 279230391Skarels } 279330391Skarels } 279430391Skarels 2795*34642Smarc /* 2796*34642Smarc * cleanup and exit */ 279734615Smarc 279830391Skarels return(0); 279930391Skarels 280030391Skarels } /* qdiint */ 280130391Skarels 280230391Skarels /****************************************************************** 280334615Smarc ******************************************************************* 280434615Smarc ******************************************************************* 280530391Skarels * 280630391Skarels * THE SUBROUTINES START HERE: 280730391Skarels * 280830391Skarels ******************************************************************/ 280930391Skarels 281030391Skarels /***************************************************************** 281130391Skarels * 281230391Skarels * clear_qd_screen()... clear the QDSS screen 281330391Skarels * 281430391Skarels ****************************************************************** 281530391Skarels * 281630391Skarels * >>> NOTE <<< 281730391Skarels * 281830391Skarels * This code requires that certain adder initialization be valid. To 281930391Skarels * assure that this requirement is satisfied, this routine should be 282030391Skarels * called only after calling the "setup_dragon()" function. 282130391Skarels * 282230391Skarels * Clear the bitmap a piece at a time. Since the fast scroll clear 282330391Skarels * only clears the current displayed portion of the bitmap put a 282430391Skarels * temporary value in the y limit register so we can access whole 282530391Skarels * bitmap 282630391Skarels * 282730391Skarels ****************/ 282830391Skarels 282930391Skarels clear_qd_screen(unit) 283030391Skarels int unit; 283130391Skarels { 283230391Skarels register struct adder *adder; 283330391Skarels adder = (struct adder *) qdmap[unit].adder; 283430391Skarels 283530391Skarels adder->x_limit = 1024; 283630391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 283730391Skarels adder->y_offset_pending = 0; 2838*34642Smarc #define WSV wait_status(adder, VSYNC); wait_status(adder, VSYNC) 2839*34642Smarc WSV; 284030391Skarels adder->y_scroll_constant = SCROLL_ERASE; 2841*34642Smarc WSV; 284230391Skarels adder->y_offset_pending = 864; 2843*34642Smarc WSV; 284430391Skarels adder->y_scroll_constant = SCROLL_ERASE; 2845*34642Smarc WSV; 284630391Skarels adder->y_offset_pending = 1728; 2847*34642Smarc WSV; 284830391Skarels adder->y_scroll_constant = SCROLL_ERASE; 2849*34642Smarc WSV; 285030391Skarels adder->y_offset_pending = 0; /* back to normal */ 2851*34642Smarc WSV; 285230391Skarels adder->x_limit = MAX_SCREEN_X; 285330391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 2854*34642Smarc #undef WSV 285530391Skarels 285630391Skarels } /* clear_qd_screen */ 285730391Skarels 285830391Skarels /********************************************************************** 285930391Skarels * 2860*34642Smarc * qdputc()... route kernel console output to the glass tty 286130391Skarels * 286230391Skarels *********************************************************************** 286330391Skarels * 286430391Skarels * calling convention: 286530391Skarels * 286630391Skarels * qdputc(chr); 286730391Skarels * 286830391Skarels * where: char chr; ;character for output 286930391Skarels * 287030391Skarels ****************/ 287130391Skarels 287230391Skarels qdputc(chr) 2873*34642Smarc register char chr; 287430391Skarels { 287530391Skarels 2876*34642Smarc /* 2877*34642Smarc * if system is now physical, forget it (ie: crash DUMP) 2878*34642Smarc */ 2879*34642Smarc if ((mfpr(MAPEN) & 1) == 0) 2880*34642Smarc return; 288134615Smarc 288234615Smarc blitc(0, chr & 0xff); 288332012Smarc if ((chr & 0177) == '\n') 288432012Smarc blitc(0, '\r'); 288530391Skarels 288630391Skarels } /* qdputc */ 288730391Skarels 288830391Skarels /******************************************************************* 288930391Skarels * 289030391Skarels * qdgetc()... get a character from the LK201 289130391Skarels * 289230391Skarels ******************************************************************* 289330391Skarels * 289430391Skarels * calling convention: 289530391Skarels * 289630391Skarels * qdgetc(); 289730391Skarels * 289830391Skarels * returns: the character read. 289930391Skarels * 290030391Skarels ****************/ 290130391Skarels 290230391Skarels qdgetc() 290330391Skarels { 290430391Skarels register short key; 290530391Skarels register char chr; 290630391Skarels register struct duart *duart; 290730391Skarels 290830391Skarels u_int status; 290930391Skarels 291030391Skarels duart = (struct duart *) qdmap[0].duart; 291130391Skarels 2912*34642Smarc /* 291330391Skarels * Get a character from the keyboard. */ 291430391Skarels 291530391Skarels LOOP: 291630391Skarels while (!((status = duart->statusA) & RCV_RDY)) 2917*34642Smarc ; 291830391Skarels 291930391Skarels key = duart->dataA; 292030391Skarels key &= 0xFF; 292130391Skarels 2922*34642Smarc /* 292330391Skarels * Check for various keyboard errors */ 292430391Skarels 2925*34642Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 292630391Skarels key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 292730391Skarels printf("Keyboard error, code = %x\n", key); 292830391Skarels return(0); 292930391Skarels } 293030391Skarels 293130391Skarels if (key < LK_LOWEST) 293230391Skarels return(0); 293330391Skarels 2934*34642Smarc /* 293530391Skarels * See if its a state change key */ 293630391Skarels 293730391Skarels switch (key) { 293830391Skarels 2939*34642Smarc case LOCK: 294030391Skarels q_keyboard.lock ^= 0xffff; /* toggle */ 294130391Skarels if (q_keyboard.lock) 294230391Skarels led_control(LK_LED_ENABLE, LK_LED_LOCK); 294330391Skarels else 2944*34642Smarc led_control(LK_LED_DISABLE, LK_LED_LOCK); 294530391Skarels goto LOOP; 294630391Skarels 2947*34642Smarc case SHIFT: 294830391Skarels q_keyboard.shift ^= 0xFFFF; 294930391Skarels goto LOOP; 295030391Skarels 2951*34642Smarc case CNTRL: 295230391Skarels q_keyboard.cntrl ^= 0xFFFF; 295330391Skarels goto LOOP; 295430391Skarels 2955*34642Smarc case ALLUP: 295630391Skarels q_keyboard.cntrl = 0; 295730391Skarels q_keyboard.shift = 0; 295830391Skarels goto LOOP; 295930391Skarels 2960*34642Smarc case REPEAT: 296130391Skarels chr = q_keyboard.last; 296230391Skarels break; 296330391Skarels 2964*34642Smarc /* 2965*34642Smarc * Test for cntrl characters. If set, see if the character 2966*34642Smarc * is elligible to become a control character. */ 296730391Skarels 2968*34642Smarc default: 296930391Skarels 297030391Skarels if (q_keyboard.cntrl) { 2971*34642Smarc chr = q_key[key]; 2972*34642Smarc if (chr >= ' ' && chr <= '~') 2973*34642Smarc chr &= 0x1F; 297430391Skarels } 297530391Skarels else if ( q_keyboard.lock || q_keyboard.shift ) 297630391Skarels chr = q_shift_key[key]; 297730391Skarels else 2978*34642Smarc chr = q_key[key]; 297930391Skarels break; 298030391Skarels } 298130391Skarels 298230391Skarels if (chr < ' ' && chr > '~') /* if input is non-displayable */ 2983*34642Smarc return(0); /* ..then pitch it! */ 298430391Skarels 298530391Skarels q_keyboard.last = chr; 298630391Skarels 2987*34642Smarc /* 298830391Skarels * Check for special function keys */ 298930391Skarels 299030391Skarels if (chr & 0x80) /* pitch the function keys */ 2991*34642Smarc return(0); 299230391Skarels else 2993*34642Smarc return(chr); 299430391Skarels 299530391Skarels } /* qdgetc */ 299630391Skarels 299730391Skarels /********************************************************************** 299830391Skarels * 299930391Skarels * ldcursor()... load the mouse cursor's template RAM bitmap 300030391Skarels * 300130391Skarels ********************************************************************* 300230391Skarels * 300330391Skarels * calling convention: 300430391Skarels * 300530391Skarels * ldcursor(unit, bitmap); 300630391Skarels * u_int unit; 300730391Skarels * short *bitmap; 300830391Skarels * 300930391Skarels ****************/ 301030391Skarels 301130391Skarels ldcursor(unit, bitmap) 3012*34642Smarc u_int unit; 3013*34642Smarc short *bitmap; 301430391Skarels { 301530391Skarels register struct dga *dga; 301630391Skarels register short *temp; 301730391Skarels register int i; 301830391Skarels 301930391Skarels int cursor; 302030391Skarels 302130391Skarels dga = (struct dga *) qdmap[unit].dga; 302230391Skarels temp = (short *) qdmap[unit].template; 302330391Skarels 302430391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 3025*34642Smarc cursor = -1; /* ..note that.. */ 3026*34642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 302730391Skarels } 302830391Skarels else { 3029*34642Smarc cursor = 0; 303030391Skarels } 303130391Skarels 303230391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 303330391Skarels 303430391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 3035*34642Smarc /* ..of the 8k WORD template space */ 303630391Skarels for (i = 0; i < 32; ++i) 3037*34642Smarc *temp++ = *bitmap++; 303830391Skarels 303930391Skarels if (cursor) { /* if cursor was enabled.. */ 3040*34642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 304130391Skarels } 304230391Skarels 304330391Skarels return(0); 304430391Skarels 304530391Skarels } /* ldcursor */ 304630391Skarels 304730391Skarels /********************************************************************** 304830391Skarels * 304930391Skarels * ldfont()... put the console font in the QDSS off-screen memory 305030391Skarels * 305130391Skarels *********************************************************************** 305230391Skarels * 305330391Skarels * calling convention: 305430391Skarels * 305530391Skarels * ldfont(unit); 305630391Skarels * u_int unit; ;QDSS unit number 305730391Skarels * 305830391Skarels ****************/ 305930391Skarels 306030391Skarels ldfont(unit) 3061*34642Smarc u_int unit; 306230391Skarels { 306330391Skarels register struct adder *adder; 306430391Skarels 306530391Skarels int i; /* scratch variables */ 306630391Skarels int j; 306730391Skarels int k; 306830391Skarels short packed; 306934615Smarc int max_chars_line; 307030391Skarels 307130391Skarels adder = (struct adder *) qdmap[unit].adder; 307230391Skarels 3073*34642Smarc /* 3074*34642Smarc * setup VIPER operand control registers */ 307530391Skarels 307630391Skarels write_ID(adder, MASK_1, 0xFFFF); 307730391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 307830391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 307930391Skarels 308030391Skarels write_ID(adder, SRC1_OCR_B, 3081*34642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 308230391Skarels write_ID(adder, SRC2_OCR_B, 3083*34642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 308430391Skarels write_ID(adder, DST_OCR_B, 3085*34642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 308630391Skarels 308730391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 308830391Skarels 3089*34642Smarc /* 3090*34642Smarc * load destination data */ 309130391Skarels 309230391Skarels wait_status(adder, RASTEROP_COMPLETE); 309330391Skarels 309430391Skarels adder->destination_x = FONT_X; 309530391Skarels adder->destination_y = FONT_Y; 309634615Smarc if (FONT_WIDTH > MAX_SCREEN_X) 3097*34642Smarc adder->fast_dest_dx = MAX_SCREEN_X; 309834615Smarc else 309934615Smarc adder->fast_dest_dx = FONT_WIDTH; 310030391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 310130391Skarels 3102*34642Smarc /* 3103*34642Smarc * setup for processor to bitmap xfer */ 310430391Skarels 310530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 310630391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 310730391Skarels 3108*34642Smarc /* 3109*34642Smarc * Figure out how many characters can be stored on one "line" of 3110*34642Smarc * offscreen memory. 3111*34642Smarc */ 3112*34642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 3113*34642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 3114*34642Smarc max_chars_line = CHARS/2 + CHARS%2; 311530391Skarels 3116*34642Smarc /* 3117*34642Smarc * iteratively do the processor to bitmap xfer */ 311834615Smarc 311930391Skarels for (i = 0; i < ROWS; ++i) { 312030391Skarels 3121*34642Smarc /* PTOB a scan line */ 312230391Skarels 3123*34642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 3124*34642Smarc /* PTOB one scan of a char cell */ 312530391Skarels 3126*34642Smarc packed = q_font[k]; 3127*34642Smarc k += ROWS; 3128*34642Smarc packed |= ((short)q_font[k] << 8); 3129*34642Smarc k += ROWS; 313030391Skarels 3131*34642Smarc wait_status(adder, TX_READY); 3132*34642Smarc adder->id_data = packed; 3133*34642Smarc } 313430391Skarels } 313530391Skarels 3136*34642Smarc /* 3137*34642Smarc * (XXX XXX XXX - should remove) 3138*34642Smarc * 3139*34642Smarc * Copy the second row of characters. Subtract the first 3140*34642Smarc * row from the total number. Divide this quantity by 2 3141*34642Smarc * because 2 chars are stored in a short in the PTOB loop 3142*34642Smarc * below. Figure out how many characters can be stored on 3143*34642Smarc * one "line" of offscreen memory 3144*34642Smarc */ 3145*34642Smarc 3146*34642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 3147*34642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 3148*34642Smarc return; 3149*34642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 3150*34642Smarc /* Paranoia check to see if 3rd row may be needed */ 3151*34642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 315234615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 315334615Smarc 315434615Smarc adder->destination_x = FONT_X; 315534615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 315634615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 315734615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 315834615Smarc 3159*34642Smarc /* 3160*34642Smarc * setup for processor to bitmap xfer 3161*34642Smarc */ 316234615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 316334615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 316434615Smarc 3165*34642Smarc /* 3166*34642Smarc * iteratively do the processor to bitmap xfer 3167*34642Smarc */ 316834615Smarc for (i = 0; i < ROWS; ++i) { 3169*34642Smarc /* 3170*34642Smarc * PTOB a scan line 3171*34642Smarc */ 3172*34642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 3173*34642Smarc /* 3174*34642Smarc * PTOB one scan of a char cell 3175*34642Smarc */ 3176*34642Smarc packed = q_font[k + FONT_OFFSET]; 3177*34642Smarc k += ROWS; 3178*34642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 3179*34642Smarc k += ROWS; 3180*34642Smarc wait_status(adder, TX_READY); 3181*34642Smarc adder->id_data = packed; 3182*34642Smarc } 318334615Smarc } 318434615Smarc 318530391Skarels } /* ldfont */ 318630391Skarels 318730391Skarels /********************************************************************* 318830391Skarels * 318930391Skarels * led_control()... twiddle LK-201 LED's 319030391Skarels * 319130391Skarels ********************************************************************** 319230391Skarels * 319330391Skarels * led_control(unit, cmd, led_mask); 319430391Skarels * u_int unit; QDSS number 319530391Skarels * int cmd; LED enable/disable command 319630391Skarels * int led_mask; which LED(s) to twiddle 319730391Skarels * 319830391Skarels *************/ 319930391Skarels 320030391Skarels led_control(unit, cmd, led_mask) 3201*34642Smarc u_int unit; 3202*34642Smarc int cmd; 3203*34642Smarc int led_mask; 320430391Skarels { 320530391Skarels register int i; 320630391Skarels register int status; 320730391Skarels register struct duart *duart; 320830391Skarels 320930391Skarels duart = (struct duart *) qdmap[unit].duart; 321030391Skarels 321130391Skarels for (i = 1000; i > 0; --i) { 3212*34642Smarc if ((status = duart->statusA) & XMT_RDY) { 3213*34642Smarc duart->dataA = cmd; 3214*34642Smarc break; 3215*34642Smarc } 321630391Skarels } 321730391Skarels for (i = 1000; i > 0; --i) { 3218*34642Smarc if ((status = duart->statusA) & XMT_RDY) { 3219*34642Smarc duart->dataA = led_mask; 3220*34642Smarc break; 3221*34642Smarc } 322230391Skarels } 322330391Skarels if (i == 0) 3224*34642Smarc return(BAD); 322530391Skarels return(GOOD); 322630391Skarels 322730391Skarels } /* led_control */ 322830391Skarels 322930391Skarels /******************************************************************* 323030391Skarels * 323130391Skarels * scroll_up()... move the screen up one character height 323230391Skarels * 323330391Skarels ******************************************************************** 323430391Skarels * 323530391Skarels * calling convention: 323630391Skarels * 323730391Skarels * scroll_up(adder); 323830391Skarels * struct adder *adder; ;address of adder 323930391Skarels * 324030391Skarels ********/ 324130391Skarels 324230391Skarels scroll_up(adder) 3243*34642Smarc register struct adder *adder; 324430391Skarels { 3245*34642Smarc /* 3246*34642Smarc * setup VIPER operand control registers 3247*34642Smarc */ 324830391Skarels wait_status(adder, ADDRESS_COMPLETE); 324930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 325030391Skarels write_ID(adder, MASK_1, 0xFFFF); 325130391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 325230391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 325330391Skarels write_ID(adder, SRC1_OCR_B, 3254*34642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 325530391Skarels write_ID(adder, DST_OCR_B, 3256*34642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 3257*34642Smarc /* 3258*34642Smarc * load DESTINATION origin and vectors 3259*34642Smarc */ 326030391Skarels adder->fast_dest_dy = 0; 326130391Skarels adder->slow_dest_dx = 0; 326230391Skarels adder->error_1 = 0; 326330391Skarels adder->error_2 = 0; 326430391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 326530391Skarels adder->destination_x = 0; 326630391Skarels adder->fast_dest_dx = 1024; 326730391Skarels adder->destination_y = 0; 326830391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 3269*34642Smarc /* 3270*34642Smarc * load SOURCE origin and vectors 3271*34642Smarc */ 327230391Skarels adder->source_1_x = 0; 327330391Skarels adder->source_1_dx = 1024; 327430391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 327530391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 327630391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 327730391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 3278*34642Smarc /* 3279*34642Smarc * do a rectangle clear of last screen line 3280*34642Smarc */ 328130391Skarels write_ID(adder, MASK_1, 0xffff); 328230391Skarels write_ID(adder, SOURCE, 0xffff); 328330391Skarels write_ID(adder,DST_OCR_B, 3284*34642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 328530391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 328630391Skarels adder->error_1 = 0; 328730391Skarels adder->error_2 = 0; 3288*34642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 328930391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 329030391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 329130391Skarels wait_status(adder, RASTEROP_COMPLETE); 329230391Skarels adder->destination_x = 0; 329330391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 329430391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 329530391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 329630391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 329730391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 329830391Skarels 329930391Skarels } /* scroll_up */ 330030391Skarels 330130391Skarels /******************************************************************** 330230391Skarels * 330330391Skarels * init_shared()... init shared memory pointers and structures 330430391Skarels * 330530391Skarels ********************************************************************* 330630391Skarels * 330730391Skarels * calling convention: 330830391Skarels * 330930391Skarels * init_shared(unit); 331030391Skarels * u_int unit; 331130391Skarels * 331230391Skarels ****************/ 331330391Skarels 331430391Skarels init_shared(unit) 3315*34642Smarc register u_int unit; 331630391Skarels { 331730391Skarels register struct dga *dga; 331830391Skarels 331930391Skarels dga = (struct dga *) qdmap[unit].dga; 332030391Skarels 3321*34642Smarc /* 3322*34642Smarc * initialize the event queue pointers and header */ 332330391Skarels 332430391Skarels eq_header[unit] = (struct qdinput *) 3325*34642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 3326*34642Smarc + (EVENT_BUFSIZE * unit)); 332730391Skarels eq_header[unit]->curs_pos.x = 0; 332830391Skarels eq_header[unit]->curs_pos.y = 0; 332930391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 333030391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 333130391Skarels eq_header[unit]->curs_box.left = 0; 333230391Skarels eq_header[unit]->curs_box.right = 0; 333330391Skarels eq_header[unit]->curs_box.top = 0; 333430391Skarels eq_header[unit]->curs_box.bottom = 0; 3335*34642Smarc /* 3336*34642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 3337*34642Smarc */ 333830391Skarels DMAheader[unit] = (struct DMAreq_header *) 3339*34642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 3340*34642Smarc + (DMAbuf_size * unit)); 334130391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 3342*34642Smarc + sizeof(struct DMAreq_header)); 334330391Skarels DMAheader[unit]->QBAreg = 0; 334430391Skarels DMAheader[unit]->status = 0; 334530391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 334630391Skarels DMAheader[unit]->used = 0; 334730391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 334830391Skarels DMAheader[unit]->oldest = 0; 334930391Skarels DMAheader[unit]->newest = 0; 3350*34642Smarc /* 3351*34642Smarc * assign a pointer to the scroll structure for this QDSS. 3352*34642Smarc */ 335330391Skarels scroll[unit] = (struct scroll *) 3354*34642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 3355*34642Smarc + (sizeof(struct scroll) * unit)); 335630391Skarels scroll[unit]->status = 0; 335730391Skarels scroll[unit]->viper_constant = 0; 335830391Skarels scroll[unit]->y_scroll_constant = 0; 335930391Skarels scroll[unit]->y_offset = 0; 336030391Skarels scroll[unit]->x_index_pending = 0; 336130391Skarels scroll[unit]->y_index_pending = 0; 3362*34642Smarc /* 3363*34642Smarc * assign a pointer to the color map write buffer for this QDSS 3364*34642Smarc */ 336530391Skarels color_buf[unit] = (struct color_buf *) 3366*34642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 3367*34642Smarc + (COLOR_BUFSIZ * unit)); 336830391Skarels color_buf[unit]->status = 0; 336930391Skarels color_buf[unit]->count = 0; 337030391Skarels 337130391Skarels } /* init_shared */ 337230391Skarels 337330391Skarels /********************************************************************* 337430391Skarels * 337530391Skarels * setup_dragon()... init the ADDER, VIPER, bitmaps, & color map 337630391Skarels * 337730391Skarels ********************************************************************** 337830391Skarels * 337930391Skarels * calling convention: 338030391Skarels * 338130391Skarels * setup_dragon(); 338230391Skarels * 338330391Skarels * return: NONE 338430391Skarels * 338530391Skarels ************************/ 338630391Skarels 338730391Skarels setup_dragon(unit) 3388*34642Smarc u_int unit; 338930391Skarels { 339030391Skarels 339130391Skarels register struct adder *adder; 339230391Skarels register struct dga *dga; 339330391Skarels short *memcsr; 339430391Skarels int i; /* general purpose variables */ 339530391Skarels int status; 339630391Skarels short top; /* clipping/scrolling boundaries */ 339730391Skarels short bottom; 339830391Skarels short right; 339930391Skarels short left; 340030391Skarels short *red; /* color map pointers */ 340130391Skarels short *green; 340230391Skarels short *blue; 340330391Skarels 3404*34642Smarc /* 3405*34642Smarc * init for setup 3406*34642Smarc */ 340730391Skarels adder = (struct adder *) qdmap[unit].adder; 340830391Skarels dga = (struct dga *) qdmap[unit].dga; 340930391Skarels memcsr = (short *) qdmap[unit].memcsr; 341030391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 341130391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 341230391Skarels adder->command = CANCEL; 3413*34642Smarc /* 3414*34642Smarc * set monitor timing 3415*34642Smarc */ 341630391Skarels adder->x_scan_count_0 = 0x2800; 341730391Skarels adder->x_scan_count_1 = 0x1020; 341830391Skarels adder->x_scan_count_2 = 0x003A; 341930391Skarels adder->x_scan_count_3 = 0x38F0; 342030391Skarels adder->x_scan_count_4 = 0x6128; 342130391Skarels adder->x_scan_count_5 = 0x093A; 342230391Skarels adder->x_scan_count_6 = 0x313C; 342330391Skarels adder->sync_phase_adj = 0x0100; 342430391Skarels adder->x_scan_conf = 0x00C8; 3425*34642Smarc /* 3426*34642Smarc * got a bug in secound pass ADDER! lets take care of it 3427*34642Smarc * 3428*34642Smarc * normally, just use the code in the following bug fix code, but to 3429*34642Smarc * make repeated demos look pretty, load the registers as if there was 3430*34642Smarc * no bug and then test to see if we are getting sync 3431*34642Smarc */ 343230391Skarels adder->y_scan_count_0 = 0x135F; 343330391Skarels adder->y_scan_count_1 = 0x3363; 343430391Skarels adder->y_scan_count_2 = 0x2366; 343530391Skarels adder->y_scan_count_3 = 0x0388; 3436*34642Smarc /* 3437*34642Smarc * if no sync, do the bug fix code 3438*34642Smarc */ 343930391Skarels if (wait_status(adder, VSYNC) == BAD) { 3440*34642Smarc /* first load all Y scan registers with very short frame and 3441*34642Smarc * wait for scroll service. This guarantees at least one SYNC 3442*34642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 3443*34642Smarc * XCINCH with DMSEEDH) 3444*34642Smarc */ 3445*34642Smarc adder->y_scan_count_0 = 0x01; 3446*34642Smarc adder->y_scan_count_1 = 0x01; 3447*34642Smarc adder->y_scan_count_2 = 0x01; 3448*34642Smarc adder->y_scan_count_3 = 0x01; 3449*34642Smarc /* 3450*34642Smarc * delay at least 1 full frame time 3451*34642Smarc */ 3452*34642Smarc wait_status(adder, VSYNC); 3453*34642Smarc wait_status(adder, VSYNC); 3454*34642Smarc /* 3455*34642Smarc * now load the REAL sync values (in reverse order just to 3456*34642Smarc * be safe. 3457*34642Smarc */ 3458*34642Smarc adder->y_scan_count_3 = 0x0388; 3459*34642Smarc adder->y_scan_count_2 = 0x2366; 3460*34642Smarc adder->y_scan_count_1 = 0x3363; 3461*34642Smarc adder->y_scan_count_0 = 0x135F; 346230391Skarels } 346330391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 3464*34642Smarc /* 3465*34642Smarc * zero the index registers 3466*34642Smarc */ 346730391Skarels adder->x_index_pending = 0; 346830391Skarels adder->y_index_pending = 0; 346930391Skarels adder->x_index_new = 0; 347030391Skarels adder->y_index_new = 0; 347130391Skarels adder->x_index_old = 0; 347230391Skarels adder->y_index_old = 0; 347330391Skarels adder->pause = 0; 3474*34642Smarc /* 3475*34642Smarc * set rasterop mode to normal pen down 3476*34642Smarc */ 347730391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 3478*34642Smarc /* 3479*34642Smarc * set the rasterop registers to a default values 3480*34642Smarc */ 348130391Skarels adder->source_1_dx = 1; 348230391Skarels adder->source_1_dy = 1; 348330391Skarels adder->source_1_x = 0; 348430391Skarels adder->source_1_y = 0; 348530391Skarels adder->destination_x = 0; 348630391Skarels adder->destination_y = 0; 348730391Skarels adder->fast_dest_dx = 1; 348830391Skarels adder->fast_dest_dy = 0; 348930391Skarels adder->slow_dest_dx = 0; 349030391Skarels adder->slow_dest_dy = 1; 349130391Skarels adder->error_1 = 0; 349230391Skarels adder->error_2 = 0; 3493*34642Smarc /* 3494*34642Smarc * scale factor = unity 3495*34642Smarc */ 349630391Skarels adder->fast_scale = UNITY; 349730391Skarels adder->slow_scale = UNITY; 3498*34642Smarc /* 3499*34642Smarc * set the source 2 parameters 3500*34642Smarc */ 350130391Skarels adder->source_2_x = 0; 350230391Skarels adder->source_2_y = 0; 350330391Skarels adder->source_2_size = 0x0022; 3504*34642Smarc /* 3505*34642Smarc * initialize plane addresses for eight vipers 3506*34642Smarc */ 350730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 350830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 350930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 351030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 351130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 351230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 351330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 351430391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 351530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 351630391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 351730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 351830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 351930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 352030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 352130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 352230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 3523*34642Smarc /* 3524*34642Smarc * initialize the external registers. 3525*34642Smarc */ 352630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 352730391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 3528*34642Smarc /* 3529*34642Smarc * initialize resolution mode 3530*34642Smarc */ 353130391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 353230391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 3533*34642Smarc /* 3534*34642Smarc * initialize viper registers 3535*34642Smarc */ 353630391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 353730391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 3538*34642Smarc /* 3539*34642Smarc * set clipping and scrolling limits to full screen 3540*34642Smarc */ 3541*34642Smarc for ( i = 1000, adder->status = 0 ; 3542*34642Smarc i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) ; --i) 3543*34642Smarc ; 354430391Skarels if (i == 0) 354534615Smarc printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit); 354630391Skarels top = 0; 354730391Skarels bottom = 2048; 354830391Skarels left = 0; 354930391Skarels right = 1024; 355030391Skarels adder->x_clip_min = left; 355130391Skarels adder->x_clip_max = right; 355230391Skarels adder->y_clip_min = top; 355330391Skarels adder->y_clip_max = bottom; 355430391Skarels adder->scroll_x_min = left; 355530391Skarels adder->scroll_x_max = right; 355630391Skarels adder->scroll_y_min = top; 355730391Skarels adder->scroll_y_max = bottom; 355830391Skarels wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 355930391Skarels wait_status(adder, VSYNC); 356030391Skarels adder->x_index_pending = left; 356130391Skarels adder->y_index_pending = top; 356230391Skarels adder->x_index_new = left; 356330391Skarels adder->y_index_new = top; 356430391Skarels adder->x_index_old = left; 356530391Skarels adder->y_index_old = top; 356630391Skarels 3567*34642Smarc for ( i = 1000, adder->status = 0 ; 3568*34642Smarc i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) ; 3569*34642Smarc --i) 3570*34642Smarc ; 357130391Skarels if (i == 0) 3572*34642Smarc printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit); 357330391Skarels 357430391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 357530391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 3576*34642Smarc /* 3577*34642Smarc * set source and the mask register to all ones (ie: white) o 3578*34642Smarc */ 357930391Skarels write_ID(adder, SOURCE, 0xFFFF); 358030391Skarels write_ID(adder, MASK_1, 0xFFFF); 358130391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 358230391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 3583*34642Smarc /* 3584*34642Smarc * initialize Operand Control Register banks for fill command 3585*34642Smarc */ 358630391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 358730391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 358830391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 358930391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 359030391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 359130391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 3592*34642Smarc /* 3593*34642Smarc * init Logic Unit Function registers, (these are just common values, 3594*34642Smarc * and may be changed as required). 3595*34642Smarc */ 359630391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 3597*34642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 3598*34642Smarc INV_M1_M2); 359930391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 360030391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 3601*34642Smarc /* 3602*34642Smarc * load the color map for black & white 3603*34642Smarc */ 3604*34642Smarc for ( i = 0, adder->status = 0; i < 10000 && 3605*34642Smarc !((status = adder->status) & VSYNC) ; ++i) 3606*34642Smarc ; 360730391Skarels 360830391Skarels if (i == 0) 360934615Smarc printf("\nqd%d: setup_dragon: timeout on VSYNC", unit); 361030391Skarels 361130391Skarels red = (short *) qdmap[unit].red; 361230391Skarels green = (short *) qdmap[unit].green; 361330391Skarels blue = (short *) qdmap[unit].blue; 361430391Skarels 361530391Skarels *red++ = 0x00; /* black */ 361630391Skarels *green++ = 0x00; 361730391Skarels *blue++ = 0x00; 361830391Skarels 361930391Skarels *red-- = 0xFF; /* white */ 362030391Skarels *green-- = 0xFF; 362130391Skarels *blue-- = 0xFF; 362230391Skarels 3623*34642Smarc /* 362430391Skarels * set color map for mouse cursor */ 362530391Skarels 362630391Skarels red += 254; 362730391Skarels green += 254; 362830391Skarels blue += 254; 362930391Skarels 363030391Skarels *red++ = 0x00; /* black */ 363130391Skarels *green++ = 0x00; 363230391Skarels *blue++ = 0x00; 363330391Skarels 363430391Skarels *red = 0xFF; /* white */ 363530391Skarels *green = 0xFF; 363630391Skarels *blue = 0xFF; 363730391Skarels 363830391Skarels return(0); 363930391Skarels 364030391Skarels } /* setup_dragon */ 364130391Skarels 364230391Skarels /****************************************************************** 364330391Skarels * 364430391Skarels * setup_input()... init the DUART and set defaults in input 364530391Skarels * devices 364630391Skarels * 364730391Skarels ******************************************************************* 364830391Skarels * 364930391Skarels * calling convention: 365030391Skarels * 365130391Skarels * setup_input(unit); 365230391Skarels * 365330391Skarels * where: unit - is the QDSS unit number to be setup 365430391Skarels * 365530391Skarels *********/ 365630391Skarels 365730391Skarels setup_input(unit) 365830391Skarels u_int unit; 365930391Skarels { 366030391Skarels register struct duart *duart; /* DUART register structure pointer */ 366130391Skarels register int i; /* scratch variable */ 366230391Skarels register int bits; 366330391Skarels char id_byte; 366430391Skarels short status; 366530391Skarels 366630391Skarels duart = (struct duart *) qdmap[unit].duart; 366730391Skarels duart->imask = 0; 366830391Skarels 3669*34642Smarc /* 3670*34642Smarc * setup the DUART for kbd & pointing device 3671*34642Smarc */ 367230391Skarels duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 367330391Skarels duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 3674*34642Smarc /* no RTS control,char error mode */ 367530391Skarels duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 3676*34642Smarc /* no RTS control,no echo or loop */ 367730391Skarels duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 367830391Skarels duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 3679*34642Smarc /* ..no RTS cntrl, char error mode */ 368030391Skarels duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 3681*34642Smarc /* no RTS control,no echo or loop */ 368230391Skarels 368330391Skarels duart->auxctl = 0x00; /* baud rate set 1 */ 368430391Skarels 368530391Skarels duart->clkselA = 0x99; /* 4800 baud for kbd */ 368630391Skarels duart->clkselB = 0x99; /* 4800 baud for mouse */ 368730391Skarels 368830391Skarels /* reset everything for keyboard */ 368930391Skarels 369030391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 3691*34642Smarc duart->cmdA = bits; 369230391Skarels 369330391Skarels /* reset everything for host */ 369430391Skarels 369530391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 3696*34642Smarc duart->cmdB = bits; 369730391Skarels 369830391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 369930391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 370030391Skarels 3701*34642Smarc /* 3702*34642Smarc * init keyboard defaults (DUART channel A) */ 370330391Skarels 370430391Skarels for (i = 500; i > 0; --i) { 3705*34642Smarc if ((status = duart->statusA) & XMT_RDY) { 3706*34642Smarc duart->dataA = LK_DEFAULTS; 3707*34642Smarc break; 3708*34642Smarc } 370930391Skarels } 371030391Skarels 371130391Skarels for (i = 100000; i > 0; --i) { 3712*34642Smarc if ((status = duart->statusA) & RCV_RDY) { 3713*34642Smarc break; 3714*34642Smarc } 371530391Skarels } 371630391Skarels 371730391Skarels status = duart->dataA; /* flush the ACK */ 371830391Skarels 3719*34642Smarc /* 3720*34642Smarc * identify the pointing device */ 372130391Skarels 372230391Skarels for (i = 500; i > 0; --i) { 3723*34642Smarc if ((status = duart->statusB) & XMT_RDY) { 3724*34642Smarc duart->dataB = SELF_TEST; 3725*34642Smarc break; 3726*34642Smarc } 372730391Skarels } 372830391Skarels 3729*34642Smarc /* 373030391Skarels * wait for 1st byte of self test report */ 373130391Skarels 373230391Skarels for (i = 100000; i > 0; --i) { 3733*34642Smarc if ((status = duart->statusB) & RCV_RDY) { 3734*34642Smarc break; 3735*34642Smarc } 373630391Skarels } 373730391Skarels 373830391Skarels if (i == 0) { 3739*34642Smarc printf("\nqd[%d]: setup_input: timeout on 1st byte of self test" 3740*34642Smarc ,unit); 3741*34642Smarc goto OUT; 374230391Skarels } 374330391Skarels 374430391Skarels status = duart->dataB; 374530391Skarels 3746*34642Smarc /* 374730391Skarels * wait for ID byte of self test report */ 374830391Skarels 374930391Skarels for (i = 100000; i > 0; --i) { 3750*34642Smarc if ((status = duart->statusB) & RCV_RDY) { 3751*34642Smarc break; 3752*34642Smarc } 375330391Skarels } 375430391Skarels 375530391Skarels if (i == 0) { 3756*34642Smarc printf("\nqd[%d]: setup_input: timeout on 2nd byte of self test", unit); 3757*34642Smarc goto OUT; 375830391Skarels } 375930391Skarels 376030391Skarels id_byte = duart->dataB; 376130391Skarels 3762*34642Smarc /* 376330391Skarels * wait for other bytes to come in */ 376430391Skarels 376530391Skarels for (i = 100000; i > 0; --i) { 3766*34642Smarc if ((status = duart->statusB) & RCV_RDY) { 3767*34642Smarc status = duart->dataB; 3768*34642Smarc break; 3769*34642Smarc } 377030391Skarels } 377130391Skarels 377230391Skarels if (i == 0) { 3773*34642Smarc printf("\nqd[%d]: setup_input: timeout on 3rd byte of self test", unit); 3774*34642Smarc goto OUT; 377530391Skarels } 377630391Skarels 377730391Skarels for (i = 100000; i > 0; --i) { 3778*34642Smarc if ((status = duart->statusB) & RCV_RDY) { 3779*34642Smarc status = duart->dataB; 3780*34642Smarc break; 3781*34642Smarc } 378230391Skarels } 378330391Skarels 378430391Skarels if (i == 0) { 3785*34642Smarc printf("\nqd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 3786*34642Smarc goto OUT; 378730391Skarels } 378830391Skarels 3789*34642Smarc /* 379030391Skarels * flag pointing device type and set defaults */ 379130391Skarels 379230391Skarels for (i=100000; i>0; --i); 379330391Skarels 379430391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 379530391Skarels 3796*34642Smarc qdflags[unit].pntr_id = MOUSE_ID; 379730391Skarels 3798*34642Smarc for (i = 500; i > 0; --i) { 3799*34642Smarc if ((status = duart->statusB) & XMT_RDY) { 3800*34642Smarc duart->dataB = INC_STREAM_MODE; 3801*34642Smarc break; 3802*34642Smarc } 380330391Skarels } 3804*34642Smarc } 3805*34642Smarc else { 380630391Skarels 3807*34642Smarc qdflags[unit].pntr_id = TABLET_ID; 380830391Skarels 3809*34642Smarc for (i = 500; i > 0; --i) { 3810*34642Smarc if ((status = duart->statusB) & XMT_RDY) { 3811*34642Smarc duart->dataB = T_STREAM; 3812*34642Smarc break; 3813*34642Smarc } 381430391Skarels } 381530391Skarels } 381630391Skarels 3817*34642Smarc /* 3818*34642Smarc * exit */ 381930391Skarels 382030391Skarels OUT: 382130391Skarels duart->imask = qdflags[unit].duart_imask; 382230391Skarels return(0); 382330391Skarels 382430391Skarels } /* setup_input */ 382530391Skarels 382630391Skarels /********************************************************************** 382730391Skarels * 382830391Skarels * wait_status()... delay for at least one display frame time 382930391Skarels * 383030391Skarels *********************************************************************** 383130391Skarels * 383230391Skarels * calling convention: 383330391Skarels * 383430391Skarels * wait_status(adder, mask); 383530391Skarels * struct *adder adder; 383630391Skarels * int mask; 383730391Skarels * 383830391Skarels * return: BAD means that we timed out without ever seeing the 383930391Skarels * vertical sync status bit 384030391Skarels * GOOD otherwise 384130391Skarels * 384230391Skarels **************/ 384330391Skarels 384430391Skarels wait_status(adder, mask) 3845*34642Smarc register struct adder *adder; 3846*34642Smarc register int mask; 384730391Skarels { 384830391Skarels register short status; 384930391Skarels int i; 385030391Skarels 3851*34642Smarc for ( i = 10000, adder->status = 0 ; i > 0 && 3852*34642Smarc !((status = adder->status) & mask) ; --i) 3853*34642Smarc ; 385430391Skarels 385530391Skarels if (i == 0) { 3856*34642Smarc printf("\nwait_status: timeout polling for 0x%x in adder->status", mask); 3857*34642Smarc return(BAD); 385830391Skarels } 385930391Skarels 386030391Skarels return(GOOD); 386130391Skarels 386230391Skarels } /* wait_status */ 386330391Skarels 386430391Skarels /********************************************************************** 386530391Skarels * 386630391Skarels * write_ID()... write out onto the ID bus 386730391Skarels * 386830391Skarels *********************************************************************** 386930391Skarels * 387030391Skarels * calling convention: 387130391Skarels * 387230391Skarels * struct *adder adder; ;pntr to ADDER structure 387330391Skarels * short adrs; ;VIPER address 387430391Skarels * short data; ;data to be written 387530391Skarels * write_ID(adder); 387630391Skarels * 387730391Skarels * return: BAD means that we timed out waiting for status bits 387830391Skarels * VIPER-access-specific status bits 387930391Skarels * GOOD otherwise 388030391Skarels * 388130391Skarels **************/ 388230391Skarels 388330391Skarels write_ID(adder, adrs, data) 3884*34642Smarc register struct adder *adder; 3885*34642Smarc register short adrs; 3886*34642Smarc register short data; 388730391Skarels { 388830391Skarels int i; 388930391Skarels short status; 389030391Skarels 3891*34642Smarc for ( i = 100000, adder->status = 0 ; 3892*34642Smarc i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) ; 3893*34642Smarc --i) 3894*34642Smarc ; 389530391Skarels 389630391Skarels if (i == 0) 389730391Skarels goto ERR; 389830391Skarels 3899*34642Smarc for ( i = 100000, adder->status = 0 ; 3900*34642Smarc i > 0 && !((status = adder->status) & TX_READY) ; --i) 3901*34642Smarc ; 390230391Skarels 390330391Skarels if (i > 0) { 3904*34642Smarc adder->id_data = data; 3905*34642Smarc adder->command = ID_LOAD | adrs; 3906*34642Smarc return(GOOD); 390730391Skarels } 390830391Skarels 390930391Skarels ERR: 391034615Smarc printf("\nwrite_ID: timeout trying to write to VIPER"); 391130391Skarels return(BAD); 391230391Skarels 391330391Skarels } /* write_ID */ 391434511Smarc #endif 3915