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*40817Smarc * @(#)qd.c 1.15 (Berkeley) 04/05/90 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" 5037513Smckusick #include "machine/pte.h" 5137513Smckusick #include "machine/mtpr.h" 5237513Smckusick #include "machine/cpu.h" 5334642Smarc #include "param.h" 5434642Smarc #include "conf.h" 5534642Smarc #include "user.h" 5634642Smarc #include "qdioctl.h" 5734511Smarc #include "tty.h" 5834642Smarc #include "map.h" 5934642Smarc #include "buf.h" 6034642Smarc #include "vm.h" 6134642Smarc #include "clist.h" 6234642Smarc #include "file.h" 6334642Smarc #include "uio.h" 6434642Smarc #include "kernel.h" 6534615Smarc #include "exec.h" 6634615Smarc #include "proc.h" 6734642Smarc #include "ubareg.h" 6834642Smarc #include "ubavar.h" 6934511Smarc #include "syslog.h" 7034642Smarc #include "qduser.h" /* definitions shared with user level client */ 7134615Smarc #include "qdreg.h" /* QDSS device register structures */ 7232012Smarc 7334642Smarc /* 7434642Smarc * QDSS driver status flags for tracking operational state 7534642Smarc */ 7634642Smarc struct qdflags { 7734642Smarc u_int inuse; /* which minor dev's are in use now */ 7834642Smarc u_int config; /* I/O page register content */ 7934642Smarc u_int mapped; /* user mapping status word */ 8034642Smarc u_int kernel_loop; /* if kernel console is redirected */ 8134642Smarc u_int user_dma; /* DMA from user space in progress */ 8234642Smarc u_short pntr_id; /* type code of pointing device */ 8334642Smarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 8434642Smarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 8534642Smarc u_short curs_acc; /* cursor acceleration factor */ 8634642Smarc u_short curs_thr; /* cursor acceleration threshold level */ 8734642Smarc u_short tab_res; /* tablet resolution factor */ 8834642Smarc u_short selmask; /* mask for active qd select entries */ 8934642Smarc }; 9032012Smarc 9134642Smarc /* 9234642Smarc * bit definitions for 'inuse' entry 9334642Smarc */ 9432012Smarc #define CONS_DEV 0x01 9532012Smarc #define GRAPHIC_DEV 0x04 9632012Smarc 9734642Smarc /* 9834642Smarc * bit definitions for 'mapped' member of flag structure 9934642Smarc */ 10032012Smarc #define MAPDEV 0x01 /* hardware is mapped */ 10132012Smarc #define MAPDMA 0x02 /* DMA buffer mapped */ 10232012Smarc #define MAPEQ 0x04 /* event queue buffer mapped */ 10332012Smarc #define MAPSCR 0x08 /* scroll param area mapped */ 10432012Smarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 10532012Smarc 10634642Smarc /* 10734642Smarc * bit definitions for 'selmask' member of qdflag structure 10834642Smarc */ 10932012Smarc #define SEL_READ 0x01 /* read select is active */ 11032012Smarc #define SEL_WRITE 0x02 /* write select is active */ 11132012Smarc 11234642Smarc /* 11334732Smarc * constants used in shared memory operations 11434732Smarc */ 11532012Smarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 11632012Smarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 11734642Smarc / sizeof(struct _vs_event) ) 11834527Smarc #define DMA_BUFSIZ (1024 * 10) 11932012Smarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 12032012Smarc 12134642Smarc /* 12234732Smarc * reference to an array of "uba_device" structures built by the auto 12334732Smarc * configuration program. The uba_device structure decribes the device 12434732Smarc * sufficiently for the driver to talk to it. The auto configuration code 12534732Smarc * fills in the uba_device structures (located in ioconf.c) from user 12634732Smarc * maintained info. 12734732Smarc */ 12834642Smarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 12934642Smarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 13034732Smarc extern char qvmem[][128*NBPG]; 13134642Smarc extern struct pte QVmap[][128]; 13234642Smarc #define CHUNK (64 * 1024) 13334642Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 13432012Smarc 13534642Smarc /* 13634642Smarc * static storage used by multiple functions in this code 13734642Smarc */ 13834642Smarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 13934642Smarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 14034642Smarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 14134642Smarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 14234642Smarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 14334642Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 14432012Smarc 14534642Smarc /* 14634732Smarc * the array "event_shared[]" is made up of a number of event queue buffers 14734732Smarc * equal to the number of QDSS's configured into the running kernel (NQD). 14834732Smarc * Each event queue buffer begins with an event queue header (struct qdinput) 14934732Smarc * followed by a group of event queue entries (struct _vs_event). The array 15034732Smarc * "*eq_header[]" is an array of pointers to the start of each event queue 15134732Smarc * buffer in "event_shared[]". 15234732Smarc */ 15332012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 15432012Smarc 15534642Smarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 15634642Smarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 15732012Smarc 15834642Smarc /* 15934732Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 16034732Smarc * buffers. Each buffer must consume an integral number of memory pages to 16134732Smarc * guarantee that a following buffer will begin on a page boundary. Also, 16234732Smarc * enough space is allocated so that the FIRST I/O buffer can start at the 16334732Smarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 16434732Smarc * memory protections can be turned on/off for individual buffers. 16534732Smarc */ 16632012Smarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 16732012Smarc 16834642Smarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 16934642Smarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 17032012Smarc 17134642Smarc /* 17234732Smarc * The driver assists a client in scroll operations by loading dragon 17334732Smarc * registers from an interrupt service routine. The loading is done using 17434732Smarc * parameters found in memory shrade between the driver and it's client. 17534732Smarc * The scroll parameter structures are ALL loacted in the same memory page 17634732Smarc * for reasons of memory economy. 17734732Smarc */ 17834642Smarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 17934642Smarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 18032012Smarc 18134642Smarc /* 18234732Smarc * the driver is programmable to provide the user with color map write 18334732Smarc * services at VSYNC interrupt time. At interrupt time the driver loads 18434732Smarc * the color map with any user-requested load data found in shared memory 18534732Smarc */ 18632012Smarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 18732012Smarc 18834642Smarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 18934642Smarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 19032012Smarc 19134642Smarc /* 19234732Smarc * mouse input event structures 19334732Smarc */ 19434642Smarc struct mouse_report last_rep[NQD]; 19534642Smarc struct mouse_report current_rep[NQD]; 19632012Smarc 19734732Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 19834642Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 19934642Smarc int qdcount = 0; /* count of successfully probed qd's */ 20034642Smarc int nNQD = NQD; 20134642Smarc int DMAbuf_size = DMA_BUFSIZ; 20234642Smarc int QDlast_DMAtype; /* type of the last DMA operation */ 20332012Smarc 20434642Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 20534642Smarc /* 20634732Smarc * macro to get system time. Used to time stamp event queue entries 20734732Smarc */ 20830391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 20930391Skarels 21034642Smarc int qdprobe(); 21134642Smarc int qdattach(); 21234642Smarc int qddint(); /* DMA gate array intrpt service */ 21334642Smarc int qdaint(); /* Dragon ADDER intrpt service */ 21434642Smarc int qdiint(); 21530391Skarels 21634642Smarc u_short qdstd[] = { 0 }; 21730391Skarels 21834642Smarc struct uba_driver qddriver = { 21934732Smarc qdprobe, /* device probe entry */ 22034732Smarc 0, /* no slave device */ 22134732Smarc qdattach, /* device attach entry */ 22234732Smarc 0, /* no "fill csr/ba to start" */ 22334642Smarc qdstd, /* device addresses */ 22434642Smarc "qd", /* device name string */ 22534642Smarc qdinfo /* ptr to QDSS's uba_device struct */ 22634642Smarc }; 22730391Skarels 22834615Smarc #define QDPRIOR (PZERO-1) /* must be negative */ 22930391Skarels #define FALSE 0 23030391Skarels #define TRUE ~FALSE 23130391Skarels #define BAD -1 23230391Skarels #define GOOD 0 23330391Skarels 23434642Smarc /* 23534642Smarc * macro to create a system virtual page number from system virtual adrs 23634642Smarc */ 23734642Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 23830391Skarels 23934642Smarc /* 24034642Smarc * QDSS register address offsets from start of QDSS address space 24134642Smarc */ 24230391Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 24330391Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 24430391Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 24530391Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 24630391Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 24730391Skarels #define ADDER (REGSTART+0x000) 24830391Skarels #define DGA (REGSTART+0x200) 24930391Skarels #define DUART (REGSTART+0x400) 25030391Skarels #define MEMCSR (REGSTART+0x800) 25130391Skarels #define CLRSIZE (3 * 512) /* color map size */ 25230391Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 25334642Smarc /* 0x0C00 really */ 25430391Skarels #define RED (CLRSTART+0x000) 25530391Skarels #define BLUE (CLRSTART+0x200) 25630391Skarels #define GREEN (CLRSTART+0x400) 25730391Skarels 25830391Skarels 25934642Smarc /* 26034642Smarc * QDSS minor device numbers. The *real* minor device numbers are in 26134642Smarc * the bottom two bits of the major/minor device spec. Bits 2 and up are 26234642Smarc * used to specify the QDSS device number (ie: which one?) 26334642Smarc */ 26430391Skarels 26530391Skarels #define CONS 0 26630391Skarels #define GRAPHIC 2 26730391Skarels 26834642Smarc /* 26934642Smarc * console cursor bitmap (white block cursor) 27034642Smarc */ 27134642Smarc short cons_cursor[32] = { 27234642Smarc /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27334642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27434642Smarc /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27534642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 27634642Smarc }; 27730391Skarels 27834642Smarc /* 27934642Smarc * constants used in font operations 28034642Smarc */ 28134615Smarc #define CHARS 190 /* # of chars in the font */ 28230391Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 28330391Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 28430391Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 28530391Skarels #define ROWS CHAR_HEIGHT 28630391Skarels #define FONT_X 0 /* font's off screen adrs */ 28730391Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 28830391Skarels 28934642Smarc /* Offset to second row characters (XXX - should remove) */ 29034615Smarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 29130391Skarels 29234642Smarc extern char q_font[]; /* reference font object code */ 29334642Smarc extern u_short q_key[]; /* reference key xlation tables */ 29434642Smarc extern u_short q_shift_key[]; 29534642Smarc extern char *q_special[]; 29630391Skarels 29734642Smarc /* 29834642Smarc * definitions for cursor acceleration reporting 29934642Smarc */ 30030391Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 30130391Skarels 30234642Smarc /* 30334642Smarc * virtual console support. 30434642Smarc */ 30534642Smarc extern (*v_putc)(); 306*40817Smarc #ifdef KADB 307*40817Smarc extern (*v_getc)(); 308*40817Smarc extern (*v_poll)(); 309*40817Smarc #endif 31034642Smarc extern struct cdevsw *consops; 31134642Smarc int qdputc(); 312*40817Smarc int qdgetc(); 313*40817Smarc int qdpoll(); 31434642Smarc int qdstart(); 315*40817Smarc int qdpolling = 0; 31630391Skarels 31734642Smarc /* 31834642Smarc * LK-201 state storage for input console keyboard conversion to ASCII 31934642Smarc */ 32034642Smarc struct q_keyboard { 32134642Smarc int shift; /* state variables */ 32234642Smarc int cntrl; 32334642Smarc int lock; 32434642Smarc int lastcode; /* last keycode typed */ 32534642Smarc unsigned kup[8]; /* bits for each keycode*/ 32634642Smarc unsigned dkeys[8]; /* down/up mode keys */ 32734642Smarc char last; /* last character */ 32834642Smarc } q_keyboard; 32930391Skarels 33034642Smarc /* 33134642Smarc * tty settings on first open 33234642Smarc */ 333*40817Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL) 33434615Smarc #define OFLAG (OPOST|OXTABS|ONLCR) 335*40817Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN) 33634615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 33734615Smarc 33834732Smarc /* 33934732Smarc * Init QDSS as console (before probe routine) 34034732Smarc */ 34130391Skarels 34230391Skarels qdcons_init() 34330391Skarels { 34434732Smarc register unit; 34530391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 34634615Smarc u_int mapix; /* index into QVmap[] array */ 34734615Smarc struct percpu *pcpu; /* pointer to cpusw structure */ 34834615Smarc register struct qbus *qb; 34930391Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 35030391Skarels u_short *devptr; /* vitual device space */ 35134615Smarc extern cnputc(); 35230391Skarels 35330391Skarels #define QDSSCSR 0x1F00 35430391Skarels 35532012Smarc if (v_putc != cnputc) 35634732Smarc return 0; 35732012Smarc 35830391Skarels unit = 0; 35930391Skarels 36034642Smarc /* 36134642Smarc * find the cpusw entry that matches this machine. 36234642Smarc */ 36332012Smarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 36432012Smarc ; 36532012Smarc if (pcpu == NULL) 36634732Smarc return 0; 36736705Stef if (pcpu->pc_io->io_type != IO_QBUS) 36836705Stef return 0; 36930391Skarels 37032012Smarc /* 37134615Smarc * Map device registers - the last 8K of qvmem. 37232012Smarc */ 37332012Smarc qb = (struct qbus *)pcpu->pc_io->io_details; 37432012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 37534732Smarc UBAIOPAGES * NBPG); 37632012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 37730391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 37834732Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 37934732Smarc return 0; 38034615Smarc 38132012Smarc /* 38232012Smarc * Map q-bus memory used by qdss. (separate map) 38332012Smarc */ 38432012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 38532012Smarc phys_adr = qb->qb_maddr + mapix; 38632012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 38730391Skarels 38832012Smarc /* 38932012Smarc * tell QDSS which Q memory address base to decode 39034642Smarc * (shifted right 16 bits - its in 64K units) 39132012Smarc */ 39232012Smarc *qdaddr = (u_short)((int)mapix >> 16); 39330391Skarels qdflags[unit].config = *(u_short *)qdaddr; 39430391Skarels 39534642Smarc /* 39634642Smarc * load qdmap struct with the virtual addresses of the QDSS elements 39734642Smarc */ 39834615Smarc qdbase[unit] = (caddr_t) (qvmem[0]); 39930391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 40030391Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 40130391Skarels qdmap[unit].dga = qdbase[unit] + DGA; 40230391Skarels qdmap[unit].duart = qdbase[unit] + DUART; 40330391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 40430391Skarels qdmap[unit].red = qdbase[unit] + RED; 40530391Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 40630391Skarels qdmap[unit].green = qdbase[unit] + GREEN; 40730391Skarels 40830391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 40930391Skarels 41034642Smarc /* 41134642Smarc * init the QDSS 41234642Smarc */ 41334642Smarc /* 41432012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 41534642Smarc (char *)qdbase[0], qdmap[0].memcsr); 41634642Smarc */ 41732012Smarc 41830391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 41930391Skarels 42030391Skarels cursor[unit].x = 0; 42130391Skarels cursor[unit].y = 0; 42230391Skarels init_shared(unit); /* init shared memory */ 42330391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 42430391Skarels clear_qd_screen(unit); /* clear the screen */ 42530391Skarels ldfont(unit); /* load the console font */ 42630391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 42730391Skarels setup_input(unit); /* init the DUART */ 42834642Smarc v_putc = qdputc; /* kernel console output to qdss */ 429*40817Smarc #ifdef KADB 430*40817Smarc v_getc = qdgetc; /* kernel console input from qdss */ 431*40817Smarc v_poll = qdpoll; /* kdb hook to disable char intr */ 432*40817Smarc #endif 43334642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 43434732Smarc return 1; 43530391Skarels 43630391Skarels } /* qdcons_init */ 43730391Skarels 43834732Smarc /* 43934732Smarc * Configure QDSS into Q memory and make it intrpt. 44034732Smarc * 44134732Smarc * side effects: QDSS gets mapped into Qbus memory space at the first 44234732Smarc * vacant 64kb boundary counting back from the top of 44334732Smarc * Qbus memory space (qvmem+4mb) 44434732Smarc * 44534732Smarc * return: QDSS bus request level and vector address returned in 44634732Smarc * registers by UNIX convention. 44734732Smarc * 44834732Smarc */ 44930391Skarels qdprobe(reg) 45034732Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 45130391Skarels { 452*40817Smarc register int br, cvec; 45330391Skarels register int unit; 45430391Skarels struct dga *dga; /* pointer to gate array structure */ 45534732Smarc int vector; 45634732Smarc #ifdef notdef 45730391Skarels int *ptep; /* page table entry pointer */ 45830391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 45930391Skarels u_int mapix; 46034732Smarc #endif 46130391Skarels 46234732Smarc #ifdef lint 46334732Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 46434732Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 46534732Smarc #endif 46634732Smarc 46734642Smarc /* 46834642Smarc * calculate board unit number from I/O page register address 46934642Smarc */ 47030391Skarels unit = (int) (((int)reg >> 1) & 0x0007); 47130391Skarels 47234642Smarc /* 47334642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 47434642Smarc * physical boundary. The Qbus memory space is mapped into 47534642Smarc * the system memory space at config time. After config 47634642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 47734642Smarc * of the start of Qbus memory. The Qbus memory page table 47834642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 47934642Smarc * which is also loaded at config time. These are the 48034642Smarc * variables used below to find a vacant 64kb boundary in 48134642Smarc * Qbus memory, and load it's corresponding physical adrs 48234642Smarc * into the QDSS's I/O page CSR. 48334642Smarc */ 48430391Skarels 48534615Smarc /* 48634615Smarc * Only if QD is the graphics device. 48734615Smarc */ 48834615Smarc 48930391Skarels /* if this QDSS is NOT the console, then do init here.. */ 49030391Skarels 49134615Smarc if (unit != 0) { 49234615Smarc printf("qd: can't support two qdss's (yet)\n"); 49334732Smarc #ifdef notdef /* can't test */ 49434642Smarc if (v_consputc != qdputc || unit != 0) { 49530391Skarels 49634642Smarc /* 49734642Smarc * read QDSS config info 49834642Smarc */ 49934642Smarc qdflags[unit].config = *(u_short *)reg; 50034615Smarc 50134642Smarc /* 50234642Smarc * find an empty 64kb adrs boundary 50334642Smarc */ 50430391Skarels 50534642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 50630391Skarels 50734642Smarc /* 50834732Smarc * find the cpusw entry that matches this machine. 50934732Smarc */ 51034642Smarc cpup = &cpusw[cpu]; 51134732Smarc while (!(BADADDR(qdbase[unit], sizeof(short)))) 51234732Smarc qdbase[unit] -= CHUNK; 51334615Smarc 51434642Smarc /* 51534732Smarc * tell QDSS which Q memory address base to decode 51634732Smarc */ 51734642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 51834642Smarc ptep = (int *) QVmap[0] + mapix; 51934642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 52034642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 52134615Smarc 52234642Smarc /* 52334642Smarc * load QDSS adrs map with system addresses 52434642Smarc * of device regs 52534642Smarc */ 52634642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART; 52734642Smarc qdmap[unit].adder = qdbase[unit] + ADDER; 52834642Smarc qdmap[unit].dga = qdbase[unit] + DGA; 52934642Smarc qdmap[unit].duart = qdbase[unit] + DUART; 53034642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 53134642Smarc qdmap[unit].red = qdbase[unit] + RED; 53234642Smarc qdmap[unit].blue = qdbase[unit] + BLUE; 53334642Smarc qdmap[unit].green = qdbase[unit] + GREEN; 53430391Skarels 53534642Smarc /* device init */ 53634615Smarc 53734642Smarc cursor[unit].x = 0; 53834642Smarc cursor[unit].y = 0; 53934642Smarc init_shared(unit); /* init shared memory */ 54034642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */ 54134642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */ 54234642Smarc setup_input(unit); /* init the DUART */ 54334642Smarc clear_qd_screen(unit); 54434642Smarc ldfont(unit); /* load the console font */ 54530391Skarels 54634642Smarc /* once only: turn on sync */ 54730391Skarels 54834642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON; 54934642Smarc } 55034615Smarc #endif /*notdef*/ 55130391Skarels } 55230391Skarels 55334642Smarc /* 55434642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 55534642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 55634642Smarc * vectors from the vector pool, and then continue 55734642Smarc * to take them until we get a xx0 HEX vector. The 55834642Smarc * pool provides vectors in contiguous decending 55934642Smarc * order. 56034642Smarc */ 56130391Skarels 56230391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 56330391Skarels 56434642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */ 56534642Smarc /* ..take another vector */ 56634642Smarc vector = (uba_hd[0].uh_lastiv -= 4); 56730391Skarels } 56830391Skarels 56934642Smarc /* 57034642Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 57134642Smarc */ 57230391Skarels dga = (struct dga *) qdmap[unit].dga; 57334642Smarc dga->csr = (short) HALT; /* disable everything */ 57434642Smarc dga->ivr = (short) vector; /* load intrpt base vector */ 57534642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 57630391Skarels dga->bytcnt_hi = (short) 0; 57730391Skarels 57834642Smarc /* 57934642Smarc * turn on DMA interrupts 58034642Smarc */ 58130391Skarels dga->csr &= ~SET_DONE_FIFO; 58230391Skarels dga->csr |= DMA_IE | DL_ENB; 58330391Skarels 58430391Skarels DELAY(20000); /* wait for the intrpt */ 58530391Skarels dga->csr = HALT; /* stop the wheels */ 58630391Skarels 58730391Skarels if (cvec != vector) /* if vector != base vector.. */ 58834732Smarc return(0); /* ..return = 'no device' */ 58930391Skarels 59034615Smarc /* 59134642Smarc * score this as an existing qdss 59234642Smarc */ 59334615Smarc qdcount++; 59434615Smarc 59530391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 59630391Skarels 59730391Skarels } /* qdprobe */ 59830391Skarels 59930391Skarels qdattach(ui) 60034642Smarc struct uba_device *ui; 60130391Skarels { 60234732Smarc register unit; /* QDSS module # for this call */ 60330391Skarels 60430391Skarels unit = ui->ui_unit; /* get QDSS number */ 60530391Skarels 60634642Smarc /* 60734642Smarc * init "qdflags[]" for this QDSS 60834642Smarc */ 60930391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 61030391Skarels qdflags[unit].mapped = 0; 61134615Smarc qdflags[unit].kernel_loop = -1; 61230391Skarels qdflags[unit].user_dma = 0; 61330391Skarels qdflags[unit].curs_acc = ACC_OFF; 61430391Skarels qdflags[unit].curs_thr = 128; 61530391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 61630391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 61730391Skarels qdflags[unit].adder_ie = 0; 61830391Skarels 61934642Smarc /* 62034642Smarc * init structures used in kbd/mouse interrupt service. This code must 62134642Smarc * come after the "init_shared()" routine has run since that routine 62234642Smarc * inits the eq_header[unit] structure used here. 62334642Smarc */ 62430391Skarels 62534642Smarc /* 62634642Smarc * init the "latest mouse report" structure 62734642Smarc */ 62830391Skarels last_rep[unit].state = 0; 62930391Skarels last_rep[unit].dx = 0; 63030391Skarels last_rep[unit].dy = 0; 63130391Skarels last_rep[unit].bytcnt = 0; 63230391Skarels 63334642Smarc /* 63434732Smarc * init the event queue (except mouse position) 63534732Smarc */ 63634732Smarc eq_header[unit]->header.events = 63734732Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 63830391Skarels 63930391Skarels eq_header[unit]->header.size = MAXEVENTS; 64030391Skarels eq_header[unit]->header.head = 0; 64130391Skarels eq_header[unit]->header.tail = 0; 64230391Skarels 64334642Smarc /* 64434642Smarc * open exclusive for graphics device. 64534642Smarc */ 64634642Smarc qdopened[unit] = 0; 64730391Skarels 64830391Skarels } /* qdattach */ 64930391Skarels 65034732Smarc /*ARGSUSED*/ 65130391Skarels qdopen(dev, flag) 65234642Smarc dev_t dev; 65334642Smarc int flag; 65430391Skarels { 65530391Skarels register struct uba_device *ui; /* ptr to uba structures */ 65630391Skarels register struct dga *dga; /* ptr to gate array struct */ 65730391Skarels register struct tty *tp; 65830391Skarels struct duart *duart; 65934732Smarc int unit; 66034732Smarc int minor_dev; 66130391Skarels 66230391Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 66330391Skarels unit = minor_dev >> 2; 66430391Skarels 66534642Smarc /* 66634642Smarc * check for illegal conditions 66734642Smarc */ 66830391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 66930391Skarels if (ui == 0 || ui->ui_alive == 0) 67034642Smarc return(ENXIO); /* no such device or address */ 67130391Skarels 67230391Skarels duart = (struct duart *) qdmap[unit].duart; 67330391Skarels dga = (struct dga *) qdmap[unit].dga; 67430391Skarels 67530391Skarels if ((minor_dev & 0x03) == 2) { 67634642Smarc /* 67734642Smarc * this is the graphic device... 67834642Smarc */ 67934642Smarc if (qdopened[unit] != 0) 68034732Smarc return(EBUSY); 68134642Smarc else 68234642Smarc qdopened[unit] = 1; 68334642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 68434642Smarc /* 68534642Smarc * enble kbd & mouse intrpts in DUART mask reg 68634642Smarc */ 68734642Smarc qdflags[unit].duart_imask |= 0x22; 68834642Smarc duart->imask = qdflags[unit].duart_imask; 68934642Smarc } else { 69034642Smarc /* 69134642Smarc * this is the console 69234642Smarc */ 69334642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 69434642Smarc dga->csr |= CURS_ENB; 69534642Smarc qdflags[unit].duart_imask |= 0x02; 69634642Smarc duart->imask = qdflags[unit].duart_imask; 69734642Smarc /* 69834642Smarc * some setup for tty handling 69934642Smarc */ 70034642Smarc tp = &qd_tty[minor_dev]; 70134642Smarc tp->t_addr = ui->ui_addr; 70234642Smarc tp->t_oproc = qdstart; 70334642Smarc if ((tp->t_state & TS_ISOPEN) == 0) { 70434642Smarc ttychars(tp); 70534642Smarc tp->t_ispeed = B9600; 70634642Smarc tp->t_ospeed = B9600; 70734642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 70834642Smarc tp->t_iflag = TTYDEF_IFLAG; 70934642Smarc tp->t_oflag = TTYDEF_OFLAG; 71034642Smarc tp->t_lflag = TTYDEF_LFLAG; 71134642Smarc tp->t_cflag = TTYDEF_CFLAG; 71232012Smarc } 71334642Smarc /* 71434642Smarc * enable intrpts, open line discipline 71534642Smarc */ 71634642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 71734642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp)); 71830391Skarels } 71930391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 72030391Skarels return(0); 72130391Skarels 72230391Skarels } /* qdopen */ 72330391Skarels 72434732Smarc /*ARGSUSED*/ 72530391Skarels qdclose(dev, flag) 72634642Smarc dev_t dev; 72734642Smarc int flag; 72830391Skarels { 72930391Skarels register struct tty *tp; 73030391Skarels register struct qdmap *qd; 73130391Skarels register int *ptep; 73230391Skarels struct dga *dga; /* gate array register map pointer */ 73330391Skarels struct duart *duart; 73430391Skarels struct adder *adder; 73534732Smarc int unit; 73634732Smarc int minor_dev; 73730391Skarels u_int mapix; 73834642Smarc int i; /* SIGNED index */ 73930391Skarels 74030391Skarels minor_dev = minor(dev); /* get minor device number */ 74130391Skarels unit = minor_dev >> 2; /* get QDSS number */ 74230391Skarels qd = &qdmap[unit]; 74330391Skarels 74430391Skarels if ((minor_dev & 0x03) == 2) { 74534642Smarc /* 74634642Smarc * this is the graphic device... 74734642Smarc */ 74834642Smarc if (qdopened[unit] != 1) 74934732Smarc return(EBUSY); 75034642Smarc else 75134642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 75234642Smarc /* 75334642Smarc * re-protect device memory 75434642Smarc */ 75534642Smarc if (qdflags[unit].mapped & MAPDEV) { 75634642Smarc /* 75734642Smarc * TEMPLATE RAM 75834642Smarc */ 75934642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 76034642Smarc ptep = (int *)(QVmap[0] + mapix); 76134732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 76234732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76334642Smarc /* 76434642Smarc * ADDER 76534642Smarc */ 76634642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 76734642Smarc ptep = (int *)(QVmap[0] + mapix); 76834732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 76934732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 77034642Smarc /* 77134642Smarc * COLOR MAPS 77234642Smarc */ 77334642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 77434642Smarc ptep = (int *)(QVmap[0] + mapix); 77534732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 77634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 77734642Smarc } 77834615Smarc 77934642Smarc /* 78034642Smarc * re-protect DMA buffer and free the map registers 78134642Smarc */ 78234642Smarc if (qdflags[unit].mapped & MAPDMA) { 78334642Smarc dga = (struct dga *) qdmap[unit].dga; 78434642Smarc adder = (struct adder *) qdmap[unit].adder; 78534642Smarc dga->csr &= ~DMA_IE; 78634642Smarc dga->csr &= ~0x0600; /* kill DMA */ 78734642Smarc adder->command = CANCEL; 78834642Smarc /* 78934642Smarc * if DMA was running, flush spurious intrpt 79034642Smarc */ 79134642Smarc if (dga->bytcnt_lo != 0) { 79234642Smarc dga->bytcnt_lo = 0; 79334642Smarc dga->bytcnt_hi = 0; 79434642Smarc DMA_SETIGNORE(DMAheader[unit]); 79534642Smarc dga->csr |= DMA_IE; 79634642Smarc dga->csr &= ~DMA_IE; 79734642Smarc } 79834642Smarc ptep = (int *) 79934642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 80034732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 80134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 80234642Smarc ubarelse(0, &Qbus_unmap[unit]); 80334642Smarc } 80434615Smarc 80534642Smarc /* 80634642Smarc * re-protect 1K (2 pages) event queue 80734642Smarc */ 80834642Smarc if (qdflags[unit].mapped & MAPEQ) { 80934642Smarc ptep = (int *) 81034642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 81134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 81234642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 81330391Skarels } 81434642Smarc /* 81534642Smarc * re-protect scroll param area and disable scroll intrpts 81634642Smarc */ 81734642Smarc if (qdflags[unit].mapped & MAPSCR) { 81834642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 81934642Smarc + (mfpr(SBR) | 0x80000000)); 82034642Smarc /* 82134642Smarc * re-protect 512 scroll param area 82234642Smarc */ 82334642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 82434642Smarc adder = (struct adder *) qdmap[unit].adder; 82534642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 82634642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 82734642Smarc } 82834642Smarc /* 82934642Smarc * re-protect color map write buffer area and kill intrpts 83034642Smarc */ 83134642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 83234642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 83334642Smarc + (mfpr(SBR) | 0x80000000)); 83434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 83534642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 83634642Smarc color_buf[unit]->status = 0; 83734642Smarc adder = (struct adder *) qdmap[unit].adder; 83834642Smarc qdflags[unit].adder_ie &= ~VSYNC; 83934642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 84034642Smarc } 84134642Smarc mtpr(TBIA, 0); 84234642Smarc /* flag everything now unmapped */ 84334642Smarc qdflags[unit].mapped = 0; 84434642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 84534642Smarc qdflags[unit].curs_acc = ACC_OFF; 84634642Smarc qdflags[unit].curs_thr = 128; 84734642Smarc /* 84834642Smarc * restore the console 84934642Smarc */ 85030391Skarels dga = (struct dga *) qdmap[unit].dga; 85130391Skarels adder = (struct adder *) qdmap[unit].adder; 85230391Skarels dga->csr &= ~DMA_IE; 85330391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 85430391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 85530391Skarels adder->command = CANCEL; 85634642Smarc /* 85734642Smarc * if DMA was running, flush spurious intrpt 85834642Smarc */ 85930391Skarels if (dga->bytcnt_lo != 0) { 86034642Smarc dga->bytcnt_lo = 0; 86134642Smarc dga->bytcnt_hi = 0; 86234642Smarc DMA_SETIGNORE(DMAheader[unit]); 86334642Smarc dga->csr |= DMA_IE; 86434642Smarc dga->csr &= ~DMA_IE; 86530391Skarels } 86630391Skarels init_shared(unit); /* init shared memory */ 86730391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 86830391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 86930391Skarels setup_input(unit); /* init the DUART */ 87030391Skarels ldfont(unit); 87130391Skarels cursor[unit].x = 0; 87230391Skarels cursor[unit].y = 0; 87334642Smarc /* 87434642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 87534642Smarc */ 87634642Smarc duart = (struct duart *) qdmap[unit].duart; 87734642Smarc qdflags[unit].duart_imask &= ~(0x20); 87834642Smarc qdflags[unit].duart_imask |= 0x02; 87934642Smarc duart->imask = qdflags[unit].duart_imask; 88034642Smarc /* 88134642Smarc * shut off interrupts if all is closed 88234642Smarc */ 88334642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 88434642Smarc dga = (struct dga *) qdmap[unit].dga; 88534642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 88634642Smarc } 88734642Smarc } else { 88834642Smarc /* 88934642Smarc * this is the console 89034642Smarc */ 89134642Smarc tp = &qd_tty[minor_dev]; 89234642Smarc (*linesw[tp->t_line].l_close)(tp); 89334642Smarc ttyclose(tp); 89434642Smarc tp->t_state = 0; 89534642Smarc qdflags[unit].inuse &= ~CONS_DEV; 89634642Smarc /* 89734642Smarc * if graphics device is closed, kill interrupts 89834642Smarc */ 89934642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 90034642Smarc dga = (struct dga *) qdmap[unit].dga; 90134642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 90234642Smarc } 90330391Skarels } 90434615Smarc 90530391Skarels return(0); 90630391Skarels 90730391Skarels } /* qdclose */ 90830391Skarels 90930391Skarels qdioctl(dev, cmd, datap, flags) 91034642Smarc dev_t dev; 91134642Smarc int cmd; 91234732Smarc register caddr_t datap; 91334642Smarc int flags; 91430391Skarels { 91530391Skarels register int *ptep; /* page table entry pointer */ 91632012Smarc register int mapix; /* QVmap[] page table index */ 91730391Skarels register struct _vs_event *event; 91830391Skarels register struct tty *tp; 91934732Smarc register i; 92030391Skarels struct qdmap *qd; /* pointer to device map struct */ 92130391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 92230391Skarels struct duart *duart; /* DUART reg structure pointer */ 92330391Skarels struct adder *adder; /* ADDER reg structure pointer */ 92430391Skarels struct prgkbd *cmdbuf; 92530391Skarels struct prg_cursor *curs; 92630391Skarels struct _vs_cursor *pos; 92734732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 92830391Skarels u_int minor_dev = minor(dev); 92930391Skarels int error; 93030391Skarels int s; 93130391Skarels short *temp; /* a pointer to template RAM */ 93230391Skarels 93334642Smarc /* 93434642Smarc * service graphic device ioctl commands 93534642Smarc */ 93630391Skarels switch (cmd) { 93734615Smarc 93834642Smarc case QD_GETEVENT: 93934642Smarc /* 94034642Smarc * extract the oldest event from the event queue 94134642Smarc */ 94230391Skarels if (ISEMPTY(eq_header[unit])) { 94334642Smarc event = (struct _vs_event *) datap; 94434642Smarc event->vse_device = VSE_NULL; 94534642Smarc break; 94630391Skarels } 94730391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 94834615Smarc s = spl5(); 94930391Skarels GETEND(eq_header[unit]); 95030391Skarels splx(s); 95134732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 95230391Skarels break; 95330391Skarels 95434642Smarc case QD_RESET: 95534642Smarc /* 95634642Smarc * init the dragon stuff, DUART, and driver variables 95734642Smarc */ 95830391Skarels init_shared(unit); /* init shared memory */ 95930391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 96030391Skarels clear_qd_screen(unit); 96130391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 96230391Skarels ldfont(unit); /* load the console font */ 96330391Skarels setup_input(unit); /* init the DUART */ 96430391Skarels break; 96530391Skarels 96634642Smarc case QD_SET: 96734642Smarc /* 96834642Smarc * init the DUART and driver variables 96934642Smarc */ 97030391Skarels init_shared(unit); 97130391Skarels setup_input(unit); 97230391Skarels break; 97330391Skarels 97434642Smarc case QD_CLRSCRN: 97534642Smarc /* 97634642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 97734642Smarc */ 97834732Smarc #ifdef notdef /* has caused problems and isn't necessary */ 97930391Skarels setup_dragon(unit); 98030391Skarels clear_qd_screen(unit); 98134615Smarc #endif 98230391Skarels break; 98330391Skarels 98434642Smarc case QD_WTCURSOR: 98534642Smarc /* 98634642Smarc * load a cursor into template RAM 98734642Smarc */ 98834732Smarc ldcursor(unit, (short *)datap); 98930391Skarels break; 99030391Skarels 99134642Smarc case QD_RDCURSOR: 99230391Skarels 99330391Skarels temp = (short *) qdmap[unit].template; 99434642Smarc /* 99534642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 99634642Smarc * ...template space 99734642Smarc */ 99830391Skarels temp += (8 * 1024) - 32; 99930391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 100034642Smarc *(short *)datap = *temp++; 100130391Skarels break; 100230391Skarels 100334642Smarc case QD_POSCURSOR: 100434642Smarc /* 100534642Smarc * position the mouse cursor 100634642Smarc */ 100730391Skarels dga = (struct dga *) qdmap[unit].dga; 100830391Skarels pos = (struct _vs_cursor *) datap; 100934615Smarc s = spl5(); 101030391Skarels dga->x_cursor = TRANX(pos->x); 101130391Skarels dga->y_cursor = TRANY(pos->y); 101230391Skarels eq_header[unit]->curs_pos.x = pos->x; 101330391Skarels eq_header[unit]->curs_pos.y = pos->y; 101430391Skarels splx(s); 101530391Skarels break; 101630391Skarels 101734642Smarc case QD_PRGCURSOR: 101834642Smarc /* 101934642Smarc * set the cursor acceleration factor 102034642Smarc */ 102130391Skarels curs = (struct prg_cursor *) datap; 102234615Smarc s = spl5(); 102330391Skarels qdflags[unit].curs_acc = curs->acc_factor; 102430391Skarels qdflags[unit].curs_thr = curs->threshold; 102530391Skarels splx(s); 102630391Skarels break; 102730391Skarels 102834642Smarc case QD_MAPDEVICE: 102934642Smarc /* 103034642Smarc * enable 'user write' to device pages 103134642Smarc */ 103230391Skarels qdflags[unit].mapped |= MAPDEV; 103330391Skarels qd = (struct qdmap *) &qdmap[unit]; 103434642Smarc /* 103534642Smarc * enable user write to template RAM 103634642Smarc */ 103732012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 103832012Smarc ptep = (int *)(QVmap[0] + mapix); 103934732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 104034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104134642Smarc /* 104234642Smarc * enable user write to registers 104334642Smarc */ 104432012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 104532012Smarc ptep = (int *)(QVmap[0] + mapix); 104634732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 104734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104834642Smarc /* 104934642Smarc * enable user write to color maps 105034642Smarc */ 105132012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 105232012Smarc ptep = (int *)(QVmap[0] + mapix); 105334732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 105434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 105534642Smarc /* 105634642Smarc * enable user write to DUART 105734642Smarc */ 105832012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 105932012Smarc ptep = (int *)(QVmap[0] + mapix); 106030391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 106130391Skarels 106234732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 106330391Skarels 106434642Smarc /* 106534732Smarc * stuff qdmap structure in return buffer 106634732Smarc */ 106734732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 106830391Skarels break; 106930391Skarels 107034642Smarc case QD_MAPIOBUF: 107134642Smarc /* 107234642Smarc * do setup for DMA by user process 107334642Smarc * 107434642Smarc * set 'user write enable' bits for DMA buffer 107534642Smarc */ 107630391Skarels qdflags[unit].mapped |= MAPDMA; 107730391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 107834642Smarc + (mfpr(SBR) | 0x80000000)); 107934732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 108034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 108134732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 108234642Smarc /* 108334642Smarc * set up QBUS map registers for DMA 108434642Smarc */ 108530391Skarels DMAheader[unit]->QBAreg = 108634732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 108730391Skarels if (DMAheader[unit]->QBAreg == 0) 108834732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 108930391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 109030391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 109134642Smarc /* 109234642Smarc * return I/O buf adr 109334642Smarc */ 109430391Skarels *(int *)datap = (int) DMAheader[unit]; 109530391Skarels break; 109630391Skarels 109734642Smarc case QD_MAPSCROLL: 109834642Smarc /* 109934642Smarc * map the shared scroll param area and enable scroll interpts 110034642Smarc */ 110130391Skarels qdflags[unit].mapped |= MAPSCR; 110230391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 110334642Smarc + (mfpr(SBR) | 0x80000000)); 110434642Smarc /* 110534642Smarc * allow user write to scroll area 110634642Smarc */ 110730391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 110834732Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 110930391Skarels scroll[unit]->status = 0; 111030391Skarels adder = (struct adder *) qdmap[unit].adder; 111130391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 111230391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 111334642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 111430391Skarels break; 111530391Skarels 111634642Smarc case QD_UNMAPSCROLL: 111734642Smarc /* 111834642Smarc * unmap shared scroll param area and disable scroll intrpts 111934642Smarc */ 112030391Skarels if (qdflags[unit].mapped & MAPSCR) { 112134642Smarc qdflags[unit].mapped &= ~MAPSCR; 112234642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 112334642Smarc + (mfpr(SBR) | 0x80000000)); 112434642Smarc /* 112534642Smarc * re-protect 512 scroll param area 112634642Smarc */ 112734642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 112834642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 112934642Smarc adder = (struct adder *) qdmap[unit].adder; 113034642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 113134642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 113230391Skarels } 113330391Skarels break; 113430391Skarels 113534642Smarc case QD_MAPCOLOR: 113634642Smarc /* 113734642Smarc * map shared color map write buf and turn on vsync intrpt 113834642Smarc */ 113930391Skarels qdflags[unit].mapped |= MAPCOLOR; 114030391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 114134642Smarc + (mfpr(SBR) | 0x80000000)); 114234732Smarc /* 114334732Smarc * allow user write to color map write buffer 114434732Smarc */ 114534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 114630391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 114730391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 114834642Smarc adder = (struct adder *) qdmap[unit].adder; 114930391Skarels qdflags[unit].adder_ie |= VSYNC; 115030391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 115134732Smarc /* 115234732Smarc * return color area address 115334732Smarc */ 115430391Skarels *(int *)datap = (int) color_buf[unit]; 115530391Skarels break; 115630391Skarels 115734642Smarc case QD_UNMAPCOLOR: 115834642Smarc /* 115934732Smarc * unmap shared color map write buffer and kill VSYNC intrpts 116034732Smarc */ 116130391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 116234642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 116334642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 116434642Smarc + (mfpr(SBR) | 0x80000000)); 116534732Smarc /* 116634732Smarc * re-protect color map write buffer 116734732Smarc */ 116834732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 116934642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 117034732Smarc mtpr(TBIA, 0); 117134642Smarc adder = (struct adder *) qdmap[unit].adder; 117234642Smarc qdflags[unit].adder_ie &= ~VSYNC; 117334642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 117430391Skarels } 117530391Skarels break; 117630391Skarels 117734642Smarc case QD_MAPEVENT: 117834642Smarc /* 117934642Smarc * give user write access to the event queue 118034642Smarc */ 118130391Skarels qdflags[unit].mapped |= MAPEQ; 118230391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 118334642Smarc + (mfpr(SBR) | 0x80000000)); 118434732Smarc /* 118534732Smarc * allow user write to 1K event queue 118634732Smarc */ 118734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 118830391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 118930391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 119034732Smarc /* 119134732Smarc * return event queue address 119234732Smarc */ 119334732Smarc *(int *)datap = (int)eq_header[unit]; 119430391Skarels break; 119530391Skarels 119634642Smarc case QD_PRGKBD: 119734642Smarc /* 119834642Smarc * pass caller's programming commands to LK201 119934642Smarc */ 120034732Smarc duart = (struct duart *)qdmap[unit].duart; 120134732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 120234642Smarc /* 120334642Smarc * send command 120434642Smarc */ 120530391Skarels for (i = 1000; i > 0; --i) { 120634732Smarc if (duart->statusA&XMT_RDY) { 120734642Smarc duart->dataA = cmdbuf->cmd; 120834642Smarc break; 120934642Smarc } 121030391Skarels } 121130391Skarels if (i == 0) { 121234732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 121334642Smarc break; 121430391Skarels } 121534642Smarc /* 121634642Smarc * send param1? 121734642Smarc */ 121830391Skarels if (cmdbuf->cmd & LAST_PARAM) 121934642Smarc break; 122030391Skarels for (i = 1000; i > 0; --i) { 122134732Smarc if (duart->statusA&XMT_RDY) { 122234642Smarc duart->dataA = cmdbuf->param1; 122334642Smarc break; 122434642Smarc } 122530391Skarels } 122630391Skarels if (i == 0) { 122734732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 122834642Smarc break; 122930391Skarels } 123034642Smarc /* 123134642Smarc * send param2? 123234642Smarc */ 123330391Skarels if (cmdbuf->param1 & LAST_PARAM) 123430391Skarels break; 123530391Skarels for (i = 1000; i > 0; --i) { 123634732Smarc if (duart->statusA&XMT_RDY) { 123734642Smarc duart->dataA = cmdbuf->param2; 123834642Smarc break; 123934642Smarc } 124030391Skarels } 124130391Skarels if (i == 0) { 124234732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 124334642Smarc break; 124430391Skarels } 124530391Skarels break; 124630391Skarels 124734642Smarc case QD_PRGMOUSE: 124834642Smarc /* 124934642Smarc * pass caller's programming commands to the mouse 125034642Smarc */ 125130391Skarels duart = (struct duart *) qdmap[unit].duart; 125230391Skarels for (i = 1000; i > 0; --i) { 125334732Smarc if (duart->statusB&XMT_RDY) { 125434642Smarc duart->dataB = *datap; 125534642Smarc break; 125634642Smarc } 125730391Skarels } 125830391Skarels if (i == 0) { 125934732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 126030391Skarels } 126130391Skarels break; 126230391Skarels 126334642Smarc case QD_RDCONFIG: 126434642Smarc /* 126534642Smarc * get QDSS configuration word and return it 126634642Smarc */ 126730391Skarels *(short *)datap = qdflags[unit].config; 126830391Skarels break; 126930391Skarels 127034642Smarc case QD_KERN_LOOP: 127134642Smarc case QD_KERN_UNLOOP: 127234642Smarc /* 127334642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 127434642Smarc * kernel console output. 127534642Smarc */ 127634615Smarc break; 127734615Smarc 127834642Smarc case QD_PRGTABLET: 127934642Smarc /* 128034642Smarc * program the tablet 128134642Smarc */ 128230391Skarels duart = (struct duart *) qdmap[unit].duart; 128330391Skarels for (i = 1000; i > 0; --i) { 128434732Smarc if (duart->statusB&XMT_RDY) { 128534642Smarc duart->dataB = *datap; 128634642Smarc break; 128734642Smarc } 128830391Skarels } 128930391Skarels if (i == 0) { 129034732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 129130391Skarels } 129230391Skarels break; 129330391Skarels 129434642Smarc case QD_PRGTABRES: 129534642Smarc /* 129634642Smarc * program the tablet report resolution factor 129734642Smarc */ 129830391Skarels qdflags[unit].tab_res = *(short *)datap; 129930391Skarels break; 130030391Skarels 130134642Smarc default: 130234642Smarc /* 130334642Smarc * service tty ioctl's 130434642Smarc */ 130534642Smarc if (!(minor_dev & 0x02)) { 130630391Skarels tp = &qd_tty[minor_dev]; 130734642Smarc error = 130834642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 130930391Skarels if (error >= 0) { 131034642Smarc return(error); 131130391Skarels } 131230391Skarels error = ttioctl(tp, cmd, datap, flags); 131330391Skarels if (error >= 0) { 131434642Smarc return(error); 131530391Skarels } 131634642Smarc } 131734642Smarc break; 131830391Skarels } 131930391Skarels 132030391Skarels return(0); 132130391Skarels 132230391Skarels } /* qdioctl */ 132330391Skarels 132430391Skarels qdselect(dev, rw) 132534642Smarc dev_t dev; 132634642Smarc int rw; 132730391Skarels { 132834732Smarc register s; 132934732Smarc register unit; 133034615Smarc register struct tty *tp; 133134615Smarc u_int minor_dev = minor(dev); 133230391Skarels 133334615Smarc s = spl5(); 133434615Smarc unit = minor_dev >> 2; 133530391Skarels 133630391Skarels switch (rw) { 133734642Smarc case FREAD: 133834642Smarc if ((minor_dev & 0x03) == 2) { 133934642Smarc /* 134034642Smarc * this is a graphics device, so check for events 134134642Smarc */ 134234732Smarc if(!(ISEMPTY(eq_header[unit]))) { 134334642Smarc splx(s); 134434642Smarc return(1); 134534642Smarc } 134634732Smarc qdrsel[unit] = u.u_procp; 134734642Smarc qdflags[unit].selmask |= SEL_READ; 134834642Smarc splx(s); 134934642Smarc return(0); 135034642Smarc } else { 135134642Smarc /* 135234642Smarc * this is a tty device 135334642Smarc */ 135434642Smarc tp = &qd_tty[minor_dev]; 135534642Smarc if (ttnread(tp)) 135634642Smarc return(1); 135734642Smarc tp->t_rsel = u.u_procp; 135834642Smarc splx(s); 135934642Smarc return(0); 136030391Skarels } 136130391Skarels 136234642Smarc case FWRITE: 136334642Smarc if ((minor(dev) & 0x03) == 2) { 136434642Smarc /* 136534642Smarc * this is a graphics device, so check for dma buffers 136634642Smarc */ 136734642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 136834642Smarc { 136934642Smarc splx(s); 137034642Smarc return(1); 137134642Smarc } 137234732Smarc qdrsel[unit] = u.u_procp; 137334642Smarc qdflags[unit].selmask |= SEL_WRITE; 137434642Smarc splx(s); 137534642Smarc return(0); 137634642Smarc } else { 137734642Smarc /* 137834642Smarc * this is a tty device 137934642Smarc */ 138034642Smarc tp = &qd_tty[minor_dev]; 138137605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 138234642Smarc return(1); 138334642Smarc tp->t_wsel = u.u_procp; 138434642Smarc splx(s); 138534642Smarc return(0); 138630391Skarels } 138730391Skarels } 138834732Smarc splx(s); 138934732Smarc return(0); 139030391Skarels 139130391Skarels } /* qdselect() */ 139230391Skarels 139330391Skarels extern qd_strategy(); 139430391Skarels 139530391Skarels qdwrite(dev, uio) 139634642Smarc dev_t dev; 139734642Smarc struct uio *uio; 139830391Skarels { 139930391Skarels register struct tty *tp; 140034732Smarc register minor_dev; 140134732Smarc register unit; 140230391Skarels 140330391Skarels minor_dev = minor(dev); 140430391Skarels unit = (minor_dev >> 2) & 0x07; 140530391Skarels 140634642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 140734642Smarc /* 140834642Smarc * this is the console... 140934642Smarc */ 141034642Smarc tp = &qd_tty[minor_dev]; 141134642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 141234642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 141334642Smarc /* 141434642Smarc * this is a DMA xfer from user space 141534642Smarc */ 141634642Smarc return (physio(qd_strategy, &qdbuf[unit], 141734642Smarc dev, B_WRITE, minphys, uio)); 141830391Skarels } 141934732Smarc return (ENXIO); 142030391Skarels } 142130391Skarels 142230391Skarels qdread(dev, uio) 142334642Smarc dev_t dev; 142434642Smarc struct uio *uio; 142530391Skarels { 142630391Skarels register struct tty *tp; 142734732Smarc register minor_dev; 142834732Smarc register unit; 142930391Skarels 143030391Skarels minor_dev = minor(dev); 143130391Skarels unit = (minor_dev >> 2) & 0x07; 143230391Skarels 143334642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 143434642Smarc /* 143534642Smarc * this is the console 143634642Smarc */ 143734642Smarc tp = &qd_tty[minor_dev]; 143834642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 143934642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 144034642Smarc /* 144134642Smarc * this is a bitmap-to-processor xfer 144234642Smarc */ 144334642Smarc return (physio(qd_strategy, &qdbuf[unit], 144434642Smarc dev, B_READ, minphys, uio)); 144530391Skarels } 144634732Smarc return (ENXIO); 144730391Skarels } 144830391Skarels 144930391Skarels /*************************************************************** 145030391Skarels * 145130391Skarels * qd_strategy()... strategy routine to do DMA 145230391Skarels * 145330391Skarels ***************************************************************/ 145430391Skarels 145530391Skarels qd_strategy(bp) 145634642Smarc register struct buf *bp; 145730391Skarels { 145830391Skarels register struct dga *dga; 145930391Skarels register struct adder *adder; 146034732Smarc register unit; 146130391Skarels int QBAreg; 146230391Skarels int s; 146330391Skarels int cookie; 146430391Skarels 146530391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 146630391Skarels 146734642Smarc /* 146834642Smarc * init pointers 146934642Smarc */ 147030391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 147134732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 147234642Smarc goto STRAT_ERR; 147330391Skarels } 147430391Skarels dga = (struct dga *) qdmap[unit].dga; 147534615Smarc s = spl5(); 147630391Skarels qdflags[unit].user_dma = -1; 147730391Skarels dga->csr |= DMA_IE; 147830391Skarels cookie = QBAreg & 0x3FFFF; 147930391Skarels dga->adrs_lo = (short) cookie; 148030391Skarels dga->adrs_hi = (short) (cookie >> 16); 148130391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 148230391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 148330391Skarels 148430391Skarels while (qdflags[unit].user_dma) { 148534642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 148630391Skarels } 148730391Skarels splx(s); 148830391Skarels ubarelse(0, &QBAreg); 148930391Skarels if (!(dga->csr & DMA_ERR)) { 149034642Smarc iodone(bp); 149134642Smarc return; 149230391Skarels } 149330391Skarels 149430391Skarels STRAT_ERR: 149530391Skarels adder = (struct adder *) qdmap[unit].adder; 149634642Smarc adder->command = CANCEL; /* cancel adder activity */ 149730391Skarels dga->csr &= ~DMA_IE; 149830391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 149930391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 150030391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 150130391Skarels 150234642Smarc /* 150334642Smarc * if DMA was running, flush spurious intrpt 150434642Smarc */ 150530391Skarels if (dga->bytcnt_lo != 0) { 150634642Smarc dga->bytcnt_lo = 0; 150734642Smarc dga->bytcnt_hi = 0; 150834642Smarc DMA_SETIGNORE(DMAheader[unit]); 150934642Smarc dga->csr |= DMA_IE; 151030391Skarels } 151130391Skarels iodone(bp); 151230391Skarels 151330391Skarels } /* qd_strategy */ 151430391Skarels 151534732Smarc /* 151634732Smarc * Start output to the console screen 151734732Smarc */ 151830391Skarels qdstart(tp) 151934642Smarc register struct tty *tp; 152030391Skarels { 152134732Smarc register which_unit, unit, c; 152230391Skarels int s; 152334615Smarc 152430391Skarels unit = minor(tp->t_dev); 152530391Skarels which_unit = (unit >> 2) & 0x3; 152634615Smarc unit &= 0x03; 152730391Skarels 152834615Smarc s = spl5(); 152934615Smarc 153034642Smarc /* 153134642Smarc * If it's currently active, or delaying, no need to do anything. 153234642Smarc */ 153330391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 153430391Skarels goto out; 153530391Skarels 153634642Smarc /* 153734642Smarc * Display chars until the queue is empty. 153834642Smarc * Drop input from anything but the console 153934642Smarc * device on the floor. 154034642Smarc * 154134642Smarc * XXX - this loop is done at spltty. 154234642Smarc * 154334642Smarc */ 154434642Smarc while (tp->t_outq.c_cc) { 154534511Smarc c = getc(&tp->t_outq); 154634615Smarc if (unit == 0) 154734732Smarc blitc(which_unit, (u_char)c); 154830391Skarels } 154934642Smarc /* 155034642Smarc * If there are sleepers, and output has drained below low 155134642Smarc * water mark, wake up the sleepers. 155234642Smarc */ 155337605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 155434615Smarc if (tp->t_state & TS_ASLEEP){ 155534615Smarc tp->t_state &= ~TS_ASLEEP; 155634615Smarc wakeup((caddr_t) &tp->t_outq); 155734615Smarc } 155830391Skarels } 155930391Skarels 156034615Smarc tp->t_state &= ~TS_BUSY; 156134615Smarc 156230391Skarels out: 156330391Skarels splx(s); 156430391Skarels 156530391Skarels } /* qdstart */ 156630391Skarels 156734732Smarc /*ARGSUSED*/ 156830391Skarels qdstop(tp, flag) 156934642Smarc register struct tty *tp; 157034642Smarc int flag; 157130391Skarels { 157230391Skarels register int s; 157330391Skarels 157434615Smarc s = spl5(); /* block intrpts during state modification */ 157534732Smarc if (tp->t_state & TS_BUSY) 157634732Smarc if ((tp->t_state & TS_TTSTOP) == 0) 157734642Smarc tp->t_state |= TS_FLUSH; 157834642Smarc else 157934642Smarc tp->t_state &= ~TS_BUSY; 158030391Skarels splx(s); 158130391Skarels } 158230391Skarels 158334732Smarc /* 158434732Smarc * Output a character to the QDSS screen 158534732Smarc */ 158630391Skarels 158730391Skarels blitc(unit, chr) 158834732Smarc register unit; 158934732Smarc register u_char chr; 159030391Skarels { 159130391Skarels register struct adder *adder; 159230391Skarels register struct dga *dga; 159330391Skarels register int i; 159434642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 159534642Smarc static short inescape[NQD]; 159630391Skarels 159734732Smarc adder = (struct adder *)qdmap[unit].adder; 159830391Skarels dga = (struct dga *) qdmap[unit].dga; 159934642Smarc /* 160034642Smarc * BSD comment: this (&=0177) defeats the extended character 160134642Smarc * set code for the glass tty, but if i had the time i would 160234642Smarc * spend it ripping out the code completely. This driver 160334642Smarc * is too big for its own good. 160434642Smarc */ 160534642Smarc chr &= 0177; 160634642Smarc /* 160734732Smarc * Cursor addressing (so vi will work). 160834642Smarc * Decode for "\E=%.%." cursor motion description. 160934732Smarc * Corresponds to type "qdcons" in /etc/termcap: 161034642Smarc * 161134642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 161234642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 161334642Smarc * 161434642Smarc */ 161534642Smarc if (inescape[unit] && nograph) { 161634642Smarc switch (inescape[unit]++) { 161734642Smarc case 1: 161834642Smarc if (chr != '=') { 161934642Smarc /* abort escape sequence */ 162034642Smarc inescape[unit] = 0; 162134642Smarc blitc(unit, chr); 162234642Smarc } 162334732Smarc return; 162434642Smarc case 2: 162534642Smarc /* position row */ 162634642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 162734642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 162834642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 162934642Smarc dga->y_cursor = TRANY(cursor[unit].y); 163034732Smarc return; 163134642Smarc case 3: 163234642Smarc /* position column */ 163334642Smarc cursor[unit].x = CHAR_WIDTH * chr; 163434642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 163534642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 163634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 163734642Smarc inescape[unit] = 0; 163834732Smarc return; 163934642Smarc default: 164034642Smarc inescape[unit] = 0; 164134642Smarc blitc(unit, chr); 164234642Smarc } 164334642Smarc } 164430391Skarels 164530391Skarels switch (chr) { 164634642Smarc case '\r': /* return char */ 164730391Skarels cursor[unit].x = 0; 164834642Smarc if (nograph) 164934642Smarc dga->x_cursor = TRANX(cursor[unit].x); 165034732Smarc return; 165130391Skarels 165234642Smarc case '\t': /* tab char */ 165330391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 165434642Smarc blitc(unit, ' '); 165530391Skarels } 165634732Smarc return; 165730391Skarels 165834642Smarc case '\n': /* line feed char */ 165930391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 166034642Smarc if (nograph) { 166134642Smarc cursor[unit].y -= CHAR_HEIGHT; 166234642Smarc scroll_up(adder); 166334642Smarc } else 166434642Smarc cursor[unit].y = 0; 166530391Skarels } 166634642Smarc if (nograph) 166734642Smarc dga->y_cursor = TRANY(cursor[unit].y); 166834732Smarc return; 166930391Skarels 167034642Smarc case '\b': /* backspace char */ 167130391Skarels if (cursor[unit].x > 0) { 167234642Smarc cursor[unit].x -= CHAR_WIDTH; 167334642Smarc if (nograph) 167434642Smarc dga->x_cursor = TRANX(cursor[unit].x); 167530391Skarels } 167634732Smarc return; 167734642Smarc case CTRL('k'): /* cursor up */ 167834642Smarc if (nograph && cursor[unit].y > 0) { 167934642Smarc cursor[unit].y -= CHAR_HEIGHT; 168034642Smarc dga->y_cursor = TRANY(cursor[unit].y); 168134642Smarc } 168234732Smarc return; 168330391Skarels 168434642Smarc case CTRL('^'): /* home cursor */ 168534642Smarc if (nograph) { 168634642Smarc cursor[unit].x = 0; 168734642Smarc dga->x_cursor = TRANX(cursor[unit].x); 168834642Smarc cursor[unit].y = 0; 168934642Smarc dga->y_cursor = TRANY(cursor[unit].y); 169034642Smarc } 169134732Smarc return; 169232012Smarc 169334642Smarc case CTRL('l'): /* cursor right */ 169434642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 169534642Smarc cursor[unit].x += CHAR_WIDTH; 169634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 169734642Smarc } 169834732Smarc return; 169930391Skarels 170034642Smarc case CTRL('z'): /* clear screen */ 170134642Smarc if (nograph) { 170234642Smarc setup_dragon(unit); 170334642Smarc clear_qd_screen(unit); 170434642Smarc /* home cursor - termcap seems to assume this */ 170534642Smarc cursor[unit].x = 0; 170634642Smarc dga->x_cursor = TRANX(cursor[unit].x); 170734642Smarc cursor[unit].y = 0; 170834642Smarc dga->y_cursor = TRANY(cursor[unit].y); 170934642Smarc } 171034732Smarc return; 171130391Skarels 171234642Smarc case '\033': /* start escape sequence */ 171334642Smarc if (nograph) 171434642Smarc inescape[unit] = 1; 171534732Smarc return; 171634642Smarc 171734642Smarc default: 171834642Smarc if ((chr < ' ') || (chr > '~')) 171934732Smarc return; 172034642Smarc } 172134642Smarc /* 172234642Smarc * setup VIPER operand control registers 172334642Smarc */ 172430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 172530391Skarels write_ID(adder, SRC1_OCR_B, 172634642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 172730391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 172830391Skarels write_ID(adder, SRC1_OCR_B, 172934642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 173030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 173130391Skarels write_ID(adder, DST_OCR_B, 173234642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 173330391Skarels write_ID(adder, MASK_1, 0xFFFF); 173430391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 173530391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 173634642Smarc adder->x_clip_min = 0; 173734642Smarc adder->x_clip_max = 1024; 173834642Smarc adder->y_clip_min = 0; 173934642Smarc adder->y_clip_max = 864; 174034642Smarc /* 174134642Smarc * load DESTINATION origin and vectors 174234642Smarc */ 174330391Skarels adder->fast_dest_dy = 0; 174430391Skarels adder->slow_dest_dx = 0; 174530391Skarels adder->error_1 = 0; 174630391Skarels adder->error_2 = 0; 174730391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 174834732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 174930391Skarels adder->destination_x = cursor[unit].x; 175030391Skarels adder->fast_dest_dx = CHAR_WIDTH; 175130391Skarels adder->destination_y = cursor[unit].y; 175230391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 175334642Smarc /* 175434642Smarc * load SOURCE origin and vectors 175534642Smarc */ 175634615Smarc if ((chr - ' ') > (CHARS - 1)) { 175734615Smarc printf("Invalid character (x)%x in blitc\n",chr); 175834615Smarc chr = ' '; 175934615Smarc } 176034642Smarc /* 176134642Smarc * X position is modulo the number of characters per line 176234642Smarc */ 176334615Smarc adder->source_1_x = FONT_X + 176434642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 176534642Smarc /* 176634642Smarc * Point to either first or second row 176734642Smarc */ 176834615Smarc adder->source_1_y = 2048 - 15 * 176934642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 177030391Skarels adder->source_1_dx = CHAR_WIDTH; 177130391Skarels adder->source_1_dy = CHAR_HEIGHT; 177230391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 177330391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 177434642Smarc /* 177534642Smarc * update console cursor coordinates 177634642Smarc */ 177730391Skarels cursor[unit].x += CHAR_WIDTH; 177834642Smarc if (nograph) 177934642Smarc dga->x_cursor = TRANX(cursor[unit].x); 178030391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 178134642Smarc blitc(unit, '\r'); 178234642Smarc blitc(unit, '\n'); 178330391Skarels } 178430391Skarels 178530391Skarels } /* blitc */ 178630391Skarels 178734732Smarc qdreset() { } 178830391Skarels 178934732Smarc /* 179034732Smarc * INTERRUPT SERVICE ROUTINES 179134732Smarc */ 179230391Skarels 179334732Smarc /* 179434732Smarc * Service "DMA DONE" interrupt condition 179534732Smarc */ 179630391Skarels qddint(qd) 179734732Smarc register qd; 179830391Skarels { 179930391Skarels register struct DMAreq_header *header; 180030391Skarels register struct DMAreq *request; 180130391Skarels register struct dga *dga; 180230391Skarels struct adder *adder; 180330391Skarels int cookie; /* DMA adrs for QDSS */ 180430391Skarels 180534732Smarc (void)spl4(); /* allow interval timer in */ 180630391Skarels 180734642Smarc /* 180834642Smarc * init pointers 180934642Smarc */ 181030391Skarels header = DMAheader[qd]; /* register for optimization */ 181130391Skarels dga = (struct dga *) qdmap[qd].dga; 181230391Skarels adder = (struct adder *) qdmap[qd].adder; 181330391Skarels 181434642Smarc /* 181534642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 181634642Smarc */ 181730391Skarels if (DMA_ISIGNORE(header)) { 181834642Smarc DMA_CLRIGNORE(header); 181934642Smarc return; 182030391Skarels } 182130391Skarels 182234642Smarc /* 182334642Smarc * dump a DMA hardware error message if appropriate 182434642Smarc */ 182530391Skarels if (dga->csr & DMA_ERR) { 182630391Skarels 182734642Smarc if (dga->csr & PARITY_ERR) 182834732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 182930391Skarels 183034642Smarc if (dga->csr & BUS_ERR) 183134732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 183230391Skarels } 183330391Skarels 183434642Smarc /* 183534642Smarc * if this was a DMA from user space... 183634642Smarc */ 183730391Skarels if (qdflags[qd].user_dma) { 183834642Smarc qdflags[qd].user_dma = 0; 183934642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 184034642Smarc return; 184130391Skarels } 184230391Skarels 184334642Smarc /* 184434642Smarc * if we're doing DMA request queue services, field the error condition 184534642Smarc */ 184630391Skarels if (dga->csr & DMA_ERR) { 184730391Skarels 184834642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 184934642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 185034642Smarc adder->command = CANCEL; /* cancel adder activity */ 185130391Skarels 185234642Smarc DMA_SETERROR(header); /* flag error in header status word */ 185334642Smarc DMA_CLRACTIVE(header); 185434642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 185534642Smarc header->newest = header->oldest; 185634642Smarc header->used = 0; 185730391Skarels 185834732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 185934732Smarc selwakeup(qdrsel[qd], 0); 186034732Smarc qdrsel[qd] = 0; 186134642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 186234642Smarc } 186330391Skarels 186434642Smarc if (dga->bytcnt_lo != 0) { 186534642Smarc dga->bytcnt_lo = 0; 186634642Smarc dga->bytcnt_hi = 0; 186734642Smarc DMA_SETIGNORE(header); 186834642Smarc } 186934642Smarc return; 187030391Skarels } 187130391Skarels 187234642Smarc /* 187334642Smarc * if the DMA request queue is now becoming non-full, 187434642Smarc * wakeup "select" client. 187534642Smarc */ 187630391Skarels if (DMA_ISFULL(header)) { 187734732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 187834732Smarc selwakeup(qdrsel[qd], 0); 187934732Smarc qdrsel[qd] = 0; 188034642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 188134642Smarc } 188230391Skarels } 188330391Skarels 188430391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 188534642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 188630391Skarels 188734615Smarc /* check for unexpected interrupt */ 188834615Smarc if (DMA_ISEMPTY(header)) 188930391Skarels return; 189030391Skarels 189130391Skarels DMA_GETEND(header); /* update request queue indices */ 189230391Skarels 189334642Smarc /* 189434732Smarc * if no more DMA pending, wake up "select" client and exit 189534732Smarc */ 189630391Skarels if (DMA_ISEMPTY(header)) { 189730391Skarels 189834732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 189934732Smarc selwakeup(qdrsel[qd], 0); 190034732Smarc qdrsel[qd] = 0; 190134642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 190234642Smarc } 190330391Skarels 190434642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 190534642Smarc return; 190630391Skarels } 190730391Skarels 190834642Smarc /* 190934732Smarc * initiate next DMA xfer 191034732Smarc */ 191130391Skarels request = DMA_GETBEGIN(header); 191234615Smarc if (request->DMAtype != QDlast_DMAtype) { 191334642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 191434642Smarc adder->command = CANCEL; /* cancel adder activity */ 191534615Smarc } 191630391Skarels 191734615Smarc 191830391Skarels switch (request->DMAtype) { 191930391Skarels 192034642Smarc case DISPLIST: 192134615Smarc if (request->DMAtype != QDlast_DMAtype) { 192234615Smarc dga->csr |= DL_ENB; 192334615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 192434615Smarc } 192530391Skarels break; 192630391Skarels 192734642Smarc case PTOB: 192834615Smarc if (request->DMAtype != QDlast_DMAtype) { 192934615Smarc if (request->DMAdone & BYTE_PACK) 193034642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 193134615Smarc else { 193234615Smarc dga->csr |= PTOB_ENB; 193334615Smarc dga->csr &= ~BYTE_DMA; 193434615Smarc } 193534615Smarc } 193630391Skarels break; 193730391Skarels 193834642Smarc case BTOP: 193934615Smarc if (request->DMAtype != QDlast_DMAtype) { 194034615Smarc if (request->DMAdone & BYTE_PACK) { 194134615Smarc dga->csr &= ~DL_ENB; 194234615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 194334615Smarc } 194434615Smarc else { 194534615Smarc dga->csr |= BTOP_ENB; 194634615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 194734615Smarc } 194834615Smarc } 194930391Skarels break; 195034642Smarc default: 195134732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 195230391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 195330391Skarels return; 195430391Skarels } 195530391Skarels 195630391Skarels if (request->DMAdone & COUNT_ZERO) { 195734642Smarc dga->csr &= ~SET_DONE_FIFO; 195834642Smarc } 195934642Smarc else if (request->DMAdone & FIFO_EMPTY) { 196034642Smarc dga->csr |= SET_DONE_FIFO; 196130391Skarels } 196230391Skarels 196330391Skarels if (request->DMAdone & WORD_PACK) 196430391Skarels dga->csr &= ~BYTE_DMA; 196530391Skarels else if (request->DMAdone & BYTE_PACK) 196630391Skarels dga->csr |= BYTE_DMA; 196730391Skarels 196830391Skarels dga->csr |= DMA_IE; 196934642Smarc QDlast_DMAtype = request->DMAtype; 197030391Skarels 197130391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 197230391Skarels 197330391Skarels dga->adrs_lo = (short) cookie; 197430391Skarels dga->adrs_hi = (short) (cookie >> 16); 197530391Skarels 197630391Skarels dga->bytcnt_lo = (short) request->length; 197730391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 197830391Skarels 197930391Skarels return; 198030391Skarels } 198130391Skarels 198234732Smarc /* 198334732Smarc * ADDER interrupt service routine 198434732Smarc */ 198530391Skarels qdaint(qd) 198634732Smarc register qd; 198730391Skarels { 198830391Skarels register struct adder *adder; 198930391Skarels struct color_buf *cbuf; 199030391Skarels int i; 199130391Skarels register struct rgb *rgbp; 199230391Skarels register short *red; 199330391Skarels register short *green; 199430391Skarels register short *blue; 199530391Skarels 199634732Smarc (void)spl4(); /* allow interval timer in */ 199730391Skarels 199830391Skarels adder = (struct adder *) qdmap[qd].adder; 199930391Skarels 200034642Smarc /* 200134642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 200234642Smarc * any pending color map load request 200334642Smarc */ 200430391Skarels if (adder->status & VSYNC) { 200534642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 200634642Smarc cbuf = color_buf[qd]; 200734642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 200830391Skarels 200934642Smarc red = (short *) qdmap[qd].red; 201034642Smarc green = (short *) qdmap[qd].green; 201134642Smarc blue = (short *) qdmap[qd].blue; 201230391Skarels 201334642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 201434642Smarc --i >= 0; rgbp++) { 201534642Smarc red[rgbp->offset] = (short) rgbp->red; 201634642Smarc green[rgbp->offset] = (short) rgbp->green; 201734642Smarc blue[rgbp->offset] = (short) rgbp->blue; 201834642Smarc } 201930391Skarels 202034642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 202130391Skarels } 202230391Skarels } 202330391Skarels 202434642Smarc /* 202534642Smarc * service the scroll interrupt (FRAME_SYNC bit) 202634642Smarc */ 202730391Skarels if (adder->status & FRAME_SYNC) { 202834642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 202930391Skarels 203034642Smarc if (scroll[qd]->status & LOAD_REGS) { 203130391Skarels 203234732Smarc for (i = 1000, adder->status = 0; i > 0 && 203334732Smarc !(adder->status&ID_SCROLL_READY); --i) 203434642Smarc ; 203530391Skarels 203634642Smarc if (i == 0) { 203734732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 203834642Smarc qd); 203934642Smarc return; 204034642Smarc } 204130391Skarels 204234642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 204334642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 204430391Skarels 204534642Smarc adder->y_scroll_constant = 204634642Smarc scroll[qd]->y_scroll_constant; 204734642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 204830391Skarels 204934642Smarc if (scroll[qd]->status & LOAD_INDEX) { 205030391Skarels 205134642Smarc adder->x_index_pending = 205234642Smarc scroll[qd]->x_index_pending; 205334642Smarc adder->y_index_pending = 205434642Smarc scroll[qd]->y_index_pending; 205534642Smarc } 205634642Smarc 205734642Smarc scroll[qd]->status = 0x00; 205830391Skarels } 205930391Skarels } 206030391Skarels } 206130391Skarels 206234732Smarc /* 206334732Smarc * DUART input interrupt service routine 206434732Smarc * 206534732Smarc * XXX - this routine should be broken out - it is essentially 206634732Smarc * straight line code. 206734732Smarc */ 206830391Skarels 206930391Skarels qdiint(qd) 207034732Smarc register qd; 207130391Skarels { 207230391Skarels register struct _vs_event *event; 207330391Skarels register struct qdinput *eqh; 207430391Skarels struct dga *dga; 207530391Skarels struct duart *duart; 207630391Skarels struct mouse_report *new_rep; 207730391Skarels struct uba_device *ui; 207830391Skarels struct tty *tp; 207934615Smarc u_short chr; 208030391Skarels u_short status; 208130391Skarels u_short data; 208230391Skarels u_short key; 208330391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 208430391Skarels char a, b, c; /* mouse button test variables */ 208530391Skarels 208634732Smarc (void)spl4(); /* allow interval timer in */ 208730391Skarels 208830391Skarels eqh = eq_header[qd]; /* optimized as a register */ 208930391Skarels new_rep = ¤t_rep[qd]; 209030391Skarels duart = (struct duart *) qdmap[qd].duart; 209130391Skarels 209234642Smarc /* 209334732Smarc * if the graphic device is turned on.. 209434732Smarc */ 209530391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 209634642Smarc /* 209734642Smarc * empty DUART 209834642Smarc */ 209934732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 210034642Smarc /* 210134732Smarc * pick up LK-201 input (if any) 210234732Smarc */ 210334732Smarc if (duart->statusA&RCV_RDY) { 210430391Skarels 210534642Smarc /* if error condition, then reset it */ 210630391Skarels 210734732Smarc if (duart->statusA&0x70) { 210834642Smarc duart->cmdA = 0x40; 210934642Smarc continue; 211034642Smarc } 211130391Skarels 211234642Smarc /* event queue full now? (overflow condition) */ 211330391Skarels 211434642Smarc if (ISFULL(eqh) == TRUE) { 211534642Smarc printf( 211634732Smarc "qd%d: qdiint: event queue overflow\n", 211734642Smarc qd); 211834642Smarc break; 211934642Smarc } 212030391Skarels 212134642Smarc /* 212234642Smarc * Check for various keyboard errors */ 212330391Skarels 212434642Smarc key = duart->dataA & 0xFF; 212530391Skarels 212634642Smarc if (key==LK_POWER_ERROR || 212734642Smarc key==LK_KDOWN_ERROR || 212834642Smarc key == LK_INPUT_ERROR || 212934642Smarc key == LK_OUTPUT_ERROR) { 213034642Smarc printf( 213134732Smarc "qd%d: qdiint: keyboard error, code = %x\n", 213234642Smarc qd,key); 213334732Smarc return; 213434642Smarc } 213530391Skarels 213634642Smarc if (key < LK_LOWEST) 213734732Smarc return; 213830391Skarels 213934642Smarc ++do_wakeup; /* request a select wakeup call */ 214030391Skarels 214134642Smarc event = PUTBEGIN(eqh); 214234642Smarc PUTEND(eqh); 214330391Skarels 214434642Smarc event->vse_key = key; 214534642Smarc event->vse_key &= 0x00FF; 214634642Smarc event->vse_x = eqh->curs_pos.x; 214734642Smarc event->vse_y = eqh->curs_pos.y; 214834642Smarc event->vse_time = TOY; 214934642Smarc event->vse_type = VSE_BUTTON; 215034642Smarc event->vse_direction = VSE_KBTRAW; 215134642Smarc event->vse_device = VSE_DKB; 215234642Smarc } 215330391Skarels 215434642Smarc /* 215534642Smarc * pick up the mouse input (if any) */ 215630391Skarels 215734642Smarc if ((status = duart->statusB) & RCV_RDY && 215834642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 215930391Skarels 216034642Smarc if (status & 0x70) { 216134642Smarc duart->cmdB = 0x40; 216234642Smarc continue; 216334642Smarc } 216430391Skarels 216534642Smarc /* event queue full now? (overflow condition) */ 216630391Skarels 216734642Smarc if (ISFULL(eqh) == TRUE) { 216834642Smarc printf( 216934732Smarc "qd%d: qdiint: event queue overflow\n", 217034642Smarc qd); 217134642Smarc break; 217234642Smarc } 217330391Skarels 217434642Smarc data = duart->dataB; /* get report byte */ 217534642Smarc ++new_rep->bytcnt; /* bump report byte count */ 217630391Skarels 217734642Smarc /* 217834642Smarc * if 1st byte of report.. */ 217930391Skarels 218034642Smarc if ( data & START_FRAME) { 218134642Smarc new_rep->state = data; 218234642Smarc if (new_rep->bytcnt > 1) { 218334642Smarc /* start of new frame */ 218434642Smarc new_rep->bytcnt = 1; 218534642Smarc /* ..continue looking */ 218634642Smarc continue; 218734642Smarc } 218834642Smarc } 218930391Skarels 219034642Smarc /* 219134642Smarc * if 2nd byte of report.. */ 219230391Skarels 219334642Smarc else if (new_rep->bytcnt == 2) { 219434642Smarc new_rep->dx = data & 0x00FF; 219534642Smarc } 219630391Skarels 219734642Smarc /* 219834642Smarc * if 3rd byte of report, load input event queue */ 219930391Skarels 220034642Smarc else if (new_rep->bytcnt == 3) { 220130391Skarels 220234642Smarc new_rep->dy = data & 0x00FF; 220334642Smarc new_rep->bytcnt = 0; 220430391Skarels 220534642Smarc /* 220634642Smarc * if mouse position has changed.. */ 220730391Skarels 220834642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 220930391Skarels 221034642Smarc /* 221134642Smarc * calculate acceleration factor, if needed */ 221230391Skarels 221334642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 221430391Skarels 221534642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 221634642Smarc new_rep->dx += 221734642Smarc (new_rep->dx - qdflags[qd].curs_thr) 221834642Smarc * qdflags[qd].curs_acc; 221930391Skarels 222034642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 222134642Smarc new_rep->dy += 222234642Smarc (new_rep->dy - qdflags[qd].curs_thr) 222334642Smarc * qdflags[qd].curs_acc; 222434642Smarc } 222530391Skarels 222634642Smarc /* 222734642Smarc * update cursor position coordinates */ 222830391Skarels 222934642Smarc if (new_rep->state & X_SIGN) { 223034642Smarc eqh->curs_pos.x += new_rep->dx; 223134642Smarc if (eqh->curs_pos.x > 1023) 223234642Smarc eqh->curs_pos.x = 1023; 223334642Smarc } 223434642Smarc else { 223534642Smarc eqh->curs_pos.x -= new_rep->dx; 223634642Smarc if (eqh->curs_pos.x < -15) 223734642Smarc eqh->curs_pos.x = -15; 223834642Smarc } 223930391Skarels 224034642Smarc if (new_rep->state & Y_SIGN) { 224134642Smarc eqh->curs_pos.y -= new_rep->dy; 224234642Smarc if (eqh->curs_pos.y < -15) 224334642Smarc eqh->curs_pos.y = -15; 224434642Smarc } 224534642Smarc else { 224634642Smarc eqh->curs_pos.y += new_rep->dy; 224734642Smarc if (eqh->curs_pos.y > 863) 224834642Smarc eqh->curs_pos.y = 863; 224934642Smarc } 225030391Skarels 225134642Smarc /* 225234642Smarc * update cursor screen position */ 225330391Skarels 225434642Smarc dga = (struct dga *) qdmap[qd].dga; 225534642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 225634642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 225730391Skarels 225834642Smarc /* 225934642Smarc * if cursor is in the box, no event report */ 226030391Skarels 226134642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 226234642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 226334642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 226434642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 226534642Smarc goto GET_MBUTTON; 226634642Smarc } 226730391Skarels 226834642Smarc /* 226934642Smarc * report the mouse motion event */ 227030391Skarels 227134642Smarc event = PUTBEGIN(eqh); 227234642Smarc PUTEND(eqh); 227330391Skarels 227434642Smarc ++do_wakeup; /* request a select wakeup call */ 227530391Skarels 227634642Smarc event->vse_x = eqh->curs_pos.x; 227734642Smarc event->vse_y = eqh->curs_pos.y; 227830391Skarels 227934642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 228034642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 228134642Smarc event->vse_key = 0; 228234642Smarc event->vse_direction = 0; 228334642Smarc event->vse_time = TOY; /* time stamp */ 228434642Smarc } 228530391Skarels 228630391Skarels GET_MBUTTON: 228734642Smarc /* 228834642Smarc * if button state has changed */ 228930391Skarels 229034642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 229134642Smarc b = last_rep[qd].state & 0x07; 229230391Skarels 229334642Smarc if (a ^ b) { 229430391Skarels 229534642Smarc for ( c = 1; c < 8; c <<= 1) { 229630391Skarels 229734642Smarc if (!( c & (a ^ b))) /* this button change? */ 229834642Smarc continue; 229930391Skarels 230034642Smarc /* event queue full? (overflow condition) */ 230130391Skarels 230234642Smarc if (ISFULL(eqh) == TRUE) { 230334732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 230434642Smarc break; 230534642Smarc } 230630391Skarels 230734642Smarc event = PUTBEGIN(eqh); /* get new event */ 230834642Smarc PUTEND(eqh); 230930391Skarels 231034642Smarc ++do_wakeup; /* request select wakeup */ 231130391Skarels 231234642Smarc event->vse_x = eqh->curs_pos.x; 231334642Smarc event->vse_y = eqh->curs_pos.y; 231430391Skarels 231534642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 231634642Smarc event->vse_type = VSE_BUTTON; /* new button */ 231734642Smarc event->vse_time = TOY; /* time stamp */ 231830391Skarels 231934642Smarc /* flag changed button and if up or down */ 232030391Skarels 232134642Smarc if (c == RIGHT_BUTTON) 232234642Smarc event->vse_key = VSE_RIGHT_BUTTON; 232334642Smarc else if (c == MIDDLE_BUTTON) 232434642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 232534642Smarc else if (c == LEFT_BUTTON) 232634642Smarc event->vse_key = VSE_LEFT_BUTTON; 232730391Skarels 232834642Smarc /* set bit = button depressed */ 232930391Skarels 233034642Smarc if (c & a) 233134642Smarc event->vse_direction = VSE_KBTDOWN; 233234642Smarc else 233334642Smarc event->vse_direction = VSE_KBTUP; 233434642Smarc } 233534642Smarc } 233630391Skarels 233734642Smarc /* refresh last report */ 233830391Skarels 233934642Smarc last_rep[qd] = current_rep[qd]; 234030391Skarels 234134642Smarc } /* get last byte of report */ 234234732Smarc } else if ((status = duart->statusB)&RCV_RDY && 234334732Smarc qdflags[qd].pntr_id == TABLET_ID) { 234434732Smarc /* 234534732Smarc * pickup tablet input, if any 234634732Smarc */ 234734732Smarc if (status&0x70) { 234834642Smarc duart->cmdB = 0x40; 234934642Smarc continue; 235034642Smarc } 235134732Smarc /* 235234732Smarc * event queue full now? (overflow condition) 235334732Smarc */ 235434642Smarc if (ISFULL(eqh) == TRUE) { 235534732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 235634642Smarc break; 235734642Smarc } 235830391Skarels 235934642Smarc data = duart->dataB; /* get report byte */ 236034642Smarc ++new_rep->bytcnt; /* bump report byte count */ 236130391Skarels 236234642Smarc /* 236334642Smarc * if 1st byte of report.. */ 236430391Skarels 236534642Smarc if (data & START_FRAME) { 236634642Smarc new_rep->state = data; 236734642Smarc if (new_rep->bytcnt > 1) { 236834642Smarc new_rep->bytcnt = 1; /* start of new frame */ 236934642Smarc continue; /* ..continue looking */ 237034642Smarc } 237134642Smarc } 237230391Skarels 237334642Smarc /* 237434642Smarc * if 2nd byte of report.. */ 237530391Skarels 237634642Smarc else if (new_rep->bytcnt == 2) { 237734642Smarc new_rep->dx = data & 0x3F; 237834642Smarc } 237930391Skarels 238034642Smarc /* 238134642Smarc * if 3rd byte of report.. */ 238230391Skarels 238334642Smarc else if (new_rep->bytcnt == 3) { 238434642Smarc new_rep->dx |= (data & 0x3F) << 6; 238534642Smarc } 238630391Skarels 238734642Smarc /* 238834642Smarc * if 4th byte of report.. */ 238930391Skarels 239034642Smarc else if (new_rep->bytcnt == 4) { 239134642Smarc new_rep->dy = data & 0x3F; 239234642Smarc } 239330391Skarels 239434642Smarc /* 239534642Smarc * if 5th byte of report, load input event queue */ 239630391Skarels 239734642Smarc else if (new_rep->bytcnt == 5) { 239830391Skarels 239934642Smarc new_rep->dy |= (data & 0x3F) << 6; 240034642Smarc new_rep->bytcnt = 0; 240130391Skarels 240234642Smarc /* 240334642Smarc * update cursor position coordinates */ 240430391Skarels 240534642Smarc new_rep->dx /= qdflags[qd].tab_res; 240634642Smarc new_rep->dy = (2200 - new_rep->dy) 240734642Smarc / qdflags[qd].tab_res; 240830391Skarels 240934642Smarc if (new_rep->dx > 1023) { 241034642Smarc new_rep->dx = 1023; 241134642Smarc } 241234642Smarc if (new_rep->dy > 863) { 241334642Smarc new_rep->dy = 863; 241434642Smarc } 241530391Skarels 241634642Smarc /* 241734642Smarc * report an event if the puck/stylus has moved 241834642Smarc */ 241930391Skarels 242034642Smarc if (eqh->curs_pos.x != new_rep->dx || 242134642Smarc eqh->curs_pos.y != new_rep->dy) { 242230391Skarels 242334642Smarc eqh->curs_pos.x = new_rep->dx; 242434642Smarc eqh->curs_pos.y = new_rep->dy; 242530391Skarels 242634642Smarc /* 242734642Smarc * update cursor screen position */ 242830391Skarels 242934642Smarc dga = (struct dga *) qdmap[qd].dga; 243034642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 243134642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 243230391Skarels 243334642Smarc /* 243434642Smarc * if cursor is in the box, no event report 243534642Smarc */ 243630391Skarels 243734642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 243834642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 243934642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 244034642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 244134642Smarc goto GET_TBUTTON; 244234642Smarc } 244330391Skarels 244434642Smarc /* 244534642Smarc * report the tablet motion event */ 244630391Skarels 244734642Smarc event = PUTBEGIN(eqh); 244834642Smarc PUTEND(eqh); 244930391Skarels 245034642Smarc ++do_wakeup; /* request a select wakeup call */ 245130391Skarels 245234642Smarc event->vse_x = eqh->curs_pos.x; 245334642Smarc event->vse_y = eqh->curs_pos.y; 245430391Skarels 245534642Smarc event->vse_device = VSE_TABLET; /* tablet */ 245634642Smarc /* 245734642Smarc * right now, X handles tablet motion the same 245834642Smarc * as mouse motion 245934642Smarc */ 246034642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 246134642Smarc event->vse_key = 0; 246234642Smarc event->vse_direction = 0; 246334642Smarc event->vse_time = TOY; /* time stamp */ 246434642Smarc } 246530391Skarels GET_TBUTTON: 246634642Smarc /* 246734642Smarc * if button state has changed */ 246830391Skarels 246934642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 247034642Smarc b = last_rep[qd].state & 0x1E; 247130391Skarels 247234642Smarc if (a ^ b) { 247330391Skarels 247434642Smarc /* event queue full now? (overflow condition) */ 247530391Skarels 247634642Smarc if (ISFULL(eqh) == TRUE) { 247734732Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 247834642Smarc break; 247934642Smarc } 248030391Skarels 248134642Smarc event = PUTBEGIN(eqh); /* get new event */ 248234642Smarc PUTEND(eqh); 248330391Skarels 248434642Smarc ++do_wakeup; /* request a select wakeup call */ 248530391Skarels 248634642Smarc event->vse_x = eqh->curs_pos.x; 248734642Smarc event->vse_y = eqh->curs_pos.y; 248830391Skarels 248934642Smarc event->vse_device = VSE_TABLET; /* tablet */ 249034642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 249134642Smarc event->vse_time = TOY; /* time stamp */ 249230391Skarels 249334642Smarc /* define the changed button and if up or down */ 249430391Skarels 249534642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 249634642Smarc if (c & (a ^ b)) { 249734642Smarc if (c == T_LEFT_BUTTON) 249834642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 249934642Smarc else if (c == T_FRONT_BUTTON) 250034642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 250134642Smarc else if (c == T_RIGHT_BUTTON) 250234642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 250334642Smarc else if (c == T_BACK_BUTTON) 250434642Smarc event->vse_key = VSE_T_BACK_BUTTON; 250534642Smarc break; 250634642Smarc } 250734642Smarc } 250830391Skarels 250934642Smarc /* set bit = button depressed */ 251030391Skarels 251134642Smarc if (c & a) 251234642Smarc event->vse_direction = VSE_KBTDOWN; 251334642Smarc else 251434642Smarc event->vse_direction = VSE_KBTUP; 251534642Smarc } 251630391Skarels 251734642Smarc /* refresh last report */ 251830391Skarels 251934642Smarc last_rep[qd] = current_rep[qd]; 252030391Skarels 252134642Smarc } /* get last byte of report */ 252234642Smarc } /* pick up tablet input */ 252330391Skarels 252434642Smarc } /* while input available.. */ 252530391Skarels 252634642Smarc /* 252734642Smarc * do select wakeup 252834642Smarc */ 252934732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 253034732Smarc selwakeup(qdrsel[qd], 0); 253134732Smarc qdrsel[qd] = 0; 253234642Smarc qdflags[qd].selmask &= ~SEL_READ; 253334642Smarc do_wakeup = 0; 253434642Smarc } 253534732Smarc } else { 253634732Smarc /* 253734732Smarc * if the graphic device is not turned on, this is console input 253834732Smarc */ 2539*40817Smarc if (qdpolling) 2540*40817Smarc return; 254134642Smarc ui = qdinfo[qd]; 254234642Smarc if (ui == 0 || ui->ui_alive == 0) 254334732Smarc return; 254430391Skarels 254534642Smarc tp = &qd_tty[qd << 2]; 254630391Skarels 254734642Smarc /* 254834732Smarc * Get a character from the keyboard. 254934732Smarc */ 255034732Smarc while (duart->statusA&RCV_RDY) { 255134642Smarc key = duart->dataA; 255234642Smarc key &= 0xFF; 255334642Smarc /* 255434732Smarc * Check for various keyboard errors 255534732Smarc */ 255634732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 255734642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 255834732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 255934732Smarc return; 256034642Smarc } 256130391Skarels 256234642Smarc if (key < LK_LOWEST) 256334732Smarc return; 256430391Skarels 256534642Smarc /* 256634642Smarc * See if its a state change key */ 256730391Skarels 256834642Smarc switch (key) { 256930391Skarels 257034642Smarc case LOCK: 257134642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 257234642Smarc if (q_keyboard.lock) 257334732Smarc (void)led_control(qd, LK_LED_ENABLE, 257434732Smarc LK_LED_LOCK); 257534642Smarc else 257634732Smarc (void)led_control(qd, LK_LED_DISABLE, 257734732Smarc LK_LED_LOCK); 257834642Smarc return; 257930391Skarels 258034642Smarc case SHIFT: 258134642Smarc q_keyboard.shift ^= 0xFFFF; 258234642Smarc return; 258330391Skarels 258434642Smarc case CNTRL: 258534642Smarc q_keyboard.cntrl ^= 0xFFFF; 258634642Smarc return; 258730391Skarels 258834642Smarc case ALLUP: 258934642Smarc q_keyboard.cntrl = 0; 259034642Smarc q_keyboard.shift = 0; 259134642Smarc return; 259230391Skarels 259334642Smarc case REPEAT: 259434642Smarc chr = q_keyboard.last; 259534642Smarc break; 259630391Skarels 259734642Smarc /* 259834642Smarc * Test for cntrl characters. If set, see if the character 259934642Smarc * is elligible to become a control character. */ 260030391Skarels 260134642Smarc default: 260230391Skarels 260334642Smarc if (q_keyboard.cntrl) { 260434642Smarc chr = q_key[key]; 260534642Smarc if (chr >= ' ' && chr <= '~') 260634642Smarc chr &= 0x1F; 260734642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 260834642Smarc chr &= 0x9F; 260934642Smarc } 261034642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 261134642Smarc chr = q_shift_key[key]; 261234642Smarc else 261334642Smarc chr = q_key[key]; 261434642Smarc break; 261530391Skarels } 261630391Skarels 261734642Smarc q_keyboard.last = chr; 261830391Skarels 261934642Smarc /* 262034642Smarc * Check for special function keys */ 262130391Skarels 262234642Smarc if (chr & 0x100) { 262334642Smarc char *string; 262434642Smarc string = q_special[chr & 0x7F]; 262534642Smarc while(*string) 262634642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 262734615Smarc } 262834642Smarc else { 2629*40817Smarc #ifdef KADB 2630*40817Smarc if (!kdbrintr(chr&0177, tp)) 2631*40817Smarc #endif 263234642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 263334642Smarc } 263430391Skarels } 263530391Skarels } 263630391Skarels } /* qdiint */ 263730391Skarels 263834732Smarc /* 263934732Smarc * 264034732Smarc * Clear the QDSS screen 264134732Smarc * 264234732Smarc * >>> NOTE <<< 264334732Smarc * 264434732Smarc * This code requires that certain adder initialization be valid. To 264534732Smarc * assure that this requirement is satisfied, this routine should be 264634732Smarc * called only after calling the "setup_dragon()" function. 264734732Smarc * 264834732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear 264934732Smarc * only clears the current displayed portion of the bitmap put a 265034732Smarc * temporary value in the y limit register so we can access whole 265134732Smarc * bitmap 265234732Smarc * 265334732Smarc */ 265430391Skarels clear_qd_screen(unit) 265534732Smarc int unit; 265630391Skarels { 265730391Skarels register struct adder *adder; 265830391Skarels adder = (struct adder *) qdmap[unit].adder; 265930391Skarels 266030391Skarels adder->x_limit = 1024; 266130391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 266230391Skarels adder->y_offset_pending = 0; 266334732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 266434642Smarc WSV; 266530391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266634642Smarc WSV; 266730391Skarels adder->y_offset_pending = 864; 266834642Smarc WSV; 266930391Skarels adder->y_scroll_constant = SCROLL_ERASE; 267034642Smarc WSV; 267130391Skarels adder->y_offset_pending = 1728; 267234642Smarc WSV; 267330391Skarels adder->y_scroll_constant = SCROLL_ERASE; 267434642Smarc WSV; 267530391Skarels adder->y_offset_pending = 0; /* back to normal */ 267634642Smarc WSV; 267730391Skarels adder->x_limit = MAX_SCREEN_X; 267830391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 267934642Smarc #undef WSV 268030391Skarels 268130391Skarels } /* clear_qd_screen */ 268230391Skarels 268334732Smarc /* 268434732Smarc * kernel console output to the glass tty 268534732Smarc */ 268630391Skarels qdputc(chr) 268734642Smarc register char chr; 268830391Skarels { 268930391Skarels 269034642Smarc /* 269134642Smarc * if system is now physical, forget it (ie: crash DUMP) 269234642Smarc */ 269334642Smarc if ((mfpr(MAPEN) & 1) == 0) 269434642Smarc return; 269534615Smarc 269634732Smarc blitc(0, (u_char)(chr & 0xff)); 269732012Smarc if ((chr & 0177) == '\n') 269832012Smarc blitc(0, '\r'); 269930391Skarels 270030391Skarels } /* qdputc */ 270130391Skarels 270234732Smarc /* 270334732Smarc * load the mouse cursor's template RAM bitmap 270434732Smarc */ 270530391Skarels ldcursor(unit, bitmap) 270634732Smarc int unit; 270734732Smarc register short *bitmap; 270830391Skarels { 270930391Skarels register struct dga *dga; 271030391Skarels register short *temp; 271130391Skarels register int i; 271234732Smarc int curs; 271330391Skarels 271430391Skarels dga = (struct dga *) qdmap[unit].dga; 271530391Skarels temp = (short *) qdmap[unit].template; 271630391Skarels 271730391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 271834732Smarc curs = -1; /* ..note that.. */ 271934642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 272034732Smarc } else 272134732Smarc curs = 0; 272230391Skarels 272330391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 272430391Skarels 272530391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 272634642Smarc /* ..of the 8k WORD template space */ 272730391Skarels for (i = 0; i < 32; ++i) 272834642Smarc *temp++ = *bitmap++; 272930391Skarels 273034732Smarc if (curs) { /* if cursor was enabled.. */ 273134642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 273230391Skarels } 273330391Skarels 273430391Skarels } /* ldcursor */ 273530391Skarels 273634732Smarc /* 273734732Smarc * Put the console font in the QDSS off-screen memory 273834732Smarc */ 273930391Skarels ldfont(unit) 274034732Smarc int unit; 274130391Skarels { 274230391Skarels register struct adder *adder; 274330391Skarels 274434732Smarc register i, j, k, max_chars_line; 274534732Smarc register short packed; 274630391Skarels 274730391Skarels adder = (struct adder *) qdmap[unit].adder; 274830391Skarels 274934642Smarc /* 275034732Smarc * setup VIPER operand control registers 275134732Smarc */ 275230391Skarels write_ID(adder, MASK_1, 0xFFFF); 275330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 275430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 275530391Skarels 275630391Skarels write_ID(adder, SRC1_OCR_B, 275734642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 275830391Skarels write_ID(adder, SRC2_OCR_B, 275934642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 276030391Skarels write_ID(adder, DST_OCR_B, 276134642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 276230391Skarels 276330391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 276430391Skarels 276534642Smarc /* 276634732Smarc * load destination data 276734732Smarc */ 276834732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 276930391Skarels 277030391Skarels adder->destination_x = FONT_X; 277130391Skarels adder->destination_y = FONT_Y; 277234732Smarc #if FONT_WIDTH > MAX_SCREEN_X 277334732Smarc adder->fast_dest_dx = MAX_SCREEN_X; 277434732Smarc #else 277534732Smarc adder->fast_dest_dx = FONT_WIDTH; 277634732Smarc #endif 277730391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 277830391Skarels 277934642Smarc /* 278034642Smarc * setup for processor to bitmap xfer */ 278130391Skarels 278230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 278330391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 278430391Skarels 278534642Smarc /* 278634642Smarc * Figure out how many characters can be stored on one "line" of 278734642Smarc * offscreen memory. 278834642Smarc */ 278934642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 279034642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 279134642Smarc max_chars_line = CHARS/2 + CHARS%2; 279230391Skarels 279334642Smarc /* 279434642Smarc * iteratively do the processor to bitmap xfer */ 279534615Smarc 279630391Skarels for (i = 0; i < ROWS; ++i) { 279730391Skarels 279834642Smarc /* PTOB a scan line */ 279930391Skarels 280034642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 280134642Smarc /* PTOB one scan of a char cell */ 280230391Skarels 280334642Smarc packed = q_font[k]; 280434642Smarc k += ROWS; 280534642Smarc packed |= ((short)q_font[k] << 8); 280634642Smarc k += ROWS; 280730391Skarels 280834732Smarc (void)wait_status(adder, TX_READY); 280934642Smarc adder->id_data = packed; 281034642Smarc } 281130391Skarels } 281230391Skarels 281334642Smarc /* 281434642Smarc * (XXX XXX XXX - should remove) 281534642Smarc * 281634642Smarc * Copy the second row of characters. Subtract the first 281734642Smarc * row from the total number. Divide this quantity by 2 281834642Smarc * because 2 chars are stored in a short in the PTOB loop 281934642Smarc * below. Figure out how many characters can be stored on 282034642Smarc * one "line" of offscreen memory 282134642Smarc */ 282234642Smarc 282334642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 282434642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 282534642Smarc return; 282634642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 282734642Smarc /* Paranoia check to see if 3rd row may be needed */ 282834642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 282934615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 283034615Smarc 283134615Smarc adder->destination_x = FONT_X; 283234615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 283334615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 283434615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 283534615Smarc 283634642Smarc /* 283734642Smarc * setup for processor to bitmap xfer 283834642Smarc */ 283934615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 284034615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 284134615Smarc 284234642Smarc /* 284334642Smarc * iteratively do the processor to bitmap xfer 284434642Smarc */ 284534615Smarc for (i = 0; i < ROWS; ++i) { 284634642Smarc /* 284734642Smarc * PTOB a scan line 284834642Smarc */ 284934642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 285034642Smarc /* 285134642Smarc * PTOB one scan of a char cell 285234642Smarc */ 285334642Smarc packed = q_font[k + FONT_OFFSET]; 285434642Smarc k += ROWS; 285534642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 285634642Smarc k += ROWS; 285734732Smarc (void)wait_status(adder, TX_READY); 285834642Smarc adder->id_data = packed; 285934642Smarc } 286034615Smarc } 286134615Smarc 286230391Skarels } /* ldfont */ 286330391Skarels 2864*40817Smarc qdpoll(onoff) 2865*40817Smarc { 2866*40817Smarc qdpolling = onoff; 2867*40817Smarc } 2868*40817Smarc 286934732Smarc /* 287034732Smarc * Get a character from the LK201 (polled) 287134732Smarc */ 287234732Smarc qdgetc() 287334732Smarc { 287434732Smarc register short key; 287534732Smarc register char chr; 287634732Smarc register struct duart *duart; 287730391Skarels 287834732Smarc duart = (struct duart *) qdmap[0].duart; 287934732Smarc 288034732Smarc /* 288134732Smarc * Get a character from the keyboard. 288234732Smarc */ 288334732Smarc LOOP: 288434732Smarc while (!(duart->statusA&RCV_RDY)) 288534732Smarc ; 288634732Smarc 288734732Smarc key = duart->dataA; 288834732Smarc key &= 0xFF; 288934732Smarc 289034732Smarc /* 289134732Smarc * Check for various keyboard errors */ 289234732Smarc 289334732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 289434732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 289534732Smarc printf("Keyboard error, code = %x\n", key); 289634732Smarc return(0); 289734732Smarc } 289834732Smarc 289934732Smarc if (key < LK_LOWEST) 290034732Smarc return(0); 290134732Smarc 290234732Smarc /* 290334732Smarc * See if its a state change key 290434732Smarc */ 290534732Smarc switch (key) { 290634732Smarc 290734732Smarc case LOCK: 290834732Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 290934732Smarc if (q_keyboard.lock) 291034732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 291134732Smarc else 291234732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 291334732Smarc goto LOOP; 291434732Smarc 291534732Smarc case SHIFT: 291634732Smarc q_keyboard.shift ^= 0xFFFF; 291734732Smarc goto LOOP; 291834732Smarc 291934732Smarc case CNTRL: 292034732Smarc q_keyboard.cntrl ^= 0xFFFF; 292134732Smarc goto LOOP; 292234732Smarc 292334732Smarc case ALLUP: 292434732Smarc q_keyboard.cntrl = 0; 292534732Smarc q_keyboard.shift = 0; 292634732Smarc goto LOOP; 292734732Smarc 292834732Smarc case REPEAT: 292934732Smarc chr = q_keyboard.last; 293034732Smarc break; 293134732Smarc 293234732Smarc /* 293334732Smarc * Test for cntrl characters. If set, see if the character 293434732Smarc * is elligible to become a control character. 293534732Smarc */ 293634732Smarc default: 293734732Smarc 293834732Smarc if (q_keyboard.cntrl) { 293934732Smarc chr = q_key[key]; 294034732Smarc if (chr >= ' ' && chr <= '~') 294134732Smarc chr &= 0x1F; 294234732Smarc } 294334732Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 294434732Smarc chr = q_shift_key[key]; 294534732Smarc else 294634732Smarc chr = q_key[key]; 294734732Smarc break; 294834732Smarc } 294934732Smarc 295034732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 295134732Smarc return(0); /* ..then pitch it! */ 295234732Smarc 295334732Smarc q_keyboard.last = chr; 295434732Smarc 295534732Smarc /* 295634732Smarc * Check for special function keys */ 295734732Smarc 295834732Smarc if (chr & 0x80) /* pitch the function keys */ 295934732Smarc return(0); 296034732Smarc else 296134732Smarc return(chr); 296234732Smarc 296334732Smarc } /* qdgetc */ 296434732Smarc 296534732Smarc /* 296634732Smarc * led_control()... twiddle LK-201 LED's 296734732Smarc */ 296830391Skarels led_control(unit, cmd, led_mask) 296934732Smarc int unit, cmd, led_mask; 297030391Skarels { 297134732Smarc register i; 297230391Skarels register struct duart *duart; 297330391Skarels 297434732Smarc duart = (struct duart *)qdmap[unit].duart; 297530391Skarels 297630391Skarels for (i = 1000; i > 0; --i) { 297734732Smarc if (duart->statusA&XMT_RDY) { 297834642Smarc duart->dataA = cmd; 297934642Smarc break; 298034642Smarc } 298130391Skarels } 298230391Skarels for (i = 1000; i > 0; --i) { 298334732Smarc if (duart->statusA&XMT_RDY) { 298434642Smarc duart->dataA = led_mask; 298534642Smarc break; 298634642Smarc } 298730391Skarels } 298830391Skarels if (i == 0) 298934642Smarc return(BAD); 299030391Skarels return(GOOD); 299130391Skarels 299230391Skarels } /* led_control */ 299330391Skarels 299434732Smarc /* 299534732Smarc * scroll_up()... move the screen up one character height 299634732Smarc */ 299730391Skarels scroll_up(adder) 299834642Smarc register struct adder *adder; 299930391Skarels { 300034642Smarc /* 300134642Smarc * setup VIPER operand control registers 300234642Smarc */ 300334732Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 300430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 300530391Skarels write_ID(adder, MASK_1, 0xFFFF); 300630391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 300730391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 300830391Skarels write_ID(adder, SRC1_OCR_B, 300934642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 301030391Skarels write_ID(adder, DST_OCR_B, 301134642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 301234642Smarc /* 301334642Smarc * load DESTINATION origin and vectors 301434642Smarc */ 301530391Skarels adder->fast_dest_dy = 0; 301630391Skarels adder->slow_dest_dx = 0; 301730391Skarels adder->error_1 = 0; 301830391Skarels adder->error_2 = 0; 301930391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 302030391Skarels adder->destination_x = 0; 302130391Skarels adder->fast_dest_dx = 1024; 302230391Skarels adder->destination_y = 0; 302330391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 302434642Smarc /* 302534642Smarc * load SOURCE origin and vectors 302634642Smarc */ 302730391Skarels adder->source_1_x = 0; 302830391Skarels adder->source_1_dx = 1024; 302930391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 303030391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 303130391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 303230391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 303334642Smarc /* 303434642Smarc * do a rectangle clear of last screen line 303534642Smarc */ 303630391Skarels write_ID(adder, MASK_1, 0xffff); 303730391Skarels write_ID(adder, SOURCE, 0xffff); 303830391Skarels write_ID(adder,DST_OCR_B, 303934642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 304030391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 304130391Skarels adder->error_1 = 0; 304230391Skarels adder->error_2 = 0; 304334642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 304430391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 304530391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 304634732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 304730391Skarels adder->destination_x = 0; 304830391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 304930391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 305030391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 305130391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 305230391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 305330391Skarels 305430391Skarels } /* scroll_up */ 305530391Skarels 305634732Smarc /* 305734732Smarc * init shared memory pointers and structures 305834732Smarc */ 305930391Skarels init_shared(unit) 306034732Smarc register unit; 306130391Skarels { 306230391Skarels register struct dga *dga; 306330391Skarels 306430391Skarels dga = (struct dga *) qdmap[unit].dga; 306530391Skarels 306634642Smarc /* 306734642Smarc * initialize the event queue pointers and header */ 306830391Skarels 306930391Skarels eq_header[unit] = (struct qdinput *) 307034642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 307134642Smarc + (EVENT_BUFSIZE * unit)); 307230391Skarels eq_header[unit]->curs_pos.x = 0; 307330391Skarels eq_header[unit]->curs_pos.y = 0; 307430391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 307530391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 307630391Skarels eq_header[unit]->curs_box.left = 0; 307730391Skarels eq_header[unit]->curs_box.right = 0; 307830391Skarels eq_header[unit]->curs_box.top = 0; 307930391Skarels eq_header[unit]->curs_box.bottom = 0; 308034642Smarc /* 308134642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 308234642Smarc */ 308330391Skarels DMAheader[unit] = (struct DMAreq_header *) 308434642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 308534642Smarc + (DMAbuf_size * unit)); 308630391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 308734642Smarc + sizeof(struct DMAreq_header)); 308830391Skarels DMAheader[unit]->QBAreg = 0; 308930391Skarels DMAheader[unit]->status = 0; 309030391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 309130391Skarels DMAheader[unit]->used = 0; 309230391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 309330391Skarels DMAheader[unit]->oldest = 0; 309430391Skarels DMAheader[unit]->newest = 0; 309534642Smarc /* 309634642Smarc * assign a pointer to the scroll structure for this QDSS. 309734642Smarc */ 309830391Skarels scroll[unit] = (struct scroll *) 309934642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 310034642Smarc + (sizeof(struct scroll) * unit)); 310130391Skarels scroll[unit]->status = 0; 310230391Skarels scroll[unit]->viper_constant = 0; 310330391Skarels scroll[unit]->y_scroll_constant = 0; 310430391Skarels scroll[unit]->y_offset = 0; 310530391Skarels scroll[unit]->x_index_pending = 0; 310630391Skarels scroll[unit]->y_index_pending = 0; 310734642Smarc /* 310834642Smarc * assign a pointer to the color map write buffer for this QDSS 310934642Smarc */ 311030391Skarels color_buf[unit] = (struct color_buf *) 311134642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 311234642Smarc + (COLOR_BUFSIZ * unit)); 311330391Skarels color_buf[unit]->status = 0; 311430391Skarels color_buf[unit]->count = 0; 311530391Skarels 311630391Skarels } /* init_shared */ 311730391Skarels 311834732Smarc /* 311934732Smarc * init the ADDER, VIPER, bitmaps, & color map 312034732Smarc */ 312130391Skarels setup_dragon(unit) 312234732Smarc int unit; 312330391Skarels { 312430391Skarels 312530391Skarels register struct adder *adder; 312630391Skarels register struct dga *dga; 312730391Skarels short *memcsr; 312834732Smarc register i; 312930391Skarels short top; /* clipping/scrolling boundaries */ 313030391Skarels short bottom; 313130391Skarels short right; 313230391Skarels short left; 313330391Skarels short *red; /* color map pointers */ 313430391Skarels short *green; 313530391Skarels short *blue; 313630391Skarels 313734642Smarc /* 313834642Smarc * init for setup 313934642Smarc */ 314030391Skarels adder = (struct adder *) qdmap[unit].adder; 314130391Skarels dga = (struct dga *) qdmap[unit].dga; 314230391Skarels memcsr = (short *) qdmap[unit].memcsr; 314330391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 314430391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 314530391Skarels adder->command = CANCEL; 314634642Smarc /* 314734642Smarc * set monitor timing 314834642Smarc */ 314930391Skarels adder->x_scan_count_0 = 0x2800; 315030391Skarels adder->x_scan_count_1 = 0x1020; 315130391Skarels adder->x_scan_count_2 = 0x003A; 315230391Skarels adder->x_scan_count_3 = 0x38F0; 315330391Skarels adder->x_scan_count_4 = 0x6128; 315430391Skarels adder->x_scan_count_5 = 0x093A; 315530391Skarels adder->x_scan_count_6 = 0x313C; 315630391Skarels adder->sync_phase_adj = 0x0100; 315730391Skarels adder->x_scan_conf = 0x00C8; 315834642Smarc /* 315934642Smarc * got a bug in secound pass ADDER! lets take care of it 316034642Smarc * 316134642Smarc * normally, just use the code in the following bug fix code, but to 316234642Smarc * make repeated demos look pretty, load the registers as if there was 316334642Smarc * no bug and then test to see if we are getting sync 316434642Smarc */ 316530391Skarels adder->y_scan_count_0 = 0x135F; 316630391Skarels adder->y_scan_count_1 = 0x3363; 316730391Skarels adder->y_scan_count_2 = 0x2366; 316830391Skarels adder->y_scan_count_3 = 0x0388; 316934642Smarc /* 317034642Smarc * if no sync, do the bug fix code 317134642Smarc */ 317230391Skarels if (wait_status(adder, VSYNC) == BAD) { 317334642Smarc /* first load all Y scan registers with very short frame and 317434642Smarc * wait for scroll service. This guarantees at least one SYNC 317534642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 317634642Smarc * XCINCH with DMSEEDH) 317734642Smarc */ 317834642Smarc adder->y_scan_count_0 = 0x01; 317934642Smarc adder->y_scan_count_1 = 0x01; 318034642Smarc adder->y_scan_count_2 = 0x01; 318134642Smarc adder->y_scan_count_3 = 0x01; 318234642Smarc /* 318334642Smarc * delay at least 1 full frame time 318434642Smarc */ 318534732Smarc (void)wait_status(adder, VSYNC); 318634732Smarc (void)wait_status(adder, VSYNC); 318734642Smarc /* 318834642Smarc * now load the REAL sync values (in reverse order just to 318934642Smarc * be safe. 319034642Smarc */ 319134642Smarc adder->y_scan_count_3 = 0x0388; 319234642Smarc adder->y_scan_count_2 = 0x2366; 319334642Smarc adder->y_scan_count_1 = 0x3363; 319434642Smarc adder->y_scan_count_0 = 0x135F; 319530391Skarels } 319630391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 319734642Smarc /* 319834642Smarc * zero the index registers 319934642Smarc */ 320030391Skarels adder->x_index_pending = 0; 320130391Skarels adder->y_index_pending = 0; 320230391Skarels adder->x_index_new = 0; 320330391Skarels adder->y_index_new = 0; 320430391Skarels adder->x_index_old = 0; 320530391Skarels adder->y_index_old = 0; 320630391Skarels adder->pause = 0; 320734642Smarc /* 320834642Smarc * set rasterop mode to normal pen down 320934642Smarc */ 321030391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 321134642Smarc /* 321234642Smarc * set the rasterop registers to a default values 321334642Smarc */ 321430391Skarels adder->source_1_dx = 1; 321530391Skarels adder->source_1_dy = 1; 321630391Skarels adder->source_1_x = 0; 321730391Skarels adder->source_1_y = 0; 321830391Skarels adder->destination_x = 0; 321930391Skarels adder->destination_y = 0; 322030391Skarels adder->fast_dest_dx = 1; 322130391Skarels adder->fast_dest_dy = 0; 322230391Skarels adder->slow_dest_dx = 0; 322330391Skarels adder->slow_dest_dy = 1; 322430391Skarels adder->error_1 = 0; 322530391Skarels adder->error_2 = 0; 322634642Smarc /* 322734732Smarc * scale factor = UNITY 322834642Smarc */ 322930391Skarels adder->fast_scale = UNITY; 323030391Skarels adder->slow_scale = UNITY; 323134642Smarc /* 323234642Smarc * set the source 2 parameters 323334642Smarc */ 323430391Skarels adder->source_2_x = 0; 323530391Skarels adder->source_2_y = 0; 323630391Skarels adder->source_2_size = 0x0022; 323734642Smarc /* 323834642Smarc * initialize plane addresses for eight vipers 323934642Smarc */ 324030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 324130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 324230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 324330391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 324430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 324530391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 324630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 324730391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 324830391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 324930391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 325030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 325130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 325230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 325330391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 325430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 325530391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 325634642Smarc /* 325734642Smarc * initialize the external registers. 325834642Smarc */ 325930391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 326030391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 326134642Smarc /* 326234642Smarc * initialize resolution mode 326334642Smarc */ 326430391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 326530391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 326634642Smarc /* 326734642Smarc * initialize viper registers 326834642Smarc */ 326930391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 327030391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 327134642Smarc /* 327234642Smarc * set clipping and scrolling limits to full screen 327334642Smarc */ 327434732Smarc for (i = 1000, adder->status = 0; 327534732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 327634642Smarc ; 327730391Skarels if (i == 0) 327834732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 327930391Skarels top = 0; 328030391Skarels bottom = 2048; 328130391Skarels left = 0; 328230391Skarels right = 1024; 328330391Skarels adder->x_clip_min = left; 328430391Skarels adder->x_clip_max = right; 328530391Skarels adder->y_clip_min = top; 328630391Skarels adder->y_clip_max = bottom; 328730391Skarels adder->scroll_x_min = left; 328830391Skarels adder->scroll_x_max = right; 328930391Skarels adder->scroll_y_min = top; 329030391Skarels adder->scroll_y_max = bottom; 329134732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 329234732Smarc (void)wait_status(adder, VSYNC); 329330391Skarels adder->x_index_pending = left; 329430391Skarels adder->y_index_pending = top; 329530391Skarels adder->x_index_new = left; 329630391Skarels adder->y_index_new = top; 329730391Skarels adder->x_index_old = left; 329830391Skarels adder->y_index_old = top; 329930391Skarels 330034732Smarc for (i = 1000, adder->status = 0; i > 0 && 330134732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 330234642Smarc ; 330330391Skarels if (i == 0) 330434732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 330530391Skarels 330630391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 330730391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 330834642Smarc /* 330934642Smarc * set source and the mask register to all ones (ie: white) o 331034642Smarc */ 331130391Skarels write_ID(adder, SOURCE, 0xFFFF); 331230391Skarels write_ID(adder, MASK_1, 0xFFFF); 331330391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 331430391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 331534642Smarc /* 331634642Smarc * initialize Operand Control Register banks for fill command 331734642Smarc */ 331830391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 331930391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 332030391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 332130391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 332230391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 332330391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 332434642Smarc /* 332534642Smarc * init Logic Unit Function registers, (these are just common values, 332634642Smarc * and may be changed as required). 332734642Smarc */ 332830391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 332934642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 333034642Smarc INV_M1_M2); 333130391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 333230391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 333334642Smarc /* 333434642Smarc * load the color map for black & white 333534642Smarc */ 333634732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 333734642Smarc ; 333830391Skarels 333930391Skarels if (i == 0) 334034732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 334130391Skarels 334230391Skarels red = (short *) qdmap[unit].red; 334330391Skarels green = (short *) qdmap[unit].green; 334430391Skarels blue = (short *) qdmap[unit].blue; 334530391Skarels 334630391Skarels *red++ = 0x00; /* black */ 334730391Skarels *green++ = 0x00; 334830391Skarels *blue++ = 0x00; 334930391Skarels 335030391Skarels *red-- = 0xFF; /* white */ 335130391Skarels *green-- = 0xFF; 335230391Skarels *blue-- = 0xFF; 335330391Skarels 335434642Smarc /* 335534732Smarc * set color map for mouse cursor 335634732Smarc */ 335730391Skarels 335830391Skarels red += 254; 335930391Skarels green += 254; 336030391Skarels blue += 254; 336130391Skarels 336230391Skarels *red++ = 0x00; /* black */ 336330391Skarels *green++ = 0x00; 336430391Skarels *blue++ = 0x00; 336530391Skarels 336630391Skarels *red = 0xFF; /* white */ 336730391Skarels *green = 0xFF; 336830391Skarels *blue = 0xFF; 336930391Skarels 337030391Skarels } /* setup_dragon */ 337130391Skarels 337234732Smarc /* 337334732Smarc * Init the DUART and set defaults in input 337434732Smarc */ 337530391Skarels setup_input(unit) 337634732Smarc int unit; 337730391Skarels { 337830391Skarels register struct duart *duart; /* DUART register structure pointer */ 337934732Smarc register i, bits; 338030391Skarels char id_byte; 338130391Skarels 338230391Skarels duart = (struct duart *) qdmap[unit].duart; 338330391Skarels duart->imask = 0; 338430391Skarels 338534642Smarc /* 338634642Smarc * setup the DUART for kbd & pointing device 338734642Smarc */ 338834732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 338934732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 339034732Smarc /* no RTS control,char error mode */ 339134732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 339234732Smarc /* no RTS control,no echo or loop */ 339334732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 339434732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 339534732Smarc /* ..no RTS cntrl, char error mode */ 339634732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 339734732Smarc /* no RTS control,no echo or loop */ 339834732Smarc duart->auxctl = 0x00; /* baud rate set 1 */ 339934732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */ 340034732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */ 340130391Skarels 340230391Skarels /* reset everything for keyboard */ 340330391Skarels 340430391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 340534642Smarc duart->cmdA = bits; 340630391Skarels 340730391Skarels /* reset everything for host */ 340830391Skarels 340930391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 341034642Smarc duart->cmdB = bits; 341130391Skarels 341230391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 341330391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 341430391Skarels 341534642Smarc /* 341634732Smarc * init keyboard defaults (DUART channel A) 341734732Smarc */ 341830391Skarels for (i = 500; i > 0; --i) { 341934732Smarc if (duart->statusA&XMT_RDY) { 342034642Smarc duart->dataA = LK_DEFAULTS; 342134642Smarc break; 342234642Smarc } 342330391Skarels } 342430391Skarels 342530391Skarels for (i = 100000; i > 0; --i) { 342634732Smarc if (duart->statusA&RCV_RDY) { 342734642Smarc break; 342834642Smarc } 342930391Skarels } 343030391Skarels 343134732Smarc if (duart->dataA) /* flush the ACK */ 343234732Smarc ; 343330391Skarels 343434642Smarc /* 343534732Smarc * identify the pointing device 343634732Smarc */ 343730391Skarels for (i = 500; i > 0; --i) { 343834732Smarc if (duart->statusB&XMT_RDY) { 343934642Smarc duart->dataB = SELF_TEST; 344034642Smarc break; 344134642Smarc } 344230391Skarels } 344330391Skarels 344434642Smarc /* 344530391Skarels * wait for 1st byte of self test report */ 344630391Skarels 344730391Skarels for (i = 100000; i > 0; --i) { 344834732Smarc if (duart->statusB&RCV_RDY) { 344934642Smarc break; 345034642Smarc } 345130391Skarels } 345230391Skarels 345330391Skarels if (i == 0) { 345434732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 345534642Smarc ,unit); 345634642Smarc goto OUT; 345730391Skarels } 345830391Skarels 345934732Smarc if (duart->dataB) 346034732Smarc ; 346130391Skarels 346234642Smarc /* 346334732Smarc * wait for ID byte of self test report 346434732Smarc */ 346530391Skarels for (i = 100000; i > 0; --i) { 346634732Smarc if (duart->statusB&RCV_RDY) { 346734642Smarc break; 346834642Smarc } 346930391Skarels } 347030391Skarels 347130391Skarels if (i == 0) { 347234732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 347334642Smarc goto OUT; 347430391Skarels } 347530391Skarels 347630391Skarels id_byte = duart->dataB; 347730391Skarels 347834642Smarc /* 347934732Smarc * wait for other bytes to come in 348034732Smarc */ 348130391Skarels for (i = 100000; i > 0; --i) { 348234732Smarc if (duart->statusB & RCV_RDY) { 348334732Smarc if (duart->dataB) 348434732Smarc ; 348534642Smarc break; 348634642Smarc } 348730391Skarels } 348830391Skarels if (i == 0) { 348934732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 349034642Smarc goto OUT; 349130391Skarels } 349230391Skarels for (i = 100000; i > 0; --i) { 349334732Smarc if (duart->statusB&RCV_RDY) { 349434732Smarc if (duart->dataB) 349534732Smarc ; 349634642Smarc break; 349734642Smarc } 349830391Skarels } 349930391Skarels if (i == 0) { 350034732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 350134642Smarc goto OUT; 350230391Skarels } 350334642Smarc /* 350434732Smarc * flag pointing device type and set defaults 350534732Smarc */ 350634732Smarc for (i=100000; i>0; --i) 350734732Smarc ; /*XXX*/ 350830391Skarels 350930391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 351034642Smarc qdflags[unit].pntr_id = MOUSE_ID; 351130391Skarels 351234642Smarc for (i = 500; i > 0; --i) { 351334732Smarc if (duart->statusB&XMT_RDY) { 351434642Smarc duart->dataB = INC_STREAM_MODE; 351534642Smarc break; 351634642Smarc } 351730391Skarels } 351834642Smarc } 351934642Smarc else { 352034642Smarc qdflags[unit].pntr_id = TABLET_ID; 352130391Skarels 352234642Smarc for (i = 500; i > 0; --i) { 352334732Smarc if (duart->statusB&XMT_RDY) { 352434642Smarc duart->dataB = T_STREAM; 352534642Smarc break; 352634642Smarc } 352730391Skarels } 352830391Skarels } 352930391Skarels OUT: 353030391Skarels duart->imask = qdflags[unit].duart_imask; 353130391Skarels 353230391Skarels } /* setup_input */ 353330391Skarels 353434732Smarc /* 353534732Smarc * delay for at least one display frame time 353634732Smarc * 353734732Smarc * return: BAD means that we timed out without ever seeing the 353834732Smarc * vertical sync status bit 353934732Smarc * GOOD otherwise 354034732Smarc */ 354130391Skarels wait_status(adder, mask) 354234642Smarc register struct adder *adder; 354334642Smarc register int mask; 354430391Skarels { 354534732Smarc register i; 354630391Skarels 354734732Smarc for (i = 10000, adder->status = 0 ; i > 0 && 354834732Smarc !(adder->status&mask) ; --i) 354934642Smarc ; 355030391Skarels 355130391Skarels if (i == 0) { 355234732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 355334642Smarc return(BAD); 355430391Skarels } 355530391Skarels 355630391Skarels return(GOOD); 355730391Skarels 355830391Skarels } /* wait_status */ 355930391Skarels 356034732Smarc /* 356134732Smarc * write out onto the ID bus 356234732Smarc */ 356330391Skarels write_ID(adder, adrs, data) 356434642Smarc register struct adder *adder; 356534642Smarc register short adrs; 356634642Smarc register short data; 356730391Skarels { 356834732Smarc register i; 356930391Skarels 357034732Smarc for (i = 100000, adder->status = 0 ; 357134732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 357234642Smarc ; 357330391Skarels 357430391Skarels if (i == 0) 357534732Smarc goto ERR; 357630391Skarels 357734732Smarc for (i = 100000, adder->status = 0 ; 357834732Smarc i > 0 && !(adder->status&TX_READY) ; --i) 357934642Smarc ; 358030391Skarels 358130391Skarels if (i > 0) { 358234642Smarc adder->id_data = data; 358334642Smarc adder->command = ID_LOAD | adrs; 358434732Smarc return ; 358530391Skarels } 358630391Skarels 358730391Skarels ERR: 358834732Smarc printf("write_ID: timeout trying to write to VIPER\n"); 358934732Smarc return ; 359030391Skarels 359130391Skarels } /* write_ID */ 359234511Smarc #endif 3593