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*f79d7b48Smarc * @(#)qd.c 1.15 (Berkeley) 04/05/90 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" 5019612d62Smckusick #include "machine/pte.h" 5119612d62Smckusick #include "machine/mtpr.h" 5219612d62Smckusick #include "machine/cpu.h" 53b2b69f49Smarc #include "param.h" 54b2b69f49Smarc #include "conf.h" 55b2b69f49Smarc #include "user.h" 56b2b69f49Smarc #include "qdioctl.h" 57006e9885Smarc #include "tty.h" 58b2b69f49Smarc #include "map.h" 59b2b69f49Smarc #include "buf.h" 60b2b69f49Smarc #include "vm.h" 61b2b69f49Smarc #include "clist.h" 62b2b69f49Smarc #include "file.h" 63b2b69f49Smarc #include "uio.h" 64b2b69f49Smarc #include "kernel.h" 65e977faadSmarc #include "exec.h" 66e977faadSmarc #include "proc.h" 67b2b69f49Smarc #include "ubareg.h" 68b2b69f49Smarc #include "ubavar.h" 69e977faadSmarc #include "syslog.h" 70b2b69f49Smarc #include "qduser.h" /* definitions shared with user level client */ 71e977faadSmarc #include "qdreg.h" /* QDSS device register structures */ 7224f67f6bSmarc 73b2b69f49Smarc /* 74b2b69f49Smarc * QDSS driver status flags for tracking operational state 75b2b69f49Smarc */ 7624f67f6bSmarc struct qdflags { 7724f67f6bSmarc u_int inuse; /* which minor dev's are in use now */ 7824f67f6bSmarc u_int config; /* I/O page register content */ 7924f67f6bSmarc u_int mapped; /* user mapping status word */ 80e977faadSmarc u_int kernel_loop; /* if kernel console is redirected */ 8124f67f6bSmarc u_int user_dma; /* DMA from user space in progress */ 8224f67f6bSmarc u_short pntr_id; /* type code of pointing device */ 8324f67f6bSmarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 8424f67f6bSmarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 8524f67f6bSmarc u_short curs_acc; /* cursor acceleration factor */ 8624f67f6bSmarc u_short curs_thr; /* cursor acceleration threshold level */ 8724f67f6bSmarc u_short tab_res; /* tablet resolution factor */ 8824f67f6bSmarc u_short selmask; /* mask for active qd select entries */ 8924f67f6bSmarc }; 9024f67f6bSmarc 91b2b69f49Smarc /* 92b2b69f49Smarc * bit definitions for 'inuse' entry 93b2b69f49Smarc */ 9424f67f6bSmarc #define CONS_DEV 0x01 9524f67f6bSmarc #define GRAPHIC_DEV 0x04 9624f67f6bSmarc 97b2b69f49Smarc /* 98b2b69f49Smarc * bit definitions for 'mapped' member of flag structure 99b2b69f49Smarc */ 10024f67f6bSmarc #define MAPDEV 0x01 /* hardware is mapped */ 10124f67f6bSmarc #define MAPDMA 0x02 /* DMA buffer mapped */ 10224f67f6bSmarc #define MAPEQ 0x04 /* event queue buffer mapped */ 10324f67f6bSmarc #define MAPSCR 0x08 /* scroll param area mapped */ 10424f67f6bSmarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 10524f67f6bSmarc 106b2b69f49Smarc /* 107b2b69f49Smarc * bit definitions for 'selmask' member of qdflag structure 108b2b69f49Smarc */ 10924f67f6bSmarc #define SEL_READ 0x01 /* read select is active */ 11024f67f6bSmarc #define SEL_WRITE 0x02 /* write select is active */ 11124f67f6bSmarc 112b2b69f49Smarc /* 113b2b69f49Smarc * constants used in shared memory operations 114b2b69f49Smarc */ 11524f67f6bSmarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 11624f67f6bSmarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 11724f67f6bSmarc / sizeof(struct _vs_event) ) 1180d59d4d6Smarc #define DMA_BUFSIZ (1024 * 10) 11924f67f6bSmarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 12024f67f6bSmarc 121b2b69f49Smarc /* 12224f67f6bSmarc * reference to an array of "uba_device" structures built by the auto 12324f67f6bSmarc * configuration program. The uba_device structure decribes the device 12424f67f6bSmarc * sufficiently for the driver to talk to it. The auto configuration code 12524f67f6bSmarc * fills in the uba_device structures (located in ioconf.c) from user 126b2b69f49Smarc * maintained info. 127b2b69f49Smarc */ 12824f67f6bSmarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 12924f67f6bSmarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 1307881ece5Smarc extern char qvmem[][128*NBPG]; 131b2b69f49Smarc extern struct pte QVmap[][128]; 132b2b69f49Smarc #define CHUNK (64 * 1024) 133b2b69f49Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 13424f67f6bSmarc 135b2b69f49Smarc /* 136b2b69f49Smarc * static storage used by multiple functions in this code 137b2b69f49Smarc */ 13824f67f6bSmarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 13924f67f6bSmarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 14024f67f6bSmarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 14124f67f6bSmarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 14224f67f6bSmarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 143b2b69f49Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 14424f67f6bSmarc 145b2b69f49Smarc /* 146e977faadSmarc * the array "event_shared[]" is made up of a number of event queue buffers 14724f67f6bSmarc * equal to the number of QDSS's configured into the running kernel (NQD). 14824f67f6bSmarc * Each event queue buffer begins with an event queue header (struct qdinput) 14924f67f6bSmarc * followed by a group of event queue entries (struct _vs_event). The array 15024f67f6bSmarc * "*eq_header[]" is an array of pointers to the start of each event queue 151b2b69f49Smarc * buffer in "event_shared[]". 152b2b69f49Smarc */ 15324f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 15424f67f6bSmarc 15524f67f6bSmarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 15624f67f6bSmarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 15724f67f6bSmarc 158b2b69f49Smarc /* 15924f67f6bSmarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 16024f67f6bSmarc * buffers. Each buffer must consume an integral number of memory pages to 16124f67f6bSmarc * guarantee that a following buffer will begin on a page boundary. Also, 16224f67f6bSmarc * enough space is allocated so that the FIRST I/O buffer can start at the 16324f67f6bSmarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 164b2b69f49Smarc * memory protections can be turned on/off for individual buffers. 165b2b69f49Smarc */ 16624f67f6bSmarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 16724f67f6bSmarc 16824f67f6bSmarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 16924f67f6bSmarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 17024f67f6bSmarc 171b2b69f49Smarc /* 17224f67f6bSmarc * The driver assists a client in scroll operations by loading dragon 17324f67f6bSmarc * registers from an interrupt service routine. The loading is done using 17424f67f6bSmarc * parameters found in memory shrade between the driver and it's client. 17524f67f6bSmarc * The scroll parameter structures are ALL loacted in the same memory page 176b2b69f49Smarc * for reasons of memory economy. 177b2b69f49Smarc */ 17824f67f6bSmarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 17924f67f6bSmarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 18024f67f6bSmarc 181b2b69f49Smarc /* 18224f67f6bSmarc * the driver is programmable to provide the user with color map write 18324f67f6bSmarc * services at VSYNC interrupt time. At interrupt time the driver loads 184b2b69f49Smarc * the color map with any user-requested load data found in shared memory 185b2b69f49Smarc */ 18624f67f6bSmarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 18724f67f6bSmarc 188e977faadSmarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 18924f67f6bSmarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 19024f67f6bSmarc 191b2b69f49Smarc /* 192b2b69f49Smarc * mouse input event structures 193b2b69f49Smarc */ 19424f67f6bSmarc struct mouse_report last_rep[NQD]; 19524f67f6bSmarc struct mouse_report current_rep[NQD]; 19624f67f6bSmarc 1977881ece5Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 198b2b69f49Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 199b2b69f49Smarc int qdcount = 0; /* count of successfully probed qd's */ 20024f67f6bSmarc int nNQD = NQD; 20124f67f6bSmarc int DMAbuf_size = DMA_BUFSIZ; 202e977faadSmarc int QDlast_DMAtype; /* type of the last DMA operation */ 203e977faadSmarc 204b2b69f49Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 205b2b69f49Smarc /* 206b2b69f49Smarc * macro to get system time. Used to time stamp event queue entries 207b2b69f49Smarc */ 2087e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 2097e911b15Skarels 2107e911b15Skarels int qdprobe(); 2117e911b15Skarels int qdattach(); 2127e911b15Skarels int qddint(); /* DMA gate array intrpt service */ 2137e911b15Skarels int qdaint(); /* Dragon ADDER intrpt service */ 2147e911b15Skarels int qdiint(); 2157e911b15Skarels 2167e911b15Skarels u_short qdstd[] = { 0 }; 2177e911b15Skarels 218b2b69f49Smarc struct uba_driver qddriver = { 2197e911b15Skarels qdprobe, /* device probe entry */ 2207e911b15Skarels 0, /* no slave device */ 2217e911b15Skarels qdattach, /* device attach entry */ 2227e911b15Skarels 0, /* no "fill csr/ba to start" */ 2237e911b15Skarels qdstd, /* device addresses */ 2247e911b15Skarels "qd", /* device name string */ 2257e911b15Skarels qdinfo /* ptr to QDSS's uba_device struct */ 2267e911b15Skarels }; 2277e911b15Skarels 228e977faadSmarc #define QDPRIOR (PZERO-1) /* must be negative */ 2297e911b15Skarels #define FALSE 0 2307e911b15Skarels #define TRUE ~FALSE 2317e911b15Skarels #define BAD -1 2327e911b15Skarels #define GOOD 0 2337e911b15Skarels 234b2b69f49Smarc /* 235b2b69f49Smarc * macro to create a system virtual page number from system virtual adrs 236b2b69f49Smarc */ 237b2b69f49Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 2387e911b15Skarels 239b2b69f49Smarc /* 240b2b69f49Smarc * QDSS register address offsets from start of QDSS address space 241b2b69f49Smarc */ 2427e911b15Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 2437e911b15Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 2447e911b15Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 2457e911b15Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 2467e911b15Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 2477e911b15Skarels #define ADDER (REGSTART+0x000) 2487e911b15Skarels #define DGA (REGSTART+0x200) 2497e911b15Skarels #define DUART (REGSTART+0x400) 2507e911b15Skarels #define MEMCSR (REGSTART+0x800) 2517e911b15Skarels #define CLRSIZE (3 * 512) /* color map size */ 2527e911b15Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 2537e911b15Skarels /* 0x0C00 really */ 2547e911b15Skarels #define RED (CLRSTART+0x000) 2557e911b15Skarels #define BLUE (CLRSTART+0x200) 2567e911b15Skarels #define GREEN (CLRSTART+0x400) 2577e911b15Skarels 2587e911b15Skarels 259b2b69f49Smarc /* 2607e911b15Skarels * QDSS minor device numbers. The *real* minor device numbers are in 2617e911b15Skarels * the bottom two bits of the major/minor device spec. Bits 2 and up are 262b2b69f49Smarc * used to specify the QDSS device number (ie: which one?) 263b2b69f49Smarc */ 2647e911b15Skarels 2657e911b15Skarels #define CONS 0 2667e911b15Skarels #define GRAPHIC 2 2677e911b15Skarels 268b2b69f49Smarc /* 269b2b69f49Smarc * console cursor bitmap (white block cursor) 270b2b69f49Smarc */ 271b2b69f49Smarc short cons_cursor[32] = { 2727e911b15Skarels /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2737e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2747e911b15Skarels /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2757e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 2767e911b15Skarels }; 2777e911b15Skarels 278b2b69f49Smarc /* 279b2b69f49Smarc * constants used in font operations 280b2b69f49Smarc */ 281e977faadSmarc #define CHARS 190 /* # of chars in the font */ 2827e911b15Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 2837e911b15Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 2847e911b15Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 2857e911b15Skarels #define ROWS CHAR_HEIGHT 2867e911b15Skarels #define FONT_X 0 /* font's off screen adrs */ 2877e911b15Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 288e977faadSmarc 289b2b69f49Smarc /* Offset to second row characters (XXX - should remove) */ 290e977faadSmarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 2917e911b15Skarels 2927e911b15Skarels extern char q_font[]; /* reference font object code */ 293e977faadSmarc extern u_short q_key[]; /* reference key xlation tables */ 294e977faadSmarc extern u_short q_shift_key[]; 2957e911b15Skarels extern char *q_special[]; 2967e911b15Skarels 297b2b69f49Smarc /* 298b2b69f49Smarc * definitions for cursor acceleration reporting 299b2b69f49Smarc */ 3007e911b15Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 3017e911b15Skarels 302b2b69f49Smarc /* 303b2b69f49Smarc * virtual console support. 3047e911b15Skarels */ 305e977faadSmarc extern (*v_putc)(); 306*f79d7b48Smarc #ifdef KADB 307*f79d7b48Smarc extern (*v_getc)(); 308*f79d7b48Smarc extern (*v_poll)(); 309*f79d7b48Smarc #endif 310e977faadSmarc extern struct cdevsw *consops; 311e977faadSmarc int qdputc(); 312*f79d7b48Smarc int qdgetc(); 313*f79d7b48Smarc int qdpoll(); 314e977faadSmarc int qdstart(); 315*f79d7b48Smarc int qdpolling = 0; 316e977faadSmarc 317b2b69f49Smarc /* 318b2b69f49Smarc * LK-201 state storage for input console keyboard conversion to ASCII 319b2b69f49Smarc */ 3207e911b15Skarels struct q_keyboard { 3217e911b15Skarels int shift; /* state variables */ 3227e911b15Skarels int cntrl; 3237e911b15Skarels int lock; 3247e911b15Skarels int lastcode; /* last keycode typed */ 3257e911b15Skarels unsigned kup[8]; /* bits for each keycode*/ 3267e911b15Skarels unsigned dkeys[8]; /* down/up mode keys */ 3277e911b15Skarels char last; /* last character */ 3287e911b15Skarels } q_keyboard; 3297e911b15Skarels 330b2b69f49Smarc /* 331b2b69f49Smarc * tty settings on first open 332b2b69f49Smarc */ 333*f79d7b48Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL) 334e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR) 335*f79d7b48Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN) 336e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 337e977faadSmarc 3387881ece5Smarc /* 3397881ece5Smarc * Init QDSS as console (before probe routine) 3407881ece5Smarc */ 3417e911b15Skarels 3427e911b15Skarels qdcons_init() 3437e911b15Skarels { 3447881ece5Smarc register unit; 3457e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 346e977faadSmarc u_int mapix; /* index into QVmap[] array */ 347e977faadSmarc struct percpu *pcpu; /* pointer to cpusw structure */ 348e977faadSmarc register struct qbus *qb; 3497e911b15Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 3507e911b15Skarels u_short *devptr; /* vitual device space */ 351e977faadSmarc extern cnputc(); 3527e911b15Skarels 3537e911b15Skarels #define QDSSCSR 0x1F00 3547e911b15Skarels 35524f67f6bSmarc if (v_putc != cnputc) 3567881ece5Smarc return 0; 35724f67f6bSmarc 3587e911b15Skarels unit = 0; 3597e911b15Skarels 360b2b69f49Smarc /* 361b2b69f49Smarc * find the cpusw entry that matches this machine. 362b2b69f49Smarc */ 36324f67f6bSmarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 3647e911b15Skarels ; 36524f67f6bSmarc if (pcpu == NULL) 3667881ece5Smarc return 0; 3672b86b1e4Stef if (pcpu->pc_io->io_type != IO_QBUS) 3682b86b1e4Stef return 0; 36924f67f6bSmarc 37024f67f6bSmarc /* 371e977faadSmarc * Map device registers - the last 8K of qvmem. 37224f67f6bSmarc */ 37324f67f6bSmarc qb = (struct qbus *)pcpu->pc_io->io_details; 37424f67f6bSmarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 37524f67f6bSmarc UBAIOPAGES * NBPG); 37624f67f6bSmarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 37724f67f6bSmarc qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 3787881ece5Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 3797881ece5Smarc return 0; 380e977faadSmarc 38124f67f6bSmarc /* 38224f67f6bSmarc * Map q-bus memory used by qdss. (separate map) 38324f67f6bSmarc */ 38424f67f6bSmarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 38524f67f6bSmarc phys_adr = qb->qb_maddr + mapix; 38624f67f6bSmarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 3877e911b15Skarels 38824f67f6bSmarc /* 38924f67f6bSmarc * tell QDSS which Q memory address base to decode 390b2b69f49Smarc * (shifted right 16 bits - its in 64K units) 39124f67f6bSmarc */ 39224f67f6bSmarc *qdaddr = (u_short)((int)mapix >> 16); 3937e911b15Skarels qdflags[unit].config = *(u_short *)qdaddr; 3947e911b15Skarels 395b2b69f49Smarc /* 396b2b69f49Smarc * load qdmap struct with the virtual addresses of the QDSS elements 397b2b69f49Smarc */ 398e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0]); 3997e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 4007e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 4017e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA; 4027e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART; 4037e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 4047e911b15Skarels qdmap[unit].red = qdbase[unit] + RED; 4057e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 4067e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN; 4077e911b15Skarels 4087e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 4097e911b15Skarels 410b2b69f49Smarc /* 411b2b69f49Smarc * init the QDSS 412b2b69f49Smarc */ 413b2b69f49Smarc /* 41424f67f6bSmarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 41524f67f6bSmarc (char *)qdbase[0], qdmap[0].memcsr); 416b2b69f49Smarc */ 4177e911b15Skarels 4187e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 4197e911b15Skarels 4207e911b15Skarels cursor[unit].x = 0; 4217e911b15Skarels cursor[unit].y = 0; 4227e911b15Skarels init_shared(unit); /* init shared memory */ 4237e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 4247e911b15Skarels clear_qd_screen(unit); /* clear the screen */ 4257e911b15Skarels ldfont(unit); /* load the console font */ 4267e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 4277e911b15Skarels setup_input(unit); /* init the DUART */ 428b2b69f49Smarc v_putc = qdputc; /* kernel console output to qdss */ 429*f79d7b48Smarc #ifdef KADB 430*f79d7b48Smarc v_getc = qdgetc; /* kernel console input from qdss */ 431*f79d7b48Smarc v_poll = qdpoll; /* kdb hook to disable char intr */ 432*f79d7b48Smarc #endif 433b2b69f49Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 4347881ece5Smarc return 1; 4357e911b15Skarels 4367e911b15Skarels } /* qdcons_init */ 4377e911b15Skarels 4387881ece5Smarc /* 4397881ece5Smarc * Configure QDSS into Q memory and make it intrpt. 4407e911b15Skarels * 4417e911b15Skarels * side effects: QDSS gets mapped into Qbus memory space at the first 4427e911b15Skarels * vacant 64kb boundary counting back from the top of 443e977faadSmarc * Qbus memory space (qvmem+4mb) 4447e911b15Skarels * 4457e911b15Skarels * return: QDSS bus request level and vector address returned in 4467e911b15Skarels * registers by UNIX convention. 4477e911b15Skarels * 4487881ece5Smarc */ 4497e911b15Skarels qdprobe(reg) 4507881ece5Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 4517e911b15Skarels { 452*f79d7b48Smarc register int br, cvec; 4537e911b15Skarels register int unit; 4547e911b15Skarels struct dga *dga; /* pointer to gate array structure */ 4557e911b15Skarels int vector; 4567881ece5Smarc #ifdef notdef 4577881ece5Smarc int *ptep; /* page table entry pointer */ 4587e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 4597e911b15Skarels u_int mapix; 4607881ece5Smarc #endif 4617881ece5Smarc 4627881ece5Smarc #ifdef lint 4637881ece5Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 4647881ece5Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 4657881ece5Smarc #endif 4667e911b15Skarels 467b2b69f49Smarc /* 468b2b69f49Smarc * calculate board unit number from I/O page register address 469b2b69f49Smarc */ 4707e911b15Skarels unit = (int) (((int)reg >> 1) & 0x0007); 4717e911b15Skarels 472b2b69f49Smarc /* 473b2b69f49Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 474b2b69f49Smarc * physical boundary. The Qbus memory space is mapped into 475b2b69f49Smarc * the system memory space at config time. After config 476b2b69f49Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 477b2b69f49Smarc * of the start of Qbus memory. The Qbus memory page table 478b2b69f49Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 479b2b69f49Smarc * which is also loaded at config time. These are the 480b2b69f49Smarc * variables used below to find a vacant 64kb boundary in 481b2b69f49Smarc * Qbus memory, and load it's corresponding physical adrs 482b2b69f49Smarc * into the QDSS's I/O page CSR. 483b2b69f49Smarc */ 484e977faadSmarc 485e977faadSmarc /* 486e977faadSmarc * Only if QD is the graphics device. 48724f67f6bSmarc */ 4887e911b15Skarels 4897e911b15Skarels /* if this QDSS is NOT the console, then do init here.. */ 4907e911b15Skarels 491e977faadSmarc if (unit != 0) { 492e977faadSmarc printf("qd: can't support two qdss's (yet)\n"); 4937881ece5Smarc #ifdef notdef /* can't test */ 4947e911b15Skarels if (v_consputc != qdputc || unit != 0) { 4957e911b15Skarels 496b2b69f49Smarc /* 497b2b69f49Smarc * read QDSS config info 498b2b69f49Smarc */ 4997e911b15Skarels qdflags[unit].config = *(u_short *)reg; 5007e911b15Skarels 501b2b69f49Smarc /* 502b2b69f49Smarc * find an empty 64kb adrs boundary 503b2b69f49Smarc */ 5047e911b15Skarels 505e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 506e977faadSmarc 507b2b69f49Smarc /* 5087881ece5Smarc * find the cpusw entry that matches this machine. 5097881ece5Smarc */ 5107e911b15Skarels cpup = &cpusw[cpu]; 5117e911b15Skarels while (!(BADADDR(qdbase[unit], sizeof(short)))) 5127e911b15Skarels qdbase[unit] -= CHUNK; 5137e911b15Skarels 514b2b69f49Smarc /* 5157881ece5Smarc * tell QDSS which Q memory address base to decode 5167881ece5Smarc */ 517e977faadSmarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 518e977faadSmarc ptep = (int *) QVmap[0] + mapix; 5197e911b15Skarels phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 5207e911b15Skarels *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 5217e911b15Skarels 522b2b69f49Smarc /* 523b2b69f49Smarc * load QDSS adrs map with system addresses 524b2b69f49Smarc * of device regs 525b2b69f49Smarc */ 5267e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 5277e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 5287e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA; 5297e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART; 5307e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 5317e911b15Skarels qdmap[unit].red = qdbase[unit] + RED; 5327e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 5337e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN; 5347e911b15Skarels 5357e911b15Skarels /* device init */ 5367e911b15Skarels 5377e911b15Skarels cursor[unit].x = 0; 5387e911b15Skarels cursor[unit].y = 0; 5397e911b15Skarels init_shared(unit); /* init shared memory */ 5407e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 5417e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 5427e911b15Skarels setup_input(unit); /* init the DUART */ 5437e911b15Skarels clear_qd_screen(unit); 5447e911b15Skarels ldfont(unit); /* load the console font */ 5457e911b15Skarels 5467e911b15Skarels /* once only: turn on sync */ 5477e911b15Skarels 5487e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; 549b2b69f49Smarc } 550006e9885Smarc #endif /*notdef*/ 551e977faadSmarc } 5527e911b15Skarels 553b2b69f49Smarc /* 554b2b69f49Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 555b2b69f49Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 556b2b69f49Smarc * vectors from the vector pool, and then continue 557b2b69f49Smarc * to take them until we get a xx0 HEX vector. The 558b2b69f49Smarc * pool provides vectors in contiguous decending 559b2b69f49Smarc * order. 560b2b69f49Smarc */ 5617e911b15Skarels 5627e911b15Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 5637e911b15Skarels 5647e911b15Skarels while (vector & 0x0F) { /* if lo nibble != 0.. */ 565b2b69f49Smarc /* ..take another vector */ 566b2b69f49Smarc vector = (uba_hd[0].uh_lastiv -= 4); 5677e911b15Skarels } 5687e911b15Skarels 569b2b69f49Smarc /* 570b2b69f49Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 571b2b69f49Smarc */ 5727e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 5737e911b15Skarels dga->csr = (short) HALT; /* disable everything */ 5747e911b15Skarels dga->ivr = (short) vector; /* load intrpt base vector */ 5757e911b15Skarels dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 5767e911b15Skarels dga->bytcnt_hi = (short) 0; 5777e911b15Skarels 578b2b69f49Smarc /* 579b2b69f49Smarc * turn on DMA interrupts 580b2b69f49Smarc */ 5817e911b15Skarels dga->csr &= ~SET_DONE_FIFO; 5827e911b15Skarels dga->csr |= DMA_IE | DL_ENB; 5837e911b15Skarels 5847e911b15Skarels DELAY(20000); /* wait for the intrpt */ 5857e911b15Skarels dga->csr = HALT; /* stop the wheels */ 5867e911b15Skarels 5877e911b15Skarels if (cvec != vector) /* if vector != base vector.. */ 5887e911b15Skarels return(0); /* ..return = 'no device' */ 5897e911b15Skarels 590e977faadSmarc /* 591e977faadSmarc * score this as an existing qdss 592e977faadSmarc */ 593e977faadSmarc qdcount++; 594e977faadSmarc 5957e911b15Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 5967e911b15Skarels 5977e911b15Skarels } /* qdprobe */ 5987e911b15Skarels 5997e911b15Skarels qdattach(ui) 6007e911b15Skarels struct uba_device *ui; 6017e911b15Skarels { 6027881ece5Smarc register unit; /* QDSS module # for this call */ 6037e911b15Skarels 6047e911b15Skarels unit = ui->ui_unit; /* get QDSS number */ 6057e911b15Skarels 606b2b69f49Smarc /* 607b2b69f49Smarc * init "qdflags[]" for this QDSS 608b2b69f49Smarc */ 6097e911b15Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 6107e911b15Skarels qdflags[unit].mapped = 0; 611e977faadSmarc qdflags[unit].kernel_loop = -1; 6127e911b15Skarels qdflags[unit].user_dma = 0; 6137e911b15Skarels qdflags[unit].curs_acc = ACC_OFF; 6147e911b15Skarels qdflags[unit].curs_thr = 128; 6157e911b15Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 6167e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 6177e911b15Skarels qdflags[unit].adder_ie = 0; 6187e911b15Skarels 619b2b69f49Smarc /* 6207e911b15Skarels * init structures used in kbd/mouse interrupt service. This code must 621b2b69f49Smarc * come after the "init_shared()" routine has run since that routine 622b2b69f49Smarc * inits the eq_header[unit] structure used here. 623b2b69f49Smarc */ 6247e911b15Skarels 625b2b69f49Smarc /* 626b2b69f49Smarc * init the "latest mouse report" structure 627b2b69f49Smarc */ 6287e911b15Skarels last_rep[unit].state = 0; 6297e911b15Skarels last_rep[unit].dx = 0; 6307e911b15Skarels last_rep[unit].dy = 0; 6317e911b15Skarels last_rep[unit].bytcnt = 0; 6327e911b15Skarels 633b2b69f49Smarc /* 6347881ece5Smarc * init the event queue (except mouse position) 6357881ece5Smarc */ 6367881ece5Smarc eq_header[unit]->header.events = 6377881ece5Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 6387e911b15Skarels 6397e911b15Skarels eq_header[unit]->header.size = MAXEVENTS; 6407e911b15Skarels eq_header[unit]->header.head = 0; 6417e911b15Skarels eq_header[unit]->header.tail = 0; 6427e911b15Skarels 643b2b69f49Smarc /* 644b2b69f49Smarc * open exclusive for graphics device. 645b2b69f49Smarc */ 646b2b69f49Smarc qdopened[unit] = 0; 6477e911b15Skarels 6487e911b15Skarels } /* qdattach */ 6497e911b15Skarels 6507881ece5Smarc /*ARGSUSED*/ 6517e911b15Skarels qdopen(dev, flag) 6527e911b15Skarels dev_t dev; 6537e911b15Skarels int flag; 6547e911b15Skarels { 6557e911b15Skarels register struct uba_device *ui; /* ptr to uba structures */ 6567e911b15Skarels register struct dga *dga; /* ptr to gate array struct */ 6577e911b15Skarels register struct tty *tp; 6587e911b15Skarels struct duart *duart; 6597881ece5Smarc int unit; 6607881ece5Smarc int minor_dev; 6617e911b15Skarels 6627e911b15Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 6637e911b15Skarels unit = minor_dev >> 2; 6647e911b15Skarels 665b2b69f49Smarc /* 666b2b69f49Smarc * check for illegal conditions 667b2b69f49Smarc */ 6687e911b15Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 6697e911b15Skarels if (ui == 0 || ui->ui_alive == 0) 6707e911b15Skarels return(ENXIO); /* no such device or address */ 6717e911b15Skarels 6727e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 6737e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 6747e911b15Skarels 6757e911b15Skarels if ((minor_dev & 0x03) == 2) { 676b2b69f49Smarc /* 677b2b69f49Smarc * this is the graphic device... 678b2b69f49Smarc */ 679b2b69f49Smarc if (qdopened[unit] != 0) 6807e911b15Skarels return(EBUSY); 6817e911b15Skarels else 682b2b69f49Smarc qdopened[unit] = 1; 6837e911b15Skarels qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 684b2b69f49Smarc /* 685b2b69f49Smarc * enble kbd & mouse intrpts in DUART mask reg 686b2b69f49Smarc */ 6877e911b15Skarels qdflags[unit].duart_imask |= 0x22; 6887e911b15Skarels duart->imask = qdflags[unit].duart_imask; 689b2b69f49Smarc } else { 690b2b69f49Smarc /* 691b2b69f49Smarc * this is the console 692b2b69f49Smarc */ 6937e911b15Skarels qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 6947e911b15Skarels dga->csr |= CURS_ENB; 6957e911b15Skarels qdflags[unit].duart_imask |= 0x02; 6967e911b15Skarels duart->imask = qdflags[unit].duart_imask; 697b2b69f49Smarc /* 698b2b69f49Smarc * some setup for tty handling 699b2b69f49Smarc */ 7007e911b15Skarels tp = &qd_tty[minor_dev]; 7017e911b15Skarels tp->t_addr = ui->ui_addr; 7027e911b15Skarels tp->t_oproc = qdstart; 7037e911b15Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 7047e911b15Skarels ttychars(tp); 7057e911b15Skarels tp->t_ispeed = B9600; 7067e911b15Skarels tp->t_ospeed = B9600; 707e977faadSmarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 708b2b69f49Smarc tp->t_iflag = TTYDEF_IFLAG; 709b2b69f49Smarc tp->t_oflag = TTYDEF_OFLAG; 710b2b69f49Smarc tp->t_lflag = TTYDEF_LFLAG; 711b2b69f49Smarc tp->t_cflag = TTYDEF_CFLAG; 712e977faadSmarc } 713b2b69f49Smarc /* 714b2b69f49Smarc * enable intrpts, open line discipline 715b2b69f49Smarc */ 7167e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 7177e911b15Skarels return ((*linesw[tp->t_line].l_open)(dev, tp)); 7187e911b15Skarels } 7197e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 7207e911b15Skarels return(0); 7217e911b15Skarels 7227e911b15Skarels } /* qdopen */ 7237e911b15Skarels 7247881ece5Smarc /*ARGSUSED*/ 7257e911b15Skarels qdclose(dev, flag) 7267e911b15Skarels dev_t dev; 7277e911b15Skarels int flag; 7287e911b15Skarels { 7297e911b15Skarels register struct tty *tp; 7307e911b15Skarels register struct qdmap *qd; 7317e911b15Skarels register int *ptep; 7327e911b15Skarels struct dga *dga; /* gate array register map pointer */ 7337e911b15Skarels struct duart *duart; 7347e911b15Skarels struct adder *adder; 7357881ece5Smarc int unit; 7367881ece5Smarc int minor_dev; 7377e911b15Skarels u_int mapix; 738b2b69f49Smarc int i; /* SIGNED index */ 7397e911b15Skarels 7407e911b15Skarels minor_dev = minor(dev); /* get minor device number */ 7417e911b15Skarels unit = minor_dev >> 2; /* get QDSS number */ 7427e911b15Skarels qd = &qdmap[unit]; 7437e911b15Skarels 7447e911b15Skarels if ((minor_dev & 0x03) == 2) { 745b2b69f49Smarc /* 746b2b69f49Smarc * this is the graphic device... 747b2b69f49Smarc */ 748b2b69f49Smarc if (qdopened[unit] != 1) 7497e911b15Skarels return(EBUSY); 7507e911b15Skarels else 751b2b69f49Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 752b2b69f49Smarc /* 753b2b69f49Smarc * re-protect device memory 754b2b69f49Smarc */ 7557e911b15Skarels if (qdflags[unit].mapped & MAPDEV) { 756b2b69f49Smarc /* 757b2b69f49Smarc * TEMPLATE RAM 758b2b69f49Smarc */ 75924f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 76024f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7617881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 7627881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 763b2b69f49Smarc /* 764b2b69f49Smarc * ADDER 765b2b69f49Smarc */ 76624f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 76724f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7687881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 7697881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 770b2b69f49Smarc /* 771b2b69f49Smarc * COLOR MAPS 772b2b69f49Smarc */ 77324f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 77424f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7757881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 7767881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 7777e911b15Skarels } 7787e911b15Skarels 779b2b69f49Smarc /* 780b2b69f49Smarc * re-protect DMA buffer and free the map registers 781b2b69f49Smarc */ 7827e911b15Skarels if (qdflags[unit].mapped & MAPDMA) { 7837e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 7847e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 7857e911b15Skarels dga->csr &= ~DMA_IE; 7867e911b15Skarels dga->csr &= ~0x0600; /* kill DMA */ 7877e911b15Skarels adder->command = CANCEL; 788b2b69f49Smarc /* 789b2b69f49Smarc * if DMA was running, flush spurious intrpt 790b2b69f49Smarc */ 7917e911b15Skarels if (dga->bytcnt_lo != 0) { 7927e911b15Skarels dga->bytcnt_lo = 0; 7937e911b15Skarels dga->bytcnt_hi = 0; 7947e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 7957e911b15Skarels dga->csr |= DMA_IE; 7967e911b15Skarels dga->csr &= ~DMA_IE; 7977e911b15Skarels } 7987e911b15Skarels ptep = (int *) 7997e911b15Skarels ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 8007881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 8017881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 8027e911b15Skarels ubarelse(0, &Qbus_unmap[unit]); 8037e911b15Skarels } 8047e911b15Skarels 805b2b69f49Smarc /* 806b2b69f49Smarc * re-protect 1K (2 pages) event queue 807b2b69f49Smarc */ 8087e911b15Skarels if (qdflags[unit].mapped & MAPEQ) { 8097e911b15Skarels ptep = (int *) 8107e911b15Skarels ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 8117881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 8127e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8137e911b15Skarels } 814b2b69f49Smarc /* 815b2b69f49Smarc * re-protect scroll param area and disable scroll intrpts 816b2b69f49Smarc */ 8177e911b15Skarels if (qdflags[unit].mapped & MAPSCR) { 8187e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 8197e911b15Skarels + (mfpr(SBR) | 0x80000000)); 820b2b69f49Smarc /* 821b2b69f49Smarc * re-protect 512 scroll param area 822b2b69f49Smarc */ 8237e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8247e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8257e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC; 8267e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 8277e911b15Skarels } 828b2b69f49Smarc /* 829b2b69f49Smarc * re-protect color map write buffer area and kill intrpts 830b2b69f49Smarc */ 8317e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) { 8327e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 8337e911b15Skarels + (mfpr(SBR) | 0x80000000)); 8347881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 8357e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8367e911b15Skarels color_buf[unit]->status = 0; 8377e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8387e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC; 8397e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 8407e911b15Skarels } 841b2b69f49Smarc mtpr(TBIA, 0); 842b2b69f49Smarc /* flag everything now unmapped */ 843b2b69f49Smarc qdflags[unit].mapped = 0; 8447e911b15Skarels qdflags[unit].inuse &= ~GRAPHIC_DEV; 8457e911b15Skarels qdflags[unit].curs_acc = ACC_OFF; 8467e911b15Skarels qdflags[unit].curs_thr = 128; 847b2b69f49Smarc /* 848b2b69f49Smarc * restore the console 849b2b69f49Smarc */ 8507e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8517e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8527e911b15Skarels dga->csr &= ~DMA_IE; 8537e911b15Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 8547e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 8557e911b15Skarels adder->command = CANCEL; 856b2b69f49Smarc /* 857b2b69f49Smarc * if DMA was running, flush spurious intrpt 858b2b69f49Smarc */ 8597e911b15Skarels if (dga->bytcnt_lo != 0) { 8607e911b15Skarels dga->bytcnt_lo = 0; 8617e911b15Skarels dga->bytcnt_hi = 0; 8627e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 8637e911b15Skarels dga->csr |= DMA_IE; 8647e911b15Skarels dga->csr &= ~DMA_IE; 8657e911b15Skarels } 8667e911b15Skarels init_shared(unit); /* init shared memory */ 8677e911b15Skarels setup_dragon(unit); /* init ADDER/VIPER */ 8687e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 8697e911b15Skarels setup_input(unit); /* init the DUART */ 8707e911b15Skarels ldfont(unit); 8717e911b15Skarels cursor[unit].x = 0; 8727e911b15Skarels cursor[unit].y = 0; 873b2b69f49Smarc /* 874b2b69f49Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 875b2b69f49Smarc */ 8767e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 8777e911b15Skarels qdflags[unit].duart_imask &= ~(0x20); 8787e911b15Skarels qdflags[unit].duart_imask |= 0x02; 8797e911b15Skarels duart->imask = qdflags[unit].duart_imask; 880b2b69f49Smarc /* 881b2b69f49Smarc * shut off interrupts if all is closed 882b2b69f49Smarc */ 883b2b69f49Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 8847e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8857e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE); 8867e911b15Skarels } 887b2b69f49Smarc } else { 888b2b69f49Smarc /* 889b2b69f49Smarc * this is the console 890b2b69f49Smarc */ 8917e911b15Skarels tp = &qd_tty[minor_dev]; 8927e911b15Skarels (*linesw[tp->t_line].l_close)(tp); 8937e911b15Skarels ttyclose(tp); 8947e911b15Skarels tp->t_state = 0; 8957e911b15Skarels qdflags[unit].inuse &= ~CONS_DEV; 896b2b69f49Smarc /* 897b2b69f49Smarc * if graphics device is closed, kill interrupts 898b2b69f49Smarc */ 8997e911b15Skarels if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 9007e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 9017e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE); 9027e911b15Skarels } 9037e911b15Skarels } 9047e911b15Skarels 9057e911b15Skarels return(0); 9067e911b15Skarels 9077e911b15Skarels } /* qdclose */ 9087e911b15Skarels 9097e911b15Skarels qdioctl(dev, cmd, datap, flags) 9107e911b15Skarels dev_t dev; 9117e911b15Skarels int cmd; 9127881ece5Smarc register caddr_t datap; 9137e911b15Skarels int flags; 9147e911b15Skarels { 9157e911b15Skarels register int *ptep; /* page table entry pointer */ 91624f67f6bSmarc register int mapix; /* QVmap[] page table index */ 9177e911b15Skarels register struct _vs_event *event; 9187e911b15Skarels register struct tty *tp; 9197881ece5Smarc register i; 9207e911b15Skarels struct qdmap *qd; /* pointer to device map struct */ 9217e911b15Skarels struct dga *dga; /* Gate Array reg structure pntr */ 9227e911b15Skarels struct duart *duart; /* DUART reg structure pointer */ 9237e911b15Skarels struct adder *adder; /* ADDER reg structure pointer */ 9247e911b15Skarels struct prgkbd *cmdbuf; 9257e911b15Skarels struct prg_cursor *curs; 9267e911b15Skarels struct _vs_cursor *pos; 9277881ece5Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 9287e911b15Skarels u_int minor_dev = minor(dev); 9297e911b15Skarels int error; 9307e911b15Skarels int s; 9317e911b15Skarels short *temp; /* a pointer to template RAM */ 9327e911b15Skarels 933b2b69f49Smarc /* 934b2b69f49Smarc * service graphic device ioctl commands 935b2b69f49Smarc */ 9367e911b15Skarels switch (cmd) { 937e977faadSmarc 9387e911b15Skarels case QD_GETEVENT: 939b2b69f49Smarc /* 940b2b69f49Smarc * extract the oldest event from the event queue 941b2b69f49Smarc */ 9427e911b15Skarels if (ISEMPTY(eq_header[unit])) { 9437e911b15Skarels event = (struct _vs_event *) datap; 9447e911b15Skarels event->vse_device = VSE_NULL; 9457e911b15Skarels break; 9467e911b15Skarels } 9477e911b15Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 948e977faadSmarc s = spl5(); 9497e911b15Skarels GETEND(eq_header[unit]); 9507e911b15Skarels splx(s); 9517881ece5Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 9527e911b15Skarels break; 9537e911b15Skarels 9547e911b15Skarels case QD_RESET: 955b2b69f49Smarc /* 956b2b69f49Smarc * init the dragon stuff, DUART, and driver variables 957b2b69f49Smarc */ 9587e911b15Skarels init_shared(unit); /* init shared memory */ 9597e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 9607e911b15Skarels clear_qd_screen(unit); 9617e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 9627e911b15Skarels ldfont(unit); /* load the console font */ 9637e911b15Skarels setup_input(unit); /* init the DUART */ 9647e911b15Skarels break; 9657e911b15Skarels 9667e911b15Skarels case QD_SET: 967b2b69f49Smarc /* 968b2b69f49Smarc * init the DUART and driver variables 969b2b69f49Smarc */ 9707e911b15Skarels init_shared(unit); 9717e911b15Skarels setup_input(unit); 9727e911b15Skarels break; 9737e911b15Skarels 9747e911b15Skarels case QD_CLRSCRN: 975b2b69f49Smarc /* 976b2b69f49Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 977b2b69f49Smarc */ 9787881ece5Smarc #ifdef notdef /* has caused problems and isn't necessary */ 9797e911b15Skarels setup_dragon(unit); 9807e911b15Skarels clear_qd_screen(unit); 981e977faadSmarc #endif 9827e911b15Skarels break; 9837e911b15Skarels 9847e911b15Skarels case QD_WTCURSOR: 985b2b69f49Smarc /* 986b2b69f49Smarc * load a cursor into template RAM 987b2b69f49Smarc */ 9887881ece5Smarc ldcursor(unit, (short *)datap); 9897e911b15Skarels break; 9907e911b15Skarels 9917e911b15Skarels case QD_RDCURSOR: 9927e911b15Skarels 9937e911b15Skarels temp = (short *) qdmap[unit].template; 994b2b69f49Smarc /* 995b2b69f49Smarc * cursor is 32 WORDS from the end of the 8k WORD... 996b2b69f49Smarc * ...template space 997b2b69f49Smarc */ 9987e911b15Skarels temp += (8 * 1024) - 32; 9997e911b15Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 10007e911b15Skarels *(short *)datap = *temp++; 10017e911b15Skarels break; 10027e911b15Skarels 10037e911b15Skarels case QD_POSCURSOR: 1004b2b69f49Smarc /* 1005b2b69f49Smarc * position the mouse cursor 1006b2b69f49Smarc */ 10077e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 10087e911b15Skarels pos = (struct _vs_cursor *) datap; 1009e977faadSmarc s = spl5(); 10107e911b15Skarels dga->x_cursor = TRANX(pos->x); 10117e911b15Skarels dga->y_cursor = TRANY(pos->y); 10127e911b15Skarels eq_header[unit]->curs_pos.x = pos->x; 10137e911b15Skarels eq_header[unit]->curs_pos.y = pos->y; 10147e911b15Skarels splx(s); 10157e911b15Skarels break; 10167e911b15Skarels 10177e911b15Skarels case QD_PRGCURSOR: 1018b2b69f49Smarc /* 1019b2b69f49Smarc * set the cursor acceleration factor 1020b2b69f49Smarc */ 10217e911b15Skarels curs = (struct prg_cursor *) datap; 1022e977faadSmarc s = spl5(); 10237e911b15Skarels qdflags[unit].curs_acc = curs->acc_factor; 10247e911b15Skarels qdflags[unit].curs_thr = curs->threshold; 10257e911b15Skarels splx(s); 10267e911b15Skarels break; 10277e911b15Skarels 10287e911b15Skarels case QD_MAPDEVICE: 1029b2b69f49Smarc /* 1030b2b69f49Smarc * enable 'user write' to device pages 1031b2b69f49Smarc */ 10327e911b15Skarels qdflags[unit].mapped |= MAPDEV; 10337e911b15Skarels qd = (struct qdmap *) &qdmap[unit]; 1034b2b69f49Smarc /* 1035b2b69f49Smarc * enable user write to template RAM 1036b2b69f49Smarc */ 103724f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 103824f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10397881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 10407881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1041b2b69f49Smarc /* 1042b2b69f49Smarc * enable user write to registers 1043b2b69f49Smarc */ 104424f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 104524f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10467881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 10477881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1048b2b69f49Smarc /* 1049b2b69f49Smarc * enable user write to color maps 1050b2b69f49Smarc */ 105124f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 105224f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10537881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 10547881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1055b2b69f49Smarc /* 1056b2b69f49Smarc * enable user write to DUART 1057b2b69f49Smarc */ 105824f67f6bSmarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 105924f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10607e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 10617e911b15Skarels 10627881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 10637e911b15Skarels 1064b2b69f49Smarc /* 1065b2b69f49Smarc * stuff qdmap structure in return buffer 1066b2b69f49Smarc */ 10677881ece5Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 10687e911b15Skarels break; 10697e911b15Skarels 10707e911b15Skarels case QD_MAPIOBUF: 1071b2b69f49Smarc /* 1072b2b69f49Smarc * do setup for DMA by user process 1073b2b69f49Smarc * 1074b2b69f49Smarc * set 'user write enable' bits for DMA buffer 1075b2b69f49Smarc */ 10767e911b15Skarels qdflags[unit].mapped |= MAPDMA; 10777e911b15Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 10787e911b15Skarels + (mfpr(SBR) | 0x80000000)); 10797881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 10807881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 10817881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 1082b2b69f49Smarc /* 1083b2b69f49Smarc * set up QBUS map registers for DMA 1084b2b69f49Smarc */ 10857e911b15Skarels DMAheader[unit]->QBAreg = 10867881ece5Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 10877e911b15Skarels if (DMAheader[unit]->QBAreg == 0) 10887881ece5Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 10897e911b15Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 10907e911b15Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 1091b2b69f49Smarc /* 1092b2b69f49Smarc * return I/O buf adr 1093b2b69f49Smarc */ 10947e911b15Skarels *(int *)datap = (int) DMAheader[unit]; 10957e911b15Skarels break; 10967e911b15Skarels 10977e911b15Skarels case QD_MAPSCROLL: 1098b2b69f49Smarc /* 1099b2b69f49Smarc * map the shared scroll param area and enable scroll interpts 1100b2b69f49Smarc */ 11017e911b15Skarels qdflags[unit].mapped |= MAPSCR; 11027e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 11037e911b15Skarels + (mfpr(SBR) | 0x80000000)); 1104b2b69f49Smarc /* 1105b2b69f49Smarc * allow user write to scroll area 1106b2b69f49Smarc */ 11077e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11087881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 11097e911b15Skarels scroll[unit]->status = 0; 11107e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11117e911b15Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 11127e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 1113b2b69f49Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 11147e911b15Skarels break; 11157e911b15Skarels 11167e911b15Skarels case QD_UNMAPSCROLL: 1117b2b69f49Smarc /* 1118b2b69f49Smarc * unmap shared scroll param area and disable scroll intrpts 1119b2b69f49Smarc */ 11207e911b15Skarels if (qdflags[unit].mapped & MAPSCR) { 11217e911b15Skarels qdflags[unit].mapped &= ~MAPSCR; 11227e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 11237e911b15Skarels + (mfpr(SBR) | 0x80000000)); 1124b2b69f49Smarc /* 1125b2b69f49Smarc * re-protect 512 scroll param area 1126b2b69f49Smarc */ 11277e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 11287e911b15Skarels mtpr(TBIA, 0); /* smash CPU's translation buf */ 11297e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11307e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC; 11317e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11327e911b15Skarels } 11337e911b15Skarels break; 11347e911b15Skarels 11357e911b15Skarels case QD_MAPCOLOR: 1136b2b69f49Smarc /* 1137b2b69f49Smarc * map shared color map write buf and turn on vsync intrpt 1138b2b69f49Smarc */ 11397e911b15Skarels qdflags[unit].mapped |= MAPCOLOR; 11407e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 11417e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11427881ece5Smarc /* 11437881ece5Smarc * allow user write to color map write buffer 11447881ece5Smarc */ 11457881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 11467e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11477e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 1148b2b69f49Smarc adder = (struct adder *) qdmap[unit].adder; 11497e911b15Skarels qdflags[unit].adder_ie |= VSYNC; 11507e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11517881ece5Smarc /* 11527881ece5Smarc * return color area address 11537881ece5Smarc */ 11547e911b15Skarels *(int *)datap = (int) color_buf[unit]; 11557e911b15Skarels break; 11567e911b15Skarels 11577e911b15Skarels case QD_UNMAPCOLOR: 1158b2b69f49Smarc /* 1159b2b69f49Smarc * unmap shared color map write buffer and kill VSYNC intrpts 1160b2b69f49Smarc */ 11617e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) { 11627e911b15Skarels qdflags[unit].mapped &= ~MAPCOLOR; 11637e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 11647e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11657881ece5Smarc /* 11667881ece5Smarc * re-protect color map write buffer 11677881ece5Smarc */ 11687881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 11697e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 11707881ece5Smarc mtpr(TBIA, 0); 11717e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11727e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC; 11737e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11747e911b15Skarels } 11757e911b15Skarels break; 11767e911b15Skarels 11777e911b15Skarels case QD_MAPEVENT: 1178b2b69f49Smarc /* 1179b2b69f49Smarc * give user write access to the event queue 1180b2b69f49Smarc */ 11817e911b15Skarels qdflags[unit].mapped |= MAPEQ; 11827e911b15Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 11837e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11847881ece5Smarc /* 11857881ece5Smarc * allow user write to 1K event queue 11867881ece5Smarc */ 11877881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 11887e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11897e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 11907881ece5Smarc /* 11917881ece5Smarc * return event queue address 11927881ece5Smarc */ 11937e911b15Skarels *(int *)datap = (int)eq_header[unit]; 11947e911b15Skarels break; 11957e911b15Skarels 11967e911b15Skarels case QD_PRGKBD: 1197b2b69f49Smarc /* 1198b2b69f49Smarc * pass caller's programming commands to LK201 1199b2b69f49Smarc */ 12007e911b15Skarels duart = (struct duart *)qdmap[unit].duart; 12017e911b15Skarels cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 1202b2b69f49Smarc /* 1203b2b69f49Smarc * send command 1204b2b69f49Smarc */ 12057e911b15Skarels for (i = 1000; i > 0; --i) { 12067881ece5Smarc if (duart->statusA&XMT_RDY) { 12077e911b15Skarels duart->dataA = cmdbuf->cmd; 12087e911b15Skarels break; 12097e911b15Skarels } 12107e911b15Skarels } 12117e911b15Skarels if (i == 0) { 12127881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 12137e911b15Skarels break; 12147e911b15Skarels } 1215b2b69f49Smarc /* 1216b2b69f49Smarc * send param1? 1217b2b69f49Smarc */ 12187e911b15Skarels if (cmdbuf->cmd & LAST_PARAM) 12197e911b15Skarels break; 12207e911b15Skarels for (i = 1000; i > 0; --i) { 12217881ece5Smarc if (duart->statusA&XMT_RDY) { 12227e911b15Skarels duart->dataA = cmdbuf->param1; 12237e911b15Skarels break; 12247e911b15Skarels } 12257e911b15Skarels } 12267e911b15Skarels if (i == 0) { 12277881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 12287e911b15Skarels break; 12297e911b15Skarels } 1230b2b69f49Smarc /* 1231b2b69f49Smarc * send param2? 1232b2b69f49Smarc */ 12337e911b15Skarels if (cmdbuf->param1 & LAST_PARAM) 12347e911b15Skarels break; 12357e911b15Skarels for (i = 1000; i > 0; --i) { 12367881ece5Smarc if (duart->statusA&XMT_RDY) { 12377e911b15Skarels duart->dataA = cmdbuf->param2; 12387e911b15Skarels break; 12397e911b15Skarels } 12407e911b15Skarels } 12417e911b15Skarels if (i == 0) { 12427881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 12437e911b15Skarels break; 12447e911b15Skarels } 12457e911b15Skarels break; 12467e911b15Skarels 12477e911b15Skarels case QD_PRGMOUSE: 1248b2b69f49Smarc /* 1249b2b69f49Smarc * pass caller's programming commands to the mouse 1250b2b69f49Smarc */ 12517e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 12527e911b15Skarels for (i = 1000; i > 0; --i) { 12537881ece5Smarc if (duart->statusB&XMT_RDY) { 12547e911b15Skarels duart->dataB = *datap; 12557e911b15Skarels break; 12567e911b15Skarels } 12577e911b15Skarels } 12587e911b15Skarels if (i == 0) { 12597881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 12607e911b15Skarels } 12617e911b15Skarels break; 12627e911b15Skarels 12637e911b15Skarels case QD_RDCONFIG: 1264b2b69f49Smarc /* 1265b2b69f49Smarc * get QDSS configuration word and return it 1266b2b69f49Smarc */ 12677e911b15Skarels *(short *)datap = qdflags[unit].config; 12687e911b15Skarels break; 12697e911b15Skarels 1270e977faadSmarc case QD_KERN_LOOP: 1271e977faadSmarc case QD_KERN_UNLOOP: 1272b2b69f49Smarc /* 1273b2b69f49Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 1274b2b69f49Smarc * kernel console output. 1275b2b69f49Smarc */ 1276e977faadSmarc break; 1277e977faadSmarc 12787e911b15Skarels case QD_PRGTABLET: 1279b2b69f49Smarc /* 1280b2b69f49Smarc * program the tablet 1281b2b69f49Smarc */ 12827e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 12837e911b15Skarels for (i = 1000; i > 0; --i) { 12847881ece5Smarc if (duart->statusB&XMT_RDY) { 12857e911b15Skarels duart->dataB = *datap; 12867e911b15Skarels break; 12877e911b15Skarels } 12887e911b15Skarels } 12897e911b15Skarels if (i == 0) { 12907881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 12917e911b15Skarels } 12927e911b15Skarels break; 12937e911b15Skarels 12947e911b15Skarels case QD_PRGTABRES: 1295b2b69f49Smarc /* 1296b2b69f49Smarc * program the tablet report resolution factor 1297b2b69f49Smarc */ 12987e911b15Skarels qdflags[unit].tab_res = *(short *)datap; 12997e911b15Skarels break; 13008a2bf9b0Smarc 13017e911b15Skarels default: 1302b2b69f49Smarc /* 1303b2b69f49Smarc * service tty ioctl's 1304b2b69f49Smarc */ 13057e911b15Skarels if (!(minor_dev & 0x02)) { 13067e911b15Skarels tp = &qd_tty[minor_dev]; 1307b2b69f49Smarc error = 1308b2b69f49Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 13097e911b15Skarels if (error >= 0) { 13107e911b15Skarels return(error); 13117e911b15Skarels } 13127e911b15Skarels error = ttioctl(tp, cmd, datap, flags); 13137e911b15Skarels if (error >= 0) { 13147e911b15Skarels return(error); 13157e911b15Skarels } 13167e911b15Skarels } 13177e911b15Skarels break; 13187e911b15Skarels } 13197e911b15Skarels 13207e911b15Skarels return(0); 13217e911b15Skarels 13227e911b15Skarels } /* qdioctl */ 13237e911b15Skarels 13247e911b15Skarels qdselect(dev, rw) 13257e911b15Skarels dev_t dev; 13267e911b15Skarels int rw; 13277e911b15Skarels { 13287881ece5Smarc register s; 13297881ece5Smarc register unit; 1330e977faadSmarc register struct tty *tp; 1331e977faadSmarc u_int minor_dev = minor(dev); 13327e911b15Skarels 1333e977faadSmarc s = spl5(); 1334e977faadSmarc unit = minor_dev >> 2; 13357e911b15Skarels 13367e911b15Skarels switch (rw) { 1337e977faadSmarc case FREAD: 1338b2b69f49Smarc if ((minor_dev & 0x03) == 2) { 1339e977faadSmarc /* 1340e977faadSmarc * this is a graphics device, so check for events 1341e977faadSmarc */ 13427881ece5Smarc if(!(ISEMPTY(eq_header[unit]))) { 13437e911b15Skarels splx(s); 1344e977faadSmarc return(1); 13457e911b15Skarels } 13467881ece5Smarc qdrsel[unit] = u.u_procp; 13477e911b15Skarels qdflags[unit].selmask |= SEL_READ; 13487e911b15Skarels splx(s); 13497e911b15Skarels return(0); 1350b2b69f49Smarc } else { 1351e977faadSmarc /* 1352e977faadSmarc * this is a tty device 1353e977faadSmarc */ 1354e977faadSmarc tp = &qd_tty[minor_dev]; 1355e977faadSmarc if (ttnread(tp)) 1356e977faadSmarc return(1); 1357e977faadSmarc tp->t_rsel = u.u_procp; 13587e911b15Skarels splx(s); 1359e977faadSmarc return(0); 1360e977faadSmarc } 1361e977faadSmarc 1362e977faadSmarc case FWRITE: 1363b2b69f49Smarc if ((minor(dev) & 0x03) == 2) { 1364e977faadSmarc /* 1365e977faadSmarc * this is a graphics device, so check for dma buffers 1366e977faadSmarc */ 1367e977faadSmarc if (DMA_ISEMPTY(DMAheader[unit])) 1368e977faadSmarc { 1369e977faadSmarc splx(s); 1370e977faadSmarc return(1); 13717e911b15Skarels } 13727881ece5Smarc qdrsel[unit] = u.u_procp; 13737e911b15Skarels qdflags[unit].selmask |= SEL_WRITE; 13747e911b15Skarels splx(s); 13757e911b15Skarels return(0); 1376b2b69f49Smarc } else { 1377e977faadSmarc /* 1378e977faadSmarc * this is a tty device 1379e977faadSmarc */ 1380e977faadSmarc tp = &qd_tty[minor_dev]; 1381f5319004Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 1382e977faadSmarc return(1); 1383e977faadSmarc tp->t_wsel = u.u_procp; 1384e977faadSmarc splx(s); 1385e977faadSmarc return(0); 1386e977faadSmarc } 1387e977faadSmarc } 13887881ece5Smarc splx(s); 13897881ece5Smarc return(0); 13907e911b15Skarels 13917e911b15Skarels } /* qdselect() */ 13927e911b15Skarels 13937e911b15Skarels extern qd_strategy(); 13947e911b15Skarels 13957e911b15Skarels qdwrite(dev, uio) 13967e911b15Skarels dev_t dev; 13977e911b15Skarels struct uio *uio; 13987e911b15Skarels { 13997e911b15Skarels register struct tty *tp; 14007881ece5Smarc register minor_dev; 14017881ece5Smarc register unit; 14027e911b15Skarels 14037e911b15Skarels minor_dev = minor(dev); 14047e911b15Skarels unit = (minor_dev >> 2) & 0x07; 14057e911b15Skarels 1406b2b69f49Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 1407b2b69f49Smarc /* 1408b2b69f49Smarc * this is the console... 1409b2b69f49Smarc */ 14107e911b15Skarels tp = &qd_tty[minor_dev]; 14117e911b15Skarels return ((*linesw[tp->t_line].l_write)(tp, uio)); 1412b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1413b2b69f49Smarc /* 1414b2b69f49Smarc * this is a DMA xfer from user space 1415b2b69f49Smarc */ 14167e911b15Skarels return (physio(qd_strategy, &qdbuf[unit], 14177e911b15Skarels dev, B_WRITE, minphys, uio)); 14187e911b15Skarels } 14197881ece5Smarc return (ENXIO); 14207e911b15Skarels } 14217e911b15Skarels 14227e911b15Skarels qdread(dev, uio) 14237e911b15Skarels dev_t dev; 14247e911b15Skarels struct uio *uio; 14257e911b15Skarels { 14267e911b15Skarels register struct tty *tp; 14277881ece5Smarc register minor_dev; 14287881ece5Smarc register unit; 14297e911b15Skarels 14307e911b15Skarels minor_dev = minor(dev); 14317e911b15Skarels unit = (minor_dev >> 2) & 0x07; 14327e911b15Skarels 1433b2b69f49Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 1434b2b69f49Smarc /* 1435b2b69f49Smarc * this is the console 1436b2b69f49Smarc */ 14377e911b15Skarels tp = &qd_tty[minor_dev]; 14387e911b15Skarels return ((*linesw[tp->t_line].l_read)(tp, uio)); 1439b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1440b2b69f49Smarc /* 1441b2b69f49Smarc * this is a bitmap-to-processor xfer 1442b2b69f49Smarc */ 14437e911b15Skarels return (physio(qd_strategy, &qdbuf[unit], 14447e911b15Skarels dev, B_READ, minphys, uio)); 14457e911b15Skarels } 14467881ece5Smarc return (ENXIO); 14477e911b15Skarels } 14487e911b15Skarels 14497e911b15Skarels /*************************************************************** 14507e911b15Skarels * 14517e911b15Skarels * qd_strategy()... strategy routine to do DMA 14527e911b15Skarels * 14537e911b15Skarels ***************************************************************/ 14547e911b15Skarels 14557e911b15Skarels qd_strategy(bp) 14567e911b15Skarels register struct buf *bp; 14577e911b15Skarels { 14587e911b15Skarels register struct dga *dga; 14597e911b15Skarels register struct adder *adder; 14607881ece5Smarc register unit; 14617e911b15Skarels int QBAreg; 14627e911b15Skarels int s; 14637e911b15Skarels int cookie; 14647e911b15Skarels 14657e911b15Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 14667e911b15Skarels 1467b2b69f49Smarc /* 1468b2b69f49Smarc * init pointers 1469b2b69f49Smarc */ 14707e911b15Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 14717881ece5Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 14727e911b15Skarels goto STRAT_ERR; 14737e911b15Skarels } 14747e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 1475e977faadSmarc s = spl5(); 14767e911b15Skarels qdflags[unit].user_dma = -1; 14777e911b15Skarels dga->csr |= DMA_IE; 14787e911b15Skarels cookie = QBAreg & 0x3FFFF; 14797e911b15Skarels dga->adrs_lo = (short) cookie; 14807e911b15Skarels dga->adrs_hi = (short) (cookie >> 16); 14817e911b15Skarels dga->bytcnt_lo = (short) bp->b_bcount; 14827e911b15Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 14837e911b15Skarels 14847e911b15Skarels while (qdflags[unit].user_dma) { 14857e911b15Skarels sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 14867e911b15Skarels } 14877e911b15Skarels splx(s); 14887e911b15Skarels ubarelse(0, &QBAreg); 14897e911b15Skarels if (!(dga->csr & DMA_ERR)) { 14907e911b15Skarels iodone(bp); 14917e911b15Skarels return; 14927e911b15Skarels } 14937e911b15Skarels 14947e911b15Skarels STRAT_ERR: 14957e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 14967e911b15Skarels adder->command = CANCEL; /* cancel adder activity */ 14977e911b15Skarels dga->csr &= ~DMA_IE; 14987e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 14997e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 15007e911b15Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 15017e911b15Skarels 1502b2b69f49Smarc /* 1503b2b69f49Smarc * if DMA was running, flush spurious intrpt 1504b2b69f49Smarc */ 15057e911b15Skarels if (dga->bytcnt_lo != 0) { 15067e911b15Skarels dga->bytcnt_lo = 0; 15077e911b15Skarels dga->bytcnt_hi = 0; 15087e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 15097e911b15Skarels dga->csr |= DMA_IE; 15107e911b15Skarels } 15117e911b15Skarels iodone(bp); 15127e911b15Skarels 15137e911b15Skarels } /* qd_strategy */ 15147e911b15Skarels 15157881ece5Smarc /* 15167881ece5Smarc * Start output to the console screen 15177881ece5Smarc */ 15187e911b15Skarels qdstart(tp) 15197e911b15Skarels register struct tty *tp; 15207e911b15Skarels { 15217881ece5Smarc register which_unit, unit, c; 15227e911b15Skarels int s; 15237e911b15Skarels 1524e977faadSmarc unit = minor(tp->t_dev); 1525e977faadSmarc which_unit = (unit >> 2) & 0x3; 1526e977faadSmarc unit &= 0x03; 1527e977faadSmarc 1528e977faadSmarc s = spl5(); 1529e977faadSmarc 1530b2b69f49Smarc /* 1531b2b69f49Smarc * If it's currently active, or delaying, no need to do anything. 1532b2b69f49Smarc */ 15337e911b15Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 15347e911b15Skarels goto out; 15357e911b15Skarels 1536b2b69f49Smarc /* 1537b2b69f49Smarc * Display chars until the queue is empty. 1538b2b69f49Smarc * Drop input from anything but the console 1539b2b69f49Smarc * device on the floor. 1540b2b69f49Smarc * 1541b2b69f49Smarc * XXX - this loop is done at spltty. 1542b2b69f49Smarc * 1543b2b69f49Smarc */ 15447e911b15Skarels while (tp->t_outq.c_cc) { 15457e911b15Skarels c = getc(&tp->t_outq); 1546e977faadSmarc if (unit == 0) 15477881ece5Smarc blitc(which_unit, (u_char)c); 15487e911b15Skarels } 1549b2b69f49Smarc /* 1550e977faadSmarc * If there are sleepers, and output has drained below low 1551b2b69f49Smarc * water mark, wake up the sleepers. 1552b2b69f49Smarc */ 1553f5319004Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 15547e911b15Skarels if (tp->t_state & TS_ASLEEP){ 15557e911b15Skarels tp->t_state &= ~TS_ASLEEP; 15567e911b15Skarels wakeup((caddr_t) &tp->t_outq); 15577e911b15Skarels } 1558e977faadSmarc } 1559e977faadSmarc 1560e977faadSmarc tp->t_state &= ~TS_BUSY; 15617e911b15Skarels 15627e911b15Skarels out: 15637e911b15Skarels splx(s); 15647e911b15Skarels 15657e911b15Skarels } /* qdstart */ 15667e911b15Skarels 15677881ece5Smarc /*ARGSUSED*/ 15687e911b15Skarels qdstop(tp, flag) 15697e911b15Skarels register struct tty *tp; 15707e911b15Skarels int flag; 15717e911b15Skarels { 15727e911b15Skarels register int s; 15737e911b15Skarels 1574e977faadSmarc s = spl5(); /* block intrpts during state modification */ 15757881ece5Smarc if (tp->t_state & TS_BUSY) 15767881ece5Smarc if ((tp->t_state & TS_TTSTOP) == 0) 15777e911b15Skarels tp->t_state |= TS_FLUSH; 1578b2b69f49Smarc else 15797e911b15Skarels tp->t_state &= ~TS_BUSY; 15807e911b15Skarels splx(s); 15817e911b15Skarels } 15827e911b15Skarels 15837881ece5Smarc /* 15847881ece5Smarc * Output a character to the QDSS screen 15857881ece5Smarc */ 15867e911b15Skarels 15877e911b15Skarels blitc(unit, chr) 15887881ece5Smarc register unit; 15897881ece5Smarc register u_char chr; 15907e911b15Skarels { 15917e911b15Skarels register struct adder *adder; 15927e911b15Skarels register struct dga *dga; 15937e911b15Skarels register int i; 1594b2b69f49Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 1595b2b69f49Smarc static short inescape[NQD]; 15967e911b15Skarels 15977e911b15Skarels adder = (struct adder *)qdmap[unit].adder; 15987e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 1599b2b69f49Smarc /* 1600b2b69f49Smarc * BSD comment: this (&=0177) defeats the extended character 1601b2b69f49Smarc * set code for the glass tty, but if i had the time i would 1602b2b69f49Smarc * spend it ripping out the code completely. This driver 1603b2b69f49Smarc * is too big for its own good. 1604b2b69f49Smarc */ 1605b2b69f49Smarc chr &= 0177; 1606b2b69f49Smarc /* 16077881ece5Smarc * Cursor addressing (so vi will work). 1608b2b69f49Smarc * Decode for "\E=%.%." cursor motion description. 16097881ece5Smarc * Corresponds to type "qdcons" in /etc/termcap: 1610b2b69f49Smarc * 1611b2b69f49Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 1612b2b69f49Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 1613b2b69f49Smarc * 1614b2b69f49Smarc */ 1615b2b69f49Smarc if (inescape[unit] && nograph) { 1616b2b69f49Smarc switch (inescape[unit]++) { 1617b2b69f49Smarc case 1: 1618b2b69f49Smarc if (chr != '=') { 1619b2b69f49Smarc /* abort escape sequence */ 1620b2b69f49Smarc inescape[unit] = 0; 1621b2b69f49Smarc blitc(unit, chr); 1622b2b69f49Smarc } 16237881ece5Smarc return; 1624b2b69f49Smarc case 2: 1625b2b69f49Smarc /* position row */ 1626b2b69f49Smarc cursor[unit].y = CHAR_HEIGHT * chr; 1627b2b69f49Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 1628b2b69f49Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 1629b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 16307881ece5Smarc return; 1631b2b69f49Smarc case 3: 1632b2b69f49Smarc /* position column */ 1633b2b69f49Smarc cursor[unit].x = CHAR_WIDTH * chr; 1634b2b69f49Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 1635b2b69f49Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 1636b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1637b2b69f49Smarc inescape[unit] = 0; 16387881ece5Smarc return; 1639b2b69f49Smarc default: 1640b2b69f49Smarc inescape[unit] = 0; 1641b2b69f49Smarc blitc(unit, chr); 1642b2b69f49Smarc } 1643b2b69f49Smarc } 164424f67f6bSmarc 16457e911b15Skarels switch (chr) { 16467e911b15Skarels case '\r': /* return char */ 16477e911b15Skarels cursor[unit].x = 0; 1648b2b69f49Smarc if (nograph) 16497e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 16507881ece5Smarc return; 16517e911b15Skarels 16527e911b15Skarels case '\t': /* tab char */ 16537e911b15Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 16547e911b15Skarels blitc(unit, ' '); 16557e911b15Skarels } 16567881ece5Smarc return; 16577e911b15Skarels 16587e911b15Skarels case '\n': /* line feed char */ 16597e911b15Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 1660b2b69f49Smarc if (nograph) { 16617e911b15Skarels cursor[unit].y -= CHAR_HEIGHT; 16627e911b15Skarels scroll_up(adder); 1663b2b69f49Smarc } else 1664b2b69f49Smarc cursor[unit].y = 0; 16657e911b15Skarels } 1666b2b69f49Smarc if (nograph) 16677e911b15Skarels dga->y_cursor = TRANY(cursor[unit].y); 16687881ece5Smarc return; 16697e911b15Skarels 16707e911b15Skarels case '\b': /* backspace char */ 16717e911b15Skarels if (cursor[unit].x > 0) { 16727e911b15Skarels cursor[unit].x -= CHAR_WIDTH; 1673b2b69f49Smarc if (nograph) 1674b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1675b2b69f49Smarc } 16767881ece5Smarc return; 1677b2b69f49Smarc case CTRL('k'): /* cursor up */ 1678b2b69f49Smarc if (nograph && cursor[unit].y > 0) { 1679b2b69f49Smarc cursor[unit].y -= CHAR_HEIGHT; 1680b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1681b2b69f49Smarc } 16827881ece5Smarc return; 1683b2b69f49Smarc 1684b2b69f49Smarc case CTRL('^'): /* home cursor */ 1685b2b69f49Smarc if (nograph) { 1686b2b69f49Smarc cursor[unit].x = 0; 1687b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1688b2b69f49Smarc cursor[unit].y = 0; 1689b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1690b2b69f49Smarc } 16917881ece5Smarc return; 1692b2b69f49Smarc 1693b2b69f49Smarc case CTRL('l'): /* cursor right */ 1694b2b69f49Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 1695b2b69f49Smarc cursor[unit].x += CHAR_WIDTH; 16967e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 16977e911b15Skarels } 16987881ece5Smarc return; 16997e911b15Skarels 1700b2b69f49Smarc case CTRL('z'): /* clear screen */ 1701b2b69f49Smarc if (nograph) { 1702b2b69f49Smarc setup_dragon(unit); 1703b2b69f49Smarc clear_qd_screen(unit); 1704b2b69f49Smarc /* home cursor - termcap seems to assume this */ 1705b2b69f49Smarc cursor[unit].x = 0; 1706b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1707b2b69f49Smarc cursor[unit].y = 0; 1708b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1709b2b69f49Smarc } 17107881ece5Smarc return; 1711e977faadSmarc 1712b2b69f49Smarc case '\033': /* start escape sequence */ 1713b2b69f49Smarc if (nograph) 1714b2b69f49Smarc inescape[unit] = 1; 17157881ece5Smarc return; 1716b2b69f49Smarc 1717b2b69f49Smarc default: 1718b2b69f49Smarc if ((chr < ' ') || (chr > '~')) 17197881ece5Smarc return; 17207e911b15Skarels } 1721b2b69f49Smarc /* 1722b2b69f49Smarc * setup VIPER operand control registers 1723b2b69f49Smarc */ 17247e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 17257e911b15Skarels write_ID(adder, SRC1_OCR_B, 17267e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 17277e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 17287e911b15Skarels write_ID(adder, SRC1_OCR_B, 17297e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 17307e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 17317e911b15Skarels write_ID(adder, DST_OCR_B, 17327e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 17337e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 17347e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 17357e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 1736e977faadSmarc adder->x_clip_min = 0; 1737e977faadSmarc adder->x_clip_max = 1024; 1738e977faadSmarc adder->y_clip_min = 0; 1739e977faadSmarc adder->y_clip_max = 864; 1740b2b69f49Smarc /* 1741b2b69f49Smarc * load DESTINATION origin and vectors 1742b2b69f49Smarc */ 17437e911b15Skarels adder->fast_dest_dy = 0; 17447e911b15Skarels adder->slow_dest_dx = 0; 17457e911b15Skarels adder->error_1 = 0; 17467e911b15Skarels adder->error_2 = 0; 17477e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 17487881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 17497e911b15Skarels adder->destination_x = cursor[unit].x; 17507e911b15Skarels adder->fast_dest_dx = CHAR_WIDTH; 17517e911b15Skarels adder->destination_y = cursor[unit].y; 17527e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; 1753b2b69f49Smarc /* 1754b2b69f49Smarc * load SOURCE origin and vectors 1755b2b69f49Smarc */ 1756e977faadSmarc if ((chr - ' ') > (CHARS - 1)) { 1757e977faadSmarc printf("Invalid character (x)%x in blitc\n",chr); 1758e977faadSmarc chr = ' '; 1759e977faadSmarc } 1760b2b69f49Smarc /* 1761b2b69f49Smarc * X position is modulo the number of characters per line 1762b2b69f49Smarc */ 1763e977faadSmarc adder->source_1_x = FONT_X + 1764e977faadSmarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 1765b2b69f49Smarc /* 1766b2b69f49Smarc * Point to either first or second row 1767b2b69f49Smarc */ 1768e977faadSmarc adder->source_1_y = 2048 - 15 * 1769e977faadSmarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 17707e911b15Skarels adder->source_1_dx = CHAR_WIDTH; 17717e911b15Skarels adder->source_1_dy = CHAR_HEIGHT; 17727e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 17737e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 1774b2b69f49Smarc /* 1775b2b69f49Smarc * update console cursor coordinates 1776b2b69f49Smarc */ 17777e911b15Skarels cursor[unit].x += CHAR_WIDTH; 1778b2b69f49Smarc if (nograph) 17797e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 17807e911b15Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 17817e911b15Skarels blitc(unit, '\r'); 17827e911b15Skarels blitc(unit, '\n'); 17837e911b15Skarels } 17847e911b15Skarels 17857e911b15Skarels } /* blitc */ 17867e911b15Skarels 17877881ece5Smarc qdreset() { } 17887e911b15Skarels 17897881ece5Smarc /* 1790b2b69f49Smarc * INTERRUPT SERVICE ROUTINES 17917881ece5Smarc */ 17927e911b15Skarels 17937881ece5Smarc /* 17947881ece5Smarc * Service "DMA DONE" interrupt condition 17957881ece5Smarc */ 17967e911b15Skarels qddint(qd) 17977881ece5Smarc register qd; 17987e911b15Skarels { 17997e911b15Skarels register struct DMAreq_header *header; 18007e911b15Skarels register struct DMAreq *request; 18017e911b15Skarels register struct dga *dga; 18027e911b15Skarels struct adder *adder; 18037e911b15Skarels int cookie; /* DMA adrs for QDSS */ 18047e911b15Skarels 18057881ece5Smarc (void)spl4(); /* allow interval timer in */ 18067e911b15Skarels 1807b2b69f49Smarc /* 1808b2b69f49Smarc * init pointers 1809b2b69f49Smarc */ 18107e911b15Skarels header = DMAheader[qd]; /* register for optimization */ 18117e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 18127e911b15Skarels adder = (struct adder *) qdmap[qd].adder; 18137e911b15Skarels 1814b2b69f49Smarc /* 1815b2b69f49Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 1816b2b69f49Smarc */ 18177e911b15Skarels if (DMA_ISIGNORE(header)) { 18187e911b15Skarels DMA_CLRIGNORE(header); 18197e911b15Skarels return; 18207e911b15Skarels } 18217e911b15Skarels 1822b2b69f49Smarc /* 1823b2b69f49Smarc * dump a DMA hardware error message if appropriate 1824b2b69f49Smarc */ 18257e911b15Skarels if (dga->csr & DMA_ERR) { 18267e911b15Skarels 18277e911b15Skarels if (dga->csr & PARITY_ERR) 18287881ece5Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 18297e911b15Skarels 18307e911b15Skarels if (dga->csr & BUS_ERR) 18317881ece5Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 18327e911b15Skarels } 18337e911b15Skarels 1834b2b69f49Smarc /* 1835b2b69f49Smarc * if this was a DMA from user space... 1836b2b69f49Smarc */ 18377e911b15Skarels if (qdflags[qd].user_dma) { 18387e911b15Skarels qdflags[qd].user_dma = 0; 18397e911b15Skarels wakeup((caddr_t)&qdflags[qd].user_dma); 18407e911b15Skarels return; 18417e911b15Skarels } 18427e911b15Skarels 1843b2b69f49Smarc /* 1844b2b69f49Smarc * if we're doing DMA request queue services, field the error condition 1845b2b69f49Smarc */ 18467e911b15Skarels if (dga->csr & DMA_ERR) { 18477e911b15Skarels 18487e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 18497e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 18507e911b15Skarels adder->command = CANCEL; /* cancel adder activity */ 18517e911b15Skarels 18527e911b15Skarels DMA_SETERROR(header); /* flag error in header status word */ 18537e911b15Skarels DMA_CLRACTIVE(header); 18547e911b15Skarels header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 18557e911b15Skarels header->newest = header->oldest; 18567e911b15Skarels header->used = 0; 18577e911b15Skarels 18587881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18597881ece5Smarc selwakeup(qdrsel[qd], 0); 18607881ece5Smarc qdrsel[qd] = 0; 18617e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18627e911b15Skarels } 18637e911b15Skarels 18647e911b15Skarels if (dga->bytcnt_lo != 0) { 18657e911b15Skarels dga->bytcnt_lo = 0; 18667e911b15Skarels dga->bytcnt_hi = 0; 18677e911b15Skarels DMA_SETIGNORE(header); 18687e911b15Skarels } 18697e911b15Skarels return; 18707e911b15Skarels } 18717e911b15Skarels 1872b2b69f49Smarc /* 1873b2b69f49Smarc * if the DMA request queue is now becoming non-full, 1874b2b69f49Smarc * wakeup "select" client. 1875b2b69f49Smarc */ 18767e911b15Skarels if (DMA_ISFULL(header)) { 18777881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18787881ece5Smarc selwakeup(qdrsel[qd], 0); 18797881ece5Smarc qdrsel[qd] = 0; 18807e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18817e911b15Skarels } 18827e911b15Skarels } 18837e911b15Skarels 18847e911b15Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 1885e977faadSmarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 18867e911b15Skarels 1887e977faadSmarc /* check for unexpected interrupt */ 1888e977faadSmarc if (DMA_ISEMPTY(header)) 18897e911b15Skarels return; 18907e911b15Skarels 18917e911b15Skarels DMA_GETEND(header); /* update request queue indices */ 18927e911b15Skarels 1893b2b69f49Smarc /* 18947881ece5Smarc * if no more DMA pending, wake up "select" client and exit 18957881ece5Smarc */ 18967e911b15Skarels if (DMA_ISEMPTY(header)) { 18977e911b15Skarels 18987881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18997881ece5Smarc selwakeup(qdrsel[qd], 0); 19007881ece5Smarc qdrsel[qd] = 0; 19017e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 19027e911b15Skarels } 19037e911b15Skarels 19047e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 19057e911b15Skarels return; 19067e911b15Skarels } 19077e911b15Skarels 1908b2b69f49Smarc /* 19097881ece5Smarc * initiate next DMA xfer 19107881ece5Smarc */ 19117e911b15Skarels request = DMA_GETBEGIN(header); 1912e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1913e977faadSmarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 1914e977faadSmarc adder->command = CANCEL; /* cancel adder activity */ 1915e977faadSmarc } 1916e977faadSmarc 19177e911b15Skarels 19187e911b15Skarels switch (request->DMAtype) { 19197e911b15Skarels 19207e911b15Skarels case DISPLIST: 1921e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 19227e911b15Skarels dga->csr |= DL_ENB; 1923e977faadSmarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 1924e977faadSmarc } 19257e911b15Skarels break; 19267e911b15Skarels 19277e911b15Skarels case PTOB: 1928e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1929e977faadSmarc if (request->DMAdone & BYTE_PACK) 1930e977faadSmarc dga->csr |= (PTOB_ENB | BYTE_DMA); 1931e977faadSmarc else { 19327e911b15Skarels dga->csr |= PTOB_ENB; 1933e977faadSmarc dga->csr &= ~BYTE_DMA; 1934e977faadSmarc } 1935e977faadSmarc } 19367e911b15Skarels break; 19377e911b15Skarels 19387e911b15Skarels case BTOP: 1939e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1940e977faadSmarc if (request->DMAdone & BYTE_PACK) { 1941e977faadSmarc dga->csr &= ~DL_ENB; 1942e977faadSmarc dga->csr |= (BTOP_ENB | BYTE_DMA); 1943e977faadSmarc } 1944e977faadSmarc else { 19457e911b15Skarels dga->csr |= BTOP_ENB; 1946e977faadSmarc dga->csr &= ~(BYTE_DMA | DL_ENB); 1947e977faadSmarc } 1948e977faadSmarc } 19497e911b15Skarels break; 19507e911b15Skarels default: 19517881ece5Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 19527e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 19537e911b15Skarels return; 19547e911b15Skarels } 19557e911b15Skarels 19567e911b15Skarels if (request->DMAdone & COUNT_ZERO) { 19577e911b15Skarels dga->csr &= ~SET_DONE_FIFO; 1958b2b69f49Smarc } 1959b2b69f49Smarc else if (request->DMAdone & FIFO_EMPTY) { 19607e911b15Skarels dga->csr |= SET_DONE_FIFO; 19617e911b15Skarels } 19627e911b15Skarels 19637e911b15Skarels if (request->DMAdone & WORD_PACK) 19647e911b15Skarels dga->csr &= ~BYTE_DMA; 19657e911b15Skarels else if (request->DMAdone & BYTE_PACK) 19667e911b15Skarels dga->csr |= BYTE_DMA; 19677e911b15Skarels 19687e911b15Skarels dga->csr |= DMA_IE; 1969e977faadSmarc QDlast_DMAtype = request->DMAtype; 19707e911b15Skarels 19717e911b15Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 19727e911b15Skarels 19737e911b15Skarels dga->adrs_lo = (short) cookie; 19747e911b15Skarels dga->adrs_hi = (short) (cookie >> 16); 19757e911b15Skarels 19767e911b15Skarels dga->bytcnt_lo = (short) request->length; 19777e911b15Skarels dga->bytcnt_hi = (short) (request->length >> 16); 19787e911b15Skarels 19797e911b15Skarels return; 19807e911b15Skarels } 19817e911b15Skarels 19827881ece5Smarc /* 19837881ece5Smarc * ADDER interrupt service routine 19847881ece5Smarc */ 19857e911b15Skarels qdaint(qd) 19867881ece5Smarc register qd; 19877e911b15Skarels { 19887e911b15Skarels register struct adder *adder; 19897e911b15Skarels struct color_buf *cbuf; 19907e911b15Skarels int i; 19917e911b15Skarels register struct rgb *rgbp; 19927e911b15Skarels register short *red; 19937e911b15Skarels register short *green; 19947e911b15Skarels register short *blue; 19957e911b15Skarels 19967881ece5Smarc (void)spl4(); /* allow interval timer in */ 19977e911b15Skarels 19987e911b15Skarels adder = (struct adder *) qdmap[qd].adder; 19997e911b15Skarels 2000b2b69f49Smarc /* 2001b2b69f49Smarc * service the vertical blank interrupt (VSYNC bit) by loading 2002b2b69f49Smarc * any pending color map load request 2003b2b69f49Smarc */ 20047e911b15Skarels if (adder->status & VSYNC) { 20057e911b15Skarels adder->status &= ~VSYNC; /* clear the interrupt */ 20067e911b15Skarels cbuf = color_buf[qd]; 20077e911b15Skarels if (cbuf->status & LOAD_COLOR_MAP) { 20087e911b15Skarels 20097e911b15Skarels red = (short *) qdmap[qd].red; 20107e911b15Skarels green = (short *) qdmap[qd].green; 20117e911b15Skarels blue = (short *) qdmap[qd].blue; 20127e911b15Skarels 2013b2b69f49Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 2014b2b69f49Smarc --i >= 0; rgbp++) { 20157e911b15Skarels red[rgbp->offset] = (short) rgbp->red; 20167e911b15Skarels green[rgbp->offset] = (short) rgbp->green; 20177e911b15Skarels blue[rgbp->offset] = (short) rgbp->blue; 20187e911b15Skarels } 20197e911b15Skarels 20207e911b15Skarels cbuf->status &= ~LOAD_COLOR_MAP; 20217e911b15Skarels } 20227e911b15Skarels } 20237e911b15Skarels 2024b2b69f49Smarc /* 2025b2b69f49Smarc * service the scroll interrupt (FRAME_SYNC bit) 2026b2b69f49Smarc */ 20277e911b15Skarels if (adder->status & FRAME_SYNC) { 20287e911b15Skarels adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 20297e911b15Skarels 20307e911b15Skarels if (scroll[qd]->status & LOAD_REGS) { 20317e911b15Skarels 20327881ece5Smarc for (i = 1000, adder->status = 0; i > 0 && 20337881ece5Smarc !(adder->status&ID_SCROLL_READY); --i) 2034b2b69f49Smarc ; 20357e911b15Skarels 20367e911b15Skarels if (i == 0) { 20377881ece5Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 2038b2b69f49Smarc qd); 20397e911b15Skarels return; 20407e911b15Skarels } 20417e911b15Skarels 20427e911b15Skarels adder->ID_scroll_data = scroll[qd]->viper_constant; 20437e911b15Skarels adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 20447e911b15Skarels 2045b2b69f49Smarc adder->y_scroll_constant = 2046b2b69f49Smarc scroll[qd]->y_scroll_constant; 20477e911b15Skarels adder->y_offset_pending = scroll[qd]->y_offset; 20487e911b15Skarels 20497e911b15Skarels if (scroll[qd]->status & LOAD_INDEX) { 20507e911b15Skarels 2051b2b69f49Smarc adder->x_index_pending = 2052b2b69f49Smarc scroll[qd]->x_index_pending; 2053b2b69f49Smarc adder->y_index_pending = 2054b2b69f49Smarc scroll[qd]->y_index_pending; 20557e911b15Skarels } 20567e911b15Skarels 20577e911b15Skarels scroll[qd]->status = 0x00; 20587e911b15Skarels } 20597e911b15Skarels } 20607e911b15Skarels } 20617e911b15Skarels 20627881ece5Smarc /* 20637881ece5Smarc * DUART input interrupt service routine 20647e911b15Skarels * 2065b2b69f49Smarc * XXX - this routine should be broken out - it is essentially 2066b2b69f49Smarc * straight line code. 20677881ece5Smarc */ 20687e911b15Skarels 20697e911b15Skarels qdiint(qd) 20707881ece5Smarc register qd; 20717e911b15Skarels { 20727e911b15Skarels register struct _vs_event *event; 20737e911b15Skarels register struct qdinput *eqh; 20747e911b15Skarels struct dga *dga; 20757e911b15Skarels struct duart *duart; 20767e911b15Skarels struct mouse_report *new_rep; 20777e911b15Skarels struct uba_device *ui; 20787e911b15Skarels struct tty *tp; 2079e977faadSmarc u_short chr; 20807e911b15Skarels u_short status; 20817e911b15Skarels u_short data; 20827e911b15Skarels u_short key; 20837e911b15Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 20847e911b15Skarels char a, b, c; /* mouse button test variables */ 20857e911b15Skarels 20867881ece5Smarc (void)spl4(); /* allow interval timer in */ 20877e911b15Skarels 20887e911b15Skarels eqh = eq_header[qd]; /* optimized as a register */ 20897e911b15Skarels new_rep = ¤t_rep[qd]; 20907e911b15Skarels duart = (struct duart *) qdmap[qd].duart; 20917e911b15Skarels 2092b2b69f49Smarc /* 20937881ece5Smarc * if the graphic device is turned on.. 20947881ece5Smarc */ 20957e911b15Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 2096b2b69f49Smarc /* 2097b2b69f49Smarc * empty DUART 2098b2b69f49Smarc */ 20997881ece5Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 2100b2b69f49Smarc /* 21017881ece5Smarc * pick up LK-201 input (if any) 21027881ece5Smarc */ 21037881ece5Smarc if (duart->statusA&RCV_RDY) { 21047e911b15Skarels 21057e911b15Skarels /* if error condition, then reset it */ 21067e911b15Skarels 21077881ece5Smarc if (duart->statusA&0x70) { 21087e911b15Skarels duart->cmdA = 0x40; 21097e911b15Skarels continue; 21107e911b15Skarels } 21117e911b15Skarels 21127e911b15Skarels /* event queue full now? (overflow condition) */ 21137e911b15Skarels 21147e911b15Skarels if (ISFULL(eqh) == TRUE) { 2115b2b69f49Smarc printf( 21167881ece5Smarc "qd%d: qdiint: event queue overflow\n", 2117b2b69f49Smarc qd); 21187e911b15Skarels break; 21197e911b15Skarels } 21207e911b15Skarels 2121b2b69f49Smarc /* 21227e911b15Skarels * Check for various keyboard errors */ 21237e911b15Skarels 21247e911b15Skarels key = duart->dataA & 0xFF; 21257e911b15Skarels 2126b2b69f49Smarc if (key==LK_POWER_ERROR || 2127b2b69f49Smarc key==LK_KDOWN_ERROR || 2128b2b69f49Smarc key == LK_INPUT_ERROR || 2129b2b69f49Smarc key == LK_OUTPUT_ERROR) { 2130b2b69f49Smarc printf( 21317881ece5Smarc "qd%d: qdiint: keyboard error, code = %x\n", 2132b2b69f49Smarc qd,key); 21337881ece5Smarc return; 21347e911b15Skarels } 21357e911b15Skarels 21367e911b15Skarels if (key < LK_LOWEST) 21377881ece5Smarc return; 21387e911b15Skarels 21397e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 21407e911b15Skarels 21417e911b15Skarels event = PUTBEGIN(eqh); 21427e911b15Skarels PUTEND(eqh); 21437e911b15Skarels 21447e911b15Skarels event->vse_key = key; 21457e911b15Skarels event->vse_key &= 0x00FF; 21467e911b15Skarels event->vse_x = eqh->curs_pos.x; 21477e911b15Skarels event->vse_y = eqh->curs_pos.y; 21487e911b15Skarels event->vse_time = TOY; 21497e911b15Skarels event->vse_type = VSE_BUTTON; 21507e911b15Skarels event->vse_direction = VSE_KBTRAW; 21517e911b15Skarels event->vse_device = VSE_DKB; 21527e911b15Skarels } 21537e911b15Skarels 2154b2b69f49Smarc /* 21557e911b15Skarels * pick up the mouse input (if any) */ 21567e911b15Skarels 21577e911b15Skarels if ((status = duart->statusB) & RCV_RDY && 21587e911b15Skarels qdflags[qd].pntr_id == MOUSE_ID) { 21597e911b15Skarels 21607e911b15Skarels if (status & 0x70) { 21617e911b15Skarels duart->cmdB = 0x40; 21627e911b15Skarels continue; 21637e911b15Skarels } 21647e911b15Skarels 21657e911b15Skarels /* event queue full now? (overflow condition) */ 21667e911b15Skarels 21677e911b15Skarels if (ISFULL(eqh) == TRUE) { 2168b2b69f49Smarc printf( 21697881ece5Smarc "qd%d: qdiint: event queue overflow\n", 2170b2b69f49Smarc qd); 21717e911b15Skarels break; 21727e911b15Skarels } 21737e911b15Skarels 21747e911b15Skarels data = duart->dataB; /* get report byte */ 21757e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */ 21767e911b15Skarels 2177b2b69f49Smarc /* 21787e911b15Skarels * if 1st byte of report.. */ 21797e911b15Skarels 21807e911b15Skarels if ( data & START_FRAME) { 21817e911b15Skarels new_rep->state = data; 21827e911b15Skarels if (new_rep->bytcnt > 1) { 2183b2b69f49Smarc /* start of new frame */ 2184b2b69f49Smarc new_rep->bytcnt = 1; 2185b2b69f49Smarc /* ..continue looking */ 2186b2b69f49Smarc continue; 21877e911b15Skarels } 21887e911b15Skarels } 21897e911b15Skarels 2190b2b69f49Smarc /* 21917e911b15Skarels * if 2nd byte of report.. */ 21927e911b15Skarels 21937e911b15Skarels else if (new_rep->bytcnt == 2) { 21947e911b15Skarels new_rep->dx = data & 0x00FF; 21957e911b15Skarels } 21967e911b15Skarels 2197b2b69f49Smarc /* 21987e911b15Skarels * if 3rd byte of report, load input event queue */ 21997e911b15Skarels 22007e911b15Skarels else if (new_rep->bytcnt == 3) { 22017e911b15Skarels 22027e911b15Skarels new_rep->dy = data & 0x00FF; 22037e911b15Skarels new_rep->bytcnt = 0; 22047e911b15Skarels 2205b2b69f49Smarc /* 22067e911b15Skarels * if mouse position has changed.. */ 22077e911b15Skarels 22087e911b15Skarels if (new_rep->dx != 0 || new_rep->dy != 0) { 22097e911b15Skarels 2210b2b69f49Smarc /* 22117e911b15Skarels * calculate acceleration factor, if needed */ 22127e911b15Skarels 22137e911b15Skarels if (qdflags[qd].curs_acc > ACC_OFF) { 22147e911b15Skarels 22157e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dx) 22167e911b15Skarels new_rep->dx += 22177e911b15Skarels (new_rep->dx - qdflags[qd].curs_thr) 22187e911b15Skarels * qdflags[qd].curs_acc; 22197e911b15Skarels 22207e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dy) 22217e911b15Skarels new_rep->dy += 22227e911b15Skarels (new_rep->dy - qdflags[qd].curs_thr) 22237e911b15Skarels * qdflags[qd].curs_acc; 22247e911b15Skarels } 22257e911b15Skarels 2226b2b69f49Smarc /* 22277e911b15Skarels * update cursor position coordinates */ 22287e911b15Skarels 22297e911b15Skarels if (new_rep->state & X_SIGN) { 22307e911b15Skarels eqh->curs_pos.x += new_rep->dx; 22317e911b15Skarels if (eqh->curs_pos.x > 1023) 22327e911b15Skarels eqh->curs_pos.x = 1023; 22337e911b15Skarels } 22347e911b15Skarels else { 22357e911b15Skarels eqh->curs_pos.x -= new_rep->dx; 22367e911b15Skarels if (eqh->curs_pos.x < -15) 22377e911b15Skarels eqh->curs_pos.x = -15; 22387e911b15Skarels } 22397e911b15Skarels 22407e911b15Skarels if (new_rep->state & Y_SIGN) { 22417e911b15Skarels eqh->curs_pos.y -= new_rep->dy; 22427e911b15Skarels if (eqh->curs_pos.y < -15) 22437e911b15Skarels eqh->curs_pos.y = -15; 22447e911b15Skarels } 22457e911b15Skarels else { 22467e911b15Skarels eqh->curs_pos.y += new_rep->dy; 22477e911b15Skarels if (eqh->curs_pos.y > 863) 22487e911b15Skarels eqh->curs_pos.y = 863; 22497e911b15Skarels } 22507e911b15Skarels 2251b2b69f49Smarc /* 22527e911b15Skarels * update cursor screen position */ 22537e911b15Skarels 22547e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 22557e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x); 22567e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y); 22577e911b15Skarels 2258b2b69f49Smarc /* 22597e911b15Skarels * if cursor is in the box, no event report */ 22607e911b15Skarels 22617e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right && 22627e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left && 22637e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top && 22647e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) { 22657e911b15Skarels goto GET_MBUTTON; 22667e911b15Skarels } 22677e911b15Skarels 2268b2b69f49Smarc /* 22697e911b15Skarels * report the mouse motion event */ 22707e911b15Skarels 22717e911b15Skarels event = PUTBEGIN(eqh); 22727e911b15Skarels PUTEND(eqh); 22737e911b15Skarels 22747e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 22757e911b15Skarels 22767e911b15Skarels event->vse_x = eqh->curs_pos.x; 22777e911b15Skarels event->vse_y = eqh->curs_pos.y; 22787e911b15Skarels 22797e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */ 22807e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */ 22817e911b15Skarels event->vse_key = 0; 22827e911b15Skarels event->vse_direction = 0; 22837e911b15Skarels event->vse_time = TOY; /* time stamp */ 22847e911b15Skarels } 22857e911b15Skarels 22867e911b15Skarels GET_MBUTTON: 2287b2b69f49Smarc /* 22887e911b15Skarels * if button state has changed */ 22897e911b15Skarels 22907e911b15Skarels a = new_rep->state & 0x07; /*mask nonbutton bits */ 22917e911b15Skarels b = last_rep[qd].state & 0x07; 22927e911b15Skarels 22937e911b15Skarels if (a ^ b) { 22947e911b15Skarels 22957e911b15Skarels for ( c = 1; c < 8; c <<= 1) { 22967e911b15Skarels 22977e911b15Skarels if (!( c & (a ^ b))) /* this button change? */ 22987e911b15Skarels continue; 22997e911b15Skarels 23007e911b15Skarels /* event queue full? (overflow condition) */ 23017e911b15Skarels 23027e911b15Skarels if (ISFULL(eqh) == TRUE) { 23037881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 23047e911b15Skarels break; 23057e911b15Skarels } 23067e911b15Skarels 23077e911b15Skarels event = PUTBEGIN(eqh); /* get new event */ 23087e911b15Skarels PUTEND(eqh); 23097e911b15Skarels 23107e911b15Skarels ++do_wakeup; /* request select wakeup */ 23117e911b15Skarels 23127e911b15Skarels event->vse_x = eqh->curs_pos.x; 23137e911b15Skarels event->vse_y = eqh->curs_pos.y; 23147e911b15Skarels 23157e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */ 23167e911b15Skarels event->vse_type = VSE_BUTTON; /* new button */ 23177e911b15Skarels event->vse_time = TOY; /* time stamp */ 23187e911b15Skarels 23197e911b15Skarels /* flag changed button and if up or down */ 23207e911b15Skarels 23217e911b15Skarels if (c == RIGHT_BUTTON) 23227e911b15Skarels event->vse_key = VSE_RIGHT_BUTTON; 23237e911b15Skarels else if (c == MIDDLE_BUTTON) 23247e911b15Skarels event->vse_key = VSE_MIDDLE_BUTTON; 23257e911b15Skarels else if (c == LEFT_BUTTON) 23267e911b15Skarels event->vse_key = VSE_LEFT_BUTTON; 23277e911b15Skarels 23287e911b15Skarels /* set bit = button depressed */ 23297e911b15Skarels 23307e911b15Skarels if (c & a) 23317e911b15Skarels event->vse_direction = VSE_KBTDOWN; 23327e911b15Skarels else 23337e911b15Skarels event->vse_direction = VSE_KBTUP; 23347e911b15Skarels } 23357e911b15Skarels } 23367e911b15Skarels 23377e911b15Skarels /* refresh last report */ 23387e911b15Skarels 23397e911b15Skarels last_rep[qd] = current_rep[qd]; 23407e911b15Skarels 23417e911b15Skarels } /* get last byte of report */ 23427881ece5Smarc } else if ((status = duart->statusB)&RCV_RDY && 23437e911b15Skarels qdflags[qd].pntr_id == TABLET_ID) { 23447881ece5Smarc /* 23457881ece5Smarc * pickup tablet input, if any 23467881ece5Smarc */ 23477e911b15Skarels if (status&0x70) { 23487e911b15Skarels duart->cmdB = 0x40; 23497e911b15Skarels continue; 23507e911b15Skarels } 23517881ece5Smarc /* 23527881ece5Smarc * event queue full now? (overflow condition) 23537881ece5Smarc */ 23547e911b15Skarels if (ISFULL(eqh) == TRUE) { 23557881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 23567e911b15Skarels break; 23577e911b15Skarels } 23587e911b15Skarels 23597e911b15Skarels data = duart->dataB; /* get report byte */ 23607e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */ 23617e911b15Skarels 2362b2b69f49Smarc /* 23637e911b15Skarels * if 1st byte of report.. */ 23647e911b15Skarels 23657e911b15Skarels if (data & START_FRAME) { 23667e911b15Skarels new_rep->state = data; 23677e911b15Skarels if (new_rep->bytcnt > 1) { 23687e911b15Skarels new_rep->bytcnt = 1; /* start of new frame */ 23697e911b15Skarels continue; /* ..continue looking */ 23707e911b15Skarels } 23717e911b15Skarels } 23727e911b15Skarels 2373b2b69f49Smarc /* 23747e911b15Skarels * if 2nd byte of report.. */ 23757e911b15Skarels 23767e911b15Skarels else if (new_rep->bytcnt == 2) { 23777e911b15Skarels new_rep->dx = data & 0x3F; 23787e911b15Skarels } 23797e911b15Skarels 2380b2b69f49Smarc /* 23817e911b15Skarels * if 3rd byte of report.. */ 23827e911b15Skarels 23837e911b15Skarels else if (new_rep->bytcnt == 3) { 23847e911b15Skarels new_rep->dx |= (data & 0x3F) << 6; 23857e911b15Skarels } 23867e911b15Skarels 2387b2b69f49Smarc /* 23887e911b15Skarels * if 4th byte of report.. */ 23897e911b15Skarels 23907e911b15Skarels else if (new_rep->bytcnt == 4) { 23917e911b15Skarels new_rep->dy = data & 0x3F; 23927e911b15Skarels } 23937e911b15Skarels 2394b2b69f49Smarc /* 23957e911b15Skarels * if 5th byte of report, load input event queue */ 23967e911b15Skarels 23977e911b15Skarels else if (new_rep->bytcnt == 5) { 23987e911b15Skarels 23997e911b15Skarels new_rep->dy |= (data & 0x3F) << 6; 24007e911b15Skarels new_rep->bytcnt = 0; 24017e911b15Skarels 2402b2b69f49Smarc /* 24037e911b15Skarels * update cursor position coordinates */ 24047e911b15Skarels 24057e911b15Skarels new_rep->dx /= qdflags[qd].tab_res; 24067e911b15Skarels new_rep->dy = (2200 - new_rep->dy) 24077e911b15Skarels / qdflags[qd].tab_res; 24087e911b15Skarels 24097e911b15Skarels if (new_rep->dx > 1023) { 24107e911b15Skarels new_rep->dx = 1023; 24117e911b15Skarels } 24127e911b15Skarels if (new_rep->dy > 863) { 24137e911b15Skarels new_rep->dy = 863; 24147e911b15Skarels } 24157e911b15Skarels 24167e911b15Skarels /* 24177e911b15Skarels * report an event if the puck/stylus has moved 24187e911b15Skarels */ 24197e911b15Skarels 24207e911b15Skarels if (eqh->curs_pos.x != new_rep->dx || 24217e911b15Skarels eqh->curs_pos.y != new_rep->dy) { 24227e911b15Skarels 24237e911b15Skarels eqh->curs_pos.x = new_rep->dx; 24247e911b15Skarels eqh->curs_pos.y = new_rep->dy; 24257e911b15Skarels 2426b2b69f49Smarc /* 24277e911b15Skarels * update cursor screen position */ 24287e911b15Skarels 24297e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 24307e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x); 24317e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y); 24327e911b15Skarels 24337e911b15Skarels /* 24347e911b15Skarels * if cursor is in the box, no event report 24357e911b15Skarels */ 24367e911b15Skarels 24377e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right && 24387e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left && 24397e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top && 24407e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) { 24417e911b15Skarels goto GET_TBUTTON; 24427e911b15Skarels } 24437e911b15Skarels 2444b2b69f49Smarc /* 24457e911b15Skarels * report the tablet motion event */ 24467e911b15Skarels 24477e911b15Skarels event = PUTBEGIN(eqh); 24487e911b15Skarels PUTEND(eqh); 24497e911b15Skarels 24507e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 24517e911b15Skarels 24527e911b15Skarels event->vse_x = eqh->curs_pos.x; 24537e911b15Skarels event->vse_y = eqh->curs_pos.y; 24547e911b15Skarels 24557e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */ 24567e911b15Skarels /* 24577e911b15Skarels * right now, X handles tablet motion the same 24587e911b15Skarels * as mouse motion 24597e911b15Skarels */ 24607e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */ 24617e911b15Skarels event->vse_key = 0; 24627e911b15Skarels event->vse_direction = 0; 24637e911b15Skarels event->vse_time = TOY; /* time stamp */ 24647e911b15Skarels } 24657e911b15Skarels GET_TBUTTON: 2466b2b69f49Smarc /* 24677e911b15Skarels * if button state has changed */ 24687e911b15Skarels 24697e911b15Skarels a = new_rep->state & 0x1E; /* mask nonbutton bits */ 24707e911b15Skarels b = last_rep[qd].state & 0x1E; 24717e911b15Skarels 24727e911b15Skarels if (a ^ b) { 24737e911b15Skarels 24747e911b15Skarels /* event queue full now? (overflow condition) */ 24757e911b15Skarels 24767e911b15Skarels if (ISFULL(eqh) == TRUE) { 24777881ece5Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 24787e911b15Skarels break; 24797e911b15Skarels } 24807e911b15Skarels 24817e911b15Skarels event = PUTBEGIN(eqh); /* get new event */ 24827e911b15Skarels PUTEND(eqh); 24837e911b15Skarels 24847e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 24857e911b15Skarels 24867e911b15Skarels event->vse_x = eqh->curs_pos.x; 24877e911b15Skarels event->vse_y = eqh->curs_pos.y; 24887e911b15Skarels 24897e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */ 24907e911b15Skarels event->vse_type = VSE_BUTTON; /* button changed */ 24917e911b15Skarels event->vse_time = TOY; /* time stamp */ 24927e911b15Skarels 24937e911b15Skarels /* define the changed button and if up or down */ 24947e911b15Skarels 24957e911b15Skarels for ( c = 1; c <= 0x10; c <<= 1) { 24967e911b15Skarels if (c & (a ^ b)) { 24977e911b15Skarels if (c == T_LEFT_BUTTON) 24987e911b15Skarels event->vse_key = VSE_T_LEFT_BUTTON; 24997e911b15Skarels else if (c == T_FRONT_BUTTON) 25007e911b15Skarels event->vse_key = VSE_T_FRONT_BUTTON; 25017e911b15Skarels else if (c == T_RIGHT_BUTTON) 25027e911b15Skarels event->vse_key = VSE_T_RIGHT_BUTTON; 25037e911b15Skarels else if (c == T_BACK_BUTTON) 25047e911b15Skarels event->vse_key = VSE_T_BACK_BUTTON; 25057e911b15Skarels break; 25067e911b15Skarels } 25077e911b15Skarels } 25087e911b15Skarels 25097e911b15Skarels /* set bit = button depressed */ 25107e911b15Skarels 25117e911b15Skarels if (c & a) 25127e911b15Skarels event->vse_direction = VSE_KBTDOWN; 25137e911b15Skarels else 25147e911b15Skarels event->vse_direction = VSE_KBTUP; 25157e911b15Skarels } 25167e911b15Skarels 25177e911b15Skarels /* refresh last report */ 25187e911b15Skarels 25197e911b15Skarels last_rep[qd] = current_rep[qd]; 25207e911b15Skarels 25217e911b15Skarels } /* get last byte of report */ 25227e911b15Skarels } /* pick up tablet input */ 25237e911b15Skarels 25247e911b15Skarels } /* while input available.. */ 25257e911b15Skarels 2526b2b69f49Smarc /* 2527b2b69f49Smarc * do select wakeup 2528b2b69f49Smarc */ 25297881ece5Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 25307881ece5Smarc selwakeup(qdrsel[qd], 0); 25317881ece5Smarc qdrsel[qd] = 0; 25327e911b15Skarels qdflags[qd].selmask &= ~SEL_READ; 25337e911b15Skarels do_wakeup = 0; 25347e911b15Skarels } 25357881ece5Smarc } else { 2536b2b69f49Smarc /* 25377881ece5Smarc * if the graphic device is not turned on, this is console input 25387881ece5Smarc */ 2539*f79d7b48Smarc if (qdpolling) 2540*f79d7b48Smarc return; 25417e911b15Skarels ui = qdinfo[qd]; 25427e911b15Skarels if (ui == 0 || ui->ui_alive == 0) 25437881ece5Smarc return; 25447e911b15Skarels 25457e911b15Skarels tp = &qd_tty[qd << 2]; 25467e911b15Skarels 2547b2b69f49Smarc /* 25487881ece5Smarc * Get a character from the keyboard. 25497881ece5Smarc */ 25507881ece5Smarc while (duart->statusA&RCV_RDY) { 25517e911b15Skarels key = duart->dataA; 25527e911b15Skarels key &= 0xFF; 2553b2b69f49Smarc /* 25547881ece5Smarc * Check for various keyboard errors 25557881ece5Smarc */ 25567e911b15Skarels if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 25577e911b15Skarels key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 25587881ece5Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 25597881ece5Smarc return; 25607e911b15Skarels } 25617e911b15Skarels 25627e911b15Skarels if (key < LK_LOWEST) 25637881ece5Smarc return; 25647e911b15Skarels 2565b2b69f49Smarc /* 25667e911b15Skarels * See if its a state change key */ 25677e911b15Skarels 25687e911b15Skarels switch (key) { 25697e911b15Skarels 25707e911b15Skarels case LOCK: 25717e911b15Skarels q_keyboard.lock ^= 0xffff; /* toggle */ 25727e911b15Skarels if (q_keyboard.lock) 25737881ece5Smarc (void)led_control(qd, LK_LED_ENABLE, 25747881ece5Smarc LK_LED_LOCK); 25757e911b15Skarels else 25767881ece5Smarc (void)led_control(qd, LK_LED_DISABLE, 25777881ece5Smarc LK_LED_LOCK); 25787e911b15Skarels return; 25797e911b15Skarels 25807e911b15Skarels case SHIFT: 25817e911b15Skarels q_keyboard.shift ^= 0xFFFF; 25827e911b15Skarels return; 25837e911b15Skarels 25847e911b15Skarels case CNTRL: 25857e911b15Skarels q_keyboard.cntrl ^= 0xFFFF; 25867e911b15Skarels return; 25877e911b15Skarels 25887e911b15Skarels case ALLUP: 25897e911b15Skarels q_keyboard.cntrl = 0; 25907e911b15Skarels q_keyboard.shift = 0; 25917e911b15Skarels return; 25927e911b15Skarels 25937e911b15Skarels case REPEAT: 25947e911b15Skarels chr = q_keyboard.last; 25957e911b15Skarels break; 25967e911b15Skarels 2597b2b69f49Smarc /* 25987e911b15Skarels * Test for cntrl characters. If set, see if the character 25997e911b15Skarels * is elligible to become a control character. */ 26007e911b15Skarels 26017e911b15Skarels default: 26027e911b15Skarels 26037e911b15Skarels if (q_keyboard.cntrl) { 26047e911b15Skarels chr = q_key[key]; 26057e911b15Skarels if (chr >= ' ' && chr <= '~') 26067e911b15Skarels chr &= 0x1F; 2607e977faadSmarc else if (chr >= 0xA1 && chr <= 0xFE) 2608e977faadSmarc chr &= 0x9F; 26097e911b15Skarels } 26107e911b15Skarels else if( q_keyboard.lock || q_keyboard.shift ) 26117e911b15Skarels chr = q_shift_key[key]; 26127e911b15Skarels else 26137e911b15Skarels chr = q_key[key]; 26147e911b15Skarels break; 26157e911b15Skarels } 26167e911b15Skarels 26177e911b15Skarels q_keyboard.last = chr; 26187e911b15Skarels 2619b2b69f49Smarc /* 26207e911b15Skarels * Check for special function keys */ 26217e911b15Skarels 2622e977faadSmarc if (chr & 0x100) { 26237e911b15Skarels char *string; 26247e911b15Skarels string = q_special[chr & 0x7F]; 26257e911b15Skarels while(*string) 26267e911b15Skarels (*linesw[tp->t_line].l_rint)(*string++, tp); 26277e911b15Skarels } 26287e911b15Skarels else { 2629*f79d7b48Smarc #ifdef KADB 2630*f79d7b48Smarc if (!kdbrintr(chr&0177, tp)) 2631*f79d7b48Smarc #endif 2632b2b69f49Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 26337e911b15Skarels } 26347e911b15Skarels } 26357e911b15Skarels } 26367e911b15Skarels } /* qdiint */ 26377e911b15Skarels 26387881ece5Smarc /* 26397e911b15Skarels * 26407881ece5Smarc * Clear the QDSS screen 26417e911b15Skarels * 26427e911b15Skarels * >>> NOTE <<< 26437e911b15Skarels * 26447e911b15Skarels * This code requires that certain adder initialization be valid. To 26457e911b15Skarels * assure that this requirement is satisfied, this routine should be 26467e911b15Skarels * called only after calling the "setup_dragon()" function. 26477e911b15Skarels * 26487e911b15Skarels * Clear the bitmap a piece at a time. Since the fast scroll clear 26497e911b15Skarels * only clears the current displayed portion of the bitmap put a 26507e911b15Skarels * temporary value in the y limit register so we can access whole 26517e911b15Skarels * bitmap 26527e911b15Skarels * 26537881ece5Smarc */ 26547e911b15Skarels clear_qd_screen(unit) 26557e911b15Skarels int unit; 26567e911b15Skarels { 26577e911b15Skarels register struct adder *adder; 26587e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 26597e911b15Skarels 26607e911b15Skarels adder->x_limit = 1024; 26617e911b15Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 26627e911b15Skarels adder->y_offset_pending = 0; 26637881ece5Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 2664b2b69f49Smarc WSV; 26657e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2666b2b69f49Smarc WSV; 26677e911b15Skarels adder->y_offset_pending = 864; 2668b2b69f49Smarc WSV; 26697e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2670b2b69f49Smarc WSV; 26717e911b15Skarels adder->y_offset_pending = 1728; 2672b2b69f49Smarc WSV; 26737e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2674b2b69f49Smarc WSV; 26757e911b15Skarels adder->y_offset_pending = 0; /* back to normal */ 2676b2b69f49Smarc WSV; 26777e911b15Skarels adder->x_limit = MAX_SCREEN_X; 26787e911b15Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 2679b2b69f49Smarc #undef WSV 26807e911b15Skarels 26817e911b15Skarels } /* clear_qd_screen */ 26827e911b15Skarels 26837881ece5Smarc /* 26847881ece5Smarc * kernel console output to the glass tty 26857881ece5Smarc */ 26867e911b15Skarels qdputc(chr) 26877e911b15Skarels register char chr; 26887e911b15Skarels { 26897e911b15Skarels 2690b2b69f49Smarc /* 2691b2b69f49Smarc * if system is now physical, forget it (ie: crash DUMP) 2692b2b69f49Smarc */ 26937e911b15Skarels if ((mfpr(MAPEN) & 1) == 0) 26947e911b15Skarels return; 26957e911b15Skarels 26967881ece5Smarc blitc(0, (u_char)(chr & 0xff)); 269724f67f6bSmarc if ((chr & 0177) == '\n') 269824f67f6bSmarc blitc(0, '\r'); 269924f67f6bSmarc 27007e911b15Skarels } /* qdputc */ 27017e911b15Skarels 2702b2b69f49Smarc /* 27037881ece5Smarc * load the mouse cursor's template RAM bitmap 27047881ece5Smarc */ 27057e911b15Skarels ldcursor(unit, bitmap) 27067881ece5Smarc int unit; 27077881ece5Smarc register short *bitmap; 27087e911b15Skarels { 27097e911b15Skarels register struct dga *dga; 27107e911b15Skarels register short *temp; 27117e911b15Skarels register int i; 27127881ece5Smarc int curs; 27137e911b15Skarels 27147e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 27157e911b15Skarels temp = (short *) qdmap[unit].template; 27167e911b15Skarels 27177e911b15Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 27187881ece5Smarc curs = -1; /* ..note that.. */ 27197e911b15Skarels dga->csr &= ~CURS_ENB; /* ..and shut it off */ 27207881ece5Smarc } else 27217881ece5Smarc curs = 0; 27227e911b15Skarels 27237e911b15Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 27247e911b15Skarels 27257e911b15Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 27267e911b15Skarels /* ..of the 8k WORD template space */ 27277e911b15Skarels for (i = 0; i < 32; ++i) 27287e911b15Skarels *temp++ = *bitmap++; 27297e911b15Skarels 27307881ece5Smarc if (curs) { /* if cursor was enabled.. */ 27317e911b15Skarels dga->csr |= CURS_ENB; /* ..turn it back on */ 27327e911b15Skarels } 27337e911b15Skarels 27347e911b15Skarels } /* ldcursor */ 27357e911b15Skarels 27367881ece5Smarc /* 27377881ece5Smarc * Put the console font in the QDSS off-screen memory 27387881ece5Smarc */ 27397e911b15Skarels ldfont(unit) 27407881ece5Smarc int unit; 27417e911b15Skarels { 27427e911b15Skarels register struct adder *adder; 27437e911b15Skarels 27447881ece5Smarc register i, j, k, max_chars_line; 27457881ece5Smarc register short packed; 27467e911b15Skarels 27477e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 27487e911b15Skarels 2749b2b69f49Smarc /* 27507881ece5Smarc * setup VIPER operand control registers 27517881ece5Smarc */ 27527e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 27537e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 27547e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 27557e911b15Skarels 27567e911b15Skarels write_ID(adder, SRC1_OCR_B, 27577e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 27587e911b15Skarels write_ID(adder, SRC2_OCR_B, 27597e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 27607e911b15Skarels write_ID(adder, DST_OCR_B, 27617e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 27627e911b15Skarels 27637e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 27647e911b15Skarels 2765b2b69f49Smarc /* 27667881ece5Smarc * load destination data 27677881ece5Smarc */ 27687881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 27697e911b15Skarels 27707e911b15Skarels adder->destination_x = FONT_X; 27717e911b15Skarels adder->destination_y = FONT_Y; 27727881ece5Smarc #if FONT_WIDTH > MAX_SCREEN_X 2773e977faadSmarc adder->fast_dest_dx = MAX_SCREEN_X; 27747881ece5Smarc #else 27757e911b15Skarels adder->fast_dest_dx = FONT_WIDTH; 27767881ece5Smarc #endif 27777e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; 27787e911b15Skarels 2779b2b69f49Smarc /* 27807e911b15Skarels * setup for processor to bitmap xfer */ 27817e911b15Skarels 27827e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 27837e911b15Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 27847e911b15Skarels 2785b2b69f49Smarc /* 2786b2b69f49Smarc * Figure out how many characters can be stored on one "line" of 2787b2b69f49Smarc * offscreen memory. 2788e977faadSmarc */ 2789e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2790e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line) 2791e977faadSmarc max_chars_line = CHARS/2 + CHARS%2; 2792e977faadSmarc 2793b2b69f49Smarc /* 2794e977faadSmarc * iteratively do the processor to bitmap xfer */ 2795e977faadSmarc 2796e977faadSmarc for (i = 0; i < ROWS; ++i) { 2797e977faadSmarc 2798e977faadSmarc /* PTOB a scan line */ 2799e977faadSmarc 2800e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) { 2801e977faadSmarc /* PTOB one scan of a char cell */ 2802e977faadSmarc 2803e977faadSmarc packed = q_font[k]; 2804e977faadSmarc k += ROWS; 2805e977faadSmarc packed |= ((short)q_font[k] << 8); 2806e977faadSmarc k += ROWS; 2807e977faadSmarc 28087881ece5Smarc (void)wait_status(adder, TX_READY); 2809e977faadSmarc adder->id_data = packed; 2810e977faadSmarc } 2811e977faadSmarc } 2812e977faadSmarc 2813b2b69f49Smarc /* 2814b2b69f49Smarc * (XXX XXX XXX - should remove) 2815b2b69f49Smarc * 2816b2b69f49Smarc * Copy the second row of characters. Subtract the first 2817b2b69f49Smarc * row from the total number. Divide this quantity by 2 2818b2b69f49Smarc * because 2 chars are stored in a short in the PTOB loop 2819b2b69f49Smarc * below. Figure out how many characters can be stored on 2820b2b69f49Smarc * one "line" of offscreen memory 2821e977faadSmarc */ 2822b2b69f49Smarc 2823e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2824e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line) 2825e977faadSmarc return; 2826e977faadSmarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 2827e977faadSmarc /* Paranoia check to see if 3rd row may be needed */ 2828e977faadSmarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 2829e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2830e977faadSmarc 2831e977faadSmarc adder->destination_x = FONT_X; 2832e977faadSmarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 2833e977faadSmarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 2834e977faadSmarc adder->slow_dest_dy = CHAR_HEIGHT; 2835e977faadSmarc 2836b2b69f49Smarc /* 2837b2b69f49Smarc * setup for processor to bitmap xfer 2838b2b69f49Smarc */ 2839e977faadSmarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 2840e977faadSmarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 2841e977faadSmarc 2842b2b69f49Smarc /* 2843b2b69f49Smarc * iteratively do the processor to bitmap xfer 2844b2b69f49Smarc */ 28457e911b15Skarels for (i = 0; i < ROWS; ++i) { 2846b2b69f49Smarc /* 2847b2b69f49Smarc * PTOB a scan line 2848b2b69f49Smarc */ 2849e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) { 2850b2b69f49Smarc /* 2851b2b69f49Smarc * PTOB one scan of a char cell 2852b2b69f49Smarc */ 2853e977faadSmarc packed = q_font[k + FONT_OFFSET]; 28547e911b15Skarels k += ROWS; 2855e977faadSmarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 28567e911b15Skarels k += ROWS; 28577881ece5Smarc (void)wait_status(adder, TX_READY); 28587e911b15Skarels adder->id_data = packed; 28597e911b15Skarels } 28607e911b15Skarels } 28617e911b15Skarels 28627e911b15Skarels } /* ldfont */ 28637e911b15Skarels 2864*f79d7b48Smarc qdpoll(onoff) 2865*f79d7b48Smarc { 2866*f79d7b48Smarc qdpolling = onoff; 2867*f79d7b48Smarc } 2868*f79d7b48Smarc 28697881ece5Smarc /* 28707881ece5Smarc * Get a character from the LK201 (polled) 28717881ece5Smarc */ 28727881ece5Smarc qdgetc() 28737e911b15Skarels { 28747881ece5Smarc register short key; 28757881ece5Smarc register char chr; 28767881ece5Smarc register struct duart *duart; 28777881ece5Smarc 28787881ece5Smarc duart = (struct duart *) qdmap[0].duart; 28797881ece5Smarc 28807881ece5Smarc /* 28817881ece5Smarc * Get a character from the keyboard. 28827881ece5Smarc */ 28837881ece5Smarc LOOP: 28847881ece5Smarc while (!(duart->statusA&RCV_RDY)) 28857881ece5Smarc ; 28867881ece5Smarc 28877881ece5Smarc key = duart->dataA; 28887881ece5Smarc key &= 0xFF; 28897881ece5Smarc 28907881ece5Smarc /* 28917881ece5Smarc * Check for various keyboard errors */ 28927881ece5Smarc 28937881ece5Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 28947881ece5Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 28957881ece5Smarc printf("Keyboard error, code = %x\n", key); 28967881ece5Smarc return(0); 28977881ece5Smarc } 28987881ece5Smarc 28997881ece5Smarc if (key < LK_LOWEST) 29007881ece5Smarc return(0); 29017881ece5Smarc 29027881ece5Smarc /* 29037881ece5Smarc * See if its a state change key 29047881ece5Smarc */ 29057881ece5Smarc switch (key) { 29067881ece5Smarc 29077881ece5Smarc case LOCK: 29087881ece5Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 29097881ece5Smarc if (q_keyboard.lock) 29107881ece5Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 29117881ece5Smarc else 29127881ece5Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 29137881ece5Smarc goto LOOP; 29147881ece5Smarc 29157881ece5Smarc case SHIFT: 29167881ece5Smarc q_keyboard.shift ^= 0xFFFF; 29177881ece5Smarc goto LOOP; 29187881ece5Smarc 29197881ece5Smarc case CNTRL: 29207881ece5Smarc q_keyboard.cntrl ^= 0xFFFF; 29217881ece5Smarc goto LOOP; 29227881ece5Smarc 29237881ece5Smarc case ALLUP: 29247881ece5Smarc q_keyboard.cntrl = 0; 29257881ece5Smarc q_keyboard.shift = 0; 29267881ece5Smarc goto LOOP; 29277881ece5Smarc 29287881ece5Smarc case REPEAT: 29297881ece5Smarc chr = q_keyboard.last; 29307881ece5Smarc break; 29317881ece5Smarc 29327881ece5Smarc /* 29337881ece5Smarc * Test for cntrl characters. If set, see if the character 29347881ece5Smarc * is elligible to become a control character. 29357881ece5Smarc */ 29367881ece5Smarc default: 29377881ece5Smarc 29387881ece5Smarc if (q_keyboard.cntrl) { 29397881ece5Smarc chr = q_key[key]; 29407881ece5Smarc if (chr >= ' ' && chr <= '~') 29417881ece5Smarc chr &= 0x1F; 29427881ece5Smarc } 29437881ece5Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 29447881ece5Smarc chr = q_shift_key[key]; 29457881ece5Smarc else 29467881ece5Smarc chr = q_key[key]; 29477881ece5Smarc break; 29487881ece5Smarc } 29497881ece5Smarc 29507881ece5Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 29517881ece5Smarc return(0); /* ..then pitch it! */ 29527881ece5Smarc 29537881ece5Smarc q_keyboard.last = chr; 29547881ece5Smarc 29557881ece5Smarc /* 29567881ece5Smarc * Check for special function keys */ 29577881ece5Smarc 29587881ece5Smarc if (chr & 0x80) /* pitch the function keys */ 29597881ece5Smarc return(0); 29607881ece5Smarc else 29617881ece5Smarc return(chr); 29627881ece5Smarc 29637881ece5Smarc } /* qdgetc */ 29647881ece5Smarc 29657881ece5Smarc /* 29667881ece5Smarc * led_control()... twiddle LK-201 LED's 29677881ece5Smarc */ 29687881ece5Smarc led_control(unit, cmd, led_mask) 29697881ece5Smarc int unit, cmd, led_mask; 29707881ece5Smarc { 29717881ece5Smarc register i; 29727e911b15Skarels register struct duart *duart; 29737e911b15Skarels 29747e911b15Skarels duart = (struct duart *)qdmap[unit].duart; 29757e911b15Skarels 29767e911b15Skarels for (i = 1000; i > 0; --i) { 29777881ece5Smarc if (duart->statusA&XMT_RDY) { 29787e911b15Skarels duart->dataA = cmd; 29797e911b15Skarels break; 29807e911b15Skarels } 29817e911b15Skarels } 29827e911b15Skarels for (i = 1000; i > 0; --i) { 29837881ece5Smarc if (duart->statusA&XMT_RDY) { 29847e911b15Skarels duart->dataA = led_mask; 29857e911b15Skarels break; 29867e911b15Skarels } 29877e911b15Skarels } 29887e911b15Skarels if (i == 0) 29897e911b15Skarels return(BAD); 29907e911b15Skarels return(GOOD); 29917e911b15Skarels 29927e911b15Skarels } /* led_control */ 29937e911b15Skarels 29947881ece5Smarc /* 29957e911b15Skarels * scroll_up()... move the screen up one character height 29967881ece5Smarc */ 29977e911b15Skarels scroll_up(adder) 29987e911b15Skarels register struct adder *adder; 29997e911b15Skarels { 3000b2b69f49Smarc /* 3001b2b69f49Smarc * setup VIPER operand control registers 3002b2b69f49Smarc */ 30037881ece5Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 30047e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 30057e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 30067e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 30077e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 30087e911b15Skarels write_ID(adder, SRC1_OCR_B, 30097e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 30107e911b15Skarels write_ID(adder, DST_OCR_B, 30117e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 3012b2b69f49Smarc /* 3013b2b69f49Smarc * load DESTINATION origin and vectors 3014b2b69f49Smarc */ 30157e911b15Skarels adder->fast_dest_dy = 0; 30167e911b15Skarels adder->slow_dest_dx = 0; 30177e911b15Skarels adder->error_1 = 0; 30187e911b15Skarels adder->error_2 = 0; 30197e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 30207e911b15Skarels adder->destination_x = 0; 30217e911b15Skarels adder->fast_dest_dx = 1024; 30227e911b15Skarels adder->destination_y = 0; 30237e911b15Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 3024b2b69f49Smarc /* 3025b2b69f49Smarc * load SOURCE origin and vectors 3026b2b69f49Smarc */ 30277e911b15Skarels adder->source_1_x = 0; 30287e911b15Skarels adder->source_1_dx = 1024; 30297e911b15Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 30307e911b15Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 30317e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 30327e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 3033b2b69f49Smarc /* 3034b2b69f49Smarc * do a rectangle clear of last screen line 3035b2b69f49Smarc */ 30367e911b15Skarels write_ID(adder, MASK_1, 0xffff); 30377e911b15Skarels write_ID(adder, SOURCE, 0xffff); 30387e911b15Skarels write_ID(adder,DST_OCR_B, 30397e911b15Skarels (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 30407e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 30417e911b15Skarels adder->error_1 = 0; 30427e911b15Skarels adder->error_2 = 0; 30437e911b15Skarels adder->slow_dest_dx = 0; /* set up the width of */ 30447e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 30457e911b15Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 30467881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 30477e911b15Skarels adder->destination_x = 0; 30487e911b15Skarels adder->destination_y = 864 - CHAR_HEIGHT; 30497e911b15Skarels adder->fast_dest_dx = 1024; /* set up the height */ 30507e911b15Skarels adder->fast_dest_dy = 0; /* of rectangle */ 30517e911b15Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 30527e911b15Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 30537e911b15Skarels 30547e911b15Skarels } /* scroll_up */ 30557e911b15Skarels 30567881ece5Smarc /* 30577881ece5Smarc * init shared memory pointers and structures 30587881ece5Smarc */ 30597e911b15Skarels init_shared(unit) 30607881ece5Smarc register unit; 30617e911b15Skarels { 30627e911b15Skarels register struct dga *dga; 30637e911b15Skarels 30647e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 30657e911b15Skarels 3066b2b69f49Smarc /* 30677e911b15Skarels * initialize the event queue pointers and header */ 30687e911b15Skarels 30697e911b15Skarels eq_header[unit] = (struct qdinput *) 30707e911b15Skarels ((((int)event_shared & ~(0x01FF)) + 512) 30717e911b15Skarels + (EVENT_BUFSIZE * unit)); 30727e911b15Skarels eq_header[unit]->curs_pos.x = 0; 30737e911b15Skarels eq_header[unit]->curs_pos.y = 0; 30747e911b15Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 30757e911b15Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 30767e911b15Skarels eq_header[unit]->curs_box.left = 0; 30777e911b15Skarels eq_header[unit]->curs_box.right = 0; 30787e911b15Skarels eq_header[unit]->curs_box.top = 0; 30797e911b15Skarels eq_header[unit]->curs_box.bottom = 0; 3080b2b69f49Smarc /* 3081b2b69f49Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 3082b2b69f49Smarc */ 30837e911b15Skarels DMAheader[unit] = (struct DMAreq_header *) 30847e911b15Skarels (((int)(&DMA_shared[0] + 512) & ~0x1FF) 30857e911b15Skarels + (DMAbuf_size * unit)); 30867e911b15Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 30877e911b15Skarels + sizeof(struct DMAreq_header)); 30887e911b15Skarels DMAheader[unit]->QBAreg = 0; 30897e911b15Skarels DMAheader[unit]->status = 0; 30907e911b15Skarels DMAheader[unit]->shared_size = DMAbuf_size; 30917e911b15Skarels DMAheader[unit]->used = 0; 30927e911b15Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 30937e911b15Skarels DMAheader[unit]->oldest = 0; 30947e911b15Skarels DMAheader[unit]->newest = 0; 3095b2b69f49Smarc /* 3096b2b69f49Smarc * assign a pointer to the scroll structure for this QDSS. 3097b2b69f49Smarc */ 30987e911b15Skarels scroll[unit] = (struct scroll *) 30997e911b15Skarels (((int)(&scroll_shared[0] + 512) & ~0x1FF) 31007e911b15Skarels + (sizeof(struct scroll) * unit)); 31017e911b15Skarels scroll[unit]->status = 0; 31027e911b15Skarels scroll[unit]->viper_constant = 0; 31037e911b15Skarels scroll[unit]->y_scroll_constant = 0; 31047e911b15Skarels scroll[unit]->y_offset = 0; 31057e911b15Skarels scroll[unit]->x_index_pending = 0; 31067e911b15Skarels scroll[unit]->y_index_pending = 0; 3107b2b69f49Smarc /* 3108b2b69f49Smarc * assign a pointer to the color map write buffer for this QDSS 3109b2b69f49Smarc */ 31107e911b15Skarels color_buf[unit] = (struct color_buf *) 31117e911b15Skarels (((int)(&color_shared[0] + 512) & ~0x1FF) 31127e911b15Skarels + (COLOR_BUFSIZ * unit)); 31137e911b15Skarels color_buf[unit]->status = 0; 31147e911b15Skarels color_buf[unit]->count = 0; 31157e911b15Skarels 31167e911b15Skarels } /* init_shared */ 31177e911b15Skarels 31187881ece5Smarc /* 31197881ece5Smarc * init the ADDER, VIPER, bitmaps, & color map 31207881ece5Smarc */ 31217e911b15Skarels setup_dragon(unit) 31227881ece5Smarc int unit; 31237e911b15Skarels { 31247e911b15Skarels 31257e911b15Skarels register struct adder *adder; 31267e911b15Skarels register struct dga *dga; 31277e911b15Skarels short *memcsr; 31287881ece5Smarc register i; 31297e911b15Skarels short top; /* clipping/scrolling boundaries */ 31307e911b15Skarels short bottom; 31317e911b15Skarels short right; 31327e911b15Skarels short left; 31337e911b15Skarels short *red; /* color map pointers */ 31347e911b15Skarels short *green; 31357e911b15Skarels short *blue; 31367e911b15Skarels 3137b2b69f49Smarc /* 3138b2b69f49Smarc * init for setup 3139b2b69f49Smarc */ 31407e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 31417e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 31427e911b15Skarels memcsr = (short *) qdmap[unit].memcsr; 31437e911b15Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 31447e911b15Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 31457e911b15Skarels adder->command = CANCEL; 3146b2b69f49Smarc /* 3147b2b69f49Smarc * set monitor timing 3148b2b69f49Smarc */ 31497e911b15Skarels adder->x_scan_count_0 = 0x2800; 31507e911b15Skarels adder->x_scan_count_1 = 0x1020; 31517e911b15Skarels adder->x_scan_count_2 = 0x003A; 31527e911b15Skarels adder->x_scan_count_3 = 0x38F0; 31537e911b15Skarels adder->x_scan_count_4 = 0x6128; 31547e911b15Skarels adder->x_scan_count_5 = 0x093A; 31557e911b15Skarels adder->x_scan_count_6 = 0x313C; 31567e911b15Skarels adder->sync_phase_adj = 0x0100; 31577e911b15Skarels adder->x_scan_conf = 0x00C8; 3158b2b69f49Smarc /* 3159b2b69f49Smarc * got a bug in secound pass ADDER! lets take care of it 3160b2b69f49Smarc * 3161b2b69f49Smarc * normally, just use the code in the following bug fix code, but to 31627e911b15Skarels * make repeated demos look pretty, load the registers as if there was 3163b2b69f49Smarc * no bug and then test to see if we are getting sync 3164b2b69f49Smarc */ 31657e911b15Skarels adder->y_scan_count_0 = 0x135F; 31667e911b15Skarels adder->y_scan_count_1 = 0x3363; 31677e911b15Skarels adder->y_scan_count_2 = 0x2366; 31687e911b15Skarels adder->y_scan_count_3 = 0x0388; 3169b2b69f49Smarc /* 3170b2b69f49Smarc * if no sync, do the bug fix code 3171b2b69f49Smarc */ 31727e911b15Skarels if (wait_status(adder, VSYNC) == BAD) { 31737e911b15Skarels /* first load all Y scan registers with very short frame and 31747e911b15Skarels * wait for scroll service. This guarantees at least one SYNC 31757e911b15Skarels * to fix the pass 2 Adder initialization bug (synchronizes 3176b2b69f49Smarc * XCINCH with DMSEEDH) 3177b2b69f49Smarc */ 31787e911b15Skarels adder->y_scan_count_0 = 0x01; 31797e911b15Skarels adder->y_scan_count_1 = 0x01; 31807e911b15Skarels adder->y_scan_count_2 = 0x01; 31817e911b15Skarels adder->y_scan_count_3 = 0x01; 3182b2b69f49Smarc /* 3183b2b69f49Smarc * delay at least 1 full frame time 3184b2b69f49Smarc */ 31857881ece5Smarc (void)wait_status(adder, VSYNC); 31867881ece5Smarc (void)wait_status(adder, VSYNC); 3187b2b69f49Smarc /* 3188b2b69f49Smarc * now load the REAL sync values (in reverse order just to 3189b2b69f49Smarc * be safe. 3190b2b69f49Smarc */ 31917e911b15Skarels adder->y_scan_count_3 = 0x0388; 31927e911b15Skarels adder->y_scan_count_2 = 0x2366; 31937e911b15Skarels adder->y_scan_count_1 = 0x3363; 31947e911b15Skarels adder->y_scan_count_0 = 0x135F; 31957e911b15Skarels } 31967e911b15Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 3197b2b69f49Smarc /* 3198b2b69f49Smarc * zero the index registers 3199b2b69f49Smarc */ 32007e911b15Skarels adder->x_index_pending = 0; 32017e911b15Skarels adder->y_index_pending = 0; 32027e911b15Skarels adder->x_index_new = 0; 32037e911b15Skarels adder->y_index_new = 0; 32047e911b15Skarels adder->x_index_old = 0; 32057e911b15Skarels adder->y_index_old = 0; 32067e911b15Skarels adder->pause = 0; 3207b2b69f49Smarc /* 3208b2b69f49Smarc * set rasterop mode to normal pen down 3209b2b69f49Smarc */ 32107e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 3211b2b69f49Smarc /* 3212b2b69f49Smarc * set the rasterop registers to a default values 3213b2b69f49Smarc */ 32147e911b15Skarels adder->source_1_dx = 1; 32157e911b15Skarels adder->source_1_dy = 1; 32167e911b15Skarels adder->source_1_x = 0; 32177e911b15Skarels adder->source_1_y = 0; 32187e911b15Skarels adder->destination_x = 0; 32197e911b15Skarels adder->destination_y = 0; 32207e911b15Skarels adder->fast_dest_dx = 1; 32217e911b15Skarels adder->fast_dest_dy = 0; 32227e911b15Skarels adder->slow_dest_dx = 0; 32237e911b15Skarels adder->slow_dest_dy = 1; 32247e911b15Skarels adder->error_1 = 0; 32257e911b15Skarels adder->error_2 = 0; 3226b2b69f49Smarc /* 32277881ece5Smarc * scale factor = UNITY 3228b2b69f49Smarc */ 32297e911b15Skarels adder->fast_scale = UNITY; 32307e911b15Skarels adder->slow_scale = UNITY; 3231b2b69f49Smarc /* 3232b2b69f49Smarc * set the source 2 parameters 3233b2b69f49Smarc */ 32347e911b15Skarels adder->source_2_x = 0; 32357e911b15Skarels adder->source_2_y = 0; 32367e911b15Skarels adder->source_2_size = 0x0022; 3237b2b69f49Smarc /* 3238b2b69f49Smarc * initialize plane addresses for eight vipers 3239b2b69f49Smarc */ 32407e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 32417e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 32427e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 32437e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 32447e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 32457e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 32467e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 32477e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 32487e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 32497e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 32507e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 32517e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 32527e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 32537e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 32547e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 32557e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 3256b2b69f49Smarc /* 3257b2b69f49Smarc * initialize the external registers. 3258b2b69f49Smarc */ 32597e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 32607e911b15Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 3261b2b69f49Smarc /* 3262b2b69f49Smarc * initialize resolution mode 3263b2b69f49Smarc */ 32647e911b15Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 32657e911b15Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 3266b2b69f49Smarc /* 3267b2b69f49Smarc * initialize viper registers 3268b2b69f49Smarc */ 32697e911b15Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 32707e911b15Skarels write_ID(adder, SCROLL_FILL, 0x0000); 3271b2b69f49Smarc /* 3272b2b69f49Smarc * set clipping and scrolling limits to full screen 3273b2b69f49Smarc */ 3274b2b69f49Smarc for (i = 1000, adder->status = 0; 32757881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 3276b2b69f49Smarc ; 32777e911b15Skarels if (i == 0) 32787881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 32797e911b15Skarels top = 0; 32807e911b15Skarels bottom = 2048; 32817e911b15Skarels left = 0; 32827e911b15Skarels right = 1024; 32837e911b15Skarels adder->x_clip_min = left; 32847e911b15Skarels adder->x_clip_max = right; 32857e911b15Skarels adder->y_clip_min = top; 32867e911b15Skarels adder->y_clip_max = bottom; 32877e911b15Skarels adder->scroll_x_min = left; 32887e911b15Skarels adder->scroll_x_max = right; 32897e911b15Skarels adder->scroll_y_min = top; 32907e911b15Skarels adder->scroll_y_max = bottom; 32917881ece5Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 32927881ece5Smarc (void)wait_status(adder, VSYNC); 32937e911b15Skarels adder->x_index_pending = left; 32947e911b15Skarels adder->y_index_pending = top; 32957e911b15Skarels adder->x_index_new = left; 32967e911b15Skarels adder->y_index_new = top; 32977e911b15Skarels adder->x_index_old = left; 32987e911b15Skarels adder->y_index_old = top; 32997e911b15Skarels 33007881ece5Smarc for (i = 1000, adder->status = 0; i > 0 && 33017881ece5Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 3302b2b69f49Smarc ; 33037e911b15Skarels if (i == 0) 33047881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 33057e911b15Skarels 33067e911b15Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 33077e911b15Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 3308b2b69f49Smarc /* 3309b2b69f49Smarc * set source and the mask register to all ones (ie: white) o 3310b2b69f49Smarc */ 33117e911b15Skarels write_ID(adder, SOURCE, 0xFFFF); 33127e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 33137e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 33147e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 3315b2b69f49Smarc /* 3316b2b69f49Smarc * initialize Operand Control Register banks for fill command 3317b2b69f49Smarc */ 33187e911b15Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 33197e911b15Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 33207e911b15Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 33217e911b15Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 33227e911b15Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 33237e911b15Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 3324b2b69f49Smarc /* 33257e911b15Skarels * init Logic Unit Function registers, (these are just common values, 3326b2b69f49Smarc * and may be changed as required). 3327b2b69f49Smarc */ 33287e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 3329b2b69f49Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 3330b2b69f49Smarc INV_M1_M2); 33317e911b15Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 33327e911b15Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 3333b2b69f49Smarc /* 3334b2b69f49Smarc * load the color map for black & white 3335b2b69f49Smarc */ 33367881ece5Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 3337b2b69f49Smarc ; 33387e911b15Skarels 33397e911b15Skarels if (i == 0) 33407881ece5Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 33417e911b15Skarels 33427e911b15Skarels red = (short *) qdmap[unit].red; 33437e911b15Skarels green = (short *) qdmap[unit].green; 33447e911b15Skarels blue = (short *) qdmap[unit].blue; 33457e911b15Skarels 33467e911b15Skarels *red++ = 0x00; /* black */ 33477e911b15Skarels *green++ = 0x00; 33487e911b15Skarels *blue++ = 0x00; 33497e911b15Skarels 33507e911b15Skarels *red-- = 0xFF; /* white */ 33517e911b15Skarels *green-- = 0xFF; 33527e911b15Skarels *blue-- = 0xFF; 33537e911b15Skarels 3354b2b69f49Smarc /* 33557881ece5Smarc * set color map for mouse cursor 33567881ece5Smarc */ 33577e911b15Skarels 33587e911b15Skarels red += 254; 33597e911b15Skarels green += 254; 33607e911b15Skarels blue += 254; 33617e911b15Skarels 33627e911b15Skarels *red++ = 0x00; /* black */ 33637e911b15Skarels *green++ = 0x00; 33647e911b15Skarels *blue++ = 0x00; 33657e911b15Skarels 33667e911b15Skarels *red = 0xFF; /* white */ 33677e911b15Skarels *green = 0xFF; 33687e911b15Skarels *blue = 0xFF; 33697e911b15Skarels 33707e911b15Skarels } /* setup_dragon */ 33717e911b15Skarels 33727881ece5Smarc /* 33737881ece5Smarc * Init the DUART and set defaults in input 33747881ece5Smarc */ 33757e911b15Skarels setup_input(unit) 33767881ece5Smarc int unit; 33777e911b15Skarels { 33787e911b15Skarels register struct duart *duart; /* DUART register structure pointer */ 33797881ece5Smarc register i, bits; 33807e911b15Skarels char id_byte; 33817e911b15Skarels 33827e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 33837e911b15Skarels duart->imask = 0; 33847e911b15Skarels 3385b2b69f49Smarc /* 3386b2b69f49Smarc * setup the DUART for kbd & pointing device 3387b2b69f49Smarc */ 33887e911b15Skarels duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 33897e911b15Skarels duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 33907e911b15Skarels /* no RTS control,char error mode */ 33917e911b15Skarels duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 33927e911b15Skarels /* no RTS control,no echo or loop */ 33937e911b15Skarels duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 33947e911b15Skarels duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 33957e911b15Skarels /* ..no RTS cntrl, char error mode */ 33967e911b15Skarels duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 33977e911b15Skarels /* no RTS control,no echo or loop */ 33987e911b15Skarels duart->auxctl = 0x00; /* baud rate set 1 */ 33997e911b15Skarels duart->clkselA = 0x99; /* 4800 baud for kbd */ 34007e911b15Skarels duart->clkselB = 0x99; /* 4800 baud for mouse */ 34017e911b15Skarels 34027e911b15Skarels /* reset everything for keyboard */ 34037e911b15Skarels 34047e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 34057e911b15Skarels duart->cmdA = bits; 34067e911b15Skarels 34077e911b15Skarels /* reset everything for host */ 34087e911b15Skarels 34097e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 34107e911b15Skarels duart->cmdB = bits; 34117e911b15Skarels 34127e911b15Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 34137e911b15Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 34147e911b15Skarels 3415b2b69f49Smarc /* 34167881ece5Smarc * init keyboard defaults (DUART channel A) 34177881ece5Smarc */ 34187e911b15Skarels for (i = 500; i > 0; --i) { 34197881ece5Smarc if (duart->statusA&XMT_RDY) { 34207e911b15Skarels duart->dataA = LK_DEFAULTS; 34217e911b15Skarels break; 34227e911b15Skarels } 34237e911b15Skarels } 34247e911b15Skarels 34257e911b15Skarels for (i = 100000; i > 0; --i) { 34267881ece5Smarc if (duart->statusA&RCV_RDY) { 34277e911b15Skarels break; 34287e911b15Skarels } 34297e911b15Skarels } 34307e911b15Skarels 34317881ece5Smarc if (duart->dataA) /* flush the ACK */ 34327881ece5Smarc ; 34337e911b15Skarels 3434b2b69f49Smarc /* 34357881ece5Smarc * identify the pointing device 34367881ece5Smarc */ 34377e911b15Skarels for (i = 500; i > 0; --i) { 34387881ece5Smarc if (duart->statusB&XMT_RDY) { 34397e911b15Skarels duart->dataB = SELF_TEST; 34407e911b15Skarels break; 34417e911b15Skarels } 34427e911b15Skarels } 34437e911b15Skarels 3444b2b69f49Smarc /* 34457e911b15Skarels * wait for 1st byte of self test report */ 34467e911b15Skarels 34477e911b15Skarels for (i = 100000; i > 0; --i) { 34487881ece5Smarc if (duart->statusB&RCV_RDY) { 34497e911b15Skarels break; 34507e911b15Skarels } 34517e911b15Skarels } 34527e911b15Skarels 34537e911b15Skarels if (i == 0) { 34547881ece5Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 3455b2b69f49Smarc ,unit); 34567e911b15Skarels goto OUT; 34577e911b15Skarels } 34587e911b15Skarels 34597881ece5Smarc if (duart->dataB) 34607881ece5Smarc ; 34617e911b15Skarels 3462b2b69f49Smarc /* 34637881ece5Smarc * wait for ID byte of self test report 34647881ece5Smarc */ 34657e911b15Skarels for (i = 100000; i > 0; --i) { 34667881ece5Smarc if (duart->statusB&RCV_RDY) { 34677e911b15Skarels break; 34687e911b15Skarels } 34697e911b15Skarels } 34707e911b15Skarels 34717e911b15Skarels if (i == 0) { 34727881ece5Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 34737e911b15Skarels goto OUT; 34747e911b15Skarels } 34757e911b15Skarels 34767e911b15Skarels id_byte = duart->dataB; 34777e911b15Skarels 3478b2b69f49Smarc /* 34797881ece5Smarc * wait for other bytes to come in 34807881ece5Smarc */ 34817e911b15Skarels for (i = 100000; i > 0; --i) { 34827881ece5Smarc if (duart->statusB & RCV_RDY) { 34837881ece5Smarc if (duart->dataB) 34847881ece5Smarc ; 34857e911b15Skarels break; 34867e911b15Skarels } 34877e911b15Skarels } 34887e911b15Skarels if (i == 0) { 34897881ece5Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 34907e911b15Skarels goto OUT; 34917e911b15Skarels } 34927e911b15Skarels for (i = 100000; i > 0; --i) { 34937881ece5Smarc if (duart->statusB&RCV_RDY) { 34947881ece5Smarc if (duart->dataB) 34957881ece5Smarc ; 34967e911b15Skarels break; 34977e911b15Skarels } 34987e911b15Skarels } 34997e911b15Skarels if (i == 0) { 35007881ece5Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 35017e911b15Skarels goto OUT; 35027e911b15Skarels } 3503b2b69f49Smarc /* 35047881ece5Smarc * flag pointing device type and set defaults 35057881ece5Smarc */ 35067881ece5Smarc for (i=100000; i>0; --i) 35077881ece5Smarc ; /*XXX*/ 35087e911b15Skarels 35097e911b15Skarels if ((id_byte & 0x0F) != TABLET_ID) { 35107e911b15Skarels qdflags[unit].pntr_id = MOUSE_ID; 35117e911b15Skarels 35127e911b15Skarels for (i = 500; i > 0; --i) { 35137881ece5Smarc if (duart->statusB&XMT_RDY) { 35147e911b15Skarels duart->dataB = INC_STREAM_MODE; 35157e911b15Skarels break; 35167e911b15Skarels } 35177e911b15Skarels } 3518b2b69f49Smarc } 3519b2b69f49Smarc else { 35207e911b15Skarels qdflags[unit].pntr_id = TABLET_ID; 35217e911b15Skarels 35227e911b15Skarels for (i = 500; i > 0; --i) { 35237881ece5Smarc if (duart->statusB&XMT_RDY) { 35247e911b15Skarels duart->dataB = T_STREAM; 35257e911b15Skarels break; 35267e911b15Skarels } 35277e911b15Skarels } 35287e911b15Skarels } 35297e911b15Skarels OUT: 35307e911b15Skarels duart->imask = qdflags[unit].duart_imask; 35317e911b15Skarels 35327e911b15Skarels } /* setup_input */ 35337e911b15Skarels 35347881ece5Smarc /* 35357881ece5Smarc * delay for at least one display frame time 35367e911b15Skarels * 35377e911b15Skarels * return: BAD means that we timed out without ever seeing the 35387e911b15Skarels * vertical sync status bit 35397e911b15Skarels * GOOD otherwise 35407881ece5Smarc */ 35417e911b15Skarels wait_status(adder, mask) 35427e911b15Skarels register struct adder *adder; 35437e911b15Skarels register int mask; 35447e911b15Skarels { 35457881ece5Smarc register i; 35467e911b15Skarels 3547b2b69f49Smarc for (i = 10000, adder->status = 0 ; i > 0 && 35487881ece5Smarc !(adder->status&mask) ; --i) 3549b2b69f49Smarc ; 35507e911b15Skarels 35517e911b15Skarels if (i == 0) { 35527881ece5Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 35537e911b15Skarels return(BAD); 35547e911b15Skarels } 35557e911b15Skarels 35567e911b15Skarels return(GOOD); 35577e911b15Skarels 35587e911b15Skarels } /* wait_status */ 35597e911b15Skarels 35607881ece5Smarc /* 35617881ece5Smarc * write out onto the ID bus 35627881ece5Smarc */ 35637e911b15Skarels write_ID(adder, adrs, data) 35647e911b15Skarels register struct adder *adder; 35657e911b15Skarels register short adrs; 35667e911b15Skarels register short data; 35677e911b15Skarels { 35687881ece5Smarc register i; 35697e911b15Skarels 3570b2b69f49Smarc for (i = 100000, adder->status = 0 ; 35717881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 3572b2b69f49Smarc ; 35737e911b15Skarels 35747e911b15Skarels if (i == 0) 35757e911b15Skarels goto ERR; 35767e911b15Skarels 3577b2b69f49Smarc for (i = 100000, adder->status = 0 ; 35787881ece5Smarc i > 0 && !(adder->status&TX_READY) ; --i) 3579b2b69f49Smarc ; 35807e911b15Skarels 35817e911b15Skarels if (i > 0) { 35827e911b15Skarels adder->id_data = data; 35837e911b15Skarels adder->command = ID_LOAD | adrs; 35847881ece5Smarc return ; 35857e911b15Skarels } 35867e911b15Skarels 35877e911b15Skarels ERR: 35887881ece5Smarc printf("write_ID: timeout trying to write to VIPER\n"); 35897881ece5Smarc return ; 35907e911b15Skarels 35917e911b15Skarels } /* write_ID */ 3592006e9885Smarc #endif 3593