134511Smarc /* 2*35353Sbostic * Copyright (c) 1988 Regents of the University of California. 3*35353Sbostic * All rights reserved. 4*35353Sbostic * 5*35353Sbostic * Redistribution and use in source and binary forms are permitted 6*35353Sbostic * provided that the above copyright notice and this paragraph are 7*35353Sbostic * duplicated in all such forms and that any documentation, 8*35353Sbostic * advertising materials, and other materials related to such 9*35353Sbostic * distribution and use acknowledge that the software was developed 10*35353Sbostic * by the University of California, Berkeley. The name of the 11*35353Sbostic * University may not be used to endorse or promote products derived 12*35353Sbostic * from this software without specific prior written permission. 13*35353Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*35353Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*35353Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*35353Sbostic * 17*35353Sbostic * @(#)qd.c 1.10 (Berkeley) 08/09/88 18*35353Sbostic */ 1934642Smarc 2030391Skarels /************************************************************************ 2134511Smarc * * 2234615Smarc * Copyright (c) 1985-1988 by * 2330391Skarels * Digital Equipment Corporation, Maynard, MA * 2430391Skarels * All rights reserved. * 2530391Skarels * * 2630391Skarels * This software is furnished under a license and may be used and * 2730391Skarels * copied only in accordance with the terms of such license and * 2830391Skarels * with the inclusion of the above copyright notice. This * 2930391Skarels * software or any other copies thereof may not be provided or * 3030391Skarels * otherwise made available to any other person. No title to and * 3130391Skarels * ownership of the software is hereby transferred. * 3230391Skarels * * 3330391Skarels * The information in this software is subject to change without * 3430391Skarels * notice and should not be construed as a commitment by Digital * 3530391Skarels * Equipment Corporation. * 3630391Skarels * * 3730391Skarels * Digital assumes no responsibility for the use or reliability * 3830391Skarels * of its software on equipment which is not supplied by Digital. * 3930391Skarels * * 4030391Skarels *************************************************************************/ 4134615Smarc 4230391Skarels /* 4334642Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation 4430391Skarels */ 4530391Skarels 4634642Smarc #include "qd.h" 4734615Smarc 4834511Smarc #if NQD > 0 4934615Smarc #include "types.h" 5034642Smarc #include "../machine/pte.h" 5134642Smarc #include "../machine/mtpr.h" 5234511Smarc #include "../machine/cpu.h" 5334642Smarc #include "param.h" 5434642Smarc #include "conf.h" 5534642Smarc #include "dir.h" 5634642Smarc #include "user.h" 5734642Smarc #include "qdioctl.h" 5834511Smarc #include "tty.h" 5934642Smarc #include "map.h" 6034642Smarc #include "buf.h" 6134642Smarc #include "vm.h" 6234642Smarc #include "bk.h" 6334642Smarc #include "clist.h" 6434642Smarc #include "file.h" 6534642Smarc #include "uio.h" 6634642Smarc #include "kernel.h" 6734615Smarc #include "exec.h" 6834615Smarc #include "proc.h" 6934642Smarc #include "ubareg.h" 7034642Smarc #include "ubavar.h" 7134511Smarc #include "syslog.h" 7234642Smarc #include "qduser.h" /* definitions shared with user level client */ 7334615Smarc #include "qdreg.h" /* QDSS device register structures */ 7432012Smarc 7534642Smarc /* 7634642Smarc * QDSS driver status flags for tracking operational state 7734642Smarc */ 7834642Smarc struct qdflags { 7934642Smarc u_int inuse; /* which minor dev's are in use now */ 8034642Smarc u_int config; /* I/O page register content */ 8134642Smarc u_int mapped; /* user mapping status word */ 8234642Smarc u_int kernel_loop; /* if kernel console is redirected */ 8334642Smarc u_int user_dma; /* DMA from user space in progress */ 8434642Smarc u_short pntr_id; /* type code of pointing device */ 8534642Smarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 8634642Smarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 8734642Smarc u_short curs_acc; /* cursor acceleration factor */ 8834642Smarc u_short curs_thr; /* cursor acceleration threshold level */ 8934642Smarc u_short tab_res; /* tablet resolution factor */ 9034642Smarc u_short selmask; /* mask for active qd select entries */ 9134642Smarc }; 9232012Smarc 9334642Smarc /* 9434642Smarc * bit definitions for 'inuse' entry 9534642Smarc */ 9632012Smarc #define CONS_DEV 0x01 9732012Smarc #define GRAPHIC_DEV 0x04 9832012Smarc 9934642Smarc /* 10034642Smarc * bit definitions for 'mapped' member of flag structure 10134642Smarc */ 10232012Smarc #define MAPDEV 0x01 /* hardware is mapped */ 10332012Smarc #define MAPDMA 0x02 /* DMA buffer mapped */ 10432012Smarc #define MAPEQ 0x04 /* event queue buffer mapped */ 10532012Smarc #define MAPSCR 0x08 /* scroll param area mapped */ 10632012Smarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 10732012Smarc 10834642Smarc /* 10934642Smarc * bit definitions for 'selmask' member of qdflag structure 11034642Smarc */ 11132012Smarc #define SEL_READ 0x01 /* read select is active */ 11232012Smarc #define SEL_WRITE 0x02 /* write select is active */ 11332012Smarc 11434642Smarc /* 11534732Smarc * constants used in shared memory operations 11634732Smarc */ 11732012Smarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 11832012Smarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 11934642Smarc / sizeof(struct _vs_event) ) 12034527Smarc #define DMA_BUFSIZ (1024 * 10) 12132012Smarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 12232012Smarc 12334642Smarc /* 12434732Smarc * reference to an array of "uba_device" structures built by the auto 12534732Smarc * configuration program. The uba_device structure decribes the device 12634732Smarc * sufficiently for the driver to talk to it. The auto configuration code 12734732Smarc * fills in the uba_device structures (located in ioconf.c) from user 12834732Smarc * maintained info. 12934732Smarc */ 13034642Smarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 13134642Smarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 13234732Smarc extern char qvmem[][128*NBPG]; 13334642Smarc extern struct pte QVmap[][128]; 13434642Smarc #define CHUNK (64 * 1024) 13534642Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 13632012Smarc 13734642Smarc /* 13834642Smarc * static storage used by multiple functions in this code 13934642Smarc */ 14034642Smarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 14134642Smarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 14234642Smarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 14334642Smarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 14434642Smarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 14534642Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 14632012Smarc 14734642Smarc /* 14834732Smarc * the array "event_shared[]" is made up of a number of event queue buffers 14934732Smarc * equal to the number of QDSS's configured into the running kernel (NQD). 15034732Smarc * Each event queue buffer begins with an event queue header (struct qdinput) 15134732Smarc * followed by a group of event queue entries (struct _vs_event). The array 15234732Smarc * "*eq_header[]" is an array of pointers to the start of each event queue 15334732Smarc * buffer in "event_shared[]". 15434732Smarc */ 15532012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 15632012Smarc 15734642Smarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 15834642Smarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 15932012Smarc 16034642Smarc /* 16134732Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 16234732Smarc * buffers. Each buffer must consume an integral number of memory pages to 16334732Smarc * guarantee that a following buffer will begin on a page boundary. Also, 16434732Smarc * enough space is allocated so that the FIRST I/O buffer can start at the 16534732Smarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 16634732Smarc * memory protections can be turned on/off for individual buffers. 16734732Smarc */ 16832012Smarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 16932012Smarc 17034642Smarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 17134642Smarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 17232012Smarc 17334642Smarc /* 17434732Smarc * The driver assists a client in scroll operations by loading dragon 17534732Smarc * registers from an interrupt service routine. The loading is done using 17634732Smarc * parameters found in memory shrade between the driver and it's client. 17734732Smarc * The scroll parameter structures are ALL loacted in the same memory page 17834732Smarc * for reasons of memory economy. 17934732Smarc */ 18034642Smarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 18134642Smarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 18232012Smarc 18334642Smarc /* 18434732Smarc * the driver is programmable to provide the user with color map write 18534732Smarc * services at VSYNC interrupt time. At interrupt time the driver loads 18634732Smarc * the color map with any user-requested load data found in shared memory 18734732Smarc */ 18832012Smarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 18932012Smarc 19034642Smarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 19134642Smarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 19232012Smarc 19334642Smarc /* 19434732Smarc * mouse input event structures 19534732Smarc */ 19634642Smarc struct mouse_report last_rep[NQD]; 19734642Smarc struct mouse_report current_rep[NQD]; 19832012Smarc 19934732Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 20034642Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 20134642Smarc int qdcount = 0; /* count of successfully probed qd's */ 20234642Smarc int nNQD = NQD; 20334642Smarc int DMAbuf_size = DMA_BUFSIZ; 20434642Smarc int QDlast_DMAtype; /* type of the last DMA operation */ 20532012Smarc 20634642Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 20734642Smarc /* 20834732Smarc * macro to get system time. Used to time stamp event queue entries 20934732Smarc */ 21030391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 21130391Skarels 21234642Smarc int qdprobe(); 21334642Smarc int qdattach(); 21434642Smarc int qddint(); /* DMA gate array intrpt service */ 21534642Smarc int qdaint(); /* Dragon ADDER intrpt service */ 21634642Smarc int qdiint(); 21730391Skarels 21834642Smarc u_short qdstd[] = { 0 }; 21930391Skarels 22034642Smarc struct uba_driver qddriver = { 22134732Smarc qdprobe, /* device probe entry */ 22234732Smarc 0, /* no slave device */ 22334732Smarc qdattach, /* device attach entry */ 22434732Smarc 0, /* no "fill csr/ba to start" */ 22534642Smarc qdstd, /* device addresses */ 22634642Smarc "qd", /* device name string */ 22734642Smarc qdinfo /* ptr to QDSS's uba_device struct */ 22834642Smarc }; 22930391Skarels 23034615Smarc #define QDPRIOR (PZERO-1) /* must be negative */ 23130391Skarels #define FALSE 0 23230391Skarels #define TRUE ~FALSE 23330391Skarels #define BAD -1 23430391Skarels #define GOOD 0 23530391Skarels 23634642Smarc /* 23734642Smarc * macro to create a system virtual page number from system virtual adrs 23834642Smarc */ 23934642Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 24030391Skarels 24134642Smarc /* 24234642Smarc * QDSS register address offsets from start of QDSS address space 24334642Smarc */ 24430391Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 24530391Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 24630391Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 24730391Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 24830391Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 24930391Skarels #define ADDER (REGSTART+0x000) 25030391Skarels #define DGA (REGSTART+0x200) 25130391Skarels #define DUART (REGSTART+0x400) 25230391Skarels #define MEMCSR (REGSTART+0x800) 25330391Skarels #define CLRSIZE (3 * 512) /* color map size */ 25430391Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 25534642Smarc /* 0x0C00 really */ 25630391Skarels #define RED (CLRSTART+0x000) 25730391Skarels #define BLUE (CLRSTART+0x200) 25830391Skarels #define GREEN (CLRSTART+0x400) 25930391Skarels 26030391Skarels 26134642Smarc /* 26234642Smarc * QDSS minor device numbers. The *real* minor device numbers are in 26334642Smarc * the bottom two bits of the major/minor device spec. Bits 2 and up are 26434642Smarc * used to specify the QDSS device number (ie: which one?) 26534642Smarc */ 26630391Skarels 26730391Skarels #define CONS 0 26830391Skarels #define GRAPHIC 2 26930391Skarels 27034642Smarc /* 27134642Smarc * console cursor bitmap (white block cursor) 27234642Smarc */ 27334642Smarc short cons_cursor[32] = { 27434642Smarc /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27534642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27634642Smarc /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27734642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 27834642Smarc }; 27930391Skarels 28034642Smarc /* 28134642Smarc * constants used in font operations 28234642Smarc */ 28334615Smarc #define CHARS 190 /* # of chars in the font */ 28430391Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 28530391Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 28630391Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 28730391Skarels #define ROWS CHAR_HEIGHT 28830391Skarels #define FONT_X 0 /* font's off screen adrs */ 28930391Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 29030391Skarels 29134642Smarc /* Offset to second row characters (XXX - should remove) */ 29234615Smarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 29330391Skarels 29434642Smarc extern char q_font[]; /* reference font object code */ 29534642Smarc extern u_short q_key[]; /* reference key xlation tables */ 29634642Smarc extern u_short q_shift_key[]; 29734642Smarc extern char *q_special[]; 29830391Skarels 29934642Smarc /* 30034642Smarc * definitions for cursor acceleration reporting 30134642Smarc */ 30230391Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 30330391Skarels 30434642Smarc /* 30534642Smarc * virtual console support. 30634642Smarc */ 30734642Smarc extern (*v_putc)(); 30834642Smarc extern struct cdevsw *consops; 30934642Smarc int qdputc(); 31034642Smarc int qdstart(); 31130391Skarels 31234642Smarc /* 31334642Smarc * LK-201 state storage for input console keyboard conversion to ASCII 31434642Smarc */ 31534642Smarc struct q_keyboard { 31634642Smarc int shift; /* state variables */ 31734642Smarc int cntrl; 31834642Smarc int lock; 31934642Smarc int lastcode; /* last keycode typed */ 32034642Smarc unsigned kup[8]; /* bits for each keycode*/ 32134642Smarc unsigned dkeys[8]; /* down/up mode keys */ 32234642Smarc char last; /* last character */ 32334642Smarc } q_keyboard; 32430391Skarels 32534642Smarc /* 32634642Smarc * tty settings on first open 32734642Smarc */ 32834615Smarc #define IFLAGS (EVENP|ECHO|XTABS|CRMOD) 32934615Smarc #ifdef POSIXTTY 33034615Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL) 33134615Smarc #define OFLAG (OPOST|OXTABS|ONLCR) 33234615Smarc #define LFLAG (ISIG|ICANON|ECHO) 33334615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 33434615Smarc #endif 33534615Smarc 33634732Smarc /* 33734732Smarc * Init QDSS as console (before probe routine) 33834732Smarc */ 33930391Skarels 34030391Skarels qdcons_init() 34130391Skarels { 34234732Smarc register unit; 34330391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 34434615Smarc u_int mapix; /* index into QVmap[] array */ 34534615Smarc struct percpu *pcpu; /* pointer to cpusw structure */ 34634615Smarc register struct qbus *qb; 34730391Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 34830391Skarels u_short *devptr; /* vitual device space */ 34934615Smarc extern cnputc(); 35030391Skarels 35130391Skarels #define QDSSCSR 0x1F00 35230391Skarels 35332012Smarc if (v_putc != cnputc) 35434732Smarc return 0; 35532012Smarc 35630391Skarels unit = 0; 35730391Skarels 35834642Smarc /* 35934642Smarc * find the cpusw entry that matches this machine. 36034642Smarc */ 36132012Smarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 36232012Smarc ; 36332012Smarc if (pcpu == NULL) 36434732Smarc return 0; 36530391Skarels 36632012Smarc /* 36734615Smarc * Map device registers - the last 8K of qvmem. 36832012Smarc */ 36932012Smarc qb = (struct qbus *)pcpu->pc_io->io_details; 37032012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 37134732Smarc UBAIOPAGES * NBPG); 37232012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 37330391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 37434732Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 37534732Smarc return 0; 37634615Smarc 37732012Smarc /* 37832012Smarc * Map q-bus memory used by qdss. (separate map) 37932012Smarc */ 38032012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 38132012Smarc phys_adr = qb->qb_maddr + mapix; 38232012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 38330391Skarels 38432012Smarc /* 38532012Smarc * tell QDSS which Q memory address base to decode 38634642Smarc * (shifted right 16 bits - its in 64K units) 38732012Smarc */ 38832012Smarc *qdaddr = (u_short)((int)mapix >> 16); 38930391Skarels qdflags[unit].config = *(u_short *)qdaddr; 39030391Skarels 39134642Smarc /* 39234642Smarc * load qdmap struct with the virtual addresses of the QDSS elements 39334642Smarc */ 39434615Smarc qdbase[unit] = (caddr_t) (qvmem[0]); 39530391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 39630391Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 39730391Skarels qdmap[unit].dga = qdbase[unit] + DGA; 39830391Skarels qdmap[unit].duart = qdbase[unit] + DUART; 39930391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 40030391Skarels qdmap[unit].red = qdbase[unit] + RED; 40130391Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 40230391Skarels qdmap[unit].green = qdbase[unit] + GREEN; 40330391Skarels 40430391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 40530391Skarels 40634642Smarc /* 40734642Smarc * init the QDSS 40834642Smarc */ 40934642Smarc /* 41032012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 41134642Smarc (char *)qdbase[0], qdmap[0].memcsr); 41234642Smarc */ 41332012Smarc 41430391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 41530391Skarels 41630391Skarels cursor[unit].x = 0; 41730391Skarels cursor[unit].y = 0; 41830391Skarels init_shared(unit); /* init shared memory */ 41930391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 42030391Skarels clear_qd_screen(unit); /* clear the screen */ 42130391Skarels ldfont(unit); /* load the console font */ 42230391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 42330391Skarels setup_input(unit); /* init the DUART */ 42434642Smarc v_putc = qdputc; /* kernel console output to qdss */ 42534642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 42634732Smarc return 1; 42730391Skarels 42830391Skarels } /* qdcons_init */ 42930391Skarels 43034732Smarc /* 43134732Smarc * Configure QDSS into Q memory and make it intrpt. 43234732Smarc * 43334732Smarc * side effects: QDSS gets mapped into Qbus memory space at the first 43434732Smarc * vacant 64kb boundary counting back from the top of 43534732Smarc * Qbus memory space (qvmem+4mb) 43634732Smarc * 43734732Smarc * return: QDSS bus request level and vector address returned in 43834732Smarc * registers by UNIX convention. 43934732Smarc * 44034732Smarc */ 44130391Skarels qdprobe(reg) 44234732Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 44330391Skarels { 44434642Smarc register int br, cvec; /* value-result */ 44530391Skarels register int unit; 44630391Skarels struct dga *dga; /* pointer to gate array structure */ 44734732Smarc int vector; 44834732Smarc #ifdef notdef 44930391Skarels int *ptep; /* page table entry pointer */ 45030391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 45130391Skarels u_int mapix; 45234732Smarc #endif 45330391Skarels 45434732Smarc #ifdef lint 45534732Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 45634732Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 45734732Smarc #endif 45834732Smarc 45934642Smarc /* 46034642Smarc * calculate board unit number from I/O page register address 46134642Smarc */ 46230391Skarels unit = (int) (((int)reg >> 1) & 0x0007); 46330391Skarels 46434642Smarc /* 46534642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 46634642Smarc * physical boundary. The Qbus memory space is mapped into 46734642Smarc * the system memory space at config time. After config 46834642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 46934642Smarc * of the start of Qbus memory. The Qbus memory page table 47034642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 47134642Smarc * which is also loaded at config time. These are the 47234642Smarc * variables used below to find a vacant 64kb boundary in 47334642Smarc * Qbus memory, and load it's corresponding physical adrs 47434642Smarc * into the QDSS's I/O page CSR. 47534642Smarc */ 47630391Skarels 47734615Smarc /* 47834615Smarc * Only if QD is the graphics device. 47934615Smarc */ 48034615Smarc 48130391Skarels /* if this QDSS is NOT the console, then do init here.. */ 48230391Skarels 48334615Smarc if (unit != 0) { 48434615Smarc printf("qd: can't support two qdss's (yet)\n"); 48534732Smarc #ifdef notdef /* can't test */ 48634642Smarc if (v_consputc != qdputc || unit != 0) { 48730391Skarels 48834642Smarc /* 48934642Smarc * read QDSS config info 49034642Smarc */ 49134642Smarc qdflags[unit].config = *(u_short *)reg; 49234615Smarc 49334642Smarc /* 49434642Smarc * find an empty 64kb adrs boundary 49534642Smarc */ 49630391Skarels 49734642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 49830391Skarels 49934642Smarc /* 50034732Smarc * find the cpusw entry that matches this machine. 50134732Smarc */ 50234642Smarc cpup = &cpusw[cpu]; 50334732Smarc while (!(BADADDR(qdbase[unit], sizeof(short)))) 50434732Smarc qdbase[unit] -= CHUNK; 50534615Smarc 50634642Smarc /* 50734732Smarc * tell QDSS which Q memory address base to decode 50834732Smarc */ 50934642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 51034642Smarc ptep = (int *) QVmap[0] + mapix; 51134642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 51234642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 51334615Smarc 51434642Smarc /* 51534642Smarc * load QDSS adrs map with system addresses 51634642Smarc * of device regs 51734642Smarc */ 51834642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART; 51934642Smarc qdmap[unit].adder = qdbase[unit] + ADDER; 52034642Smarc qdmap[unit].dga = qdbase[unit] + DGA; 52134642Smarc qdmap[unit].duart = qdbase[unit] + DUART; 52234642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 52334642Smarc qdmap[unit].red = qdbase[unit] + RED; 52434642Smarc qdmap[unit].blue = qdbase[unit] + BLUE; 52534642Smarc qdmap[unit].green = qdbase[unit] + GREEN; 52630391Skarels 52734642Smarc /* device init */ 52834615Smarc 52934642Smarc cursor[unit].x = 0; 53034642Smarc cursor[unit].y = 0; 53134642Smarc init_shared(unit); /* init shared memory */ 53234642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */ 53334642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */ 53434642Smarc setup_input(unit); /* init the DUART */ 53534642Smarc clear_qd_screen(unit); 53634642Smarc ldfont(unit); /* load the console font */ 53730391Skarels 53834642Smarc /* once only: turn on sync */ 53930391Skarels 54034642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON; 54134642Smarc } 54234615Smarc #endif /*notdef*/ 54330391Skarels } 54430391Skarels 54534642Smarc /* 54634642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 54734642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 54834642Smarc * vectors from the vector pool, and then continue 54934642Smarc * to take them until we get a xx0 HEX vector. The 55034642Smarc * pool provides vectors in contiguous decending 55134642Smarc * order. 55234642Smarc */ 55330391Skarels 55430391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 55530391Skarels 55634642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */ 55734642Smarc /* ..take another vector */ 55834642Smarc vector = (uba_hd[0].uh_lastiv -= 4); 55930391Skarels } 56030391Skarels 56134642Smarc /* 56234642Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 56334642Smarc */ 56430391Skarels dga = (struct dga *) qdmap[unit].dga; 56534642Smarc dga->csr = (short) HALT; /* disable everything */ 56634642Smarc dga->ivr = (short) vector; /* load intrpt base vector */ 56734642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 56830391Skarels dga->bytcnt_hi = (short) 0; 56930391Skarels 57034642Smarc /* 57134642Smarc * turn on DMA interrupts 57234642Smarc */ 57330391Skarels dga->csr &= ~SET_DONE_FIFO; 57430391Skarels dga->csr |= DMA_IE | DL_ENB; 57530391Skarels 57630391Skarels DELAY(20000); /* wait for the intrpt */ 57730391Skarels dga->csr = HALT; /* stop the wheels */ 57830391Skarels 57930391Skarels if (cvec != vector) /* if vector != base vector.. */ 58034732Smarc return(0); /* ..return = 'no device' */ 58130391Skarels 58234615Smarc /* 58334642Smarc * score this as an existing qdss 58434642Smarc */ 58534615Smarc qdcount++; 58634615Smarc 58730391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 58830391Skarels 58930391Skarels } /* qdprobe */ 59030391Skarels 59130391Skarels qdattach(ui) 59234642Smarc struct uba_device *ui; 59330391Skarels { 59434732Smarc register unit; /* QDSS module # for this call */ 59530391Skarels 59630391Skarels unit = ui->ui_unit; /* get QDSS number */ 59730391Skarels 59834642Smarc /* 59934642Smarc * init "qdflags[]" for this QDSS 60034642Smarc */ 60130391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 60230391Skarels qdflags[unit].mapped = 0; 60334615Smarc qdflags[unit].kernel_loop = -1; 60430391Skarels qdflags[unit].user_dma = 0; 60530391Skarels qdflags[unit].curs_acc = ACC_OFF; 60630391Skarels qdflags[unit].curs_thr = 128; 60730391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 60830391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 60930391Skarels qdflags[unit].adder_ie = 0; 61030391Skarels 61134642Smarc /* 61234642Smarc * init structures used in kbd/mouse interrupt service. This code must 61334642Smarc * come after the "init_shared()" routine has run since that routine 61434642Smarc * inits the eq_header[unit] structure used here. 61534642Smarc */ 61630391Skarels 61734642Smarc /* 61834642Smarc * init the "latest mouse report" structure 61934642Smarc */ 62030391Skarels last_rep[unit].state = 0; 62130391Skarels last_rep[unit].dx = 0; 62230391Skarels last_rep[unit].dy = 0; 62330391Skarels last_rep[unit].bytcnt = 0; 62430391Skarels 62534642Smarc /* 62634732Smarc * init the event queue (except mouse position) 62734732Smarc */ 62834732Smarc eq_header[unit]->header.events = 62934732Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 63030391Skarels 63130391Skarels eq_header[unit]->header.size = MAXEVENTS; 63230391Skarels eq_header[unit]->header.head = 0; 63330391Skarels eq_header[unit]->header.tail = 0; 63430391Skarels 63534642Smarc /* 63634642Smarc * open exclusive for graphics device. 63734642Smarc */ 63834642Smarc qdopened[unit] = 0; 63930391Skarels 64030391Skarels } /* qdattach */ 64130391Skarels 64234732Smarc /*ARGSUSED*/ 64330391Skarels qdopen(dev, flag) 64434642Smarc dev_t dev; 64534642Smarc int flag; 64630391Skarels { 64730391Skarels register struct uba_device *ui; /* ptr to uba structures */ 64830391Skarels register struct dga *dga; /* ptr to gate array struct */ 64930391Skarels register struct tty *tp; 65030391Skarels struct duart *duart; 65134732Smarc int unit; 65234732Smarc int minor_dev; 65330391Skarels 65430391Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 65530391Skarels unit = minor_dev >> 2; 65630391Skarels 65734642Smarc /* 65834642Smarc * check for illegal conditions 65934642Smarc */ 66030391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 66130391Skarels if (ui == 0 || ui->ui_alive == 0) 66234642Smarc return(ENXIO); /* no such device or address */ 66330391Skarels 66430391Skarels duart = (struct duart *) qdmap[unit].duart; 66530391Skarels dga = (struct dga *) qdmap[unit].dga; 66630391Skarels 66730391Skarels if ((minor_dev & 0x03) == 2) { 66834642Smarc /* 66934642Smarc * this is the graphic device... 67034642Smarc */ 67134642Smarc if (qdopened[unit] != 0) 67234732Smarc return(EBUSY); 67334642Smarc else 67434642Smarc qdopened[unit] = 1; 67534642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 67634642Smarc /* 67734642Smarc * enble kbd & mouse intrpts in DUART mask reg 67834642Smarc */ 67934642Smarc qdflags[unit].duart_imask |= 0x22; 68034642Smarc duart->imask = qdflags[unit].duart_imask; 68134642Smarc } else { 68234642Smarc /* 68334642Smarc * this is the console 68434642Smarc */ 68534642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 68634642Smarc dga->csr |= CURS_ENB; 68734642Smarc qdflags[unit].duart_imask |= 0x02; 68834642Smarc duart->imask = qdflags[unit].duart_imask; 68934642Smarc /* 69034642Smarc * some setup for tty handling 69134642Smarc */ 69234642Smarc tp = &qd_tty[minor_dev]; 69334642Smarc tp->t_addr = ui->ui_addr; 69434642Smarc tp->t_oproc = qdstart; 69534642Smarc if ((tp->t_state & TS_ISOPEN) == 0) { 69634642Smarc ttychars(tp); 69734642Smarc tp->t_flags = IFLAGS; 69834642Smarc tp->t_ispeed = B9600; 69934642Smarc tp->t_ospeed = B9600; 70034642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 70134642Smarc #ifdef POSIXTTY 70234642Smarc tp->t_iflag = TTYDEF_IFLAG; 70334642Smarc tp->t_oflag = TTYDEF_OFLAG; 70434642Smarc tp->t_lflag = TTYDEF_LFLAG; 70534642Smarc tp->t_cflag = TTYDEF_CFLAG; 70634642Smarc #endif 70732012Smarc } 70834642Smarc /* 70934642Smarc * enable intrpts, open line discipline 71034642Smarc */ 71134642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 71234642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp)); 71330391Skarels } 71430391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 71530391Skarels return(0); 71630391Skarels 71730391Skarels } /* qdopen */ 71830391Skarels 71934732Smarc /*ARGSUSED*/ 72030391Skarels qdclose(dev, flag) 72134642Smarc dev_t dev; 72234642Smarc int flag; 72330391Skarels { 72430391Skarels register struct tty *tp; 72530391Skarels register struct qdmap *qd; 72630391Skarels register int *ptep; 72730391Skarels struct dga *dga; /* gate array register map pointer */ 72830391Skarels struct duart *duart; 72930391Skarels struct adder *adder; 73034732Smarc int unit; 73134732Smarc int minor_dev; 73230391Skarels u_int mapix; 73334642Smarc int i; /* SIGNED index */ 73430391Skarels 73530391Skarels minor_dev = minor(dev); /* get minor device number */ 73630391Skarels unit = minor_dev >> 2; /* get QDSS number */ 73730391Skarels qd = &qdmap[unit]; 73830391Skarels 73930391Skarels if ((minor_dev & 0x03) == 2) { 74034642Smarc /* 74134642Smarc * this is the graphic device... 74234642Smarc */ 74334642Smarc if (qdopened[unit] != 1) 74434732Smarc return(EBUSY); 74534642Smarc else 74634642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 74734642Smarc /* 74834642Smarc * re-protect device memory 74934642Smarc */ 75034642Smarc if (qdflags[unit].mapped & MAPDEV) { 75134642Smarc /* 75234642Smarc * TEMPLATE RAM 75334642Smarc */ 75434642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 75534642Smarc ptep = (int *)(QVmap[0] + mapix); 75634732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 75734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 75834642Smarc /* 75934642Smarc * ADDER 76034642Smarc */ 76134642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 76234642Smarc ptep = (int *)(QVmap[0] + mapix); 76334732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 76434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76534642Smarc /* 76634642Smarc * COLOR MAPS 76734642Smarc */ 76834642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 76934642Smarc ptep = (int *)(QVmap[0] + mapix); 77034732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 77134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 77234642Smarc } 77334615Smarc 77434642Smarc /* 77534642Smarc * re-protect DMA buffer and free the map registers 77634642Smarc */ 77734642Smarc if (qdflags[unit].mapped & MAPDMA) { 77834642Smarc dga = (struct dga *) qdmap[unit].dga; 77934642Smarc adder = (struct adder *) qdmap[unit].adder; 78034642Smarc dga->csr &= ~DMA_IE; 78134642Smarc dga->csr &= ~0x0600; /* kill DMA */ 78234642Smarc adder->command = CANCEL; 78334642Smarc /* 78434642Smarc * if DMA was running, flush spurious intrpt 78534642Smarc */ 78634642Smarc if (dga->bytcnt_lo != 0) { 78734642Smarc dga->bytcnt_lo = 0; 78834642Smarc dga->bytcnt_hi = 0; 78934642Smarc DMA_SETIGNORE(DMAheader[unit]); 79034642Smarc dga->csr |= DMA_IE; 79134642Smarc dga->csr &= ~DMA_IE; 79234642Smarc } 79334642Smarc ptep = (int *) 79434642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 79534732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 79634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 79734642Smarc ubarelse(0, &Qbus_unmap[unit]); 79834642Smarc } 79934615Smarc 80034642Smarc /* 80134642Smarc * re-protect 1K (2 pages) event queue 80234642Smarc */ 80334642Smarc if (qdflags[unit].mapped & MAPEQ) { 80434642Smarc ptep = (int *) 80534642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 80634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 80734642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 80830391Skarels } 80934642Smarc /* 81034642Smarc * re-protect scroll param area and disable scroll intrpts 81134642Smarc */ 81234642Smarc if (qdflags[unit].mapped & MAPSCR) { 81334642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 81434642Smarc + (mfpr(SBR) | 0x80000000)); 81534642Smarc /* 81634642Smarc * re-protect 512 scroll param area 81734642Smarc */ 81834642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 81934642Smarc adder = (struct adder *) qdmap[unit].adder; 82034642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 82134642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 82234642Smarc } 82334642Smarc /* 82434642Smarc * re-protect color map write buffer area and kill intrpts 82534642Smarc */ 82634642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 82734642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 82834642Smarc + (mfpr(SBR) | 0x80000000)); 82934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 83034642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 83134642Smarc color_buf[unit]->status = 0; 83234642Smarc adder = (struct adder *) qdmap[unit].adder; 83334642Smarc qdflags[unit].adder_ie &= ~VSYNC; 83434642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 83534642Smarc } 83634642Smarc mtpr(TBIA, 0); 83734642Smarc /* flag everything now unmapped */ 83834642Smarc qdflags[unit].mapped = 0; 83934642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 84034642Smarc qdflags[unit].curs_acc = ACC_OFF; 84134642Smarc qdflags[unit].curs_thr = 128; 84234642Smarc /* 84334642Smarc * restore the console 84434642Smarc */ 84530391Skarels dga = (struct dga *) qdmap[unit].dga; 84630391Skarels adder = (struct adder *) qdmap[unit].adder; 84730391Skarels dga->csr &= ~DMA_IE; 84830391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 84930391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 85030391Skarels adder->command = CANCEL; 85134642Smarc /* 85234642Smarc * if DMA was running, flush spurious intrpt 85334642Smarc */ 85430391Skarels if (dga->bytcnt_lo != 0) { 85534642Smarc dga->bytcnt_lo = 0; 85634642Smarc dga->bytcnt_hi = 0; 85734642Smarc DMA_SETIGNORE(DMAheader[unit]); 85834642Smarc dga->csr |= DMA_IE; 85934642Smarc dga->csr &= ~DMA_IE; 86030391Skarels } 86130391Skarels init_shared(unit); /* init shared memory */ 86230391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 86330391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 86430391Skarels setup_input(unit); /* init the DUART */ 86530391Skarels ldfont(unit); 86630391Skarels cursor[unit].x = 0; 86730391Skarels cursor[unit].y = 0; 86834642Smarc /* 86934642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 87034642Smarc */ 87134642Smarc duart = (struct duart *) qdmap[unit].duart; 87234642Smarc qdflags[unit].duart_imask &= ~(0x20); 87334642Smarc qdflags[unit].duart_imask |= 0x02; 87434642Smarc duart->imask = qdflags[unit].duart_imask; 87534642Smarc /* 87634642Smarc * shut off interrupts if all is closed 87734642Smarc */ 87834642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 87934642Smarc dga = (struct dga *) qdmap[unit].dga; 88034642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 88134642Smarc } 88234642Smarc } else { 88334642Smarc /* 88434642Smarc * this is the console 88534642Smarc */ 88634642Smarc tp = &qd_tty[minor_dev]; 88734642Smarc (*linesw[tp->t_line].l_close)(tp); 88834642Smarc ttyclose(tp); 88934642Smarc tp->t_state = 0; 89034642Smarc qdflags[unit].inuse &= ~CONS_DEV; 89134642Smarc /* 89234642Smarc * if graphics device is closed, kill interrupts 89334642Smarc */ 89434642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 89534642Smarc dga = (struct dga *) qdmap[unit].dga; 89634642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 89734642Smarc } 89830391Skarels } 89934615Smarc 90030391Skarels return(0); 90130391Skarels 90230391Skarels } /* qdclose */ 90330391Skarels 90430391Skarels qdioctl(dev, cmd, datap, flags) 90534642Smarc dev_t dev; 90634642Smarc int cmd; 90734732Smarc register caddr_t datap; 90834642Smarc int flags; 90930391Skarels { 91030391Skarels register int *ptep; /* page table entry pointer */ 91132012Smarc register int mapix; /* QVmap[] page table index */ 91230391Skarels register struct _vs_event *event; 91330391Skarels register struct tty *tp; 91434732Smarc register i; 91530391Skarels struct qdmap *qd; /* pointer to device map struct */ 91630391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 91730391Skarels struct duart *duart; /* DUART reg structure pointer */ 91830391Skarels struct adder *adder; /* ADDER reg structure pointer */ 91930391Skarels struct prgkbd *cmdbuf; 92030391Skarels struct prg_cursor *curs; 92130391Skarels struct _vs_cursor *pos; 92234732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 92330391Skarels u_int minor_dev = minor(dev); 92430391Skarels int error; 92530391Skarels int s; 92630391Skarels short *temp; /* a pointer to template RAM */ 92730391Skarels 92834642Smarc /* 92934642Smarc * service graphic device ioctl commands 93034642Smarc */ 93130391Skarels switch (cmd) { 93234615Smarc 93334642Smarc case QD_GETEVENT: 93434642Smarc /* 93534642Smarc * extract the oldest event from the event queue 93634642Smarc */ 93730391Skarels if (ISEMPTY(eq_header[unit])) { 93834642Smarc event = (struct _vs_event *) datap; 93934642Smarc event->vse_device = VSE_NULL; 94034642Smarc break; 94130391Skarels } 94230391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 94334615Smarc s = spl5(); 94430391Skarels GETEND(eq_header[unit]); 94530391Skarels splx(s); 94634732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 94730391Skarels break; 94830391Skarels 94934642Smarc case QD_RESET: 95034642Smarc /* 95134642Smarc * init the dragon stuff, DUART, and driver variables 95234642Smarc */ 95330391Skarels init_shared(unit); /* init shared memory */ 95430391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 95530391Skarels clear_qd_screen(unit); 95630391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 95730391Skarels ldfont(unit); /* load the console font */ 95830391Skarels setup_input(unit); /* init the DUART */ 95930391Skarels break; 96030391Skarels 96134642Smarc case QD_SET: 96234642Smarc /* 96334642Smarc * init the DUART and driver variables 96434642Smarc */ 96530391Skarels init_shared(unit); 96630391Skarels setup_input(unit); 96730391Skarels break; 96830391Skarels 96934642Smarc case QD_CLRSCRN: 97034642Smarc /* 97134642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 97234642Smarc */ 97334732Smarc #ifdef notdef /* has caused problems and isn't necessary */ 97430391Skarels setup_dragon(unit); 97530391Skarels clear_qd_screen(unit); 97634615Smarc #endif 97730391Skarels break; 97830391Skarels 97934642Smarc case QD_WTCURSOR: 98034642Smarc /* 98134642Smarc * load a cursor into template RAM 98234642Smarc */ 98334732Smarc ldcursor(unit, (short *)datap); 98430391Skarels break; 98530391Skarels 98634642Smarc case QD_RDCURSOR: 98730391Skarels 98830391Skarels temp = (short *) qdmap[unit].template; 98934642Smarc /* 99034642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 99134642Smarc * ...template space 99234642Smarc */ 99330391Skarels temp += (8 * 1024) - 32; 99430391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 99534642Smarc *(short *)datap = *temp++; 99630391Skarels break; 99730391Skarels 99834642Smarc case QD_POSCURSOR: 99934642Smarc /* 100034642Smarc * position the mouse cursor 100134642Smarc */ 100230391Skarels dga = (struct dga *) qdmap[unit].dga; 100330391Skarels pos = (struct _vs_cursor *) datap; 100434615Smarc s = spl5(); 100530391Skarels dga->x_cursor = TRANX(pos->x); 100630391Skarels dga->y_cursor = TRANY(pos->y); 100730391Skarels eq_header[unit]->curs_pos.x = pos->x; 100830391Skarels eq_header[unit]->curs_pos.y = pos->y; 100930391Skarels splx(s); 101030391Skarels break; 101130391Skarels 101234642Smarc case QD_PRGCURSOR: 101334642Smarc /* 101434642Smarc * set the cursor acceleration factor 101534642Smarc */ 101630391Skarels curs = (struct prg_cursor *) datap; 101734615Smarc s = spl5(); 101830391Skarels qdflags[unit].curs_acc = curs->acc_factor; 101930391Skarels qdflags[unit].curs_thr = curs->threshold; 102030391Skarels splx(s); 102130391Skarels break; 102230391Skarels 102334642Smarc case QD_MAPDEVICE: 102434642Smarc /* 102534642Smarc * enable 'user write' to device pages 102634642Smarc */ 102730391Skarels qdflags[unit].mapped |= MAPDEV; 102830391Skarels qd = (struct qdmap *) &qdmap[unit]; 102934642Smarc /* 103034642Smarc * enable user write to template RAM 103134642Smarc */ 103232012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 103332012Smarc ptep = (int *)(QVmap[0] + mapix); 103434732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 103534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103634642Smarc /* 103734642Smarc * enable user write to registers 103834642Smarc */ 103932012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 104032012Smarc ptep = (int *)(QVmap[0] + mapix); 104134732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 104234732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104334642Smarc /* 104434642Smarc * enable user write to color maps 104534642Smarc */ 104632012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 104732012Smarc ptep = (int *)(QVmap[0] + mapix); 104834732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 104934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 105034642Smarc /* 105134642Smarc * enable user write to DUART 105234642Smarc */ 105332012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 105432012Smarc ptep = (int *)(QVmap[0] + mapix); 105530391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 105630391Skarels 105734732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 105830391Skarels 105934642Smarc /* 106034732Smarc * stuff qdmap structure in return buffer 106134732Smarc */ 106234732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 106330391Skarels break; 106430391Skarels 106534642Smarc case QD_MAPIOBUF: 106634642Smarc /* 106734642Smarc * do setup for DMA by user process 106834642Smarc * 106934642Smarc * set 'user write enable' bits for DMA buffer 107034642Smarc */ 107130391Skarels qdflags[unit].mapped |= MAPDMA; 107230391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 107334642Smarc + (mfpr(SBR) | 0x80000000)); 107434732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 107534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 107634732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 107734642Smarc /* 107834642Smarc * set up QBUS map registers for DMA 107934642Smarc */ 108030391Skarels DMAheader[unit]->QBAreg = 108134732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 108230391Skarels if (DMAheader[unit]->QBAreg == 0) 108334732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 108430391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 108530391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 108634642Smarc /* 108734642Smarc * return I/O buf adr 108834642Smarc */ 108930391Skarels *(int *)datap = (int) DMAheader[unit]; 109030391Skarels break; 109130391Skarels 109234642Smarc case QD_MAPSCROLL: 109334642Smarc /* 109434642Smarc * map the shared scroll param area and enable scroll interpts 109534642Smarc */ 109630391Skarels qdflags[unit].mapped |= MAPSCR; 109730391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 109834642Smarc + (mfpr(SBR) | 0x80000000)); 109934642Smarc /* 110034642Smarc * allow user write to scroll area 110134642Smarc */ 110230391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 110334732Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 110430391Skarels scroll[unit]->status = 0; 110530391Skarels adder = (struct adder *) qdmap[unit].adder; 110630391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 110730391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 110834642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 110930391Skarels break; 111030391Skarels 111134642Smarc case QD_UNMAPSCROLL: 111234642Smarc /* 111334642Smarc * unmap shared scroll param area and disable scroll intrpts 111434642Smarc */ 111530391Skarels if (qdflags[unit].mapped & MAPSCR) { 111634642Smarc qdflags[unit].mapped &= ~MAPSCR; 111734642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 111834642Smarc + (mfpr(SBR) | 0x80000000)); 111934642Smarc /* 112034642Smarc * re-protect 512 scroll param area 112134642Smarc */ 112234642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 112334642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 112434642Smarc adder = (struct adder *) qdmap[unit].adder; 112534642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 112634642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 112730391Skarels } 112830391Skarels break; 112930391Skarels 113034642Smarc case QD_MAPCOLOR: 113134642Smarc /* 113234642Smarc * map shared color map write buf and turn on vsync intrpt 113334642Smarc */ 113430391Skarels qdflags[unit].mapped |= MAPCOLOR; 113530391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 113634642Smarc + (mfpr(SBR) | 0x80000000)); 113734732Smarc /* 113834732Smarc * allow user write to color map write buffer 113934732Smarc */ 114034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 114130391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 114230391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 114334642Smarc adder = (struct adder *) qdmap[unit].adder; 114430391Skarels qdflags[unit].adder_ie |= VSYNC; 114530391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 114634732Smarc /* 114734732Smarc * return color area address 114834732Smarc */ 114930391Skarels *(int *)datap = (int) color_buf[unit]; 115030391Skarels break; 115130391Skarels 115234642Smarc case QD_UNMAPCOLOR: 115334642Smarc /* 115434732Smarc * unmap shared color map write buffer and kill VSYNC intrpts 115534732Smarc */ 115630391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 115734642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 115834642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 115934642Smarc + (mfpr(SBR) | 0x80000000)); 116034732Smarc /* 116134732Smarc * re-protect color map write buffer 116234732Smarc */ 116334732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 116434642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 116534732Smarc mtpr(TBIA, 0); 116634642Smarc adder = (struct adder *) qdmap[unit].adder; 116734642Smarc qdflags[unit].adder_ie &= ~VSYNC; 116834642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 116930391Skarels } 117030391Skarels break; 117130391Skarels 117234642Smarc case QD_MAPEVENT: 117334642Smarc /* 117434642Smarc * give user write access to the event queue 117534642Smarc */ 117630391Skarels qdflags[unit].mapped |= MAPEQ; 117730391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 117834642Smarc + (mfpr(SBR) | 0x80000000)); 117934732Smarc /* 118034732Smarc * allow user write to 1K event queue 118134732Smarc */ 118234732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 118330391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 118430391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 118534732Smarc /* 118634732Smarc * return event queue address 118734732Smarc */ 118834732Smarc *(int *)datap = (int)eq_header[unit]; 118930391Skarels break; 119030391Skarels 119134642Smarc case QD_PRGKBD: 119234642Smarc /* 119334642Smarc * pass caller's programming commands to LK201 119434642Smarc */ 119534732Smarc duart = (struct duart *)qdmap[unit].duart; 119634732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 119734642Smarc /* 119834642Smarc * send command 119934642Smarc */ 120030391Skarels for (i = 1000; i > 0; --i) { 120134732Smarc if (duart->statusA&XMT_RDY) { 120234642Smarc duart->dataA = cmdbuf->cmd; 120334642Smarc break; 120434642Smarc } 120530391Skarels } 120630391Skarels if (i == 0) { 120734732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 120834642Smarc break; 120930391Skarels } 121034642Smarc /* 121134642Smarc * send param1? 121234642Smarc */ 121330391Skarels if (cmdbuf->cmd & LAST_PARAM) 121434642Smarc break; 121530391Skarels for (i = 1000; i > 0; --i) { 121634732Smarc if (duart->statusA&XMT_RDY) { 121734642Smarc duart->dataA = cmdbuf->param1; 121834642Smarc break; 121934642Smarc } 122030391Skarels } 122130391Skarels if (i == 0) { 122234732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 122334642Smarc break; 122430391Skarels } 122534642Smarc /* 122634642Smarc * send param2? 122734642Smarc */ 122830391Skarels if (cmdbuf->param1 & LAST_PARAM) 122930391Skarels break; 123030391Skarels for (i = 1000; i > 0; --i) { 123134732Smarc if (duart->statusA&XMT_RDY) { 123234642Smarc duart->dataA = cmdbuf->param2; 123334642Smarc break; 123434642Smarc } 123530391Skarels } 123630391Skarels if (i == 0) { 123734732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 123834642Smarc break; 123930391Skarels } 124030391Skarels break; 124130391Skarels 124234642Smarc case QD_PRGMOUSE: 124334642Smarc /* 124434642Smarc * pass caller's programming commands to the mouse 124534642Smarc */ 124630391Skarels duart = (struct duart *) qdmap[unit].duart; 124730391Skarels for (i = 1000; i > 0; --i) { 124834732Smarc if (duart->statusB&XMT_RDY) { 124934642Smarc duart->dataB = *datap; 125034642Smarc break; 125134642Smarc } 125230391Skarels } 125330391Skarels if (i == 0) { 125434732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 125530391Skarels } 125630391Skarels break; 125730391Skarels 125834642Smarc case QD_RDCONFIG: 125934642Smarc /* 126034642Smarc * get QDSS configuration word and return it 126134642Smarc */ 126230391Skarels *(short *)datap = qdflags[unit].config; 126330391Skarels break; 126430391Skarels 126534642Smarc case QD_KERN_LOOP: 126634642Smarc case QD_KERN_UNLOOP: 126734642Smarc /* 126834642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 126934642Smarc * kernel console output. 127034642Smarc */ 127134615Smarc break; 127234615Smarc 127334642Smarc case QD_PRGTABLET: 127434642Smarc /* 127534642Smarc * program the tablet 127634642Smarc */ 127730391Skarels duart = (struct duart *) qdmap[unit].duart; 127830391Skarels for (i = 1000; i > 0; --i) { 127934732Smarc if (duart->statusB&XMT_RDY) { 128034642Smarc duart->dataB = *datap; 128134642Smarc break; 128234642Smarc } 128330391Skarels } 128430391Skarels if (i == 0) { 128534732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 128630391Skarels } 128730391Skarels break; 128830391Skarels 128934642Smarc case QD_PRGTABRES: 129034642Smarc /* 129134642Smarc * program the tablet report resolution factor 129234642Smarc */ 129330391Skarels qdflags[unit].tab_res = *(short *)datap; 129430391Skarels break; 129530391Skarels 129634642Smarc default: 129734642Smarc /* 129834642Smarc * service tty ioctl's 129934642Smarc */ 130034642Smarc if (!(minor_dev & 0x02)) { 130130391Skarels tp = &qd_tty[minor_dev]; 130234642Smarc error = 130334642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 130430391Skarels if (error >= 0) { 130534642Smarc return(error); 130630391Skarels } 130730391Skarels error = ttioctl(tp, cmd, datap, flags); 130830391Skarels if (error >= 0) { 130934642Smarc return(error); 131030391Skarels } 131134642Smarc } 131234642Smarc break; 131330391Skarels } 131430391Skarels 131530391Skarels return(0); 131630391Skarels 131730391Skarels } /* qdioctl */ 131830391Skarels 131930391Skarels qdselect(dev, rw) 132034642Smarc dev_t dev; 132134642Smarc int rw; 132230391Skarels { 132334732Smarc register s; 132434732Smarc register unit; 132534615Smarc register struct tty *tp; 132634615Smarc u_int minor_dev = minor(dev); 132730391Skarels 132834615Smarc s = spl5(); 132934615Smarc unit = minor_dev >> 2; 133030391Skarels 133130391Skarels switch (rw) { 133234642Smarc case FREAD: 133334642Smarc if ((minor_dev & 0x03) == 2) { 133434642Smarc /* 133534642Smarc * this is a graphics device, so check for events 133634642Smarc */ 133734732Smarc if(!(ISEMPTY(eq_header[unit]))) { 133834642Smarc splx(s); 133934642Smarc return(1); 134034642Smarc } 134134732Smarc qdrsel[unit] = u.u_procp; 134234642Smarc qdflags[unit].selmask |= SEL_READ; 134334642Smarc splx(s); 134434642Smarc return(0); 134534642Smarc } else { 134634642Smarc /* 134734642Smarc * this is a tty device 134834642Smarc */ 134934642Smarc tp = &qd_tty[minor_dev]; 135034642Smarc if (ttnread(tp)) 135134642Smarc return(1); 135234642Smarc tp->t_rsel = u.u_procp; 135334642Smarc splx(s); 135434642Smarc return(0); 135530391Skarels } 135630391Skarels 135734642Smarc case FWRITE: 135834642Smarc if ((minor(dev) & 0x03) == 2) { 135934642Smarc /* 136034642Smarc * this is a graphics device, so check for dma buffers 136134642Smarc */ 136234642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 136334642Smarc { 136434642Smarc splx(s); 136534642Smarc return(1); 136634642Smarc } 136734732Smarc qdrsel[unit] = u.u_procp; 136834642Smarc qdflags[unit].selmask |= SEL_WRITE; 136934642Smarc splx(s); 137034642Smarc return(0); 137134642Smarc } else { 137234642Smarc /* 137334642Smarc * this is a tty device 137434642Smarc */ 137534642Smarc tp = &qd_tty[minor_dev]; 137634642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) 137734642Smarc return(1); 137834642Smarc tp->t_wsel = u.u_procp; 137934642Smarc splx(s); 138034642Smarc return(0); 138130391Skarels } 138230391Skarels } 138334732Smarc splx(s); 138434732Smarc return(0); 138530391Skarels 138630391Skarels } /* qdselect() */ 138730391Skarels 138830391Skarels extern qd_strategy(); 138930391Skarels 139030391Skarels qdwrite(dev, uio) 139134642Smarc dev_t dev; 139234642Smarc struct uio *uio; 139330391Skarels { 139430391Skarels register struct tty *tp; 139534732Smarc register minor_dev; 139634732Smarc register unit; 139730391Skarels 139830391Skarels minor_dev = minor(dev); 139930391Skarels unit = (minor_dev >> 2) & 0x07; 140030391Skarels 140134642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 140234642Smarc /* 140334642Smarc * this is the console... 140434642Smarc */ 140534642Smarc tp = &qd_tty[minor_dev]; 140634642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 140734642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 140834642Smarc /* 140934642Smarc * this is a DMA xfer from user space 141034642Smarc */ 141134642Smarc return (physio(qd_strategy, &qdbuf[unit], 141234642Smarc dev, B_WRITE, minphys, uio)); 141330391Skarels } 141434732Smarc return (ENXIO); 141530391Skarels } 141630391Skarels 141730391Skarels qdread(dev, uio) 141834642Smarc dev_t dev; 141934642Smarc struct uio *uio; 142030391Skarels { 142130391Skarels register struct tty *tp; 142234732Smarc register minor_dev; 142334732Smarc register unit; 142430391Skarels 142530391Skarels minor_dev = minor(dev); 142630391Skarels unit = (minor_dev >> 2) & 0x07; 142730391Skarels 142834642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 142934642Smarc /* 143034642Smarc * this is the console 143134642Smarc */ 143234642Smarc tp = &qd_tty[minor_dev]; 143334642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 143434642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 143534642Smarc /* 143634642Smarc * this is a bitmap-to-processor xfer 143734642Smarc */ 143834642Smarc return (physio(qd_strategy, &qdbuf[unit], 143934642Smarc dev, B_READ, minphys, uio)); 144030391Skarels } 144134732Smarc return (ENXIO); 144230391Skarels } 144330391Skarels 144430391Skarels /*************************************************************** 144530391Skarels * 144630391Skarels * qd_strategy()... strategy routine to do DMA 144730391Skarels * 144830391Skarels ***************************************************************/ 144930391Skarels 145030391Skarels qd_strategy(bp) 145134642Smarc register struct buf *bp; 145230391Skarels { 145330391Skarels register struct dga *dga; 145430391Skarels register struct adder *adder; 145534732Smarc register unit; 145630391Skarels int QBAreg; 145730391Skarels int s; 145830391Skarels int cookie; 145930391Skarels 146030391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 146130391Skarels 146234642Smarc /* 146334642Smarc * init pointers 146434642Smarc */ 146530391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 146634732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 146734642Smarc goto STRAT_ERR; 146830391Skarels } 146930391Skarels dga = (struct dga *) qdmap[unit].dga; 147034615Smarc s = spl5(); 147130391Skarels qdflags[unit].user_dma = -1; 147230391Skarels dga->csr |= DMA_IE; 147330391Skarels cookie = QBAreg & 0x3FFFF; 147430391Skarels dga->adrs_lo = (short) cookie; 147530391Skarels dga->adrs_hi = (short) (cookie >> 16); 147630391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 147730391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 147830391Skarels 147930391Skarels while (qdflags[unit].user_dma) { 148034642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 148130391Skarels } 148230391Skarels splx(s); 148330391Skarels ubarelse(0, &QBAreg); 148430391Skarels if (!(dga->csr & DMA_ERR)) { 148534642Smarc iodone(bp); 148634642Smarc return; 148730391Skarels } 148830391Skarels 148930391Skarels STRAT_ERR: 149030391Skarels adder = (struct adder *) qdmap[unit].adder; 149134642Smarc adder->command = CANCEL; /* cancel adder activity */ 149230391Skarels dga->csr &= ~DMA_IE; 149330391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 149430391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 149530391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 149630391Skarels 149734642Smarc /* 149834642Smarc * if DMA was running, flush spurious intrpt 149934642Smarc */ 150030391Skarels if (dga->bytcnt_lo != 0) { 150134642Smarc dga->bytcnt_lo = 0; 150234642Smarc dga->bytcnt_hi = 0; 150334642Smarc DMA_SETIGNORE(DMAheader[unit]); 150434642Smarc dga->csr |= DMA_IE; 150530391Skarels } 150630391Skarels iodone(bp); 150730391Skarels 150830391Skarels } /* qd_strategy */ 150930391Skarels 151034732Smarc /* 151134732Smarc * Start output to the console screen 151234732Smarc */ 151330391Skarels qdstart(tp) 151434642Smarc register struct tty *tp; 151530391Skarels { 151634732Smarc register which_unit, unit, c; 151730391Skarels int s; 151834615Smarc 151930391Skarels unit = minor(tp->t_dev); 152030391Skarels which_unit = (unit >> 2) & 0x3; 152134615Smarc unit &= 0x03; 152230391Skarels 152334615Smarc s = spl5(); 152434615Smarc 152534642Smarc /* 152634642Smarc * If it's currently active, or delaying, no need to do anything. 152734642Smarc */ 152830391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 152930391Skarels goto out; 153030391Skarels 153134642Smarc /* 153234642Smarc * Display chars until the queue is empty. 153334642Smarc * Drop input from anything but the console 153434642Smarc * device on the floor. 153534642Smarc * 153634642Smarc * XXX - this loop is done at spltty. 153734642Smarc * 153834642Smarc */ 153934642Smarc while (tp->t_outq.c_cc) { 154034511Smarc c = getc(&tp->t_outq); 154134615Smarc if (unit == 0) 154234732Smarc blitc(which_unit, (u_char)c); 154330391Skarels } 154434642Smarc /* 154534642Smarc * If there are sleepers, and output has drained below low 154634642Smarc * water mark, wake up the sleepers. 154734642Smarc */ 154834642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 154934615Smarc if (tp->t_state & TS_ASLEEP){ 155034615Smarc tp->t_state &= ~TS_ASLEEP; 155134615Smarc wakeup((caddr_t) &tp->t_outq); 155234615Smarc } 155330391Skarels } 155430391Skarels 155534615Smarc tp->t_state &= ~TS_BUSY; 155634615Smarc 155730391Skarels out: 155830391Skarels splx(s); 155930391Skarels 156030391Skarels } /* qdstart */ 156130391Skarels 156234732Smarc /*ARGSUSED*/ 156330391Skarels qdstop(tp, flag) 156434642Smarc register struct tty *tp; 156534642Smarc int flag; 156630391Skarels { 156730391Skarels register int s; 156830391Skarels 156934615Smarc s = spl5(); /* block intrpts during state modification */ 157034732Smarc if (tp->t_state & TS_BUSY) 157134732Smarc if ((tp->t_state & TS_TTSTOP) == 0) 157234642Smarc tp->t_state |= TS_FLUSH; 157334642Smarc else 157434642Smarc tp->t_state &= ~TS_BUSY; 157530391Skarels splx(s); 157630391Skarels } 157730391Skarels 157834732Smarc /* 157934732Smarc * Output a character to the QDSS screen 158034732Smarc */ 158130391Skarels 158230391Skarels blitc(unit, chr) 158334732Smarc register unit; 158434732Smarc register u_char chr; 158530391Skarels { 158630391Skarels register struct adder *adder; 158730391Skarels register struct dga *dga; 158830391Skarels register int i; 158934642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 159034642Smarc static short inescape[NQD]; 159130391Skarels 159234732Smarc adder = (struct adder *)qdmap[unit].adder; 159330391Skarels dga = (struct dga *) qdmap[unit].dga; 159434642Smarc /* 159534642Smarc * BSD comment: this (&=0177) defeats the extended character 159634642Smarc * set code for the glass tty, but if i had the time i would 159734642Smarc * spend it ripping out the code completely. This driver 159834642Smarc * is too big for its own good. 159934642Smarc */ 160034642Smarc chr &= 0177; 160134642Smarc /* 160234732Smarc * Cursor addressing (so vi will work). 160334642Smarc * Decode for "\E=%.%." cursor motion description. 160434732Smarc * Corresponds to type "qdcons" in /etc/termcap: 160534642Smarc * 160634642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 160734642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 160834642Smarc * 160934642Smarc */ 161034642Smarc if (inescape[unit] && nograph) { 161134642Smarc switch (inescape[unit]++) { 161234642Smarc case 1: 161334642Smarc if (chr != '=') { 161434642Smarc /* abort escape sequence */ 161534642Smarc inescape[unit] = 0; 161634642Smarc blitc(unit, chr); 161734642Smarc } 161834732Smarc return; 161934642Smarc case 2: 162034642Smarc /* position row */ 162134642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 162234642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 162334642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 162434642Smarc dga->y_cursor = TRANY(cursor[unit].y); 162534732Smarc return; 162634642Smarc case 3: 162734642Smarc /* position column */ 162834642Smarc cursor[unit].x = CHAR_WIDTH * chr; 162934642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 163034642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 163134642Smarc dga->x_cursor = TRANX(cursor[unit].x); 163234642Smarc inescape[unit] = 0; 163334732Smarc return; 163434642Smarc default: 163534642Smarc inescape[unit] = 0; 163634642Smarc blitc(unit, chr); 163734642Smarc } 163834642Smarc } 163930391Skarels 164030391Skarels switch (chr) { 164134642Smarc case '\r': /* return char */ 164230391Skarels cursor[unit].x = 0; 164334642Smarc if (nograph) 164434642Smarc dga->x_cursor = TRANX(cursor[unit].x); 164534732Smarc return; 164630391Skarels 164734642Smarc case '\t': /* tab char */ 164830391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 164934642Smarc blitc(unit, ' '); 165030391Skarels } 165134732Smarc return; 165230391Skarels 165334642Smarc case '\n': /* line feed char */ 165430391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 165534642Smarc if (nograph) { 165634642Smarc cursor[unit].y -= CHAR_HEIGHT; 165734642Smarc scroll_up(adder); 165834642Smarc } else 165934642Smarc cursor[unit].y = 0; 166030391Skarels } 166134642Smarc if (nograph) 166234642Smarc dga->y_cursor = TRANY(cursor[unit].y); 166334732Smarc return; 166430391Skarels 166534642Smarc case '\b': /* backspace char */ 166630391Skarels if (cursor[unit].x > 0) { 166734642Smarc cursor[unit].x -= CHAR_WIDTH; 166834642Smarc if (nograph) 166934642Smarc dga->x_cursor = TRANX(cursor[unit].x); 167030391Skarels } 167134732Smarc return; 167234642Smarc case CTRL('k'): /* cursor up */ 167334642Smarc if (nograph && cursor[unit].y > 0) { 167434642Smarc cursor[unit].y -= CHAR_HEIGHT; 167534642Smarc dga->y_cursor = TRANY(cursor[unit].y); 167634642Smarc } 167734732Smarc return; 167830391Skarels 167934642Smarc case CTRL('^'): /* home cursor */ 168034642Smarc if (nograph) { 168134642Smarc cursor[unit].x = 0; 168234642Smarc dga->x_cursor = TRANX(cursor[unit].x); 168334642Smarc cursor[unit].y = 0; 168434642Smarc dga->y_cursor = TRANY(cursor[unit].y); 168534642Smarc } 168634732Smarc return; 168732012Smarc 168834642Smarc case CTRL('l'): /* cursor right */ 168934642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 169034642Smarc cursor[unit].x += CHAR_WIDTH; 169134642Smarc dga->x_cursor = TRANX(cursor[unit].x); 169234642Smarc } 169334732Smarc return; 169430391Skarels 169534642Smarc case CTRL('z'): /* clear screen */ 169634642Smarc if (nograph) { 169734642Smarc setup_dragon(unit); 169834642Smarc clear_qd_screen(unit); 169934642Smarc /* home cursor - termcap seems to assume this */ 170034642Smarc cursor[unit].x = 0; 170134642Smarc dga->x_cursor = TRANX(cursor[unit].x); 170234642Smarc cursor[unit].y = 0; 170334642Smarc dga->y_cursor = TRANY(cursor[unit].y); 170434642Smarc } 170534732Smarc return; 170630391Skarels 170734642Smarc case '\033': /* start escape sequence */ 170834642Smarc if (nograph) 170934642Smarc inescape[unit] = 1; 171034732Smarc return; 171134642Smarc 171234642Smarc default: 171334642Smarc if ((chr < ' ') || (chr > '~')) 171434732Smarc return; 171534642Smarc } 171634642Smarc /* 171734642Smarc * setup VIPER operand control registers 171834642Smarc */ 171930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 172030391Skarels write_ID(adder, SRC1_OCR_B, 172134642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 172230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 172330391Skarels write_ID(adder, SRC1_OCR_B, 172434642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 172530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 172630391Skarels write_ID(adder, DST_OCR_B, 172734642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 172830391Skarels write_ID(adder, MASK_1, 0xFFFF); 172930391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 173030391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 173134642Smarc adder->x_clip_min = 0; 173234642Smarc adder->x_clip_max = 1024; 173334642Smarc adder->y_clip_min = 0; 173434642Smarc adder->y_clip_max = 864; 173534642Smarc /* 173634642Smarc * load DESTINATION origin and vectors 173734642Smarc */ 173830391Skarels adder->fast_dest_dy = 0; 173930391Skarels adder->slow_dest_dx = 0; 174030391Skarels adder->error_1 = 0; 174130391Skarels adder->error_2 = 0; 174230391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 174334732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 174430391Skarels adder->destination_x = cursor[unit].x; 174530391Skarels adder->fast_dest_dx = CHAR_WIDTH; 174630391Skarels adder->destination_y = cursor[unit].y; 174730391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 174834642Smarc /* 174934642Smarc * load SOURCE origin and vectors 175034642Smarc */ 175134615Smarc if ((chr - ' ') > (CHARS - 1)) { 175234615Smarc printf("Invalid character (x)%x in blitc\n",chr); 175334615Smarc chr = ' '; 175434615Smarc } 175534642Smarc /* 175634642Smarc * X position is modulo the number of characters per line 175734642Smarc */ 175834615Smarc adder->source_1_x = FONT_X + 175934642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 176034642Smarc /* 176134642Smarc * Point to either first or second row 176234642Smarc */ 176334615Smarc adder->source_1_y = 2048 - 15 * 176434642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 176530391Skarels adder->source_1_dx = CHAR_WIDTH; 176630391Skarels adder->source_1_dy = CHAR_HEIGHT; 176730391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 176830391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 176934642Smarc /* 177034642Smarc * update console cursor coordinates 177134642Smarc */ 177230391Skarels cursor[unit].x += CHAR_WIDTH; 177334642Smarc if (nograph) 177434642Smarc dga->x_cursor = TRANX(cursor[unit].x); 177530391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 177634642Smarc blitc(unit, '\r'); 177734642Smarc blitc(unit, '\n'); 177830391Skarels } 177930391Skarels 178030391Skarels } /* blitc */ 178130391Skarels 178234732Smarc qdreset() { } 178330391Skarels 178434732Smarc /* 178534732Smarc * INTERRUPT SERVICE ROUTINES 178634732Smarc */ 178730391Skarels 178834732Smarc /* 178934732Smarc * Service "DMA DONE" interrupt condition 179034732Smarc */ 179130391Skarels qddint(qd) 179234732Smarc register qd; 179330391Skarels { 179430391Skarels register struct DMAreq_header *header; 179530391Skarels register struct DMAreq *request; 179630391Skarels register struct dga *dga; 179730391Skarels struct adder *adder; 179830391Skarels int cookie; /* DMA adrs for QDSS */ 179930391Skarels 180034732Smarc (void)spl4(); /* allow interval timer in */ 180130391Skarels 180234642Smarc /* 180334642Smarc * init pointers 180434642Smarc */ 180530391Skarels header = DMAheader[qd]; /* register for optimization */ 180630391Skarels dga = (struct dga *) qdmap[qd].dga; 180730391Skarels adder = (struct adder *) qdmap[qd].adder; 180830391Skarels 180934642Smarc /* 181034642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 181134642Smarc */ 181230391Skarels if (DMA_ISIGNORE(header)) { 181334642Smarc DMA_CLRIGNORE(header); 181434642Smarc return; 181530391Skarels } 181630391Skarels 181734642Smarc /* 181834642Smarc * dump a DMA hardware error message if appropriate 181934642Smarc */ 182030391Skarels if (dga->csr & DMA_ERR) { 182130391Skarels 182234642Smarc if (dga->csr & PARITY_ERR) 182334732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 182430391Skarels 182534642Smarc if (dga->csr & BUS_ERR) 182634732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 182730391Skarels } 182830391Skarels 182934642Smarc /* 183034642Smarc * if this was a DMA from user space... 183134642Smarc */ 183230391Skarels if (qdflags[qd].user_dma) { 183334642Smarc qdflags[qd].user_dma = 0; 183434642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 183534642Smarc return; 183630391Skarels } 183730391Skarels 183834642Smarc /* 183934642Smarc * if we're doing DMA request queue services, field the error condition 184034642Smarc */ 184130391Skarels if (dga->csr & DMA_ERR) { 184230391Skarels 184334642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 184434642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 184534642Smarc adder->command = CANCEL; /* cancel adder activity */ 184630391Skarels 184734642Smarc DMA_SETERROR(header); /* flag error in header status word */ 184834642Smarc DMA_CLRACTIVE(header); 184934642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 185034642Smarc header->newest = header->oldest; 185134642Smarc header->used = 0; 185230391Skarels 185334732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 185434732Smarc selwakeup(qdrsel[qd], 0); 185534732Smarc qdrsel[qd] = 0; 185634642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 185734642Smarc } 185830391Skarels 185934642Smarc if (dga->bytcnt_lo != 0) { 186034642Smarc dga->bytcnt_lo = 0; 186134642Smarc dga->bytcnt_hi = 0; 186234642Smarc DMA_SETIGNORE(header); 186334642Smarc } 186434642Smarc return; 186530391Skarels } 186630391Skarels 186734642Smarc /* 186834642Smarc * if the DMA request queue is now becoming non-full, 186934642Smarc * wakeup "select" client. 187034642Smarc */ 187130391Skarels if (DMA_ISFULL(header)) { 187234732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 187334732Smarc selwakeup(qdrsel[qd], 0); 187434732Smarc qdrsel[qd] = 0; 187534642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 187634642Smarc } 187730391Skarels } 187830391Skarels 187930391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 188034642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 188130391Skarels 188234615Smarc /* check for unexpected interrupt */ 188334615Smarc if (DMA_ISEMPTY(header)) 188430391Skarels return; 188530391Skarels 188630391Skarels DMA_GETEND(header); /* update request queue indices */ 188730391Skarels 188834642Smarc /* 188934732Smarc * if no more DMA pending, wake up "select" client and exit 189034732Smarc */ 189130391Skarels if (DMA_ISEMPTY(header)) { 189230391Skarels 189334732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 189434732Smarc selwakeup(qdrsel[qd], 0); 189534732Smarc qdrsel[qd] = 0; 189634642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 189734642Smarc } 189830391Skarels 189934642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 190034642Smarc return; 190130391Skarels } 190230391Skarels 190334642Smarc /* 190434732Smarc * initiate next DMA xfer 190534732Smarc */ 190630391Skarels request = DMA_GETBEGIN(header); 190734615Smarc if (request->DMAtype != QDlast_DMAtype) { 190834642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 190934642Smarc adder->command = CANCEL; /* cancel adder activity */ 191034615Smarc } 191130391Skarels 191234615Smarc 191330391Skarels switch (request->DMAtype) { 191430391Skarels 191534642Smarc case DISPLIST: 191634615Smarc if (request->DMAtype != QDlast_DMAtype) { 191734615Smarc dga->csr |= DL_ENB; 191834615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 191934615Smarc } 192030391Skarels break; 192130391Skarels 192234642Smarc case PTOB: 192334615Smarc if (request->DMAtype != QDlast_DMAtype) { 192434615Smarc if (request->DMAdone & BYTE_PACK) 192534642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 192634615Smarc else { 192734615Smarc dga->csr |= PTOB_ENB; 192834615Smarc dga->csr &= ~BYTE_DMA; 192934615Smarc } 193034615Smarc } 193130391Skarels break; 193230391Skarels 193334642Smarc case BTOP: 193434615Smarc if (request->DMAtype != QDlast_DMAtype) { 193534615Smarc if (request->DMAdone & BYTE_PACK) { 193634615Smarc dga->csr &= ~DL_ENB; 193734615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 193834615Smarc } 193934615Smarc else { 194034615Smarc dga->csr |= BTOP_ENB; 194134615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 194234615Smarc } 194334615Smarc } 194430391Skarels break; 194534642Smarc default: 194634732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 194730391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 194830391Skarels return; 194930391Skarels } 195030391Skarels 195130391Skarels if (request->DMAdone & COUNT_ZERO) { 195234642Smarc dga->csr &= ~SET_DONE_FIFO; 195334642Smarc } 195434642Smarc else if (request->DMAdone & FIFO_EMPTY) { 195534642Smarc dga->csr |= SET_DONE_FIFO; 195630391Skarels } 195730391Skarels 195830391Skarels if (request->DMAdone & WORD_PACK) 195930391Skarels dga->csr &= ~BYTE_DMA; 196030391Skarels else if (request->DMAdone & BYTE_PACK) 196130391Skarels dga->csr |= BYTE_DMA; 196230391Skarels 196330391Skarels dga->csr |= DMA_IE; 196434642Smarc QDlast_DMAtype = request->DMAtype; 196530391Skarels 196630391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 196730391Skarels 196830391Skarels dga->adrs_lo = (short) cookie; 196930391Skarels dga->adrs_hi = (short) (cookie >> 16); 197030391Skarels 197130391Skarels dga->bytcnt_lo = (short) request->length; 197230391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 197330391Skarels 197430391Skarels return; 197530391Skarels } 197630391Skarels 197734732Smarc /* 197834732Smarc * ADDER interrupt service routine 197934732Smarc */ 198030391Skarels qdaint(qd) 198134732Smarc register qd; 198230391Skarels { 198330391Skarels register struct adder *adder; 198430391Skarels struct color_buf *cbuf; 198530391Skarels int i; 198630391Skarels register struct rgb *rgbp; 198730391Skarels register short *red; 198830391Skarels register short *green; 198930391Skarels register short *blue; 199030391Skarels 199134732Smarc (void)spl4(); /* allow interval timer in */ 199230391Skarels 199330391Skarels adder = (struct adder *) qdmap[qd].adder; 199430391Skarels 199534642Smarc /* 199634642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 199734642Smarc * any pending color map load request 199834642Smarc */ 199930391Skarels if (adder->status & VSYNC) { 200034642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 200134642Smarc cbuf = color_buf[qd]; 200234642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 200330391Skarels 200434642Smarc red = (short *) qdmap[qd].red; 200534642Smarc green = (short *) qdmap[qd].green; 200634642Smarc blue = (short *) qdmap[qd].blue; 200730391Skarels 200834642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 200934642Smarc --i >= 0; rgbp++) { 201034642Smarc red[rgbp->offset] = (short) rgbp->red; 201134642Smarc green[rgbp->offset] = (short) rgbp->green; 201234642Smarc blue[rgbp->offset] = (short) rgbp->blue; 201334642Smarc } 201430391Skarels 201534642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 201630391Skarels } 201730391Skarels } 201830391Skarels 201934642Smarc /* 202034642Smarc * service the scroll interrupt (FRAME_SYNC bit) 202134642Smarc */ 202230391Skarels if (adder->status & FRAME_SYNC) { 202334642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 202430391Skarels 202534642Smarc if (scroll[qd]->status & LOAD_REGS) { 202630391Skarels 202734732Smarc for (i = 1000, adder->status = 0; i > 0 && 202834732Smarc !(adder->status&ID_SCROLL_READY); --i) 202934642Smarc ; 203030391Skarels 203134642Smarc if (i == 0) { 203234732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 203334642Smarc qd); 203434642Smarc return; 203534642Smarc } 203630391Skarels 203734642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 203834642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 203930391Skarels 204034642Smarc adder->y_scroll_constant = 204134642Smarc scroll[qd]->y_scroll_constant; 204234642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 204330391Skarels 204434642Smarc if (scroll[qd]->status & LOAD_INDEX) { 204530391Skarels 204634642Smarc adder->x_index_pending = 204734642Smarc scroll[qd]->x_index_pending; 204834642Smarc adder->y_index_pending = 204934642Smarc scroll[qd]->y_index_pending; 205034642Smarc } 205134642Smarc 205234642Smarc scroll[qd]->status = 0x00; 205330391Skarels } 205430391Skarels } 205530391Skarels } 205630391Skarels 205734732Smarc /* 205834732Smarc * DUART input interrupt service routine 205934732Smarc * 206034732Smarc * XXX - this routine should be broken out - it is essentially 206134732Smarc * straight line code. 206234732Smarc */ 206330391Skarels 206430391Skarels qdiint(qd) 206534732Smarc register qd; 206630391Skarels { 206730391Skarels register struct _vs_event *event; 206830391Skarels register struct qdinput *eqh; 206930391Skarels struct dga *dga; 207030391Skarels struct duart *duart; 207130391Skarels struct mouse_report *new_rep; 207230391Skarels struct uba_device *ui; 207330391Skarels struct tty *tp; 207434615Smarc u_short chr; 207530391Skarels u_short status; 207630391Skarels u_short data; 207730391Skarels u_short key; 207830391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 207930391Skarels char a, b, c; /* mouse button test variables */ 208030391Skarels 208134732Smarc (void)spl4(); /* allow interval timer in */ 208230391Skarels 208330391Skarels eqh = eq_header[qd]; /* optimized as a register */ 208430391Skarels new_rep = ¤t_rep[qd]; 208530391Skarels duart = (struct duart *) qdmap[qd].duart; 208630391Skarels 208734642Smarc /* 208834732Smarc * if the graphic device is turned on.. 208934732Smarc */ 209030391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 209134642Smarc /* 209234642Smarc * empty DUART 209334642Smarc */ 209434732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 209534642Smarc /* 209634732Smarc * pick up LK-201 input (if any) 209734732Smarc */ 209834732Smarc if (duart->statusA&RCV_RDY) { 209930391Skarels 210034642Smarc /* if error condition, then reset it */ 210130391Skarels 210234732Smarc if (duart->statusA&0x70) { 210334642Smarc duart->cmdA = 0x40; 210434642Smarc continue; 210534642Smarc } 210630391Skarels 210734642Smarc /* event queue full now? (overflow condition) */ 210830391Skarels 210934642Smarc if (ISFULL(eqh) == TRUE) { 211034642Smarc printf( 211134732Smarc "qd%d: qdiint: event queue overflow\n", 211234642Smarc qd); 211334642Smarc break; 211434642Smarc } 211530391Skarels 211634642Smarc /* 211734642Smarc * Check for various keyboard errors */ 211830391Skarels 211934642Smarc key = duart->dataA & 0xFF; 212030391Skarels 212134642Smarc if (key==LK_POWER_ERROR || 212234642Smarc key==LK_KDOWN_ERROR || 212334642Smarc key == LK_INPUT_ERROR || 212434642Smarc key == LK_OUTPUT_ERROR) { 212534642Smarc printf( 212634732Smarc "qd%d: qdiint: keyboard error, code = %x\n", 212734642Smarc qd,key); 212834732Smarc return; 212934642Smarc } 213030391Skarels 213134642Smarc if (key < LK_LOWEST) 213234732Smarc return; 213330391Skarels 213434642Smarc ++do_wakeup; /* request a select wakeup call */ 213530391Skarels 213634642Smarc event = PUTBEGIN(eqh); 213734642Smarc PUTEND(eqh); 213830391Skarels 213934642Smarc event->vse_key = key; 214034642Smarc event->vse_key &= 0x00FF; 214134642Smarc event->vse_x = eqh->curs_pos.x; 214234642Smarc event->vse_y = eqh->curs_pos.y; 214334642Smarc event->vse_time = TOY; 214434642Smarc event->vse_type = VSE_BUTTON; 214534642Smarc event->vse_direction = VSE_KBTRAW; 214634642Smarc event->vse_device = VSE_DKB; 214734642Smarc } 214830391Skarels 214934642Smarc /* 215034642Smarc * pick up the mouse input (if any) */ 215130391Skarels 215234642Smarc if ((status = duart->statusB) & RCV_RDY && 215334642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 215430391Skarels 215534642Smarc if (status & 0x70) { 215634642Smarc duart->cmdB = 0x40; 215734642Smarc continue; 215834642Smarc } 215930391Skarels 216034642Smarc /* event queue full now? (overflow condition) */ 216130391Skarels 216234642Smarc if (ISFULL(eqh) == TRUE) { 216334642Smarc printf( 216434732Smarc "qd%d: qdiint: event queue overflow\n", 216534642Smarc qd); 216634642Smarc break; 216734642Smarc } 216830391Skarels 216934642Smarc data = duart->dataB; /* get report byte */ 217034642Smarc ++new_rep->bytcnt; /* bump report byte count */ 217130391Skarels 217234642Smarc /* 217334642Smarc * if 1st byte of report.. */ 217430391Skarels 217534642Smarc if ( data & START_FRAME) { 217634642Smarc new_rep->state = data; 217734642Smarc if (new_rep->bytcnt > 1) { 217834642Smarc /* start of new frame */ 217934642Smarc new_rep->bytcnt = 1; 218034642Smarc /* ..continue looking */ 218134642Smarc continue; 218234642Smarc } 218334642Smarc } 218430391Skarels 218534642Smarc /* 218634642Smarc * if 2nd byte of report.. */ 218730391Skarels 218834642Smarc else if (new_rep->bytcnt == 2) { 218934642Smarc new_rep->dx = data & 0x00FF; 219034642Smarc } 219130391Skarels 219234642Smarc /* 219334642Smarc * if 3rd byte of report, load input event queue */ 219430391Skarels 219534642Smarc else if (new_rep->bytcnt == 3) { 219630391Skarels 219734642Smarc new_rep->dy = data & 0x00FF; 219834642Smarc new_rep->bytcnt = 0; 219930391Skarels 220034642Smarc /* 220134642Smarc * if mouse position has changed.. */ 220230391Skarels 220334642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 220430391Skarels 220534642Smarc /* 220634642Smarc * calculate acceleration factor, if needed */ 220730391Skarels 220834642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 220930391Skarels 221034642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 221134642Smarc new_rep->dx += 221234642Smarc (new_rep->dx - qdflags[qd].curs_thr) 221334642Smarc * qdflags[qd].curs_acc; 221430391Skarels 221534642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 221634642Smarc new_rep->dy += 221734642Smarc (new_rep->dy - qdflags[qd].curs_thr) 221834642Smarc * qdflags[qd].curs_acc; 221934642Smarc } 222030391Skarels 222134642Smarc /* 222234642Smarc * update cursor position coordinates */ 222330391Skarels 222434642Smarc if (new_rep->state & X_SIGN) { 222534642Smarc eqh->curs_pos.x += new_rep->dx; 222634642Smarc if (eqh->curs_pos.x > 1023) 222734642Smarc eqh->curs_pos.x = 1023; 222834642Smarc } 222934642Smarc else { 223034642Smarc eqh->curs_pos.x -= new_rep->dx; 223134642Smarc if (eqh->curs_pos.x < -15) 223234642Smarc eqh->curs_pos.x = -15; 223334642Smarc } 223430391Skarels 223534642Smarc if (new_rep->state & Y_SIGN) { 223634642Smarc eqh->curs_pos.y -= new_rep->dy; 223734642Smarc if (eqh->curs_pos.y < -15) 223834642Smarc eqh->curs_pos.y = -15; 223934642Smarc } 224034642Smarc else { 224134642Smarc eqh->curs_pos.y += new_rep->dy; 224234642Smarc if (eqh->curs_pos.y > 863) 224334642Smarc eqh->curs_pos.y = 863; 224434642Smarc } 224530391Skarels 224634642Smarc /* 224734642Smarc * update cursor screen position */ 224830391Skarels 224934642Smarc dga = (struct dga *) qdmap[qd].dga; 225034642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 225134642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 225230391Skarels 225334642Smarc /* 225434642Smarc * if cursor is in the box, no event report */ 225530391Skarels 225634642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 225734642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 225834642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 225934642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 226034642Smarc goto GET_MBUTTON; 226134642Smarc } 226230391Skarels 226334642Smarc /* 226434642Smarc * report the mouse motion event */ 226530391Skarels 226634642Smarc event = PUTBEGIN(eqh); 226734642Smarc PUTEND(eqh); 226830391Skarels 226934642Smarc ++do_wakeup; /* request a select wakeup call */ 227030391Skarels 227134642Smarc event->vse_x = eqh->curs_pos.x; 227234642Smarc event->vse_y = eqh->curs_pos.y; 227330391Skarels 227434642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 227534642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 227634642Smarc event->vse_key = 0; 227734642Smarc event->vse_direction = 0; 227834642Smarc event->vse_time = TOY; /* time stamp */ 227934642Smarc } 228030391Skarels 228130391Skarels GET_MBUTTON: 228234642Smarc /* 228334642Smarc * if button state has changed */ 228430391Skarels 228534642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 228634642Smarc b = last_rep[qd].state & 0x07; 228730391Skarels 228834642Smarc if (a ^ b) { 228930391Skarels 229034642Smarc for ( c = 1; c < 8; c <<= 1) { 229130391Skarels 229234642Smarc if (!( c & (a ^ b))) /* this button change? */ 229334642Smarc continue; 229430391Skarels 229534642Smarc /* event queue full? (overflow condition) */ 229630391Skarels 229734642Smarc if (ISFULL(eqh) == TRUE) { 229834732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 229934642Smarc break; 230034642Smarc } 230130391Skarels 230234642Smarc event = PUTBEGIN(eqh); /* get new event */ 230334642Smarc PUTEND(eqh); 230430391Skarels 230534642Smarc ++do_wakeup; /* request select wakeup */ 230630391Skarels 230734642Smarc event->vse_x = eqh->curs_pos.x; 230834642Smarc event->vse_y = eqh->curs_pos.y; 230930391Skarels 231034642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 231134642Smarc event->vse_type = VSE_BUTTON; /* new button */ 231234642Smarc event->vse_time = TOY; /* time stamp */ 231330391Skarels 231434642Smarc /* flag changed button and if up or down */ 231530391Skarels 231634642Smarc if (c == RIGHT_BUTTON) 231734642Smarc event->vse_key = VSE_RIGHT_BUTTON; 231834642Smarc else if (c == MIDDLE_BUTTON) 231934642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 232034642Smarc else if (c == LEFT_BUTTON) 232134642Smarc event->vse_key = VSE_LEFT_BUTTON; 232230391Skarels 232334642Smarc /* set bit = button depressed */ 232430391Skarels 232534642Smarc if (c & a) 232634642Smarc event->vse_direction = VSE_KBTDOWN; 232734642Smarc else 232834642Smarc event->vse_direction = VSE_KBTUP; 232934642Smarc } 233034642Smarc } 233130391Skarels 233234642Smarc /* refresh last report */ 233330391Skarels 233434642Smarc last_rep[qd] = current_rep[qd]; 233530391Skarels 233634642Smarc } /* get last byte of report */ 233734732Smarc } else if ((status = duart->statusB)&RCV_RDY && 233834732Smarc qdflags[qd].pntr_id == TABLET_ID) { 233934732Smarc /* 234034732Smarc * pickup tablet input, if any 234134732Smarc */ 234234732Smarc if (status&0x70) { 234334642Smarc duart->cmdB = 0x40; 234434642Smarc continue; 234534642Smarc } 234634732Smarc /* 234734732Smarc * event queue full now? (overflow condition) 234834732Smarc */ 234934642Smarc if (ISFULL(eqh) == TRUE) { 235034732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 235134642Smarc break; 235234642Smarc } 235330391Skarels 235434642Smarc data = duart->dataB; /* get report byte */ 235534642Smarc ++new_rep->bytcnt; /* bump report byte count */ 235630391Skarels 235734642Smarc /* 235834642Smarc * if 1st byte of report.. */ 235930391Skarels 236034642Smarc if (data & START_FRAME) { 236134642Smarc new_rep->state = data; 236234642Smarc if (new_rep->bytcnt > 1) { 236334642Smarc new_rep->bytcnt = 1; /* start of new frame */ 236434642Smarc continue; /* ..continue looking */ 236534642Smarc } 236634642Smarc } 236730391Skarels 236834642Smarc /* 236934642Smarc * if 2nd byte of report.. */ 237030391Skarels 237134642Smarc else if (new_rep->bytcnt == 2) { 237234642Smarc new_rep->dx = data & 0x3F; 237334642Smarc } 237430391Skarels 237534642Smarc /* 237634642Smarc * if 3rd byte of report.. */ 237730391Skarels 237834642Smarc else if (new_rep->bytcnt == 3) { 237934642Smarc new_rep->dx |= (data & 0x3F) << 6; 238034642Smarc } 238130391Skarels 238234642Smarc /* 238334642Smarc * if 4th byte of report.. */ 238430391Skarels 238534642Smarc else if (new_rep->bytcnt == 4) { 238634642Smarc new_rep->dy = data & 0x3F; 238734642Smarc } 238830391Skarels 238934642Smarc /* 239034642Smarc * if 5th byte of report, load input event queue */ 239130391Skarels 239234642Smarc else if (new_rep->bytcnt == 5) { 239330391Skarels 239434642Smarc new_rep->dy |= (data & 0x3F) << 6; 239534642Smarc new_rep->bytcnt = 0; 239630391Skarels 239734642Smarc /* 239834642Smarc * update cursor position coordinates */ 239930391Skarels 240034642Smarc new_rep->dx /= qdflags[qd].tab_res; 240134642Smarc new_rep->dy = (2200 - new_rep->dy) 240234642Smarc / qdflags[qd].tab_res; 240330391Skarels 240434642Smarc if (new_rep->dx > 1023) { 240534642Smarc new_rep->dx = 1023; 240634642Smarc } 240734642Smarc if (new_rep->dy > 863) { 240834642Smarc new_rep->dy = 863; 240934642Smarc } 241030391Skarels 241134642Smarc /* 241234642Smarc * report an event if the puck/stylus has moved 241334642Smarc */ 241430391Skarels 241534642Smarc if (eqh->curs_pos.x != new_rep->dx || 241634642Smarc eqh->curs_pos.y != new_rep->dy) { 241730391Skarels 241834642Smarc eqh->curs_pos.x = new_rep->dx; 241934642Smarc eqh->curs_pos.y = new_rep->dy; 242030391Skarels 242134642Smarc /* 242234642Smarc * update cursor screen position */ 242330391Skarels 242434642Smarc dga = (struct dga *) qdmap[qd].dga; 242534642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 242634642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 242730391Skarels 242834642Smarc /* 242934642Smarc * if cursor is in the box, no event report 243034642Smarc */ 243130391Skarels 243234642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 243334642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 243434642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 243534642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 243634642Smarc goto GET_TBUTTON; 243734642Smarc } 243830391Skarels 243934642Smarc /* 244034642Smarc * report the tablet motion event */ 244130391Skarels 244234642Smarc event = PUTBEGIN(eqh); 244334642Smarc PUTEND(eqh); 244430391Skarels 244534642Smarc ++do_wakeup; /* request a select wakeup call */ 244630391Skarels 244734642Smarc event->vse_x = eqh->curs_pos.x; 244834642Smarc event->vse_y = eqh->curs_pos.y; 244930391Skarels 245034642Smarc event->vse_device = VSE_TABLET; /* tablet */ 245134642Smarc /* 245234642Smarc * right now, X handles tablet motion the same 245334642Smarc * as mouse motion 245434642Smarc */ 245534642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 245634642Smarc event->vse_key = 0; 245734642Smarc event->vse_direction = 0; 245834642Smarc event->vse_time = TOY; /* time stamp */ 245934642Smarc } 246030391Skarels GET_TBUTTON: 246134642Smarc /* 246234642Smarc * if button state has changed */ 246330391Skarels 246434642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 246534642Smarc b = last_rep[qd].state & 0x1E; 246630391Skarels 246734642Smarc if (a ^ b) { 246830391Skarels 246934642Smarc /* event queue full now? (overflow condition) */ 247030391Skarels 247134642Smarc if (ISFULL(eqh) == TRUE) { 247234732Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 247334642Smarc break; 247434642Smarc } 247530391Skarels 247634642Smarc event = PUTBEGIN(eqh); /* get new event */ 247734642Smarc PUTEND(eqh); 247830391Skarels 247934642Smarc ++do_wakeup; /* request a select wakeup call */ 248030391Skarels 248134642Smarc event->vse_x = eqh->curs_pos.x; 248234642Smarc event->vse_y = eqh->curs_pos.y; 248330391Skarels 248434642Smarc event->vse_device = VSE_TABLET; /* tablet */ 248534642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 248634642Smarc event->vse_time = TOY; /* time stamp */ 248730391Skarels 248834642Smarc /* define the changed button and if up or down */ 248930391Skarels 249034642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 249134642Smarc if (c & (a ^ b)) { 249234642Smarc if (c == T_LEFT_BUTTON) 249334642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 249434642Smarc else if (c == T_FRONT_BUTTON) 249534642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 249634642Smarc else if (c == T_RIGHT_BUTTON) 249734642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 249834642Smarc else if (c == T_BACK_BUTTON) 249934642Smarc event->vse_key = VSE_T_BACK_BUTTON; 250034642Smarc break; 250134642Smarc } 250234642Smarc } 250330391Skarels 250434642Smarc /* set bit = button depressed */ 250530391Skarels 250634642Smarc if (c & a) 250734642Smarc event->vse_direction = VSE_KBTDOWN; 250834642Smarc else 250934642Smarc event->vse_direction = VSE_KBTUP; 251034642Smarc } 251130391Skarels 251234642Smarc /* refresh last report */ 251330391Skarels 251434642Smarc last_rep[qd] = current_rep[qd]; 251530391Skarels 251634642Smarc } /* get last byte of report */ 251734642Smarc } /* pick up tablet input */ 251830391Skarels 251934642Smarc } /* while input available.. */ 252030391Skarels 252134642Smarc /* 252234642Smarc * do select wakeup 252334642Smarc */ 252434732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 252534732Smarc selwakeup(qdrsel[qd], 0); 252634732Smarc qdrsel[qd] = 0; 252734642Smarc qdflags[qd].selmask &= ~SEL_READ; 252834642Smarc do_wakeup = 0; 252934642Smarc } 253034732Smarc } else { 253134732Smarc /* 253234732Smarc * if the graphic device is not turned on, this is console input 253334732Smarc */ 253434642Smarc ui = qdinfo[qd]; 253534642Smarc if (ui == 0 || ui->ui_alive == 0) 253634732Smarc return; 253730391Skarels 253834642Smarc tp = &qd_tty[qd << 2]; 253930391Skarels 254034642Smarc /* 254134732Smarc * Get a character from the keyboard. 254234732Smarc */ 254334732Smarc while (duart->statusA&RCV_RDY) { 254434642Smarc key = duart->dataA; 254534642Smarc key &= 0xFF; 254634642Smarc /* 254734732Smarc * Check for various keyboard errors 254834732Smarc */ 254934732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 255034642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 255134732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 255234732Smarc return; 255334642Smarc } 255430391Skarels 255534642Smarc if (key < LK_LOWEST) 255634732Smarc return; 255730391Skarels 255834642Smarc /* 255934642Smarc * See if its a state change key */ 256030391Skarels 256134642Smarc switch (key) { 256230391Skarels 256334642Smarc case LOCK: 256434642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 256534642Smarc if (q_keyboard.lock) 256634732Smarc (void)led_control(qd, LK_LED_ENABLE, 256734732Smarc LK_LED_LOCK); 256834642Smarc else 256934732Smarc (void)led_control(qd, LK_LED_DISABLE, 257034732Smarc LK_LED_LOCK); 257134642Smarc return; 257230391Skarels 257334642Smarc case SHIFT: 257434642Smarc q_keyboard.shift ^= 0xFFFF; 257534642Smarc return; 257630391Skarels 257734642Smarc case CNTRL: 257834642Smarc q_keyboard.cntrl ^= 0xFFFF; 257934642Smarc return; 258030391Skarels 258134642Smarc case ALLUP: 258234642Smarc q_keyboard.cntrl = 0; 258334642Smarc q_keyboard.shift = 0; 258434642Smarc return; 258530391Skarels 258634642Smarc case REPEAT: 258734642Smarc chr = q_keyboard.last; 258834642Smarc break; 258930391Skarels 259034642Smarc /* 259134642Smarc * Test for cntrl characters. If set, see if the character 259234642Smarc * is elligible to become a control character. */ 259330391Skarels 259434642Smarc default: 259530391Skarels 259634642Smarc if (q_keyboard.cntrl) { 259734642Smarc chr = q_key[key]; 259834642Smarc if (chr >= ' ' && chr <= '~') 259934642Smarc chr &= 0x1F; 260034642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 260134642Smarc chr &= 0x9F; 260234642Smarc } 260334642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 260434642Smarc chr = q_shift_key[key]; 260534642Smarc else 260634642Smarc chr = q_key[key]; 260734642Smarc break; 260830391Skarels } 260930391Skarels 261034642Smarc q_keyboard.last = chr; 261130391Skarels 261234642Smarc /* 261334642Smarc * Check for special function keys */ 261430391Skarels 261534642Smarc if (chr & 0x100) { 261634642Smarc char *string; 261734642Smarc string = q_special[chr & 0x7F]; 261834642Smarc while(*string) 261934642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 262034615Smarc } 262134642Smarc else { 262234642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 262334642Smarc } 262430391Skarels } 262530391Skarels } 262630391Skarels } /* qdiint */ 262730391Skarels 262834732Smarc /* 262934732Smarc * 263034732Smarc * Clear the QDSS screen 263134732Smarc * 263234732Smarc * >>> NOTE <<< 263334732Smarc * 263434732Smarc * This code requires that certain adder initialization be valid. To 263534732Smarc * assure that this requirement is satisfied, this routine should be 263634732Smarc * called only after calling the "setup_dragon()" function. 263734732Smarc * 263834732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear 263934732Smarc * only clears the current displayed portion of the bitmap put a 264034732Smarc * temporary value in the y limit register so we can access whole 264134732Smarc * bitmap 264234732Smarc * 264334732Smarc */ 264430391Skarels clear_qd_screen(unit) 264534732Smarc int unit; 264630391Skarels { 264730391Skarels register struct adder *adder; 264830391Skarels adder = (struct adder *) qdmap[unit].adder; 264930391Skarels 265030391Skarels adder->x_limit = 1024; 265130391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 265230391Skarels adder->y_offset_pending = 0; 265334732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 265434642Smarc WSV; 265530391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265634642Smarc WSV; 265730391Skarels adder->y_offset_pending = 864; 265834642Smarc WSV; 265930391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266034642Smarc WSV; 266130391Skarels adder->y_offset_pending = 1728; 266234642Smarc WSV; 266330391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266434642Smarc WSV; 266530391Skarels adder->y_offset_pending = 0; /* back to normal */ 266634642Smarc WSV; 266730391Skarels adder->x_limit = MAX_SCREEN_X; 266830391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 266934642Smarc #undef WSV 267030391Skarels 267130391Skarels } /* clear_qd_screen */ 267230391Skarels 267334732Smarc /* 267434732Smarc * kernel console output to the glass tty 267534732Smarc */ 267630391Skarels qdputc(chr) 267734642Smarc register char chr; 267830391Skarels { 267930391Skarels 268034642Smarc /* 268134642Smarc * if system is now physical, forget it (ie: crash DUMP) 268234642Smarc */ 268334642Smarc if ((mfpr(MAPEN) & 1) == 0) 268434642Smarc return; 268534615Smarc 268634732Smarc blitc(0, (u_char)(chr & 0xff)); 268732012Smarc if ((chr & 0177) == '\n') 268832012Smarc blitc(0, '\r'); 268930391Skarels 269030391Skarels } /* qdputc */ 269130391Skarels 269234732Smarc /* 269334732Smarc * load the mouse cursor's template RAM bitmap 269434732Smarc */ 269530391Skarels ldcursor(unit, bitmap) 269634732Smarc int unit; 269734732Smarc register short *bitmap; 269830391Skarels { 269930391Skarels register struct dga *dga; 270030391Skarels register short *temp; 270130391Skarels register int i; 270234732Smarc int curs; 270330391Skarels 270430391Skarels dga = (struct dga *) qdmap[unit].dga; 270530391Skarels temp = (short *) qdmap[unit].template; 270630391Skarels 270730391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 270834732Smarc curs = -1; /* ..note that.. */ 270934642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 271034732Smarc } else 271134732Smarc curs = 0; 271230391Skarels 271330391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 271430391Skarels 271530391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 271634642Smarc /* ..of the 8k WORD template space */ 271730391Skarels for (i = 0; i < 32; ++i) 271834642Smarc *temp++ = *bitmap++; 271930391Skarels 272034732Smarc if (curs) { /* if cursor was enabled.. */ 272134642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 272230391Skarels } 272330391Skarels 272430391Skarels } /* ldcursor */ 272530391Skarels 272634732Smarc /* 272734732Smarc * Put the console font in the QDSS off-screen memory 272834732Smarc */ 272930391Skarels ldfont(unit) 273034732Smarc int unit; 273130391Skarels { 273230391Skarels register struct adder *adder; 273330391Skarels 273434732Smarc register i, j, k, max_chars_line; 273534732Smarc register short packed; 273630391Skarels 273730391Skarels adder = (struct adder *) qdmap[unit].adder; 273830391Skarels 273934642Smarc /* 274034732Smarc * setup VIPER operand control registers 274134732Smarc */ 274230391Skarels write_ID(adder, MASK_1, 0xFFFF); 274330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 274430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 274530391Skarels 274630391Skarels write_ID(adder, SRC1_OCR_B, 274734642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 274830391Skarels write_ID(adder, SRC2_OCR_B, 274934642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 275030391Skarels write_ID(adder, DST_OCR_B, 275134642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 275230391Skarels 275330391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 275430391Skarels 275534642Smarc /* 275634732Smarc * load destination data 275734732Smarc */ 275834732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 275930391Skarels 276030391Skarels adder->destination_x = FONT_X; 276130391Skarels adder->destination_y = FONT_Y; 276234732Smarc #if FONT_WIDTH > MAX_SCREEN_X 276334732Smarc adder->fast_dest_dx = MAX_SCREEN_X; 276434732Smarc #else 276534732Smarc adder->fast_dest_dx = FONT_WIDTH; 276634732Smarc #endif 276730391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 276830391Skarels 276934642Smarc /* 277034642Smarc * setup for processor to bitmap xfer */ 277130391Skarels 277230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 277330391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 277430391Skarels 277534642Smarc /* 277634642Smarc * Figure out how many characters can be stored on one "line" of 277734642Smarc * offscreen memory. 277834642Smarc */ 277934642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 278034642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 278134642Smarc max_chars_line = CHARS/2 + CHARS%2; 278230391Skarels 278334642Smarc /* 278434642Smarc * iteratively do the processor to bitmap xfer */ 278534615Smarc 278630391Skarels for (i = 0; i < ROWS; ++i) { 278730391Skarels 278834642Smarc /* PTOB a scan line */ 278930391Skarels 279034642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 279134642Smarc /* PTOB one scan of a char cell */ 279230391Skarels 279334642Smarc packed = q_font[k]; 279434642Smarc k += ROWS; 279534642Smarc packed |= ((short)q_font[k] << 8); 279634642Smarc k += ROWS; 279730391Skarels 279834732Smarc (void)wait_status(adder, TX_READY); 279934642Smarc adder->id_data = packed; 280034642Smarc } 280130391Skarels } 280230391Skarels 280334642Smarc /* 280434642Smarc * (XXX XXX XXX - should remove) 280534642Smarc * 280634642Smarc * Copy the second row of characters. Subtract the first 280734642Smarc * row from the total number. Divide this quantity by 2 280834642Smarc * because 2 chars are stored in a short in the PTOB loop 280934642Smarc * below. Figure out how many characters can be stored on 281034642Smarc * one "line" of offscreen memory 281134642Smarc */ 281234642Smarc 281334642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 281434642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 281534642Smarc return; 281634642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 281734642Smarc /* Paranoia check to see if 3rd row may be needed */ 281834642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 281934615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 282034615Smarc 282134615Smarc adder->destination_x = FONT_X; 282234615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 282334615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 282434615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 282534615Smarc 282634642Smarc /* 282734642Smarc * setup for processor to bitmap xfer 282834642Smarc */ 282934615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 283034615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 283134615Smarc 283234642Smarc /* 283334642Smarc * iteratively do the processor to bitmap xfer 283434642Smarc */ 283534615Smarc for (i = 0; i < ROWS; ++i) { 283634642Smarc /* 283734642Smarc * PTOB a scan line 283834642Smarc */ 283934642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 284034642Smarc /* 284134642Smarc * PTOB one scan of a char cell 284234642Smarc */ 284334642Smarc packed = q_font[k + FONT_OFFSET]; 284434642Smarc k += ROWS; 284534642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 284634642Smarc k += ROWS; 284734732Smarc (void)wait_status(adder, TX_READY); 284834642Smarc adder->id_data = packed; 284934642Smarc } 285034615Smarc } 285134615Smarc 285230391Skarels } /* ldfont */ 285330391Skarels 285434732Smarc /* 285534732Smarc * Get a character from the LK201 (polled) 285634732Smarc */ 285734732Smarc qdgetc() 285834732Smarc { 285934732Smarc register short key; 286034732Smarc register char chr; 286134732Smarc register struct duart *duart; 286230391Skarels 286334732Smarc duart = (struct duart *) qdmap[0].duart; 286434732Smarc 286534732Smarc /* 286634732Smarc * Get a character from the keyboard. 286734732Smarc */ 286834732Smarc LOOP: 286934732Smarc while (!(duart->statusA&RCV_RDY)) 287034732Smarc ; 287134732Smarc 287234732Smarc key = duart->dataA; 287334732Smarc key &= 0xFF; 287434732Smarc 287534732Smarc /* 287634732Smarc * Check for various keyboard errors */ 287734732Smarc 287834732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 287934732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 288034732Smarc printf("Keyboard error, code = %x\n", key); 288134732Smarc return(0); 288234732Smarc } 288334732Smarc 288434732Smarc if (key < LK_LOWEST) 288534732Smarc return(0); 288634732Smarc 288734732Smarc /* 288834732Smarc * See if its a state change key 288934732Smarc */ 289034732Smarc switch (key) { 289134732Smarc 289234732Smarc case LOCK: 289334732Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 289434732Smarc if (q_keyboard.lock) 289534732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 289634732Smarc else 289734732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 289834732Smarc goto LOOP; 289934732Smarc 290034732Smarc case SHIFT: 290134732Smarc q_keyboard.shift ^= 0xFFFF; 290234732Smarc goto LOOP; 290334732Smarc 290434732Smarc case CNTRL: 290534732Smarc q_keyboard.cntrl ^= 0xFFFF; 290634732Smarc goto LOOP; 290734732Smarc 290834732Smarc case ALLUP: 290934732Smarc q_keyboard.cntrl = 0; 291034732Smarc q_keyboard.shift = 0; 291134732Smarc goto LOOP; 291234732Smarc 291334732Smarc case REPEAT: 291434732Smarc chr = q_keyboard.last; 291534732Smarc break; 291634732Smarc 291734732Smarc /* 291834732Smarc * Test for cntrl characters. If set, see if the character 291934732Smarc * is elligible to become a control character. 292034732Smarc */ 292134732Smarc default: 292234732Smarc 292334732Smarc if (q_keyboard.cntrl) { 292434732Smarc chr = q_key[key]; 292534732Smarc if (chr >= ' ' && chr <= '~') 292634732Smarc chr &= 0x1F; 292734732Smarc } 292834732Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 292934732Smarc chr = q_shift_key[key]; 293034732Smarc else 293134732Smarc chr = q_key[key]; 293234732Smarc break; 293334732Smarc } 293434732Smarc 293534732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 293634732Smarc return(0); /* ..then pitch it! */ 293734732Smarc 293834732Smarc q_keyboard.last = chr; 293934732Smarc 294034732Smarc /* 294134732Smarc * Check for special function keys */ 294234732Smarc 294334732Smarc if (chr & 0x80) /* pitch the function keys */ 294434732Smarc return(0); 294534732Smarc else 294634732Smarc return(chr); 294734732Smarc 294834732Smarc } /* qdgetc */ 294934732Smarc 295034732Smarc /* 295134732Smarc * led_control()... twiddle LK-201 LED's 295234732Smarc */ 295330391Skarels led_control(unit, cmd, led_mask) 295434732Smarc int unit, cmd, led_mask; 295530391Skarels { 295634732Smarc register i; 295730391Skarels register struct duart *duart; 295830391Skarels 295934732Smarc duart = (struct duart *)qdmap[unit].duart; 296030391Skarels 296130391Skarels for (i = 1000; i > 0; --i) { 296234732Smarc if (duart->statusA&XMT_RDY) { 296334642Smarc duart->dataA = cmd; 296434642Smarc break; 296534642Smarc } 296630391Skarels } 296730391Skarels for (i = 1000; i > 0; --i) { 296834732Smarc if (duart->statusA&XMT_RDY) { 296934642Smarc duart->dataA = led_mask; 297034642Smarc break; 297134642Smarc } 297230391Skarels } 297330391Skarels if (i == 0) 297434642Smarc return(BAD); 297530391Skarels return(GOOD); 297630391Skarels 297730391Skarels } /* led_control */ 297830391Skarels 297934732Smarc /* 298034732Smarc * scroll_up()... move the screen up one character height 298134732Smarc */ 298230391Skarels scroll_up(adder) 298334642Smarc register struct adder *adder; 298430391Skarels { 298534642Smarc /* 298634642Smarc * setup VIPER operand control registers 298734642Smarc */ 298834732Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 298930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 299030391Skarels write_ID(adder, MASK_1, 0xFFFF); 299130391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 299230391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 299330391Skarels write_ID(adder, SRC1_OCR_B, 299434642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 299530391Skarels write_ID(adder, DST_OCR_B, 299634642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 299734642Smarc /* 299834642Smarc * load DESTINATION origin and vectors 299934642Smarc */ 300030391Skarels adder->fast_dest_dy = 0; 300130391Skarels adder->slow_dest_dx = 0; 300230391Skarels adder->error_1 = 0; 300330391Skarels adder->error_2 = 0; 300430391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 300530391Skarels adder->destination_x = 0; 300630391Skarels adder->fast_dest_dx = 1024; 300730391Skarels adder->destination_y = 0; 300830391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 300934642Smarc /* 301034642Smarc * load SOURCE origin and vectors 301134642Smarc */ 301230391Skarels adder->source_1_x = 0; 301330391Skarels adder->source_1_dx = 1024; 301430391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 301530391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 301630391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 301730391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 301834642Smarc /* 301934642Smarc * do a rectangle clear of last screen line 302034642Smarc */ 302130391Skarels write_ID(adder, MASK_1, 0xffff); 302230391Skarels write_ID(adder, SOURCE, 0xffff); 302330391Skarels write_ID(adder,DST_OCR_B, 302434642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 302530391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 302630391Skarels adder->error_1 = 0; 302730391Skarels adder->error_2 = 0; 302834642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 302930391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 303030391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 303134732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 303230391Skarels adder->destination_x = 0; 303330391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 303430391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 303530391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 303630391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 303730391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 303830391Skarels 303930391Skarels } /* scroll_up */ 304030391Skarels 304134732Smarc /* 304234732Smarc * init shared memory pointers and structures 304334732Smarc */ 304430391Skarels init_shared(unit) 304534732Smarc register unit; 304630391Skarels { 304730391Skarels register struct dga *dga; 304830391Skarels 304930391Skarels dga = (struct dga *) qdmap[unit].dga; 305030391Skarels 305134642Smarc /* 305234642Smarc * initialize the event queue pointers and header */ 305330391Skarels 305430391Skarels eq_header[unit] = (struct qdinput *) 305534642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 305634642Smarc + (EVENT_BUFSIZE * unit)); 305730391Skarels eq_header[unit]->curs_pos.x = 0; 305830391Skarels eq_header[unit]->curs_pos.y = 0; 305930391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 306030391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 306130391Skarels eq_header[unit]->curs_box.left = 0; 306230391Skarels eq_header[unit]->curs_box.right = 0; 306330391Skarels eq_header[unit]->curs_box.top = 0; 306430391Skarels eq_header[unit]->curs_box.bottom = 0; 306534642Smarc /* 306634642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 306734642Smarc */ 306830391Skarels DMAheader[unit] = (struct DMAreq_header *) 306934642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 307034642Smarc + (DMAbuf_size * unit)); 307130391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 307234642Smarc + sizeof(struct DMAreq_header)); 307330391Skarels DMAheader[unit]->QBAreg = 0; 307430391Skarels DMAheader[unit]->status = 0; 307530391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 307630391Skarels DMAheader[unit]->used = 0; 307730391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 307830391Skarels DMAheader[unit]->oldest = 0; 307930391Skarels DMAheader[unit]->newest = 0; 308034642Smarc /* 308134642Smarc * assign a pointer to the scroll structure for this QDSS. 308234642Smarc */ 308330391Skarels scroll[unit] = (struct scroll *) 308434642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 308534642Smarc + (sizeof(struct scroll) * unit)); 308630391Skarels scroll[unit]->status = 0; 308730391Skarels scroll[unit]->viper_constant = 0; 308830391Skarels scroll[unit]->y_scroll_constant = 0; 308930391Skarels scroll[unit]->y_offset = 0; 309030391Skarels scroll[unit]->x_index_pending = 0; 309130391Skarels scroll[unit]->y_index_pending = 0; 309234642Smarc /* 309334642Smarc * assign a pointer to the color map write buffer for this QDSS 309434642Smarc */ 309530391Skarels color_buf[unit] = (struct color_buf *) 309634642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 309734642Smarc + (COLOR_BUFSIZ * unit)); 309830391Skarels color_buf[unit]->status = 0; 309930391Skarels color_buf[unit]->count = 0; 310030391Skarels 310130391Skarels } /* init_shared */ 310230391Skarels 310334732Smarc /* 310434732Smarc * init the ADDER, VIPER, bitmaps, & color map 310534732Smarc */ 310630391Skarels setup_dragon(unit) 310734732Smarc int unit; 310830391Skarels { 310930391Skarels 311030391Skarels register struct adder *adder; 311130391Skarels register struct dga *dga; 311230391Skarels short *memcsr; 311334732Smarc register i; 311430391Skarels short top; /* clipping/scrolling boundaries */ 311530391Skarels short bottom; 311630391Skarels short right; 311730391Skarels short left; 311830391Skarels short *red; /* color map pointers */ 311930391Skarels short *green; 312030391Skarels short *blue; 312130391Skarels 312234642Smarc /* 312334642Smarc * init for setup 312434642Smarc */ 312530391Skarels adder = (struct adder *) qdmap[unit].adder; 312630391Skarels dga = (struct dga *) qdmap[unit].dga; 312730391Skarels memcsr = (short *) qdmap[unit].memcsr; 312830391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 312930391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 313030391Skarels adder->command = CANCEL; 313134642Smarc /* 313234642Smarc * set monitor timing 313334642Smarc */ 313430391Skarels adder->x_scan_count_0 = 0x2800; 313530391Skarels adder->x_scan_count_1 = 0x1020; 313630391Skarels adder->x_scan_count_2 = 0x003A; 313730391Skarels adder->x_scan_count_3 = 0x38F0; 313830391Skarels adder->x_scan_count_4 = 0x6128; 313930391Skarels adder->x_scan_count_5 = 0x093A; 314030391Skarels adder->x_scan_count_6 = 0x313C; 314130391Skarels adder->sync_phase_adj = 0x0100; 314230391Skarels adder->x_scan_conf = 0x00C8; 314334642Smarc /* 314434642Smarc * got a bug in secound pass ADDER! lets take care of it 314534642Smarc * 314634642Smarc * normally, just use the code in the following bug fix code, but to 314734642Smarc * make repeated demos look pretty, load the registers as if there was 314834642Smarc * no bug and then test to see if we are getting sync 314934642Smarc */ 315030391Skarels adder->y_scan_count_0 = 0x135F; 315130391Skarels adder->y_scan_count_1 = 0x3363; 315230391Skarels adder->y_scan_count_2 = 0x2366; 315330391Skarels adder->y_scan_count_3 = 0x0388; 315434642Smarc /* 315534642Smarc * if no sync, do the bug fix code 315634642Smarc */ 315730391Skarels if (wait_status(adder, VSYNC) == BAD) { 315834642Smarc /* first load all Y scan registers with very short frame and 315934642Smarc * wait for scroll service. This guarantees at least one SYNC 316034642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 316134642Smarc * XCINCH with DMSEEDH) 316234642Smarc */ 316334642Smarc adder->y_scan_count_0 = 0x01; 316434642Smarc adder->y_scan_count_1 = 0x01; 316534642Smarc adder->y_scan_count_2 = 0x01; 316634642Smarc adder->y_scan_count_3 = 0x01; 316734642Smarc /* 316834642Smarc * delay at least 1 full frame time 316934642Smarc */ 317034732Smarc (void)wait_status(adder, VSYNC); 317134732Smarc (void)wait_status(adder, VSYNC); 317234642Smarc /* 317334642Smarc * now load the REAL sync values (in reverse order just to 317434642Smarc * be safe. 317534642Smarc */ 317634642Smarc adder->y_scan_count_3 = 0x0388; 317734642Smarc adder->y_scan_count_2 = 0x2366; 317834642Smarc adder->y_scan_count_1 = 0x3363; 317934642Smarc adder->y_scan_count_0 = 0x135F; 318030391Skarels } 318130391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 318234642Smarc /* 318334642Smarc * zero the index registers 318434642Smarc */ 318530391Skarels adder->x_index_pending = 0; 318630391Skarels adder->y_index_pending = 0; 318730391Skarels adder->x_index_new = 0; 318830391Skarels adder->y_index_new = 0; 318930391Skarels adder->x_index_old = 0; 319030391Skarels adder->y_index_old = 0; 319130391Skarels adder->pause = 0; 319234642Smarc /* 319334642Smarc * set rasterop mode to normal pen down 319434642Smarc */ 319530391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 319634642Smarc /* 319734642Smarc * set the rasterop registers to a default values 319834642Smarc */ 319930391Skarels adder->source_1_dx = 1; 320030391Skarels adder->source_1_dy = 1; 320130391Skarels adder->source_1_x = 0; 320230391Skarels adder->source_1_y = 0; 320330391Skarels adder->destination_x = 0; 320430391Skarels adder->destination_y = 0; 320530391Skarels adder->fast_dest_dx = 1; 320630391Skarels adder->fast_dest_dy = 0; 320730391Skarels adder->slow_dest_dx = 0; 320830391Skarels adder->slow_dest_dy = 1; 320930391Skarels adder->error_1 = 0; 321030391Skarels adder->error_2 = 0; 321134642Smarc /* 321234732Smarc * scale factor = UNITY 321334642Smarc */ 321430391Skarels adder->fast_scale = UNITY; 321530391Skarels adder->slow_scale = UNITY; 321634642Smarc /* 321734642Smarc * set the source 2 parameters 321834642Smarc */ 321930391Skarels adder->source_2_x = 0; 322030391Skarels adder->source_2_y = 0; 322130391Skarels adder->source_2_size = 0x0022; 322234642Smarc /* 322334642Smarc * initialize plane addresses for eight vipers 322434642Smarc */ 322530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 322630391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 322730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 322830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 322930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 323030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 323130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 323230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 323330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 323430391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 323530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 323630391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 323730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 323830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 323930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 324030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 324134642Smarc /* 324234642Smarc * initialize the external registers. 324334642Smarc */ 324430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 324530391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 324634642Smarc /* 324734642Smarc * initialize resolution mode 324834642Smarc */ 324930391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 325030391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 325134642Smarc /* 325234642Smarc * initialize viper registers 325334642Smarc */ 325430391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 325530391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 325634642Smarc /* 325734642Smarc * set clipping and scrolling limits to full screen 325834642Smarc */ 325934732Smarc for (i = 1000, adder->status = 0; 326034732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 326134642Smarc ; 326230391Skarels if (i == 0) 326334732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 326430391Skarels top = 0; 326530391Skarels bottom = 2048; 326630391Skarels left = 0; 326730391Skarels right = 1024; 326830391Skarels adder->x_clip_min = left; 326930391Skarels adder->x_clip_max = right; 327030391Skarels adder->y_clip_min = top; 327130391Skarels adder->y_clip_max = bottom; 327230391Skarels adder->scroll_x_min = left; 327330391Skarels adder->scroll_x_max = right; 327430391Skarels adder->scroll_y_min = top; 327530391Skarels adder->scroll_y_max = bottom; 327634732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 327734732Smarc (void)wait_status(adder, VSYNC); 327830391Skarels adder->x_index_pending = left; 327930391Skarels adder->y_index_pending = top; 328030391Skarels adder->x_index_new = left; 328130391Skarels adder->y_index_new = top; 328230391Skarels adder->x_index_old = left; 328330391Skarels adder->y_index_old = top; 328430391Skarels 328534732Smarc for (i = 1000, adder->status = 0; i > 0 && 328634732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 328734642Smarc ; 328830391Skarels if (i == 0) 328934732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 329030391Skarels 329130391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 329230391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 329334642Smarc /* 329434642Smarc * set source and the mask register to all ones (ie: white) o 329534642Smarc */ 329630391Skarels write_ID(adder, SOURCE, 0xFFFF); 329730391Skarels write_ID(adder, MASK_1, 0xFFFF); 329830391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 329930391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 330034642Smarc /* 330134642Smarc * initialize Operand Control Register banks for fill command 330234642Smarc */ 330330391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 330430391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 330530391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 330630391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 330730391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 330830391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 330934642Smarc /* 331034642Smarc * init Logic Unit Function registers, (these are just common values, 331134642Smarc * and may be changed as required). 331234642Smarc */ 331330391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 331434642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 331534642Smarc INV_M1_M2); 331630391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 331730391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 331834642Smarc /* 331934642Smarc * load the color map for black & white 332034642Smarc */ 332134732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 332234642Smarc ; 332330391Skarels 332430391Skarels if (i == 0) 332534732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 332630391Skarels 332730391Skarels red = (short *) qdmap[unit].red; 332830391Skarels green = (short *) qdmap[unit].green; 332930391Skarels blue = (short *) qdmap[unit].blue; 333030391Skarels 333130391Skarels *red++ = 0x00; /* black */ 333230391Skarels *green++ = 0x00; 333330391Skarels *blue++ = 0x00; 333430391Skarels 333530391Skarels *red-- = 0xFF; /* white */ 333630391Skarels *green-- = 0xFF; 333730391Skarels *blue-- = 0xFF; 333830391Skarels 333934642Smarc /* 334034732Smarc * set color map for mouse cursor 334134732Smarc */ 334230391Skarels 334330391Skarels red += 254; 334430391Skarels green += 254; 334530391Skarels blue += 254; 334630391Skarels 334730391Skarels *red++ = 0x00; /* black */ 334830391Skarels *green++ = 0x00; 334930391Skarels *blue++ = 0x00; 335030391Skarels 335130391Skarels *red = 0xFF; /* white */ 335230391Skarels *green = 0xFF; 335330391Skarels *blue = 0xFF; 335430391Skarels 335530391Skarels } /* setup_dragon */ 335630391Skarels 335734732Smarc /* 335834732Smarc * Init the DUART and set defaults in input 335934732Smarc */ 336030391Skarels setup_input(unit) 336134732Smarc int unit; 336230391Skarels { 336330391Skarels register struct duart *duart; /* DUART register structure pointer */ 336434732Smarc register i, bits; 336530391Skarels char id_byte; 336630391Skarels 336730391Skarels duart = (struct duart *) qdmap[unit].duart; 336830391Skarels duart->imask = 0; 336930391Skarels 337034642Smarc /* 337134642Smarc * setup the DUART for kbd & pointing device 337234642Smarc */ 337334732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 337434732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 337534732Smarc /* no RTS control,char error mode */ 337634732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 337734732Smarc /* no RTS control,no echo or loop */ 337834732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 337934732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 338034732Smarc /* ..no RTS cntrl, char error mode */ 338134732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 338234732Smarc /* no RTS control,no echo or loop */ 338334732Smarc duart->auxctl = 0x00; /* baud rate set 1 */ 338434732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */ 338534732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */ 338630391Skarels 338730391Skarels /* reset everything for keyboard */ 338830391Skarels 338930391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339034642Smarc duart->cmdA = bits; 339130391Skarels 339230391Skarels /* reset everything for host */ 339330391Skarels 339430391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339534642Smarc duart->cmdB = bits; 339630391Skarels 339730391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 339830391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 339930391Skarels 340034642Smarc /* 340134732Smarc * init keyboard defaults (DUART channel A) 340234732Smarc */ 340330391Skarels for (i = 500; i > 0; --i) { 340434732Smarc if (duart->statusA&XMT_RDY) { 340534642Smarc duart->dataA = LK_DEFAULTS; 340634642Smarc break; 340734642Smarc } 340830391Skarels } 340930391Skarels 341030391Skarels for (i = 100000; i > 0; --i) { 341134732Smarc if (duart->statusA&RCV_RDY) { 341234642Smarc break; 341334642Smarc } 341430391Skarels } 341530391Skarels 341634732Smarc if (duart->dataA) /* flush the ACK */ 341734732Smarc ; 341830391Skarels 341934642Smarc /* 342034732Smarc * identify the pointing device 342134732Smarc */ 342230391Skarels for (i = 500; i > 0; --i) { 342334732Smarc if (duart->statusB&XMT_RDY) { 342434642Smarc duart->dataB = SELF_TEST; 342534642Smarc break; 342634642Smarc } 342730391Skarels } 342830391Skarels 342934642Smarc /* 343030391Skarels * wait for 1st byte of self test report */ 343130391Skarels 343230391Skarels for (i = 100000; i > 0; --i) { 343334732Smarc if (duart->statusB&RCV_RDY) { 343434642Smarc break; 343534642Smarc } 343630391Skarels } 343730391Skarels 343830391Skarels if (i == 0) { 343934732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 344034642Smarc ,unit); 344134642Smarc goto OUT; 344230391Skarels } 344330391Skarels 344434732Smarc if (duart->dataB) 344534732Smarc ; 344630391Skarels 344734642Smarc /* 344834732Smarc * wait for ID byte of self test report 344934732Smarc */ 345030391Skarels for (i = 100000; i > 0; --i) { 345134732Smarc if (duart->statusB&RCV_RDY) { 345234642Smarc break; 345334642Smarc } 345430391Skarels } 345530391Skarels 345630391Skarels if (i == 0) { 345734732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 345834642Smarc goto OUT; 345930391Skarels } 346030391Skarels 346130391Skarels id_byte = duart->dataB; 346230391Skarels 346334642Smarc /* 346434732Smarc * wait for other bytes to come in 346534732Smarc */ 346630391Skarels for (i = 100000; i > 0; --i) { 346734732Smarc if (duart->statusB & RCV_RDY) { 346834732Smarc if (duart->dataB) 346934732Smarc ; 347034642Smarc break; 347134642Smarc } 347230391Skarels } 347330391Skarels if (i == 0) { 347434732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 347534642Smarc goto OUT; 347630391Skarels } 347730391Skarels for (i = 100000; i > 0; --i) { 347834732Smarc if (duart->statusB&RCV_RDY) { 347934732Smarc if (duart->dataB) 348034732Smarc ; 348134642Smarc break; 348234642Smarc } 348330391Skarels } 348430391Skarels if (i == 0) { 348534732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 348634642Smarc goto OUT; 348730391Skarels } 348834642Smarc /* 348934732Smarc * flag pointing device type and set defaults 349034732Smarc */ 349134732Smarc for (i=100000; i>0; --i) 349234732Smarc ; /*XXX*/ 349330391Skarels 349430391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 349534642Smarc qdflags[unit].pntr_id = MOUSE_ID; 349630391Skarels 349734642Smarc for (i = 500; i > 0; --i) { 349834732Smarc if (duart->statusB&XMT_RDY) { 349934642Smarc duart->dataB = INC_STREAM_MODE; 350034642Smarc break; 350134642Smarc } 350230391Skarels } 350334642Smarc } 350434642Smarc else { 350534642Smarc qdflags[unit].pntr_id = TABLET_ID; 350630391Skarels 350734642Smarc for (i = 500; i > 0; --i) { 350834732Smarc if (duart->statusB&XMT_RDY) { 350934642Smarc duart->dataB = T_STREAM; 351034642Smarc break; 351134642Smarc } 351230391Skarels } 351330391Skarels } 351430391Skarels OUT: 351530391Skarels duart->imask = qdflags[unit].duart_imask; 351630391Skarels 351730391Skarels } /* setup_input */ 351830391Skarels 351934732Smarc /* 352034732Smarc * delay for at least one display frame time 352134732Smarc * 352234732Smarc * return: BAD means that we timed out without ever seeing the 352334732Smarc * vertical sync status bit 352434732Smarc * GOOD otherwise 352534732Smarc */ 352630391Skarels wait_status(adder, mask) 352734642Smarc register struct adder *adder; 352834642Smarc register int mask; 352930391Skarels { 353034732Smarc register i; 353130391Skarels 353234732Smarc for (i = 10000, adder->status = 0 ; i > 0 && 353334732Smarc !(adder->status&mask) ; --i) 353434642Smarc ; 353530391Skarels 353630391Skarels if (i == 0) { 353734732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 353834642Smarc return(BAD); 353930391Skarels } 354030391Skarels 354130391Skarels return(GOOD); 354230391Skarels 354330391Skarels } /* wait_status */ 354430391Skarels 354534732Smarc /* 354634732Smarc * write out onto the ID bus 354734732Smarc */ 354830391Skarels write_ID(adder, adrs, data) 354934642Smarc register struct adder *adder; 355034642Smarc register short adrs; 355134642Smarc register short data; 355230391Skarels { 355334732Smarc register i; 355430391Skarels 355534732Smarc for (i = 100000, adder->status = 0 ; 355634732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 355734642Smarc ; 355830391Skarels 355930391Skarels if (i == 0) 356034732Smarc goto ERR; 356130391Skarels 356234732Smarc for (i = 100000, adder->status = 0 ; 356334732Smarc i > 0 && !(adder->status&TX_READY) ; --i) 356434642Smarc ; 356530391Skarels 356630391Skarels if (i > 0) { 356734642Smarc adder->id_data = data; 356834642Smarc adder->command = ID_LOAD | adrs; 356934732Smarc return ; 357030391Skarels } 357130391Skarels 357230391Skarels ERR: 357334732Smarc printf("write_ID: timeout trying to write to VIPER\n"); 357434732Smarc return ; 357530391Skarels 357630391Skarels } /* write_ID */ 357734511Smarc #endif 3578