134511Smarc /* 235353Sbostic * Copyright (c) 1988 Regents of the University of California. 335353Sbostic * All rights reserved. 435353Sbostic * 535353Sbostic * Redistribution and use in source and binary forms are permitted 635353Sbostic * provided that the above copyright notice and this paragraph are 735353Sbostic * duplicated in all such forms and that any documentation, 835353Sbostic * advertising materials, and other materials related to such 935353Sbostic * distribution and use acknowledge that the software was developed 1035353Sbostic * by the University of California, Berkeley. The name of the 1135353Sbostic * University may not be used to endorse or promote products derived 1235353Sbostic * from this software without specific prior written permission. 1335353Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435353Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535353Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1635353Sbostic * 17*36705Stef * @(#)qd.c 1.11 (Berkeley) 02/07/89 1835353Sbostic */ 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; 365*36705Stef if (pcpu->pc_io->io_type != IO_QBUS) 366*36705Stef return 0; 36730391Skarels 36832012Smarc /* 36934615Smarc * Map device registers - the last 8K of qvmem. 37032012Smarc */ 37132012Smarc qb = (struct qbus *)pcpu->pc_io->io_details; 37232012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 37334732Smarc UBAIOPAGES * NBPG); 37432012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 37530391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 37634732Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 37734732Smarc return 0; 37834615Smarc 37932012Smarc /* 38032012Smarc * Map q-bus memory used by qdss. (separate map) 38132012Smarc */ 38232012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 38332012Smarc phys_adr = qb->qb_maddr + mapix; 38432012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 38530391Skarels 38632012Smarc /* 38732012Smarc * tell QDSS which Q memory address base to decode 38834642Smarc * (shifted right 16 bits - its in 64K units) 38932012Smarc */ 39032012Smarc *qdaddr = (u_short)((int)mapix >> 16); 39130391Skarels qdflags[unit].config = *(u_short *)qdaddr; 39230391Skarels 39334642Smarc /* 39434642Smarc * load qdmap struct with the virtual addresses of the QDSS elements 39534642Smarc */ 39634615Smarc qdbase[unit] = (caddr_t) (qvmem[0]); 39730391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 39830391Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 39930391Skarels qdmap[unit].dga = qdbase[unit] + DGA; 40030391Skarels qdmap[unit].duart = qdbase[unit] + DUART; 40130391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 40230391Skarels qdmap[unit].red = qdbase[unit] + RED; 40330391Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 40430391Skarels qdmap[unit].green = qdbase[unit] + GREEN; 40530391Skarels 40630391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 40730391Skarels 40834642Smarc /* 40934642Smarc * init the QDSS 41034642Smarc */ 41134642Smarc /* 41232012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 41334642Smarc (char *)qdbase[0], qdmap[0].memcsr); 41434642Smarc */ 41532012Smarc 41630391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 41730391Skarels 41830391Skarels cursor[unit].x = 0; 41930391Skarels cursor[unit].y = 0; 42030391Skarels init_shared(unit); /* init shared memory */ 42130391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 42230391Skarels clear_qd_screen(unit); /* clear the screen */ 42330391Skarels ldfont(unit); /* load the console font */ 42430391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 42530391Skarels setup_input(unit); /* init the DUART */ 42634642Smarc v_putc = qdputc; /* kernel console output to qdss */ 42734642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 42834732Smarc return 1; 42930391Skarels 43030391Skarels } /* qdcons_init */ 43130391Skarels 43234732Smarc /* 43334732Smarc * Configure QDSS into Q memory and make it intrpt. 43434732Smarc * 43534732Smarc * side effects: QDSS gets mapped into Qbus memory space at the first 43634732Smarc * vacant 64kb boundary counting back from the top of 43734732Smarc * Qbus memory space (qvmem+4mb) 43834732Smarc * 43934732Smarc * return: QDSS bus request level and vector address returned in 44034732Smarc * registers by UNIX convention. 44134732Smarc * 44234732Smarc */ 44330391Skarels qdprobe(reg) 44434732Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 44530391Skarels { 44634642Smarc register int br, cvec; /* value-result */ 44730391Skarels register int unit; 44830391Skarels struct dga *dga; /* pointer to gate array structure */ 44934732Smarc int vector; 45034732Smarc #ifdef notdef 45130391Skarels int *ptep; /* page table entry pointer */ 45230391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 45330391Skarels u_int mapix; 45434732Smarc #endif 45530391Skarels 45634732Smarc #ifdef lint 45734732Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 45834732Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 45934732Smarc #endif 46034732Smarc 46134642Smarc /* 46234642Smarc * calculate board unit number from I/O page register address 46334642Smarc */ 46430391Skarels unit = (int) (((int)reg >> 1) & 0x0007); 46530391Skarels 46634642Smarc /* 46734642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 46834642Smarc * physical boundary. The Qbus memory space is mapped into 46934642Smarc * the system memory space at config time. After config 47034642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 47134642Smarc * of the start of Qbus memory. The Qbus memory page table 47234642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 47334642Smarc * which is also loaded at config time. These are the 47434642Smarc * variables used below to find a vacant 64kb boundary in 47534642Smarc * Qbus memory, and load it's corresponding physical adrs 47634642Smarc * into the QDSS's I/O page CSR. 47734642Smarc */ 47830391Skarels 47934615Smarc /* 48034615Smarc * Only if QD is the graphics device. 48134615Smarc */ 48234615Smarc 48330391Skarels /* if this QDSS is NOT the console, then do init here.. */ 48430391Skarels 48534615Smarc if (unit != 0) { 48634615Smarc printf("qd: can't support two qdss's (yet)\n"); 48734732Smarc #ifdef notdef /* can't test */ 48834642Smarc if (v_consputc != qdputc || unit != 0) { 48930391Skarels 49034642Smarc /* 49134642Smarc * read QDSS config info 49234642Smarc */ 49334642Smarc qdflags[unit].config = *(u_short *)reg; 49434615Smarc 49534642Smarc /* 49634642Smarc * find an empty 64kb adrs boundary 49734642Smarc */ 49830391Skarels 49934642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 50030391Skarels 50134642Smarc /* 50234732Smarc * find the cpusw entry that matches this machine. 50334732Smarc */ 50434642Smarc cpup = &cpusw[cpu]; 50534732Smarc while (!(BADADDR(qdbase[unit], sizeof(short)))) 50634732Smarc qdbase[unit] -= CHUNK; 50734615Smarc 50834642Smarc /* 50934732Smarc * tell QDSS which Q memory address base to decode 51034732Smarc */ 51134642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 51234642Smarc ptep = (int *) QVmap[0] + mapix; 51334642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 51434642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 51534615Smarc 51634642Smarc /* 51734642Smarc * load QDSS adrs map with system addresses 51834642Smarc * of device regs 51934642Smarc */ 52034642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART; 52134642Smarc qdmap[unit].adder = qdbase[unit] + ADDER; 52234642Smarc qdmap[unit].dga = qdbase[unit] + DGA; 52334642Smarc qdmap[unit].duart = qdbase[unit] + DUART; 52434642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 52534642Smarc qdmap[unit].red = qdbase[unit] + RED; 52634642Smarc qdmap[unit].blue = qdbase[unit] + BLUE; 52734642Smarc qdmap[unit].green = qdbase[unit] + GREEN; 52830391Skarels 52934642Smarc /* device init */ 53034615Smarc 53134642Smarc cursor[unit].x = 0; 53234642Smarc cursor[unit].y = 0; 53334642Smarc init_shared(unit); /* init shared memory */ 53434642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */ 53534642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */ 53634642Smarc setup_input(unit); /* init the DUART */ 53734642Smarc clear_qd_screen(unit); 53834642Smarc ldfont(unit); /* load the console font */ 53930391Skarels 54034642Smarc /* once only: turn on sync */ 54130391Skarels 54234642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON; 54334642Smarc } 54434615Smarc #endif /*notdef*/ 54530391Skarels } 54630391Skarels 54734642Smarc /* 54834642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 54934642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 55034642Smarc * vectors from the vector pool, and then continue 55134642Smarc * to take them until we get a xx0 HEX vector. The 55234642Smarc * pool provides vectors in contiguous decending 55334642Smarc * order. 55434642Smarc */ 55530391Skarels 55630391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 55730391Skarels 55834642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */ 55934642Smarc /* ..take another vector */ 56034642Smarc vector = (uba_hd[0].uh_lastiv -= 4); 56130391Skarels } 56230391Skarels 56334642Smarc /* 56434642Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 56534642Smarc */ 56630391Skarels dga = (struct dga *) qdmap[unit].dga; 56734642Smarc dga->csr = (short) HALT; /* disable everything */ 56834642Smarc dga->ivr = (short) vector; /* load intrpt base vector */ 56934642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 57030391Skarels dga->bytcnt_hi = (short) 0; 57130391Skarels 57234642Smarc /* 57334642Smarc * turn on DMA interrupts 57434642Smarc */ 57530391Skarels dga->csr &= ~SET_DONE_FIFO; 57630391Skarels dga->csr |= DMA_IE | DL_ENB; 57730391Skarels 57830391Skarels DELAY(20000); /* wait for the intrpt */ 57930391Skarels dga->csr = HALT; /* stop the wheels */ 58030391Skarels 58130391Skarels if (cvec != vector) /* if vector != base vector.. */ 58234732Smarc return(0); /* ..return = 'no device' */ 58330391Skarels 58434615Smarc /* 58534642Smarc * score this as an existing qdss 58634642Smarc */ 58734615Smarc qdcount++; 58834615Smarc 58930391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 59030391Skarels 59130391Skarels } /* qdprobe */ 59230391Skarels 59330391Skarels qdattach(ui) 59434642Smarc struct uba_device *ui; 59530391Skarels { 59634732Smarc register unit; /* QDSS module # for this call */ 59730391Skarels 59830391Skarels unit = ui->ui_unit; /* get QDSS number */ 59930391Skarels 60034642Smarc /* 60134642Smarc * init "qdflags[]" for this QDSS 60234642Smarc */ 60330391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 60430391Skarels qdflags[unit].mapped = 0; 60534615Smarc qdflags[unit].kernel_loop = -1; 60630391Skarels qdflags[unit].user_dma = 0; 60730391Skarels qdflags[unit].curs_acc = ACC_OFF; 60830391Skarels qdflags[unit].curs_thr = 128; 60930391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 61030391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 61130391Skarels qdflags[unit].adder_ie = 0; 61230391Skarels 61334642Smarc /* 61434642Smarc * init structures used in kbd/mouse interrupt service. This code must 61534642Smarc * come after the "init_shared()" routine has run since that routine 61634642Smarc * inits the eq_header[unit] structure used here. 61734642Smarc */ 61830391Skarels 61934642Smarc /* 62034642Smarc * init the "latest mouse report" structure 62134642Smarc */ 62230391Skarels last_rep[unit].state = 0; 62330391Skarels last_rep[unit].dx = 0; 62430391Skarels last_rep[unit].dy = 0; 62530391Skarels last_rep[unit].bytcnt = 0; 62630391Skarels 62734642Smarc /* 62834732Smarc * init the event queue (except mouse position) 62934732Smarc */ 63034732Smarc eq_header[unit]->header.events = 63134732Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 63230391Skarels 63330391Skarels eq_header[unit]->header.size = MAXEVENTS; 63430391Skarels eq_header[unit]->header.head = 0; 63530391Skarels eq_header[unit]->header.tail = 0; 63630391Skarels 63734642Smarc /* 63834642Smarc * open exclusive for graphics device. 63934642Smarc */ 64034642Smarc qdopened[unit] = 0; 64130391Skarels 64230391Skarels } /* qdattach */ 64330391Skarels 64434732Smarc /*ARGSUSED*/ 64530391Skarels qdopen(dev, flag) 64634642Smarc dev_t dev; 64734642Smarc int flag; 64830391Skarels { 64930391Skarels register struct uba_device *ui; /* ptr to uba structures */ 65030391Skarels register struct dga *dga; /* ptr to gate array struct */ 65130391Skarels register struct tty *tp; 65230391Skarels struct duart *duart; 65334732Smarc int unit; 65434732Smarc int minor_dev; 65530391Skarels 65630391Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 65730391Skarels unit = minor_dev >> 2; 65830391Skarels 65934642Smarc /* 66034642Smarc * check for illegal conditions 66134642Smarc */ 66230391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 66330391Skarels if (ui == 0 || ui->ui_alive == 0) 66434642Smarc return(ENXIO); /* no such device or address */ 66530391Skarels 66630391Skarels duart = (struct duart *) qdmap[unit].duart; 66730391Skarels dga = (struct dga *) qdmap[unit].dga; 66830391Skarels 66930391Skarels if ((minor_dev & 0x03) == 2) { 67034642Smarc /* 67134642Smarc * this is the graphic device... 67234642Smarc */ 67334642Smarc if (qdopened[unit] != 0) 67434732Smarc return(EBUSY); 67534642Smarc else 67634642Smarc qdopened[unit] = 1; 67734642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 67834642Smarc /* 67934642Smarc * enble kbd & mouse intrpts in DUART mask reg 68034642Smarc */ 68134642Smarc qdflags[unit].duart_imask |= 0x22; 68234642Smarc duart->imask = qdflags[unit].duart_imask; 68334642Smarc } else { 68434642Smarc /* 68534642Smarc * this is the console 68634642Smarc */ 68734642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 68834642Smarc dga->csr |= CURS_ENB; 68934642Smarc qdflags[unit].duart_imask |= 0x02; 69034642Smarc duart->imask = qdflags[unit].duart_imask; 69134642Smarc /* 69234642Smarc * some setup for tty handling 69334642Smarc */ 69434642Smarc tp = &qd_tty[minor_dev]; 69534642Smarc tp->t_addr = ui->ui_addr; 69634642Smarc tp->t_oproc = qdstart; 69734642Smarc if ((tp->t_state & TS_ISOPEN) == 0) { 69834642Smarc ttychars(tp); 69934642Smarc tp->t_flags = IFLAGS; 70034642Smarc tp->t_ispeed = B9600; 70134642Smarc tp->t_ospeed = B9600; 70234642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 70334642Smarc #ifdef POSIXTTY 70434642Smarc tp->t_iflag = TTYDEF_IFLAG; 70534642Smarc tp->t_oflag = TTYDEF_OFLAG; 70634642Smarc tp->t_lflag = TTYDEF_LFLAG; 70734642Smarc tp->t_cflag = TTYDEF_CFLAG; 70834642Smarc #endif 70932012Smarc } 71034642Smarc /* 71134642Smarc * enable intrpts, open line discipline 71234642Smarc */ 71334642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 71434642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp)); 71530391Skarels } 71630391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 71730391Skarels return(0); 71830391Skarels 71930391Skarels } /* qdopen */ 72030391Skarels 72134732Smarc /*ARGSUSED*/ 72230391Skarels qdclose(dev, flag) 72334642Smarc dev_t dev; 72434642Smarc int flag; 72530391Skarels { 72630391Skarels register struct tty *tp; 72730391Skarels register struct qdmap *qd; 72830391Skarels register int *ptep; 72930391Skarels struct dga *dga; /* gate array register map pointer */ 73030391Skarels struct duart *duart; 73130391Skarels struct adder *adder; 73234732Smarc int unit; 73334732Smarc int minor_dev; 73430391Skarels u_int mapix; 73534642Smarc int i; /* SIGNED index */ 73630391Skarels 73730391Skarels minor_dev = minor(dev); /* get minor device number */ 73830391Skarels unit = minor_dev >> 2; /* get QDSS number */ 73930391Skarels qd = &qdmap[unit]; 74030391Skarels 74130391Skarels if ((minor_dev & 0x03) == 2) { 74234642Smarc /* 74334642Smarc * this is the graphic device... 74434642Smarc */ 74534642Smarc if (qdopened[unit] != 1) 74634732Smarc return(EBUSY); 74734642Smarc else 74834642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 74934642Smarc /* 75034642Smarc * re-protect device memory 75134642Smarc */ 75234642Smarc if (qdflags[unit].mapped & MAPDEV) { 75334642Smarc /* 75434642Smarc * TEMPLATE RAM 75534642Smarc */ 75634642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 75734642Smarc ptep = (int *)(QVmap[0] + mapix); 75834732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 75934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76034642Smarc /* 76134642Smarc * ADDER 76234642Smarc */ 76334642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 76434642Smarc ptep = (int *)(QVmap[0] + mapix); 76534732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 76634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76734642Smarc /* 76834642Smarc * COLOR MAPS 76934642Smarc */ 77034642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 77134642Smarc ptep = (int *)(QVmap[0] + mapix); 77234732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 77334732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 77434642Smarc } 77534615Smarc 77634642Smarc /* 77734642Smarc * re-protect DMA buffer and free the map registers 77834642Smarc */ 77934642Smarc if (qdflags[unit].mapped & MAPDMA) { 78034642Smarc dga = (struct dga *) qdmap[unit].dga; 78134642Smarc adder = (struct adder *) qdmap[unit].adder; 78234642Smarc dga->csr &= ~DMA_IE; 78334642Smarc dga->csr &= ~0x0600; /* kill DMA */ 78434642Smarc adder->command = CANCEL; 78534642Smarc /* 78634642Smarc * if DMA was running, flush spurious intrpt 78734642Smarc */ 78834642Smarc if (dga->bytcnt_lo != 0) { 78934642Smarc dga->bytcnt_lo = 0; 79034642Smarc dga->bytcnt_hi = 0; 79134642Smarc DMA_SETIGNORE(DMAheader[unit]); 79234642Smarc dga->csr |= DMA_IE; 79334642Smarc dga->csr &= ~DMA_IE; 79434642Smarc } 79534642Smarc ptep = (int *) 79634642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 79734732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 79834732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 79934642Smarc ubarelse(0, &Qbus_unmap[unit]); 80034642Smarc } 80134615Smarc 80234642Smarc /* 80334642Smarc * re-protect 1K (2 pages) event queue 80434642Smarc */ 80534642Smarc if (qdflags[unit].mapped & MAPEQ) { 80634642Smarc ptep = (int *) 80734642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 80834732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 80934642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 81030391Skarels } 81134642Smarc /* 81234642Smarc * re-protect scroll param area and disable scroll intrpts 81334642Smarc */ 81434642Smarc if (qdflags[unit].mapped & MAPSCR) { 81534642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 81634642Smarc + (mfpr(SBR) | 0x80000000)); 81734642Smarc /* 81834642Smarc * re-protect 512 scroll param area 81934642Smarc */ 82034642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 82134642Smarc adder = (struct adder *) qdmap[unit].adder; 82234642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 82334642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 82434642Smarc } 82534642Smarc /* 82634642Smarc * re-protect color map write buffer area and kill intrpts 82734642Smarc */ 82834642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 82934642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 83034642Smarc + (mfpr(SBR) | 0x80000000)); 83134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 83234642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 83334642Smarc color_buf[unit]->status = 0; 83434642Smarc adder = (struct adder *) qdmap[unit].adder; 83534642Smarc qdflags[unit].adder_ie &= ~VSYNC; 83634642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 83734642Smarc } 83834642Smarc mtpr(TBIA, 0); 83934642Smarc /* flag everything now unmapped */ 84034642Smarc qdflags[unit].mapped = 0; 84134642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 84234642Smarc qdflags[unit].curs_acc = ACC_OFF; 84334642Smarc qdflags[unit].curs_thr = 128; 84434642Smarc /* 84534642Smarc * restore the console 84634642Smarc */ 84730391Skarels dga = (struct dga *) qdmap[unit].dga; 84830391Skarels adder = (struct adder *) qdmap[unit].adder; 84930391Skarels dga->csr &= ~DMA_IE; 85030391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 85130391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 85230391Skarels adder->command = CANCEL; 85334642Smarc /* 85434642Smarc * if DMA was running, flush spurious intrpt 85534642Smarc */ 85630391Skarels if (dga->bytcnt_lo != 0) { 85734642Smarc dga->bytcnt_lo = 0; 85834642Smarc dga->bytcnt_hi = 0; 85934642Smarc DMA_SETIGNORE(DMAheader[unit]); 86034642Smarc dga->csr |= DMA_IE; 86134642Smarc dga->csr &= ~DMA_IE; 86230391Skarels } 86330391Skarels init_shared(unit); /* init shared memory */ 86430391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 86530391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 86630391Skarels setup_input(unit); /* init the DUART */ 86730391Skarels ldfont(unit); 86830391Skarels cursor[unit].x = 0; 86930391Skarels cursor[unit].y = 0; 87034642Smarc /* 87134642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 87234642Smarc */ 87334642Smarc duart = (struct duart *) qdmap[unit].duart; 87434642Smarc qdflags[unit].duart_imask &= ~(0x20); 87534642Smarc qdflags[unit].duart_imask |= 0x02; 87634642Smarc duart->imask = qdflags[unit].duart_imask; 87734642Smarc /* 87834642Smarc * shut off interrupts if all is closed 87934642Smarc */ 88034642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 88134642Smarc dga = (struct dga *) qdmap[unit].dga; 88234642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 88334642Smarc } 88434642Smarc } else { 88534642Smarc /* 88634642Smarc * this is the console 88734642Smarc */ 88834642Smarc tp = &qd_tty[minor_dev]; 88934642Smarc (*linesw[tp->t_line].l_close)(tp); 89034642Smarc ttyclose(tp); 89134642Smarc tp->t_state = 0; 89234642Smarc qdflags[unit].inuse &= ~CONS_DEV; 89334642Smarc /* 89434642Smarc * if graphics device is closed, kill interrupts 89534642Smarc */ 89634642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 89734642Smarc dga = (struct dga *) qdmap[unit].dga; 89834642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 89934642Smarc } 90030391Skarels } 90134615Smarc 90230391Skarels return(0); 90330391Skarels 90430391Skarels } /* qdclose */ 90530391Skarels 90630391Skarels qdioctl(dev, cmd, datap, flags) 90734642Smarc dev_t dev; 90834642Smarc int cmd; 90934732Smarc register caddr_t datap; 91034642Smarc int flags; 91130391Skarels { 91230391Skarels register int *ptep; /* page table entry pointer */ 91332012Smarc register int mapix; /* QVmap[] page table index */ 91430391Skarels register struct _vs_event *event; 91530391Skarels register struct tty *tp; 91634732Smarc register i; 91730391Skarels struct qdmap *qd; /* pointer to device map struct */ 91830391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 91930391Skarels struct duart *duart; /* DUART reg structure pointer */ 92030391Skarels struct adder *adder; /* ADDER reg structure pointer */ 92130391Skarels struct prgkbd *cmdbuf; 92230391Skarels struct prg_cursor *curs; 92330391Skarels struct _vs_cursor *pos; 92434732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 92530391Skarels u_int minor_dev = minor(dev); 92630391Skarels int error; 92730391Skarels int s; 92830391Skarels short *temp; /* a pointer to template RAM */ 92930391Skarels 93034642Smarc /* 93134642Smarc * service graphic device ioctl commands 93234642Smarc */ 93330391Skarels switch (cmd) { 93434615Smarc 93534642Smarc case QD_GETEVENT: 93634642Smarc /* 93734642Smarc * extract the oldest event from the event queue 93834642Smarc */ 93930391Skarels if (ISEMPTY(eq_header[unit])) { 94034642Smarc event = (struct _vs_event *) datap; 94134642Smarc event->vse_device = VSE_NULL; 94234642Smarc break; 94330391Skarels } 94430391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 94534615Smarc s = spl5(); 94630391Skarels GETEND(eq_header[unit]); 94730391Skarels splx(s); 94834732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 94930391Skarels break; 95030391Skarels 95134642Smarc case QD_RESET: 95234642Smarc /* 95334642Smarc * init the dragon stuff, DUART, and driver variables 95434642Smarc */ 95530391Skarels init_shared(unit); /* init shared memory */ 95630391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 95730391Skarels clear_qd_screen(unit); 95830391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 95930391Skarels ldfont(unit); /* load the console font */ 96030391Skarels setup_input(unit); /* init the DUART */ 96130391Skarels break; 96230391Skarels 96334642Smarc case QD_SET: 96434642Smarc /* 96534642Smarc * init the DUART and driver variables 96634642Smarc */ 96730391Skarels init_shared(unit); 96830391Skarels setup_input(unit); 96930391Skarels break; 97030391Skarels 97134642Smarc case QD_CLRSCRN: 97234642Smarc /* 97334642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 97434642Smarc */ 97534732Smarc #ifdef notdef /* has caused problems and isn't necessary */ 97630391Skarels setup_dragon(unit); 97730391Skarels clear_qd_screen(unit); 97834615Smarc #endif 97930391Skarels break; 98030391Skarels 98134642Smarc case QD_WTCURSOR: 98234642Smarc /* 98334642Smarc * load a cursor into template RAM 98434642Smarc */ 98534732Smarc ldcursor(unit, (short *)datap); 98630391Skarels break; 98730391Skarels 98834642Smarc case QD_RDCURSOR: 98930391Skarels 99030391Skarels temp = (short *) qdmap[unit].template; 99134642Smarc /* 99234642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 99334642Smarc * ...template space 99434642Smarc */ 99530391Skarels temp += (8 * 1024) - 32; 99630391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 99734642Smarc *(short *)datap = *temp++; 99830391Skarels break; 99930391Skarels 100034642Smarc case QD_POSCURSOR: 100134642Smarc /* 100234642Smarc * position the mouse cursor 100334642Smarc */ 100430391Skarels dga = (struct dga *) qdmap[unit].dga; 100530391Skarels pos = (struct _vs_cursor *) datap; 100634615Smarc s = spl5(); 100730391Skarels dga->x_cursor = TRANX(pos->x); 100830391Skarels dga->y_cursor = TRANY(pos->y); 100930391Skarels eq_header[unit]->curs_pos.x = pos->x; 101030391Skarels eq_header[unit]->curs_pos.y = pos->y; 101130391Skarels splx(s); 101230391Skarels break; 101330391Skarels 101434642Smarc case QD_PRGCURSOR: 101534642Smarc /* 101634642Smarc * set the cursor acceleration factor 101734642Smarc */ 101830391Skarels curs = (struct prg_cursor *) datap; 101934615Smarc s = spl5(); 102030391Skarels qdflags[unit].curs_acc = curs->acc_factor; 102130391Skarels qdflags[unit].curs_thr = curs->threshold; 102230391Skarels splx(s); 102330391Skarels break; 102430391Skarels 102534642Smarc case QD_MAPDEVICE: 102634642Smarc /* 102734642Smarc * enable 'user write' to device pages 102834642Smarc */ 102930391Skarels qdflags[unit].mapped |= MAPDEV; 103030391Skarels qd = (struct qdmap *) &qdmap[unit]; 103134642Smarc /* 103234642Smarc * enable user write to template RAM 103334642Smarc */ 103432012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 103532012Smarc ptep = (int *)(QVmap[0] + mapix); 103634732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 103734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103834642Smarc /* 103934642Smarc * enable user write to registers 104034642Smarc */ 104132012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 104232012Smarc ptep = (int *)(QVmap[0] + mapix); 104334732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 104434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104534642Smarc /* 104634642Smarc * enable user write to color maps 104734642Smarc */ 104832012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 104932012Smarc ptep = (int *)(QVmap[0] + mapix); 105034732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 105134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 105234642Smarc /* 105334642Smarc * enable user write to DUART 105434642Smarc */ 105532012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 105632012Smarc ptep = (int *)(QVmap[0] + mapix); 105730391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 105830391Skarels 105934732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 106030391Skarels 106134642Smarc /* 106234732Smarc * stuff qdmap structure in return buffer 106334732Smarc */ 106434732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 106530391Skarels break; 106630391Skarels 106734642Smarc case QD_MAPIOBUF: 106834642Smarc /* 106934642Smarc * do setup for DMA by user process 107034642Smarc * 107134642Smarc * set 'user write enable' bits for DMA buffer 107234642Smarc */ 107330391Skarels qdflags[unit].mapped |= MAPDMA; 107430391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 107534642Smarc + (mfpr(SBR) | 0x80000000)); 107634732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 107734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 107834732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 107934642Smarc /* 108034642Smarc * set up QBUS map registers for DMA 108134642Smarc */ 108230391Skarels DMAheader[unit]->QBAreg = 108334732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 108430391Skarels if (DMAheader[unit]->QBAreg == 0) 108534732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 108630391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 108730391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 108834642Smarc /* 108934642Smarc * return I/O buf adr 109034642Smarc */ 109130391Skarels *(int *)datap = (int) DMAheader[unit]; 109230391Skarels break; 109330391Skarels 109434642Smarc case QD_MAPSCROLL: 109534642Smarc /* 109634642Smarc * map the shared scroll param area and enable scroll interpts 109734642Smarc */ 109830391Skarels qdflags[unit].mapped |= MAPSCR; 109930391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 110034642Smarc + (mfpr(SBR) | 0x80000000)); 110134642Smarc /* 110234642Smarc * allow user write to scroll area 110334642Smarc */ 110430391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 110534732Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 110630391Skarels scroll[unit]->status = 0; 110730391Skarels adder = (struct adder *) qdmap[unit].adder; 110830391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 110930391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 111034642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 111130391Skarels break; 111230391Skarels 111334642Smarc case QD_UNMAPSCROLL: 111434642Smarc /* 111534642Smarc * unmap shared scroll param area and disable scroll intrpts 111634642Smarc */ 111730391Skarels if (qdflags[unit].mapped & MAPSCR) { 111834642Smarc qdflags[unit].mapped &= ~MAPSCR; 111934642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 112034642Smarc + (mfpr(SBR) | 0x80000000)); 112134642Smarc /* 112234642Smarc * re-protect 512 scroll param area 112334642Smarc */ 112434642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 112534642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 112634642Smarc adder = (struct adder *) qdmap[unit].adder; 112734642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 112834642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 112930391Skarels } 113030391Skarels break; 113130391Skarels 113234642Smarc case QD_MAPCOLOR: 113334642Smarc /* 113434642Smarc * map shared color map write buf and turn on vsync intrpt 113534642Smarc */ 113630391Skarels qdflags[unit].mapped |= MAPCOLOR; 113730391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 113834642Smarc + (mfpr(SBR) | 0x80000000)); 113934732Smarc /* 114034732Smarc * allow user write to color map write buffer 114134732Smarc */ 114234732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 114330391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 114430391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 114534642Smarc adder = (struct adder *) qdmap[unit].adder; 114630391Skarels qdflags[unit].adder_ie |= VSYNC; 114730391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 114834732Smarc /* 114934732Smarc * return color area address 115034732Smarc */ 115130391Skarels *(int *)datap = (int) color_buf[unit]; 115230391Skarels break; 115330391Skarels 115434642Smarc case QD_UNMAPCOLOR: 115534642Smarc /* 115634732Smarc * unmap shared color map write buffer and kill VSYNC intrpts 115734732Smarc */ 115830391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 115934642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 116034642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 116134642Smarc + (mfpr(SBR) | 0x80000000)); 116234732Smarc /* 116334732Smarc * re-protect color map write buffer 116434732Smarc */ 116534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 116634642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 116734732Smarc mtpr(TBIA, 0); 116834642Smarc adder = (struct adder *) qdmap[unit].adder; 116934642Smarc qdflags[unit].adder_ie &= ~VSYNC; 117034642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 117130391Skarels } 117230391Skarels break; 117330391Skarels 117434642Smarc case QD_MAPEVENT: 117534642Smarc /* 117634642Smarc * give user write access to the event queue 117734642Smarc */ 117830391Skarels qdflags[unit].mapped |= MAPEQ; 117930391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 118034642Smarc + (mfpr(SBR) | 0x80000000)); 118134732Smarc /* 118234732Smarc * allow user write to 1K event queue 118334732Smarc */ 118434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 118530391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 118630391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 118734732Smarc /* 118834732Smarc * return event queue address 118934732Smarc */ 119034732Smarc *(int *)datap = (int)eq_header[unit]; 119130391Skarels break; 119230391Skarels 119334642Smarc case QD_PRGKBD: 119434642Smarc /* 119534642Smarc * pass caller's programming commands to LK201 119634642Smarc */ 119734732Smarc duart = (struct duart *)qdmap[unit].duart; 119834732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 119934642Smarc /* 120034642Smarc * send command 120134642Smarc */ 120230391Skarels for (i = 1000; i > 0; --i) { 120334732Smarc if (duart->statusA&XMT_RDY) { 120434642Smarc duart->dataA = cmdbuf->cmd; 120534642Smarc break; 120634642Smarc } 120730391Skarels } 120830391Skarels if (i == 0) { 120934732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 121034642Smarc break; 121130391Skarels } 121234642Smarc /* 121334642Smarc * send param1? 121434642Smarc */ 121530391Skarels if (cmdbuf->cmd & LAST_PARAM) 121634642Smarc break; 121730391Skarels for (i = 1000; i > 0; --i) { 121834732Smarc if (duart->statusA&XMT_RDY) { 121934642Smarc duart->dataA = cmdbuf->param1; 122034642Smarc break; 122134642Smarc } 122230391Skarels } 122330391Skarels if (i == 0) { 122434732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 122534642Smarc break; 122630391Skarels } 122734642Smarc /* 122834642Smarc * send param2? 122934642Smarc */ 123030391Skarels if (cmdbuf->param1 & LAST_PARAM) 123130391Skarels break; 123230391Skarels for (i = 1000; i > 0; --i) { 123334732Smarc if (duart->statusA&XMT_RDY) { 123434642Smarc duart->dataA = cmdbuf->param2; 123534642Smarc break; 123634642Smarc } 123730391Skarels } 123830391Skarels if (i == 0) { 123934732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 124034642Smarc break; 124130391Skarels } 124230391Skarels break; 124330391Skarels 124434642Smarc case QD_PRGMOUSE: 124534642Smarc /* 124634642Smarc * pass caller's programming commands to the mouse 124734642Smarc */ 124830391Skarels duart = (struct duart *) qdmap[unit].duart; 124930391Skarels for (i = 1000; i > 0; --i) { 125034732Smarc if (duart->statusB&XMT_RDY) { 125134642Smarc duart->dataB = *datap; 125234642Smarc break; 125334642Smarc } 125430391Skarels } 125530391Skarels if (i == 0) { 125634732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 125730391Skarels } 125830391Skarels break; 125930391Skarels 126034642Smarc case QD_RDCONFIG: 126134642Smarc /* 126234642Smarc * get QDSS configuration word and return it 126334642Smarc */ 126430391Skarels *(short *)datap = qdflags[unit].config; 126530391Skarels break; 126630391Skarels 126734642Smarc case QD_KERN_LOOP: 126834642Smarc case QD_KERN_UNLOOP: 126934642Smarc /* 127034642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 127134642Smarc * kernel console output. 127234642Smarc */ 127334615Smarc break; 127434615Smarc 127534642Smarc case QD_PRGTABLET: 127634642Smarc /* 127734642Smarc * program the tablet 127834642Smarc */ 127930391Skarels duart = (struct duart *) qdmap[unit].duart; 128030391Skarels for (i = 1000; i > 0; --i) { 128134732Smarc if (duart->statusB&XMT_RDY) { 128234642Smarc duart->dataB = *datap; 128334642Smarc break; 128434642Smarc } 128530391Skarels } 128630391Skarels if (i == 0) { 128734732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 128830391Skarels } 128930391Skarels break; 129030391Skarels 129134642Smarc case QD_PRGTABRES: 129234642Smarc /* 129334642Smarc * program the tablet report resolution factor 129434642Smarc */ 129530391Skarels qdflags[unit].tab_res = *(short *)datap; 129630391Skarels break; 129730391Skarels 129834642Smarc default: 129934642Smarc /* 130034642Smarc * service tty ioctl's 130134642Smarc */ 130234642Smarc if (!(minor_dev & 0x02)) { 130330391Skarels tp = &qd_tty[minor_dev]; 130434642Smarc error = 130534642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 130630391Skarels if (error >= 0) { 130734642Smarc return(error); 130830391Skarels } 130930391Skarels error = ttioctl(tp, cmd, datap, flags); 131030391Skarels if (error >= 0) { 131134642Smarc return(error); 131230391Skarels } 131334642Smarc } 131434642Smarc break; 131530391Skarels } 131630391Skarels 131730391Skarels return(0); 131830391Skarels 131930391Skarels } /* qdioctl */ 132030391Skarels 132130391Skarels qdselect(dev, rw) 132234642Smarc dev_t dev; 132334642Smarc int rw; 132430391Skarels { 132534732Smarc register s; 132634732Smarc register unit; 132734615Smarc register struct tty *tp; 132834615Smarc u_int minor_dev = minor(dev); 132930391Skarels 133034615Smarc s = spl5(); 133134615Smarc unit = minor_dev >> 2; 133230391Skarels 133330391Skarels switch (rw) { 133434642Smarc case FREAD: 133534642Smarc if ((minor_dev & 0x03) == 2) { 133634642Smarc /* 133734642Smarc * this is a graphics device, so check for events 133834642Smarc */ 133934732Smarc if(!(ISEMPTY(eq_header[unit]))) { 134034642Smarc splx(s); 134134642Smarc return(1); 134234642Smarc } 134334732Smarc qdrsel[unit] = u.u_procp; 134434642Smarc qdflags[unit].selmask |= SEL_READ; 134534642Smarc splx(s); 134634642Smarc return(0); 134734642Smarc } else { 134834642Smarc /* 134934642Smarc * this is a tty device 135034642Smarc */ 135134642Smarc tp = &qd_tty[minor_dev]; 135234642Smarc if (ttnread(tp)) 135334642Smarc return(1); 135434642Smarc tp->t_rsel = u.u_procp; 135534642Smarc splx(s); 135634642Smarc return(0); 135730391Skarels } 135830391Skarels 135934642Smarc case FWRITE: 136034642Smarc if ((minor(dev) & 0x03) == 2) { 136134642Smarc /* 136234642Smarc * this is a graphics device, so check for dma buffers 136334642Smarc */ 136434642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 136534642Smarc { 136634642Smarc splx(s); 136734642Smarc return(1); 136834642Smarc } 136934732Smarc qdrsel[unit] = u.u_procp; 137034642Smarc qdflags[unit].selmask |= SEL_WRITE; 137134642Smarc splx(s); 137234642Smarc return(0); 137334642Smarc } else { 137434642Smarc /* 137534642Smarc * this is a tty device 137634642Smarc */ 137734642Smarc tp = &qd_tty[minor_dev]; 137834642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) 137934642Smarc return(1); 138034642Smarc tp->t_wsel = u.u_procp; 138134642Smarc splx(s); 138234642Smarc return(0); 138330391Skarels } 138430391Skarels } 138534732Smarc splx(s); 138634732Smarc return(0); 138730391Skarels 138830391Skarels } /* qdselect() */ 138930391Skarels 139030391Skarels extern qd_strategy(); 139130391Skarels 139230391Skarels qdwrite(dev, uio) 139334642Smarc dev_t dev; 139434642Smarc struct uio *uio; 139530391Skarels { 139630391Skarels register struct tty *tp; 139734732Smarc register minor_dev; 139834732Smarc register unit; 139930391Skarels 140030391Skarels minor_dev = minor(dev); 140130391Skarels unit = (minor_dev >> 2) & 0x07; 140230391Skarels 140334642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 140434642Smarc /* 140534642Smarc * this is the console... 140634642Smarc */ 140734642Smarc tp = &qd_tty[minor_dev]; 140834642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 140934642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 141034642Smarc /* 141134642Smarc * this is a DMA xfer from user space 141234642Smarc */ 141334642Smarc return (physio(qd_strategy, &qdbuf[unit], 141434642Smarc dev, B_WRITE, minphys, uio)); 141530391Skarels } 141634732Smarc return (ENXIO); 141730391Skarels } 141830391Skarels 141930391Skarels qdread(dev, uio) 142034642Smarc dev_t dev; 142134642Smarc struct uio *uio; 142230391Skarels { 142330391Skarels register struct tty *tp; 142434732Smarc register minor_dev; 142534732Smarc register unit; 142630391Skarels 142730391Skarels minor_dev = minor(dev); 142830391Skarels unit = (minor_dev >> 2) & 0x07; 142930391Skarels 143034642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 143134642Smarc /* 143234642Smarc * this is the console 143334642Smarc */ 143434642Smarc tp = &qd_tty[minor_dev]; 143534642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 143634642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 143734642Smarc /* 143834642Smarc * this is a bitmap-to-processor xfer 143934642Smarc */ 144034642Smarc return (physio(qd_strategy, &qdbuf[unit], 144134642Smarc dev, B_READ, minphys, uio)); 144230391Skarels } 144334732Smarc return (ENXIO); 144430391Skarels } 144530391Skarels 144630391Skarels /*************************************************************** 144730391Skarels * 144830391Skarels * qd_strategy()... strategy routine to do DMA 144930391Skarels * 145030391Skarels ***************************************************************/ 145130391Skarels 145230391Skarels qd_strategy(bp) 145334642Smarc register struct buf *bp; 145430391Skarels { 145530391Skarels register struct dga *dga; 145630391Skarels register struct adder *adder; 145734732Smarc register unit; 145830391Skarels int QBAreg; 145930391Skarels int s; 146030391Skarels int cookie; 146130391Skarels 146230391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 146330391Skarels 146434642Smarc /* 146534642Smarc * init pointers 146634642Smarc */ 146730391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 146834732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 146934642Smarc goto STRAT_ERR; 147030391Skarels } 147130391Skarels dga = (struct dga *) qdmap[unit].dga; 147234615Smarc s = spl5(); 147330391Skarels qdflags[unit].user_dma = -1; 147430391Skarels dga->csr |= DMA_IE; 147530391Skarels cookie = QBAreg & 0x3FFFF; 147630391Skarels dga->adrs_lo = (short) cookie; 147730391Skarels dga->adrs_hi = (short) (cookie >> 16); 147830391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 147930391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 148030391Skarels 148130391Skarels while (qdflags[unit].user_dma) { 148234642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 148330391Skarels } 148430391Skarels splx(s); 148530391Skarels ubarelse(0, &QBAreg); 148630391Skarels if (!(dga->csr & DMA_ERR)) { 148734642Smarc iodone(bp); 148834642Smarc return; 148930391Skarels } 149030391Skarels 149130391Skarels STRAT_ERR: 149230391Skarels adder = (struct adder *) qdmap[unit].adder; 149334642Smarc adder->command = CANCEL; /* cancel adder activity */ 149430391Skarels dga->csr &= ~DMA_IE; 149530391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 149630391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 149730391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 149830391Skarels 149934642Smarc /* 150034642Smarc * if DMA was running, flush spurious intrpt 150134642Smarc */ 150230391Skarels if (dga->bytcnt_lo != 0) { 150334642Smarc dga->bytcnt_lo = 0; 150434642Smarc dga->bytcnt_hi = 0; 150534642Smarc DMA_SETIGNORE(DMAheader[unit]); 150634642Smarc dga->csr |= DMA_IE; 150730391Skarels } 150830391Skarels iodone(bp); 150930391Skarels 151030391Skarels } /* qd_strategy */ 151130391Skarels 151234732Smarc /* 151334732Smarc * Start output to the console screen 151434732Smarc */ 151530391Skarels qdstart(tp) 151634642Smarc register struct tty *tp; 151730391Skarels { 151834732Smarc register which_unit, unit, c; 151930391Skarels int s; 152034615Smarc 152130391Skarels unit = minor(tp->t_dev); 152230391Skarels which_unit = (unit >> 2) & 0x3; 152334615Smarc unit &= 0x03; 152430391Skarels 152534615Smarc s = spl5(); 152634615Smarc 152734642Smarc /* 152834642Smarc * If it's currently active, or delaying, no need to do anything. 152934642Smarc */ 153030391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 153130391Skarels goto out; 153230391Skarels 153334642Smarc /* 153434642Smarc * Display chars until the queue is empty. 153534642Smarc * Drop input from anything but the console 153634642Smarc * device on the floor. 153734642Smarc * 153834642Smarc * XXX - this loop is done at spltty. 153934642Smarc * 154034642Smarc */ 154134642Smarc while (tp->t_outq.c_cc) { 154234511Smarc c = getc(&tp->t_outq); 154334615Smarc if (unit == 0) 154434732Smarc blitc(which_unit, (u_char)c); 154530391Skarels } 154634642Smarc /* 154734642Smarc * If there are sleepers, and output has drained below low 154834642Smarc * water mark, wake up the sleepers. 154934642Smarc */ 155034642Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 155134615Smarc if (tp->t_state & TS_ASLEEP){ 155234615Smarc tp->t_state &= ~TS_ASLEEP; 155334615Smarc wakeup((caddr_t) &tp->t_outq); 155434615Smarc } 155530391Skarels } 155630391Skarels 155734615Smarc tp->t_state &= ~TS_BUSY; 155834615Smarc 155930391Skarels out: 156030391Skarels splx(s); 156130391Skarels 156230391Skarels } /* qdstart */ 156330391Skarels 156434732Smarc /*ARGSUSED*/ 156530391Skarels qdstop(tp, flag) 156634642Smarc register struct tty *tp; 156734642Smarc int flag; 156830391Skarels { 156930391Skarels register int s; 157030391Skarels 157134615Smarc s = spl5(); /* block intrpts during state modification */ 157234732Smarc if (tp->t_state & TS_BUSY) 157334732Smarc if ((tp->t_state & TS_TTSTOP) == 0) 157434642Smarc tp->t_state |= TS_FLUSH; 157534642Smarc else 157634642Smarc tp->t_state &= ~TS_BUSY; 157730391Skarels splx(s); 157830391Skarels } 157930391Skarels 158034732Smarc /* 158134732Smarc * Output a character to the QDSS screen 158234732Smarc */ 158330391Skarels 158430391Skarels blitc(unit, chr) 158534732Smarc register unit; 158634732Smarc register u_char chr; 158730391Skarels { 158830391Skarels register struct adder *adder; 158930391Skarels register struct dga *dga; 159030391Skarels register int i; 159134642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 159234642Smarc static short inescape[NQD]; 159330391Skarels 159434732Smarc adder = (struct adder *)qdmap[unit].adder; 159530391Skarels dga = (struct dga *) qdmap[unit].dga; 159634642Smarc /* 159734642Smarc * BSD comment: this (&=0177) defeats the extended character 159834642Smarc * set code for the glass tty, but if i had the time i would 159934642Smarc * spend it ripping out the code completely. This driver 160034642Smarc * is too big for its own good. 160134642Smarc */ 160234642Smarc chr &= 0177; 160334642Smarc /* 160434732Smarc * Cursor addressing (so vi will work). 160534642Smarc * Decode for "\E=%.%." cursor motion description. 160634732Smarc * Corresponds to type "qdcons" in /etc/termcap: 160734642Smarc * 160834642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 160934642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 161034642Smarc * 161134642Smarc */ 161234642Smarc if (inescape[unit] && nograph) { 161334642Smarc switch (inescape[unit]++) { 161434642Smarc case 1: 161534642Smarc if (chr != '=') { 161634642Smarc /* abort escape sequence */ 161734642Smarc inescape[unit] = 0; 161834642Smarc blitc(unit, chr); 161934642Smarc } 162034732Smarc return; 162134642Smarc case 2: 162234642Smarc /* position row */ 162334642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 162434642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 162534642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 162634642Smarc dga->y_cursor = TRANY(cursor[unit].y); 162734732Smarc return; 162834642Smarc case 3: 162934642Smarc /* position column */ 163034642Smarc cursor[unit].x = CHAR_WIDTH * chr; 163134642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 163234642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 163334642Smarc dga->x_cursor = TRANX(cursor[unit].x); 163434642Smarc inescape[unit] = 0; 163534732Smarc return; 163634642Smarc default: 163734642Smarc inescape[unit] = 0; 163834642Smarc blitc(unit, chr); 163934642Smarc } 164034642Smarc } 164130391Skarels 164230391Skarels switch (chr) { 164334642Smarc case '\r': /* return char */ 164430391Skarels cursor[unit].x = 0; 164534642Smarc if (nograph) 164634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 164734732Smarc return; 164830391Skarels 164934642Smarc case '\t': /* tab char */ 165030391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 165134642Smarc blitc(unit, ' '); 165230391Skarels } 165334732Smarc return; 165430391Skarels 165534642Smarc case '\n': /* line feed char */ 165630391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 165734642Smarc if (nograph) { 165834642Smarc cursor[unit].y -= CHAR_HEIGHT; 165934642Smarc scroll_up(adder); 166034642Smarc } else 166134642Smarc cursor[unit].y = 0; 166230391Skarels } 166334642Smarc if (nograph) 166434642Smarc dga->y_cursor = TRANY(cursor[unit].y); 166534732Smarc return; 166630391Skarels 166734642Smarc case '\b': /* backspace char */ 166830391Skarels if (cursor[unit].x > 0) { 166934642Smarc cursor[unit].x -= CHAR_WIDTH; 167034642Smarc if (nograph) 167134642Smarc dga->x_cursor = TRANX(cursor[unit].x); 167230391Skarels } 167334732Smarc return; 167434642Smarc case CTRL('k'): /* cursor up */ 167534642Smarc if (nograph && cursor[unit].y > 0) { 167634642Smarc cursor[unit].y -= CHAR_HEIGHT; 167734642Smarc dga->y_cursor = TRANY(cursor[unit].y); 167834642Smarc } 167934732Smarc return; 168030391Skarels 168134642Smarc case CTRL('^'): /* home cursor */ 168234642Smarc if (nograph) { 168334642Smarc cursor[unit].x = 0; 168434642Smarc dga->x_cursor = TRANX(cursor[unit].x); 168534642Smarc cursor[unit].y = 0; 168634642Smarc dga->y_cursor = TRANY(cursor[unit].y); 168734642Smarc } 168834732Smarc return; 168932012Smarc 169034642Smarc case CTRL('l'): /* cursor right */ 169134642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 169234642Smarc cursor[unit].x += CHAR_WIDTH; 169334642Smarc dga->x_cursor = TRANX(cursor[unit].x); 169434642Smarc } 169534732Smarc return; 169630391Skarels 169734642Smarc case CTRL('z'): /* clear screen */ 169834642Smarc if (nograph) { 169934642Smarc setup_dragon(unit); 170034642Smarc clear_qd_screen(unit); 170134642Smarc /* home cursor - termcap seems to assume this */ 170234642Smarc cursor[unit].x = 0; 170334642Smarc dga->x_cursor = TRANX(cursor[unit].x); 170434642Smarc cursor[unit].y = 0; 170534642Smarc dga->y_cursor = TRANY(cursor[unit].y); 170634642Smarc } 170734732Smarc return; 170830391Skarels 170934642Smarc case '\033': /* start escape sequence */ 171034642Smarc if (nograph) 171134642Smarc inescape[unit] = 1; 171234732Smarc return; 171334642Smarc 171434642Smarc default: 171534642Smarc if ((chr < ' ') || (chr > '~')) 171634732Smarc return; 171734642Smarc } 171834642Smarc /* 171934642Smarc * setup VIPER operand control registers 172034642Smarc */ 172130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 172230391Skarels write_ID(adder, SRC1_OCR_B, 172334642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 172430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 172530391Skarels write_ID(adder, SRC1_OCR_B, 172634642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 172730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 172830391Skarels write_ID(adder, DST_OCR_B, 172934642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 173030391Skarels write_ID(adder, MASK_1, 0xFFFF); 173130391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 173230391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 173334642Smarc adder->x_clip_min = 0; 173434642Smarc adder->x_clip_max = 1024; 173534642Smarc adder->y_clip_min = 0; 173634642Smarc adder->y_clip_max = 864; 173734642Smarc /* 173834642Smarc * load DESTINATION origin and vectors 173934642Smarc */ 174030391Skarels adder->fast_dest_dy = 0; 174130391Skarels adder->slow_dest_dx = 0; 174230391Skarels adder->error_1 = 0; 174330391Skarels adder->error_2 = 0; 174430391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 174534732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 174630391Skarels adder->destination_x = cursor[unit].x; 174730391Skarels adder->fast_dest_dx = CHAR_WIDTH; 174830391Skarels adder->destination_y = cursor[unit].y; 174930391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 175034642Smarc /* 175134642Smarc * load SOURCE origin and vectors 175234642Smarc */ 175334615Smarc if ((chr - ' ') > (CHARS - 1)) { 175434615Smarc printf("Invalid character (x)%x in blitc\n",chr); 175534615Smarc chr = ' '; 175634615Smarc } 175734642Smarc /* 175834642Smarc * X position is modulo the number of characters per line 175934642Smarc */ 176034615Smarc adder->source_1_x = FONT_X + 176134642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 176234642Smarc /* 176334642Smarc * Point to either first or second row 176434642Smarc */ 176534615Smarc adder->source_1_y = 2048 - 15 * 176634642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 176730391Skarels adder->source_1_dx = CHAR_WIDTH; 176830391Skarels adder->source_1_dy = CHAR_HEIGHT; 176930391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 177030391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 177134642Smarc /* 177234642Smarc * update console cursor coordinates 177334642Smarc */ 177430391Skarels cursor[unit].x += CHAR_WIDTH; 177534642Smarc if (nograph) 177634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 177730391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 177834642Smarc blitc(unit, '\r'); 177934642Smarc blitc(unit, '\n'); 178030391Skarels } 178130391Skarels 178230391Skarels } /* blitc */ 178330391Skarels 178434732Smarc qdreset() { } 178530391Skarels 178634732Smarc /* 178734732Smarc * INTERRUPT SERVICE ROUTINES 178834732Smarc */ 178930391Skarels 179034732Smarc /* 179134732Smarc * Service "DMA DONE" interrupt condition 179234732Smarc */ 179330391Skarels qddint(qd) 179434732Smarc register qd; 179530391Skarels { 179630391Skarels register struct DMAreq_header *header; 179730391Skarels register struct DMAreq *request; 179830391Skarels register struct dga *dga; 179930391Skarels struct adder *adder; 180030391Skarels int cookie; /* DMA adrs for QDSS */ 180130391Skarels 180234732Smarc (void)spl4(); /* allow interval timer in */ 180330391Skarels 180434642Smarc /* 180534642Smarc * init pointers 180634642Smarc */ 180730391Skarels header = DMAheader[qd]; /* register for optimization */ 180830391Skarels dga = (struct dga *) qdmap[qd].dga; 180930391Skarels adder = (struct adder *) qdmap[qd].adder; 181030391Skarels 181134642Smarc /* 181234642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 181334642Smarc */ 181430391Skarels if (DMA_ISIGNORE(header)) { 181534642Smarc DMA_CLRIGNORE(header); 181634642Smarc return; 181730391Skarels } 181830391Skarels 181934642Smarc /* 182034642Smarc * dump a DMA hardware error message if appropriate 182134642Smarc */ 182230391Skarels if (dga->csr & DMA_ERR) { 182330391Skarels 182434642Smarc if (dga->csr & PARITY_ERR) 182534732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 182630391Skarels 182734642Smarc if (dga->csr & BUS_ERR) 182834732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 182930391Skarels } 183030391Skarels 183134642Smarc /* 183234642Smarc * if this was a DMA from user space... 183334642Smarc */ 183430391Skarels if (qdflags[qd].user_dma) { 183534642Smarc qdflags[qd].user_dma = 0; 183634642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 183734642Smarc return; 183830391Skarels } 183930391Skarels 184034642Smarc /* 184134642Smarc * if we're doing DMA request queue services, field the error condition 184234642Smarc */ 184330391Skarels if (dga->csr & DMA_ERR) { 184430391Skarels 184534642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 184634642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 184734642Smarc adder->command = CANCEL; /* cancel adder activity */ 184830391Skarels 184934642Smarc DMA_SETERROR(header); /* flag error in header status word */ 185034642Smarc DMA_CLRACTIVE(header); 185134642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 185234642Smarc header->newest = header->oldest; 185334642Smarc header->used = 0; 185430391Skarels 185534732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 185634732Smarc selwakeup(qdrsel[qd], 0); 185734732Smarc qdrsel[qd] = 0; 185834642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 185934642Smarc } 186030391Skarels 186134642Smarc if (dga->bytcnt_lo != 0) { 186234642Smarc dga->bytcnt_lo = 0; 186334642Smarc dga->bytcnt_hi = 0; 186434642Smarc DMA_SETIGNORE(header); 186534642Smarc } 186634642Smarc return; 186730391Skarels } 186830391Skarels 186934642Smarc /* 187034642Smarc * if the DMA request queue is now becoming non-full, 187134642Smarc * wakeup "select" client. 187234642Smarc */ 187330391Skarels if (DMA_ISFULL(header)) { 187434732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 187534732Smarc selwakeup(qdrsel[qd], 0); 187634732Smarc qdrsel[qd] = 0; 187734642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 187834642Smarc } 187930391Skarels } 188030391Skarels 188130391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 188234642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 188330391Skarels 188434615Smarc /* check for unexpected interrupt */ 188534615Smarc if (DMA_ISEMPTY(header)) 188630391Skarels return; 188730391Skarels 188830391Skarels DMA_GETEND(header); /* update request queue indices */ 188930391Skarels 189034642Smarc /* 189134732Smarc * if no more DMA pending, wake up "select" client and exit 189234732Smarc */ 189330391Skarels if (DMA_ISEMPTY(header)) { 189430391Skarels 189534732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 189634732Smarc selwakeup(qdrsel[qd], 0); 189734732Smarc qdrsel[qd] = 0; 189834642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 189934642Smarc } 190030391Skarels 190134642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 190234642Smarc return; 190330391Skarels } 190430391Skarels 190534642Smarc /* 190634732Smarc * initiate next DMA xfer 190734732Smarc */ 190830391Skarels request = DMA_GETBEGIN(header); 190934615Smarc if (request->DMAtype != QDlast_DMAtype) { 191034642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 191134642Smarc adder->command = CANCEL; /* cancel adder activity */ 191234615Smarc } 191330391Skarels 191434615Smarc 191530391Skarels switch (request->DMAtype) { 191630391Skarels 191734642Smarc case DISPLIST: 191834615Smarc if (request->DMAtype != QDlast_DMAtype) { 191934615Smarc dga->csr |= DL_ENB; 192034615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 192134615Smarc } 192230391Skarels break; 192330391Skarels 192434642Smarc case PTOB: 192534615Smarc if (request->DMAtype != QDlast_DMAtype) { 192634615Smarc if (request->DMAdone & BYTE_PACK) 192734642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 192834615Smarc else { 192934615Smarc dga->csr |= PTOB_ENB; 193034615Smarc dga->csr &= ~BYTE_DMA; 193134615Smarc } 193234615Smarc } 193330391Skarels break; 193430391Skarels 193534642Smarc case BTOP: 193634615Smarc if (request->DMAtype != QDlast_DMAtype) { 193734615Smarc if (request->DMAdone & BYTE_PACK) { 193834615Smarc dga->csr &= ~DL_ENB; 193934615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 194034615Smarc } 194134615Smarc else { 194234615Smarc dga->csr |= BTOP_ENB; 194334615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 194434615Smarc } 194534615Smarc } 194630391Skarels break; 194734642Smarc default: 194834732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 194930391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 195030391Skarels return; 195130391Skarels } 195230391Skarels 195330391Skarels if (request->DMAdone & COUNT_ZERO) { 195434642Smarc dga->csr &= ~SET_DONE_FIFO; 195534642Smarc } 195634642Smarc else if (request->DMAdone & FIFO_EMPTY) { 195734642Smarc dga->csr |= SET_DONE_FIFO; 195830391Skarels } 195930391Skarels 196030391Skarels if (request->DMAdone & WORD_PACK) 196130391Skarels dga->csr &= ~BYTE_DMA; 196230391Skarels else if (request->DMAdone & BYTE_PACK) 196330391Skarels dga->csr |= BYTE_DMA; 196430391Skarels 196530391Skarels dga->csr |= DMA_IE; 196634642Smarc QDlast_DMAtype = request->DMAtype; 196730391Skarels 196830391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 196930391Skarels 197030391Skarels dga->adrs_lo = (short) cookie; 197130391Skarels dga->adrs_hi = (short) (cookie >> 16); 197230391Skarels 197330391Skarels dga->bytcnt_lo = (short) request->length; 197430391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 197530391Skarels 197630391Skarels return; 197730391Skarels } 197830391Skarels 197934732Smarc /* 198034732Smarc * ADDER interrupt service routine 198134732Smarc */ 198230391Skarels qdaint(qd) 198334732Smarc register qd; 198430391Skarels { 198530391Skarels register struct adder *adder; 198630391Skarels struct color_buf *cbuf; 198730391Skarels int i; 198830391Skarels register struct rgb *rgbp; 198930391Skarels register short *red; 199030391Skarels register short *green; 199130391Skarels register short *blue; 199230391Skarels 199334732Smarc (void)spl4(); /* allow interval timer in */ 199430391Skarels 199530391Skarels adder = (struct adder *) qdmap[qd].adder; 199630391Skarels 199734642Smarc /* 199834642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 199934642Smarc * any pending color map load request 200034642Smarc */ 200130391Skarels if (adder->status & VSYNC) { 200234642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 200334642Smarc cbuf = color_buf[qd]; 200434642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 200530391Skarels 200634642Smarc red = (short *) qdmap[qd].red; 200734642Smarc green = (short *) qdmap[qd].green; 200834642Smarc blue = (short *) qdmap[qd].blue; 200930391Skarels 201034642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 201134642Smarc --i >= 0; rgbp++) { 201234642Smarc red[rgbp->offset] = (short) rgbp->red; 201334642Smarc green[rgbp->offset] = (short) rgbp->green; 201434642Smarc blue[rgbp->offset] = (short) rgbp->blue; 201534642Smarc } 201630391Skarels 201734642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 201830391Skarels } 201930391Skarels } 202030391Skarels 202134642Smarc /* 202234642Smarc * service the scroll interrupt (FRAME_SYNC bit) 202334642Smarc */ 202430391Skarels if (adder->status & FRAME_SYNC) { 202534642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 202630391Skarels 202734642Smarc if (scroll[qd]->status & LOAD_REGS) { 202830391Skarels 202934732Smarc for (i = 1000, adder->status = 0; i > 0 && 203034732Smarc !(adder->status&ID_SCROLL_READY); --i) 203134642Smarc ; 203230391Skarels 203334642Smarc if (i == 0) { 203434732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 203534642Smarc qd); 203634642Smarc return; 203734642Smarc } 203830391Skarels 203934642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 204034642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 204130391Skarels 204234642Smarc adder->y_scroll_constant = 204334642Smarc scroll[qd]->y_scroll_constant; 204434642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 204530391Skarels 204634642Smarc if (scroll[qd]->status & LOAD_INDEX) { 204730391Skarels 204834642Smarc adder->x_index_pending = 204934642Smarc scroll[qd]->x_index_pending; 205034642Smarc adder->y_index_pending = 205134642Smarc scroll[qd]->y_index_pending; 205234642Smarc } 205334642Smarc 205434642Smarc scroll[qd]->status = 0x00; 205530391Skarels } 205630391Skarels } 205730391Skarels } 205830391Skarels 205934732Smarc /* 206034732Smarc * DUART input interrupt service routine 206134732Smarc * 206234732Smarc * XXX - this routine should be broken out - it is essentially 206334732Smarc * straight line code. 206434732Smarc */ 206530391Skarels 206630391Skarels qdiint(qd) 206734732Smarc register qd; 206830391Skarels { 206930391Skarels register struct _vs_event *event; 207030391Skarels register struct qdinput *eqh; 207130391Skarels struct dga *dga; 207230391Skarels struct duart *duart; 207330391Skarels struct mouse_report *new_rep; 207430391Skarels struct uba_device *ui; 207530391Skarels struct tty *tp; 207634615Smarc u_short chr; 207730391Skarels u_short status; 207830391Skarels u_short data; 207930391Skarels u_short key; 208030391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 208130391Skarels char a, b, c; /* mouse button test variables */ 208230391Skarels 208334732Smarc (void)spl4(); /* allow interval timer in */ 208430391Skarels 208530391Skarels eqh = eq_header[qd]; /* optimized as a register */ 208630391Skarels new_rep = ¤t_rep[qd]; 208730391Skarels duart = (struct duart *) qdmap[qd].duart; 208830391Skarels 208934642Smarc /* 209034732Smarc * if the graphic device is turned on.. 209134732Smarc */ 209230391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 209334642Smarc /* 209434642Smarc * empty DUART 209534642Smarc */ 209634732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 209734642Smarc /* 209834732Smarc * pick up LK-201 input (if any) 209934732Smarc */ 210034732Smarc if (duart->statusA&RCV_RDY) { 210130391Skarels 210234642Smarc /* if error condition, then reset it */ 210330391Skarels 210434732Smarc if (duart->statusA&0x70) { 210534642Smarc duart->cmdA = 0x40; 210634642Smarc continue; 210734642Smarc } 210830391Skarels 210934642Smarc /* event queue full now? (overflow condition) */ 211030391Skarels 211134642Smarc if (ISFULL(eqh) == TRUE) { 211234642Smarc printf( 211334732Smarc "qd%d: qdiint: event queue overflow\n", 211434642Smarc qd); 211534642Smarc break; 211634642Smarc } 211730391Skarels 211834642Smarc /* 211934642Smarc * Check for various keyboard errors */ 212030391Skarels 212134642Smarc key = duart->dataA & 0xFF; 212230391Skarels 212334642Smarc if (key==LK_POWER_ERROR || 212434642Smarc key==LK_KDOWN_ERROR || 212534642Smarc key == LK_INPUT_ERROR || 212634642Smarc key == LK_OUTPUT_ERROR) { 212734642Smarc printf( 212834732Smarc "qd%d: qdiint: keyboard error, code = %x\n", 212934642Smarc qd,key); 213034732Smarc return; 213134642Smarc } 213230391Skarels 213334642Smarc if (key < LK_LOWEST) 213434732Smarc return; 213530391Skarels 213634642Smarc ++do_wakeup; /* request a select wakeup call */ 213730391Skarels 213834642Smarc event = PUTBEGIN(eqh); 213934642Smarc PUTEND(eqh); 214030391Skarels 214134642Smarc event->vse_key = key; 214234642Smarc event->vse_key &= 0x00FF; 214334642Smarc event->vse_x = eqh->curs_pos.x; 214434642Smarc event->vse_y = eqh->curs_pos.y; 214534642Smarc event->vse_time = TOY; 214634642Smarc event->vse_type = VSE_BUTTON; 214734642Smarc event->vse_direction = VSE_KBTRAW; 214834642Smarc event->vse_device = VSE_DKB; 214934642Smarc } 215030391Skarels 215134642Smarc /* 215234642Smarc * pick up the mouse input (if any) */ 215330391Skarels 215434642Smarc if ((status = duart->statusB) & RCV_RDY && 215534642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 215630391Skarels 215734642Smarc if (status & 0x70) { 215834642Smarc duart->cmdB = 0x40; 215934642Smarc continue; 216034642Smarc } 216130391Skarels 216234642Smarc /* event queue full now? (overflow condition) */ 216330391Skarels 216434642Smarc if (ISFULL(eqh) == TRUE) { 216534642Smarc printf( 216634732Smarc "qd%d: qdiint: event queue overflow\n", 216734642Smarc qd); 216834642Smarc break; 216934642Smarc } 217030391Skarels 217134642Smarc data = duart->dataB; /* get report byte */ 217234642Smarc ++new_rep->bytcnt; /* bump report byte count */ 217330391Skarels 217434642Smarc /* 217534642Smarc * if 1st byte of report.. */ 217630391Skarels 217734642Smarc if ( data & START_FRAME) { 217834642Smarc new_rep->state = data; 217934642Smarc if (new_rep->bytcnt > 1) { 218034642Smarc /* start of new frame */ 218134642Smarc new_rep->bytcnt = 1; 218234642Smarc /* ..continue looking */ 218334642Smarc continue; 218434642Smarc } 218534642Smarc } 218630391Skarels 218734642Smarc /* 218834642Smarc * if 2nd byte of report.. */ 218930391Skarels 219034642Smarc else if (new_rep->bytcnt == 2) { 219134642Smarc new_rep->dx = data & 0x00FF; 219234642Smarc } 219330391Skarels 219434642Smarc /* 219534642Smarc * if 3rd byte of report, load input event queue */ 219630391Skarels 219734642Smarc else if (new_rep->bytcnt == 3) { 219830391Skarels 219934642Smarc new_rep->dy = data & 0x00FF; 220034642Smarc new_rep->bytcnt = 0; 220130391Skarels 220234642Smarc /* 220334642Smarc * if mouse position has changed.. */ 220430391Skarels 220534642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 220630391Skarels 220734642Smarc /* 220834642Smarc * calculate acceleration factor, if needed */ 220930391Skarels 221034642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 221130391Skarels 221234642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 221334642Smarc new_rep->dx += 221434642Smarc (new_rep->dx - qdflags[qd].curs_thr) 221534642Smarc * qdflags[qd].curs_acc; 221630391Skarels 221734642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 221834642Smarc new_rep->dy += 221934642Smarc (new_rep->dy - qdflags[qd].curs_thr) 222034642Smarc * qdflags[qd].curs_acc; 222134642Smarc } 222230391Skarels 222334642Smarc /* 222434642Smarc * update cursor position coordinates */ 222530391Skarels 222634642Smarc if (new_rep->state & X_SIGN) { 222734642Smarc eqh->curs_pos.x += new_rep->dx; 222834642Smarc if (eqh->curs_pos.x > 1023) 222934642Smarc eqh->curs_pos.x = 1023; 223034642Smarc } 223134642Smarc else { 223234642Smarc eqh->curs_pos.x -= new_rep->dx; 223334642Smarc if (eqh->curs_pos.x < -15) 223434642Smarc eqh->curs_pos.x = -15; 223534642Smarc } 223630391Skarels 223734642Smarc if (new_rep->state & Y_SIGN) { 223834642Smarc eqh->curs_pos.y -= new_rep->dy; 223934642Smarc if (eqh->curs_pos.y < -15) 224034642Smarc eqh->curs_pos.y = -15; 224134642Smarc } 224234642Smarc else { 224334642Smarc eqh->curs_pos.y += new_rep->dy; 224434642Smarc if (eqh->curs_pos.y > 863) 224534642Smarc eqh->curs_pos.y = 863; 224634642Smarc } 224730391Skarels 224834642Smarc /* 224934642Smarc * update cursor screen position */ 225030391Skarels 225134642Smarc dga = (struct dga *) qdmap[qd].dga; 225234642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 225334642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 225430391Skarels 225534642Smarc /* 225634642Smarc * if cursor is in the box, no event report */ 225730391Skarels 225834642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 225934642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 226034642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 226134642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 226234642Smarc goto GET_MBUTTON; 226334642Smarc } 226430391Skarels 226534642Smarc /* 226634642Smarc * report the mouse motion event */ 226730391Skarels 226834642Smarc event = PUTBEGIN(eqh); 226934642Smarc PUTEND(eqh); 227030391Skarels 227134642Smarc ++do_wakeup; /* request a select wakeup call */ 227230391Skarels 227334642Smarc event->vse_x = eqh->curs_pos.x; 227434642Smarc event->vse_y = eqh->curs_pos.y; 227530391Skarels 227634642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 227734642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 227834642Smarc event->vse_key = 0; 227934642Smarc event->vse_direction = 0; 228034642Smarc event->vse_time = TOY; /* time stamp */ 228134642Smarc } 228230391Skarels 228330391Skarels GET_MBUTTON: 228434642Smarc /* 228534642Smarc * if button state has changed */ 228630391Skarels 228734642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 228834642Smarc b = last_rep[qd].state & 0x07; 228930391Skarels 229034642Smarc if (a ^ b) { 229130391Skarels 229234642Smarc for ( c = 1; c < 8; c <<= 1) { 229330391Skarels 229434642Smarc if (!( c & (a ^ b))) /* this button change? */ 229534642Smarc continue; 229630391Skarels 229734642Smarc /* event queue full? (overflow condition) */ 229830391Skarels 229934642Smarc if (ISFULL(eqh) == TRUE) { 230034732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 230134642Smarc break; 230234642Smarc } 230330391Skarels 230434642Smarc event = PUTBEGIN(eqh); /* get new event */ 230534642Smarc PUTEND(eqh); 230630391Skarels 230734642Smarc ++do_wakeup; /* request select wakeup */ 230830391Skarels 230934642Smarc event->vse_x = eqh->curs_pos.x; 231034642Smarc event->vse_y = eqh->curs_pos.y; 231130391Skarels 231234642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 231334642Smarc event->vse_type = VSE_BUTTON; /* new button */ 231434642Smarc event->vse_time = TOY; /* time stamp */ 231530391Skarels 231634642Smarc /* flag changed button and if up or down */ 231730391Skarels 231834642Smarc if (c == RIGHT_BUTTON) 231934642Smarc event->vse_key = VSE_RIGHT_BUTTON; 232034642Smarc else if (c == MIDDLE_BUTTON) 232134642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 232234642Smarc else if (c == LEFT_BUTTON) 232334642Smarc event->vse_key = VSE_LEFT_BUTTON; 232430391Skarels 232534642Smarc /* set bit = button depressed */ 232630391Skarels 232734642Smarc if (c & a) 232834642Smarc event->vse_direction = VSE_KBTDOWN; 232934642Smarc else 233034642Smarc event->vse_direction = VSE_KBTUP; 233134642Smarc } 233234642Smarc } 233330391Skarels 233434642Smarc /* refresh last report */ 233530391Skarels 233634642Smarc last_rep[qd] = current_rep[qd]; 233730391Skarels 233834642Smarc } /* get last byte of report */ 233934732Smarc } else if ((status = duart->statusB)&RCV_RDY && 234034732Smarc qdflags[qd].pntr_id == TABLET_ID) { 234134732Smarc /* 234234732Smarc * pickup tablet input, if any 234334732Smarc */ 234434732Smarc if (status&0x70) { 234534642Smarc duart->cmdB = 0x40; 234634642Smarc continue; 234734642Smarc } 234834732Smarc /* 234934732Smarc * event queue full now? (overflow condition) 235034732Smarc */ 235134642Smarc if (ISFULL(eqh) == TRUE) { 235234732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 235334642Smarc break; 235434642Smarc } 235530391Skarels 235634642Smarc data = duart->dataB; /* get report byte */ 235734642Smarc ++new_rep->bytcnt; /* bump report byte count */ 235830391Skarels 235934642Smarc /* 236034642Smarc * if 1st byte of report.. */ 236130391Skarels 236234642Smarc if (data & START_FRAME) { 236334642Smarc new_rep->state = data; 236434642Smarc if (new_rep->bytcnt > 1) { 236534642Smarc new_rep->bytcnt = 1; /* start of new frame */ 236634642Smarc continue; /* ..continue looking */ 236734642Smarc } 236834642Smarc } 236930391Skarels 237034642Smarc /* 237134642Smarc * if 2nd byte of report.. */ 237230391Skarels 237334642Smarc else if (new_rep->bytcnt == 2) { 237434642Smarc new_rep->dx = data & 0x3F; 237534642Smarc } 237630391Skarels 237734642Smarc /* 237834642Smarc * if 3rd byte of report.. */ 237930391Skarels 238034642Smarc else if (new_rep->bytcnt == 3) { 238134642Smarc new_rep->dx |= (data & 0x3F) << 6; 238234642Smarc } 238330391Skarels 238434642Smarc /* 238534642Smarc * if 4th byte of report.. */ 238630391Skarels 238734642Smarc else if (new_rep->bytcnt == 4) { 238834642Smarc new_rep->dy = data & 0x3F; 238934642Smarc } 239030391Skarels 239134642Smarc /* 239234642Smarc * if 5th byte of report, load input event queue */ 239330391Skarels 239434642Smarc else if (new_rep->bytcnt == 5) { 239530391Skarels 239634642Smarc new_rep->dy |= (data & 0x3F) << 6; 239734642Smarc new_rep->bytcnt = 0; 239830391Skarels 239934642Smarc /* 240034642Smarc * update cursor position coordinates */ 240130391Skarels 240234642Smarc new_rep->dx /= qdflags[qd].tab_res; 240334642Smarc new_rep->dy = (2200 - new_rep->dy) 240434642Smarc / qdflags[qd].tab_res; 240530391Skarels 240634642Smarc if (new_rep->dx > 1023) { 240734642Smarc new_rep->dx = 1023; 240834642Smarc } 240934642Smarc if (new_rep->dy > 863) { 241034642Smarc new_rep->dy = 863; 241134642Smarc } 241230391Skarels 241334642Smarc /* 241434642Smarc * report an event if the puck/stylus has moved 241534642Smarc */ 241630391Skarels 241734642Smarc if (eqh->curs_pos.x != new_rep->dx || 241834642Smarc eqh->curs_pos.y != new_rep->dy) { 241930391Skarels 242034642Smarc eqh->curs_pos.x = new_rep->dx; 242134642Smarc eqh->curs_pos.y = new_rep->dy; 242230391Skarels 242334642Smarc /* 242434642Smarc * update cursor screen position */ 242530391Skarels 242634642Smarc dga = (struct dga *) qdmap[qd].dga; 242734642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 242834642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 242930391Skarels 243034642Smarc /* 243134642Smarc * if cursor is in the box, no event report 243234642Smarc */ 243330391Skarels 243434642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 243534642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 243634642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 243734642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 243834642Smarc goto GET_TBUTTON; 243934642Smarc } 244030391Skarels 244134642Smarc /* 244234642Smarc * report the tablet motion event */ 244330391Skarels 244434642Smarc event = PUTBEGIN(eqh); 244534642Smarc PUTEND(eqh); 244630391Skarels 244734642Smarc ++do_wakeup; /* request a select wakeup call */ 244830391Skarels 244934642Smarc event->vse_x = eqh->curs_pos.x; 245034642Smarc event->vse_y = eqh->curs_pos.y; 245130391Skarels 245234642Smarc event->vse_device = VSE_TABLET; /* tablet */ 245334642Smarc /* 245434642Smarc * right now, X handles tablet motion the same 245534642Smarc * as mouse motion 245634642Smarc */ 245734642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 245834642Smarc event->vse_key = 0; 245934642Smarc event->vse_direction = 0; 246034642Smarc event->vse_time = TOY; /* time stamp */ 246134642Smarc } 246230391Skarels GET_TBUTTON: 246334642Smarc /* 246434642Smarc * if button state has changed */ 246530391Skarels 246634642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 246734642Smarc b = last_rep[qd].state & 0x1E; 246830391Skarels 246934642Smarc if (a ^ b) { 247030391Skarels 247134642Smarc /* event queue full now? (overflow condition) */ 247230391Skarels 247334642Smarc if (ISFULL(eqh) == TRUE) { 247434732Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 247534642Smarc break; 247634642Smarc } 247730391Skarels 247834642Smarc event = PUTBEGIN(eqh); /* get new event */ 247934642Smarc PUTEND(eqh); 248030391Skarels 248134642Smarc ++do_wakeup; /* request a select wakeup call */ 248230391Skarels 248334642Smarc event->vse_x = eqh->curs_pos.x; 248434642Smarc event->vse_y = eqh->curs_pos.y; 248530391Skarels 248634642Smarc event->vse_device = VSE_TABLET; /* tablet */ 248734642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 248834642Smarc event->vse_time = TOY; /* time stamp */ 248930391Skarels 249034642Smarc /* define the changed button and if up or down */ 249130391Skarels 249234642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 249334642Smarc if (c & (a ^ b)) { 249434642Smarc if (c == T_LEFT_BUTTON) 249534642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 249634642Smarc else if (c == T_FRONT_BUTTON) 249734642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 249834642Smarc else if (c == T_RIGHT_BUTTON) 249934642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 250034642Smarc else if (c == T_BACK_BUTTON) 250134642Smarc event->vse_key = VSE_T_BACK_BUTTON; 250234642Smarc break; 250334642Smarc } 250434642Smarc } 250530391Skarels 250634642Smarc /* set bit = button depressed */ 250730391Skarels 250834642Smarc if (c & a) 250934642Smarc event->vse_direction = VSE_KBTDOWN; 251034642Smarc else 251134642Smarc event->vse_direction = VSE_KBTUP; 251234642Smarc } 251330391Skarels 251434642Smarc /* refresh last report */ 251530391Skarels 251634642Smarc last_rep[qd] = current_rep[qd]; 251730391Skarels 251834642Smarc } /* get last byte of report */ 251934642Smarc } /* pick up tablet input */ 252030391Skarels 252134642Smarc } /* while input available.. */ 252230391Skarels 252334642Smarc /* 252434642Smarc * do select wakeup 252534642Smarc */ 252634732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 252734732Smarc selwakeup(qdrsel[qd], 0); 252834732Smarc qdrsel[qd] = 0; 252934642Smarc qdflags[qd].selmask &= ~SEL_READ; 253034642Smarc do_wakeup = 0; 253134642Smarc } 253234732Smarc } else { 253334732Smarc /* 253434732Smarc * if the graphic device is not turned on, this is console input 253534732Smarc */ 253634642Smarc ui = qdinfo[qd]; 253734642Smarc if (ui == 0 || ui->ui_alive == 0) 253834732Smarc return; 253930391Skarels 254034642Smarc tp = &qd_tty[qd << 2]; 254130391Skarels 254234642Smarc /* 254334732Smarc * Get a character from the keyboard. 254434732Smarc */ 254534732Smarc while (duart->statusA&RCV_RDY) { 254634642Smarc key = duart->dataA; 254734642Smarc key &= 0xFF; 254834642Smarc /* 254934732Smarc * Check for various keyboard errors 255034732Smarc */ 255134732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 255234642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 255334732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 255434732Smarc return; 255534642Smarc } 255630391Skarels 255734642Smarc if (key < LK_LOWEST) 255834732Smarc return; 255930391Skarels 256034642Smarc /* 256134642Smarc * See if its a state change key */ 256230391Skarels 256334642Smarc switch (key) { 256430391Skarels 256534642Smarc case LOCK: 256634642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 256734642Smarc if (q_keyboard.lock) 256834732Smarc (void)led_control(qd, LK_LED_ENABLE, 256934732Smarc LK_LED_LOCK); 257034642Smarc else 257134732Smarc (void)led_control(qd, LK_LED_DISABLE, 257234732Smarc LK_LED_LOCK); 257334642Smarc return; 257430391Skarels 257534642Smarc case SHIFT: 257634642Smarc q_keyboard.shift ^= 0xFFFF; 257734642Smarc return; 257830391Skarels 257934642Smarc case CNTRL: 258034642Smarc q_keyboard.cntrl ^= 0xFFFF; 258134642Smarc return; 258230391Skarels 258334642Smarc case ALLUP: 258434642Smarc q_keyboard.cntrl = 0; 258534642Smarc q_keyboard.shift = 0; 258634642Smarc return; 258730391Skarels 258834642Smarc case REPEAT: 258934642Smarc chr = q_keyboard.last; 259034642Smarc break; 259130391Skarels 259234642Smarc /* 259334642Smarc * Test for cntrl characters. If set, see if the character 259434642Smarc * is elligible to become a control character. */ 259530391Skarels 259634642Smarc default: 259730391Skarels 259834642Smarc if (q_keyboard.cntrl) { 259934642Smarc chr = q_key[key]; 260034642Smarc if (chr >= ' ' && chr <= '~') 260134642Smarc chr &= 0x1F; 260234642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 260334642Smarc chr &= 0x9F; 260434642Smarc } 260534642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 260634642Smarc chr = q_shift_key[key]; 260734642Smarc else 260834642Smarc chr = q_key[key]; 260934642Smarc break; 261030391Skarels } 261130391Skarels 261234642Smarc q_keyboard.last = chr; 261330391Skarels 261434642Smarc /* 261534642Smarc * Check for special function keys */ 261630391Skarels 261734642Smarc if (chr & 0x100) { 261834642Smarc char *string; 261934642Smarc string = q_special[chr & 0x7F]; 262034642Smarc while(*string) 262134642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 262234615Smarc } 262334642Smarc else { 262434642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 262534642Smarc } 262630391Skarels } 262730391Skarels } 262830391Skarels } /* qdiint */ 262930391Skarels 263034732Smarc /* 263134732Smarc * 263234732Smarc * Clear the QDSS screen 263334732Smarc * 263434732Smarc * >>> NOTE <<< 263534732Smarc * 263634732Smarc * This code requires that certain adder initialization be valid. To 263734732Smarc * assure that this requirement is satisfied, this routine should be 263834732Smarc * called only after calling the "setup_dragon()" function. 263934732Smarc * 264034732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear 264134732Smarc * only clears the current displayed portion of the bitmap put a 264234732Smarc * temporary value in the y limit register so we can access whole 264334732Smarc * bitmap 264434732Smarc * 264534732Smarc */ 264630391Skarels clear_qd_screen(unit) 264734732Smarc int unit; 264830391Skarels { 264930391Skarels register struct adder *adder; 265030391Skarels adder = (struct adder *) qdmap[unit].adder; 265130391Skarels 265230391Skarels adder->x_limit = 1024; 265330391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 265430391Skarels adder->y_offset_pending = 0; 265534732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 265634642Smarc WSV; 265730391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265834642Smarc WSV; 265930391Skarels adder->y_offset_pending = 864; 266034642Smarc WSV; 266130391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266234642Smarc WSV; 266330391Skarels adder->y_offset_pending = 1728; 266434642Smarc WSV; 266530391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266634642Smarc WSV; 266730391Skarels adder->y_offset_pending = 0; /* back to normal */ 266834642Smarc WSV; 266930391Skarels adder->x_limit = MAX_SCREEN_X; 267030391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 267134642Smarc #undef WSV 267230391Skarels 267330391Skarels } /* clear_qd_screen */ 267430391Skarels 267534732Smarc /* 267634732Smarc * kernel console output to the glass tty 267734732Smarc */ 267830391Skarels qdputc(chr) 267934642Smarc register char chr; 268030391Skarels { 268130391Skarels 268234642Smarc /* 268334642Smarc * if system is now physical, forget it (ie: crash DUMP) 268434642Smarc */ 268534642Smarc if ((mfpr(MAPEN) & 1) == 0) 268634642Smarc return; 268734615Smarc 268834732Smarc blitc(0, (u_char)(chr & 0xff)); 268932012Smarc if ((chr & 0177) == '\n') 269032012Smarc blitc(0, '\r'); 269130391Skarels 269230391Skarels } /* qdputc */ 269330391Skarels 269434732Smarc /* 269534732Smarc * load the mouse cursor's template RAM bitmap 269634732Smarc */ 269730391Skarels ldcursor(unit, bitmap) 269834732Smarc int unit; 269934732Smarc register short *bitmap; 270030391Skarels { 270130391Skarels register struct dga *dga; 270230391Skarels register short *temp; 270330391Skarels register int i; 270434732Smarc int curs; 270530391Skarels 270630391Skarels dga = (struct dga *) qdmap[unit].dga; 270730391Skarels temp = (short *) qdmap[unit].template; 270830391Skarels 270930391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 271034732Smarc curs = -1; /* ..note that.. */ 271134642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 271234732Smarc } else 271334732Smarc curs = 0; 271430391Skarels 271530391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 271630391Skarels 271730391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 271834642Smarc /* ..of the 8k WORD template space */ 271930391Skarels for (i = 0; i < 32; ++i) 272034642Smarc *temp++ = *bitmap++; 272130391Skarels 272234732Smarc if (curs) { /* if cursor was enabled.. */ 272334642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 272430391Skarels } 272530391Skarels 272630391Skarels } /* ldcursor */ 272730391Skarels 272834732Smarc /* 272934732Smarc * Put the console font in the QDSS off-screen memory 273034732Smarc */ 273130391Skarels ldfont(unit) 273234732Smarc int unit; 273330391Skarels { 273430391Skarels register struct adder *adder; 273530391Skarels 273634732Smarc register i, j, k, max_chars_line; 273734732Smarc register short packed; 273830391Skarels 273930391Skarels adder = (struct adder *) qdmap[unit].adder; 274030391Skarels 274134642Smarc /* 274234732Smarc * setup VIPER operand control registers 274334732Smarc */ 274430391Skarels write_ID(adder, MASK_1, 0xFFFF); 274530391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 274630391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 274730391Skarels 274830391Skarels write_ID(adder, SRC1_OCR_B, 274934642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 275030391Skarels write_ID(adder, SRC2_OCR_B, 275134642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 275230391Skarels write_ID(adder, DST_OCR_B, 275334642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 275430391Skarels 275530391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 275630391Skarels 275734642Smarc /* 275834732Smarc * load destination data 275934732Smarc */ 276034732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 276130391Skarels 276230391Skarels adder->destination_x = FONT_X; 276330391Skarels adder->destination_y = FONT_Y; 276434732Smarc #if FONT_WIDTH > MAX_SCREEN_X 276534732Smarc adder->fast_dest_dx = MAX_SCREEN_X; 276634732Smarc #else 276734732Smarc adder->fast_dest_dx = FONT_WIDTH; 276834732Smarc #endif 276930391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 277030391Skarels 277134642Smarc /* 277234642Smarc * setup for processor to bitmap xfer */ 277330391Skarels 277430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 277530391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 277630391Skarels 277734642Smarc /* 277834642Smarc * Figure out how many characters can be stored on one "line" of 277934642Smarc * offscreen memory. 278034642Smarc */ 278134642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 278234642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 278334642Smarc max_chars_line = CHARS/2 + CHARS%2; 278430391Skarels 278534642Smarc /* 278634642Smarc * iteratively do the processor to bitmap xfer */ 278734615Smarc 278830391Skarels for (i = 0; i < ROWS; ++i) { 278930391Skarels 279034642Smarc /* PTOB a scan line */ 279130391Skarels 279234642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 279334642Smarc /* PTOB one scan of a char cell */ 279430391Skarels 279534642Smarc packed = q_font[k]; 279634642Smarc k += ROWS; 279734642Smarc packed |= ((short)q_font[k] << 8); 279834642Smarc k += ROWS; 279930391Skarels 280034732Smarc (void)wait_status(adder, TX_READY); 280134642Smarc adder->id_data = packed; 280234642Smarc } 280330391Skarels } 280430391Skarels 280534642Smarc /* 280634642Smarc * (XXX XXX XXX - should remove) 280734642Smarc * 280834642Smarc * Copy the second row of characters. Subtract the first 280934642Smarc * row from the total number. Divide this quantity by 2 281034642Smarc * because 2 chars are stored in a short in the PTOB loop 281134642Smarc * below. Figure out how many characters can be stored on 281234642Smarc * one "line" of offscreen memory 281334642Smarc */ 281434642Smarc 281534642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 281634642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 281734642Smarc return; 281834642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 281934642Smarc /* Paranoia check to see if 3rd row may be needed */ 282034642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 282134615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 282234615Smarc 282334615Smarc adder->destination_x = FONT_X; 282434615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 282534615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 282634615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 282734615Smarc 282834642Smarc /* 282934642Smarc * setup for processor to bitmap xfer 283034642Smarc */ 283134615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 283234615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 283334615Smarc 283434642Smarc /* 283534642Smarc * iteratively do the processor to bitmap xfer 283634642Smarc */ 283734615Smarc for (i = 0; i < ROWS; ++i) { 283834642Smarc /* 283934642Smarc * PTOB a scan line 284034642Smarc */ 284134642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 284234642Smarc /* 284334642Smarc * PTOB one scan of a char cell 284434642Smarc */ 284534642Smarc packed = q_font[k + FONT_OFFSET]; 284634642Smarc k += ROWS; 284734642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 284834642Smarc k += ROWS; 284934732Smarc (void)wait_status(adder, TX_READY); 285034642Smarc adder->id_data = packed; 285134642Smarc } 285234615Smarc } 285334615Smarc 285430391Skarels } /* ldfont */ 285530391Skarels 285634732Smarc /* 285734732Smarc * Get a character from the LK201 (polled) 285834732Smarc */ 285934732Smarc qdgetc() 286034732Smarc { 286134732Smarc register short key; 286234732Smarc register char chr; 286334732Smarc register struct duart *duart; 286430391Skarels 286534732Smarc duart = (struct duart *) qdmap[0].duart; 286634732Smarc 286734732Smarc /* 286834732Smarc * Get a character from the keyboard. 286934732Smarc */ 287034732Smarc LOOP: 287134732Smarc while (!(duart->statusA&RCV_RDY)) 287234732Smarc ; 287334732Smarc 287434732Smarc key = duart->dataA; 287534732Smarc key &= 0xFF; 287634732Smarc 287734732Smarc /* 287834732Smarc * Check for various keyboard errors */ 287934732Smarc 288034732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 288134732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 288234732Smarc printf("Keyboard error, code = %x\n", key); 288334732Smarc return(0); 288434732Smarc } 288534732Smarc 288634732Smarc if (key < LK_LOWEST) 288734732Smarc return(0); 288834732Smarc 288934732Smarc /* 289034732Smarc * See if its a state change key 289134732Smarc */ 289234732Smarc switch (key) { 289334732Smarc 289434732Smarc case LOCK: 289534732Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 289634732Smarc if (q_keyboard.lock) 289734732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 289834732Smarc else 289934732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 290034732Smarc goto LOOP; 290134732Smarc 290234732Smarc case SHIFT: 290334732Smarc q_keyboard.shift ^= 0xFFFF; 290434732Smarc goto LOOP; 290534732Smarc 290634732Smarc case CNTRL: 290734732Smarc q_keyboard.cntrl ^= 0xFFFF; 290834732Smarc goto LOOP; 290934732Smarc 291034732Smarc case ALLUP: 291134732Smarc q_keyboard.cntrl = 0; 291234732Smarc q_keyboard.shift = 0; 291334732Smarc goto LOOP; 291434732Smarc 291534732Smarc case REPEAT: 291634732Smarc chr = q_keyboard.last; 291734732Smarc break; 291834732Smarc 291934732Smarc /* 292034732Smarc * Test for cntrl characters. If set, see if the character 292134732Smarc * is elligible to become a control character. 292234732Smarc */ 292334732Smarc default: 292434732Smarc 292534732Smarc if (q_keyboard.cntrl) { 292634732Smarc chr = q_key[key]; 292734732Smarc if (chr >= ' ' && chr <= '~') 292834732Smarc chr &= 0x1F; 292934732Smarc } 293034732Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 293134732Smarc chr = q_shift_key[key]; 293234732Smarc else 293334732Smarc chr = q_key[key]; 293434732Smarc break; 293534732Smarc } 293634732Smarc 293734732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 293834732Smarc return(0); /* ..then pitch it! */ 293934732Smarc 294034732Smarc q_keyboard.last = chr; 294134732Smarc 294234732Smarc /* 294334732Smarc * Check for special function keys */ 294434732Smarc 294534732Smarc if (chr & 0x80) /* pitch the function keys */ 294634732Smarc return(0); 294734732Smarc else 294834732Smarc return(chr); 294934732Smarc 295034732Smarc } /* qdgetc */ 295134732Smarc 295234732Smarc /* 295334732Smarc * led_control()... twiddle LK-201 LED's 295434732Smarc */ 295530391Skarels led_control(unit, cmd, led_mask) 295634732Smarc int unit, cmd, led_mask; 295730391Skarels { 295834732Smarc register i; 295930391Skarels register struct duart *duart; 296030391Skarels 296134732Smarc duart = (struct duart *)qdmap[unit].duart; 296230391Skarels 296330391Skarels for (i = 1000; i > 0; --i) { 296434732Smarc if (duart->statusA&XMT_RDY) { 296534642Smarc duart->dataA = cmd; 296634642Smarc break; 296734642Smarc } 296830391Skarels } 296930391Skarels for (i = 1000; i > 0; --i) { 297034732Smarc if (duart->statusA&XMT_RDY) { 297134642Smarc duart->dataA = led_mask; 297234642Smarc break; 297334642Smarc } 297430391Skarels } 297530391Skarels if (i == 0) 297634642Smarc return(BAD); 297730391Skarels return(GOOD); 297830391Skarels 297930391Skarels } /* led_control */ 298030391Skarels 298134732Smarc /* 298234732Smarc * scroll_up()... move the screen up one character height 298334732Smarc */ 298430391Skarels scroll_up(adder) 298534642Smarc register struct adder *adder; 298630391Skarels { 298734642Smarc /* 298834642Smarc * setup VIPER operand control registers 298934642Smarc */ 299034732Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 299130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 299230391Skarels write_ID(adder, MASK_1, 0xFFFF); 299330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 299430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 299530391Skarels write_ID(adder, SRC1_OCR_B, 299634642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 299730391Skarels write_ID(adder, DST_OCR_B, 299834642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 299934642Smarc /* 300034642Smarc * load DESTINATION origin and vectors 300134642Smarc */ 300230391Skarels adder->fast_dest_dy = 0; 300330391Skarels adder->slow_dest_dx = 0; 300430391Skarels adder->error_1 = 0; 300530391Skarels adder->error_2 = 0; 300630391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 300730391Skarels adder->destination_x = 0; 300830391Skarels adder->fast_dest_dx = 1024; 300930391Skarels adder->destination_y = 0; 301030391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 301134642Smarc /* 301234642Smarc * load SOURCE origin and vectors 301334642Smarc */ 301430391Skarels adder->source_1_x = 0; 301530391Skarels adder->source_1_dx = 1024; 301630391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 301730391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 301830391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 301930391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 302034642Smarc /* 302134642Smarc * do a rectangle clear of last screen line 302234642Smarc */ 302330391Skarels write_ID(adder, MASK_1, 0xffff); 302430391Skarels write_ID(adder, SOURCE, 0xffff); 302530391Skarels write_ID(adder,DST_OCR_B, 302634642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 302730391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 302830391Skarels adder->error_1 = 0; 302930391Skarels adder->error_2 = 0; 303034642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 303130391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 303230391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 303334732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 303430391Skarels adder->destination_x = 0; 303530391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 303630391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 303730391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 303830391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 303930391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 304030391Skarels 304130391Skarels } /* scroll_up */ 304230391Skarels 304334732Smarc /* 304434732Smarc * init shared memory pointers and structures 304534732Smarc */ 304630391Skarels init_shared(unit) 304734732Smarc register unit; 304830391Skarels { 304930391Skarels register struct dga *dga; 305030391Skarels 305130391Skarels dga = (struct dga *) qdmap[unit].dga; 305230391Skarels 305334642Smarc /* 305434642Smarc * initialize the event queue pointers and header */ 305530391Skarels 305630391Skarels eq_header[unit] = (struct qdinput *) 305734642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 305834642Smarc + (EVENT_BUFSIZE * unit)); 305930391Skarels eq_header[unit]->curs_pos.x = 0; 306030391Skarels eq_header[unit]->curs_pos.y = 0; 306130391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 306230391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 306330391Skarels eq_header[unit]->curs_box.left = 0; 306430391Skarels eq_header[unit]->curs_box.right = 0; 306530391Skarels eq_header[unit]->curs_box.top = 0; 306630391Skarels eq_header[unit]->curs_box.bottom = 0; 306734642Smarc /* 306834642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 306934642Smarc */ 307030391Skarels DMAheader[unit] = (struct DMAreq_header *) 307134642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 307234642Smarc + (DMAbuf_size * unit)); 307330391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 307434642Smarc + sizeof(struct DMAreq_header)); 307530391Skarels DMAheader[unit]->QBAreg = 0; 307630391Skarels DMAheader[unit]->status = 0; 307730391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 307830391Skarels DMAheader[unit]->used = 0; 307930391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 308030391Skarels DMAheader[unit]->oldest = 0; 308130391Skarels DMAheader[unit]->newest = 0; 308234642Smarc /* 308334642Smarc * assign a pointer to the scroll structure for this QDSS. 308434642Smarc */ 308530391Skarels scroll[unit] = (struct scroll *) 308634642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 308734642Smarc + (sizeof(struct scroll) * unit)); 308830391Skarels scroll[unit]->status = 0; 308930391Skarels scroll[unit]->viper_constant = 0; 309030391Skarels scroll[unit]->y_scroll_constant = 0; 309130391Skarels scroll[unit]->y_offset = 0; 309230391Skarels scroll[unit]->x_index_pending = 0; 309330391Skarels scroll[unit]->y_index_pending = 0; 309434642Smarc /* 309534642Smarc * assign a pointer to the color map write buffer for this QDSS 309634642Smarc */ 309730391Skarels color_buf[unit] = (struct color_buf *) 309834642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 309934642Smarc + (COLOR_BUFSIZ * unit)); 310030391Skarels color_buf[unit]->status = 0; 310130391Skarels color_buf[unit]->count = 0; 310230391Skarels 310330391Skarels } /* init_shared */ 310430391Skarels 310534732Smarc /* 310634732Smarc * init the ADDER, VIPER, bitmaps, & color map 310734732Smarc */ 310830391Skarels setup_dragon(unit) 310934732Smarc int unit; 311030391Skarels { 311130391Skarels 311230391Skarels register struct adder *adder; 311330391Skarels register struct dga *dga; 311430391Skarels short *memcsr; 311534732Smarc register i; 311630391Skarels short top; /* clipping/scrolling boundaries */ 311730391Skarels short bottom; 311830391Skarels short right; 311930391Skarels short left; 312030391Skarels short *red; /* color map pointers */ 312130391Skarels short *green; 312230391Skarels short *blue; 312330391Skarels 312434642Smarc /* 312534642Smarc * init for setup 312634642Smarc */ 312730391Skarels adder = (struct adder *) qdmap[unit].adder; 312830391Skarels dga = (struct dga *) qdmap[unit].dga; 312930391Skarels memcsr = (short *) qdmap[unit].memcsr; 313030391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 313130391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 313230391Skarels adder->command = CANCEL; 313334642Smarc /* 313434642Smarc * set monitor timing 313534642Smarc */ 313630391Skarels adder->x_scan_count_0 = 0x2800; 313730391Skarels adder->x_scan_count_1 = 0x1020; 313830391Skarels adder->x_scan_count_2 = 0x003A; 313930391Skarels adder->x_scan_count_3 = 0x38F0; 314030391Skarels adder->x_scan_count_4 = 0x6128; 314130391Skarels adder->x_scan_count_5 = 0x093A; 314230391Skarels adder->x_scan_count_6 = 0x313C; 314330391Skarels adder->sync_phase_adj = 0x0100; 314430391Skarels adder->x_scan_conf = 0x00C8; 314534642Smarc /* 314634642Smarc * got a bug in secound pass ADDER! lets take care of it 314734642Smarc * 314834642Smarc * normally, just use the code in the following bug fix code, but to 314934642Smarc * make repeated demos look pretty, load the registers as if there was 315034642Smarc * no bug and then test to see if we are getting sync 315134642Smarc */ 315230391Skarels adder->y_scan_count_0 = 0x135F; 315330391Skarels adder->y_scan_count_1 = 0x3363; 315430391Skarels adder->y_scan_count_2 = 0x2366; 315530391Skarels adder->y_scan_count_3 = 0x0388; 315634642Smarc /* 315734642Smarc * if no sync, do the bug fix code 315834642Smarc */ 315930391Skarels if (wait_status(adder, VSYNC) == BAD) { 316034642Smarc /* first load all Y scan registers with very short frame and 316134642Smarc * wait for scroll service. This guarantees at least one SYNC 316234642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 316334642Smarc * XCINCH with DMSEEDH) 316434642Smarc */ 316534642Smarc adder->y_scan_count_0 = 0x01; 316634642Smarc adder->y_scan_count_1 = 0x01; 316734642Smarc adder->y_scan_count_2 = 0x01; 316834642Smarc adder->y_scan_count_3 = 0x01; 316934642Smarc /* 317034642Smarc * delay at least 1 full frame time 317134642Smarc */ 317234732Smarc (void)wait_status(adder, VSYNC); 317334732Smarc (void)wait_status(adder, VSYNC); 317434642Smarc /* 317534642Smarc * now load the REAL sync values (in reverse order just to 317634642Smarc * be safe. 317734642Smarc */ 317834642Smarc adder->y_scan_count_3 = 0x0388; 317934642Smarc adder->y_scan_count_2 = 0x2366; 318034642Smarc adder->y_scan_count_1 = 0x3363; 318134642Smarc adder->y_scan_count_0 = 0x135F; 318230391Skarels } 318330391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 318434642Smarc /* 318534642Smarc * zero the index registers 318634642Smarc */ 318730391Skarels adder->x_index_pending = 0; 318830391Skarels adder->y_index_pending = 0; 318930391Skarels adder->x_index_new = 0; 319030391Skarels adder->y_index_new = 0; 319130391Skarels adder->x_index_old = 0; 319230391Skarels adder->y_index_old = 0; 319330391Skarels adder->pause = 0; 319434642Smarc /* 319534642Smarc * set rasterop mode to normal pen down 319634642Smarc */ 319730391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 319834642Smarc /* 319934642Smarc * set the rasterop registers to a default values 320034642Smarc */ 320130391Skarels adder->source_1_dx = 1; 320230391Skarels adder->source_1_dy = 1; 320330391Skarels adder->source_1_x = 0; 320430391Skarels adder->source_1_y = 0; 320530391Skarels adder->destination_x = 0; 320630391Skarels adder->destination_y = 0; 320730391Skarels adder->fast_dest_dx = 1; 320830391Skarels adder->fast_dest_dy = 0; 320930391Skarels adder->slow_dest_dx = 0; 321030391Skarels adder->slow_dest_dy = 1; 321130391Skarels adder->error_1 = 0; 321230391Skarels adder->error_2 = 0; 321334642Smarc /* 321434732Smarc * scale factor = UNITY 321534642Smarc */ 321630391Skarels adder->fast_scale = UNITY; 321730391Skarels adder->slow_scale = UNITY; 321834642Smarc /* 321934642Smarc * set the source 2 parameters 322034642Smarc */ 322130391Skarels adder->source_2_x = 0; 322230391Skarels adder->source_2_y = 0; 322330391Skarels adder->source_2_size = 0x0022; 322434642Smarc /* 322534642Smarc * initialize plane addresses for eight vipers 322634642Smarc */ 322730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 322830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 322930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 323030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 323130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 323230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 323330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 323430391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 323530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 323630391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 323730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 323830391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 323930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 324030391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 324130391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 324230391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 324334642Smarc /* 324434642Smarc * initialize the external registers. 324534642Smarc */ 324630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 324730391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 324834642Smarc /* 324934642Smarc * initialize resolution mode 325034642Smarc */ 325130391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 325230391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 325334642Smarc /* 325434642Smarc * initialize viper registers 325534642Smarc */ 325630391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 325730391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 325834642Smarc /* 325934642Smarc * set clipping and scrolling limits to full screen 326034642Smarc */ 326134732Smarc for (i = 1000, adder->status = 0; 326234732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 326334642Smarc ; 326430391Skarels if (i == 0) 326534732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 326630391Skarels top = 0; 326730391Skarels bottom = 2048; 326830391Skarels left = 0; 326930391Skarels right = 1024; 327030391Skarels adder->x_clip_min = left; 327130391Skarels adder->x_clip_max = right; 327230391Skarels adder->y_clip_min = top; 327330391Skarels adder->y_clip_max = bottom; 327430391Skarels adder->scroll_x_min = left; 327530391Skarels adder->scroll_x_max = right; 327630391Skarels adder->scroll_y_min = top; 327730391Skarels adder->scroll_y_max = bottom; 327834732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 327934732Smarc (void)wait_status(adder, VSYNC); 328030391Skarels adder->x_index_pending = left; 328130391Skarels adder->y_index_pending = top; 328230391Skarels adder->x_index_new = left; 328330391Skarels adder->y_index_new = top; 328430391Skarels adder->x_index_old = left; 328530391Skarels adder->y_index_old = top; 328630391Skarels 328734732Smarc for (i = 1000, adder->status = 0; i > 0 && 328834732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 328934642Smarc ; 329030391Skarels if (i == 0) 329134732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 329230391Skarels 329330391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 329430391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 329534642Smarc /* 329634642Smarc * set source and the mask register to all ones (ie: white) o 329734642Smarc */ 329830391Skarels write_ID(adder, SOURCE, 0xFFFF); 329930391Skarels write_ID(adder, MASK_1, 0xFFFF); 330030391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 330130391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 330234642Smarc /* 330334642Smarc * initialize Operand Control Register banks for fill command 330434642Smarc */ 330530391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 330630391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 330730391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 330830391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 330930391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 331030391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 331134642Smarc /* 331234642Smarc * init Logic Unit Function registers, (these are just common values, 331334642Smarc * and may be changed as required). 331434642Smarc */ 331530391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 331634642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 331734642Smarc INV_M1_M2); 331830391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 331930391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 332034642Smarc /* 332134642Smarc * load the color map for black & white 332234642Smarc */ 332334732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 332434642Smarc ; 332530391Skarels 332630391Skarels if (i == 0) 332734732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 332830391Skarels 332930391Skarels red = (short *) qdmap[unit].red; 333030391Skarels green = (short *) qdmap[unit].green; 333130391Skarels blue = (short *) qdmap[unit].blue; 333230391Skarels 333330391Skarels *red++ = 0x00; /* black */ 333430391Skarels *green++ = 0x00; 333530391Skarels *blue++ = 0x00; 333630391Skarels 333730391Skarels *red-- = 0xFF; /* white */ 333830391Skarels *green-- = 0xFF; 333930391Skarels *blue-- = 0xFF; 334030391Skarels 334134642Smarc /* 334234732Smarc * set color map for mouse cursor 334334732Smarc */ 334430391Skarels 334530391Skarels red += 254; 334630391Skarels green += 254; 334730391Skarels blue += 254; 334830391Skarels 334930391Skarels *red++ = 0x00; /* black */ 335030391Skarels *green++ = 0x00; 335130391Skarels *blue++ = 0x00; 335230391Skarels 335330391Skarels *red = 0xFF; /* white */ 335430391Skarels *green = 0xFF; 335530391Skarels *blue = 0xFF; 335630391Skarels 335730391Skarels } /* setup_dragon */ 335830391Skarels 335934732Smarc /* 336034732Smarc * Init the DUART and set defaults in input 336134732Smarc */ 336230391Skarels setup_input(unit) 336334732Smarc int unit; 336430391Skarels { 336530391Skarels register struct duart *duart; /* DUART register structure pointer */ 336634732Smarc register i, bits; 336730391Skarels char id_byte; 336830391Skarels 336930391Skarels duart = (struct duart *) qdmap[unit].duart; 337030391Skarels duart->imask = 0; 337130391Skarels 337234642Smarc /* 337334642Smarc * setup the DUART for kbd & pointing device 337434642Smarc */ 337534732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 337634732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 337734732Smarc /* no RTS control,char error mode */ 337834732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 337934732Smarc /* no RTS control,no echo or loop */ 338034732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 338134732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 338234732Smarc /* ..no RTS cntrl, char error mode */ 338334732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 338434732Smarc /* no RTS control,no echo or loop */ 338534732Smarc duart->auxctl = 0x00; /* baud rate set 1 */ 338634732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */ 338734732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */ 338830391Skarels 338930391Skarels /* reset everything for keyboard */ 339030391Skarels 339130391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339234642Smarc duart->cmdA = bits; 339330391Skarels 339430391Skarels /* reset everything for host */ 339530391Skarels 339630391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339734642Smarc duart->cmdB = bits; 339830391Skarels 339930391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 340030391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 340130391Skarels 340234642Smarc /* 340334732Smarc * init keyboard defaults (DUART channel A) 340434732Smarc */ 340530391Skarels for (i = 500; i > 0; --i) { 340634732Smarc if (duart->statusA&XMT_RDY) { 340734642Smarc duart->dataA = LK_DEFAULTS; 340834642Smarc break; 340934642Smarc } 341030391Skarels } 341130391Skarels 341230391Skarels for (i = 100000; i > 0; --i) { 341334732Smarc if (duart->statusA&RCV_RDY) { 341434642Smarc break; 341534642Smarc } 341630391Skarels } 341730391Skarels 341834732Smarc if (duart->dataA) /* flush the ACK */ 341934732Smarc ; 342030391Skarels 342134642Smarc /* 342234732Smarc * identify the pointing device 342334732Smarc */ 342430391Skarels for (i = 500; i > 0; --i) { 342534732Smarc if (duart->statusB&XMT_RDY) { 342634642Smarc duart->dataB = SELF_TEST; 342734642Smarc break; 342834642Smarc } 342930391Skarels } 343030391Skarels 343134642Smarc /* 343230391Skarels * wait for 1st byte of self test report */ 343330391Skarels 343430391Skarels for (i = 100000; i > 0; --i) { 343534732Smarc if (duart->statusB&RCV_RDY) { 343634642Smarc break; 343734642Smarc } 343830391Skarels } 343930391Skarels 344030391Skarels if (i == 0) { 344134732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 344234642Smarc ,unit); 344334642Smarc goto OUT; 344430391Skarels } 344530391Skarels 344634732Smarc if (duart->dataB) 344734732Smarc ; 344830391Skarels 344934642Smarc /* 345034732Smarc * wait for ID byte of self test report 345134732Smarc */ 345230391Skarels for (i = 100000; i > 0; --i) { 345334732Smarc if (duart->statusB&RCV_RDY) { 345434642Smarc break; 345534642Smarc } 345630391Skarels } 345730391Skarels 345830391Skarels if (i == 0) { 345934732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 346034642Smarc goto OUT; 346130391Skarels } 346230391Skarels 346330391Skarels id_byte = duart->dataB; 346430391Skarels 346534642Smarc /* 346634732Smarc * wait for other bytes to come in 346734732Smarc */ 346830391Skarels for (i = 100000; i > 0; --i) { 346934732Smarc if (duart->statusB & RCV_RDY) { 347034732Smarc if (duart->dataB) 347134732Smarc ; 347234642Smarc break; 347334642Smarc } 347430391Skarels } 347530391Skarels if (i == 0) { 347634732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 347734642Smarc goto OUT; 347830391Skarels } 347930391Skarels for (i = 100000; i > 0; --i) { 348034732Smarc if (duart->statusB&RCV_RDY) { 348134732Smarc if (duart->dataB) 348234732Smarc ; 348334642Smarc break; 348434642Smarc } 348530391Skarels } 348630391Skarels if (i == 0) { 348734732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 348834642Smarc goto OUT; 348930391Skarels } 349034642Smarc /* 349134732Smarc * flag pointing device type and set defaults 349234732Smarc */ 349334732Smarc for (i=100000; i>0; --i) 349434732Smarc ; /*XXX*/ 349530391Skarels 349630391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 349734642Smarc qdflags[unit].pntr_id = MOUSE_ID; 349830391Skarels 349934642Smarc for (i = 500; i > 0; --i) { 350034732Smarc if (duart->statusB&XMT_RDY) { 350134642Smarc duart->dataB = INC_STREAM_MODE; 350234642Smarc break; 350334642Smarc } 350430391Skarels } 350534642Smarc } 350634642Smarc else { 350734642Smarc qdflags[unit].pntr_id = TABLET_ID; 350830391Skarels 350934642Smarc for (i = 500; i > 0; --i) { 351034732Smarc if (duart->statusB&XMT_RDY) { 351134642Smarc duart->dataB = T_STREAM; 351234642Smarc break; 351334642Smarc } 351430391Skarels } 351530391Skarels } 351630391Skarels OUT: 351730391Skarels duart->imask = qdflags[unit].duart_imask; 351830391Skarels 351930391Skarels } /* setup_input */ 352030391Skarels 352134732Smarc /* 352234732Smarc * delay for at least one display frame time 352334732Smarc * 352434732Smarc * return: BAD means that we timed out without ever seeing the 352534732Smarc * vertical sync status bit 352634732Smarc * GOOD otherwise 352734732Smarc */ 352830391Skarels wait_status(adder, mask) 352934642Smarc register struct adder *adder; 353034642Smarc register int mask; 353130391Skarels { 353234732Smarc register i; 353330391Skarels 353434732Smarc for (i = 10000, adder->status = 0 ; i > 0 && 353534732Smarc !(adder->status&mask) ; --i) 353634642Smarc ; 353730391Skarels 353830391Skarels if (i == 0) { 353934732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 354034642Smarc return(BAD); 354130391Skarels } 354230391Skarels 354330391Skarels return(GOOD); 354430391Skarels 354530391Skarels } /* wait_status */ 354630391Skarels 354734732Smarc /* 354834732Smarc * write out onto the ID bus 354934732Smarc */ 355030391Skarels write_ID(adder, adrs, data) 355134642Smarc register struct adder *adder; 355234642Smarc register short adrs; 355334642Smarc register short data; 355430391Skarels { 355534732Smarc register i; 355630391Skarels 355734732Smarc for (i = 100000, adder->status = 0 ; 355834732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 355934642Smarc ; 356030391Skarels 356130391Skarels if (i == 0) 356234732Smarc goto ERR; 356330391Skarels 356434732Smarc for (i = 100000, adder->status = 0 ; 356534732Smarc i > 0 && !(adder->status&TX_READY) ; --i) 356634642Smarc ; 356730391Skarels 356830391Skarels if (i > 0) { 356934642Smarc adder->id_data = data; 357034642Smarc adder->command = ID_LOAD | adrs; 357134732Smarc return ; 357230391Skarels } 357330391Skarels 357430391Skarels ERR: 357534732Smarc printf("write_ID: timeout trying to write to VIPER\n"); 357634732Smarc return ; 357730391Skarels 357830391Skarels } /* write_ID */ 357934511Smarc #endif 3580