134511Smarc /* 235353Sbostic * Copyright (c) 1988 Regents of the University of California. 335353Sbostic * All rights reserved. 435353Sbostic * 544551Sbostic * %sccs.include.redist.c% 635353Sbostic * 7*45804Sbostic * @(#)qd.c 1.17 (Berkeley) 12/16/90 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 39*45804Sbostic #include "../include/pte.h" 40*45804Sbostic #include "../include/mtpr.h" 41*45804Sbostic #include "sys/param.h" 42*45804Sbostic #include "../include/cpu.h" 43*45804Sbostic #include "sys/conf.h" 44*45804Sbostic #include "sys/user.h" 4534642Smarc #include "qdioctl.h" 46*45804Sbostic #include "sys/tty.h" 47*45804Sbostic #include "sys/map.h" 48*45804Sbostic #include "sys/buf.h" 49*45804Sbostic #include "sys/vm.h" 50*45804Sbostic #include "sys/clist.h" 51*45804Sbostic #include "sys/file.h" 52*45804Sbostic #include "sys/uio.h" 53*45804Sbostic #include "sys/kernel.h" 54*45804Sbostic #include "sys/exec.h" 55*45804Sbostic #include "sys/proc.h" 5634642Smarc #include "ubareg.h" 5734642Smarc #include "ubavar.h" 58*45804Sbostic #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*/ 71430391Skarels qdclose(dev, flag) 71534642Smarc dev_t dev; 71634642Smarc int flag; 71730391Skarels { 71830391Skarels register struct tty *tp; 71930391Skarels register struct qdmap *qd; 72030391Skarels register int *ptep; 72130391Skarels struct dga *dga; /* gate array register map pointer */ 72230391Skarels struct duart *duart; 72330391Skarels struct adder *adder; 72434732Smarc int unit; 72534732Smarc int minor_dev; 72630391Skarels u_int mapix; 72734642Smarc int i; /* SIGNED index */ 72830391Skarels 72930391Skarels minor_dev = minor(dev); /* get minor device number */ 73030391Skarels unit = minor_dev >> 2; /* get QDSS number */ 73130391Skarels qd = &qdmap[unit]; 73230391Skarels 73330391Skarels if ((minor_dev & 0x03) == 2) { 73434642Smarc /* 73534642Smarc * this is the graphic device... 73634642Smarc */ 73734642Smarc if (qdopened[unit] != 1) 73834732Smarc return(EBUSY); 73934642Smarc else 74034642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 74134642Smarc /* 74234642Smarc * re-protect device memory 74334642Smarc */ 74434642Smarc if (qdflags[unit].mapped & MAPDEV) { 74534642Smarc /* 74634642Smarc * TEMPLATE RAM 74734642Smarc */ 74834642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 74934642Smarc ptep = (int *)(QVmap[0] + mapix); 75034732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 75134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 75234642Smarc /* 75334642Smarc * ADDER 75434642Smarc */ 75534642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 75634642Smarc ptep = (int *)(QVmap[0] + mapix); 75734732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 75834732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 75934642Smarc /* 76034642Smarc * COLOR MAPS 76134642Smarc */ 76234642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 76334642Smarc ptep = (int *)(QVmap[0] + mapix); 76434732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 76534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76634642Smarc } 76734615Smarc 76834642Smarc /* 76934642Smarc * re-protect DMA buffer and free the map registers 77034642Smarc */ 77134642Smarc if (qdflags[unit].mapped & MAPDMA) { 77234642Smarc dga = (struct dga *) qdmap[unit].dga; 77334642Smarc adder = (struct adder *) qdmap[unit].adder; 77434642Smarc dga->csr &= ~DMA_IE; 77534642Smarc dga->csr &= ~0x0600; /* kill DMA */ 77634642Smarc adder->command = CANCEL; 77734642Smarc /* 77834642Smarc * if DMA was running, flush spurious intrpt 77934642Smarc */ 78034642Smarc if (dga->bytcnt_lo != 0) { 78134642Smarc dga->bytcnt_lo = 0; 78234642Smarc dga->bytcnt_hi = 0; 78334642Smarc DMA_SETIGNORE(DMAheader[unit]); 78434642Smarc dga->csr |= DMA_IE; 78534642Smarc dga->csr &= ~DMA_IE; 78634642Smarc } 78734642Smarc ptep = (int *) 78834642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 78934732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 79034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 79134642Smarc ubarelse(0, &Qbus_unmap[unit]); 79234642Smarc } 79334615Smarc 79434642Smarc /* 79534642Smarc * re-protect 1K (2 pages) event queue 79634642Smarc */ 79734642Smarc if (qdflags[unit].mapped & MAPEQ) { 79834642Smarc ptep = (int *) 79934642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 80034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 80134642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 80230391Skarels } 80334642Smarc /* 80434642Smarc * re-protect scroll param area and disable scroll intrpts 80534642Smarc */ 80634642Smarc if (qdflags[unit].mapped & MAPSCR) { 80734642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 80834642Smarc + (mfpr(SBR) | 0x80000000)); 80934642Smarc /* 81034642Smarc * re-protect 512 scroll param area 81134642Smarc */ 81234642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 81334642Smarc adder = (struct adder *) qdmap[unit].adder; 81434642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 81534642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 81634642Smarc } 81734642Smarc /* 81834642Smarc * re-protect color map write buffer area and kill intrpts 81934642Smarc */ 82034642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 82134642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 82234642Smarc + (mfpr(SBR) | 0x80000000)); 82334732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 82434642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 82534642Smarc color_buf[unit]->status = 0; 82634642Smarc adder = (struct adder *) qdmap[unit].adder; 82734642Smarc qdflags[unit].adder_ie &= ~VSYNC; 82834642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 82934642Smarc } 83034642Smarc mtpr(TBIA, 0); 83134642Smarc /* flag everything now unmapped */ 83234642Smarc qdflags[unit].mapped = 0; 83334642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 83434642Smarc qdflags[unit].curs_acc = ACC_OFF; 83534642Smarc qdflags[unit].curs_thr = 128; 83634642Smarc /* 83734642Smarc * restore the console 83834642Smarc */ 83930391Skarels dga = (struct dga *) qdmap[unit].dga; 84030391Skarels adder = (struct adder *) qdmap[unit].adder; 84130391Skarels dga->csr &= ~DMA_IE; 84230391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 84330391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 84430391Skarels adder->command = CANCEL; 84534642Smarc /* 84634642Smarc * if DMA was running, flush spurious intrpt 84734642Smarc */ 84830391Skarels if (dga->bytcnt_lo != 0) { 84934642Smarc dga->bytcnt_lo = 0; 85034642Smarc dga->bytcnt_hi = 0; 85134642Smarc DMA_SETIGNORE(DMAheader[unit]); 85234642Smarc dga->csr |= DMA_IE; 85334642Smarc dga->csr &= ~DMA_IE; 85430391Skarels } 85530391Skarels init_shared(unit); /* init shared memory */ 85630391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 85730391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 85830391Skarels setup_input(unit); /* init the DUART */ 85930391Skarels ldfont(unit); 86030391Skarels cursor[unit].x = 0; 86130391Skarels cursor[unit].y = 0; 86234642Smarc /* 86334642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 86434642Smarc */ 86534642Smarc duart = (struct duart *) qdmap[unit].duart; 86634642Smarc qdflags[unit].duart_imask &= ~(0x20); 86734642Smarc qdflags[unit].duart_imask |= 0x02; 86834642Smarc duart->imask = qdflags[unit].duart_imask; 86934642Smarc /* 87034642Smarc * shut off interrupts if all is closed 87134642Smarc */ 87234642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 87334642Smarc dga = (struct dga *) qdmap[unit].dga; 87434642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 87534642Smarc } 87634642Smarc } else { 87734642Smarc /* 87834642Smarc * this is the console 87934642Smarc */ 88034642Smarc tp = &qd_tty[minor_dev]; 88134642Smarc (*linesw[tp->t_line].l_close)(tp); 88234642Smarc ttyclose(tp); 88334642Smarc tp->t_state = 0; 88434642Smarc qdflags[unit].inuse &= ~CONS_DEV; 88534642Smarc /* 88634642Smarc * if graphics device is closed, kill interrupts 88734642Smarc */ 88834642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 88934642Smarc dga = (struct dga *) qdmap[unit].dga; 89034642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 89134642Smarc } 89230391Skarels } 89334615Smarc 89430391Skarels return(0); 89530391Skarels 89630391Skarels } /* qdclose */ 89730391Skarels 89830391Skarels qdioctl(dev, cmd, datap, flags) 89934642Smarc dev_t dev; 90034642Smarc int cmd; 90134732Smarc register caddr_t datap; 90234642Smarc int flags; 90330391Skarels { 90430391Skarels register int *ptep; /* page table entry pointer */ 90532012Smarc register int mapix; /* QVmap[] page table index */ 90630391Skarels register struct _vs_event *event; 90730391Skarels register struct tty *tp; 90834732Smarc register i; 90930391Skarels struct qdmap *qd; /* pointer to device map struct */ 91030391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 91130391Skarels struct duart *duart; /* DUART reg structure pointer */ 91230391Skarels struct adder *adder; /* ADDER reg structure pointer */ 91330391Skarels struct prgkbd *cmdbuf; 91430391Skarels struct prg_cursor *curs; 91530391Skarels struct _vs_cursor *pos; 91634732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 91730391Skarels u_int minor_dev = minor(dev); 91830391Skarels int error; 91930391Skarels int s; 92030391Skarels short *temp; /* a pointer to template RAM */ 92130391Skarels 92234642Smarc /* 92334642Smarc * service graphic device ioctl commands 92434642Smarc */ 92530391Skarels switch (cmd) { 92634615Smarc 92734642Smarc case QD_GETEVENT: 92834642Smarc /* 92934642Smarc * extract the oldest event from the event queue 93034642Smarc */ 93130391Skarels if (ISEMPTY(eq_header[unit])) { 93234642Smarc event = (struct _vs_event *) datap; 93334642Smarc event->vse_device = VSE_NULL; 93434642Smarc break; 93530391Skarels } 93630391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 93734615Smarc s = spl5(); 93830391Skarels GETEND(eq_header[unit]); 93930391Skarels splx(s); 94034732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 94130391Skarels break; 94230391Skarels 94334642Smarc case QD_RESET: 94434642Smarc /* 94534642Smarc * init the dragon stuff, DUART, and driver variables 94634642Smarc */ 94730391Skarels init_shared(unit); /* init shared memory */ 94830391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 94930391Skarels clear_qd_screen(unit); 95030391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 95130391Skarels ldfont(unit); /* load the console font */ 95230391Skarels setup_input(unit); /* init the DUART */ 95330391Skarels break; 95430391Skarels 95534642Smarc case QD_SET: 95634642Smarc /* 95734642Smarc * init the DUART and driver variables 95834642Smarc */ 95930391Skarels init_shared(unit); 96030391Skarels setup_input(unit); 96130391Skarels break; 96230391Skarels 96334642Smarc case QD_CLRSCRN: 96434642Smarc /* 96534642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 96634642Smarc */ 96734732Smarc #ifdef notdef /* has caused problems and isn't necessary */ 96830391Skarels setup_dragon(unit); 96930391Skarels clear_qd_screen(unit); 97034615Smarc #endif 97130391Skarels break; 97230391Skarels 97334642Smarc case QD_WTCURSOR: 97434642Smarc /* 97534642Smarc * load a cursor into template RAM 97634642Smarc */ 97734732Smarc ldcursor(unit, (short *)datap); 97830391Skarels break; 97930391Skarels 98034642Smarc case QD_RDCURSOR: 98130391Skarels 98230391Skarels temp = (short *) qdmap[unit].template; 98334642Smarc /* 98434642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 98534642Smarc * ...template space 98634642Smarc */ 98730391Skarels temp += (8 * 1024) - 32; 98830391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 98934642Smarc *(short *)datap = *temp++; 99030391Skarels break; 99130391Skarels 99234642Smarc case QD_POSCURSOR: 99334642Smarc /* 99434642Smarc * position the mouse cursor 99534642Smarc */ 99630391Skarels dga = (struct dga *) qdmap[unit].dga; 99730391Skarels pos = (struct _vs_cursor *) datap; 99834615Smarc s = spl5(); 99930391Skarels dga->x_cursor = TRANX(pos->x); 100030391Skarels dga->y_cursor = TRANY(pos->y); 100130391Skarels eq_header[unit]->curs_pos.x = pos->x; 100230391Skarels eq_header[unit]->curs_pos.y = pos->y; 100330391Skarels splx(s); 100430391Skarels break; 100530391Skarels 100634642Smarc case QD_PRGCURSOR: 100734642Smarc /* 100834642Smarc * set the cursor acceleration factor 100934642Smarc */ 101030391Skarels curs = (struct prg_cursor *) datap; 101134615Smarc s = spl5(); 101230391Skarels qdflags[unit].curs_acc = curs->acc_factor; 101330391Skarels qdflags[unit].curs_thr = curs->threshold; 101430391Skarels splx(s); 101530391Skarels break; 101630391Skarels 101734642Smarc case QD_MAPDEVICE: 101834642Smarc /* 101934642Smarc * enable 'user write' to device pages 102034642Smarc */ 102130391Skarels qdflags[unit].mapped |= MAPDEV; 102230391Skarels qd = (struct qdmap *) &qdmap[unit]; 102334642Smarc /* 102434642Smarc * enable user write to template RAM 102534642Smarc */ 102632012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 102732012Smarc ptep = (int *)(QVmap[0] + mapix); 102834732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 102934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103034642Smarc /* 103134642Smarc * enable user write to registers 103234642Smarc */ 103332012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 103432012Smarc ptep = (int *)(QVmap[0] + mapix); 103534732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 103634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103734642Smarc /* 103834642Smarc * enable user write to color maps 103934642Smarc */ 104032012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 104132012Smarc ptep = (int *)(QVmap[0] + mapix); 104234732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 104334732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104434642Smarc /* 104534642Smarc * enable user write to DUART 104634642Smarc */ 104732012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 104832012Smarc ptep = (int *)(QVmap[0] + mapix); 104930391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 105030391Skarels 105134732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 105230391Skarels 105334642Smarc /* 105434732Smarc * stuff qdmap structure in return buffer 105534732Smarc */ 105634732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 105730391Skarels break; 105830391Skarels 105934642Smarc case QD_MAPIOBUF: 106034642Smarc /* 106134642Smarc * do setup for DMA by user process 106234642Smarc * 106334642Smarc * set 'user write enable' bits for DMA buffer 106434642Smarc */ 106530391Skarels qdflags[unit].mapped |= MAPDMA; 106630391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 106734642Smarc + (mfpr(SBR) | 0x80000000)); 106834732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 106934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 107034732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 107134642Smarc /* 107234642Smarc * set up QBUS map registers for DMA 107334642Smarc */ 107430391Skarels DMAheader[unit]->QBAreg = 107534732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 107630391Skarels if (DMAheader[unit]->QBAreg == 0) 107734732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 107830391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 107930391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 108034642Smarc /* 108134642Smarc * return I/O buf adr 108234642Smarc */ 108330391Skarels *(int *)datap = (int) DMAheader[unit]; 108430391Skarels break; 108530391Skarels 108634642Smarc case QD_MAPSCROLL: 108734642Smarc /* 108834642Smarc * map the shared scroll param area and enable scroll interpts 108934642Smarc */ 109030391Skarels qdflags[unit].mapped |= MAPSCR; 109130391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 109234642Smarc + (mfpr(SBR) | 0x80000000)); 109334642Smarc /* 109434642Smarc * allow user write to scroll area 109534642Smarc */ 109630391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 109734732Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 109830391Skarels scroll[unit]->status = 0; 109930391Skarels adder = (struct adder *) qdmap[unit].adder; 110030391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 110130391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 110234642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 110330391Skarels break; 110430391Skarels 110534642Smarc case QD_UNMAPSCROLL: 110634642Smarc /* 110734642Smarc * unmap shared scroll param area and disable scroll intrpts 110834642Smarc */ 110930391Skarels if (qdflags[unit].mapped & MAPSCR) { 111034642Smarc qdflags[unit].mapped &= ~MAPSCR; 111134642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 111234642Smarc + (mfpr(SBR) | 0x80000000)); 111334642Smarc /* 111434642Smarc * re-protect 512 scroll param area 111534642Smarc */ 111634642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 111734642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 111834642Smarc adder = (struct adder *) qdmap[unit].adder; 111934642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 112034642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 112130391Skarels } 112230391Skarels break; 112330391Skarels 112434642Smarc case QD_MAPCOLOR: 112534642Smarc /* 112634642Smarc * map shared color map write buf and turn on vsync intrpt 112734642Smarc */ 112830391Skarels qdflags[unit].mapped |= MAPCOLOR; 112930391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 113034642Smarc + (mfpr(SBR) | 0x80000000)); 113134732Smarc /* 113234732Smarc * allow user write to color map write buffer 113334732Smarc */ 113434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 113530391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 113630391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 113734642Smarc adder = (struct adder *) qdmap[unit].adder; 113830391Skarels qdflags[unit].adder_ie |= VSYNC; 113930391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 114034732Smarc /* 114134732Smarc * return color area address 114234732Smarc */ 114330391Skarels *(int *)datap = (int) color_buf[unit]; 114430391Skarels break; 114530391Skarels 114634642Smarc case QD_UNMAPCOLOR: 114734642Smarc /* 114834732Smarc * unmap shared color map write buffer and kill VSYNC intrpts 114934732Smarc */ 115030391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 115134642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 115234642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 115334642Smarc + (mfpr(SBR) | 0x80000000)); 115434732Smarc /* 115534732Smarc * re-protect color map write buffer 115634732Smarc */ 115734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 115834642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 115934732Smarc mtpr(TBIA, 0); 116034642Smarc adder = (struct adder *) qdmap[unit].adder; 116134642Smarc qdflags[unit].adder_ie &= ~VSYNC; 116234642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 116330391Skarels } 116430391Skarels break; 116530391Skarels 116634642Smarc case QD_MAPEVENT: 116734642Smarc /* 116834642Smarc * give user write access to the event queue 116934642Smarc */ 117030391Skarels qdflags[unit].mapped |= MAPEQ; 117130391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 117234642Smarc + (mfpr(SBR) | 0x80000000)); 117334732Smarc /* 117434732Smarc * allow user write to 1K event queue 117534732Smarc */ 117634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 117730391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 117830391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 117934732Smarc /* 118034732Smarc * return event queue address 118134732Smarc */ 118234732Smarc *(int *)datap = (int)eq_header[unit]; 118330391Skarels break; 118430391Skarels 118534642Smarc case QD_PRGKBD: 118634642Smarc /* 118734642Smarc * pass caller's programming commands to LK201 118834642Smarc */ 118934732Smarc duart = (struct duart *)qdmap[unit].duart; 119034732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 119134642Smarc /* 119234642Smarc * send command 119334642Smarc */ 119430391Skarels for (i = 1000; i > 0; --i) { 119534732Smarc if (duart->statusA&XMT_RDY) { 119634642Smarc duart->dataA = cmdbuf->cmd; 119734642Smarc break; 119834642Smarc } 119930391Skarels } 120030391Skarels if (i == 0) { 120134732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 120234642Smarc break; 120330391Skarels } 120434642Smarc /* 120534642Smarc * send param1? 120634642Smarc */ 120730391Skarels if (cmdbuf->cmd & LAST_PARAM) 120834642Smarc break; 120930391Skarels for (i = 1000; i > 0; --i) { 121034732Smarc if (duart->statusA&XMT_RDY) { 121134642Smarc duart->dataA = cmdbuf->param1; 121234642Smarc break; 121334642Smarc } 121430391Skarels } 121530391Skarels if (i == 0) { 121634732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 121734642Smarc break; 121830391Skarels } 121934642Smarc /* 122034642Smarc * send param2? 122134642Smarc */ 122230391Skarels if (cmdbuf->param1 & LAST_PARAM) 122330391Skarels break; 122430391Skarels for (i = 1000; i > 0; --i) { 122534732Smarc if (duart->statusA&XMT_RDY) { 122634642Smarc duart->dataA = cmdbuf->param2; 122734642Smarc break; 122834642Smarc } 122930391Skarels } 123030391Skarels if (i == 0) { 123134732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 123234642Smarc break; 123330391Skarels } 123430391Skarels break; 123530391Skarels 123634642Smarc case QD_PRGMOUSE: 123734642Smarc /* 123834642Smarc * pass caller's programming commands to the mouse 123934642Smarc */ 124030391Skarels duart = (struct duart *) qdmap[unit].duart; 124130391Skarels for (i = 1000; i > 0; --i) { 124234732Smarc if (duart->statusB&XMT_RDY) { 124334642Smarc duart->dataB = *datap; 124434642Smarc break; 124534642Smarc } 124630391Skarels } 124730391Skarels if (i == 0) { 124834732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 124930391Skarels } 125030391Skarels break; 125130391Skarels 125234642Smarc case QD_RDCONFIG: 125334642Smarc /* 125434642Smarc * get QDSS configuration word and return it 125534642Smarc */ 125630391Skarels *(short *)datap = qdflags[unit].config; 125730391Skarels break; 125830391Skarels 125934642Smarc case QD_KERN_LOOP: 126034642Smarc case QD_KERN_UNLOOP: 126134642Smarc /* 126234642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 126334642Smarc * kernel console output. 126434642Smarc */ 126534615Smarc break; 126634615Smarc 126734642Smarc case QD_PRGTABLET: 126834642Smarc /* 126934642Smarc * program the tablet 127034642Smarc */ 127130391Skarels duart = (struct duart *) qdmap[unit].duart; 127230391Skarels for (i = 1000; i > 0; --i) { 127334732Smarc if (duart->statusB&XMT_RDY) { 127434642Smarc duart->dataB = *datap; 127534642Smarc break; 127634642Smarc } 127730391Skarels } 127830391Skarels if (i == 0) { 127934732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 128030391Skarels } 128130391Skarels break; 128230391Skarels 128334642Smarc case QD_PRGTABRES: 128434642Smarc /* 128534642Smarc * program the tablet report resolution factor 128634642Smarc */ 128730391Skarels qdflags[unit].tab_res = *(short *)datap; 128830391Skarels break; 128930391Skarels 129034642Smarc default: 129134642Smarc /* 129234642Smarc * service tty ioctl's 129334642Smarc */ 129434642Smarc if (!(minor_dev & 0x02)) { 129530391Skarels tp = &qd_tty[minor_dev]; 129634642Smarc error = 129734642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 129830391Skarels if (error >= 0) { 129934642Smarc return(error); 130030391Skarels } 130130391Skarels error = ttioctl(tp, cmd, datap, flags); 130230391Skarels if (error >= 0) { 130334642Smarc return(error); 130430391Skarels } 130534642Smarc } 130634642Smarc break; 130730391Skarels } 130830391Skarels 130930391Skarels return(0); 131030391Skarels 131130391Skarels } /* qdioctl */ 131230391Skarels 131330391Skarels qdselect(dev, rw) 131434642Smarc dev_t dev; 131534642Smarc int rw; 131630391Skarels { 131734732Smarc register s; 131834732Smarc register unit; 131934615Smarc register struct tty *tp; 132034615Smarc u_int minor_dev = minor(dev); 132130391Skarels 132234615Smarc s = spl5(); 132334615Smarc unit = minor_dev >> 2; 132430391Skarels 132530391Skarels switch (rw) { 132634642Smarc case FREAD: 132734642Smarc if ((minor_dev & 0x03) == 2) { 132834642Smarc /* 132934642Smarc * this is a graphics device, so check for events 133034642Smarc */ 133134732Smarc if(!(ISEMPTY(eq_header[unit]))) { 133234642Smarc splx(s); 133334642Smarc return(1); 133434642Smarc } 133534732Smarc qdrsel[unit] = u.u_procp; 133634642Smarc qdflags[unit].selmask |= SEL_READ; 133734642Smarc splx(s); 133834642Smarc return(0); 133934642Smarc } else { 134034642Smarc /* 134134642Smarc * this is a tty device 134234642Smarc */ 134334642Smarc tp = &qd_tty[minor_dev]; 134434642Smarc if (ttnread(tp)) 134534642Smarc return(1); 134634642Smarc tp->t_rsel = u.u_procp; 134734642Smarc splx(s); 134834642Smarc return(0); 134930391Skarels } 135030391Skarels 135134642Smarc case FWRITE: 135234642Smarc if ((minor(dev) & 0x03) == 2) { 135334642Smarc /* 135434642Smarc * this is a graphics device, so check for dma buffers 135534642Smarc */ 135634642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 135734642Smarc { 135834642Smarc splx(s); 135934642Smarc return(1); 136034642Smarc } 136134732Smarc qdrsel[unit] = u.u_procp; 136234642Smarc qdflags[unit].selmask |= SEL_WRITE; 136334642Smarc splx(s); 136434642Smarc return(0); 136534642Smarc } else { 136634642Smarc /* 136734642Smarc * this is a tty device 136834642Smarc */ 136934642Smarc tp = &qd_tty[minor_dev]; 137037605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 137134642Smarc return(1); 137234642Smarc tp->t_wsel = u.u_procp; 137334642Smarc splx(s); 137434642Smarc return(0); 137530391Skarels } 137630391Skarels } 137734732Smarc splx(s); 137834732Smarc return(0); 137930391Skarels 138030391Skarels } /* qdselect() */ 138130391Skarels 138230391Skarels extern qd_strategy(); 138330391Skarels 138430391Skarels qdwrite(dev, uio) 138534642Smarc dev_t dev; 138634642Smarc struct uio *uio; 138730391Skarels { 138830391Skarels register struct tty *tp; 138934732Smarc register minor_dev; 139034732Smarc register unit; 139130391Skarels 139230391Skarels minor_dev = minor(dev); 139330391Skarels unit = (minor_dev >> 2) & 0x07; 139430391Skarels 139534642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 139634642Smarc /* 139734642Smarc * this is the console... 139834642Smarc */ 139934642Smarc tp = &qd_tty[minor_dev]; 140034642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 140134642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 140234642Smarc /* 140334642Smarc * this is a DMA xfer from user space 140434642Smarc */ 140534642Smarc return (physio(qd_strategy, &qdbuf[unit], 140634642Smarc dev, B_WRITE, minphys, uio)); 140730391Skarels } 140834732Smarc return (ENXIO); 140930391Skarels } 141030391Skarels 141130391Skarels qdread(dev, uio) 141234642Smarc dev_t dev; 141334642Smarc struct uio *uio; 141430391Skarels { 141530391Skarels register struct tty *tp; 141634732Smarc register minor_dev; 141734732Smarc register unit; 141830391Skarels 141930391Skarels minor_dev = minor(dev); 142030391Skarels unit = (minor_dev >> 2) & 0x07; 142130391Skarels 142234642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 142334642Smarc /* 142434642Smarc * this is the console 142534642Smarc */ 142634642Smarc tp = &qd_tty[minor_dev]; 142734642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 142834642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 142934642Smarc /* 143034642Smarc * this is a bitmap-to-processor xfer 143134642Smarc */ 143234642Smarc return (physio(qd_strategy, &qdbuf[unit], 143334642Smarc dev, B_READ, minphys, uio)); 143430391Skarels } 143534732Smarc return (ENXIO); 143630391Skarels } 143730391Skarels 143830391Skarels /*************************************************************** 143930391Skarels * 144030391Skarels * qd_strategy()... strategy routine to do DMA 144130391Skarels * 144230391Skarels ***************************************************************/ 144330391Skarels 144430391Skarels qd_strategy(bp) 144534642Smarc register struct buf *bp; 144630391Skarels { 144730391Skarels register struct dga *dga; 144830391Skarels register struct adder *adder; 144934732Smarc register unit; 145030391Skarels int QBAreg; 145130391Skarels int s; 145230391Skarels int cookie; 145330391Skarels 145430391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 145530391Skarels 145634642Smarc /* 145734642Smarc * init pointers 145834642Smarc */ 145930391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 146034732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 146134642Smarc goto STRAT_ERR; 146230391Skarels } 146330391Skarels dga = (struct dga *) qdmap[unit].dga; 146434615Smarc s = spl5(); 146530391Skarels qdflags[unit].user_dma = -1; 146630391Skarels dga->csr |= DMA_IE; 146730391Skarels cookie = QBAreg & 0x3FFFF; 146830391Skarels dga->adrs_lo = (short) cookie; 146930391Skarels dga->adrs_hi = (short) (cookie >> 16); 147030391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 147130391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 147230391Skarels 147330391Skarels while (qdflags[unit].user_dma) { 147434642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 147530391Skarels } 147630391Skarels splx(s); 147730391Skarels ubarelse(0, &QBAreg); 147830391Skarels if (!(dga->csr & DMA_ERR)) { 147934642Smarc iodone(bp); 148034642Smarc return; 148130391Skarels } 148230391Skarels 148330391Skarels STRAT_ERR: 148430391Skarels adder = (struct adder *) qdmap[unit].adder; 148534642Smarc adder->command = CANCEL; /* cancel adder activity */ 148630391Skarels dga->csr &= ~DMA_IE; 148730391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 148830391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 148930391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 149030391Skarels 149134642Smarc /* 149234642Smarc * if DMA was running, flush spurious intrpt 149334642Smarc */ 149430391Skarels if (dga->bytcnt_lo != 0) { 149534642Smarc dga->bytcnt_lo = 0; 149634642Smarc dga->bytcnt_hi = 0; 149734642Smarc DMA_SETIGNORE(DMAheader[unit]); 149834642Smarc dga->csr |= DMA_IE; 149930391Skarels } 150030391Skarels iodone(bp); 150130391Skarels 150230391Skarels } /* qd_strategy */ 150330391Skarels 150434732Smarc /* 150534732Smarc * Start output to the console screen 150634732Smarc */ 150730391Skarels qdstart(tp) 150834642Smarc register struct tty *tp; 150930391Skarels { 151034732Smarc register which_unit, unit, c; 151130391Skarels int s; 151234615Smarc 151330391Skarels unit = minor(tp->t_dev); 151430391Skarels which_unit = (unit >> 2) & 0x3; 151534615Smarc unit &= 0x03; 151630391Skarels 151734615Smarc s = spl5(); 151834615Smarc 151934642Smarc /* 152034642Smarc * If it's currently active, or delaying, no need to do anything. 152134642Smarc */ 152230391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 152330391Skarels goto out; 152430391Skarels 152534642Smarc /* 152634642Smarc * Display chars until the queue is empty. 152734642Smarc * Drop input from anything but the console 152834642Smarc * device on the floor. 152934642Smarc * 153034642Smarc * XXX - this loop is done at spltty. 153134642Smarc * 153234642Smarc */ 153334642Smarc while (tp->t_outq.c_cc) { 153434511Smarc c = getc(&tp->t_outq); 153534615Smarc if (unit == 0) 153634732Smarc blitc(which_unit, (u_char)c); 153730391Skarels } 153834642Smarc /* 153934642Smarc * If there are sleepers, and output has drained below low 154034642Smarc * water mark, wake up the sleepers. 154134642Smarc */ 154237605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 154334615Smarc if (tp->t_state & TS_ASLEEP){ 154434615Smarc tp->t_state &= ~TS_ASLEEP; 154534615Smarc wakeup((caddr_t) &tp->t_outq); 154634615Smarc } 154730391Skarels } 154830391Skarels 154934615Smarc tp->t_state &= ~TS_BUSY; 155034615Smarc 155130391Skarels out: 155230391Skarels splx(s); 155330391Skarels 155430391Skarels } /* qdstart */ 155530391Skarels 155634732Smarc /*ARGSUSED*/ 155730391Skarels qdstop(tp, flag) 155834642Smarc register struct tty *tp; 155934642Smarc int flag; 156030391Skarels { 156130391Skarels register int s; 156230391Skarels 156334615Smarc s = spl5(); /* block intrpts during state modification */ 156434732Smarc if (tp->t_state & TS_BUSY) 156534732Smarc if ((tp->t_state & TS_TTSTOP) == 0) 156634642Smarc tp->t_state |= TS_FLUSH; 156734642Smarc else 156834642Smarc tp->t_state &= ~TS_BUSY; 156930391Skarels splx(s); 157030391Skarels } 157130391Skarels 157234732Smarc /* 157334732Smarc * Output a character to the QDSS screen 157434732Smarc */ 157530391Skarels 157630391Skarels blitc(unit, chr) 157734732Smarc register unit; 157834732Smarc register u_char chr; 157930391Skarels { 158030391Skarels register struct adder *adder; 158130391Skarels register struct dga *dga; 158230391Skarels register int i; 158334642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 158434642Smarc static short inescape[NQD]; 158530391Skarels 158634732Smarc adder = (struct adder *)qdmap[unit].adder; 158730391Skarels dga = (struct dga *) qdmap[unit].dga; 158834642Smarc /* 158934642Smarc * BSD comment: this (&=0177) defeats the extended character 159034642Smarc * set code for the glass tty, but if i had the time i would 159134642Smarc * spend it ripping out the code completely. This driver 159234642Smarc * is too big for its own good. 159334642Smarc */ 159434642Smarc chr &= 0177; 159534642Smarc /* 159634732Smarc * Cursor addressing (so vi will work). 159734642Smarc * Decode for "\E=%.%." cursor motion description. 159834732Smarc * Corresponds to type "qdcons" in /etc/termcap: 159934642Smarc * 160034642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 160134642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 160234642Smarc * 160334642Smarc */ 160434642Smarc if (inescape[unit] && nograph) { 160534642Smarc switch (inescape[unit]++) { 160634642Smarc case 1: 160734642Smarc if (chr != '=') { 160834642Smarc /* abort escape sequence */ 160934642Smarc inescape[unit] = 0; 161034642Smarc blitc(unit, chr); 161134642Smarc } 161234732Smarc return; 161334642Smarc case 2: 161434642Smarc /* position row */ 161534642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 161634642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 161734642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 161834642Smarc dga->y_cursor = TRANY(cursor[unit].y); 161934732Smarc return; 162034642Smarc case 3: 162134642Smarc /* position column */ 162234642Smarc cursor[unit].x = CHAR_WIDTH * chr; 162334642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 162434642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 162534642Smarc dga->x_cursor = TRANX(cursor[unit].x); 162634642Smarc inescape[unit] = 0; 162734732Smarc return; 162834642Smarc default: 162934642Smarc inescape[unit] = 0; 163034642Smarc blitc(unit, chr); 163134642Smarc } 163234642Smarc } 163330391Skarels 163430391Skarels switch (chr) { 163534642Smarc case '\r': /* return char */ 163630391Skarels cursor[unit].x = 0; 163734642Smarc if (nograph) 163834642Smarc dga->x_cursor = TRANX(cursor[unit].x); 163934732Smarc return; 164030391Skarels 164134642Smarc case '\t': /* tab char */ 164230391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 164334642Smarc blitc(unit, ' '); 164430391Skarels } 164534732Smarc return; 164630391Skarels 164734642Smarc case '\n': /* line feed char */ 164830391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 164934642Smarc if (nograph) { 165034642Smarc cursor[unit].y -= CHAR_HEIGHT; 165134642Smarc scroll_up(adder); 165234642Smarc } else 165334642Smarc cursor[unit].y = 0; 165430391Skarels } 165534642Smarc if (nograph) 165634642Smarc dga->y_cursor = TRANY(cursor[unit].y); 165734732Smarc return; 165830391Skarels 165934642Smarc case '\b': /* backspace char */ 166030391Skarels if (cursor[unit].x > 0) { 166134642Smarc cursor[unit].x -= CHAR_WIDTH; 166234642Smarc if (nograph) 166334642Smarc dga->x_cursor = TRANX(cursor[unit].x); 166430391Skarels } 166534732Smarc return; 166634642Smarc case CTRL('k'): /* cursor up */ 166734642Smarc if (nograph && cursor[unit].y > 0) { 166834642Smarc cursor[unit].y -= CHAR_HEIGHT; 166934642Smarc dga->y_cursor = TRANY(cursor[unit].y); 167034642Smarc } 167134732Smarc return; 167230391Skarels 167334642Smarc case CTRL('^'): /* home cursor */ 167434642Smarc if (nograph) { 167534642Smarc cursor[unit].x = 0; 167634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 167734642Smarc cursor[unit].y = 0; 167834642Smarc dga->y_cursor = TRANY(cursor[unit].y); 167934642Smarc } 168034732Smarc return; 168132012Smarc 168234642Smarc case CTRL('l'): /* cursor right */ 168334642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 168434642Smarc cursor[unit].x += CHAR_WIDTH; 168534642Smarc dga->x_cursor = TRANX(cursor[unit].x); 168634642Smarc } 168734732Smarc return; 168830391Skarels 168934642Smarc case CTRL('z'): /* clear screen */ 169034642Smarc if (nograph) { 169134642Smarc setup_dragon(unit); 169234642Smarc clear_qd_screen(unit); 169334642Smarc /* home cursor - termcap seems to assume this */ 169434642Smarc cursor[unit].x = 0; 169534642Smarc dga->x_cursor = TRANX(cursor[unit].x); 169634642Smarc cursor[unit].y = 0; 169734642Smarc dga->y_cursor = TRANY(cursor[unit].y); 169834642Smarc } 169934732Smarc return; 170030391Skarels 170134642Smarc case '\033': /* start escape sequence */ 170234642Smarc if (nograph) 170334642Smarc inescape[unit] = 1; 170434732Smarc return; 170534642Smarc 170634642Smarc default: 170734642Smarc if ((chr < ' ') || (chr > '~')) 170834732Smarc return; 170934642Smarc } 171034642Smarc /* 171134642Smarc * setup VIPER operand control registers 171234642Smarc */ 171330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 171430391Skarels write_ID(adder, SRC1_OCR_B, 171534642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 171630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 171730391Skarels write_ID(adder, SRC1_OCR_B, 171834642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 171930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 172030391Skarels write_ID(adder, DST_OCR_B, 172134642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 172230391Skarels write_ID(adder, MASK_1, 0xFFFF); 172330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 172430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 172534642Smarc adder->x_clip_min = 0; 172634642Smarc adder->x_clip_max = 1024; 172734642Smarc adder->y_clip_min = 0; 172834642Smarc adder->y_clip_max = 864; 172934642Smarc /* 173034642Smarc * load DESTINATION origin and vectors 173134642Smarc */ 173230391Skarels adder->fast_dest_dy = 0; 173330391Skarels adder->slow_dest_dx = 0; 173430391Skarels adder->error_1 = 0; 173530391Skarels adder->error_2 = 0; 173630391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 173734732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 173830391Skarels adder->destination_x = cursor[unit].x; 173930391Skarels adder->fast_dest_dx = CHAR_WIDTH; 174030391Skarels adder->destination_y = cursor[unit].y; 174130391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 174234642Smarc /* 174334642Smarc * load SOURCE origin and vectors 174434642Smarc */ 174534615Smarc if ((chr - ' ') > (CHARS - 1)) { 174634615Smarc printf("Invalid character (x)%x in blitc\n",chr); 174734615Smarc chr = ' '; 174834615Smarc } 174934642Smarc /* 175034642Smarc * X position is modulo the number of characters per line 175134642Smarc */ 175234615Smarc adder->source_1_x = FONT_X + 175334642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 175434642Smarc /* 175534642Smarc * Point to either first or second row 175634642Smarc */ 175734615Smarc adder->source_1_y = 2048 - 15 * 175834642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 175930391Skarels adder->source_1_dx = CHAR_WIDTH; 176030391Skarels adder->source_1_dy = CHAR_HEIGHT; 176130391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 176230391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 176334642Smarc /* 176434642Smarc * update console cursor coordinates 176534642Smarc */ 176630391Skarels cursor[unit].x += CHAR_WIDTH; 176734642Smarc if (nograph) 176834642Smarc dga->x_cursor = TRANX(cursor[unit].x); 176930391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 177034642Smarc blitc(unit, '\r'); 177134642Smarc blitc(unit, '\n'); 177230391Skarels } 177330391Skarels 177430391Skarels } /* blitc */ 177530391Skarels 177634732Smarc qdreset() { } 177730391Skarels 177834732Smarc /* 177934732Smarc * INTERRUPT SERVICE ROUTINES 178034732Smarc */ 178130391Skarels 178234732Smarc /* 178334732Smarc * Service "DMA DONE" interrupt condition 178434732Smarc */ 178530391Skarels qddint(qd) 178634732Smarc register qd; 178730391Skarels { 178830391Skarels register struct DMAreq_header *header; 178930391Skarels register struct DMAreq *request; 179030391Skarels register struct dga *dga; 179130391Skarels struct adder *adder; 179230391Skarels int cookie; /* DMA adrs for QDSS */ 179330391Skarels 179434732Smarc (void)spl4(); /* allow interval timer in */ 179530391Skarels 179634642Smarc /* 179734642Smarc * init pointers 179834642Smarc */ 179930391Skarels header = DMAheader[qd]; /* register for optimization */ 180030391Skarels dga = (struct dga *) qdmap[qd].dga; 180130391Skarels adder = (struct adder *) qdmap[qd].adder; 180230391Skarels 180334642Smarc /* 180434642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 180534642Smarc */ 180630391Skarels if (DMA_ISIGNORE(header)) { 180734642Smarc DMA_CLRIGNORE(header); 180834642Smarc return; 180930391Skarels } 181030391Skarels 181134642Smarc /* 181234642Smarc * dump a DMA hardware error message if appropriate 181334642Smarc */ 181430391Skarels if (dga->csr & DMA_ERR) { 181530391Skarels 181634642Smarc if (dga->csr & PARITY_ERR) 181734732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 181830391Skarels 181934642Smarc if (dga->csr & BUS_ERR) 182034732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 182130391Skarels } 182230391Skarels 182334642Smarc /* 182434642Smarc * if this was a DMA from user space... 182534642Smarc */ 182630391Skarels if (qdflags[qd].user_dma) { 182734642Smarc qdflags[qd].user_dma = 0; 182834642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 182934642Smarc return; 183030391Skarels } 183130391Skarels 183234642Smarc /* 183334642Smarc * if we're doing DMA request queue services, field the error condition 183434642Smarc */ 183530391Skarels if (dga->csr & DMA_ERR) { 183630391Skarels 183734642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 183834642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 183934642Smarc adder->command = CANCEL; /* cancel adder activity */ 184030391Skarels 184134642Smarc DMA_SETERROR(header); /* flag error in header status word */ 184234642Smarc DMA_CLRACTIVE(header); 184334642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 184434642Smarc header->newest = header->oldest; 184534642Smarc header->used = 0; 184630391Skarels 184734732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 184834732Smarc selwakeup(qdrsel[qd], 0); 184934732Smarc qdrsel[qd] = 0; 185034642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 185134642Smarc } 185230391Skarels 185334642Smarc if (dga->bytcnt_lo != 0) { 185434642Smarc dga->bytcnt_lo = 0; 185534642Smarc dga->bytcnt_hi = 0; 185634642Smarc DMA_SETIGNORE(header); 185734642Smarc } 185834642Smarc return; 185930391Skarels } 186030391Skarels 186134642Smarc /* 186234642Smarc * if the DMA request queue is now becoming non-full, 186334642Smarc * wakeup "select" client. 186434642Smarc */ 186530391Skarels if (DMA_ISFULL(header)) { 186634732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 186734732Smarc selwakeup(qdrsel[qd], 0); 186834732Smarc qdrsel[qd] = 0; 186934642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 187034642Smarc } 187130391Skarels } 187230391Skarels 187330391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 187434642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 187530391Skarels 187634615Smarc /* check for unexpected interrupt */ 187734615Smarc if (DMA_ISEMPTY(header)) 187830391Skarels return; 187930391Skarels 188030391Skarels DMA_GETEND(header); /* update request queue indices */ 188130391Skarels 188234642Smarc /* 188334732Smarc * if no more DMA pending, wake up "select" client and exit 188434732Smarc */ 188530391Skarels if (DMA_ISEMPTY(header)) { 188630391Skarels 188734732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 188834732Smarc selwakeup(qdrsel[qd], 0); 188934732Smarc qdrsel[qd] = 0; 189034642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 189134642Smarc } 189230391Skarels 189334642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 189434642Smarc return; 189530391Skarels } 189630391Skarels 189734642Smarc /* 189834732Smarc * initiate next DMA xfer 189934732Smarc */ 190030391Skarels request = DMA_GETBEGIN(header); 190134615Smarc if (request->DMAtype != QDlast_DMAtype) { 190234642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 190334642Smarc adder->command = CANCEL; /* cancel adder activity */ 190434615Smarc } 190530391Skarels 190634615Smarc 190730391Skarels switch (request->DMAtype) { 190830391Skarels 190934642Smarc case DISPLIST: 191034615Smarc if (request->DMAtype != QDlast_DMAtype) { 191134615Smarc dga->csr |= DL_ENB; 191234615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 191334615Smarc } 191430391Skarels break; 191530391Skarels 191634642Smarc case PTOB: 191734615Smarc if (request->DMAtype != QDlast_DMAtype) { 191834615Smarc if (request->DMAdone & BYTE_PACK) 191934642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 192034615Smarc else { 192134615Smarc dga->csr |= PTOB_ENB; 192234615Smarc dga->csr &= ~BYTE_DMA; 192334615Smarc } 192434615Smarc } 192530391Skarels break; 192630391Skarels 192734642Smarc case BTOP: 192834615Smarc if (request->DMAtype != QDlast_DMAtype) { 192934615Smarc if (request->DMAdone & BYTE_PACK) { 193034615Smarc dga->csr &= ~DL_ENB; 193134615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 193234615Smarc } 193334615Smarc else { 193434615Smarc dga->csr |= BTOP_ENB; 193534615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 193634615Smarc } 193734615Smarc } 193830391Skarels break; 193934642Smarc default: 194034732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 194130391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 194230391Skarels return; 194330391Skarels } 194430391Skarels 194530391Skarels if (request->DMAdone & COUNT_ZERO) { 194634642Smarc dga->csr &= ~SET_DONE_FIFO; 194734642Smarc } 194834642Smarc else if (request->DMAdone & FIFO_EMPTY) { 194934642Smarc dga->csr |= SET_DONE_FIFO; 195030391Skarels } 195130391Skarels 195230391Skarels if (request->DMAdone & WORD_PACK) 195330391Skarels dga->csr &= ~BYTE_DMA; 195430391Skarels else if (request->DMAdone & BYTE_PACK) 195530391Skarels dga->csr |= BYTE_DMA; 195630391Skarels 195730391Skarels dga->csr |= DMA_IE; 195834642Smarc QDlast_DMAtype = request->DMAtype; 195930391Skarels 196030391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 196130391Skarels 196230391Skarels dga->adrs_lo = (short) cookie; 196330391Skarels dga->adrs_hi = (short) (cookie >> 16); 196430391Skarels 196530391Skarels dga->bytcnt_lo = (short) request->length; 196630391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 196730391Skarels 196830391Skarels return; 196930391Skarels } 197030391Skarels 197134732Smarc /* 197234732Smarc * ADDER interrupt service routine 197334732Smarc */ 197430391Skarels qdaint(qd) 197534732Smarc register qd; 197630391Skarels { 197730391Skarels register struct adder *adder; 197830391Skarels struct color_buf *cbuf; 197930391Skarels int i; 198030391Skarels register struct rgb *rgbp; 198130391Skarels register short *red; 198230391Skarels register short *green; 198330391Skarels register short *blue; 198430391Skarels 198534732Smarc (void)spl4(); /* allow interval timer in */ 198630391Skarels 198730391Skarels adder = (struct adder *) qdmap[qd].adder; 198830391Skarels 198934642Smarc /* 199034642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 199134642Smarc * any pending color map load request 199234642Smarc */ 199330391Skarels if (adder->status & VSYNC) { 199434642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 199534642Smarc cbuf = color_buf[qd]; 199634642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 199730391Skarels 199834642Smarc red = (short *) qdmap[qd].red; 199934642Smarc green = (short *) qdmap[qd].green; 200034642Smarc blue = (short *) qdmap[qd].blue; 200130391Skarels 200234642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 200334642Smarc --i >= 0; rgbp++) { 200434642Smarc red[rgbp->offset] = (short) rgbp->red; 200534642Smarc green[rgbp->offset] = (short) rgbp->green; 200634642Smarc blue[rgbp->offset] = (short) rgbp->blue; 200734642Smarc } 200830391Skarels 200934642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 201030391Skarels } 201130391Skarels } 201230391Skarels 201334642Smarc /* 201434642Smarc * service the scroll interrupt (FRAME_SYNC bit) 201534642Smarc */ 201630391Skarels if (adder->status & FRAME_SYNC) { 201734642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 201830391Skarels 201934642Smarc if (scroll[qd]->status & LOAD_REGS) { 202030391Skarels 202134732Smarc for (i = 1000, adder->status = 0; i > 0 && 202234732Smarc !(adder->status&ID_SCROLL_READY); --i) 202334642Smarc ; 202430391Skarels 202534642Smarc if (i == 0) { 202634732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 202734642Smarc qd); 202834642Smarc return; 202934642Smarc } 203030391Skarels 203134642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 203234642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 203330391Skarels 203434642Smarc adder->y_scroll_constant = 203534642Smarc scroll[qd]->y_scroll_constant; 203634642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 203730391Skarels 203834642Smarc if (scroll[qd]->status & LOAD_INDEX) { 203930391Skarels 204034642Smarc adder->x_index_pending = 204134642Smarc scroll[qd]->x_index_pending; 204234642Smarc adder->y_index_pending = 204334642Smarc scroll[qd]->y_index_pending; 204434642Smarc } 204534642Smarc 204634642Smarc scroll[qd]->status = 0x00; 204730391Skarels } 204830391Skarels } 204930391Skarels } 205030391Skarels 205134732Smarc /* 205234732Smarc * DUART input interrupt service routine 205334732Smarc * 205434732Smarc * XXX - this routine should be broken out - it is essentially 205534732Smarc * straight line code. 205634732Smarc */ 205730391Skarels 205830391Skarels qdiint(qd) 205934732Smarc register qd; 206030391Skarels { 206130391Skarels register struct _vs_event *event; 206230391Skarels register struct qdinput *eqh; 206330391Skarels struct dga *dga; 206430391Skarels struct duart *duart; 206530391Skarels struct mouse_report *new_rep; 206630391Skarels struct uba_device *ui; 206730391Skarels struct tty *tp; 206834615Smarc u_short chr; 206930391Skarels u_short status; 207030391Skarels u_short data; 207130391Skarels u_short key; 207230391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 207330391Skarels char a, b, c; /* mouse button test variables */ 207430391Skarels 207534732Smarc (void)spl4(); /* allow interval timer in */ 207630391Skarels 207730391Skarels eqh = eq_header[qd]; /* optimized as a register */ 207830391Skarels new_rep = ¤t_rep[qd]; 207930391Skarels duart = (struct duart *) qdmap[qd].duart; 208030391Skarels 208134642Smarc /* 208234732Smarc * if the graphic device is turned on.. 208334732Smarc */ 208430391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 208534642Smarc /* 208634642Smarc * empty DUART 208734642Smarc */ 208834732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 208934642Smarc /* 209034732Smarc * pick up LK-201 input (if any) 209134732Smarc */ 209234732Smarc if (duart->statusA&RCV_RDY) { 209330391Skarels 209434642Smarc /* if error condition, then reset it */ 209530391Skarels 209634732Smarc if (duart->statusA&0x70) { 209734642Smarc duart->cmdA = 0x40; 209834642Smarc continue; 209934642Smarc } 210030391Skarels 210134642Smarc /* event queue full now? (overflow condition) */ 210230391Skarels 210334642Smarc if (ISFULL(eqh) == TRUE) { 210434642Smarc printf( 210534732Smarc "qd%d: qdiint: event queue overflow\n", 210634642Smarc qd); 210734642Smarc break; 210834642Smarc } 210930391Skarels 211034642Smarc /* 211134642Smarc * Check for various keyboard errors */ 211230391Skarels 211334642Smarc key = duart->dataA & 0xFF; 211430391Skarels 211534642Smarc if (key==LK_POWER_ERROR || 211634642Smarc key==LK_KDOWN_ERROR || 211734642Smarc key == LK_INPUT_ERROR || 211834642Smarc key == LK_OUTPUT_ERROR) { 211934642Smarc printf( 212034732Smarc "qd%d: qdiint: keyboard error, code = %x\n", 212134642Smarc qd,key); 212234732Smarc return; 212334642Smarc } 212430391Skarels 212534642Smarc if (key < LK_LOWEST) 212634732Smarc return; 212730391Skarels 212834642Smarc ++do_wakeup; /* request a select wakeup call */ 212930391Skarels 213034642Smarc event = PUTBEGIN(eqh); 213134642Smarc PUTEND(eqh); 213230391Skarels 213334642Smarc event->vse_key = key; 213434642Smarc event->vse_key &= 0x00FF; 213534642Smarc event->vse_x = eqh->curs_pos.x; 213634642Smarc event->vse_y = eqh->curs_pos.y; 213734642Smarc event->vse_time = TOY; 213834642Smarc event->vse_type = VSE_BUTTON; 213934642Smarc event->vse_direction = VSE_KBTRAW; 214034642Smarc event->vse_device = VSE_DKB; 214134642Smarc } 214230391Skarels 214334642Smarc /* 214434642Smarc * pick up the mouse input (if any) */ 214530391Skarels 214634642Smarc if ((status = duart->statusB) & RCV_RDY && 214734642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 214830391Skarels 214934642Smarc if (status & 0x70) { 215034642Smarc duart->cmdB = 0x40; 215134642Smarc continue; 215234642Smarc } 215330391Skarels 215434642Smarc /* event queue full now? (overflow condition) */ 215530391Skarels 215634642Smarc if (ISFULL(eqh) == TRUE) { 215734642Smarc printf( 215834732Smarc "qd%d: qdiint: event queue overflow\n", 215934642Smarc qd); 216034642Smarc break; 216134642Smarc } 216230391Skarels 216334642Smarc data = duart->dataB; /* get report byte */ 216434642Smarc ++new_rep->bytcnt; /* bump report byte count */ 216530391Skarels 216634642Smarc /* 216734642Smarc * if 1st byte of report.. */ 216830391Skarels 216934642Smarc if ( data & START_FRAME) { 217034642Smarc new_rep->state = data; 217134642Smarc if (new_rep->bytcnt > 1) { 217234642Smarc /* start of new frame */ 217334642Smarc new_rep->bytcnt = 1; 217434642Smarc /* ..continue looking */ 217534642Smarc continue; 217634642Smarc } 217734642Smarc } 217830391Skarels 217934642Smarc /* 218034642Smarc * if 2nd byte of report.. */ 218130391Skarels 218234642Smarc else if (new_rep->bytcnt == 2) { 218334642Smarc new_rep->dx = data & 0x00FF; 218434642Smarc } 218530391Skarels 218634642Smarc /* 218734642Smarc * if 3rd byte of report, load input event queue */ 218830391Skarels 218934642Smarc else if (new_rep->bytcnt == 3) { 219030391Skarels 219134642Smarc new_rep->dy = data & 0x00FF; 219234642Smarc new_rep->bytcnt = 0; 219330391Skarels 219434642Smarc /* 219534642Smarc * if mouse position has changed.. */ 219630391Skarels 219734642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 219830391Skarels 219934642Smarc /* 220034642Smarc * calculate acceleration factor, if needed */ 220130391Skarels 220234642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 220330391Skarels 220434642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 220534642Smarc new_rep->dx += 220634642Smarc (new_rep->dx - qdflags[qd].curs_thr) 220734642Smarc * qdflags[qd].curs_acc; 220830391Skarels 220934642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 221034642Smarc new_rep->dy += 221134642Smarc (new_rep->dy - qdflags[qd].curs_thr) 221234642Smarc * qdflags[qd].curs_acc; 221334642Smarc } 221430391Skarels 221534642Smarc /* 221634642Smarc * update cursor position coordinates */ 221730391Skarels 221834642Smarc if (new_rep->state & X_SIGN) { 221934642Smarc eqh->curs_pos.x += new_rep->dx; 222034642Smarc if (eqh->curs_pos.x > 1023) 222134642Smarc eqh->curs_pos.x = 1023; 222234642Smarc } 222334642Smarc else { 222434642Smarc eqh->curs_pos.x -= new_rep->dx; 222534642Smarc if (eqh->curs_pos.x < -15) 222634642Smarc eqh->curs_pos.x = -15; 222734642Smarc } 222830391Skarels 222934642Smarc if (new_rep->state & Y_SIGN) { 223034642Smarc eqh->curs_pos.y -= new_rep->dy; 223134642Smarc if (eqh->curs_pos.y < -15) 223234642Smarc eqh->curs_pos.y = -15; 223334642Smarc } 223434642Smarc else { 223534642Smarc eqh->curs_pos.y += new_rep->dy; 223634642Smarc if (eqh->curs_pos.y > 863) 223734642Smarc eqh->curs_pos.y = 863; 223834642Smarc } 223930391Skarels 224034642Smarc /* 224134642Smarc * update cursor screen position */ 224230391Skarels 224334642Smarc dga = (struct dga *) qdmap[qd].dga; 224434642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 224534642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 224630391Skarels 224734642Smarc /* 224834642Smarc * if cursor is in the box, no event report */ 224930391Skarels 225034642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 225134642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 225234642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 225334642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 225434642Smarc goto GET_MBUTTON; 225534642Smarc } 225630391Skarels 225734642Smarc /* 225834642Smarc * report the mouse motion event */ 225930391Skarels 226034642Smarc event = PUTBEGIN(eqh); 226134642Smarc PUTEND(eqh); 226230391Skarels 226334642Smarc ++do_wakeup; /* request a select wakeup call */ 226430391Skarels 226534642Smarc event->vse_x = eqh->curs_pos.x; 226634642Smarc event->vse_y = eqh->curs_pos.y; 226730391Skarels 226834642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 226934642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 227034642Smarc event->vse_key = 0; 227134642Smarc event->vse_direction = 0; 227234642Smarc event->vse_time = TOY; /* time stamp */ 227334642Smarc } 227430391Skarels 227530391Skarels GET_MBUTTON: 227634642Smarc /* 227734642Smarc * if button state has changed */ 227830391Skarels 227934642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 228034642Smarc b = last_rep[qd].state & 0x07; 228130391Skarels 228234642Smarc if (a ^ b) { 228330391Skarels 228434642Smarc for ( c = 1; c < 8; c <<= 1) { 228530391Skarels 228634642Smarc if (!( c & (a ^ b))) /* this button change? */ 228734642Smarc continue; 228830391Skarels 228934642Smarc /* event queue full? (overflow condition) */ 229030391Skarels 229134642Smarc if (ISFULL(eqh) == TRUE) { 229234732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 229334642Smarc break; 229434642Smarc } 229530391Skarels 229634642Smarc event = PUTBEGIN(eqh); /* get new event */ 229734642Smarc PUTEND(eqh); 229830391Skarels 229934642Smarc ++do_wakeup; /* request select wakeup */ 230030391Skarels 230134642Smarc event->vse_x = eqh->curs_pos.x; 230234642Smarc event->vse_y = eqh->curs_pos.y; 230330391Skarels 230434642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 230534642Smarc event->vse_type = VSE_BUTTON; /* new button */ 230634642Smarc event->vse_time = TOY; /* time stamp */ 230730391Skarels 230834642Smarc /* flag changed button and if up or down */ 230930391Skarels 231034642Smarc if (c == RIGHT_BUTTON) 231134642Smarc event->vse_key = VSE_RIGHT_BUTTON; 231234642Smarc else if (c == MIDDLE_BUTTON) 231334642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 231434642Smarc else if (c == LEFT_BUTTON) 231534642Smarc event->vse_key = VSE_LEFT_BUTTON; 231630391Skarels 231734642Smarc /* set bit = button depressed */ 231830391Skarels 231934642Smarc if (c & a) 232034642Smarc event->vse_direction = VSE_KBTDOWN; 232134642Smarc else 232234642Smarc event->vse_direction = VSE_KBTUP; 232334642Smarc } 232434642Smarc } 232530391Skarels 232634642Smarc /* refresh last report */ 232730391Skarels 232834642Smarc last_rep[qd] = current_rep[qd]; 232930391Skarels 233034642Smarc } /* get last byte of report */ 233134732Smarc } else if ((status = duart->statusB)&RCV_RDY && 233234732Smarc qdflags[qd].pntr_id == TABLET_ID) { 233334732Smarc /* 233434732Smarc * pickup tablet input, if any 233534732Smarc */ 233634732Smarc if (status&0x70) { 233734642Smarc duart->cmdB = 0x40; 233834642Smarc continue; 233934642Smarc } 234034732Smarc /* 234134732Smarc * event queue full now? (overflow condition) 234234732Smarc */ 234334642Smarc if (ISFULL(eqh) == TRUE) { 234434732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 234534642Smarc break; 234634642Smarc } 234730391Skarels 234834642Smarc data = duart->dataB; /* get report byte */ 234934642Smarc ++new_rep->bytcnt; /* bump report byte count */ 235030391Skarels 235134642Smarc /* 235234642Smarc * if 1st byte of report.. */ 235330391Skarels 235434642Smarc if (data & START_FRAME) { 235534642Smarc new_rep->state = data; 235634642Smarc if (new_rep->bytcnt > 1) { 235734642Smarc new_rep->bytcnt = 1; /* start of new frame */ 235834642Smarc continue; /* ..continue looking */ 235934642Smarc } 236034642Smarc } 236130391Skarels 236234642Smarc /* 236334642Smarc * if 2nd byte of report.. */ 236430391Skarels 236534642Smarc else if (new_rep->bytcnt == 2) { 236634642Smarc new_rep->dx = data & 0x3F; 236734642Smarc } 236830391Skarels 236934642Smarc /* 237034642Smarc * if 3rd byte of report.. */ 237130391Skarels 237234642Smarc else if (new_rep->bytcnt == 3) { 237334642Smarc new_rep->dx |= (data & 0x3F) << 6; 237434642Smarc } 237530391Skarels 237634642Smarc /* 237734642Smarc * if 4th byte of report.. */ 237830391Skarels 237934642Smarc else if (new_rep->bytcnt == 4) { 238034642Smarc new_rep->dy = data & 0x3F; 238134642Smarc } 238230391Skarels 238334642Smarc /* 238434642Smarc * if 5th byte of report, load input event queue */ 238530391Skarels 238634642Smarc else if (new_rep->bytcnt == 5) { 238730391Skarels 238834642Smarc new_rep->dy |= (data & 0x3F) << 6; 238934642Smarc new_rep->bytcnt = 0; 239030391Skarels 239134642Smarc /* 239234642Smarc * update cursor position coordinates */ 239330391Skarels 239434642Smarc new_rep->dx /= qdflags[qd].tab_res; 239534642Smarc new_rep->dy = (2200 - new_rep->dy) 239634642Smarc / qdflags[qd].tab_res; 239730391Skarels 239834642Smarc if (new_rep->dx > 1023) { 239934642Smarc new_rep->dx = 1023; 240034642Smarc } 240134642Smarc if (new_rep->dy > 863) { 240234642Smarc new_rep->dy = 863; 240334642Smarc } 240430391Skarels 240534642Smarc /* 240634642Smarc * report an event if the puck/stylus has moved 240734642Smarc */ 240830391Skarels 240934642Smarc if (eqh->curs_pos.x != new_rep->dx || 241034642Smarc eqh->curs_pos.y != new_rep->dy) { 241130391Skarels 241234642Smarc eqh->curs_pos.x = new_rep->dx; 241334642Smarc eqh->curs_pos.y = new_rep->dy; 241430391Skarels 241534642Smarc /* 241634642Smarc * update cursor screen position */ 241730391Skarels 241834642Smarc dga = (struct dga *) qdmap[qd].dga; 241934642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 242034642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 242130391Skarels 242234642Smarc /* 242334642Smarc * if cursor is in the box, no event report 242434642Smarc */ 242530391Skarels 242634642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 242734642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 242834642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 242934642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 243034642Smarc goto GET_TBUTTON; 243134642Smarc } 243230391Skarels 243334642Smarc /* 243434642Smarc * report the tablet motion event */ 243530391Skarels 243634642Smarc event = PUTBEGIN(eqh); 243734642Smarc PUTEND(eqh); 243830391Skarels 243934642Smarc ++do_wakeup; /* request a select wakeup call */ 244030391Skarels 244134642Smarc event->vse_x = eqh->curs_pos.x; 244234642Smarc event->vse_y = eqh->curs_pos.y; 244330391Skarels 244434642Smarc event->vse_device = VSE_TABLET; /* tablet */ 244534642Smarc /* 244634642Smarc * right now, X handles tablet motion the same 244734642Smarc * as mouse motion 244834642Smarc */ 244934642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 245034642Smarc event->vse_key = 0; 245134642Smarc event->vse_direction = 0; 245234642Smarc event->vse_time = TOY; /* time stamp */ 245334642Smarc } 245430391Skarels GET_TBUTTON: 245534642Smarc /* 245634642Smarc * if button state has changed */ 245730391Skarels 245834642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 245934642Smarc b = last_rep[qd].state & 0x1E; 246030391Skarels 246134642Smarc if (a ^ b) { 246230391Skarels 246334642Smarc /* event queue full now? (overflow condition) */ 246430391Skarels 246534642Smarc if (ISFULL(eqh) == TRUE) { 246634732Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 246734642Smarc break; 246834642Smarc } 246930391Skarels 247034642Smarc event = PUTBEGIN(eqh); /* get new event */ 247134642Smarc PUTEND(eqh); 247230391Skarels 247334642Smarc ++do_wakeup; /* request a select wakeup call */ 247430391Skarels 247534642Smarc event->vse_x = eqh->curs_pos.x; 247634642Smarc event->vse_y = eqh->curs_pos.y; 247730391Skarels 247834642Smarc event->vse_device = VSE_TABLET; /* tablet */ 247934642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 248034642Smarc event->vse_time = TOY; /* time stamp */ 248130391Skarels 248234642Smarc /* define the changed button and if up or down */ 248330391Skarels 248434642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 248534642Smarc if (c & (a ^ b)) { 248634642Smarc if (c == T_LEFT_BUTTON) 248734642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 248834642Smarc else if (c == T_FRONT_BUTTON) 248934642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 249034642Smarc else if (c == T_RIGHT_BUTTON) 249134642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 249234642Smarc else if (c == T_BACK_BUTTON) 249334642Smarc event->vse_key = VSE_T_BACK_BUTTON; 249434642Smarc break; 249534642Smarc } 249634642Smarc } 249730391Skarels 249834642Smarc /* set bit = button depressed */ 249930391Skarels 250034642Smarc if (c & a) 250134642Smarc event->vse_direction = VSE_KBTDOWN; 250234642Smarc else 250334642Smarc event->vse_direction = VSE_KBTUP; 250434642Smarc } 250530391Skarels 250634642Smarc /* refresh last report */ 250730391Skarels 250834642Smarc last_rep[qd] = current_rep[qd]; 250930391Skarels 251034642Smarc } /* get last byte of report */ 251134642Smarc } /* pick up tablet input */ 251230391Skarels 251334642Smarc } /* while input available.. */ 251430391Skarels 251534642Smarc /* 251634642Smarc * do select wakeup 251734642Smarc */ 251834732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 251934732Smarc selwakeup(qdrsel[qd], 0); 252034732Smarc qdrsel[qd] = 0; 252134642Smarc qdflags[qd].selmask &= ~SEL_READ; 252234642Smarc do_wakeup = 0; 252334642Smarc } 252434732Smarc } else { 252534732Smarc /* 252634732Smarc * if the graphic device is not turned on, this is console input 252734732Smarc */ 252840817Smarc if (qdpolling) 252940817Smarc return; 253034642Smarc ui = qdinfo[qd]; 253134642Smarc if (ui == 0 || ui->ui_alive == 0) 253234732Smarc return; 253330391Skarels 253434642Smarc tp = &qd_tty[qd << 2]; 253530391Skarels 253634642Smarc /* 253734732Smarc * Get a character from the keyboard. 253834732Smarc */ 253934732Smarc while (duart->statusA&RCV_RDY) { 254034642Smarc key = duart->dataA; 254134642Smarc key &= 0xFF; 254234642Smarc /* 254334732Smarc * Check for various keyboard errors 254434732Smarc */ 254534732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 254634642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 254734732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 254834732Smarc return; 254934642Smarc } 255030391Skarels 255134642Smarc if (key < LK_LOWEST) 255234732Smarc return; 255330391Skarels 255434642Smarc /* 255534642Smarc * See if its a state change key */ 255630391Skarels 255734642Smarc switch (key) { 255830391Skarels 255934642Smarc case LOCK: 256034642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 256134642Smarc if (q_keyboard.lock) 256234732Smarc (void)led_control(qd, LK_LED_ENABLE, 256334732Smarc LK_LED_LOCK); 256434642Smarc else 256534732Smarc (void)led_control(qd, LK_LED_DISABLE, 256634732Smarc LK_LED_LOCK); 256734642Smarc return; 256830391Skarels 256934642Smarc case SHIFT: 257034642Smarc q_keyboard.shift ^= 0xFFFF; 257134642Smarc return; 257230391Skarels 257334642Smarc case CNTRL: 257434642Smarc q_keyboard.cntrl ^= 0xFFFF; 257534642Smarc return; 257630391Skarels 257734642Smarc case ALLUP: 257834642Smarc q_keyboard.cntrl = 0; 257934642Smarc q_keyboard.shift = 0; 258034642Smarc return; 258130391Skarels 258234642Smarc case REPEAT: 258334642Smarc chr = q_keyboard.last; 258434642Smarc break; 258530391Skarels 258634642Smarc /* 258734642Smarc * Test for cntrl characters. If set, see if the character 258834642Smarc * is elligible to become a control character. */ 258930391Skarels 259034642Smarc default: 259130391Skarels 259234642Smarc if (q_keyboard.cntrl) { 259334642Smarc chr = q_key[key]; 259434642Smarc if (chr >= ' ' && chr <= '~') 259534642Smarc chr &= 0x1F; 259634642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 259734642Smarc chr &= 0x9F; 259834642Smarc } 259934642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 260034642Smarc chr = q_shift_key[key]; 260134642Smarc else 260234642Smarc chr = q_key[key]; 260334642Smarc break; 260430391Skarels } 260530391Skarels 260634642Smarc q_keyboard.last = chr; 260730391Skarels 260834642Smarc /* 260934642Smarc * Check for special function keys */ 261030391Skarels 261134642Smarc if (chr & 0x100) { 261234642Smarc char *string; 261334642Smarc string = q_special[chr & 0x7F]; 261434642Smarc while(*string) 261534642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 261634615Smarc } 261734642Smarc else { 261840817Smarc #ifdef KADB 261940817Smarc if (!kdbrintr(chr&0177, tp)) 262040817Smarc #endif 262134642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 262234642Smarc } 262330391Skarels } 262430391Skarels } 262530391Skarels } /* qdiint */ 262630391Skarels 262734732Smarc /* 262834732Smarc * 262934732Smarc * Clear the QDSS screen 263034732Smarc * 263134732Smarc * >>> NOTE <<< 263234732Smarc * 263334732Smarc * This code requires that certain adder initialization be valid. To 263434732Smarc * assure that this requirement is satisfied, this routine should be 263534732Smarc * called only after calling the "setup_dragon()" function. 263634732Smarc * 263734732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear 263834732Smarc * only clears the current displayed portion of the bitmap put a 263934732Smarc * temporary value in the y limit register so we can access whole 264034732Smarc * bitmap 264134732Smarc * 264234732Smarc */ 264330391Skarels clear_qd_screen(unit) 264434732Smarc int unit; 264530391Skarels { 264630391Skarels register struct adder *adder; 264730391Skarels adder = (struct adder *) qdmap[unit].adder; 264830391Skarels 264930391Skarels adder->x_limit = 1024; 265030391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 265130391Skarels adder->y_offset_pending = 0; 265234732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 265334642Smarc WSV; 265430391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265534642Smarc WSV; 265630391Skarels adder->y_offset_pending = 864; 265734642Smarc WSV; 265830391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265934642Smarc WSV; 266030391Skarels adder->y_offset_pending = 1728; 266134642Smarc WSV; 266230391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266334642Smarc WSV; 266430391Skarels adder->y_offset_pending = 0; /* back to normal */ 266534642Smarc WSV; 266630391Skarels adder->x_limit = MAX_SCREEN_X; 266730391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 266834642Smarc #undef WSV 266930391Skarels 267030391Skarels } /* clear_qd_screen */ 267130391Skarels 267234732Smarc /* 267334732Smarc * kernel console output to the glass tty 267434732Smarc */ 267530391Skarels qdputc(chr) 267634642Smarc register char chr; 267730391Skarels { 267830391Skarels 267934642Smarc /* 268034642Smarc * if system is now physical, forget it (ie: crash DUMP) 268134642Smarc */ 268234642Smarc if ((mfpr(MAPEN) & 1) == 0) 268334642Smarc return; 268434615Smarc 268534732Smarc blitc(0, (u_char)(chr & 0xff)); 268632012Smarc if ((chr & 0177) == '\n') 268732012Smarc blitc(0, '\r'); 268830391Skarels 268930391Skarels } /* qdputc */ 269030391Skarels 269134732Smarc /* 269234732Smarc * load the mouse cursor's template RAM bitmap 269334732Smarc */ 269430391Skarels ldcursor(unit, bitmap) 269534732Smarc int unit; 269634732Smarc register short *bitmap; 269730391Skarels { 269830391Skarels register struct dga *dga; 269930391Skarels register short *temp; 270030391Skarels register int i; 270134732Smarc int curs; 270230391Skarels 270330391Skarels dga = (struct dga *) qdmap[unit].dga; 270430391Skarels temp = (short *) qdmap[unit].template; 270530391Skarels 270630391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 270734732Smarc curs = -1; /* ..note that.. */ 270834642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 270934732Smarc } else 271034732Smarc curs = 0; 271130391Skarels 271230391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 271330391Skarels 271430391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 271534642Smarc /* ..of the 8k WORD template space */ 271630391Skarels for (i = 0; i < 32; ++i) 271734642Smarc *temp++ = *bitmap++; 271830391Skarels 271934732Smarc if (curs) { /* if cursor was enabled.. */ 272034642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 272130391Skarels } 272230391Skarels 272330391Skarels } /* ldcursor */ 272430391Skarels 272534732Smarc /* 272634732Smarc * Put the console font in the QDSS off-screen memory 272734732Smarc */ 272830391Skarels ldfont(unit) 272934732Smarc int unit; 273030391Skarels { 273130391Skarels register struct adder *adder; 273230391Skarels 273334732Smarc register i, j, k, max_chars_line; 273434732Smarc register short packed; 273530391Skarels 273630391Skarels adder = (struct adder *) qdmap[unit].adder; 273730391Skarels 273834642Smarc /* 273934732Smarc * setup VIPER operand control registers 274034732Smarc */ 274130391Skarels write_ID(adder, MASK_1, 0xFFFF); 274230391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 274330391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 274430391Skarels 274530391Skarels write_ID(adder, SRC1_OCR_B, 274634642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 274730391Skarels write_ID(adder, SRC2_OCR_B, 274834642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 274930391Skarels write_ID(adder, DST_OCR_B, 275034642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 275130391Skarels 275230391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 275330391Skarels 275434642Smarc /* 275534732Smarc * load destination data 275634732Smarc */ 275734732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 275830391Skarels 275930391Skarels adder->destination_x = FONT_X; 276030391Skarels adder->destination_y = FONT_Y; 276134732Smarc #if FONT_WIDTH > MAX_SCREEN_X 276234732Smarc adder->fast_dest_dx = MAX_SCREEN_X; 276334732Smarc #else 276434732Smarc adder->fast_dest_dx = FONT_WIDTH; 276534732Smarc #endif 276630391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 276730391Skarels 276834642Smarc /* 276934642Smarc * setup for processor to bitmap xfer */ 277030391Skarels 277130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 277230391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 277330391Skarels 277434642Smarc /* 277534642Smarc * Figure out how many characters can be stored on one "line" of 277634642Smarc * offscreen memory. 277734642Smarc */ 277834642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 277934642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 278034642Smarc max_chars_line = CHARS/2 + CHARS%2; 278130391Skarels 278234642Smarc /* 278334642Smarc * iteratively do the processor to bitmap xfer */ 278434615Smarc 278530391Skarels for (i = 0; i < ROWS; ++i) { 278630391Skarels 278734642Smarc /* PTOB a scan line */ 278830391Skarels 278934642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 279034642Smarc /* PTOB one scan of a char cell */ 279130391Skarels 279234642Smarc packed = q_font[k]; 279334642Smarc k += ROWS; 279434642Smarc packed |= ((short)q_font[k] << 8); 279534642Smarc k += ROWS; 279630391Skarels 279734732Smarc (void)wait_status(adder, TX_READY); 279834642Smarc adder->id_data = packed; 279934642Smarc } 280030391Skarels } 280130391Skarels 280234642Smarc /* 280334642Smarc * (XXX XXX XXX - should remove) 280434642Smarc * 280534642Smarc * Copy the second row of characters. Subtract the first 280634642Smarc * row from the total number. Divide this quantity by 2 280734642Smarc * because 2 chars are stored in a short in the PTOB loop 280834642Smarc * below. Figure out how many characters can be stored on 280934642Smarc * one "line" of offscreen memory 281034642Smarc */ 281134642Smarc 281234642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 281334642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 281434642Smarc return; 281534642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 281634642Smarc /* Paranoia check to see if 3rd row may be needed */ 281734642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 281834615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 281934615Smarc 282034615Smarc adder->destination_x = FONT_X; 282134615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 282234615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 282334615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 282434615Smarc 282534642Smarc /* 282634642Smarc * setup for processor to bitmap xfer 282734642Smarc */ 282834615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 282934615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 283034615Smarc 283134642Smarc /* 283234642Smarc * iteratively do the processor to bitmap xfer 283334642Smarc */ 283434615Smarc for (i = 0; i < ROWS; ++i) { 283534642Smarc /* 283634642Smarc * PTOB a scan line 283734642Smarc */ 283834642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 283934642Smarc /* 284034642Smarc * PTOB one scan of a char cell 284134642Smarc */ 284234642Smarc packed = q_font[k + FONT_OFFSET]; 284334642Smarc k += ROWS; 284434642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 284534642Smarc k += ROWS; 284634732Smarc (void)wait_status(adder, TX_READY); 284734642Smarc adder->id_data = packed; 284834642Smarc } 284934615Smarc } 285034615Smarc 285130391Skarels } /* ldfont */ 285230391Skarels 285340817Smarc qdpoll(onoff) 285440817Smarc { 285540817Smarc qdpolling = onoff; 285640817Smarc } 285740817Smarc 285834732Smarc /* 285934732Smarc * Get a character from the LK201 (polled) 286034732Smarc */ 286134732Smarc qdgetc() 286234732Smarc { 286334732Smarc register short key; 286434732Smarc register char chr; 286534732Smarc register struct duart *duart; 286630391Skarels 286734732Smarc duart = (struct duart *) qdmap[0].duart; 286834732Smarc 286934732Smarc /* 287034732Smarc * Get a character from the keyboard. 287134732Smarc */ 287234732Smarc LOOP: 287334732Smarc while (!(duart->statusA&RCV_RDY)) 287434732Smarc ; 287534732Smarc 287634732Smarc key = duart->dataA; 287734732Smarc key &= 0xFF; 287834732Smarc 287934732Smarc /* 288034732Smarc * Check for various keyboard errors */ 288134732Smarc 288234732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 288334732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 288434732Smarc printf("Keyboard error, code = %x\n", key); 288534732Smarc return(0); 288634732Smarc } 288734732Smarc 288834732Smarc if (key < LK_LOWEST) 288934732Smarc return(0); 289034732Smarc 289134732Smarc /* 289234732Smarc * See if its a state change key 289334732Smarc */ 289434732Smarc switch (key) { 289534732Smarc 289634732Smarc case LOCK: 289734732Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 289834732Smarc if (q_keyboard.lock) 289934732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 290034732Smarc else 290134732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 290234732Smarc goto LOOP; 290334732Smarc 290434732Smarc case SHIFT: 290534732Smarc q_keyboard.shift ^= 0xFFFF; 290634732Smarc goto LOOP; 290734732Smarc 290834732Smarc case CNTRL: 290934732Smarc q_keyboard.cntrl ^= 0xFFFF; 291034732Smarc goto LOOP; 291134732Smarc 291234732Smarc case ALLUP: 291334732Smarc q_keyboard.cntrl = 0; 291434732Smarc q_keyboard.shift = 0; 291534732Smarc goto LOOP; 291634732Smarc 291734732Smarc case REPEAT: 291834732Smarc chr = q_keyboard.last; 291934732Smarc break; 292034732Smarc 292134732Smarc /* 292234732Smarc * Test for cntrl characters. If set, see if the character 292334732Smarc * is elligible to become a control character. 292434732Smarc */ 292534732Smarc default: 292634732Smarc 292734732Smarc if (q_keyboard.cntrl) { 292834732Smarc chr = q_key[key]; 292934732Smarc if (chr >= ' ' && chr <= '~') 293034732Smarc chr &= 0x1F; 293134732Smarc } 293234732Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 293334732Smarc chr = q_shift_key[key]; 293434732Smarc else 293534732Smarc chr = q_key[key]; 293634732Smarc break; 293734732Smarc } 293834732Smarc 293934732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 294034732Smarc return(0); /* ..then pitch it! */ 294134732Smarc 294234732Smarc q_keyboard.last = chr; 294334732Smarc 294434732Smarc /* 294534732Smarc * Check for special function keys */ 294634732Smarc 294734732Smarc if (chr & 0x80) /* pitch the function keys */ 294834732Smarc return(0); 294934732Smarc else 295034732Smarc return(chr); 295134732Smarc 295234732Smarc } /* qdgetc */ 295334732Smarc 295434732Smarc /* 295534732Smarc * led_control()... twiddle LK-201 LED's 295634732Smarc */ 295730391Skarels led_control(unit, cmd, led_mask) 295834732Smarc int unit, cmd, led_mask; 295930391Skarels { 296034732Smarc register i; 296130391Skarels register struct duart *duart; 296230391Skarels 296334732Smarc duart = (struct duart *)qdmap[unit].duart; 296430391Skarels 296530391Skarels for (i = 1000; i > 0; --i) { 296634732Smarc if (duart->statusA&XMT_RDY) { 296734642Smarc duart->dataA = cmd; 296834642Smarc break; 296934642Smarc } 297030391Skarels } 297130391Skarels for (i = 1000; i > 0; --i) { 297234732Smarc if (duart->statusA&XMT_RDY) { 297334642Smarc duart->dataA = led_mask; 297434642Smarc break; 297534642Smarc } 297630391Skarels } 297730391Skarels if (i == 0) 297834642Smarc return(BAD); 297930391Skarels return(GOOD); 298030391Skarels 298130391Skarels } /* led_control */ 298230391Skarels 298334732Smarc /* 298434732Smarc * scroll_up()... move the screen up one character height 298534732Smarc */ 298630391Skarels scroll_up(adder) 298734642Smarc register struct adder *adder; 298830391Skarels { 298934642Smarc /* 299034642Smarc * setup VIPER operand control registers 299134642Smarc */ 299234732Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 299330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 299430391Skarels write_ID(adder, MASK_1, 0xFFFF); 299530391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 299630391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 299730391Skarels write_ID(adder, SRC1_OCR_B, 299834642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 299930391Skarels write_ID(adder, DST_OCR_B, 300034642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 300134642Smarc /* 300234642Smarc * load DESTINATION origin and vectors 300334642Smarc */ 300430391Skarels adder->fast_dest_dy = 0; 300530391Skarels adder->slow_dest_dx = 0; 300630391Skarels adder->error_1 = 0; 300730391Skarels adder->error_2 = 0; 300830391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 300930391Skarels adder->destination_x = 0; 301030391Skarels adder->fast_dest_dx = 1024; 301130391Skarels adder->destination_y = 0; 301230391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 301334642Smarc /* 301434642Smarc * load SOURCE origin and vectors 301534642Smarc */ 301630391Skarels adder->source_1_x = 0; 301730391Skarels adder->source_1_dx = 1024; 301830391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 301930391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 302030391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 302130391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 302234642Smarc /* 302334642Smarc * do a rectangle clear of last screen line 302434642Smarc */ 302530391Skarels write_ID(adder, MASK_1, 0xffff); 302630391Skarels write_ID(adder, SOURCE, 0xffff); 302730391Skarels write_ID(adder,DST_OCR_B, 302834642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 302930391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 303030391Skarels adder->error_1 = 0; 303130391Skarels adder->error_2 = 0; 303234642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 303330391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 303430391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 303534732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 303630391Skarels adder->destination_x = 0; 303730391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 303830391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 303930391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 304030391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 304130391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 304230391Skarels 304330391Skarels } /* scroll_up */ 304430391Skarels 304534732Smarc /* 304634732Smarc * init shared memory pointers and structures 304734732Smarc */ 304830391Skarels init_shared(unit) 304934732Smarc register unit; 305030391Skarels { 305130391Skarels register struct dga *dga; 305230391Skarels 305330391Skarels dga = (struct dga *) qdmap[unit].dga; 305430391Skarels 305534642Smarc /* 305634642Smarc * initialize the event queue pointers and header */ 305730391Skarels 305830391Skarels eq_header[unit] = (struct qdinput *) 305934642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 306034642Smarc + (EVENT_BUFSIZE * unit)); 306130391Skarels eq_header[unit]->curs_pos.x = 0; 306230391Skarels eq_header[unit]->curs_pos.y = 0; 306330391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 306430391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 306530391Skarels eq_header[unit]->curs_box.left = 0; 306630391Skarels eq_header[unit]->curs_box.right = 0; 306730391Skarels eq_header[unit]->curs_box.top = 0; 306830391Skarels eq_header[unit]->curs_box.bottom = 0; 306934642Smarc /* 307034642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 307134642Smarc */ 307230391Skarels DMAheader[unit] = (struct DMAreq_header *) 307334642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 307434642Smarc + (DMAbuf_size * unit)); 307530391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 307634642Smarc + sizeof(struct DMAreq_header)); 307730391Skarels DMAheader[unit]->QBAreg = 0; 307830391Skarels DMAheader[unit]->status = 0; 307930391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 308030391Skarels DMAheader[unit]->used = 0; 308130391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 308230391Skarels DMAheader[unit]->oldest = 0; 308330391Skarels DMAheader[unit]->newest = 0; 308434642Smarc /* 308534642Smarc * assign a pointer to the scroll structure for this QDSS. 308634642Smarc */ 308730391Skarels scroll[unit] = (struct scroll *) 308834642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 308934642Smarc + (sizeof(struct scroll) * unit)); 309030391Skarels scroll[unit]->status = 0; 309130391Skarels scroll[unit]->viper_constant = 0; 309230391Skarels scroll[unit]->y_scroll_constant = 0; 309330391Skarels scroll[unit]->y_offset = 0; 309430391Skarels scroll[unit]->x_index_pending = 0; 309530391Skarels scroll[unit]->y_index_pending = 0; 309634642Smarc /* 309734642Smarc * assign a pointer to the color map write buffer for this QDSS 309834642Smarc */ 309930391Skarels color_buf[unit] = (struct color_buf *) 310034642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 310134642Smarc + (COLOR_BUFSIZ * unit)); 310230391Skarels color_buf[unit]->status = 0; 310330391Skarels color_buf[unit]->count = 0; 310430391Skarels 310530391Skarels } /* init_shared */ 310630391Skarels 310734732Smarc /* 310834732Smarc * init the ADDER, VIPER, bitmaps, & color map 310934732Smarc */ 311030391Skarels setup_dragon(unit) 311134732Smarc int unit; 311230391Skarels { 311330391Skarels 311430391Skarels register struct adder *adder; 311530391Skarels register struct dga *dga; 311630391Skarels short *memcsr; 311734732Smarc register i; 311830391Skarels short top; /* clipping/scrolling boundaries */ 311930391Skarels short bottom; 312030391Skarels short right; 312130391Skarels short left; 312230391Skarels short *red; /* color map pointers */ 312330391Skarels short *green; 312430391Skarels short *blue; 312530391Skarels 312634642Smarc /* 312734642Smarc * init for setup 312834642Smarc */ 312930391Skarels adder = (struct adder *) qdmap[unit].adder; 313030391Skarels dga = (struct dga *) qdmap[unit].dga; 313130391Skarels memcsr = (short *) qdmap[unit].memcsr; 313230391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 313330391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 313430391Skarels adder->command = CANCEL; 313534642Smarc /* 313634642Smarc * set monitor timing 313734642Smarc */ 313830391Skarels adder->x_scan_count_0 = 0x2800; 313930391Skarels adder->x_scan_count_1 = 0x1020; 314030391Skarels adder->x_scan_count_2 = 0x003A; 314130391Skarels adder->x_scan_count_3 = 0x38F0; 314230391Skarels adder->x_scan_count_4 = 0x6128; 314330391Skarels adder->x_scan_count_5 = 0x093A; 314430391Skarels adder->x_scan_count_6 = 0x313C; 314530391Skarels adder->sync_phase_adj = 0x0100; 314630391Skarels adder->x_scan_conf = 0x00C8; 314734642Smarc /* 314834642Smarc * got a bug in secound pass ADDER! lets take care of it 314934642Smarc * 315034642Smarc * normally, just use the code in the following bug fix code, but to 315134642Smarc * make repeated demos look pretty, load the registers as if there was 315234642Smarc * no bug and then test to see if we are getting sync 315334642Smarc */ 315430391Skarels adder->y_scan_count_0 = 0x135F; 315530391Skarels adder->y_scan_count_1 = 0x3363; 315630391Skarels adder->y_scan_count_2 = 0x2366; 315730391Skarels adder->y_scan_count_3 = 0x0388; 315834642Smarc /* 315934642Smarc * if no sync, do the bug fix code 316034642Smarc */ 316130391Skarels if (wait_status(adder, VSYNC) == BAD) { 316234642Smarc /* first load all Y scan registers with very short frame and 316334642Smarc * wait for scroll service. This guarantees at least one SYNC 316434642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 316534642Smarc * XCINCH with DMSEEDH) 316634642Smarc */ 316734642Smarc adder->y_scan_count_0 = 0x01; 316834642Smarc adder->y_scan_count_1 = 0x01; 316934642Smarc adder->y_scan_count_2 = 0x01; 317034642Smarc adder->y_scan_count_3 = 0x01; 317134642Smarc /* 317234642Smarc * delay at least 1 full frame time 317334642Smarc */ 317434732Smarc (void)wait_status(adder, VSYNC); 317534732Smarc (void)wait_status(adder, VSYNC); 317634642Smarc /* 317734642Smarc * now load the REAL sync values (in reverse order just to 317834642Smarc * be safe. 317934642Smarc */ 318034642Smarc adder->y_scan_count_3 = 0x0388; 318134642Smarc adder->y_scan_count_2 = 0x2366; 318234642Smarc adder->y_scan_count_1 = 0x3363; 318334642Smarc adder->y_scan_count_0 = 0x135F; 318430391Skarels } 318530391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 318634642Smarc /* 318734642Smarc * zero the index registers 318834642Smarc */ 318930391Skarels adder->x_index_pending = 0; 319030391Skarels adder->y_index_pending = 0; 319130391Skarels adder->x_index_new = 0; 319230391Skarels adder->y_index_new = 0; 319330391Skarels adder->x_index_old = 0; 319430391Skarels adder->y_index_old = 0; 319530391Skarels adder->pause = 0; 319634642Smarc /* 319734642Smarc * set rasterop mode to normal pen down 319834642Smarc */ 319930391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 320034642Smarc /* 320134642Smarc * set the rasterop registers to a default values 320234642Smarc */ 320330391Skarels adder->source_1_dx = 1; 320430391Skarels adder->source_1_dy = 1; 320530391Skarels adder->source_1_x = 0; 320630391Skarels adder->source_1_y = 0; 320730391Skarels adder->destination_x = 0; 320830391Skarels adder->destination_y = 0; 320930391Skarels adder->fast_dest_dx = 1; 321030391Skarels adder->fast_dest_dy = 0; 321130391Skarels adder->slow_dest_dx = 0; 321230391Skarels adder->slow_dest_dy = 1; 321330391Skarels adder->error_1 = 0; 321430391Skarels adder->error_2 = 0; 321534642Smarc /* 321634732Smarc * scale factor = UNITY 321734642Smarc */ 321830391Skarels adder->fast_scale = UNITY; 321930391Skarels adder->slow_scale = UNITY; 322034642Smarc /* 322134642Smarc * set the source 2 parameters 322234642Smarc */ 322330391Skarels adder->source_2_x = 0; 322430391Skarels adder->source_2_y = 0; 322530391Skarels adder->source_2_size = 0x0022; 322634642Smarc /* 322734642Smarc * initialize plane addresses for eight vipers 322834642Smarc */ 322930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 323030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 323130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 323230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 323330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 323430391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 323530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 323630391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 323730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 323830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 323930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 324030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 324130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 324230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 324330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 324430391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 324534642Smarc /* 324634642Smarc * initialize the external registers. 324734642Smarc */ 324830391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 324930391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 325034642Smarc /* 325134642Smarc * initialize resolution mode 325234642Smarc */ 325330391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 325430391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 325534642Smarc /* 325634642Smarc * initialize viper registers 325734642Smarc */ 325830391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 325930391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 326034642Smarc /* 326134642Smarc * set clipping and scrolling limits to full screen 326234642Smarc */ 326334732Smarc for (i = 1000, adder->status = 0; 326434732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 326534642Smarc ; 326630391Skarels if (i == 0) 326734732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 326830391Skarels top = 0; 326930391Skarels bottom = 2048; 327030391Skarels left = 0; 327130391Skarels right = 1024; 327230391Skarels adder->x_clip_min = left; 327330391Skarels adder->x_clip_max = right; 327430391Skarels adder->y_clip_min = top; 327530391Skarels adder->y_clip_max = bottom; 327630391Skarels adder->scroll_x_min = left; 327730391Skarels adder->scroll_x_max = right; 327830391Skarels adder->scroll_y_min = top; 327930391Skarels adder->scroll_y_max = bottom; 328034732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 328134732Smarc (void)wait_status(adder, VSYNC); 328230391Skarels adder->x_index_pending = left; 328330391Skarels adder->y_index_pending = top; 328430391Skarels adder->x_index_new = left; 328530391Skarels adder->y_index_new = top; 328630391Skarels adder->x_index_old = left; 328730391Skarels adder->y_index_old = top; 328830391Skarels 328934732Smarc for (i = 1000, adder->status = 0; i > 0 && 329034732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 329134642Smarc ; 329230391Skarels if (i == 0) 329334732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 329430391Skarels 329530391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 329630391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 329734642Smarc /* 329834642Smarc * set source and the mask register to all ones (ie: white) o 329934642Smarc */ 330030391Skarels write_ID(adder, SOURCE, 0xFFFF); 330130391Skarels write_ID(adder, MASK_1, 0xFFFF); 330230391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 330330391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 330434642Smarc /* 330534642Smarc * initialize Operand Control Register banks for fill command 330634642Smarc */ 330730391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 330830391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 330930391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 331030391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 331130391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 331230391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 331334642Smarc /* 331434642Smarc * init Logic Unit Function registers, (these are just common values, 331534642Smarc * and may be changed as required). 331634642Smarc */ 331730391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 331834642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 331934642Smarc INV_M1_M2); 332030391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 332130391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 332234642Smarc /* 332334642Smarc * load the color map for black & white 332434642Smarc */ 332534732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 332634642Smarc ; 332730391Skarels 332830391Skarels if (i == 0) 332934732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 333030391Skarels 333130391Skarels red = (short *) qdmap[unit].red; 333230391Skarels green = (short *) qdmap[unit].green; 333330391Skarels blue = (short *) qdmap[unit].blue; 333430391Skarels 333530391Skarels *red++ = 0x00; /* black */ 333630391Skarels *green++ = 0x00; 333730391Skarels *blue++ = 0x00; 333830391Skarels 333930391Skarels *red-- = 0xFF; /* white */ 334030391Skarels *green-- = 0xFF; 334130391Skarels *blue-- = 0xFF; 334230391Skarels 334334642Smarc /* 334434732Smarc * set color map for mouse cursor 334534732Smarc */ 334630391Skarels 334730391Skarels red += 254; 334830391Skarels green += 254; 334930391Skarels blue += 254; 335030391Skarels 335130391Skarels *red++ = 0x00; /* black */ 335230391Skarels *green++ = 0x00; 335330391Skarels *blue++ = 0x00; 335430391Skarels 335530391Skarels *red = 0xFF; /* white */ 335630391Skarels *green = 0xFF; 335730391Skarels *blue = 0xFF; 335830391Skarels 335930391Skarels } /* setup_dragon */ 336030391Skarels 336134732Smarc /* 336234732Smarc * Init the DUART and set defaults in input 336334732Smarc */ 336430391Skarels setup_input(unit) 336534732Smarc int unit; 336630391Skarels { 336730391Skarels register struct duart *duart; /* DUART register structure pointer */ 336834732Smarc register i, bits; 336930391Skarels char id_byte; 337030391Skarels 337130391Skarels duart = (struct duart *) qdmap[unit].duart; 337230391Skarels duart->imask = 0; 337330391Skarels 337434642Smarc /* 337534642Smarc * setup the DUART for kbd & pointing device 337634642Smarc */ 337734732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 337834732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 337934732Smarc /* no RTS control,char error mode */ 338034732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 338134732Smarc /* no RTS control,no echo or loop */ 338234732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 338334732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 338434732Smarc /* ..no RTS cntrl, char error mode */ 338534732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 338634732Smarc /* no RTS control,no echo or loop */ 338734732Smarc duart->auxctl = 0x00; /* baud rate set 1 */ 338834732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */ 338934732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */ 339030391Skarels 339130391Skarels /* reset everything for keyboard */ 339230391Skarels 339330391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339434642Smarc duart->cmdA = bits; 339530391Skarels 339630391Skarels /* reset everything for host */ 339730391Skarels 339830391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339934642Smarc duart->cmdB = bits; 340030391Skarels 340130391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 340230391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 340330391Skarels 340434642Smarc /* 340534732Smarc * init keyboard defaults (DUART channel A) 340634732Smarc */ 340730391Skarels for (i = 500; i > 0; --i) { 340834732Smarc if (duart->statusA&XMT_RDY) { 340934642Smarc duart->dataA = LK_DEFAULTS; 341034642Smarc break; 341134642Smarc } 341230391Skarels } 341330391Skarels 341430391Skarels for (i = 100000; i > 0; --i) { 341534732Smarc if (duart->statusA&RCV_RDY) { 341634642Smarc break; 341734642Smarc } 341830391Skarels } 341930391Skarels 342034732Smarc if (duart->dataA) /* flush the ACK */ 342134732Smarc ; 342230391Skarels 342334642Smarc /* 342434732Smarc * identify the pointing device 342534732Smarc */ 342630391Skarels for (i = 500; i > 0; --i) { 342734732Smarc if (duart->statusB&XMT_RDY) { 342834642Smarc duart->dataB = SELF_TEST; 342934642Smarc break; 343034642Smarc } 343130391Skarels } 343230391Skarels 343334642Smarc /* 343430391Skarels * wait for 1st byte of self test report */ 343530391Skarels 343630391Skarels for (i = 100000; i > 0; --i) { 343734732Smarc if (duart->statusB&RCV_RDY) { 343834642Smarc break; 343934642Smarc } 344030391Skarels } 344130391Skarels 344230391Skarels if (i == 0) { 344334732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 344434642Smarc ,unit); 344534642Smarc goto OUT; 344630391Skarels } 344730391Skarels 344834732Smarc if (duart->dataB) 344934732Smarc ; 345030391Skarels 345134642Smarc /* 345234732Smarc * wait for ID byte of self test report 345334732Smarc */ 345430391Skarels for (i = 100000; i > 0; --i) { 345534732Smarc if (duart->statusB&RCV_RDY) { 345634642Smarc break; 345734642Smarc } 345830391Skarels } 345930391Skarels 346030391Skarels if (i == 0) { 346134732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 346234642Smarc goto OUT; 346330391Skarels } 346430391Skarels 346530391Skarels id_byte = duart->dataB; 346630391Skarels 346734642Smarc /* 346834732Smarc * wait for other bytes to come in 346934732Smarc */ 347030391Skarels for (i = 100000; i > 0; --i) { 347134732Smarc if (duart->statusB & RCV_RDY) { 347234732Smarc if (duart->dataB) 347334732Smarc ; 347434642Smarc break; 347534642Smarc } 347630391Skarels } 347730391Skarels if (i == 0) { 347834732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 347934642Smarc goto OUT; 348030391Skarels } 348130391Skarels for (i = 100000; i > 0; --i) { 348234732Smarc if (duart->statusB&RCV_RDY) { 348334732Smarc if (duart->dataB) 348434732Smarc ; 348534642Smarc break; 348634642Smarc } 348730391Skarels } 348830391Skarels if (i == 0) { 348934732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 349034642Smarc goto OUT; 349130391Skarels } 349234642Smarc /* 349334732Smarc * flag pointing device type and set defaults 349434732Smarc */ 349534732Smarc for (i=100000; i>0; --i) 349634732Smarc ; /*XXX*/ 349730391Skarels 349830391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 349934642Smarc qdflags[unit].pntr_id = MOUSE_ID; 350030391Skarels 350134642Smarc for (i = 500; i > 0; --i) { 350234732Smarc if (duart->statusB&XMT_RDY) { 350334642Smarc duart->dataB = INC_STREAM_MODE; 350434642Smarc break; 350534642Smarc } 350630391Skarels } 350734642Smarc } 350834642Smarc else { 350934642Smarc qdflags[unit].pntr_id = TABLET_ID; 351030391Skarels 351134642Smarc for (i = 500; i > 0; --i) { 351234732Smarc if (duart->statusB&XMT_RDY) { 351334642Smarc duart->dataB = T_STREAM; 351434642Smarc break; 351534642Smarc } 351630391Skarels } 351730391Skarels } 351830391Skarels OUT: 351930391Skarels duart->imask = qdflags[unit].duart_imask; 352030391Skarels 352130391Skarels } /* setup_input */ 352230391Skarels 352334732Smarc /* 352434732Smarc * delay for at least one display frame time 352534732Smarc * 352634732Smarc * return: BAD means that we timed out without ever seeing the 352734732Smarc * vertical sync status bit 352834732Smarc * GOOD otherwise 352934732Smarc */ 353030391Skarels wait_status(adder, mask) 353134642Smarc register struct adder *adder; 353234642Smarc register int mask; 353330391Skarels { 353434732Smarc register i; 353530391Skarels 353634732Smarc for (i = 10000, adder->status = 0 ; i > 0 && 353734732Smarc !(adder->status&mask) ; --i) 353834642Smarc ; 353930391Skarels 354030391Skarels if (i == 0) { 354134732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 354234642Smarc return(BAD); 354330391Skarels } 354430391Skarels 354530391Skarels return(GOOD); 354630391Skarels 354730391Skarels } /* wait_status */ 354830391Skarels 354934732Smarc /* 355034732Smarc * write out onto the ID bus 355134732Smarc */ 355230391Skarels write_ID(adder, adrs, data) 355334642Smarc register struct adder *adder; 355434642Smarc register short adrs; 355534642Smarc register short data; 355630391Skarels { 355734732Smarc register i; 355830391Skarels 355934732Smarc for (i = 100000, adder->status = 0 ; 356034732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 356134642Smarc ; 356230391Skarels 356330391Skarels if (i == 0) 356434732Smarc goto ERR; 356530391Skarels 356634732Smarc for (i = 100000, adder->status = 0 ; 356734732Smarc i > 0 && !(adder->status&TX_READY) ; --i) 356834642Smarc ; 356930391Skarels 357030391Skarels if (i > 0) { 357134642Smarc adder->id_data = data; 357234642Smarc adder->command = ID_LOAD | adrs; 357334732Smarc return ; 357430391Skarels } 357530391Skarels 357630391Skarels ERR: 357734732Smarc printf("write_ID: timeout trying to write to VIPER\n"); 357834732Smarc return ; 357930391Skarels 358030391Skarels } /* write_ID */ 358134511Smarc #endif 3582