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*37605Smarc * @(#)qd.c 1.13 (Berkeley) 05/01/89 1835353Sbostic */ 1934642Smarc 2030391Skarels /************************************************************************ 2134511Smarc * * 2234615Smarc * Copyright (c) 1985-1988 by * 2330391Skarels * Digital Equipment Corporation, Maynard, MA * 2430391Skarels * All rights reserved. * 2530391Skarels * * 2630391Skarels * This software is furnished under a license and may be used and * 2730391Skarels * copied only in accordance with the terms of such license and * 2830391Skarels * with the inclusion of the above copyright notice. This * 2930391Skarels * software or any other copies thereof may not be provided or * 3030391Skarels * otherwise made available to any other person. No title to and * 3130391Skarels * ownership of the software is hereby transferred. * 3230391Skarels * * 3330391Skarels * The information in this software is subject to change without * 3430391Skarels * notice and should not be construed as a commitment by Digital * 3530391Skarels * Equipment Corporation. * 3630391Skarels * * 3730391Skarels * Digital assumes no responsibility for the use or reliability * 3830391Skarels * of its software on equipment which is not supplied by Digital. * 3930391Skarels * * 4030391Skarels *************************************************************************/ 4134615Smarc 4230391Skarels /* 4334642Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation 4430391Skarels */ 4530391Skarels 4634642Smarc #include "qd.h" 4734615Smarc 4834511Smarc #if NQD > 0 4934615Smarc #include "types.h" 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 "dir.h" 5634642Smarc #include "user.h" 5734642Smarc #include "qdioctl.h" 5834511Smarc #include "tty.h" 5934642Smarc #include "map.h" 6034642Smarc #include "buf.h" 6134642Smarc #include "vm.h" 6234642Smarc #include "clist.h" 6334642Smarc #include "file.h" 6434642Smarc #include "uio.h" 6534642Smarc #include "kernel.h" 6634615Smarc #include "exec.h" 6734615Smarc #include "proc.h" 6834642Smarc #include "ubareg.h" 6934642Smarc #include "ubavar.h" 7034511Smarc #include "syslog.h" 7134642Smarc #include "qduser.h" /* definitions shared with user level client */ 7234615Smarc #include "qdreg.h" /* QDSS device register structures */ 7332012Smarc 7434642Smarc /* 7534642Smarc * QDSS driver status flags for tracking operational state 7634642Smarc */ 7734642Smarc struct qdflags { 7834642Smarc u_int inuse; /* which minor dev's are in use now */ 7934642Smarc u_int config; /* I/O page register content */ 8034642Smarc u_int mapped; /* user mapping status word */ 8134642Smarc u_int kernel_loop; /* if kernel console is redirected */ 8234642Smarc u_int user_dma; /* DMA from user space in progress */ 8334642Smarc u_short pntr_id; /* type code of pointing device */ 8434642Smarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 8534642Smarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 8634642Smarc u_short curs_acc; /* cursor acceleration factor */ 8734642Smarc u_short curs_thr; /* cursor acceleration threshold level */ 8834642Smarc u_short tab_res; /* tablet resolution factor */ 8934642Smarc u_short selmask; /* mask for active qd select entries */ 9034642Smarc }; 9132012Smarc 9234642Smarc /* 9334642Smarc * bit definitions for 'inuse' entry 9434642Smarc */ 9532012Smarc #define CONS_DEV 0x01 9632012Smarc #define GRAPHIC_DEV 0x04 9732012Smarc 9834642Smarc /* 9934642Smarc * bit definitions for 'mapped' member of flag structure 10034642Smarc */ 10132012Smarc #define MAPDEV 0x01 /* hardware is mapped */ 10232012Smarc #define MAPDMA 0x02 /* DMA buffer mapped */ 10332012Smarc #define MAPEQ 0x04 /* event queue buffer mapped */ 10432012Smarc #define MAPSCR 0x08 /* scroll param area mapped */ 10532012Smarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 10632012Smarc 10734642Smarc /* 10834642Smarc * bit definitions for 'selmask' member of qdflag structure 10934642Smarc */ 11032012Smarc #define SEL_READ 0x01 /* read select is active */ 11132012Smarc #define SEL_WRITE 0x02 /* write select is active */ 11232012Smarc 11334642Smarc /* 11434732Smarc * constants used in shared memory operations 11534732Smarc */ 11632012Smarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 11732012Smarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 11834642Smarc / sizeof(struct _vs_event) ) 11934527Smarc #define DMA_BUFSIZ (1024 * 10) 12032012Smarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 12132012Smarc 12234642Smarc /* 12334732Smarc * reference to an array of "uba_device" structures built by the auto 12434732Smarc * configuration program. The uba_device structure decribes the device 12534732Smarc * sufficiently for the driver to talk to it. The auto configuration code 12634732Smarc * fills in the uba_device structures (located in ioconf.c) from user 12734732Smarc * maintained info. 12834732Smarc */ 12934642Smarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 13034642Smarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 13134732Smarc extern char qvmem[][128*NBPG]; 13234642Smarc extern struct pte QVmap[][128]; 13334642Smarc #define CHUNK (64 * 1024) 13434642Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 13532012Smarc 13634642Smarc /* 13734642Smarc * static storage used by multiple functions in this code 13834642Smarc */ 13934642Smarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 14034642Smarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 14134642Smarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 14234642Smarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 14334642Smarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 14434642Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 14532012Smarc 14634642Smarc /* 14734732Smarc * the array "event_shared[]" is made up of a number of event queue buffers 14834732Smarc * equal to the number of QDSS's configured into the running kernel (NQD). 14934732Smarc * Each event queue buffer begins with an event queue header (struct qdinput) 15034732Smarc * followed by a group of event queue entries (struct _vs_event). The array 15134732Smarc * "*eq_header[]" is an array of pointers to the start of each event queue 15234732Smarc * buffer in "event_shared[]". 15334732Smarc */ 15432012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 15532012Smarc 15634642Smarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 15734642Smarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 15832012Smarc 15934642Smarc /* 16034732Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 16134732Smarc * buffers. Each buffer must consume an integral number of memory pages to 16234732Smarc * guarantee that a following buffer will begin on a page boundary. Also, 16334732Smarc * enough space is allocated so that the FIRST I/O buffer can start at the 16434732Smarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 16534732Smarc * memory protections can be turned on/off for individual buffers. 16634732Smarc */ 16732012Smarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 16832012Smarc 16934642Smarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 17034642Smarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 17132012Smarc 17234642Smarc /* 17334732Smarc * The driver assists a client in scroll operations by loading dragon 17434732Smarc * registers from an interrupt service routine. The loading is done using 17534732Smarc * parameters found in memory shrade between the driver and it's client. 17634732Smarc * The scroll parameter structures are ALL loacted in the same memory page 17734732Smarc * for reasons of memory economy. 17834732Smarc */ 17934642Smarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 18034642Smarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 18132012Smarc 18234642Smarc /* 18334732Smarc * the driver is programmable to provide the user with color map write 18434732Smarc * services at VSYNC interrupt time. At interrupt time the driver loads 18534732Smarc * the color map with any user-requested load data found in shared memory 18634732Smarc */ 18732012Smarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 18832012Smarc 18934642Smarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 19034642Smarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 19132012Smarc 19234642Smarc /* 19334732Smarc * mouse input event structures 19434732Smarc */ 19534642Smarc struct mouse_report last_rep[NQD]; 19634642Smarc struct mouse_report current_rep[NQD]; 19732012Smarc 19834732Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 19934642Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 20034642Smarc int qdcount = 0; /* count of successfully probed qd's */ 20134642Smarc int nNQD = NQD; 20234642Smarc int DMAbuf_size = DMA_BUFSIZ; 20334642Smarc int QDlast_DMAtype; /* type of the last DMA operation */ 20432012Smarc 20534642Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 20634642Smarc /* 20734732Smarc * macro to get system time. Used to time stamp event queue entries 20834732Smarc */ 20930391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 21030391Skarels 21134642Smarc int qdprobe(); 21234642Smarc int qdattach(); 21334642Smarc int qddint(); /* DMA gate array intrpt service */ 21434642Smarc int qdaint(); /* Dragon ADDER intrpt service */ 21534642Smarc int qdiint(); 21630391Skarels 21734642Smarc u_short qdstd[] = { 0 }; 21830391Skarels 21934642Smarc struct uba_driver qddriver = { 22034732Smarc qdprobe, /* device probe entry */ 22134732Smarc 0, /* no slave device */ 22234732Smarc qdattach, /* device attach entry */ 22334732Smarc 0, /* no "fill csr/ba to start" */ 22434642Smarc qdstd, /* device addresses */ 22534642Smarc "qd", /* device name string */ 22634642Smarc qdinfo /* ptr to QDSS's uba_device struct */ 22734642Smarc }; 22830391Skarels 22934615Smarc #define QDPRIOR (PZERO-1) /* must be negative */ 23030391Skarels #define FALSE 0 23130391Skarels #define TRUE ~FALSE 23230391Skarels #define BAD -1 23330391Skarels #define GOOD 0 23430391Skarels 23534642Smarc /* 23634642Smarc * macro to create a system virtual page number from system virtual adrs 23734642Smarc */ 23834642Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 23930391Skarels 24034642Smarc /* 24134642Smarc * QDSS register address offsets from start of QDSS address space 24234642Smarc */ 24330391Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 24430391Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 24530391Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 24630391Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 24730391Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 24830391Skarels #define ADDER (REGSTART+0x000) 24930391Skarels #define DGA (REGSTART+0x200) 25030391Skarels #define DUART (REGSTART+0x400) 25130391Skarels #define MEMCSR (REGSTART+0x800) 25230391Skarels #define CLRSIZE (3 * 512) /* color map size */ 25330391Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 25434642Smarc /* 0x0C00 really */ 25530391Skarels #define RED (CLRSTART+0x000) 25630391Skarels #define BLUE (CLRSTART+0x200) 25730391Skarels #define GREEN (CLRSTART+0x400) 25830391Skarels 25930391Skarels 26034642Smarc /* 26134642Smarc * QDSS minor device numbers. The *real* minor device numbers are in 26234642Smarc * the bottom two bits of the major/minor device spec. Bits 2 and up are 26334642Smarc * used to specify the QDSS device number (ie: which one?) 26434642Smarc */ 26530391Skarels 26630391Skarels #define CONS 0 26730391Skarels #define GRAPHIC 2 26830391Skarels 26934642Smarc /* 27034642Smarc * console cursor bitmap (white block cursor) 27134642Smarc */ 27234642Smarc short cons_cursor[32] = { 27334642Smarc /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27434642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27534642Smarc /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 27634642Smarc 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 27734642Smarc }; 27830391Skarels 27934642Smarc /* 28034642Smarc * constants used in font operations 28134642Smarc */ 28234615Smarc #define CHARS 190 /* # of chars in the font */ 28330391Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 28430391Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 28530391Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 28630391Skarels #define ROWS CHAR_HEIGHT 28730391Skarels #define FONT_X 0 /* font's off screen adrs */ 28830391Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 28930391Skarels 29034642Smarc /* Offset to second row characters (XXX - should remove) */ 29134615Smarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 29230391Skarels 29334642Smarc extern char q_font[]; /* reference font object code */ 29434642Smarc extern u_short q_key[]; /* reference key xlation tables */ 29534642Smarc extern u_short q_shift_key[]; 29634642Smarc extern char *q_special[]; 29730391Skarels 29834642Smarc /* 29934642Smarc * definitions for cursor acceleration reporting 30034642Smarc */ 30130391Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 30230391Skarels 30334642Smarc /* 30434642Smarc * virtual console support. 30534642Smarc */ 30634642Smarc extern (*v_putc)(); 30734642Smarc extern struct cdevsw *consops; 30834642Smarc int qdputc(); 30934642Smarc int qdstart(); 31030391Skarels 31134642Smarc /* 31234642Smarc * LK-201 state storage for input console keyboard conversion to ASCII 31334642Smarc */ 31434642Smarc struct q_keyboard { 31534642Smarc int shift; /* state variables */ 31634642Smarc int cntrl; 31734642Smarc int lock; 31834642Smarc int lastcode; /* last keycode typed */ 31934642Smarc unsigned kup[8]; /* bits for each keycode*/ 32034642Smarc unsigned dkeys[8]; /* down/up mode keys */ 32134642Smarc char last; /* last character */ 32234642Smarc } q_keyboard; 32330391Skarels 32434642Smarc /* 32534642Smarc * tty settings on first open 32634642Smarc */ 32734615Smarc #define IFLAGS (EVENP|ECHO|XTABS|CRMOD) 32834615Smarc #ifdef POSIXTTY 32934615Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL) 33034615Smarc #define OFLAG (OPOST|OXTABS|ONLCR) 33134615Smarc #define LFLAG (ISIG|ICANON|ECHO) 33234615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 33334615Smarc #endif 33434615Smarc 33534732Smarc /* 33634732Smarc * Init QDSS as console (before probe routine) 33734732Smarc */ 33830391Skarels 33930391Skarels qdcons_init() 34030391Skarels { 34134732Smarc register unit; 34230391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 34334615Smarc u_int mapix; /* index into QVmap[] array */ 34434615Smarc struct percpu *pcpu; /* pointer to cpusw structure */ 34534615Smarc register struct qbus *qb; 34630391Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 34730391Skarels u_short *devptr; /* vitual device space */ 34834615Smarc extern cnputc(); 34930391Skarels 35030391Skarels #define QDSSCSR 0x1F00 35130391Skarels 35232012Smarc if (v_putc != cnputc) 35334732Smarc return 0; 35432012Smarc 35530391Skarels unit = 0; 35630391Skarels 35734642Smarc /* 35834642Smarc * find the cpusw entry that matches this machine. 35934642Smarc */ 36032012Smarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 36132012Smarc ; 36232012Smarc if (pcpu == NULL) 36334732Smarc return 0; 36436705Stef if (pcpu->pc_io->io_type != IO_QBUS) 36536705Stef return 0; 36630391Skarels 36732012Smarc /* 36834615Smarc * Map device registers - the last 8K of qvmem. 36932012Smarc */ 37032012Smarc qb = (struct qbus *)pcpu->pc_io->io_details; 37132012Smarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 37234732Smarc UBAIOPAGES * NBPG); 37332012Smarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 37430391Skarels qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 37534732Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 37634732Smarc return 0; 37734615Smarc 37832012Smarc /* 37932012Smarc * Map q-bus memory used by qdss. (separate map) 38032012Smarc */ 38132012Smarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 38232012Smarc phys_adr = qb->qb_maddr + mapix; 38332012Smarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 38430391Skarels 38532012Smarc /* 38632012Smarc * tell QDSS which Q memory address base to decode 38734642Smarc * (shifted right 16 bits - its in 64K units) 38832012Smarc */ 38932012Smarc *qdaddr = (u_short)((int)mapix >> 16); 39030391Skarels qdflags[unit].config = *(u_short *)qdaddr; 39130391Skarels 39234642Smarc /* 39334642Smarc * load qdmap struct with the virtual addresses of the QDSS elements 39434642Smarc */ 39534615Smarc qdbase[unit] = (caddr_t) (qvmem[0]); 39630391Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 39730391Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 39830391Skarels qdmap[unit].dga = qdbase[unit] + DGA; 39930391Skarels qdmap[unit].duart = qdbase[unit] + DUART; 40030391Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 40130391Skarels qdmap[unit].red = qdbase[unit] + RED; 40230391Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 40330391Skarels qdmap[unit].green = qdbase[unit] + GREEN; 40430391Skarels 40530391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 40630391Skarels 40734642Smarc /* 40834642Smarc * init the QDSS 40934642Smarc */ 41034642Smarc /* 41132012Smarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 41234642Smarc (char *)qdbase[0], qdmap[0].memcsr); 41334642Smarc */ 41432012Smarc 41530391Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 41630391Skarels 41730391Skarels cursor[unit].x = 0; 41830391Skarels cursor[unit].y = 0; 41930391Skarels init_shared(unit); /* init shared memory */ 42030391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 42130391Skarels clear_qd_screen(unit); /* clear the screen */ 42230391Skarels ldfont(unit); /* load the console font */ 42330391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 42430391Skarels setup_input(unit); /* init the DUART */ 42534642Smarc v_putc = qdputc; /* kernel console output to qdss */ 42634642Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 42734732Smarc return 1; 42830391Skarels 42930391Skarels } /* qdcons_init */ 43030391Skarels 43134732Smarc /* 43234732Smarc * Configure QDSS into Q memory and make it intrpt. 43334732Smarc * 43434732Smarc * side effects: QDSS gets mapped into Qbus memory space at the first 43534732Smarc * vacant 64kb boundary counting back from the top of 43634732Smarc * Qbus memory space (qvmem+4mb) 43734732Smarc * 43834732Smarc * return: QDSS bus request level and vector address returned in 43934732Smarc * registers by UNIX convention. 44034732Smarc * 44134732Smarc */ 44230391Skarels qdprobe(reg) 44334732Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 44430391Skarels { 44534642Smarc register int br, cvec; /* value-result */ 44630391Skarels register int unit; 44730391Skarels struct dga *dga; /* pointer to gate array structure */ 44834732Smarc int vector; 44934732Smarc #ifdef notdef 45030391Skarels int *ptep; /* page table entry pointer */ 45130391Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 45230391Skarels u_int mapix; 45334732Smarc #endif 45430391Skarels 45534732Smarc #ifdef lint 45634732Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 45734732Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 45834732Smarc #endif 45934732Smarc 46034642Smarc /* 46134642Smarc * calculate board unit number from I/O page register address 46234642Smarc */ 46330391Skarels unit = (int) (((int)reg >> 1) & 0x0007); 46430391Skarels 46534642Smarc /* 46634642Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 46734642Smarc * physical boundary. The Qbus memory space is mapped into 46834642Smarc * the system memory space at config time. After config 46934642Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 47034642Smarc * of the start of Qbus memory. The Qbus memory page table 47134642Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 47234642Smarc * which is also loaded at config time. These are the 47334642Smarc * variables used below to find a vacant 64kb boundary in 47434642Smarc * Qbus memory, and load it's corresponding physical adrs 47534642Smarc * into the QDSS's I/O page CSR. 47634642Smarc */ 47730391Skarels 47834615Smarc /* 47934615Smarc * Only if QD is the graphics device. 48034615Smarc */ 48134615Smarc 48230391Skarels /* if this QDSS is NOT the console, then do init here.. */ 48330391Skarels 48434615Smarc if (unit != 0) { 48534615Smarc printf("qd: can't support two qdss's (yet)\n"); 48634732Smarc #ifdef notdef /* can't test */ 48734642Smarc if (v_consputc != qdputc || unit != 0) { 48830391Skarels 48934642Smarc /* 49034642Smarc * read QDSS config info 49134642Smarc */ 49234642Smarc qdflags[unit].config = *(u_short *)reg; 49334615Smarc 49434642Smarc /* 49534642Smarc * find an empty 64kb adrs boundary 49634642Smarc */ 49730391Skarels 49834642Smarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 49930391Skarels 50034642Smarc /* 50134732Smarc * find the cpusw entry that matches this machine. 50234732Smarc */ 50334642Smarc cpup = &cpusw[cpu]; 50434732Smarc while (!(BADADDR(qdbase[unit], sizeof(short)))) 50534732Smarc qdbase[unit] -= CHUNK; 50634615Smarc 50734642Smarc /* 50834732Smarc * tell QDSS which Q memory address base to decode 50934732Smarc */ 51034642Smarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 51134642Smarc ptep = (int *) QVmap[0] + mapix; 51234642Smarc phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 51334642Smarc *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 51434615Smarc 51534642Smarc /* 51634642Smarc * load QDSS adrs map with system addresses 51734642Smarc * of device regs 51834642Smarc */ 51934642Smarc qdmap[unit].template = qdbase[unit] + TMPSTART; 52034642Smarc qdmap[unit].adder = qdbase[unit] + ADDER; 52134642Smarc qdmap[unit].dga = qdbase[unit] + DGA; 52234642Smarc qdmap[unit].duart = qdbase[unit] + DUART; 52334642Smarc qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 52434642Smarc qdmap[unit].red = qdbase[unit] + RED; 52534642Smarc qdmap[unit].blue = qdbase[unit] + BLUE; 52634642Smarc qdmap[unit].green = qdbase[unit] + GREEN; 52730391Skarels 52834642Smarc /* device init */ 52934615Smarc 53034642Smarc cursor[unit].x = 0; 53134642Smarc cursor[unit].y = 0; 53234642Smarc init_shared(unit); /* init shared memory */ 53334642Smarc setup_dragon(unit); /* init the ADDER/VIPER stuff */ 53434642Smarc ldcursor(unit, cons_cursor); /* load default cursor map */ 53534642Smarc setup_input(unit); /* init the DUART */ 53634642Smarc clear_qd_screen(unit); 53734642Smarc ldfont(unit); /* load the console font */ 53830391Skarels 53934642Smarc /* once only: turn on sync */ 54030391Skarels 54134642Smarc *(short *)qdmap[unit].memcsr |= SYNC_ON; 54234642Smarc } 54334615Smarc #endif /*notdef*/ 54430391Skarels } 54530391Skarels 54634642Smarc /* 54734642Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 54834642Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 54934642Smarc * vectors from the vector pool, and then continue 55034642Smarc * to take them until we get a xx0 HEX vector. The 55134642Smarc * pool provides vectors in contiguous decending 55234642Smarc * order. 55334642Smarc */ 55430391Skarels 55530391Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 55630391Skarels 55734642Smarc while (vector & 0x0F) { /* if lo nibble != 0.. */ 55834642Smarc /* ..take another vector */ 55934642Smarc vector = (uba_hd[0].uh_lastiv -= 4); 56030391Skarels } 56130391Skarels 56234642Smarc /* 56334642Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 56434642Smarc */ 56530391Skarels dga = (struct dga *) qdmap[unit].dga; 56634642Smarc dga->csr = (short) HALT; /* disable everything */ 56734642Smarc dga->ivr = (short) vector; /* load intrpt base vector */ 56834642Smarc dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 56930391Skarels dga->bytcnt_hi = (short) 0; 57030391Skarels 57134642Smarc /* 57234642Smarc * turn on DMA interrupts 57334642Smarc */ 57430391Skarels dga->csr &= ~SET_DONE_FIFO; 57530391Skarels dga->csr |= DMA_IE | DL_ENB; 57630391Skarels 57730391Skarels DELAY(20000); /* wait for the intrpt */ 57830391Skarels dga->csr = HALT; /* stop the wheels */ 57930391Skarels 58030391Skarels if (cvec != vector) /* if vector != base vector.. */ 58134732Smarc return(0); /* ..return = 'no device' */ 58230391Skarels 58334615Smarc /* 58434642Smarc * score this as an existing qdss 58534642Smarc */ 58634615Smarc qdcount++; 58734615Smarc 58830391Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 58930391Skarels 59030391Skarels } /* qdprobe */ 59130391Skarels 59230391Skarels qdattach(ui) 59334642Smarc struct uba_device *ui; 59430391Skarels { 59534732Smarc register unit; /* QDSS module # for this call */ 59630391Skarels 59730391Skarels unit = ui->ui_unit; /* get QDSS number */ 59830391Skarels 59934642Smarc /* 60034642Smarc * init "qdflags[]" for this QDSS 60134642Smarc */ 60230391Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 60330391Skarels qdflags[unit].mapped = 0; 60434615Smarc qdflags[unit].kernel_loop = -1; 60530391Skarels qdflags[unit].user_dma = 0; 60630391Skarels qdflags[unit].curs_acc = ACC_OFF; 60730391Skarels qdflags[unit].curs_thr = 128; 60830391Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 60930391Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 61030391Skarels qdflags[unit].adder_ie = 0; 61130391Skarels 61234642Smarc /* 61334642Smarc * init structures used in kbd/mouse interrupt service. This code must 61434642Smarc * come after the "init_shared()" routine has run since that routine 61534642Smarc * inits the eq_header[unit] structure used here. 61634642Smarc */ 61730391Skarels 61834642Smarc /* 61934642Smarc * init the "latest mouse report" structure 62034642Smarc */ 62130391Skarels last_rep[unit].state = 0; 62230391Skarels last_rep[unit].dx = 0; 62330391Skarels last_rep[unit].dy = 0; 62430391Skarels last_rep[unit].bytcnt = 0; 62530391Skarels 62634642Smarc /* 62734732Smarc * init the event queue (except mouse position) 62834732Smarc */ 62934732Smarc eq_header[unit]->header.events = 63034732Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 63130391Skarels 63230391Skarels eq_header[unit]->header.size = MAXEVENTS; 63330391Skarels eq_header[unit]->header.head = 0; 63430391Skarels eq_header[unit]->header.tail = 0; 63530391Skarels 63634642Smarc /* 63734642Smarc * open exclusive for graphics device. 63834642Smarc */ 63934642Smarc qdopened[unit] = 0; 64030391Skarels 64130391Skarels } /* qdattach */ 64230391Skarels 64334732Smarc /*ARGSUSED*/ 64430391Skarels qdopen(dev, flag) 64534642Smarc dev_t dev; 64634642Smarc int flag; 64730391Skarels { 64830391Skarels register struct uba_device *ui; /* ptr to uba structures */ 64930391Skarels register struct dga *dga; /* ptr to gate array struct */ 65030391Skarels register struct tty *tp; 65130391Skarels struct duart *duart; 65234732Smarc int unit; 65334732Smarc int minor_dev; 65430391Skarels 65530391Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 65630391Skarels unit = minor_dev >> 2; 65730391Skarels 65834642Smarc /* 65934642Smarc * check for illegal conditions 66034642Smarc */ 66130391Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 66230391Skarels if (ui == 0 || ui->ui_alive == 0) 66334642Smarc return(ENXIO); /* no such device or address */ 66430391Skarels 66530391Skarels duart = (struct duart *) qdmap[unit].duart; 66630391Skarels dga = (struct dga *) qdmap[unit].dga; 66730391Skarels 66830391Skarels if ((minor_dev & 0x03) == 2) { 66934642Smarc /* 67034642Smarc * this is the graphic device... 67134642Smarc */ 67234642Smarc if (qdopened[unit] != 0) 67334732Smarc return(EBUSY); 67434642Smarc else 67534642Smarc qdopened[unit] = 1; 67634642Smarc qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 67734642Smarc /* 67834642Smarc * enble kbd & mouse intrpts in DUART mask reg 67934642Smarc */ 68034642Smarc qdflags[unit].duart_imask |= 0x22; 68134642Smarc duart->imask = qdflags[unit].duart_imask; 68234642Smarc } else { 68334642Smarc /* 68434642Smarc * this is the console 68534642Smarc */ 68634642Smarc qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 68734642Smarc dga->csr |= CURS_ENB; 68834642Smarc qdflags[unit].duart_imask |= 0x02; 68934642Smarc duart->imask = qdflags[unit].duart_imask; 69034642Smarc /* 69134642Smarc * some setup for tty handling 69234642Smarc */ 69334642Smarc tp = &qd_tty[minor_dev]; 69434642Smarc tp->t_addr = ui->ui_addr; 69534642Smarc tp->t_oproc = qdstart; 69634642Smarc if ((tp->t_state & TS_ISOPEN) == 0) { 69734642Smarc ttychars(tp); 69834642Smarc tp->t_flags = IFLAGS; 69934642Smarc tp->t_ispeed = B9600; 70034642Smarc tp->t_ospeed = B9600; 70134642Smarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 70234642Smarc #ifdef POSIXTTY 70334642Smarc tp->t_iflag = TTYDEF_IFLAG; 70434642Smarc tp->t_oflag = TTYDEF_OFLAG; 70534642Smarc tp->t_lflag = TTYDEF_LFLAG; 70634642Smarc tp->t_cflag = TTYDEF_CFLAG; 70734642Smarc #endif 70832012Smarc } 70934642Smarc /* 71034642Smarc * enable intrpts, open line discipline 71134642Smarc */ 71234642Smarc dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 71334642Smarc return ((*linesw[tp->t_line].l_open)(dev, tp)); 71430391Skarels } 71530391Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 71630391Skarels return(0); 71730391Skarels 71830391Skarels } /* qdopen */ 71930391Skarels 72034732Smarc /*ARGSUSED*/ 72130391Skarels qdclose(dev, flag) 72234642Smarc dev_t dev; 72334642Smarc int flag; 72430391Skarels { 72530391Skarels register struct tty *tp; 72630391Skarels register struct qdmap *qd; 72730391Skarels register int *ptep; 72830391Skarels struct dga *dga; /* gate array register map pointer */ 72930391Skarels struct duart *duart; 73030391Skarels struct adder *adder; 73134732Smarc int unit; 73234732Smarc int minor_dev; 73330391Skarels u_int mapix; 73434642Smarc int i; /* SIGNED index */ 73530391Skarels 73630391Skarels minor_dev = minor(dev); /* get minor device number */ 73730391Skarels unit = minor_dev >> 2; /* get QDSS number */ 73830391Skarels qd = &qdmap[unit]; 73930391Skarels 74030391Skarels if ((minor_dev & 0x03) == 2) { 74134642Smarc /* 74234642Smarc * this is the graphic device... 74334642Smarc */ 74434642Smarc if (qdopened[unit] != 1) 74534732Smarc return(EBUSY); 74634642Smarc else 74734642Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 74834642Smarc /* 74934642Smarc * re-protect device memory 75034642Smarc */ 75134642Smarc if (qdflags[unit].mapped & MAPDEV) { 75234642Smarc /* 75334642Smarc * TEMPLATE RAM 75434642Smarc */ 75534642Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 75634642Smarc ptep = (int *)(QVmap[0] + mapix); 75734732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 75834732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 75934642Smarc /* 76034642Smarc * ADDER 76134642Smarc */ 76234642Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 76334642Smarc ptep = (int *)(QVmap[0] + mapix); 76434732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 76534732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 76634642Smarc /* 76734642Smarc * COLOR MAPS 76834642Smarc */ 76934642Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 77034642Smarc ptep = (int *)(QVmap[0] + mapix); 77134732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 77234732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 77334642Smarc } 77434615Smarc 77534642Smarc /* 77634642Smarc * re-protect DMA buffer and free the map registers 77734642Smarc */ 77834642Smarc if (qdflags[unit].mapped & MAPDMA) { 77934642Smarc dga = (struct dga *) qdmap[unit].dga; 78034642Smarc adder = (struct adder *) qdmap[unit].adder; 78134642Smarc dga->csr &= ~DMA_IE; 78234642Smarc dga->csr &= ~0x0600; /* kill DMA */ 78334642Smarc adder->command = CANCEL; 78434642Smarc /* 78534642Smarc * if DMA was running, flush spurious intrpt 78634642Smarc */ 78734642Smarc if (dga->bytcnt_lo != 0) { 78834642Smarc dga->bytcnt_lo = 0; 78934642Smarc dga->bytcnt_hi = 0; 79034642Smarc DMA_SETIGNORE(DMAheader[unit]); 79134642Smarc dga->csr |= DMA_IE; 79234642Smarc dga->csr &= ~DMA_IE; 79334642Smarc } 79434642Smarc ptep = (int *) 79534642Smarc ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 79634732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 79734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 79834642Smarc ubarelse(0, &Qbus_unmap[unit]); 79934642Smarc } 80034615Smarc 80134642Smarc /* 80234642Smarc * re-protect 1K (2 pages) event queue 80334642Smarc */ 80434642Smarc if (qdflags[unit].mapped & MAPEQ) { 80534642Smarc ptep = (int *) 80634642Smarc ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 80734732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 80834642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 80930391Skarels } 81034642Smarc /* 81134642Smarc * re-protect scroll param area and disable scroll intrpts 81234642Smarc */ 81334642Smarc if (qdflags[unit].mapped & MAPSCR) { 81434642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 81534642Smarc + (mfpr(SBR) | 0x80000000)); 81634642Smarc /* 81734642Smarc * re-protect 512 scroll param area 81834642Smarc */ 81934642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 82034642Smarc adder = (struct adder *) qdmap[unit].adder; 82134642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 82234642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 82334642Smarc } 82434642Smarc /* 82534642Smarc * re-protect color map write buffer area and kill intrpts 82634642Smarc */ 82734642Smarc if (qdflags[unit].mapped & MAPCOLOR) { 82834642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 82934642Smarc + (mfpr(SBR) | 0x80000000)); 83034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 83134642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 83234642Smarc color_buf[unit]->status = 0; 83334642Smarc adder = (struct adder *) qdmap[unit].adder; 83434642Smarc qdflags[unit].adder_ie &= ~VSYNC; 83534642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 83634642Smarc } 83734642Smarc mtpr(TBIA, 0); 83834642Smarc /* flag everything now unmapped */ 83934642Smarc qdflags[unit].mapped = 0; 84034642Smarc qdflags[unit].inuse &= ~GRAPHIC_DEV; 84134642Smarc qdflags[unit].curs_acc = ACC_OFF; 84234642Smarc qdflags[unit].curs_thr = 128; 84334642Smarc /* 84434642Smarc * restore the console 84534642Smarc */ 84630391Skarels dga = (struct dga *) qdmap[unit].dga; 84730391Skarels adder = (struct adder *) qdmap[unit].adder; 84830391Skarels dga->csr &= ~DMA_IE; 84930391Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 85030391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 85130391Skarels adder->command = CANCEL; 85234642Smarc /* 85334642Smarc * if DMA was running, flush spurious intrpt 85434642Smarc */ 85530391Skarels if (dga->bytcnt_lo != 0) { 85634642Smarc dga->bytcnt_lo = 0; 85734642Smarc dga->bytcnt_hi = 0; 85834642Smarc DMA_SETIGNORE(DMAheader[unit]); 85934642Smarc dga->csr |= DMA_IE; 86034642Smarc dga->csr &= ~DMA_IE; 86130391Skarels } 86230391Skarels init_shared(unit); /* init shared memory */ 86330391Skarels setup_dragon(unit); /* init ADDER/VIPER */ 86430391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 86530391Skarels setup_input(unit); /* init the DUART */ 86630391Skarels ldfont(unit); 86730391Skarels cursor[unit].x = 0; 86830391Skarels cursor[unit].y = 0; 86934642Smarc /* 87034642Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 87134642Smarc */ 87234642Smarc duart = (struct duart *) qdmap[unit].duart; 87334642Smarc qdflags[unit].duart_imask &= ~(0x20); 87434642Smarc qdflags[unit].duart_imask |= 0x02; 87534642Smarc duart->imask = qdflags[unit].duart_imask; 87634642Smarc /* 87734642Smarc * shut off interrupts if all is closed 87834642Smarc */ 87934642Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 88034642Smarc dga = (struct dga *) qdmap[unit].dga; 88134642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 88234642Smarc } 88334642Smarc } else { 88434642Smarc /* 88534642Smarc * this is the console 88634642Smarc */ 88734642Smarc tp = &qd_tty[minor_dev]; 88834642Smarc (*linesw[tp->t_line].l_close)(tp); 88934642Smarc ttyclose(tp); 89034642Smarc tp->t_state = 0; 89134642Smarc qdflags[unit].inuse &= ~CONS_DEV; 89234642Smarc /* 89334642Smarc * if graphics device is closed, kill interrupts 89434642Smarc */ 89534642Smarc if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 89634642Smarc dga = (struct dga *) qdmap[unit].dga; 89734642Smarc dga->csr &= ~(GLOBAL_IE | DMA_IE); 89834642Smarc } 89930391Skarels } 90034615Smarc 90130391Skarels return(0); 90230391Skarels 90330391Skarels } /* qdclose */ 90430391Skarels 90530391Skarels qdioctl(dev, cmd, datap, flags) 90634642Smarc dev_t dev; 90734642Smarc int cmd; 90834732Smarc register caddr_t datap; 90934642Smarc int flags; 91030391Skarels { 91130391Skarels register int *ptep; /* page table entry pointer */ 91232012Smarc register int mapix; /* QVmap[] page table index */ 91330391Skarels register struct _vs_event *event; 91430391Skarels register struct tty *tp; 91534732Smarc register i; 91630391Skarels struct qdmap *qd; /* pointer to device map struct */ 91730391Skarels struct dga *dga; /* Gate Array reg structure pntr */ 91830391Skarels struct duart *duart; /* DUART reg structure pointer */ 91930391Skarels struct adder *adder; /* ADDER reg structure pointer */ 92030391Skarels struct prgkbd *cmdbuf; 92130391Skarels struct prg_cursor *curs; 92230391Skarels struct _vs_cursor *pos; 92334732Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 92430391Skarels u_int minor_dev = minor(dev); 92530391Skarels int error; 92630391Skarels int s; 92730391Skarels short *temp; /* a pointer to template RAM */ 92830391Skarels 92934642Smarc /* 93034642Smarc * service graphic device ioctl commands 93134642Smarc */ 93230391Skarels switch (cmd) { 93334615Smarc 93434642Smarc case QD_GETEVENT: 93534642Smarc /* 93634642Smarc * extract the oldest event from the event queue 93734642Smarc */ 93830391Skarels if (ISEMPTY(eq_header[unit])) { 93934642Smarc event = (struct _vs_event *) datap; 94034642Smarc event->vse_device = VSE_NULL; 94134642Smarc break; 94230391Skarels } 94330391Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 94434615Smarc s = spl5(); 94530391Skarels GETEND(eq_header[unit]); 94630391Skarels splx(s); 94734732Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 94830391Skarels break; 94930391Skarels 95034642Smarc case QD_RESET: 95134642Smarc /* 95234642Smarc * init the dragon stuff, DUART, and driver variables 95334642Smarc */ 95430391Skarels init_shared(unit); /* init shared memory */ 95530391Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 95630391Skarels clear_qd_screen(unit); 95730391Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 95830391Skarels ldfont(unit); /* load the console font */ 95930391Skarels setup_input(unit); /* init the DUART */ 96030391Skarels break; 96130391Skarels 96234642Smarc case QD_SET: 96334642Smarc /* 96434642Smarc * init the DUART and driver variables 96534642Smarc */ 96630391Skarels init_shared(unit); 96730391Skarels setup_input(unit); 96830391Skarels break; 96930391Skarels 97034642Smarc case QD_CLRSCRN: 97134642Smarc /* 97234642Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 97334642Smarc */ 97434732Smarc #ifdef notdef /* has caused problems and isn't necessary */ 97530391Skarels setup_dragon(unit); 97630391Skarels clear_qd_screen(unit); 97734615Smarc #endif 97830391Skarels break; 97930391Skarels 98034642Smarc case QD_WTCURSOR: 98134642Smarc /* 98234642Smarc * load a cursor into template RAM 98334642Smarc */ 98434732Smarc ldcursor(unit, (short *)datap); 98530391Skarels break; 98630391Skarels 98734642Smarc case QD_RDCURSOR: 98830391Skarels 98930391Skarels temp = (short *) qdmap[unit].template; 99034642Smarc /* 99134642Smarc * cursor is 32 WORDS from the end of the 8k WORD... 99234642Smarc * ...template space 99334642Smarc */ 99430391Skarels temp += (8 * 1024) - 32; 99530391Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 99634642Smarc *(short *)datap = *temp++; 99730391Skarels break; 99830391Skarels 99934642Smarc case QD_POSCURSOR: 100034642Smarc /* 100134642Smarc * position the mouse cursor 100234642Smarc */ 100330391Skarels dga = (struct dga *) qdmap[unit].dga; 100430391Skarels pos = (struct _vs_cursor *) datap; 100534615Smarc s = spl5(); 100630391Skarels dga->x_cursor = TRANX(pos->x); 100730391Skarels dga->y_cursor = TRANY(pos->y); 100830391Skarels eq_header[unit]->curs_pos.x = pos->x; 100930391Skarels eq_header[unit]->curs_pos.y = pos->y; 101030391Skarels splx(s); 101130391Skarels break; 101230391Skarels 101334642Smarc case QD_PRGCURSOR: 101434642Smarc /* 101534642Smarc * set the cursor acceleration factor 101634642Smarc */ 101730391Skarels curs = (struct prg_cursor *) datap; 101834615Smarc s = spl5(); 101930391Skarels qdflags[unit].curs_acc = curs->acc_factor; 102030391Skarels qdflags[unit].curs_thr = curs->threshold; 102130391Skarels splx(s); 102230391Skarels break; 102330391Skarels 102434642Smarc case QD_MAPDEVICE: 102534642Smarc /* 102634642Smarc * enable 'user write' to device pages 102734642Smarc */ 102830391Skarels qdflags[unit].mapped |= MAPDEV; 102930391Skarels qd = (struct qdmap *) &qdmap[unit]; 103034642Smarc /* 103134642Smarc * enable user write to template RAM 103234642Smarc */ 103332012Smarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 103432012Smarc ptep = (int *)(QVmap[0] + mapix); 103534732Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 103634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 103734642Smarc /* 103834642Smarc * enable user write to registers 103934642Smarc */ 104032012Smarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 104132012Smarc ptep = (int *)(QVmap[0] + mapix); 104234732Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 104334732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 104434642Smarc /* 104534642Smarc * enable user write to color maps 104634642Smarc */ 104732012Smarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 104832012Smarc ptep = (int *)(QVmap[0] + mapix); 104934732Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 105034732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 105134642Smarc /* 105234642Smarc * enable user write to DUART 105334642Smarc */ 105432012Smarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 105532012Smarc ptep = (int *)(QVmap[0] + mapix); 105630391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 105730391Skarels 105834732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 105930391Skarels 106034642Smarc /* 106134732Smarc * stuff qdmap structure in return buffer 106234732Smarc */ 106334732Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 106430391Skarels break; 106530391Skarels 106634642Smarc case QD_MAPIOBUF: 106734642Smarc /* 106834642Smarc * do setup for DMA by user process 106934642Smarc * 107034642Smarc * set 'user write enable' bits for DMA buffer 107134642Smarc */ 107230391Skarels qdflags[unit].mapped |= MAPDMA; 107330391Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 107434642Smarc + (mfpr(SBR) | 0x80000000)); 107534732Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 107634732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 107734732Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 107834642Smarc /* 107934642Smarc * set up QBUS map registers for DMA 108034642Smarc */ 108130391Skarels DMAheader[unit]->QBAreg = 108234732Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 108330391Skarels if (DMAheader[unit]->QBAreg == 0) 108434732Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 108530391Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 108630391Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 108734642Smarc /* 108834642Smarc * return I/O buf adr 108934642Smarc */ 109030391Skarels *(int *)datap = (int) DMAheader[unit]; 109130391Skarels break; 109230391Skarels 109334642Smarc case QD_MAPSCROLL: 109434642Smarc /* 109534642Smarc * map the shared scroll param area and enable scroll interpts 109634642Smarc */ 109730391Skarels qdflags[unit].mapped |= MAPSCR; 109830391Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 109934642Smarc + (mfpr(SBR) | 0x80000000)); 110034642Smarc /* 110134642Smarc * allow user write to scroll area 110234642Smarc */ 110330391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 110434732Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 110530391Skarels scroll[unit]->status = 0; 110630391Skarels adder = (struct adder *) qdmap[unit].adder; 110730391Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 110830391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 110934642Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 111030391Skarels break; 111130391Skarels 111234642Smarc case QD_UNMAPSCROLL: 111334642Smarc /* 111434642Smarc * unmap shared scroll param area and disable scroll intrpts 111534642Smarc */ 111630391Skarels if (qdflags[unit].mapped & MAPSCR) { 111734642Smarc qdflags[unit].mapped &= ~MAPSCR; 111834642Smarc ptep = (int *) ((VTOP(scroll[unit]) * 4) 111934642Smarc + (mfpr(SBR) | 0x80000000)); 112034642Smarc /* 112134642Smarc * re-protect 512 scroll param area 112234642Smarc */ 112334642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 112434642Smarc mtpr(TBIA, 0); /* smash CPU's translation buf */ 112534642Smarc adder = (struct adder *) qdmap[unit].adder; 112634642Smarc qdflags[unit].adder_ie &= ~FRAME_SYNC; 112734642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 112830391Skarels } 112930391Skarels break; 113030391Skarels 113134642Smarc case QD_MAPCOLOR: 113234642Smarc /* 113334642Smarc * map shared color map write buf and turn on vsync intrpt 113434642Smarc */ 113530391Skarels qdflags[unit].mapped |= MAPCOLOR; 113630391Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 113734642Smarc + (mfpr(SBR) | 0x80000000)); 113834732Smarc /* 113934732Smarc * allow user write to color map write buffer 114034732Smarc */ 114134732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 114230391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 114330391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 114434642Smarc adder = (struct adder *) qdmap[unit].adder; 114530391Skarels qdflags[unit].adder_ie |= VSYNC; 114630391Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 114734732Smarc /* 114834732Smarc * return color area address 114934732Smarc */ 115030391Skarels *(int *)datap = (int) color_buf[unit]; 115130391Skarels break; 115230391Skarels 115334642Smarc case QD_UNMAPCOLOR: 115434642Smarc /* 115534732Smarc * unmap shared color map write buffer and kill VSYNC intrpts 115634732Smarc */ 115730391Skarels if (qdflags[unit].mapped & MAPCOLOR) { 115834642Smarc qdflags[unit].mapped &= ~MAPCOLOR; 115934642Smarc ptep = (int *) ((VTOP(color_buf[unit]) * 4) 116034642Smarc + (mfpr(SBR) | 0x80000000)); 116134732Smarc /* 116234732Smarc * re-protect color map write buffer 116334732Smarc */ 116434732Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 116534642Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 116634732Smarc mtpr(TBIA, 0); 116734642Smarc adder = (struct adder *) qdmap[unit].adder; 116834642Smarc qdflags[unit].adder_ie &= ~VSYNC; 116934642Smarc adder->interrupt_enable = qdflags[unit].adder_ie; 117030391Skarels } 117130391Skarels break; 117230391Skarels 117334642Smarc case QD_MAPEVENT: 117434642Smarc /* 117534642Smarc * give user write access to the event queue 117634642Smarc */ 117730391Skarels qdflags[unit].mapped |= MAPEQ; 117830391Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 117934642Smarc + (mfpr(SBR) | 0x80000000)); 118034732Smarc /* 118134732Smarc * allow user write to 1K event queue 118234732Smarc */ 118334732Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 118430391Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 118530391Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 118634732Smarc /* 118734732Smarc * return event queue address 118834732Smarc */ 118934732Smarc *(int *)datap = (int)eq_header[unit]; 119030391Skarels break; 119130391Skarels 119234642Smarc case QD_PRGKBD: 119334642Smarc /* 119434642Smarc * pass caller's programming commands to LK201 119534642Smarc */ 119634732Smarc duart = (struct duart *)qdmap[unit].duart; 119734732Smarc cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 119834642Smarc /* 119934642Smarc * send command 120034642Smarc */ 120130391Skarels for (i = 1000; i > 0; --i) { 120234732Smarc if (duart->statusA&XMT_RDY) { 120334642Smarc duart->dataA = cmdbuf->cmd; 120434642Smarc break; 120534642Smarc } 120630391Skarels } 120730391Skarels if (i == 0) { 120834732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 120934642Smarc break; 121030391Skarels } 121134642Smarc /* 121234642Smarc * send param1? 121334642Smarc */ 121430391Skarels if (cmdbuf->cmd & LAST_PARAM) 121534642Smarc break; 121630391Skarels for (i = 1000; i > 0; --i) { 121734732Smarc if (duart->statusA&XMT_RDY) { 121834642Smarc duart->dataA = cmdbuf->param1; 121934642Smarc break; 122034642Smarc } 122130391Skarels } 122230391Skarels if (i == 0) { 122334732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 122434642Smarc break; 122530391Skarels } 122634642Smarc /* 122734642Smarc * send param2? 122834642Smarc */ 122930391Skarels if (cmdbuf->param1 & LAST_PARAM) 123030391Skarels break; 123130391Skarels for (i = 1000; i > 0; --i) { 123234732Smarc if (duart->statusA&XMT_RDY) { 123334642Smarc duart->dataA = cmdbuf->param2; 123434642Smarc break; 123534642Smarc } 123630391Skarels } 123730391Skarels if (i == 0) { 123834732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 123934642Smarc break; 124030391Skarels } 124130391Skarels break; 124230391Skarels 124334642Smarc case QD_PRGMOUSE: 124434642Smarc /* 124534642Smarc * pass caller's programming commands to the mouse 124634642Smarc */ 124730391Skarels duart = (struct duart *) qdmap[unit].duart; 124830391Skarels for (i = 1000; i > 0; --i) { 124934732Smarc if (duart->statusB&XMT_RDY) { 125034642Smarc duart->dataB = *datap; 125134642Smarc break; 125234642Smarc } 125330391Skarels } 125430391Skarels if (i == 0) { 125534732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 125630391Skarels } 125730391Skarels break; 125830391Skarels 125934642Smarc case QD_RDCONFIG: 126034642Smarc /* 126134642Smarc * get QDSS configuration word and return it 126234642Smarc */ 126330391Skarels *(short *)datap = qdflags[unit].config; 126430391Skarels break; 126530391Skarels 126634642Smarc case QD_KERN_LOOP: 126734642Smarc case QD_KERN_UNLOOP: 126834642Smarc /* 126934642Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 127034642Smarc * kernel console output. 127134642Smarc */ 127234615Smarc break; 127334615Smarc 127434642Smarc case QD_PRGTABLET: 127534642Smarc /* 127634642Smarc * program the tablet 127734642Smarc */ 127830391Skarels duart = (struct duart *) qdmap[unit].duart; 127930391Skarels for (i = 1000; i > 0; --i) { 128034732Smarc if (duart->statusB&XMT_RDY) { 128134642Smarc duart->dataB = *datap; 128234642Smarc break; 128334642Smarc } 128430391Skarels } 128530391Skarels if (i == 0) { 128634732Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 128730391Skarels } 128830391Skarels break; 128930391Skarels 129034642Smarc case QD_PRGTABRES: 129134642Smarc /* 129234642Smarc * program the tablet report resolution factor 129334642Smarc */ 129430391Skarels qdflags[unit].tab_res = *(short *)datap; 129530391Skarels break; 129630391Skarels 129734642Smarc default: 129834642Smarc /* 129934642Smarc * service tty ioctl's 130034642Smarc */ 130134642Smarc if (!(minor_dev & 0x02)) { 130230391Skarels tp = &qd_tty[minor_dev]; 130334642Smarc error = 130434642Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 130530391Skarels if (error >= 0) { 130634642Smarc return(error); 130730391Skarels } 130830391Skarels error = ttioctl(tp, cmd, datap, flags); 130930391Skarels if (error >= 0) { 131034642Smarc return(error); 131130391Skarels } 131234642Smarc } 131334642Smarc break; 131430391Skarels } 131530391Skarels 131630391Skarels return(0); 131730391Skarels 131830391Skarels } /* qdioctl */ 131930391Skarels 132030391Skarels qdselect(dev, rw) 132134642Smarc dev_t dev; 132234642Smarc int rw; 132330391Skarels { 132434732Smarc register s; 132534732Smarc register unit; 132634615Smarc register struct tty *tp; 132734615Smarc u_int minor_dev = minor(dev); 132830391Skarels 132934615Smarc s = spl5(); 133034615Smarc unit = minor_dev >> 2; 133130391Skarels 133230391Skarels switch (rw) { 133334642Smarc case FREAD: 133434642Smarc if ((minor_dev & 0x03) == 2) { 133534642Smarc /* 133634642Smarc * this is a graphics device, so check for events 133734642Smarc */ 133834732Smarc if(!(ISEMPTY(eq_header[unit]))) { 133934642Smarc splx(s); 134034642Smarc return(1); 134134642Smarc } 134234732Smarc qdrsel[unit] = u.u_procp; 134334642Smarc qdflags[unit].selmask |= SEL_READ; 134434642Smarc splx(s); 134534642Smarc return(0); 134634642Smarc } else { 134734642Smarc /* 134834642Smarc * this is a tty device 134934642Smarc */ 135034642Smarc tp = &qd_tty[minor_dev]; 135134642Smarc if (ttnread(tp)) 135234642Smarc return(1); 135334642Smarc tp->t_rsel = u.u_procp; 135434642Smarc splx(s); 135534642Smarc return(0); 135630391Skarels } 135730391Skarels 135834642Smarc case FWRITE: 135934642Smarc if ((minor(dev) & 0x03) == 2) { 136034642Smarc /* 136134642Smarc * this is a graphics device, so check for dma buffers 136234642Smarc */ 136334642Smarc if (DMA_ISEMPTY(DMAheader[unit])) 136434642Smarc { 136534642Smarc splx(s); 136634642Smarc return(1); 136734642Smarc } 136834732Smarc qdrsel[unit] = u.u_procp; 136934642Smarc qdflags[unit].selmask |= SEL_WRITE; 137034642Smarc splx(s); 137134642Smarc return(0); 137234642Smarc } else { 137334642Smarc /* 137434642Smarc * this is a tty device 137534642Smarc */ 137634642Smarc tp = &qd_tty[minor_dev]; 1377*37605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 137834642Smarc return(1); 137934642Smarc tp->t_wsel = u.u_procp; 138034642Smarc splx(s); 138134642Smarc return(0); 138230391Skarels } 138330391Skarels } 138434732Smarc splx(s); 138534732Smarc return(0); 138630391Skarels 138730391Skarels } /* qdselect() */ 138830391Skarels 138930391Skarels extern qd_strategy(); 139030391Skarels 139130391Skarels qdwrite(dev, uio) 139234642Smarc dev_t dev; 139334642Smarc struct uio *uio; 139430391Skarels { 139530391Skarels register struct tty *tp; 139634732Smarc register minor_dev; 139734732Smarc register unit; 139830391Skarels 139930391Skarels minor_dev = minor(dev); 140030391Skarels unit = (minor_dev >> 2) & 0x07; 140130391Skarels 140234642Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 140334642Smarc /* 140434642Smarc * this is the console... 140534642Smarc */ 140634642Smarc tp = &qd_tty[minor_dev]; 140734642Smarc return ((*linesw[tp->t_line].l_write)(tp, uio)); 140834642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 140934642Smarc /* 141034642Smarc * this is a DMA xfer from user space 141134642Smarc */ 141234642Smarc return (physio(qd_strategy, &qdbuf[unit], 141334642Smarc dev, B_WRITE, minphys, uio)); 141430391Skarels } 141534732Smarc return (ENXIO); 141630391Skarels } 141730391Skarels 141830391Skarels qdread(dev, uio) 141934642Smarc dev_t dev; 142034642Smarc struct uio *uio; 142130391Skarels { 142230391Skarels register struct tty *tp; 142334732Smarc register minor_dev; 142434732Smarc register unit; 142530391Skarels 142630391Skarels minor_dev = minor(dev); 142730391Skarels unit = (minor_dev >> 2) & 0x07; 142830391Skarels 142934642Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 143034642Smarc /* 143134642Smarc * this is the console 143234642Smarc */ 143334642Smarc tp = &qd_tty[minor_dev]; 143434642Smarc return ((*linesw[tp->t_line].l_read)(tp, uio)); 143534642Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 143634642Smarc /* 143734642Smarc * this is a bitmap-to-processor xfer 143834642Smarc */ 143934642Smarc return (physio(qd_strategy, &qdbuf[unit], 144034642Smarc dev, B_READ, minphys, uio)); 144130391Skarels } 144234732Smarc return (ENXIO); 144330391Skarels } 144430391Skarels 144530391Skarels /*************************************************************** 144630391Skarels * 144730391Skarels * qd_strategy()... strategy routine to do DMA 144830391Skarels * 144930391Skarels ***************************************************************/ 145030391Skarels 145130391Skarels qd_strategy(bp) 145234642Smarc register struct buf *bp; 145330391Skarels { 145430391Skarels register struct dga *dga; 145530391Skarels register struct adder *adder; 145634732Smarc register unit; 145730391Skarels int QBAreg; 145830391Skarels int s; 145930391Skarels int cookie; 146030391Skarels 146130391Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 146230391Skarels 146334642Smarc /* 146434642Smarc * init pointers 146534642Smarc */ 146630391Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 146734732Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 146834642Smarc goto STRAT_ERR; 146930391Skarels } 147030391Skarels dga = (struct dga *) qdmap[unit].dga; 147134615Smarc s = spl5(); 147230391Skarels qdflags[unit].user_dma = -1; 147330391Skarels dga->csr |= DMA_IE; 147430391Skarels cookie = QBAreg & 0x3FFFF; 147530391Skarels dga->adrs_lo = (short) cookie; 147630391Skarels dga->adrs_hi = (short) (cookie >> 16); 147730391Skarels dga->bytcnt_lo = (short) bp->b_bcount; 147830391Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 147930391Skarels 148030391Skarels while (qdflags[unit].user_dma) { 148134642Smarc sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 148230391Skarels } 148330391Skarels splx(s); 148430391Skarels ubarelse(0, &QBAreg); 148530391Skarels if (!(dga->csr & DMA_ERR)) { 148634642Smarc iodone(bp); 148734642Smarc return; 148830391Skarels } 148930391Skarels 149030391Skarels STRAT_ERR: 149130391Skarels adder = (struct adder *) qdmap[unit].adder; 149234642Smarc adder->command = CANCEL; /* cancel adder activity */ 149330391Skarels dga->csr &= ~DMA_IE; 149430391Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 149530391Skarels dga->csr |= DMA_ERR; /* clear error condition */ 149630391Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 149730391Skarels 149834642Smarc /* 149934642Smarc * if DMA was running, flush spurious intrpt 150034642Smarc */ 150130391Skarels if (dga->bytcnt_lo != 0) { 150234642Smarc dga->bytcnt_lo = 0; 150334642Smarc dga->bytcnt_hi = 0; 150434642Smarc DMA_SETIGNORE(DMAheader[unit]); 150534642Smarc dga->csr |= DMA_IE; 150630391Skarels } 150730391Skarels iodone(bp); 150830391Skarels 150930391Skarels } /* qd_strategy */ 151030391Skarels 151134732Smarc /* 151234732Smarc * Start output to the console screen 151334732Smarc */ 151430391Skarels qdstart(tp) 151534642Smarc register struct tty *tp; 151630391Skarels { 151734732Smarc register which_unit, unit, c; 151830391Skarels int s; 151934615Smarc 152030391Skarels unit = minor(tp->t_dev); 152130391Skarels which_unit = (unit >> 2) & 0x3; 152234615Smarc unit &= 0x03; 152330391Skarels 152434615Smarc s = spl5(); 152534615Smarc 152634642Smarc /* 152734642Smarc * If it's currently active, or delaying, no need to do anything. 152834642Smarc */ 152930391Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 153030391Skarels goto out; 153130391Skarels 153234642Smarc /* 153334642Smarc * Display chars until the queue is empty. 153434642Smarc * Drop input from anything but the console 153534642Smarc * device on the floor. 153634642Smarc * 153734642Smarc * XXX - this loop is done at spltty. 153834642Smarc * 153934642Smarc */ 154034642Smarc while (tp->t_outq.c_cc) { 154134511Smarc c = getc(&tp->t_outq); 154234615Smarc if (unit == 0) 154334732Smarc blitc(which_unit, (u_char)c); 154430391Skarels } 154534642Smarc /* 154634642Smarc * If there are sleepers, and output has drained below low 154734642Smarc * water mark, wake up the sleepers. 154834642Smarc */ 1549*37605Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 155034615Smarc if (tp->t_state & TS_ASLEEP){ 155134615Smarc tp->t_state &= ~TS_ASLEEP; 155234615Smarc wakeup((caddr_t) &tp->t_outq); 155334615Smarc } 155430391Skarels } 155530391Skarels 155634615Smarc tp->t_state &= ~TS_BUSY; 155734615Smarc 155830391Skarels out: 155930391Skarels splx(s); 156030391Skarels 156130391Skarels } /* qdstart */ 156230391Skarels 156334732Smarc /*ARGSUSED*/ 156430391Skarels qdstop(tp, flag) 156534642Smarc register struct tty *tp; 156634642Smarc int flag; 156730391Skarels { 156830391Skarels register int s; 156930391Skarels 157034615Smarc s = spl5(); /* block intrpts during state modification */ 157134732Smarc if (tp->t_state & TS_BUSY) 157234732Smarc if ((tp->t_state & TS_TTSTOP) == 0) 157334642Smarc tp->t_state |= TS_FLUSH; 157434642Smarc else 157534642Smarc tp->t_state &= ~TS_BUSY; 157630391Skarels splx(s); 157730391Skarels } 157830391Skarels 157934732Smarc /* 158034732Smarc * Output a character to the QDSS screen 158134732Smarc */ 158230391Skarels 158330391Skarels blitc(unit, chr) 158434732Smarc register unit; 158534732Smarc register u_char chr; 158630391Skarels { 158730391Skarels register struct adder *adder; 158830391Skarels register struct dga *dga; 158930391Skarels register int i; 159034642Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 159134642Smarc static short inescape[NQD]; 159230391Skarels 159334732Smarc adder = (struct adder *)qdmap[unit].adder; 159430391Skarels dga = (struct dga *) qdmap[unit].dga; 159534642Smarc /* 159634642Smarc * BSD comment: this (&=0177) defeats the extended character 159734642Smarc * set code for the glass tty, but if i had the time i would 159834642Smarc * spend it ripping out the code completely. This driver 159934642Smarc * is too big for its own good. 160034642Smarc */ 160134642Smarc chr &= 0177; 160234642Smarc /* 160334732Smarc * Cursor addressing (so vi will work). 160434642Smarc * Decode for "\E=%.%." cursor motion description. 160534732Smarc * Corresponds to type "qdcons" in /etc/termcap: 160634642Smarc * 160734642Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 160834642Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 160934642Smarc * 161034642Smarc */ 161134642Smarc if (inescape[unit] && nograph) { 161234642Smarc switch (inescape[unit]++) { 161334642Smarc case 1: 161434642Smarc if (chr != '=') { 161534642Smarc /* abort escape sequence */ 161634642Smarc inescape[unit] = 0; 161734642Smarc blitc(unit, chr); 161834642Smarc } 161934732Smarc return; 162034642Smarc case 2: 162134642Smarc /* position row */ 162234642Smarc cursor[unit].y = CHAR_HEIGHT * chr; 162334642Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 162434642Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 162534642Smarc dga->y_cursor = TRANY(cursor[unit].y); 162634732Smarc return; 162734642Smarc case 3: 162834642Smarc /* position column */ 162934642Smarc cursor[unit].x = CHAR_WIDTH * chr; 163034642Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 163134642Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 163234642Smarc dga->x_cursor = TRANX(cursor[unit].x); 163334642Smarc inescape[unit] = 0; 163434732Smarc return; 163534642Smarc default: 163634642Smarc inescape[unit] = 0; 163734642Smarc blitc(unit, chr); 163834642Smarc } 163934642Smarc } 164030391Skarels 164130391Skarels switch (chr) { 164234642Smarc case '\r': /* return char */ 164330391Skarels cursor[unit].x = 0; 164434642Smarc if (nograph) 164534642Smarc dga->x_cursor = TRANX(cursor[unit].x); 164634732Smarc return; 164730391Skarels 164834642Smarc case '\t': /* tab char */ 164930391Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 165034642Smarc blitc(unit, ' '); 165130391Skarels } 165234732Smarc return; 165330391Skarels 165434642Smarc case '\n': /* line feed char */ 165530391Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 165634642Smarc if (nograph) { 165734642Smarc cursor[unit].y -= CHAR_HEIGHT; 165834642Smarc scroll_up(adder); 165934642Smarc } else 166034642Smarc cursor[unit].y = 0; 166130391Skarels } 166234642Smarc if (nograph) 166334642Smarc dga->y_cursor = TRANY(cursor[unit].y); 166434732Smarc return; 166530391Skarels 166634642Smarc case '\b': /* backspace char */ 166730391Skarels if (cursor[unit].x > 0) { 166834642Smarc cursor[unit].x -= CHAR_WIDTH; 166934642Smarc if (nograph) 167034642Smarc dga->x_cursor = TRANX(cursor[unit].x); 167130391Skarels } 167234732Smarc return; 167334642Smarc case CTRL('k'): /* cursor up */ 167434642Smarc if (nograph && cursor[unit].y > 0) { 167534642Smarc cursor[unit].y -= CHAR_HEIGHT; 167634642Smarc dga->y_cursor = TRANY(cursor[unit].y); 167734642Smarc } 167834732Smarc return; 167930391Skarels 168034642Smarc case CTRL('^'): /* home cursor */ 168134642Smarc if (nograph) { 168234642Smarc cursor[unit].x = 0; 168334642Smarc dga->x_cursor = TRANX(cursor[unit].x); 168434642Smarc cursor[unit].y = 0; 168534642Smarc dga->y_cursor = TRANY(cursor[unit].y); 168634642Smarc } 168734732Smarc return; 168832012Smarc 168934642Smarc case CTRL('l'): /* cursor right */ 169034642Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 169134642Smarc cursor[unit].x += CHAR_WIDTH; 169234642Smarc dga->x_cursor = TRANX(cursor[unit].x); 169334642Smarc } 169434732Smarc return; 169530391Skarels 169634642Smarc case CTRL('z'): /* clear screen */ 169734642Smarc if (nograph) { 169834642Smarc setup_dragon(unit); 169934642Smarc clear_qd_screen(unit); 170034642Smarc /* home cursor - termcap seems to assume this */ 170134642Smarc cursor[unit].x = 0; 170234642Smarc dga->x_cursor = TRANX(cursor[unit].x); 170334642Smarc cursor[unit].y = 0; 170434642Smarc dga->y_cursor = TRANY(cursor[unit].y); 170534642Smarc } 170634732Smarc return; 170730391Skarels 170834642Smarc case '\033': /* start escape sequence */ 170934642Smarc if (nograph) 171034642Smarc inescape[unit] = 1; 171134732Smarc return; 171234642Smarc 171334642Smarc default: 171434642Smarc if ((chr < ' ') || (chr > '~')) 171534732Smarc return; 171634642Smarc } 171734642Smarc /* 171834642Smarc * setup VIPER operand control registers 171934642Smarc */ 172030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 172130391Skarels write_ID(adder, SRC1_OCR_B, 172234642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 172330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 172430391Skarels write_ID(adder, SRC1_OCR_B, 172534642Smarc EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 172630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 172730391Skarels write_ID(adder, DST_OCR_B, 172834642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 172930391Skarels write_ID(adder, MASK_1, 0xFFFF); 173030391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 173130391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 173234642Smarc adder->x_clip_min = 0; 173334642Smarc adder->x_clip_max = 1024; 173434642Smarc adder->y_clip_min = 0; 173534642Smarc adder->y_clip_max = 864; 173634642Smarc /* 173734642Smarc * load DESTINATION origin and vectors 173834642Smarc */ 173930391Skarels adder->fast_dest_dy = 0; 174030391Skarels adder->slow_dest_dx = 0; 174130391Skarels adder->error_1 = 0; 174230391Skarels adder->error_2 = 0; 174330391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 174434732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 174530391Skarels adder->destination_x = cursor[unit].x; 174630391Skarels adder->fast_dest_dx = CHAR_WIDTH; 174730391Skarels adder->destination_y = cursor[unit].y; 174830391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 174934642Smarc /* 175034642Smarc * load SOURCE origin and vectors 175134642Smarc */ 175234615Smarc if ((chr - ' ') > (CHARS - 1)) { 175334615Smarc printf("Invalid character (x)%x in blitc\n",chr); 175434615Smarc chr = ' '; 175534615Smarc } 175634642Smarc /* 175734642Smarc * X position is modulo the number of characters per line 175834642Smarc */ 175934615Smarc adder->source_1_x = FONT_X + 176034642Smarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 176134642Smarc /* 176234642Smarc * Point to either first or second row 176334642Smarc */ 176434615Smarc adder->source_1_y = 2048 - 15 * 176534642Smarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 176630391Skarels adder->source_1_dx = CHAR_WIDTH; 176730391Skarels adder->source_1_dy = CHAR_HEIGHT; 176830391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 176930391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 177034642Smarc /* 177134642Smarc * update console cursor coordinates 177234642Smarc */ 177330391Skarels cursor[unit].x += CHAR_WIDTH; 177434642Smarc if (nograph) 177534642Smarc dga->x_cursor = TRANX(cursor[unit].x); 177630391Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 177734642Smarc blitc(unit, '\r'); 177834642Smarc blitc(unit, '\n'); 177930391Skarels } 178030391Skarels 178130391Skarels } /* blitc */ 178230391Skarels 178334732Smarc qdreset() { } 178430391Skarels 178534732Smarc /* 178634732Smarc * INTERRUPT SERVICE ROUTINES 178734732Smarc */ 178830391Skarels 178934732Smarc /* 179034732Smarc * Service "DMA DONE" interrupt condition 179134732Smarc */ 179230391Skarels qddint(qd) 179334732Smarc register qd; 179430391Skarels { 179530391Skarels register struct DMAreq_header *header; 179630391Skarels register struct DMAreq *request; 179730391Skarels register struct dga *dga; 179830391Skarels struct adder *adder; 179930391Skarels int cookie; /* DMA adrs for QDSS */ 180030391Skarels 180134732Smarc (void)spl4(); /* allow interval timer in */ 180230391Skarels 180334642Smarc /* 180434642Smarc * init pointers 180534642Smarc */ 180630391Skarels header = DMAheader[qd]; /* register for optimization */ 180730391Skarels dga = (struct dga *) qdmap[qd].dga; 180830391Skarels adder = (struct adder *) qdmap[qd].adder; 180930391Skarels 181034642Smarc /* 181134642Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 181234642Smarc */ 181330391Skarels if (DMA_ISIGNORE(header)) { 181434642Smarc DMA_CLRIGNORE(header); 181534642Smarc return; 181630391Skarels } 181730391Skarels 181834642Smarc /* 181934642Smarc * dump a DMA hardware error message if appropriate 182034642Smarc */ 182130391Skarels if (dga->csr & DMA_ERR) { 182230391Skarels 182334642Smarc if (dga->csr & PARITY_ERR) 182434732Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 182530391Skarels 182634642Smarc if (dga->csr & BUS_ERR) 182734732Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 182830391Skarels } 182930391Skarels 183034642Smarc /* 183134642Smarc * if this was a DMA from user space... 183234642Smarc */ 183330391Skarels if (qdflags[qd].user_dma) { 183434642Smarc qdflags[qd].user_dma = 0; 183534642Smarc wakeup((caddr_t)&qdflags[qd].user_dma); 183634642Smarc return; 183730391Skarels } 183830391Skarels 183934642Smarc /* 184034642Smarc * if we're doing DMA request queue services, field the error condition 184134642Smarc */ 184230391Skarels if (dga->csr & DMA_ERR) { 184330391Skarels 184434642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 184534642Smarc dga->csr |= DMA_ERR; /* clear error condition */ 184634642Smarc adder->command = CANCEL; /* cancel adder activity */ 184730391Skarels 184834642Smarc DMA_SETERROR(header); /* flag error in header status word */ 184934642Smarc DMA_CLRACTIVE(header); 185034642Smarc header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 185134642Smarc header->newest = header->oldest; 185234642Smarc header->used = 0; 185330391Skarels 185434732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 185534732Smarc selwakeup(qdrsel[qd], 0); 185634732Smarc qdrsel[qd] = 0; 185734642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 185834642Smarc } 185930391Skarels 186034642Smarc if (dga->bytcnt_lo != 0) { 186134642Smarc dga->bytcnt_lo = 0; 186234642Smarc dga->bytcnt_hi = 0; 186334642Smarc DMA_SETIGNORE(header); 186434642Smarc } 186534642Smarc return; 186630391Skarels } 186730391Skarels 186834642Smarc /* 186934642Smarc * if the DMA request queue is now becoming non-full, 187034642Smarc * wakeup "select" client. 187134642Smarc */ 187230391Skarels if (DMA_ISFULL(header)) { 187334732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 187434732Smarc selwakeup(qdrsel[qd], 0); 187534732Smarc qdrsel[qd] = 0; 187634642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 187734642Smarc } 187830391Skarels } 187930391Skarels 188030391Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 188134642Smarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 188230391Skarels 188334615Smarc /* check for unexpected interrupt */ 188434615Smarc if (DMA_ISEMPTY(header)) 188530391Skarels return; 188630391Skarels 188730391Skarels DMA_GETEND(header); /* update request queue indices */ 188830391Skarels 188934642Smarc /* 189034732Smarc * if no more DMA pending, wake up "select" client and exit 189134732Smarc */ 189230391Skarels if (DMA_ISEMPTY(header)) { 189330391Skarels 189434732Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 189534732Smarc selwakeup(qdrsel[qd], 0); 189634732Smarc qdrsel[qd] = 0; 189734642Smarc qdflags[qd].selmask &= ~SEL_WRITE; 189834642Smarc } 189930391Skarels 190034642Smarc DMA_CLRACTIVE(header); /* flag DMA done */ 190134642Smarc return; 190230391Skarels } 190330391Skarels 190434642Smarc /* 190534732Smarc * initiate next DMA xfer 190634732Smarc */ 190730391Skarels request = DMA_GETBEGIN(header); 190834615Smarc if (request->DMAtype != QDlast_DMAtype) { 190934642Smarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 191034642Smarc adder->command = CANCEL; /* cancel adder activity */ 191134615Smarc } 191230391Skarels 191334615Smarc 191430391Skarels switch (request->DMAtype) { 191530391Skarels 191634642Smarc case DISPLIST: 191734615Smarc if (request->DMAtype != QDlast_DMAtype) { 191834615Smarc dga->csr |= DL_ENB; 191934615Smarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 192034615Smarc } 192130391Skarels break; 192230391Skarels 192334642Smarc case PTOB: 192434615Smarc if (request->DMAtype != QDlast_DMAtype) { 192534615Smarc if (request->DMAdone & BYTE_PACK) 192634642Smarc dga->csr |= (PTOB_ENB | BYTE_DMA); 192734615Smarc else { 192834615Smarc dga->csr |= PTOB_ENB; 192934615Smarc dga->csr &= ~BYTE_DMA; 193034615Smarc } 193134615Smarc } 193230391Skarels break; 193330391Skarels 193434642Smarc case BTOP: 193534615Smarc if (request->DMAtype != QDlast_DMAtype) { 193634615Smarc if (request->DMAdone & BYTE_PACK) { 193734615Smarc dga->csr &= ~DL_ENB; 193834615Smarc dga->csr |= (BTOP_ENB | BYTE_DMA); 193934615Smarc } 194034615Smarc else { 194134615Smarc dga->csr |= BTOP_ENB; 194234615Smarc dga->csr &= ~(BYTE_DMA | DL_ENB); 194334615Smarc } 194434615Smarc } 194530391Skarels break; 194634642Smarc default: 194734732Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 194830391Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 194930391Skarels return; 195030391Skarels } 195130391Skarels 195230391Skarels if (request->DMAdone & COUNT_ZERO) { 195334642Smarc dga->csr &= ~SET_DONE_FIFO; 195434642Smarc } 195534642Smarc else if (request->DMAdone & FIFO_EMPTY) { 195634642Smarc dga->csr |= SET_DONE_FIFO; 195730391Skarels } 195830391Skarels 195930391Skarels if (request->DMAdone & WORD_PACK) 196030391Skarels dga->csr &= ~BYTE_DMA; 196130391Skarels else if (request->DMAdone & BYTE_PACK) 196230391Skarels dga->csr |= BYTE_DMA; 196330391Skarels 196430391Skarels dga->csr |= DMA_IE; 196534642Smarc QDlast_DMAtype = request->DMAtype; 196630391Skarels 196730391Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 196830391Skarels 196930391Skarels dga->adrs_lo = (short) cookie; 197030391Skarels dga->adrs_hi = (short) (cookie >> 16); 197130391Skarels 197230391Skarels dga->bytcnt_lo = (short) request->length; 197330391Skarels dga->bytcnt_hi = (short) (request->length >> 16); 197430391Skarels 197530391Skarels return; 197630391Skarels } 197730391Skarels 197834732Smarc /* 197934732Smarc * ADDER interrupt service routine 198034732Smarc */ 198130391Skarels qdaint(qd) 198234732Smarc register qd; 198330391Skarels { 198430391Skarels register struct adder *adder; 198530391Skarels struct color_buf *cbuf; 198630391Skarels int i; 198730391Skarels register struct rgb *rgbp; 198830391Skarels register short *red; 198930391Skarels register short *green; 199030391Skarels register short *blue; 199130391Skarels 199234732Smarc (void)spl4(); /* allow interval timer in */ 199330391Skarels 199430391Skarels adder = (struct adder *) qdmap[qd].adder; 199530391Skarels 199634642Smarc /* 199734642Smarc * service the vertical blank interrupt (VSYNC bit) by loading 199834642Smarc * any pending color map load request 199934642Smarc */ 200030391Skarels if (adder->status & VSYNC) { 200134642Smarc adder->status &= ~VSYNC; /* clear the interrupt */ 200234642Smarc cbuf = color_buf[qd]; 200334642Smarc if (cbuf->status & LOAD_COLOR_MAP) { 200430391Skarels 200534642Smarc red = (short *) qdmap[qd].red; 200634642Smarc green = (short *) qdmap[qd].green; 200734642Smarc blue = (short *) qdmap[qd].blue; 200830391Skarels 200934642Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 201034642Smarc --i >= 0; rgbp++) { 201134642Smarc red[rgbp->offset] = (short) rgbp->red; 201234642Smarc green[rgbp->offset] = (short) rgbp->green; 201334642Smarc blue[rgbp->offset] = (short) rgbp->blue; 201434642Smarc } 201530391Skarels 201634642Smarc cbuf->status &= ~LOAD_COLOR_MAP; 201730391Skarels } 201830391Skarels } 201930391Skarels 202034642Smarc /* 202134642Smarc * service the scroll interrupt (FRAME_SYNC bit) 202234642Smarc */ 202330391Skarels if (adder->status & FRAME_SYNC) { 202434642Smarc adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 202530391Skarels 202634642Smarc if (scroll[qd]->status & LOAD_REGS) { 202730391Skarels 202834732Smarc for (i = 1000, adder->status = 0; i > 0 && 202934732Smarc !(adder->status&ID_SCROLL_READY); --i) 203034642Smarc ; 203130391Skarels 203234642Smarc if (i == 0) { 203334732Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 203434642Smarc qd); 203534642Smarc return; 203634642Smarc } 203730391Skarels 203834642Smarc adder->ID_scroll_data = scroll[qd]->viper_constant; 203934642Smarc adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 204030391Skarels 204134642Smarc adder->y_scroll_constant = 204234642Smarc scroll[qd]->y_scroll_constant; 204334642Smarc adder->y_offset_pending = scroll[qd]->y_offset; 204430391Skarels 204534642Smarc if (scroll[qd]->status & LOAD_INDEX) { 204630391Skarels 204734642Smarc adder->x_index_pending = 204834642Smarc scroll[qd]->x_index_pending; 204934642Smarc adder->y_index_pending = 205034642Smarc scroll[qd]->y_index_pending; 205134642Smarc } 205234642Smarc 205334642Smarc scroll[qd]->status = 0x00; 205430391Skarels } 205530391Skarels } 205630391Skarels } 205730391Skarels 205834732Smarc /* 205934732Smarc * DUART input interrupt service routine 206034732Smarc * 206134732Smarc * XXX - this routine should be broken out - it is essentially 206234732Smarc * straight line code. 206334732Smarc */ 206430391Skarels 206530391Skarels qdiint(qd) 206634732Smarc register qd; 206730391Skarels { 206830391Skarels register struct _vs_event *event; 206930391Skarels register struct qdinput *eqh; 207030391Skarels struct dga *dga; 207130391Skarels struct duart *duart; 207230391Skarels struct mouse_report *new_rep; 207330391Skarels struct uba_device *ui; 207430391Skarels struct tty *tp; 207534615Smarc u_short chr; 207630391Skarels u_short status; 207730391Skarels u_short data; 207830391Skarels u_short key; 207930391Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 208030391Skarels char a, b, c; /* mouse button test variables */ 208130391Skarels 208234732Smarc (void)spl4(); /* allow interval timer in */ 208330391Skarels 208430391Skarels eqh = eq_header[qd]; /* optimized as a register */ 208530391Skarels new_rep = ¤t_rep[qd]; 208630391Skarels duart = (struct duart *) qdmap[qd].duart; 208730391Skarels 208834642Smarc /* 208934732Smarc * if the graphic device is turned on.. 209034732Smarc */ 209130391Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 209234642Smarc /* 209334642Smarc * empty DUART 209434642Smarc */ 209534732Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 209634642Smarc /* 209734732Smarc * pick up LK-201 input (if any) 209834732Smarc */ 209934732Smarc if (duart->statusA&RCV_RDY) { 210030391Skarels 210134642Smarc /* if error condition, then reset it */ 210230391Skarels 210334732Smarc if (duart->statusA&0x70) { 210434642Smarc duart->cmdA = 0x40; 210534642Smarc continue; 210634642Smarc } 210730391Skarels 210834642Smarc /* event queue full now? (overflow condition) */ 210930391Skarels 211034642Smarc if (ISFULL(eqh) == TRUE) { 211134642Smarc printf( 211234732Smarc "qd%d: qdiint: event queue overflow\n", 211334642Smarc qd); 211434642Smarc break; 211534642Smarc } 211630391Skarels 211734642Smarc /* 211834642Smarc * Check for various keyboard errors */ 211930391Skarels 212034642Smarc key = duart->dataA & 0xFF; 212130391Skarels 212234642Smarc if (key==LK_POWER_ERROR || 212334642Smarc key==LK_KDOWN_ERROR || 212434642Smarc key == LK_INPUT_ERROR || 212534642Smarc key == LK_OUTPUT_ERROR) { 212634642Smarc printf( 212734732Smarc "qd%d: qdiint: keyboard error, code = %x\n", 212834642Smarc qd,key); 212934732Smarc return; 213034642Smarc } 213130391Skarels 213234642Smarc if (key < LK_LOWEST) 213334732Smarc return; 213430391Skarels 213534642Smarc ++do_wakeup; /* request a select wakeup call */ 213630391Skarels 213734642Smarc event = PUTBEGIN(eqh); 213834642Smarc PUTEND(eqh); 213930391Skarels 214034642Smarc event->vse_key = key; 214134642Smarc event->vse_key &= 0x00FF; 214234642Smarc event->vse_x = eqh->curs_pos.x; 214334642Smarc event->vse_y = eqh->curs_pos.y; 214434642Smarc event->vse_time = TOY; 214534642Smarc event->vse_type = VSE_BUTTON; 214634642Smarc event->vse_direction = VSE_KBTRAW; 214734642Smarc event->vse_device = VSE_DKB; 214834642Smarc } 214930391Skarels 215034642Smarc /* 215134642Smarc * pick up the mouse input (if any) */ 215230391Skarels 215334642Smarc if ((status = duart->statusB) & RCV_RDY && 215434642Smarc qdflags[qd].pntr_id == MOUSE_ID) { 215530391Skarels 215634642Smarc if (status & 0x70) { 215734642Smarc duart->cmdB = 0x40; 215834642Smarc continue; 215934642Smarc } 216030391Skarels 216134642Smarc /* event queue full now? (overflow condition) */ 216230391Skarels 216334642Smarc if (ISFULL(eqh) == TRUE) { 216434642Smarc printf( 216534732Smarc "qd%d: qdiint: event queue overflow\n", 216634642Smarc qd); 216734642Smarc break; 216834642Smarc } 216930391Skarels 217034642Smarc data = duart->dataB; /* get report byte */ 217134642Smarc ++new_rep->bytcnt; /* bump report byte count */ 217230391Skarels 217334642Smarc /* 217434642Smarc * if 1st byte of report.. */ 217530391Skarels 217634642Smarc if ( data & START_FRAME) { 217734642Smarc new_rep->state = data; 217834642Smarc if (new_rep->bytcnt > 1) { 217934642Smarc /* start of new frame */ 218034642Smarc new_rep->bytcnt = 1; 218134642Smarc /* ..continue looking */ 218234642Smarc continue; 218334642Smarc } 218434642Smarc } 218530391Skarels 218634642Smarc /* 218734642Smarc * if 2nd byte of report.. */ 218830391Skarels 218934642Smarc else if (new_rep->bytcnt == 2) { 219034642Smarc new_rep->dx = data & 0x00FF; 219134642Smarc } 219230391Skarels 219334642Smarc /* 219434642Smarc * if 3rd byte of report, load input event queue */ 219530391Skarels 219634642Smarc else if (new_rep->bytcnt == 3) { 219730391Skarels 219834642Smarc new_rep->dy = data & 0x00FF; 219934642Smarc new_rep->bytcnt = 0; 220030391Skarels 220134642Smarc /* 220234642Smarc * if mouse position has changed.. */ 220330391Skarels 220434642Smarc if (new_rep->dx != 0 || new_rep->dy != 0) { 220530391Skarels 220634642Smarc /* 220734642Smarc * calculate acceleration factor, if needed */ 220830391Skarels 220934642Smarc if (qdflags[qd].curs_acc > ACC_OFF) { 221030391Skarels 221134642Smarc if (qdflags[qd].curs_thr <= new_rep->dx) 221234642Smarc new_rep->dx += 221334642Smarc (new_rep->dx - qdflags[qd].curs_thr) 221434642Smarc * qdflags[qd].curs_acc; 221530391Skarels 221634642Smarc if (qdflags[qd].curs_thr <= new_rep->dy) 221734642Smarc new_rep->dy += 221834642Smarc (new_rep->dy - qdflags[qd].curs_thr) 221934642Smarc * qdflags[qd].curs_acc; 222034642Smarc } 222130391Skarels 222234642Smarc /* 222334642Smarc * update cursor position coordinates */ 222430391Skarels 222534642Smarc if (new_rep->state & X_SIGN) { 222634642Smarc eqh->curs_pos.x += new_rep->dx; 222734642Smarc if (eqh->curs_pos.x > 1023) 222834642Smarc eqh->curs_pos.x = 1023; 222934642Smarc } 223034642Smarc else { 223134642Smarc eqh->curs_pos.x -= new_rep->dx; 223234642Smarc if (eqh->curs_pos.x < -15) 223334642Smarc eqh->curs_pos.x = -15; 223434642Smarc } 223530391Skarels 223634642Smarc if (new_rep->state & Y_SIGN) { 223734642Smarc eqh->curs_pos.y -= new_rep->dy; 223834642Smarc if (eqh->curs_pos.y < -15) 223934642Smarc eqh->curs_pos.y = -15; 224034642Smarc } 224134642Smarc else { 224234642Smarc eqh->curs_pos.y += new_rep->dy; 224334642Smarc if (eqh->curs_pos.y > 863) 224434642Smarc eqh->curs_pos.y = 863; 224534642Smarc } 224630391Skarels 224734642Smarc /* 224834642Smarc * update cursor screen position */ 224930391Skarels 225034642Smarc dga = (struct dga *) qdmap[qd].dga; 225134642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 225234642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 225330391Skarels 225434642Smarc /* 225534642Smarc * if cursor is in the box, no event report */ 225630391Skarels 225734642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 225834642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 225934642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 226034642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 226134642Smarc goto GET_MBUTTON; 226234642Smarc } 226330391Skarels 226434642Smarc /* 226534642Smarc * report the mouse motion event */ 226630391Skarels 226734642Smarc event = PUTBEGIN(eqh); 226834642Smarc PUTEND(eqh); 226930391Skarels 227034642Smarc ++do_wakeup; /* request a select wakeup call */ 227130391Skarels 227234642Smarc event->vse_x = eqh->curs_pos.x; 227334642Smarc event->vse_y = eqh->curs_pos.y; 227430391Skarels 227534642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 227634642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 227734642Smarc event->vse_key = 0; 227834642Smarc event->vse_direction = 0; 227934642Smarc event->vse_time = TOY; /* time stamp */ 228034642Smarc } 228130391Skarels 228230391Skarels GET_MBUTTON: 228334642Smarc /* 228434642Smarc * if button state has changed */ 228530391Skarels 228634642Smarc a = new_rep->state & 0x07; /*mask nonbutton bits */ 228734642Smarc b = last_rep[qd].state & 0x07; 228830391Skarels 228934642Smarc if (a ^ b) { 229030391Skarels 229134642Smarc for ( c = 1; c < 8; c <<= 1) { 229230391Skarels 229334642Smarc if (!( c & (a ^ b))) /* this button change? */ 229434642Smarc continue; 229530391Skarels 229634642Smarc /* event queue full? (overflow condition) */ 229730391Skarels 229834642Smarc if (ISFULL(eqh) == TRUE) { 229934732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 230034642Smarc break; 230134642Smarc } 230230391Skarels 230334642Smarc event = PUTBEGIN(eqh); /* get new event */ 230434642Smarc PUTEND(eqh); 230530391Skarels 230634642Smarc ++do_wakeup; /* request select wakeup */ 230730391Skarels 230834642Smarc event->vse_x = eqh->curs_pos.x; 230934642Smarc event->vse_y = eqh->curs_pos.y; 231030391Skarels 231134642Smarc event->vse_device = VSE_MOUSE; /* mouse */ 231234642Smarc event->vse_type = VSE_BUTTON; /* new button */ 231334642Smarc event->vse_time = TOY; /* time stamp */ 231430391Skarels 231534642Smarc /* flag changed button and if up or down */ 231630391Skarels 231734642Smarc if (c == RIGHT_BUTTON) 231834642Smarc event->vse_key = VSE_RIGHT_BUTTON; 231934642Smarc else if (c == MIDDLE_BUTTON) 232034642Smarc event->vse_key = VSE_MIDDLE_BUTTON; 232134642Smarc else if (c == LEFT_BUTTON) 232234642Smarc event->vse_key = VSE_LEFT_BUTTON; 232330391Skarels 232434642Smarc /* set bit = button depressed */ 232530391Skarels 232634642Smarc if (c & a) 232734642Smarc event->vse_direction = VSE_KBTDOWN; 232834642Smarc else 232934642Smarc event->vse_direction = VSE_KBTUP; 233034642Smarc } 233134642Smarc } 233230391Skarels 233334642Smarc /* refresh last report */ 233430391Skarels 233534642Smarc last_rep[qd] = current_rep[qd]; 233630391Skarels 233734642Smarc } /* get last byte of report */ 233834732Smarc } else if ((status = duart->statusB)&RCV_RDY && 233934732Smarc qdflags[qd].pntr_id == TABLET_ID) { 234034732Smarc /* 234134732Smarc * pickup tablet input, if any 234234732Smarc */ 234334732Smarc if (status&0x70) { 234434642Smarc duart->cmdB = 0x40; 234534642Smarc continue; 234634642Smarc } 234734732Smarc /* 234834732Smarc * event queue full now? (overflow condition) 234934732Smarc */ 235034642Smarc if (ISFULL(eqh) == TRUE) { 235134732Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 235234642Smarc break; 235334642Smarc } 235430391Skarels 235534642Smarc data = duart->dataB; /* get report byte */ 235634642Smarc ++new_rep->bytcnt; /* bump report byte count */ 235730391Skarels 235834642Smarc /* 235934642Smarc * if 1st byte of report.. */ 236030391Skarels 236134642Smarc if (data & START_FRAME) { 236234642Smarc new_rep->state = data; 236334642Smarc if (new_rep->bytcnt > 1) { 236434642Smarc new_rep->bytcnt = 1; /* start of new frame */ 236534642Smarc continue; /* ..continue looking */ 236634642Smarc } 236734642Smarc } 236830391Skarels 236934642Smarc /* 237034642Smarc * if 2nd byte of report.. */ 237130391Skarels 237234642Smarc else if (new_rep->bytcnt == 2) { 237334642Smarc new_rep->dx = data & 0x3F; 237434642Smarc } 237530391Skarels 237634642Smarc /* 237734642Smarc * if 3rd byte of report.. */ 237830391Skarels 237934642Smarc else if (new_rep->bytcnt == 3) { 238034642Smarc new_rep->dx |= (data & 0x3F) << 6; 238134642Smarc } 238230391Skarels 238334642Smarc /* 238434642Smarc * if 4th byte of report.. */ 238530391Skarels 238634642Smarc else if (new_rep->bytcnt == 4) { 238734642Smarc new_rep->dy = data & 0x3F; 238834642Smarc } 238930391Skarels 239034642Smarc /* 239134642Smarc * if 5th byte of report, load input event queue */ 239230391Skarels 239334642Smarc else if (new_rep->bytcnt == 5) { 239430391Skarels 239534642Smarc new_rep->dy |= (data & 0x3F) << 6; 239634642Smarc new_rep->bytcnt = 0; 239730391Skarels 239834642Smarc /* 239934642Smarc * update cursor position coordinates */ 240030391Skarels 240134642Smarc new_rep->dx /= qdflags[qd].tab_res; 240234642Smarc new_rep->dy = (2200 - new_rep->dy) 240334642Smarc / qdflags[qd].tab_res; 240430391Skarels 240534642Smarc if (new_rep->dx > 1023) { 240634642Smarc new_rep->dx = 1023; 240734642Smarc } 240834642Smarc if (new_rep->dy > 863) { 240934642Smarc new_rep->dy = 863; 241034642Smarc } 241130391Skarels 241234642Smarc /* 241334642Smarc * report an event if the puck/stylus has moved 241434642Smarc */ 241530391Skarels 241634642Smarc if (eqh->curs_pos.x != new_rep->dx || 241734642Smarc eqh->curs_pos.y != new_rep->dy) { 241830391Skarels 241934642Smarc eqh->curs_pos.x = new_rep->dx; 242034642Smarc eqh->curs_pos.y = new_rep->dy; 242130391Skarels 242234642Smarc /* 242334642Smarc * update cursor screen position */ 242430391Skarels 242534642Smarc dga = (struct dga *) qdmap[qd].dga; 242634642Smarc dga->x_cursor = TRANX(eqh->curs_pos.x); 242734642Smarc dga->y_cursor = TRANY(eqh->curs_pos.y); 242830391Skarels 242934642Smarc /* 243034642Smarc * if cursor is in the box, no event report 243134642Smarc */ 243230391Skarels 243334642Smarc if (eqh->curs_pos.x <= eqh->curs_box.right && 243434642Smarc eqh->curs_pos.x >= eqh->curs_box.left && 243534642Smarc eqh->curs_pos.y >= eqh->curs_box.top && 243634642Smarc eqh->curs_pos.y <= eqh->curs_box.bottom ) { 243734642Smarc goto GET_TBUTTON; 243834642Smarc } 243930391Skarels 244034642Smarc /* 244134642Smarc * report the tablet motion event */ 244230391Skarels 244334642Smarc event = PUTBEGIN(eqh); 244434642Smarc PUTEND(eqh); 244530391Skarels 244634642Smarc ++do_wakeup; /* request a select wakeup call */ 244730391Skarels 244834642Smarc event->vse_x = eqh->curs_pos.x; 244934642Smarc event->vse_y = eqh->curs_pos.y; 245030391Skarels 245134642Smarc event->vse_device = VSE_TABLET; /* tablet */ 245234642Smarc /* 245334642Smarc * right now, X handles tablet motion the same 245434642Smarc * as mouse motion 245534642Smarc */ 245634642Smarc event->vse_type = VSE_MMOTION; /* pos changed */ 245734642Smarc event->vse_key = 0; 245834642Smarc event->vse_direction = 0; 245934642Smarc event->vse_time = TOY; /* time stamp */ 246034642Smarc } 246130391Skarels GET_TBUTTON: 246234642Smarc /* 246334642Smarc * if button state has changed */ 246430391Skarels 246534642Smarc a = new_rep->state & 0x1E; /* mask nonbutton bits */ 246634642Smarc b = last_rep[qd].state & 0x1E; 246730391Skarels 246834642Smarc if (a ^ b) { 246930391Skarels 247034642Smarc /* event queue full now? (overflow condition) */ 247130391Skarels 247234642Smarc if (ISFULL(eqh) == TRUE) { 247334732Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 247434642Smarc break; 247534642Smarc } 247630391Skarels 247734642Smarc event = PUTBEGIN(eqh); /* get new event */ 247834642Smarc PUTEND(eqh); 247930391Skarels 248034642Smarc ++do_wakeup; /* request a select wakeup call */ 248130391Skarels 248234642Smarc event->vse_x = eqh->curs_pos.x; 248334642Smarc event->vse_y = eqh->curs_pos.y; 248430391Skarels 248534642Smarc event->vse_device = VSE_TABLET; /* tablet */ 248634642Smarc event->vse_type = VSE_BUTTON; /* button changed */ 248734642Smarc event->vse_time = TOY; /* time stamp */ 248830391Skarels 248934642Smarc /* define the changed button and if up or down */ 249030391Skarels 249134642Smarc for ( c = 1; c <= 0x10; c <<= 1) { 249234642Smarc if (c & (a ^ b)) { 249334642Smarc if (c == T_LEFT_BUTTON) 249434642Smarc event->vse_key = VSE_T_LEFT_BUTTON; 249534642Smarc else if (c == T_FRONT_BUTTON) 249634642Smarc event->vse_key = VSE_T_FRONT_BUTTON; 249734642Smarc else if (c == T_RIGHT_BUTTON) 249834642Smarc event->vse_key = VSE_T_RIGHT_BUTTON; 249934642Smarc else if (c == T_BACK_BUTTON) 250034642Smarc event->vse_key = VSE_T_BACK_BUTTON; 250134642Smarc break; 250234642Smarc } 250334642Smarc } 250430391Skarels 250534642Smarc /* set bit = button depressed */ 250630391Skarels 250734642Smarc if (c & a) 250834642Smarc event->vse_direction = VSE_KBTDOWN; 250934642Smarc else 251034642Smarc event->vse_direction = VSE_KBTUP; 251134642Smarc } 251230391Skarels 251334642Smarc /* refresh last report */ 251430391Skarels 251534642Smarc last_rep[qd] = current_rep[qd]; 251630391Skarels 251734642Smarc } /* get last byte of report */ 251834642Smarc } /* pick up tablet input */ 251930391Skarels 252034642Smarc } /* while input available.. */ 252130391Skarels 252234642Smarc /* 252334642Smarc * do select wakeup 252434642Smarc */ 252534732Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 252634732Smarc selwakeup(qdrsel[qd], 0); 252734732Smarc qdrsel[qd] = 0; 252834642Smarc qdflags[qd].selmask &= ~SEL_READ; 252934642Smarc do_wakeup = 0; 253034642Smarc } 253134732Smarc } else { 253234732Smarc /* 253334732Smarc * if the graphic device is not turned on, this is console input 253434732Smarc */ 253534642Smarc ui = qdinfo[qd]; 253634642Smarc if (ui == 0 || ui->ui_alive == 0) 253734732Smarc return; 253830391Skarels 253934642Smarc tp = &qd_tty[qd << 2]; 254030391Skarels 254134642Smarc /* 254234732Smarc * Get a character from the keyboard. 254334732Smarc */ 254434732Smarc while (duart->statusA&RCV_RDY) { 254534642Smarc key = duart->dataA; 254634642Smarc key &= 0xFF; 254734642Smarc /* 254834732Smarc * Check for various keyboard errors 254934732Smarc */ 255034732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 255134642Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 255234732Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 255334732Smarc return; 255434642Smarc } 255530391Skarels 255634642Smarc if (key < LK_LOWEST) 255734732Smarc return; 255830391Skarels 255934642Smarc /* 256034642Smarc * See if its a state change key */ 256130391Skarels 256234642Smarc switch (key) { 256330391Skarels 256434642Smarc case LOCK: 256534642Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 256634642Smarc if (q_keyboard.lock) 256734732Smarc (void)led_control(qd, LK_LED_ENABLE, 256834732Smarc LK_LED_LOCK); 256934642Smarc else 257034732Smarc (void)led_control(qd, LK_LED_DISABLE, 257134732Smarc LK_LED_LOCK); 257234642Smarc return; 257330391Skarels 257434642Smarc case SHIFT: 257534642Smarc q_keyboard.shift ^= 0xFFFF; 257634642Smarc return; 257730391Skarels 257834642Smarc case CNTRL: 257934642Smarc q_keyboard.cntrl ^= 0xFFFF; 258034642Smarc return; 258130391Skarels 258234642Smarc case ALLUP: 258334642Smarc q_keyboard.cntrl = 0; 258434642Smarc q_keyboard.shift = 0; 258534642Smarc return; 258630391Skarels 258734642Smarc case REPEAT: 258834642Smarc chr = q_keyboard.last; 258934642Smarc break; 259030391Skarels 259134642Smarc /* 259234642Smarc * Test for cntrl characters. If set, see if the character 259334642Smarc * is elligible to become a control character. */ 259430391Skarels 259534642Smarc default: 259630391Skarels 259734642Smarc if (q_keyboard.cntrl) { 259834642Smarc chr = q_key[key]; 259934642Smarc if (chr >= ' ' && chr <= '~') 260034642Smarc chr &= 0x1F; 260134642Smarc else if (chr >= 0xA1 && chr <= 0xFE) 260234642Smarc chr &= 0x9F; 260334642Smarc } 260434642Smarc else if( q_keyboard.lock || q_keyboard.shift ) 260534642Smarc chr = q_shift_key[key]; 260634642Smarc else 260734642Smarc chr = q_key[key]; 260834642Smarc break; 260930391Skarels } 261030391Skarels 261134642Smarc q_keyboard.last = chr; 261230391Skarels 261334642Smarc /* 261434642Smarc * Check for special function keys */ 261530391Skarels 261634642Smarc if (chr & 0x100) { 261734642Smarc char *string; 261834642Smarc string = q_special[chr & 0x7F]; 261934642Smarc while(*string) 262034642Smarc (*linesw[tp->t_line].l_rint)(*string++, tp); 262134615Smarc } 262234642Smarc else { 262334642Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 262434642Smarc } 262530391Skarels } 262630391Skarels } 262730391Skarels } /* qdiint */ 262830391Skarels 262934732Smarc /* 263034732Smarc * 263134732Smarc * Clear the QDSS screen 263234732Smarc * 263334732Smarc * >>> NOTE <<< 263434732Smarc * 263534732Smarc * This code requires that certain adder initialization be valid. To 263634732Smarc * assure that this requirement is satisfied, this routine should be 263734732Smarc * called only after calling the "setup_dragon()" function. 263834732Smarc * 263934732Smarc * Clear the bitmap a piece at a time. Since the fast scroll clear 264034732Smarc * only clears the current displayed portion of the bitmap put a 264134732Smarc * temporary value in the y limit register so we can access whole 264234732Smarc * bitmap 264334732Smarc * 264434732Smarc */ 264530391Skarels clear_qd_screen(unit) 264634732Smarc int unit; 264730391Skarels { 264830391Skarels register struct adder *adder; 264930391Skarels adder = (struct adder *) qdmap[unit].adder; 265030391Skarels 265130391Skarels adder->x_limit = 1024; 265230391Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 265330391Skarels adder->y_offset_pending = 0; 265434732Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 265534642Smarc WSV; 265630391Skarels adder->y_scroll_constant = SCROLL_ERASE; 265734642Smarc WSV; 265830391Skarels adder->y_offset_pending = 864; 265934642Smarc WSV; 266030391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266134642Smarc WSV; 266230391Skarels adder->y_offset_pending = 1728; 266334642Smarc WSV; 266430391Skarels adder->y_scroll_constant = SCROLL_ERASE; 266534642Smarc WSV; 266630391Skarels adder->y_offset_pending = 0; /* back to normal */ 266734642Smarc WSV; 266830391Skarels adder->x_limit = MAX_SCREEN_X; 266930391Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 267034642Smarc #undef WSV 267130391Skarels 267230391Skarels } /* clear_qd_screen */ 267330391Skarels 267434732Smarc /* 267534732Smarc * kernel console output to the glass tty 267634732Smarc */ 267730391Skarels qdputc(chr) 267834642Smarc register char chr; 267930391Skarels { 268030391Skarels 268134642Smarc /* 268234642Smarc * if system is now physical, forget it (ie: crash DUMP) 268334642Smarc */ 268434642Smarc if ((mfpr(MAPEN) & 1) == 0) 268534642Smarc return; 268634615Smarc 268734732Smarc blitc(0, (u_char)(chr & 0xff)); 268832012Smarc if ((chr & 0177) == '\n') 268932012Smarc blitc(0, '\r'); 269030391Skarels 269130391Skarels } /* qdputc */ 269230391Skarels 269334732Smarc /* 269434732Smarc * load the mouse cursor's template RAM bitmap 269534732Smarc */ 269630391Skarels ldcursor(unit, bitmap) 269734732Smarc int unit; 269834732Smarc register short *bitmap; 269930391Skarels { 270030391Skarels register struct dga *dga; 270130391Skarels register short *temp; 270230391Skarels register int i; 270334732Smarc int curs; 270430391Skarels 270530391Skarels dga = (struct dga *) qdmap[unit].dga; 270630391Skarels temp = (short *) qdmap[unit].template; 270730391Skarels 270830391Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 270934732Smarc curs = -1; /* ..note that.. */ 271034642Smarc dga->csr &= ~CURS_ENB; /* ..and shut it off */ 271134732Smarc } else 271234732Smarc curs = 0; 271330391Skarels 271430391Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 271530391Skarels 271630391Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 271734642Smarc /* ..of the 8k WORD template space */ 271830391Skarels for (i = 0; i < 32; ++i) 271934642Smarc *temp++ = *bitmap++; 272030391Skarels 272134732Smarc if (curs) { /* if cursor was enabled.. */ 272234642Smarc dga->csr |= CURS_ENB; /* ..turn it back on */ 272330391Skarels } 272430391Skarels 272530391Skarels } /* ldcursor */ 272630391Skarels 272734732Smarc /* 272834732Smarc * Put the console font in the QDSS off-screen memory 272934732Smarc */ 273030391Skarels ldfont(unit) 273134732Smarc int unit; 273230391Skarels { 273330391Skarels register struct adder *adder; 273430391Skarels 273534732Smarc register i, j, k, max_chars_line; 273634732Smarc register short packed; 273730391Skarels 273830391Skarels adder = (struct adder *) qdmap[unit].adder; 273930391Skarels 274034642Smarc /* 274134732Smarc * setup VIPER operand control registers 274234732Smarc */ 274330391Skarels write_ID(adder, MASK_1, 0xFFFF); 274430391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 274530391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 274630391Skarels 274730391Skarels write_ID(adder, SRC1_OCR_B, 274834642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 274930391Skarels write_ID(adder, SRC2_OCR_B, 275034642Smarc EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 275130391Skarels write_ID(adder, DST_OCR_B, 275234642Smarc EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 275330391Skarels 275430391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 275530391Skarels 275634642Smarc /* 275734732Smarc * load destination data 275834732Smarc */ 275934732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 276030391Skarels 276130391Skarels adder->destination_x = FONT_X; 276230391Skarels adder->destination_y = FONT_Y; 276334732Smarc #if FONT_WIDTH > MAX_SCREEN_X 276434732Smarc adder->fast_dest_dx = MAX_SCREEN_X; 276534732Smarc #else 276634732Smarc adder->fast_dest_dx = FONT_WIDTH; 276734732Smarc #endif 276830391Skarels adder->slow_dest_dy = CHAR_HEIGHT; 276930391Skarels 277034642Smarc /* 277134642Smarc * setup for processor to bitmap xfer */ 277230391Skarels 277330391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 277430391Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 277530391Skarels 277634642Smarc /* 277734642Smarc * Figure out how many characters can be stored on one "line" of 277834642Smarc * offscreen memory. 277934642Smarc */ 278034642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 278134642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 278234642Smarc max_chars_line = CHARS/2 + CHARS%2; 278330391Skarels 278434642Smarc /* 278534642Smarc * iteratively do the processor to bitmap xfer */ 278634615Smarc 278730391Skarels for (i = 0; i < ROWS; ++i) { 278830391Skarels 278934642Smarc /* PTOB a scan line */ 279030391Skarels 279134642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 279234642Smarc /* PTOB one scan of a char cell */ 279330391Skarels 279434642Smarc packed = q_font[k]; 279534642Smarc k += ROWS; 279634642Smarc packed |= ((short)q_font[k] << 8); 279734642Smarc k += ROWS; 279830391Skarels 279934732Smarc (void)wait_status(adder, TX_READY); 280034642Smarc adder->id_data = packed; 280134642Smarc } 280230391Skarels } 280330391Skarels 280434642Smarc /* 280534642Smarc * (XXX XXX XXX - should remove) 280634642Smarc * 280734642Smarc * Copy the second row of characters. Subtract the first 280834642Smarc * row from the total number. Divide this quantity by 2 280934642Smarc * because 2 chars are stored in a short in the PTOB loop 281034642Smarc * below. Figure out how many characters can be stored on 281134642Smarc * one "line" of offscreen memory 281234642Smarc */ 281334642Smarc 281434642Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 281534642Smarc if ((CHARS/2 + CHARS%2) < max_chars_line) 281634642Smarc return; 281734642Smarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 281834642Smarc /* Paranoia check to see if 3rd row may be needed */ 281934642Smarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 282034615Smarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 282134615Smarc 282234615Smarc adder->destination_x = FONT_X; 282334615Smarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 282434615Smarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 282534615Smarc adder->slow_dest_dy = CHAR_HEIGHT; 282634615Smarc 282734642Smarc /* 282834642Smarc * setup for processor to bitmap xfer 282934642Smarc */ 283034615Smarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 283134615Smarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 283234615Smarc 283334642Smarc /* 283434642Smarc * iteratively do the processor to bitmap xfer 283534642Smarc */ 283634615Smarc for (i = 0; i < ROWS; ++i) { 283734642Smarc /* 283834642Smarc * PTOB a scan line 283934642Smarc */ 284034642Smarc for (j = 0, k = i; j < max_chars_line; ++j) { 284134642Smarc /* 284234642Smarc * PTOB one scan of a char cell 284334642Smarc */ 284434642Smarc packed = q_font[k + FONT_OFFSET]; 284534642Smarc k += ROWS; 284634642Smarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 284734642Smarc k += ROWS; 284834732Smarc (void)wait_status(adder, TX_READY); 284934642Smarc adder->id_data = packed; 285034642Smarc } 285134615Smarc } 285234615Smarc 285330391Skarels } /* ldfont */ 285430391Skarels 285534732Smarc /* 285634732Smarc * Get a character from the LK201 (polled) 285734732Smarc */ 285834732Smarc qdgetc() 285934732Smarc { 286034732Smarc register short key; 286134732Smarc register char chr; 286234732Smarc register struct duart *duart; 286330391Skarels 286434732Smarc duart = (struct duart *) qdmap[0].duart; 286534732Smarc 286634732Smarc /* 286734732Smarc * Get a character from the keyboard. 286834732Smarc */ 286934732Smarc LOOP: 287034732Smarc while (!(duart->statusA&RCV_RDY)) 287134732Smarc ; 287234732Smarc 287334732Smarc key = duart->dataA; 287434732Smarc key &= 0xFF; 287534732Smarc 287634732Smarc /* 287734732Smarc * Check for various keyboard errors */ 287834732Smarc 287934732Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 288034732Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 288134732Smarc printf("Keyboard error, code = %x\n", key); 288234732Smarc return(0); 288334732Smarc } 288434732Smarc 288534732Smarc if (key < LK_LOWEST) 288634732Smarc return(0); 288734732Smarc 288834732Smarc /* 288934732Smarc * See if its a state change key 289034732Smarc */ 289134732Smarc switch (key) { 289234732Smarc 289334732Smarc case LOCK: 289434732Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 289534732Smarc if (q_keyboard.lock) 289634732Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 289734732Smarc else 289834732Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 289934732Smarc goto LOOP; 290034732Smarc 290134732Smarc case SHIFT: 290234732Smarc q_keyboard.shift ^= 0xFFFF; 290334732Smarc goto LOOP; 290434732Smarc 290534732Smarc case CNTRL: 290634732Smarc q_keyboard.cntrl ^= 0xFFFF; 290734732Smarc goto LOOP; 290834732Smarc 290934732Smarc case ALLUP: 291034732Smarc q_keyboard.cntrl = 0; 291134732Smarc q_keyboard.shift = 0; 291234732Smarc goto LOOP; 291334732Smarc 291434732Smarc case REPEAT: 291534732Smarc chr = q_keyboard.last; 291634732Smarc break; 291734732Smarc 291834732Smarc /* 291934732Smarc * Test for cntrl characters. If set, see if the character 292034732Smarc * is elligible to become a control character. 292134732Smarc */ 292234732Smarc default: 292334732Smarc 292434732Smarc if (q_keyboard.cntrl) { 292534732Smarc chr = q_key[key]; 292634732Smarc if (chr >= ' ' && chr <= '~') 292734732Smarc chr &= 0x1F; 292834732Smarc } 292934732Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 293034732Smarc chr = q_shift_key[key]; 293134732Smarc else 293234732Smarc chr = q_key[key]; 293334732Smarc break; 293434732Smarc } 293534732Smarc 293634732Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 293734732Smarc return(0); /* ..then pitch it! */ 293834732Smarc 293934732Smarc q_keyboard.last = chr; 294034732Smarc 294134732Smarc /* 294234732Smarc * Check for special function keys */ 294334732Smarc 294434732Smarc if (chr & 0x80) /* pitch the function keys */ 294534732Smarc return(0); 294634732Smarc else 294734732Smarc return(chr); 294834732Smarc 294934732Smarc } /* qdgetc */ 295034732Smarc 295134732Smarc /* 295234732Smarc * led_control()... twiddle LK-201 LED's 295334732Smarc */ 295430391Skarels led_control(unit, cmd, led_mask) 295534732Smarc int unit, cmd, led_mask; 295630391Skarels { 295734732Smarc register i; 295830391Skarels register struct duart *duart; 295930391Skarels 296034732Smarc duart = (struct duart *)qdmap[unit].duart; 296130391Skarels 296230391Skarels for (i = 1000; i > 0; --i) { 296334732Smarc if (duart->statusA&XMT_RDY) { 296434642Smarc duart->dataA = cmd; 296534642Smarc break; 296634642Smarc } 296730391Skarels } 296830391Skarels for (i = 1000; i > 0; --i) { 296934732Smarc if (duart->statusA&XMT_RDY) { 297034642Smarc duart->dataA = led_mask; 297134642Smarc break; 297234642Smarc } 297330391Skarels } 297430391Skarels if (i == 0) 297534642Smarc return(BAD); 297630391Skarels return(GOOD); 297730391Skarels 297830391Skarels } /* led_control */ 297930391Skarels 298034732Smarc /* 298134732Smarc * scroll_up()... move the screen up one character height 298234732Smarc */ 298330391Skarels scroll_up(adder) 298434642Smarc register struct adder *adder; 298530391Skarels { 298634642Smarc /* 298734642Smarc * setup VIPER operand control registers 298834642Smarc */ 298934732Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 299030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 299130391Skarels write_ID(adder, MASK_1, 0xFFFF); 299230391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 299330391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 299430391Skarels write_ID(adder, SRC1_OCR_B, 299534642Smarc EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 299630391Skarels write_ID(adder, DST_OCR_B, 299734642Smarc EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 299834642Smarc /* 299934642Smarc * load DESTINATION origin and vectors 300034642Smarc */ 300130391Skarels adder->fast_dest_dy = 0; 300230391Skarels adder->slow_dest_dx = 0; 300330391Skarels adder->error_1 = 0; 300430391Skarels adder->error_2 = 0; 300530391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 300630391Skarels adder->destination_x = 0; 300730391Skarels adder->fast_dest_dx = 1024; 300830391Skarels adder->destination_y = 0; 300930391Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 301034642Smarc /* 301134642Smarc * load SOURCE origin and vectors 301234642Smarc */ 301330391Skarels adder->source_1_x = 0; 301430391Skarels adder->source_1_dx = 1024; 301530391Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 301630391Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 301730391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 301830391Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 301934642Smarc /* 302034642Smarc * do a rectangle clear of last screen line 302134642Smarc */ 302230391Skarels write_ID(adder, MASK_1, 0xffff); 302330391Skarels write_ID(adder, SOURCE, 0xffff); 302430391Skarels write_ID(adder,DST_OCR_B, 302534642Smarc (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 302630391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 302730391Skarels adder->error_1 = 0; 302830391Skarels adder->error_2 = 0; 302934642Smarc adder->slow_dest_dx = 0; /* set up the width of */ 303030391Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 303130391Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 303234732Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 303330391Skarels adder->destination_x = 0; 303430391Skarels adder->destination_y = 864 - CHAR_HEIGHT; 303530391Skarels adder->fast_dest_dx = 1024; /* set up the height */ 303630391Skarels adder->fast_dest_dy = 0; /* of rectangle */ 303730391Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 303830391Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 303930391Skarels 304030391Skarels } /* scroll_up */ 304130391Skarels 304234732Smarc /* 304334732Smarc * init shared memory pointers and structures 304434732Smarc */ 304530391Skarels init_shared(unit) 304634732Smarc register unit; 304730391Skarels { 304830391Skarels register struct dga *dga; 304930391Skarels 305030391Skarels dga = (struct dga *) qdmap[unit].dga; 305130391Skarels 305234642Smarc /* 305334642Smarc * initialize the event queue pointers and header */ 305430391Skarels 305530391Skarels eq_header[unit] = (struct qdinput *) 305634642Smarc ((((int)event_shared & ~(0x01FF)) + 512) 305734642Smarc + (EVENT_BUFSIZE * unit)); 305830391Skarels eq_header[unit]->curs_pos.x = 0; 305930391Skarels eq_header[unit]->curs_pos.y = 0; 306030391Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 306130391Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 306230391Skarels eq_header[unit]->curs_box.left = 0; 306330391Skarels eq_header[unit]->curs_box.right = 0; 306430391Skarels eq_header[unit]->curs_box.top = 0; 306530391Skarels eq_header[unit]->curs_box.bottom = 0; 306634642Smarc /* 306734642Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 306834642Smarc */ 306930391Skarels DMAheader[unit] = (struct DMAreq_header *) 307034642Smarc (((int)(&DMA_shared[0] + 512) & ~0x1FF) 307134642Smarc + (DMAbuf_size * unit)); 307230391Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 307334642Smarc + sizeof(struct DMAreq_header)); 307430391Skarels DMAheader[unit]->QBAreg = 0; 307530391Skarels DMAheader[unit]->status = 0; 307630391Skarels DMAheader[unit]->shared_size = DMAbuf_size; 307730391Skarels DMAheader[unit]->used = 0; 307830391Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 307930391Skarels DMAheader[unit]->oldest = 0; 308030391Skarels DMAheader[unit]->newest = 0; 308134642Smarc /* 308234642Smarc * assign a pointer to the scroll structure for this QDSS. 308334642Smarc */ 308430391Skarels scroll[unit] = (struct scroll *) 308534642Smarc (((int)(&scroll_shared[0] + 512) & ~0x1FF) 308634642Smarc + (sizeof(struct scroll) * unit)); 308730391Skarels scroll[unit]->status = 0; 308830391Skarels scroll[unit]->viper_constant = 0; 308930391Skarels scroll[unit]->y_scroll_constant = 0; 309030391Skarels scroll[unit]->y_offset = 0; 309130391Skarels scroll[unit]->x_index_pending = 0; 309230391Skarels scroll[unit]->y_index_pending = 0; 309334642Smarc /* 309434642Smarc * assign a pointer to the color map write buffer for this QDSS 309534642Smarc */ 309630391Skarels color_buf[unit] = (struct color_buf *) 309734642Smarc (((int)(&color_shared[0] + 512) & ~0x1FF) 309834642Smarc + (COLOR_BUFSIZ * unit)); 309930391Skarels color_buf[unit]->status = 0; 310030391Skarels color_buf[unit]->count = 0; 310130391Skarels 310230391Skarels } /* init_shared */ 310330391Skarels 310434732Smarc /* 310534732Smarc * init the ADDER, VIPER, bitmaps, & color map 310634732Smarc */ 310730391Skarels setup_dragon(unit) 310834732Smarc int unit; 310930391Skarels { 311030391Skarels 311130391Skarels register struct adder *adder; 311230391Skarels register struct dga *dga; 311330391Skarels short *memcsr; 311434732Smarc register i; 311530391Skarels short top; /* clipping/scrolling boundaries */ 311630391Skarels short bottom; 311730391Skarels short right; 311830391Skarels short left; 311930391Skarels short *red; /* color map pointers */ 312030391Skarels short *green; 312130391Skarels short *blue; 312230391Skarels 312334642Smarc /* 312434642Smarc * init for setup 312534642Smarc */ 312630391Skarels adder = (struct adder *) qdmap[unit].adder; 312730391Skarels dga = (struct dga *) qdmap[unit].dga; 312830391Skarels memcsr = (short *) qdmap[unit].memcsr; 312930391Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 313030391Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 313130391Skarels adder->command = CANCEL; 313234642Smarc /* 313334642Smarc * set monitor timing 313434642Smarc */ 313530391Skarels adder->x_scan_count_0 = 0x2800; 313630391Skarels adder->x_scan_count_1 = 0x1020; 313730391Skarels adder->x_scan_count_2 = 0x003A; 313830391Skarels adder->x_scan_count_3 = 0x38F0; 313930391Skarels adder->x_scan_count_4 = 0x6128; 314030391Skarels adder->x_scan_count_5 = 0x093A; 314130391Skarels adder->x_scan_count_6 = 0x313C; 314230391Skarels adder->sync_phase_adj = 0x0100; 314330391Skarels adder->x_scan_conf = 0x00C8; 314434642Smarc /* 314534642Smarc * got a bug in secound pass ADDER! lets take care of it 314634642Smarc * 314734642Smarc * normally, just use the code in the following bug fix code, but to 314834642Smarc * make repeated demos look pretty, load the registers as if there was 314934642Smarc * no bug and then test to see if we are getting sync 315034642Smarc */ 315130391Skarels adder->y_scan_count_0 = 0x135F; 315230391Skarels adder->y_scan_count_1 = 0x3363; 315330391Skarels adder->y_scan_count_2 = 0x2366; 315430391Skarels adder->y_scan_count_3 = 0x0388; 315534642Smarc /* 315634642Smarc * if no sync, do the bug fix code 315734642Smarc */ 315830391Skarels if (wait_status(adder, VSYNC) == BAD) { 315934642Smarc /* first load all Y scan registers with very short frame and 316034642Smarc * wait for scroll service. This guarantees at least one SYNC 316134642Smarc * to fix the pass 2 Adder initialization bug (synchronizes 316234642Smarc * XCINCH with DMSEEDH) 316334642Smarc */ 316434642Smarc adder->y_scan_count_0 = 0x01; 316534642Smarc adder->y_scan_count_1 = 0x01; 316634642Smarc adder->y_scan_count_2 = 0x01; 316734642Smarc adder->y_scan_count_3 = 0x01; 316834642Smarc /* 316934642Smarc * delay at least 1 full frame time 317034642Smarc */ 317134732Smarc (void)wait_status(adder, VSYNC); 317234732Smarc (void)wait_status(adder, VSYNC); 317334642Smarc /* 317434642Smarc * now load the REAL sync values (in reverse order just to 317534642Smarc * be safe. 317634642Smarc */ 317734642Smarc adder->y_scan_count_3 = 0x0388; 317834642Smarc adder->y_scan_count_2 = 0x2366; 317934642Smarc adder->y_scan_count_1 = 0x3363; 318034642Smarc adder->y_scan_count_0 = 0x135F; 318130391Skarels } 318230391Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 318334642Smarc /* 318434642Smarc * zero the index registers 318534642Smarc */ 318630391Skarels adder->x_index_pending = 0; 318730391Skarels adder->y_index_pending = 0; 318830391Skarels adder->x_index_new = 0; 318930391Skarels adder->y_index_new = 0; 319030391Skarels adder->x_index_old = 0; 319130391Skarels adder->y_index_old = 0; 319230391Skarels adder->pause = 0; 319334642Smarc /* 319434642Smarc * set rasterop mode to normal pen down 319534642Smarc */ 319630391Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 319734642Smarc /* 319834642Smarc * set the rasterop registers to a default values 319934642Smarc */ 320030391Skarels adder->source_1_dx = 1; 320130391Skarels adder->source_1_dy = 1; 320230391Skarels adder->source_1_x = 0; 320330391Skarels adder->source_1_y = 0; 320430391Skarels adder->destination_x = 0; 320530391Skarels adder->destination_y = 0; 320630391Skarels adder->fast_dest_dx = 1; 320730391Skarels adder->fast_dest_dy = 0; 320830391Skarels adder->slow_dest_dx = 0; 320930391Skarels adder->slow_dest_dy = 1; 321030391Skarels adder->error_1 = 0; 321130391Skarels adder->error_2 = 0; 321234642Smarc /* 321334732Smarc * scale factor = UNITY 321434642Smarc */ 321530391Skarels adder->fast_scale = UNITY; 321630391Skarels adder->slow_scale = UNITY; 321734642Smarc /* 321834642Smarc * set the source 2 parameters 321934642Smarc */ 322030391Skarels adder->source_2_x = 0; 322130391Skarels adder->source_2_y = 0; 322230391Skarels adder->source_2_size = 0x0022; 322334642Smarc /* 322434642Smarc * initialize plane addresses for eight vipers 322534642Smarc */ 322630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 322730391Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 322830391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 322930391Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 323030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 323130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 323230391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 323330391Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 323430391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 323530391Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 323630391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 323730391Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 323830391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 323930391Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 324030391Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 324130391Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 324234642Smarc /* 324334642Smarc * initialize the external registers. 324434642Smarc */ 324530391Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 324630391Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 324734642Smarc /* 324834642Smarc * initialize resolution mode 324934642Smarc */ 325030391Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 325130391Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 325234642Smarc /* 325334642Smarc * initialize viper registers 325434642Smarc */ 325530391Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 325630391Skarels write_ID(adder, SCROLL_FILL, 0x0000); 325734642Smarc /* 325834642Smarc * set clipping and scrolling limits to full screen 325934642Smarc */ 326034732Smarc for (i = 1000, adder->status = 0; 326134732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 326234642Smarc ; 326330391Skarels if (i == 0) 326434732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 326530391Skarels top = 0; 326630391Skarels bottom = 2048; 326730391Skarels left = 0; 326830391Skarels right = 1024; 326930391Skarels adder->x_clip_min = left; 327030391Skarels adder->x_clip_max = right; 327130391Skarels adder->y_clip_min = top; 327230391Skarels adder->y_clip_max = bottom; 327330391Skarels adder->scroll_x_min = left; 327430391Skarels adder->scroll_x_max = right; 327530391Skarels adder->scroll_y_min = top; 327630391Skarels adder->scroll_y_max = bottom; 327734732Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 327834732Smarc (void)wait_status(adder, VSYNC); 327930391Skarels adder->x_index_pending = left; 328030391Skarels adder->y_index_pending = top; 328130391Skarels adder->x_index_new = left; 328230391Skarels adder->y_index_new = top; 328330391Skarels adder->x_index_old = left; 328430391Skarels adder->y_index_old = top; 328530391Skarels 328634732Smarc for (i = 1000, adder->status = 0; i > 0 && 328734732Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 328834642Smarc ; 328930391Skarels if (i == 0) 329034732Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 329130391Skarels 329230391Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 329330391Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 329434642Smarc /* 329534642Smarc * set source and the mask register to all ones (ie: white) o 329634642Smarc */ 329730391Skarels write_ID(adder, SOURCE, 0xFFFF); 329830391Skarels write_ID(adder, MASK_1, 0xFFFF); 329930391Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 330030391Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 330134642Smarc /* 330234642Smarc * initialize Operand Control Register banks for fill command 330334642Smarc */ 330430391Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 330530391Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 330630391Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 330730391Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 330830391Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 330930391Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 331034642Smarc /* 331134642Smarc * init Logic Unit Function registers, (these are just common values, 331234642Smarc * and may be changed as required). 331334642Smarc */ 331430391Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 331534642Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 331634642Smarc INV_M1_M2); 331730391Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 331830391Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 331934642Smarc /* 332034642Smarc * load the color map for black & white 332134642Smarc */ 332234732Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 332334642Smarc ; 332430391Skarels 332530391Skarels if (i == 0) 332634732Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 332730391Skarels 332830391Skarels red = (short *) qdmap[unit].red; 332930391Skarels green = (short *) qdmap[unit].green; 333030391Skarels blue = (short *) qdmap[unit].blue; 333130391Skarels 333230391Skarels *red++ = 0x00; /* black */ 333330391Skarels *green++ = 0x00; 333430391Skarels *blue++ = 0x00; 333530391Skarels 333630391Skarels *red-- = 0xFF; /* white */ 333730391Skarels *green-- = 0xFF; 333830391Skarels *blue-- = 0xFF; 333930391Skarels 334034642Smarc /* 334134732Smarc * set color map for mouse cursor 334234732Smarc */ 334330391Skarels 334430391Skarels red += 254; 334530391Skarels green += 254; 334630391Skarels blue += 254; 334730391Skarels 334830391Skarels *red++ = 0x00; /* black */ 334930391Skarels *green++ = 0x00; 335030391Skarels *blue++ = 0x00; 335130391Skarels 335230391Skarels *red = 0xFF; /* white */ 335330391Skarels *green = 0xFF; 335430391Skarels *blue = 0xFF; 335530391Skarels 335630391Skarels } /* setup_dragon */ 335730391Skarels 335834732Smarc /* 335934732Smarc * Init the DUART and set defaults in input 336034732Smarc */ 336130391Skarels setup_input(unit) 336234732Smarc int unit; 336330391Skarels { 336430391Skarels register struct duart *duart; /* DUART register structure pointer */ 336534732Smarc register i, bits; 336630391Skarels char id_byte; 336730391Skarels 336830391Skarels duart = (struct duart *) qdmap[unit].duart; 336930391Skarels duart->imask = 0; 337030391Skarels 337134642Smarc /* 337234642Smarc * setup the DUART for kbd & pointing device 337334642Smarc */ 337434732Smarc duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 337534732Smarc duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 337634732Smarc /* no RTS control,char error mode */ 337734732Smarc duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 337834732Smarc /* no RTS control,no echo or loop */ 337934732Smarc duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 338034732Smarc duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 338134732Smarc /* ..no RTS cntrl, char error mode */ 338234732Smarc duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 338334732Smarc /* no RTS control,no echo or loop */ 338434732Smarc duart->auxctl = 0x00; /* baud rate set 1 */ 338534732Smarc duart->clkselA = 0x99; /* 4800 baud for kbd */ 338634732Smarc duart->clkselB = 0x99; /* 4800 baud for mouse */ 338730391Skarels 338830391Skarels /* reset everything for keyboard */ 338930391Skarels 339030391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339134642Smarc duart->cmdA = bits; 339230391Skarels 339330391Skarels /* reset everything for host */ 339430391Skarels 339530391Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 339634642Smarc duart->cmdB = bits; 339730391Skarels 339830391Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 339930391Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 340030391Skarels 340134642Smarc /* 340234732Smarc * init keyboard defaults (DUART channel A) 340334732Smarc */ 340430391Skarels for (i = 500; i > 0; --i) { 340534732Smarc if (duart->statusA&XMT_RDY) { 340634642Smarc duart->dataA = LK_DEFAULTS; 340734642Smarc break; 340834642Smarc } 340930391Skarels } 341030391Skarels 341130391Skarels for (i = 100000; i > 0; --i) { 341234732Smarc if (duart->statusA&RCV_RDY) { 341334642Smarc break; 341434642Smarc } 341530391Skarels } 341630391Skarels 341734732Smarc if (duart->dataA) /* flush the ACK */ 341834732Smarc ; 341930391Skarels 342034642Smarc /* 342134732Smarc * identify the pointing device 342234732Smarc */ 342330391Skarels for (i = 500; i > 0; --i) { 342434732Smarc if (duart->statusB&XMT_RDY) { 342534642Smarc duart->dataB = SELF_TEST; 342634642Smarc break; 342734642Smarc } 342830391Skarels } 342930391Skarels 343034642Smarc /* 343130391Skarels * wait for 1st byte of self test report */ 343230391Skarels 343330391Skarels for (i = 100000; i > 0; --i) { 343434732Smarc if (duart->statusB&RCV_RDY) { 343534642Smarc break; 343634642Smarc } 343730391Skarels } 343830391Skarels 343930391Skarels if (i == 0) { 344034732Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 344134642Smarc ,unit); 344234642Smarc goto OUT; 344330391Skarels } 344430391Skarels 344534732Smarc if (duart->dataB) 344634732Smarc ; 344730391Skarels 344834642Smarc /* 344934732Smarc * wait for ID byte of self test report 345034732Smarc */ 345130391Skarels for (i = 100000; i > 0; --i) { 345234732Smarc if (duart->statusB&RCV_RDY) { 345334642Smarc break; 345434642Smarc } 345530391Skarels } 345630391Skarels 345730391Skarels if (i == 0) { 345834732Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 345934642Smarc goto OUT; 346030391Skarels } 346130391Skarels 346230391Skarels id_byte = duart->dataB; 346330391Skarels 346434642Smarc /* 346534732Smarc * wait for other bytes to come in 346634732Smarc */ 346730391Skarels for (i = 100000; i > 0; --i) { 346834732Smarc if (duart->statusB & RCV_RDY) { 346934732Smarc if (duart->dataB) 347034732Smarc ; 347134642Smarc break; 347234642Smarc } 347330391Skarels } 347430391Skarels if (i == 0) { 347534732Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 347634642Smarc goto OUT; 347730391Skarels } 347830391Skarels for (i = 100000; i > 0; --i) { 347934732Smarc if (duart->statusB&RCV_RDY) { 348034732Smarc if (duart->dataB) 348134732Smarc ; 348234642Smarc break; 348334642Smarc } 348430391Skarels } 348530391Skarels if (i == 0) { 348634732Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 348734642Smarc goto OUT; 348830391Skarels } 348934642Smarc /* 349034732Smarc * flag pointing device type and set defaults 349134732Smarc */ 349234732Smarc for (i=100000; i>0; --i) 349334732Smarc ; /*XXX*/ 349430391Skarels 349530391Skarels if ((id_byte & 0x0F) != TABLET_ID) { 349634642Smarc qdflags[unit].pntr_id = MOUSE_ID; 349730391Skarels 349834642Smarc for (i = 500; i > 0; --i) { 349934732Smarc if (duart->statusB&XMT_RDY) { 350034642Smarc duart->dataB = INC_STREAM_MODE; 350134642Smarc break; 350234642Smarc } 350330391Skarels } 350434642Smarc } 350534642Smarc else { 350634642Smarc qdflags[unit].pntr_id = TABLET_ID; 350730391Skarels 350834642Smarc for (i = 500; i > 0; --i) { 350934732Smarc if (duart->statusB&XMT_RDY) { 351034642Smarc duart->dataB = T_STREAM; 351134642Smarc break; 351234642Smarc } 351330391Skarels } 351430391Skarels } 351530391Skarels OUT: 351630391Skarels duart->imask = qdflags[unit].duart_imask; 351730391Skarels 351830391Skarels } /* setup_input */ 351930391Skarels 352034732Smarc /* 352134732Smarc * delay for at least one display frame time 352234732Smarc * 352334732Smarc * return: BAD means that we timed out without ever seeing the 352434732Smarc * vertical sync status bit 352534732Smarc * GOOD otherwise 352634732Smarc */ 352730391Skarels wait_status(adder, mask) 352834642Smarc register struct adder *adder; 352934642Smarc register int mask; 353030391Skarels { 353134732Smarc register i; 353230391Skarels 353334732Smarc for (i = 10000, adder->status = 0 ; i > 0 && 353434732Smarc !(adder->status&mask) ; --i) 353534642Smarc ; 353630391Skarels 353730391Skarels if (i == 0) { 353834732Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 353934642Smarc return(BAD); 354030391Skarels } 354130391Skarels 354230391Skarels return(GOOD); 354330391Skarels 354430391Skarels } /* wait_status */ 354530391Skarels 354634732Smarc /* 354734732Smarc * write out onto the ID bus 354834732Smarc */ 354930391Skarels write_ID(adder, adrs, data) 355034642Smarc register struct adder *adder; 355134642Smarc register short adrs; 355234642Smarc register short data; 355330391Skarels { 355434732Smarc register i; 355530391Skarels 355634732Smarc for (i = 100000, adder->status = 0 ; 355734732Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 355834642Smarc ; 355930391Skarels 356030391Skarels if (i == 0) 356134732Smarc goto ERR; 356230391Skarels 356334732Smarc for (i = 100000, adder->status = 0 ; 356434732Smarc i > 0 && !(adder->status&TX_READY) ; --i) 356534642Smarc ; 356630391Skarels 356730391Skarels if (i > 0) { 356834642Smarc adder->id_data = data; 356934642Smarc adder->command = ID_LOAD | adrs; 357034732Smarc return ; 357130391Skarels } 357230391Skarels 357330391Skarels ERR: 357434732Smarc printf("write_ID: timeout trying to write to VIPER\n"); 357534732Smarc return ; 357630391Skarels 357730391Skarels } /* write_ID */ 357834511Smarc #endif 3579