134511Smarc /* 235353Sbostic * Copyright (c) 1988 Regents of the University of California. 335353Sbostic * All rights reserved. 435353Sbostic * 544551Sbostic * %sccs.include.redist.c% 635353Sbostic * 7*49759Smarc * @(#)qd.c 1.18 (Berkeley) 05/16/91 835353Sbostic */ 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 3945804Sbostic #include "../include/pte.h" 4045804Sbostic #include "../include/mtpr.h" 4145804Sbostic #include "sys/param.h" 4245804Sbostic #include "../include/cpu.h" 4345804Sbostic #include "sys/conf.h" 4445804Sbostic #include "sys/user.h" 4534642Smarc #include "qdioctl.h" 4645804Sbostic #include "sys/tty.h" 4745804Sbostic #include "sys/map.h" 4845804Sbostic #include "sys/buf.h" 4945804Sbostic #include "sys/vm.h" 5045804Sbostic #include "sys/clist.h" 5145804Sbostic #include "sys/file.h" 5245804Sbostic #include "sys/uio.h" 5345804Sbostic #include "sys/kernel.h" 5445804Sbostic #include "sys/exec.h" 5545804Sbostic #include "sys/proc.h" 5634642Smarc #include "ubareg.h" 5734642Smarc #include "ubavar.h" 5845804Sbostic #include "sys/syslog.h" 5934642Smarc #include "qduser.h" /* definitions shared with user level client */ 6034615Smarc #include "qdreg.h" /* QDSS device register structures */ 6132012Smarc 6234642Smarc /* 6334642Smarc * QDSS driver status flags for tracking operational state 6434642Smarc */ 6534642Smarc struct qdflags { 6634642Smarc u_int inuse; /* which minor dev's are in use now */ 6734642Smarc u_int config; /* I/O page register content */ 6834642Smarc u_int mapped; /* user mapping status word */ 6934642Smarc u_int kernel_loop; /* if kernel console is redirected */ 7034642Smarc u_int user_dma; /* DMA from user space in progress */ 7134642Smarc u_short pntr_id; /* type code of pointing device */ 7234642Smarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 7334642Smarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 7434642Smarc u_short curs_acc; /* cursor acceleration factor */ 7534642Smarc u_short curs_thr; /* cursor acceleration threshold level */ 7634642Smarc u_short tab_res; /* tablet resolution factor */ 7734642Smarc u_short selmask; /* mask for active qd select entries */ 7834642Smarc }; 7932012Smarc 8034642Smarc /* 8134642Smarc * bit definitions for 'inuse' entry 8234642Smarc */ 8332012Smarc #define CONS_DEV 0x01 8432012Smarc #define GRAPHIC_DEV 0x04 8532012Smarc 8634642Smarc /* 8734642Smarc * bit definitions for 'mapped' member of flag structure 8834642Smarc */ 8932012Smarc #define MAPDEV 0x01 /* hardware is mapped */ 9032012Smarc #define MAPDMA 0x02 /* DMA buffer mapped */ 9132012Smarc #define MAPEQ 0x04 /* event queue buffer mapped */ 9232012Smarc #define MAPSCR 0x08 /* scroll param area mapped */ 9332012Smarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 9432012Smarc 9534642Smarc /* 9634642Smarc * bit definitions for 'selmask' member of qdflag structure 9734642Smarc */ 9832012Smarc #define SEL_READ 0x01 /* read select is active */ 9932012Smarc #define SEL_WRITE 0x02 /* write select is active */ 10032012Smarc 10134642Smarc /* 10234732Smarc * constants used in shared memory operations 10334732Smarc */ 10432012Smarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 10532012Smarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 10634642Smarc / sizeof(struct _vs_event) ) 10734527Smarc #define DMA_BUFSIZ (1024 * 10) 10832012Smarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 10932012Smarc 11034642Smarc /* 11134732Smarc * reference to an array of "uba_device" structures built by the auto 11234732Smarc * configuration program. The uba_device structure decribes the device 11334732Smarc * sufficiently for the driver to talk to it. The auto configuration code 11434732Smarc * fills in the uba_device structures (located in ioconf.c) from user 11534732Smarc * maintained info. 11634732Smarc */ 11734642Smarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 11834642Smarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 11934732Smarc extern char qvmem[][128*NBPG]; 12034642Smarc extern struct pte QVmap[][128]; 12134642Smarc #define CHUNK (64 * 1024) 12234642Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 12332012Smarc 12434642Smarc /* 12534642Smarc * static storage used by multiple functions in this code 12634642Smarc */ 12734642Smarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 12834642Smarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 12934642Smarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 13034642Smarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 13134642Smarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 13234642Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 13332012Smarc 13434642Smarc /* 13534732Smarc * the array "event_shared[]" is made up of a number of event queue buffers 13634732Smarc * equal to the number of QDSS's configured into the running kernel (NQD). 13734732Smarc * Each event queue buffer begins with an event queue header (struct qdinput) 13834732Smarc * followed by a group of event queue entries (struct _vs_event). The array 13934732Smarc * "*eq_header[]" is an array of pointers to the start of each event queue 14034732Smarc * buffer in "event_shared[]". 14134732Smarc */ 14232012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 14332012Smarc 14434642Smarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 14534642Smarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 14632012Smarc 14734642Smarc /* 14834732Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 14934732Smarc * buffers. Each buffer must consume an integral number of memory pages to 15034732Smarc * guarantee that a following buffer will begin on a page boundary. Also, 15134732Smarc * enough space is allocated so that the FIRST I/O buffer can start at the 15234732Smarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 15334732Smarc * memory protections can be turned on/off for individual buffers. 15434732Smarc */ 15532012Smarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 15632012Smarc 15734642Smarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 15834642Smarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 15932012Smarc 16034642Smarc /* 16134732Smarc * The driver assists a client in scroll operations by loading dragon 16234732Smarc * registers from an interrupt service routine. The loading is done using 16334732Smarc * parameters found in memory shrade between the driver and it's client. 16434732Smarc * The scroll parameter structures are ALL loacted in the same memory page 16534732Smarc * for reasons of memory economy. 16634732Smarc */ 16734642Smarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 16834642Smarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 16932012Smarc 17034642Smarc /* 17134732Smarc * the driver is programmable to provide the user with color map write 17234732Smarc * services at VSYNC interrupt time. At interrupt time the driver loads 17334732Smarc * the color map with any user-requested load data found in shared memory 17434732Smarc */ 17532012Smarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 17632012Smarc 17734642Smarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 17834642Smarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 17932012Smarc 18034642Smarc /* 18134732Smarc * mouse input event structures 18234732Smarc */ 18334642Smarc struct mouse_report last_rep[NQD]; 18434642Smarc struct mouse_report current_rep[NQD]; 18532012Smarc 18634732Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 18734642Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 18834642Smarc int qdcount = 0; /* count of successfully probed qd's */ 18934642Smarc int nNQD = NQD; 19034642Smarc int DMAbuf_size = DMA_BUFSIZ; 19134642Smarc int QDlast_DMAtype; /* type of the last DMA operation */ 19232012Smarc 19334642Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 19434642Smarc /* 19534732Smarc * macro to get system time. Used to time stamp event queue entries 19634732Smarc */ 19730391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 19830391Skarels 19934642Smarc int qdprobe(); 20034642Smarc int qdattach(); 20134642Smarc int qddint(); /* DMA gate array intrpt service */ 20234642Smarc int qdaint(); /* Dragon ADDER intrpt service */ 20334642Smarc int qdiint(); 20430391Skarels 20534642Smarc u_short qdstd[] = { 0 }; 20630391Skarels 20734642Smarc struct uba_driver qddriver = { 20834732Smarc qdprobe, /* device probe entry */ 20934732Smarc 0, /* no slave device */ 21034732Smarc qdattach, /* device attach entry */ 21134732Smarc 0, /* no "fill csr/ba to start" */ 21234642Smarc qdstd, /* device addresses */ 21334642Smarc "qd", /* device name string */ 21434642Smarc qdinfo /* ptr to QDSS's uba_device struct */ 21534642Smarc }; 21630391Skarels 21734615Smarc #define QDPRIOR (PZERO-1) /* must be negative */ 21830391Skarels #define FALSE 0 21930391Skarels #define TRUE ~FALSE 22030391Skarels #define BAD -1 22130391Skarels #define GOOD 0 22230391Skarels 22334642Smarc /* 22434642Smarc * macro to create a system virtual page number from system virtual adrs 22534642Smarc */ 22634642Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 22730391Skarels 22834642Smarc /* 22934642Smarc * QDSS register address offsets from start of QDSS address space 23034642Smarc */ 23130391Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 23230391Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 23330391Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 23430391Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 23530391Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 23630391Skarels #define ADDER (REGSTART+0x000) 23730391Skarels #define DGA (REGSTART+0x200) 23830391Skarels #define DUART (REGSTART+0x400) 23930391Skarels #define MEMCSR (REGSTART+0x800) 24030391Skarels #define CLRSIZE (3 * 512) /* color map size */ 24130391Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 24234642Smarc /* 0x0C00 really */ 24330391Skarels #define RED (CLRSTART+0x000) 24430391Skarels #define BLUE (CLRSTART+0x200) 24530391Skarels #define GREEN (CLRSTART+0x400) 24630391Skarels 24730391Skarels 24834642Smarc /* 24934642Smarc * QDSS minor device numbers. The *real* minor device numbers are in 25034642Smarc * the bottom two bits of the major/minor device spec. Bits 2 and up are 25134642Smarc * used to specify the QDSS device number (ie: which one?) 25234642Smarc */ 25330391Skarels 25430391Skarels #define CONS 0 25530391Skarels #define GRAPHIC 2 25630391Skarels 25734642Smarc /* 25834642Smarc * console cursor bitmap (white block cursor) 25934642Smarc */ 26034642Smarc short cons_cursor[32] = { 26134642Smarc /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 26234642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 26334642Smarc /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 26434642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 26534642Smarc }; 26630391Skarels 26734642Smarc /* 26834642Smarc * constants used in font operations 26934642Smarc */ 27034615Smarc #define CHARS 190 /* # of chars in the font */ 27130391Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 27230391Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 27330391Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 27430391Skarels #define ROWS CHAR_HEIGHT 27530391Skarels #define FONT_X 0 /* font's off screen adrs */ 27630391Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 27730391Skarels 27834642Smarc /* Offset to second row characters (XXX - should remove) */ 27934615Smarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 28030391Skarels 28134642Smarc extern char q_font[]; /* reference font object code */ 28234642Smarc extern u_short q_key[]; /* reference key xlation tables */ 28334642Smarc extern u_short q_shift_key[]; 28434642Smarc extern char *q_special[]; 28530391Skarels 28634642Smarc /* 28734642Smarc * definitions for cursor acceleration reporting 28834642Smarc */ 28930391Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 29030391Skarels 29134642Smarc /* 29234642Smarc * virtual console support. 29334642Smarc */ 29434642Smarc extern (*v_putc)(); 29540817Smarc #ifdef KADB 29640817Smarc extern (*v_getc)(); 29740817Smarc extern (*v_poll)(); 29840817Smarc #endif 29934642Smarc extern struct cdevsw *consops; 30034642Smarc int qdputc(); 30140817Smarc int qdgetc(); 30240817Smarc int qdpoll(); 30334642Smarc int qdstart(); 30440817Smarc int qdpolling = 0; 30530391Skarels 30634642Smarc /* 30734642Smarc * LK-201 state storage for input console keyboard conversion to ASCII 30834642Smarc */ 30934642Smarc struct q_keyboard { 31034642Smarc int shift; /* state variables */ 31134642Smarc int cntrl; 31234642Smarc int lock; 31334642Smarc int lastcode; /* last keycode typed */ 31434642Smarc unsigned kup[8]; /* bits for each keycode*/ 31534642Smarc unsigned dkeys[8]; /* down/up mode keys */ 31634642Smarc char last; /* last character */ 31734642Smarc } q_keyboard; 31830391Skarels 31934642Smarc /* 32034642Smarc * tty settings on first open 32134642Smarc */ 32240817Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL) 32334615Smarc #define OFLAG (OPOST|OXTABS|ONLCR) 32440817Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN) 32534615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 32634615Smarc 32734732Smarc /* 32834732Smarc * Init QDSS as console (before probe routine) 32934732Smarc */ 33030391Skarels 33130391Skarels qdcons_init() 33230391Skarels { 33334732Smarc register unit; 33430391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 33534615Smarc u_int mapix; /* index into QVmap[] array */ 33634615Smarc struct percpu *pcpu; /* pointer to cpusw structure */ 33734615Smarc register struct qbus *qb; 33830391Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 33930391Skarels u_short *devptr; /* vitual device space */ 34034615Smarc extern cnputc(); 34130391Skarels 34230391Skarels #define QDSSCSR 0x1F00 34330391Skarels 34432012Smarc if (v_putc != cnputc) 34534732Smarc return 0; 34632012Smarc 34730391Skarels unit = 0; 34830391Skarels 34934642Smarc /* 35034642Smarc * find the cpusw entry that matches this machine. 35134642Smarc */ 35232012Smarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 35332012Smarc ; 35432012Smarc if (pcpu == NULL) 35534732Smarc return 0; 35636705Stef if (pcpu->pc_io->io_type != IO_QBUS) 35736705Stef return 0; 35830391Skarels 35932012Smarc /* 36034615Smarc * Map device registers - the last 8K of qvmem. 36132012Smarc */ 36232012Smarc qb = (struct qbus *)pcpu->pc_io->io_details; 36332012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 36434732Smarc UBAIOPAGES * NBPG); 36532012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 36630391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 36734732Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 36834732Smarc return 0; 36934615Smarc 37032012Smarc /* 37132012Smarc * Map q-bus memory used by qdss. (separate map) 37232012Smarc */ 37332012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 37432012Smarc phys_adr = qb->qb_maddr + mapix; 37532012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 37630391Skarels 37732012Smarc /* 37832012Smarc * tell QDSS which Q memory address base to decode 37934642Smarc * (shifted right 16 bits - its in 64K units) 38032012Smarc */ 38132012Smarc *qdaddr = (u_short)((int)mapix >> 16); 38230391Skarels qdflags[unit].config = *(u_short *)qdaddr; 38330391Skarels 38434642Smarc /* 38534642Smarc * load qdmap struct with the virtual addresses of the QDSS elements 38634642Smarc */ 38734615Smarc qdbase[unit] = (caddr_t) (qvmem[0]); 38830391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 38930391Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 39030391Skarels qdmap[unit].dga = qdbase[unit] + DGA; 39130391Skarels qdmap[unit].duart = qdbase[unit] + DUART; 39230391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 39330391Skarels qdmap[unit].red = qdbase[unit] + RED; 39430391Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 39530391Skarels qdmap[unit].green = qdbase[unit] + GREEN; 39630391Skarels 39730391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 39830391Skarels 39934642Smarc /* 40034642Smarc * init the QDSS 40134642Smarc */ 40234642Smarc /* 40332012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 40434642Smarc (char *)qdbase[0], qdmap[0].memcsr); 40534642Smarc */ 40632012Smarc 40730391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 40830391Skarels 40930391Skarels cursor[unit].x = 0; 41030391Skarels cursor[unit].y = 0; 41130391Skarels init_shared(unit); /* init shared memory */ 41230391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 41330391Skarels clear_qd_screen(unit); /* clear the screen */ 41430391Skarels ldfont(unit); /* load the console font */ 41530391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 41630391Skarels setup_input(unit); /* init the DUART */ 41734642Smarc v_putc = qdputc; /* kernel console output to qdss */ 41840817Smarc #ifdef KADB 41940817Smarc v_getc = qdgetc; /* kernel console input from qdss */ 42040817Smarc v_poll = qdpoll; /* kdb hook to disable char intr */ 42140817Smarc #endif 42234642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 42334732Smarc return 1; 42430391Skarels 42530391Skarels } /* qdcons_init */ 42630391Skarels 42734732Smarc /* 42834732Smarc * Configure QDSS into Q memory and make it intrpt. 42934732Smarc * 43034732Smarc * side effects: QDSS gets mapped into Qbus memory space at the first 43134732Smarc * vacant 64kb boundary counting back from the top of 43234732Smarc * Qbus memory space (qvmem+4mb) 43334732Smarc * 43434732Smarc * return: QDSS bus request level and vector address returned in 43534732Smarc * registers by UNIX convention. 43634732Smarc * 43734732Smarc */ 43830391Skarels qdprobe(reg) 43934732Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 44030391Skarels { 44140817Smarc register int br, cvec; 44230391Skarels register int unit; 44330391Skarels struct dga *dga; /* pointer to gate array structure */ 44434732Smarc int vector; 44534732Smarc #ifdef notdef 44630391Skarels int *ptep; /* page table entry pointer */ 44730391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 44830391Skarels u_int mapix; 44934732Smarc #endif 45030391Skarels 45134732Smarc #ifdef lint 45234732Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 45334732Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 45434732Smarc #endif 45534732Smarc 45634642Smarc /* 45734642Smarc * calculate board unit number from I/O page register address 45834642Smarc */ 45930391Skarels unit = (int) (((int)reg >> 1) & 0x0007); 46030391Skarels 46134642Smarc /* 46234642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 46334642Smarc * physical boundary. The Qbus memory space is mapped into 46434642Smarc * the system memory space at config time. After config 46534642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 46634642Smarc * of the start of Qbus memory. The Qbus memory page table 46734642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 46834642Smarc * which is also loaded at config time. These are the 46934642Smarc * variables used below to find a vacant 64kb boundary in 47034642Smarc * Qbus memory, and load it's corresponding physical adrs 47134642Smarc * into the QDSS's I/O page CSR. 47234642Smarc */ 47330391Skarels 47434615Smarc /* 47534615Smarc * Only if QD is the graphics device. 47634615Smarc */ 47734615Smarc 47830391Skarels /* if this QDSS is NOT the console, then do init here.. */ 47930391Skarels 48034615Smarc if (unit != 0) { 48134615Smarc printf("qd: can't support two qdss's (yet)\n"); 48234732Smarc #ifdef notdef /* can't test */ 48334642Smarc if (v_consputc != qdputc || unit != 0) { 48430391Skarels 48534642Smarc /* 48634642Smarc * read QDSS config info 48734642Smarc */ 48834642Smarc qdflags[unit].config = *(u_short *)reg; 48934615Smarc 49034642Smarc /* 49134642Smarc * find an empty 64kb adrs boundary 49234642Smarc */ 49330391Skarels 49434642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 49530391Skarels 49634642Smarc /* 49734732Smarc * find the cpusw entry that matches this machine. 49834732Smarc */ 49934642Smarc cpup = &cpusw[cpu]; 50034732Smarc while (!(BADADDR(qdbase[unit], sizeof(short)))) 50134732Smarc qdbase[unit] -= CHUNK; 50234615Smarc 50334642Smarc /* 50434732Smarc * tell QDSS which Q memory address base to decode 50534732Smarc */ 50634642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 50734642Smarc ptep = (int *) QVmap[0] + mapix; 50834642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 50934642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 51034615Smarc 51134642Smarc /* 51234642Smarc * load QDSS adrs map with system addresses 51334642Smarc * of device regs 51434642Smarc */ 51534642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART; 51634642Smarc qdmap[unit].adder = qdbase[unit] + ADDER; 51734642Smarc qdmap[unit].dga = qdbase[unit] + DGA; 51834642Smarc qdmap[unit].duart = qdbase[unit] + DUART; 51934642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 52034642Smarc qdmap[unit].red = qdbase[unit] + RED; 52134642Smarc qdmap[unit].blue = qdbase[unit] + BLUE; 52234642Smarc qdmap[unit].green = qdbase[unit] + GREEN; 52330391Skarels 52434642Smarc /* device init */ 52534615Smarc 52634642Smarc cursor[unit].x = 0; 52734642Smarc cursor[unit].y = 0; 52834642Smarc init_shared(unit); /* init shared memory */ 52934642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */ 53034642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */ 53134642Smarc setup_input(unit); /* init the DUART */ 53234642Smarc clear_qd_screen(unit); 53334642Smarc ldfont(unit); /* load the console font */ 53430391Skarels 53534642Smarc /* once only: turn on sync */ 53630391Skarels 53734642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON; 53834642Smarc } 53934615Smarc #endif /*notdef*/ 54030391Skarels } 54130391Skarels 54234642Smarc /* 54334642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 54434642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 54534642Smarc * vectors from the vector pool, and then continue 54634642Smarc * to take them until we get a xx0 HEX vector. The 54734642Smarc * pool provides vectors in contiguous decending 54834642Smarc * order. 54934642Smarc */ 55030391Skarels 55130391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 55230391Skarels 55334642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */ 55434642Smarc /* ..take another vector */ 55534642Smarc vector = (uba_hd[0].uh_lastiv -= 4); 55630391Skarels } 55730391Skarels 55834642Smarc /* 55934642Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 56034642Smarc */ 56130391Skarels dga = (struct dga *) qdmap[unit].dga; 56234642Smarc dga->csr = (short) HALT; /* disable everything */ 56334642Smarc dga->ivr = (short) vector; /* load intrpt base vector */ 56434642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 56530391Skarels dga->bytcnt_hi = (short) 0; 56630391Skarels 56734642Smarc /* 56834642Smarc * turn on DMA interrupts 56934642Smarc */ 57030391Skarels dga->csr &= ~SET_DONE_FIFO; 57130391Skarels dga->csr |= DMA_IE | DL_ENB; 57230391Skarels 57330391Skarels DELAY(20000); /* wait for the intrpt */ 57430391Skarels dga->csr = HALT; /* stop the wheels */ 57530391Skarels 57630391Skarels if (cvec != vector) /* if vector != base vector.. */ 57734732Smarc return(0); /* ..return = 'no device' */ 57830391Skarels 57934615Smarc /* 58034642Smarc * score this as an existing qdss 58134642Smarc */ 58234615Smarc qdcount++; 58334615Smarc 58430391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 58530391Skarels 58630391Skarels } /* qdprobe */ 58730391Skarels 58830391Skarels qdattach(ui) 58934642Smarc struct uba_device *ui; 59030391Skarels { 59134732Smarc register unit; /* QDSS module # for this call */ 59230391Skarels 59330391Skarels unit = ui->ui_unit; /* get QDSS number */ 59430391Skarels 59534642Smarc /* 59634642Smarc * init "qdflags[]" for this QDSS 59734642Smarc */ 59830391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 59930391Skarels qdflags[unit].mapped = 0; 60034615Smarc qdflags[unit].kernel_loop = -1; 60130391Skarels qdflags[unit].user_dma = 0; 60230391Skarels qdflags[unit].curs_acc = ACC_OFF; 60330391Skarels qdflags[unit].curs_thr = 128; 60430391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 60530391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 60630391Skarels qdflags[unit].adder_ie = 0; 60730391Skarels 60834642Smarc /* 60934642Smarc * init structures used in kbd/mouse interrupt service. This code must 61034642Smarc * come after the "init_shared()" routine has run since that routine 61134642Smarc * inits the eq_header[unit] structure used here. 61234642Smarc */ 61330391Skarels 61434642Smarc /* 61534642Smarc * init the "latest mouse report" structure 61634642Smarc */ 61730391Skarels last_rep[unit].state = 0; 61830391Skarels last_rep[unit].dx = 0; 61930391Skarels last_rep[unit].dy = 0; 62030391Skarels last_rep[unit].bytcnt = 0; 62130391Skarels 62234642Smarc /* 62334732Smarc * init the event queue (except mouse position) 62434732Smarc */ 62534732Smarc eq_header[unit]->header.events = 62634732Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 62730391Skarels 62830391Skarels eq_header[unit]->header.size = MAXEVENTS; 62930391Skarels eq_header[unit]->header.head = 0; 63030391Skarels eq_header[unit]->header.tail = 0; 63130391Skarels 63234642Smarc /* 63334642Smarc * open exclusive for graphics device. 63434642Smarc */ 63534642Smarc qdopened[unit] = 0; 63630391Skarels 63730391Skarels } /* qdattach */ 63830391Skarels 63934732Smarc /*ARGSUSED*/ 64030391Skarels qdopen(dev, flag) 64134642Smarc dev_t dev; 64234642Smarc int flag; 64330391Skarels { 64430391Skarels register struct uba_device *ui; /* ptr to uba structures */ 64530391Skarels register struct dga *dga; /* ptr to gate array struct */ 64630391Skarels register struct tty *tp; 64730391Skarels struct duart *duart; 64834732Smarc int unit; 64934732Smarc int minor_dev; 65030391Skarels 65130391Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 65230391Skarels unit = minor_dev >> 2; 65330391Skarels 65434642Smarc /* 65534642Smarc * check for illegal conditions 65634642Smarc */ 65730391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 65830391Skarels if (ui == 0 || ui->ui_alive == 0) 65934642Smarc return(ENXIO); /* no such device or address */ 66030391Skarels 66130391Skarels duart = (struct duart *) qdmap[unit].duart; 66230391Skarels dga = (struct dga *) qdmap[unit].dga; 66330391Skarels 66430391Skarels if ((minor_dev & 0x03) == 2) { 66534642Smarc /* 66634642Smarc * this is the graphic device... 66734642Smarc */ 66834642Smarc if (qdopened[unit] != 0) 66934732Smarc return(EBUSY); 67034642Smarc else 67134642Smarc qdopened[unit] = 1; 67234642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 67334642Smarc /* 67434642Smarc * enble kbd & mouse intrpts in DUART mask reg 67534642Smarc */ 67634642Smarc qdflags[unit].duart_imask |= 0x22; 67734642Smarc duart->imask = qdflags[unit].duart_imask; 67834642Smarc } else { 67934642Smarc /* 68034642Smarc * this is the console 68134642Smarc */ 68234642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 68334642Smarc dga->csr |= CURS_ENB; 68434642Smarc qdflags[unit].duart_imask |= 0x02; 68534642Smarc duart->imask = qdflags[unit].duart_imask; 68634642Smarc /* 68734642Smarc * some setup for tty handling 68834642Smarc */ 68934642Smarc tp = &qd_tty[minor_dev]; 69034642Smarc tp->t_addr = ui->ui_addr; 69134642Smarc tp->t_oproc = qdstart; 69234642Smarc if ((tp->t_state & TS_ISOPEN) == 0) { 69334642Smarc ttychars(tp); 69434642Smarc tp->t_ispeed = B9600; 69534642Smarc tp->t_ospeed = B9600; 69634642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 69734642Smarc tp->t_iflag = TTYDEF_IFLAG; 69834642Smarc tp->t_oflag = TTYDEF_OFLAG; 69934642Smarc tp->t_lflag = TTYDEF_LFLAG; 70034642Smarc tp->t_cflag = TTYDEF_CFLAG; 70132012Smarc } 70234642Smarc /* 70334642Smarc * enable intrpts, open line discipline 70434642Smarc */ 70534642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 70634642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp)); 70730391Skarels } 70830391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 70930391Skarels return(0); 71030391Skarels 71130391Skarels } /* qdopen */ 71230391Skarels 71334732Smarc /*ARGSUSED*/ 714*49759Smarc qdclose(dev, flag, mode, p) 71534642Smarc dev_t dev; 716*49759Smarc int flag, mode; 717*49759Smarc struct proc *p; 71830391Skarels { 71930391Skarels register struct tty *tp; 72030391Skarels register struct qdmap *qd; 72130391Skarels register int *ptep; 72230391Skarels struct dga *dga; /* gate array register map pointer */ 72330391Skarels struct duart *duart; 72430391Skarels struct adder *adder; 72534732Smarc int unit; 72634732Smarc int minor_dev; 72730391Skarels u_int mapix; 72834642Smarc int i; /* SIGNED index */ 72930391Skarels 73030391Skarels minor_dev = minor(dev); /* get minor device number */ 73130391Skarels unit = minor_dev >> 2; /* get QDSS number */ 73230391Skarels qd = &qdmap[unit]; 73330391Skarels 73430391Skarels if ((minor_dev & 0x03) == 2) { 73534642Smarc /* 73634642Smarc * this is the graphic device... 73734642Smarc */ 73834642Smarc if (qdopened[unit] != 1) 73934732Smarc return(EBUSY); 74034642Smarc else 74134642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 74234642Smarc /* 74334642Smarc * re-protect device memory 74434642Smarc */ 74534642Smarc if (qdflags[unit].mapped & MAPDEV) { 74634642Smarc /* 74734642Smarc * TEMPLATE RAM 74834642Smarc */ 74934642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 75034642Smarc ptep = (int *)(QVmap[0] + mapix); 75134732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 75234732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 75334642Smarc /* 75434642Smarc * ADDER 75534642Smarc */ 75634642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 75734642Smarc ptep = (int *)(QVmap[0] + mapix); 75834732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 75934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76034642Smarc /* 76134642Smarc * COLOR MAPS 76234642Smarc */ 76334642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 76434642Smarc ptep = (int *)(QVmap[0] + mapix); 76534732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 76634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76734642Smarc } 76834615Smarc 76934642Smarc /* 77034642Smarc * re-protect DMA buffer and free the map registers 77134642Smarc */ 77234642Smarc if (qdflags[unit].mapped & MAPDMA) { 77334642Smarc dga = (struct dga *) qdmap[unit].dga; 77434642Smarc adder = (struct adder *) qdmap[unit].adder; 77534642Smarc dga->csr &= ~DMA_IE; 77634642Smarc dga->csr &= ~0x0600; /* kill DMA */ 77734642Smarc adder->command = CANCEL; 77834642Smarc /* 77934642Smarc * if DMA was running, flush spurious intrpt 78034642Smarc */ 78134642Smarc if (dga->bytcnt_lo != 0) { 78234642Smarc dga->bytcnt_lo = 0; 78334642Smarc dga->bytcnt_hi = 0; 78434642Smarc DMA_SETIGNORE(DMAheader[unit]); 78534642Smarc dga->csr |= DMA_IE; 78634642Smarc dga->csr &= ~DMA_IE; 78734642Smarc } 78834642Smarc ptep = (int *) 78934642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 79034732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 79134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 79234642Smarc ubarelse(0, &Qbus_unmap[unit]); 79334642Smarc } 79434615Smarc 79534642Smarc /* 79634642Smarc * re-protect 1K (2 pages) event queue 79734642Smarc */ 79834642Smarc if (qdflags[unit].mapped & MAPEQ) { 79934642Smarc ptep = (int *) 80034642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 80134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 80234642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 80330391Skarels } 80434642Smarc /* 80534642Smarc * re-protect scroll param area and disable scroll intrpts 80634642Smarc */ 80734642Smarc if (qdflags[unit].mapped & MAPSCR) { 80834642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 80934642Smarc + (mfpr(SBR) | 0x80000000)); 81034642Smarc /* 81134642Smarc * re-protect 512 scroll param area 81234642Smarc */ 81334642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 81434642Smarc adder = (struct adder *) qdmap[unit].adder; 81534642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 81634642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 81734642Smarc } 81834642Smarc /* 81934642Smarc * re-protect color map write buffer area and kill intrpts 82034642Smarc */ 82134642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 82234642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 82334642Smarc + (mfpr(SBR) | 0x80000000)); 82434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 82534642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 82634642Smarc color_buf[unit]->status = 0; 82734642Smarc adder = (struct adder *) qdmap[unit].adder; 82834642Smarc qdflags[unit].adder_ie &= ~VSYNC; 82934642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 83034642Smarc } 83134642Smarc mtpr(TBIA, 0); 83234642Smarc /* flag everything now unmapped */ 83334642Smarc qdflags[unit].mapped = 0; 83434642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 83534642Smarc qdflags[unit].curs_acc = ACC_OFF; 83634642Smarc qdflags[unit].curs_thr = 128; 83734642Smarc /* 83834642Smarc * restore the console 83934642Smarc */ 84030391Skarels dga = (struct dga *) qdmap[unit].dga; 84130391Skarels adder = (struct adder *) qdmap[unit].adder; 84230391Skarels dga->csr &= ~DMA_IE; 84330391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 84430391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 84530391Skarels adder->command = CANCEL; 84634642Smarc /* 84734642Smarc * if DMA was running, flush spurious intrpt 84834642Smarc */ 84930391Skarels if (dga->bytcnt_lo != 0) { 85034642Smarc dga->bytcnt_lo = 0; 85134642Smarc dga->bytcnt_hi = 0; 85234642Smarc DMA_SETIGNORE(DMAheader[unit]); 85334642Smarc dga->csr |= DMA_IE; 85434642Smarc dga->csr &= ~DMA_IE; 85530391Skarels } 85630391Skarels init_shared(unit); /* init shared memory */ 85730391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 85830391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 85930391Skarels setup_input(unit); /* init the DUART */ 86030391Skarels ldfont(unit); 86130391Skarels cursor[unit].x = 0; 86230391Skarels cursor[unit].y = 0; 86334642Smarc /* 86434642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 86534642Smarc */ 86634642Smarc duart = (struct duart *) qdmap[unit].duart; 86734642Smarc qdflags[unit].duart_imask &= ~(0x20); 86834642Smarc qdflags[unit].duart_imask |= 0x02; 86934642Smarc duart->imask = qdflags[unit].duart_imask; 87034642Smarc /* 87134642Smarc * shut off interrupts if all is closed 87234642Smarc */ 87334642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 87434642Smarc dga = (struct dga *) qdmap[unit].dga; 87534642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 87634642Smarc } 87734642Smarc } else { 87834642Smarc /* 87934642Smarc * this is the console 88034642Smarc */ 88134642Smarc tp = &qd_tty[minor_dev]; 882*49759Smarc (*linesw[tp->t_line].l_close)(tp, flag); 88334642Smarc ttyclose(tp); 88434642Smarc tp->t_state = 0; 88534642Smarc qdflags[unit].inuse &= ~CONS_DEV; 88634642Smarc /* 88734642Smarc * if graphics device is closed, kill interrupts 88834642Smarc */ 88934642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 89034642Smarc dga = (struct dga *) qdmap[unit].dga; 89134642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 89234642Smarc } 89330391Skarels } 89434615Smarc 89530391Skarels return(0); 89630391Skarels 89730391Skarels } /* qdclose */ 89830391Skarels 89930391Skarels qdioctl(dev, cmd, datap, flags) 90034642Smarc dev_t dev; 90134642Smarc int cmd; 90234732Smarc register caddr_t datap; 90334642Smarc int flags; 90430391Skarels { 90530391Skarels register int *ptep; /* page table entry pointer */ 90632012Smarc register int mapix; /* QVmap[] page table index */ 90730391Skarels register struct _vs_event *event; 90830391Skarels register struct tty *tp; 90934732Smarc register i; 91030391Skarels struct qdmap *qd; /* pointer to device map struct */ 91130391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 91230391Skarels struct duart *duart; /* DUART reg structure pointer */ 91330391Skarels struct adder *adder; /* ADDER reg structure pointer */ 91430391Skarels struct prgkbd *cmdbuf; 91530391Skarels struct prg_cursor *curs; 91630391Skarels struct _vs_cursor *pos; 91734732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 91830391Skarels u_int minor_dev = minor(dev); 91930391Skarels int error; 92030391Skarels int s; 92130391Skarels short *temp; /* a pointer to template RAM */ 92230391Skarels 92334642Smarc /* 92434642Smarc * service graphic device ioctl commands 92534642Smarc */ 92630391Skarels switch (cmd) { 92734615Smarc 92834642Smarc case QD_GETEVENT: 92934642Smarc /* 93034642Smarc * extract the oldest event from the event queue 93134642Smarc */ 93230391Skarels if (ISEMPTY(eq_header[unit])) { 93334642Smarc event = (struct _vs_event *) datap; 93434642Smarc event->vse_device = VSE_NULL; 93534642Smarc break; 93630391Skarels } 93730391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 93834615Smarc s = spl5(); 93930391Skarels GETEND(eq_header[unit]); 94030391Skarels splx(s); 94134732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 94230391Skarels break; 94330391Skarels 94434642Smarc case QD_RESET: 94534642Smarc /* 94634642Smarc * init the dragon stuff, DUART, and driver variables 94734642Smarc */ 94830391Skarels init_shared(unit); /* init shared memory */ 94930391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 95030391Skarels clear_qd_screen(unit); 95130391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 95230391Skarels ldfont(unit); /* load the console font */ 95330391Skarels setup_input(unit); /* init the DUART */ 95430391Skarels break; 95530391Skarels 95634642Smarc case QD_SET: 95734642Smarc /* 95834642Smarc * init the DUART and driver variables 95934642Smarc */ 96030391Skarels init_shared(unit); 96130391Skarels setup_input(unit); 96230391Skarels break; 96330391Skarels 96434642Smarc case QD_CLRSCRN: 96534642Smarc /* 96634642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 96734642Smarc */ 96834732Smarc #ifdef notdef /* has caused problems and isn't necessary */ 96930391Skarels setup_dragon(unit); 97030391Skarels clear_qd_screen(unit); 97134615Smarc #endif 97230391Skarels break; 97330391Skarels 97434642Smarc case QD_WTCURSOR: 97534642Smarc /* 97634642Smarc * load a cursor into template RAM 97734642Smarc */ 97834732Smarc ldcursor(unit, (short *)datap); 97930391Skarels break; 98030391Skarels 98134642Smarc case QD_RDCURSOR: 98230391Skarels 98330391Skarels temp = (short *) qdmap[unit].template; 98434642Smarc /* 98534642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 98634642Smarc * ...template space 98734642Smarc */ 98830391Skarels temp += (8 * 1024) - 32; 98930391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 99034642Smarc *(short *)datap = *temp++; 99130391Skarels break; 99230391Skarels 99334642Smarc case QD_POSCURSOR: 99434642Smarc /* 99534642Smarc * position the mouse cursor 99634642Smarc */ 99730391Skarels dga = (struct dga *) qdmap[unit].dga; 99830391Skarels pos = (struct _vs_cursor *) datap; 99934615Smarc s = spl5(); 100030391Skarels dga->x_cursor = TRANX(pos->x); 100130391Skarels dga->y_cursor = TRANY(pos->y); 100230391Skarels eq_header[unit]->curs_pos.x = pos->x; 100330391Skarels eq_header[unit]->curs_pos.y = pos->y; 100430391Skarels splx(s); 100530391Skarels break; 100630391Skarels 100734642Smarc case QD_PRGCURSOR: 100834642Smarc /* 100934642Smarc * set the cursor acceleration factor 101034642Smarc */ 101130391Skarels curs = (struct prg_cursor *) datap; 101234615Smarc s = spl5(); 101330391Skarels qdflags[unit].curs_acc = curs->acc_factor; 101430391Skarels qdflags[unit].curs_thr = curs->threshold; 101530391Skarels splx(s); 101630391Skarels break; 101730391Skarels 101834642Smarc case QD_MAPDEVICE: 101934642Smarc /* 102034642Smarc * enable 'user write' to device pages 102134642Smarc */ 102230391Skarels qdflags[unit].mapped |= MAPDEV; 102330391Skarels qd = (struct qdmap *) &qdmap[unit]; 102434642Smarc /* 102534642Smarc * enable user write to template RAM 102634642Smarc */ 102732012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 102832012Smarc ptep = (int *)(QVmap[0] + mapix); 102934732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 103034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103134642Smarc /* 103234642Smarc * enable user write to registers 103334642Smarc */ 103432012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 103532012Smarc ptep = (int *)(QVmap[0] + mapix); 103634732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 103734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103834642Smarc /* 103934642Smarc * enable user write to color maps 104034642Smarc */ 104132012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 104232012Smarc ptep = (int *)(QVmap[0] + mapix); 104334732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 104434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104534642Smarc /* 104634642Smarc * enable user write to DUART 104734642Smarc */ 104832012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 104932012Smarc ptep = (int *)(QVmap[0] + mapix); 105030391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 105130391Skarels 105234732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 105330391Skarels 105434642Smarc /* 105534732Smarc * stuff qdmap structure in return buffer 105634732Smarc */ 105734732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 105830391Skarels break; 105930391Skarels 106034642Smarc case QD_MAPIOBUF: 106134642Smarc /* 106234642Smarc * do setup for DMA by user process 106334642Smarc * 106434642Smarc * set 'user write enable' bits for DMA buffer 106534642Smarc */ 106630391Skarels qdflags[unit].mapped |= MAPDMA; 106730391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 106834642Smarc + (mfpr(SBR) | 0x80000000)); 106934732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 107034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 107134732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 107234642Smarc /* 107334642Smarc * set up QBUS map registers for DMA 107434642Smarc */ 107530391Skarels DMAheader[unit]->QBAreg = 107634732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 107730391Skarels if (DMAheader[unit]->QBAreg == 0) 107834732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 107930391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 108030391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 108134642Smarc /* 108234642Smarc * return I/O buf adr 108334642Smarc */ 108430391Skarels *(int *)datap = (int) DMAheader[unit]; 108530391Skarels break; 108630391Skarels 108734642Smarc case QD_MAPSCROLL: 108834642Smarc /* 108934642Smarc * map the shared scroll param area and enable scroll interpts 109034642Smarc */ 109130391Skarels qdflags[unit].mapped |= MAPSCR; 109230391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 109334642Smarc + (mfpr(SBR) | 0x80000000)); 109434642Smarc /* 109534642Smarc * allow user write to scroll area 109634642Smarc */ 109730391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 109834732Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 109930391Skarels scroll[unit]->status = 0; 110030391Skarels adder = (struct adder *) qdmap[unit].adder; 110130391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 110230391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 110334642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 110430391Skarels break; 110530391Skarels 110634642Smarc case QD_UNMAPSCROLL: 110734642Smarc /* 110834642Smarc * unmap shared scroll param area and disable scroll intrpts 110934642Smarc */ 111030391Skarels if (qdflags[unit].mapped & MAPSCR) { 111134642Smarc qdflags[unit].mapped &= ~MAPSCR; 111234642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 111334642Smarc + (mfpr(SBR) | 0x80000000)); 111434642Smarc /* 111534642Smarc * re-protect 512 scroll param area 111634642Smarc */ 111734642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 111834642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 111934642Smarc adder = (struct adder *) qdmap[unit].adder; 112034642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 112134642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 112230391Skarels } 112330391Skarels break; 112430391Skarels 112534642Smarc case QD_MAPCOLOR: 112634642Smarc /* 112734642Smarc * map shared color map write buf and turn on vsync intrpt 112834642Smarc */ 112930391Skarels qdflags[unit].mapped |= MAPCOLOR; 113030391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 113134642Smarc + (mfpr(SBR) | 0x80000000)); 113234732Smarc /* 113334732Smarc * allow user write to color map write buffer 113434732Smarc */ 113534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 113630391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 113730391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 113834642Smarc adder = (struct adder *) qdmap[unit].adder; 113930391Skarels qdflags[unit].adder_ie |= VSYNC; 114030391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 114134732Smarc /* 114234732Smarc * return color area address 114334732Smarc */ 114430391Skarels *(int *)datap = (int) color_buf[unit]; 114530391Skarels break; 114630391Skarels 114734642Smarc case QD_UNMAPCOLOR: 114834642Smarc /* 114934732Smarc * unmap shared color map write buffer and kill VSYNC intrpts 115034732Smarc */ 115130391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 115234642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 115334642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 115434642Smarc + (mfpr(SBR) | 0x80000000)); 115534732Smarc /* 115634732Smarc * re-protect color map write buffer 115734732Smarc */ 115834732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 115934642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 116034732Smarc mtpr(TBIA, 0); 116134642Smarc adder = (struct adder *) qdmap[unit].adder; 116234642Smarc qdflags[unit].adder_ie &= ~VSYNC; 116334642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 116430391Skarels } 116530391Skarels break; 116630391Skarels 116734642Smarc case QD_MAPEVENT: 116834642Smarc /* 116934642Smarc * give user write access to the event queue 117034642Smarc */ 117130391Skarels qdflags[unit].mapped |= MAPEQ; 117230391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 117334642Smarc + (mfpr(SBR) | 0x80000000)); 117434732Smarc /* 117534732Smarc * allow user write to 1K event queue 117634732Smarc */ 117734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 117830391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 117930391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 118034732Smarc /* 118134732Smarc * return event queue address 118234732Smarc */ 118334732Smarc *(int *)datap = (int)eq_header[unit]; 118430391Skarels break; 118530391Skarels 118634642Smarc case QD_PRGKBD: 118734642Smarc /* 118834642Smarc * pass caller's programming commands to LK201 118934642Smarc */ 119034732Smarc duart = (struct duart *)qdmap[unit].duart; 119134732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 119234642Smarc /* 119334642Smarc * send command 119434642Smarc */ 119530391Skarels for (i = 1000; i > 0; --i) { 119634732Smarc if (duart->statusA&XMT_RDY) { 119734642Smarc duart->dataA = cmdbuf->cmd; 119834642Smarc break; 119934642Smarc } 120030391Skarels } 120130391Skarels if (i == 0) { 120234732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 120334642Smarc break; 120430391Skarels } 120534642Smarc /* 120634642Smarc * send param1? 120734642Smarc */ 120830391Skarels if (cmdbuf->cmd & LAST_PARAM) 120934642Smarc break; 121030391Skarels for (i = 1000; i > 0; --i) { 121134732Smarc if (duart->statusA&XMT_RDY) { 121234642Smarc duart->dataA = cmdbuf->param1; 121334642Smarc break; 121434642Smarc } 121530391Skarels } 121630391Skarels if (i == 0) { 121734732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 121834642Smarc break; 121930391Skarels } 122034642Smarc /* 122134642Smarc * send param2? 122234642Smarc */ 122330391Skarels if (cmdbuf->param1 & LAST_PARAM) 122430391Skarels break; 122530391Skarels for (i = 1000; i > 0; --i) { 122634732Smarc if (duart->statusA&XMT_RDY) { 122734642Smarc duart->dataA = cmdbuf->param2; 122834642Smarc break; 122934642Smarc } 123030391Skarels } 123130391Skarels if (i == 0) { 123234732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 123334642Smarc break; 123430391Skarels } 123530391Skarels break; 123630391Skarels 123734642Smarc case QD_PRGMOUSE: 123834642Smarc /* 123934642Smarc * pass caller's programming commands to the mouse 124034642Smarc */ 124130391Skarels duart = (struct duart *) qdmap[unit].duart; 124230391Skarels for (i = 1000; i > 0; --i) { 124334732Smarc if (duart->statusB&XMT_RDY) { 124434642Smarc duart->dataB = *datap; 124534642Smarc break; 124634642Smarc } 124730391Skarels } 124830391Skarels if (i == 0) { 124934732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 125030391Skarels } 125130391Skarels break; 125230391Skarels 125334642Smarc case QD_RDCONFIG: 125434642Smarc /* 125534642Smarc * get QDSS configuration word and return it 125634642Smarc */ 125730391Skarels *(short *)datap = qdflags[unit].config; 125830391Skarels break; 125930391Skarels 126034642Smarc case QD_KERN_LOOP: 126134642Smarc case QD_KERN_UNLOOP: 126234642Smarc /* 126334642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 126434642Smarc * kernel console output. 126534642Smarc */ 126634615Smarc break; 126734615Smarc 126834642Smarc case QD_PRGTABLET: 126934642Smarc /* 127034642Smarc * program the tablet 127134642Smarc */ 127230391Skarels duart = (struct duart *) qdmap[unit].duart; 127330391Skarels for (i = 1000; i > 0; --i) { 127434732Smarc if (duart->statusB&XMT_RDY) { 127534642Smarc duart->dataB = *datap; 127634642Smarc break; 127734642Smarc } 127830391Skarels } 127930391Skarels if (i == 0) { 128034732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 128130391Skarels } 128230391Skarels break; 128330391Skarels 128434642Smarc case QD_PRGTABRES: 128534642Smarc /* 128634642Smarc * program the tablet report resolution factor 128734642Smarc */ 128830391Skarels qdflags[unit].tab_res = *(short *)datap; 128930391Skarels break; 129030391Skarels 129134642Smarc default: 129234642Smarc /* 129334642Smarc * service tty ioctl's 129434642Smarc */ 129534642Smarc if (!(minor_dev & 0x02)) { 129630391Skarels tp = &qd_tty[minor_dev]; 129734642Smarc error = 129834642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 129930391Skarels if (error >= 0) { 130034642Smarc return(error); 130130391Skarels } 130230391Skarels error = ttioctl(tp, cmd, datap, flags); 130330391Skarels if (error >= 0) { 130434642Smarc return(error); 130530391Skarels } 130634642Smarc } 130734642Smarc break; 130830391Skarels } 130930391Skarels 131030391Skarels return(0); 131130391Skarels 131230391Skarels } /* qdioctl */ 131330391Skarels 131430391Skarels qdselect(dev, rw) 131534642Smarc dev_t dev; 131634642Smarc int rw; 131730391Skarels { 131834732Smarc register s; 131934732Smarc register unit; 132034615Smarc register struct tty *tp; 132134615Smarc u_int minor_dev = minor(dev); 132230391Skarels 132334615Smarc s = spl5(); 132434615Smarc unit = minor_dev >> 2; 132530391Skarels 132630391Skarels switch (rw) { 132734642Smarc case FREAD: 132834642Smarc if ((minor_dev & 0x03) == 2) { 132934642Smarc /* 133034642Smarc * this is a graphics device, so check for events 133134642Smarc */ 133234732Smarc if(!(ISEMPTY(eq_header[unit]))) { 133334642Smarc splx(s); 133434642Smarc return(1); 133534642Smarc } 133634732Smarc qdrsel[unit] = u.u_procp; 133734642Smarc qdflags[unit].selmask |= SEL_READ; 133834642Smarc splx(s); 133934642Smarc return(0); 134034642Smarc } else { 134134642Smarc /* 134234642Smarc * this is a tty device 134334642Smarc */ 134434642Smarc tp = &qd_tty[minor_dev]; 134534642Smarc if (ttnread(tp)) 134634642Smarc return(1); 134734642Smarc tp->t_rsel = u.u_procp; 134834642Smarc splx(s); 134934642Smarc return(0); 135030391Skarels } 135130391Skarels 135234642Smarc case FWRITE: 135334642Smarc if ((minor(dev) & 0x03) == 2) { 135434642Smarc /* 135534642Smarc * this is a graphics device, so check for dma buffers 135634642Smarc */ 135734642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 135834642Smarc { 135934642Smarc splx(s); 136034642Smarc return(1); 136134642Smarc } 136234732Smarc qdrsel[unit] = u.u_procp; 136334642Smarc qdflags[unit].selmask |= SEL_WRITE; 136434642Smarc splx(s); 136534642Smarc return(0); 136634642Smarc } else { 136734642Smarc /* 136834642Smarc * this is a tty device 136934642Smarc */ 137034642Smarc tp = &qd_tty[minor_dev]; 137137605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 137234642Smarc return(1); 137334642Smarc tp->t_wsel = u.u_procp; 137434642Smarc splx(s); 137534642Smarc return(0); 137630391Skarels } 137730391Skarels } 137834732Smarc splx(s); 137934732Smarc return(0); 138030391Skarels 138130391Skarels } /* qdselect() */ 138230391Skarels 138330391Skarels extern qd_strategy(); 138430391Skarels 138530391Skarels qdwrite(dev, uio) 138634642Smarc dev_t dev; 138734642Smarc struct uio *uio; 138830391Skarels { 138930391Skarels register struct tty *tp; 139034732Smarc register minor_dev; 139134732Smarc register unit; 139230391Skarels 139330391Skarels minor_dev = minor(dev); 139430391Skarels unit = (minor_dev >> 2) & 0x07; 139530391Skarels 139634642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 139734642Smarc /* 139834642Smarc * this is the console... 139934642Smarc */ 140034642Smarc tp = &qd_tty[minor_dev]; 140134642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 140234642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 140334642Smarc /* 140434642Smarc * this is a DMA xfer from user space 140534642Smarc */ 140634642Smarc return (physio(qd_strategy, &qdbuf[unit], 140734642Smarc dev, B_WRITE, minphys, uio)); 140830391Skarels } 140934732Smarc return (ENXIO); 141030391Skarels } 141130391Skarels 141230391Skarels qdread(dev, uio) 141334642Smarc dev_t dev; 141434642Smarc struct uio *uio; 141530391Skarels { 141630391Skarels register struct tty *tp; 141734732Smarc register minor_dev; 141834732Smarc register unit; 141930391Skarels 142030391Skarels minor_dev = minor(dev); 142130391Skarels unit = (minor_dev >> 2) & 0x07; 142230391Skarels 142334642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 142434642Smarc /* 142534642Smarc * this is the console 142634642Smarc */ 142734642Smarc tp = &qd_tty[minor_dev]; 142834642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 142934642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 143034642Smarc /* 143134642Smarc * this is a bitmap-to-processor xfer 143234642Smarc */ 143334642Smarc return (physio(qd_strategy, &qdbuf[unit], 143434642Smarc dev, B_READ, minphys, uio)); 143530391Skarels } 143634732Smarc return (ENXIO); 143730391Skarels } 143830391Skarels 143930391Skarels /*************************************************************** 144030391Skarels * 144130391Skarels * qd_strategy()... strategy routine to do DMA 144230391Skarels * 144330391Skarels ***************************************************************/ 144430391Skarels 144530391Skarels qd_strategy(bp) 144634642Smarc register struct buf *bp; 144730391Skarels { 144830391Skarels register struct dga *dga; 144930391Skarels register struct adder *adder; 145034732Smarc register unit; 145130391Skarels int QBAreg; 145230391Skarels int s; 145330391Skarels int cookie; 145430391Skarels 145530391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 145630391Skarels 145734642Smarc /* 145834642Smarc * init pointers 145934642Smarc */ 146030391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 146134732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 146234642Smarc goto STRAT_ERR; 146330391Skarels } 146430391Skarels dga = (struct dga *) qdmap[unit].dga; 146534615Smarc s = spl5(); 146630391Skarels qdflags[unit].user_dma = -1; 146730391Skarels dga->csr |= DMA_IE; 146830391Skarels cookie = QBAreg & 0x3FFFF; 146930391Skarels dga->adrs_lo = (short) cookie; 147030391Skarels dga->adrs_hi = (short) (cookie >> 16); 147130391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 147230391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 147330391Skarels 147430391Skarels while (qdflags[unit].user_dma) { 147534642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 147630391Skarels } 147730391Skarels splx(s); 147830391Skarels ubarelse(0, &QBAreg); 147930391Skarels if (!(dga->csr & DMA_ERR)) { 148034642Smarc iodone(bp); 148134642Smarc return; 148230391Skarels } 148330391Skarels 148430391Skarels STRAT_ERR: 148530391Skarels adder = (struct adder *) qdmap[unit].adder; 148634642Smarc adder->command = CANCEL; /* cancel adder activity */ 148730391Skarels dga->csr &= ~DMA_IE; 148830391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 148930391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 149030391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 149130391Skarels 149234642Smarc /* 149334642Smarc * if DMA was running, flush spurious intrpt 149434642Smarc */ 149530391Skarels if (dga->bytcnt_lo != 0) { 149634642Smarc dga->bytcnt_lo = 0; 149734642Smarc dga->bytcnt_hi = 0; 149834642Smarc DMA_SETIGNORE(DMAheader[unit]); 149934642Smarc dga->csr |= DMA_IE; 150030391Skarels } 150130391Skarels iodone(bp); 150230391Skarels 150330391Skarels } /* qd_strategy */ 150430391Skarels 150534732Smarc /* 150634732Smarc * Start output to the console screen 150734732Smarc */ 150830391Skarels qdstart(tp) 150934642Smarc register struct tty *tp; 151030391Skarels { 151134732Smarc register which_unit, unit, c; 151230391Skarels int s; 151334615Smarc 151430391Skarels unit = minor(tp->t_dev); 151530391Skarels which_unit = (unit >> 2) & 0x3; 151634615Smarc unit &= 0x03; 151730391Skarels 151834615Smarc s = spl5(); 151934615Smarc 152034642Smarc /* 152134642Smarc * If it's currently active, or delaying, no need to do anything. 152234642Smarc */ 152330391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 152430391Skarels goto out; 152530391Skarels 152634642Smarc /* 152734642Smarc * Display chars until the queue is empty. 152834642Smarc * Drop input from anything but the console 152934642Smarc * device on the floor. 153034642Smarc * 153134642Smarc * XXX - this loop is done at spltty. 153234642Smarc * 153334642Smarc */ 153434642Smarc while (tp->t_outq.c_cc) { 153534511Smarc c = getc(&tp->t_outq); 153634615Smarc if (unit == 0) 153734732Smarc blitc(which_unit, (u_char)c); 153830391Skarels } 153934642Smarc /* 154034642Smarc * If there are sleepers, and output has drained below low 154134642Smarc * water mark, wake up the sleepers. 154234642Smarc */ 154337605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 154434615Smarc if (tp->t_state & TS_ASLEEP){ 154534615Smarc tp->t_state &= ~TS_ASLEEP; 154634615Smarc wakeup((caddr_t) &tp->t_outq); 154734615Smarc } 154830391Skarels } 154930391Skarels 155034615Smarc tp->t_state &= ~TS_BUSY; 155134615Smarc 155230391Skarels out: 155330391Skarels splx(s); 155430391Skarels 155530391Skarels } /* qdstart */ 155630391Skarels 155734732Smarc /*ARGSUSED*/ 155830391Skarels qdstop(tp, flag) 155934642Smarc register struct tty *tp; 156034642Smarc int flag; 156130391Skarels { 156230391Skarels register int s; 156330391Skarels 156434615Smarc s = spl5(); /* block intrpts during state modification */ 156534732Smarc if (tp->t_state & TS_BUSY) 156634732Smarc if ((tp->t_state & TS_TTSTOP) == 0) 156734642Smarc tp->t_state |= TS_FLUSH; 156834642Smarc else 156934642Smarc tp->t_state &= ~TS_BUSY; 157030391Skarels splx(s); 157130391Skarels } 157230391Skarels 157334732Smarc /* 157434732Smarc * Output a character to the QDSS screen 157534732Smarc */ 157630391Skarels 157730391Skarels blitc(unit, chr) 157834732Smarc register unit; 157934732Smarc register u_char chr; 158030391Skarels { 158130391Skarels register struct adder *adder; 158230391Skarels register struct dga *dga; 158330391Skarels register int i; 158434642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 158534642Smarc static short inescape[NQD]; 158630391Skarels 158734732Smarc adder = (struct adder *)qdmap[unit].adder; 158830391Skarels dga = (struct dga *) qdmap[unit].dga; 158934642Smarc /* 159034642Smarc * BSD comment: this (&=0177) defeats the extended character 159134642Smarc * set code for the glass tty, but if i had the time i would 159234642Smarc * spend it ripping out the code completely. This driver 159334642Smarc * is too big for its own good. 159434642Smarc */ 159534642Smarc chr &= 0177; 159634642Smarc /* 159734732Smarc * Cursor addressing (so vi will work). 159834642Smarc * Decode for "\E=%.%." cursor motion description. 159934732Smarc * Corresponds to type "qdcons" in /etc/termcap: 160034642Smarc * 160134642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 160234642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 160334642Smarc * 160434642Smarc */ 160534642Smarc if (inescape[unit] && nograph) { 160634642Smarc switch (inescape[unit]++) { 160734642Smarc case 1: 160834642Smarc if (chr != '=') { 160934642Smarc /* abort escape sequence */ 161034642Smarc inescape[unit] = 0; 161134642Smarc blitc(unit, chr); 161234642Smarc } 161334732Smarc return; 161434642Smarc case 2: 161534642Smarc /* position row */ 161634642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 161734642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 161834642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 161934642Smarc dga->y_cursor = TRANY(cursor[unit].y); 162034732Smarc return; 162134642Smarc case 3: 162234642Smarc /* position column */ 162334642Smarc cursor[unit].x = CHAR_WIDTH * chr; 162434642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 162534642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 162634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 162734642Smarc inescape[unit] = 0; 162834732Smarc return; 162934642Smarc default: 163034642Smarc inescape[unit] = 0; 163134642Smarc blitc(unit, chr); 163234642Smarc } 163334642Smarc } 163430391Skarels 163530391Skarels switch (chr) { 163634642Smarc case '\r': /* return char */ 163730391Skarels cursor[unit].x = 0; 163834642Smarc if (nograph) 163934642Smarc dga->x_cursor = TRANX(cursor[unit].x); 164034732Smarc return; 164130391Skarels 164234642Smarc case '\t': /* tab char */ 164330391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 164434642Smarc blitc(unit, ' '); 164530391Skarels } 164634732Smarc return; 164730391Skarels 164834642Smarc case '\n': /* line feed char */ 164930391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 165034642Smarc if (nograph) { 165134642Smarc cursor[unit].y -= CHAR_HEIGHT; 165234642Smarc scroll_up(adder); 165334642Smarc } else 165434642Smarc cursor[unit].y = 0; 165530391Skarels } 165634642Smarc if (nograph) 165734642Smarc dga->y_cursor = TRANY(cursor[unit].y); 165834732Smarc return; 165930391Skarels 166034642Smarc case '\b': /* backspace char */ 166130391Skarels if (cursor[unit].x > 0) { 166234642Smarc cursor[unit].x -= CHAR_WIDTH; 166334642Smarc if (nograph) 166434642Smarc dga->x_cursor = TRANX(cursor[unit].x); 166530391Skarels } 166634732Smarc return; 166734642Smarc case CTRL('k'): /* cursor up */ 166834642Smarc if (nograph && cursor[unit].y > 0) { 166934642Smarc cursor[unit].y -= CHAR_HEIGHT; 167034642Smarc dga->y_cursor = TRANY(cursor[unit].y); 167134642Smarc } 167234732Smarc return; 167330391Skarels 167434642Smarc case CTRL('^'): /* home cursor */ 167534642Smarc if (nograph) { 167634642Smarc cursor[unit].x = 0; 167734642Smarc dga->x_cursor = TRANX(cursor[unit].x); 167834642Smarc cursor[unit].y = 0; 167934642Smarc dga->y_cursor = TRANY(cursor[unit].y); 168034642Smarc } 168134732Smarc return; 168232012Smarc 168334642Smarc case CTRL('l'): /* cursor right */ 168434642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 168534642Smarc cursor[unit].x += CHAR_WIDTH; 168634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 168734642Smarc } 168834732Smarc return; 168930391Skarels 169034642Smarc case CTRL('z'): /* clear screen */ 169134642Smarc if (nograph) { 169234642Smarc setup_dragon(unit); 169334642Smarc clear_qd_screen(unit); 169434642Smarc /* home cursor - termcap seems to assume this */ 169534642Smarc cursor[unit].x = 0; 169634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 169734642Smarc cursor[unit].y = 0; 169834642Smarc dga->y_cursor = TRANY(cursor[unit].y); 169934642Smarc } 170034732Smarc return; 170130391Skarels 170234642Smarc case '\033': /* start escape sequence */ 170334642Smarc if (nograph) 170434642Smarc inescape[unit] = 1; 170534732Smarc return; 170634642Smarc 170734642Smarc default: 170834642Smarc if ((chr < ' ') || (chr > '~')) 170934732Smarc return; 171034642Smarc } 171134642Smarc /* 171234642Smarc * setup VIPER operand control registers 171334642Smarc */ 171430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 171530391Skarels write_ID(adder, SRC1_OCR_B, 171634642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 171730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 171830391Skarels write_ID(adder, SRC1_OCR_B, 171934642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 172030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 172130391Skarels write_ID(adder, DST_OCR_B, 172234642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 172330391Skarels write_ID(adder, MASK_1, 0xFFFF); 172430391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 172530391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 172634642Smarc adder->x_clip_min = 0; 172734642Smarc adder->x_clip_max = 1024; 172834642Smarc adder->y_clip_min = 0; 172934642Smarc adder->y_clip_max = 864; 173034642Smarc /* 173134642Smarc * load DESTINATION origin and vectors 173234642Smarc */ 173330391Skarels adder->fast_dest_dy = 0; 173430391Skarels adder->slow_dest_dx = 0; 173530391Skarels adder->error_1 = 0; 173630391Skarels adder->error_2 = 0; 173730391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 173834732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 173930391Skarels adder->destination_x = cursor[unit].x; 174030391Skarels adder->fast_dest_dx = CHAR_WIDTH; 174130391Skarels adder->destination_y = cursor[unit].y; 174230391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 174334642Smarc /* 174434642Smarc * load SOURCE origin and vectors 174534642Smarc */ 174634615Smarc if ((chr - ' ') > (CHARS - 1)) { 174734615Smarc printf("Invalid character (x)%x in blitc\n",chr); 174834615Smarc chr = ' '; 174934615Smarc } 175034642Smarc /* 175134642Smarc * X position is modulo the number of characters per line 175234642Smarc */ 175334615Smarc adder->source_1_x = FONT_X + 175434642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 175534642Smarc /* 175634642Smarc * Point to either first or second row 175734642Smarc */ 175834615Smarc adder->source_1_y = 2048 - 15 * 175934642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 176030391Skarels adder->source_1_dx = CHAR_WIDTH; 176130391Skarels adder->source_1_dy = CHAR_HEIGHT; 176230391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 176330391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 176434642Smarc /* 176534642Smarc * update console cursor coordinates 176634642Smarc */ 176730391Skarels cursor[unit].x += CHAR_WIDTH; 176834642Smarc if (nograph) 176934642Smarc dga->x_cursor = TRANX(cursor[unit].x); 177030391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 177134642Smarc blitc(unit, '\r'); 177234642Smarc blitc(unit, '\n'); 177330391Skarels } 177430391Skarels 177530391Skarels } /* blitc */ 177630391Skarels 177734732Smarc qdreset() { } 177830391Skarels 177934732Smarc /* 178034732Smarc * INTERRUPT SERVICE ROUTINES 178134732Smarc */ 178230391Skarels 178334732Smarc /* 178434732Smarc * Service "DMA DONE" interrupt condition 178534732Smarc */ 178630391Skarels qddint(qd) 178734732Smarc register qd; 178830391Skarels { 178930391Skarels register struct DMAreq_header *header; 179030391Skarels register struct DMAreq *request; 179130391Skarels register struct dga *dga; 179230391Skarels struct adder *adder; 179330391Skarels int cookie; /* DMA adrs for QDSS */ 179430391Skarels 179534732Smarc (void)spl4(); /* allow interval timer in */ 179630391Skarels 179734642Smarc /* 179834642Smarc * init pointers 179934642Smarc */ 180030391Skarels header = DMAheader[qd]; /* register for optimization */ 180130391Skarels dga = (struct dga *) qdmap[qd].dga; 180230391Skarels adder = (struct adder *) qdmap[qd].adder; 180330391Skarels 180434642Smarc /* 180534642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 180634642Smarc */ 180730391Skarels if (DMA_ISIGNORE(header)) { 180834642Smarc DMA_CLRIGNORE(header); 180934642Smarc return; 181030391Skarels } 181130391Skarels 181234642Smarc /* 181334642Smarc * dump a DMA hardware error message if appropriate 181434642Smarc */ 181530391Skarels if (dga->csr & DMA_ERR) { 181630391Skarels 181734642Smarc if (dga->csr & PARITY_ERR) 181834732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 181930391Skarels 182034642Smarc if (dga->csr & BUS_ERR) 182134732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 182230391Skarels } 182330391Skarels 182434642Smarc /* 182534642Smarc * if this was a DMA from user space... 182634642Smarc */ 182730391Skarels if (qdflags[qd].user_dma) { 182834642Smarc qdflags[qd].user_dma = 0; 182934642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 183034642Smarc return; 183130391Skarels } 183230391Skarels 183334642Smarc /* 183434642Smarc * if we're doing DMA request queue services, field the error condition 183534642Smarc */ 183630391Skarels if (dga->csr & DMA_ERR) { 183730391Skarels 183834642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 183934642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 184034642Smarc adder->command = CANCEL; /* cancel adder activity */ 184130391Skarels 184234642Smarc DMA_SETERROR(header); /* flag error in header status word */ 184334642Smarc DMA_CLRACTIVE(header); 184434642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 184534642Smarc header->newest = header->oldest; 184634642Smarc header->used = 0; 184730391Skarels 184834732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 184934732Smarc selwakeup(qdrsel[qd], 0); 185034732Smarc qdrsel[qd] = 0; 185134642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 185234642Smarc } 185330391Skarels 185434642Smarc if (dga->bytcnt_lo != 0) { 185534642Smarc dga->bytcnt_lo = 0; 185634642Smarc dga->bytcnt_hi = 0; 185734642Smarc DMA_SETIGNORE(header); 185834642Smarc } 185934642Smarc return; 186030391Skarels } 186130391Skarels 186234642Smarc /* 186334642Smarc * if the DMA request queue is now becoming non-full, 186434642Smarc * wakeup "select" client. 186534642Smarc */ 186630391Skarels if (DMA_ISFULL(header)) { 186734732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 186834732Smarc selwakeup(qdrsel[qd], 0); 186934732Smarc qdrsel[qd] = 0; 187034642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 187134642Smarc } 187230391Skarels } 187330391Skarels 187430391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 187534642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 187630391Skarels 187734615Smarc /* check for unexpected interrupt */ 187834615Smarc if (DMA_ISEMPTY(header)) 187930391Skarels return; 188030391Skarels 188130391Skarels DMA_GETEND(header); /* update request queue indices */ 188230391Skarels 188334642Smarc /* 188434732Smarc * if no more DMA pending, wake up "select" client and exit 188534732Smarc */ 188630391Skarels if (DMA_ISEMPTY(header)) { 188730391Skarels 188834732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 188934732Smarc selwakeup(qdrsel[qd], 0); 189034732Smarc qdrsel[qd] = 0; 189134642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 189234642Smarc } 189330391Skarels 189434642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 189534642Smarc return; 189630391Skarels } 189730391Skarels 189834642Smarc /* 189934732Smarc * initiate next DMA xfer 190034732Smarc */ 190130391Skarels request = DMA_GETBEGIN(header); 190234615Smarc if (request->DMAtype != QDlast_DMAtype) { 190334642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 190434642Smarc adder->command = CANCEL; /* cancel adder activity */ 190534615Smarc } 190630391Skarels 190734615Smarc 190830391Skarels switch (request->DMAtype) { 190930391Skarels 191034642Smarc case DISPLIST: 191134615Smarc if (request->DMAtype != QDlast_DMAtype) { 191234615Smarc dga->csr |= DL_ENB; 191334615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 191434615Smarc } 191530391Skarels break; 191630391Skarels 191734642Smarc case PTOB: 191834615Smarc if (request->DMAtype != QDlast_DMAtype) { 191934615Smarc if (request->DMAdone & BYTE_PACK) 192034642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 192134615Smarc else { 192234615Smarc dga->csr |= PTOB_ENB; 192334615Smarc dga->csr &= ~BYTE_DMA; 192434615Smarc } 192534615Smarc } 192630391Skarels break; 192730391Skarels 192834642Smarc case BTOP: 192934615Smarc if (request->DMAtype != QDlast_DMAtype) { 193034615Smarc if (request->DMAdone & BYTE_PACK) { 193134615Smarc dga->csr &= ~DL_ENB; 193234615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 193334615Smarc } 193434615Smarc else { 193534615Smarc dga->csr |= BTOP_ENB; 193634615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 193734615Smarc } 193834615Smarc } 193930391Skarels break; 194034642Smarc default: 194134732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 194230391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 194330391Skarels return; 194430391Skarels } 194530391Skarels 194630391Skarels if (request->DMAdone & COUNT_ZERO) { 194734642Smarc dga->csr &= ~SET_DONE_FIFO; 194834642Smarc } 194934642Smarc else if (request->DMAdone & FIFO_EMPTY) { 195034642Smarc dga->csr |= SET_DONE_FIFO; 195130391Skarels } 195230391Skarels 195330391Skarels if (request->DMAdone & WORD_PACK) 195430391Skarels dga->csr &= ~BYTE_DMA; 195530391Skarels else if (request->DMAdone & BYTE_PACK) 195630391Skarels dga->csr |= BYTE_DMA; 195730391Skarels 195830391Skarels dga->csr |= DMA_IE; 195934642Smarc QDlast_DMAtype = request->DMAtype; 196030391Skarels 196130391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 196230391Skarels 196330391Skarels dga->adrs_lo = (short) cookie; 196430391Skarels dga->adrs_hi = (short) (cookie >> 16); 196530391Skarels 196630391Skarels dga->bytcnt_lo = (short) request->length; 196730391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 196830391Skarels 196930391Skarels return; 197030391Skarels } 197130391Skarels 197234732Smarc /* 197334732Smarc * ADDER interrupt service routine 197434732Smarc */ 197530391Skarels qdaint(qd) 197634732Smarc register qd; 197730391Skarels { 197830391Skarels register struct adder *adder; 197930391Skarels struct color_buf *cbuf; 198030391Skarels int i; 198130391Skarels register struct rgb *rgbp; 198230391Skarels register short *red; 198330391Skarels register short *green; 198430391Skarels register short *blue; 198530391Skarels 198634732Smarc (void)spl4(); /* allow interval timer in */ 198730391Skarels 198830391Skarels adder = (struct adder *) qdmap[qd].adder; 198930391Skarels 199034642Smarc /* 199134642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 199234642Smarc * any pending color map load request 199334642Smarc */ 199430391Skarels if (adder->status & VSYNC) { 199534642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 199634642Smarc cbuf = color_buf[qd]; 199734642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 199830391Skarels 199934642Smarc red = (short *) qdmap[qd].red; 200034642Smarc green = (short *) qdmap[qd].green; 200134642Smarc blue = (short *) qdmap[qd].blue; 200230391Skarels 200334642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 200434642Smarc --i >= 0; rgbp++) { 200534642Smarc red[rgbp->offset] = (short) rgbp->red; 200634642Smarc green[rgbp->offset] = (short) rgbp->green; 200734642Smarc blue[rgbp->offset] = (short) rgbp->blue; 200834642Smarc } 200930391Skarels 201034642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 201130391Skarels } 201230391Skarels } 201330391Skarels 201434642Smarc /* 201534642Smarc * service the scroll interrupt (FRAME_SYNC bit) 201634642Smarc */ 201730391Skarels if (adder->status & FRAME_SYNC) { 201834642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 201930391Skarels 202034642Smarc if (scroll[qd]->status & LOAD_REGS) { 202130391Skarels 202234732Smarc for (i = 1000, adder->status = 0; i > 0 && 202334732Smarc !(adder->status&ID_SCROLL_READY); --i) 202434642Smarc ; 202530391Skarels 202634642Smarc if (i == 0) { 202734732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 202834642Smarc qd); 202934642Smarc return; 203034642Smarc } 203130391Skarels 203234642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 203334642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 203430391Skarels 203534642Smarc adder->y_scroll_constant = 203634642Smarc scroll[qd]->y_scroll_constant; 203734642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 203830391Skarels 203934642Smarc if (scroll[qd]->status & LOAD_INDEX) { 204030391Skarels 204134642Smarc adder->x_index_pending = 204234642Smarc scroll[qd]->x_index_pending; 204334642Smarc adder->y_index_pending = 204434642Smarc scroll[qd]->y_index_pending; 204534642Smarc } 204634642Smarc 204734642Smarc scroll[qd]->status = 0x00; 204830391Skarels } 204930391Skarels } 205030391Skarels } 205130391Skarels 205234732Smarc /* 205334732Smarc * DUART input interrupt service routine 205434732Smarc * 205534732Smarc * XXX - this routine should be broken out - it is essentially 205634732Smarc * straight line code. 205734732Smarc */ 205830391Skarels 205930391Skarels qdiint(qd) 206034732Smarc register qd; 206130391Skarels { 206230391Skarels register struct _vs_event *event; 206330391Skarels register struct qdinput *eqh; 206430391Skarels struct dga *dga; 206530391Skarels struct duart *duart; 206630391Skarels struct mouse_report *new_rep; 206730391Skarels struct uba_device *ui; 206830391Skarels struct tty *tp; 206934615Smarc u_short chr; 207030391Skarels u_short status; 207130391Skarels u_short data; 207230391Skarels u_short key; 207330391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 207430391Skarels char a, b, c; /* mouse button test variables */ 207530391Skarels 207634732Smarc (void)spl4(); /* allow interval timer in */ 207730391Skarels 207830391Skarels eqh = eq_header[qd]; /* optimized as a register */ 207930391Skarels new_rep = ¤t_rep[qd]; 208030391Skarels duart = (struct duart *) qdmap[qd].duart; 208130391Skarels 208234642Smarc /* 208334732Smarc * if the graphic device is turned on.. 208434732Smarc */ 208530391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 208634642Smarc /* 208734642Smarc * empty DUART 208834642Smarc */ 208934732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 209034642Smarc /* 209134732Smarc * pick up LK-201 input (if any) 209234732Smarc */ 209334732Smarc if (duart->statusA&RCV_RDY) { 209430391Skarels 209534642Smarc /* if error condition, then reset it */ 209630391Skarels 209734732Smarc if (duart->statusA&0x70) { 209834642Smarc duart->cmdA = 0x40; 209934642Smarc continue; 210034642Smarc } 210130391Skarels 210234642Smarc /* event queue full now? (overflow condition) */ 210330391Skarels 210434642Smarc if (ISFULL(eqh) == TRUE) { 210534642Smarc printf( 210634732Smarc "qd%d: qdiint: event queue overflow\n", 210734642Smarc qd); 210834642Smarc break; 210934642Smarc } 211030391Skarels 211134642Smarc /* 211234642Smarc * Check for various keyboard errors */ 211330391Skarels 211434642Smarc key = duart->dataA & 0xFF; 211530391Skarels 211634642Smarc if (key==LK_POWER_ERROR || 211734642Smarc key==LK_KDOWN_ERROR || 211834642Smarc key == LK_INPUT_ERROR || 211934642Smarc key == LK_OUTPUT_ERROR) { 212034642Smarc printf( 212134732Smarc "qd%d: qdiint: keyboard error, code = %x\n", 212234642Smarc qd,key); 212334732Smarc return; 212434642Smarc } 212530391Skarels 212634642Smarc if (key < LK_LOWEST) 212734732Smarc return; 212830391Skarels 212934642Smarc ++do_wakeup; /* request a select wakeup call */ 213030391Skarels 213134642Smarc event = PUTBEGIN(eqh); 213234642Smarc PUTEND(eqh); 213330391Skarels 213434642Smarc event->vse_key = key; 213534642Smarc event->vse_key &= 0x00FF; 213634642Smarc event->vse_x = eqh->curs_pos.x; 213734642Smarc event->vse_y = eqh->curs_pos.y; 213834642Smarc event->vse_time = TOY; 213934642Smarc event->vse_type = VSE_BUTTON; 214034642Smarc event->vse_direction = VSE_KBTRAW; 214134642Smarc event->vse_device = VSE_DKB; 214234642Smarc } 214330391Skarels 214434642Smarc /* 214534642Smarc * pick up the mouse input (if any) */ 214630391Skarels 214734642Smarc if ((status = duart->statusB) & RCV_RDY && 214834642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 214930391Skarels 215034642Smarc if (status & 0x70) { 215134642Smarc duart->cmdB = 0x40; 215234642Smarc continue; 215334642Smarc } 215430391Skarels 215534642Smarc /* event queue full now? (overflow condition) */ 215630391Skarels 215734642Smarc if (ISFULL(eqh) == TRUE) { 215834642Smarc printf( 215934732Smarc "qd%d: qdiint: event queue overflow\n", 216034642Smarc qd); 216134642Smarc break; 216234642Smarc } 216330391Skarels 216434642Smarc data = duart->dataB; /* get report byte */ 216534642Smarc ++new_rep->bytcnt; /* bump report byte count */ 216630391Skarels 216734642Smarc /* 216834642Smarc * if 1st byte of report.. */ 216930391Skarels 217034642Smarc if ( data & START_FRAME) { 217134642Smarc new_rep->state = data; 217234642Smarc if (new_rep->bytcnt > 1) { 217334642Smarc /* start of new frame */ 217434642Smarc new_rep->bytcnt = 1; 217534642Smarc /* ..continue looking */ 217634642Smarc continue; 217734642Smarc } 217834642Smarc } 217930391Skarels 218034642Smarc /* 218134642Smarc * if 2nd byte of report.. */ 218230391Skarels 218334642Smarc else if (new_rep->bytcnt == 2) { 218434642Smarc new_rep->dx = data & 0x00FF; 218534642Smarc } 218630391Skarels 218734642Smarc /* 218834642Smarc * if 3rd byte of report, load input event queue */ 218930391Skarels 219034642Smarc else if (new_rep->bytcnt == 3) { 219130391Skarels 219234642Smarc new_rep->dy = data & 0x00FF; 219334642Smarc new_rep->bytcnt = 0; 219430391Skarels 219534642Smarc /* 219634642Smarc * if mouse position has changed.. */ 219730391Skarels 219834642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 219930391Skarels 220034642Smarc /* 220134642Smarc * calculate acceleration factor, if needed */ 220230391Skarels 220334642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 220430391Skarels 220534642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 220634642Smarc new_rep->dx += 220734642Smarc (new_rep->dx - qdflags[qd].curs_thr) 220834642Smarc * qdflags[qd].curs_acc; 220930391Skarels 221034642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 221134642Smarc new_rep->dy += 221234642Smarc (new_rep->dy - qdflags[qd].curs_thr) 221334642Smarc * qdflags[qd].curs_acc; 221434642Smarc } 221530391Skarels 221634642Smarc /* 221734642Smarc * update cursor position coordinates */ 221830391Skarels 221934642Smarc if (new_rep->state & X_SIGN) { 222034642Smarc eqh->curs_pos.x += new_rep->dx; 222134642Smarc if (eqh->curs_pos.x > 1023) 222234642Smarc eqh->curs_pos.x = 1023; 222334642Smarc } 222434642Smarc else { 222534642Smarc eqh->curs_pos.x -= new_rep->dx; 222634642Smarc if (eqh->curs_pos.x < -15) 222734642Smarc eqh->curs_pos.x = -15; 222834642Smarc } 222930391Skarels 223034642Smarc if (new_rep->state & Y_SIGN) { 223134642Smarc eqh->curs_pos.y -= new_rep->dy; 223234642Smarc if (eqh->curs_pos.y < -15) 223334642Smarc eqh->curs_pos.y = -15; 223434642Smarc } 223534642Smarc else { 223634642Smarc eqh->curs_pos.y += new_rep->dy; 223734642Smarc if (eqh->curs_pos.y > 863) 223834642Smarc eqh->curs_pos.y = 863; 223934642Smarc } 224030391Skarels 224134642Smarc /* 224234642Smarc * update cursor screen position */ 224330391Skarels 224434642Smarc dga = (struct dga *) qdmap[qd].dga; 224534642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 224634642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 224730391Skarels 224834642Smarc /* 224934642Smarc * if cursor is in the box, no event report */ 225030391Skarels 225134642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 225234642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 225334642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 225434642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 225534642Smarc goto GET_MBUTTON; 225634642Smarc } 225730391Skarels 225834642Smarc /* 225934642Smarc * report the mouse motion event */ 226030391Skarels 226134642Smarc event = PUTBEGIN(eqh); 226234642Smarc PUTEND(eqh); 226330391Skarels 226434642Smarc ++do_wakeup; /* request a select wakeup call */ 226530391Skarels 226634642Smarc event->vse_x = eqh->curs_pos.x; 226734642Smarc event->vse_y = eqh->curs_pos.y; 226830391Skarels 226934642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 227034642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 227134642Smarc event->vse_key = 0; 227234642Smarc event->vse_direction = 0; 227334642Smarc event->vse_time = TOY; /* time stamp */ 227434642Smarc } 227530391Skarels 227630391Skarels GET_MBUTTON: 227734642Smarc /* 227834642Smarc * if button state has changed */ 227930391Skarels 228034642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 228134642Smarc b = last_rep[qd].state & 0x07; 228230391Skarels 228334642Smarc if (a ^ b) { 228430391Skarels 228534642Smarc for ( c = 1; c < 8; c <<= 1) { 228630391Skarels 228734642Smarc if (!( c & (a ^ b))) /* this button change? */ 228834642Smarc continue; 228930391Skarels 229034642Smarc /* event queue full? (overflow condition) */ 229130391Skarels 229234642Smarc if (ISFULL(eqh) == TRUE) { 229334732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 229434642Smarc break; 229534642Smarc } 229630391Skarels 229734642Smarc event = PUTBEGIN(eqh); /* get new event */ 229834642Smarc PUTEND(eqh); 229930391Skarels 230034642Smarc ++do_wakeup; /* request select wakeup */ 230130391Skarels 230234642Smarc event->vse_x = eqh->curs_pos.x; 230334642Smarc event->vse_y = eqh->curs_pos.y; 230430391Skarels 230534642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 230634642Smarc event->vse_type = VSE_BUTTON; /* new button */ 230734642Smarc event->vse_time = TOY; /* time stamp */ 230830391Skarels 230934642Smarc /* flag changed button and if up or down */ 231030391Skarels 231134642Smarc if (c == RIGHT_BUTTON) 231234642Smarc event->vse_key = VSE_RIGHT_BUTTON; 231334642Smarc else if (c == MIDDLE_BUTTON) 231434642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 231534642Smarc else if (c == LEFT_BUTTON) 231634642Smarc event->vse_key = VSE_LEFT_BUTTON; 231730391Skarels 231834642Smarc /* set bit = button depressed */ 231930391Skarels 232034642Smarc if (c & a) 232134642Smarc event->vse_direction = VSE_KBTDOWN; 232234642Smarc else 232334642Smarc event->vse_direction = VSE_KBTUP; 232434642Smarc } 232534642Smarc } 232630391Skarels 232734642Smarc /* refresh last report */ 232830391Skarels 232934642Smarc last_rep[qd] = current_rep[qd]; 233030391Skarels 233134642Smarc } /* get last byte of report */ 233234732Smarc } else if ((status = duart->statusB)&RCV_RDY && 233334732Smarc qdflags[qd].pntr_id == TABLET_ID) { 233434732Smarc /* 233534732Smarc * pickup tablet input, if any 233634732Smarc */ 233734732Smarc if (status&0x70) { 233834642Smarc duart->cmdB = 0x40; 233934642Smarc continue; 234034642Smarc } 234134732Smarc /* 234234732Smarc * event queue full now? (overflow condition) 234334732Smarc */ 234434642Smarc if (ISFULL(eqh) == TRUE) { 234534732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 234634642Smarc break; 234734642Smarc } 234830391Skarels 234934642Smarc data = duart->dataB; /* get report byte */ 235034642Smarc ++new_rep->bytcnt; /* bump report byte count */ 235130391Skarels 235234642Smarc /* 235334642Smarc * if 1st byte of report.. */ 235430391Skarels 235534642Smarc if (data & START_FRAME) { 235634642Smarc new_rep->state = data; 235734642Smarc if (new_rep->bytcnt > 1) { 235834642Smarc new_rep->bytcnt = 1; /* start of new frame */ 235934642Smarc continue; /* ..continue looking */ 236034642Smarc } 236134642Smarc } 236230391Skarels 236334642Smarc /* 236434642Smarc * if 2nd byte of report.. */ 236530391Skarels 236634642Smarc else if (new_rep->bytcnt == 2) { 236734642Smarc new_rep->dx = data & 0x3F; 236834642Smarc } 236930391Skarels 237034642Smarc /* 237134642Smarc * if 3rd byte of report.. */ 237230391Skarels 237334642Smarc else if (new_rep->bytcnt == 3) { 237434642Smarc new_rep->dx |= (data & 0x3F) << 6; 237534642Smarc } 237630391Skarels 237734642Smarc /* 237834642Smarc * if 4th byte of report.. */ 237930391Skarels 238034642Smarc else if (new_rep->bytcnt == 4) { 238134642Smarc new_rep->dy = data & 0x3F; 238234642Smarc } 238330391Skarels 238434642Smarc /* 238534642Smarc * if 5th byte of report, load input event queue */ 238630391Skarels 238734642Smarc else if (new_rep->bytcnt == 5) { 238830391Skarels 238934642Smarc new_rep->dy |= (data & 0x3F) << 6; 239034642Smarc new_rep->bytcnt = 0; 239130391Skarels 239234642Smarc /* 239334642Smarc * update cursor position coordinates */ 239430391Skarels 239534642Smarc new_rep->dx /= qdflags[qd].tab_res; 239634642Smarc new_rep->dy = (2200 - new_rep->dy) 239734642Smarc / qdflags[qd].tab_res; 239830391Skarels 239934642Smarc if (new_rep->dx > 1023) { 240034642Smarc new_rep->dx = 1023; 240134642Smarc } 240234642Smarc if (new_rep->dy > 863) { 240334642Smarc new_rep->dy = 863; 240434642Smarc } 240530391Skarels 240634642Smarc /* 240734642Smarc * report an event if the puck/stylus has moved 240834642Smarc */ 240930391Skarels 241034642Smarc if (eqh->curs_pos.x != new_rep->dx || 241134642Smarc eqh->curs_pos.y != new_rep->dy) { 241230391Skarels 241334642Smarc eqh->curs_pos.x = new_rep->dx; 241434642Smarc eqh->curs_pos.y = new_rep->dy; 241530391Skarels 241634642Smarc /* 241734642Smarc * update cursor screen position */ 241830391Skarels 241934642Smarc dga = (struct dga *) qdmap[qd].dga; 242034642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 242134642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 242230391Skarels 242334642Smarc /* 242434642Smarc * if cursor is in the box, no event report 242534642Smarc */ 242630391Skarels 242734642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 242834642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 242934642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 243034642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 243134642Smarc goto GET_TBUTTON; 243234642Smarc } 243330391Skarels 243434642Smarc /* 243534642Smarc * report the tablet motion event */ 243630391Skarels 243734642Smarc event = PUTBEGIN(eqh); 243834642Smarc PUTEND(eqh); 243930391Skarels 244034642Smarc ++do_wakeup; /* request a select wakeup call */ 244130391Skarels 244234642Smarc event->vse_x = eqh->curs_pos.x; 244334642Smarc event->vse_y = eqh->curs_pos.y; 244430391Skarels 244534642Smarc event->vse_device = VSE_TABLET; /* tablet */ 244634642Smarc /* 244734642Smarc * right now, X handles tablet motion the same 244834642Smarc * as mouse motion 244934642Smarc */ 245034642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 245134642Smarc event->vse_key = 0; 245234642Smarc event->vse_direction = 0; 245334642Smarc event->vse_time = TOY; /* time stamp */ 245434642Smarc } 245530391Skarels GET_TBUTTON: 245634642Smarc /* 245734642Smarc * if button state has changed */ 245830391Skarels 245934642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 246034642Smarc b = last_rep[qd].state & 0x1E; 246130391Skarels 246234642Smarc if (a ^ b) { 246330391Skarels 246434642Smarc /* event queue full now? (overflow condition) */ 246530391Skarels 246634642Smarc if (ISFULL(eqh) == TRUE) { 246734732Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 246834642Smarc break; 246934642Smarc } 247030391Skarels 247134642Smarc event = PUTBEGIN(eqh); /* get new event */ 247234642Smarc PUTEND(eqh); 247330391Skarels 247434642Smarc ++do_wakeup; /* request a select wakeup call */ 247530391Skarels 247634642Smarc event->vse_x = eqh->curs_pos.x; 247734642Smarc event->vse_y = eqh->curs_pos.y; 247830391Skarels 247934642Smarc event->vse_device = VSE_TABLET; /* tablet */ 248034642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 248134642Smarc event->vse_time = TOY; /* time stamp */ 248230391Skarels 248334642Smarc /* define the changed button and if up or down */ 248430391Skarels 248534642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 248634642Smarc if (c & (a ^ b)) { 248734642Smarc if (c == T_LEFT_BUTTON) 248834642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 248934642Smarc else if (c == T_FRONT_BUTTON) 249034642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 249134642Smarc else if (c == T_RIGHT_BUTTON) 249234642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 249334642Smarc else if (c == T_BACK_BUTTON) 249434642Smarc event->vse_key = VSE_T_BACK_BUTTON; 249534642Smarc break; 249634642Smarc } 249734642Smarc } 249830391Skarels 249934642Smarc /* set bit = button depressed */ 250030391Skarels 250134642Smarc if (c & a) 250234642Smarc event->vse_direction = VSE_KBTDOWN; 250334642Smarc else 250434642Smarc event->vse_direction = VSE_KBTUP; 250534642Smarc } 250630391Skarels 250734642Smarc /* refresh last report */ 250830391Skarels 250934642Smarc last_rep[qd] = current_rep[qd]; 251030391Skarels 251134642Smarc } /* get last byte of report */ 251234642Smarc } /* pick up tablet input */ 251330391Skarels 251434642Smarc } /* while input available.. */ 251530391Skarels 251634642Smarc /* 251734642Smarc * do select wakeup 251834642Smarc */ 251934732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 252034732Smarc selwakeup(qdrsel[qd], 0); 252134732Smarc qdrsel[qd] = 0; 252234642Smarc qdflags[qd].selmask &= ~SEL_READ; 252334642Smarc do_wakeup = 0; 252434642Smarc } 252534732Smarc } else { 252634732Smarc /* 252734732Smarc * if the graphic device is not turned on, this is console input 252834732Smarc */ 252940817Smarc if (qdpolling) 253040817Smarc return; 253134642Smarc ui = qdinfo[qd]; 253234642Smarc if (ui == 0 || ui->ui_alive == 0) 253334732Smarc return; 253430391Skarels 253534642Smarc tp = &qd_tty[qd << 2]; 253630391Skarels 253734642Smarc /* 253834732Smarc * Get a character from the keyboard. 253934732Smarc */ 254034732Smarc while (duart->statusA&RCV_RDY) { 254134642Smarc key = duart->dataA; 254234642Smarc key &= 0xFF; 254334642Smarc /* 254434732Smarc * Check for various keyboard errors 254534732Smarc */ 254634732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 254734642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 254834732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 254934732Smarc return; 255034642Smarc } 255130391Skarels 255234642Smarc if (key < LK_LOWEST) 255334732Smarc return; 255430391Skarels 255534642Smarc /* 255634642Smarc * See if its a state change key */ 255730391Skarels 255834642Smarc switch (key) { 255930391Skarels 256034642Smarc case LOCK: 256134642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 256234642Smarc if (q_keyboard.lock) 256334732Smarc (void)led_control(qd, LK_LED_ENABLE, 256434732Smarc LK_LED_LOCK); 256534642Smarc else 256634732Smarc (void)led_control(qd, LK_LED_DISABLE, 256734732Smarc LK_LED_LOCK); 256834642Smarc return; 256930391Skarels 257034642Smarc case SHIFT: 257134642Smarc q_keyboard.shift ^= 0xFFFF; 257234642Smarc return; 257330391Skarels 257434642Smarc case CNTRL: 257534642Smarc q_keyboard.cntrl ^= 0xFFFF; 257634642Smarc return; 257730391Skarels 257834642Smarc case ALLUP: 257934642Smarc q_keyboard.cntrl = 0; 258034642Smarc q_keyboard.shift = 0; 258134642Smarc return; 258230391Skarels 258334642Smarc case REPEAT: 258434642Smarc chr = q_keyboard.last; 258534642Smarc break; 258630391Skarels 258734642Smarc /* 258834642Smarc * Test for cntrl characters. If set, see if the character 258934642Smarc * is elligible to become a control character. */ 259030391Skarels 259134642Smarc default: 259230391Skarels 259334642Smarc if (q_keyboard.cntrl) { 259434642Smarc chr = q_key[key]; 259534642Smarc if (chr >= ' ' && chr <= '~') 259634642Smarc chr &= 0x1F; 259734642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 259834642Smarc chr &= 0x9F; 259934642Smarc } 260034642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 260134642Smarc chr = q_shift_key[key]; 260234642Smarc else 260334642Smarc chr = q_key[key]; 260434642Smarc break; 260530391Skarels } 260630391Skarels 260734642Smarc q_keyboard.last = chr; 260830391Skarels 260934642Smarc /* 261034642Smarc * Check for special function keys */ 261130391Skarels 261234642Smarc if (chr & 0x100) { 261334642Smarc char *string; 261434642Smarc string = q_special[chr & 0x7F]; 261534642Smarc while(*string) 261634642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 261734615Smarc } 261834642Smarc else { 261940817Smarc #ifdef KADB 262040817Smarc if (!kdbrintr(chr&0177, tp)) 262140817Smarc #endif 262234642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 262334642Smarc } 262430391Skarels } 262530391Skarels } 262630391Skarels } /* qdiint */ 262730391Skarels 262834732Smarc /* 262934732Smarc * 263034732Smarc * Clear the QDSS screen 263134732Smarc * 263234732Smarc * >>> NOTE <<< 263334732Smarc * 263434732Smarc * This code requires that certain adder initialization be valid. To 263534732Smarc * assure that this requirement is satisfied, this routine should be 263634732Smarc * called only after calling the "setup_dragon()" function. 263734732Smarc * 263834732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear 263934732Smarc * only clears the current displayed portion of the bitmap put a 264034732Smarc * temporary value in the y limit register so we can access whole 264134732Smarc * bitmap 264234732Smarc * 264334732Smarc */ 264430391Skarels clear_qd_screen(unit) 264534732Smarc int unit; 264630391Skarels { 264730391Skarels register struct adder *adder; 264830391Skarels adder = (struct adder *) qdmap[unit].adder; 264930391Skarels 265030391Skarels adder->x_limit = 1024; 265130391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 265230391Skarels adder->y_offset_pending = 0; 265334732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 265434642Smarc WSV; 265530391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265634642Smarc WSV; 265730391Skarels adder->y_offset_pending = 864; 265834642Smarc WSV; 265930391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266034642Smarc WSV; 266130391Skarels adder->y_offset_pending = 1728; 266234642Smarc WSV; 266330391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266434642Smarc WSV; 266530391Skarels adder->y_offset_pending = 0; /* back to normal */ 266634642Smarc WSV; 266730391Skarels adder->x_limit = MAX_SCREEN_X; 266830391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 266934642Smarc #undef WSV 267030391Skarels 267130391Skarels } /* clear_qd_screen */ 267230391Skarels 267334732Smarc /* 267434732Smarc * kernel console output to the glass tty 267534732Smarc */ 267630391Skarels qdputc(chr) 267734642Smarc register char chr; 267830391Skarels { 267930391Skarels 268034642Smarc /* 268134642Smarc * if system is now physical, forget it (ie: crash DUMP) 268234642Smarc */ 268334642Smarc if ((mfpr(MAPEN) & 1) == 0) 268434642Smarc return; 268534615Smarc 268634732Smarc blitc(0, (u_char)(chr & 0xff)); 268732012Smarc if ((chr & 0177) == '\n') 268832012Smarc blitc(0, '\r'); 268930391Skarels 269030391Skarels } /* qdputc */ 269130391Skarels 269234732Smarc /* 269334732Smarc * load the mouse cursor's template RAM bitmap 269434732Smarc */ 269530391Skarels ldcursor(unit, bitmap) 269634732Smarc int unit; 269734732Smarc register short *bitmap; 269830391Skarels { 269930391Skarels register struct dga *dga; 270030391Skarels register short *temp; 270130391Skarels register int i; 270234732Smarc int curs; 270330391Skarels 270430391Skarels dga = (struct dga *) qdmap[unit].dga; 270530391Skarels temp = (short *) qdmap[unit].template; 270630391Skarels 270730391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 270834732Smarc curs = -1; /* ..note that.. */ 270934642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 271034732Smarc } else 271134732Smarc curs = 0; 271230391Skarels 271330391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 271430391Skarels 271530391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 271634642Smarc /* ..of the 8k WORD template space */ 271730391Skarels for (i = 0; i < 32; ++i) 271834642Smarc *temp++ = *bitmap++; 271930391Skarels 272034732Smarc if (curs) { /* if cursor was enabled.. */ 272134642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 272230391Skarels } 272330391Skarels 272430391Skarels } /* ldcursor */ 272530391Skarels 272634732Smarc /* 272734732Smarc * Put the console font in the QDSS off-screen memory 272834732Smarc */ 272930391Skarels ldfont(unit) 273034732Smarc int unit; 273130391Skarels { 273230391Skarels register struct adder *adder; 273330391Skarels 273434732Smarc register i, j, k, max_chars_line; 273534732Smarc register short packed; 273630391Skarels 273730391Skarels adder = (struct adder *) qdmap[unit].adder; 273830391Skarels 273934642Smarc /* 274034732Smarc * setup VIPER operand control registers 274134732Smarc */ 274230391Skarels write_ID(adder, MASK_1, 0xFFFF); 274330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 274430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 274530391Skarels 274630391Skarels write_ID(adder, SRC1_OCR_B, 274734642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 274830391Skarels write_ID(adder, SRC2_OCR_B, 274934642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 275030391Skarels write_ID(adder, DST_OCR_B, 275134642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 275230391Skarels 275330391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 275430391Skarels 275534642Smarc /* 275634732Smarc * load destination data 275734732Smarc */ 275834732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 275930391Skarels 276030391Skarels adder->destination_x = FONT_X; 276130391Skarels adder->destination_y = FONT_Y; 276234732Smarc #if FONT_WIDTH > MAX_SCREEN_X 276334732Smarc adder->fast_dest_dx = MAX_SCREEN_X; 276434732Smarc #else 276534732Smarc adder->fast_dest_dx = FONT_WIDTH; 276634732Smarc #endif 276730391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 276830391Skarels 276934642Smarc /* 277034642Smarc * setup for processor to bitmap xfer */ 277130391Skarels 277230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 277330391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 277430391Skarels 277534642Smarc /* 277634642Smarc * Figure out how many characters can be stored on one "line" of 277734642Smarc * offscreen memory. 277834642Smarc */ 277934642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 278034642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 278134642Smarc max_chars_line = CHARS/2 + CHARS%2; 278230391Skarels 278334642Smarc /* 278434642Smarc * iteratively do the processor to bitmap xfer */ 278534615Smarc 278630391Skarels for (i = 0; i < ROWS; ++i) { 278730391Skarels 278834642Smarc /* PTOB a scan line */ 278930391Skarels 279034642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 279134642Smarc /* PTOB one scan of a char cell */ 279230391Skarels 279334642Smarc packed = q_font[k]; 279434642Smarc k += ROWS; 279534642Smarc packed |= ((short)q_font[k] << 8); 279634642Smarc k += ROWS; 279730391Skarels 279834732Smarc (void)wait_status(adder, TX_READY); 279934642Smarc adder->id_data = packed; 280034642Smarc } 280130391Skarels } 280230391Skarels 280334642Smarc /* 280434642Smarc * (XXX XXX XXX - should remove) 280534642Smarc * 280634642Smarc * Copy the second row of characters. Subtract the first 280734642Smarc * row from the total number. Divide this quantity by 2 280834642Smarc * because 2 chars are stored in a short in the PTOB loop 280934642Smarc * below. Figure out how many characters can be stored on 281034642Smarc * one "line" of offscreen memory 281134642Smarc */ 281234642Smarc 281334642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 281434642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 281534642Smarc return; 281634642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 281734642Smarc /* Paranoia check to see if 3rd row may be needed */ 281834642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 281934615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 282034615Smarc 282134615Smarc adder->destination_x = FONT_X; 282234615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 282334615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 282434615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 282534615Smarc 282634642Smarc /* 282734642Smarc * setup for processor to bitmap xfer 282834642Smarc */ 282934615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 283034615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 283134615Smarc 283234642Smarc /* 283334642Smarc * iteratively do the processor to bitmap xfer 283434642Smarc */ 283534615Smarc for (i = 0; i < ROWS; ++i) { 283634642Smarc /* 283734642Smarc * PTOB a scan line 283834642Smarc */ 283934642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 284034642Smarc /* 284134642Smarc * PTOB one scan of a char cell 284234642Smarc */ 284334642Smarc packed = q_font[k + FONT_OFFSET]; 284434642Smarc k += ROWS; 284534642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 284634642Smarc k += ROWS; 284734732Smarc (void)wait_status(adder, TX_READY); 284834642Smarc adder->id_data = packed; 284934642Smarc } 285034615Smarc } 285134615Smarc 285230391Skarels } /* ldfont */ 285330391Skarels 285440817Smarc qdpoll(onoff) 285540817Smarc { 285640817Smarc qdpolling = onoff; 285740817Smarc } 285840817Smarc 285934732Smarc /* 286034732Smarc * Get a character from the LK201 (polled) 286134732Smarc */ 286234732Smarc qdgetc() 286334732Smarc { 286434732Smarc register short key; 286534732Smarc register char chr; 286634732Smarc register struct duart *duart; 286730391Skarels 286834732Smarc duart = (struct duart *) qdmap[0].duart; 286934732Smarc 287034732Smarc /* 287134732Smarc * Get a character from the keyboard. 287234732Smarc */ 287334732Smarc LOOP: 287434732Smarc while (!(duart->statusA&RCV_RDY)) 287534732Smarc ; 287634732Smarc 287734732Smarc key = duart->dataA; 287834732Smarc key &= 0xFF; 287934732Smarc 288034732Smarc /* 288134732Smarc * Check for various keyboard errors */ 288234732Smarc 288334732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 288434732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 288534732Smarc printf("Keyboard error, code = %x\n", key); 288634732Smarc return(0); 288734732Smarc } 288834732Smarc 288934732Smarc if (key < LK_LOWEST) 289034732Smarc return(0); 289134732Smarc 289234732Smarc /* 289334732Smarc * See if its a state change key 289434732Smarc */ 289534732Smarc switch (key) { 289634732Smarc 289734732Smarc case LOCK: 289834732Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 289934732Smarc if (q_keyboard.lock) 290034732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 290134732Smarc else 290234732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 290334732Smarc goto LOOP; 290434732Smarc 290534732Smarc case SHIFT: 290634732Smarc q_keyboard.shift ^= 0xFFFF; 290734732Smarc goto LOOP; 290834732Smarc 290934732Smarc case CNTRL: 291034732Smarc q_keyboard.cntrl ^= 0xFFFF; 291134732Smarc goto LOOP; 291234732Smarc 291334732Smarc case ALLUP: 291434732Smarc q_keyboard.cntrl = 0; 291534732Smarc q_keyboard.shift = 0; 291634732Smarc goto LOOP; 291734732Smarc 291834732Smarc case REPEAT: 291934732Smarc chr = q_keyboard.last; 292034732Smarc break; 292134732Smarc 292234732Smarc /* 292334732Smarc * Test for cntrl characters. If set, see if the character 292434732Smarc * is elligible to become a control character. 292534732Smarc */ 292634732Smarc default: 292734732Smarc 292834732Smarc if (q_keyboard.cntrl) { 292934732Smarc chr = q_key[key]; 293034732Smarc if (chr >= ' ' && chr <= '~') 293134732Smarc chr &= 0x1F; 293234732Smarc } 293334732Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 293434732Smarc chr = q_shift_key[key]; 293534732Smarc else 293634732Smarc chr = q_key[key]; 293734732Smarc break; 293834732Smarc } 293934732Smarc 294034732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 294134732Smarc return(0); /* ..then pitch it! */ 294234732Smarc 294334732Smarc q_keyboard.last = chr; 294434732Smarc 294534732Smarc /* 294634732Smarc * Check for special function keys */ 294734732Smarc 294834732Smarc if (chr & 0x80) /* pitch the function keys */ 294934732Smarc return(0); 295034732Smarc else 295134732Smarc return(chr); 295234732Smarc 295334732Smarc } /* qdgetc */ 295434732Smarc 295534732Smarc /* 295634732Smarc * led_control()... twiddle LK-201 LED's 295734732Smarc */ 295830391Skarels led_control(unit, cmd, led_mask) 295934732Smarc int unit, cmd, led_mask; 296030391Skarels { 296134732Smarc register i; 296230391Skarels register struct duart *duart; 296330391Skarels 296434732Smarc duart = (struct duart *)qdmap[unit].duart; 296530391Skarels 296630391Skarels for (i = 1000; i > 0; --i) { 296734732Smarc if (duart->statusA&XMT_RDY) { 296834642Smarc duart->dataA = cmd; 296934642Smarc break; 297034642Smarc } 297130391Skarels } 297230391Skarels for (i = 1000; i > 0; --i) { 297334732Smarc if (duart->statusA&XMT_RDY) { 297434642Smarc duart->dataA = led_mask; 297534642Smarc break; 297634642Smarc } 297730391Skarels } 297830391Skarels if (i == 0) 297934642Smarc return(BAD); 298030391Skarels return(GOOD); 298130391Skarels 298230391Skarels } /* led_control */ 298330391Skarels 298434732Smarc /* 298534732Smarc * scroll_up()... move the screen up one character height 298634732Smarc */ 298730391Skarels scroll_up(adder) 298834642Smarc register struct adder *adder; 298930391Skarels { 299034642Smarc /* 299134642Smarc * setup VIPER operand control registers 299234642Smarc */ 299334732Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 299430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 299530391Skarels write_ID(adder, MASK_1, 0xFFFF); 299630391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 299730391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 299830391Skarels write_ID(adder, SRC1_OCR_B, 299934642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 300030391Skarels write_ID(adder, DST_OCR_B, 300134642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 300234642Smarc /* 300334642Smarc * load DESTINATION origin and vectors 300434642Smarc */ 300530391Skarels adder->fast_dest_dy = 0; 300630391Skarels adder->slow_dest_dx = 0; 300730391Skarels adder->error_1 = 0; 300830391Skarels adder->error_2 = 0; 300930391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 301030391Skarels adder->destination_x = 0; 301130391Skarels adder->fast_dest_dx = 1024; 301230391Skarels adder->destination_y = 0; 301330391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 301434642Smarc /* 301534642Smarc * load SOURCE origin and vectors 301634642Smarc */ 301730391Skarels adder->source_1_x = 0; 301830391Skarels adder->source_1_dx = 1024; 301930391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 302030391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 302130391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 302230391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 302334642Smarc /* 302434642Smarc * do a rectangle clear of last screen line 302534642Smarc */ 302630391Skarels write_ID(adder, MASK_1, 0xffff); 302730391Skarels write_ID(adder, SOURCE, 0xffff); 302830391Skarels write_ID(adder,DST_OCR_B, 302934642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 303030391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 303130391Skarels adder->error_1 = 0; 303230391Skarels adder->error_2 = 0; 303334642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 303430391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 303530391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 303634732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 303730391Skarels adder->destination_x = 0; 303830391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 303930391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 304030391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 304130391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 304230391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 304330391Skarels 304430391Skarels } /* scroll_up */ 304530391Skarels 304634732Smarc /* 304734732Smarc * init shared memory pointers and structures 304834732Smarc */ 304930391Skarels init_shared(unit) 305034732Smarc register unit; 305130391Skarels { 305230391Skarels register struct dga *dga; 305330391Skarels 305430391Skarels dga = (struct dga *) qdmap[unit].dga; 305530391Skarels 305634642Smarc /* 305734642Smarc * initialize the event queue pointers and header */ 305830391Skarels 305930391Skarels eq_header[unit] = (struct qdinput *) 306034642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 306134642Smarc + (EVENT_BUFSIZE * unit)); 306230391Skarels eq_header[unit]->curs_pos.x = 0; 306330391Skarels eq_header[unit]->curs_pos.y = 0; 306430391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 306530391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 306630391Skarels eq_header[unit]->curs_box.left = 0; 306730391Skarels eq_header[unit]->curs_box.right = 0; 306830391Skarels eq_header[unit]->curs_box.top = 0; 306930391Skarels eq_header[unit]->curs_box.bottom = 0; 307034642Smarc /* 307134642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 307234642Smarc */ 307330391Skarels DMAheader[unit] = (struct DMAreq_header *) 307434642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 307534642Smarc + (DMAbuf_size * unit)); 307630391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 307734642Smarc + sizeof(struct DMAreq_header)); 307830391Skarels DMAheader[unit]->QBAreg = 0; 307930391Skarels DMAheader[unit]->status = 0; 308030391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 308130391Skarels DMAheader[unit]->used = 0; 308230391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 308330391Skarels DMAheader[unit]->oldest = 0; 308430391Skarels DMAheader[unit]->newest = 0; 308534642Smarc /* 308634642Smarc * assign a pointer to the scroll structure for this QDSS. 308734642Smarc */ 308830391Skarels scroll[unit] = (struct scroll *) 308934642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 309034642Smarc + (sizeof(struct scroll) * unit)); 309130391Skarels scroll[unit]->status = 0; 309230391Skarels scroll[unit]->viper_constant = 0; 309330391Skarels scroll[unit]->y_scroll_constant = 0; 309430391Skarels scroll[unit]->y_offset = 0; 309530391Skarels scroll[unit]->x_index_pending = 0; 309630391Skarels scroll[unit]->y_index_pending = 0; 309734642Smarc /* 309834642Smarc * assign a pointer to the color map write buffer for this QDSS 309934642Smarc */ 310030391Skarels color_buf[unit] = (struct color_buf *) 310134642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 310234642Smarc + (COLOR_BUFSIZ * unit)); 310330391Skarels color_buf[unit]->status = 0; 310430391Skarels color_buf[unit]->count = 0; 310530391Skarels 310630391Skarels } /* init_shared */ 310730391Skarels 310834732Smarc /* 310934732Smarc * init the ADDER, VIPER, bitmaps, & color map 311034732Smarc */ 311130391Skarels setup_dragon(unit) 311234732Smarc int unit; 311330391Skarels { 311430391Skarels 311530391Skarels register struct adder *adder; 311630391Skarels register struct dga *dga; 311730391Skarels short *memcsr; 311834732Smarc register i; 311930391Skarels short top; /* clipping/scrolling boundaries */ 312030391Skarels short bottom; 312130391Skarels short right; 312230391Skarels short left; 312330391Skarels short *red; /* color map pointers */ 312430391Skarels short *green; 312530391Skarels short *blue; 312630391Skarels 312734642Smarc /* 312834642Smarc * init for setup 312934642Smarc */ 313030391Skarels adder = (struct adder *) qdmap[unit].adder; 313130391Skarels dga = (struct dga *) qdmap[unit].dga; 313230391Skarels memcsr = (short *) qdmap[unit].memcsr; 313330391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 313430391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 313530391Skarels adder->command = CANCEL; 313634642Smarc /* 313734642Smarc * set monitor timing 313834642Smarc */ 313930391Skarels adder->x_scan_count_0 = 0x2800; 314030391Skarels adder->x_scan_count_1 = 0x1020; 314130391Skarels adder->x_scan_count_2 = 0x003A; 314230391Skarels adder->x_scan_count_3 = 0x38F0; 314330391Skarels adder->x_scan_count_4 = 0x6128; 314430391Skarels adder->x_scan_count_5 = 0x093A; 314530391Skarels adder->x_scan_count_6 = 0x313C; 314630391Skarels adder->sync_phase_adj = 0x0100; 314730391Skarels adder->x_scan_conf = 0x00C8; 314834642Smarc /* 314934642Smarc * got a bug in secound pass ADDER! lets take care of it 315034642Smarc * 315134642Smarc * normally, just use the code in the following bug fix code, but to 315234642Smarc * make repeated demos look pretty, load the registers as if there was 315334642Smarc * no bug and then test to see if we are getting sync 315434642Smarc */ 315530391Skarels adder->y_scan_count_0 = 0x135F; 315630391Skarels adder->y_scan_count_1 = 0x3363; 315730391Skarels adder->y_scan_count_2 = 0x2366; 315830391Skarels adder->y_scan_count_3 = 0x0388; 315934642Smarc /* 316034642Smarc * if no sync, do the bug fix code 316134642Smarc */ 316230391Skarels if (wait_status(adder, VSYNC) == BAD) { 316334642Smarc /* first load all Y scan registers with very short frame and 316434642Smarc * wait for scroll service. This guarantees at least one SYNC 316534642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 316634642Smarc * XCINCH with DMSEEDH) 316734642Smarc */ 316834642Smarc adder->y_scan_count_0 = 0x01; 316934642Smarc adder->y_scan_count_1 = 0x01; 317034642Smarc adder->y_scan_count_2 = 0x01; 317134642Smarc adder->y_scan_count_3 = 0x01; 317234642Smarc /* 317334642Smarc * delay at least 1 full frame time 317434642Smarc */ 317534732Smarc (void)wait_status(adder, VSYNC); 317634732Smarc (void)wait_status(adder, VSYNC); 317734642Smarc /* 317834642Smarc * now load the REAL sync values (in reverse order just to 317934642Smarc * be safe. 318034642Smarc */ 318134642Smarc adder->y_scan_count_3 = 0x0388; 318234642Smarc adder->y_scan_count_2 = 0x2366; 318334642Smarc adder->y_scan_count_1 = 0x3363; 318434642Smarc adder->y_scan_count_0 = 0x135F; 318530391Skarels } 318630391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 318734642Smarc /* 318834642Smarc * zero the index registers 318934642Smarc */ 319030391Skarels adder->x_index_pending = 0; 319130391Skarels adder->y_index_pending = 0; 319230391Skarels adder->x_index_new = 0; 319330391Skarels adder->y_index_new = 0; 319430391Skarels adder->x_index_old = 0; 319530391Skarels adder->y_index_old = 0; 319630391Skarels adder->pause = 0; 319734642Smarc /* 319834642Smarc * set rasterop mode to normal pen down 319934642Smarc */ 320030391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 320134642Smarc /* 320234642Smarc * set the rasterop registers to a default values 320334642Smarc */ 320430391Skarels adder->source_1_dx = 1; 320530391Skarels adder->source_1_dy = 1; 320630391Skarels adder->source_1_x = 0; 320730391Skarels adder->source_1_y = 0; 320830391Skarels adder->destination_x = 0; 320930391Skarels adder->destination_y = 0; 321030391Skarels adder->fast_dest_dx = 1; 321130391Skarels adder->fast_dest_dy = 0; 321230391Skarels adder->slow_dest_dx = 0; 321330391Skarels adder->slow_dest_dy = 1; 321430391Skarels adder->error_1 = 0; 321530391Skarels adder->error_2 = 0; 321634642Smarc /* 321734732Smarc * scale factor = UNITY 321834642Smarc */ 321930391Skarels adder->fast_scale = UNITY; 322030391Skarels adder->slow_scale = UNITY; 322134642Smarc /* 322234642Smarc * set the source 2 parameters 322334642Smarc */ 322430391Skarels adder->source_2_x = 0; 322530391Skarels adder->source_2_y = 0; 322630391Skarels adder->source_2_size = 0x0022; 322734642Smarc /* 322834642Smarc * initialize plane addresses for eight vipers 322934642Smarc */ 323030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 323130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 323230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 323330391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 323430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 323530391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 323630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 323730391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 323830391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 323930391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 324030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 324130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 324230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 324330391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 324430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 324530391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 324634642Smarc /* 324734642Smarc * initialize the external registers. 324834642Smarc */ 324930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 325030391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 325134642Smarc /* 325234642Smarc * initialize resolution mode 325334642Smarc */ 325430391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 325530391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 325634642Smarc /* 325734642Smarc * initialize viper registers 325834642Smarc */ 325930391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 326030391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 326134642Smarc /* 326234642Smarc * set clipping and scrolling limits to full screen 326334642Smarc */ 326434732Smarc for (i = 1000, adder->status = 0; 326534732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 326634642Smarc ; 326730391Skarels if (i == 0) 326834732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 326930391Skarels top = 0; 327030391Skarels bottom = 2048; 327130391Skarels left = 0; 327230391Skarels right = 1024; 327330391Skarels adder->x_clip_min = left; 327430391Skarels adder->x_clip_max = right; 327530391Skarels adder->y_clip_min = top; 327630391Skarels adder->y_clip_max = bottom; 327730391Skarels adder->scroll_x_min = left; 327830391Skarels adder->scroll_x_max = right; 327930391Skarels adder->scroll_y_min = top; 328030391Skarels adder->scroll_y_max = bottom; 328134732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 328234732Smarc (void)wait_status(adder, VSYNC); 328330391Skarels adder->x_index_pending = left; 328430391Skarels adder->y_index_pending = top; 328530391Skarels adder->x_index_new = left; 328630391Skarels adder->y_index_new = top; 328730391Skarels adder->x_index_old = left; 328830391Skarels adder->y_index_old = top; 328930391Skarels 329034732Smarc for (i = 1000, adder->status = 0; i > 0 && 329134732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 329234642Smarc ; 329330391Skarels if (i == 0) 329434732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 329530391Skarels 329630391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 329730391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 329834642Smarc /* 329934642Smarc * set source and the mask register to all ones (ie: white) o 330034642Smarc */ 330130391Skarels write_ID(adder, SOURCE, 0xFFFF); 330230391Skarels write_ID(adder, MASK_1, 0xFFFF); 330330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 330430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 330534642Smarc /* 330634642Smarc * initialize Operand Control Register banks for fill command 330734642Smarc */ 330830391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 330930391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 331030391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 331130391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 331230391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 331330391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 331434642Smarc /* 331534642Smarc * init Logic Unit Function registers, (these are just common values, 331634642Smarc * and may be changed as required). 331734642Smarc */ 331830391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 331934642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 332034642Smarc INV_M1_M2); 332130391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 332230391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 332334642Smarc /* 332434642Smarc * load the color map for black & white 332534642Smarc */ 332634732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 332734642Smarc ; 332830391Skarels 332930391Skarels if (i == 0) 333034732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 333130391Skarels 333230391Skarels red = (short *) qdmap[unit].red; 333330391Skarels green = (short *) qdmap[unit].green; 333430391Skarels blue = (short *) qdmap[unit].blue; 333530391Skarels 333630391Skarels *red++ = 0x00; /* black */ 333730391Skarels *green++ = 0x00; 333830391Skarels *blue++ = 0x00; 333930391Skarels 334030391Skarels *red-- = 0xFF; /* white */ 334130391Skarels *green-- = 0xFF; 334230391Skarels *blue-- = 0xFF; 334330391Skarels 334434642Smarc /* 334534732Smarc * set color map for mouse cursor 334634732Smarc */ 334730391Skarels 334830391Skarels red += 254; 334930391Skarels green += 254; 335030391Skarels blue += 254; 335130391Skarels 335230391Skarels *red++ = 0x00; /* black */ 335330391Skarels *green++ = 0x00; 335430391Skarels *blue++ = 0x00; 335530391Skarels 335630391Skarels *red = 0xFF; /* white */ 335730391Skarels *green = 0xFF; 335830391Skarels *blue = 0xFF; 335930391Skarels 336030391Skarels } /* setup_dragon */ 336130391Skarels 336234732Smarc /* 336334732Smarc * Init the DUART and set defaults in input 336434732Smarc */ 336530391Skarels setup_input(unit) 336634732Smarc int unit; 336730391Skarels { 336830391Skarels register struct duart *duart; /* DUART register structure pointer */ 336934732Smarc register i, bits; 337030391Skarels char id_byte; 337130391Skarels 337230391Skarels duart = (struct duart *) qdmap[unit].duart; 337330391Skarels duart->imask = 0; 337430391Skarels 337534642Smarc /* 337634642Smarc * setup the DUART for kbd & pointing device 337734642Smarc */ 337834732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 337934732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 338034732Smarc /* no RTS control,char error mode */ 338134732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 338234732Smarc /* no RTS control,no echo or loop */ 338334732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 338434732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 338534732Smarc /* ..no RTS cntrl, char error mode */ 338634732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 338734732Smarc /* no RTS control,no echo or loop */ 338834732Smarc duart->auxctl = 0x00; /* baud rate set 1 */ 338934732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */ 339034732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */ 339130391Skarels 339230391Skarels /* reset everything for keyboard */ 339330391Skarels 339430391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339534642Smarc duart->cmdA = bits; 339630391Skarels 339730391Skarels /* reset everything for host */ 339830391Skarels 339930391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 340034642Smarc duart->cmdB = bits; 340130391Skarels 340230391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 340330391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 340430391Skarels 340534642Smarc /* 340634732Smarc * init keyboard defaults (DUART channel A) 340734732Smarc */ 340830391Skarels for (i = 500; i > 0; --i) { 340934732Smarc if (duart->statusA&XMT_RDY) { 341034642Smarc duart->dataA = LK_DEFAULTS; 341134642Smarc break; 341234642Smarc } 341330391Skarels } 341430391Skarels 341530391Skarels for (i = 100000; i > 0; --i) { 341634732Smarc if (duart->statusA&RCV_RDY) { 341734642Smarc break; 341834642Smarc } 341930391Skarels } 342030391Skarels 342134732Smarc if (duart->dataA) /* flush the ACK */ 342234732Smarc ; 342330391Skarels 342434642Smarc /* 342534732Smarc * identify the pointing device 342634732Smarc */ 342730391Skarels for (i = 500; i > 0; --i) { 342834732Smarc if (duart->statusB&XMT_RDY) { 342934642Smarc duart->dataB = SELF_TEST; 343034642Smarc break; 343134642Smarc } 343230391Skarels } 343330391Skarels 343434642Smarc /* 343530391Skarels * wait for 1st byte of self test report */ 343630391Skarels 343730391Skarels for (i = 100000; i > 0; --i) { 343834732Smarc if (duart->statusB&RCV_RDY) { 343934642Smarc break; 344034642Smarc } 344130391Skarels } 344230391Skarels 344330391Skarels if (i == 0) { 344434732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 344534642Smarc ,unit); 344634642Smarc goto OUT; 344730391Skarels } 344830391Skarels 344934732Smarc if (duart->dataB) 345034732Smarc ; 345130391Skarels 345234642Smarc /* 345334732Smarc * wait for ID byte of self test report 345434732Smarc */ 345530391Skarels for (i = 100000; i > 0; --i) { 345634732Smarc if (duart->statusB&RCV_RDY) { 345734642Smarc break; 345834642Smarc } 345930391Skarels } 346030391Skarels 346130391Skarels if (i == 0) { 346234732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 346334642Smarc goto OUT; 346430391Skarels } 346530391Skarels 346630391Skarels id_byte = duart->dataB; 346730391Skarels 346834642Smarc /* 346934732Smarc * wait for other bytes to come in 347034732Smarc */ 347130391Skarels for (i = 100000; i > 0; --i) { 347234732Smarc if (duart->statusB & RCV_RDY) { 347334732Smarc if (duart->dataB) 347434732Smarc ; 347534642Smarc break; 347634642Smarc } 347730391Skarels } 347830391Skarels if (i == 0) { 347934732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 348034642Smarc goto OUT; 348130391Skarels } 348230391Skarels for (i = 100000; i > 0; --i) { 348334732Smarc if (duart->statusB&RCV_RDY) { 348434732Smarc if (duart->dataB) 348534732Smarc ; 348634642Smarc break; 348734642Smarc } 348830391Skarels } 348930391Skarels if (i == 0) { 349034732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 349134642Smarc goto OUT; 349230391Skarels } 349334642Smarc /* 349434732Smarc * flag pointing device type and set defaults 349534732Smarc */ 349634732Smarc for (i=100000; i>0; --i) 349734732Smarc ; /*XXX*/ 349830391Skarels 349930391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 350034642Smarc qdflags[unit].pntr_id = MOUSE_ID; 350130391Skarels 350234642Smarc for (i = 500; i > 0; --i) { 350334732Smarc if (duart->statusB&XMT_RDY) { 350434642Smarc duart->dataB = INC_STREAM_MODE; 350534642Smarc break; 350634642Smarc } 350730391Skarels } 350834642Smarc } 350934642Smarc else { 351034642Smarc qdflags[unit].pntr_id = TABLET_ID; 351130391Skarels 351234642Smarc for (i = 500; i > 0; --i) { 351334732Smarc if (duart->statusB&XMT_RDY) { 351434642Smarc duart->dataB = T_STREAM; 351534642Smarc break; 351634642Smarc } 351730391Skarels } 351830391Skarels } 351930391Skarels OUT: 352030391Skarels duart->imask = qdflags[unit].duart_imask; 352130391Skarels 352230391Skarels } /* setup_input */ 352330391Skarels 352434732Smarc /* 352534732Smarc * delay for at least one display frame time 352634732Smarc * 352734732Smarc * return: BAD means that we timed out without ever seeing the 352834732Smarc * vertical sync status bit 352934732Smarc * GOOD otherwise 353034732Smarc */ 353130391Skarels wait_status(adder, mask) 353234642Smarc register struct adder *adder; 353334642Smarc register int mask; 353430391Skarels { 353534732Smarc register i; 353630391Skarels 353734732Smarc for (i = 10000, adder->status = 0 ; i > 0 && 353834732Smarc !(adder->status&mask) ; --i) 353934642Smarc ; 354030391Skarels 354130391Skarels if (i == 0) { 354234732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 354334642Smarc return(BAD); 354430391Skarels } 354530391Skarels 354630391Skarels return(GOOD); 354730391Skarels 354830391Skarels } /* wait_status */ 354930391Skarels 355034732Smarc /* 355134732Smarc * write out onto the ID bus 355234732Smarc */ 355330391Skarels write_ID(adder, adrs, data) 355434642Smarc register struct adder *adder; 355534642Smarc register short adrs; 355634642Smarc register short data; 355730391Skarels { 355834732Smarc register i; 355930391Skarels 356034732Smarc for (i = 100000, adder->status = 0 ; 356134732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 356234642Smarc ; 356330391Skarels 356430391Skarels if (i == 0) 356534732Smarc goto ERR; 356630391Skarels 356734732Smarc for (i = 100000, adder->status = 0 ; 356834732Smarc i > 0 && !(adder->status&TX_READY) ; --i) 356934642Smarc ; 357030391Skarels 357130391Skarels if (i > 0) { 357234642Smarc adder->id_data = data; 357334642Smarc adder->command = ID_LOAD | adrs; 357434732Smarc return ; 357530391Skarels } 357630391Skarels 357730391Skarels ERR: 357834732Smarc printf("write_ID: timeout trying to write to VIPER\n"); 357934732Smarc return ; 358030391Skarels 358130391Skarels } /* write_ID */ 358234511Smarc #endif 3583