1006e9885Smarc /* 2537afb73Sbostic * Copyright (c) 1988 Regents of the University of California. 3537afb73Sbostic * All rights reserved. 4006e9885Smarc * 5537afb73Sbostic * Redistribution and use in source and binary forms are permitted 6537afb73Sbostic * provided that the above copyright notice and this paragraph are 7537afb73Sbostic * duplicated in all such forms and that any documentation, 8537afb73Sbostic * advertising materials, and other materials related to such 9537afb73Sbostic * distribution and use acknowledge that the software was developed 10537afb73Sbostic * by the University of California, Berkeley. The name of the 11537afb73Sbostic * University may not be used to endorse or promote products derived 12537afb73Sbostic * from this software without specific prior written permission. 13537afb73Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14537afb73Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15537afb73Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16006e9885Smarc * 17*2b86b1e4Stef * @(#)qd.c 1.11 (Berkeley) 02/07/89 18006e9885Smarc */ 19b2b69f49Smarc 207e911b15Skarels /************************************************************************ 217e911b15Skarels * * 22e977faadSmarc * Copyright (c) 1985-1988 by * 237e911b15Skarels * Digital Equipment Corporation, Maynard, MA * 247e911b15Skarels * All rights reserved. * 257e911b15Skarels * * 267e911b15Skarels * This software is furnished under a license and may be used and * 277e911b15Skarels * copied only in accordance with the terms of such license and * 287e911b15Skarels * with the inclusion of the above copyright notice. This * 297e911b15Skarels * software or any other copies thereof may not be provided or * 307e911b15Skarels * otherwise made available to any other person. No title to and * 317e911b15Skarels * ownership of the software is hereby transferred. * 327e911b15Skarels * * 337e911b15Skarels * The information in this software is subject to change without * 347e911b15Skarels * notice and should not be construed as a commitment by Digital * 357e911b15Skarels * Equipment Corporation. * 367e911b15Skarels * * 377e911b15Skarels * Digital assumes no responsibility for the use or reliability * 387e911b15Skarels * of its software on equipment which is not supplied by Digital. * 397e911b15Skarels * * 407e911b15Skarels *************************************************************************/ 41e977faadSmarc 427e911b15Skarels /* 43b2b69f49Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation 447e911b15Skarels */ 457e911b15Skarels 46b2b69f49Smarc #include "qd.h" 47e977faadSmarc 48006e9885Smarc #if NQD > 0 49e977faadSmarc #include "types.h" 50b2b69f49Smarc #include "../machine/pte.h" 51b2b69f49Smarc #include "../machine/mtpr.h" 52006e9885Smarc #include "../machine/cpu.h" 53b2b69f49Smarc #include "param.h" 54b2b69f49Smarc #include "conf.h" 55b2b69f49Smarc #include "dir.h" 56b2b69f49Smarc #include "user.h" 57b2b69f49Smarc #include "qdioctl.h" 58006e9885Smarc #include "tty.h" 59b2b69f49Smarc #include "map.h" 60b2b69f49Smarc #include "buf.h" 61b2b69f49Smarc #include "vm.h" 62b2b69f49Smarc #include "bk.h" 63b2b69f49Smarc #include "clist.h" 64b2b69f49Smarc #include "file.h" 65b2b69f49Smarc #include "uio.h" 66b2b69f49Smarc #include "kernel.h" 67e977faadSmarc #include "exec.h" 68e977faadSmarc #include "proc.h" 69b2b69f49Smarc #include "ubareg.h" 70b2b69f49Smarc #include "ubavar.h" 71e977faadSmarc #include "syslog.h" 72b2b69f49Smarc #include "qduser.h" /* definitions shared with user level client */ 73e977faadSmarc #include "qdreg.h" /* QDSS device register structures */ 7424f67f6bSmarc 75b2b69f49Smarc /* 76b2b69f49Smarc * QDSS driver status flags for tracking operational state 77b2b69f49Smarc */ 7824f67f6bSmarc struct qdflags { 7924f67f6bSmarc u_int inuse; /* which minor dev's are in use now */ 8024f67f6bSmarc u_int config; /* I/O page register content */ 8124f67f6bSmarc u_int mapped; /* user mapping status word */ 82e977faadSmarc u_int kernel_loop; /* if kernel console is redirected */ 8324f67f6bSmarc u_int user_dma; /* DMA from user space in progress */ 8424f67f6bSmarc u_short pntr_id; /* type code of pointing device */ 8524f67f6bSmarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 8624f67f6bSmarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 8724f67f6bSmarc u_short curs_acc; /* cursor acceleration factor */ 8824f67f6bSmarc u_short curs_thr; /* cursor acceleration threshold level */ 8924f67f6bSmarc u_short tab_res; /* tablet resolution factor */ 9024f67f6bSmarc u_short selmask; /* mask for active qd select entries */ 9124f67f6bSmarc }; 9224f67f6bSmarc 93b2b69f49Smarc /* 94b2b69f49Smarc * bit definitions for 'inuse' entry 95b2b69f49Smarc */ 9624f67f6bSmarc #define CONS_DEV 0x01 9724f67f6bSmarc #define GRAPHIC_DEV 0x04 9824f67f6bSmarc 99b2b69f49Smarc /* 100b2b69f49Smarc * bit definitions for 'mapped' member of flag structure 101b2b69f49Smarc */ 10224f67f6bSmarc #define MAPDEV 0x01 /* hardware is mapped */ 10324f67f6bSmarc #define MAPDMA 0x02 /* DMA buffer mapped */ 10424f67f6bSmarc #define MAPEQ 0x04 /* event queue buffer mapped */ 10524f67f6bSmarc #define MAPSCR 0x08 /* scroll param area mapped */ 10624f67f6bSmarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 10724f67f6bSmarc 108b2b69f49Smarc /* 109b2b69f49Smarc * bit definitions for 'selmask' member of qdflag structure 110b2b69f49Smarc */ 11124f67f6bSmarc #define SEL_READ 0x01 /* read select is active */ 11224f67f6bSmarc #define SEL_WRITE 0x02 /* write select is active */ 11324f67f6bSmarc 114b2b69f49Smarc /* 115b2b69f49Smarc * constants used in shared memory operations 116b2b69f49Smarc */ 11724f67f6bSmarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 11824f67f6bSmarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 11924f67f6bSmarc / sizeof(struct _vs_event) ) 1200d59d4d6Smarc #define DMA_BUFSIZ (1024 * 10) 12124f67f6bSmarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 12224f67f6bSmarc 123b2b69f49Smarc /* 12424f67f6bSmarc * reference to an array of "uba_device" structures built by the auto 12524f67f6bSmarc * configuration program. The uba_device structure decribes the device 12624f67f6bSmarc * sufficiently for the driver to talk to it. The auto configuration code 12724f67f6bSmarc * fills in the uba_device structures (located in ioconf.c) from user 128b2b69f49Smarc * maintained info. 129b2b69f49Smarc */ 13024f67f6bSmarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 13124f67f6bSmarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 1327881ece5Smarc extern char qvmem[][128*NBPG]; 133b2b69f49Smarc extern struct pte QVmap[][128]; 134b2b69f49Smarc #define CHUNK (64 * 1024) 135b2b69f49Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 13624f67f6bSmarc 137b2b69f49Smarc /* 138b2b69f49Smarc * static storage used by multiple functions in this code 139b2b69f49Smarc */ 14024f67f6bSmarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 14124f67f6bSmarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 14224f67f6bSmarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 14324f67f6bSmarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 14424f67f6bSmarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 145b2b69f49Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 14624f67f6bSmarc 147b2b69f49Smarc /* 148e977faadSmarc * the array "event_shared[]" is made up of a number of event queue buffers 14924f67f6bSmarc * equal to the number of QDSS's configured into the running kernel (NQD). 15024f67f6bSmarc * Each event queue buffer begins with an event queue header (struct qdinput) 15124f67f6bSmarc * followed by a group of event queue entries (struct _vs_event). The array 15224f67f6bSmarc * "*eq_header[]" is an array of pointers to the start of each event queue 153b2b69f49Smarc * buffer in "event_shared[]". 154b2b69f49Smarc */ 15524f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 15624f67f6bSmarc 15724f67f6bSmarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 15824f67f6bSmarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 15924f67f6bSmarc 160b2b69f49Smarc /* 16124f67f6bSmarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 16224f67f6bSmarc * buffers. Each buffer must consume an integral number of memory pages to 16324f67f6bSmarc * guarantee that a following buffer will begin on a page boundary. Also, 16424f67f6bSmarc * enough space is allocated so that the FIRST I/O buffer can start at the 16524f67f6bSmarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 166b2b69f49Smarc * memory protections can be turned on/off for individual buffers. 167b2b69f49Smarc */ 16824f67f6bSmarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 16924f67f6bSmarc 17024f67f6bSmarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 17124f67f6bSmarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 17224f67f6bSmarc 173b2b69f49Smarc /* 17424f67f6bSmarc * The driver assists a client in scroll operations by loading dragon 17524f67f6bSmarc * registers from an interrupt service routine. The loading is done using 17624f67f6bSmarc * parameters found in memory shrade between the driver and it's client. 17724f67f6bSmarc * The scroll parameter structures are ALL loacted in the same memory page 178b2b69f49Smarc * for reasons of memory economy. 179b2b69f49Smarc */ 18024f67f6bSmarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 18124f67f6bSmarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 18224f67f6bSmarc 183b2b69f49Smarc /* 18424f67f6bSmarc * the driver is programmable to provide the user with color map write 18524f67f6bSmarc * services at VSYNC interrupt time. At interrupt time the driver loads 186b2b69f49Smarc * the color map with any user-requested load data found in shared memory 187b2b69f49Smarc */ 18824f67f6bSmarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 18924f67f6bSmarc 190e977faadSmarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 19124f67f6bSmarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 19224f67f6bSmarc 193b2b69f49Smarc /* 194b2b69f49Smarc * mouse input event structures 195b2b69f49Smarc */ 19624f67f6bSmarc struct mouse_report last_rep[NQD]; 19724f67f6bSmarc struct mouse_report current_rep[NQD]; 19824f67f6bSmarc 1997881ece5Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 200b2b69f49Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 201b2b69f49Smarc int qdcount = 0; /* count of successfully probed qd's */ 20224f67f6bSmarc int nNQD = NQD; 20324f67f6bSmarc int DMAbuf_size = DMA_BUFSIZ; 204e977faadSmarc int QDlast_DMAtype; /* type of the last DMA operation */ 205e977faadSmarc 206b2b69f49Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 207b2b69f49Smarc /* 208b2b69f49Smarc * macro to get system time. Used to time stamp event queue entries 209b2b69f49Smarc */ 2107e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 2117e911b15Skarels 2127e911b15Skarels int qdprobe(); 2137e911b15Skarels int qdattach(); 2147e911b15Skarels int qddint(); /* DMA gate array intrpt service */ 2157e911b15Skarels int qdaint(); /* Dragon ADDER intrpt service */ 2167e911b15Skarels int qdiint(); 2177e911b15Skarels 2187e911b15Skarels u_short qdstd[] = { 0 }; 2197e911b15Skarels 220b2b69f49Smarc struct uba_driver qddriver = { 2217e911b15Skarels qdprobe, /* device probe entry */ 2227e911b15Skarels 0, /* no slave device */ 2237e911b15Skarels qdattach, /* device attach entry */ 2247e911b15Skarels 0, /* no "fill csr/ba to start" */ 2257e911b15Skarels qdstd, /* device addresses */ 2267e911b15Skarels "qd", /* device name string */ 2277e911b15Skarels qdinfo /* ptr to QDSS's uba_device struct */ 2287e911b15Skarels }; 2297e911b15Skarels 230e977faadSmarc #define QDPRIOR (PZERO-1) /* must be negative */ 2317e911b15Skarels #define FALSE 0 2327e911b15Skarels #define TRUE ~FALSE 2337e911b15Skarels #define BAD -1 2347e911b15Skarels #define GOOD 0 2357e911b15Skarels 236b2b69f49Smarc /* 237b2b69f49Smarc * macro to create a system virtual page number from system virtual adrs 238b2b69f49Smarc */ 239b2b69f49Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 2407e911b15Skarels 241b2b69f49Smarc /* 242b2b69f49Smarc * QDSS register address offsets from start of QDSS address space 243b2b69f49Smarc */ 2447e911b15Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 2457e911b15Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 2467e911b15Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 2477e911b15Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 2487e911b15Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 2497e911b15Skarels #define ADDER (REGSTART+0x000) 2507e911b15Skarels #define DGA (REGSTART+0x200) 2517e911b15Skarels #define DUART (REGSTART+0x400) 2527e911b15Skarels #define MEMCSR (REGSTART+0x800) 2537e911b15Skarels #define CLRSIZE (3 * 512) /* color map size */ 2547e911b15Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 2557e911b15Skarels /* 0x0C00 really */ 2567e911b15Skarels #define RED (CLRSTART+0x000) 2577e911b15Skarels #define BLUE (CLRSTART+0x200) 2587e911b15Skarels #define GREEN (CLRSTART+0x400) 2597e911b15Skarels 2607e911b15Skarels 261b2b69f49Smarc /* 2627e911b15Skarels * QDSS minor device numbers. The *real* minor device numbers are in 2637e911b15Skarels * the bottom two bits of the major/minor device spec. Bits 2 and up are 264b2b69f49Smarc * used to specify the QDSS device number (ie: which one?) 265b2b69f49Smarc */ 2667e911b15Skarels 2677e911b15Skarels #define CONS 0 2687e911b15Skarels #define GRAPHIC 2 2697e911b15Skarels 270b2b69f49Smarc /* 271b2b69f49Smarc * console cursor bitmap (white block cursor) 272b2b69f49Smarc */ 273b2b69f49Smarc short cons_cursor[32] = { 2747e911b15Skarels /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2757e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2767e911b15Skarels /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2777e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 2787e911b15Skarels }; 2797e911b15Skarels 280b2b69f49Smarc /* 281b2b69f49Smarc * constants used in font operations 282b2b69f49Smarc */ 283e977faadSmarc #define CHARS 190 /* # of chars in the font */ 2847e911b15Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 2857e911b15Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 2867e911b15Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 2877e911b15Skarels #define ROWS CHAR_HEIGHT 2887e911b15Skarels #define FONT_X 0 /* font's off screen adrs */ 2897e911b15Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 290e977faadSmarc 291b2b69f49Smarc /* Offset to second row characters (XXX - should remove) */ 292e977faadSmarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 2937e911b15Skarels 2947e911b15Skarels extern char q_font[]; /* reference font object code */ 295e977faadSmarc extern u_short q_key[]; /* reference key xlation tables */ 296e977faadSmarc extern u_short q_shift_key[]; 2977e911b15Skarels extern char *q_special[]; 2987e911b15Skarels 299b2b69f49Smarc /* 300b2b69f49Smarc * definitions for cursor acceleration reporting 301b2b69f49Smarc */ 3027e911b15Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 3037e911b15Skarels 304b2b69f49Smarc /* 305b2b69f49Smarc * virtual console support. 3067e911b15Skarels */ 307e977faadSmarc extern (*v_putc)(); 308e977faadSmarc extern struct cdevsw *consops; 309e977faadSmarc int qdputc(); 310e977faadSmarc int qdstart(); 311e977faadSmarc 312b2b69f49Smarc /* 313b2b69f49Smarc * LK-201 state storage for input console keyboard conversion to ASCII 314b2b69f49Smarc */ 3157e911b15Skarels struct q_keyboard { 3167e911b15Skarels int shift; /* state variables */ 3177e911b15Skarels int cntrl; 3187e911b15Skarels int lock; 3197e911b15Skarels int lastcode; /* last keycode typed */ 3207e911b15Skarels unsigned kup[8]; /* bits for each keycode*/ 3217e911b15Skarels unsigned dkeys[8]; /* down/up mode keys */ 3227e911b15Skarels char last; /* last character */ 3237e911b15Skarels } q_keyboard; 3247e911b15Skarels 325b2b69f49Smarc /* 326b2b69f49Smarc * tty settings on first open 327b2b69f49Smarc */ 328e977faadSmarc #define IFLAGS (EVENP|ECHO|XTABS|CRMOD) 329e977faadSmarc #ifdef POSIXTTY 330e977faadSmarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL) 331e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR) 332e977faadSmarc #define LFLAG (ISIG|ICANON|ECHO) 333e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 334e977faadSmarc #endif 335e977faadSmarc 3367881ece5Smarc /* 3377881ece5Smarc * Init QDSS as console (before probe routine) 3387881ece5Smarc */ 3397e911b15Skarels 3407e911b15Skarels qdcons_init() 3417e911b15Skarels { 3427881ece5Smarc register unit; 3437e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 344e977faadSmarc u_int mapix; /* index into QVmap[] array */ 345e977faadSmarc struct percpu *pcpu; /* pointer to cpusw structure */ 346e977faadSmarc register struct qbus *qb; 3477e911b15Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 3487e911b15Skarels u_short *devptr; /* vitual device space */ 349e977faadSmarc extern cnputc(); 3507e911b15Skarels 3517e911b15Skarels #define QDSSCSR 0x1F00 3527e911b15Skarels 35324f67f6bSmarc if (v_putc != cnputc) 3547881ece5Smarc return 0; 35524f67f6bSmarc 3567e911b15Skarels unit = 0; 3577e911b15Skarels 358b2b69f49Smarc /* 359b2b69f49Smarc * find the cpusw entry that matches this machine. 360b2b69f49Smarc */ 36124f67f6bSmarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 3627e911b15Skarels ; 36324f67f6bSmarc if (pcpu == NULL) 3647881ece5Smarc return 0; 365*2b86b1e4Stef if (pcpu->pc_io->io_type != IO_QBUS) 366*2b86b1e4Stef return 0; 36724f67f6bSmarc 36824f67f6bSmarc /* 369e977faadSmarc * Map device registers - the last 8K of qvmem. 37024f67f6bSmarc */ 37124f67f6bSmarc qb = (struct qbus *)pcpu->pc_io->io_details; 37224f67f6bSmarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 37324f67f6bSmarc UBAIOPAGES * NBPG); 37424f67f6bSmarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 37524f67f6bSmarc qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 3767881ece5Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 3777881ece5Smarc return 0; 378e977faadSmarc 37924f67f6bSmarc /* 38024f67f6bSmarc * Map q-bus memory used by qdss. (separate map) 38124f67f6bSmarc */ 38224f67f6bSmarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 38324f67f6bSmarc phys_adr = qb->qb_maddr + mapix; 38424f67f6bSmarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 3857e911b15Skarels 38624f67f6bSmarc /* 38724f67f6bSmarc * tell QDSS which Q memory address base to decode 388b2b69f49Smarc * (shifted right 16 bits - its in 64K units) 38924f67f6bSmarc */ 39024f67f6bSmarc *qdaddr = (u_short)((int)mapix >> 16); 3917e911b15Skarels qdflags[unit].config = *(u_short *)qdaddr; 3927e911b15Skarels 393b2b69f49Smarc /* 394b2b69f49Smarc * load qdmap struct with the virtual addresses of the QDSS elements 395b2b69f49Smarc */ 396e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0]); 3977e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 3987e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 3997e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA; 4007e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART; 4017e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 4027e911b15Skarels qdmap[unit].red = qdbase[unit] + RED; 4037e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 4047e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN; 4057e911b15Skarels 4067e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 4077e911b15Skarels 408b2b69f49Smarc /* 409b2b69f49Smarc * init the QDSS 410b2b69f49Smarc */ 411b2b69f49Smarc /* 41224f67f6bSmarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 41324f67f6bSmarc (char *)qdbase[0], qdmap[0].memcsr); 414b2b69f49Smarc */ 4157e911b15Skarels 4167e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 4177e911b15Skarels 4187e911b15Skarels cursor[unit].x = 0; 4197e911b15Skarels cursor[unit].y = 0; 4207e911b15Skarels init_shared(unit); /* init shared memory */ 4217e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 4227e911b15Skarels clear_qd_screen(unit); /* clear the screen */ 4237e911b15Skarels ldfont(unit); /* load the console font */ 4247e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 4257e911b15Skarels setup_input(unit); /* init the DUART */ 426b2b69f49Smarc v_putc = qdputc; /* kernel console output to qdss */ 427b2b69f49Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 4287881ece5Smarc return 1; 4297e911b15Skarels 4307e911b15Skarels } /* qdcons_init */ 4317e911b15Skarels 4327881ece5Smarc /* 4337881ece5Smarc * Configure QDSS into Q memory and make it intrpt. 4347e911b15Skarels * 4357e911b15Skarels * side effects: QDSS gets mapped into Qbus memory space at the first 4367e911b15Skarels * vacant 64kb boundary counting back from the top of 437e977faadSmarc * Qbus memory space (qvmem+4mb) 4387e911b15Skarels * 4397e911b15Skarels * return: QDSS bus request level and vector address returned in 4407e911b15Skarels * registers by UNIX convention. 4417e911b15Skarels * 4427881ece5Smarc */ 4437e911b15Skarels qdprobe(reg) 4447881ece5Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 4457e911b15Skarels { 44624f67f6bSmarc register int br, cvec; /* value-result */ 4477e911b15Skarels register int unit; 4487e911b15Skarels struct dga *dga; /* pointer to gate array structure */ 4497e911b15Skarels int vector; 4507881ece5Smarc #ifdef notdef 4517881ece5Smarc int *ptep; /* page table entry pointer */ 4527e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 4537e911b15Skarels u_int mapix; 4547881ece5Smarc #endif 4557881ece5Smarc 4567881ece5Smarc #ifdef lint 4577881ece5Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 4587881ece5Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 4597881ece5Smarc #endif 4607e911b15Skarels 461b2b69f49Smarc /* 462b2b69f49Smarc * calculate board unit number from I/O page register address 463b2b69f49Smarc */ 4647e911b15Skarels unit = (int) (((int)reg >> 1) & 0x0007); 4657e911b15Skarels 466b2b69f49Smarc /* 467b2b69f49Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 468b2b69f49Smarc * physical boundary. The Qbus memory space is mapped into 469b2b69f49Smarc * the system memory space at config time. After config 470b2b69f49Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 471b2b69f49Smarc * of the start of Qbus memory. The Qbus memory page table 472b2b69f49Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 473b2b69f49Smarc * which is also loaded at config time. These are the 474b2b69f49Smarc * variables used below to find a vacant 64kb boundary in 475b2b69f49Smarc * Qbus memory, and load it's corresponding physical adrs 476b2b69f49Smarc * into the QDSS's I/O page CSR. 477b2b69f49Smarc */ 478e977faadSmarc 479e977faadSmarc /* 480e977faadSmarc * Only if QD is the graphics device. 48124f67f6bSmarc */ 4827e911b15Skarels 4837e911b15Skarels /* if this QDSS is NOT the console, then do init here.. */ 4847e911b15Skarels 485e977faadSmarc if (unit != 0) { 486e977faadSmarc printf("qd: can't support two qdss's (yet)\n"); 4877881ece5Smarc #ifdef notdef /* can't test */ 4887e911b15Skarels if (v_consputc != qdputc || unit != 0) { 4897e911b15Skarels 490b2b69f49Smarc /* 491b2b69f49Smarc * read QDSS config info 492b2b69f49Smarc */ 4937e911b15Skarels qdflags[unit].config = *(u_short *)reg; 4947e911b15Skarels 495b2b69f49Smarc /* 496b2b69f49Smarc * find an empty 64kb adrs boundary 497b2b69f49Smarc */ 4987e911b15Skarels 499e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 500e977faadSmarc 501b2b69f49Smarc /* 5027881ece5Smarc * find the cpusw entry that matches this machine. 5037881ece5Smarc */ 5047e911b15Skarels cpup = &cpusw[cpu]; 5057e911b15Skarels while (!(BADADDR(qdbase[unit], sizeof(short)))) 5067e911b15Skarels qdbase[unit] -= CHUNK; 5077e911b15Skarels 508b2b69f49Smarc /* 5097881ece5Smarc * tell QDSS which Q memory address base to decode 5107881ece5Smarc */ 511e977faadSmarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 512e977faadSmarc ptep = (int *) QVmap[0] + mapix; 5137e911b15Skarels phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 5147e911b15Skarels *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 5157e911b15Skarels 516b2b69f49Smarc /* 517b2b69f49Smarc * load QDSS adrs map with system addresses 518b2b69f49Smarc * of device regs 519b2b69f49Smarc */ 5207e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 5217e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 5227e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA; 5237e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART; 5247e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 5257e911b15Skarels qdmap[unit].red = qdbase[unit] + RED; 5267e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 5277e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN; 5287e911b15Skarels 5297e911b15Skarels /* device init */ 5307e911b15Skarels 5317e911b15Skarels cursor[unit].x = 0; 5327e911b15Skarels cursor[unit].y = 0; 5337e911b15Skarels init_shared(unit); /* init shared memory */ 5347e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 5357e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 5367e911b15Skarels setup_input(unit); /* init the DUART */ 5377e911b15Skarels clear_qd_screen(unit); 5387e911b15Skarels ldfont(unit); /* load the console font */ 5397e911b15Skarels 5407e911b15Skarels /* once only: turn on sync */ 5417e911b15Skarels 5427e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; 543b2b69f49Smarc } 544006e9885Smarc #endif /*notdef*/ 545e977faadSmarc } 5467e911b15Skarels 547b2b69f49Smarc /* 548b2b69f49Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 549b2b69f49Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 550b2b69f49Smarc * vectors from the vector pool, and then continue 551b2b69f49Smarc * to take them until we get a xx0 HEX vector. The 552b2b69f49Smarc * pool provides vectors in contiguous decending 553b2b69f49Smarc * order. 554b2b69f49Smarc */ 5557e911b15Skarels 5567e911b15Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 5577e911b15Skarels 5587e911b15Skarels while (vector & 0x0F) { /* if lo nibble != 0.. */ 559b2b69f49Smarc /* ..take another vector */ 560b2b69f49Smarc vector = (uba_hd[0].uh_lastiv -= 4); 5617e911b15Skarels } 5627e911b15Skarels 563b2b69f49Smarc /* 564b2b69f49Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 565b2b69f49Smarc */ 5667e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 5677e911b15Skarels dga->csr = (short) HALT; /* disable everything */ 5687e911b15Skarels dga->ivr = (short) vector; /* load intrpt base vector */ 5697e911b15Skarels dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 5707e911b15Skarels dga->bytcnt_hi = (short) 0; 5717e911b15Skarels 572b2b69f49Smarc /* 573b2b69f49Smarc * turn on DMA interrupts 574b2b69f49Smarc */ 5757e911b15Skarels dga->csr &= ~SET_DONE_FIFO; 5767e911b15Skarels dga->csr |= DMA_IE | DL_ENB; 5777e911b15Skarels 5787e911b15Skarels DELAY(20000); /* wait for the intrpt */ 5797e911b15Skarels dga->csr = HALT; /* stop the wheels */ 5807e911b15Skarels 5817e911b15Skarels if (cvec != vector) /* if vector != base vector.. */ 5827e911b15Skarels return(0); /* ..return = 'no device' */ 5837e911b15Skarels 584e977faadSmarc /* 585e977faadSmarc * score this as an existing qdss 586e977faadSmarc */ 587e977faadSmarc qdcount++; 588e977faadSmarc 5897e911b15Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 5907e911b15Skarels 5917e911b15Skarels } /* qdprobe */ 5927e911b15Skarels 5937e911b15Skarels qdattach(ui) 5947e911b15Skarels struct uba_device *ui; 5957e911b15Skarels { 5967881ece5Smarc register unit; /* QDSS module # for this call */ 5977e911b15Skarels 5987e911b15Skarels unit = ui->ui_unit; /* get QDSS number */ 5997e911b15Skarels 600b2b69f49Smarc /* 601b2b69f49Smarc * init "qdflags[]" for this QDSS 602b2b69f49Smarc */ 6037e911b15Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 6047e911b15Skarels qdflags[unit].mapped = 0; 605e977faadSmarc qdflags[unit].kernel_loop = -1; 6067e911b15Skarels qdflags[unit].user_dma = 0; 6077e911b15Skarels qdflags[unit].curs_acc = ACC_OFF; 6087e911b15Skarels qdflags[unit].curs_thr = 128; 6097e911b15Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 6107e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 6117e911b15Skarels qdflags[unit].adder_ie = 0; 6127e911b15Skarels 613b2b69f49Smarc /* 6147e911b15Skarels * init structures used in kbd/mouse interrupt service. This code must 615b2b69f49Smarc * come after the "init_shared()" routine has run since that routine 616b2b69f49Smarc * inits the eq_header[unit] structure used here. 617b2b69f49Smarc */ 6187e911b15Skarels 619b2b69f49Smarc /* 620b2b69f49Smarc * init the "latest mouse report" structure 621b2b69f49Smarc */ 6227e911b15Skarels last_rep[unit].state = 0; 6237e911b15Skarels last_rep[unit].dx = 0; 6247e911b15Skarels last_rep[unit].dy = 0; 6257e911b15Skarels last_rep[unit].bytcnt = 0; 6267e911b15Skarels 627b2b69f49Smarc /* 6287881ece5Smarc * init the event queue (except mouse position) 6297881ece5Smarc */ 6307881ece5Smarc eq_header[unit]->header.events = 6317881ece5Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 6327e911b15Skarels 6337e911b15Skarels eq_header[unit]->header.size = MAXEVENTS; 6347e911b15Skarels eq_header[unit]->header.head = 0; 6357e911b15Skarels eq_header[unit]->header.tail = 0; 6367e911b15Skarels 637b2b69f49Smarc /* 638b2b69f49Smarc * open exclusive for graphics device. 639b2b69f49Smarc */ 640b2b69f49Smarc qdopened[unit] = 0; 6417e911b15Skarels 6427e911b15Skarels } /* qdattach */ 6437e911b15Skarels 6447881ece5Smarc /*ARGSUSED*/ 6457e911b15Skarels qdopen(dev, flag) 6467e911b15Skarels dev_t dev; 6477e911b15Skarels int flag; 6487e911b15Skarels { 6497e911b15Skarels register struct uba_device *ui; /* ptr to uba structures */ 6507e911b15Skarels register struct dga *dga; /* ptr to gate array struct */ 6517e911b15Skarels register struct tty *tp; 6527e911b15Skarels struct duart *duart; 6537881ece5Smarc int unit; 6547881ece5Smarc int minor_dev; 6557e911b15Skarels 6567e911b15Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 6577e911b15Skarels unit = minor_dev >> 2; 6587e911b15Skarels 659b2b69f49Smarc /* 660b2b69f49Smarc * check for illegal conditions 661b2b69f49Smarc */ 6627e911b15Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 6637e911b15Skarels if (ui == 0 || ui->ui_alive == 0) 6647e911b15Skarels return(ENXIO); /* no such device or address */ 6657e911b15Skarels 6667e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 6677e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 6687e911b15Skarels 6697e911b15Skarels if ((minor_dev & 0x03) == 2) { 670b2b69f49Smarc /* 671b2b69f49Smarc * this is the graphic device... 672b2b69f49Smarc */ 673b2b69f49Smarc if (qdopened[unit] != 0) 6747e911b15Skarels return(EBUSY); 6757e911b15Skarels else 676b2b69f49Smarc qdopened[unit] = 1; 6777e911b15Skarels qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 678b2b69f49Smarc /* 679b2b69f49Smarc * enble kbd & mouse intrpts in DUART mask reg 680b2b69f49Smarc */ 6817e911b15Skarels qdflags[unit].duart_imask |= 0x22; 6827e911b15Skarels duart->imask = qdflags[unit].duart_imask; 683b2b69f49Smarc } else { 684b2b69f49Smarc /* 685b2b69f49Smarc * this is the console 686b2b69f49Smarc */ 6877e911b15Skarels qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 6887e911b15Skarels dga->csr |= CURS_ENB; 6897e911b15Skarels qdflags[unit].duart_imask |= 0x02; 6907e911b15Skarels duart->imask = qdflags[unit].duart_imask; 691b2b69f49Smarc /* 692b2b69f49Smarc * some setup for tty handling 693b2b69f49Smarc */ 6947e911b15Skarels tp = &qd_tty[minor_dev]; 6957e911b15Skarels tp->t_addr = ui->ui_addr; 6967e911b15Skarels tp->t_oproc = qdstart; 6977e911b15Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 6987e911b15Skarels ttychars(tp); 699e977faadSmarc tp->t_flags = IFLAGS; 7007e911b15Skarels tp->t_ispeed = B9600; 7017e911b15Skarels tp->t_ospeed = B9600; 702e977faadSmarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 703b2b69f49Smarc #ifdef POSIXTTY 704b2b69f49Smarc tp->t_iflag = TTYDEF_IFLAG; 705b2b69f49Smarc tp->t_oflag = TTYDEF_OFLAG; 706b2b69f49Smarc tp->t_lflag = TTYDEF_LFLAG; 707b2b69f49Smarc tp->t_cflag = TTYDEF_CFLAG; 708b2b69f49Smarc #endif 709e977faadSmarc } 710b2b69f49Smarc /* 711b2b69f49Smarc * enable intrpts, open line discipline 712b2b69f49Smarc */ 7137e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 7147e911b15Skarels return ((*linesw[tp->t_line].l_open)(dev, tp)); 7157e911b15Skarels } 7167e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 7177e911b15Skarels return(0); 7187e911b15Skarels 7197e911b15Skarels } /* qdopen */ 7207e911b15Skarels 7217881ece5Smarc /*ARGSUSED*/ 7227e911b15Skarels qdclose(dev, flag) 7237e911b15Skarels dev_t dev; 7247e911b15Skarels int flag; 7257e911b15Skarels { 7267e911b15Skarels register struct tty *tp; 7277e911b15Skarels register struct qdmap *qd; 7287e911b15Skarels register int *ptep; 7297e911b15Skarels struct dga *dga; /* gate array register map pointer */ 7307e911b15Skarels struct duart *duart; 7317e911b15Skarels struct adder *adder; 7327881ece5Smarc int unit; 7337881ece5Smarc int minor_dev; 7347e911b15Skarels u_int mapix; 735b2b69f49Smarc int i; /* SIGNED index */ 7367e911b15Skarels 7377e911b15Skarels minor_dev = minor(dev); /* get minor device number */ 7387e911b15Skarels unit = minor_dev >> 2; /* get QDSS number */ 7397e911b15Skarels qd = &qdmap[unit]; 7407e911b15Skarels 7417e911b15Skarels if ((minor_dev & 0x03) == 2) { 742b2b69f49Smarc /* 743b2b69f49Smarc * this is the graphic device... 744b2b69f49Smarc */ 745b2b69f49Smarc if (qdopened[unit] != 1) 7467e911b15Skarels return(EBUSY); 7477e911b15Skarels else 748b2b69f49Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 749b2b69f49Smarc /* 750b2b69f49Smarc * re-protect device memory 751b2b69f49Smarc */ 7527e911b15Skarels if (qdflags[unit].mapped & MAPDEV) { 753b2b69f49Smarc /* 754b2b69f49Smarc * TEMPLATE RAM 755b2b69f49Smarc */ 75624f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 75724f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7587881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 7597881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 760b2b69f49Smarc /* 761b2b69f49Smarc * ADDER 762b2b69f49Smarc */ 76324f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 76424f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7657881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 7667881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 767b2b69f49Smarc /* 768b2b69f49Smarc * COLOR MAPS 769b2b69f49Smarc */ 77024f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 77124f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7727881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 7737881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 7747e911b15Skarels } 7757e911b15Skarels 776b2b69f49Smarc /* 777b2b69f49Smarc * re-protect DMA buffer and free the map registers 778b2b69f49Smarc */ 7797e911b15Skarels if (qdflags[unit].mapped & MAPDMA) { 7807e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 7817e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 7827e911b15Skarels dga->csr &= ~DMA_IE; 7837e911b15Skarels dga->csr &= ~0x0600; /* kill DMA */ 7847e911b15Skarels adder->command = CANCEL; 785b2b69f49Smarc /* 786b2b69f49Smarc * if DMA was running, flush spurious intrpt 787b2b69f49Smarc */ 7887e911b15Skarels if (dga->bytcnt_lo != 0) { 7897e911b15Skarels dga->bytcnt_lo = 0; 7907e911b15Skarels dga->bytcnt_hi = 0; 7917e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 7927e911b15Skarels dga->csr |= DMA_IE; 7937e911b15Skarels dga->csr &= ~DMA_IE; 7947e911b15Skarels } 7957e911b15Skarels ptep = (int *) 7967e911b15Skarels ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 7977881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 7987881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 7997e911b15Skarels ubarelse(0, &Qbus_unmap[unit]); 8007e911b15Skarels } 8017e911b15Skarels 802b2b69f49Smarc /* 803b2b69f49Smarc * re-protect 1K (2 pages) event queue 804b2b69f49Smarc */ 8057e911b15Skarels if (qdflags[unit].mapped & MAPEQ) { 8067e911b15Skarels ptep = (int *) 8077e911b15Skarels ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 8087881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 8097e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8107e911b15Skarels } 811b2b69f49Smarc /* 812b2b69f49Smarc * re-protect scroll param area and disable scroll intrpts 813b2b69f49Smarc */ 8147e911b15Skarels if (qdflags[unit].mapped & MAPSCR) { 8157e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 8167e911b15Skarels + (mfpr(SBR) | 0x80000000)); 817b2b69f49Smarc /* 818b2b69f49Smarc * re-protect 512 scroll param area 819b2b69f49Smarc */ 8207e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8217e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8227e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC; 8237e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 8247e911b15Skarels } 825b2b69f49Smarc /* 826b2b69f49Smarc * re-protect color map write buffer area and kill intrpts 827b2b69f49Smarc */ 8287e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) { 8297e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 8307e911b15Skarels + (mfpr(SBR) | 0x80000000)); 8317881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 8327e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8337e911b15Skarels color_buf[unit]->status = 0; 8347e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8357e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC; 8367e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 8377e911b15Skarels } 838b2b69f49Smarc mtpr(TBIA, 0); 839b2b69f49Smarc /* flag everything now unmapped */ 840b2b69f49Smarc qdflags[unit].mapped = 0; 8417e911b15Skarels qdflags[unit].inuse &= ~GRAPHIC_DEV; 8427e911b15Skarels qdflags[unit].curs_acc = ACC_OFF; 8437e911b15Skarels qdflags[unit].curs_thr = 128; 844b2b69f49Smarc /* 845b2b69f49Smarc * restore the console 846b2b69f49Smarc */ 8477e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8487e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8497e911b15Skarels dga->csr &= ~DMA_IE; 8507e911b15Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 8517e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 8527e911b15Skarels adder->command = CANCEL; 853b2b69f49Smarc /* 854b2b69f49Smarc * if DMA was running, flush spurious intrpt 855b2b69f49Smarc */ 8567e911b15Skarels if (dga->bytcnt_lo != 0) { 8577e911b15Skarels dga->bytcnt_lo = 0; 8587e911b15Skarels dga->bytcnt_hi = 0; 8597e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 8607e911b15Skarels dga->csr |= DMA_IE; 8617e911b15Skarels dga->csr &= ~DMA_IE; 8627e911b15Skarels } 8637e911b15Skarels init_shared(unit); /* init shared memory */ 8647e911b15Skarels setup_dragon(unit); /* init ADDER/VIPER */ 8657e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 8667e911b15Skarels setup_input(unit); /* init the DUART */ 8677e911b15Skarels ldfont(unit); 8687e911b15Skarels cursor[unit].x = 0; 8697e911b15Skarels cursor[unit].y = 0; 870b2b69f49Smarc /* 871b2b69f49Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 872b2b69f49Smarc */ 8737e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 8747e911b15Skarels qdflags[unit].duart_imask &= ~(0x20); 8757e911b15Skarels qdflags[unit].duart_imask |= 0x02; 8767e911b15Skarels duart->imask = qdflags[unit].duart_imask; 877b2b69f49Smarc /* 878b2b69f49Smarc * shut off interrupts if all is closed 879b2b69f49Smarc */ 880b2b69f49Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 8817e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8827e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE); 8837e911b15Skarels } 884b2b69f49Smarc } else { 885b2b69f49Smarc /* 886b2b69f49Smarc * this is the console 887b2b69f49Smarc */ 8887e911b15Skarels tp = &qd_tty[minor_dev]; 8897e911b15Skarels (*linesw[tp->t_line].l_close)(tp); 8907e911b15Skarels ttyclose(tp); 8917e911b15Skarels tp->t_state = 0; 8927e911b15Skarels qdflags[unit].inuse &= ~CONS_DEV; 893b2b69f49Smarc /* 894b2b69f49Smarc * if graphics device is closed, kill interrupts 895b2b69f49Smarc */ 8967e911b15Skarels if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 8977e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8987e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE); 8997e911b15Skarels } 9007e911b15Skarels } 9017e911b15Skarels 9027e911b15Skarels return(0); 9037e911b15Skarels 9047e911b15Skarels } /* qdclose */ 9057e911b15Skarels 9067e911b15Skarels qdioctl(dev, cmd, datap, flags) 9077e911b15Skarels dev_t dev; 9087e911b15Skarels int cmd; 9097881ece5Smarc register caddr_t datap; 9107e911b15Skarels int flags; 9117e911b15Skarels { 9127e911b15Skarels register int *ptep; /* page table entry pointer */ 91324f67f6bSmarc register int mapix; /* QVmap[] page table index */ 9147e911b15Skarels register struct _vs_event *event; 9157e911b15Skarels register struct tty *tp; 9167881ece5Smarc register i; 9177e911b15Skarels struct qdmap *qd; /* pointer to device map struct */ 9187e911b15Skarels struct dga *dga; /* Gate Array reg structure pntr */ 9197e911b15Skarels struct duart *duart; /* DUART reg structure pointer */ 9207e911b15Skarels struct adder *adder; /* ADDER reg structure pointer */ 9217e911b15Skarels struct prgkbd *cmdbuf; 9227e911b15Skarels struct prg_cursor *curs; 9237e911b15Skarels struct _vs_cursor *pos; 9247881ece5Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 9257e911b15Skarels u_int minor_dev = minor(dev); 9267e911b15Skarels int error; 9277e911b15Skarels int s; 9287e911b15Skarels short *temp; /* a pointer to template RAM */ 9297e911b15Skarels 930b2b69f49Smarc /* 931b2b69f49Smarc * service graphic device ioctl commands 932b2b69f49Smarc */ 9337e911b15Skarels switch (cmd) { 934e977faadSmarc 9357e911b15Skarels case QD_GETEVENT: 936b2b69f49Smarc /* 937b2b69f49Smarc * extract the oldest event from the event queue 938b2b69f49Smarc */ 9397e911b15Skarels if (ISEMPTY(eq_header[unit])) { 9407e911b15Skarels event = (struct _vs_event *) datap; 9417e911b15Skarels event->vse_device = VSE_NULL; 9427e911b15Skarels break; 9437e911b15Skarels } 9447e911b15Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 945e977faadSmarc s = spl5(); 9467e911b15Skarels GETEND(eq_header[unit]); 9477e911b15Skarels splx(s); 9487881ece5Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 9497e911b15Skarels break; 9507e911b15Skarels 9517e911b15Skarels case QD_RESET: 952b2b69f49Smarc /* 953b2b69f49Smarc * init the dragon stuff, DUART, and driver variables 954b2b69f49Smarc */ 9557e911b15Skarels init_shared(unit); /* init shared memory */ 9567e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 9577e911b15Skarels clear_qd_screen(unit); 9587e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 9597e911b15Skarels ldfont(unit); /* load the console font */ 9607e911b15Skarels setup_input(unit); /* init the DUART */ 9617e911b15Skarels break; 9627e911b15Skarels 9637e911b15Skarels case QD_SET: 964b2b69f49Smarc /* 965b2b69f49Smarc * init the DUART and driver variables 966b2b69f49Smarc */ 9677e911b15Skarels init_shared(unit); 9687e911b15Skarels setup_input(unit); 9697e911b15Skarels break; 9707e911b15Skarels 9717e911b15Skarels case QD_CLRSCRN: 972b2b69f49Smarc /* 973b2b69f49Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 974b2b69f49Smarc */ 9757881ece5Smarc #ifdef notdef /* has caused problems and isn't necessary */ 9767e911b15Skarels setup_dragon(unit); 9777e911b15Skarels clear_qd_screen(unit); 978e977faadSmarc #endif 9797e911b15Skarels break; 9807e911b15Skarels 9817e911b15Skarels case QD_WTCURSOR: 982b2b69f49Smarc /* 983b2b69f49Smarc * load a cursor into template RAM 984b2b69f49Smarc */ 9857881ece5Smarc ldcursor(unit, (short *)datap); 9867e911b15Skarels break; 9877e911b15Skarels 9887e911b15Skarels case QD_RDCURSOR: 9897e911b15Skarels 9907e911b15Skarels temp = (short *) qdmap[unit].template; 991b2b69f49Smarc /* 992b2b69f49Smarc * cursor is 32 WORDS from the end of the 8k WORD... 993b2b69f49Smarc * ...template space 994b2b69f49Smarc */ 9957e911b15Skarels temp += (8 * 1024) - 32; 9967e911b15Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 9977e911b15Skarels *(short *)datap = *temp++; 9987e911b15Skarels break; 9997e911b15Skarels 10007e911b15Skarels case QD_POSCURSOR: 1001b2b69f49Smarc /* 1002b2b69f49Smarc * position the mouse cursor 1003b2b69f49Smarc */ 10047e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 10057e911b15Skarels pos = (struct _vs_cursor *) datap; 1006e977faadSmarc s = spl5(); 10077e911b15Skarels dga->x_cursor = TRANX(pos->x); 10087e911b15Skarels dga->y_cursor = TRANY(pos->y); 10097e911b15Skarels eq_header[unit]->curs_pos.x = pos->x; 10107e911b15Skarels eq_header[unit]->curs_pos.y = pos->y; 10117e911b15Skarels splx(s); 10127e911b15Skarels break; 10137e911b15Skarels 10147e911b15Skarels case QD_PRGCURSOR: 1015b2b69f49Smarc /* 1016b2b69f49Smarc * set the cursor acceleration factor 1017b2b69f49Smarc */ 10187e911b15Skarels curs = (struct prg_cursor *) datap; 1019e977faadSmarc s = spl5(); 10207e911b15Skarels qdflags[unit].curs_acc = curs->acc_factor; 10217e911b15Skarels qdflags[unit].curs_thr = curs->threshold; 10227e911b15Skarels splx(s); 10237e911b15Skarels break; 10247e911b15Skarels 10257e911b15Skarels case QD_MAPDEVICE: 1026b2b69f49Smarc /* 1027b2b69f49Smarc * enable 'user write' to device pages 1028b2b69f49Smarc */ 10297e911b15Skarels qdflags[unit].mapped |= MAPDEV; 10307e911b15Skarels qd = (struct qdmap *) &qdmap[unit]; 1031b2b69f49Smarc /* 1032b2b69f49Smarc * enable user write to template RAM 1033b2b69f49Smarc */ 103424f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 103524f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10367881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 10377881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1038b2b69f49Smarc /* 1039b2b69f49Smarc * enable user write to registers 1040b2b69f49Smarc */ 104124f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 104224f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10437881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 10447881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1045b2b69f49Smarc /* 1046b2b69f49Smarc * enable user write to color maps 1047b2b69f49Smarc */ 104824f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 104924f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10507881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 10517881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1052b2b69f49Smarc /* 1053b2b69f49Smarc * enable user write to DUART 1054b2b69f49Smarc */ 105524f67f6bSmarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 105624f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10577e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 10587e911b15Skarels 10597881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 10607e911b15Skarels 1061b2b69f49Smarc /* 1062b2b69f49Smarc * stuff qdmap structure in return buffer 1063b2b69f49Smarc */ 10647881ece5Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 10657e911b15Skarels break; 10667e911b15Skarels 10677e911b15Skarels case QD_MAPIOBUF: 1068b2b69f49Smarc /* 1069b2b69f49Smarc * do setup for DMA by user process 1070b2b69f49Smarc * 1071b2b69f49Smarc * set 'user write enable' bits for DMA buffer 1072b2b69f49Smarc */ 10737e911b15Skarels qdflags[unit].mapped |= MAPDMA; 10747e911b15Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 10757e911b15Skarels + (mfpr(SBR) | 0x80000000)); 10767881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 10777881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 10787881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 1079b2b69f49Smarc /* 1080b2b69f49Smarc * set up QBUS map registers for DMA 1081b2b69f49Smarc */ 10827e911b15Skarels DMAheader[unit]->QBAreg = 10837881ece5Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 10847e911b15Skarels if (DMAheader[unit]->QBAreg == 0) 10857881ece5Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 10867e911b15Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 10877e911b15Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 1088b2b69f49Smarc /* 1089b2b69f49Smarc * return I/O buf adr 1090b2b69f49Smarc */ 10917e911b15Skarels *(int *)datap = (int) DMAheader[unit]; 10927e911b15Skarels break; 10937e911b15Skarels 10947e911b15Skarels case QD_MAPSCROLL: 1095b2b69f49Smarc /* 1096b2b69f49Smarc * map the shared scroll param area and enable scroll interpts 1097b2b69f49Smarc */ 10987e911b15Skarels qdflags[unit].mapped |= MAPSCR; 10997e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 11007e911b15Skarels + (mfpr(SBR) | 0x80000000)); 1101b2b69f49Smarc /* 1102b2b69f49Smarc * allow user write to scroll area 1103b2b69f49Smarc */ 11047e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11057881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 11067e911b15Skarels scroll[unit]->status = 0; 11077e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11087e911b15Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 11097e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 1110b2b69f49Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 11117e911b15Skarels break; 11127e911b15Skarels 11137e911b15Skarels case QD_UNMAPSCROLL: 1114b2b69f49Smarc /* 1115b2b69f49Smarc * unmap shared scroll param area and disable scroll intrpts 1116b2b69f49Smarc */ 11177e911b15Skarels if (qdflags[unit].mapped & MAPSCR) { 11187e911b15Skarels qdflags[unit].mapped &= ~MAPSCR; 11197e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 11207e911b15Skarels + (mfpr(SBR) | 0x80000000)); 1121b2b69f49Smarc /* 1122b2b69f49Smarc * re-protect 512 scroll param area 1123b2b69f49Smarc */ 11247e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 11257e911b15Skarels mtpr(TBIA, 0); /* smash CPU's translation buf */ 11267e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11277e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC; 11287e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11297e911b15Skarels } 11307e911b15Skarels break; 11317e911b15Skarels 11327e911b15Skarels case QD_MAPCOLOR: 1133b2b69f49Smarc /* 1134b2b69f49Smarc * map shared color map write buf and turn on vsync intrpt 1135b2b69f49Smarc */ 11367e911b15Skarels qdflags[unit].mapped |= MAPCOLOR; 11377e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 11387e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11397881ece5Smarc /* 11407881ece5Smarc * allow user write to color map write buffer 11417881ece5Smarc */ 11427881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 11437e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11447e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 1145b2b69f49Smarc adder = (struct adder *) qdmap[unit].adder; 11467e911b15Skarels qdflags[unit].adder_ie |= VSYNC; 11477e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11487881ece5Smarc /* 11497881ece5Smarc * return color area address 11507881ece5Smarc */ 11517e911b15Skarels *(int *)datap = (int) color_buf[unit]; 11527e911b15Skarels break; 11537e911b15Skarels 11547e911b15Skarels case QD_UNMAPCOLOR: 1155b2b69f49Smarc /* 1156b2b69f49Smarc * unmap shared color map write buffer and kill VSYNC intrpts 1157b2b69f49Smarc */ 11587e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) { 11597e911b15Skarels qdflags[unit].mapped &= ~MAPCOLOR; 11607e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 11617e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11627881ece5Smarc /* 11637881ece5Smarc * re-protect color map write buffer 11647881ece5Smarc */ 11657881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 11667e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 11677881ece5Smarc mtpr(TBIA, 0); 11687e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11697e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC; 11707e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11717e911b15Skarels } 11727e911b15Skarels break; 11737e911b15Skarels 11747e911b15Skarels case QD_MAPEVENT: 1175b2b69f49Smarc /* 1176b2b69f49Smarc * give user write access to the event queue 1177b2b69f49Smarc */ 11787e911b15Skarels qdflags[unit].mapped |= MAPEQ; 11797e911b15Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 11807e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11817881ece5Smarc /* 11827881ece5Smarc * allow user write to 1K event queue 11837881ece5Smarc */ 11847881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 11857e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11867e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 11877881ece5Smarc /* 11887881ece5Smarc * return event queue address 11897881ece5Smarc */ 11907e911b15Skarels *(int *)datap = (int)eq_header[unit]; 11917e911b15Skarels break; 11927e911b15Skarels 11937e911b15Skarels case QD_PRGKBD: 1194b2b69f49Smarc /* 1195b2b69f49Smarc * pass caller's programming commands to LK201 1196b2b69f49Smarc */ 11977e911b15Skarels duart = (struct duart *)qdmap[unit].duart; 11987e911b15Skarels cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 1199b2b69f49Smarc /* 1200b2b69f49Smarc * send command 1201b2b69f49Smarc */ 12027e911b15Skarels for (i = 1000; i > 0; --i) { 12037881ece5Smarc if (duart->statusA&XMT_RDY) { 12047e911b15Skarels duart->dataA = cmdbuf->cmd; 12057e911b15Skarels break; 12067e911b15Skarels } 12077e911b15Skarels } 12087e911b15Skarels if (i == 0) { 12097881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 12107e911b15Skarels break; 12117e911b15Skarels } 1212b2b69f49Smarc /* 1213b2b69f49Smarc * send param1? 1214b2b69f49Smarc */ 12157e911b15Skarels if (cmdbuf->cmd & LAST_PARAM) 12167e911b15Skarels break; 12177e911b15Skarels for (i = 1000; i > 0; --i) { 12187881ece5Smarc if (duart->statusA&XMT_RDY) { 12197e911b15Skarels duart->dataA = cmdbuf->param1; 12207e911b15Skarels break; 12217e911b15Skarels } 12227e911b15Skarels } 12237e911b15Skarels if (i == 0) { 12247881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 12257e911b15Skarels break; 12267e911b15Skarels } 1227b2b69f49Smarc /* 1228b2b69f49Smarc * send param2? 1229b2b69f49Smarc */ 12307e911b15Skarels if (cmdbuf->param1 & LAST_PARAM) 12317e911b15Skarels break; 12327e911b15Skarels for (i = 1000; i > 0; --i) { 12337881ece5Smarc if (duart->statusA&XMT_RDY) { 12347e911b15Skarels duart->dataA = cmdbuf->param2; 12357e911b15Skarels break; 12367e911b15Skarels } 12377e911b15Skarels } 12387e911b15Skarels if (i == 0) { 12397881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 12407e911b15Skarels break; 12417e911b15Skarels } 12427e911b15Skarels break; 12437e911b15Skarels 12447e911b15Skarels case QD_PRGMOUSE: 1245b2b69f49Smarc /* 1246b2b69f49Smarc * pass caller's programming commands to the mouse 1247b2b69f49Smarc */ 12487e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 12497e911b15Skarels for (i = 1000; i > 0; --i) { 12507881ece5Smarc if (duart->statusB&XMT_RDY) { 12517e911b15Skarels duart->dataB = *datap; 12527e911b15Skarels break; 12537e911b15Skarels } 12547e911b15Skarels } 12557e911b15Skarels if (i == 0) { 12567881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 12577e911b15Skarels } 12587e911b15Skarels break; 12597e911b15Skarels 12607e911b15Skarels case QD_RDCONFIG: 1261b2b69f49Smarc /* 1262b2b69f49Smarc * get QDSS configuration word and return it 1263b2b69f49Smarc */ 12647e911b15Skarels *(short *)datap = qdflags[unit].config; 12657e911b15Skarels break; 12667e911b15Skarels 1267e977faadSmarc case QD_KERN_LOOP: 1268e977faadSmarc case QD_KERN_UNLOOP: 1269b2b69f49Smarc /* 1270b2b69f49Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 1271b2b69f49Smarc * kernel console output. 1272b2b69f49Smarc */ 1273e977faadSmarc break; 1274e977faadSmarc 12757e911b15Skarels case QD_PRGTABLET: 1276b2b69f49Smarc /* 1277b2b69f49Smarc * program the tablet 1278b2b69f49Smarc */ 12797e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 12807e911b15Skarels for (i = 1000; i > 0; --i) { 12817881ece5Smarc if (duart->statusB&XMT_RDY) { 12827e911b15Skarels duart->dataB = *datap; 12837e911b15Skarels break; 12847e911b15Skarels } 12857e911b15Skarels } 12867e911b15Skarels if (i == 0) { 12877881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 12887e911b15Skarels } 12897e911b15Skarels break; 12907e911b15Skarels 12917e911b15Skarels case QD_PRGTABRES: 1292b2b69f49Smarc /* 1293b2b69f49Smarc * program the tablet report resolution factor 1294b2b69f49Smarc */ 12957e911b15Skarels qdflags[unit].tab_res = *(short *)datap; 12967e911b15Skarels break; 12978a2bf9b0Smarc 12987e911b15Skarels default: 1299b2b69f49Smarc /* 1300b2b69f49Smarc * service tty ioctl's 1301b2b69f49Smarc */ 13027e911b15Skarels if (!(minor_dev & 0x02)) { 13037e911b15Skarels tp = &qd_tty[minor_dev]; 1304b2b69f49Smarc error = 1305b2b69f49Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 13067e911b15Skarels if (error >= 0) { 13077e911b15Skarels return(error); 13087e911b15Skarels } 13097e911b15Skarels error = ttioctl(tp, cmd, datap, flags); 13107e911b15Skarels if (error >= 0) { 13117e911b15Skarels return(error); 13127e911b15Skarels } 13137e911b15Skarels } 13147e911b15Skarels break; 13157e911b15Skarels } 13167e911b15Skarels 13177e911b15Skarels return(0); 13187e911b15Skarels 13197e911b15Skarels } /* qdioctl */ 13207e911b15Skarels 13217e911b15Skarels qdselect(dev, rw) 13227e911b15Skarels dev_t dev; 13237e911b15Skarels int rw; 13247e911b15Skarels { 13257881ece5Smarc register s; 13267881ece5Smarc register unit; 1327e977faadSmarc register struct tty *tp; 1328e977faadSmarc u_int minor_dev = minor(dev); 13297e911b15Skarels 1330e977faadSmarc s = spl5(); 1331e977faadSmarc unit = minor_dev >> 2; 13327e911b15Skarels 13337e911b15Skarels switch (rw) { 1334e977faadSmarc case FREAD: 1335b2b69f49Smarc if ((minor_dev & 0x03) == 2) { 1336e977faadSmarc /* 1337e977faadSmarc * this is a graphics device, so check for events 1338e977faadSmarc */ 13397881ece5Smarc if(!(ISEMPTY(eq_header[unit]))) { 13407e911b15Skarels splx(s); 1341e977faadSmarc return(1); 13427e911b15Skarels } 13437881ece5Smarc qdrsel[unit] = u.u_procp; 13447e911b15Skarels qdflags[unit].selmask |= SEL_READ; 13457e911b15Skarels splx(s); 13467e911b15Skarels return(0); 1347b2b69f49Smarc } else { 1348e977faadSmarc /* 1349e977faadSmarc * this is a tty device 1350e977faadSmarc */ 1351e977faadSmarc tp = &qd_tty[minor_dev]; 1352e977faadSmarc if (ttnread(tp)) 1353e977faadSmarc return(1); 1354e977faadSmarc tp->t_rsel = u.u_procp; 13557e911b15Skarels splx(s); 1356e977faadSmarc return(0); 1357e977faadSmarc } 1358e977faadSmarc 1359e977faadSmarc case FWRITE: 1360b2b69f49Smarc if ((minor(dev) & 0x03) == 2) { 1361e977faadSmarc /* 1362e977faadSmarc * this is a graphics device, so check for dma buffers 1363e977faadSmarc */ 1364e977faadSmarc if (DMA_ISEMPTY(DMAheader[unit])) 1365e977faadSmarc { 1366e977faadSmarc splx(s); 1367e977faadSmarc return(1); 13687e911b15Skarels } 13697881ece5Smarc qdrsel[unit] = u.u_procp; 13707e911b15Skarels qdflags[unit].selmask |= SEL_WRITE; 13717e911b15Skarels splx(s); 13727e911b15Skarels return(0); 1373b2b69f49Smarc } else { 1374e977faadSmarc /* 1375e977faadSmarc * this is a tty device 1376e977faadSmarc */ 1377e977faadSmarc tp = &qd_tty[minor_dev]; 1378e977faadSmarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) 1379e977faadSmarc return(1); 1380e977faadSmarc tp->t_wsel = u.u_procp; 1381e977faadSmarc splx(s); 1382e977faadSmarc return(0); 1383e977faadSmarc } 1384e977faadSmarc } 13857881ece5Smarc splx(s); 13867881ece5Smarc return(0); 13877e911b15Skarels 13887e911b15Skarels } /* qdselect() */ 13897e911b15Skarels 13907e911b15Skarels extern qd_strategy(); 13917e911b15Skarels 13927e911b15Skarels qdwrite(dev, uio) 13937e911b15Skarels dev_t dev; 13947e911b15Skarels struct uio *uio; 13957e911b15Skarels { 13967e911b15Skarels register struct tty *tp; 13977881ece5Smarc register minor_dev; 13987881ece5Smarc register unit; 13997e911b15Skarels 14007e911b15Skarels minor_dev = minor(dev); 14017e911b15Skarels unit = (minor_dev >> 2) & 0x07; 14027e911b15Skarels 1403b2b69f49Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 1404b2b69f49Smarc /* 1405b2b69f49Smarc * this is the console... 1406b2b69f49Smarc */ 14077e911b15Skarels tp = &qd_tty[minor_dev]; 14087e911b15Skarels return ((*linesw[tp->t_line].l_write)(tp, uio)); 1409b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1410b2b69f49Smarc /* 1411b2b69f49Smarc * this is a DMA xfer from user space 1412b2b69f49Smarc */ 14137e911b15Skarels return (physio(qd_strategy, &qdbuf[unit], 14147e911b15Skarels dev, B_WRITE, minphys, uio)); 14157e911b15Skarels } 14167881ece5Smarc return (ENXIO); 14177e911b15Skarels } 14187e911b15Skarels 14197e911b15Skarels qdread(dev, uio) 14207e911b15Skarels dev_t dev; 14217e911b15Skarels struct uio *uio; 14227e911b15Skarels { 14237e911b15Skarels register struct tty *tp; 14247881ece5Smarc register minor_dev; 14257881ece5Smarc register unit; 14267e911b15Skarels 14277e911b15Skarels minor_dev = minor(dev); 14287e911b15Skarels unit = (minor_dev >> 2) & 0x07; 14297e911b15Skarels 1430b2b69f49Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 1431b2b69f49Smarc /* 1432b2b69f49Smarc * this is the console 1433b2b69f49Smarc */ 14347e911b15Skarels tp = &qd_tty[minor_dev]; 14357e911b15Skarels return ((*linesw[tp->t_line].l_read)(tp, uio)); 1436b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1437b2b69f49Smarc /* 1438b2b69f49Smarc * this is a bitmap-to-processor xfer 1439b2b69f49Smarc */ 14407e911b15Skarels return (physio(qd_strategy, &qdbuf[unit], 14417e911b15Skarels dev, B_READ, minphys, uio)); 14427e911b15Skarels } 14437881ece5Smarc return (ENXIO); 14447e911b15Skarels } 14457e911b15Skarels 14467e911b15Skarels /*************************************************************** 14477e911b15Skarels * 14487e911b15Skarels * qd_strategy()... strategy routine to do DMA 14497e911b15Skarels * 14507e911b15Skarels ***************************************************************/ 14517e911b15Skarels 14527e911b15Skarels qd_strategy(bp) 14537e911b15Skarels register struct buf *bp; 14547e911b15Skarels { 14557e911b15Skarels register struct dga *dga; 14567e911b15Skarels register struct adder *adder; 14577881ece5Smarc register unit; 14587e911b15Skarels int QBAreg; 14597e911b15Skarels int s; 14607e911b15Skarels int cookie; 14617e911b15Skarels 14627e911b15Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 14637e911b15Skarels 1464b2b69f49Smarc /* 1465b2b69f49Smarc * init pointers 1466b2b69f49Smarc */ 14677e911b15Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 14687881ece5Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 14697e911b15Skarels goto STRAT_ERR; 14707e911b15Skarels } 14717e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 1472e977faadSmarc s = spl5(); 14737e911b15Skarels qdflags[unit].user_dma = -1; 14747e911b15Skarels dga->csr |= DMA_IE; 14757e911b15Skarels cookie = QBAreg & 0x3FFFF; 14767e911b15Skarels dga->adrs_lo = (short) cookie; 14777e911b15Skarels dga->adrs_hi = (short) (cookie >> 16); 14787e911b15Skarels dga->bytcnt_lo = (short) bp->b_bcount; 14797e911b15Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 14807e911b15Skarels 14817e911b15Skarels while (qdflags[unit].user_dma) { 14827e911b15Skarels sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 14837e911b15Skarels } 14847e911b15Skarels splx(s); 14857e911b15Skarels ubarelse(0, &QBAreg); 14867e911b15Skarels if (!(dga->csr & DMA_ERR)) { 14877e911b15Skarels iodone(bp); 14887e911b15Skarels return; 14897e911b15Skarels } 14907e911b15Skarels 14917e911b15Skarels STRAT_ERR: 14927e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 14937e911b15Skarels adder->command = CANCEL; /* cancel adder activity */ 14947e911b15Skarels dga->csr &= ~DMA_IE; 14957e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 14967e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 14977e911b15Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 14987e911b15Skarels 1499b2b69f49Smarc /* 1500b2b69f49Smarc * if DMA was running, flush spurious intrpt 1501b2b69f49Smarc */ 15027e911b15Skarels if (dga->bytcnt_lo != 0) { 15037e911b15Skarels dga->bytcnt_lo = 0; 15047e911b15Skarels dga->bytcnt_hi = 0; 15057e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 15067e911b15Skarels dga->csr |= DMA_IE; 15077e911b15Skarels } 15087e911b15Skarels iodone(bp); 15097e911b15Skarels 15107e911b15Skarels } /* qd_strategy */ 15117e911b15Skarels 15127881ece5Smarc /* 15137881ece5Smarc * Start output to the console screen 15147881ece5Smarc */ 15157e911b15Skarels qdstart(tp) 15167e911b15Skarels register struct tty *tp; 15177e911b15Skarels { 15187881ece5Smarc register which_unit, unit, c; 15197e911b15Skarels int s; 15207e911b15Skarels 1521e977faadSmarc unit = minor(tp->t_dev); 1522e977faadSmarc which_unit = (unit >> 2) & 0x3; 1523e977faadSmarc unit &= 0x03; 1524e977faadSmarc 1525e977faadSmarc s = spl5(); 1526e977faadSmarc 1527b2b69f49Smarc /* 1528b2b69f49Smarc * If it's currently active, or delaying, no need to do anything. 1529b2b69f49Smarc */ 15307e911b15Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 15317e911b15Skarels goto out; 15327e911b15Skarels 1533b2b69f49Smarc /* 1534b2b69f49Smarc * Display chars until the queue is empty. 1535b2b69f49Smarc * Drop input from anything but the console 1536b2b69f49Smarc * device on the floor. 1537b2b69f49Smarc * 1538b2b69f49Smarc * XXX - this loop is done at spltty. 1539b2b69f49Smarc * 1540b2b69f49Smarc */ 15417e911b15Skarels while (tp->t_outq.c_cc) { 15427e911b15Skarels c = getc(&tp->t_outq); 1543e977faadSmarc if (unit == 0) 15447881ece5Smarc blitc(which_unit, (u_char)c); 15457e911b15Skarels } 1546b2b69f49Smarc /* 1547e977faadSmarc * If there are sleepers, and output has drained below low 1548b2b69f49Smarc * water mark, wake up the sleepers. 1549b2b69f49Smarc */ 1550e977faadSmarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 15517e911b15Skarels if (tp->t_state & TS_ASLEEP){ 15527e911b15Skarels tp->t_state &= ~TS_ASLEEP; 15537e911b15Skarels wakeup((caddr_t) &tp->t_outq); 15547e911b15Skarels } 1555e977faadSmarc } 1556e977faadSmarc 1557e977faadSmarc tp->t_state &= ~TS_BUSY; 15587e911b15Skarels 15597e911b15Skarels out: 15607e911b15Skarels splx(s); 15617e911b15Skarels 15627e911b15Skarels } /* qdstart */ 15637e911b15Skarels 15647881ece5Smarc /*ARGSUSED*/ 15657e911b15Skarels qdstop(tp, flag) 15667e911b15Skarels register struct tty *tp; 15677e911b15Skarels int flag; 15687e911b15Skarels { 15697e911b15Skarels register int s; 15707e911b15Skarels 1571e977faadSmarc s = spl5(); /* block intrpts during state modification */ 15727881ece5Smarc if (tp->t_state & TS_BUSY) 15737881ece5Smarc if ((tp->t_state & TS_TTSTOP) == 0) 15747e911b15Skarels tp->t_state |= TS_FLUSH; 1575b2b69f49Smarc else 15767e911b15Skarels tp->t_state &= ~TS_BUSY; 15777e911b15Skarels splx(s); 15787e911b15Skarels } 15797e911b15Skarels 15807881ece5Smarc /* 15817881ece5Smarc * Output a character to the QDSS screen 15827881ece5Smarc */ 15837e911b15Skarels 15847e911b15Skarels blitc(unit, chr) 15857881ece5Smarc register unit; 15867881ece5Smarc register u_char chr; 15877e911b15Skarels { 15887e911b15Skarels register struct adder *adder; 15897e911b15Skarels register struct dga *dga; 15907e911b15Skarels register int i; 1591b2b69f49Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 1592b2b69f49Smarc static short inescape[NQD]; 15937e911b15Skarels 15947e911b15Skarels adder = (struct adder *)qdmap[unit].adder; 15957e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 1596b2b69f49Smarc /* 1597b2b69f49Smarc * BSD comment: this (&=0177) defeats the extended character 1598b2b69f49Smarc * set code for the glass tty, but if i had the time i would 1599b2b69f49Smarc * spend it ripping out the code completely. This driver 1600b2b69f49Smarc * is too big for its own good. 1601b2b69f49Smarc */ 1602b2b69f49Smarc chr &= 0177; 1603b2b69f49Smarc /* 16047881ece5Smarc * Cursor addressing (so vi will work). 1605b2b69f49Smarc * Decode for "\E=%.%." cursor motion description. 16067881ece5Smarc * Corresponds to type "qdcons" in /etc/termcap: 1607b2b69f49Smarc * 1608b2b69f49Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 1609b2b69f49Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 1610b2b69f49Smarc * 1611b2b69f49Smarc */ 1612b2b69f49Smarc if (inescape[unit] && nograph) { 1613b2b69f49Smarc switch (inescape[unit]++) { 1614b2b69f49Smarc case 1: 1615b2b69f49Smarc if (chr != '=') { 1616b2b69f49Smarc /* abort escape sequence */ 1617b2b69f49Smarc inescape[unit] = 0; 1618b2b69f49Smarc blitc(unit, chr); 1619b2b69f49Smarc } 16207881ece5Smarc return; 1621b2b69f49Smarc case 2: 1622b2b69f49Smarc /* position row */ 1623b2b69f49Smarc cursor[unit].y = CHAR_HEIGHT * chr; 1624b2b69f49Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 1625b2b69f49Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 1626b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 16277881ece5Smarc return; 1628b2b69f49Smarc case 3: 1629b2b69f49Smarc /* position column */ 1630b2b69f49Smarc cursor[unit].x = CHAR_WIDTH * chr; 1631b2b69f49Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 1632b2b69f49Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 1633b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1634b2b69f49Smarc inescape[unit] = 0; 16357881ece5Smarc return; 1636b2b69f49Smarc default: 1637b2b69f49Smarc inescape[unit] = 0; 1638b2b69f49Smarc blitc(unit, chr); 1639b2b69f49Smarc } 1640b2b69f49Smarc } 164124f67f6bSmarc 16427e911b15Skarels switch (chr) { 16437e911b15Skarels case '\r': /* return char */ 16447e911b15Skarels cursor[unit].x = 0; 1645b2b69f49Smarc if (nograph) 16467e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 16477881ece5Smarc return; 16487e911b15Skarels 16497e911b15Skarels case '\t': /* tab char */ 16507e911b15Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 16517e911b15Skarels blitc(unit, ' '); 16527e911b15Skarels } 16537881ece5Smarc return; 16547e911b15Skarels 16557e911b15Skarels case '\n': /* line feed char */ 16567e911b15Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 1657b2b69f49Smarc if (nograph) { 16587e911b15Skarels cursor[unit].y -= CHAR_HEIGHT; 16597e911b15Skarels scroll_up(adder); 1660b2b69f49Smarc } else 1661b2b69f49Smarc cursor[unit].y = 0; 16627e911b15Skarels } 1663b2b69f49Smarc if (nograph) 16647e911b15Skarels dga->y_cursor = TRANY(cursor[unit].y); 16657881ece5Smarc return; 16667e911b15Skarels 16677e911b15Skarels case '\b': /* backspace char */ 16687e911b15Skarels if (cursor[unit].x > 0) { 16697e911b15Skarels cursor[unit].x -= CHAR_WIDTH; 1670b2b69f49Smarc if (nograph) 1671b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1672b2b69f49Smarc } 16737881ece5Smarc return; 1674b2b69f49Smarc case CTRL('k'): /* cursor up */ 1675b2b69f49Smarc if (nograph && cursor[unit].y > 0) { 1676b2b69f49Smarc cursor[unit].y -= CHAR_HEIGHT; 1677b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1678b2b69f49Smarc } 16797881ece5Smarc return; 1680b2b69f49Smarc 1681b2b69f49Smarc case CTRL('^'): /* home cursor */ 1682b2b69f49Smarc if (nograph) { 1683b2b69f49Smarc cursor[unit].x = 0; 1684b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1685b2b69f49Smarc cursor[unit].y = 0; 1686b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1687b2b69f49Smarc } 16887881ece5Smarc return; 1689b2b69f49Smarc 1690b2b69f49Smarc case CTRL('l'): /* cursor right */ 1691b2b69f49Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 1692b2b69f49Smarc cursor[unit].x += CHAR_WIDTH; 16937e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 16947e911b15Skarels } 16957881ece5Smarc return; 16967e911b15Skarels 1697b2b69f49Smarc case CTRL('z'): /* clear screen */ 1698b2b69f49Smarc if (nograph) { 1699b2b69f49Smarc setup_dragon(unit); 1700b2b69f49Smarc clear_qd_screen(unit); 1701b2b69f49Smarc /* home cursor - termcap seems to assume this */ 1702b2b69f49Smarc cursor[unit].x = 0; 1703b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1704b2b69f49Smarc cursor[unit].y = 0; 1705b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1706b2b69f49Smarc } 17077881ece5Smarc return; 1708e977faadSmarc 1709b2b69f49Smarc case '\033': /* start escape sequence */ 1710b2b69f49Smarc if (nograph) 1711b2b69f49Smarc inescape[unit] = 1; 17127881ece5Smarc return; 1713b2b69f49Smarc 1714b2b69f49Smarc default: 1715b2b69f49Smarc if ((chr < ' ') || (chr > '~')) 17167881ece5Smarc return; 17177e911b15Skarels } 1718b2b69f49Smarc /* 1719b2b69f49Smarc * setup VIPER operand control registers 1720b2b69f49Smarc */ 17217e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 17227e911b15Skarels write_ID(adder, SRC1_OCR_B, 17237e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 17247e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 17257e911b15Skarels write_ID(adder, SRC1_OCR_B, 17267e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 17277e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 17287e911b15Skarels write_ID(adder, DST_OCR_B, 17297e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 17307e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 17317e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 17327e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 1733e977faadSmarc adder->x_clip_min = 0; 1734e977faadSmarc adder->x_clip_max = 1024; 1735e977faadSmarc adder->y_clip_min = 0; 1736e977faadSmarc adder->y_clip_max = 864; 1737b2b69f49Smarc /* 1738b2b69f49Smarc * load DESTINATION origin and vectors 1739b2b69f49Smarc */ 17407e911b15Skarels adder->fast_dest_dy = 0; 17417e911b15Skarels adder->slow_dest_dx = 0; 17427e911b15Skarels adder->error_1 = 0; 17437e911b15Skarels adder->error_2 = 0; 17447e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 17457881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 17467e911b15Skarels adder->destination_x = cursor[unit].x; 17477e911b15Skarels adder->fast_dest_dx = CHAR_WIDTH; 17487e911b15Skarels adder->destination_y = cursor[unit].y; 17497e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; 1750b2b69f49Smarc /* 1751b2b69f49Smarc * load SOURCE origin and vectors 1752b2b69f49Smarc */ 1753e977faadSmarc if ((chr - ' ') > (CHARS - 1)) { 1754e977faadSmarc printf("Invalid character (x)%x in blitc\n",chr); 1755e977faadSmarc chr = ' '; 1756e977faadSmarc } 1757b2b69f49Smarc /* 1758b2b69f49Smarc * X position is modulo the number of characters per line 1759b2b69f49Smarc */ 1760e977faadSmarc adder->source_1_x = FONT_X + 1761e977faadSmarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 1762b2b69f49Smarc /* 1763b2b69f49Smarc * Point to either first or second row 1764b2b69f49Smarc */ 1765e977faadSmarc adder->source_1_y = 2048 - 15 * 1766e977faadSmarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 17677e911b15Skarels adder->source_1_dx = CHAR_WIDTH; 17687e911b15Skarels adder->source_1_dy = CHAR_HEIGHT; 17697e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 17707e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 1771b2b69f49Smarc /* 1772b2b69f49Smarc * update console cursor coordinates 1773b2b69f49Smarc */ 17747e911b15Skarels cursor[unit].x += CHAR_WIDTH; 1775b2b69f49Smarc if (nograph) 17767e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 17777e911b15Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 17787e911b15Skarels blitc(unit, '\r'); 17797e911b15Skarels blitc(unit, '\n'); 17807e911b15Skarels } 17817e911b15Skarels 17827e911b15Skarels } /* blitc */ 17837e911b15Skarels 17847881ece5Smarc qdreset() { } 17857e911b15Skarels 17867881ece5Smarc /* 1787b2b69f49Smarc * INTERRUPT SERVICE ROUTINES 17887881ece5Smarc */ 17897e911b15Skarels 17907881ece5Smarc /* 17917881ece5Smarc * Service "DMA DONE" interrupt condition 17927881ece5Smarc */ 17937e911b15Skarels qddint(qd) 17947881ece5Smarc register qd; 17957e911b15Skarels { 17967e911b15Skarels register struct DMAreq_header *header; 17977e911b15Skarels register struct DMAreq *request; 17987e911b15Skarels register struct dga *dga; 17997e911b15Skarels struct adder *adder; 18007e911b15Skarels int cookie; /* DMA adrs for QDSS */ 18017e911b15Skarels 18027881ece5Smarc (void)spl4(); /* allow interval timer in */ 18037e911b15Skarels 1804b2b69f49Smarc /* 1805b2b69f49Smarc * init pointers 1806b2b69f49Smarc */ 18077e911b15Skarels header = DMAheader[qd]; /* register for optimization */ 18087e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 18097e911b15Skarels adder = (struct adder *) qdmap[qd].adder; 18107e911b15Skarels 1811b2b69f49Smarc /* 1812b2b69f49Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 1813b2b69f49Smarc */ 18147e911b15Skarels if (DMA_ISIGNORE(header)) { 18157e911b15Skarels DMA_CLRIGNORE(header); 18167e911b15Skarels return; 18177e911b15Skarels } 18187e911b15Skarels 1819b2b69f49Smarc /* 1820b2b69f49Smarc * dump a DMA hardware error message if appropriate 1821b2b69f49Smarc */ 18227e911b15Skarels if (dga->csr & DMA_ERR) { 18237e911b15Skarels 18247e911b15Skarels if (dga->csr & PARITY_ERR) 18257881ece5Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 18267e911b15Skarels 18277e911b15Skarels if (dga->csr & BUS_ERR) 18287881ece5Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 18297e911b15Skarels } 18307e911b15Skarels 1831b2b69f49Smarc /* 1832b2b69f49Smarc * if this was a DMA from user space... 1833b2b69f49Smarc */ 18347e911b15Skarels if (qdflags[qd].user_dma) { 18357e911b15Skarels qdflags[qd].user_dma = 0; 18367e911b15Skarels wakeup((caddr_t)&qdflags[qd].user_dma); 18377e911b15Skarels return; 18387e911b15Skarels } 18397e911b15Skarels 1840b2b69f49Smarc /* 1841b2b69f49Smarc * if we're doing DMA request queue services, field the error condition 1842b2b69f49Smarc */ 18437e911b15Skarels if (dga->csr & DMA_ERR) { 18447e911b15Skarels 18457e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 18467e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 18477e911b15Skarels adder->command = CANCEL; /* cancel adder activity */ 18487e911b15Skarels 18497e911b15Skarels DMA_SETERROR(header); /* flag error in header status word */ 18507e911b15Skarels DMA_CLRACTIVE(header); 18517e911b15Skarels header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 18527e911b15Skarels header->newest = header->oldest; 18537e911b15Skarels header->used = 0; 18547e911b15Skarels 18557881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18567881ece5Smarc selwakeup(qdrsel[qd], 0); 18577881ece5Smarc qdrsel[qd] = 0; 18587e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18597e911b15Skarels } 18607e911b15Skarels 18617e911b15Skarels if (dga->bytcnt_lo != 0) { 18627e911b15Skarels dga->bytcnt_lo = 0; 18637e911b15Skarels dga->bytcnt_hi = 0; 18647e911b15Skarels DMA_SETIGNORE(header); 18657e911b15Skarels } 18667e911b15Skarels return; 18677e911b15Skarels } 18687e911b15Skarels 1869b2b69f49Smarc /* 1870b2b69f49Smarc * if the DMA request queue is now becoming non-full, 1871b2b69f49Smarc * wakeup "select" client. 1872b2b69f49Smarc */ 18737e911b15Skarels if (DMA_ISFULL(header)) { 18747881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18757881ece5Smarc selwakeup(qdrsel[qd], 0); 18767881ece5Smarc qdrsel[qd] = 0; 18777e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18787e911b15Skarels } 18797e911b15Skarels } 18807e911b15Skarels 18817e911b15Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 1882e977faadSmarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 18837e911b15Skarels 1884e977faadSmarc /* check for unexpected interrupt */ 1885e977faadSmarc if (DMA_ISEMPTY(header)) 18867e911b15Skarels return; 18877e911b15Skarels 18887e911b15Skarels DMA_GETEND(header); /* update request queue indices */ 18897e911b15Skarels 1890b2b69f49Smarc /* 18917881ece5Smarc * if no more DMA pending, wake up "select" client and exit 18927881ece5Smarc */ 18937e911b15Skarels if (DMA_ISEMPTY(header)) { 18947e911b15Skarels 18957881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18967881ece5Smarc selwakeup(qdrsel[qd], 0); 18977881ece5Smarc qdrsel[qd] = 0; 18987e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18997e911b15Skarels } 19007e911b15Skarels 19017e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 19027e911b15Skarels return; 19037e911b15Skarels } 19047e911b15Skarels 1905b2b69f49Smarc /* 19067881ece5Smarc * initiate next DMA xfer 19077881ece5Smarc */ 19087e911b15Skarels request = DMA_GETBEGIN(header); 1909e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1910e977faadSmarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 1911e977faadSmarc adder->command = CANCEL; /* cancel adder activity */ 1912e977faadSmarc } 1913e977faadSmarc 19147e911b15Skarels 19157e911b15Skarels switch (request->DMAtype) { 19167e911b15Skarels 19177e911b15Skarels case DISPLIST: 1918e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 19197e911b15Skarels dga->csr |= DL_ENB; 1920e977faadSmarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 1921e977faadSmarc } 19227e911b15Skarels break; 19237e911b15Skarels 19247e911b15Skarels case PTOB: 1925e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1926e977faadSmarc if (request->DMAdone & BYTE_PACK) 1927e977faadSmarc dga->csr |= (PTOB_ENB | BYTE_DMA); 1928e977faadSmarc else { 19297e911b15Skarels dga->csr |= PTOB_ENB; 1930e977faadSmarc dga->csr &= ~BYTE_DMA; 1931e977faadSmarc } 1932e977faadSmarc } 19337e911b15Skarels break; 19347e911b15Skarels 19357e911b15Skarels case BTOP: 1936e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1937e977faadSmarc if (request->DMAdone & BYTE_PACK) { 1938e977faadSmarc dga->csr &= ~DL_ENB; 1939e977faadSmarc dga->csr |= (BTOP_ENB | BYTE_DMA); 1940e977faadSmarc } 1941e977faadSmarc else { 19427e911b15Skarels dga->csr |= BTOP_ENB; 1943e977faadSmarc dga->csr &= ~(BYTE_DMA | DL_ENB); 1944e977faadSmarc } 1945e977faadSmarc } 19467e911b15Skarels break; 19477e911b15Skarels default: 19487881ece5Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 19497e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 19507e911b15Skarels return; 19517e911b15Skarels } 19527e911b15Skarels 19537e911b15Skarels if (request->DMAdone & COUNT_ZERO) { 19547e911b15Skarels dga->csr &= ~SET_DONE_FIFO; 1955b2b69f49Smarc } 1956b2b69f49Smarc else if (request->DMAdone & FIFO_EMPTY) { 19577e911b15Skarels dga->csr |= SET_DONE_FIFO; 19587e911b15Skarels } 19597e911b15Skarels 19607e911b15Skarels if (request->DMAdone & WORD_PACK) 19617e911b15Skarels dga->csr &= ~BYTE_DMA; 19627e911b15Skarels else if (request->DMAdone & BYTE_PACK) 19637e911b15Skarels dga->csr |= BYTE_DMA; 19647e911b15Skarels 19657e911b15Skarels dga->csr |= DMA_IE; 1966e977faadSmarc QDlast_DMAtype = request->DMAtype; 19677e911b15Skarels 19687e911b15Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 19697e911b15Skarels 19707e911b15Skarels dga->adrs_lo = (short) cookie; 19717e911b15Skarels dga->adrs_hi = (short) (cookie >> 16); 19727e911b15Skarels 19737e911b15Skarels dga->bytcnt_lo = (short) request->length; 19747e911b15Skarels dga->bytcnt_hi = (short) (request->length >> 16); 19757e911b15Skarels 19767e911b15Skarels return; 19777e911b15Skarels } 19787e911b15Skarels 19797881ece5Smarc /* 19807881ece5Smarc * ADDER interrupt service routine 19817881ece5Smarc */ 19827e911b15Skarels qdaint(qd) 19837881ece5Smarc register qd; 19847e911b15Skarels { 19857e911b15Skarels register struct adder *adder; 19867e911b15Skarels struct color_buf *cbuf; 19877e911b15Skarels int i; 19887e911b15Skarels register struct rgb *rgbp; 19897e911b15Skarels register short *red; 19907e911b15Skarels register short *green; 19917e911b15Skarels register short *blue; 19927e911b15Skarels 19937881ece5Smarc (void)spl4(); /* allow interval timer in */ 19947e911b15Skarels 19957e911b15Skarels adder = (struct adder *) qdmap[qd].adder; 19967e911b15Skarels 1997b2b69f49Smarc /* 1998b2b69f49Smarc * service the vertical blank interrupt (VSYNC bit) by loading 1999b2b69f49Smarc * any pending color map load request 2000b2b69f49Smarc */ 20017e911b15Skarels if (adder->status & VSYNC) { 20027e911b15Skarels adder->status &= ~VSYNC; /* clear the interrupt */ 20037e911b15Skarels cbuf = color_buf[qd]; 20047e911b15Skarels if (cbuf->status & LOAD_COLOR_MAP) { 20057e911b15Skarels 20067e911b15Skarels red = (short *) qdmap[qd].red; 20077e911b15Skarels green = (short *) qdmap[qd].green; 20087e911b15Skarels blue = (short *) qdmap[qd].blue; 20097e911b15Skarels 2010b2b69f49Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 2011b2b69f49Smarc --i >= 0; rgbp++) { 20127e911b15Skarels red[rgbp->offset] = (short) rgbp->red; 20137e911b15Skarels green[rgbp->offset] = (short) rgbp->green; 20147e911b15Skarels blue[rgbp->offset] = (short) rgbp->blue; 20157e911b15Skarels } 20167e911b15Skarels 20177e911b15Skarels cbuf->status &= ~LOAD_COLOR_MAP; 20187e911b15Skarels } 20197e911b15Skarels } 20207e911b15Skarels 2021b2b69f49Smarc /* 2022b2b69f49Smarc * service the scroll interrupt (FRAME_SYNC bit) 2023b2b69f49Smarc */ 20247e911b15Skarels if (adder->status & FRAME_SYNC) { 20257e911b15Skarels adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 20267e911b15Skarels 20277e911b15Skarels if (scroll[qd]->status & LOAD_REGS) { 20287e911b15Skarels 20297881ece5Smarc for (i = 1000, adder->status = 0; i > 0 && 20307881ece5Smarc !(adder->status&ID_SCROLL_READY); --i) 2031b2b69f49Smarc ; 20327e911b15Skarels 20337e911b15Skarels if (i == 0) { 20347881ece5Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 2035b2b69f49Smarc qd); 20367e911b15Skarels return; 20377e911b15Skarels } 20387e911b15Skarels 20397e911b15Skarels adder->ID_scroll_data = scroll[qd]->viper_constant; 20407e911b15Skarels adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 20417e911b15Skarels 2042b2b69f49Smarc adder->y_scroll_constant = 2043b2b69f49Smarc scroll[qd]->y_scroll_constant; 20447e911b15Skarels adder->y_offset_pending = scroll[qd]->y_offset; 20457e911b15Skarels 20467e911b15Skarels if (scroll[qd]->status & LOAD_INDEX) { 20477e911b15Skarels 2048b2b69f49Smarc adder->x_index_pending = 2049b2b69f49Smarc scroll[qd]->x_index_pending; 2050b2b69f49Smarc adder->y_index_pending = 2051b2b69f49Smarc scroll[qd]->y_index_pending; 20527e911b15Skarels } 20537e911b15Skarels 20547e911b15Skarels scroll[qd]->status = 0x00; 20557e911b15Skarels } 20567e911b15Skarels } 20577e911b15Skarels } 20587e911b15Skarels 20597881ece5Smarc /* 20607881ece5Smarc * DUART input interrupt service routine 20617e911b15Skarels * 2062b2b69f49Smarc * XXX - this routine should be broken out - it is essentially 2063b2b69f49Smarc * straight line code. 20647881ece5Smarc */ 20657e911b15Skarels 20667e911b15Skarels qdiint(qd) 20677881ece5Smarc register qd; 20687e911b15Skarels { 20697e911b15Skarels register struct _vs_event *event; 20707e911b15Skarels register struct qdinput *eqh; 20717e911b15Skarels struct dga *dga; 20727e911b15Skarels struct duart *duart; 20737e911b15Skarels struct mouse_report *new_rep; 20747e911b15Skarels struct uba_device *ui; 20757e911b15Skarels struct tty *tp; 2076e977faadSmarc u_short chr; 20777e911b15Skarels u_short status; 20787e911b15Skarels u_short data; 20797e911b15Skarels u_short key; 20807e911b15Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 20817e911b15Skarels char a, b, c; /* mouse button test variables */ 20827e911b15Skarels 20837881ece5Smarc (void)spl4(); /* allow interval timer in */ 20847e911b15Skarels 20857e911b15Skarels eqh = eq_header[qd]; /* optimized as a register */ 20867e911b15Skarels new_rep = ¤t_rep[qd]; 20877e911b15Skarels duart = (struct duart *) qdmap[qd].duart; 20887e911b15Skarels 2089b2b69f49Smarc /* 20907881ece5Smarc * if the graphic device is turned on.. 20917881ece5Smarc */ 20927e911b15Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 2093b2b69f49Smarc /* 2094b2b69f49Smarc * empty DUART 2095b2b69f49Smarc */ 20967881ece5Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 2097b2b69f49Smarc /* 20987881ece5Smarc * pick up LK-201 input (if any) 20997881ece5Smarc */ 21007881ece5Smarc if (duart->statusA&RCV_RDY) { 21017e911b15Skarels 21027e911b15Skarels /* if error condition, then reset it */ 21037e911b15Skarels 21047881ece5Smarc if (duart->statusA&0x70) { 21057e911b15Skarels duart->cmdA = 0x40; 21067e911b15Skarels continue; 21077e911b15Skarels } 21087e911b15Skarels 21097e911b15Skarels /* event queue full now? (overflow condition) */ 21107e911b15Skarels 21117e911b15Skarels if (ISFULL(eqh) == TRUE) { 2112b2b69f49Smarc printf( 21137881ece5Smarc "qd%d: qdiint: event queue overflow\n", 2114b2b69f49Smarc qd); 21157e911b15Skarels break; 21167e911b15Skarels } 21177e911b15Skarels 2118b2b69f49Smarc /* 21197e911b15Skarels * Check for various keyboard errors */ 21207e911b15Skarels 21217e911b15Skarels key = duart->dataA & 0xFF; 21227e911b15Skarels 2123b2b69f49Smarc if (key==LK_POWER_ERROR || 2124b2b69f49Smarc key==LK_KDOWN_ERROR || 2125b2b69f49Smarc key == LK_INPUT_ERROR || 2126b2b69f49Smarc key == LK_OUTPUT_ERROR) { 2127b2b69f49Smarc printf( 21287881ece5Smarc "qd%d: qdiint: keyboard error, code = %x\n", 2129b2b69f49Smarc qd,key); 21307881ece5Smarc return; 21317e911b15Skarels } 21327e911b15Skarels 21337e911b15Skarels if (key < LK_LOWEST) 21347881ece5Smarc return; 21357e911b15Skarels 21367e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 21377e911b15Skarels 21387e911b15Skarels event = PUTBEGIN(eqh); 21397e911b15Skarels PUTEND(eqh); 21407e911b15Skarels 21417e911b15Skarels event->vse_key = key; 21427e911b15Skarels event->vse_key &= 0x00FF; 21437e911b15Skarels event->vse_x = eqh->curs_pos.x; 21447e911b15Skarels event->vse_y = eqh->curs_pos.y; 21457e911b15Skarels event->vse_time = TOY; 21467e911b15Skarels event->vse_type = VSE_BUTTON; 21477e911b15Skarels event->vse_direction = VSE_KBTRAW; 21487e911b15Skarels event->vse_device = VSE_DKB; 21497e911b15Skarels } 21507e911b15Skarels 2151b2b69f49Smarc /* 21527e911b15Skarels * pick up the mouse input (if any) */ 21537e911b15Skarels 21547e911b15Skarels if ((status = duart->statusB) & RCV_RDY && 21557e911b15Skarels qdflags[qd].pntr_id == MOUSE_ID) { 21567e911b15Skarels 21577e911b15Skarels if (status & 0x70) { 21587e911b15Skarels duart->cmdB = 0x40; 21597e911b15Skarels continue; 21607e911b15Skarels } 21617e911b15Skarels 21627e911b15Skarels /* event queue full now? (overflow condition) */ 21637e911b15Skarels 21647e911b15Skarels if (ISFULL(eqh) == TRUE) { 2165b2b69f49Smarc printf( 21667881ece5Smarc "qd%d: qdiint: event queue overflow\n", 2167b2b69f49Smarc qd); 21687e911b15Skarels break; 21697e911b15Skarels } 21707e911b15Skarels 21717e911b15Skarels data = duart->dataB; /* get report byte */ 21727e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */ 21737e911b15Skarels 2174b2b69f49Smarc /* 21757e911b15Skarels * if 1st byte of report.. */ 21767e911b15Skarels 21777e911b15Skarels if ( data & START_FRAME) { 21787e911b15Skarels new_rep->state = data; 21797e911b15Skarels if (new_rep->bytcnt > 1) { 2180b2b69f49Smarc /* start of new frame */ 2181b2b69f49Smarc new_rep->bytcnt = 1; 2182b2b69f49Smarc /* ..continue looking */ 2183b2b69f49Smarc continue; 21847e911b15Skarels } 21857e911b15Skarels } 21867e911b15Skarels 2187b2b69f49Smarc /* 21887e911b15Skarels * if 2nd byte of report.. */ 21897e911b15Skarels 21907e911b15Skarels else if (new_rep->bytcnt == 2) { 21917e911b15Skarels new_rep->dx = data & 0x00FF; 21927e911b15Skarels } 21937e911b15Skarels 2194b2b69f49Smarc /* 21957e911b15Skarels * if 3rd byte of report, load input event queue */ 21967e911b15Skarels 21977e911b15Skarels else if (new_rep->bytcnt == 3) { 21987e911b15Skarels 21997e911b15Skarels new_rep->dy = data & 0x00FF; 22007e911b15Skarels new_rep->bytcnt = 0; 22017e911b15Skarels 2202b2b69f49Smarc /* 22037e911b15Skarels * if mouse position has changed.. */ 22047e911b15Skarels 22057e911b15Skarels if (new_rep->dx != 0 || new_rep->dy != 0) { 22067e911b15Skarels 2207b2b69f49Smarc /* 22087e911b15Skarels * calculate acceleration factor, if needed */ 22097e911b15Skarels 22107e911b15Skarels if (qdflags[qd].curs_acc > ACC_OFF) { 22117e911b15Skarels 22127e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dx) 22137e911b15Skarels new_rep->dx += 22147e911b15Skarels (new_rep->dx - qdflags[qd].curs_thr) 22157e911b15Skarels * qdflags[qd].curs_acc; 22167e911b15Skarels 22177e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dy) 22187e911b15Skarels new_rep->dy += 22197e911b15Skarels (new_rep->dy - qdflags[qd].curs_thr) 22207e911b15Skarels * qdflags[qd].curs_acc; 22217e911b15Skarels } 22227e911b15Skarels 2223b2b69f49Smarc /* 22247e911b15Skarels * update cursor position coordinates */ 22257e911b15Skarels 22267e911b15Skarels if (new_rep->state & X_SIGN) { 22277e911b15Skarels eqh->curs_pos.x += new_rep->dx; 22287e911b15Skarels if (eqh->curs_pos.x > 1023) 22297e911b15Skarels eqh->curs_pos.x = 1023; 22307e911b15Skarels } 22317e911b15Skarels else { 22327e911b15Skarels eqh->curs_pos.x -= new_rep->dx; 22337e911b15Skarels if (eqh->curs_pos.x < -15) 22347e911b15Skarels eqh->curs_pos.x = -15; 22357e911b15Skarels } 22367e911b15Skarels 22377e911b15Skarels if (new_rep->state & Y_SIGN) { 22387e911b15Skarels eqh->curs_pos.y -= new_rep->dy; 22397e911b15Skarels if (eqh->curs_pos.y < -15) 22407e911b15Skarels eqh->curs_pos.y = -15; 22417e911b15Skarels } 22427e911b15Skarels else { 22437e911b15Skarels eqh->curs_pos.y += new_rep->dy; 22447e911b15Skarels if (eqh->curs_pos.y > 863) 22457e911b15Skarels eqh->curs_pos.y = 863; 22467e911b15Skarels } 22477e911b15Skarels 2248b2b69f49Smarc /* 22497e911b15Skarels * update cursor screen position */ 22507e911b15Skarels 22517e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 22527e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x); 22537e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y); 22547e911b15Skarels 2255b2b69f49Smarc /* 22567e911b15Skarels * if cursor is in the box, no event report */ 22577e911b15Skarels 22587e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right && 22597e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left && 22607e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top && 22617e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) { 22627e911b15Skarels goto GET_MBUTTON; 22637e911b15Skarels } 22647e911b15Skarels 2265b2b69f49Smarc /* 22667e911b15Skarels * report the mouse motion event */ 22677e911b15Skarels 22687e911b15Skarels event = PUTBEGIN(eqh); 22697e911b15Skarels PUTEND(eqh); 22707e911b15Skarels 22717e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 22727e911b15Skarels 22737e911b15Skarels event->vse_x = eqh->curs_pos.x; 22747e911b15Skarels event->vse_y = eqh->curs_pos.y; 22757e911b15Skarels 22767e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */ 22777e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */ 22787e911b15Skarels event->vse_key = 0; 22797e911b15Skarels event->vse_direction = 0; 22807e911b15Skarels event->vse_time = TOY; /* time stamp */ 22817e911b15Skarels } 22827e911b15Skarels 22837e911b15Skarels GET_MBUTTON: 2284b2b69f49Smarc /* 22857e911b15Skarels * if button state has changed */ 22867e911b15Skarels 22877e911b15Skarels a = new_rep->state & 0x07; /*mask nonbutton bits */ 22887e911b15Skarels b = last_rep[qd].state & 0x07; 22897e911b15Skarels 22907e911b15Skarels if (a ^ b) { 22917e911b15Skarels 22927e911b15Skarels for ( c = 1; c < 8; c <<= 1) { 22937e911b15Skarels 22947e911b15Skarels if (!( c & (a ^ b))) /* this button change? */ 22957e911b15Skarels continue; 22967e911b15Skarels 22977e911b15Skarels /* event queue full? (overflow condition) */ 22987e911b15Skarels 22997e911b15Skarels if (ISFULL(eqh) == TRUE) { 23007881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 23017e911b15Skarels break; 23027e911b15Skarels } 23037e911b15Skarels 23047e911b15Skarels event = PUTBEGIN(eqh); /* get new event */ 23057e911b15Skarels PUTEND(eqh); 23067e911b15Skarels 23077e911b15Skarels ++do_wakeup; /* request select wakeup */ 23087e911b15Skarels 23097e911b15Skarels event->vse_x = eqh->curs_pos.x; 23107e911b15Skarels event->vse_y = eqh->curs_pos.y; 23117e911b15Skarels 23127e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */ 23137e911b15Skarels event->vse_type = VSE_BUTTON; /* new button */ 23147e911b15Skarels event->vse_time = TOY; /* time stamp */ 23157e911b15Skarels 23167e911b15Skarels /* flag changed button and if up or down */ 23177e911b15Skarels 23187e911b15Skarels if (c == RIGHT_BUTTON) 23197e911b15Skarels event->vse_key = VSE_RIGHT_BUTTON; 23207e911b15Skarels else if (c == MIDDLE_BUTTON) 23217e911b15Skarels event->vse_key = VSE_MIDDLE_BUTTON; 23227e911b15Skarels else if (c == LEFT_BUTTON) 23237e911b15Skarels event->vse_key = VSE_LEFT_BUTTON; 23247e911b15Skarels 23257e911b15Skarels /* set bit = button depressed */ 23267e911b15Skarels 23277e911b15Skarels if (c & a) 23287e911b15Skarels event->vse_direction = VSE_KBTDOWN; 23297e911b15Skarels else 23307e911b15Skarels event->vse_direction = VSE_KBTUP; 23317e911b15Skarels } 23327e911b15Skarels } 23337e911b15Skarels 23347e911b15Skarels /* refresh last report */ 23357e911b15Skarels 23367e911b15Skarels last_rep[qd] = current_rep[qd]; 23377e911b15Skarels 23387e911b15Skarels } /* get last byte of report */ 23397881ece5Smarc } else if ((status = duart->statusB)&RCV_RDY && 23407e911b15Skarels qdflags[qd].pntr_id == TABLET_ID) { 23417881ece5Smarc /* 23427881ece5Smarc * pickup tablet input, if any 23437881ece5Smarc */ 23447e911b15Skarels if (status&0x70) { 23457e911b15Skarels duart->cmdB = 0x40; 23467e911b15Skarels continue; 23477e911b15Skarels } 23487881ece5Smarc /* 23497881ece5Smarc * event queue full now? (overflow condition) 23507881ece5Smarc */ 23517e911b15Skarels if (ISFULL(eqh) == TRUE) { 23527881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 23537e911b15Skarels break; 23547e911b15Skarels } 23557e911b15Skarels 23567e911b15Skarels data = duart->dataB; /* get report byte */ 23577e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */ 23587e911b15Skarels 2359b2b69f49Smarc /* 23607e911b15Skarels * if 1st byte of report.. */ 23617e911b15Skarels 23627e911b15Skarels if (data & START_FRAME) { 23637e911b15Skarels new_rep->state = data; 23647e911b15Skarels if (new_rep->bytcnt > 1) { 23657e911b15Skarels new_rep->bytcnt = 1; /* start of new frame */ 23667e911b15Skarels continue; /* ..continue looking */ 23677e911b15Skarels } 23687e911b15Skarels } 23697e911b15Skarels 2370b2b69f49Smarc /* 23717e911b15Skarels * if 2nd byte of report.. */ 23727e911b15Skarels 23737e911b15Skarels else if (new_rep->bytcnt == 2) { 23747e911b15Skarels new_rep->dx = data & 0x3F; 23757e911b15Skarels } 23767e911b15Skarels 2377b2b69f49Smarc /* 23787e911b15Skarels * if 3rd byte of report.. */ 23797e911b15Skarels 23807e911b15Skarels else if (new_rep->bytcnt == 3) { 23817e911b15Skarels new_rep->dx |= (data & 0x3F) << 6; 23827e911b15Skarels } 23837e911b15Skarels 2384b2b69f49Smarc /* 23857e911b15Skarels * if 4th byte of report.. */ 23867e911b15Skarels 23877e911b15Skarels else if (new_rep->bytcnt == 4) { 23887e911b15Skarels new_rep->dy = data & 0x3F; 23897e911b15Skarels } 23907e911b15Skarels 2391b2b69f49Smarc /* 23927e911b15Skarels * if 5th byte of report, load input event queue */ 23937e911b15Skarels 23947e911b15Skarels else if (new_rep->bytcnt == 5) { 23957e911b15Skarels 23967e911b15Skarels new_rep->dy |= (data & 0x3F) << 6; 23977e911b15Skarels new_rep->bytcnt = 0; 23987e911b15Skarels 2399b2b69f49Smarc /* 24007e911b15Skarels * update cursor position coordinates */ 24017e911b15Skarels 24027e911b15Skarels new_rep->dx /= qdflags[qd].tab_res; 24037e911b15Skarels new_rep->dy = (2200 - new_rep->dy) 24047e911b15Skarels / qdflags[qd].tab_res; 24057e911b15Skarels 24067e911b15Skarels if (new_rep->dx > 1023) { 24077e911b15Skarels new_rep->dx = 1023; 24087e911b15Skarels } 24097e911b15Skarels if (new_rep->dy > 863) { 24107e911b15Skarels new_rep->dy = 863; 24117e911b15Skarels } 24127e911b15Skarels 24137e911b15Skarels /* 24147e911b15Skarels * report an event if the puck/stylus has moved 24157e911b15Skarels */ 24167e911b15Skarels 24177e911b15Skarels if (eqh->curs_pos.x != new_rep->dx || 24187e911b15Skarels eqh->curs_pos.y != new_rep->dy) { 24197e911b15Skarels 24207e911b15Skarels eqh->curs_pos.x = new_rep->dx; 24217e911b15Skarels eqh->curs_pos.y = new_rep->dy; 24227e911b15Skarels 2423b2b69f49Smarc /* 24247e911b15Skarels * update cursor screen position */ 24257e911b15Skarels 24267e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 24277e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x); 24287e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y); 24297e911b15Skarels 24307e911b15Skarels /* 24317e911b15Skarels * if cursor is in the box, no event report 24327e911b15Skarels */ 24337e911b15Skarels 24347e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right && 24357e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left && 24367e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top && 24377e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) { 24387e911b15Skarels goto GET_TBUTTON; 24397e911b15Skarels } 24407e911b15Skarels 2441b2b69f49Smarc /* 24427e911b15Skarels * report the tablet motion event */ 24437e911b15Skarels 24447e911b15Skarels event = PUTBEGIN(eqh); 24457e911b15Skarels PUTEND(eqh); 24467e911b15Skarels 24477e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 24487e911b15Skarels 24497e911b15Skarels event->vse_x = eqh->curs_pos.x; 24507e911b15Skarels event->vse_y = eqh->curs_pos.y; 24517e911b15Skarels 24527e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */ 24537e911b15Skarels /* 24547e911b15Skarels * right now, X handles tablet motion the same 24557e911b15Skarels * as mouse motion 24567e911b15Skarels */ 24577e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */ 24587e911b15Skarels event->vse_key = 0; 24597e911b15Skarels event->vse_direction = 0; 24607e911b15Skarels event->vse_time = TOY; /* time stamp */ 24617e911b15Skarels } 24627e911b15Skarels GET_TBUTTON: 2463b2b69f49Smarc /* 24647e911b15Skarels * if button state has changed */ 24657e911b15Skarels 24667e911b15Skarels a = new_rep->state & 0x1E; /* mask nonbutton bits */ 24677e911b15Skarels b = last_rep[qd].state & 0x1E; 24687e911b15Skarels 24697e911b15Skarels if (a ^ b) { 24707e911b15Skarels 24717e911b15Skarels /* event queue full now? (overflow condition) */ 24727e911b15Skarels 24737e911b15Skarels if (ISFULL(eqh) == TRUE) { 24747881ece5Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 24757e911b15Skarels break; 24767e911b15Skarels } 24777e911b15Skarels 24787e911b15Skarels event = PUTBEGIN(eqh); /* get new event */ 24797e911b15Skarels PUTEND(eqh); 24807e911b15Skarels 24817e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 24827e911b15Skarels 24837e911b15Skarels event->vse_x = eqh->curs_pos.x; 24847e911b15Skarels event->vse_y = eqh->curs_pos.y; 24857e911b15Skarels 24867e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */ 24877e911b15Skarels event->vse_type = VSE_BUTTON; /* button changed */ 24887e911b15Skarels event->vse_time = TOY; /* time stamp */ 24897e911b15Skarels 24907e911b15Skarels /* define the changed button and if up or down */ 24917e911b15Skarels 24927e911b15Skarels for ( c = 1; c <= 0x10; c <<= 1) { 24937e911b15Skarels if (c & (a ^ b)) { 24947e911b15Skarels if (c == T_LEFT_BUTTON) 24957e911b15Skarels event->vse_key = VSE_T_LEFT_BUTTON; 24967e911b15Skarels else if (c == T_FRONT_BUTTON) 24977e911b15Skarels event->vse_key = VSE_T_FRONT_BUTTON; 24987e911b15Skarels else if (c == T_RIGHT_BUTTON) 24997e911b15Skarels event->vse_key = VSE_T_RIGHT_BUTTON; 25007e911b15Skarels else if (c == T_BACK_BUTTON) 25017e911b15Skarels event->vse_key = VSE_T_BACK_BUTTON; 25027e911b15Skarels break; 25037e911b15Skarels } 25047e911b15Skarels } 25057e911b15Skarels 25067e911b15Skarels /* set bit = button depressed */ 25077e911b15Skarels 25087e911b15Skarels if (c & a) 25097e911b15Skarels event->vse_direction = VSE_KBTDOWN; 25107e911b15Skarels else 25117e911b15Skarels event->vse_direction = VSE_KBTUP; 25127e911b15Skarels } 25137e911b15Skarels 25147e911b15Skarels /* refresh last report */ 25157e911b15Skarels 25167e911b15Skarels last_rep[qd] = current_rep[qd]; 25177e911b15Skarels 25187e911b15Skarels } /* get last byte of report */ 25197e911b15Skarels } /* pick up tablet input */ 25207e911b15Skarels 25217e911b15Skarels } /* while input available.. */ 25227e911b15Skarels 2523b2b69f49Smarc /* 2524b2b69f49Smarc * do select wakeup 2525b2b69f49Smarc */ 25267881ece5Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 25277881ece5Smarc selwakeup(qdrsel[qd], 0); 25287881ece5Smarc qdrsel[qd] = 0; 25297e911b15Skarels qdflags[qd].selmask &= ~SEL_READ; 25307e911b15Skarels do_wakeup = 0; 25317e911b15Skarels } 25327881ece5Smarc } else { 2533b2b69f49Smarc /* 25347881ece5Smarc * if the graphic device is not turned on, this is console input 25357881ece5Smarc */ 25367e911b15Skarels ui = qdinfo[qd]; 25377e911b15Skarels if (ui == 0 || ui->ui_alive == 0) 25387881ece5Smarc return; 25397e911b15Skarels 25407e911b15Skarels tp = &qd_tty[qd << 2]; 25417e911b15Skarels 2542b2b69f49Smarc /* 25437881ece5Smarc * Get a character from the keyboard. 25447881ece5Smarc */ 25457881ece5Smarc while (duart->statusA&RCV_RDY) { 25467e911b15Skarels key = duart->dataA; 25477e911b15Skarels key &= 0xFF; 2548b2b69f49Smarc /* 25497881ece5Smarc * Check for various keyboard errors 25507881ece5Smarc */ 25517e911b15Skarels if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 25527e911b15Skarels key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 25537881ece5Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 25547881ece5Smarc return; 25557e911b15Skarels } 25567e911b15Skarels 25577e911b15Skarels if (key < LK_LOWEST) 25587881ece5Smarc return; 25597e911b15Skarels 2560b2b69f49Smarc /* 25617e911b15Skarels * See if its a state change key */ 25627e911b15Skarels 25637e911b15Skarels switch (key) { 25647e911b15Skarels 25657e911b15Skarels case LOCK: 25667e911b15Skarels q_keyboard.lock ^= 0xffff; /* toggle */ 25677e911b15Skarels if (q_keyboard.lock) 25687881ece5Smarc (void)led_control(qd, LK_LED_ENABLE, 25697881ece5Smarc LK_LED_LOCK); 25707e911b15Skarels else 25717881ece5Smarc (void)led_control(qd, LK_LED_DISABLE, 25727881ece5Smarc LK_LED_LOCK); 25737e911b15Skarels return; 25747e911b15Skarels 25757e911b15Skarels case SHIFT: 25767e911b15Skarels q_keyboard.shift ^= 0xFFFF; 25777e911b15Skarels return; 25787e911b15Skarels 25797e911b15Skarels case CNTRL: 25807e911b15Skarels q_keyboard.cntrl ^= 0xFFFF; 25817e911b15Skarels return; 25827e911b15Skarels 25837e911b15Skarels case ALLUP: 25847e911b15Skarels q_keyboard.cntrl = 0; 25857e911b15Skarels q_keyboard.shift = 0; 25867e911b15Skarels return; 25877e911b15Skarels 25887e911b15Skarels case REPEAT: 25897e911b15Skarels chr = q_keyboard.last; 25907e911b15Skarels break; 25917e911b15Skarels 2592b2b69f49Smarc /* 25937e911b15Skarels * Test for cntrl characters. If set, see if the character 25947e911b15Skarels * is elligible to become a control character. */ 25957e911b15Skarels 25967e911b15Skarels default: 25977e911b15Skarels 25987e911b15Skarels if (q_keyboard.cntrl) { 25997e911b15Skarels chr = q_key[key]; 26007e911b15Skarels if (chr >= ' ' && chr <= '~') 26017e911b15Skarels chr &= 0x1F; 2602e977faadSmarc else if (chr >= 0xA1 && chr <= 0xFE) 2603e977faadSmarc chr &= 0x9F; 26047e911b15Skarels } 26057e911b15Skarels else if( q_keyboard.lock || q_keyboard.shift ) 26067e911b15Skarels chr = q_shift_key[key]; 26077e911b15Skarels else 26087e911b15Skarels chr = q_key[key]; 26097e911b15Skarels break; 26107e911b15Skarels } 26117e911b15Skarels 26127e911b15Skarels q_keyboard.last = chr; 26137e911b15Skarels 2614b2b69f49Smarc /* 26157e911b15Skarels * Check for special function keys */ 26167e911b15Skarels 2617e977faadSmarc if (chr & 0x100) { 26187e911b15Skarels char *string; 26197e911b15Skarels string = q_special[chr & 0x7F]; 26207e911b15Skarels while(*string) 26217e911b15Skarels (*linesw[tp->t_line].l_rint)(*string++, tp); 26227e911b15Skarels } 26237e911b15Skarels else { 2624b2b69f49Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 26257e911b15Skarels } 26267e911b15Skarels } 26277e911b15Skarels } 26287e911b15Skarels } /* qdiint */ 26297e911b15Skarels 26307881ece5Smarc /* 26317e911b15Skarels * 26327881ece5Smarc * Clear the QDSS screen 26337e911b15Skarels * 26347e911b15Skarels * >>> NOTE <<< 26357e911b15Skarels * 26367e911b15Skarels * This code requires that certain adder initialization be valid. To 26377e911b15Skarels * assure that this requirement is satisfied, this routine should be 26387e911b15Skarels * called only after calling the "setup_dragon()" function. 26397e911b15Skarels * 26407e911b15Skarels * Clear the bitmap a piece at a time. Since the fast scroll clear 26417e911b15Skarels * only clears the current displayed portion of the bitmap put a 26427e911b15Skarels * temporary value in the y limit register so we can access whole 26437e911b15Skarels * bitmap 26447e911b15Skarels * 26457881ece5Smarc */ 26467e911b15Skarels clear_qd_screen(unit) 26477e911b15Skarels int unit; 26487e911b15Skarels { 26497e911b15Skarels register struct adder *adder; 26507e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 26517e911b15Skarels 26527e911b15Skarels adder->x_limit = 1024; 26537e911b15Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 26547e911b15Skarels adder->y_offset_pending = 0; 26557881ece5Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 2656b2b69f49Smarc WSV; 26577e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2658b2b69f49Smarc WSV; 26597e911b15Skarels adder->y_offset_pending = 864; 2660b2b69f49Smarc WSV; 26617e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2662b2b69f49Smarc WSV; 26637e911b15Skarels adder->y_offset_pending = 1728; 2664b2b69f49Smarc WSV; 26657e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2666b2b69f49Smarc WSV; 26677e911b15Skarels adder->y_offset_pending = 0; /* back to normal */ 2668b2b69f49Smarc WSV; 26697e911b15Skarels adder->x_limit = MAX_SCREEN_X; 26707e911b15Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 2671b2b69f49Smarc #undef WSV 26727e911b15Skarels 26737e911b15Skarels } /* clear_qd_screen */ 26747e911b15Skarels 26757881ece5Smarc /* 26767881ece5Smarc * kernel console output to the glass tty 26777881ece5Smarc */ 26787e911b15Skarels qdputc(chr) 26797e911b15Skarels register char chr; 26807e911b15Skarels { 26817e911b15Skarels 2682b2b69f49Smarc /* 2683b2b69f49Smarc * if system is now physical, forget it (ie: crash DUMP) 2684b2b69f49Smarc */ 26857e911b15Skarels if ((mfpr(MAPEN) & 1) == 0) 26867e911b15Skarels return; 26877e911b15Skarels 26887881ece5Smarc blitc(0, (u_char)(chr & 0xff)); 268924f67f6bSmarc if ((chr & 0177) == '\n') 269024f67f6bSmarc blitc(0, '\r'); 269124f67f6bSmarc 26927e911b15Skarels } /* qdputc */ 26937e911b15Skarels 2694b2b69f49Smarc /* 26957881ece5Smarc * load the mouse cursor's template RAM bitmap 26967881ece5Smarc */ 26977e911b15Skarels ldcursor(unit, bitmap) 26987881ece5Smarc int unit; 26997881ece5Smarc register short *bitmap; 27007e911b15Skarels { 27017e911b15Skarels register struct dga *dga; 27027e911b15Skarels register short *temp; 27037e911b15Skarels register int i; 27047881ece5Smarc int curs; 27057e911b15Skarels 27067e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 27077e911b15Skarels temp = (short *) qdmap[unit].template; 27087e911b15Skarels 27097e911b15Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 27107881ece5Smarc curs = -1; /* ..note that.. */ 27117e911b15Skarels dga->csr &= ~CURS_ENB; /* ..and shut it off */ 27127881ece5Smarc } else 27137881ece5Smarc curs = 0; 27147e911b15Skarels 27157e911b15Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 27167e911b15Skarels 27177e911b15Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 27187e911b15Skarels /* ..of the 8k WORD template space */ 27197e911b15Skarels for (i = 0; i < 32; ++i) 27207e911b15Skarels *temp++ = *bitmap++; 27217e911b15Skarels 27227881ece5Smarc if (curs) { /* if cursor was enabled.. */ 27237e911b15Skarels dga->csr |= CURS_ENB; /* ..turn it back on */ 27247e911b15Skarels } 27257e911b15Skarels 27267e911b15Skarels } /* ldcursor */ 27277e911b15Skarels 27287881ece5Smarc /* 27297881ece5Smarc * Put the console font in the QDSS off-screen memory 27307881ece5Smarc */ 27317e911b15Skarels ldfont(unit) 27327881ece5Smarc int unit; 27337e911b15Skarels { 27347e911b15Skarels register struct adder *adder; 27357e911b15Skarels 27367881ece5Smarc register i, j, k, max_chars_line; 27377881ece5Smarc register short packed; 27387e911b15Skarels 27397e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 27407e911b15Skarels 2741b2b69f49Smarc /* 27427881ece5Smarc * setup VIPER operand control registers 27437881ece5Smarc */ 27447e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 27457e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 27467e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 27477e911b15Skarels 27487e911b15Skarels write_ID(adder, SRC1_OCR_B, 27497e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 27507e911b15Skarels write_ID(adder, SRC2_OCR_B, 27517e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 27527e911b15Skarels write_ID(adder, DST_OCR_B, 27537e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 27547e911b15Skarels 27557e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 27567e911b15Skarels 2757b2b69f49Smarc /* 27587881ece5Smarc * load destination data 27597881ece5Smarc */ 27607881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 27617e911b15Skarels 27627e911b15Skarels adder->destination_x = FONT_X; 27637e911b15Skarels adder->destination_y = FONT_Y; 27647881ece5Smarc #if FONT_WIDTH > MAX_SCREEN_X 2765e977faadSmarc adder->fast_dest_dx = MAX_SCREEN_X; 27667881ece5Smarc #else 27677e911b15Skarels adder->fast_dest_dx = FONT_WIDTH; 27687881ece5Smarc #endif 27697e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; 27707e911b15Skarels 2771b2b69f49Smarc /* 27727e911b15Skarels * setup for processor to bitmap xfer */ 27737e911b15Skarels 27747e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 27757e911b15Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 27767e911b15Skarels 2777b2b69f49Smarc /* 2778b2b69f49Smarc * Figure out how many characters can be stored on one "line" of 2779b2b69f49Smarc * offscreen memory. 2780e977faadSmarc */ 2781e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2782e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line) 2783e977faadSmarc max_chars_line = CHARS/2 + CHARS%2; 2784e977faadSmarc 2785b2b69f49Smarc /* 2786e977faadSmarc * iteratively do the processor to bitmap xfer */ 2787e977faadSmarc 2788e977faadSmarc for (i = 0; i < ROWS; ++i) { 2789e977faadSmarc 2790e977faadSmarc /* PTOB a scan line */ 2791e977faadSmarc 2792e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) { 2793e977faadSmarc /* PTOB one scan of a char cell */ 2794e977faadSmarc 2795e977faadSmarc packed = q_font[k]; 2796e977faadSmarc k += ROWS; 2797e977faadSmarc packed |= ((short)q_font[k] << 8); 2798e977faadSmarc k += ROWS; 2799e977faadSmarc 28007881ece5Smarc (void)wait_status(adder, TX_READY); 2801e977faadSmarc adder->id_data = packed; 2802e977faadSmarc } 2803e977faadSmarc } 2804e977faadSmarc 2805b2b69f49Smarc /* 2806b2b69f49Smarc * (XXX XXX XXX - should remove) 2807b2b69f49Smarc * 2808b2b69f49Smarc * Copy the second row of characters. Subtract the first 2809b2b69f49Smarc * row from the total number. Divide this quantity by 2 2810b2b69f49Smarc * because 2 chars are stored in a short in the PTOB loop 2811b2b69f49Smarc * below. Figure out how many characters can be stored on 2812b2b69f49Smarc * one "line" of offscreen memory 2813e977faadSmarc */ 2814b2b69f49Smarc 2815e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2816e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line) 2817e977faadSmarc return; 2818e977faadSmarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 2819e977faadSmarc /* Paranoia check to see if 3rd row may be needed */ 2820e977faadSmarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 2821e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2822e977faadSmarc 2823e977faadSmarc adder->destination_x = FONT_X; 2824e977faadSmarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 2825e977faadSmarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 2826e977faadSmarc adder->slow_dest_dy = CHAR_HEIGHT; 2827e977faadSmarc 2828b2b69f49Smarc /* 2829b2b69f49Smarc * setup for processor to bitmap xfer 2830b2b69f49Smarc */ 2831e977faadSmarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 2832e977faadSmarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 2833e977faadSmarc 2834b2b69f49Smarc /* 2835b2b69f49Smarc * iteratively do the processor to bitmap xfer 2836b2b69f49Smarc */ 28377e911b15Skarels for (i = 0; i < ROWS; ++i) { 2838b2b69f49Smarc /* 2839b2b69f49Smarc * PTOB a scan line 2840b2b69f49Smarc */ 2841e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) { 2842b2b69f49Smarc /* 2843b2b69f49Smarc * PTOB one scan of a char cell 2844b2b69f49Smarc */ 2845e977faadSmarc packed = q_font[k + FONT_OFFSET]; 28467e911b15Skarels k += ROWS; 2847e977faadSmarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 28487e911b15Skarels k += ROWS; 28497881ece5Smarc (void)wait_status(adder, TX_READY); 28507e911b15Skarels adder->id_data = packed; 28517e911b15Skarels } 28527e911b15Skarels } 28537e911b15Skarels 28547e911b15Skarels } /* ldfont */ 28557e911b15Skarels 28567881ece5Smarc /* 28577881ece5Smarc * Get a character from the LK201 (polled) 28587881ece5Smarc */ 28597881ece5Smarc qdgetc() 28607e911b15Skarels { 28617881ece5Smarc register short key; 28627881ece5Smarc register char chr; 28637881ece5Smarc register struct duart *duart; 28647881ece5Smarc 28657881ece5Smarc duart = (struct duart *) qdmap[0].duart; 28667881ece5Smarc 28677881ece5Smarc /* 28687881ece5Smarc * Get a character from the keyboard. 28697881ece5Smarc */ 28707881ece5Smarc LOOP: 28717881ece5Smarc while (!(duart->statusA&RCV_RDY)) 28727881ece5Smarc ; 28737881ece5Smarc 28747881ece5Smarc key = duart->dataA; 28757881ece5Smarc key &= 0xFF; 28767881ece5Smarc 28777881ece5Smarc /* 28787881ece5Smarc * Check for various keyboard errors */ 28797881ece5Smarc 28807881ece5Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 28817881ece5Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 28827881ece5Smarc printf("Keyboard error, code = %x\n", key); 28837881ece5Smarc return(0); 28847881ece5Smarc } 28857881ece5Smarc 28867881ece5Smarc if (key < LK_LOWEST) 28877881ece5Smarc return(0); 28887881ece5Smarc 28897881ece5Smarc /* 28907881ece5Smarc * See if its a state change key 28917881ece5Smarc */ 28927881ece5Smarc switch (key) { 28937881ece5Smarc 28947881ece5Smarc case LOCK: 28957881ece5Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 28967881ece5Smarc if (q_keyboard.lock) 28977881ece5Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 28987881ece5Smarc else 28997881ece5Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 29007881ece5Smarc goto LOOP; 29017881ece5Smarc 29027881ece5Smarc case SHIFT: 29037881ece5Smarc q_keyboard.shift ^= 0xFFFF; 29047881ece5Smarc goto LOOP; 29057881ece5Smarc 29067881ece5Smarc case CNTRL: 29077881ece5Smarc q_keyboard.cntrl ^= 0xFFFF; 29087881ece5Smarc goto LOOP; 29097881ece5Smarc 29107881ece5Smarc case ALLUP: 29117881ece5Smarc q_keyboard.cntrl = 0; 29127881ece5Smarc q_keyboard.shift = 0; 29137881ece5Smarc goto LOOP; 29147881ece5Smarc 29157881ece5Smarc case REPEAT: 29167881ece5Smarc chr = q_keyboard.last; 29177881ece5Smarc break; 29187881ece5Smarc 29197881ece5Smarc /* 29207881ece5Smarc * Test for cntrl characters. If set, see if the character 29217881ece5Smarc * is elligible to become a control character. 29227881ece5Smarc */ 29237881ece5Smarc default: 29247881ece5Smarc 29257881ece5Smarc if (q_keyboard.cntrl) { 29267881ece5Smarc chr = q_key[key]; 29277881ece5Smarc if (chr >= ' ' && chr <= '~') 29287881ece5Smarc chr &= 0x1F; 29297881ece5Smarc } 29307881ece5Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 29317881ece5Smarc chr = q_shift_key[key]; 29327881ece5Smarc else 29337881ece5Smarc chr = q_key[key]; 29347881ece5Smarc break; 29357881ece5Smarc } 29367881ece5Smarc 29377881ece5Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 29387881ece5Smarc return(0); /* ..then pitch it! */ 29397881ece5Smarc 29407881ece5Smarc q_keyboard.last = chr; 29417881ece5Smarc 29427881ece5Smarc /* 29437881ece5Smarc * Check for special function keys */ 29447881ece5Smarc 29457881ece5Smarc if (chr & 0x80) /* pitch the function keys */ 29467881ece5Smarc return(0); 29477881ece5Smarc else 29487881ece5Smarc return(chr); 29497881ece5Smarc 29507881ece5Smarc } /* qdgetc */ 29517881ece5Smarc 29527881ece5Smarc /* 29537881ece5Smarc * led_control()... twiddle LK-201 LED's 29547881ece5Smarc */ 29557881ece5Smarc led_control(unit, cmd, led_mask) 29567881ece5Smarc int unit, cmd, led_mask; 29577881ece5Smarc { 29587881ece5Smarc register i; 29597e911b15Skarels register struct duart *duart; 29607e911b15Skarels 29617e911b15Skarels duart = (struct duart *)qdmap[unit].duart; 29627e911b15Skarels 29637e911b15Skarels for (i = 1000; i > 0; --i) { 29647881ece5Smarc if (duart->statusA&XMT_RDY) { 29657e911b15Skarels duart->dataA = cmd; 29667e911b15Skarels break; 29677e911b15Skarels } 29687e911b15Skarels } 29697e911b15Skarels for (i = 1000; i > 0; --i) { 29707881ece5Smarc if (duart->statusA&XMT_RDY) { 29717e911b15Skarels duart->dataA = led_mask; 29727e911b15Skarels break; 29737e911b15Skarels } 29747e911b15Skarels } 29757e911b15Skarels if (i == 0) 29767e911b15Skarels return(BAD); 29777e911b15Skarels return(GOOD); 29787e911b15Skarels 29797e911b15Skarels } /* led_control */ 29807e911b15Skarels 29817881ece5Smarc /* 29827e911b15Skarels * scroll_up()... move the screen up one character height 29837881ece5Smarc */ 29847e911b15Skarels scroll_up(adder) 29857e911b15Skarels register struct adder *adder; 29867e911b15Skarels { 2987b2b69f49Smarc /* 2988b2b69f49Smarc * setup VIPER operand control registers 2989b2b69f49Smarc */ 29907881ece5Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 29917e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 29927e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 29937e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 29947e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 29957e911b15Skarels write_ID(adder, SRC1_OCR_B, 29967e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 29977e911b15Skarels write_ID(adder, DST_OCR_B, 29987e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 2999b2b69f49Smarc /* 3000b2b69f49Smarc * load DESTINATION origin and vectors 3001b2b69f49Smarc */ 30027e911b15Skarels adder->fast_dest_dy = 0; 30037e911b15Skarels adder->slow_dest_dx = 0; 30047e911b15Skarels adder->error_1 = 0; 30057e911b15Skarels adder->error_2 = 0; 30067e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 30077e911b15Skarels adder->destination_x = 0; 30087e911b15Skarels adder->fast_dest_dx = 1024; 30097e911b15Skarels adder->destination_y = 0; 30107e911b15Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 3011b2b69f49Smarc /* 3012b2b69f49Smarc * load SOURCE origin and vectors 3013b2b69f49Smarc */ 30147e911b15Skarels adder->source_1_x = 0; 30157e911b15Skarels adder->source_1_dx = 1024; 30167e911b15Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 30177e911b15Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 30187e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 30197e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 3020b2b69f49Smarc /* 3021b2b69f49Smarc * do a rectangle clear of last screen line 3022b2b69f49Smarc */ 30237e911b15Skarels write_ID(adder, MASK_1, 0xffff); 30247e911b15Skarels write_ID(adder, SOURCE, 0xffff); 30257e911b15Skarels write_ID(adder,DST_OCR_B, 30267e911b15Skarels (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 30277e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 30287e911b15Skarels adder->error_1 = 0; 30297e911b15Skarels adder->error_2 = 0; 30307e911b15Skarels adder->slow_dest_dx = 0; /* set up the width of */ 30317e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 30327e911b15Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 30337881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 30347e911b15Skarels adder->destination_x = 0; 30357e911b15Skarels adder->destination_y = 864 - CHAR_HEIGHT; 30367e911b15Skarels adder->fast_dest_dx = 1024; /* set up the height */ 30377e911b15Skarels adder->fast_dest_dy = 0; /* of rectangle */ 30387e911b15Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 30397e911b15Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 30407e911b15Skarels 30417e911b15Skarels } /* scroll_up */ 30427e911b15Skarels 30437881ece5Smarc /* 30447881ece5Smarc * init shared memory pointers and structures 30457881ece5Smarc */ 30467e911b15Skarels init_shared(unit) 30477881ece5Smarc register unit; 30487e911b15Skarels { 30497e911b15Skarels register struct dga *dga; 30507e911b15Skarels 30517e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 30527e911b15Skarels 3053b2b69f49Smarc /* 30547e911b15Skarels * initialize the event queue pointers and header */ 30557e911b15Skarels 30567e911b15Skarels eq_header[unit] = (struct qdinput *) 30577e911b15Skarels ((((int)event_shared & ~(0x01FF)) + 512) 30587e911b15Skarels + (EVENT_BUFSIZE * unit)); 30597e911b15Skarels eq_header[unit]->curs_pos.x = 0; 30607e911b15Skarels eq_header[unit]->curs_pos.y = 0; 30617e911b15Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 30627e911b15Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 30637e911b15Skarels eq_header[unit]->curs_box.left = 0; 30647e911b15Skarels eq_header[unit]->curs_box.right = 0; 30657e911b15Skarels eq_header[unit]->curs_box.top = 0; 30667e911b15Skarels eq_header[unit]->curs_box.bottom = 0; 3067b2b69f49Smarc /* 3068b2b69f49Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 3069b2b69f49Smarc */ 30707e911b15Skarels DMAheader[unit] = (struct DMAreq_header *) 30717e911b15Skarels (((int)(&DMA_shared[0] + 512) & ~0x1FF) 30727e911b15Skarels + (DMAbuf_size * unit)); 30737e911b15Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 30747e911b15Skarels + sizeof(struct DMAreq_header)); 30757e911b15Skarels DMAheader[unit]->QBAreg = 0; 30767e911b15Skarels DMAheader[unit]->status = 0; 30777e911b15Skarels DMAheader[unit]->shared_size = DMAbuf_size; 30787e911b15Skarels DMAheader[unit]->used = 0; 30797e911b15Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 30807e911b15Skarels DMAheader[unit]->oldest = 0; 30817e911b15Skarels DMAheader[unit]->newest = 0; 3082b2b69f49Smarc /* 3083b2b69f49Smarc * assign a pointer to the scroll structure for this QDSS. 3084b2b69f49Smarc */ 30857e911b15Skarels scroll[unit] = (struct scroll *) 30867e911b15Skarels (((int)(&scroll_shared[0] + 512) & ~0x1FF) 30877e911b15Skarels + (sizeof(struct scroll) * unit)); 30887e911b15Skarels scroll[unit]->status = 0; 30897e911b15Skarels scroll[unit]->viper_constant = 0; 30907e911b15Skarels scroll[unit]->y_scroll_constant = 0; 30917e911b15Skarels scroll[unit]->y_offset = 0; 30927e911b15Skarels scroll[unit]->x_index_pending = 0; 30937e911b15Skarels scroll[unit]->y_index_pending = 0; 3094b2b69f49Smarc /* 3095b2b69f49Smarc * assign a pointer to the color map write buffer for this QDSS 3096b2b69f49Smarc */ 30977e911b15Skarels color_buf[unit] = (struct color_buf *) 30987e911b15Skarels (((int)(&color_shared[0] + 512) & ~0x1FF) 30997e911b15Skarels + (COLOR_BUFSIZ * unit)); 31007e911b15Skarels color_buf[unit]->status = 0; 31017e911b15Skarels color_buf[unit]->count = 0; 31027e911b15Skarels 31037e911b15Skarels } /* init_shared */ 31047e911b15Skarels 31057881ece5Smarc /* 31067881ece5Smarc * init the ADDER, VIPER, bitmaps, & color map 31077881ece5Smarc */ 31087e911b15Skarels setup_dragon(unit) 31097881ece5Smarc int unit; 31107e911b15Skarels { 31117e911b15Skarels 31127e911b15Skarels register struct adder *adder; 31137e911b15Skarels register struct dga *dga; 31147e911b15Skarels short *memcsr; 31157881ece5Smarc register i; 31167e911b15Skarels short top; /* clipping/scrolling boundaries */ 31177e911b15Skarels short bottom; 31187e911b15Skarels short right; 31197e911b15Skarels short left; 31207e911b15Skarels short *red; /* color map pointers */ 31217e911b15Skarels short *green; 31227e911b15Skarels short *blue; 31237e911b15Skarels 3124b2b69f49Smarc /* 3125b2b69f49Smarc * init for setup 3126b2b69f49Smarc */ 31277e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 31287e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 31297e911b15Skarels memcsr = (short *) qdmap[unit].memcsr; 31307e911b15Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 31317e911b15Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 31327e911b15Skarels adder->command = CANCEL; 3133b2b69f49Smarc /* 3134b2b69f49Smarc * set monitor timing 3135b2b69f49Smarc */ 31367e911b15Skarels adder->x_scan_count_0 = 0x2800; 31377e911b15Skarels adder->x_scan_count_1 = 0x1020; 31387e911b15Skarels adder->x_scan_count_2 = 0x003A; 31397e911b15Skarels adder->x_scan_count_3 = 0x38F0; 31407e911b15Skarels adder->x_scan_count_4 = 0x6128; 31417e911b15Skarels adder->x_scan_count_5 = 0x093A; 31427e911b15Skarels adder->x_scan_count_6 = 0x313C; 31437e911b15Skarels adder->sync_phase_adj = 0x0100; 31447e911b15Skarels adder->x_scan_conf = 0x00C8; 3145b2b69f49Smarc /* 3146b2b69f49Smarc * got a bug in secound pass ADDER! lets take care of it 3147b2b69f49Smarc * 3148b2b69f49Smarc * normally, just use the code in the following bug fix code, but to 31497e911b15Skarels * make repeated demos look pretty, load the registers as if there was 3150b2b69f49Smarc * no bug and then test to see if we are getting sync 3151b2b69f49Smarc */ 31527e911b15Skarels adder->y_scan_count_0 = 0x135F; 31537e911b15Skarels adder->y_scan_count_1 = 0x3363; 31547e911b15Skarels adder->y_scan_count_2 = 0x2366; 31557e911b15Skarels adder->y_scan_count_3 = 0x0388; 3156b2b69f49Smarc /* 3157b2b69f49Smarc * if no sync, do the bug fix code 3158b2b69f49Smarc */ 31597e911b15Skarels if (wait_status(adder, VSYNC) == BAD) { 31607e911b15Skarels /* first load all Y scan registers with very short frame and 31617e911b15Skarels * wait for scroll service. This guarantees at least one SYNC 31627e911b15Skarels * to fix the pass 2 Adder initialization bug (synchronizes 3163b2b69f49Smarc * XCINCH with DMSEEDH) 3164b2b69f49Smarc */ 31657e911b15Skarels adder->y_scan_count_0 = 0x01; 31667e911b15Skarels adder->y_scan_count_1 = 0x01; 31677e911b15Skarels adder->y_scan_count_2 = 0x01; 31687e911b15Skarels adder->y_scan_count_3 = 0x01; 3169b2b69f49Smarc /* 3170b2b69f49Smarc * delay at least 1 full frame time 3171b2b69f49Smarc */ 31727881ece5Smarc (void)wait_status(adder, VSYNC); 31737881ece5Smarc (void)wait_status(adder, VSYNC); 3174b2b69f49Smarc /* 3175b2b69f49Smarc * now load the REAL sync values (in reverse order just to 3176b2b69f49Smarc * be safe. 3177b2b69f49Smarc */ 31787e911b15Skarels adder->y_scan_count_3 = 0x0388; 31797e911b15Skarels adder->y_scan_count_2 = 0x2366; 31807e911b15Skarels adder->y_scan_count_1 = 0x3363; 31817e911b15Skarels adder->y_scan_count_0 = 0x135F; 31827e911b15Skarels } 31837e911b15Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 3184b2b69f49Smarc /* 3185b2b69f49Smarc * zero the index registers 3186b2b69f49Smarc */ 31877e911b15Skarels adder->x_index_pending = 0; 31887e911b15Skarels adder->y_index_pending = 0; 31897e911b15Skarels adder->x_index_new = 0; 31907e911b15Skarels adder->y_index_new = 0; 31917e911b15Skarels adder->x_index_old = 0; 31927e911b15Skarels adder->y_index_old = 0; 31937e911b15Skarels adder->pause = 0; 3194b2b69f49Smarc /* 3195b2b69f49Smarc * set rasterop mode to normal pen down 3196b2b69f49Smarc */ 31977e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 3198b2b69f49Smarc /* 3199b2b69f49Smarc * set the rasterop registers to a default values 3200b2b69f49Smarc */ 32017e911b15Skarels adder->source_1_dx = 1; 32027e911b15Skarels adder->source_1_dy = 1; 32037e911b15Skarels adder->source_1_x = 0; 32047e911b15Skarels adder->source_1_y = 0; 32057e911b15Skarels adder->destination_x = 0; 32067e911b15Skarels adder->destination_y = 0; 32077e911b15Skarels adder->fast_dest_dx = 1; 32087e911b15Skarels adder->fast_dest_dy = 0; 32097e911b15Skarels adder->slow_dest_dx = 0; 32107e911b15Skarels adder->slow_dest_dy = 1; 32117e911b15Skarels adder->error_1 = 0; 32127e911b15Skarels adder->error_2 = 0; 3213b2b69f49Smarc /* 32147881ece5Smarc * scale factor = UNITY 3215b2b69f49Smarc */ 32167e911b15Skarels adder->fast_scale = UNITY; 32177e911b15Skarels adder->slow_scale = UNITY; 3218b2b69f49Smarc /* 3219b2b69f49Smarc * set the source 2 parameters 3220b2b69f49Smarc */ 32217e911b15Skarels adder->source_2_x = 0; 32227e911b15Skarels adder->source_2_y = 0; 32237e911b15Skarels adder->source_2_size = 0x0022; 3224b2b69f49Smarc /* 3225b2b69f49Smarc * initialize plane addresses for eight vipers 3226b2b69f49Smarc */ 32277e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 32287e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 32297e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 32307e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 32317e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 32327e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 32337e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 32347e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 32357e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 32367e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 32377e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 32387e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 32397e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 32407e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 32417e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 32427e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 3243b2b69f49Smarc /* 3244b2b69f49Smarc * initialize the external registers. 3245b2b69f49Smarc */ 32467e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 32477e911b15Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 3248b2b69f49Smarc /* 3249b2b69f49Smarc * initialize resolution mode 3250b2b69f49Smarc */ 32517e911b15Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 32527e911b15Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 3253b2b69f49Smarc /* 3254b2b69f49Smarc * initialize viper registers 3255b2b69f49Smarc */ 32567e911b15Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 32577e911b15Skarels write_ID(adder, SCROLL_FILL, 0x0000); 3258b2b69f49Smarc /* 3259b2b69f49Smarc * set clipping and scrolling limits to full screen 3260b2b69f49Smarc */ 3261b2b69f49Smarc for (i = 1000, adder->status = 0; 32627881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 3263b2b69f49Smarc ; 32647e911b15Skarels if (i == 0) 32657881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 32667e911b15Skarels top = 0; 32677e911b15Skarels bottom = 2048; 32687e911b15Skarels left = 0; 32697e911b15Skarels right = 1024; 32707e911b15Skarels adder->x_clip_min = left; 32717e911b15Skarels adder->x_clip_max = right; 32727e911b15Skarels adder->y_clip_min = top; 32737e911b15Skarels adder->y_clip_max = bottom; 32747e911b15Skarels adder->scroll_x_min = left; 32757e911b15Skarels adder->scroll_x_max = right; 32767e911b15Skarels adder->scroll_y_min = top; 32777e911b15Skarels adder->scroll_y_max = bottom; 32787881ece5Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 32797881ece5Smarc (void)wait_status(adder, VSYNC); 32807e911b15Skarels adder->x_index_pending = left; 32817e911b15Skarels adder->y_index_pending = top; 32827e911b15Skarels adder->x_index_new = left; 32837e911b15Skarels adder->y_index_new = top; 32847e911b15Skarels adder->x_index_old = left; 32857e911b15Skarels adder->y_index_old = top; 32867e911b15Skarels 32877881ece5Smarc for (i = 1000, adder->status = 0; i > 0 && 32887881ece5Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 3289b2b69f49Smarc ; 32907e911b15Skarels if (i == 0) 32917881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 32927e911b15Skarels 32937e911b15Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 32947e911b15Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 3295b2b69f49Smarc /* 3296b2b69f49Smarc * set source and the mask register to all ones (ie: white) o 3297b2b69f49Smarc */ 32987e911b15Skarels write_ID(adder, SOURCE, 0xFFFF); 32997e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 33007e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 33017e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 3302b2b69f49Smarc /* 3303b2b69f49Smarc * initialize Operand Control Register banks for fill command 3304b2b69f49Smarc */ 33057e911b15Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 33067e911b15Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 33077e911b15Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 33087e911b15Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 33097e911b15Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 33107e911b15Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 3311b2b69f49Smarc /* 33127e911b15Skarels * init Logic Unit Function registers, (these are just common values, 3313b2b69f49Smarc * and may be changed as required). 3314b2b69f49Smarc */ 33157e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 3316b2b69f49Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 3317b2b69f49Smarc INV_M1_M2); 33187e911b15Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 33197e911b15Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 3320b2b69f49Smarc /* 3321b2b69f49Smarc * load the color map for black & white 3322b2b69f49Smarc */ 33237881ece5Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 3324b2b69f49Smarc ; 33257e911b15Skarels 33267e911b15Skarels if (i == 0) 33277881ece5Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 33287e911b15Skarels 33297e911b15Skarels red = (short *) qdmap[unit].red; 33307e911b15Skarels green = (short *) qdmap[unit].green; 33317e911b15Skarels blue = (short *) qdmap[unit].blue; 33327e911b15Skarels 33337e911b15Skarels *red++ = 0x00; /* black */ 33347e911b15Skarels *green++ = 0x00; 33357e911b15Skarels *blue++ = 0x00; 33367e911b15Skarels 33377e911b15Skarels *red-- = 0xFF; /* white */ 33387e911b15Skarels *green-- = 0xFF; 33397e911b15Skarels *blue-- = 0xFF; 33407e911b15Skarels 3341b2b69f49Smarc /* 33427881ece5Smarc * set color map for mouse cursor 33437881ece5Smarc */ 33447e911b15Skarels 33457e911b15Skarels red += 254; 33467e911b15Skarels green += 254; 33477e911b15Skarels blue += 254; 33487e911b15Skarels 33497e911b15Skarels *red++ = 0x00; /* black */ 33507e911b15Skarels *green++ = 0x00; 33517e911b15Skarels *blue++ = 0x00; 33527e911b15Skarels 33537e911b15Skarels *red = 0xFF; /* white */ 33547e911b15Skarels *green = 0xFF; 33557e911b15Skarels *blue = 0xFF; 33567e911b15Skarels 33577e911b15Skarels } /* setup_dragon */ 33587e911b15Skarels 33597881ece5Smarc /* 33607881ece5Smarc * Init the DUART and set defaults in input 33617881ece5Smarc */ 33627e911b15Skarels setup_input(unit) 33637881ece5Smarc int unit; 33647e911b15Skarels { 33657e911b15Skarels register struct duart *duart; /* DUART register structure pointer */ 33667881ece5Smarc register i, bits; 33677e911b15Skarels char id_byte; 33687e911b15Skarels 33697e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 33707e911b15Skarels duart->imask = 0; 33717e911b15Skarels 3372b2b69f49Smarc /* 3373b2b69f49Smarc * setup the DUART for kbd & pointing device 3374b2b69f49Smarc */ 33757e911b15Skarels duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 33767e911b15Skarels duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 33777e911b15Skarels /* no RTS control,char error mode */ 33787e911b15Skarels duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 33797e911b15Skarels /* no RTS control,no echo or loop */ 33807e911b15Skarels duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 33817e911b15Skarels duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 33827e911b15Skarels /* ..no RTS cntrl, char error mode */ 33837e911b15Skarels duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 33847e911b15Skarels /* no RTS control,no echo or loop */ 33857e911b15Skarels duart->auxctl = 0x00; /* baud rate set 1 */ 33867e911b15Skarels duart->clkselA = 0x99; /* 4800 baud for kbd */ 33877e911b15Skarels duart->clkselB = 0x99; /* 4800 baud for mouse */ 33887e911b15Skarels 33897e911b15Skarels /* reset everything for keyboard */ 33907e911b15Skarels 33917e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 33927e911b15Skarels duart->cmdA = bits; 33937e911b15Skarels 33947e911b15Skarels /* reset everything for host */ 33957e911b15Skarels 33967e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 33977e911b15Skarels duart->cmdB = bits; 33987e911b15Skarels 33997e911b15Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 34007e911b15Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 34017e911b15Skarels 3402b2b69f49Smarc /* 34037881ece5Smarc * init keyboard defaults (DUART channel A) 34047881ece5Smarc */ 34057e911b15Skarels for (i = 500; i > 0; --i) { 34067881ece5Smarc if (duart->statusA&XMT_RDY) { 34077e911b15Skarels duart->dataA = LK_DEFAULTS; 34087e911b15Skarels break; 34097e911b15Skarels } 34107e911b15Skarels } 34117e911b15Skarels 34127e911b15Skarels for (i = 100000; i > 0; --i) { 34137881ece5Smarc if (duart->statusA&RCV_RDY) { 34147e911b15Skarels break; 34157e911b15Skarels } 34167e911b15Skarels } 34177e911b15Skarels 34187881ece5Smarc if (duart->dataA) /* flush the ACK */ 34197881ece5Smarc ; 34207e911b15Skarels 3421b2b69f49Smarc /* 34227881ece5Smarc * identify the pointing device 34237881ece5Smarc */ 34247e911b15Skarels for (i = 500; i > 0; --i) { 34257881ece5Smarc if (duart->statusB&XMT_RDY) { 34267e911b15Skarels duart->dataB = SELF_TEST; 34277e911b15Skarels break; 34287e911b15Skarels } 34297e911b15Skarels } 34307e911b15Skarels 3431b2b69f49Smarc /* 34327e911b15Skarels * wait for 1st byte of self test report */ 34337e911b15Skarels 34347e911b15Skarels for (i = 100000; i > 0; --i) { 34357881ece5Smarc if (duart->statusB&RCV_RDY) { 34367e911b15Skarels break; 34377e911b15Skarels } 34387e911b15Skarels } 34397e911b15Skarels 34407e911b15Skarels if (i == 0) { 34417881ece5Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 3442b2b69f49Smarc ,unit); 34437e911b15Skarels goto OUT; 34447e911b15Skarels } 34457e911b15Skarels 34467881ece5Smarc if (duart->dataB) 34477881ece5Smarc ; 34487e911b15Skarels 3449b2b69f49Smarc /* 34507881ece5Smarc * wait for ID byte of self test report 34517881ece5Smarc */ 34527e911b15Skarels for (i = 100000; i > 0; --i) { 34537881ece5Smarc if (duart->statusB&RCV_RDY) { 34547e911b15Skarels break; 34557e911b15Skarels } 34567e911b15Skarels } 34577e911b15Skarels 34587e911b15Skarels if (i == 0) { 34597881ece5Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 34607e911b15Skarels goto OUT; 34617e911b15Skarels } 34627e911b15Skarels 34637e911b15Skarels id_byte = duart->dataB; 34647e911b15Skarels 3465b2b69f49Smarc /* 34667881ece5Smarc * wait for other bytes to come in 34677881ece5Smarc */ 34687e911b15Skarels for (i = 100000; i > 0; --i) { 34697881ece5Smarc if (duart->statusB & RCV_RDY) { 34707881ece5Smarc if (duart->dataB) 34717881ece5Smarc ; 34727e911b15Skarels break; 34737e911b15Skarels } 34747e911b15Skarels } 34757e911b15Skarels if (i == 0) { 34767881ece5Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 34777e911b15Skarels goto OUT; 34787e911b15Skarels } 34797e911b15Skarels for (i = 100000; i > 0; --i) { 34807881ece5Smarc if (duart->statusB&RCV_RDY) { 34817881ece5Smarc if (duart->dataB) 34827881ece5Smarc ; 34837e911b15Skarels break; 34847e911b15Skarels } 34857e911b15Skarels } 34867e911b15Skarels if (i == 0) { 34877881ece5Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 34887e911b15Skarels goto OUT; 34897e911b15Skarels } 3490b2b69f49Smarc /* 34917881ece5Smarc * flag pointing device type and set defaults 34927881ece5Smarc */ 34937881ece5Smarc for (i=100000; i>0; --i) 34947881ece5Smarc ; /*XXX*/ 34957e911b15Skarels 34967e911b15Skarels if ((id_byte & 0x0F) != TABLET_ID) { 34977e911b15Skarels qdflags[unit].pntr_id = MOUSE_ID; 34987e911b15Skarels 34997e911b15Skarels for (i = 500; i > 0; --i) { 35007881ece5Smarc if (duart->statusB&XMT_RDY) { 35017e911b15Skarels duart->dataB = INC_STREAM_MODE; 35027e911b15Skarels break; 35037e911b15Skarels } 35047e911b15Skarels } 3505b2b69f49Smarc } 3506b2b69f49Smarc else { 35077e911b15Skarels qdflags[unit].pntr_id = TABLET_ID; 35087e911b15Skarels 35097e911b15Skarels for (i = 500; i > 0; --i) { 35107881ece5Smarc if (duart->statusB&XMT_RDY) { 35117e911b15Skarels duart->dataB = T_STREAM; 35127e911b15Skarels break; 35137e911b15Skarels } 35147e911b15Skarels } 35157e911b15Skarels } 35167e911b15Skarels OUT: 35177e911b15Skarels duart->imask = qdflags[unit].duart_imask; 35187e911b15Skarels 35197e911b15Skarels } /* setup_input */ 35207e911b15Skarels 35217881ece5Smarc /* 35227881ece5Smarc * delay for at least one display frame time 35237e911b15Skarels * 35247e911b15Skarels * return: BAD means that we timed out without ever seeing the 35257e911b15Skarels * vertical sync status bit 35267e911b15Skarels * GOOD otherwise 35277881ece5Smarc */ 35287e911b15Skarels wait_status(adder, mask) 35297e911b15Skarels register struct adder *adder; 35307e911b15Skarels register int mask; 35317e911b15Skarels { 35327881ece5Smarc register i; 35337e911b15Skarels 3534b2b69f49Smarc for (i = 10000, adder->status = 0 ; i > 0 && 35357881ece5Smarc !(adder->status&mask) ; --i) 3536b2b69f49Smarc ; 35377e911b15Skarels 35387e911b15Skarels if (i == 0) { 35397881ece5Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 35407e911b15Skarels return(BAD); 35417e911b15Skarels } 35427e911b15Skarels 35437e911b15Skarels return(GOOD); 35447e911b15Skarels 35457e911b15Skarels } /* wait_status */ 35467e911b15Skarels 35477881ece5Smarc /* 35487881ece5Smarc * write out onto the ID bus 35497881ece5Smarc */ 35507e911b15Skarels write_ID(adder, adrs, data) 35517e911b15Skarels register struct adder *adder; 35527e911b15Skarels register short adrs; 35537e911b15Skarels register short data; 35547e911b15Skarels { 35557881ece5Smarc register i; 35567e911b15Skarels 3557b2b69f49Smarc for (i = 100000, adder->status = 0 ; 35587881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 3559b2b69f49Smarc ; 35607e911b15Skarels 35617e911b15Skarels if (i == 0) 35627e911b15Skarels goto ERR; 35637e911b15Skarels 3564b2b69f49Smarc for (i = 100000, adder->status = 0 ; 35657881ece5Smarc i > 0 && !(adder->status&TX_READY) ; --i) 3566b2b69f49Smarc ; 35677e911b15Skarels 35687e911b15Skarels if (i > 0) { 35697e911b15Skarels adder->id_data = data; 35707e911b15Skarels adder->command = ID_LOAD | adrs; 35717881ece5Smarc return ; 35727e911b15Skarels } 35737e911b15Skarels 35747e911b15Skarels ERR: 35757881ece5Smarc printf("write_ID: timeout trying to write to VIPER\n"); 35767881ece5Smarc return ; 35777e911b15Skarels 35787e911b15Skarels } /* write_ID */ 3579006e9885Smarc #endif 3580