1006e9885Smarc /* 2537afb73Sbostic * Copyright (c) 1988 Regents of the University of California. 3537afb73Sbostic * All rights reserved. 4006e9885Smarc * 5*9c395af7Sbostic * %sccs.include.redist.c% 6006e9885Smarc * 7*9c395af7Sbostic * @(#)qd.c 1.16 (Berkeley) 06/28/90 8006e9885Smarc */ 9b2b69f49Smarc 107e911b15Skarels /************************************************************************ 117e911b15Skarels * * 12e977faadSmarc * Copyright (c) 1985-1988 by * 137e911b15Skarels * Digital Equipment Corporation, Maynard, MA * 147e911b15Skarels * All rights reserved. * 157e911b15Skarels * * 167e911b15Skarels * This software is furnished under a license and may be used and * 177e911b15Skarels * copied only in accordance with the terms of such license and * 187e911b15Skarels * with the inclusion of the above copyright notice. This * 197e911b15Skarels * software or any other copies thereof may not be provided or * 207e911b15Skarels * otherwise made available to any other person. No title to and * 217e911b15Skarels * ownership of the software is hereby transferred. * 227e911b15Skarels * * 237e911b15Skarels * The information in this software is subject to change without * 247e911b15Skarels * notice and should not be construed as a commitment by Digital * 257e911b15Skarels * Equipment Corporation. * 267e911b15Skarels * * 277e911b15Skarels * Digital assumes no responsibility for the use or reliability * 287e911b15Skarels * of its software on equipment which is not supplied by Digital. * 297e911b15Skarels * * 307e911b15Skarels *************************************************************************/ 31e977faadSmarc 327e911b15Skarels /* 33b2b69f49Smarc * qd.c - QDSS display driver for VAXSTATION-II GPX workstation 347e911b15Skarels */ 357e911b15Skarels 36b2b69f49Smarc #include "qd.h" 37e977faadSmarc 38006e9885Smarc #if NQD > 0 39e977faadSmarc #include "types.h" 4019612d62Smckusick #include "machine/pte.h" 4119612d62Smckusick #include "machine/mtpr.h" 4219612d62Smckusick #include "machine/cpu.h" 43b2b69f49Smarc #include "param.h" 44b2b69f49Smarc #include "conf.h" 45b2b69f49Smarc #include "user.h" 46b2b69f49Smarc #include "qdioctl.h" 47006e9885Smarc #include "tty.h" 48b2b69f49Smarc #include "map.h" 49b2b69f49Smarc #include "buf.h" 50b2b69f49Smarc #include "vm.h" 51b2b69f49Smarc #include "clist.h" 52b2b69f49Smarc #include "file.h" 53b2b69f49Smarc #include "uio.h" 54b2b69f49Smarc #include "kernel.h" 55e977faadSmarc #include "exec.h" 56e977faadSmarc #include "proc.h" 57b2b69f49Smarc #include "ubareg.h" 58b2b69f49Smarc #include "ubavar.h" 59e977faadSmarc #include "syslog.h" 60b2b69f49Smarc #include "qduser.h" /* definitions shared with user level client */ 61e977faadSmarc #include "qdreg.h" /* QDSS device register structures */ 6224f67f6bSmarc 63b2b69f49Smarc /* 64b2b69f49Smarc * QDSS driver status flags for tracking operational state 65b2b69f49Smarc */ 6624f67f6bSmarc struct qdflags { 6724f67f6bSmarc u_int inuse; /* which minor dev's are in use now */ 6824f67f6bSmarc u_int config; /* I/O page register content */ 6924f67f6bSmarc u_int mapped; /* user mapping status word */ 70e977faadSmarc u_int kernel_loop; /* if kernel console is redirected */ 7124f67f6bSmarc u_int user_dma; /* DMA from user space in progress */ 7224f67f6bSmarc u_short pntr_id; /* type code of pointing device */ 7324f67f6bSmarc u_short duart_imask; /* shadowing for duart intrpt mask reg */ 7424f67f6bSmarc u_short adder_ie; /* shadowing for adder intrpt enbl reg */ 7524f67f6bSmarc u_short curs_acc; /* cursor acceleration factor */ 7624f67f6bSmarc u_short curs_thr; /* cursor acceleration threshold level */ 7724f67f6bSmarc u_short tab_res; /* tablet resolution factor */ 7824f67f6bSmarc u_short selmask; /* mask for active qd select entries */ 7924f67f6bSmarc }; 8024f67f6bSmarc 81b2b69f49Smarc /* 82b2b69f49Smarc * bit definitions for 'inuse' entry 83b2b69f49Smarc */ 8424f67f6bSmarc #define CONS_DEV 0x01 8524f67f6bSmarc #define GRAPHIC_DEV 0x04 8624f67f6bSmarc 87b2b69f49Smarc /* 88b2b69f49Smarc * bit definitions for 'mapped' member of flag structure 89b2b69f49Smarc */ 9024f67f6bSmarc #define MAPDEV 0x01 /* hardware is mapped */ 9124f67f6bSmarc #define MAPDMA 0x02 /* DMA buffer mapped */ 9224f67f6bSmarc #define MAPEQ 0x04 /* event queue buffer mapped */ 9324f67f6bSmarc #define MAPSCR 0x08 /* scroll param area mapped */ 9424f67f6bSmarc #define MAPCOLOR 0x10 /* color map writing buffer mapped */ 9524f67f6bSmarc 96b2b69f49Smarc /* 97b2b69f49Smarc * bit definitions for 'selmask' member of qdflag structure 98b2b69f49Smarc */ 9924f67f6bSmarc #define SEL_READ 0x01 /* read select is active */ 10024f67f6bSmarc #define SEL_WRITE 0x02 /* write select is active */ 10124f67f6bSmarc 102b2b69f49Smarc /* 103b2b69f49Smarc * constants used in shared memory operations 104b2b69f49Smarc */ 10524f67f6bSmarc #define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */ 10624f67f6bSmarc #define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ 10724f67f6bSmarc / sizeof(struct _vs_event) ) 1080d59d4d6Smarc #define DMA_BUFSIZ (1024 * 10) 10924f67f6bSmarc #define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF) 11024f67f6bSmarc 111b2b69f49Smarc /* 11224f67f6bSmarc * reference to an array of "uba_device" structures built by the auto 11324f67f6bSmarc * configuration program. The uba_device structure decribes the device 11424f67f6bSmarc * sufficiently for the driver to talk to it. The auto configuration code 11524f67f6bSmarc * fills in the uba_device structures (located in ioconf.c) from user 116b2b69f49Smarc * maintained info. 117b2b69f49Smarc */ 11824f67f6bSmarc struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */ 11924f67f6bSmarc struct tty qd_tty[NQD*4]; /* teletype structures for each.. */ 1207881ece5Smarc extern char qvmem[][128*NBPG]; 121b2b69f49Smarc extern struct pte QVmap[][128]; 122b2b69f49Smarc #define CHUNK (64 * 1024) 123b2b69f49Smarc #define QMEMSIZE (1024 * 1024 * 4) /* 4 meg */ 12424f67f6bSmarc 125b2b69f49Smarc /* 126b2b69f49Smarc * static storage used by multiple functions in this code 127b2b69f49Smarc */ 12824f67f6bSmarc int Qbus_unmap[NQD]; /* Qbus mapper release code */ 12924f67f6bSmarc struct qdflags qdflags[NQD]; /* QDSS device status flags */ 13024f67f6bSmarc struct qdmap qdmap[NQD]; /* QDSS register map structure */ 13124f67f6bSmarc caddr_t qdbase[NQD]; /* base address of each QDSS unit */ 13224f67f6bSmarc struct buf qdbuf[NQD]; /* buf structs used by strategy */ 133b2b69f49Smarc short qdopened[NQD]; /* graphics device is open exclusive use */ 13424f67f6bSmarc 135b2b69f49Smarc /* 136e977faadSmarc * the array "event_shared[]" is made up of a number of event queue buffers 13724f67f6bSmarc * equal to the number of QDSS's configured into the running kernel (NQD). 13824f67f6bSmarc * Each event queue buffer begins with an event queue header (struct qdinput) 13924f67f6bSmarc * followed by a group of event queue entries (struct _vs_event). The array 14024f67f6bSmarc * "*eq_header[]" is an array of pointers to the start of each event queue 141b2b69f49Smarc * buffer in "event_shared[]". 142b2b69f49Smarc */ 14324f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512) 14424f67f6bSmarc 14524f67f6bSmarc char event_shared[EQSIZE]; /* reserve space for event bufs */ 14624f67f6bSmarc struct qdinput *eq_header[NQD]; /* event queue header pntrs */ 14724f67f6bSmarc 148b2b69f49Smarc /* 14924f67f6bSmarc * This allocation method reserves enough memory pages for NQD shared DMA I/O 15024f67f6bSmarc * buffers. Each buffer must consume an integral number of memory pages to 15124f67f6bSmarc * guarantee that a following buffer will begin on a page boundary. Also, 15224f67f6bSmarc * enough space is allocated so that the FIRST I/O buffer can start at the 15324f67f6bSmarc * 1st page boundary after "&DMA_shared". Page boundaries are used so that 154b2b69f49Smarc * memory protections can be turned on/off for individual buffers. 155b2b69f49Smarc */ 15624f67f6bSmarc #define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512) 15724f67f6bSmarc 15824f67f6bSmarc char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */ 15924f67f6bSmarc struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs */ 16024f67f6bSmarc 161b2b69f49Smarc /* 16224f67f6bSmarc * The driver assists a client in scroll operations by loading dragon 16324f67f6bSmarc * registers from an interrupt service routine. The loading is done using 16424f67f6bSmarc * parameters found in memory shrade between the driver and it's client. 16524f67f6bSmarc * The scroll parameter structures are ALL loacted in the same memory page 166b2b69f49Smarc * for reasons of memory economy. 167b2b69f49Smarc */ 16824f67f6bSmarc char scroll_shared[2 * 512]; /* reserve space for scroll structs */ 16924f67f6bSmarc struct scroll *scroll[NQD]; /* pointers to scroll structures */ 17024f67f6bSmarc 171b2b69f49Smarc /* 17224f67f6bSmarc * the driver is programmable to provide the user with color map write 17324f67f6bSmarc * services at VSYNC interrupt time. At interrupt time the driver loads 174b2b69f49Smarc * the color map with any user-requested load data found in shared memory 175b2b69f49Smarc */ 17624f67f6bSmarc #define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512) 17724f67f6bSmarc 178e977faadSmarc char color_shared[COLOR_SHARED]; /* reserve space: color bufs */ 17924f67f6bSmarc struct color_buf *color_buf[NQD]; /* pointers to color bufs */ 18024f67f6bSmarc 181b2b69f49Smarc /* 182b2b69f49Smarc * mouse input event structures 183b2b69f49Smarc */ 18424f67f6bSmarc struct mouse_report last_rep[NQD]; 18524f67f6bSmarc struct mouse_report current_rep[NQD]; 18624f67f6bSmarc 1877881ece5Smarc struct proc *qdrsel[NQD]; /* process waiting for select */ 188b2b69f49Smarc struct _vs_cursor cursor[NQD]; /* console cursor */ 189b2b69f49Smarc int qdcount = 0; /* count of successfully probed qd's */ 19024f67f6bSmarc int nNQD = NQD; 19124f67f6bSmarc int DMAbuf_size = DMA_BUFSIZ; 192e977faadSmarc int QDlast_DMAtype; /* type of the last DMA operation */ 193e977faadSmarc 194b2b69f49Smarc #define QDSSMAJOR 41 /* QDSS major device number */ 195b2b69f49Smarc /* 196b2b69f49Smarc * macro to get system time. Used to time stamp event queue entries 197b2b69f49Smarc */ 1987e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000)) 1997e911b15Skarels 2007e911b15Skarels int qdprobe(); 2017e911b15Skarels int qdattach(); 2027e911b15Skarels int qddint(); /* DMA gate array intrpt service */ 2037e911b15Skarels int qdaint(); /* Dragon ADDER intrpt service */ 2047e911b15Skarels int qdiint(); 2057e911b15Skarels 2067e911b15Skarels u_short qdstd[] = { 0 }; 2077e911b15Skarels 208b2b69f49Smarc struct uba_driver qddriver = { 2097e911b15Skarels qdprobe, /* device probe entry */ 2107e911b15Skarels 0, /* no slave device */ 2117e911b15Skarels qdattach, /* device attach entry */ 2127e911b15Skarels 0, /* no "fill csr/ba to start" */ 2137e911b15Skarels qdstd, /* device addresses */ 2147e911b15Skarels "qd", /* device name string */ 2157e911b15Skarels qdinfo /* ptr to QDSS's uba_device struct */ 2167e911b15Skarels }; 2177e911b15Skarels 218e977faadSmarc #define QDPRIOR (PZERO-1) /* must be negative */ 2197e911b15Skarels #define FALSE 0 2207e911b15Skarels #define TRUE ~FALSE 2217e911b15Skarels #define BAD -1 2227e911b15Skarels #define GOOD 0 2237e911b15Skarels 224b2b69f49Smarc /* 225b2b69f49Smarc * macro to create a system virtual page number from system virtual adrs 226b2b69f49Smarc */ 227b2b69f49Smarc #define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT) 2287e911b15Skarels 229b2b69f49Smarc /* 230b2b69f49Smarc * QDSS register address offsets from start of QDSS address space 231b2b69f49Smarc */ 2327e911b15Skarels #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ 2337e911b15Skarels #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ 2347e911b15Skarels #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ 2357e911b15Skarels #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ 2367e911b15Skarels #define REGSTART 0xC000 /* offset of reg pages from base adrs */ 2377e911b15Skarels #define ADDER (REGSTART+0x000) 2387e911b15Skarels #define DGA (REGSTART+0x200) 2397e911b15Skarels #define DUART (REGSTART+0x400) 2407e911b15Skarels #define MEMCSR (REGSTART+0x800) 2417e911b15Skarels #define CLRSIZE (3 * 512) /* color map size */ 2427e911b15Skarels #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ 2437e911b15Skarels /* 0x0C00 really */ 2447e911b15Skarels #define RED (CLRSTART+0x000) 2457e911b15Skarels #define BLUE (CLRSTART+0x200) 2467e911b15Skarels #define GREEN (CLRSTART+0x400) 2477e911b15Skarels 2487e911b15Skarels 249b2b69f49Smarc /* 2507e911b15Skarels * QDSS minor device numbers. The *real* minor device numbers are in 2517e911b15Skarels * the bottom two bits of the major/minor device spec. Bits 2 and up are 252b2b69f49Smarc * used to specify the QDSS device number (ie: which one?) 253b2b69f49Smarc */ 2547e911b15Skarels 2557e911b15Skarels #define CONS 0 2567e911b15Skarels #define GRAPHIC 2 2577e911b15Skarels 258b2b69f49Smarc /* 259b2b69f49Smarc * console cursor bitmap (white block cursor) 260b2b69f49Smarc */ 261b2b69f49Smarc short cons_cursor[32] = { 2627e911b15Skarels /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2637e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2647e911b15Skarels /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 2657e911b15Skarels 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 2667e911b15Skarels }; 2677e911b15Skarels 268b2b69f49Smarc /* 269b2b69f49Smarc * constants used in font operations 270b2b69f49Smarc */ 271e977faadSmarc #define CHARS 190 /* # of chars in the font */ 2727e911b15Skarels #define CHAR_HEIGHT 15 /* char height in pixels */ 2737e911b15Skarels #define CHAR_WIDTH 8 /* char width in pixels*/ 2747e911b15Skarels #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ 2757e911b15Skarels #define ROWS CHAR_HEIGHT 2767e911b15Skarels #define FONT_X 0 /* font's off screen adrs */ 2777e911b15Skarels #define FONT_Y (2048 - CHAR_HEIGHT) 278e977faadSmarc 279b2b69f49Smarc /* Offset to second row characters (XXX - should remove) */ 280e977faadSmarc #define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT) 2817e911b15Skarels 2827e911b15Skarels extern char q_font[]; /* reference font object code */ 283e977faadSmarc extern u_short q_key[]; /* reference key xlation tables */ 284e977faadSmarc extern u_short q_shift_key[]; 2857e911b15Skarels extern char *q_special[]; 2867e911b15Skarels 287b2b69f49Smarc /* 288b2b69f49Smarc * definitions for cursor acceleration reporting 289b2b69f49Smarc */ 2907e911b15Skarels #define ACC_OFF 0x01 /* acceleration is inactive */ 2917e911b15Skarels 292b2b69f49Smarc /* 293b2b69f49Smarc * virtual console support. 2947e911b15Skarels */ 295e977faadSmarc extern (*v_putc)(); 296f79d7b48Smarc #ifdef KADB 297f79d7b48Smarc extern (*v_getc)(); 298f79d7b48Smarc extern (*v_poll)(); 299f79d7b48Smarc #endif 300e977faadSmarc extern struct cdevsw *consops; 301e977faadSmarc int qdputc(); 302f79d7b48Smarc int qdgetc(); 303f79d7b48Smarc int qdpoll(); 304e977faadSmarc int qdstart(); 305f79d7b48Smarc int qdpolling = 0; 306e977faadSmarc 307b2b69f49Smarc /* 308b2b69f49Smarc * LK-201 state storage for input console keyboard conversion to ASCII 309b2b69f49Smarc */ 3107e911b15Skarels struct q_keyboard { 3117e911b15Skarels int shift; /* state variables */ 3127e911b15Skarels int cntrl; 3137e911b15Skarels int lock; 3147e911b15Skarels int lastcode; /* last keycode typed */ 3157e911b15Skarels unsigned kup[8]; /* bits for each keycode*/ 3167e911b15Skarels unsigned dkeys[8]; /* down/up mode keys */ 3177e911b15Skarels char last; /* last character */ 3187e911b15Skarels } q_keyboard; 3197e911b15Skarels 320b2b69f49Smarc /* 321b2b69f49Smarc * tty settings on first open 322b2b69f49Smarc */ 323f79d7b48Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL) 324e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR) 325f79d7b48Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN) 326e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL) 327e977faadSmarc 3287881ece5Smarc /* 3297881ece5Smarc * Init QDSS as console (before probe routine) 3307881ece5Smarc */ 3317e911b15Skarels 3327e911b15Skarels qdcons_init() 3337e911b15Skarels { 3347881ece5Smarc register unit; 3357e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 336e977faadSmarc u_int mapix; /* index into QVmap[] array */ 337e977faadSmarc struct percpu *pcpu; /* pointer to cpusw structure */ 338e977faadSmarc register struct qbus *qb; 3397e911b15Skarels u_short *qdaddr; /* address of QDSS IO page CSR */ 3407e911b15Skarels u_short *devptr; /* vitual device space */ 341e977faadSmarc extern cnputc(); 3427e911b15Skarels 3437e911b15Skarels #define QDSSCSR 0x1F00 3447e911b15Skarels 34524f67f6bSmarc if (v_putc != cnputc) 3467881ece5Smarc return 0; 34724f67f6bSmarc 3487e911b15Skarels unit = 0; 3497e911b15Skarels 350b2b69f49Smarc /* 351b2b69f49Smarc * find the cpusw entry that matches this machine. 352b2b69f49Smarc */ 35324f67f6bSmarc for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) 3547e911b15Skarels ; 35524f67f6bSmarc if (pcpu == NULL) 3567881ece5Smarc return 0; 3572b86b1e4Stef if (pcpu->pc_io->io_type != IO_QBUS) 3582b86b1e4Stef return 0; 35924f67f6bSmarc 36024f67f6bSmarc /* 361e977faadSmarc * Map device registers - the last 8K of qvmem. 36224f67f6bSmarc */ 36324f67f6bSmarc qb = (struct qbus *)pcpu->pc_io->io_details; 36424f67f6bSmarc ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, 36524f67f6bSmarc UBAIOPAGES * NBPG); 36624f67f6bSmarc devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); 36724f67f6bSmarc qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); 3687881ece5Smarc if (badaddr((caddr_t)qdaddr, sizeof(short))) 3697881ece5Smarc return 0; 370e977faadSmarc 37124f67f6bSmarc /* 37224f67f6bSmarc * Map q-bus memory used by qdss. (separate map) 37324f67f6bSmarc */ 37424f67f6bSmarc mapix = QMEMSIZE - (CHUNK * (unit + 1)); 37524f67f6bSmarc phys_adr = qb->qb_maddr + mapix; 37624f67f6bSmarc ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); 3777e911b15Skarels 37824f67f6bSmarc /* 37924f67f6bSmarc * tell QDSS which Q memory address base to decode 380b2b69f49Smarc * (shifted right 16 bits - its in 64K units) 38124f67f6bSmarc */ 38224f67f6bSmarc *qdaddr = (u_short)((int)mapix >> 16); 3837e911b15Skarels qdflags[unit].config = *(u_short *)qdaddr; 3847e911b15Skarels 385b2b69f49Smarc /* 386b2b69f49Smarc * load qdmap struct with the virtual addresses of the QDSS elements 387b2b69f49Smarc */ 388e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0]); 3897e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 3907e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 3917e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA; 3927e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART; 3937e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 3947e911b15Skarels qdmap[unit].red = qdbase[unit] + RED; 3957e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 3967e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN; 3977e911b15Skarels 3987e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 3997e911b15Skarels 400b2b69f49Smarc /* 401b2b69f49Smarc * init the QDSS 402b2b69f49Smarc */ 403b2b69f49Smarc /* 40424f67f6bSmarc printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", 40524f67f6bSmarc (char *)qdbase[0], qdmap[0].memcsr); 406b2b69f49Smarc */ 4077e911b15Skarels 4087e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ 4097e911b15Skarels 4107e911b15Skarels cursor[unit].x = 0; 4117e911b15Skarels cursor[unit].y = 0; 4127e911b15Skarels init_shared(unit); /* init shared memory */ 4137e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 4147e911b15Skarels clear_qd_screen(unit); /* clear the screen */ 4157e911b15Skarels ldfont(unit); /* load the console font */ 4167e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 4177e911b15Skarels setup_input(unit); /* init the DUART */ 418b2b69f49Smarc v_putc = qdputc; /* kernel console output to qdss */ 419f79d7b48Smarc #ifdef KADB 420f79d7b48Smarc v_getc = qdgetc; /* kernel console input from qdss */ 421f79d7b48Smarc v_poll = qdpoll; /* kdb hook to disable char intr */ 422f79d7b48Smarc #endif 423b2b69f49Smarc consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ 4247881ece5Smarc return 1; 4257e911b15Skarels 4267e911b15Skarels } /* qdcons_init */ 4277e911b15Skarels 4287881ece5Smarc /* 4297881ece5Smarc * Configure QDSS into Q memory and make it intrpt. 4307e911b15Skarels * 4317e911b15Skarels * side effects: QDSS gets mapped into Qbus memory space at the first 4327e911b15Skarels * vacant 64kb boundary counting back from the top of 433e977faadSmarc * Qbus memory space (qvmem+4mb) 4347e911b15Skarels * 4357e911b15Skarels * return: QDSS bus request level and vector address returned in 4367e911b15Skarels * registers by UNIX convention. 4377e911b15Skarels * 4387881ece5Smarc */ 4397e911b15Skarels qdprobe(reg) 4407881ece5Smarc caddr_t reg; /* character pointer to the QDSS I/O page register */ 4417e911b15Skarels { 442f79d7b48Smarc register int br, cvec; 4437e911b15Skarels register int unit; 4447e911b15Skarels struct dga *dga; /* pointer to gate array structure */ 4457e911b15Skarels int vector; 4467881ece5Smarc #ifdef notdef 4477881ece5Smarc int *ptep; /* page table entry pointer */ 4487e911b15Skarels caddr_t phys_adr; /* physical QDSS base adrs */ 4497e911b15Skarels u_int mapix; 4507881ece5Smarc #endif 4517881ece5Smarc 4527881ece5Smarc #ifdef lint 4537881ece5Smarc br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; 4547881ece5Smarc qddint(0); qdaint(0); qdiint(0); (void)qdgetc(); 4557881ece5Smarc #endif 4567e911b15Skarels 457b2b69f49Smarc /* 458b2b69f49Smarc * calculate board unit number from I/O page register address 459b2b69f49Smarc */ 4607e911b15Skarels unit = (int) (((int)reg >> 1) & 0x0007); 4617e911b15Skarels 462b2b69f49Smarc /* 463b2b69f49Smarc * QDSS regs must be mapped to Qbus memory space at a 64kb 464b2b69f49Smarc * physical boundary. The Qbus memory space is mapped into 465b2b69f49Smarc * the system memory space at config time. After config 466b2b69f49Smarc * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs 467b2b69f49Smarc * of the start of Qbus memory. The Qbus memory page table 468b2b69f49Smarc * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) 469b2b69f49Smarc * which is also loaded at config time. These are the 470b2b69f49Smarc * variables used below to find a vacant 64kb boundary in 471b2b69f49Smarc * Qbus memory, and load it's corresponding physical adrs 472b2b69f49Smarc * into the QDSS's I/O page CSR. 473b2b69f49Smarc */ 474e977faadSmarc 475e977faadSmarc /* 476e977faadSmarc * Only if QD is the graphics device. 47724f67f6bSmarc */ 4787e911b15Skarels 4797e911b15Skarels /* if this QDSS is NOT the console, then do init here.. */ 4807e911b15Skarels 481e977faadSmarc if (unit != 0) { 482e977faadSmarc printf("qd: can't support two qdss's (yet)\n"); 4837881ece5Smarc #ifdef notdef /* can't test */ 4847e911b15Skarels if (v_consputc != qdputc || unit != 0) { 4857e911b15Skarels 486b2b69f49Smarc /* 487b2b69f49Smarc * read QDSS config info 488b2b69f49Smarc */ 4897e911b15Skarels qdflags[unit].config = *(u_short *)reg; 4907e911b15Skarels 491b2b69f49Smarc /* 492b2b69f49Smarc * find an empty 64kb adrs boundary 493b2b69f49Smarc */ 4947e911b15Skarels 495e977faadSmarc qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK); 496e977faadSmarc 497b2b69f49Smarc /* 4987881ece5Smarc * find the cpusw entry that matches this machine. 4997881ece5Smarc */ 5007e911b15Skarels cpup = &cpusw[cpu]; 5017e911b15Skarels while (!(BADADDR(qdbase[unit], sizeof(short)))) 5027e911b15Skarels qdbase[unit] -= CHUNK; 5037e911b15Skarels 504b2b69f49Smarc /* 5057881ece5Smarc * tell QDSS which Q memory address base to decode 5067881ece5Smarc */ 507e977faadSmarc mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0])); 508e977faadSmarc ptep = (int *) QVmap[0] + mapix; 5097e911b15Skarels phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT); 5107e911b15Skarels *(u_short *)reg = (u_short) ((int)phys_adr >> 16); 5117e911b15Skarels 512b2b69f49Smarc /* 513b2b69f49Smarc * load QDSS adrs map with system addresses 514b2b69f49Smarc * of device regs 515b2b69f49Smarc */ 5167e911b15Skarels qdmap[unit].template = qdbase[unit] + TMPSTART; 5177e911b15Skarels qdmap[unit].adder = qdbase[unit] + ADDER; 5187e911b15Skarels qdmap[unit].dga = qdbase[unit] + DGA; 5197e911b15Skarels qdmap[unit].duart = qdbase[unit] + DUART; 5207e911b15Skarels qdmap[unit].memcsr = qdbase[unit] + MEMCSR; 5217e911b15Skarels qdmap[unit].red = qdbase[unit] + RED; 5227e911b15Skarels qdmap[unit].blue = qdbase[unit] + BLUE; 5237e911b15Skarels qdmap[unit].green = qdbase[unit] + GREEN; 5247e911b15Skarels 5257e911b15Skarels /* device init */ 5267e911b15Skarels 5277e911b15Skarels cursor[unit].x = 0; 5287e911b15Skarels cursor[unit].y = 0; 5297e911b15Skarels init_shared(unit); /* init shared memory */ 5307e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 5317e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 5327e911b15Skarels setup_input(unit); /* init the DUART */ 5337e911b15Skarels clear_qd_screen(unit); 5347e911b15Skarels ldfont(unit); /* load the console font */ 5357e911b15Skarels 5367e911b15Skarels /* once only: turn on sync */ 5377e911b15Skarels 5387e911b15Skarels *(short *)qdmap[unit].memcsr |= SYNC_ON; 539b2b69f49Smarc } 540006e9885Smarc #endif /*notdef*/ 541e977faadSmarc } 5427e911b15Skarels 543b2b69f49Smarc /* 544b2b69f49Smarc * The QDSS interrupts at HEX vectors xx0 (DMA) xx4 545b2b69f49Smarc * (ADDER) and xx8 (DUART). Therefore, we take three 546b2b69f49Smarc * vectors from the vector pool, and then continue 547b2b69f49Smarc * to take them until we get a xx0 HEX vector. The 548b2b69f49Smarc * pool provides vectors in contiguous decending 549b2b69f49Smarc * order. 550b2b69f49Smarc */ 5517e911b15Skarels 5527e911b15Skarels vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */ 5537e911b15Skarels 5547e911b15Skarels while (vector & 0x0F) { /* if lo nibble != 0.. */ 555b2b69f49Smarc /* ..take another vector */ 556b2b69f49Smarc vector = (uba_hd[0].uh_lastiv -= 4); 5577e911b15Skarels } 5587e911b15Skarels 559b2b69f49Smarc /* 560b2b69f49Smarc * setup DGA to do a DMA interrupt (transfer count = 0) 561b2b69f49Smarc */ 5627e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 5637e911b15Skarels dga->csr = (short) HALT; /* disable everything */ 5647e911b15Skarels dga->ivr = (short) vector; /* load intrpt base vector */ 5657e911b15Skarels dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */ 5667e911b15Skarels dga->bytcnt_hi = (short) 0; 5677e911b15Skarels 568b2b69f49Smarc /* 569b2b69f49Smarc * turn on DMA interrupts 570b2b69f49Smarc */ 5717e911b15Skarels dga->csr &= ~SET_DONE_FIFO; 5727e911b15Skarels dga->csr |= DMA_IE | DL_ENB; 5737e911b15Skarels 5747e911b15Skarels DELAY(20000); /* wait for the intrpt */ 5757e911b15Skarels dga->csr = HALT; /* stop the wheels */ 5767e911b15Skarels 5777e911b15Skarels if (cvec != vector) /* if vector != base vector.. */ 5787e911b15Skarels return(0); /* ..return = 'no device' */ 5797e911b15Skarels 580e977faadSmarc /* 581e977faadSmarc * score this as an existing qdss 582e977faadSmarc */ 583e977faadSmarc qdcount++; 584e977faadSmarc 5857e911b15Skarels return(sizeof(short)); /* return size of QDSS I/O page reg */ 5867e911b15Skarels 5877e911b15Skarels } /* qdprobe */ 5887e911b15Skarels 5897e911b15Skarels qdattach(ui) 5907e911b15Skarels struct uba_device *ui; 5917e911b15Skarels { 5927881ece5Smarc register unit; /* QDSS module # for this call */ 5937e911b15Skarels 5947e911b15Skarels unit = ui->ui_unit; /* get QDSS number */ 5957e911b15Skarels 596b2b69f49Smarc /* 597b2b69f49Smarc * init "qdflags[]" for this QDSS 598b2b69f49Smarc */ 5997e911b15Skarels qdflags[unit].inuse = 0; /* init inuse variable EARLY! */ 6007e911b15Skarels qdflags[unit].mapped = 0; 601e977faadSmarc qdflags[unit].kernel_loop = -1; 6027e911b15Skarels qdflags[unit].user_dma = 0; 6037e911b15Skarels qdflags[unit].curs_acc = ACC_OFF; 6047e911b15Skarels qdflags[unit].curs_thr = 128; 6057e911b15Skarels qdflags[unit].tab_res = 2; /* default tablet resolution factor */ 6067e911b15Skarels qdflags[unit].duart_imask = 0; /* init shadow variables */ 6077e911b15Skarels qdflags[unit].adder_ie = 0; 6087e911b15Skarels 609b2b69f49Smarc /* 6107e911b15Skarels * init structures used in kbd/mouse interrupt service. This code must 611b2b69f49Smarc * come after the "init_shared()" routine has run since that routine 612b2b69f49Smarc * inits the eq_header[unit] structure used here. 613b2b69f49Smarc */ 6147e911b15Skarels 615b2b69f49Smarc /* 616b2b69f49Smarc * init the "latest mouse report" structure 617b2b69f49Smarc */ 6187e911b15Skarels last_rep[unit].state = 0; 6197e911b15Skarels last_rep[unit].dx = 0; 6207e911b15Skarels last_rep[unit].dy = 0; 6217e911b15Skarels last_rep[unit].bytcnt = 0; 6227e911b15Skarels 623b2b69f49Smarc /* 6247881ece5Smarc * init the event queue (except mouse position) 6257881ece5Smarc */ 6267881ece5Smarc eq_header[unit]->header.events = 6277881ece5Smarc (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput)); 6287e911b15Skarels 6297e911b15Skarels eq_header[unit]->header.size = MAXEVENTS; 6307e911b15Skarels eq_header[unit]->header.head = 0; 6317e911b15Skarels eq_header[unit]->header.tail = 0; 6327e911b15Skarels 633b2b69f49Smarc /* 634b2b69f49Smarc * open exclusive for graphics device. 635b2b69f49Smarc */ 636b2b69f49Smarc qdopened[unit] = 0; 6377e911b15Skarels 6387e911b15Skarels } /* qdattach */ 6397e911b15Skarels 6407881ece5Smarc /*ARGSUSED*/ 6417e911b15Skarels qdopen(dev, flag) 6427e911b15Skarels dev_t dev; 6437e911b15Skarels int flag; 6447e911b15Skarels { 6457e911b15Skarels register struct uba_device *ui; /* ptr to uba structures */ 6467e911b15Skarels register struct dga *dga; /* ptr to gate array struct */ 6477e911b15Skarels register struct tty *tp; 6487e911b15Skarels struct duart *duart; 6497881ece5Smarc int unit; 6507881ece5Smarc int minor_dev; 6517e911b15Skarels 6527e911b15Skarels minor_dev = minor(dev); /* get QDSS minor device number */ 6537e911b15Skarels unit = minor_dev >> 2; 6547e911b15Skarels 655b2b69f49Smarc /* 656b2b69f49Smarc * check for illegal conditions 657b2b69f49Smarc */ 6587e911b15Skarels ui = qdinfo[unit]; /* get ptr to QDSS device struct */ 6597e911b15Skarels if (ui == 0 || ui->ui_alive == 0) 6607e911b15Skarels return(ENXIO); /* no such device or address */ 6617e911b15Skarels 6627e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 6637e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 6647e911b15Skarels 6657e911b15Skarels if ((minor_dev & 0x03) == 2) { 666b2b69f49Smarc /* 667b2b69f49Smarc * this is the graphic device... 668b2b69f49Smarc */ 669b2b69f49Smarc if (qdopened[unit] != 0) 6707e911b15Skarels return(EBUSY); 6717e911b15Skarels else 672b2b69f49Smarc qdopened[unit] = 1; 6737e911b15Skarels qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */ 674b2b69f49Smarc /* 675b2b69f49Smarc * enble kbd & mouse intrpts in DUART mask reg 676b2b69f49Smarc */ 6777e911b15Skarels qdflags[unit].duart_imask |= 0x22; 6787e911b15Skarels duart->imask = qdflags[unit].duart_imask; 679b2b69f49Smarc } else { 680b2b69f49Smarc /* 681b2b69f49Smarc * this is the console 682b2b69f49Smarc */ 6837e911b15Skarels qdflags[unit].inuse |= CONS_DEV; /* mark console as open */ 6847e911b15Skarels dga->csr |= CURS_ENB; 6857e911b15Skarels qdflags[unit].duart_imask |= 0x02; 6867e911b15Skarels duart->imask = qdflags[unit].duart_imask; 687b2b69f49Smarc /* 688b2b69f49Smarc * some setup for tty handling 689b2b69f49Smarc */ 6907e911b15Skarels tp = &qd_tty[minor_dev]; 6917e911b15Skarels tp->t_addr = ui->ui_addr; 6927e911b15Skarels tp->t_oproc = qdstart; 6937e911b15Skarels if ((tp->t_state & TS_ISOPEN) == 0) { 6947e911b15Skarels ttychars(tp); 6957e911b15Skarels tp->t_ispeed = B9600; 6967e911b15Skarels tp->t_ospeed = B9600; 697e977faadSmarc tp->t_state = TS_ISOPEN | TS_CARR_ON; 698b2b69f49Smarc tp->t_iflag = TTYDEF_IFLAG; 699b2b69f49Smarc tp->t_oflag = TTYDEF_OFLAG; 700b2b69f49Smarc tp->t_lflag = TTYDEF_LFLAG; 701b2b69f49Smarc tp->t_cflag = TTYDEF_CFLAG; 702e977faadSmarc } 703b2b69f49Smarc /* 704b2b69f49Smarc * enable intrpts, open line discipline 705b2b69f49Smarc */ 7067e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 7077e911b15Skarels return ((*linesw[tp->t_line].l_open)(dev, tp)); 7087e911b15Skarels } 7097e911b15Skarels dga->csr |= GLOBAL_IE; /* turn on the interrupts */ 7107e911b15Skarels return(0); 7117e911b15Skarels 7127e911b15Skarels } /* qdopen */ 7137e911b15Skarels 7147881ece5Smarc /*ARGSUSED*/ 7157e911b15Skarels qdclose(dev, flag) 7167e911b15Skarels dev_t dev; 7177e911b15Skarels int flag; 7187e911b15Skarels { 7197e911b15Skarels register struct tty *tp; 7207e911b15Skarels register struct qdmap *qd; 7217e911b15Skarels register int *ptep; 7227e911b15Skarels struct dga *dga; /* gate array register map pointer */ 7237e911b15Skarels struct duart *duart; 7247e911b15Skarels struct adder *adder; 7257881ece5Smarc int unit; 7267881ece5Smarc int minor_dev; 7277e911b15Skarels u_int mapix; 728b2b69f49Smarc int i; /* SIGNED index */ 7297e911b15Skarels 7307e911b15Skarels minor_dev = minor(dev); /* get minor device number */ 7317e911b15Skarels unit = minor_dev >> 2; /* get QDSS number */ 7327e911b15Skarels qd = &qdmap[unit]; 7337e911b15Skarels 7347e911b15Skarels if ((minor_dev & 0x03) == 2) { 735b2b69f49Smarc /* 736b2b69f49Smarc * this is the graphic device... 737b2b69f49Smarc */ 738b2b69f49Smarc if (qdopened[unit] != 1) 7397e911b15Skarels return(EBUSY); 7407e911b15Skarels else 741b2b69f49Smarc qdopened[unit] = 0; /* allow it to be re-opened */ 742b2b69f49Smarc /* 743b2b69f49Smarc * re-protect device memory 744b2b69f49Smarc */ 7457e911b15Skarels if (qdflags[unit].mapped & MAPDEV) { 746b2b69f49Smarc /* 747b2b69f49Smarc * TEMPLATE RAM 748b2b69f49Smarc */ 74924f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 75024f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7517881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 7527881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 753b2b69f49Smarc /* 754b2b69f49Smarc * ADDER 755b2b69f49Smarc */ 75624f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 75724f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7587881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 7597881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 760b2b69f49Smarc /* 761b2b69f49Smarc * COLOR MAPS 762b2b69f49Smarc */ 76324f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 76424f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 7657881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 7667881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 7677e911b15Skarels } 7687e911b15Skarels 769b2b69f49Smarc /* 770b2b69f49Smarc * re-protect DMA buffer and free the map registers 771b2b69f49Smarc */ 7727e911b15Skarels if (qdflags[unit].mapped & MAPDMA) { 7737e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 7747e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 7757e911b15Skarels dga->csr &= ~DMA_IE; 7767e911b15Skarels dga->csr &= ~0x0600; /* kill DMA */ 7777e911b15Skarels adder->command = CANCEL; 778b2b69f49Smarc /* 779b2b69f49Smarc * if DMA was running, flush spurious intrpt 780b2b69f49Smarc */ 7817e911b15Skarels if (dga->bytcnt_lo != 0) { 7827e911b15Skarels dga->bytcnt_lo = 0; 7837e911b15Skarels dga->bytcnt_hi = 0; 7847e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 7857e911b15Skarels dga->csr |= DMA_IE; 7867e911b15Skarels dga->csr &= ~DMA_IE; 7877e911b15Skarels } 7887e911b15Skarels ptep = (int *) 7897e911b15Skarels ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000)); 7907881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 7917881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW; 7927e911b15Skarels ubarelse(0, &Qbus_unmap[unit]); 7937e911b15Skarels } 7947e911b15Skarels 795b2b69f49Smarc /* 796b2b69f49Smarc * re-protect 1K (2 pages) event queue 797b2b69f49Smarc */ 7987e911b15Skarels if (qdflags[unit].mapped & MAPEQ) { 7997e911b15Skarels ptep = (int *) 8007e911b15Skarels ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000)); 8017881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 8027e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8037e911b15Skarels } 804b2b69f49Smarc /* 805b2b69f49Smarc * re-protect scroll param area and disable scroll intrpts 806b2b69f49Smarc */ 8077e911b15Skarels if (qdflags[unit].mapped & MAPSCR) { 8087e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 8097e911b15Skarels + (mfpr(SBR) | 0x80000000)); 810b2b69f49Smarc /* 811b2b69f49Smarc * re-protect 512 scroll param area 812b2b69f49Smarc */ 8137e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8147e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8157e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC; 8167e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 8177e911b15Skarels } 818b2b69f49Smarc /* 819b2b69f49Smarc * re-protect color map write buffer area and kill intrpts 820b2b69f49Smarc */ 8217e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) { 8227e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 8237e911b15Skarels + (mfpr(SBR) | 0x80000000)); 8247881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 8257e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 8267e911b15Skarels color_buf[unit]->status = 0; 8277e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8287e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC; 8297e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 8307e911b15Skarels } 831b2b69f49Smarc mtpr(TBIA, 0); 832b2b69f49Smarc /* flag everything now unmapped */ 833b2b69f49Smarc qdflags[unit].mapped = 0; 8347e911b15Skarels qdflags[unit].inuse &= ~GRAPHIC_DEV; 8357e911b15Skarels qdflags[unit].curs_acc = ACC_OFF; 8367e911b15Skarels qdflags[unit].curs_thr = 128; 837b2b69f49Smarc /* 838b2b69f49Smarc * restore the console 839b2b69f49Smarc */ 8407e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8417e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 8427e911b15Skarels dga->csr &= ~DMA_IE; 8437e911b15Skarels dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */ 8447e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 8457e911b15Skarels adder->command = CANCEL; 846b2b69f49Smarc /* 847b2b69f49Smarc * if DMA was running, flush spurious intrpt 848b2b69f49Smarc */ 8497e911b15Skarels if (dga->bytcnt_lo != 0) { 8507e911b15Skarels dga->bytcnt_lo = 0; 8517e911b15Skarels dga->bytcnt_hi = 0; 8527e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 8537e911b15Skarels dga->csr |= DMA_IE; 8547e911b15Skarels dga->csr &= ~DMA_IE; 8557e911b15Skarels } 8567e911b15Skarels init_shared(unit); /* init shared memory */ 8577e911b15Skarels setup_dragon(unit); /* init ADDER/VIPER */ 8587e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 8597e911b15Skarels setup_input(unit); /* init the DUART */ 8607e911b15Skarels ldfont(unit); 8617e911b15Skarels cursor[unit].x = 0; 8627e911b15Skarels cursor[unit].y = 0; 863b2b69f49Smarc /* 864b2b69f49Smarc * shut off the mouse rcv intrpt and turn on kbd intrpts 865b2b69f49Smarc */ 8667e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 8677e911b15Skarels qdflags[unit].duart_imask &= ~(0x20); 8687e911b15Skarels qdflags[unit].duart_imask |= 0x02; 8697e911b15Skarels duart->imask = qdflags[unit].duart_imask; 870b2b69f49Smarc /* 871b2b69f49Smarc * shut off interrupts if all is closed 872b2b69f49Smarc */ 873b2b69f49Smarc if (!(qdflags[unit].inuse & CONS_DEV)) { 8747e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8757e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE); 8767e911b15Skarels } 877b2b69f49Smarc } else { 878b2b69f49Smarc /* 879b2b69f49Smarc * this is the console 880b2b69f49Smarc */ 8817e911b15Skarels tp = &qd_tty[minor_dev]; 8827e911b15Skarels (*linesw[tp->t_line].l_close)(tp); 8837e911b15Skarels ttyclose(tp); 8847e911b15Skarels tp->t_state = 0; 8857e911b15Skarels qdflags[unit].inuse &= ~CONS_DEV; 886b2b69f49Smarc /* 887b2b69f49Smarc * if graphics device is closed, kill interrupts 888b2b69f49Smarc */ 8897e911b15Skarels if (!(qdflags[unit].inuse & GRAPHIC_DEV)) { 8907e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 8917e911b15Skarels dga->csr &= ~(GLOBAL_IE | DMA_IE); 8927e911b15Skarels } 8937e911b15Skarels } 8947e911b15Skarels 8957e911b15Skarels return(0); 8967e911b15Skarels 8977e911b15Skarels } /* qdclose */ 8987e911b15Skarels 8997e911b15Skarels qdioctl(dev, cmd, datap, flags) 9007e911b15Skarels dev_t dev; 9017e911b15Skarels int cmd; 9027881ece5Smarc register caddr_t datap; 9037e911b15Skarels int flags; 9047e911b15Skarels { 9057e911b15Skarels register int *ptep; /* page table entry pointer */ 90624f67f6bSmarc register int mapix; /* QVmap[] page table index */ 9077e911b15Skarels register struct _vs_event *event; 9087e911b15Skarels register struct tty *tp; 9097881ece5Smarc register i; 9107e911b15Skarels struct qdmap *qd; /* pointer to device map struct */ 9117e911b15Skarels struct dga *dga; /* Gate Array reg structure pntr */ 9127e911b15Skarels struct duart *duart; /* DUART reg structure pointer */ 9137e911b15Skarels struct adder *adder; /* ADDER reg structure pointer */ 9147e911b15Skarels struct prgkbd *cmdbuf; 9157e911b15Skarels struct prg_cursor *curs; 9167e911b15Skarels struct _vs_cursor *pos; 9177881ece5Smarc int unit = minor(dev) >> 2; /* number of caller's QDSS */ 9187e911b15Skarels u_int minor_dev = minor(dev); 9197e911b15Skarels int error; 9207e911b15Skarels int s; 9217e911b15Skarels short *temp; /* a pointer to template RAM */ 9227e911b15Skarels 923b2b69f49Smarc /* 924b2b69f49Smarc * service graphic device ioctl commands 925b2b69f49Smarc */ 9267e911b15Skarels switch (cmd) { 927e977faadSmarc 9287e911b15Skarels case QD_GETEVENT: 929b2b69f49Smarc /* 930b2b69f49Smarc * extract the oldest event from the event queue 931b2b69f49Smarc */ 9327e911b15Skarels if (ISEMPTY(eq_header[unit])) { 9337e911b15Skarels event = (struct _vs_event *) datap; 9347e911b15Skarels event->vse_device = VSE_NULL; 9357e911b15Skarels break; 9367e911b15Skarels } 9377e911b15Skarels event = (struct _vs_event *) GETBEGIN(eq_header[unit]); 938e977faadSmarc s = spl5(); 9397e911b15Skarels GETEND(eq_header[unit]); 9407e911b15Skarels splx(s); 9417881ece5Smarc bcopy((caddr_t)event, datap, sizeof(struct _vs_event)); 9427e911b15Skarels break; 9437e911b15Skarels 9447e911b15Skarels case QD_RESET: 945b2b69f49Smarc /* 946b2b69f49Smarc * init the dragon stuff, DUART, and driver variables 947b2b69f49Smarc */ 9487e911b15Skarels init_shared(unit); /* init shared memory */ 9497e911b15Skarels setup_dragon(unit); /* init the ADDER/VIPER stuff */ 9507e911b15Skarels clear_qd_screen(unit); 9517e911b15Skarels ldcursor(unit, cons_cursor); /* load default cursor map */ 9527e911b15Skarels ldfont(unit); /* load the console font */ 9537e911b15Skarels setup_input(unit); /* init the DUART */ 9547e911b15Skarels break; 9557e911b15Skarels 9567e911b15Skarels case QD_SET: 957b2b69f49Smarc /* 958b2b69f49Smarc * init the DUART and driver variables 959b2b69f49Smarc */ 9607e911b15Skarels init_shared(unit); 9617e911b15Skarels setup_input(unit); 9627e911b15Skarels break; 9637e911b15Skarels 9647e911b15Skarels case QD_CLRSCRN: 965b2b69f49Smarc /* 966b2b69f49Smarc * clear the QDSS screen. (NOTE that this reinits the dragon) 967b2b69f49Smarc */ 9687881ece5Smarc #ifdef notdef /* has caused problems and isn't necessary */ 9697e911b15Skarels setup_dragon(unit); 9707e911b15Skarels clear_qd_screen(unit); 971e977faadSmarc #endif 9727e911b15Skarels break; 9737e911b15Skarels 9747e911b15Skarels case QD_WTCURSOR: 975b2b69f49Smarc /* 976b2b69f49Smarc * load a cursor into template RAM 977b2b69f49Smarc */ 9787881ece5Smarc ldcursor(unit, (short *)datap); 9797e911b15Skarels break; 9807e911b15Skarels 9817e911b15Skarels case QD_RDCURSOR: 9827e911b15Skarels 9837e911b15Skarels temp = (short *) qdmap[unit].template; 984b2b69f49Smarc /* 985b2b69f49Smarc * cursor is 32 WORDS from the end of the 8k WORD... 986b2b69f49Smarc * ...template space 987b2b69f49Smarc */ 9887e911b15Skarels temp += (8 * 1024) - 32; 9897e911b15Skarels for (i = 0; i < 32; ++i, datap += sizeof(short)) 9907e911b15Skarels *(short *)datap = *temp++; 9917e911b15Skarels break; 9927e911b15Skarels 9937e911b15Skarels case QD_POSCURSOR: 994b2b69f49Smarc /* 995b2b69f49Smarc * position the mouse cursor 996b2b69f49Smarc */ 9977e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 9987e911b15Skarels pos = (struct _vs_cursor *) datap; 999e977faadSmarc s = spl5(); 10007e911b15Skarels dga->x_cursor = TRANX(pos->x); 10017e911b15Skarels dga->y_cursor = TRANY(pos->y); 10027e911b15Skarels eq_header[unit]->curs_pos.x = pos->x; 10037e911b15Skarels eq_header[unit]->curs_pos.y = pos->y; 10047e911b15Skarels splx(s); 10057e911b15Skarels break; 10067e911b15Skarels 10077e911b15Skarels case QD_PRGCURSOR: 1008b2b69f49Smarc /* 1009b2b69f49Smarc * set the cursor acceleration factor 1010b2b69f49Smarc */ 10117e911b15Skarels curs = (struct prg_cursor *) datap; 1012e977faadSmarc s = spl5(); 10137e911b15Skarels qdflags[unit].curs_acc = curs->acc_factor; 10147e911b15Skarels qdflags[unit].curs_thr = curs->threshold; 10157e911b15Skarels splx(s); 10167e911b15Skarels break; 10177e911b15Skarels 10187e911b15Skarels case QD_MAPDEVICE: 1019b2b69f49Smarc /* 1020b2b69f49Smarc * enable 'user write' to device pages 1021b2b69f49Smarc */ 10227e911b15Skarels qdflags[unit].mapped |= MAPDEV; 10237e911b15Skarels qd = (struct qdmap *) &qdmap[unit]; 1024b2b69f49Smarc /* 1025b2b69f49Smarc * enable user write to template RAM 1026b2b69f49Smarc */ 102724f67f6bSmarc mapix = VTOP((int)qd->template) - VTOP(qvmem[0]); 102824f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10297881ece5Smarc for (i = 0; i < btop(TMPSIZE); i++, ptep++) 10307881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1031b2b69f49Smarc /* 1032b2b69f49Smarc * enable user write to registers 1033b2b69f49Smarc */ 103424f67f6bSmarc mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]); 103524f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10367881ece5Smarc for (i = 0; i < btop(REGSIZE); i++, ptep++) 10377881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1038b2b69f49Smarc /* 1039b2b69f49Smarc * enable user write to color maps 1040b2b69f49Smarc */ 104124f67f6bSmarc mapix = VTOP((int)qd->red) - VTOP(qvmem[0]); 104224f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10437881ece5Smarc for (i = 0; i < btop(CLRSIZE); i++, ptep++) 10447881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 1045b2b69f49Smarc /* 1046b2b69f49Smarc * enable user write to DUART 1047b2b69f49Smarc */ 104824f67f6bSmarc mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]); 104924f67f6bSmarc ptep = (int *)(QVmap[0] + mapix); 10507e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */ 10517e911b15Skarels 10527881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 10537e911b15Skarels 1054b2b69f49Smarc /* 1055b2b69f49Smarc * stuff qdmap structure in return buffer 1056b2b69f49Smarc */ 10577881ece5Smarc bcopy((caddr_t)qd, datap, sizeof(struct qdmap)); 10587e911b15Skarels break; 10597e911b15Skarels 10607e911b15Skarels case QD_MAPIOBUF: 1061b2b69f49Smarc /* 1062b2b69f49Smarc * do setup for DMA by user process 1063b2b69f49Smarc * 1064b2b69f49Smarc * set 'user write enable' bits for DMA buffer 1065b2b69f49Smarc */ 10667e911b15Skarels qdflags[unit].mapped |= MAPDMA; 10677e911b15Skarels ptep = (int *) ((VTOP(DMAheader[unit]) * 4) 10687e911b15Skarels + (mfpr(SBR) | 0x80000000)); 10697881ece5Smarc for (i = 0; i < btop(DMAbuf_size); i++, ptep++) 10707881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 10717881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buffer */ 1072b2b69f49Smarc /* 1073b2b69f49Smarc * set up QBUS map registers for DMA 1074b2b69f49Smarc */ 10757e911b15Skarels DMAheader[unit]->QBAreg = 10767881ece5Smarc uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0); 10777e911b15Skarels if (DMAheader[unit]->QBAreg == 0) 10787881ece5Smarc printf("qd%d: qdioctl: QBA setup error\n", unit); 10797e911b15Skarels Qbus_unmap[unit] = DMAheader[unit]->QBAreg; 10807e911b15Skarels DMAheader[unit]->QBAreg &= 0x3FFFF; 1081b2b69f49Smarc /* 1082b2b69f49Smarc * return I/O buf adr 1083b2b69f49Smarc */ 10847e911b15Skarels *(int *)datap = (int) DMAheader[unit]; 10857e911b15Skarels break; 10867e911b15Skarels 10877e911b15Skarels case QD_MAPSCROLL: 1088b2b69f49Smarc /* 1089b2b69f49Smarc * map the shared scroll param area and enable scroll interpts 1090b2b69f49Smarc */ 10917e911b15Skarels qdflags[unit].mapped |= MAPSCR; 10927e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 10937e911b15Skarels + (mfpr(SBR) | 0x80000000)); 1094b2b69f49Smarc /* 1095b2b69f49Smarc * allow user write to scroll area 1096b2b69f49Smarc */ 10977e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 10987881ece5Smarc mtpr(TBIA, 0); /* invalidate translation buf */ 10997e911b15Skarels scroll[unit]->status = 0; 11007e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11017e911b15Skarels qdflags[unit].adder_ie |= FRAME_SYNC; 11027e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 1103b2b69f49Smarc *(int *)datap = (int) scroll[unit]; /* return scroll area */ 11047e911b15Skarels break; 11057e911b15Skarels 11067e911b15Skarels case QD_UNMAPSCROLL: 1107b2b69f49Smarc /* 1108b2b69f49Smarc * unmap shared scroll param area and disable scroll intrpts 1109b2b69f49Smarc */ 11107e911b15Skarels if (qdflags[unit].mapped & MAPSCR) { 11117e911b15Skarels qdflags[unit].mapped &= ~MAPSCR; 11127e911b15Skarels ptep = (int *) ((VTOP(scroll[unit]) * 4) 11137e911b15Skarels + (mfpr(SBR) | 0x80000000)); 1114b2b69f49Smarc /* 1115b2b69f49Smarc * re-protect 512 scroll param area 1116b2b69f49Smarc */ 11177e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 11187e911b15Skarels mtpr(TBIA, 0); /* smash CPU's translation buf */ 11197e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11207e911b15Skarels qdflags[unit].adder_ie &= ~FRAME_SYNC; 11217e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11227e911b15Skarels } 11237e911b15Skarels break; 11247e911b15Skarels 11257e911b15Skarels case QD_MAPCOLOR: 1126b2b69f49Smarc /* 1127b2b69f49Smarc * map shared color map write buf and turn on vsync intrpt 1128b2b69f49Smarc */ 11297e911b15Skarels qdflags[unit].mapped |= MAPCOLOR; 11307e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 11317e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11327881ece5Smarc /* 11337881ece5Smarc * allow user write to color map write buffer 11347881ece5Smarc */ 11357881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 11367e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11377e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 1138b2b69f49Smarc adder = (struct adder *) qdmap[unit].adder; 11397e911b15Skarels qdflags[unit].adder_ie |= VSYNC; 11407e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11417881ece5Smarc /* 11427881ece5Smarc * return color area address 11437881ece5Smarc */ 11447e911b15Skarels *(int *)datap = (int) color_buf[unit]; 11457e911b15Skarels break; 11467e911b15Skarels 11477e911b15Skarels case QD_UNMAPCOLOR: 1148b2b69f49Smarc /* 1149b2b69f49Smarc * unmap shared color map write buffer and kill VSYNC intrpts 1150b2b69f49Smarc */ 11517e911b15Skarels if (qdflags[unit].mapped & MAPCOLOR) { 11527e911b15Skarels qdflags[unit].mapped &= ~MAPCOLOR; 11537e911b15Skarels ptep = (int *) ((VTOP(color_buf[unit]) * 4) 11547e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11557881ece5Smarc /* 11567881ece5Smarc * re-protect color map write buffer 11577881ece5Smarc */ 11587881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++; 11597e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; 11607881ece5Smarc mtpr(TBIA, 0); 11617e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 11627e911b15Skarels qdflags[unit].adder_ie &= ~VSYNC; 11637e911b15Skarels adder->interrupt_enable = qdflags[unit].adder_ie; 11647e911b15Skarels } 11657e911b15Skarels break; 11667e911b15Skarels 11677e911b15Skarels case QD_MAPEVENT: 1168b2b69f49Smarc /* 1169b2b69f49Smarc * give user write access to the event queue 1170b2b69f49Smarc */ 11717e911b15Skarels qdflags[unit].mapped |= MAPEQ; 11727e911b15Skarels ptep = (int *) ((VTOP(eq_header[unit]) * 4) 11737e911b15Skarels + (mfpr(SBR) | 0x80000000)); 11747881ece5Smarc /* 11757881ece5Smarc * allow user write to 1K event queue 11767881ece5Smarc */ 11777881ece5Smarc *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++; 11787e911b15Skarels *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; 11797e911b15Skarels mtpr(TBIA, 0); /* clr CPU translation buf */ 11807881ece5Smarc /* 11817881ece5Smarc * return event queue address 11827881ece5Smarc */ 11837e911b15Skarels *(int *)datap = (int)eq_header[unit]; 11847e911b15Skarels break; 11857e911b15Skarels 11867e911b15Skarels case QD_PRGKBD: 1187b2b69f49Smarc /* 1188b2b69f49Smarc * pass caller's programming commands to LK201 1189b2b69f49Smarc */ 11907e911b15Skarels duart = (struct duart *)qdmap[unit].duart; 11917e911b15Skarels cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */ 1192b2b69f49Smarc /* 1193b2b69f49Smarc * send command 1194b2b69f49Smarc */ 11957e911b15Skarels for (i = 1000; i > 0; --i) { 11967881ece5Smarc if (duart->statusA&XMT_RDY) { 11977e911b15Skarels duart->dataA = cmdbuf->cmd; 11987e911b15Skarels break; 11997e911b15Skarels } 12007e911b15Skarels } 12017e911b15Skarels if (i == 0) { 12027881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit); 12037e911b15Skarels break; 12047e911b15Skarels } 1205b2b69f49Smarc /* 1206b2b69f49Smarc * send param1? 1207b2b69f49Smarc */ 12087e911b15Skarels if (cmdbuf->cmd & LAST_PARAM) 12097e911b15Skarels break; 12107e911b15Skarels for (i = 1000; i > 0; --i) { 12117881ece5Smarc if (duart->statusA&XMT_RDY) { 12127e911b15Skarels duart->dataA = cmdbuf->param1; 12137e911b15Skarels break; 12147e911b15Skarels } 12157e911b15Skarels } 12167e911b15Skarels if (i == 0) { 12177881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit); 12187e911b15Skarels break; 12197e911b15Skarels } 1220b2b69f49Smarc /* 1221b2b69f49Smarc * send param2? 1222b2b69f49Smarc */ 12237e911b15Skarels if (cmdbuf->param1 & LAST_PARAM) 12247e911b15Skarels break; 12257e911b15Skarels for (i = 1000; i > 0; --i) { 12267881ece5Smarc if (duart->statusA&XMT_RDY) { 12277e911b15Skarels duart->dataA = cmdbuf->param2; 12287e911b15Skarels break; 12297e911b15Skarels } 12307e911b15Skarels } 12317e911b15Skarels if (i == 0) { 12327881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit); 12337e911b15Skarels break; 12347e911b15Skarels } 12357e911b15Skarels break; 12367e911b15Skarels 12377e911b15Skarels case QD_PRGMOUSE: 1238b2b69f49Smarc /* 1239b2b69f49Smarc * pass caller's programming commands to the mouse 1240b2b69f49Smarc */ 12417e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 12427e911b15Skarels for (i = 1000; i > 0; --i) { 12437881ece5Smarc if (duart->statusB&XMT_RDY) { 12447e911b15Skarels duart->dataB = *datap; 12457e911b15Skarels break; 12467e911b15Skarels } 12477e911b15Skarels } 12487e911b15Skarels if (i == 0) { 12497881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit); 12507e911b15Skarels } 12517e911b15Skarels break; 12527e911b15Skarels 12537e911b15Skarels case QD_RDCONFIG: 1254b2b69f49Smarc /* 1255b2b69f49Smarc * get QDSS configuration word and return it 1256b2b69f49Smarc */ 12577e911b15Skarels *(short *)datap = qdflags[unit].config; 12587e911b15Skarels break; 12597e911b15Skarels 1260e977faadSmarc case QD_KERN_LOOP: 1261e977faadSmarc case QD_KERN_UNLOOP: 1262b2b69f49Smarc /* 1263b2b69f49Smarc * vestige from ultrix. BSD uses TIOCCONS to redirect 1264b2b69f49Smarc * kernel console output. 1265b2b69f49Smarc */ 1266e977faadSmarc break; 1267e977faadSmarc 12687e911b15Skarels case QD_PRGTABLET: 1269b2b69f49Smarc /* 1270b2b69f49Smarc * program the tablet 1271b2b69f49Smarc */ 12727e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 12737e911b15Skarels for (i = 1000; i > 0; --i) { 12747881ece5Smarc if (duart->statusB&XMT_RDY) { 12757e911b15Skarels duart->dataB = *datap; 12767e911b15Skarels break; 12777e911b15Skarels } 12787e911b15Skarels } 12797e911b15Skarels if (i == 0) { 12807881ece5Smarc printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit); 12817e911b15Skarels } 12827e911b15Skarels break; 12837e911b15Skarels 12847e911b15Skarels case QD_PRGTABRES: 1285b2b69f49Smarc /* 1286b2b69f49Smarc * program the tablet report resolution factor 1287b2b69f49Smarc */ 12887e911b15Skarels qdflags[unit].tab_res = *(short *)datap; 12897e911b15Skarels break; 12908a2bf9b0Smarc 12917e911b15Skarels default: 1292b2b69f49Smarc /* 1293b2b69f49Smarc * service tty ioctl's 1294b2b69f49Smarc */ 12957e911b15Skarels if (!(minor_dev & 0x02)) { 12967e911b15Skarels tp = &qd_tty[minor_dev]; 1297b2b69f49Smarc error = 1298b2b69f49Smarc (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags); 12997e911b15Skarels if (error >= 0) { 13007e911b15Skarels return(error); 13017e911b15Skarels } 13027e911b15Skarels error = ttioctl(tp, cmd, datap, flags); 13037e911b15Skarels if (error >= 0) { 13047e911b15Skarels return(error); 13057e911b15Skarels } 13067e911b15Skarels } 13077e911b15Skarels break; 13087e911b15Skarels } 13097e911b15Skarels 13107e911b15Skarels return(0); 13117e911b15Skarels 13127e911b15Skarels } /* qdioctl */ 13137e911b15Skarels 13147e911b15Skarels qdselect(dev, rw) 13157e911b15Skarels dev_t dev; 13167e911b15Skarels int rw; 13177e911b15Skarels { 13187881ece5Smarc register s; 13197881ece5Smarc register unit; 1320e977faadSmarc register struct tty *tp; 1321e977faadSmarc u_int minor_dev = minor(dev); 13227e911b15Skarels 1323e977faadSmarc s = spl5(); 1324e977faadSmarc unit = minor_dev >> 2; 13257e911b15Skarels 13267e911b15Skarels switch (rw) { 1327e977faadSmarc case FREAD: 1328b2b69f49Smarc if ((minor_dev & 0x03) == 2) { 1329e977faadSmarc /* 1330e977faadSmarc * this is a graphics device, so check for events 1331e977faadSmarc */ 13327881ece5Smarc if(!(ISEMPTY(eq_header[unit]))) { 13337e911b15Skarels splx(s); 1334e977faadSmarc return(1); 13357e911b15Skarels } 13367881ece5Smarc qdrsel[unit] = u.u_procp; 13377e911b15Skarels qdflags[unit].selmask |= SEL_READ; 13387e911b15Skarels splx(s); 13397e911b15Skarels return(0); 1340b2b69f49Smarc } else { 1341e977faadSmarc /* 1342e977faadSmarc * this is a tty device 1343e977faadSmarc */ 1344e977faadSmarc tp = &qd_tty[minor_dev]; 1345e977faadSmarc if (ttnread(tp)) 1346e977faadSmarc return(1); 1347e977faadSmarc tp->t_rsel = u.u_procp; 13487e911b15Skarels splx(s); 1349e977faadSmarc return(0); 1350e977faadSmarc } 1351e977faadSmarc 1352e977faadSmarc case FWRITE: 1353b2b69f49Smarc if ((minor(dev) & 0x03) == 2) { 1354e977faadSmarc /* 1355e977faadSmarc * this is a graphics device, so check for dma buffers 1356e977faadSmarc */ 1357e977faadSmarc if (DMA_ISEMPTY(DMAheader[unit])) 1358e977faadSmarc { 1359e977faadSmarc splx(s); 1360e977faadSmarc return(1); 13617e911b15Skarels } 13627881ece5Smarc qdrsel[unit] = u.u_procp; 13637e911b15Skarels qdflags[unit].selmask |= SEL_WRITE; 13647e911b15Skarels splx(s); 13657e911b15Skarels return(0); 1366b2b69f49Smarc } else { 1367e977faadSmarc /* 1368e977faadSmarc * this is a tty device 1369e977faadSmarc */ 1370e977faadSmarc tp = &qd_tty[minor_dev]; 1371f5319004Smarc if (tp->t_outq.c_cc <= tp->t_lowat) 1372e977faadSmarc return(1); 1373e977faadSmarc tp->t_wsel = u.u_procp; 1374e977faadSmarc splx(s); 1375e977faadSmarc return(0); 1376e977faadSmarc } 1377e977faadSmarc } 13787881ece5Smarc splx(s); 13797881ece5Smarc return(0); 13807e911b15Skarels 13817e911b15Skarels } /* qdselect() */ 13827e911b15Skarels 13837e911b15Skarels extern qd_strategy(); 13847e911b15Skarels 13857e911b15Skarels qdwrite(dev, uio) 13867e911b15Skarels dev_t dev; 13877e911b15Skarels struct uio *uio; 13887e911b15Skarels { 13897e911b15Skarels register struct tty *tp; 13907881ece5Smarc register minor_dev; 13917881ece5Smarc register unit; 13927e911b15Skarels 13937e911b15Skarels minor_dev = minor(dev); 13947e911b15Skarels unit = (minor_dev >> 2) & 0x07; 13957e911b15Skarels 1396b2b69f49Smarc if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) { 1397b2b69f49Smarc /* 1398b2b69f49Smarc * this is the console... 1399b2b69f49Smarc */ 14007e911b15Skarels tp = &qd_tty[minor_dev]; 14017e911b15Skarels return ((*linesw[tp->t_line].l_write)(tp, uio)); 1402b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1403b2b69f49Smarc /* 1404b2b69f49Smarc * this is a DMA xfer from user space 1405b2b69f49Smarc */ 14067e911b15Skarels return (physio(qd_strategy, &qdbuf[unit], 14077e911b15Skarels dev, B_WRITE, minphys, uio)); 14087e911b15Skarels } 14097881ece5Smarc return (ENXIO); 14107e911b15Skarels } 14117e911b15Skarels 14127e911b15Skarels qdread(dev, uio) 14137e911b15Skarels dev_t dev; 14147e911b15Skarels struct uio *uio; 14157e911b15Skarels { 14167e911b15Skarels register struct tty *tp; 14177881ece5Smarc register minor_dev; 14187881ece5Smarc register unit; 14197e911b15Skarels 14207e911b15Skarels minor_dev = minor(dev); 14217e911b15Skarels unit = (minor_dev >> 2) & 0x07; 14227e911b15Skarels 1423b2b69f49Smarc if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) { 1424b2b69f49Smarc /* 1425b2b69f49Smarc * this is the console 1426b2b69f49Smarc */ 14277e911b15Skarels tp = &qd_tty[minor_dev]; 14287e911b15Skarels return ((*linesw[tp->t_line].l_read)(tp, uio)); 1429b2b69f49Smarc } else if (qdflags[unit].inuse & GRAPHIC_DEV) { 1430b2b69f49Smarc /* 1431b2b69f49Smarc * this is a bitmap-to-processor xfer 1432b2b69f49Smarc */ 14337e911b15Skarels return (physio(qd_strategy, &qdbuf[unit], 14347e911b15Skarels dev, B_READ, minphys, uio)); 14357e911b15Skarels } 14367881ece5Smarc return (ENXIO); 14377e911b15Skarels } 14387e911b15Skarels 14397e911b15Skarels /*************************************************************** 14407e911b15Skarels * 14417e911b15Skarels * qd_strategy()... strategy routine to do DMA 14427e911b15Skarels * 14437e911b15Skarels ***************************************************************/ 14447e911b15Skarels 14457e911b15Skarels qd_strategy(bp) 14467e911b15Skarels register struct buf *bp; 14477e911b15Skarels { 14487e911b15Skarels register struct dga *dga; 14497e911b15Skarels register struct adder *adder; 14507881ece5Smarc register unit; 14517e911b15Skarels int QBAreg; 14527e911b15Skarels int s; 14537e911b15Skarels int cookie; 14547e911b15Skarels 14557e911b15Skarels unit = (minor(bp->b_dev) >> 2) & 0x07; 14567e911b15Skarels 1457b2b69f49Smarc /* 1458b2b69f49Smarc * init pointers 1459b2b69f49Smarc */ 14607e911b15Skarels if ((QBAreg = ubasetup(0, bp, 0)) == 0) { 14617881ece5Smarc printf("qd%d: qd_strategy: QBA setup error\n", unit); 14627e911b15Skarels goto STRAT_ERR; 14637e911b15Skarels } 14647e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 1465e977faadSmarc s = spl5(); 14667e911b15Skarels qdflags[unit].user_dma = -1; 14677e911b15Skarels dga->csr |= DMA_IE; 14687e911b15Skarels cookie = QBAreg & 0x3FFFF; 14697e911b15Skarels dga->adrs_lo = (short) cookie; 14707e911b15Skarels dga->adrs_hi = (short) (cookie >> 16); 14717e911b15Skarels dga->bytcnt_lo = (short) bp->b_bcount; 14727e911b15Skarels dga->bytcnt_hi = (short) (bp->b_bcount >> 16); 14737e911b15Skarels 14747e911b15Skarels while (qdflags[unit].user_dma) { 14757e911b15Skarels sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR); 14767e911b15Skarels } 14777e911b15Skarels splx(s); 14787e911b15Skarels ubarelse(0, &QBAreg); 14797e911b15Skarels if (!(dga->csr & DMA_ERR)) { 14807e911b15Skarels iodone(bp); 14817e911b15Skarels return; 14827e911b15Skarels } 14837e911b15Skarels 14847e911b15Skarels STRAT_ERR: 14857e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 14867e911b15Skarels adder->command = CANCEL; /* cancel adder activity */ 14877e911b15Skarels dga->csr &= ~DMA_IE; 14887e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 14897e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 14907e911b15Skarels bp->b_flags |= B_ERROR; /* flag an error to physio() */ 14917e911b15Skarels 1492b2b69f49Smarc /* 1493b2b69f49Smarc * if DMA was running, flush spurious intrpt 1494b2b69f49Smarc */ 14957e911b15Skarels if (dga->bytcnt_lo != 0) { 14967e911b15Skarels dga->bytcnt_lo = 0; 14977e911b15Skarels dga->bytcnt_hi = 0; 14987e911b15Skarels DMA_SETIGNORE(DMAheader[unit]); 14997e911b15Skarels dga->csr |= DMA_IE; 15007e911b15Skarels } 15017e911b15Skarels iodone(bp); 15027e911b15Skarels 15037e911b15Skarels } /* qd_strategy */ 15047e911b15Skarels 15057881ece5Smarc /* 15067881ece5Smarc * Start output to the console screen 15077881ece5Smarc */ 15087e911b15Skarels qdstart(tp) 15097e911b15Skarels register struct tty *tp; 15107e911b15Skarels { 15117881ece5Smarc register which_unit, unit, c; 15127e911b15Skarels int s; 15137e911b15Skarels 1514e977faadSmarc unit = minor(tp->t_dev); 1515e977faadSmarc which_unit = (unit >> 2) & 0x3; 1516e977faadSmarc unit &= 0x03; 1517e977faadSmarc 1518e977faadSmarc s = spl5(); 1519e977faadSmarc 1520b2b69f49Smarc /* 1521b2b69f49Smarc * If it's currently active, or delaying, no need to do anything. 1522b2b69f49Smarc */ 15237e911b15Skarels if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 15247e911b15Skarels goto out; 15257e911b15Skarels 1526b2b69f49Smarc /* 1527b2b69f49Smarc * Display chars until the queue is empty. 1528b2b69f49Smarc * Drop input from anything but the console 1529b2b69f49Smarc * device on the floor. 1530b2b69f49Smarc * 1531b2b69f49Smarc * XXX - this loop is done at spltty. 1532b2b69f49Smarc * 1533b2b69f49Smarc */ 15347e911b15Skarels while (tp->t_outq.c_cc) { 15357e911b15Skarels c = getc(&tp->t_outq); 1536e977faadSmarc if (unit == 0) 15377881ece5Smarc blitc(which_unit, (u_char)c); 15387e911b15Skarels } 1539b2b69f49Smarc /* 1540e977faadSmarc * If there are sleepers, and output has drained below low 1541b2b69f49Smarc * water mark, wake up the sleepers. 1542b2b69f49Smarc */ 1543f5319004Smarc if (tp->t_outq.c_cc <= tp->t_lowat) { 15447e911b15Skarels if (tp->t_state & TS_ASLEEP){ 15457e911b15Skarels tp->t_state &= ~TS_ASLEEP; 15467e911b15Skarels wakeup((caddr_t) &tp->t_outq); 15477e911b15Skarels } 1548e977faadSmarc } 1549e977faadSmarc 1550e977faadSmarc tp->t_state &= ~TS_BUSY; 15517e911b15Skarels 15527e911b15Skarels out: 15537e911b15Skarels splx(s); 15547e911b15Skarels 15557e911b15Skarels } /* qdstart */ 15567e911b15Skarels 15577881ece5Smarc /*ARGSUSED*/ 15587e911b15Skarels qdstop(tp, flag) 15597e911b15Skarels register struct tty *tp; 15607e911b15Skarels int flag; 15617e911b15Skarels { 15627e911b15Skarels register int s; 15637e911b15Skarels 1564e977faadSmarc s = spl5(); /* block intrpts during state modification */ 15657881ece5Smarc if (tp->t_state & TS_BUSY) 15667881ece5Smarc if ((tp->t_state & TS_TTSTOP) == 0) 15677e911b15Skarels tp->t_state |= TS_FLUSH; 1568b2b69f49Smarc else 15697e911b15Skarels tp->t_state &= ~TS_BUSY; 15707e911b15Skarels splx(s); 15717e911b15Skarels } 15727e911b15Skarels 15737881ece5Smarc /* 15747881ece5Smarc * Output a character to the QDSS screen 15757881ece5Smarc */ 15767e911b15Skarels 15777e911b15Skarels blitc(unit, chr) 15787881ece5Smarc register unit; 15797881ece5Smarc register u_char chr; 15807e911b15Skarels { 15817e911b15Skarels register struct adder *adder; 15827e911b15Skarels register struct dga *dga; 15837e911b15Skarels register int i; 1584b2b69f49Smarc int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV); 1585b2b69f49Smarc static short inescape[NQD]; 15867e911b15Skarels 15877e911b15Skarels adder = (struct adder *)qdmap[unit].adder; 15887e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 1589b2b69f49Smarc /* 1590b2b69f49Smarc * BSD comment: this (&=0177) defeats the extended character 1591b2b69f49Smarc * set code for the glass tty, but if i had the time i would 1592b2b69f49Smarc * spend it ripping out the code completely. This driver 1593b2b69f49Smarc * is too big for its own good. 1594b2b69f49Smarc */ 1595b2b69f49Smarc chr &= 0177; 1596b2b69f49Smarc /* 15977881ece5Smarc * Cursor addressing (so vi will work). 1598b2b69f49Smarc * Decode for "\E=%.%." cursor motion description. 15997881ece5Smarc * Corresponds to type "qdcons" in /etc/termcap: 1600b2b69f49Smarc * 1601b2b69f49Smarc * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\ 1602b2b69f49Smarc * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: 1603b2b69f49Smarc * 1604b2b69f49Smarc */ 1605b2b69f49Smarc if (inescape[unit] && nograph) { 1606b2b69f49Smarc switch (inescape[unit]++) { 1607b2b69f49Smarc case 1: 1608b2b69f49Smarc if (chr != '=') { 1609b2b69f49Smarc /* abort escape sequence */ 1610b2b69f49Smarc inescape[unit] = 0; 1611b2b69f49Smarc blitc(unit, chr); 1612b2b69f49Smarc } 16137881ece5Smarc return; 1614b2b69f49Smarc case 2: 1615b2b69f49Smarc /* position row */ 1616b2b69f49Smarc cursor[unit].y = CHAR_HEIGHT * chr; 1617b2b69f49Smarc if (cursor[unit].y > 863 - CHAR_HEIGHT) 1618b2b69f49Smarc cursor[unit].y = 863 - CHAR_HEIGHT; 1619b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 16207881ece5Smarc return; 1621b2b69f49Smarc case 3: 1622b2b69f49Smarc /* position column */ 1623b2b69f49Smarc cursor[unit].x = CHAR_WIDTH * chr; 1624b2b69f49Smarc if (cursor[unit].x > 1024 - CHAR_WIDTH) 1625b2b69f49Smarc cursor[unit].x = 1023 - CHAR_WIDTH; 1626b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1627b2b69f49Smarc inescape[unit] = 0; 16287881ece5Smarc return; 1629b2b69f49Smarc default: 1630b2b69f49Smarc inescape[unit] = 0; 1631b2b69f49Smarc blitc(unit, chr); 1632b2b69f49Smarc } 1633b2b69f49Smarc } 163424f67f6bSmarc 16357e911b15Skarels switch (chr) { 16367e911b15Skarels case '\r': /* return char */ 16377e911b15Skarels cursor[unit].x = 0; 1638b2b69f49Smarc if (nograph) 16397e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 16407881ece5Smarc return; 16417e911b15Skarels 16427e911b15Skarels case '\t': /* tab char */ 16437e911b15Skarels for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) { 16447e911b15Skarels blitc(unit, ' '); 16457e911b15Skarels } 16467881ece5Smarc return; 16477e911b15Skarels 16487e911b15Skarels case '\n': /* line feed char */ 16497e911b15Skarels if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { 1650b2b69f49Smarc if (nograph) { 16517e911b15Skarels cursor[unit].y -= CHAR_HEIGHT; 16527e911b15Skarels scroll_up(adder); 1653b2b69f49Smarc } else 1654b2b69f49Smarc cursor[unit].y = 0; 16557e911b15Skarels } 1656b2b69f49Smarc if (nograph) 16577e911b15Skarels dga->y_cursor = TRANY(cursor[unit].y); 16587881ece5Smarc return; 16597e911b15Skarels 16607e911b15Skarels case '\b': /* backspace char */ 16617e911b15Skarels if (cursor[unit].x > 0) { 16627e911b15Skarels cursor[unit].x -= CHAR_WIDTH; 1663b2b69f49Smarc if (nograph) 1664b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1665b2b69f49Smarc } 16667881ece5Smarc return; 1667b2b69f49Smarc case CTRL('k'): /* cursor up */ 1668b2b69f49Smarc if (nograph && cursor[unit].y > 0) { 1669b2b69f49Smarc cursor[unit].y -= CHAR_HEIGHT; 1670b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1671b2b69f49Smarc } 16727881ece5Smarc return; 1673b2b69f49Smarc 1674b2b69f49Smarc case CTRL('^'): /* home cursor */ 1675b2b69f49Smarc if (nograph) { 1676b2b69f49Smarc cursor[unit].x = 0; 1677b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1678b2b69f49Smarc cursor[unit].y = 0; 1679b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1680b2b69f49Smarc } 16817881ece5Smarc return; 1682b2b69f49Smarc 1683b2b69f49Smarc case CTRL('l'): /* cursor right */ 1684b2b69f49Smarc if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) { 1685b2b69f49Smarc cursor[unit].x += CHAR_WIDTH; 16867e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 16877e911b15Skarels } 16887881ece5Smarc return; 16897e911b15Skarels 1690b2b69f49Smarc case CTRL('z'): /* clear screen */ 1691b2b69f49Smarc if (nograph) { 1692b2b69f49Smarc setup_dragon(unit); 1693b2b69f49Smarc clear_qd_screen(unit); 1694b2b69f49Smarc /* home cursor - termcap seems to assume this */ 1695b2b69f49Smarc cursor[unit].x = 0; 1696b2b69f49Smarc dga->x_cursor = TRANX(cursor[unit].x); 1697b2b69f49Smarc cursor[unit].y = 0; 1698b2b69f49Smarc dga->y_cursor = TRANY(cursor[unit].y); 1699b2b69f49Smarc } 17007881ece5Smarc return; 1701e977faadSmarc 1702b2b69f49Smarc case '\033': /* start escape sequence */ 1703b2b69f49Smarc if (nograph) 1704b2b69f49Smarc inescape[unit] = 1; 17057881ece5Smarc return; 1706b2b69f49Smarc 1707b2b69f49Smarc default: 1708b2b69f49Smarc if ((chr < ' ') || (chr > '~')) 17097881ece5Smarc return; 17107e911b15Skarels } 1711b2b69f49Smarc /* 1712b2b69f49Smarc * setup VIPER operand control registers 1713b2b69f49Smarc */ 17147e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ 17157e911b15Skarels write_ID(adder, SRC1_OCR_B, 17167e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 17177e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ 17187e911b15Skarels write_ID(adder, SRC1_OCR_B, 17197e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); 17207e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 17217e911b15Skarels write_ID(adder, DST_OCR_B, 17227e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 17237e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 17247e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); 17257e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 1726e977faadSmarc adder->x_clip_min = 0; 1727e977faadSmarc adder->x_clip_max = 1024; 1728e977faadSmarc adder->y_clip_min = 0; 1729e977faadSmarc adder->y_clip_max = 864; 1730b2b69f49Smarc /* 1731b2b69f49Smarc * load DESTINATION origin and vectors 1732b2b69f49Smarc */ 17337e911b15Skarels adder->fast_dest_dy = 0; 17347e911b15Skarels adder->slow_dest_dx = 0; 17357e911b15Skarels adder->error_1 = 0; 17367e911b15Skarels adder->error_2 = 0; 17377e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 17387881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 17397e911b15Skarels adder->destination_x = cursor[unit].x; 17407e911b15Skarels adder->fast_dest_dx = CHAR_WIDTH; 17417e911b15Skarels adder->destination_y = cursor[unit].y; 17427e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; 1743b2b69f49Smarc /* 1744b2b69f49Smarc * load SOURCE origin and vectors 1745b2b69f49Smarc */ 1746e977faadSmarc if ((chr - ' ') > (CHARS - 1)) { 1747e977faadSmarc printf("Invalid character (x)%x in blitc\n",chr); 1748e977faadSmarc chr = ' '; 1749e977faadSmarc } 1750b2b69f49Smarc /* 1751b2b69f49Smarc * X position is modulo the number of characters per line 1752b2b69f49Smarc */ 1753e977faadSmarc adder->source_1_x = FONT_X + 1754e977faadSmarc (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH); 1755b2b69f49Smarc /* 1756b2b69f49Smarc * Point to either first or second row 1757b2b69f49Smarc */ 1758e977faadSmarc adder->source_1_y = 2048 - 15 * 1759e977faadSmarc (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1); 17607e911b15Skarels adder->source_1_dx = CHAR_WIDTH; 17617e911b15Skarels adder->source_1_dy = CHAR_HEIGHT; 17627e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 17637e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 1764b2b69f49Smarc /* 1765b2b69f49Smarc * update console cursor coordinates 1766b2b69f49Smarc */ 17677e911b15Skarels cursor[unit].x += CHAR_WIDTH; 1768b2b69f49Smarc if (nograph) 17697e911b15Skarels dga->x_cursor = TRANX(cursor[unit].x); 17707e911b15Skarels if (cursor[unit].x > (1024 - CHAR_WIDTH)) { 17717e911b15Skarels blitc(unit, '\r'); 17727e911b15Skarels blitc(unit, '\n'); 17737e911b15Skarels } 17747e911b15Skarels 17757e911b15Skarels } /* blitc */ 17767e911b15Skarels 17777881ece5Smarc qdreset() { } 17787e911b15Skarels 17797881ece5Smarc /* 1780b2b69f49Smarc * INTERRUPT SERVICE ROUTINES 17817881ece5Smarc */ 17827e911b15Skarels 17837881ece5Smarc /* 17847881ece5Smarc * Service "DMA DONE" interrupt condition 17857881ece5Smarc */ 17867e911b15Skarels qddint(qd) 17877881ece5Smarc register qd; 17887e911b15Skarels { 17897e911b15Skarels register struct DMAreq_header *header; 17907e911b15Skarels register struct DMAreq *request; 17917e911b15Skarels register struct dga *dga; 17927e911b15Skarels struct adder *adder; 17937e911b15Skarels int cookie; /* DMA adrs for QDSS */ 17947e911b15Skarels 17957881ece5Smarc (void)spl4(); /* allow interval timer in */ 17967e911b15Skarels 1797b2b69f49Smarc /* 1798b2b69f49Smarc * init pointers 1799b2b69f49Smarc */ 18007e911b15Skarels header = DMAheader[qd]; /* register for optimization */ 18017e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 18027e911b15Skarels adder = (struct adder *) qdmap[qd].adder; 18037e911b15Skarels 1804b2b69f49Smarc /* 1805b2b69f49Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. 1806b2b69f49Smarc */ 18077e911b15Skarels if (DMA_ISIGNORE(header)) { 18087e911b15Skarels DMA_CLRIGNORE(header); 18097e911b15Skarels return; 18107e911b15Skarels } 18117e911b15Skarels 1812b2b69f49Smarc /* 1813b2b69f49Smarc * dump a DMA hardware error message if appropriate 1814b2b69f49Smarc */ 18157e911b15Skarels if (dga->csr & DMA_ERR) { 18167e911b15Skarels 18177e911b15Skarels if (dga->csr & PARITY_ERR) 18187881ece5Smarc printf("qd%d: qddint: DMA hardware parity fault.\n", qd); 18197e911b15Skarels 18207e911b15Skarels if (dga->csr & BUS_ERR) 18217881ece5Smarc printf("qd%d: qddint: DMA hardware bus error.\n", qd); 18227e911b15Skarels } 18237e911b15Skarels 1824b2b69f49Smarc /* 1825b2b69f49Smarc * if this was a DMA from user space... 1826b2b69f49Smarc */ 18277e911b15Skarels if (qdflags[qd].user_dma) { 18287e911b15Skarels qdflags[qd].user_dma = 0; 18297e911b15Skarels wakeup((caddr_t)&qdflags[qd].user_dma); 18307e911b15Skarels return; 18317e911b15Skarels } 18327e911b15Skarels 1833b2b69f49Smarc /* 1834b2b69f49Smarc * if we're doing DMA request queue services, field the error condition 1835b2b69f49Smarc */ 18367e911b15Skarels if (dga->csr & DMA_ERR) { 18377e911b15Skarels 18387e911b15Skarels dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 18397e911b15Skarels dga->csr |= DMA_ERR; /* clear error condition */ 18407e911b15Skarels adder->command = CANCEL; /* cancel adder activity */ 18417e911b15Skarels 18427e911b15Skarels DMA_SETERROR(header); /* flag error in header status word */ 18437e911b15Skarels DMA_CLRACTIVE(header); 18447e911b15Skarels header->DMAreq[header->oldest].DMAdone |= HARD_ERROR; 18457e911b15Skarels header->newest = header->oldest; 18467e911b15Skarels header->used = 0; 18477e911b15Skarels 18487881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18497881ece5Smarc selwakeup(qdrsel[qd], 0); 18507881ece5Smarc qdrsel[qd] = 0; 18517e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18527e911b15Skarels } 18537e911b15Skarels 18547e911b15Skarels if (dga->bytcnt_lo != 0) { 18557e911b15Skarels dga->bytcnt_lo = 0; 18567e911b15Skarels dga->bytcnt_hi = 0; 18577e911b15Skarels DMA_SETIGNORE(header); 18587e911b15Skarels } 18597e911b15Skarels return; 18607e911b15Skarels } 18617e911b15Skarels 1862b2b69f49Smarc /* 1863b2b69f49Smarc * if the DMA request queue is now becoming non-full, 1864b2b69f49Smarc * wakeup "select" client. 1865b2b69f49Smarc */ 18667e911b15Skarels if (DMA_ISFULL(header)) { 18677881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18687881ece5Smarc selwakeup(qdrsel[qd], 0); 18697881ece5Smarc qdrsel[qd] = 0; 18707e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18717e911b15Skarels } 18727e911b15Skarels } 18737e911b15Skarels 18747e911b15Skarels header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE; 1875e977faadSmarc QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype; 18767e911b15Skarels 1877e977faadSmarc /* check for unexpected interrupt */ 1878e977faadSmarc if (DMA_ISEMPTY(header)) 18797e911b15Skarels return; 18807e911b15Skarels 18817e911b15Skarels DMA_GETEND(header); /* update request queue indices */ 18827e911b15Skarels 1883b2b69f49Smarc /* 18847881ece5Smarc * if no more DMA pending, wake up "select" client and exit 18857881ece5Smarc */ 18867e911b15Skarels if (DMA_ISEMPTY(header)) { 18877e911b15Skarels 18887881ece5Smarc if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) { 18897881ece5Smarc selwakeup(qdrsel[qd], 0); 18907881ece5Smarc qdrsel[qd] = 0; 18917e911b15Skarels qdflags[qd].selmask &= ~SEL_WRITE; 18927e911b15Skarels } 18937e911b15Skarels 18947e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 18957e911b15Skarels return; 18967e911b15Skarels } 18977e911b15Skarels 1898b2b69f49Smarc /* 18997881ece5Smarc * initiate next DMA xfer 19007881ece5Smarc */ 19017e911b15Skarels request = DMA_GETBEGIN(header); 1902e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1903e977faadSmarc dga->csr &= ~0x0600; /* halt DMA (reset fifo) */ 1904e977faadSmarc adder->command = CANCEL; /* cancel adder activity */ 1905e977faadSmarc } 1906e977faadSmarc 19077e911b15Skarels 19087e911b15Skarels switch (request->DMAtype) { 19097e911b15Skarels 19107e911b15Skarels case DISPLIST: 1911e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 19127e911b15Skarels dga->csr |= DL_ENB; 1913e977faadSmarc dga->csr &= ~(BTOP_ENB | BYTE_DMA); 1914e977faadSmarc } 19157e911b15Skarels break; 19167e911b15Skarels 19177e911b15Skarels case PTOB: 1918e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1919e977faadSmarc if (request->DMAdone & BYTE_PACK) 1920e977faadSmarc dga->csr |= (PTOB_ENB | BYTE_DMA); 1921e977faadSmarc else { 19227e911b15Skarels dga->csr |= PTOB_ENB; 1923e977faadSmarc dga->csr &= ~BYTE_DMA; 1924e977faadSmarc } 1925e977faadSmarc } 19267e911b15Skarels break; 19277e911b15Skarels 19287e911b15Skarels case BTOP: 1929e977faadSmarc if (request->DMAtype != QDlast_DMAtype) { 1930e977faadSmarc if (request->DMAdone & BYTE_PACK) { 1931e977faadSmarc dga->csr &= ~DL_ENB; 1932e977faadSmarc dga->csr |= (BTOP_ENB | BYTE_DMA); 1933e977faadSmarc } 1934e977faadSmarc else { 19357e911b15Skarels dga->csr |= BTOP_ENB; 1936e977faadSmarc dga->csr &= ~(BYTE_DMA | DL_ENB); 1937e977faadSmarc } 1938e977faadSmarc } 19397e911b15Skarels break; 19407e911b15Skarels default: 19417881ece5Smarc printf("qd%d: qddint: illegal DMAtype parameter.\n", qd); 19427e911b15Skarels DMA_CLRACTIVE(header); /* flag DMA done */ 19437e911b15Skarels return; 19447e911b15Skarels } 19457e911b15Skarels 19467e911b15Skarels if (request->DMAdone & COUNT_ZERO) { 19477e911b15Skarels dga->csr &= ~SET_DONE_FIFO; 1948b2b69f49Smarc } 1949b2b69f49Smarc else if (request->DMAdone & FIFO_EMPTY) { 19507e911b15Skarels dga->csr |= SET_DONE_FIFO; 19517e911b15Skarels } 19527e911b15Skarels 19537e911b15Skarels if (request->DMAdone & WORD_PACK) 19547e911b15Skarels dga->csr &= ~BYTE_DMA; 19557e911b15Skarels else if (request->DMAdone & BYTE_PACK) 19567e911b15Skarels dga->csr |= BYTE_DMA; 19577e911b15Skarels 19587e911b15Skarels dga->csr |= DMA_IE; 1959e977faadSmarc QDlast_DMAtype = request->DMAtype; 19607e911b15Skarels 19617e911b15Skarels cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg; 19627e911b15Skarels 19637e911b15Skarels dga->adrs_lo = (short) cookie; 19647e911b15Skarels dga->adrs_hi = (short) (cookie >> 16); 19657e911b15Skarels 19667e911b15Skarels dga->bytcnt_lo = (short) request->length; 19677e911b15Skarels dga->bytcnt_hi = (short) (request->length >> 16); 19687e911b15Skarels 19697e911b15Skarels return; 19707e911b15Skarels } 19717e911b15Skarels 19727881ece5Smarc /* 19737881ece5Smarc * ADDER interrupt service routine 19747881ece5Smarc */ 19757e911b15Skarels qdaint(qd) 19767881ece5Smarc register qd; 19777e911b15Skarels { 19787e911b15Skarels register struct adder *adder; 19797e911b15Skarels struct color_buf *cbuf; 19807e911b15Skarels int i; 19817e911b15Skarels register struct rgb *rgbp; 19827e911b15Skarels register short *red; 19837e911b15Skarels register short *green; 19847e911b15Skarels register short *blue; 19857e911b15Skarels 19867881ece5Smarc (void)spl4(); /* allow interval timer in */ 19877e911b15Skarels 19887e911b15Skarels adder = (struct adder *) qdmap[qd].adder; 19897e911b15Skarels 1990b2b69f49Smarc /* 1991b2b69f49Smarc * service the vertical blank interrupt (VSYNC bit) by loading 1992b2b69f49Smarc * any pending color map load request 1993b2b69f49Smarc */ 19947e911b15Skarels if (adder->status & VSYNC) { 19957e911b15Skarels adder->status &= ~VSYNC; /* clear the interrupt */ 19967e911b15Skarels cbuf = color_buf[qd]; 19977e911b15Skarels if (cbuf->status & LOAD_COLOR_MAP) { 19987e911b15Skarels 19997e911b15Skarels red = (short *) qdmap[qd].red; 20007e911b15Skarels green = (short *) qdmap[qd].green; 20017e911b15Skarels blue = (short *) qdmap[qd].blue; 20027e911b15Skarels 2003b2b69f49Smarc for (i = cbuf->count, rgbp = cbuf->rgb; 2004b2b69f49Smarc --i >= 0; rgbp++) { 20057e911b15Skarels red[rgbp->offset] = (short) rgbp->red; 20067e911b15Skarels green[rgbp->offset] = (short) rgbp->green; 20077e911b15Skarels blue[rgbp->offset] = (short) rgbp->blue; 20087e911b15Skarels } 20097e911b15Skarels 20107e911b15Skarels cbuf->status &= ~LOAD_COLOR_MAP; 20117e911b15Skarels } 20127e911b15Skarels } 20137e911b15Skarels 2014b2b69f49Smarc /* 2015b2b69f49Smarc * service the scroll interrupt (FRAME_SYNC bit) 2016b2b69f49Smarc */ 20177e911b15Skarels if (adder->status & FRAME_SYNC) { 20187e911b15Skarels adder->status &= ~FRAME_SYNC; /* clear the interrupt */ 20197e911b15Skarels 20207e911b15Skarels if (scroll[qd]->status & LOAD_REGS) { 20217e911b15Skarels 20227881ece5Smarc for (i = 1000, adder->status = 0; i > 0 && 20237881ece5Smarc !(adder->status&ID_SCROLL_READY); --i) 2024b2b69f49Smarc ; 20257e911b15Skarels 20267e911b15Skarels if (i == 0) { 20277881ece5Smarc printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", 2028b2b69f49Smarc qd); 20297e911b15Skarels return; 20307e911b15Skarels } 20317e911b15Skarels 20327e911b15Skarels adder->ID_scroll_data = scroll[qd]->viper_constant; 20337e911b15Skarels adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT; 20347e911b15Skarels 2035b2b69f49Smarc adder->y_scroll_constant = 2036b2b69f49Smarc scroll[qd]->y_scroll_constant; 20377e911b15Skarels adder->y_offset_pending = scroll[qd]->y_offset; 20387e911b15Skarels 20397e911b15Skarels if (scroll[qd]->status & LOAD_INDEX) { 20407e911b15Skarels 2041b2b69f49Smarc adder->x_index_pending = 2042b2b69f49Smarc scroll[qd]->x_index_pending; 2043b2b69f49Smarc adder->y_index_pending = 2044b2b69f49Smarc scroll[qd]->y_index_pending; 20457e911b15Skarels } 20467e911b15Skarels 20477e911b15Skarels scroll[qd]->status = 0x00; 20487e911b15Skarels } 20497e911b15Skarels } 20507e911b15Skarels } 20517e911b15Skarels 20527881ece5Smarc /* 20537881ece5Smarc * DUART input interrupt service routine 20547e911b15Skarels * 2055b2b69f49Smarc * XXX - this routine should be broken out - it is essentially 2056b2b69f49Smarc * straight line code. 20577881ece5Smarc */ 20587e911b15Skarels 20597e911b15Skarels qdiint(qd) 20607881ece5Smarc register qd; 20617e911b15Skarels { 20627e911b15Skarels register struct _vs_event *event; 20637e911b15Skarels register struct qdinput *eqh; 20647e911b15Skarels struct dga *dga; 20657e911b15Skarels struct duart *duart; 20667e911b15Skarels struct mouse_report *new_rep; 20677e911b15Skarels struct uba_device *ui; 20687e911b15Skarels struct tty *tp; 2069e977faadSmarc u_short chr; 20707e911b15Skarels u_short status; 20717e911b15Skarels u_short data; 20727e911b15Skarels u_short key; 20737e911b15Skarels char do_wakeup = 0; /* flag to do a select wakeup call */ 20747e911b15Skarels char a, b, c; /* mouse button test variables */ 20757e911b15Skarels 20767881ece5Smarc (void)spl4(); /* allow interval timer in */ 20777e911b15Skarels 20787e911b15Skarels eqh = eq_header[qd]; /* optimized as a register */ 20797e911b15Skarels new_rep = ¤t_rep[qd]; 20807e911b15Skarels duart = (struct duart *) qdmap[qd].duart; 20817e911b15Skarels 2082b2b69f49Smarc /* 20837881ece5Smarc * if the graphic device is turned on.. 20847881ece5Smarc */ 20857e911b15Skarels if (qdflags[qd].inuse & GRAPHIC_DEV) { 2086b2b69f49Smarc /* 2087b2b69f49Smarc * empty DUART 2088b2b69f49Smarc */ 20897881ece5Smarc while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) { 2090b2b69f49Smarc /* 20917881ece5Smarc * pick up LK-201 input (if any) 20927881ece5Smarc */ 20937881ece5Smarc if (duart->statusA&RCV_RDY) { 20947e911b15Skarels 20957e911b15Skarels /* if error condition, then reset it */ 20967e911b15Skarels 20977881ece5Smarc if (duart->statusA&0x70) { 20987e911b15Skarels duart->cmdA = 0x40; 20997e911b15Skarels continue; 21007e911b15Skarels } 21017e911b15Skarels 21027e911b15Skarels /* event queue full now? (overflow condition) */ 21037e911b15Skarels 21047e911b15Skarels if (ISFULL(eqh) == TRUE) { 2105b2b69f49Smarc printf( 21067881ece5Smarc "qd%d: qdiint: event queue overflow\n", 2107b2b69f49Smarc qd); 21087e911b15Skarels break; 21097e911b15Skarels } 21107e911b15Skarels 2111b2b69f49Smarc /* 21127e911b15Skarels * Check for various keyboard errors */ 21137e911b15Skarels 21147e911b15Skarels key = duart->dataA & 0xFF; 21157e911b15Skarels 2116b2b69f49Smarc if (key==LK_POWER_ERROR || 2117b2b69f49Smarc key==LK_KDOWN_ERROR || 2118b2b69f49Smarc key == LK_INPUT_ERROR || 2119b2b69f49Smarc key == LK_OUTPUT_ERROR) { 2120b2b69f49Smarc printf( 21217881ece5Smarc "qd%d: qdiint: keyboard error, code = %x\n", 2122b2b69f49Smarc qd,key); 21237881ece5Smarc return; 21247e911b15Skarels } 21257e911b15Skarels 21267e911b15Skarels if (key < LK_LOWEST) 21277881ece5Smarc return; 21287e911b15Skarels 21297e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 21307e911b15Skarels 21317e911b15Skarels event = PUTBEGIN(eqh); 21327e911b15Skarels PUTEND(eqh); 21337e911b15Skarels 21347e911b15Skarels event->vse_key = key; 21357e911b15Skarels event->vse_key &= 0x00FF; 21367e911b15Skarels event->vse_x = eqh->curs_pos.x; 21377e911b15Skarels event->vse_y = eqh->curs_pos.y; 21387e911b15Skarels event->vse_time = TOY; 21397e911b15Skarels event->vse_type = VSE_BUTTON; 21407e911b15Skarels event->vse_direction = VSE_KBTRAW; 21417e911b15Skarels event->vse_device = VSE_DKB; 21427e911b15Skarels } 21437e911b15Skarels 2144b2b69f49Smarc /* 21457e911b15Skarels * pick up the mouse input (if any) */ 21467e911b15Skarels 21477e911b15Skarels if ((status = duart->statusB) & RCV_RDY && 21487e911b15Skarels qdflags[qd].pntr_id == MOUSE_ID) { 21497e911b15Skarels 21507e911b15Skarels if (status & 0x70) { 21517e911b15Skarels duart->cmdB = 0x40; 21527e911b15Skarels continue; 21537e911b15Skarels } 21547e911b15Skarels 21557e911b15Skarels /* event queue full now? (overflow condition) */ 21567e911b15Skarels 21577e911b15Skarels if (ISFULL(eqh) == TRUE) { 2158b2b69f49Smarc printf( 21597881ece5Smarc "qd%d: qdiint: event queue overflow\n", 2160b2b69f49Smarc qd); 21617e911b15Skarels break; 21627e911b15Skarels } 21637e911b15Skarels 21647e911b15Skarels data = duart->dataB; /* get report byte */ 21657e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */ 21667e911b15Skarels 2167b2b69f49Smarc /* 21687e911b15Skarels * if 1st byte of report.. */ 21697e911b15Skarels 21707e911b15Skarels if ( data & START_FRAME) { 21717e911b15Skarels new_rep->state = data; 21727e911b15Skarels if (new_rep->bytcnt > 1) { 2173b2b69f49Smarc /* start of new frame */ 2174b2b69f49Smarc new_rep->bytcnt = 1; 2175b2b69f49Smarc /* ..continue looking */ 2176b2b69f49Smarc continue; 21777e911b15Skarels } 21787e911b15Skarels } 21797e911b15Skarels 2180b2b69f49Smarc /* 21817e911b15Skarels * if 2nd byte of report.. */ 21827e911b15Skarels 21837e911b15Skarels else if (new_rep->bytcnt == 2) { 21847e911b15Skarels new_rep->dx = data & 0x00FF; 21857e911b15Skarels } 21867e911b15Skarels 2187b2b69f49Smarc /* 21887e911b15Skarels * if 3rd byte of report, load input event queue */ 21897e911b15Skarels 21907e911b15Skarels else if (new_rep->bytcnt == 3) { 21917e911b15Skarels 21927e911b15Skarels new_rep->dy = data & 0x00FF; 21937e911b15Skarels new_rep->bytcnt = 0; 21947e911b15Skarels 2195b2b69f49Smarc /* 21967e911b15Skarels * if mouse position has changed.. */ 21977e911b15Skarels 21987e911b15Skarels if (new_rep->dx != 0 || new_rep->dy != 0) { 21997e911b15Skarels 2200b2b69f49Smarc /* 22017e911b15Skarels * calculate acceleration factor, if needed */ 22027e911b15Skarels 22037e911b15Skarels if (qdflags[qd].curs_acc > ACC_OFF) { 22047e911b15Skarels 22057e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dx) 22067e911b15Skarels new_rep->dx += 22077e911b15Skarels (new_rep->dx - qdflags[qd].curs_thr) 22087e911b15Skarels * qdflags[qd].curs_acc; 22097e911b15Skarels 22107e911b15Skarels if (qdflags[qd].curs_thr <= new_rep->dy) 22117e911b15Skarels new_rep->dy += 22127e911b15Skarels (new_rep->dy - qdflags[qd].curs_thr) 22137e911b15Skarels * qdflags[qd].curs_acc; 22147e911b15Skarels } 22157e911b15Skarels 2216b2b69f49Smarc /* 22177e911b15Skarels * update cursor position coordinates */ 22187e911b15Skarels 22197e911b15Skarels if (new_rep->state & X_SIGN) { 22207e911b15Skarels eqh->curs_pos.x += new_rep->dx; 22217e911b15Skarels if (eqh->curs_pos.x > 1023) 22227e911b15Skarels eqh->curs_pos.x = 1023; 22237e911b15Skarels } 22247e911b15Skarels else { 22257e911b15Skarels eqh->curs_pos.x -= new_rep->dx; 22267e911b15Skarels if (eqh->curs_pos.x < -15) 22277e911b15Skarels eqh->curs_pos.x = -15; 22287e911b15Skarels } 22297e911b15Skarels 22307e911b15Skarels if (new_rep->state & Y_SIGN) { 22317e911b15Skarels eqh->curs_pos.y -= new_rep->dy; 22327e911b15Skarels if (eqh->curs_pos.y < -15) 22337e911b15Skarels eqh->curs_pos.y = -15; 22347e911b15Skarels } 22357e911b15Skarels else { 22367e911b15Skarels eqh->curs_pos.y += new_rep->dy; 22377e911b15Skarels if (eqh->curs_pos.y > 863) 22387e911b15Skarels eqh->curs_pos.y = 863; 22397e911b15Skarels } 22407e911b15Skarels 2241b2b69f49Smarc /* 22427e911b15Skarels * update cursor screen position */ 22437e911b15Skarels 22447e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 22457e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x); 22467e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y); 22477e911b15Skarels 2248b2b69f49Smarc /* 22497e911b15Skarels * if cursor is in the box, no event report */ 22507e911b15Skarels 22517e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right && 22527e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left && 22537e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top && 22547e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) { 22557e911b15Skarels goto GET_MBUTTON; 22567e911b15Skarels } 22577e911b15Skarels 2258b2b69f49Smarc /* 22597e911b15Skarels * report the mouse motion event */ 22607e911b15Skarels 22617e911b15Skarels event = PUTBEGIN(eqh); 22627e911b15Skarels PUTEND(eqh); 22637e911b15Skarels 22647e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 22657e911b15Skarels 22667e911b15Skarels event->vse_x = eqh->curs_pos.x; 22677e911b15Skarels event->vse_y = eqh->curs_pos.y; 22687e911b15Skarels 22697e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */ 22707e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */ 22717e911b15Skarels event->vse_key = 0; 22727e911b15Skarels event->vse_direction = 0; 22737e911b15Skarels event->vse_time = TOY; /* time stamp */ 22747e911b15Skarels } 22757e911b15Skarels 22767e911b15Skarels GET_MBUTTON: 2277b2b69f49Smarc /* 22787e911b15Skarels * if button state has changed */ 22797e911b15Skarels 22807e911b15Skarels a = new_rep->state & 0x07; /*mask nonbutton bits */ 22817e911b15Skarels b = last_rep[qd].state & 0x07; 22827e911b15Skarels 22837e911b15Skarels if (a ^ b) { 22847e911b15Skarels 22857e911b15Skarels for ( c = 1; c < 8; c <<= 1) { 22867e911b15Skarels 22877e911b15Skarels if (!( c & (a ^ b))) /* this button change? */ 22887e911b15Skarels continue; 22897e911b15Skarels 22907e911b15Skarels /* event queue full? (overflow condition) */ 22917e911b15Skarels 22927e911b15Skarels if (ISFULL(eqh) == TRUE) { 22937881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 22947e911b15Skarels break; 22957e911b15Skarels } 22967e911b15Skarels 22977e911b15Skarels event = PUTBEGIN(eqh); /* get new event */ 22987e911b15Skarels PUTEND(eqh); 22997e911b15Skarels 23007e911b15Skarels ++do_wakeup; /* request select wakeup */ 23017e911b15Skarels 23027e911b15Skarels event->vse_x = eqh->curs_pos.x; 23037e911b15Skarels event->vse_y = eqh->curs_pos.y; 23047e911b15Skarels 23057e911b15Skarels event->vse_device = VSE_MOUSE; /* mouse */ 23067e911b15Skarels event->vse_type = VSE_BUTTON; /* new button */ 23077e911b15Skarels event->vse_time = TOY; /* time stamp */ 23087e911b15Skarels 23097e911b15Skarels /* flag changed button and if up or down */ 23107e911b15Skarels 23117e911b15Skarels if (c == RIGHT_BUTTON) 23127e911b15Skarels event->vse_key = VSE_RIGHT_BUTTON; 23137e911b15Skarels else if (c == MIDDLE_BUTTON) 23147e911b15Skarels event->vse_key = VSE_MIDDLE_BUTTON; 23157e911b15Skarels else if (c == LEFT_BUTTON) 23167e911b15Skarels event->vse_key = VSE_LEFT_BUTTON; 23177e911b15Skarels 23187e911b15Skarels /* set bit = button depressed */ 23197e911b15Skarels 23207e911b15Skarels if (c & a) 23217e911b15Skarels event->vse_direction = VSE_KBTDOWN; 23227e911b15Skarels else 23237e911b15Skarels event->vse_direction = VSE_KBTUP; 23247e911b15Skarels } 23257e911b15Skarels } 23267e911b15Skarels 23277e911b15Skarels /* refresh last report */ 23287e911b15Skarels 23297e911b15Skarels last_rep[qd] = current_rep[qd]; 23307e911b15Skarels 23317e911b15Skarels } /* get last byte of report */ 23327881ece5Smarc } else if ((status = duart->statusB)&RCV_RDY && 23337e911b15Skarels qdflags[qd].pntr_id == TABLET_ID) { 23347881ece5Smarc /* 23357881ece5Smarc * pickup tablet input, if any 23367881ece5Smarc */ 23377e911b15Skarels if (status&0x70) { 23387e911b15Skarels duart->cmdB = 0x40; 23397e911b15Skarels continue; 23407e911b15Skarels } 23417881ece5Smarc /* 23427881ece5Smarc * event queue full now? (overflow condition) 23437881ece5Smarc */ 23447e911b15Skarels if (ISFULL(eqh) == TRUE) { 23457881ece5Smarc printf("qd%d: qdiint: event queue overflow\n", qd); 23467e911b15Skarels break; 23477e911b15Skarels } 23487e911b15Skarels 23497e911b15Skarels data = duart->dataB; /* get report byte */ 23507e911b15Skarels ++new_rep->bytcnt; /* bump report byte count */ 23517e911b15Skarels 2352b2b69f49Smarc /* 23537e911b15Skarels * if 1st byte of report.. */ 23547e911b15Skarels 23557e911b15Skarels if (data & START_FRAME) { 23567e911b15Skarels new_rep->state = data; 23577e911b15Skarels if (new_rep->bytcnt > 1) { 23587e911b15Skarels new_rep->bytcnt = 1; /* start of new frame */ 23597e911b15Skarels continue; /* ..continue looking */ 23607e911b15Skarels } 23617e911b15Skarels } 23627e911b15Skarels 2363b2b69f49Smarc /* 23647e911b15Skarels * if 2nd byte of report.. */ 23657e911b15Skarels 23667e911b15Skarels else if (new_rep->bytcnt == 2) { 23677e911b15Skarels new_rep->dx = data & 0x3F; 23687e911b15Skarels } 23697e911b15Skarels 2370b2b69f49Smarc /* 23717e911b15Skarels * if 3rd byte of report.. */ 23727e911b15Skarels 23737e911b15Skarels else if (new_rep->bytcnt == 3) { 23747e911b15Skarels new_rep->dx |= (data & 0x3F) << 6; 23757e911b15Skarels } 23767e911b15Skarels 2377b2b69f49Smarc /* 23787e911b15Skarels * if 4th byte of report.. */ 23797e911b15Skarels 23807e911b15Skarels else if (new_rep->bytcnt == 4) { 23817e911b15Skarels new_rep->dy = data & 0x3F; 23827e911b15Skarels } 23837e911b15Skarels 2384b2b69f49Smarc /* 23857e911b15Skarels * if 5th byte of report, load input event queue */ 23867e911b15Skarels 23877e911b15Skarels else if (new_rep->bytcnt == 5) { 23887e911b15Skarels 23897e911b15Skarels new_rep->dy |= (data & 0x3F) << 6; 23907e911b15Skarels new_rep->bytcnt = 0; 23917e911b15Skarels 2392b2b69f49Smarc /* 23937e911b15Skarels * update cursor position coordinates */ 23947e911b15Skarels 23957e911b15Skarels new_rep->dx /= qdflags[qd].tab_res; 23967e911b15Skarels new_rep->dy = (2200 - new_rep->dy) 23977e911b15Skarels / qdflags[qd].tab_res; 23987e911b15Skarels 23997e911b15Skarels if (new_rep->dx > 1023) { 24007e911b15Skarels new_rep->dx = 1023; 24017e911b15Skarels } 24027e911b15Skarels if (new_rep->dy > 863) { 24037e911b15Skarels new_rep->dy = 863; 24047e911b15Skarels } 24057e911b15Skarels 24067e911b15Skarels /* 24077e911b15Skarels * report an event if the puck/stylus has moved 24087e911b15Skarels */ 24097e911b15Skarels 24107e911b15Skarels if (eqh->curs_pos.x != new_rep->dx || 24117e911b15Skarels eqh->curs_pos.y != new_rep->dy) { 24127e911b15Skarels 24137e911b15Skarels eqh->curs_pos.x = new_rep->dx; 24147e911b15Skarels eqh->curs_pos.y = new_rep->dy; 24157e911b15Skarels 2416b2b69f49Smarc /* 24177e911b15Skarels * update cursor screen position */ 24187e911b15Skarels 24197e911b15Skarels dga = (struct dga *) qdmap[qd].dga; 24207e911b15Skarels dga->x_cursor = TRANX(eqh->curs_pos.x); 24217e911b15Skarels dga->y_cursor = TRANY(eqh->curs_pos.y); 24227e911b15Skarels 24237e911b15Skarels /* 24247e911b15Skarels * if cursor is in the box, no event report 24257e911b15Skarels */ 24267e911b15Skarels 24277e911b15Skarels if (eqh->curs_pos.x <= eqh->curs_box.right && 24287e911b15Skarels eqh->curs_pos.x >= eqh->curs_box.left && 24297e911b15Skarels eqh->curs_pos.y >= eqh->curs_box.top && 24307e911b15Skarels eqh->curs_pos.y <= eqh->curs_box.bottom ) { 24317e911b15Skarels goto GET_TBUTTON; 24327e911b15Skarels } 24337e911b15Skarels 2434b2b69f49Smarc /* 24357e911b15Skarels * report the tablet motion event */ 24367e911b15Skarels 24377e911b15Skarels event = PUTBEGIN(eqh); 24387e911b15Skarels PUTEND(eqh); 24397e911b15Skarels 24407e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 24417e911b15Skarels 24427e911b15Skarels event->vse_x = eqh->curs_pos.x; 24437e911b15Skarels event->vse_y = eqh->curs_pos.y; 24447e911b15Skarels 24457e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */ 24467e911b15Skarels /* 24477e911b15Skarels * right now, X handles tablet motion the same 24487e911b15Skarels * as mouse motion 24497e911b15Skarels */ 24507e911b15Skarels event->vse_type = VSE_MMOTION; /* pos changed */ 24517e911b15Skarels event->vse_key = 0; 24527e911b15Skarels event->vse_direction = 0; 24537e911b15Skarels event->vse_time = TOY; /* time stamp */ 24547e911b15Skarels } 24557e911b15Skarels GET_TBUTTON: 2456b2b69f49Smarc /* 24577e911b15Skarels * if button state has changed */ 24587e911b15Skarels 24597e911b15Skarels a = new_rep->state & 0x1E; /* mask nonbutton bits */ 24607e911b15Skarels b = last_rep[qd].state & 0x1E; 24617e911b15Skarels 24627e911b15Skarels if (a ^ b) { 24637e911b15Skarels 24647e911b15Skarels /* event queue full now? (overflow condition) */ 24657e911b15Skarels 24667e911b15Skarels if (ISFULL(eqh) == TRUE) { 24677881ece5Smarc printf("qd%d: qdiint: event queue overflow\n",qd); 24687e911b15Skarels break; 24697e911b15Skarels } 24707e911b15Skarels 24717e911b15Skarels event = PUTBEGIN(eqh); /* get new event */ 24727e911b15Skarels PUTEND(eqh); 24737e911b15Skarels 24747e911b15Skarels ++do_wakeup; /* request a select wakeup call */ 24757e911b15Skarels 24767e911b15Skarels event->vse_x = eqh->curs_pos.x; 24777e911b15Skarels event->vse_y = eqh->curs_pos.y; 24787e911b15Skarels 24797e911b15Skarels event->vse_device = VSE_TABLET; /* tablet */ 24807e911b15Skarels event->vse_type = VSE_BUTTON; /* button changed */ 24817e911b15Skarels event->vse_time = TOY; /* time stamp */ 24827e911b15Skarels 24837e911b15Skarels /* define the changed button and if up or down */ 24847e911b15Skarels 24857e911b15Skarels for ( c = 1; c <= 0x10; c <<= 1) { 24867e911b15Skarels if (c & (a ^ b)) { 24877e911b15Skarels if (c == T_LEFT_BUTTON) 24887e911b15Skarels event->vse_key = VSE_T_LEFT_BUTTON; 24897e911b15Skarels else if (c == T_FRONT_BUTTON) 24907e911b15Skarels event->vse_key = VSE_T_FRONT_BUTTON; 24917e911b15Skarels else if (c == T_RIGHT_BUTTON) 24927e911b15Skarels event->vse_key = VSE_T_RIGHT_BUTTON; 24937e911b15Skarels else if (c == T_BACK_BUTTON) 24947e911b15Skarels event->vse_key = VSE_T_BACK_BUTTON; 24957e911b15Skarels break; 24967e911b15Skarels } 24977e911b15Skarels } 24987e911b15Skarels 24997e911b15Skarels /* set bit = button depressed */ 25007e911b15Skarels 25017e911b15Skarels if (c & a) 25027e911b15Skarels event->vse_direction = VSE_KBTDOWN; 25037e911b15Skarels else 25047e911b15Skarels event->vse_direction = VSE_KBTUP; 25057e911b15Skarels } 25067e911b15Skarels 25077e911b15Skarels /* refresh last report */ 25087e911b15Skarels 25097e911b15Skarels last_rep[qd] = current_rep[qd]; 25107e911b15Skarels 25117e911b15Skarels } /* get last byte of report */ 25127e911b15Skarels } /* pick up tablet input */ 25137e911b15Skarels 25147e911b15Skarels } /* while input available.. */ 25157e911b15Skarels 2516b2b69f49Smarc /* 2517b2b69f49Smarc * do select wakeup 2518b2b69f49Smarc */ 25197881ece5Smarc if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) { 25207881ece5Smarc selwakeup(qdrsel[qd], 0); 25217881ece5Smarc qdrsel[qd] = 0; 25227e911b15Skarels qdflags[qd].selmask &= ~SEL_READ; 25237e911b15Skarels do_wakeup = 0; 25247e911b15Skarels } 25257881ece5Smarc } else { 2526b2b69f49Smarc /* 25277881ece5Smarc * if the graphic device is not turned on, this is console input 25287881ece5Smarc */ 2529f79d7b48Smarc if (qdpolling) 2530f79d7b48Smarc return; 25317e911b15Skarels ui = qdinfo[qd]; 25327e911b15Skarels if (ui == 0 || ui->ui_alive == 0) 25337881ece5Smarc return; 25347e911b15Skarels 25357e911b15Skarels tp = &qd_tty[qd << 2]; 25367e911b15Skarels 2537b2b69f49Smarc /* 25387881ece5Smarc * Get a character from the keyboard. 25397881ece5Smarc */ 25407881ece5Smarc while (duart->statusA&RCV_RDY) { 25417e911b15Skarels key = duart->dataA; 25427e911b15Skarels key &= 0xFF; 2543b2b69f49Smarc /* 25447881ece5Smarc * Check for various keyboard errors 25457881ece5Smarc */ 25467e911b15Skarels if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 25477e911b15Skarels key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 25487881ece5Smarc printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key); 25497881ece5Smarc return; 25507e911b15Skarels } 25517e911b15Skarels 25527e911b15Skarels if (key < LK_LOWEST) 25537881ece5Smarc return; 25547e911b15Skarels 2555b2b69f49Smarc /* 25567e911b15Skarels * See if its a state change key */ 25577e911b15Skarels 25587e911b15Skarels switch (key) { 25597e911b15Skarels 25607e911b15Skarels case LOCK: 25617e911b15Skarels q_keyboard.lock ^= 0xffff; /* toggle */ 25627e911b15Skarels if (q_keyboard.lock) 25637881ece5Smarc (void)led_control(qd, LK_LED_ENABLE, 25647881ece5Smarc LK_LED_LOCK); 25657e911b15Skarels else 25667881ece5Smarc (void)led_control(qd, LK_LED_DISABLE, 25677881ece5Smarc LK_LED_LOCK); 25687e911b15Skarels return; 25697e911b15Skarels 25707e911b15Skarels case SHIFT: 25717e911b15Skarels q_keyboard.shift ^= 0xFFFF; 25727e911b15Skarels return; 25737e911b15Skarels 25747e911b15Skarels case CNTRL: 25757e911b15Skarels q_keyboard.cntrl ^= 0xFFFF; 25767e911b15Skarels return; 25777e911b15Skarels 25787e911b15Skarels case ALLUP: 25797e911b15Skarels q_keyboard.cntrl = 0; 25807e911b15Skarels q_keyboard.shift = 0; 25817e911b15Skarels return; 25827e911b15Skarels 25837e911b15Skarels case REPEAT: 25847e911b15Skarels chr = q_keyboard.last; 25857e911b15Skarels break; 25867e911b15Skarels 2587b2b69f49Smarc /* 25887e911b15Skarels * Test for cntrl characters. If set, see if the character 25897e911b15Skarels * is elligible to become a control character. */ 25907e911b15Skarels 25917e911b15Skarels default: 25927e911b15Skarels 25937e911b15Skarels if (q_keyboard.cntrl) { 25947e911b15Skarels chr = q_key[key]; 25957e911b15Skarels if (chr >= ' ' && chr <= '~') 25967e911b15Skarels chr &= 0x1F; 2597e977faadSmarc else if (chr >= 0xA1 && chr <= 0xFE) 2598e977faadSmarc chr &= 0x9F; 25997e911b15Skarels } 26007e911b15Skarels else if( q_keyboard.lock || q_keyboard.shift ) 26017e911b15Skarels chr = q_shift_key[key]; 26027e911b15Skarels else 26037e911b15Skarels chr = q_key[key]; 26047e911b15Skarels break; 26057e911b15Skarels } 26067e911b15Skarels 26077e911b15Skarels q_keyboard.last = chr; 26087e911b15Skarels 2609b2b69f49Smarc /* 26107e911b15Skarels * Check for special function keys */ 26117e911b15Skarels 2612e977faadSmarc if (chr & 0x100) { 26137e911b15Skarels char *string; 26147e911b15Skarels string = q_special[chr & 0x7F]; 26157e911b15Skarels while(*string) 26167e911b15Skarels (*linesw[tp->t_line].l_rint)(*string++, tp); 26177e911b15Skarels } 26187e911b15Skarels else { 2619f79d7b48Smarc #ifdef KADB 2620f79d7b48Smarc if (!kdbrintr(chr&0177, tp)) 2621f79d7b48Smarc #endif 2622b2b69f49Smarc (*linesw[tp->t_line].l_rint)(chr&0177, tp); 26237e911b15Skarels } 26247e911b15Skarels } 26257e911b15Skarels } 26267e911b15Skarels } /* qdiint */ 26277e911b15Skarels 26287881ece5Smarc /* 26297e911b15Skarels * 26307881ece5Smarc * Clear the QDSS screen 26317e911b15Skarels * 26327e911b15Skarels * >>> NOTE <<< 26337e911b15Skarels * 26347e911b15Skarels * This code requires that certain adder initialization be valid. To 26357e911b15Skarels * assure that this requirement is satisfied, this routine should be 26367e911b15Skarels * called only after calling the "setup_dragon()" function. 26377e911b15Skarels * 26387e911b15Skarels * Clear the bitmap a piece at a time. Since the fast scroll clear 26397e911b15Skarels * only clears the current displayed portion of the bitmap put a 26407e911b15Skarels * temporary value in the y limit register so we can access whole 26417e911b15Skarels * bitmap 26427e911b15Skarels * 26437881ece5Smarc */ 26447e911b15Skarels clear_qd_screen(unit) 26457e911b15Skarels int unit; 26467e911b15Skarels { 26477e911b15Skarels register struct adder *adder; 26487e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 26497e911b15Skarels 26507e911b15Skarels adder->x_limit = 1024; 26517e911b15Skarels adder->y_limit = 2048 - CHAR_HEIGHT; 26527e911b15Skarels adder->y_offset_pending = 0; 26537881ece5Smarc #define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC) 2654b2b69f49Smarc WSV; 26557e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2656b2b69f49Smarc WSV; 26577e911b15Skarels adder->y_offset_pending = 864; 2658b2b69f49Smarc WSV; 26597e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2660b2b69f49Smarc WSV; 26617e911b15Skarels adder->y_offset_pending = 1728; 2662b2b69f49Smarc WSV; 26637e911b15Skarels adder->y_scroll_constant = SCROLL_ERASE; 2664b2b69f49Smarc WSV; 26657e911b15Skarels adder->y_offset_pending = 0; /* back to normal */ 2666b2b69f49Smarc WSV; 26677e911b15Skarels adder->x_limit = MAX_SCREEN_X; 26687e911b15Skarels adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; 2669b2b69f49Smarc #undef WSV 26707e911b15Skarels 26717e911b15Skarels } /* clear_qd_screen */ 26727e911b15Skarels 26737881ece5Smarc /* 26747881ece5Smarc * kernel console output to the glass tty 26757881ece5Smarc */ 26767e911b15Skarels qdputc(chr) 26777e911b15Skarels register char chr; 26787e911b15Skarels { 26797e911b15Skarels 2680b2b69f49Smarc /* 2681b2b69f49Smarc * if system is now physical, forget it (ie: crash DUMP) 2682b2b69f49Smarc */ 26837e911b15Skarels if ((mfpr(MAPEN) & 1) == 0) 26847e911b15Skarels return; 26857e911b15Skarels 26867881ece5Smarc blitc(0, (u_char)(chr & 0xff)); 268724f67f6bSmarc if ((chr & 0177) == '\n') 268824f67f6bSmarc blitc(0, '\r'); 268924f67f6bSmarc 26907e911b15Skarels } /* qdputc */ 26917e911b15Skarels 2692b2b69f49Smarc /* 26937881ece5Smarc * load the mouse cursor's template RAM bitmap 26947881ece5Smarc */ 26957e911b15Skarels ldcursor(unit, bitmap) 26967881ece5Smarc int unit; 26977881ece5Smarc register short *bitmap; 26987e911b15Skarels { 26997e911b15Skarels register struct dga *dga; 27007e911b15Skarels register short *temp; 27017e911b15Skarels register int i; 27027881ece5Smarc int curs; 27037e911b15Skarels 27047e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 27057e911b15Skarels temp = (short *) qdmap[unit].template; 27067e911b15Skarels 27077e911b15Skarels if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */ 27087881ece5Smarc curs = -1; /* ..note that.. */ 27097e911b15Skarels dga->csr &= ~CURS_ENB; /* ..and shut it off */ 27107881ece5Smarc } else 27117881ece5Smarc curs = 0; 27127e911b15Skarels 27137e911b15Skarels dga->csr &= ~CURS_ENB; /* shut off the cursor */ 27147e911b15Skarels 27157e911b15Skarels temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ 27167e911b15Skarels /* ..of the 8k WORD template space */ 27177e911b15Skarels for (i = 0; i < 32; ++i) 27187e911b15Skarels *temp++ = *bitmap++; 27197e911b15Skarels 27207881ece5Smarc if (curs) { /* if cursor was enabled.. */ 27217e911b15Skarels dga->csr |= CURS_ENB; /* ..turn it back on */ 27227e911b15Skarels } 27237e911b15Skarels 27247e911b15Skarels } /* ldcursor */ 27257e911b15Skarels 27267881ece5Smarc /* 27277881ece5Smarc * Put the console font in the QDSS off-screen memory 27287881ece5Smarc */ 27297e911b15Skarels ldfont(unit) 27307881ece5Smarc int unit; 27317e911b15Skarels { 27327e911b15Skarels register struct adder *adder; 27337e911b15Skarels 27347881ece5Smarc register i, j, k, max_chars_line; 27357881ece5Smarc register short packed; 27367e911b15Skarels 27377e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 27387e911b15Skarels 2739b2b69f49Smarc /* 27407881ece5Smarc * setup VIPER operand control registers 27417881ece5Smarc */ 27427e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 27437e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 27447e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 27457e911b15Skarels 27467e911b15Skarels write_ID(adder, SRC1_OCR_B, 27477e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 27487e911b15Skarels write_ID(adder, SRC2_OCR_B, 27497e911b15Skarels EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); 27507e911b15Skarels write_ID(adder, DST_OCR_B, 27517e911b15Skarels EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 27527e911b15Skarels 27537e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 27547e911b15Skarels 2755b2b69f49Smarc /* 27567881ece5Smarc * load destination data 27577881ece5Smarc */ 27587881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 27597e911b15Skarels 27607e911b15Skarels adder->destination_x = FONT_X; 27617e911b15Skarels adder->destination_y = FONT_Y; 27627881ece5Smarc #if FONT_WIDTH > MAX_SCREEN_X 2763e977faadSmarc adder->fast_dest_dx = MAX_SCREEN_X; 27647881ece5Smarc #else 27657e911b15Skarels adder->fast_dest_dx = FONT_WIDTH; 27667881ece5Smarc #endif 27677e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; 27687e911b15Skarels 2769b2b69f49Smarc /* 27707e911b15Skarels * setup for processor to bitmap xfer */ 27717e911b15Skarels 27727e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 27737e911b15Skarels adder->cmd = PBT | OCRB | 2 | DTE | 2; 27747e911b15Skarels 2775b2b69f49Smarc /* 2776b2b69f49Smarc * Figure out how many characters can be stored on one "line" of 2777b2b69f49Smarc * offscreen memory. 2778e977faadSmarc */ 2779e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2780e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line) 2781e977faadSmarc max_chars_line = CHARS/2 + CHARS%2; 2782e977faadSmarc 2783b2b69f49Smarc /* 2784e977faadSmarc * iteratively do the processor to bitmap xfer */ 2785e977faadSmarc 2786e977faadSmarc for (i = 0; i < ROWS; ++i) { 2787e977faadSmarc 2788e977faadSmarc /* PTOB a scan line */ 2789e977faadSmarc 2790e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) { 2791e977faadSmarc /* PTOB one scan of a char cell */ 2792e977faadSmarc 2793e977faadSmarc packed = q_font[k]; 2794e977faadSmarc k += ROWS; 2795e977faadSmarc packed |= ((short)q_font[k] << 8); 2796e977faadSmarc k += ROWS; 2797e977faadSmarc 27987881ece5Smarc (void)wait_status(adder, TX_READY); 2799e977faadSmarc adder->id_data = packed; 2800e977faadSmarc } 2801e977faadSmarc } 2802e977faadSmarc 2803b2b69f49Smarc /* 2804b2b69f49Smarc * (XXX XXX XXX - should remove) 2805b2b69f49Smarc * 2806b2b69f49Smarc * Copy the second row of characters. Subtract the first 2807b2b69f49Smarc * row from the total number. Divide this quantity by 2 2808b2b69f49Smarc * because 2 chars are stored in a short in the PTOB loop 2809b2b69f49Smarc * below. Figure out how many characters can be stored on 2810b2b69f49Smarc * one "line" of offscreen memory 2811e977faadSmarc */ 2812b2b69f49Smarc 2813e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2814e977faadSmarc if ((CHARS/2 + CHARS%2) < max_chars_line) 2815e977faadSmarc return; 2816e977faadSmarc max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */ 2817e977faadSmarc /* Paranoia check to see if 3rd row may be needed */ 2818e977faadSmarc if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2))) 2819e977faadSmarc max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2); 2820e977faadSmarc 2821e977faadSmarc adder->destination_x = FONT_X; 2822e977faadSmarc adder->destination_y = FONT_Y - CHAR_HEIGHT; 2823e977faadSmarc adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2; 2824e977faadSmarc adder->slow_dest_dy = CHAR_HEIGHT; 2825e977faadSmarc 2826b2b69f49Smarc /* 2827b2b69f49Smarc * setup for processor to bitmap xfer 2828b2b69f49Smarc */ 2829e977faadSmarc write_ID(adder, CS_UPDATE_MASK, 0x0001); 2830e977faadSmarc adder->cmd = PBT | OCRB | 2 | DTE | 2; 2831e977faadSmarc 2832b2b69f49Smarc /* 2833b2b69f49Smarc * iteratively do the processor to bitmap xfer 2834b2b69f49Smarc */ 28357e911b15Skarels for (i = 0; i < ROWS; ++i) { 2836b2b69f49Smarc /* 2837b2b69f49Smarc * PTOB a scan line 2838b2b69f49Smarc */ 2839e977faadSmarc for (j = 0, k = i; j < max_chars_line; ++j) { 2840b2b69f49Smarc /* 2841b2b69f49Smarc * PTOB one scan of a char cell 2842b2b69f49Smarc */ 2843e977faadSmarc packed = q_font[k + FONT_OFFSET]; 28447e911b15Skarels k += ROWS; 2845e977faadSmarc packed |= ((short)q_font[k + FONT_OFFSET] << 8); 28467e911b15Skarels k += ROWS; 28477881ece5Smarc (void)wait_status(adder, TX_READY); 28487e911b15Skarels adder->id_data = packed; 28497e911b15Skarels } 28507e911b15Skarels } 28517e911b15Skarels 28527e911b15Skarels } /* ldfont */ 28537e911b15Skarels 2854f79d7b48Smarc qdpoll(onoff) 2855f79d7b48Smarc { 2856f79d7b48Smarc qdpolling = onoff; 2857f79d7b48Smarc } 2858f79d7b48Smarc 28597881ece5Smarc /* 28607881ece5Smarc * Get a character from the LK201 (polled) 28617881ece5Smarc */ 28627881ece5Smarc qdgetc() 28637e911b15Skarels { 28647881ece5Smarc register short key; 28657881ece5Smarc register char chr; 28667881ece5Smarc register struct duart *duart; 28677881ece5Smarc 28687881ece5Smarc duart = (struct duart *) qdmap[0].duart; 28697881ece5Smarc 28707881ece5Smarc /* 28717881ece5Smarc * Get a character from the keyboard. 28727881ece5Smarc */ 28737881ece5Smarc LOOP: 28747881ece5Smarc while (!(duart->statusA&RCV_RDY)) 28757881ece5Smarc ; 28767881ece5Smarc 28777881ece5Smarc key = duart->dataA; 28787881ece5Smarc key &= 0xFF; 28797881ece5Smarc 28807881ece5Smarc /* 28817881ece5Smarc * Check for various keyboard errors */ 28827881ece5Smarc 28837881ece5Smarc if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || 28847881ece5Smarc key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { 28857881ece5Smarc printf("Keyboard error, code = %x\n", key); 28867881ece5Smarc return(0); 28877881ece5Smarc } 28887881ece5Smarc 28897881ece5Smarc if (key < LK_LOWEST) 28907881ece5Smarc return(0); 28917881ece5Smarc 28927881ece5Smarc /* 28937881ece5Smarc * See if its a state change key 28947881ece5Smarc */ 28957881ece5Smarc switch (key) { 28967881ece5Smarc 28977881ece5Smarc case LOCK: 28987881ece5Smarc q_keyboard.lock ^= 0xffff; /* toggle */ 28997881ece5Smarc if (q_keyboard.lock) 29007881ece5Smarc (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK); 29017881ece5Smarc else 29027881ece5Smarc (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK); 29037881ece5Smarc goto LOOP; 29047881ece5Smarc 29057881ece5Smarc case SHIFT: 29067881ece5Smarc q_keyboard.shift ^= 0xFFFF; 29077881ece5Smarc goto LOOP; 29087881ece5Smarc 29097881ece5Smarc case CNTRL: 29107881ece5Smarc q_keyboard.cntrl ^= 0xFFFF; 29117881ece5Smarc goto LOOP; 29127881ece5Smarc 29137881ece5Smarc case ALLUP: 29147881ece5Smarc q_keyboard.cntrl = 0; 29157881ece5Smarc q_keyboard.shift = 0; 29167881ece5Smarc goto LOOP; 29177881ece5Smarc 29187881ece5Smarc case REPEAT: 29197881ece5Smarc chr = q_keyboard.last; 29207881ece5Smarc break; 29217881ece5Smarc 29227881ece5Smarc /* 29237881ece5Smarc * Test for cntrl characters. If set, see if the character 29247881ece5Smarc * is elligible to become a control character. 29257881ece5Smarc */ 29267881ece5Smarc default: 29277881ece5Smarc 29287881ece5Smarc if (q_keyboard.cntrl) { 29297881ece5Smarc chr = q_key[key]; 29307881ece5Smarc if (chr >= ' ' && chr <= '~') 29317881ece5Smarc chr &= 0x1F; 29327881ece5Smarc } 29337881ece5Smarc else if ( q_keyboard.lock || q_keyboard.shift ) 29347881ece5Smarc chr = q_shift_key[key]; 29357881ece5Smarc else 29367881ece5Smarc chr = q_key[key]; 29377881ece5Smarc break; 29387881ece5Smarc } 29397881ece5Smarc 29407881ece5Smarc if (chr < ' ' && chr > '~') /* if input is non-displayable */ 29417881ece5Smarc return(0); /* ..then pitch it! */ 29427881ece5Smarc 29437881ece5Smarc q_keyboard.last = chr; 29447881ece5Smarc 29457881ece5Smarc /* 29467881ece5Smarc * Check for special function keys */ 29477881ece5Smarc 29487881ece5Smarc if (chr & 0x80) /* pitch the function keys */ 29497881ece5Smarc return(0); 29507881ece5Smarc else 29517881ece5Smarc return(chr); 29527881ece5Smarc 29537881ece5Smarc } /* qdgetc */ 29547881ece5Smarc 29557881ece5Smarc /* 29567881ece5Smarc * led_control()... twiddle LK-201 LED's 29577881ece5Smarc */ 29587881ece5Smarc led_control(unit, cmd, led_mask) 29597881ece5Smarc int unit, cmd, led_mask; 29607881ece5Smarc { 29617881ece5Smarc register i; 29627e911b15Skarels register struct duart *duart; 29637e911b15Skarels 29647e911b15Skarels duart = (struct duart *)qdmap[unit].duart; 29657e911b15Skarels 29667e911b15Skarels for (i = 1000; i > 0; --i) { 29677881ece5Smarc if (duart->statusA&XMT_RDY) { 29687e911b15Skarels duart->dataA = cmd; 29697e911b15Skarels break; 29707e911b15Skarels } 29717e911b15Skarels } 29727e911b15Skarels for (i = 1000; i > 0; --i) { 29737881ece5Smarc if (duart->statusA&XMT_RDY) { 29747e911b15Skarels duart->dataA = led_mask; 29757e911b15Skarels break; 29767e911b15Skarels } 29777e911b15Skarels } 29787e911b15Skarels if (i == 0) 29797e911b15Skarels return(BAD); 29807e911b15Skarels return(GOOD); 29817e911b15Skarels 29827e911b15Skarels } /* led_control */ 29837e911b15Skarels 29847881ece5Smarc /* 29857e911b15Skarels * scroll_up()... move the screen up one character height 29867881ece5Smarc */ 29877e911b15Skarels scroll_up(adder) 29887e911b15Skarels register struct adder *adder; 29897e911b15Skarels { 2990b2b69f49Smarc /* 2991b2b69f49Smarc * setup VIPER operand control registers 2992b2b69f49Smarc */ 29937881ece5Smarc (void)wait_status(adder, ADDRESS_COMPLETE); 29947e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ 29957e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 29967e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 29977e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 29987e911b15Skarels write_ID(adder, SRC1_OCR_B, 29997e911b15Skarels EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); 30007e911b15Skarels write_ID(adder, DST_OCR_B, 30017e911b15Skarels EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); 3002b2b69f49Smarc /* 3003b2b69f49Smarc * load DESTINATION origin and vectors 3004b2b69f49Smarc */ 30057e911b15Skarels adder->fast_dest_dy = 0; 30067e911b15Skarels adder->slow_dest_dx = 0; 30077e911b15Skarels adder->error_1 = 0; 30087e911b15Skarels adder->error_2 = 0; 30097e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; 30107e911b15Skarels adder->destination_x = 0; 30117e911b15Skarels adder->fast_dest_dx = 1024; 30127e911b15Skarels adder->destination_y = 0; 30137e911b15Skarels adder->slow_dest_dy = 864 - CHAR_HEIGHT; 3014b2b69f49Smarc /* 3015b2b69f49Smarc * load SOURCE origin and vectors 3016b2b69f49Smarc */ 30177e911b15Skarels adder->source_1_x = 0; 30187e911b15Skarels adder->source_1_dx = 1024; 30197e911b15Skarels adder->source_1_y = 0 + CHAR_HEIGHT; 30207e911b15Skarels adder->source_1_dy = 864 - CHAR_HEIGHT; 30217e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 30227e911b15Skarels adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; 3023b2b69f49Smarc /* 3024b2b69f49Smarc * do a rectangle clear of last screen line 3025b2b69f49Smarc */ 30267e911b15Skarels write_ID(adder, MASK_1, 0xffff); 30277e911b15Skarels write_ID(adder, SOURCE, 0xffff); 30287e911b15Skarels write_ID(adder,DST_OCR_B, 30297e911b15Skarels (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); 30307e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); 30317e911b15Skarels adder->error_1 = 0; 30327e911b15Skarels adder->error_2 = 0; 30337e911b15Skarels adder->slow_dest_dx = 0; /* set up the width of */ 30347e911b15Skarels adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ 30357e911b15Skarels adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; 30367881ece5Smarc (void)wait_status(adder, RASTEROP_COMPLETE); 30377e911b15Skarels adder->destination_x = 0; 30387e911b15Skarels adder->destination_y = 864 - CHAR_HEIGHT; 30397e911b15Skarels adder->fast_dest_dx = 1024; /* set up the height */ 30407e911b15Skarels adder->fast_dest_dy = 0; /* of rectangle */ 30417e911b15Skarels write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); 30427e911b15Skarels adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; 30437e911b15Skarels 30447e911b15Skarels } /* scroll_up */ 30457e911b15Skarels 30467881ece5Smarc /* 30477881ece5Smarc * init shared memory pointers and structures 30487881ece5Smarc */ 30497e911b15Skarels init_shared(unit) 30507881ece5Smarc register unit; 30517e911b15Skarels { 30527e911b15Skarels register struct dga *dga; 30537e911b15Skarels 30547e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 30557e911b15Skarels 3056b2b69f49Smarc /* 30577e911b15Skarels * initialize the event queue pointers and header */ 30587e911b15Skarels 30597e911b15Skarels eq_header[unit] = (struct qdinput *) 30607e911b15Skarels ((((int)event_shared & ~(0x01FF)) + 512) 30617e911b15Skarels + (EVENT_BUFSIZE * unit)); 30627e911b15Skarels eq_header[unit]->curs_pos.x = 0; 30637e911b15Skarels eq_header[unit]->curs_pos.y = 0; 30647e911b15Skarels dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x); 30657e911b15Skarels dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y); 30667e911b15Skarels eq_header[unit]->curs_box.left = 0; 30677e911b15Skarels eq_header[unit]->curs_box.right = 0; 30687e911b15Skarels eq_header[unit]->curs_box.top = 0; 30697e911b15Skarels eq_header[unit]->curs_box.bottom = 0; 3070b2b69f49Smarc /* 3071b2b69f49Smarc * assign a pointer to the DMA I/O buffer for this QDSS. 3072b2b69f49Smarc */ 30737e911b15Skarels DMAheader[unit] = (struct DMAreq_header *) 30747e911b15Skarels (((int)(&DMA_shared[0] + 512) & ~0x1FF) 30757e911b15Skarels + (DMAbuf_size * unit)); 30767e911b15Skarels DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit] 30777e911b15Skarels + sizeof(struct DMAreq_header)); 30787e911b15Skarels DMAheader[unit]->QBAreg = 0; 30797e911b15Skarels DMAheader[unit]->status = 0; 30807e911b15Skarels DMAheader[unit]->shared_size = DMAbuf_size; 30817e911b15Skarels DMAheader[unit]->used = 0; 30827e911b15Skarels DMAheader[unit]->size = 10; /* default = 10 requests */ 30837e911b15Skarels DMAheader[unit]->oldest = 0; 30847e911b15Skarels DMAheader[unit]->newest = 0; 3085b2b69f49Smarc /* 3086b2b69f49Smarc * assign a pointer to the scroll structure for this QDSS. 3087b2b69f49Smarc */ 30887e911b15Skarels scroll[unit] = (struct scroll *) 30897e911b15Skarels (((int)(&scroll_shared[0] + 512) & ~0x1FF) 30907e911b15Skarels + (sizeof(struct scroll) * unit)); 30917e911b15Skarels scroll[unit]->status = 0; 30927e911b15Skarels scroll[unit]->viper_constant = 0; 30937e911b15Skarels scroll[unit]->y_scroll_constant = 0; 30947e911b15Skarels scroll[unit]->y_offset = 0; 30957e911b15Skarels scroll[unit]->x_index_pending = 0; 30967e911b15Skarels scroll[unit]->y_index_pending = 0; 3097b2b69f49Smarc /* 3098b2b69f49Smarc * assign a pointer to the color map write buffer for this QDSS 3099b2b69f49Smarc */ 31007e911b15Skarels color_buf[unit] = (struct color_buf *) 31017e911b15Skarels (((int)(&color_shared[0] + 512) & ~0x1FF) 31027e911b15Skarels + (COLOR_BUFSIZ * unit)); 31037e911b15Skarels color_buf[unit]->status = 0; 31047e911b15Skarels color_buf[unit]->count = 0; 31057e911b15Skarels 31067e911b15Skarels } /* init_shared */ 31077e911b15Skarels 31087881ece5Smarc /* 31097881ece5Smarc * init the ADDER, VIPER, bitmaps, & color map 31107881ece5Smarc */ 31117e911b15Skarels setup_dragon(unit) 31127881ece5Smarc int unit; 31137e911b15Skarels { 31147e911b15Skarels 31157e911b15Skarels register struct adder *adder; 31167e911b15Skarels register struct dga *dga; 31177e911b15Skarels short *memcsr; 31187881ece5Smarc register i; 31197e911b15Skarels short top; /* clipping/scrolling boundaries */ 31207e911b15Skarels short bottom; 31217e911b15Skarels short right; 31227e911b15Skarels short left; 31237e911b15Skarels short *red; /* color map pointers */ 31247e911b15Skarels short *green; 31257e911b15Skarels short *blue; 31267e911b15Skarels 3127b2b69f49Smarc /* 3128b2b69f49Smarc * init for setup 3129b2b69f49Smarc */ 31307e911b15Skarels adder = (struct adder *) qdmap[unit].adder; 31317e911b15Skarels dga = (struct dga *) qdmap[unit].dga; 31327e911b15Skarels memcsr = (short *) qdmap[unit].memcsr; 31337e911b15Skarels dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */ 31347e911b15Skarels *memcsr = SYNC_ON; /* blank screen and turn off LED's */ 31357e911b15Skarels adder->command = CANCEL; 3136b2b69f49Smarc /* 3137b2b69f49Smarc * set monitor timing 3138b2b69f49Smarc */ 31397e911b15Skarels adder->x_scan_count_0 = 0x2800; 31407e911b15Skarels adder->x_scan_count_1 = 0x1020; 31417e911b15Skarels adder->x_scan_count_2 = 0x003A; 31427e911b15Skarels adder->x_scan_count_3 = 0x38F0; 31437e911b15Skarels adder->x_scan_count_4 = 0x6128; 31447e911b15Skarels adder->x_scan_count_5 = 0x093A; 31457e911b15Skarels adder->x_scan_count_6 = 0x313C; 31467e911b15Skarels adder->sync_phase_adj = 0x0100; 31477e911b15Skarels adder->x_scan_conf = 0x00C8; 3148b2b69f49Smarc /* 3149b2b69f49Smarc * got a bug in secound pass ADDER! lets take care of it 3150b2b69f49Smarc * 3151b2b69f49Smarc * normally, just use the code in the following bug fix code, but to 31527e911b15Skarels * make repeated demos look pretty, load the registers as if there was 3153b2b69f49Smarc * no bug and then test to see if we are getting sync 3154b2b69f49Smarc */ 31557e911b15Skarels adder->y_scan_count_0 = 0x135F; 31567e911b15Skarels adder->y_scan_count_1 = 0x3363; 31577e911b15Skarels adder->y_scan_count_2 = 0x2366; 31587e911b15Skarels adder->y_scan_count_3 = 0x0388; 3159b2b69f49Smarc /* 3160b2b69f49Smarc * if no sync, do the bug fix code 3161b2b69f49Smarc */ 31627e911b15Skarels if (wait_status(adder, VSYNC) == BAD) { 31637e911b15Skarels /* first load all Y scan registers with very short frame and 31647e911b15Skarels * wait for scroll service. This guarantees at least one SYNC 31657e911b15Skarels * to fix the pass 2 Adder initialization bug (synchronizes 3166b2b69f49Smarc * XCINCH with DMSEEDH) 3167b2b69f49Smarc */ 31687e911b15Skarels adder->y_scan_count_0 = 0x01; 31697e911b15Skarels adder->y_scan_count_1 = 0x01; 31707e911b15Skarels adder->y_scan_count_2 = 0x01; 31717e911b15Skarels adder->y_scan_count_3 = 0x01; 3172b2b69f49Smarc /* 3173b2b69f49Smarc * delay at least 1 full frame time 3174b2b69f49Smarc */ 31757881ece5Smarc (void)wait_status(adder, VSYNC); 31767881ece5Smarc (void)wait_status(adder, VSYNC); 3177b2b69f49Smarc /* 3178b2b69f49Smarc * now load the REAL sync values (in reverse order just to 3179b2b69f49Smarc * be safe. 3180b2b69f49Smarc */ 31817e911b15Skarels adder->y_scan_count_3 = 0x0388; 31827e911b15Skarels adder->y_scan_count_2 = 0x2366; 31837e911b15Skarels adder->y_scan_count_1 = 0x3363; 31847e911b15Skarels adder->y_scan_count_0 = 0x135F; 31857e911b15Skarels } 31867e911b15Skarels *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ 3187b2b69f49Smarc /* 3188b2b69f49Smarc * zero the index registers 3189b2b69f49Smarc */ 31907e911b15Skarels adder->x_index_pending = 0; 31917e911b15Skarels adder->y_index_pending = 0; 31927e911b15Skarels adder->x_index_new = 0; 31937e911b15Skarels adder->y_index_new = 0; 31947e911b15Skarels adder->x_index_old = 0; 31957e911b15Skarels adder->y_index_old = 0; 31967e911b15Skarels adder->pause = 0; 3197b2b69f49Smarc /* 3198b2b69f49Smarc * set rasterop mode to normal pen down 3199b2b69f49Smarc */ 32007e911b15Skarels adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; 3201b2b69f49Smarc /* 3202b2b69f49Smarc * set the rasterop registers to a default values 3203b2b69f49Smarc */ 32047e911b15Skarels adder->source_1_dx = 1; 32057e911b15Skarels adder->source_1_dy = 1; 32067e911b15Skarels adder->source_1_x = 0; 32077e911b15Skarels adder->source_1_y = 0; 32087e911b15Skarels adder->destination_x = 0; 32097e911b15Skarels adder->destination_y = 0; 32107e911b15Skarels adder->fast_dest_dx = 1; 32117e911b15Skarels adder->fast_dest_dy = 0; 32127e911b15Skarels adder->slow_dest_dx = 0; 32137e911b15Skarels adder->slow_dest_dy = 1; 32147e911b15Skarels adder->error_1 = 0; 32157e911b15Skarels adder->error_2 = 0; 3216b2b69f49Smarc /* 32177881ece5Smarc * scale factor = UNITY 3218b2b69f49Smarc */ 32197e911b15Skarels adder->fast_scale = UNITY; 32207e911b15Skarels adder->slow_scale = UNITY; 3221b2b69f49Smarc /* 3222b2b69f49Smarc * set the source 2 parameters 3223b2b69f49Smarc */ 32247e911b15Skarels adder->source_2_x = 0; 32257e911b15Skarels adder->source_2_y = 0; 32267e911b15Skarels adder->source_2_size = 0x0022; 3227b2b69f49Smarc /* 3228b2b69f49Smarc * initialize plane addresses for eight vipers 3229b2b69f49Smarc */ 32307e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0001); 32317e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0000); 32327e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0002); 32337e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0001); 32347e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0004); 32357e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0002); 32367e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0008); 32377e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0003); 32387e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0010); 32397e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0004); 32407e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0020); 32417e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0005); 32427e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0040); 32437e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0006); 32447e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x0080); 32457e911b15Skarels write_ID(adder, PLANE_ADDRESS, 0x0007); 3246b2b69f49Smarc /* 3247b2b69f49Smarc * initialize the external registers. 3248b2b69f49Smarc */ 32497e911b15Skarels write_ID(adder, CS_UPDATE_MASK, 0x00FF); 32507e911b15Skarels write_ID(adder, CS_SCROLL_MASK, 0x00FF); 3251b2b69f49Smarc /* 3252b2b69f49Smarc * initialize resolution mode 3253b2b69f49Smarc */ 32547e911b15Skarels write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ 32557e911b15Skarels write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ 3256b2b69f49Smarc /* 3257b2b69f49Smarc * initialize viper registers 3258b2b69f49Smarc */ 32597e911b15Skarels write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); 32607e911b15Skarels write_ID(adder, SCROLL_FILL, 0x0000); 3261b2b69f49Smarc /* 3262b2b69f49Smarc * set clipping and scrolling limits to full screen 3263b2b69f49Smarc */ 3264b2b69f49Smarc for (i = 1000, adder->status = 0; 32657881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE); --i) 3266b2b69f49Smarc ; 32677e911b15Skarels if (i == 0) 32687881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 32697e911b15Skarels top = 0; 32707e911b15Skarels bottom = 2048; 32717e911b15Skarels left = 0; 32727e911b15Skarels right = 1024; 32737e911b15Skarels adder->x_clip_min = left; 32747e911b15Skarels adder->x_clip_max = right; 32757e911b15Skarels adder->y_clip_min = top; 32767e911b15Skarels adder->y_clip_max = bottom; 32777e911b15Skarels adder->scroll_x_min = left; 32787e911b15Skarels adder->scroll_x_max = right; 32797e911b15Skarels adder->scroll_y_min = top; 32807e911b15Skarels adder->scroll_y_max = bottom; 32817881ece5Smarc (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ 32827881ece5Smarc (void)wait_status(adder, VSYNC); 32837e911b15Skarels adder->x_index_pending = left; 32847e911b15Skarels adder->y_index_pending = top; 32857e911b15Skarels adder->x_index_new = left; 32867e911b15Skarels adder->y_index_new = top; 32877e911b15Skarels adder->x_index_old = left; 32887e911b15Skarels adder->y_index_old = top; 32897e911b15Skarels 32907881ece5Smarc for (i = 1000, adder->status = 0; i > 0 && 32917881ece5Smarc !(adder->status&ADDRESS_COMPLETE) ; --i) 3292b2b69f49Smarc ; 32937e911b15Skarels if (i == 0) 32947881ece5Smarc printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit); 32957e911b15Skarels 32967e911b15Skarels write_ID(adder, LEFT_SCROLL_MASK, 0x0000); 32977e911b15Skarels write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); 3298b2b69f49Smarc /* 3299b2b69f49Smarc * set source and the mask register to all ones (ie: white) o 3300b2b69f49Smarc */ 33017e911b15Skarels write_ID(adder, SOURCE, 0xFFFF); 33027e911b15Skarels write_ID(adder, MASK_1, 0xFFFF); 33037e911b15Skarels write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); 33047e911b15Skarels write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); 3305b2b69f49Smarc /* 3306b2b69f49Smarc * initialize Operand Control Register banks for fill command 3307b2b69f49Smarc */ 33087e911b15Skarels write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); 33097e911b15Skarels write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); 33107e911b15Skarels write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 33117e911b15Skarels write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); 33127e911b15Skarels write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); 33137e911b15Skarels write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); 3314b2b69f49Smarc /* 33157e911b15Skarels * init Logic Unit Function registers, (these are just common values, 3316b2b69f49Smarc * and may be changed as required). 3317b2b69f49Smarc */ 33187e911b15Skarels write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); 3319b2b69f49Smarc write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | 3320b2b69f49Smarc INV_M1_M2); 33217e911b15Skarels write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); 33227e911b15Skarels write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); 3323b2b69f49Smarc /* 3324b2b69f49Smarc * load the color map for black & white 3325b2b69f49Smarc */ 33267881ece5Smarc for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i) 3327b2b69f49Smarc ; 33287e911b15Skarels 33297e911b15Skarels if (i == 0) 33307881ece5Smarc printf("qd%d: setup_dragon: timeout on VSYNC\n", unit); 33317e911b15Skarels 33327e911b15Skarels red = (short *) qdmap[unit].red; 33337e911b15Skarels green = (short *) qdmap[unit].green; 33347e911b15Skarels blue = (short *) qdmap[unit].blue; 33357e911b15Skarels 33367e911b15Skarels *red++ = 0x00; /* black */ 33377e911b15Skarels *green++ = 0x00; 33387e911b15Skarels *blue++ = 0x00; 33397e911b15Skarels 33407e911b15Skarels *red-- = 0xFF; /* white */ 33417e911b15Skarels *green-- = 0xFF; 33427e911b15Skarels *blue-- = 0xFF; 33437e911b15Skarels 3344b2b69f49Smarc /* 33457881ece5Smarc * set color map for mouse cursor 33467881ece5Smarc */ 33477e911b15Skarels 33487e911b15Skarels red += 254; 33497e911b15Skarels green += 254; 33507e911b15Skarels blue += 254; 33517e911b15Skarels 33527e911b15Skarels *red++ = 0x00; /* black */ 33537e911b15Skarels *green++ = 0x00; 33547e911b15Skarels *blue++ = 0x00; 33557e911b15Skarels 33567e911b15Skarels *red = 0xFF; /* white */ 33577e911b15Skarels *green = 0xFF; 33587e911b15Skarels *blue = 0xFF; 33597e911b15Skarels 33607e911b15Skarels } /* setup_dragon */ 33617e911b15Skarels 33627881ece5Smarc /* 33637881ece5Smarc * Init the DUART and set defaults in input 33647881ece5Smarc */ 33657e911b15Skarels setup_input(unit) 33667881ece5Smarc int unit; 33677e911b15Skarels { 33687e911b15Skarels register struct duart *duart; /* DUART register structure pointer */ 33697881ece5Smarc register i, bits; 33707e911b15Skarels char id_byte; 33717e911b15Skarels 33727e911b15Skarels duart = (struct duart *) qdmap[unit].duart; 33737e911b15Skarels duart->imask = 0; 33747e911b15Skarels 3375b2b69f49Smarc /* 3376b2b69f49Smarc * setup the DUART for kbd & pointing device 3377b2b69f49Smarc */ 33787e911b15Skarels duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ 33797e911b15Skarels duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ 33807e911b15Skarels /* no RTS control,char error mode */ 33817e911b15Skarels duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ 33827e911b15Skarels /* no RTS control,no echo or loop */ 33837e911b15Skarels duart->cmdB = RESET_M; /* reset mode reg pntr for host */ 33847e911b15Skarels duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */ 33857e911b15Skarels /* ..no RTS cntrl, char error mode */ 33867e911b15Skarels duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */ 33877e911b15Skarels /* no RTS control,no echo or loop */ 33887e911b15Skarels duart->auxctl = 0x00; /* baud rate set 1 */ 33897e911b15Skarels duart->clkselA = 0x99; /* 4800 baud for kbd */ 33907e911b15Skarels duart->clkselB = 0x99; /* 4800 baud for mouse */ 33917e911b15Skarels 33927e911b15Skarels /* reset everything for keyboard */ 33937e911b15Skarels 33947e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 33957e911b15Skarels duart->cmdA = bits; 33967e911b15Skarels 33977e911b15Skarels /* reset everything for host */ 33987e911b15Skarels 33997e911b15Skarels for (bits = RESET_M; bits < START_BREAK; bits += 0x10) 34007e911b15Skarels duart->cmdB = bits; 34017e911b15Skarels 34027e911b15Skarels duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ 34037e911b15Skarels duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */ 34047e911b15Skarels 3405b2b69f49Smarc /* 34067881ece5Smarc * init keyboard defaults (DUART channel A) 34077881ece5Smarc */ 34087e911b15Skarels for (i = 500; i > 0; --i) { 34097881ece5Smarc if (duart->statusA&XMT_RDY) { 34107e911b15Skarels duart->dataA = LK_DEFAULTS; 34117e911b15Skarels break; 34127e911b15Skarels } 34137e911b15Skarels } 34147e911b15Skarels 34157e911b15Skarels for (i = 100000; i > 0; --i) { 34167881ece5Smarc if (duart->statusA&RCV_RDY) { 34177e911b15Skarels break; 34187e911b15Skarels } 34197e911b15Skarels } 34207e911b15Skarels 34217881ece5Smarc if (duart->dataA) /* flush the ACK */ 34227881ece5Smarc ; 34237e911b15Skarels 3424b2b69f49Smarc /* 34257881ece5Smarc * identify the pointing device 34267881ece5Smarc */ 34277e911b15Skarels for (i = 500; i > 0; --i) { 34287881ece5Smarc if (duart->statusB&XMT_RDY) { 34297e911b15Skarels duart->dataB = SELF_TEST; 34307e911b15Skarels break; 34317e911b15Skarels } 34327e911b15Skarels } 34337e911b15Skarels 3434b2b69f49Smarc /* 34357e911b15Skarels * wait for 1st byte of self test report */ 34367e911b15Skarels 34377e911b15Skarels for (i = 100000; i > 0; --i) { 34387881ece5Smarc if (duart->statusB&RCV_RDY) { 34397e911b15Skarels break; 34407e911b15Skarels } 34417e911b15Skarels } 34427e911b15Skarels 34437e911b15Skarels if (i == 0) { 34447881ece5Smarc printf("qd[%d]: setup_input: timeout on 1st byte of self test\n" 3445b2b69f49Smarc ,unit); 34467e911b15Skarels goto OUT; 34477e911b15Skarels } 34487e911b15Skarels 34497881ece5Smarc if (duart->dataB) 34507881ece5Smarc ; 34517e911b15Skarels 3452b2b69f49Smarc /* 34537881ece5Smarc * wait for ID byte of self test report 34547881ece5Smarc */ 34557e911b15Skarels for (i = 100000; i > 0; --i) { 34567881ece5Smarc if (duart->statusB&RCV_RDY) { 34577e911b15Skarels break; 34587e911b15Skarels } 34597e911b15Skarels } 34607e911b15Skarels 34617e911b15Skarels if (i == 0) { 34627881ece5Smarc printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit); 34637e911b15Skarels goto OUT; 34647e911b15Skarels } 34657e911b15Skarels 34667e911b15Skarels id_byte = duart->dataB; 34677e911b15Skarels 3468b2b69f49Smarc /* 34697881ece5Smarc * wait for other bytes to come in 34707881ece5Smarc */ 34717e911b15Skarels for (i = 100000; i > 0; --i) { 34727881ece5Smarc if (duart->statusB & RCV_RDY) { 34737881ece5Smarc if (duart->dataB) 34747881ece5Smarc ; 34757e911b15Skarels break; 34767e911b15Skarels } 34777e911b15Skarels } 34787e911b15Skarels if (i == 0) { 34797881ece5Smarc printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit); 34807e911b15Skarels goto OUT; 34817e911b15Skarels } 34827e911b15Skarels for (i = 100000; i > 0; --i) { 34837881ece5Smarc if (duart->statusB&RCV_RDY) { 34847881ece5Smarc if (duart->dataB) 34857881ece5Smarc ; 34867e911b15Skarels break; 34877e911b15Skarels } 34887e911b15Skarels } 34897e911b15Skarels if (i == 0) { 34907881ece5Smarc printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit); 34917e911b15Skarels goto OUT; 34927e911b15Skarels } 3493b2b69f49Smarc /* 34947881ece5Smarc * flag pointing device type and set defaults 34957881ece5Smarc */ 34967881ece5Smarc for (i=100000; i>0; --i) 34977881ece5Smarc ; /*XXX*/ 34987e911b15Skarels 34997e911b15Skarels if ((id_byte & 0x0F) != TABLET_ID) { 35007e911b15Skarels qdflags[unit].pntr_id = MOUSE_ID; 35017e911b15Skarels 35027e911b15Skarels for (i = 500; i > 0; --i) { 35037881ece5Smarc if (duart->statusB&XMT_RDY) { 35047e911b15Skarels duart->dataB = INC_STREAM_MODE; 35057e911b15Skarels break; 35067e911b15Skarels } 35077e911b15Skarels } 3508b2b69f49Smarc } 3509b2b69f49Smarc else { 35107e911b15Skarels qdflags[unit].pntr_id = TABLET_ID; 35117e911b15Skarels 35127e911b15Skarels for (i = 500; i > 0; --i) { 35137881ece5Smarc if (duart->statusB&XMT_RDY) { 35147e911b15Skarels duart->dataB = T_STREAM; 35157e911b15Skarels break; 35167e911b15Skarels } 35177e911b15Skarels } 35187e911b15Skarels } 35197e911b15Skarels OUT: 35207e911b15Skarels duart->imask = qdflags[unit].duart_imask; 35217e911b15Skarels 35227e911b15Skarels } /* setup_input */ 35237e911b15Skarels 35247881ece5Smarc /* 35257881ece5Smarc * delay for at least one display frame time 35267e911b15Skarels * 35277e911b15Skarels * return: BAD means that we timed out without ever seeing the 35287e911b15Skarels * vertical sync status bit 35297e911b15Skarels * GOOD otherwise 35307881ece5Smarc */ 35317e911b15Skarels wait_status(adder, mask) 35327e911b15Skarels register struct adder *adder; 35337e911b15Skarels register int mask; 35347e911b15Skarels { 35357881ece5Smarc register i; 35367e911b15Skarels 3537b2b69f49Smarc for (i = 10000, adder->status = 0 ; i > 0 && 35387881ece5Smarc !(adder->status&mask) ; --i) 3539b2b69f49Smarc ; 35407e911b15Skarels 35417e911b15Skarels if (i == 0) { 35427881ece5Smarc printf("wait_status: timeout polling for 0x%x in adder->status\n", mask); 35437e911b15Skarels return(BAD); 35447e911b15Skarels } 35457e911b15Skarels 35467e911b15Skarels return(GOOD); 35477e911b15Skarels 35487e911b15Skarels } /* wait_status */ 35497e911b15Skarels 35507881ece5Smarc /* 35517881ece5Smarc * write out onto the ID bus 35527881ece5Smarc */ 35537e911b15Skarels write_ID(adder, adrs, data) 35547e911b15Skarels register struct adder *adder; 35557e911b15Skarels register short adrs; 35567e911b15Skarels register short data; 35577e911b15Skarels { 35587881ece5Smarc register i; 35597e911b15Skarels 3560b2b69f49Smarc for (i = 100000, adder->status = 0 ; 35617881ece5Smarc i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i) 3562b2b69f49Smarc ; 35637e911b15Skarels 35647e911b15Skarels if (i == 0) 35657e911b15Skarels goto ERR; 35667e911b15Skarels 3567b2b69f49Smarc for (i = 100000, adder->status = 0 ; 35687881ece5Smarc i > 0 && !(adder->status&TX_READY) ; --i) 3569b2b69f49Smarc ; 35707e911b15Skarels 35717e911b15Skarels if (i > 0) { 35727e911b15Skarels adder->id_data = data; 35737e911b15Skarels adder->command = ID_LOAD | adrs; 35747881ece5Smarc return ; 35757e911b15Skarels } 35767e911b15Skarels 35777e911b15Skarels ERR: 35787881ece5Smarc printf("write_ID: timeout trying to write to VIPER\n"); 35797881ece5Smarc return ; 35807e911b15Skarels 35817e911b15Skarels } /* write_ID */ 3582006e9885Smarc #endif 3583