134511Smarc /* 234642Smarc * Copyright (c) 1982, 1986 Regents of the University of California. 334642Smarc * All rights reserved. The Berkeley software License Agreement 434642Smarc * specifies the terms and conditions for redistribution. 534642Smarc * 6*34732Smarc * @(#)qd.c 1.9 Berkeley 06/14/88 734642Smarc * 834642Smarc */ 934642Smarc 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 /* 3334642Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation 3430391Skarels */ 3530391Skarels 3634642Smarc #include "qd.h" 3734615Smarc 3834511Smarc #if NQD > 0 3934615Smarc #include "types.h" 4034642Smarc #include "../machine/pte.h" 4134642Smarc #include "../machine/mtpr.h" 4234511Smarc #include "../machine/cpu.h" 4334642Smarc #include "param.h" 4434642Smarc #include "conf.h" 4534642Smarc #include "dir.h" 4634642Smarc #include "user.h" 4734642Smarc #include "qdioctl.h" 4834511Smarc #include "tty.h" 4934642Smarc #include "map.h" 5034642Smarc #include "buf.h" 5134642Smarc #include "vm.h" 5234642Smarc #include "bk.h" 5334642Smarc #include "clist.h" 5434642Smarc #include "file.h" 5534642Smarc #include "uio.h" 5634642Smarc #include "kernel.h" 5734615Smarc #include "exec.h" 5834615Smarc #include "proc.h" 5934642Smarc #include "ubareg.h" 6034642Smarc #include "ubavar.h" 6134511Smarc #include "syslog.h" 6234642Smarc #include "qduser.h" /* definitions shared with user level client */ 6334615Smarc #include "qdreg.h" /* QDSS device register structures */ 6432012Smarc 6534642Smarc /* 6634642Smarc * QDSS driver status flags for tracking operational state 6734642Smarc */ 6834642Smarc struct qdflags { 6934642Smarc u_int inuse; /* which minor dev's are in use now */ 7034642Smarc u_int config; /* I/O page register content */ 7134642Smarc u_int mapped; /* user mapping status word */ 7234642Smarc u_int kernel_loop; /* if kernel console is redirected */ 7334642Smarc u_int user_dma; /* DMA from user space in progress */ 7434642Smarc u_short pntr_id; /* type code of pointing device */ 7534642Smarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 7634642Smarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 7734642Smarc u_short curs_acc; /* cursor acceleration factor */ 7834642Smarc u_short curs_thr; /* cursor acceleration threshold level */ 7934642Smarc u_short tab_res; /* tablet resolution factor */ 8034642Smarc u_short selmask; /* mask for active qd select entries */ 8134642Smarc }; 8232012Smarc 8334642Smarc /* 8434642Smarc * bit definitions for 'inuse' entry 8534642Smarc */ 8632012Smarc #define CONS_DEV 0x01 8732012Smarc #define GRAPHIC_DEV 0x04 8832012Smarc 8934642Smarc /* 9034642Smarc * bit definitions for 'mapped' member of flag structure 9134642Smarc */ 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 9834642Smarc /* 9934642Smarc * bit definitions for 'selmask' member of qdflag structure 10034642Smarc */ 10132012Smarc #define SEL_READ 0x01 /* read select is active */ 10232012Smarc #define SEL_WRITE 0x02 /* write select is active */ 10332012Smarc 10434642Smarc /* 105*34732Smarc * constants used in shared memory operations 106*34732Smarc */ 10732012Smarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 10832012Smarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 10934642Smarc / sizeof(struct _vs_event) ) 11034527Smarc #define DMA_BUFSIZ (1024 * 10) 11132012Smarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 11232012Smarc 11334642Smarc /* 114*34732Smarc * reference to an array of "uba_device" structures built by the auto 115*34732Smarc * configuration program. The uba_device structure decribes the device 116*34732Smarc * sufficiently for the driver to talk to it. The auto configuration code 117*34732Smarc * fills in the uba_device structures (located in ioconf.c) from user 118*34732Smarc * maintained info. 119*34732Smarc */ 12034642Smarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 12134642Smarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 122*34732Smarc extern char qvmem[][128*NBPG]; 12334642Smarc extern struct pte QVmap[][128]; 12434642Smarc #define CHUNK (64 * 1024) 12534642Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 12632012Smarc 12734642Smarc /* 12834642Smarc * static storage used by multiple functions in this code 12934642Smarc */ 13034642Smarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 13134642Smarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 13234642Smarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 13334642Smarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 13434642Smarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 13534642Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 13632012Smarc 13734642Smarc /* 138*34732Smarc * the array "event_shared[]" is made up of a number of event queue buffers 139*34732Smarc * equal to the number of QDSS's configured into the running kernel (NQD). 140*34732Smarc * Each event queue buffer begins with an event queue header (struct qdinput) 141*34732Smarc * followed by a group of event queue entries (struct _vs_event). The array 142*34732Smarc * "*eq_header[]" is an array of pointers to the start of each event queue 143*34732Smarc * buffer in "event_shared[]". 144*34732Smarc */ 14532012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 14632012Smarc 14734642Smarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 14834642Smarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 14932012Smarc 15034642Smarc /* 151*34732Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 152*34732Smarc * buffers. Each buffer must consume an integral number of memory pages to 153*34732Smarc * guarantee that a following buffer will begin on a page boundary. Also, 154*34732Smarc * enough space is allocated so that the FIRST I/O buffer can start at the 155*34732Smarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 156*34732Smarc * memory protections can be turned on/off for individual buffers. 157*34732Smarc */ 15832012Smarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 15932012Smarc 16034642Smarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 16134642Smarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 16232012Smarc 16334642Smarc /* 164*34732Smarc * The driver assists a client in scroll operations by loading dragon 165*34732Smarc * registers from an interrupt service routine. The loading is done using 166*34732Smarc * parameters found in memory shrade between the driver and it's client. 167*34732Smarc * The scroll parameter structures are ALL loacted in the same memory page 168*34732Smarc * for reasons of memory economy. 169*34732Smarc */ 17034642Smarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 17134642Smarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 17232012Smarc 17334642Smarc /* 174*34732Smarc * the driver is programmable to provide the user with color map write 175*34732Smarc * services at VSYNC interrupt time. At interrupt time the driver loads 176*34732Smarc * the color map with any user-requested load data found in shared memory 177*34732Smarc */ 17832012Smarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 17932012Smarc 18034642Smarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 18134642Smarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 18232012Smarc 18334642Smarc /* 184*34732Smarc * mouse input event structures 185*34732Smarc */ 18634642Smarc struct mouse_report last_rep[NQD]; 18734642Smarc struct mouse_report current_rep[NQD]; 18832012Smarc 189*34732Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 19034642Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 19134642Smarc int qdcount = 0; /* count of successfully probed qd's */ 19234642Smarc int nNQD = NQD; 19334642Smarc int DMAbuf_size = DMA_BUFSIZ; 19434642Smarc int QDlast_DMAtype; /* type of the last DMA operation */ 19532012Smarc 19634642Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 19734642Smarc /* 198*34732Smarc * macro to get system time. Used to time stamp event queue entries 199*34732Smarc */ 20030391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 20130391Skarels 20234642Smarc int qdprobe(); 20334642Smarc int qdattach(); 20434642Smarc int qddint(); /* DMA gate array intrpt service */ 20534642Smarc int qdaint(); /* Dragon ADDER intrpt service */ 20634642Smarc int qdiint(); 20730391Skarels 20834642Smarc u_short qdstd[] = { 0 }; 20930391Skarels 21034642Smarc struct uba_driver qddriver = { 211*34732Smarc qdprobe, /* device probe entry */ 212*34732Smarc 0, /* no slave device */ 213*34732Smarc qdattach, /* device attach entry */ 214*34732Smarc 0, /* no "fill csr/ba to start" */ 21534642Smarc qdstd, /* device addresses */ 21634642Smarc "qd", /* device name string */ 21734642Smarc qdinfo /* ptr to QDSS's uba_device struct */ 21834642Smarc }; 21930391Skarels 22034615Smarc #define QDPRIOR (PZERO-1) /* must be negative */ 22130391Skarels #define FALSE 0 22230391Skarels #define TRUE ~FALSE 22330391Skarels #define BAD -1 22430391Skarels #define GOOD 0 22530391Skarels 22634642Smarc /* 22734642Smarc * macro to create a system virtual page number from system virtual adrs 22834642Smarc */ 22934642Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 23030391Skarels 23134642Smarc /* 23234642Smarc * QDSS register address offsets from start of QDSS address space 23334642Smarc */ 23430391Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 23530391Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 23630391Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 23730391Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 23830391Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 23930391Skarels #define ADDER (REGSTART+0x000) 24030391Skarels #define DGA (REGSTART+0x200) 24130391Skarels #define DUART (REGSTART+0x400) 24230391Skarels #define MEMCSR (REGSTART+0x800) 24330391Skarels #define CLRSIZE (3 * 512) /* color map size */ 24430391Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 24534642Smarc /* 0x0C00 really */ 24630391Skarels #define RED (CLRSTART+0x000) 24730391Skarels #define BLUE (CLRSTART+0x200) 24830391Skarels #define GREEN (CLRSTART+0x400) 24930391Skarels 25030391Skarels 25134642Smarc /* 25234642Smarc * QDSS minor device numbers. The *real* minor device numbers are in 25334642Smarc * the bottom two bits of the major/minor device spec. Bits 2 and up are 25434642Smarc * used to specify the QDSS device number (ie: which one?) 25534642Smarc */ 25630391Skarels 25730391Skarels #define CONS 0 25830391Skarels #define GRAPHIC 2 25930391Skarels 26034642Smarc /* 26134642Smarc * console cursor bitmap (white block cursor) 26234642Smarc */ 26334642Smarc short cons_cursor[32] = { 26434642Smarc /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 26534642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 26634642Smarc /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 26734642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 26834642Smarc }; 26930391Skarels 27034642Smarc /* 27134642Smarc * constants used in font operations 27234642Smarc */ 27334615Smarc #define CHARS 190 /* # of chars in the font */ 27430391Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 27530391Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 27630391Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 27730391Skarels #define ROWS CHAR_HEIGHT 27830391Skarels #define FONT_X 0 /* font's off screen adrs */ 27930391Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 28030391Skarels 28134642Smarc /* Offset to second row characters (XXX - should remove) */ 28234615Smarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 28330391Skarels 28434642Smarc extern char q_font[]; /* reference font object code */ 28534642Smarc extern u_short q_key[]; /* reference key xlation tables */ 28634642Smarc extern u_short q_shift_key[]; 28734642Smarc extern char *q_special[]; 28830391Skarels 28934642Smarc /* 29034642Smarc * definitions for cursor acceleration reporting 29134642Smarc */ 29230391Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 29330391Skarels 29434642Smarc /* 29534642Smarc * virtual console support. 29634642Smarc */ 29734642Smarc extern (*v_putc)(); 29834642Smarc extern struct cdevsw *consops; 29934642Smarc int qdputc(); 30034642Smarc int qdstart(); 30130391Skarels 30234642Smarc /* 30334642Smarc * LK-201 state storage for input console keyboard conversion to ASCII 30434642Smarc */ 30534642Smarc struct q_keyboard { 30634642Smarc int shift; /* state variables */ 30734642Smarc int cntrl; 30834642Smarc int lock; 30934642Smarc int lastcode; /* last keycode typed */ 31034642Smarc unsigned kup[8]; /* bits for each keycode*/ 31134642Smarc unsigned dkeys[8]; /* down/up mode keys */ 31234642Smarc char last; /* last character */ 31334642Smarc } q_keyboard; 31430391Skarels 31534642Smarc /* 31634642Smarc * tty settings on first open 31734642Smarc */ 31834615Smarc #define IFLAGS (EVENP|ECHO|XTABS|CRMOD) 31934615Smarc #ifdef POSIXTTY 32034615Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL) 32134615Smarc #define OFLAG (OPOST|OXTABS|ONLCR) 32234615Smarc #define LFLAG (ISIG|ICANON|ECHO) 32334615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 32434615Smarc #endif 32534615Smarc 326*34732Smarc /* 327*34732Smarc * Init QDSS as console (before probe routine) 328*34732Smarc */ 32930391Skarels 33030391Skarels qdcons_init() 33130391Skarels { 332*34732Smarc register unit; 33330391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 33434615Smarc u_int mapix; /* index into QVmap[] array */ 33534615Smarc struct percpu *pcpu; /* pointer to cpusw structure */ 33634615Smarc register struct qbus *qb; 33730391Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 33830391Skarels u_short *devptr; /* vitual device space */ 33934615Smarc extern cnputc(); 34030391Skarels 34130391Skarels #define QDSSCSR 0x1F00 34230391Skarels 34332012Smarc if (v_putc != cnputc) 344*34732Smarc return 0; 34532012Smarc 34630391Skarels unit = 0; 34730391Skarels 34834642Smarc /* 34934642Smarc * find the cpusw entry that matches this machine. 35034642Smarc */ 35132012Smarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 35232012Smarc ; 35332012Smarc if (pcpu == NULL) 354*34732Smarc return 0; 35530391Skarels 35632012Smarc /* 35734615Smarc * Map device registers - the last 8K of qvmem. 35832012Smarc */ 35932012Smarc qb = (struct qbus *)pcpu->pc_io->io_details; 36032012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 361*34732Smarc UBAIOPAGES * NBPG); 36232012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 36330391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 364*34732Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 365*34732Smarc return 0; 36634615Smarc 36732012Smarc /* 36832012Smarc * Map q-bus memory used by qdss. (separate map) 36932012Smarc */ 37032012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 37132012Smarc phys_adr = qb->qb_maddr + mapix; 37232012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 37330391Skarels 37432012Smarc /* 37532012Smarc * tell QDSS which Q memory address base to decode 37634642Smarc * (shifted right 16 bits - its in 64K units) 37732012Smarc */ 37832012Smarc *qdaddr = (u_short)((int)mapix >> 16); 37930391Skarels qdflags[unit].config = *(u_short *)qdaddr; 38030391Skarels 38134642Smarc /* 38234642Smarc * load qdmap struct with the virtual addresses of the QDSS elements 38334642Smarc */ 38434615Smarc qdbase[unit] = (caddr_t) (qvmem[0]); 38530391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 38630391Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 38730391Skarels qdmap[unit].dga = qdbase[unit] + DGA; 38830391Skarels qdmap[unit].duart = qdbase[unit] + DUART; 38930391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 39030391Skarels qdmap[unit].red = qdbase[unit] + RED; 39130391Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 39230391Skarels qdmap[unit].green = qdbase[unit] + GREEN; 39330391Skarels 39430391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 39530391Skarels 39634642Smarc /* 39734642Smarc * init the QDSS 39834642Smarc */ 39934642Smarc /* 40032012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 40134642Smarc (char *)qdbase[0], qdmap[0].memcsr); 40234642Smarc */ 40332012Smarc 40430391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 40530391Skarels 40630391Skarels cursor[unit].x = 0; 40730391Skarels cursor[unit].y = 0; 40830391Skarels init_shared(unit); /* init shared memory */ 40930391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 41030391Skarels clear_qd_screen(unit); /* clear the screen */ 41130391Skarels ldfont(unit); /* load the console font */ 41230391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 41330391Skarels setup_input(unit); /* init the DUART */ 41434642Smarc v_putc = qdputc; /* kernel console output to qdss */ 41534642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 416*34732Smarc return 1; 41730391Skarels 41830391Skarels } /* qdcons_init */ 41930391Skarels 420*34732Smarc /* 421*34732Smarc * Configure QDSS into Q memory and make it intrpt. 422*34732Smarc * 423*34732Smarc * side effects: QDSS gets mapped into Qbus memory space at the first 424*34732Smarc * vacant 64kb boundary counting back from the top of 425*34732Smarc * Qbus memory space (qvmem+4mb) 426*34732Smarc * 427*34732Smarc * return: QDSS bus request level and vector address returned in 428*34732Smarc * registers by UNIX convention. 429*34732Smarc * 430*34732Smarc */ 43130391Skarels qdprobe(reg) 432*34732Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 43330391Skarels { 43434642Smarc register int br, cvec; /* value-result */ 43530391Skarels register int unit; 43630391Skarels struct dga *dga; /* pointer to gate array structure */ 437*34732Smarc int vector; 438*34732Smarc #ifdef notdef 43930391Skarels int *ptep; /* page table entry pointer */ 44030391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 44130391Skarels u_int mapix; 442*34732Smarc #endif 44330391Skarels 444*34732Smarc #ifdef lint 445*34732Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 446*34732Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 447*34732Smarc #endif 448*34732Smarc 44934642Smarc /* 45034642Smarc * calculate board unit number from I/O page register address 45134642Smarc */ 45230391Skarels unit = (int) (((int)reg >> 1) & 0x0007); 45330391Skarels 45434642Smarc /* 45534642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 45634642Smarc * physical boundary. The Qbus memory space is mapped into 45734642Smarc * the system memory space at config time. After config 45834642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 45934642Smarc * of the start of Qbus memory. The Qbus memory page table 46034642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 46134642Smarc * which is also loaded at config time. These are the 46234642Smarc * variables used below to find a vacant 64kb boundary in 46334642Smarc * Qbus memory, and load it's corresponding physical adrs 46434642Smarc * into the QDSS's I/O page CSR. 46534642Smarc */ 46630391Skarels 46734615Smarc /* 46834615Smarc * Only if QD is the graphics device. 46934615Smarc */ 47034615Smarc 47130391Skarels /* if this QDSS is NOT the console, then do init here.. */ 47230391Skarels 47334615Smarc if (unit != 0) { 47434615Smarc printf("qd: can't support two qdss's (yet)\n"); 475*34732Smarc #ifdef notdef /* can't test */ 47634642Smarc if (v_consputc != qdputc || unit != 0) { 47730391Skarels 47834642Smarc /* 47934642Smarc * read QDSS config info 48034642Smarc */ 48134642Smarc qdflags[unit].config = *(u_short *)reg; 48234615Smarc 48334642Smarc /* 48434642Smarc * find an empty 64kb adrs boundary 48534642Smarc */ 48630391Skarels 48734642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 48830391Skarels 48934642Smarc /* 490*34732Smarc * find the cpusw entry that matches this machine. 491*34732Smarc */ 49234642Smarc cpup = &cpusw[cpu]; 493*34732Smarc while (!(BADADDR(qdbase[unit], sizeof(short)))) 494*34732Smarc qdbase[unit] -= CHUNK; 49534615Smarc 49634642Smarc /* 497*34732Smarc * tell QDSS which Q memory address base to decode 498*34732Smarc */ 49934642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 50034642Smarc ptep = (int *) QVmap[0] + mapix; 50134642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 50234642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 50334615Smarc 50434642Smarc /* 50534642Smarc * load QDSS adrs map with system addresses 50634642Smarc * of device regs 50734642Smarc */ 50834642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART; 50934642Smarc qdmap[unit].adder = qdbase[unit] + ADDER; 51034642Smarc qdmap[unit].dga = qdbase[unit] + DGA; 51134642Smarc qdmap[unit].duart = qdbase[unit] + DUART; 51234642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 51334642Smarc qdmap[unit].red = qdbase[unit] + RED; 51434642Smarc qdmap[unit].blue = qdbase[unit] + BLUE; 51534642Smarc qdmap[unit].green = qdbase[unit] + GREEN; 51630391Skarels 51734642Smarc /* device init */ 51834615Smarc 51934642Smarc cursor[unit].x = 0; 52034642Smarc cursor[unit].y = 0; 52134642Smarc init_shared(unit); /* init shared memory */ 52234642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */ 52334642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */ 52434642Smarc setup_input(unit); /* init the DUART */ 52534642Smarc clear_qd_screen(unit); 52634642Smarc ldfont(unit); /* load the console font */ 52730391Skarels 52834642Smarc /* once only: turn on sync */ 52930391Skarels 53034642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON; 53134642Smarc } 53234615Smarc #endif /*notdef*/ 53330391Skarels } 53430391Skarels 53534642Smarc /* 53634642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 53734642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 53834642Smarc * vectors from the vector pool, and then continue 53934642Smarc * to take them until we get a xx0 HEX vector. The 54034642Smarc * pool provides vectors in contiguous decending 54134642Smarc * order. 54234642Smarc */ 54330391Skarels 54430391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 54530391Skarels 54634642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */ 54734642Smarc /* ..take another vector */ 54834642Smarc vector = (uba_hd[0].uh_lastiv -= 4); 54930391Skarels } 55030391Skarels 55134642Smarc /* 55234642Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 55334642Smarc */ 55430391Skarels dga = (struct dga *) qdmap[unit].dga; 55534642Smarc dga->csr = (short) HALT; /* disable everything */ 55634642Smarc dga->ivr = (short) vector; /* load intrpt base vector */ 55734642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 55830391Skarels dga->bytcnt_hi = (short) 0; 55930391Skarels 56034642Smarc /* 56134642Smarc * turn on DMA interrupts 56234642Smarc */ 56330391Skarels dga->csr &= ~SET_DONE_FIFO; 56430391Skarels dga->csr |= DMA_IE | DL_ENB; 56530391Skarels 56630391Skarels DELAY(20000); /* wait for the intrpt */ 56730391Skarels dga->csr = HALT; /* stop the wheels */ 56830391Skarels 56930391Skarels if (cvec != vector) /* if vector != base vector.. */ 570*34732Smarc return(0); /* ..return = 'no device' */ 57130391Skarels 57234615Smarc /* 57334642Smarc * score this as an existing qdss 57434642Smarc */ 57534615Smarc qdcount++; 57634615Smarc 57730391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 57830391Skarels 57930391Skarels } /* qdprobe */ 58030391Skarels 58130391Skarels qdattach(ui) 58234642Smarc struct uba_device *ui; 58330391Skarels { 584*34732Smarc register unit; /* QDSS module # for this call */ 58530391Skarels 58630391Skarels unit = ui->ui_unit; /* get QDSS number */ 58730391Skarels 58834642Smarc /* 58934642Smarc * init "qdflags[]" for this QDSS 59034642Smarc */ 59130391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 59230391Skarels qdflags[unit].mapped = 0; 59334615Smarc qdflags[unit].kernel_loop = -1; 59430391Skarels qdflags[unit].user_dma = 0; 59530391Skarels qdflags[unit].curs_acc = ACC_OFF; 59630391Skarels qdflags[unit].curs_thr = 128; 59730391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 59830391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 59930391Skarels qdflags[unit].adder_ie = 0; 60030391Skarels 60134642Smarc /* 60234642Smarc * init structures used in kbd/mouse interrupt service. This code must 60334642Smarc * come after the "init_shared()" routine has run since that routine 60434642Smarc * inits the eq_header[unit] structure used here. 60534642Smarc */ 60630391Skarels 60734642Smarc /* 60834642Smarc * init the "latest mouse report" structure 60934642Smarc */ 61030391Skarels last_rep[unit].state = 0; 61130391Skarels last_rep[unit].dx = 0; 61230391Skarels last_rep[unit].dy = 0; 61330391Skarels last_rep[unit].bytcnt = 0; 61430391Skarels 61534642Smarc /* 616*34732Smarc * init the event queue (except mouse position) 617*34732Smarc */ 618*34732Smarc eq_header[unit]->header.events = 619*34732Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 62030391Skarels 62130391Skarels eq_header[unit]->header.size = MAXEVENTS; 62230391Skarels eq_header[unit]->header.head = 0; 62330391Skarels eq_header[unit]->header.tail = 0; 62430391Skarels 62534642Smarc /* 62634642Smarc * open exclusive for graphics device. 62734642Smarc */ 62834642Smarc qdopened[unit] = 0; 62930391Skarels 63030391Skarels } /* qdattach */ 63130391Skarels 632*34732Smarc /*ARGSUSED*/ 63330391Skarels qdopen(dev, flag) 63434642Smarc dev_t dev; 63534642Smarc int flag; 63630391Skarels { 63730391Skarels register struct uba_device *ui; /* ptr to uba structures */ 63830391Skarels register struct dga *dga; /* ptr to gate array struct */ 63930391Skarels register struct tty *tp; 64030391Skarels struct duart *duart; 641*34732Smarc int unit; 642*34732Smarc int minor_dev; 64330391Skarels 64430391Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 64530391Skarels unit = minor_dev >> 2; 64630391Skarels 64734642Smarc /* 64834642Smarc * check for illegal conditions 64934642Smarc */ 65030391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 65130391Skarels if (ui == 0 || ui->ui_alive == 0) 65234642Smarc return(ENXIO); /* no such device or address */ 65330391Skarels 65430391Skarels duart = (struct duart *) qdmap[unit].duart; 65530391Skarels dga = (struct dga *) qdmap[unit].dga; 65630391Skarels 65730391Skarels if ((minor_dev & 0x03) == 2) { 65834642Smarc /* 65934642Smarc * this is the graphic device... 66034642Smarc */ 66134642Smarc if (qdopened[unit] != 0) 662*34732Smarc return(EBUSY); 66334642Smarc else 66434642Smarc qdopened[unit] = 1; 66534642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 66634642Smarc /* 66734642Smarc * enble kbd & mouse intrpts in DUART mask reg 66834642Smarc */ 66934642Smarc qdflags[unit].duart_imask |= 0x22; 67034642Smarc duart->imask = qdflags[unit].duart_imask; 67134642Smarc } else { 67234642Smarc /* 67334642Smarc * this is the console 67434642Smarc */ 67534642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 67634642Smarc dga->csr |= CURS_ENB; 67734642Smarc qdflags[unit].duart_imask |= 0x02; 67834642Smarc duart->imask = qdflags[unit].duart_imask; 67934642Smarc /* 68034642Smarc * some setup for tty handling 68134642Smarc */ 68234642Smarc tp = &qd_tty[minor_dev]; 68334642Smarc tp->t_addr = ui->ui_addr; 68434642Smarc tp->t_oproc = qdstart; 68534642Smarc if ((tp->t_state & TS_ISOPEN) == 0) { 68634642Smarc ttychars(tp); 68734642Smarc tp->t_flags = IFLAGS; 68834642Smarc tp->t_ispeed = B9600; 68934642Smarc tp->t_ospeed = B9600; 69034642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 69134642Smarc #ifdef POSIXTTY 69234642Smarc tp->t_iflag = TTYDEF_IFLAG; 69334642Smarc tp->t_oflag = TTYDEF_OFLAG; 69434642Smarc tp->t_lflag = TTYDEF_LFLAG; 69534642Smarc tp->t_cflag = TTYDEF_CFLAG; 69634642Smarc #endif 69732012Smarc } 69834642Smarc /* 69934642Smarc * enable intrpts, open line discipline 70034642Smarc */ 70134642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 70234642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp)); 70330391Skarels } 70430391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 70530391Skarels return(0); 70630391Skarels 70730391Skarels } /* qdopen */ 70830391Skarels 709*34732Smarc /*ARGSUSED*/ 71030391Skarels qdclose(dev, flag) 71134642Smarc dev_t dev; 71234642Smarc int flag; 71330391Skarels { 71430391Skarels register struct tty *tp; 71530391Skarels register struct qdmap *qd; 71630391Skarels register int *ptep; 71730391Skarels struct dga *dga; /* gate array register map pointer */ 71830391Skarels struct duart *duart; 71930391Skarels struct adder *adder; 720*34732Smarc int unit; 721*34732Smarc int minor_dev; 72230391Skarels u_int mapix; 72334642Smarc int i; /* SIGNED index */ 72430391Skarels 72530391Skarels minor_dev = minor(dev); /* get minor device number */ 72630391Skarels unit = minor_dev >> 2; /* get QDSS number */ 72730391Skarels qd = &qdmap[unit]; 72830391Skarels 72930391Skarels if ((minor_dev & 0x03) == 2) { 73034642Smarc /* 73134642Smarc * this is the graphic device... 73234642Smarc */ 73334642Smarc if (qdopened[unit] != 1) 734*34732Smarc return(EBUSY); 73534642Smarc else 73634642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 73734642Smarc /* 73834642Smarc * re-protect device memory 73934642Smarc */ 74034642Smarc if (qdflags[unit].mapped & MAPDEV) { 74134642Smarc /* 74234642Smarc * TEMPLATE RAM 74334642Smarc */ 74434642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 74534642Smarc ptep = (int *)(QVmap[0] + mapix); 746*34732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 747*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 74834642Smarc /* 74934642Smarc * ADDER 75034642Smarc */ 75134642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 75234642Smarc ptep = (int *)(QVmap[0] + mapix); 753*34732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 754*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 75534642Smarc /* 75634642Smarc * COLOR MAPS 75734642Smarc */ 75834642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 75934642Smarc ptep = (int *)(QVmap[0] + mapix); 760*34732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 761*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76234642Smarc } 76334615Smarc 76434642Smarc /* 76534642Smarc * re-protect DMA buffer and free the map registers 76634642Smarc */ 76734642Smarc if (qdflags[unit].mapped & MAPDMA) { 76834642Smarc dga = (struct dga *) qdmap[unit].dga; 76934642Smarc adder = (struct adder *) qdmap[unit].adder; 77034642Smarc dga->csr &= ~DMA_IE; 77134642Smarc dga->csr &= ~0x0600; /* kill DMA */ 77234642Smarc adder->command = CANCEL; 77334642Smarc /* 77434642Smarc * if DMA was running, flush spurious intrpt 77534642Smarc */ 77634642Smarc if (dga->bytcnt_lo != 0) { 77734642Smarc dga->bytcnt_lo = 0; 77834642Smarc dga->bytcnt_hi = 0; 77934642Smarc DMA_SETIGNORE(DMAheader[unit]); 78034642Smarc dga->csr |= DMA_IE; 78134642Smarc dga->csr &= ~DMA_IE; 78234642Smarc } 78334642Smarc ptep = (int *) 78434642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 785*34732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 786*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 78734642Smarc ubarelse(0, &Qbus_unmap[unit]); 78834642Smarc } 78934615Smarc 79034642Smarc /* 79134642Smarc * re-protect 1K (2 pages) event queue 79234642Smarc */ 79334642Smarc if (qdflags[unit].mapped & MAPEQ) { 79434642Smarc ptep = (int *) 79534642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 796*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 79734642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 79830391Skarels } 79934642Smarc /* 80034642Smarc * re-protect scroll param area and disable scroll intrpts 80134642Smarc */ 80234642Smarc if (qdflags[unit].mapped & MAPSCR) { 80334642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 80434642Smarc + (mfpr(SBR) | 0x80000000)); 80534642Smarc /* 80634642Smarc * re-protect 512 scroll param area 80734642Smarc */ 80834642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 80934642Smarc adder = (struct adder *) qdmap[unit].adder; 81034642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 81134642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 81234642Smarc } 81334642Smarc /* 81434642Smarc * re-protect color map write buffer area and kill intrpts 81534642Smarc */ 81634642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 81734642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 81834642Smarc + (mfpr(SBR) | 0x80000000)); 819*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 82034642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 82134642Smarc color_buf[unit]->status = 0; 82234642Smarc adder = (struct adder *) qdmap[unit].adder; 82334642Smarc qdflags[unit].adder_ie &= ~VSYNC; 82434642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 82534642Smarc } 82634642Smarc mtpr(TBIA, 0); 82734642Smarc /* flag everything now unmapped */ 82834642Smarc qdflags[unit].mapped = 0; 82934642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 83034642Smarc qdflags[unit].curs_acc = ACC_OFF; 83134642Smarc qdflags[unit].curs_thr = 128; 83234642Smarc /* 83334642Smarc * restore the console 83434642Smarc */ 83530391Skarels dga = (struct dga *) qdmap[unit].dga; 83630391Skarels adder = (struct adder *) qdmap[unit].adder; 83730391Skarels dga->csr &= ~DMA_IE; 83830391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 83930391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 84030391Skarels adder->command = CANCEL; 84134642Smarc /* 84234642Smarc * if DMA was running, flush spurious intrpt 84334642Smarc */ 84430391Skarels if (dga->bytcnt_lo != 0) { 84534642Smarc dga->bytcnt_lo = 0; 84634642Smarc dga->bytcnt_hi = 0; 84734642Smarc DMA_SETIGNORE(DMAheader[unit]); 84834642Smarc dga->csr |= DMA_IE; 84934642Smarc dga->csr &= ~DMA_IE; 85030391Skarels } 85130391Skarels init_shared(unit); /* init shared memory */ 85230391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 85330391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 85430391Skarels setup_input(unit); /* init the DUART */ 85530391Skarels ldfont(unit); 85630391Skarels cursor[unit].x = 0; 85730391Skarels cursor[unit].y = 0; 85834642Smarc /* 85934642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 86034642Smarc */ 86134642Smarc duart = (struct duart *) qdmap[unit].duart; 86234642Smarc qdflags[unit].duart_imask &= ~(0x20); 86334642Smarc qdflags[unit].duart_imask |= 0x02; 86434642Smarc duart->imask = qdflags[unit].duart_imask; 86534642Smarc /* 86634642Smarc * shut off interrupts if all is closed 86734642Smarc */ 86834642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 86934642Smarc dga = (struct dga *) qdmap[unit].dga; 87034642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 87134642Smarc } 87234642Smarc } else { 87334642Smarc /* 87434642Smarc * this is the console 87534642Smarc */ 87634642Smarc tp = &qd_tty[minor_dev]; 87734642Smarc (*linesw[tp->t_line].l_close)(tp); 87834642Smarc ttyclose(tp); 87934642Smarc tp->t_state = 0; 88034642Smarc qdflags[unit].inuse &= ~CONS_DEV; 88134642Smarc /* 88234642Smarc * if graphics device is closed, kill interrupts 88334642Smarc */ 88434642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 88534642Smarc dga = (struct dga *) qdmap[unit].dga; 88634642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 88734642Smarc } 88830391Skarels } 88934615Smarc 89030391Skarels return(0); 89130391Skarels 89230391Skarels } /* qdclose */ 89330391Skarels 89430391Skarels qdioctl(dev, cmd, datap, flags) 89534642Smarc dev_t dev; 89634642Smarc int cmd; 897*34732Smarc register caddr_t datap; 89834642Smarc int flags; 89930391Skarels { 90030391Skarels register int *ptep; /* page table entry pointer */ 90132012Smarc register int mapix; /* QVmap[] page table index */ 90230391Skarels register struct _vs_event *event; 90330391Skarels register struct tty *tp; 904*34732Smarc register i; 90530391Skarels struct qdmap *qd; /* pointer to device map struct */ 90630391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 90730391Skarels struct duart *duart; /* DUART reg structure pointer */ 90830391Skarels struct adder *adder; /* ADDER reg structure pointer */ 90930391Skarels struct prgkbd *cmdbuf; 91030391Skarels struct prg_cursor *curs; 91130391Skarels struct _vs_cursor *pos; 912*34732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 91330391Skarels u_int minor_dev = minor(dev); 91430391Skarels int error; 91530391Skarels int s; 91630391Skarels short *temp; /* a pointer to template RAM */ 91730391Skarels 91834642Smarc /* 91934642Smarc * service graphic device ioctl commands 92034642Smarc */ 92130391Skarels switch (cmd) { 92234615Smarc 92334642Smarc case QD_GETEVENT: 92434642Smarc /* 92534642Smarc * extract the oldest event from the event queue 92634642Smarc */ 92730391Skarels if (ISEMPTY(eq_header[unit])) { 92834642Smarc event = (struct _vs_event *) datap; 92934642Smarc event->vse_device = VSE_NULL; 93034642Smarc break; 93130391Skarels } 93230391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 93334615Smarc s = spl5(); 93430391Skarels GETEND(eq_header[unit]); 93530391Skarels splx(s); 936*34732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 93730391Skarels break; 93830391Skarels 93934642Smarc case QD_RESET: 94034642Smarc /* 94134642Smarc * init the dragon stuff, DUART, and driver variables 94234642Smarc */ 94330391Skarels init_shared(unit); /* init shared memory */ 94430391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 94530391Skarels clear_qd_screen(unit); 94630391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 94730391Skarels ldfont(unit); /* load the console font */ 94830391Skarels setup_input(unit); /* init the DUART */ 94930391Skarels break; 95030391Skarels 95134642Smarc case QD_SET: 95234642Smarc /* 95334642Smarc * init the DUART and driver variables 95434642Smarc */ 95530391Skarels init_shared(unit); 95630391Skarels setup_input(unit); 95730391Skarels break; 95830391Skarels 95934642Smarc case QD_CLRSCRN: 96034642Smarc /* 96134642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 96234642Smarc */ 963*34732Smarc #ifdef notdef /* has caused problems and isn't necessary */ 96430391Skarels setup_dragon(unit); 96530391Skarels clear_qd_screen(unit); 96634615Smarc #endif 96730391Skarels break; 96830391Skarels 96934642Smarc case QD_WTCURSOR: 97034642Smarc /* 97134642Smarc * load a cursor into template RAM 97234642Smarc */ 973*34732Smarc ldcursor(unit, (short *)datap); 97430391Skarels break; 97530391Skarels 97634642Smarc case QD_RDCURSOR: 97730391Skarels 97830391Skarels temp = (short *) qdmap[unit].template; 97934642Smarc /* 98034642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 98134642Smarc * ...template space 98234642Smarc */ 98330391Skarels temp += (8 * 1024) - 32; 98430391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 98534642Smarc *(short *)datap = *temp++; 98630391Skarels break; 98730391Skarels 98834642Smarc case QD_POSCURSOR: 98934642Smarc /* 99034642Smarc * position the mouse cursor 99134642Smarc */ 99230391Skarels dga = (struct dga *) qdmap[unit].dga; 99330391Skarels pos = (struct _vs_cursor *) datap; 99434615Smarc s = spl5(); 99530391Skarels dga->x_cursor = TRANX(pos->x); 99630391Skarels dga->y_cursor = TRANY(pos->y); 99730391Skarels eq_header[unit]->curs_pos.x = pos->x; 99830391Skarels eq_header[unit]->curs_pos.y = pos->y; 99930391Skarels splx(s); 100030391Skarels break; 100130391Skarels 100234642Smarc case QD_PRGCURSOR: 100334642Smarc /* 100434642Smarc * set the cursor acceleration factor 100534642Smarc */ 100630391Skarels curs = (struct prg_cursor *) datap; 100734615Smarc s = spl5(); 100830391Skarels qdflags[unit].curs_acc = curs->acc_factor; 100930391Skarels qdflags[unit].curs_thr = curs->threshold; 101030391Skarels splx(s); 101130391Skarels break; 101230391Skarels 101334642Smarc case QD_MAPDEVICE: 101434642Smarc /* 101534642Smarc * enable 'user write' to device pages 101634642Smarc */ 101730391Skarels qdflags[unit].mapped |= MAPDEV; 101830391Skarels qd = (struct qdmap *) &qdmap[unit]; 101934642Smarc /* 102034642Smarc * enable user write to template RAM 102134642Smarc */ 102232012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 102332012Smarc ptep = (int *)(QVmap[0] + mapix); 1024*34732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 1025*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 102634642Smarc /* 102734642Smarc * enable user write to registers 102834642Smarc */ 102932012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 103032012Smarc ptep = (int *)(QVmap[0] + mapix); 1031*34732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 1032*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103334642Smarc /* 103434642Smarc * enable user write to color maps 103534642Smarc */ 103632012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 103732012Smarc ptep = (int *)(QVmap[0] + mapix); 1038*34732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 1039*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104034642Smarc /* 104134642Smarc * enable user write to DUART 104234642Smarc */ 104332012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 104432012Smarc ptep = (int *)(QVmap[0] + mapix); 104530391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 104630391Skarels 1047*34732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 104830391Skarels 104934642Smarc /* 1050*34732Smarc * stuff qdmap structure in return buffer 1051*34732Smarc */ 1052*34732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 105330391Skarels break; 105430391Skarels 105534642Smarc case QD_MAPIOBUF: 105634642Smarc /* 105734642Smarc * do setup for DMA by user process 105834642Smarc * 105934642Smarc * set 'user write enable' bits for DMA buffer 106034642Smarc */ 106130391Skarels qdflags[unit].mapped |= MAPDMA; 106230391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 106334642Smarc + (mfpr(SBR) | 0x80000000)); 1064*34732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 1065*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1066*34732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 106734642Smarc /* 106834642Smarc * set up QBUS map registers for DMA 106934642Smarc */ 107030391Skarels DMAheader[unit]->QBAreg = 1071*34732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 107230391Skarels if (DMAheader[unit]->QBAreg == 0) 1073*34732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 107430391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 107530391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 107634642Smarc /* 107734642Smarc * return I/O buf adr 107834642Smarc */ 107930391Skarels *(int *)datap = (int) DMAheader[unit]; 108030391Skarels break; 108130391Skarels 108234642Smarc case QD_MAPSCROLL: 108334642Smarc /* 108434642Smarc * map the shared scroll param area and enable scroll interpts 108534642Smarc */ 108630391Skarels qdflags[unit].mapped |= MAPSCR; 108730391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 108834642Smarc + (mfpr(SBR) | 0x80000000)); 108934642Smarc /* 109034642Smarc * allow user write to scroll area 109134642Smarc */ 109230391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1093*34732Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 109430391Skarels scroll[unit]->status = 0; 109530391Skarels adder = (struct adder *) qdmap[unit].adder; 109630391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 109730391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 109834642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 109930391Skarels break; 110030391Skarels 110134642Smarc case QD_UNMAPSCROLL: 110234642Smarc /* 110334642Smarc * unmap shared scroll param area and disable scroll intrpts 110434642Smarc */ 110530391Skarels if (qdflags[unit].mapped & MAPSCR) { 110634642Smarc qdflags[unit].mapped &= ~MAPSCR; 110734642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 110834642Smarc + (mfpr(SBR) | 0x80000000)); 110934642Smarc /* 111034642Smarc * re-protect 512 scroll param area 111134642Smarc */ 111234642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 111334642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 111434642Smarc adder = (struct adder *) qdmap[unit].adder; 111534642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 111634642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 111730391Skarels } 111830391Skarels break; 111930391Skarels 112034642Smarc case QD_MAPCOLOR: 112134642Smarc /* 112234642Smarc * map shared color map write buf and turn on vsync intrpt 112334642Smarc */ 112430391Skarels qdflags[unit].mapped |= MAPCOLOR; 112530391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 112634642Smarc + (mfpr(SBR) | 0x80000000)); 1127*34732Smarc /* 1128*34732Smarc * allow user write to color map write buffer 1129*34732Smarc */ 1130*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 113130391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 113230391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 113334642Smarc adder = (struct adder *) qdmap[unit].adder; 113430391Skarels qdflags[unit].adder_ie |= VSYNC; 113530391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 1136*34732Smarc /* 1137*34732Smarc * return color area address 1138*34732Smarc */ 113930391Skarels *(int *)datap = (int) color_buf[unit]; 114030391Skarels break; 114130391Skarels 114234642Smarc case QD_UNMAPCOLOR: 114334642Smarc /* 1144*34732Smarc * unmap shared color map write buffer and kill VSYNC intrpts 1145*34732Smarc */ 114630391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 114734642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 114834642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 114934642Smarc + (mfpr(SBR) | 0x80000000)); 1150*34732Smarc /* 1151*34732Smarc * re-protect color map write buffer 1152*34732Smarc */ 1153*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 115434642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 1155*34732Smarc mtpr(TBIA, 0); 115634642Smarc adder = (struct adder *) qdmap[unit].adder; 115734642Smarc qdflags[unit].adder_ie &= ~VSYNC; 115834642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 115930391Skarels } 116030391Skarels break; 116130391Skarels 116234642Smarc case QD_MAPEVENT: 116334642Smarc /* 116434642Smarc * give user write access to the event queue 116534642Smarc */ 116630391Skarels qdflags[unit].mapped |= MAPEQ; 116730391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 116834642Smarc + (mfpr(SBR) | 0x80000000)); 1169*34732Smarc /* 1170*34732Smarc * allow user write to 1K event queue 1171*34732Smarc */ 1172*34732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 117330391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 117430391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 1175*34732Smarc /* 1176*34732Smarc * return event queue address 1177*34732Smarc */ 1178*34732Smarc *(int *)datap = (int)eq_header[unit]; 117930391Skarels break; 118030391Skarels 118134642Smarc case QD_PRGKBD: 118234642Smarc /* 118334642Smarc * pass caller's programming commands to LK201 118434642Smarc */ 1185*34732Smarc duart = (struct duart *)qdmap[unit].duart; 1186*34732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 118734642Smarc /* 118834642Smarc * send command 118934642Smarc */ 119030391Skarels for (i = 1000; i > 0; --i) { 1191*34732Smarc if (duart->statusA&XMT_RDY) { 119234642Smarc duart->dataA = cmdbuf->cmd; 119334642Smarc break; 119434642Smarc } 119530391Skarels } 119630391Skarels if (i == 0) { 1197*34732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 119834642Smarc break; 119930391Skarels } 120034642Smarc /* 120134642Smarc * send param1? 120234642Smarc */ 120330391Skarels if (cmdbuf->cmd & LAST_PARAM) 120434642Smarc break; 120530391Skarels for (i = 1000; i > 0; --i) { 1206*34732Smarc if (duart->statusA&XMT_RDY) { 120734642Smarc duart->dataA = cmdbuf->param1; 120834642Smarc break; 120934642Smarc } 121030391Skarels } 121130391Skarels if (i == 0) { 1212*34732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 121334642Smarc break; 121430391Skarels } 121534642Smarc /* 121634642Smarc * send param2? 121734642Smarc */ 121830391Skarels if (cmdbuf->param1 & LAST_PARAM) 121930391Skarels break; 122030391Skarels for (i = 1000; i > 0; --i) { 1221*34732Smarc if (duart->statusA&XMT_RDY) { 122234642Smarc duart->dataA = cmdbuf->param2; 122334642Smarc break; 122434642Smarc } 122530391Skarels } 122630391Skarels if (i == 0) { 1227*34732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 122834642Smarc break; 122930391Skarels } 123030391Skarels break; 123130391Skarels 123234642Smarc case QD_PRGMOUSE: 123334642Smarc /* 123434642Smarc * pass caller's programming commands to the mouse 123534642Smarc */ 123630391Skarels duart = (struct duart *) qdmap[unit].duart; 123730391Skarels for (i = 1000; i > 0; --i) { 1238*34732Smarc if (duart->statusB&XMT_RDY) { 123934642Smarc duart->dataB = *datap; 124034642Smarc break; 124134642Smarc } 124230391Skarels } 124330391Skarels if (i == 0) { 1244*34732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 124530391Skarels } 124630391Skarels break; 124730391Skarels 124834642Smarc case QD_RDCONFIG: 124934642Smarc /* 125034642Smarc * get QDSS configuration word and return it 125134642Smarc */ 125230391Skarels *(short *)datap = qdflags[unit].config; 125330391Skarels break; 125430391Skarels 125534642Smarc case QD_KERN_LOOP: 125634642Smarc case QD_KERN_UNLOOP: 125734642Smarc /* 125834642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 125934642Smarc * kernel console output. 126034642Smarc */ 126134615Smarc break; 126234615Smarc 126334642Smarc case QD_PRGTABLET: 126434642Smarc /* 126534642Smarc * program the tablet 126634642Smarc */ 126730391Skarels duart = (struct duart *) qdmap[unit].duart; 126830391Skarels for (i = 1000; i > 0; --i) { 1269*34732Smarc if (duart->statusB&XMT_RDY) { 127034642Smarc duart->dataB = *datap; 127134642Smarc break; 127234642Smarc } 127330391Skarels } 127430391Skarels if (i == 0) { 1275*34732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 127630391Skarels } 127730391Skarels break; 127830391Skarels 127934642Smarc case QD_PRGTABRES: 128034642Smarc /* 128134642Smarc * program the tablet report resolution factor 128234642Smarc */ 128330391Skarels qdflags[unit].tab_res = *(short *)datap; 128430391Skarels break; 128530391Skarels 128634642Smarc default: 128734642Smarc /* 128834642Smarc * service tty ioctl's 128934642Smarc */ 129034642Smarc if (!(minor_dev & 0x02)) { 129130391Skarels tp = &qd_tty[minor_dev]; 129234642Smarc error = 129334642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 129430391Skarels if (error >= 0) { 129534642Smarc return(error); 129630391Skarels } 129730391Skarels error = ttioctl(tp, cmd, datap, flags); 129830391Skarels if (error >= 0) { 129934642Smarc return(error); 130030391Skarels } 130134642Smarc } 130234642Smarc break; 130330391Skarels } 130430391Skarels 130530391Skarels return(0); 130630391Skarels 130730391Skarels } /* qdioctl */ 130830391Skarels 130930391Skarels qdselect(dev, rw) 131034642Smarc dev_t dev; 131134642Smarc int rw; 131230391Skarels { 1313*34732Smarc register s; 1314*34732Smarc register unit; 131534615Smarc register struct tty *tp; 131634615Smarc u_int minor_dev = minor(dev); 131730391Skarels 131834615Smarc s = spl5(); 131934615Smarc unit = minor_dev >> 2; 132030391Skarels 132130391Skarels switch (rw) { 132234642Smarc case FREAD: 132334642Smarc if ((minor_dev & 0x03) == 2) { 132434642Smarc /* 132534642Smarc * this is a graphics device, so check for events 132634642Smarc */ 1327*34732Smarc if(!(ISEMPTY(eq_header[unit]))) { 132834642Smarc splx(s); 132934642Smarc return(1); 133034642Smarc } 1331*34732Smarc qdrsel[unit] = u.u_procp; 133234642Smarc qdflags[unit].selmask |= SEL_READ; 133334642Smarc splx(s); 133434642Smarc return(0); 133534642Smarc } else { 133634642Smarc /* 133734642Smarc * this is a tty device 133834642Smarc */ 133934642Smarc tp = &qd_tty[minor_dev]; 134034642Smarc if (ttnread(tp)) 134134642Smarc return(1); 134234642Smarc tp->t_rsel = u.u_procp; 134334642Smarc splx(s); 134434642Smarc return(0); 134530391Skarels } 134630391Skarels 134734642Smarc case FWRITE: 134834642Smarc if ((minor(dev) & 0x03) == 2) { 134934642Smarc /* 135034642Smarc * this is a graphics device, so check for dma buffers 135134642Smarc */ 135234642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 135334642Smarc { 135434642Smarc splx(s); 135534642Smarc return(1); 135634642Smarc } 1357*34732Smarc qdrsel[unit] = u.u_procp; 135834642Smarc qdflags[unit].selmask |= SEL_WRITE; 135934642Smarc splx(s); 136034642Smarc return(0); 136134642Smarc } else { 136234642Smarc /* 136334642Smarc * this is a tty device 136434642Smarc */ 136534642Smarc tp = &qd_tty[minor_dev]; 136634642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) 136734642Smarc return(1); 136834642Smarc tp->t_wsel = u.u_procp; 136934642Smarc splx(s); 137034642Smarc return(0); 137130391Skarels } 137230391Skarels } 1373*34732Smarc splx(s); 1374*34732Smarc return(0); 137530391Skarels 137630391Skarels } /* qdselect() */ 137730391Skarels 137830391Skarels extern qd_strategy(); 137930391Skarels 138030391Skarels qdwrite(dev, uio) 138134642Smarc dev_t dev; 138234642Smarc struct uio *uio; 138330391Skarels { 138430391Skarels register struct tty *tp; 1385*34732Smarc register minor_dev; 1386*34732Smarc register unit; 138730391Skarels 138830391Skarels minor_dev = minor(dev); 138930391Skarels unit = (minor_dev >> 2) & 0x07; 139030391Skarels 139134642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 139234642Smarc /* 139334642Smarc * this is the console... 139434642Smarc */ 139534642Smarc tp = &qd_tty[minor_dev]; 139634642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 139734642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 139834642Smarc /* 139934642Smarc * this is a DMA xfer from user space 140034642Smarc */ 140134642Smarc return (physio(qd_strategy, &qdbuf[unit], 140234642Smarc dev, B_WRITE, minphys, uio)); 140330391Skarels } 1404*34732Smarc return (ENXIO); 140530391Skarels } 140630391Skarels 140730391Skarels qdread(dev, uio) 140834642Smarc dev_t dev; 140934642Smarc struct uio *uio; 141030391Skarels { 141130391Skarels register struct tty *tp; 1412*34732Smarc register minor_dev; 1413*34732Smarc register unit; 141430391Skarels 141530391Skarels minor_dev = minor(dev); 141630391Skarels unit = (minor_dev >> 2) & 0x07; 141730391Skarels 141834642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 141934642Smarc /* 142034642Smarc * this is the console 142134642Smarc */ 142234642Smarc tp = &qd_tty[minor_dev]; 142334642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 142434642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 142534642Smarc /* 142634642Smarc * this is a bitmap-to-processor xfer 142734642Smarc */ 142834642Smarc return (physio(qd_strategy, &qdbuf[unit], 142934642Smarc dev, B_READ, minphys, uio)); 143030391Skarels } 1431*34732Smarc return (ENXIO); 143230391Skarels } 143330391Skarels 143430391Skarels /*************************************************************** 143530391Skarels * 143630391Skarels * qd_strategy()... strategy routine to do DMA 143730391Skarels * 143830391Skarels ***************************************************************/ 143930391Skarels 144030391Skarels qd_strategy(bp) 144134642Smarc register struct buf *bp; 144230391Skarels { 144330391Skarels register struct dga *dga; 144430391Skarels register struct adder *adder; 1445*34732Smarc register unit; 144630391Skarels int QBAreg; 144730391Skarels int s; 144830391Skarels int cookie; 144930391Skarels 145030391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 145130391Skarels 145234642Smarc /* 145334642Smarc * init pointers 145434642Smarc */ 145530391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 1456*34732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 145734642Smarc goto STRAT_ERR; 145830391Skarels } 145930391Skarels dga = (struct dga *) qdmap[unit].dga; 146034615Smarc s = spl5(); 146130391Skarels qdflags[unit].user_dma = -1; 146230391Skarels dga->csr |= DMA_IE; 146330391Skarels cookie = QBAreg & 0x3FFFF; 146430391Skarels dga->adrs_lo = (short) cookie; 146530391Skarels dga->adrs_hi = (short) (cookie >> 16); 146630391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 146730391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 146830391Skarels 146930391Skarels while (qdflags[unit].user_dma) { 147034642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 147130391Skarels } 147230391Skarels splx(s); 147330391Skarels ubarelse(0, &QBAreg); 147430391Skarels if (!(dga->csr & DMA_ERR)) { 147534642Smarc iodone(bp); 147634642Smarc return; 147730391Skarels } 147830391Skarels 147930391Skarels STRAT_ERR: 148030391Skarels adder = (struct adder *) qdmap[unit].adder; 148134642Smarc adder->command = CANCEL; /* cancel adder activity */ 148230391Skarels dga->csr &= ~DMA_IE; 148330391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 148430391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 148530391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 148630391Skarels 148734642Smarc /* 148834642Smarc * if DMA was running, flush spurious intrpt 148934642Smarc */ 149030391Skarels if (dga->bytcnt_lo != 0) { 149134642Smarc dga->bytcnt_lo = 0; 149234642Smarc dga->bytcnt_hi = 0; 149334642Smarc DMA_SETIGNORE(DMAheader[unit]); 149434642Smarc dga->csr |= DMA_IE; 149530391Skarels } 149630391Skarels iodone(bp); 149730391Skarels 149830391Skarels } /* qd_strategy */ 149930391Skarels 1500*34732Smarc /* 1501*34732Smarc * Start output to the console screen 1502*34732Smarc */ 150330391Skarels qdstart(tp) 150434642Smarc register struct tty *tp; 150530391Skarels { 1506*34732Smarc register which_unit, unit, c; 150730391Skarels int s; 150834615Smarc 150930391Skarels unit = minor(tp->t_dev); 151030391Skarels which_unit = (unit >> 2) & 0x3; 151134615Smarc unit &= 0x03; 151230391Skarels 151334615Smarc s = spl5(); 151434615Smarc 151534642Smarc /* 151634642Smarc * If it's currently active, or delaying, no need to do anything. 151734642Smarc */ 151830391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 151930391Skarels goto out; 152030391Skarels 152134642Smarc /* 152234642Smarc * Display chars until the queue is empty. 152334642Smarc * Drop input from anything but the console 152434642Smarc * device on the floor. 152534642Smarc * 152634642Smarc * XXX - this loop is done at spltty. 152734642Smarc * 152834642Smarc */ 152934642Smarc while (tp->t_outq.c_cc) { 153034511Smarc c = getc(&tp->t_outq); 153134615Smarc if (unit == 0) 1532*34732Smarc blitc(which_unit, (u_char)c); 153330391Skarels } 153434642Smarc /* 153534642Smarc * If there are sleepers, and output has drained below low 153634642Smarc * water mark, wake up the sleepers. 153734642Smarc */ 153834642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 153934615Smarc if (tp->t_state & TS_ASLEEP){ 154034615Smarc tp->t_state &= ~TS_ASLEEP; 154134615Smarc wakeup((caddr_t) &tp->t_outq); 154234615Smarc } 154330391Skarels } 154430391Skarels 154534615Smarc tp->t_state &= ~TS_BUSY; 154634615Smarc 154730391Skarels out: 154830391Skarels splx(s); 154930391Skarels 155030391Skarels } /* qdstart */ 155130391Skarels 1552*34732Smarc /*ARGSUSED*/ 155330391Skarels qdstop(tp, flag) 155434642Smarc register struct tty *tp; 155534642Smarc int flag; 155630391Skarels { 155730391Skarels register int s; 155830391Skarels 155934615Smarc s = spl5(); /* block intrpts during state modification */ 1560*34732Smarc if (tp->t_state & TS_BUSY) 1561*34732Smarc if ((tp->t_state & TS_TTSTOP) == 0) 156234642Smarc tp->t_state |= TS_FLUSH; 156334642Smarc else 156434642Smarc tp->t_state &= ~TS_BUSY; 156530391Skarels splx(s); 156630391Skarels } 156730391Skarels 1568*34732Smarc /* 1569*34732Smarc * Output a character to the QDSS screen 1570*34732Smarc */ 157130391Skarels 157230391Skarels blitc(unit, chr) 1573*34732Smarc register unit; 1574*34732Smarc register u_char chr; 157530391Skarels { 157630391Skarels register struct adder *adder; 157730391Skarels register struct dga *dga; 157830391Skarels register int i; 157934642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 158034642Smarc static short inescape[NQD]; 158130391Skarels 1582*34732Smarc adder = (struct adder *)qdmap[unit].adder; 158330391Skarels dga = (struct dga *) qdmap[unit].dga; 158434642Smarc /* 158534642Smarc * BSD comment: this (&=0177) defeats the extended character 158634642Smarc * set code for the glass tty, but if i had the time i would 158734642Smarc * spend it ripping out the code completely. This driver 158834642Smarc * is too big for its own good. 158934642Smarc */ 159034642Smarc chr &= 0177; 159134642Smarc /* 1592*34732Smarc * Cursor addressing (so vi will work). 159334642Smarc * Decode for "\E=%.%." cursor motion description. 1594*34732Smarc * Corresponds to type "qdcons" in /etc/termcap: 159534642Smarc * 159634642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 159734642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 159834642Smarc * 159934642Smarc */ 160034642Smarc if (inescape[unit] && nograph) { 160134642Smarc switch (inescape[unit]++) { 160234642Smarc case 1: 160334642Smarc if (chr != '=') { 160434642Smarc /* abort escape sequence */ 160534642Smarc inescape[unit] = 0; 160634642Smarc blitc(unit, chr); 160734642Smarc } 1608*34732Smarc return; 160934642Smarc case 2: 161034642Smarc /* position row */ 161134642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 161234642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 161334642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 161434642Smarc dga->y_cursor = TRANY(cursor[unit].y); 1615*34732Smarc return; 161634642Smarc case 3: 161734642Smarc /* position column */ 161834642Smarc cursor[unit].x = CHAR_WIDTH * chr; 161934642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 162034642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 162134642Smarc dga->x_cursor = TRANX(cursor[unit].x); 162234642Smarc inescape[unit] = 0; 1623*34732Smarc return; 162434642Smarc default: 162534642Smarc inescape[unit] = 0; 162634642Smarc blitc(unit, chr); 162734642Smarc } 162834642Smarc } 162930391Skarels 163030391Skarels switch (chr) { 163134642Smarc case '\r': /* return char */ 163230391Skarels cursor[unit].x = 0; 163334642Smarc if (nograph) 163434642Smarc dga->x_cursor = TRANX(cursor[unit].x); 1635*34732Smarc return; 163630391Skarels 163734642Smarc case '\t': /* tab char */ 163830391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 163934642Smarc blitc(unit, ' '); 164030391Skarels } 1641*34732Smarc return; 164230391Skarels 164334642Smarc case '\n': /* line feed char */ 164430391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 164534642Smarc if (nograph) { 164634642Smarc cursor[unit].y -= CHAR_HEIGHT; 164734642Smarc scroll_up(adder); 164834642Smarc } else 164934642Smarc cursor[unit].y = 0; 165030391Skarels } 165134642Smarc if (nograph) 165234642Smarc dga->y_cursor = TRANY(cursor[unit].y); 1653*34732Smarc return; 165430391Skarels 165534642Smarc case '\b': /* backspace char */ 165630391Skarels if (cursor[unit].x > 0) { 165734642Smarc cursor[unit].x -= CHAR_WIDTH; 165834642Smarc if (nograph) 165934642Smarc dga->x_cursor = TRANX(cursor[unit].x); 166030391Skarels } 1661*34732Smarc return; 166234642Smarc case CTRL('k'): /* cursor up */ 166334642Smarc if (nograph && cursor[unit].y > 0) { 166434642Smarc cursor[unit].y -= CHAR_HEIGHT; 166534642Smarc dga->y_cursor = TRANY(cursor[unit].y); 166634642Smarc } 1667*34732Smarc return; 166830391Skarels 166934642Smarc case CTRL('^'): /* home cursor */ 167034642Smarc if (nograph) { 167134642Smarc cursor[unit].x = 0; 167234642Smarc dga->x_cursor = TRANX(cursor[unit].x); 167334642Smarc cursor[unit].y = 0; 167434642Smarc dga->y_cursor = TRANY(cursor[unit].y); 167534642Smarc } 1676*34732Smarc return; 167732012Smarc 167834642Smarc case CTRL('l'): /* cursor right */ 167934642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 168034642Smarc cursor[unit].x += CHAR_WIDTH; 168134642Smarc dga->x_cursor = TRANX(cursor[unit].x); 168234642Smarc } 1683*34732Smarc return; 168430391Skarels 168534642Smarc case CTRL('z'): /* clear screen */ 168634642Smarc if (nograph) { 168734642Smarc setup_dragon(unit); 168834642Smarc clear_qd_screen(unit); 168934642Smarc /* home cursor - termcap seems to assume this */ 169034642Smarc cursor[unit].x = 0; 169134642Smarc dga->x_cursor = TRANX(cursor[unit].x); 169234642Smarc cursor[unit].y = 0; 169334642Smarc dga->y_cursor = TRANY(cursor[unit].y); 169434642Smarc } 1695*34732Smarc return; 169630391Skarels 169734642Smarc case '\033': /* start escape sequence */ 169834642Smarc if (nograph) 169934642Smarc inescape[unit] = 1; 1700*34732Smarc return; 170134642Smarc 170234642Smarc default: 170334642Smarc if ((chr < ' ') || (chr > '~')) 1704*34732Smarc return; 170534642Smarc } 170634642Smarc /* 170734642Smarc * setup VIPER operand control registers 170834642Smarc */ 170930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 171030391Skarels write_ID(adder, SRC1_OCR_B, 171134642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 171230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 171330391Skarels write_ID(adder, SRC1_OCR_B, 171434642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 171530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 171630391Skarels write_ID(adder, DST_OCR_B, 171734642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 171830391Skarels write_ID(adder, MASK_1, 0xFFFF); 171930391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 172030391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 172134642Smarc adder->x_clip_min = 0; 172234642Smarc adder->x_clip_max = 1024; 172334642Smarc adder->y_clip_min = 0; 172434642Smarc adder->y_clip_max = 864; 172534642Smarc /* 172634642Smarc * load DESTINATION origin and vectors 172734642Smarc */ 172830391Skarels adder->fast_dest_dy = 0; 172930391Skarels adder->slow_dest_dx = 0; 173030391Skarels adder->error_1 = 0; 173130391Skarels adder->error_2 = 0; 173230391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 1733*34732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 173430391Skarels adder->destination_x = cursor[unit].x; 173530391Skarels adder->fast_dest_dx = CHAR_WIDTH; 173630391Skarels adder->destination_y = cursor[unit].y; 173730391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 173834642Smarc /* 173934642Smarc * load SOURCE origin and vectors 174034642Smarc */ 174134615Smarc if ((chr - ' ') > (CHARS - 1)) { 174234615Smarc printf("Invalid character (x)%x in blitc\n",chr); 174334615Smarc chr = ' '; 174434615Smarc } 174534642Smarc /* 174634642Smarc * X position is modulo the number of characters per line 174734642Smarc */ 174834615Smarc adder->source_1_x = FONT_X + 174934642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 175034642Smarc /* 175134642Smarc * Point to either first or second row 175234642Smarc */ 175334615Smarc adder->source_1_y = 2048 - 15 * 175434642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 175530391Skarels adder->source_1_dx = CHAR_WIDTH; 175630391Skarels adder->source_1_dy = CHAR_HEIGHT; 175730391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 175830391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 175934642Smarc /* 176034642Smarc * update console cursor coordinates 176134642Smarc */ 176230391Skarels cursor[unit].x += CHAR_WIDTH; 176334642Smarc if (nograph) 176434642Smarc dga->x_cursor = TRANX(cursor[unit].x); 176530391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 176634642Smarc blitc(unit, '\r'); 176734642Smarc blitc(unit, '\n'); 176830391Skarels } 176930391Skarels 177030391Skarels } /* blitc */ 177130391Skarels 1772*34732Smarc qdreset() { } 177330391Skarels 1774*34732Smarc /* 1775*34732Smarc * INTERRUPT SERVICE ROUTINES 1776*34732Smarc */ 177730391Skarels 1778*34732Smarc /* 1779*34732Smarc * Service "DMA DONE" interrupt condition 1780*34732Smarc */ 178130391Skarels qddint(qd) 1782*34732Smarc register qd; 178330391Skarels { 178430391Skarels register struct DMAreq_header *header; 178530391Skarels register struct DMAreq *request; 178630391Skarels register struct dga *dga; 178730391Skarels struct adder *adder; 178830391Skarels int cookie; /* DMA adrs for QDSS */ 178930391Skarels 1790*34732Smarc (void)spl4(); /* allow interval timer in */ 179130391Skarels 179234642Smarc /* 179334642Smarc * init pointers 179434642Smarc */ 179530391Skarels header = DMAheader[qd]; /* register for optimization */ 179630391Skarels dga = (struct dga *) qdmap[qd].dga; 179730391Skarels adder = (struct adder *) qdmap[qd].adder; 179830391Skarels 179934642Smarc /* 180034642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 180134642Smarc */ 180230391Skarels if (DMA_ISIGNORE(header)) { 180334642Smarc DMA_CLRIGNORE(header); 180434642Smarc return; 180530391Skarels } 180630391Skarels 180734642Smarc /* 180834642Smarc * dump a DMA hardware error message if appropriate 180934642Smarc */ 181030391Skarels if (dga->csr & DMA_ERR) { 181130391Skarels 181234642Smarc if (dga->csr & PARITY_ERR) 1813*34732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 181430391Skarels 181534642Smarc if (dga->csr & BUS_ERR) 1816*34732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 181730391Skarels } 181830391Skarels 181934642Smarc /* 182034642Smarc * if this was a DMA from user space... 182134642Smarc */ 182230391Skarels if (qdflags[qd].user_dma) { 182334642Smarc qdflags[qd].user_dma = 0; 182434642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 182534642Smarc return; 182630391Skarels } 182730391Skarels 182834642Smarc /* 182934642Smarc * if we're doing DMA request queue services, field the error condition 183034642Smarc */ 183130391Skarels if (dga->csr & DMA_ERR) { 183230391Skarels 183334642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 183434642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 183534642Smarc adder->command = CANCEL; /* cancel adder activity */ 183630391Skarels 183734642Smarc DMA_SETERROR(header); /* flag error in header status word */ 183834642Smarc DMA_CLRACTIVE(header); 183934642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 184034642Smarc header->newest = header->oldest; 184134642Smarc header->used = 0; 184230391Skarels 1843*34732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 1844*34732Smarc selwakeup(qdrsel[qd], 0); 1845*34732Smarc qdrsel[qd] = 0; 184634642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 184734642Smarc } 184830391Skarels 184934642Smarc if (dga->bytcnt_lo != 0) { 185034642Smarc dga->bytcnt_lo = 0; 185134642Smarc dga->bytcnt_hi = 0; 185234642Smarc DMA_SETIGNORE(header); 185334642Smarc } 185434642Smarc return; 185530391Skarels } 185630391Skarels 185734642Smarc /* 185834642Smarc * if the DMA request queue is now becoming non-full, 185934642Smarc * wakeup "select" client. 186034642Smarc */ 186130391Skarels if (DMA_ISFULL(header)) { 1862*34732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 1863*34732Smarc selwakeup(qdrsel[qd], 0); 1864*34732Smarc qdrsel[qd] = 0; 186534642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 186634642Smarc } 186730391Skarels } 186830391Skarels 186930391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 187034642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 187130391Skarels 187234615Smarc /* check for unexpected interrupt */ 187334615Smarc if (DMA_ISEMPTY(header)) 187430391Skarels return; 187530391Skarels 187630391Skarels DMA_GETEND(header); /* update request queue indices */ 187730391Skarels 187834642Smarc /* 1879*34732Smarc * if no more DMA pending, wake up "select" client and exit 1880*34732Smarc */ 188130391Skarels if (DMA_ISEMPTY(header)) { 188230391Skarels 1883*34732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 1884*34732Smarc selwakeup(qdrsel[qd], 0); 1885*34732Smarc qdrsel[qd] = 0; 188634642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 188734642Smarc } 188830391Skarels 188934642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 189034642Smarc return; 189130391Skarels } 189230391Skarels 189334642Smarc /* 1894*34732Smarc * initiate next DMA xfer 1895*34732Smarc */ 189630391Skarels request = DMA_GETBEGIN(header); 189734615Smarc if (request->DMAtype != QDlast_DMAtype) { 189834642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 189934642Smarc adder->command = CANCEL; /* cancel adder activity */ 190034615Smarc } 190130391Skarels 190234615Smarc 190330391Skarels switch (request->DMAtype) { 190430391Skarels 190534642Smarc case DISPLIST: 190634615Smarc if (request->DMAtype != QDlast_DMAtype) { 190734615Smarc dga->csr |= DL_ENB; 190834615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 190934615Smarc } 191030391Skarels break; 191130391Skarels 191234642Smarc case PTOB: 191334615Smarc if (request->DMAtype != QDlast_DMAtype) { 191434615Smarc if (request->DMAdone & BYTE_PACK) 191534642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 191634615Smarc else { 191734615Smarc dga->csr |= PTOB_ENB; 191834615Smarc dga->csr &= ~BYTE_DMA; 191934615Smarc } 192034615Smarc } 192130391Skarels break; 192230391Skarels 192334642Smarc case BTOP: 192434615Smarc if (request->DMAtype != QDlast_DMAtype) { 192534615Smarc if (request->DMAdone & BYTE_PACK) { 192634615Smarc dga->csr &= ~DL_ENB; 192734615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 192834615Smarc } 192934615Smarc else { 193034615Smarc dga->csr |= BTOP_ENB; 193134615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 193234615Smarc } 193334615Smarc } 193430391Skarels break; 193534642Smarc default: 1936*34732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 193730391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 193830391Skarels return; 193930391Skarels } 194030391Skarels 194130391Skarels if (request->DMAdone & COUNT_ZERO) { 194234642Smarc dga->csr &= ~SET_DONE_FIFO; 194334642Smarc } 194434642Smarc else if (request->DMAdone & FIFO_EMPTY) { 194534642Smarc dga->csr |= SET_DONE_FIFO; 194630391Skarels } 194730391Skarels 194830391Skarels if (request->DMAdone & WORD_PACK) 194930391Skarels dga->csr &= ~BYTE_DMA; 195030391Skarels else if (request->DMAdone & BYTE_PACK) 195130391Skarels dga->csr |= BYTE_DMA; 195230391Skarels 195330391Skarels dga->csr |= DMA_IE; 195434642Smarc QDlast_DMAtype = request->DMAtype; 195530391Skarels 195630391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 195730391Skarels 195830391Skarels dga->adrs_lo = (short) cookie; 195930391Skarels dga->adrs_hi = (short) (cookie >> 16); 196030391Skarels 196130391Skarels dga->bytcnt_lo = (short) request->length; 196230391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 196330391Skarels 196430391Skarels return; 196530391Skarels } 196630391Skarels 1967*34732Smarc /* 1968*34732Smarc * ADDER interrupt service routine 1969*34732Smarc */ 197030391Skarels qdaint(qd) 1971*34732Smarc register qd; 197230391Skarels { 197330391Skarels register struct adder *adder; 197430391Skarels struct color_buf *cbuf; 197530391Skarels int i; 197630391Skarels register struct rgb *rgbp; 197730391Skarels register short *red; 197830391Skarels register short *green; 197930391Skarels register short *blue; 198030391Skarels 1981*34732Smarc (void)spl4(); /* allow interval timer in */ 198230391Skarels 198330391Skarels adder = (struct adder *) qdmap[qd].adder; 198430391Skarels 198534642Smarc /* 198634642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 198734642Smarc * any pending color map load request 198834642Smarc */ 198930391Skarels if (adder->status & VSYNC) { 199034642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 199134642Smarc cbuf = color_buf[qd]; 199234642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 199330391Skarels 199434642Smarc red = (short *) qdmap[qd].red; 199534642Smarc green = (short *) qdmap[qd].green; 199634642Smarc blue = (short *) qdmap[qd].blue; 199730391Skarels 199834642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 199934642Smarc --i >= 0; rgbp++) { 200034642Smarc red[rgbp->offset] = (short) rgbp->red; 200134642Smarc green[rgbp->offset] = (short) rgbp->green; 200234642Smarc blue[rgbp->offset] = (short) rgbp->blue; 200334642Smarc } 200430391Skarels 200534642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 200630391Skarels } 200730391Skarels } 200830391Skarels 200934642Smarc /* 201034642Smarc * service the scroll interrupt (FRAME_SYNC bit) 201134642Smarc */ 201230391Skarels if (adder->status & FRAME_SYNC) { 201334642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 201430391Skarels 201534642Smarc if (scroll[qd]->status & LOAD_REGS) { 201630391Skarels 2017*34732Smarc for (i = 1000, adder->status = 0; i > 0 && 2018*34732Smarc !(adder->status&ID_SCROLL_READY); --i) 201934642Smarc ; 202030391Skarels 202134642Smarc if (i == 0) { 2022*34732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 202334642Smarc qd); 202434642Smarc return; 202534642Smarc } 202630391Skarels 202734642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 202834642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 202930391Skarels 203034642Smarc adder->y_scroll_constant = 203134642Smarc scroll[qd]->y_scroll_constant; 203234642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 203330391Skarels 203434642Smarc if (scroll[qd]->status & LOAD_INDEX) { 203530391Skarels 203634642Smarc adder->x_index_pending = 203734642Smarc scroll[qd]->x_index_pending; 203834642Smarc adder->y_index_pending = 203934642Smarc scroll[qd]->y_index_pending; 204034642Smarc } 204134642Smarc 204234642Smarc scroll[qd]->status = 0x00; 204330391Skarels } 204430391Skarels } 204530391Skarels } 204630391Skarels 2047*34732Smarc /* 2048*34732Smarc * DUART input interrupt service routine 2049*34732Smarc * 2050*34732Smarc * XXX - this routine should be broken out - it is essentially 2051*34732Smarc * straight line code. 2052*34732Smarc */ 205330391Skarels 205430391Skarels qdiint(qd) 2055*34732Smarc register qd; 205630391Skarels { 205730391Skarels register struct _vs_event *event; 205830391Skarels register struct qdinput *eqh; 205930391Skarels struct dga *dga; 206030391Skarels struct duart *duart; 206130391Skarels struct mouse_report *new_rep; 206230391Skarels struct uba_device *ui; 206330391Skarels struct tty *tp; 206434615Smarc u_short chr; 206530391Skarels u_short status; 206630391Skarels u_short data; 206730391Skarels u_short key; 206830391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 206930391Skarels char a, b, c; /* mouse button test variables */ 207030391Skarels 2071*34732Smarc (void)spl4(); /* allow interval timer in */ 207230391Skarels 207330391Skarels eqh = eq_header[qd]; /* optimized as a register */ 207430391Skarels new_rep = ¤t_rep[qd]; 207530391Skarels duart = (struct duart *) qdmap[qd].duart; 207630391Skarels 207734642Smarc /* 2078*34732Smarc * if the graphic device is turned on.. 2079*34732Smarc */ 208030391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 208134642Smarc /* 208234642Smarc * empty DUART 208334642Smarc */ 2084*34732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 208534642Smarc /* 2086*34732Smarc * pick up LK-201 input (if any) 2087*34732Smarc */ 2088*34732Smarc if (duart->statusA&RCV_RDY) { 208930391Skarels 209034642Smarc /* if error condition, then reset it */ 209130391Skarels 2092*34732Smarc if (duart->statusA&0x70) { 209334642Smarc duart->cmdA = 0x40; 209434642Smarc continue; 209534642Smarc } 209630391Skarels 209734642Smarc /* event queue full now? (overflow condition) */ 209830391Skarels 209934642Smarc if (ISFULL(eqh) == TRUE) { 210034642Smarc printf( 2101*34732Smarc "qd%d: qdiint: event queue overflow\n", 210234642Smarc qd); 210334642Smarc break; 210434642Smarc } 210530391Skarels 210634642Smarc /* 210734642Smarc * Check for various keyboard errors */ 210830391Skarels 210934642Smarc key = duart->dataA & 0xFF; 211030391Skarels 211134642Smarc if (key==LK_POWER_ERROR || 211234642Smarc key==LK_KDOWN_ERROR || 211334642Smarc key == LK_INPUT_ERROR || 211434642Smarc key == LK_OUTPUT_ERROR) { 211534642Smarc printf( 2116*34732Smarc "qd%d: qdiint: keyboard error, code = %x\n", 211734642Smarc qd,key); 2118*34732Smarc return; 211934642Smarc } 212030391Skarels 212134642Smarc if (key < LK_LOWEST) 2122*34732Smarc return; 212330391Skarels 212434642Smarc ++do_wakeup; /* request a select wakeup call */ 212530391Skarels 212634642Smarc event = PUTBEGIN(eqh); 212734642Smarc PUTEND(eqh); 212830391Skarels 212934642Smarc event->vse_key = key; 213034642Smarc event->vse_key &= 0x00FF; 213134642Smarc event->vse_x = eqh->curs_pos.x; 213234642Smarc event->vse_y = eqh->curs_pos.y; 213334642Smarc event->vse_time = TOY; 213434642Smarc event->vse_type = VSE_BUTTON; 213534642Smarc event->vse_direction = VSE_KBTRAW; 213634642Smarc event->vse_device = VSE_DKB; 213734642Smarc } 213830391Skarels 213934642Smarc /* 214034642Smarc * pick up the mouse input (if any) */ 214130391Skarels 214234642Smarc if ((status = duart->statusB) & RCV_RDY && 214334642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 214430391Skarels 214534642Smarc if (status & 0x70) { 214634642Smarc duart->cmdB = 0x40; 214734642Smarc continue; 214834642Smarc } 214930391Skarels 215034642Smarc /* event queue full now? (overflow condition) */ 215130391Skarels 215234642Smarc if (ISFULL(eqh) == TRUE) { 215334642Smarc printf( 2154*34732Smarc "qd%d: qdiint: event queue overflow\n", 215534642Smarc qd); 215634642Smarc break; 215734642Smarc } 215830391Skarels 215934642Smarc data = duart->dataB; /* get report byte */ 216034642Smarc ++new_rep->bytcnt; /* bump report byte count */ 216130391Skarels 216234642Smarc /* 216334642Smarc * if 1st byte of report.. */ 216430391Skarels 216534642Smarc if ( data & START_FRAME) { 216634642Smarc new_rep->state = data; 216734642Smarc if (new_rep->bytcnt > 1) { 216834642Smarc /* start of new frame */ 216934642Smarc new_rep->bytcnt = 1; 217034642Smarc /* ..continue looking */ 217134642Smarc continue; 217234642Smarc } 217334642Smarc } 217430391Skarels 217534642Smarc /* 217634642Smarc * if 2nd byte of report.. */ 217730391Skarels 217834642Smarc else if (new_rep->bytcnt == 2) { 217934642Smarc new_rep->dx = data & 0x00FF; 218034642Smarc } 218130391Skarels 218234642Smarc /* 218334642Smarc * if 3rd byte of report, load input event queue */ 218430391Skarels 218534642Smarc else if (new_rep->bytcnt == 3) { 218630391Skarels 218734642Smarc new_rep->dy = data & 0x00FF; 218834642Smarc new_rep->bytcnt = 0; 218930391Skarels 219034642Smarc /* 219134642Smarc * if mouse position has changed.. */ 219230391Skarels 219334642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 219430391Skarels 219534642Smarc /* 219634642Smarc * calculate acceleration factor, if needed */ 219730391Skarels 219834642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 219930391Skarels 220034642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 220134642Smarc new_rep->dx += 220234642Smarc (new_rep->dx - qdflags[qd].curs_thr) 220334642Smarc * qdflags[qd].curs_acc; 220430391Skarels 220534642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 220634642Smarc new_rep->dy += 220734642Smarc (new_rep->dy - qdflags[qd].curs_thr) 220834642Smarc * qdflags[qd].curs_acc; 220934642Smarc } 221030391Skarels 221134642Smarc /* 221234642Smarc * update cursor position coordinates */ 221330391Skarels 221434642Smarc if (new_rep->state & X_SIGN) { 221534642Smarc eqh->curs_pos.x += new_rep->dx; 221634642Smarc if (eqh->curs_pos.x > 1023) 221734642Smarc eqh->curs_pos.x = 1023; 221834642Smarc } 221934642Smarc else { 222034642Smarc eqh->curs_pos.x -= new_rep->dx; 222134642Smarc if (eqh->curs_pos.x < -15) 222234642Smarc eqh->curs_pos.x = -15; 222334642Smarc } 222430391Skarels 222534642Smarc if (new_rep->state & Y_SIGN) { 222634642Smarc eqh->curs_pos.y -= new_rep->dy; 222734642Smarc if (eqh->curs_pos.y < -15) 222834642Smarc eqh->curs_pos.y = -15; 222934642Smarc } 223034642Smarc else { 223134642Smarc eqh->curs_pos.y += new_rep->dy; 223234642Smarc if (eqh->curs_pos.y > 863) 223334642Smarc eqh->curs_pos.y = 863; 223434642Smarc } 223530391Skarels 223634642Smarc /* 223734642Smarc * update cursor screen position */ 223830391Skarels 223934642Smarc dga = (struct dga *) qdmap[qd].dga; 224034642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 224134642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 224230391Skarels 224334642Smarc /* 224434642Smarc * if cursor is in the box, no event report */ 224530391Skarels 224634642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 224734642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 224834642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 224934642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 225034642Smarc goto GET_MBUTTON; 225134642Smarc } 225230391Skarels 225334642Smarc /* 225434642Smarc * report the mouse motion event */ 225530391Skarels 225634642Smarc event = PUTBEGIN(eqh); 225734642Smarc PUTEND(eqh); 225830391Skarels 225934642Smarc ++do_wakeup; /* request a select wakeup call */ 226030391Skarels 226134642Smarc event->vse_x = eqh->curs_pos.x; 226234642Smarc event->vse_y = eqh->curs_pos.y; 226330391Skarels 226434642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 226534642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 226634642Smarc event->vse_key = 0; 226734642Smarc event->vse_direction = 0; 226834642Smarc event->vse_time = TOY; /* time stamp */ 226934642Smarc } 227030391Skarels 227130391Skarels GET_MBUTTON: 227234642Smarc /* 227334642Smarc * if button state has changed */ 227430391Skarels 227534642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 227634642Smarc b = last_rep[qd].state & 0x07; 227730391Skarels 227834642Smarc if (a ^ b) { 227930391Skarels 228034642Smarc for ( c = 1; c < 8; c <<= 1) { 228130391Skarels 228234642Smarc if (!( c & (a ^ b))) /* this button change? */ 228334642Smarc continue; 228430391Skarels 228534642Smarc /* event queue full? (overflow condition) */ 228630391Skarels 228734642Smarc if (ISFULL(eqh) == TRUE) { 2288*34732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 228934642Smarc break; 229034642Smarc } 229130391Skarels 229234642Smarc event = PUTBEGIN(eqh); /* get new event */ 229334642Smarc PUTEND(eqh); 229430391Skarels 229534642Smarc ++do_wakeup; /* request select wakeup */ 229630391Skarels 229734642Smarc event->vse_x = eqh->curs_pos.x; 229834642Smarc event->vse_y = eqh->curs_pos.y; 229930391Skarels 230034642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 230134642Smarc event->vse_type = VSE_BUTTON; /* new button */ 230234642Smarc event->vse_time = TOY; /* time stamp */ 230330391Skarels 230434642Smarc /* flag changed button and if up or down */ 230530391Skarels 230634642Smarc if (c == RIGHT_BUTTON) 230734642Smarc event->vse_key = VSE_RIGHT_BUTTON; 230834642Smarc else if (c == MIDDLE_BUTTON) 230934642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 231034642Smarc else if (c == LEFT_BUTTON) 231134642Smarc event->vse_key = VSE_LEFT_BUTTON; 231230391Skarels 231334642Smarc /* set bit = button depressed */ 231430391Skarels 231534642Smarc if (c & a) 231634642Smarc event->vse_direction = VSE_KBTDOWN; 231734642Smarc else 231834642Smarc event->vse_direction = VSE_KBTUP; 231934642Smarc } 232034642Smarc } 232130391Skarels 232234642Smarc /* refresh last report */ 232330391Skarels 232434642Smarc last_rep[qd] = current_rep[qd]; 232530391Skarels 232634642Smarc } /* get last byte of report */ 2327*34732Smarc } else if ((status = duart->statusB)&RCV_RDY && 2328*34732Smarc qdflags[qd].pntr_id == TABLET_ID) { 2329*34732Smarc /* 2330*34732Smarc * pickup tablet input, if any 2331*34732Smarc */ 2332*34732Smarc if (status&0x70) { 233334642Smarc duart->cmdB = 0x40; 233434642Smarc continue; 233534642Smarc } 2336*34732Smarc /* 2337*34732Smarc * event queue full now? (overflow condition) 2338*34732Smarc */ 233934642Smarc if (ISFULL(eqh) == TRUE) { 2340*34732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 234134642Smarc break; 234234642Smarc } 234330391Skarels 234434642Smarc data = duart->dataB; /* get report byte */ 234534642Smarc ++new_rep->bytcnt; /* bump report byte count */ 234630391Skarels 234734642Smarc /* 234834642Smarc * if 1st byte of report.. */ 234930391Skarels 235034642Smarc if (data & START_FRAME) { 235134642Smarc new_rep->state = data; 235234642Smarc if (new_rep->bytcnt > 1) { 235334642Smarc new_rep->bytcnt = 1; /* start of new frame */ 235434642Smarc continue; /* ..continue looking */ 235534642Smarc } 235634642Smarc } 235730391Skarels 235834642Smarc /* 235934642Smarc * if 2nd byte of report.. */ 236030391Skarels 236134642Smarc else if (new_rep->bytcnt == 2) { 236234642Smarc new_rep->dx = data & 0x3F; 236334642Smarc } 236430391Skarels 236534642Smarc /* 236634642Smarc * if 3rd byte of report.. */ 236730391Skarels 236834642Smarc else if (new_rep->bytcnt == 3) { 236934642Smarc new_rep->dx |= (data & 0x3F) << 6; 237034642Smarc } 237130391Skarels 237234642Smarc /* 237334642Smarc * if 4th byte of report.. */ 237430391Skarels 237534642Smarc else if (new_rep->bytcnt == 4) { 237634642Smarc new_rep->dy = data & 0x3F; 237734642Smarc } 237830391Skarels 237934642Smarc /* 238034642Smarc * if 5th byte of report, load input event queue */ 238130391Skarels 238234642Smarc else if (new_rep->bytcnt == 5) { 238330391Skarels 238434642Smarc new_rep->dy |= (data & 0x3F) << 6; 238534642Smarc new_rep->bytcnt = 0; 238630391Skarels 238734642Smarc /* 238834642Smarc * update cursor position coordinates */ 238930391Skarels 239034642Smarc new_rep->dx /= qdflags[qd].tab_res; 239134642Smarc new_rep->dy = (2200 - new_rep->dy) 239234642Smarc / qdflags[qd].tab_res; 239330391Skarels 239434642Smarc if (new_rep->dx > 1023) { 239534642Smarc new_rep->dx = 1023; 239634642Smarc } 239734642Smarc if (new_rep->dy > 863) { 239834642Smarc new_rep->dy = 863; 239934642Smarc } 240030391Skarels 240134642Smarc /* 240234642Smarc * report an event if the puck/stylus has moved 240334642Smarc */ 240430391Skarels 240534642Smarc if (eqh->curs_pos.x != new_rep->dx || 240634642Smarc eqh->curs_pos.y != new_rep->dy) { 240730391Skarels 240834642Smarc eqh->curs_pos.x = new_rep->dx; 240934642Smarc eqh->curs_pos.y = new_rep->dy; 241030391Skarels 241134642Smarc /* 241234642Smarc * update cursor screen position */ 241330391Skarels 241434642Smarc dga = (struct dga *) qdmap[qd].dga; 241534642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 241634642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 241730391Skarels 241834642Smarc /* 241934642Smarc * if cursor is in the box, no event report 242034642Smarc */ 242130391Skarels 242234642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 242334642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 242434642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 242534642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 242634642Smarc goto GET_TBUTTON; 242734642Smarc } 242830391Skarels 242934642Smarc /* 243034642Smarc * report the tablet motion event */ 243130391Skarels 243234642Smarc event = PUTBEGIN(eqh); 243334642Smarc PUTEND(eqh); 243430391Skarels 243534642Smarc ++do_wakeup; /* request a select wakeup call */ 243630391Skarels 243734642Smarc event->vse_x = eqh->curs_pos.x; 243834642Smarc event->vse_y = eqh->curs_pos.y; 243930391Skarels 244034642Smarc event->vse_device = VSE_TABLET; /* tablet */ 244134642Smarc /* 244234642Smarc * right now, X handles tablet motion the same 244334642Smarc * as mouse motion 244434642Smarc */ 244534642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 244634642Smarc event->vse_key = 0; 244734642Smarc event->vse_direction = 0; 244834642Smarc event->vse_time = TOY; /* time stamp */ 244934642Smarc } 245030391Skarels GET_TBUTTON: 245134642Smarc /* 245234642Smarc * if button state has changed */ 245330391Skarels 245434642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 245534642Smarc b = last_rep[qd].state & 0x1E; 245630391Skarels 245734642Smarc if (a ^ b) { 245830391Skarels 245934642Smarc /* event queue full now? (overflow condition) */ 246030391Skarels 246134642Smarc if (ISFULL(eqh) == TRUE) { 2462*34732Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 246334642Smarc break; 246434642Smarc } 246530391Skarels 246634642Smarc event = PUTBEGIN(eqh); /* get new event */ 246734642Smarc PUTEND(eqh); 246830391Skarels 246934642Smarc ++do_wakeup; /* request a select wakeup call */ 247030391Skarels 247134642Smarc event->vse_x = eqh->curs_pos.x; 247234642Smarc event->vse_y = eqh->curs_pos.y; 247330391Skarels 247434642Smarc event->vse_device = VSE_TABLET; /* tablet */ 247534642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 247634642Smarc event->vse_time = TOY; /* time stamp */ 247730391Skarels 247834642Smarc /* define the changed button and if up or down */ 247930391Skarels 248034642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 248134642Smarc if (c & (a ^ b)) { 248234642Smarc if (c == T_LEFT_BUTTON) 248334642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 248434642Smarc else if (c == T_FRONT_BUTTON) 248534642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 248634642Smarc else if (c == T_RIGHT_BUTTON) 248734642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 248834642Smarc else if (c == T_BACK_BUTTON) 248934642Smarc event->vse_key = VSE_T_BACK_BUTTON; 249034642Smarc break; 249134642Smarc } 249234642Smarc } 249330391Skarels 249434642Smarc /* set bit = button depressed */ 249530391Skarels 249634642Smarc if (c & a) 249734642Smarc event->vse_direction = VSE_KBTDOWN; 249834642Smarc else 249934642Smarc event->vse_direction = VSE_KBTUP; 250034642Smarc } 250130391Skarels 250234642Smarc /* refresh last report */ 250330391Skarels 250434642Smarc last_rep[qd] = current_rep[qd]; 250530391Skarels 250634642Smarc } /* get last byte of report */ 250734642Smarc } /* pick up tablet input */ 250830391Skarels 250934642Smarc } /* while input available.. */ 251030391Skarels 251134642Smarc /* 251234642Smarc * do select wakeup 251334642Smarc */ 2514*34732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 2515*34732Smarc selwakeup(qdrsel[qd], 0); 2516*34732Smarc qdrsel[qd] = 0; 251734642Smarc qdflags[qd].selmask &= ~SEL_READ; 251834642Smarc do_wakeup = 0; 251934642Smarc } 2520*34732Smarc } else { 2521*34732Smarc /* 2522*34732Smarc * if the graphic device is not turned on, this is console input 2523*34732Smarc */ 252434642Smarc ui = qdinfo[qd]; 252534642Smarc if (ui == 0 || ui->ui_alive == 0) 2526*34732Smarc return; 252730391Skarels 252834642Smarc tp = &qd_tty[qd << 2]; 252930391Skarels 253034642Smarc /* 2531*34732Smarc * Get a character from the keyboard. 2532*34732Smarc */ 2533*34732Smarc while (duart->statusA&RCV_RDY) { 253434642Smarc key = duart->dataA; 253534642Smarc key &= 0xFF; 253634642Smarc /* 2537*34732Smarc * Check for various keyboard errors 2538*34732Smarc */ 2539*34732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 254034642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 2541*34732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 2542*34732Smarc return; 254334642Smarc } 254430391Skarels 254534642Smarc if (key < LK_LOWEST) 2546*34732Smarc return; 254730391Skarels 254834642Smarc /* 254934642Smarc * See if its a state change key */ 255030391Skarels 255134642Smarc switch (key) { 255230391Skarels 255334642Smarc case LOCK: 255434642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 255534642Smarc if (q_keyboard.lock) 2556*34732Smarc (void)led_control(qd, LK_LED_ENABLE, 2557*34732Smarc LK_LED_LOCK); 255834642Smarc else 2559*34732Smarc (void)led_control(qd, LK_LED_DISABLE, 2560*34732Smarc LK_LED_LOCK); 256134642Smarc return; 256230391Skarels 256334642Smarc case SHIFT: 256434642Smarc q_keyboard.shift ^= 0xFFFF; 256534642Smarc return; 256630391Skarels 256734642Smarc case CNTRL: 256834642Smarc q_keyboard.cntrl ^= 0xFFFF; 256934642Smarc return; 257030391Skarels 257134642Smarc case ALLUP: 257234642Smarc q_keyboard.cntrl = 0; 257334642Smarc q_keyboard.shift = 0; 257434642Smarc return; 257530391Skarels 257634642Smarc case REPEAT: 257734642Smarc chr = q_keyboard.last; 257834642Smarc break; 257930391Skarels 258034642Smarc /* 258134642Smarc * Test for cntrl characters. If set, see if the character 258234642Smarc * is elligible to become a control character. */ 258330391Skarels 258434642Smarc default: 258530391Skarels 258634642Smarc if (q_keyboard.cntrl) { 258734642Smarc chr = q_key[key]; 258834642Smarc if (chr >= ' ' && chr <= '~') 258934642Smarc chr &= 0x1F; 259034642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 259134642Smarc chr &= 0x9F; 259234642Smarc } 259334642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 259434642Smarc chr = q_shift_key[key]; 259534642Smarc else 259634642Smarc chr = q_key[key]; 259734642Smarc break; 259830391Skarels } 259930391Skarels 260034642Smarc q_keyboard.last = chr; 260130391Skarels 260234642Smarc /* 260334642Smarc * Check for special function keys */ 260430391Skarels 260534642Smarc if (chr & 0x100) { 260634642Smarc char *string; 260734642Smarc string = q_special[chr & 0x7F]; 260834642Smarc while(*string) 260934642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 261034615Smarc } 261134642Smarc else { 261234642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 261334642Smarc } 261430391Skarels } 261530391Skarels } 261630391Skarels } /* qdiint */ 261730391Skarels 2618*34732Smarc /* 2619*34732Smarc * 2620*34732Smarc * Clear the QDSS screen 2621*34732Smarc * 2622*34732Smarc * >>> NOTE <<< 2623*34732Smarc * 2624*34732Smarc * This code requires that certain adder initialization be valid. To 2625*34732Smarc * assure that this requirement is satisfied, this routine should be 2626*34732Smarc * called only after calling the "setup_dragon()" function. 2627*34732Smarc * 2628*34732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear 2629*34732Smarc * only clears the current displayed portion of the bitmap put a 2630*34732Smarc * temporary value in the y limit register so we can access whole 2631*34732Smarc * bitmap 2632*34732Smarc * 2633*34732Smarc */ 263430391Skarels clear_qd_screen(unit) 2635*34732Smarc int unit; 263630391Skarels { 263730391Skarels register struct adder *adder; 263830391Skarels adder = (struct adder *) qdmap[unit].adder; 263930391Skarels 264030391Skarels adder->x_limit = 1024; 264130391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 264230391Skarels adder->y_offset_pending = 0; 2643*34732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 264434642Smarc WSV; 264530391Skarels adder->y_scroll_constant = SCROLL_ERASE; 264634642Smarc WSV; 264730391Skarels adder->y_offset_pending = 864; 264834642Smarc WSV; 264930391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265034642Smarc WSV; 265130391Skarels adder->y_offset_pending = 1728; 265234642Smarc WSV; 265330391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265434642Smarc WSV; 265530391Skarels adder->y_offset_pending = 0; /* back to normal */ 265634642Smarc WSV; 265730391Skarels adder->x_limit = MAX_SCREEN_X; 265830391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 265934642Smarc #undef WSV 266030391Skarels 266130391Skarels } /* clear_qd_screen */ 266230391Skarels 2663*34732Smarc /* 2664*34732Smarc * kernel console output to the glass tty 2665*34732Smarc */ 266630391Skarels qdputc(chr) 266734642Smarc register char chr; 266830391Skarels { 266930391Skarels 267034642Smarc /* 267134642Smarc * if system is now physical, forget it (ie: crash DUMP) 267234642Smarc */ 267334642Smarc if ((mfpr(MAPEN) & 1) == 0) 267434642Smarc return; 267534615Smarc 2676*34732Smarc blitc(0, (u_char)(chr & 0xff)); 267732012Smarc if ((chr & 0177) == '\n') 267832012Smarc blitc(0, '\r'); 267930391Skarels 268030391Skarels } /* qdputc */ 268130391Skarels 2682*34732Smarc /* 2683*34732Smarc * load the mouse cursor's template RAM bitmap 2684*34732Smarc */ 268530391Skarels ldcursor(unit, bitmap) 2686*34732Smarc int unit; 2687*34732Smarc register short *bitmap; 268830391Skarels { 268930391Skarels register struct dga *dga; 269030391Skarels register short *temp; 269130391Skarels register int i; 2692*34732Smarc int curs; 269330391Skarels 269430391Skarels dga = (struct dga *) qdmap[unit].dga; 269530391Skarels temp = (short *) qdmap[unit].template; 269630391Skarels 269730391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 2698*34732Smarc curs = -1; /* ..note that.. */ 269934642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 2700*34732Smarc } else 2701*34732Smarc curs = 0; 270230391Skarels 270330391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 270430391Skarels 270530391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 270634642Smarc /* ..of the 8k WORD template space */ 270730391Skarels for (i = 0; i < 32; ++i) 270834642Smarc *temp++ = *bitmap++; 270930391Skarels 2710*34732Smarc if (curs) { /* if cursor was enabled.. */ 271134642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 271230391Skarels } 271330391Skarels 271430391Skarels } /* ldcursor */ 271530391Skarels 2716*34732Smarc /* 2717*34732Smarc * Put the console font in the QDSS off-screen memory 2718*34732Smarc */ 271930391Skarels ldfont(unit) 2720*34732Smarc int unit; 272130391Skarels { 272230391Skarels register struct adder *adder; 272330391Skarels 2724*34732Smarc register i, j, k, max_chars_line; 2725*34732Smarc register short packed; 272630391Skarels 272730391Skarels adder = (struct adder *) qdmap[unit].adder; 272830391Skarels 272934642Smarc /* 2730*34732Smarc * setup VIPER operand control registers 2731*34732Smarc */ 273230391Skarels write_ID(adder, MASK_1, 0xFFFF); 273330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 273430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 273530391Skarels 273630391Skarels write_ID(adder, SRC1_OCR_B, 273734642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 273830391Skarels write_ID(adder, SRC2_OCR_B, 273934642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 274030391Skarels write_ID(adder, DST_OCR_B, 274134642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 274230391Skarels 274330391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 274430391Skarels 274534642Smarc /* 2746*34732Smarc * load destination data 2747*34732Smarc */ 2748*34732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 274930391Skarels 275030391Skarels adder->destination_x = FONT_X; 275130391Skarels adder->destination_y = FONT_Y; 2752*34732Smarc #if FONT_WIDTH > MAX_SCREEN_X 2753*34732Smarc adder->fast_dest_dx = MAX_SCREEN_X; 2754*34732Smarc #else 2755*34732Smarc adder->fast_dest_dx = FONT_WIDTH; 2756*34732Smarc #endif 275730391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 275830391Skarels 275934642Smarc /* 276034642Smarc * setup for processor to bitmap xfer */ 276130391Skarels 276230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 276330391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 276430391Skarels 276534642Smarc /* 276634642Smarc * Figure out how many characters can be stored on one "line" of 276734642Smarc * offscreen memory. 276834642Smarc */ 276934642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 277034642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 277134642Smarc max_chars_line = CHARS/2 + CHARS%2; 277230391Skarels 277334642Smarc /* 277434642Smarc * iteratively do the processor to bitmap xfer */ 277534615Smarc 277630391Skarels for (i = 0; i < ROWS; ++i) { 277730391Skarels 277834642Smarc /* PTOB a scan line */ 277930391Skarels 278034642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 278134642Smarc /* PTOB one scan of a char cell */ 278230391Skarels 278334642Smarc packed = q_font[k]; 278434642Smarc k += ROWS; 278534642Smarc packed |= ((short)q_font[k] << 8); 278634642Smarc k += ROWS; 278730391Skarels 2788*34732Smarc (void)wait_status(adder, TX_READY); 278934642Smarc adder->id_data = packed; 279034642Smarc } 279130391Skarels } 279230391Skarels 279334642Smarc /* 279434642Smarc * (XXX XXX XXX - should remove) 279534642Smarc * 279634642Smarc * Copy the second row of characters. Subtract the first 279734642Smarc * row from the total number. Divide this quantity by 2 279834642Smarc * because 2 chars are stored in a short in the PTOB loop 279934642Smarc * below. Figure out how many characters can be stored on 280034642Smarc * one "line" of offscreen memory 280134642Smarc */ 280234642Smarc 280334642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 280434642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 280534642Smarc return; 280634642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 280734642Smarc /* Paranoia check to see if 3rd row may be needed */ 280834642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 280934615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 281034615Smarc 281134615Smarc adder->destination_x = FONT_X; 281234615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 281334615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 281434615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 281534615Smarc 281634642Smarc /* 281734642Smarc * setup for processor to bitmap xfer 281834642Smarc */ 281934615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 282034615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 282134615Smarc 282234642Smarc /* 282334642Smarc * iteratively do the processor to bitmap xfer 282434642Smarc */ 282534615Smarc for (i = 0; i < ROWS; ++i) { 282634642Smarc /* 282734642Smarc * PTOB a scan line 282834642Smarc */ 282934642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 283034642Smarc /* 283134642Smarc * PTOB one scan of a char cell 283234642Smarc */ 283334642Smarc packed = q_font[k + FONT_OFFSET]; 283434642Smarc k += ROWS; 283534642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 283634642Smarc k += ROWS; 2837*34732Smarc (void)wait_status(adder, TX_READY); 283834642Smarc adder->id_data = packed; 283934642Smarc } 284034615Smarc } 284134615Smarc 284230391Skarels } /* ldfont */ 284330391Skarels 2844*34732Smarc /* 2845*34732Smarc * Get a character from the LK201 (polled) 2846*34732Smarc */ 2847*34732Smarc qdgetc() 2848*34732Smarc { 2849*34732Smarc register short key; 2850*34732Smarc register char chr; 2851*34732Smarc register struct duart *duart; 285230391Skarels 2853*34732Smarc duart = (struct duart *) qdmap[0].duart; 2854*34732Smarc 2855*34732Smarc /* 2856*34732Smarc * Get a character from the keyboard. 2857*34732Smarc */ 2858*34732Smarc LOOP: 2859*34732Smarc while (!(duart->statusA&RCV_RDY)) 2860*34732Smarc ; 2861*34732Smarc 2862*34732Smarc key = duart->dataA; 2863*34732Smarc key &= 0xFF; 2864*34732Smarc 2865*34732Smarc /* 2866*34732Smarc * Check for various keyboard errors */ 2867*34732Smarc 2868*34732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 2869*34732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 2870*34732Smarc printf("Keyboard error, code = %x\n", key); 2871*34732Smarc return(0); 2872*34732Smarc } 2873*34732Smarc 2874*34732Smarc if (key < LK_LOWEST) 2875*34732Smarc return(0); 2876*34732Smarc 2877*34732Smarc /* 2878*34732Smarc * See if its a state change key 2879*34732Smarc */ 2880*34732Smarc switch (key) { 2881*34732Smarc 2882*34732Smarc case LOCK: 2883*34732Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 2884*34732Smarc if (q_keyboard.lock) 2885*34732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 2886*34732Smarc else 2887*34732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 2888*34732Smarc goto LOOP; 2889*34732Smarc 2890*34732Smarc case SHIFT: 2891*34732Smarc q_keyboard.shift ^= 0xFFFF; 2892*34732Smarc goto LOOP; 2893*34732Smarc 2894*34732Smarc case CNTRL: 2895*34732Smarc q_keyboard.cntrl ^= 0xFFFF; 2896*34732Smarc goto LOOP; 2897*34732Smarc 2898*34732Smarc case ALLUP: 2899*34732Smarc q_keyboard.cntrl = 0; 2900*34732Smarc q_keyboard.shift = 0; 2901*34732Smarc goto LOOP; 2902*34732Smarc 2903*34732Smarc case REPEAT: 2904*34732Smarc chr = q_keyboard.last; 2905*34732Smarc break; 2906*34732Smarc 2907*34732Smarc /* 2908*34732Smarc * Test for cntrl characters. If set, see if the character 2909*34732Smarc * is elligible to become a control character. 2910*34732Smarc */ 2911*34732Smarc default: 2912*34732Smarc 2913*34732Smarc if (q_keyboard.cntrl) { 2914*34732Smarc chr = q_key[key]; 2915*34732Smarc if (chr >= ' ' && chr <= '~') 2916*34732Smarc chr &= 0x1F; 2917*34732Smarc } 2918*34732Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 2919*34732Smarc chr = q_shift_key[key]; 2920*34732Smarc else 2921*34732Smarc chr = q_key[key]; 2922*34732Smarc break; 2923*34732Smarc } 2924*34732Smarc 2925*34732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 2926*34732Smarc return(0); /* ..then pitch it! */ 2927*34732Smarc 2928*34732Smarc q_keyboard.last = chr; 2929*34732Smarc 2930*34732Smarc /* 2931*34732Smarc * Check for special function keys */ 2932*34732Smarc 2933*34732Smarc if (chr & 0x80) /* pitch the function keys */ 2934*34732Smarc return(0); 2935*34732Smarc else 2936*34732Smarc return(chr); 2937*34732Smarc 2938*34732Smarc } /* qdgetc */ 2939*34732Smarc 2940*34732Smarc /* 2941*34732Smarc * led_control()... twiddle LK-201 LED's 2942*34732Smarc */ 294330391Skarels led_control(unit, cmd, led_mask) 2944*34732Smarc int unit, cmd, led_mask; 294530391Skarels { 2946*34732Smarc register i; 294730391Skarels register struct duart *duart; 294830391Skarels 2949*34732Smarc duart = (struct duart *)qdmap[unit].duart; 295030391Skarels 295130391Skarels for (i = 1000; i > 0; --i) { 2952*34732Smarc if (duart->statusA&XMT_RDY) { 295334642Smarc duart->dataA = cmd; 295434642Smarc break; 295534642Smarc } 295630391Skarels } 295730391Skarels for (i = 1000; i > 0; --i) { 2958*34732Smarc if (duart->statusA&XMT_RDY) { 295934642Smarc duart->dataA = led_mask; 296034642Smarc break; 296134642Smarc } 296230391Skarels } 296330391Skarels if (i == 0) 296434642Smarc return(BAD); 296530391Skarels return(GOOD); 296630391Skarels 296730391Skarels } /* led_control */ 296830391Skarels 2969*34732Smarc /* 2970*34732Smarc * scroll_up()... move the screen up one character height 2971*34732Smarc */ 297230391Skarels scroll_up(adder) 297334642Smarc register struct adder *adder; 297430391Skarels { 297534642Smarc /* 297634642Smarc * setup VIPER operand control registers 297734642Smarc */ 2978*34732Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 297930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 298030391Skarels write_ID(adder, MASK_1, 0xFFFF); 298130391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 298230391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 298330391Skarels write_ID(adder, SRC1_OCR_B, 298434642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 298530391Skarels write_ID(adder, DST_OCR_B, 298634642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 298734642Smarc /* 298834642Smarc * load DESTINATION origin and vectors 298934642Smarc */ 299030391Skarels adder->fast_dest_dy = 0; 299130391Skarels adder->slow_dest_dx = 0; 299230391Skarels adder->error_1 = 0; 299330391Skarels adder->error_2 = 0; 299430391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 299530391Skarels adder->destination_x = 0; 299630391Skarels adder->fast_dest_dx = 1024; 299730391Skarels adder->destination_y = 0; 299830391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 299934642Smarc /* 300034642Smarc * load SOURCE origin and vectors 300134642Smarc */ 300230391Skarels adder->source_1_x = 0; 300330391Skarels adder->source_1_dx = 1024; 300430391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 300530391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 300630391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 300730391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 300834642Smarc /* 300934642Smarc * do a rectangle clear of last screen line 301034642Smarc */ 301130391Skarels write_ID(adder, MASK_1, 0xffff); 301230391Skarels write_ID(adder, SOURCE, 0xffff); 301330391Skarels write_ID(adder,DST_OCR_B, 301434642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 301530391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 301630391Skarels adder->error_1 = 0; 301730391Skarels adder->error_2 = 0; 301834642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 301930391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 302030391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 3021*34732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 302230391Skarels adder->destination_x = 0; 302330391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 302430391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 302530391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 302630391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 302730391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 302830391Skarels 302930391Skarels } /* scroll_up */ 303030391Skarels 3031*34732Smarc /* 3032*34732Smarc * init shared memory pointers and structures 3033*34732Smarc */ 303430391Skarels init_shared(unit) 3035*34732Smarc register unit; 303630391Skarels { 303730391Skarels register struct dga *dga; 303830391Skarels 303930391Skarels dga = (struct dga *) qdmap[unit].dga; 304030391Skarels 304134642Smarc /* 304234642Smarc * initialize the event queue pointers and header */ 304330391Skarels 304430391Skarels eq_header[unit] = (struct qdinput *) 304534642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 304634642Smarc + (EVENT_BUFSIZE * unit)); 304730391Skarels eq_header[unit]->curs_pos.x = 0; 304830391Skarels eq_header[unit]->curs_pos.y = 0; 304930391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 305030391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 305130391Skarels eq_header[unit]->curs_box.left = 0; 305230391Skarels eq_header[unit]->curs_box.right = 0; 305330391Skarels eq_header[unit]->curs_box.top = 0; 305430391Skarels eq_header[unit]->curs_box.bottom = 0; 305534642Smarc /* 305634642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 305734642Smarc */ 305830391Skarels DMAheader[unit] = (struct DMAreq_header *) 305934642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 306034642Smarc + (DMAbuf_size * unit)); 306130391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 306234642Smarc + sizeof(struct DMAreq_header)); 306330391Skarels DMAheader[unit]->QBAreg = 0; 306430391Skarels DMAheader[unit]->status = 0; 306530391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 306630391Skarels DMAheader[unit]->used = 0; 306730391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 306830391Skarels DMAheader[unit]->oldest = 0; 306930391Skarels DMAheader[unit]->newest = 0; 307034642Smarc /* 307134642Smarc * assign a pointer to the scroll structure for this QDSS. 307234642Smarc */ 307330391Skarels scroll[unit] = (struct scroll *) 307434642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 307534642Smarc + (sizeof(struct scroll) * unit)); 307630391Skarels scroll[unit]->status = 0; 307730391Skarels scroll[unit]->viper_constant = 0; 307830391Skarels scroll[unit]->y_scroll_constant = 0; 307930391Skarels scroll[unit]->y_offset = 0; 308030391Skarels scroll[unit]->x_index_pending = 0; 308130391Skarels scroll[unit]->y_index_pending = 0; 308234642Smarc /* 308334642Smarc * assign a pointer to the color map write buffer for this QDSS 308434642Smarc */ 308530391Skarels color_buf[unit] = (struct color_buf *) 308634642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 308734642Smarc + (COLOR_BUFSIZ * unit)); 308830391Skarels color_buf[unit]->status = 0; 308930391Skarels color_buf[unit]->count = 0; 309030391Skarels 309130391Skarels } /* init_shared */ 309230391Skarels 3093*34732Smarc /* 3094*34732Smarc * init the ADDER, VIPER, bitmaps, & color map 3095*34732Smarc */ 309630391Skarels setup_dragon(unit) 3097*34732Smarc int unit; 309830391Skarels { 309930391Skarels 310030391Skarels register struct adder *adder; 310130391Skarels register struct dga *dga; 310230391Skarels short *memcsr; 3103*34732Smarc register i; 310430391Skarels short top; /* clipping/scrolling boundaries */ 310530391Skarels short bottom; 310630391Skarels short right; 310730391Skarels short left; 310830391Skarels short *red; /* color map pointers */ 310930391Skarels short *green; 311030391Skarels short *blue; 311130391Skarels 311234642Smarc /* 311334642Smarc * init for setup 311434642Smarc */ 311530391Skarels adder = (struct adder *) qdmap[unit].adder; 311630391Skarels dga = (struct dga *) qdmap[unit].dga; 311730391Skarels memcsr = (short *) qdmap[unit].memcsr; 311830391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 311930391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 312030391Skarels adder->command = CANCEL; 312134642Smarc /* 312234642Smarc * set monitor timing 312334642Smarc */ 312430391Skarels adder->x_scan_count_0 = 0x2800; 312530391Skarels adder->x_scan_count_1 = 0x1020; 312630391Skarels adder->x_scan_count_2 = 0x003A; 312730391Skarels adder->x_scan_count_3 = 0x38F0; 312830391Skarels adder->x_scan_count_4 = 0x6128; 312930391Skarels adder->x_scan_count_5 = 0x093A; 313030391Skarels adder->x_scan_count_6 = 0x313C; 313130391Skarels adder->sync_phase_adj = 0x0100; 313230391Skarels adder->x_scan_conf = 0x00C8; 313334642Smarc /* 313434642Smarc * got a bug in secound pass ADDER! lets take care of it 313534642Smarc * 313634642Smarc * normally, just use the code in the following bug fix code, but to 313734642Smarc * make repeated demos look pretty, load the registers as if there was 313834642Smarc * no bug and then test to see if we are getting sync 313934642Smarc */ 314030391Skarels adder->y_scan_count_0 = 0x135F; 314130391Skarels adder->y_scan_count_1 = 0x3363; 314230391Skarels adder->y_scan_count_2 = 0x2366; 314330391Skarels adder->y_scan_count_3 = 0x0388; 314434642Smarc /* 314534642Smarc * if no sync, do the bug fix code 314634642Smarc */ 314730391Skarels if (wait_status(adder, VSYNC) == BAD) { 314834642Smarc /* first load all Y scan registers with very short frame and 314934642Smarc * wait for scroll service. This guarantees at least one SYNC 315034642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 315134642Smarc * XCINCH with DMSEEDH) 315234642Smarc */ 315334642Smarc adder->y_scan_count_0 = 0x01; 315434642Smarc adder->y_scan_count_1 = 0x01; 315534642Smarc adder->y_scan_count_2 = 0x01; 315634642Smarc adder->y_scan_count_3 = 0x01; 315734642Smarc /* 315834642Smarc * delay at least 1 full frame time 315934642Smarc */ 3160*34732Smarc (void)wait_status(adder, VSYNC); 3161*34732Smarc (void)wait_status(adder, VSYNC); 316234642Smarc /* 316334642Smarc * now load the REAL sync values (in reverse order just to 316434642Smarc * be safe. 316534642Smarc */ 316634642Smarc adder->y_scan_count_3 = 0x0388; 316734642Smarc adder->y_scan_count_2 = 0x2366; 316834642Smarc adder->y_scan_count_1 = 0x3363; 316934642Smarc adder->y_scan_count_0 = 0x135F; 317030391Skarels } 317130391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 317234642Smarc /* 317334642Smarc * zero the index registers 317434642Smarc */ 317530391Skarels adder->x_index_pending = 0; 317630391Skarels adder->y_index_pending = 0; 317730391Skarels adder->x_index_new = 0; 317830391Skarels adder->y_index_new = 0; 317930391Skarels adder->x_index_old = 0; 318030391Skarels adder->y_index_old = 0; 318130391Skarels adder->pause = 0; 318234642Smarc /* 318334642Smarc * set rasterop mode to normal pen down 318434642Smarc */ 318530391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 318634642Smarc /* 318734642Smarc * set the rasterop registers to a default values 318834642Smarc */ 318930391Skarels adder->source_1_dx = 1; 319030391Skarels adder->source_1_dy = 1; 319130391Skarels adder->source_1_x = 0; 319230391Skarels adder->source_1_y = 0; 319330391Skarels adder->destination_x = 0; 319430391Skarels adder->destination_y = 0; 319530391Skarels adder->fast_dest_dx = 1; 319630391Skarels adder->fast_dest_dy = 0; 319730391Skarels adder->slow_dest_dx = 0; 319830391Skarels adder->slow_dest_dy = 1; 319930391Skarels adder->error_1 = 0; 320030391Skarels adder->error_2 = 0; 320134642Smarc /* 3202*34732Smarc * scale factor = UNITY 320334642Smarc */ 320430391Skarels adder->fast_scale = UNITY; 320530391Skarels adder->slow_scale = UNITY; 320634642Smarc /* 320734642Smarc * set the source 2 parameters 320834642Smarc */ 320930391Skarels adder->source_2_x = 0; 321030391Skarels adder->source_2_y = 0; 321130391Skarels adder->source_2_size = 0x0022; 321234642Smarc /* 321334642Smarc * initialize plane addresses for eight vipers 321434642Smarc */ 321530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 321630391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 321730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 321830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 321930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 322030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 322130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 322230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 322330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 322430391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 322530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 322630391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 322730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 322830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 322930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 323030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 323134642Smarc /* 323234642Smarc * initialize the external registers. 323334642Smarc */ 323430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 323530391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 323634642Smarc /* 323734642Smarc * initialize resolution mode 323834642Smarc */ 323930391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 324030391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 324134642Smarc /* 324234642Smarc * initialize viper registers 324334642Smarc */ 324430391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 324530391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 324634642Smarc /* 324734642Smarc * set clipping and scrolling limits to full screen 324834642Smarc */ 3249*34732Smarc for (i = 1000, adder->status = 0; 3250*34732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 325134642Smarc ; 325230391Skarels if (i == 0) 3253*34732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 325430391Skarels top = 0; 325530391Skarels bottom = 2048; 325630391Skarels left = 0; 325730391Skarels right = 1024; 325830391Skarels adder->x_clip_min = left; 325930391Skarels adder->x_clip_max = right; 326030391Skarels adder->y_clip_min = top; 326130391Skarels adder->y_clip_max = bottom; 326230391Skarels adder->scroll_x_min = left; 326330391Skarels adder->scroll_x_max = right; 326430391Skarels adder->scroll_y_min = top; 326530391Skarels adder->scroll_y_max = bottom; 3266*34732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 3267*34732Smarc (void)wait_status(adder, VSYNC); 326830391Skarels adder->x_index_pending = left; 326930391Skarels adder->y_index_pending = top; 327030391Skarels adder->x_index_new = left; 327130391Skarels adder->y_index_new = top; 327230391Skarels adder->x_index_old = left; 327330391Skarels adder->y_index_old = top; 327430391Skarels 3275*34732Smarc for (i = 1000, adder->status = 0; i > 0 && 3276*34732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 327734642Smarc ; 327830391Skarels if (i == 0) 3279*34732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 328030391Skarels 328130391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 328230391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 328334642Smarc /* 328434642Smarc * set source and the mask register to all ones (ie: white) o 328534642Smarc */ 328630391Skarels write_ID(adder, SOURCE, 0xFFFF); 328730391Skarels write_ID(adder, MASK_1, 0xFFFF); 328830391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 328930391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 329034642Smarc /* 329134642Smarc * initialize Operand Control Register banks for fill command 329234642Smarc */ 329330391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 329430391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 329530391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 329630391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 329730391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 329830391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 329934642Smarc /* 330034642Smarc * init Logic Unit Function registers, (these are just common values, 330134642Smarc * and may be changed as required). 330234642Smarc */ 330330391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 330434642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 330534642Smarc INV_M1_M2); 330630391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 330730391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 330834642Smarc /* 330934642Smarc * load the color map for black & white 331034642Smarc */ 3311*34732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 331234642Smarc ; 331330391Skarels 331430391Skarels if (i == 0) 3315*34732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 331630391Skarels 331730391Skarels red = (short *) qdmap[unit].red; 331830391Skarels green = (short *) qdmap[unit].green; 331930391Skarels blue = (short *) qdmap[unit].blue; 332030391Skarels 332130391Skarels *red++ = 0x00; /* black */ 332230391Skarels *green++ = 0x00; 332330391Skarels *blue++ = 0x00; 332430391Skarels 332530391Skarels *red-- = 0xFF; /* white */ 332630391Skarels *green-- = 0xFF; 332730391Skarels *blue-- = 0xFF; 332830391Skarels 332934642Smarc /* 3330*34732Smarc * set color map for mouse cursor 3331*34732Smarc */ 333230391Skarels 333330391Skarels red += 254; 333430391Skarels green += 254; 333530391Skarels blue += 254; 333630391Skarels 333730391Skarels *red++ = 0x00; /* black */ 333830391Skarels *green++ = 0x00; 333930391Skarels *blue++ = 0x00; 334030391Skarels 334130391Skarels *red = 0xFF; /* white */ 334230391Skarels *green = 0xFF; 334330391Skarels *blue = 0xFF; 334430391Skarels 334530391Skarels } /* setup_dragon */ 334630391Skarels 3347*34732Smarc /* 3348*34732Smarc * Init the DUART and set defaults in input 3349*34732Smarc */ 335030391Skarels setup_input(unit) 3351*34732Smarc int unit; 335230391Skarels { 335330391Skarels register struct duart *duart; /* DUART register structure pointer */ 3354*34732Smarc register i, bits; 335530391Skarels char id_byte; 335630391Skarels 335730391Skarels duart = (struct duart *) qdmap[unit].duart; 335830391Skarels duart->imask = 0; 335930391Skarels 336034642Smarc /* 336134642Smarc * setup the DUART for kbd & pointing device 336234642Smarc */ 3363*34732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 3364*34732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 3365*34732Smarc /* no RTS control,char error mode */ 3366*34732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 3367*34732Smarc /* no RTS control,no echo or loop */ 3368*34732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 3369*34732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 3370*34732Smarc /* ..no RTS cntrl, char error mode */ 3371*34732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 3372*34732Smarc /* no RTS control,no echo or loop */ 3373*34732Smarc duart->auxctl = 0x00; /* baud rate set 1 */ 3374*34732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */ 3375*34732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */ 337630391Skarels 337730391Skarels /* reset everything for keyboard */ 337830391Skarels 337930391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 338034642Smarc duart->cmdA = bits; 338130391Skarels 338230391Skarels /* reset everything for host */ 338330391Skarels 338430391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 338534642Smarc duart->cmdB = bits; 338630391Skarels 338730391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 338830391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 338930391Skarels 339034642Smarc /* 3391*34732Smarc * init keyboard defaults (DUART channel A) 3392*34732Smarc */ 339330391Skarels for (i = 500; i > 0; --i) { 3394*34732Smarc if (duart->statusA&XMT_RDY) { 339534642Smarc duart->dataA = LK_DEFAULTS; 339634642Smarc break; 339734642Smarc } 339830391Skarels } 339930391Skarels 340030391Skarels for (i = 100000; i > 0; --i) { 3401*34732Smarc if (duart->statusA&RCV_RDY) { 340234642Smarc break; 340334642Smarc } 340430391Skarels } 340530391Skarels 3406*34732Smarc if (duart->dataA) /* flush the ACK */ 3407*34732Smarc ; 340830391Skarels 340934642Smarc /* 3410*34732Smarc * identify the pointing device 3411*34732Smarc */ 341230391Skarels for (i = 500; i > 0; --i) { 3413*34732Smarc if (duart->statusB&XMT_RDY) { 341434642Smarc duart->dataB = SELF_TEST; 341534642Smarc break; 341634642Smarc } 341730391Skarels } 341830391Skarels 341934642Smarc /* 342030391Skarels * wait for 1st byte of self test report */ 342130391Skarels 342230391Skarels for (i = 100000; i > 0; --i) { 3423*34732Smarc if (duart->statusB&RCV_RDY) { 342434642Smarc break; 342534642Smarc } 342630391Skarels } 342730391Skarels 342830391Skarels if (i == 0) { 3429*34732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 343034642Smarc ,unit); 343134642Smarc goto OUT; 343230391Skarels } 343330391Skarels 3434*34732Smarc if (duart->dataB) 3435*34732Smarc ; 343630391Skarels 343734642Smarc /* 3438*34732Smarc * wait for ID byte of self test report 3439*34732Smarc */ 344030391Skarels for (i = 100000; i > 0; --i) { 3441*34732Smarc if (duart->statusB&RCV_RDY) { 344234642Smarc break; 344334642Smarc } 344430391Skarels } 344530391Skarels 344630391Skarels if (i == 0) { 3447*34732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 344834642Smarc goto OUT; 344930391Skarels } 345030391Skarels 345130391Skarels id_byte = duart->dataB; 345230391Skarels 345334642Smarc /* 3454*34732Smarc * wait for other bytes to come in 3455*34732Smarc */ 345630391Skarels for (i = 100000; i > 0; --i) { 3457*34732Smarc if (duart->statusB & RCV_RDY) { 3458*34732Smarc if (duart->dataB) 3459*34732Smarc ; 346034642Smarc break; 346134642Smarc } 346230391Skarels } 346330391Skarels if (i == 0) { 3464*34732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 346534642Smarc goto OUT; 346630391Skarels } 346730391Skarels for (i = 100000; i > 0; --i) { 3468*34732Smarc if (duart->statusB&RCV_RDY) { 3469*34732Smarc if (duart->dataB) 3470*34732Smarc ; 347134642Smarc break; 347234642Smarc } 347330391Skarels } 347430391Skarels if (i == 0) { 3475*34732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 347634642Smarc goto OUT; 347730391Skarels } 347834642Smarc /* 3479*34732Smarc * flag pointing device type and set defaults 3480*34732Smarc */ 3481*34732Smarc for (i=100000; i>0; --i) 3482*34732Smarc ; /*XXX*/ 348330391Skarels 348430391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 348534642Smarc qdflags[unit].pntr_id = MOUSE_ID; 348630391Skarels 348734642Smarc for (i = 500; i > 0; --i) { 3488*34732Smarc if (duart->statusB&XMT_RDY) { 348934642Smarc duart->dataB = INC_STREAM_MODE; 349034642Smarc break; 349134642Smarc } 349230391Skarels } 349334642Smarc } 349434642Smarc else { 349534642Smarc qdflags[unit].pntr_id = TABLET_ID; 349630391Skarels 349734642Smarc for (i = 500; i > 0; --i) { 3498*34732Smarc if (duart->statusB&XMT_RDY) { 349934642Smarc duart->dataB = T_STREAM; 350034642Smarc break; 350134642Smarc } 350230391Skarels } 350330391Skarels } 350430391Skarels OUT: 350530391Skarels duart->imask = qdflags[unit].duart_imask; 350630391Skarels 350730391Skarels } /* setup_input */ 350830391Skarels 3509*34732Smarc /* 3510*34732Smarc * delay for at least one display frame time 3511*34732Smarc * 3512*34732Smarc * return: BAD means that we timed out without ever seeing the 3513*34732Smarc * vertical sync status bit 3514*34732Smarc * GOOD otherwise 3515*34732Smarc */ 351630391Skarels wait_status(adder, mask) 351734642Smarc register struct adder *adder; 351834642Smarc register int mask; 351930391Skarels { 3520*34732Smarc register i; 352130391Skarels 3522*34732Smarc for (i = 10000, adder->status = 0 ; i > 0 && 3523*34732Smarc !(adder->status&mask) ; --i) 352434642Smarc ; 352530391Skarels 352630391Skarels if (i == 0) { 3527*34732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 352834642Smarc return(BAD); 352930391Skarels } 353030391Skarels 353130391Skarels return(GOOD); 353230391Skarels 353330391Skarels } /* wait_status */ 353430391Skarels 3535*34732Smarc /* 3536*34732Smarc * write out onto the ID bus 3537*34732Smarc */ 353830391Skarels write_ID(adder, adrs, data) 353934642Smarc register struct adder *adder; 354034642Smarc register short adrs; 354134642Smarc register short data; 354230391Skarels { 3543*34732Smarc register i; 354430391Skarels 3545*34732Smarc for (i = 100000, adder->status = 0 ; 3546*34732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 354734642Smarc ; 354830391Skarels 354930391Skarels if (i == 0) 3550*34732Smarc goto ERR; 355130391Skarels 3552*34732Smarc for (i = 100000, adder->status = 0 ; 3553*34732Smarc i > 0 && !(adder->status&TX_READY) ; --i) 355434642Smarc ; 355530391Skarels 355630391Skarels if (i > 0) { 355734642Smarc adder->id_data = data; 355834642Smarc adder->command = ID_LOAD | adrs; 3559*34732Smarc return ; 356030391Skarels } 356130391Skarels 356230391Skarels ERR: 3563*34732Smarc printf("write_ID: timeout trying to write to VIPER\n"); 3564*34732Smarc return ; 356530391Skarels 356630391Skarels } /* write_ID */ 356734511Smarc #endif 3568