The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/qbus/qd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: qd.c,v 1.31 2003/08/07 16:31:16 agc Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1988 Regents of the University of California.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)qd.c        7.1 (Berkeley) 6/28/91
   32  */
   33 
   34 /************************************************************************
   35 *                                                                       *
   36 *                       Copyright (c) 1985-1988 by                      *
   37 *               Digital Equipment Corporation, Maynard, MA              *
   38 *                       All rights reserved.                            *
   39 *                                                                       *
   40 *   This software is furnished under a license and may be used and      *
   41 *   copied  only  in accordance with the terms of such license and      *
   42 *   with the  inclusion  of  the  above  copyright  notice.   This      *
   43 *   software  or  any  other copies thereof may not be provided or      *
   44 *   otherwise made available to any other person.  No title to and      *
   45 *   ownership of the software is hereby transferred.                    *
   46 *                                                                       *
   47 *   The information in this software is subject to change  without      *
   48 *   notice  and should not be construed as a commitment by Digital      *
   49 *   Equipment Corporation.                                              *
   50 *                                                                       *
   51 *   Digital assumes no responsibility for the use  or  reliability      *
   52 *   of its software on equipment which is not supplied by Digital.      *
   53 *                                                                       *
   54 *************************************************************************/
   55 
   56 /*
   57  * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
   58  */
   59 
   60 #include <sys/cdefs.h>
   61 __KERNEL_RCSID(0, "$NetBSD: qd.c,v 1.31 2003/08/07 16:31:16 agc Exp $");
   62 
   63 #include "opt_ddb.h"
   64 
   65 #include "qd.h"
   66 
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/conf.h>
   70 #include <sys/tty.h>
   71 #include <sys/kernel.h>
   72 #include <sys/device.h>
   73 #include <sys/poll.h>
   74 #include <sys/buf.h>
   75 
   76 #include <uvm/uvm_extern.h>
   77 
   78 #include <dev/cons.h>
   79 
   80 #include <machine/bus.h>
   81 #include <machine/scb.h>
   82 
   83 #ifdef __vax__
   84 #include <machine/sid.h>
   85 #include <machine/cpu.h>
   86 #include <machine/pte.h>
   87 #endif
   88 
   89 #include <dev/qbus/ubavar.h>
   90 
   91 #include <dev/qbus/qduser.h>
   92 #include <dev/qbus/qdreg.h>
   93 #include <dev/qbus/qdioctl.h>
   94 
   95 #include "ioconf.h"
   96 
   97 /*
   98  * QDSS driver status flags for tracking operational state 
   99  */
  100 struct qdflags {
  101         u_int inuse;            /* which minor dev's are in use now */
  102         u_int config;           /* I/O page register content */
  103         u_int mapped;           /* user mapping status word */
  104         u_int kernel_loop;      /* if kernel console is redirected */
  105         u_int user_dma;         /* DMA from user space in progress */
  106         u_short pntr_id;        /* type code of pointing device */
  107         u_short duart_imask;    /* shadowing for duart intrpt mask reg */
  108         u_short adder_ie;       /* shadowing for adder intrpt enbl reg */
  109         u_short curs_acc;       /* cursor acceleration factor */
  110         u_short curs_thr;       /* cursor acceleration threshold level */
  111         u_short tab_res;        /* tablet resolution factor */
  112         u_short selmask;        /* mask for active qd select entries */
  113 };
  114 
  115 /*
  116  * Softc struct to keep track of all states in this driver.
  117  */
  118 struct  qd_softc {
  119         struct  device sc_dev;
  120         bus_space_tag_t sc_iot;
  121         bus_space_handle_t sc_ioh;
  122         bus_dma_tag_t   sc_dmat;
  123 };
  124 
  125 /*
  126  * bit definitions for 'inuse' entry  
  127  */
  128 #define CONS_DEV        0x01
  129 #define GRAPHIC_DEV     0x04
  130 
  131 /*
  132  * bit definitions for 'mapped' member of flag structure 
  133  */
  134 #define MAPDEV          0x01            /* hardware is mapped */
  135 #define MAPDMA          0x02            /* DMA buffer mapped */
  136 #define MAPEQ           0x04            /* event queue buffer mapped */
  137 #define MAPSCR          0x08            /* scroll param area mapped */
  138 #define MAPCOLOR        0x10            /* color map writing buffer mapped */
  139 
  140 /*
  141  * constants used in shared memory operations 
  142  */
  143 #define EVENT_BUFSIZE  1024     /* # of bytes per device's event buffer */
  144 #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))    \
  145         / sizeof(struct _vs_event) )
  146 #define DMA_BUFSIZ      (1024 * 10)
  147 #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
  148 
  149 /*
  150  * reference to an array of "uba_device" structures built by the auto
  151  * configuration program.  The uba_device structure decribes the device
  152  * sufficiently for the driver to talk to it.  The auto configuration code
  153  * fills in the uba_device structures (located in ioconf.c) from user
  154  * maintained info.  
  155  */
  156 struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
  157 struct tty *qd_tty[NQD*4];      /* teletype structures for each.. */
  158 volatile char *qvmem[NQD];
  159 volatile struct pte *QVmap[NQD];
  160 #define CHUNK     (64 * 1024)
  161 #define QMEMSIZE  (1024 * 1024 * 4)     /* 4 meg */
  162 
  163 /*
  164  * static storage used by multiple functions in this code  
  165  */
  166 int Qbus_unmap[NQD];            /* Qbus mapper release code */
  167 struct qdmap qdmap[NQD];        /* QDSS register map structure */
  168 struct qdflags qdflags[NQD];    /* QDSS register map structure */
  169 caddr_t qdbase[NQD];            /* base address of each QDSS unit */
  170 struct buf qdbuf[NQD];          /* buf structs used by strategy */
  171 short qdopened[NQD];            /* graphics device is open exclusive use */
  172 
  173 /*
  174  * the array "event_shared[]" is made up of a number of event queue buffers
  175  * equal to the number of QDSS's configured into the running kernel (NQD).
  176  * Each event queue buffer begins with an event queue header (struct qdinput)
  177  * followed by a group of event queue entries (struct _vs_event).  The array
  178  * "*eq_header[]" is an array of pointers to the start of each event queue
  179  * buffer in "event_shared[]".  
  180  */
  181 #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
  182 
  183 char event_shared[EQSIZE];          /* reserve space for event bufs */
  184 struct qdinput *eq_header[NQD];     /* event queue header pntrs */
  185 
  186 /*
  187  * This allocation method reserves enough memory pages for NQD shared DMA I/O
  188  * buffers.  Each buffer must consume an integral number of memory pages to
  189  * guarantee that a following buffer will begin on a page boundary.  Also,
  190  * enough space is allocated so that the FIRST I/O buffer can start at the
  191  * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
  192  * memory protections can be turned on/off for individual buffers. 
  193  */
  194 #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
  195 
  196 char DMA_shared[IOBUFSIZE];         /* reserve I/O buffer space */
  197 struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
  198 
  199 /*
  200  * The driver assists a client in scroll operations by loading dragon
  201  * registers from an interrupt service routine. The loading is done using
  202  * parameters found in memory shrade between the driver and it's client.
  203  * The scroll parameter structures are ALL loacted in the same memory page
  204  * for reasons of memory economy.  
  205  */
  206 char scroll_shared[2 * 512];    /* reserve space for scroll structs */
  207 struct scroll *scroll[NQD];     /* pointers to scroll structures */
  208 
  209 /*
  210  * the driver is programmable to provide the user with color map write
  211  * services at VSYNC interrupt time.  At interrupt time the driver loads
  212  * the color map with any user-requested load data found in shared memory 
  213  */
  214 #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
  215 
  216 char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
  217 struct color_buf *color_buf[NQD];     /* pointers to color bufs */
  218 
  219 /*
  220  * mouse input event structures 
  221  */
  222 struct mouse_report last_rep[NQD];
  223 struct mouse_report current_rep[NQD];
  224 
  225 struct selinfo qdrsel[NQD];     /* process waiting for select */
  226 struct _vs_cursor cursor[NQD];  /* console cursor */
  227 int qdcount = 0;                /* count of successfully probed qd's */
  228 int nNQD = NQD;
  229 int DMAbuf_size = DMA_BUFSIZ;
  230 int QDlast_DMAtype;             /* type of the last DMA operation */
  231 
  232 /*
  233  * macro to get system time.  Used to time stamp event queue entries 
  234  */
  235 #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
  236 
  237 void qd_attach __P((struct device *, struct device *, void *));
  238 static int qd_match __P((struct device *, struct cfdata *, void *));
  239 
  240 static void qddint __P((void *));       /* DMA gate array intrpt service */
  241 static void qdaint __P((void *));       /* Dragon ADDER intrpt service */
  242 static void qdiint __P((void *));
  243 
  244 #define QDPRIOR (PZERO-1)               /* must be negative */
  245 #define FALSE   0
  246 #ifdef TRUE
  247 #undef TRUE
  248 #endif
  249 #define TRUE    ~FALSE
  250 #define BAD     -1
  251 #define GOOD    0
  252 
  253 /*
  254  * macro to create a system virtual page number from system virtual adrs 
  255  */
  256 #define VTOP(x)  (((int)x & ~0xC0000000) >> VAX_PGSHIFT)
  257 
  258 /*
  259  * QDSS register address offsets from start of QDSS address space 
  260  */
  261 #define QDSIZE   (52 * 1024)    /* size of entire QDSS foot print */
  262 #define TMPSIZE  (16 * 1024)    /* template RAM is 8k SHORT WORDS */
  263 #define TMPSTART 0x8000         /* offset of template RAM from base adrs */
  264 #define REGSIZE  (5 * 512)      /* regs touch 2.5k (5 pages) of addr space */
  265 #define REGSTART 0xC000         /* offset of reg pages from base adrs */
  266 #define ADDER   (REGSTART+0x000)
  267 #define DGA     (REGSTART+0x200)
  268 #define DUART   (REGSTART+0x400)
  269 #define MEMCSR  (REGSTART+0x800)
  270 #define CLRSIZE  (3 * 512)              /* color map size */
  271 #define CLRSTART (REGSTART+0xA00)       /* color map start offset from base */
  272 /*  0x0C00 really */
  273 #define RED     (CLRSTART+0x000)
  274 #define BLUE    (CLRSTART+0x200)
  275 #define GREEN   (CLRSTART+0x400)
  276 
  277 
  278 /*
  279  * QDSS minor device numbers.  The *real* minor device numbers are in
  280  * the bottom two bits of the major/minor device spec.  Bits 2 and up are
  281  * used to specify the QDSS device number (ie: which one?) 
  282  */
  283 
  284 #define CONS            0
  285 #define GRAPHIC         2
  286 
  287 /*
  288  * console cursor bitmap (white block cursor)  
  289  */
  290 short cons_cursor[32] = {
  291         /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
  292         0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
  293         /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
  294         0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
  295 };
  296 
  297 /*
  298  * constants used in font operations 
  299  */
  300 #define CHARS           190                     /* # of chars in the font */
  301 #define CHAR_HEIGHT     15                      /* char height in pixels */
  302 #define CHAR_WIDTH      8                       /* char width in pixels*/
  303 #define FONT_WIDTH      (CHAR_WIDTH * CHARS)    /* font width in pixels */
  304 #define ROWS            CHAR_HEIGHT
  305 #define FONT_X          0                       /* font's off screen adrs */
  306 #define FONT_Y          (2048 - CHAR_HEIGHT)
  307 
  308 /* Offset to second row characters (XXX - should remove) */
  309 #define FONT_OFFSET     ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
  310 
  311 extern char q_font[];           /* reference font object code */
  312 extern  u_short q_key[];        /* reference key xlation tables */
  313 extern  u_short q_shift_key[];
  314 extern  char *q_special[];
  315 
  316 /*
  317  * definitions for cursor acceleration reporting  
  318  */
  319 #define ACC_OFF         0x01            /* acceleration is inactive */
  320 
  321 /*
  322  * virtual console support.
  323  */
  324 extern struct cdevsw *consops;
  325 cons_decl(qd);
  326 void setup_dragon __P((int));
  327 void init_shared __P((int));
  328 void clear_qd_screen __P((int));
  329 void ldfont __P((int));
  330 void ldcursor __P((int, short *));
  331 void setup_input __P((int));
  332 void blitc __P((int, u_char));
  333 void scroll_up __P((volatile struct adder *));
  334 void write_ID __P((volatile struct adder *, short, short));
  335 int wait_status __P((volatile struct adder *, int));
  336 void led_control __P((int, int, int));
  337 void qdstart(struct tty *);
  338 void qdearly(void);
  339 int qdpolling = 0;
  340 
  341 dev_type_open(qdopen);
  342 dev_type_close(qdclose);
  343 dev_type_read(qdread);
  344 dev_type_write(qdwrite);
  345 dev_type_ioctl(qdioctl);
  346 dev_type_stop(qdstop);
  347 dev_type_poll(qdpoll);
  348 dev_type_kqfilter(qdkqfilter);
  349 
  350 const struct cdevsw qd_cdevsw = {
  351         qdopen, qdclose, qdread, qdwrite, qdioctl,
  352         qdstop, notty, qdpoll, nommap, qdkqfilter,
  353 };
  354 
  355 /*
  356  * LK-201 state storage for input console keyboard conversion to ASCII 
  357  */
  358 struct q_keyboard {
  359         int shift;                      /* state variables      */
  360         int cntrl;
  361         int lock;
  362         int lastcode;                   /* last keycode typed   */
  363         unsigned kup[8];                /* bits for each keycode*/
  364         unsigned dkeys[8];              /* down/up mode keys    */
  365         char last;                      /* last character       */
  366 } q_keyboard;
  367 
  368 /*
  369  * tty settings on first open
  370  */
  371 #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
  372 #define OFLAG (OPOST|OXTABS|ONLCR)
  373 #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
  374 #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
  375 
  376 /*
  377  * Kernel virtual addresses where we can map in the QBUS io page and the
  378  * QDSS memory during qdcninit.  pmap_bootstrap fills this in.
  379  */
  380 void *qd_ubaio;
  381 
  382 /* This is the QDSS unit 0 CSR.  It is hard-coded in here so that the 
  383  * QDSS can be used as the console.  The console routines don't get
  384  * any config info.  The ROM also autodetects at this address, so
  385  * the console QDSS should be at this address.  Furthermore, nothing
  386  * else shuld be at this address instead because that would confuse the
  387  * ROM and this driver.
  388  */
  389 #define QDSSCSR 0x1F00
  390 
  391 volatile u_short *qdaddr;         /* Virtual address for QDSS CSR */
  392 
  393 /*
  394  * This flag is set to 1 if the console initialization (qdcninit) 
  395  * has been performed on qd0.  That initialization is required and must 
  396  * be done before the device probe routine.
  397  */
  398 int qd0cninited = 0, qd0iscons = 0;
  399 
  400 /*
  401  * Do early check if the qdss is console. If not; don't allocate
  402  * any memory for it in bootstrap.
  403  */
  404 void
  405 qdearly()
  406 {
  407         extern vaddr_t virtual_avail;
  408         int tmp;
  409 
  410         /* Make sure we're running on a system that can have a QDSS */
  411         if (vax_boardtype == VAX_BTYP_630)  {
  412                 /* Now check some undocumented flag */
  413                 if ((*(int *)(0x200B801E) & 0x60) == 0) 
  414                         /* The KA630 isn't using a QDSS as the console,
  415                          * so we won't either */
  416                         return;
  417         } else if (vax_boardtype != VAX_BTYP_650)
  418                 return;
  419 
  420         /* How to check for console on KA650? We assume that if there is a
  421          * QDSS, it is console.
  422          */
  423 #define QIOPAGE 0x20000000      /* XXX */
  424 #define UBAIOPAGES 16
  425         tmp = QIOPAGE + ubdevreg(QDSSCSR);
  426         if (badaddr((caddr_t)tmp, sizeof(short)))
  427                 return;
  428 
  429         MAPVIRT(qvmem[0], 64 * 1024 * NQD / VAX_NBPG);
  430         MAPVIRT(qd_ubaio, 16);
  431         pmap_map((int)qd_ubaio, QIOPAGE, QIOPAGE + UBAIOPAGES * VAX_NBPG,
  432             VM_PROT_READ|VM_PROT_WRITE);
  433         qdaddr = (u_short *)((u_int)qd_ubaio + ubdevreg(QDSSCSR));
  434         qd0iscons = 1;
  435 }
  436 
  437 void
  438 qdcnprobe(cndev)
  439         struct  consdev *cndev;
  440 {
  441         int i;
  442 
  443         cndev->cn_pri = CN_DEAD;
  444    
  445         if (mfpr(PR_MAPEN) == 0)
  446                 return; /* Cannot use qd if vm system is OFF */
  447 
  448         if (!qd0iscons)
  449                 return;
  450 
  451         /* Find the console device corresponding to the console QDSS */
  452         cndev->cn_dev = makedev(cdevsw_lookup_major(&qd_cdevsw), 0);
  453         cndev->cn_pri = CN_INTERNAL;
  454         return;
  455 }
  456 
  457 
  458 /*
  459  * Init QDSS as console (before probe routine)
  460  */
  461 void
  462 qdcninit(cndev)
  463         struct  consdev *cndev;
  464 {
  465         caddr_t phys_adr;               /* physical QDSS base adrs */
  466         u_int mapix;                    /* index into QVmap[] array */
  467         int unit;
  468 
  469         /* qdaddr must point to CSR for this unit! */
  470    
  471         /* The console QDSS is QDSS unit 0 */
  472         unit = 0;
  473 
  474         /*
  475          * Map q-bus memory used by qdss. (separate map)
  476          */
  477         mapix = QMEMSIZE - (CHUNK * (unit + 1));
  478 #define QMEM 0x30000000
  479         (int)phys_adr = QMEM + mapix;
  480         pmap_map((int)(qvmem[0]), (int)phys_adr, (int)(phys_adr + (CHUNK*NQD)),
  481                                     VM_PROT_READ|VM_PROT_WRITE);
  482 
  483         /* 
  484          * Set QVmap to point to page table entries for what we just
  485          * mapped.
  486          */
  487         QVmap[0] = (struct pte *)kvtopte(qvmem[0]);
  488    
  489         /*
  490          * tell QDSS which Q memory address base to decode 
  491          * (shifted right 16 bits - its in 64K units)
  492          */
  493         *qdaddr = (u_short)((int)mapix >> 16);
  494         qdflags[unit].config = *(u_short *)qdaddr;
  495 
  496         /*
  497          * load qdmap struct with the virtual addresses of the QDSS elements 
  498          */
  499         qdbase[unit] = (caddr_t) (qvmem[0]);
  500         qdmap[unit].template = qdbase[unit] + TMPSTART;
  501         qdmap[unit].adder = qdbase[unit] + ADDER;
  502         qdmap[unit].dga = qdbase[unit] + DGA;
  503         qdmap[unit].duart = qdbase[unit] + DUART;
  504         qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
  505         qdmap[unit].red = qdbase[unit] + RED;
  506         qdmap[unit].blue = qdbase[unit] + BLUE;
  507         qdmap[unit].green = qdbase[unit] + GREEN;
  508 
  509         qdflags[unit].duart_imask = 0;  /* init shadow variables */
  510 
  511         /*
  512          * init the QDSS  
  513          */
  514    
  515         *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
  516 
  517         cursor[unit].x = 0;
  518         cursor[unit].y = 0;
  519         init_shared(unit);              /* init shared memory */
  520         setup_dragon(unit);             /* init the ADDER/VIPER stuff */
  521         clear_qd_screen(unit);          /* clear the screen */
  522         ldfont(unit);                   /* load the console font */
  523         ldcursor(unit, cons_cursor);    /* load default cursor map */
  524         setup_input(unit);              /* init the DUART */
  525 
  526         /* Set flag so probe knows */
  527         qd0cninited = 1;
  528 } /* qdcninit */
  529 
  530 /* see <sys/device.h> */
  531 CFATTACH_DECL(qd, sizeof(struct qd_softc),
  532     qd_match, qd_attach, NULL, NULL);
  533 
  534 #define QD_RCSR(reg) \
  535         bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
  536 #define QD_WCSR(reg, val) \
  537         bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
  538  
  539 /*
  540  *  Configure QDSS into Q memory and make it intrpt.
  541  *
  542  *  side effects: QDSS gets mapped into Qbus memory space at the first
  543  *               vacant 64kb boundary counting back from the top of
  544  *               Qbus memory space (qvmem+4mb)
  545  *
  546  *  return: QDSS bus request level and vector address returned in
  547  *         registers by UNIX convention.
  548  *
  549  */
  550 static int
  551 qd_match(parent, match, aux)
  552         struct device *parent;
  553         struct cfdata *match;
  554         void *aux;
  555 {
  556         struct qd_softc ssc;
  557         struct qd_softc *sc = &ssc;
  558         struct uba_attach_args *ua = aux;
  559         struct uba_softc *uh = (void *)parent;
  560         int unit;
  561         volatile struct dga *dga;       /* pointer to gate array structure */
  562         int vector;
  563 #ifdef notdef
  564         int *ptep;                      /* page table entry pointer */
  565         caddr_t phys_adr;               /* physical QDSS base adrs */
  566         u_int mapix;
  567 #endif
  568 
  569         /* Create a "fake" softc with only a few fields used. */
  570         sc->sc_iot = ua->ua_iot;
  571         sc->sc_ioh = ua->ua_ioh;
  572         sc->sc_dmat = ua->ua_dmat;
  573         /*
  574          * calculate board unit number from I/O page register address  
  575          */
  576         unit = (int) (((int)sc->sc_ioh >> 1) & 0x0007);
  577 
  578         /*
  579          * QDSS regs must be mapped to Qbus memory space at a 64kb
  580          * physical boundary.  The Qbus memory space is mapped into
  581          * the system memory space at config time.  After config
  582          * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
  583          * of the start of Qbus memory.   The Qbus memory page table
  584          * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
  585          * which is also loaded at config time.   These are the
  586          * variables used below to find a vacant 64kb boundary in
  587          * Qbus memory, and load it's corresponding physical adrs
  588          * into the QDSS's I/O page CSR.  
  589          */
  590 
  591         /*
  592          * Only if QD is the graphics device.
  593          */
  594 
  595         /* if this QDSS is NOT the console, then do init here.. */
  596 
  597         if (unit != 0) {
  598                 printf("qd: can't support two qdss's (yet)\n");
  599 #ifdef notdef   /* can't test */
  600                 if (v_consputc != qdputc  ||  unit != 0) {
  601 
  602                         /*
  603                         * read QDSS config info 
  604                         */
  605                         qdflags[unit].config = *(u_short *)reg;
  606 
  607                         /*
  608                         * find an empty 64kb adrs boundary 
  609                         */
  610 
  611                         qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
  612 
  613                         /*
  614                         * find the cpusw entry that matches this machine. 
  615                         */
  616                         cpup = &cpusw[cpu];
  617                         while (!(BADADDR(qdbase[unit], sizeof(short))))
  618                                 qdbase[unit] -= CHUNK;
  619 
  620                         /*
  621                         * tell QDSS which Q memory address base to decode 
  622                         */
  623                         mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
  624                         ptep = (int *) QVmap[0] + mapix;
  625                         phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<VAX_PGSHIFT);
  626                         *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
  627 
  628                         /*
  629                         * load QDSS adrs map with system addresses 
  630                         * of device regs 
  631                         */
  632                         qdmap[unit].template = qdbase[unit] + TMPSTART;
  633                         qdmap[unit].adder = qdbase[unit] + ADDER;
  634                         qdmap[unit].dga = qdbase[unit] + DGA;
  635                         qdmap[unit].duart = qdbase[unit] + DUART;
  636                         qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
  637                         qdmap[unit].red = qdbase[unit] + RED;
  638                         qdmap[unit].blue = qdbase[unit] + BLUE;
  639                         qdmap[unit].green = qdbase[unit] + GREEN;
  640 
  641                         /* device init */
  642 
  643                         cursor[unit].x = 0;
  644                         cursor[unit].y = 0;
  645                         init_shared(unit);              /* init shared memory */
  646                         setup_dragon(unit);     /* init the ADDER/VIPER stuff */
  647                         ldcursor(unit, cons_cursor);    /* load default cursor map */
  648                         setup_input(unit);              /* init the DUART */
  649                         clear_qd_screen(unit);
  650                         ldfont(unit);                   /* load the console font */
  651 
  652                         /* once only: turn on sync */
  653 
  654                         *(short *)qdmap[unit].memcsr |= SYNC_ON;
  655                 }
  656 #endif /*notdef*/
  657         } else {
  658                 /* We are dealing with qd0 */
  659                  
  660                 if (!qd0cninited) {
  661                         /* 
  662                          * qd0 has not been initiallized as the console.
  663                          * We need to do some initialization now
  664                          * 
  665                          * XXX 
  666                          * However, if the QDSS is not the console then
  667                          * that stupid undocumented bit (see qdcnprobe)
  668                          * is cleared.  Then the QDSS refuses to work.
  669                          * (What did the ROM do to it!?)
  670                          * XXX
  671                          */
  672                          return 0;
  673                    
  674 #if 0              
  675                          qdaddr = (void *)reg;
  676 
  677                          /* Lame probe for QDSS.  Should be ok for qd0 */
  678                          if (badaddr((caddr_t)qdaddr, sizeof(short)))
  679                                  return 0;
  680 
  681                          qdcninit(NULL);
  682 #endif             
  683                 }
  684         }
  685            
  686 
  687         /*
  688         * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
  689         * (ADDER) and xx8 (DUART).  Therefore, we take three
  690         * vectors from the vector pool, and then continue
  691         * to take them until we get a xx0 HEX vector.  The
  692         * pool provides vectors in contiguous decending
  693         * order.  
  694         */
  695 
  696         vector = (uh->uh_lastiv -= 4*3);        /* take three vectors */
  697 
  698         while (vector & 0x0F) {            /* if lo nibble != 0.. */
  699                 /* ..take another vector */
  700                 vector = (uh->uh_lastiv -= 4);  
  701         }
  702 
  703         /*
  704         * setup DGA to do a DMA interrupt (transfer count = 0)  
  705         */
  706         dga = (struct dga *) qdmap[unit].dga;
  707         dga->csr = (short) HALT;        /* disable everything */
  708         dga->ivr = (short) vector;      /* load intrpt base vector */
  709         dga->bytcnt_lo = (short) 0;     /* DMA xfer count = 0 */
  710         dga->bytcnt_hi = (short) 0;
  711 
  712         /* 
  713         * turn on DMA interrupts 
  714         */
  715         dga->csr &= ~SET_DONE_FIFO;
  716         dga->csr |= DMA_IE | DL_ENB;
  717 
  718         DELAY(20000);                   /* wait for the intrpt */
  719         dga->csr = HALT;                /* stop the wheels */
  720 
  721         /*
  722         * score this as an existing qdss
  723         */
  724         qdcount++;
  725 
  726         return 1;
  727 } /* qdprobe */
  728 
  729 
  730 void qd_attach(parent, self, aux)
  731            struct device *parent, *self;
  732            void *aux;
  733      {
  734         struct uba_attach_args *ua = aux;
  735         int unit;       /* QDSS module # for this call */
  736 
  737         printf("\n");
  738         
  739         unit = self->dv_unit;           /* get QDSS number */
  740 
  741         /* Set interrupt vectors for interrupt handlers */      
  742    
  743         uba_intr_establish(ua->ua_icookie, ua->ua_cvec    , qddint, self);
  744         uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, qdaint, self);
  745         uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 8, qdiint, self);
  746 
  747         /*
  748         * init "qdflags[]" for this QDSS 
  749         */
  750         qdflags[unit].inuse = 0;        /* init inuse variable EARLY! */
  751         qdflags[unit].mapped = 0;
  752         qdflags[unit].kernel_loop = -1;
  753         qdflags[unit].user_dma = 0;
  754         qdflags[unit].curs_acc = ACC_OFF;
  755         qdflags[unit].curs_thr = 128;
  756         qdflags[unit].tab_res = 2;      /* default tablet resolution factor */
  757         qdflags[unit].duart_imask = 0;  /* init shadow variables */
  758         qdflags[unit].adder_ie = 0;
  759 
  760         /*
  761         * init structures used in kbd/mouse interrupt service.  This code must
  762         * come after the "init_shared()" routine has run since that routine 
  763         * inits the eq_header[unit] structure used here.   
  764         */
  765 
  766         /*
  767         * init the "latest mouse report" structure 
  768         */
  769         last_rep[unit].state = 0;
  770         last_rep[unit].dx = 0;
  771         last_rep[unit].dy = 0;
  772         last_rep[unit].bytcnt = 0;
  773 
  774         /*
  775         * init the event queue (except mouse position) 
  776         */
  777         eq_header[unit]->header.events = 
  778             (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
  779 
  780         eq_header[unit]->header.size = MAXEVENTS;
  781         eq_header[unit]->header.head = 0;
  782         eq_header[unit]->header.tail = 0;
  783 
  784         /*
  785          * open exclusive for graphics device.
  786          */
  787         qdopened[unit] = 0;
  788 
  789 } /* qdattach */
  790 
  791    
  792 /*ARGSUSED*/
  793 int
  794 qdopen(dev, flag, mode, p)
  795         dev_t dev;
  796         int flag, mode;
  797         struct proc *p;
  798 {
  799         volatile struct dga *dga;       /* ptr to gate array struct */
  800         struct tty *tp;
  801         volatile struct duart *duart;
  802         int unit;
  803         int minor_dev;
  804 
  805         minor_dev = minor(dev); /* get QDSS minor device number */
  806         unit = minor_dev >> 2;
  807 
  808         /*
  809         * check for illegal conditions  
  810         */
  811         if (unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[unit] == NULL)
  812                 return (ENXIO);         /* no such device or address */
  813 
  814         duart = (struct duart *) qdmap[unit].duart;
  815         dga = (struct dga *) qdmap[unit].dga;
  816 
  817         if ((minor_dev & 0x03) == 2) {
  818                 /*
  819                 * this is the graphic device... 
  820                 */
  821                 if (qdopened[unit] != 0)
  822                         return(EBUSY);
  823                 else
  824                         qdopened[unit] = 1;
  825                 qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
  826                 /*
  827                  * enble kbd & mouse intrpts in DUART mask reg 
  828                  */
  829                 qdflags[unit].duart_imask |= 0x22;
  830                 duart->imask = qdflags[unit].duart_imask;
  831         } else {
  832                /* Only one console */
  833                if (minor_dev) return ENXIO;
  834            
  835                /* If not done already, allocate tty structure */
  836                if (qd_tty[minor_dev] == NULL)
  837                        qd_tty[minor_dev] = ttymalloc();
  838               
  839                if (qd_tty[minor_dev] == NULL)
  840                        return ENXIO;
  841            
  842                /*
  843                 * this is the console 
  844                 */
  845                 qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
  846                 dga->csr |= CURS_ENB;
  847                 qdflags[unit].duart_imask |= 0x02;
  848                 duart->imask = qdflags[unit].duart_imask;
  849                 /*
  850                 * some setup for tty handling 
  851                 */
  852                 tp = qd_tty[minor_dev];
  853                 /* tp->t_addr = ui->ui_addr; */
  854                 tp->t_oproc = qdstart;
  855                 tp->t_dev = dev;
  856                 if ((tp->t_state & TS_ISOPEN) == 0) {
  857                         ttychars(tp);
  858                         tp->t_ispeed = B9600;
  859                         tp->t_ospeed = B9600;
  860                         tp->t_state = TS_ISOPEN | TS_CARR_ON;
  861                         tp->t_iflag = TTYDEF_IFLAG;
  862                         tp->t_oflag = TTYDEF_OFLAG;
  863                         tp->t_lflag = TTYDEF_LFLAG;
  864                         tp->t_cflag = TTYDEF_CFLAG;
  865                         ttsetwater(tp);
  866                 }
  867                 /*
  868                 * enable intrpts, open line discipline 
  869                 */
  870                 dga->csr |= GLOBAL_IE;  /* turn on the interrupts */
  871                 return ((*tp->t_linesw->l_open)(dev, tp));
  872         }
  873         dga->csr |= GLOBAL_IE;  /* turn on the interrupts */
  874         return(0);
  875 
  876 } /* qdopen */
  877 
  878 /*ARGSUSED*/
  879 int
  880 qdclose(dev, flag, mode, p)
  881         dev_t dev;
  882         int flag, mode;
  883         struct proc *p;
  884 {
  885         struct tty *tp;
  886         struct qdmap *qd;
  887         volatile int *ptep;
  888         volatile struct dga *dga;       /* gate array register map pointer */
  889         volatile struct duart *duart;
  890         volatile struct adder *adder;
  891         int unit;
  892         int minor_dev;
  893         u_int mapix;
  894         int i;                          /* SIGNED index */
  895         struct uba_softc *uh;
  896    
  897         minor_dev = minor(dev);         /* get minor device number */
  898         unit = minor_dev >> 2;          /* get QDSS number */
  899         qd = &qdmap[unit];
  900 
  901         uh = (struct uba_softc *)
  902              (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
  903 
  904    
  905         if ((minor_dev & 0x03) == 2) {
  906                 /*
  907                 * this is the graphic device... 
  908                 */
  909                 if (qdopened[unit] != 1)
  910                         return(EBUSY);
  911                 else
  912                         qdopened[unit] = 0;     /* allow it to be re-opened */
  913                 /*
  914                 * re-protect device memory 
  915                 */
  916                 if (qdflags[unit].mapped & MAPDEV) {
  917                         /*
  918                         * TEMPLATE RAM 
  919                         */
  920                         mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
  921                         ptep = (int *)(QVmap[0] + mapix);
  922                         for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++)
  923                                 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
  924                         /*
  925                         * ADDER 
  926                         */
  927                         mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
  928                         ptep = (int *)(QVmap[0] + mapix);
  929                         for (i = 0; i < vax_btop(REGSIZE); i++, ptep++)
  930                                 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
  931                         /*
  932                         * COLOR MAPS 
  933                         */
  934                         mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
  935                         ptep = (int *)(QVmap[0] + mapix);
  936                         for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
  937                                 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
  938                 }
  939 
  940                 /*
  941                 * re-protect DMA buffer and free the map registers 
  942                 */
  943                 if (qdflags[unit].mapped & MAPDMA) {
  944                         panic("Unmapping unmapped buffer");
  945 #ifdef notyet
  946 /*
  947  * Ragge 990620:
  948  * Can't happen because the buffer can't be mapped.
  949  */
  950                         dga = (struct dga *) qdmap[unit].dga;
  951                         adder = (struct adder *) qdmap[unit].adder;
  952                         dga->csr &= ~DMA_IE;
  953                         dga->csr &= ~0x0600;         /* kill DMA */
  954                         adder->command = CANCEL;
  955                         /* 
  956                          * if DMA was running, flush spurious intrpt 
  957                          */
  958                         if (dga->bytcnt_lo != 0) {
  959                                 dga->bytcnt_lo = 0;
  960                                 dga->bytcnt_hi = 0;
  961                                 DMA_SETIGNORE(DMAheader[unit]);
  962                                 dga->csr |= DMA_IE;
  963                                 dga->csr &= ~DMA_IE;
  964                         }
  965                         ptep = (int *)
  966                            ((VTOP(DMAheader[unit]*4)) + (mfpr(PR_SBR)|0x80000000));
  967                         for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
  968                                 *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
  969                         ubarelse(uh, &Qbus_unmap[unit]);
  970 #endif
  971                 }
  972 
  973                 /*
  974                 * re-protect 1K (2 pages) event queue 
  975                 */
  976                 if (qdflags[unit].mapped & MAPEQ) {
  977                         ptep = (int *)
  978                            ((VTOP(eq_header[unit])*4) + (mfpr(PR_SBR)|0x80000000));
  979                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
  980                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
  981                 }
  982                 /*
  983                 * re-protect scroll param area and disable scroll intrpts  
  984                 */
  985                 if (qdflags[unit].mapped & MAPSCR) {
  986                         ptep = (int *) ((VTOP(scroll[unit]) * 4)
  987                                 + (mfpr(PR_SBR) | 0x80000000));
  988                         /*
  989                          * re-protect 512 scroll param area 
  990                          */
  991                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
  992                         adder = (struct adder *) qdmap[unit].adder;
  993                         qdflags[unit].adder_ie &= ~FRAME_SYNC;
  994                         adder->interrupt_enable = qdflags[unit].adder_ie;
  995                 }
  996                 /*
  997                 * re-protect color map write buffer area and kill intrpts 
  998                 */
  999                 if (qdflags[unit].mapped & MAPCOLOR) {
 1000                         ptep = (int *) ((VTOP(color_buf[unit]) * 4)
 1001                                 + (mfpr(PR_SBR) | 0x80000000));
 1002                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
 1003                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
 1004                         color_buf[unit]->status = 0;
 1005                         adder = (struct adder *) qdmap[unit].adder;
 1006                         qdflags[unit].adder_ie &= ~VSYNC;
 1007                         adder->interrupt_enable = qdflags[unit].adder_ie;
 1008                 }
 1009                 mtpr(0, PR_TBIA);               
 1010                 /* flag everything now unmapped */
 1011                 qdflags[unit].mapped = 0;   
 1012                 qdflags[unit].inuse &= ~GRAPHIC_DEV;
 1013                 qdflags[unit].curs_acc = ACC_OFF;
 1014                 qdflags[unit].curs_thr = 128;
 1015                 /*
 1016                 * restore the console 
 1017                 */
 1018                 dga = (struct dga *) qdmap[unit].dga;
 1019                 adder = (struct adder *) qdmap[unit].adder;
 1020                 dga->csr &= ~DMA_IE;
 1021                 dga->csr &= ~0x0600;    /* halt the DMA! (just in case...) */
 1022                 dga->csr |= DMA_ERR;    /* clear error condition */
 1023                 adder->command = CANCEL;
 1024                 /*
 1025                  * if DMA was running, flush spurious intrpt 
 1026                  */
 1027                 if (dga->bytcnt_lo != 0) {
 1028                         dga->bytcnt_lo = 0;
 1029                         dga->bytcnt_hi = 0;
 1030                         DMA_SETIGNORE(DMAheader[unit]);
 1031                         dga->csr |= DMA_IE;
 1032                         dga->csr &= ~DMA_IE;
 1033                 }
 1034                 init_shared(unit);              /* init shared memory */
 1035                 setup_dragon(unit);             /* init ADDER/VIPER */
 1036                 ldcursor(unit, cons_cursor);    /* load default cursor map */
 1037                 setup_input(unit);              /* init the DUART */
 1038                 ldfont(unit);
 1039                 cursor[unit].x = 0;
 1040                 cursor[unit].y = 0;
 1041                 /*
 1042                  * shut off the mouse rcv intrpt and turn on kbd intrpts 
 1043                  */
 1044                 duart = (struct duart *) qdmap[unit].duart;
 1045                 qdflags[unit].duart_imask &= ~(0x20);
 1046                 qdflags[unit].duart_imask |= 0x02;
 1047                 duart->imask = qdflags[unit].duart_imask;
 1048                 /*
 1049                 * shut off interrupts if all is closed  
 1050                 */
 1051                 if (!(qdflags[unit].inuse & CONS_DEV)) {
 1052                         dga = (struct dga *) qdmap[unit].dga;
 1053                         dga->csr &= ~(GLOBAL_IE | DMA_IE);
 1054                 }
 1055         } else {
 1056                 /*
 1057                 * this is the console 
 1058                 */
 1059                 tp = qd_tty[minor_dev];
 1060                 (*tp->t_linesw->l_close)(tp, flag);
 1061                 ttyclose(tp);
 1062                 tp->t_state = 0;
 1063                 qdflags[unit].inuse &= ~CONS_DEV;
 1064                 /*
 1065                 * if graphics device is closed, kill interrupts 
 1066                 */
 1067                 if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
 1068                         dga = (struct dga *) qdmap[unit].dga;
 1069                         dga->csr &= ~(GLOBAL_IE | DMA_IE);
 1070                 }
 1071         }
 1072 
 1073         return(0);
 1074 
 1075 } /* qdclose */
 1076 
 1077 int
 1078 qdioctl(dev, cmd, datap, flags, p)
 1079         dev_t dev;
 1080         u_long cmd;
 1081         caddr_t datap;
 1082         int flags;
 1083         struct proc *p;
 1084 {
 1085         volatile int *ptep;     /* page table entry pointer */
 1086         int mapix;              /* QVmap[] page table index */
 1087         struct _vs_event *event;
 1088         struct tty *tp;
 1089         int i;
 1090         struct qdmap *qd;               /* pointer to device map struct */
 1091         volatile struct dga *dga;       /* Gate Array reg structure pntr */
 1092         volatile struct duart *duart;   /* DUART reg structure pointer */
 1093         volatile struct adder *adder;   /* ADDER reg structure pointer */
 1094         struct prgkbd *cmdbuf;
 1095         struct prg_cursor *curs;
 1096         struct _vs_cursor *pos;
 1097         int unit = minor(dev) >> 2;     /* number of caller's QDSS */
 1098         u_int minor_dev = minor(dev);
 1099         int error;
 1100         int s;
 1101         short *temp;                    /* a pointer to template RAM */
 1102         struct uba_softc *uh;
 1103 
 1104         uh = (struct uba_softc *)
 1105              (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
 1106 
 1107         /*
 1108         * service graphic device ioctl commands 
 1109         */
 1110         switch (cmd) {
 1111 
 1112         case QD_GETEVENT:
 1113                 /*
 1114                 * extract the oldest event from the event queue 
 1115                 */
 1116                 if (ISEMPTY(eq_header[unit])) {
 1117                         event = (struct _vs_event *) datap;
 1118                         event->vse_device = VSE_NULL;
 1119                         break;
 1120                 }
 1121                 event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
 1122                 s = spl5();
 1123                 GETEND(eq_header[unit]);
 1124                 splx(s);
 1125                 bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
 1126                 break;
 1127 
 1128         case QD_RESET:
 1129                 /*
 1130                 * init the dragon stuff, DUART, and driver variables  
 1131                 */
 1132                 init_shared(unit);              /* init shared memory */
 1133                 setup_dragon(unit);           /* init the ADDER/VIPER stuff */
 1134                 clear_qd_screen(unit);
 1135                 ldcursor(unit, cons_cursor);    /* load default cursor map */
 1136                 ldfont(unit);                   /* load the console font */
 1137                 setup_input(unit);              /* init the DUART */
 1138                 break;
 1139 
 1140         case QD_SET:
 1141                 /*
 1142                 * init the DUART and driver variables  
 1143                 */
 1144                 init_shared(unit);
 1145                 setup_input(unit);
 1146                 break;
 1147 
 1148         case QD_CLRSCRN:
 1149                 /*
 1150                 * clear the QDSS screen.  (NOTE that this reinits the dragon) 
 1151                 */
 1152 #ifdef notdef   /* has caused problems and isn't necessary */
 1153                 setup_dragon(unit);
 1154                 clear_qd_screen(unit);
 1155 #endif
 1156                 break;
 1157 
 1158         case QD_WTCURSOR:
 1159                 /*
 1160                 * load a cursor into template RAM  
 1161                 */
 1162                 ldcursor(unit, (short *)datap);
 1163                 break;
 1164 
 1165         case QD_RDCURSOR:
 1166 
 1167                 temp = (short *) qdmap[unit].template;
 1168                 /*
 1169                  * cursor is 32 WORDS from the end of the 8k WORD...
 1170                  *  ...template space 
 1171                  */
 1172                 temp += (8 * 1024) - 32;
 1173                 for (i = 0; i < 32; ++i, datap += sizeof(short))
 1174                         *(short *)datap = *temp++;
 1175                 break;
 1176 
 1177         case QD_POSCURSOR:
 1178                 /*
 1179                 * position the mouse cursor  
 1180                 */
 1181                 dga = (struct dga *) qdmap[unit].dga;
 1182                 pos = (struct _vs_cursor *) datap;
 1183                 s = spl5();
 1184                 dga->x_cursor = TRANX(pos->x);
 1185                 dga->y_cursor = TRANY(pos->y);
 1186                 eq_header[unit]->curs_pos.x = pos->x;
 1187                 eq_header[unit]->curs_pos.y = pos->y;
 1188                 splx(s);
 1189                 break;
 1190 
 1191         case QD_PRGCURSOR:
 1192                 /*
 1193                 * set the cursor acceleration factor 
 1194                 */
 1195                 curs = (struct prg_cursor *) datap;
 1196                 s = spl5();
 1197                 qdflags[unit].curs_acc = curs->acc_factor;
 1198                 qdflags[unit].curs_thr = curs->threshold;
 1199                 splx(s);
 1200                 break;
 1201 
 1202         case QD_MAPDEVICE:
 1203                /*
 1204                 * enable 'user write' to device pages 
 1205                 */
 1206                 qdflags[unit].mapped |= MAPDEV;
 1207                 qd = (struct qdmap *) &qdmap[unit];
 1208                 /*
 1209                 * enable user write to template RAM 
 1210                 */
 1211                 mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
 1212                 ptep = (int *)(QVmap[0] + mapix);
 1213                 for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++)
 1214                         *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
 1215 
 1216                /*
 1217                 * enable user write to registers 
 1218                 */
 1219                 mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
 1220                 ptep = (int *)(QVmap[0] + mapix);
 1221                 for (i = 0; i < vax_btop(REGSIZE); i++, ptep++)
 1222                         *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
 1223 
 1224                 /*
 1225                 * enable user write to color maps 
 1226                 */
 1227                 mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
 1228                 ptep = (int *)(QVmap[0] + mapix);
 1229                 for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
 1230                         *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
 1231 
 1232                /*
 1233                 * enable user write to DUART 
 1234                 */
 1235                 mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
 1236                 ptep = (int *)(QVmap[0] + mapix);
 1237                 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; /* duart page */
 1238 
 1239                 mtpr(0, PR_TBIA);               /* invalidate translation buffer */
 1240 
 1241                 /*
 1242                  * stuff qdmap structure in return buffer 
 1243                  */
 1244                 bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
 1245 
 1246                 break;
 1247 
 1248 #ifdef notyet
 1249 /*
 1250  * Ragge 999620:
 1251  * Can't map in the graphic buffer into user space for now.
 1252  * The best way to fix this is to convert this driver to wscons.
 1253  */
 1254         case QD_MAPIOBUF:
 1255                 /*
 1256                  * do setup for DMA by user process     
 1257                  *
 1258                  * set 'user write enable' bits for DMA buffer  
 1259                  */
 1260                 qdflags[unit].mapped |= MAPDMA;
 1261                 ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
 1262                         + (mfpr(PR_SBR) | 0x80000000));
 1263                 for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
 1264                         *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
 1265                 mtpr(0, PR_TBIA);       /* invalidate translation buffer */
 1266                 /*
 1267                 * set up QBUS map registers for DMA 
 1268                 */
 1269                 DMAheader[unit]->QBAreg =
 1270                     uballoc(uh, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
 1271                 if (DMAheader[unit]->QBAreg == 0)
 1272                     printf("qd%d: qdioctl: QBA setup error\n", unit);
 1273                 Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
 1274                 DMAheader[unit]->QBAreg &= 0x3FFFF;
 1275                 /*
 1276                 * return I/O buf adr 
 1277                 */
 1278                 *(int *)datap = (int) DMAheader[unit];
 1279                 break;
 1280 #endif
 1281 
 1282         case QD_MAPSCROLL:
 1283                 /*
 1284                 * map the shared scroll param area and enable scroll interpts  
 1285                 */
 1286                 qdflags[unit].mapped |= MAPSCR;
 1287                 ptep = (int *) ((VTOP(scroll[unit]) * 4)
 1288                         + (mfpr(PR_SBR) | 0x80000000));
 1289                 /*
 1290                  * allow user write to scroll area 
 1291                  */
 1292                 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
 1293                 mtpr(0, PR_TBIA);                       /* invalidate translation buf */
 1294                 scroll[unit]->status = 0;
 1295                 adder = (struct adder *) qdmap[unit].adder;
 1296                 qdflags[unit].adder_ie |= FRAME_SYNC;
 1297                 adder->interrupt_enable = qdflags[unit].adder_ie;
 1298                 *(int *)datap = (int) scroll[unit]; /* return scroll area */
 1299                 break;
 1300 
 1301         case QD_UNMAPSCROLL:
 1302                 /*
 1303                 * unmap shared scroll param area and disable scroll intrpts 
 1304                 */
 1305                 if (qdflags[unit].mapped & MAPSCR) {
 1306                         qdflags[unit].mapped &= ~MAPSCR;
 1307                         ptep = (int *) ((VTOP(scroll[unit]) * 4)
 1308                                 + (mfpr(PR_SBR) | 0x80000000));
 1309                         /*
 1310                          * re-protect 512 scroll param area 
 1311                          */
 1312                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
 1313                         mtpr(0, PR_TBIA);       /* smash CPU's translation buf */
 1314                         adder = (struct adder *) qdmap[unit].adder;
 1315                         qdflags[unit].adder_ie &= ~FRAME_SYNC;
 1316                         adder->interrupt_enable = qdflags[unit].adder_ie;
 1317                 }
 1318                 break;
 1319 
 1320         case QD_MAPCOLOR:
 1321                 /*
 1322                 * map shared color map write buf and turn on vsync intrpt 
 1323                 */
 1324                 qdflags[unit].mapped |= MAPCOLOR;
 1325                 ptep = (int *) ((VTOP(color_buf[unit]) * 4)
 1326                         + (mfpr(PR_SBR) | 0x80000000));
 1327                 /*
 1328                  * allow user write to color map write buffer 
 1329                  */
 1330                 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
 1331                 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
 1332                 mtpr(0, PR_TBIA);                       /* clr CPU translation buf */
 1333                 adder = (struct adder *) qdmap[unit].adder;
 1334                 qdflags[unit].adder_ie |= VSYNC;
 1335                 adder->interrupt_enable = qdflags[unit].adder_ie;
 1336                 /*
 1337                  * return color area address 
 1338                  */
 1339                 *(int *)datap = (int) color_buf[unit];
 1340                 break;
 1341 
 1342         case QD_UNMAPCOLOR:
 1343                 /*
 1344                  * unmap shared color map write buffer and kill VSYNC intrpts 
 1345                  */
 1346                 if (qdflags[unit].mapped & MAPCOLOR) {
 1347                         qdflags[unit].mapped &= ~MAPCOLOR;
 1348                         ptep = (int *) ((VTOP(color_buf[unit]) * 4)
 1349                                 + (mfpr(PR_SBR) | 0x80000000));
 1350                         /*
 1351                          * re-protect color map write buffer 
 1352                          */
 1353                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
 1354                         *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
 1355                         mtpr(0, PR_TBIA);
 1356                         adder = (struct adder *) qdmap[unit].adder;
 1357                         qdflags[unit].adder_ie &= ~VSYNC;
 1358                         adder->interrupt_enable = qdflags[unit].adder_ie;
 1359                 }
 1360                 break;
 1361 
 1362         case QD_MAPEVENT:
 1363                 /*
 1364                 * give user write access to the event queue 
 1365                 */
 1366                 qdflags[unit].mapped |= MAPEQ;
 1367                 ptep = (int *) ((VTOP(eq_header[unit]) * 4)
 1368                         + (mfpr(PR_SBR) | 0x80000000));
 1369                 /*
 1370                  * allow user write to 1K event queue 
 1371                  */
 1372                 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
 1373                 *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
 1374                 mtpr(0, PR_TBIA);                       /* clr CPU translation buf */
 1375                 /*
 1376                  * return event queue address 
 1377                  */
 1378                 *(int *)datap = (int)eq_header[unit];
 1379                 break;
 1380 
 1381         case QD_PRGKBD:
 1382                 /*
 1383                 * pass caller's programming commands to LK201 
 1384                 */
 1385                 duart = (struct duart *)qdmap[unit].duart;
 1386                 cmdbuf = (struct prgkbd *)datap;    /* pnt to kbd cmd buf */
 1387                 /*
 1388                 * send command 
 1389                 */
 1390                 for (i = 1000; i > 0; --i) {
 1391                         if (duart->statusA&XMT_RDY) {
 1392                                 duart->dataA = cmdbuf->cmd;
 1393                                 break;
 1394                         }
 1395                 }
 1396                 if (i == 0) {
 1397                         printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
 1398                         break;
 1399                 }
 1400                 /*
 1401                 * send param1? 
 1402                 */
 1403                 if (cmdbuf->cmd & LAST_PARAM)
 1404                         break;
 1405                 for (i = 1000; i > 0; --i) {
 1406                         if (duart->statusA&XMT_RDY) {
 1407                                 duart->dataA = cmdbuf->param1;
 1408                                 break;
 1409                         }
 1410                 }
 1411                 if (i == 0) {
 1412                         printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
 1413                         break;
 1414                 }
 1415                 /*
 1416                 * send param2? 
 1417                 */
 1418                 if (cmdbuf->param1 & LAST_PARAM)
 1419                     break;
 1420                 for (i = 1000; i > 0; --i) {
 1421                         if (duart->statusA&XMT_RDY) {
 1422                                 duart->dataA = cmdbuf->param2;
 1423                                 break;
 1424                         }
 1425                 }
 1426                 if (i == 0) {
 1427                         printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
 1428                         break;
 1429                 }
 1430                 break;
 1431 
 1432         case QD_PRGMOUSE:
 1433                 /*
 1434                 * pass caller's programming commands to the mouse  
 1435                 */
 1436                 duart = (struct duart *) qdmap[unit].duart;
 1437                 for (i = 1000; i > 0; --i) {
 1438                         if (duart->statusB&XMT_RDY) {
 1439                                 duart->dataB = *datap;
 1440                                 break;
 1441                         }
 1442                 }
 1443                 if (i == 0) {
 1444                         printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
 1445                 }
 1446                 break;
 1447 
 1448         case QD_RDCONFIG:
 1449                 /*
 1450                 * get QDSS configuration word and return it  
 1451                 */
 1452                 *(short *)datap = qdflags[unit].config;
 1453                 break;
 1454 
 1455         case QD_KERN_LOOP:
 1456         case QD_KERN_UNLOOP:
 1457                 /*
 1458                  * vestige from ultrix.  BSD uses TIOCCONS to redirect
 1459                  * kernel console output.
 1460                  */
 1461                 break;
 1462 
 1463         case QD_PRGTABLET:
 1464                 /*
 1465                 * program the tablet 
 1466                 */
 1467                 duart = (struct duart *) qdmap[unit].duart;
 1468                 for (i = 1000; i > 0; --i) {
 1469                         if (duart->statusB&XMT_RDY) {
 1470                                 duart->dataB = *datap;
 1471                                 break;
 1472                         }
 1473                 }
 1474                 if (i == 0) {
 1475                         printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
 1476                 }
 1477                 break;
 1478 
 1479         case QD_PRGTABRES:
 1480                 /*
 1481                 * program the tablet report resolution factor 
 1482                 */
 1483                 qdflags[unit].tab_res = *(short *)datap;
 1484                 break;
 1485 
 1486         default:
 1487                 /*
 1488                 * service tty ioctl's  
 1489                 */
 1490                 if (!(minor_dev & 0x02)) {
 1491                         tp = qd_tty[minor_dev];
 1492                         error = 
 1493                            
 1494                    (*tp->t_linesw->l_ioctl)(tp, cmd, datap, flags, p);
 1495                         if (error != EPASSTHROUGH) {
 1496                                 return(error);
 1497                         }
 1498                         return ttioctl(tp, cmd, datap, flags, p);
 1499                 }
 1500                 break;
 1501         }
 1502 
 1503         return(0);
 1504 
 1505 } /* qdioctl */
 1506 
 1507 
 1508 int
 1509 qdpoll(dev, events, p)
 1510         dev_t dev;
 1511         int events;
 1512         struct proc *p;
 1513 {
 1514         int s;
 1515         int unit;
 1516         struct tty *tp;
 1517         u_int minor_dev = minor(dev);
 1518         int revents = 0;
 1519 
 1520         s = spl5();
 1521         unit = minor_dev >> 2;
 1522 
 1523         if ((minor_dev & 0x03) == 2)  {
 1524                 /* 
 1525                  * This is a graphics device, so check for events.
 1526                  */
 1527 
 1528                 if (events & (POLLIN | POLLRDNORM))
 1529                         if(!(ISEMPTY(eq_header[unit])))
 1530                                 revents |= events & (POLLIN | POLLRDNORM);
 1531                            
 1532                 if (events & (POLLOUT | POLLWRNORM))
 1533                         if (DMA_ISEMPTY(DMAheader[unit]))
 1534                                 revents |= events & (POLLOUT | POLLWRNORM);
 1535            
 1536                 if (revents == 0)  {
 1537                         if (events & (POLLIN | POLLRDNORM))
 1538                                 selrecord(p, &qdrsel[unit]);
 1539 
 1540                         if (events & (POLLOUT | POLLWRNORM))
 1541                                 selrecord(p, &qdrsel[unit]);
 1542                 }
 1543         } else  {
 1544                 /*
 1545                 * this is a tty device
 1546                 */
 1547                 tp = qd_tty[minor_dev];
 1548                 revents = (*tp->t_linesw->l_poll)(tp, events, p);
 1549         }
 1550            
 1551         splx(s);
 1552         return (revents);
 1553 } /* qdpoll() */
 1554 
 1555 static void
 1556 filt_qdrdetach(struct knote *kn)
 1557 {
 1558         dev_t dev = (intptr_t) kn->kn_hook;
 1559         u_int minor_dev = minor(dev);
 1560         int unit = minor_dev >> 2;
 1561         int s;
 1562 
 1563         s = spl5();
 1564         SLIST_REMOVE(&qdrsel[unit].sel_klist, kn, knote, kn_selnext);
 1565         splx(s);
 1566 }
 1567 
 1568 static int
 1569 filt_qdread(struct knote *kn, long hint)
 1570 {
 1571         dev_t dev = (intptr_t) kn->kn_hook;
 1572         u_int minor_dev = minor(dev);
 1573         int unit = minor_dev >> 2;
 1574 
 1575         if (ISEMPTY(eq_header[unit]))
 1576                 return (0);
 1577 
 1578         kn->kn_data = 0;        /* XXXLUKEM (thorpej): what to put here? */
 1579         return (1);
 1580 }
 1581 
 1582 static int
 1583 filt_qdwrite(struct knote *kn, long hint)
 1584 {
 1585         dev_t dev = (intptr_t) kn->kn_hook;
 1586         u_int minor_dev = minor(dev);
 1587         int unit = minor_dev >> 2;
 1588 
 1589         if (! DMA_ISEMPTY(DMAheader[unit]))
 1590                 return (0);
 1591 
 1592         kn->kn_data = 0;        /* XXXLUKEM (thorpej): what to put here? */
 1593         return (1);
 1594 }
 1595 
 1596 static const struct filterops qdread_filtops =
 1597         { 1, NULL, filt_qdrdetach, filt_qdread };
 1598 
 1599 static const struct filterops qdwrite_filtops =
 1600         { 1, NULL, filt_qdrdetach, filt_qdwrite };
 1601 
 1602 int
 1603 qdkqfilter(dev_t dev, struct knote *kn)
 1604 {
 1605         struct klist *klist;
 1606         u_int minor_dev = minor(dev);
 1607         int s, unit = minor_dev >> 2;
 1608 
 1609         if ((minor_dev & 0x03) != 2) {
 1610                 /* TTY device. */
 1611                 return (ttykqfilter(dev, kn));
 1612         }
 1613 
 1614         switch (kn->kn_filter) {
 1615         case EVFILT_READ:
 1616                 klist = &qdrsel[unit].sel_klist;
 1617                 kn->kn_fop = &qdread_filtops;
 1618                 break;
 1619 
 1620         case EVFILT_WRITE:
 1621                 klist = &qdrsel[unit].sel_klist;
 1622                 kn->kn_fop = &qdwrite_filtops;
 1623                 break;
 1624 
 1625         default:
 1626                 return (1);
 1627         }
 1628 
 1629         kn->kn_hook = (void *)(intptr_t) dev;
 1630 
 1631         s = spl5();
 1632         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
 1633         splx(s);
 1634 
 1635         return (0);
 1636 }
 1637 
 1638 void qd_strategy(struct buf *bp);
 1639 
 1640 /*ARGSUSED*/
 1641 int
 1642 qdwrite(dev, uio, flag)
 1643         dev_t dev;
 1644         struct uio *uio;
 1645         int flag;
 1646 {
 1647         struct tty *tp;
 1648         int minor_dev;
 1649         int unit;
 1650 
 1651         minor_dev = minor(dev);
 1652         unit = (minor_dev >> 2) & 0x07;
 1653 
 1654         if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
 1655                /*
 1656                 * this is the console...  
 1657                 */
 1658                 tp = qd_tty[minor_dev];
 1659                 return ((*tp->t_linesw->l_write)(tp, uio, flag));
 1660         } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
 1661                /*
 1662                 * this is a DMA xfer from user space 
 1663                 */
 1664                 return (physio(qd_strategy, &qdbuf[unit],
 1665                 dev, B_WRITE, minphys, uio));
 1666         }
 1667         return (ENXIO);
 1668 }
 1669 
 1670 /*ARGSUSED*/
 1671 int
 1672 qdread(dev, uio, flag)
 1673         dev_t dev;
 1674         struct uio *uio;
 1675         int flag;
 1676 {
 1677         struct tty *tp;
 1678         int minor_dev;
 1679         int unit;
 1680 
 1681         minor_dev = minor(dev);
 1682         unit = (minor_dev >> 2) & 0x07;
 1683 
 1684         if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
 1685                /*
 1686                 * this is the console
 1687                 */
 1688                 tp = qd_tty[minor_dev];
 1689                 return ((*tp->t_linesw->l_read)(tp, uio, flag));
 1690         } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
 1691                /*
 1692                 * this is a bitmap-to-processor xfer 
 1693                 */
 1694                 return (physio(qd_strategy, &qdbuf[unit],
 1695                 dev, B_READ, minphys, uio));
 1696         }
 1697         return (ENXIO);
 1698 }
 1699 
 1700 /***************************************************************
 1701 *
 1702 *       qd_strategy()... strategy routine to do DMA
 1703 *
 1704 ***************************************************************/
 1705 
 1706 void
 1707 qd_strategy(bp)
 1708         struct buf *bp;
 1709 {
 1710         volatile struct dga *dga;
 1711         volatile struct adder *adder;
 1712         int unit;
 1713         int QBAreg;
 1714         int s;
 1715         int cookie;
 1716         struct uba_softc *uh;
 1717    
 1718         unit = (minor(bp->b_dev) >> 2) & 0x07;
 1719 
 1720         uh = (struct uba_softc *)
 1721              (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
 1722    
 1723         /*
 1724         * init pointers 
 1725         */
 1726         dga = (struct dga *) qdmap[unit].dga;
 1727 panic("qd_strategy");
 1728 #ifdef notyet
 1729         if ((QBAreg = ubasetup(uh, bp, 0)) == 0) {
 1730                 printf("qd%d: qd_strategy: QBA setup error\n", unit);
 1731                 goto STRAT_ERR;
 1732         }
 1733 #endif
 1734         s = spl5();
 1735         qdflags[unit].user_dma = -1;
 1736         dga->csr |= DMA_IE;
 1737         cookie = QBAreg & 0x3FFFF;
 1738         dga->adrs_lo = (short) cookie;
 1739         dga->adrs_hi = (short) (cookie >> 16);
 1740         dga->bytcnt_lo = (short) bp->b_bcount;
 1741         dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
 1742        
 1743         while (qdflags[unit].user_dma) {
 1744                 (void) tsleep(&qdflags[unit].user_dma, QSPRIOR,
 1745                     "qdstrat", 0);
 1746         }
 1747         splx(s);
 1748 #ifdef notyet
 1749         ubarelse(uh, &QBAreg);
 1750 #endif
 1751         if (!(dga->csr & DMA_ERR)) {
 1752                 biodone(bp);
 1753                 return;
 1754         }
 1755 
 1756 /* STRAT_ERR: */
 1757         adder = (struct adder *) qdmap[unit].adder;
 1758         adder->command = CANCEL;        /* cancel adder activity */
 1759         dga->csr &= ~DMA_IE;
 1760         dga->csr &= ~0x0600;            /* halt DMA (reset fifo) */
 1761         dga->csr |= DMA_ERR;            /* clear error condition */
 1762         bp->b_flags |= B_ERROR;         /* flag an error to physio() */
 1763 
 1764         /*
 1765          * if DMA was running, flush spurious intrpt 
 1766          */
 1767         if (dga->bytcnt_lo != 0) {
 1768                 dga->bytcnt_lo = 0;
 1769                 dga->bytcnt_hi = 0;
 1770                 DMA_SETIGNORE(DMAheader[unit]);
 1771                 dga->csr |= DMA_IE;
 1772         }
 1773         biodone(bp);
 1774 } /* qd_strategy */
 1775 
 1776 
 1777 /*
 1778  *  Start output to the console screen
 1779  */
 1780 void qdstart(tp)
 1781         struct tty *tp;
 1782 {
 1783         int which_unit, unit, c;
 1784         int s;
 1785 
 1786         unit = minor(tp->t_dev);
 1787         which_unit = (unit >> 2) & 0x3;
 1788         unit &= 0x03;
 1789 
 1790         s = spl5();
 1791 
 1792         /*
 1793         * If it's currently active, or delaying, no need to do anything. 
 1794         */
 1795         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
 1796                 goto out;
 1797 
 1798         /*
 1799         * Display chars until the queue is empty.
 1800         * Drop input from anything but the console
 1801         * device on the floor.  
 1802         *
 1803         * XXX - this loop is done at spltty.
 1804         *
 1805         */
 1806         while (tp->t_outq.c_cc) {
 1807                 c = getc(&tp->t_outq);
 1808                 if (unit == 0)
 1809                         blitc(which_unit, (u_char)c);
 1810         }
 1811         /*
 1812         * If there are sleepers, and output has drained below low
 1813         * water mark, wake up the sleepers. 
 1814         */
 1815         if (tp->t_outq.c_cc <= tp->t_lowat) {
 1816                 if (tp->t_state & TS_ASLEEP){
 1817                         tp->t_state &= ~TS_ASLEEP;
 1818                         wakeup((caddr_t) &tp->t_outq);
 1819                 }
 1820         }
 1821 
 1822         tp->t_state &= ~TS_BUSY;
 1823 
 1824 out:
 1825         splx(s);
 1826 
 1827 } /* qdstart */
 1828 
 1829 /*ARGSUSED*/
 1830 void
 1831 qdstop(tp, flag)
 1832         struct tty *tp;
 1833         int flag;
 1834 {
 1835         int s;
 1836 
 1837         s = spl5();     /* block intrpts during state modification */
 1838         if (tp->t_state & TS_BUSY) {
 1839                 if ((tp->t_state & TS_TTSTOP) == 0)
 1840                         tp->t_state |= TS_FLUSH;
 1841                 else
 1842                         tp->t_state &= ~TS_BUSY;
 1843         }
 1844         splx(s);
 1845 }
 1846 
 1847 /*
 1848  *  Output a character to the QDSS screen
 1849  */
 1850 void
 1851 blitc(unit, chr)
 1852         int unit;
 1853         u_char chr;
 1854 {
 1855         volatile struct adder *adder;
 1856         volatile struct dga *dga;
 1857         int i;
 1858         int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
 1859         static short inescape[NQD];
 1860 
 1861         adder = (struct adder *)qdmap[unit].adder;
 1862         dga = (struct dga *) qdmap[unit].dga;
 1863         /* 
 1864          * BSD comment: this (&=0177) defeats the extended character 
 1865          * set code for the glass tty, but if i had the time i would 
 1866          * spend it ripping out the code completely.  This driver
 1867          * is too big for its own good.
 1868          */
 1869         chr &= 0177;
 1870         /*
 1871          * Cursor addressing (so vi will work).
 1872          * Decode for "\E=%.%." cursor motion description.
 1873          * Corresponds to type "qdcons" in /etc/termcap:
 1874          *
 1875          *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
 1876          *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
 1877          *
 1878          */
 1879         if (inescape[unit] && nograph) {        
 1880                 switch (inescape[unit]++) {
 1881                 case 1:
 1882                         if (chr != '=') {
 1883                                 /* abort escape sequence */
 1884                                 inescape[unit] = 0;
 1885                                 blitc(unit, chr);
 1886                         }
 1887                         return;
 1888                 case 2:
 1889                         /* position row */
 1890                         cursor[unit].y = CHAR_HEIGHT * chr;
 1891                         if (cursor[unit].y > 863 - CHAR_HEIGHT)
 1892                                 cursor[unit].y = 863 - CHAR_HEIGHT;
 1893                         dga->y_cursor = TRANY(cursor[unit].y);
 1894                         return;
 1895                 case 3:
 1896                         /* position column */
 1897                         cursor[unit].x = CHAR_WIDTH * chr;
 1898                         if (cursor[unit].x > 1024 - CHAR_WIDTH)
 1899                                 cursor[unit].x = 1023 - CHAR_WIDTH;
 1900                         dga->x_cursor = TRANX(cursor[unit].x);
 1901                         inescape[unit] = 0;
 1902                         return;
 1903                 default:
 1904                         inescape[unit] = 0;
 1905                         blitc(unit, chr);
 1906                 }
 1907         }
 1908 
 1909         switch (chr) {
 1910         case '\r':                      /* return char */
 1911                 cursor[unit].x = 0;
 1912                 if (nograph)
 1913                         dga->x_cursor = TRANX(cursor[unit].x);
 1914                 return;
 1915 
 1916         case '\t':                      /* tab char */
 1917                 for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
 1918                         blitc(unit, ' ');
 1919                 }
 1920                 return;
 1921 
 1922         case '\n':                      /* line feed char */
 1923                 if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
 1924                         if (nograph) {
 1925                                 cursor[unit].y -= CHAR_HEIGHT;
 1926                                 scroll_up(adder);
 1927                         } else
 1928                                 cursor[unit].y = 0;
 1929                 }
 1930                 if (nograph)
 1931                         dga->y_cursor = TRANY(cursor[unit].y);
 1932                 return;
 1933 
 1934         case '\b':                      /* backspace char */
 1935                 if (cursor[unit].x > 0) {
 1936                         cursor[unit].x -= CHAR_WIDTH;
 1937                         if (nograph)
 1938                                 dga->x_cursor = TRANX(cursor[unit].x);
 1939                 }
 1940                 return;
 1941         case CTRL('k'):         /* cursor up */
 1942                 if (nograph && cursor[unit].y > 0) {
 1943                         cursor[unit].y -= CHAR_HEIGHT;
 1944                         dga->y_cursor = TRANY(cursor[unit].y);
 1945                 }
 1946                 return;
 1947 
 1948         case CTRL('^'):         /* home cursor */
 1949                 if (nograph) {
 1950                         cursor[unit].x = 0;
 1951                         dga->x_cursor = TRANX(cursor[unit].x);
 1952                         cursor[unit].y = 0;
 1953                         dga->y_cursor = TRANY(cursor[unit].y);
 1954                 }
 1955                 return;
 1956 
 1957         case CTRL('l'):         /* cursor right */
 1958                 if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
 1959                         cursor[unit].x += CHAR_WIDTH;
 1960                         dga->x_cursor = TRANX(cursor[unit].x);
 1961                 }
 1962                 return;
 1963 
 1964         case CTRL('z'):         /* clear screen */
 1965                 if (nograph) {
 1966                         setup_dragon(unit);     
 1967                         clear_qd_screen(unit);
 1968                         /* home cursor - termcap seems to assume this */
 1969                         cursor[unit].x = 0;
 1970                         dga->x_cursor = TRANX(cursor[unit].x);
 1971                         cursor[unit].y = 0;
 1972                         dga->y_cursor = TRANY(cursor[unit].y);
 1973                 }
 1974                 return;
 1975 
 1976         case '\033':            /* start escape sequence */
 1977                 if (nograph)
 1978                         inescape[unit] = 1;
 1979                 return;
 1980 
 1981         default:
 1982                 if ((chr < ' ') || (chr > '~'))
 1983                         return;
 1984         }
 1985         /*
 1986          * setup VIPER operand control registers  
 1987          */
 1988         write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
 1989         write_ID(adder, SRC1_OCR_B,
 1990         EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
 1991         write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
 1992         write_ID(adder, SRC1_OCR_B,
 1993         EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
 1994         write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
 1995         write_ID(adder, DST_OCR_B,
 1996         EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
 1997         write_ID(adder, MASK_1, 0xFFFF);
 1998         write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
 1999         write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
 2000         adder->x_clip_min = 0;
 2001         adder->x_clip_max = 1024;
 2002         adder->y_clip_min = 0;
 2003         adder->y_clip_max = 864;
 2004         /*
 2005          * load DESTINATION origin and vectors  
 2006          */
 2007         adder->fast_dest_dy = 0;
 2008         adder->slow_dest_dx = 0;
 2009         adder->error_1 = 0;
 2010         adder->error_2 = 0;
 2011         adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
 2012         (void)wait_status(adder, RASTEROP_COMPLETE);
 2013         adder->destination_x = cursor[unit].x;
 2014         adder->fast_dest_dx = CHAR_WIDTH;
 2015         adder->destination_y = cursor[unit].y;
 2016         adder->slow_dest_dy = CHAR_HEIGHT;
 2017         /*
 2018          * load SOURCE origin and vectors  
 2019          */
 2020         if ((chr - ' ') > (CHARS - 1))  {
 2021                 printf("Invalid character (x)%x in blitc\n",chr);
 2022                 chr = ' ';
 2023         }
 2024         /*
 2025          * X position is modulo the number of characters per line 
 2026          */
 2027         adder->source_1_x = FONT_X + 
 2028             (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
 2029         /*
 2030          * Point to either first or second row 
 2031          */
 2032         adder->source_1_y = 2048 - 15 * 
 2033             (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
 2034         adder->source_1_dx = CHAR_WIDTH;
 2035         adder->source_1_dy = CHAR_HEIGHT;
 2036         write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
 2037         adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
 2038         /*
 2039          * update console cursor coordinates 
 2040          */
 2041         cursor[unit].x += CHAR_WIDTH;
 2042         if (nograph)
 2043                 dga->x_cursor = TRANX(cursor[unit].x);
 2044         if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
 2045                 blitc(unit, '\r');
 2046                 blitc(unit, '\n');
 2047         }
 2048 
 2049 } /* blitc */
 2050 
 2051 /*
 2052  *  INTERRUPT SERVICE ROUTINES
 2053  */
 2054 
 2055 /*
 2056  *  Service "DMA DONE" interrupt condition
 2057  */
 2058 
 2059 static void
 2060 qddint(arg)
 2061         void *arg;
 2062 {
 2063         struct device *dv = arg;
 2064         struct DMAreq_header *header;
 2065         struct DMAreq *request;
 2066         volatile struct dga *dga;
 2067         volatile struct adder *adder;
 2068         int cookie;                     /* DMA adrs for QDSS */
 2069 
 2070         (void)spl4();                   /* allow interval timer in */
 2071 
 2072         /*
 2073         * init pointers 
 2074         */
 2075         header = DMAheader[dv->dv_unit];            /* register for optimization */
 2076         dga = (struct dga *) qdmap[dv->dv_unit].dga;
 2077         adder = (struct adder *) qdmap[dv->dv_unit].adder;
 2078 
 2079         /*
 2080         * if this interrupt flagged as bogus for interrupt flushing purposes.. 
 2081         */
 2082         if (DMA_ISIGNORE(header)) {
 2083            DMA_CLRIGNORE(header);
 2084                 return;
 2085         }
 2086 
 2087         /*
 2088         * dump a DMA hardware error message if appropriate
 2089         */
 2090         if (dga->csr & DMA_ERR) {
 2091 
 2092                 if (dga->csr & PARITY_ERR)
 2093                     printf("qd%d: qddint: DMA hardware parity fault.\n", dv->dv_unit);
 2094 
 2095                 if (dga->csr & BUS_ERR)
 2096                     printf("qd%d: qddint: DMA hardware bus error.\n", dv->dv_unit);
 2097         }
 2098 
 2099         /*
 2100         * if this was a DMA from user space... 
 2101         */
 2102         if (qdflags[dv->dv_unit].user_dma) {
 2103                 qdflags[dv->dv_unit].user_dma = 0;
 2104                 wakeup((caddr_t)&qdflags[dv->dv_unit].user_dma);
 2105                 return;
 2106         }
 2107 
 2108         /*
 2109         * if we're doing DMA request queue services, field the error condition 
 2110         */
 2111         if (dga->csr & DMA_ERR) {
 2112 
 2113                 dga->csr &= ~0x0600;            /* halt DMA (reset fifo) */
 2114                 dga->csr |= DMA_ERR;            /* clear error condition */
 2115                 adder->command = CANCEL;        /* cancel adder activity */
 2116 
 2117                 DMA_SETERROR(header);   /* flag error in header status word */
 2118                 DMA_CLRACTIVE(header);
 2119                 header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
 2120                 header->newest = header->oldest;
 2121                 header->used = 0;
 2122 
 2123                 selnotify(&qdrsel[dv->dv_unit], 0);
 2124 
 2125                 if (dga->bytcnt_lo != 0) {
 2126                         dga->bytcnt_lo = 0;
 2127                         dga->bytcnt_hi = 0;
 2128                         DMA_SETIGNORE(header);
 2129                 }
 2130                 return;
 2131         }
 2132 
 2133         /*
 2134         * if the DMA request queue is now becoming non-full, 
 2135         * wakeup "select" client.
 2136         */
 2137         if (DMA_ISFULL(header)) {
 2138                 selnotify(&qdrsel[dv->dv_unit], 0);
 2139         }
 2140 
 2141         header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
 2142         QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
 2143 
 2144         /* check for unexpected interrupt */
 2145         if (DMA_ISEMPTY(header))
 2146             return;
 2147 
 2148         DMA_GETEND(header);     /* update request queue indices */
 2149 
 2150         /*
 2151         * if no more DMA pending, wake up "select" client and exit 
 2152         */
 2153         if (DMA_ISEMPTY(header)) {
 2154                 selnotify(&qdrsel[dv->dv_unit], 0);
 2155                 DMA_CLRACTIVE(header);  /* flag DMA done */
 2156                 return;
 2157         }
 2158 
 2159         /*
 2160         * initiate next DMA xfer  
 2161         */
 2162         request = DMA_GETBEGIN(header);
 2163         if (request->DMAtype != QDlast_DMAtype) {
 2164                 dga->csr &= ~0x0600;      /* halt DMA (reset fifo) */
 2165                 adder->command = CANCEL;  /* cancel adder activity */
 2166         }
 2167 
 2168 
 2169         switch (request->DMAtype) {
 2170 
 2171         case DISPLIST:
 2172                 if (request->DMAtype != QDlast_DMAtype) {
 2173                         dga->csr |= DL_ENB;
 2174                         dga->csr &= ~(BTOP_ENB | BYTE_DMA);
 2175                 }
 2176                 break;
 2177 
 2178         case PTOB:
 2179                 if (request->DMAtype != QDlast_DMAtype) {
 2180                         if (request->DMAdone & BYTE_PACK)
 2181                             dga->csr |= (PTOB_ENB | BYTE_DMA);
 2182                         else {
 2183                                 dga->csr |= PTOB_ENB;
 2184                                 dga->csr &= ~BYTE_DMA;
 2185                         }
 2186                 }
 2187                 break;
 2188 
 2189         case BTOP:
 2190                 if (request->DMAtype != QDlast_DMAtype) {
 2191                         if (request->DMAdone & BYTE_PACK) {
 2192                                 dga->csr &= ~DL_ENB;
 2193                                 dga->csr |= (BTOP_ENB | BYTE_DMA);
 2194                         }
 2195                         else {
 2196                                 dga->csr |= BTOP_ENB;
 2197                                 dga->csr &= ~(BYTE_DMA | DL_ENB);
 2198                         }
 2199                 }
 2200                 break;
 2201         default:
 2202                 printf("qd%d: qddint: illegal DMAtype parameter.\n", dv->dv_unit);
 2203                 DMA_CLRACTIVE(header);  /* flag DMA done */
 2204                 return;
 2205         }
 2206 
 2207         if (request->DMAdone & COUNT_ZERO) {
 2208                 dga->csr &= ~SET_DONE_FIFO;
 2209         } 
 2210         else if (request->DMAdone & FIFO_EMPTY) {
 2211                 dga->csr |= SET_DONE_FIFO;
 2212         }
 2213 
 2214         if (request->DMAdone & WORD_PACK)
 2215             dga->csr &= ~BYTE_DMA;
 2216         else if (request->DMAdone & BYTE_PACK)
 2217             dga->csr |= BYTE_DMA;
 2218 
 2219         dga->csr |= DMA_IE;
 2220         QDlast_DMAtype = request->DMAtype;
 2221 
 2222         cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
 2223 
 2224         dga->adrs_lo = (short) cookie;
 2225         dga->adrs_hi = (short) (cookie >> 16);
 2226 
 2227         dga->bytcnt_lo = (short) request->length;
 2228         dga->bytcnt_hi = (short) (request->length >> 16);
 2229 
 2230         return;
 2231 }
 2232 
 2233 /*
 2234  * ADDER interrupt service routine
 2235  */
 2236 static void
 2237 qdaint(arg)
 2238         void *arg;
 2239 {
 2240         struct device *dv = arg;
 2241         volatile struct adder *adder;
 2242         struct color_buf *cbuf;
 2243         int i;
 2244         struct rgb *rgbp;
 2245         volatile short *red;
 2246         volatile short *green;
 2247         volatile short *blue;
 2248 
 2249         (void)spl4();                   /* allow interval timer in */
 2250 
 2251         adder = (struct adder *) qdmap[dv->dv_unit].adder;
 2252 
 2253         /*
 2254         * service the vertical blank interrupt (VSYNC bit) by loading 
 2255         * any pending color map load request  
 2256         */
 2257         if (adder->status & VSYNC) {
 2258                 adder->status &= ~VSYNC;        /* clear the interrupt */
 2259                 cbuf = color_buf[dv->dv_unit];
 2260                 if (cbuf->status & LOAD_COLOR_MAP) {
 2261 
 2262                         red = (short *) qdmap[dv->dv_unit].red;
 2263                         green = (short *) qdmap[dv->dv_unit].green;
 2264                         blue = (short *) qdmap[dv->dv_unit].blue;
 2265 
 2266                         for (i = cbuf->count, rgbp = cbuf->rgb;
 2267                              --i >= 0; rgbp++) {
 2268                                 red[rgbp->offset] = (short) rgbp->red;
 2269                                 green[rgbp->offset] = (short) rgbp->green;
 2270                                 blue[rgbp->offset] = (short) rgbp->blue;
 2271                         }
 2272 
 2273                         cbuf->status &= ~LOAD_COLOR_MAP;
 2274                 }
 2275         }
 2276 
 2277         /*
 2278         * service the scroll interrupt (FRAME_SYNC bit) 
 2279         */
 2280         if (adder->status & FRAME_SYNC) {
 2281                 adder->status &= ~FRAME_SYNC;   /* clear the interrupt */
 2282 
 2283                 if (scroll[dv->dv_unit]->status & LOAD_REGS) {
 2284 
 2285                         for (i = 1000, adder->status = 0; i > 0 && 
 2286                              !(adder->status&ID_SCROLL_READY); --i)
 2287                               ;
 2288 
 2289                         if (i == 0) {
 2290                             printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
 2291                                 qd);
 2292                                 return;
 2293                         }
 2294 
 2295                         adder->ID_scroll_data = scroll[dv->dv_unit]->viper_constant;
 2296                         adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
 2297 
 2298                         adder->y_scroll_constant =
 2299                                 scroll[dv->dv_unit]->y_scroll_constant;
 2300                         adder->y_offset_pending = scroll[dv->dv_unit]->y_offset;
 2301 
 2302                         if (scroll[dv->dv_unit]->status & LOAD_INDEX) {
 2303 
 2304                                 adder->x_index_pending = 
 2305                                         scroll[dv->dv_unit]->x_index_pending;
 2306                                 adder->y_index_pending = 
 2307                                         scroll[dv->dv_unit]->y_index_pending;
 2308                         }
 2309 
 2310                         scroll[dv->dv_unit]->status = 0x00;
 2311                 }
 2312         }
 2313 }
 2314 
 2315 /*
 2316  *  DUART input interrupt service routine
 2317  *
 2318  *  XXX - this routine should be broken out - it is essentially
 2319  *            straight line code.
 2320  */
 2321 
 2322 static void
 2323 qdiint(arg)
 2324         void *arg;
 2325 {
 2326         struct device *dv = arg;
 2327         struct _vs_event *event;
 2328         struct qdinput *eqh;
 2329         volatile struct dga *dga;
 2330         volatile struct duart *duart;
 2331         struct mouse_report *new_rep;
 2332         struct tty *tp;
 2333         u_short chr;
 2334         u_short status;
 2335         u_short data;
 2336         u_short key;
 2337         char do_wakeup = 0;             /* flag to do a select wakeup call */
 2338         char a, b, c;                   /* mouse button test variables */
 2339 
 2340         (void)spl4();                   /* allow interval timer in */
 2341 
 2342         eqh = eq_header[dv->dv_unit];           /* optimized as a register */
 2343         new_rep = &current_rep[dv->dv_unit];
 2344         duart = (struct duart *) qdmap[dv->dv_unit].duart;
 2345 
 2346         /*
 2347         * if the graphic device is turned on..  
 2348         */
 2349         if (qdflags[dv->dv_unit].inuse & GRAPHIC_DEV) {
 2350                 /*
 2351                 * empty DUART 
 2352                 */
 2353                 while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
 2354                         /*
 2355                          * pick up LK-201 input (if any) 
 2356                          */
 2357                         if (duart->statusA&RCV_RDY) {
 2358 
 2359                                 /* if error condition, then reset it */
 2360 
 2361                                 if (duart->statusA&0x70) {
 2362                                         duart->cmdA = 0x40;
 2363                                         continue;
 2364                                 }
 2365 
 2366                                 /* event queue full now? (overflow condition) */
 2367 
 2368                                 if (ISFULL(eqh) == TRUE) {
 2369                                         printf(
 2370                                          "qd%d: qdiint: event queue overflow\n",
 2371                                            qd);
 2372                                         break;
 2373                                 }
 2374 
 2375                                 /*
 2376                                 * Check for various keyboard errors  */
 2377 
 2378                                 key = duart->dataA & 0xFF;
 2379 
 2380                                 if (key==LK_POWER_ERROR ||
 2381                                     key==LK_KDOWN_ERROR ||
 2382                                     key == LK_INPUT_ERROR || 
 2383                                     key == LK_OUTPUT_ERROR) {
 2384                                         printf(
 2385                                     "qd%d: qdiint: keyboard error, code = %x\n",
 2386                                         qd,key);
 2387                                         return;
 2388                                 }
 2389 
 2390                                 if (key < LK_LOWEST)
 2391                                     return;
 2392 
 2393                                 ++do_wakeup;  /* request a select wakeup call */
 2394 
 2395                                 event = PUTBEGIN(eqh);
 2396                                 PUTEND(eqh);
 2397 
 2398                                 event->vse_key = key;
 2399                                 event->vse_key &= 0x00FF;
 2400                                 event->vse_x = eqh->curs_pos.x;
 2401                                 event->vse_y = eqh->curs_pos.y;
 2402                                 event->vse_time = TOY;
 2403                                 event->vse_type = VSE_BUTTON;
 2404                                 event->vse_direction = VSE_KBTRAW;
 2405                                 event->vse_device = VSE_DKB;
 2406                         }
 2407 
 2408                         /*
 2409                         * pick up the mouse input (if any)  */
 2410 
 2411                         if ((status = duart->statusB) & RCV_RDY  &&
 2412                             qdflags[dv->dv_unit].pntr_id == MOUSE_ID) {
 2413 
 2414                                 if (status & 0x70) {
 2415                                         duart->cmdB = 0x40;
 2416                                         continue;
 2417                                 }
 2418 
 2419                                 /* event queue full now? (overflow condition) */
 2420 
 2421                                 if (ISFULL(eqh) == TRUE) {
 2422                                         printf(
 2423                                         "qd%d: qdiint: event queue overflow\n",
 2424                                              qd);
 2425                                         break;
 2426                                 }
 2427 
 2428                                 data = duart->dataB;      /* get report byte */
 2429                                 ++new_rep->bytcnt; /* bump report byte count */
 2430 
 2431                                 /*
 2432                                 * if 1st byte of report.. */
 2433 
 2434                                 if ( data & START_FRAME) {
 2435                                         new_rep->state = data;
 2436                                         if (new_rep->bytcnt > 1) {
 2437                                                 /* start of new frame */
 2438                                                 new_rep->bytcnt = 1;    
 2439                                                 /* ..continue looking */
 2440                                                 continue;                   
 2441                                         }
 2442                                 }
 2443 
 2444                                 /*
 2445                                 * if 2nd byte of report.. */
 2446 
 2447                                 else if (new_rep->bytcnt == 2) {
 2448                                         new_rep->dx = data & 0x00FF;
 2449                                 }
 2450 
 2451                                 /*
 2452                                 * if 3rd byte of report, load input event queue */
 2453 
 2454                                 else if (new_rep->bytcnt == 3) {
 2455 
 2456                                         new_rep->dy = data & 0x00FF;
 2457                                         new_rep->bytcnt = 0;
 2458 
 2459                                         /*
 2460                                         * if mouse position has changed.. */
 2461 
 2462                                         if (new_rep->dx != 0  ||  new_rep->dy != 0) {
 2463 
 2464                                                 /*
 2465                                                 * calculate acceleration factor, if needed      */
 2466 
 2467                                                 if (qdflags[dv->dv_unit].curs_acc > ACC_OFF) {
 2468 
 2469                                                         if (qdflags[dv->dv_unit].curs_thr <= new_rep->dx)
 2470                                                             new_rep->dx +=
 2471                                                             (new_rep->dx - qdflags[dv->dv_unit].curs_thr)
 2472                                                             * qdflags[dv->dv_unit].curs_acc;
 2473 
 2474                                                         if (qdflags[dv->dv_unit].curs_thr <= new_rep->dy)
 2475                                                             new_rep->dy +=
 2476                                                             (new_rep->dy - qdflags[dv->dv_unit].curs_thr)
 2477                                                             * qdflags[dv->dv_unit].curs_acc;
 2478                                                 }
 2479 
 2480                                                 /*
 2481                                                 * update cursor position coordinates */
 2482 
 2483                                                 if (new_rep->state & X_SIGN) {
 2484                                                         eqh->curs_pos.x += new_rep->dx;
 2485                                                         if (eqh->curs_pos.x > 1023)
 2486                                                             eqh->curs_pos.x = 1023;
 2487                                                 }
 2488                                                 else {
 2489                                                         eqh->curs_pos.x -= new_rep->dx;
 2490                                                         if (eqh->curs_pos.x < -15)
 2491                                                             eqh->curs_pos.x = -15;
 2492                                                 }
 2493 
 2494                                                 if (new_rep->state & Y_SIGN) {
 2495                                                         eqh->curs_pos.y -= new_rep->dy;
 2496                                                         if (eqh->curs_pos.y < -15)
 2497                                                             eqh->curs_pos.y = -15;
 2498                                                 }
 2499                                                 else {
 2500                                                         eqh->curs_pos.y += new_rep->dy;
 2501                                                         if (eqh->curs_pos.y > 863)
 2502                                                             eqh->curs_pos.y = 863;
 2503                                                 }
 2504 
 2505                                                 /*
 2506                                                 * update cursor screen position */
 2507 
 2508                                                 dga = (struct dga *) qdmap[dv->dv_unit].dga;
 2509                                                 dga->x_cursor = TRANX(eqh->curs_pos.x);
 2510                                                 dga->y_cursor = TRANY(eqh->curs_pos.y);
 2511 
 2512                                                 /*
 2513                                                 * if cursor is in the box, no event report */
 2514 
 2515                                                 if (eqh->curs_pos.x <= eqh->curs_box.right      &&
 2516                                                     eqh->curs_pos.x >= eqh->curs_box.left  &&
 2517                                                     eqh->curs_pos.y >= eqh->curs_box.top  &&
 2518                                                     eqh->curs_pos.y <= eqh->curs_box.bottom ) {
 2519                                                         goto GET_MBUTTON;
 2520                                                 }
 2521 
 2522                                                 /*
 2523                                                 * report the mouse motion event */
 2524 
 2525                                                 event = PUTBEGIN(eqh);
 2526                                                 PUTEND(eqh);
 2527 
 2528                                                 ++do_wakeup;   /* request a select wakeup call */
 2529 
 2530                                                 event->vse_x = eqh->curs_pos.x;
 2531                                                 event->vse_y = eqh->curs_pos.y;
 2532 
 2533                                                 event->vse_device = VSE_MOUSE;  /* mouse */
 2534                                                 event->vse_type = VSE_MMOTION;  /* pos changed */
 2535                                                 event->vse_key = 0;
 2536                                                 event->vse_direction = 0;
 2537                                                 event->vse_time = TOY;  /* time stamp */
 2538                                         }
 2539 
 2540 GET_MBUTTON:
 2541                                         /*
 2542                                         * if button state has changed */
 2543 
 2544                                         a = new_rep->state & 0x07;    /*mask nonbutton bits */
 2545                                         b = last_rep[dv->dv_unit].state & 0x07;
 2546 
 2547                                         if (a ^ b) {
 2548 
 2549                                                 for ( c = 1;  c < 8; c <<= 1) {
 2550 
 2551                                                         if (!( c & (a ^ b))) /* this button change? */
 2552                                                             continue;
 2553 
 2554                                                         /* event queue full? (overflow condition) */
 2555 
 2556                                                         if (ISFULL(eqh) == TRUE) {
 2557                                                                 printf("qd%d: qdiint: event queue overflow\n", qd);
 2558                                                                 break;
 2559                                                         }
 2560 
 2561                                                         event = PUTBEGIN(eqh);  /* get new event */
 2562                                                         PUTEND(eqh);
 2563 
 2564                                                         ++do_wakeup;   /* request select wakeup */
 2565 
 2566                                                         event->vse_x = eqh->curs_pos.x;
 2567                                                         event->vse_y = eqh->curs_pos.y;
 2568 
 2569                                                         event->vse_device = VSE_MOUSE;  /* mouse */
 2570                                                         event->vse_type = VSE_BUTTON; /* new button */
 2571                                                         event->vse_time = TOY;        /* time stamp */
 2572 
 2573                                                         /* flag changed button and if up or down */
 2574 
 2575                                                         if (c == RIGHT_BUTTON)
 2576                                                             event->vse_key = VSE_RIGHT_BUTTON;
 2577                                                         else if (c == MIDDLE_BUTTON)
 2578                                                             event->vse_key = VSE_MIDDLE_BUTTON;
 2579                                                         else if (c == LEFT_BUTTON)
 2580                                                             event->vse_key = VSE_LEFT_BUTTON;
 2581 
 2582                                                         /* set bit = button depressed */
 2583 
 2584                                                         if (c & a)
 2585                                                             event->vse_direction = VSE_KBTDOWN;
 2586                                                         else
 2587                                                                 event->vse_direction = VSE_KBTUP;
 2588                                                 }
 2589                                         }
 2590 
 2591                                         /* refresh last report */
 2592 
 2593                                         last_rep[dv->dv_unit] = current_rep[dv->dv_unit];
 2594 
 2595                                 }  /* get last byte of report */
 2596                         } else if ((status = duart->statusB)&RCV_RDY &&
 2597                                    qdflags[dv->dv_unit].pntr_id == TABLET_ID) {
 2598                                 /*
 2599                                 * pickup tablet input, if any  
 2600                                 */
 2601                                 if (status&0x70) {
 2602                                         duart->cmdB = 0x40;
 2603                                         continue;
 2604                                 }
 2605                                 /* 
 2606                                  * event queue full now? (overflow condition) 
 2607                                  */
 2608                                 if (ISFULL(eqh) == TRUE) {
 2609                                         printf("qd%d: qdiint: event queue overflow\n", qd);
 2610                                         break;
 2611                                 }
 2612 
 2613                                 data = duart->dataB;      /* get report byte */
 2614                                 ++new_rep->bytcnt;            /* bump report byte count */
 2615 
 2616                                 /*
 2617                                 * if 1st byte of report.. */
 2618 
 2619                                 if (data & START_FRAME) {
 2620                                         new_rep->state = data;
 2621                                         if (new_rep->bytcnt > 1) {
 2622                                                 new_rep->bytcnt = 1;    /* start of new frame */
 2623                                                 continue;                   /* ..continue looking */
 2624                                         }
 2625                                 }
 2626 
 2627                                 /*
 2628                                 * if 2nd byte of report.. */
 2629 
 2630                                 else if (new_rep->bytcnt == 2) {
 2631                                         new_rep->dx = data & 0x3F;
 2632                                 }
 2633 
 2634                                 /*
 2635                                 * if 3rd byte of report.. */
 2636 
 2637                                 else if (new_rep->bytcnt == 3) {
 2638                                         new_rep->dx |= (data & 0x3F) << 6;
 2639                                 }
 2640 
 2641                                 /*
 2642                                 * if 4th byte of report.. */
 2643 
 2644                                 else if (new_rep->bytcnt == 4) {
 2645                                         new_rep->dy = data & 0x3F;
 2646                                 }
 2647 
 2648                                 /*
 2649                                 * if 5th byte of report, load input event queue */
 2650 
 2651                                 else if (new_rep->bytcnt == 5) {
 2652 
 2653                                         new_rep->dy |= (data & 0x3F) << 6;
 2654                                         new_rep->bytcnt = 0;
 2655 
 2656                                         /*
 2657                                         * update cursor position coordinates */
 2658 
 2659                                         new_rep->dx /= qdflags[dv->dv_unit].tab_res;
 2660                                         new_rep->dy = (2200 - new_rep->dy)
 2661                                             / qdflags[dv->dv_unit].tab_res;
 2662 
 2663                                         if (new_rep->dx > 1023) {
 2664                                                 new_rep->dx = 1023;
 2665                                         }
 2666                                         if (new_rep->dy > 863) {
 2667                                                 new_rep->dy = 863;
 2668                                         }
 2669 
 2670                                         /*
 2671                                         * report an event if the puck/stylus has moved
 2672                                         */
 2673 
 2674                                         if (eqh->curs_pos.x != new_rep->dx ||
 2675                                             eqh->curs_pos.y != new_rep->dy) {
 2676 
 2677                                                 eqh->curs_pos.x = new_rep->dx;
 2678                                                 eqh->curs_pos.y = new_rep->dy;
 2679 
 2680                                                 /*
 2681                                                 * update cursor screen position */
 2682 
 2683                                                 dga = (struct dga *) qdmap[dv->dv_unit].dga;
 2684                                                 dga->x_cursor = TRANX(eqh->curs_pos.x);
 2685                                                 dga->y_cursor = TRANY(eqh->curs_pos.y);
 2686 
 2687                                                 /*
 2688                                                 * if cursor is in the box, no event report
 2689                                                 */
 2690 
 2691                                                 if (eqh->curs_pos.x <= eqh->curs_box.right      &&
 2692                                                     eqh->curs_pos.x >= eqh->curs_box.left  &&
 2693                                                     eqh->curs_pos.y >= eqh->curs_box.top  &&
 2694                                                     eqh->curs_pos.y <= eqh->curs_box.bottom ) {
 2695                                                         goto GET_TBUTTON;
 2696                                                 }
 2697 
 2698                                                 /*
 2699                                                 * report the tablet motion event */
 2700 
 2701                                                 event = PUTBEGIN(eqh);
 2702                                                 PUTEND(eqh);
 2703 
 2704                                                 ++do_wakeup;   /* request a select wakeup call */
 2705 
 2706                                                 event->vse_x = eqh->curs_pos.x;
 2707                                                 event->vse_y = eqh->curs_pos.y;
 2708 
 2709                                                 event->vse_device = VSE_TABLET;  /* tablet */
 2710                                                 /*
 2711                                                 * right now, X handles tablet motion the same
 2712                                                 * as mouse motion
 2713                                                 */
 2714                                                 event->vse_type = VSE_MMOTION;   /* pos changed */
 2715                                                 event->vse_key = 0;
 2716                                                 event->vse_direction = 0;
 2717                                                 event->vse_time = TOY;  /* time stamp */
 2718                                         }
 2719 GET_TBUTTON:
 2720                                         /*
 2721                                         * if button state has changed */
 2722 
 2723                                         a = new_rep->state & 0x1E;   /* mask nonbutton bits */
 2724                                         b = last_rep[dv->dv_unit].state & 0x1E;
 2725 
 2726                                         if (a ^ b) {
 2727 
 2728                                                 /* event queue full now? (overflow condition) */
 2729 
 2730                                                 if (ISFULL(eqh) == TRUE) {
 2731                                                         printf("qd%d: qdiint: event queue overflow\n",qd);
 2732                                                         break;
 2733                                                 }
 2734 
 2735                                                 event = PUTBEGIN(eqh);  /* get new event */
 2736                                                 PUTEND(eqh);
 2737 
 2738                                                 ++do_wakeup;   /* request a select wakeup call */
 2739 
 2740                                                 event->vse_x = eqh->curs_pos.x;
 2741                                                 event->vse_y = eqh->curs_pos.y;
 2742 
 2743                                                 event->vse_device = VSE_TABLET;  /* tablet */
 2744                                                 event->vse_type = VSE_BUTTON; /* button changed */
 2745                                                 event->vse_time = TOY;     /* time stamp */
 2746 
 2747                                                 /* define the changed button and if up or down */
 2748 
 2749                                                 for ( c = 1;  c <= 0x10; c <<= 1) {
 2750                                                         if (c & (a ^ b)) {
 2751                                                                 if (c == T_LEFT_BUTTON)
 2752                                                                     event->vse_key = VSE_T_LEFT_BUTTON;
 2753                                                                 else if (c == T_FRONT_BUTTON)
 2754                                                                     event->vse_key = VSE_T_FRONT_BUTTON;
 2755                                                                 else if (c == T_RIGHT_BUTTON)
 2756                                                                     event->vse_key = VSE_T_RIGHT_BUTTON;
 2757                                                                 else if (c == T_BACK_BUTTON)
 2758                                                                     event->vse_key = VSE_T_BACK_BUTTON;
 2759                                                                 break;
 2760                                                         }
 2761                                                 }
 2762 
 2763                                                 /* set bit = button depressed */
 2764 
 2765                                                 if (c & a)
 2766                                                     event->vse_direction = VSE_KBTDOWN;
 2767                                                 else
 2768                                                         event->vse_direction = VSE_KBTUP;
 2769                                         }
 2770 
 2771                                         /* refresh last report */
 2772 
 2773                                         last_rep[dv->dv_unit] = current_rep[dv->dv_unit];
 2774 
 2775                                 } /* get last byte of report */
 2776                         } /* pick up tablet input */
 2777 
 2778                 } /* while input available.. */
 2779 
 2780                 /*
 2781                 * do select wakeup      
 2782                 */
 2783                 if (do_wakeup) {
 2784                         selnotify(&qdrsel[dv->dv_unit], 0);
 2785                         do_wakeup = 0;
 2786                 }
 2787         } else {
 2788                 /*
 2789                  * if the graphic device is not turned on, this is console input
 2790                  */
 2791                 if (qdpolling)
 2792                         return;
 2793            
 2794                 if (dv->dv_unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[dv->dv_unit] == NULL)
 2795                         return;         /* no such device or address */
 2796 
 2797                 tp = qd_tty[dv->dv_unit << 2];
 2798 
 2799                 /*
 2800                  * Get a character from the keyboard. 
 2801                  */
 2802                 while (duart->statusA&RCV_RDY) {
 2803                         key = duart->dataA;
 2804                         key &= 0xFF;
 2805                         /*
 2806                         * Check for various keyboard errors  
 2807                         */
 2808                         if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
 2809                             key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
 2810                                 printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
 2811                                 return;
 2812                         }
 2813 
 2814                         if (key < LK_LOWEST)
 2815                             return;
 2816 
 2817                         /*
 2818                         * See if its a state change key */
 2819 
 2820                         switch (key) {
 2821 
 2822                         case LOCK:
 2823                                 q_keyboard.lock ^= 0xffff;      /* toggle */
 2824                                 if (q_keyboard.lock)
 2825                                         led_control(qd, LK_LED_ENABLE,
 2826                                                           LK_LED_LOCK);
 2827                                 else
 2828                                         led_control(qd, LK_LED_DISABLE,
 2829                                                           LK_LED_LOCK);
 2830                                 return;
 2831 
 2832                         case SHIFT:
 2833                                 q_keyboard.shift ^= 0xFFFF;
 2834                                 return;
 2835 
 2836                         case CNTRL:
 2837                                 q_keyboard.cntrl ^= 0xFFFF;
 2838                                 return;
 2839 
 2840                         case ALLUP:
 2841                                 q_keyboard.cntrl = 0;
 2842                                 q_keyboard.shift = 0;
 2843                                 return;
 2844 
 2845                         case REPEAT:
 2846                                 chr = q_keyboard.last;
 2847                                 break;
 2848 
 2849                                 /*
 2850                                 * Test for cntrl characters. If set, see if the character
 2851                                 * is elligible to become a control character. */
 2852 
 2853                         default:
 2854 
 2855                                 if (q_keyboard.cntrl) {
 2856                                         chr = q_key[key];
 2857                                         if (chr >= ' ' && chr <= '~')
 2858                                             chr &= 0x1F;
 2859                                         else if (chr >= 0xA1 && chr <= 0xFE)
 2860                                             chr &= 0x9F;
 2861                                 }
 2862                                 else if( q_keyboard.lock || q_keyboard.shift )
 2863                                     chr = q_shift_key[key];
 2864                                 else
 2865                                         chr = q_key[key];
 2866                                 break;
 2867                         }
 2868 
 2869                         q_keyboard.last = chr;
 2870 
 2871                         /*
 2872                         * Check for special function keys */
 2873 
 2874                         if (chr & 0x100) {
 2875                                 char *string;
 2876                                 string = q_special[chr & 0x7F];
 2877                                 while(*string)
 2878                                     (*tp->t_linesw->l_rint)(*string++, tp);
 2879                         }
 2880                         else {
 2881 #ifdef DDB
 2882                                 /* Check for kernel debugger escape here */
 2883                                 int j;
 2884                            
 2885                                 j = kdbrint(chr&0177);
 2886                            
 2887                                 if (j == 1)  /* Escape received, just return */
 2888                                     return;
 2889                            
 2890                                 if (j == 2)  /* Second char wasn't 'D' */
 2891                                     (*tp->t_linesw->l_rint)(27, tp);
 2892 #endif
 2893                                 (*tp->t_linesw->l_rint)(chr&0177, tp);
 2894                         }
 2895                 }
 2896         }
 2897 } /* qdiint */
 2898 
 2899 /*
 2900  *
 2901  * Clear the QDSS screen
 2902  *
 2903  *                           >>> NOTE <<<
 2904  *
 2905  *   This code requires that certain adder initialization be valid.  To
 2906  *   assure that this requirement is satisfied, this routine should be
 2907  *   called only after calling the "setup_dragon()" function.
 2908  *
 2909  *   Clear the bitmap a piece at a time. Since the fast scroll clear
 2910  *   only clears the current displayed portion of the bitmap put a
 2911  *   temporary value in the y limit register so we can access whole
 2912  *   bitmap
 2913  *
 2914  */
 2915 void
 2916 clear_qd_screen(unit)
 2917         int unit;
 2918 {
 2919         volatile struct adder *adder;
 2920         adder = (struct adder *) qdmap[unit].adder;
 2921 
 2922         adder->x_limit = 1024;
 2923         adder->y_limit = 2048 - CHAR_HEIGHT;
 2924         adder->y_offset_pending = 0;
 2925 #define WSV  (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
 2926         WSV;
 2927         adder->y_scroll_constant = SCROLL_ERASE;
 2928         WSV;
 2929         adder->y_offset_pending = 864;
 2930         WSV;
 2931         adder->y_scroll_constant = SCROLL_ERASE;
 2932         WSV;
 2933         adder->y_offset_pending = 1728;
 2934         WSV;
 2935         adder->y_scroll_constant = SCROLL_ERASE;
 2936         WSV;
 2937         adder->y_offset_pending = 0;     /* back to normal */
 2938         WSV;
 2939         adder->x_limit = MAX_SCREEN_X;
 2940         adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
 2941 #undef WSV
 2942 
 2943 } /* clear_qd_screen */
 2944 
 2945 /*
 2946  *  kernel console output to the glass tty
 2947  */
 2948 void
 2949 qdcnputc(dev, chr)
 2950         dev_t dev;
 2951         int chr;
 2952 {
 2953 
 2954         /*
 2955          * if system is now physical, forget it (ie: crash DUMP) 
 2956          */
 2957         if ((mfpr(PR_MAPEN) & 1) == 0)
 2958                 return;
 2959 
 2960         blitc(0, (u_char)(chr & 0xff));
 2961         if ((chr & 0177) == '\n')
 2962                 blitc(0, '\r');
 2963 
 2964 } /* qdputc */
 2965 
 2966 /*
 2967  *  load the mouse cursor's template RAM bitmap
 2968  */
 2969 void
 2970 ldcursor(unit, bitmap)
 2971         int unit;
 2972         short *bitmap;
 2973 {
 2974         volatile struct dga *dga;
 2975         volatile short *temp;
 2976         int i;
 2977         int curs;
 2978 
 2979         dga = (struct dga *) qdmap[unit].dga;
 2980         temp = (short *) qdmap[unit].template;
 2981 
 2982         if (dga->csr & CURS_ENB) {      /* if the cursor is enabled.. */
 2983                 curs = -1;              /* ..note that.. */
 2984                 dga->csr &= ~CURS_ENB;  /* ..and shut it off */
 2985         } else 
 2986                 curs = 0;
 2987 
 2988         dga->csr &= ~CURS_ENB;          /* shut off the cursor */
 2989 
 2990         temp += (8 * 1024) - 32;        /* cursor is 32 WORDS from the end */
 2991         /* ..of the 8k WORD template space */
 2992         for (i = 0; i < 32; ++i)
 2993                 *temp++ = *bitmap++;
 2994 
 2995         if (curs) {                     /* if cursor was enabled.. */
 2996                 dga->csr |= CURS_ENB;   /* ..turn it back on */
 2997         }
 2998 
 2999 } /* ldcursor */
 3000 
 3001 /*
 3002  *  Put the console font in the QDSS off-screen memory
 3003  */
 3004 void
 3005 ldfont(unit)
 3006         int unit;
 3007 {
 3008         volatile struct adder *adder;
 3009 
 3010         int i, j, k, max_chars_line;
 3011         short packed;
 3012 
 3013         adder = (struct adder *) qdmap[unit].adder;
 3014 
 3015         /*
 3016         * setup VIPER operand control registers  
 3017         */
 3018         write_ID(adder, MASK_1, 0xFFFF);
 3019         write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
 3020         write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
 3021 
 3022         write_ID(adder, SRC1_OCR_B,
 3023         EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
 3024         write_ID(adder, SRC2_OCR_B,
 3025         EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
 3026         write_ID(adder, DST_OCR_B,
 3027         EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
 3028 
 3029         adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
 3030 
 3031         /*
 3032         * load destination data  
 3033         */
 3034         (void)wait_status(adder, RASTEROP_COMPLETE);
 3035 
 3036         adder->destination_x = FONT_X;
 3037         adder->destination_y = FONT_Y;
 3038 #if FONT_WIDTH > MAX_SCREEN_X
 3039         adder->fast_dest_dx = MAX_SCREEN_X;
 3040 #else
 3041         adder->fast_dest_dx = FONT_WIDTH;
 3042 #endif
 3043         adder->slow_dest_dy = CHAR_HEIGHT;
 3044 
 3045         /*
 3046         * setup for processor to bitmap xfer  */
 3047 
 3048         write_ID(adder, CS_UPDATE_MASK, 0x0001);
 3049         adder->cmd = PBT | OCRB | 2 | DTE | 2;
 3050 
 3051         /*
 3052         * Figure out how many characters can be stored on one "line" of 
 3053         * offscreen memory.
 3054         */
 3055         max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
 3056         if ((CHARS/2 + CHARS%2) < max_chars_line)
 3057             max_chars_line = CHARS/2 + CHARS%2;
 3058 
 3059         /*
 3060         * iteratively do the processor to bitmap xfer */
 3061 
 3062         for (i = 0; i < ROWS; ++i) {
 3063 
 3064                 /* PTOB a scan line */
 3065 
 3066                 for (j = 0, k = i; j < max_chars_line; ++j) {
 3067                         /* PTOB one scan of a char cell */
 3068 
 3069                         packed = q_font[k];
 3070                         k += ROWS;
 3071                         packed |= ((short)q_font[k] << 8);
 3072                         k += ROWS;
 3073 
 3074                         (void)wait_status(adder, TX_READY);
 3075                         adder->id_data = packed;
 3076                 }
 3077         }
 3078 
 3079         /*
 3080          * (XXX XXX XXX - should remove)
 3081          *
 3082          * Copy the second row of characters.  Subtract the first
 3083          * row from the total number.  Divide this quantity by 2
 3084          * because 2 chars are stored in a short in the PTOB loop
 3085          * below.  Figure out how many characters can be stored on
 3086          * one "line" of offscreen memory 
 3087          */
 3088 
 3089         max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
 3090         if ((CHARS/2 + CHARS%2) < max_chars_line)
 3091             return;
 3092         max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
 3093         /* Paranoia check to see if 3rd row may be needed */
 3094         if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
 3095             max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
 3096 
 3097         adder->destination_x = FONT_X;
 3098         adder->destination_y = FONT_Y - CHAR_HEIGHT;
 3099         adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
 3100         adder->slow_dest_dy = CHAR_HEIGHT;
 3101 
 3102         /*
 3103         * setup for processor to bitmap xfer  
 3104         */
 3105         write_ID(adder, CS_UPDATE_MASK, 0x0001);
 3106         adder->cmd = PBT | OCRB | 2 | DTE | 2;
 3107 
 3108         /*
 3109         * iteratively do the processor to bitmap xfer 
 3110         */
 3111         for (i = 0; i < ROWS; ++i) {
 3112                 /* 
 3113                  * PTOB a scan line 
 3114                  */
 3115                 for (j = 0, k = i; j < max_chars_line; ++j) {
 3116                         /*
 3117                          * PTOB one scan of a char cell 
 3118                          */
 3119                         packed = q_font[k + FONT_OFFSET];
 3120                         k += ROWS;
 3121                         packed |= ((short)q_font[k + FONT_OFFSET] << 8);
 3122                         k += ROWS;
 3123                         (void)wait_status(adder, TX_READY);
 3124                         adder->id_data = packed;
 3125                 }
 3126         }
 3127 
 3128 }  /* ldfont */
 3129 
 3130 
 3131 /* 
 3132  * Disable or enable polling.  This is used when entering or leaving the 
 3133  * kernel debugger.
 3134  */
 3135 void
 3136 qdcnpollc(dev, onoff)
 3137         dev_t dev;
 3138         int onoff;
 3139 {
 3140      qdpolling = onoff;
 3141 }
 3142 
 3143 
 3144 /*
 3145  *  Get a character from the LK201 (polled)
 3146  */
 3147 int
 3148 qdcngetc(dev)
 3149         dev_t dev;
 3150 {
 3151         short key;
 3152         char chr;
 3153         volatile struct duart *duart;
 3154 
 3155         duart = (struct duart *) qdmap[0].duart;
 3156 
 3157         /*
 3158         * Get a character from the keyboard. 
 3159         */
 3160 LOOP:
 3161         while (!(duart->statusA&RCV_RDY))
 3162                 ;
 3163 
 3164         key = duart->dataA;
 3165         key &= 0xFF;
 3166 
 3167         /*
 3168         * Check for various keyboard errors  */
 3169 
 3170         if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
 3171             key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
 3172                 printf("Keyboard error, code = %x\n", key);
 3173                 return(0);
 3174         }
 3175 
 3176         if (key < LK_LOWEST)
 3177                 return(0);
 3178 
 3179         /*
 3180          * See if its a state change key 
 3181          */
 3182         switch (key) {
 3183 
 3184         case LOCK:
 3185                 q_keyboard.lock ^= 0xffff;      /* toggle */
 3186                 if (q_keyboard.lock)
 3187                         led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
 3188                 else
 3189                         led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
 3190                 goto LOOP;
 3191 
 3192         case SHIFT:
 3193                 q_keyboard.shift ^= 0xFFFF;
 3194                 goto LOOP;
 3195 
 3196         case CNTRL:
 3197                 q_keyboard.cntrl ^= 0xFFFF;
 3198                 goto LOOP;
 3199 
 3200         case ALLUP:
 3201                 q_keyboard.cntrl = 0;
 3202                 q_keyboard.shift = 0;
 3203                 goto LOOP;
 3204 
 3205         case REPEAT:
 3206                 chr = q_keyboard.last;
 3207                 break;
 3208 
 3209                 /*
 3210                 * Test for cntrl characters. If set, see if the character
 3211                 * is elligible to become a control character. 
 3212                 */
 3213         default:
 3214 
 3215                 if (q_keyboard.cntrl) {
 3216                         chr = q_key[key];
 3217                         if (chr >= ' ' && chr <= '~')
 3218                             chr &= 0x1F;
 3219                 }
 3220                 else if ( q_keyboard.lock || q_keyboard.shift )
 3221                     chr = q_shift_key[key];
 3222                 else
 3223                         chr = q_key[key];
 3224                 break;
 3225         }
 3226 
 3227         if (chr < ' ' && chr > '~')     /* if input is non-displayable */
 3228                 return(0);              /* ..then pitch it! */
 3229 
 3230         q_keyboard.last = chr;
 3231 
 3232         /*
 3233         * Check for special function keys */
 3234 
 3235         if (chr & 0x80)                 /* pitch the function keys */
 3236                 return(0);
 3237         else
 3238                 return(chr);
 3239 
 3240 } /* qdgetc */
 3241 
 3242 /*
 3243  *  led_control()... twiddle LK-201 LED's
 3244  */
 3245 void
 3246 led_control(unit, cmd, led_mask)
 3247         int unit, cmd, led_mask;
 3248 {
 3249         int i;
 3250         volatile struct duart *duart;
 3251 
 3252         duart = (struct duart *)qdmap[unit].duart;
 3253 
 3254         for (i = 1000; i > 0; --i) {
 3255                 if (duart->statusA&XMT_RDY) {
 3256                         duart->dataA = cmd;
 3257                         break;
 3258                 }
 3259         }
 3260         for (i = 1000; i > 0; --i) {
 3261                 if (duart->statusA&XMT_RDY) {
 3262                         duart->dataA = led_mask;
 3263                         break;
 3264                 }
 3265         }
 3266         return;
 3267 
 3268 } /* led_control */
 3269 
 3270 /*
 3271  *  scroll_up()... move the screen up one character height
 3272  */
 3273 void
 3274 scroll_up(adder)
 3275         volatile struct adder *adder;
 3276 {
 3277         /*
 3278         * setup VIPER operand control registers  
 3279         */
 3280         (void)wait_status(adder, ADDRESS_COMPLETE);
 3281         write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
 3282         write_ID(adder, MASK_1, 0xFFFF);
 3283         write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
 3284         write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
 3285         write_ID(adder, SRC1_OCR_B,
 3286         EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
 3287         write_ID(adder, DST_OCR_B,
 3288         EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
 3289         /*
 3290          * load DESTINATION origin and vectors  
 3291          */
 3292         adder->fast_dest_dy = 0;
 3293         adder->slow_dest_dx = 0;
 3294         adder->error_1 = 0;
 3295         adder->error_2 = 0;
 3296         adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
 3297         adder->destination_x = 0;
 3298         adder->fast_dest_dx = 1024;
 3299         adder->destination_y = 0;
 3300         adder->slow_dest_dy = 864 - CHAR_HEIGHT;
 3301         /*
 3302          * load SOURCE origin and vectors  
 3303          */
 3304         adder->source_1_x = 0;
 3305         adder->source_1_dx = 1024;
 3306         adder->source_1_y = 0 + CHAR_HEIGHT;
 3307         adder->source_1_dy = 864 - CHAR_HEIGHT;
 3308         write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
 3309         adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
 3310         /*
 3311          * do a rectangle clear of last screen line 
 3312          */
 3313         write_ID(adder, MASK_1, 0xffff);
 3314         write_ID(adder, SOURCE, 0xffff);
 3315         write_ID(adder,DST_OCR_B,
 3316         (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
 3317         write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
 3318         adder->error_1 = 0;
 3319         adder->error_2 = 0;
 3320         adder->slow_dest_dx = 0;                /* set up the width of  */
 3321         adder->slow_dest_dy = CHAR_HEIGHT;      /* rectangle */
 3322         adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
 3323         (void)wait_status(adder, RASTEROP_COMPLETE);
 3324         adder->destination_x = 0;
 3325         adder->destination_y = 864 - CHAR_HEIGHT;
 3326         adder->fast_dest_dx = 1024;     /* set up the height    */
 3327         adder->fast_dest_dy = 0;        /* of rectangle         */
 3328         write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
 3329         adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
 3330 
 3331 } /* scroll_up */
 3332 
 3333 /*
 3334  *  init shared memory pointers and structures
 3335  */
 3336 void
 3337 init_shared(unit)
 3338         int unit;
 3339 {
 3340         volatile struct dga *dga;
 3341 
 3342         dga = (struct dga *) qdmap[unit].dga;
 3343 
 3344         /*
 3345         * initialize the event queue pointers and header */
 3346 
 3347         eq_header[unit] = (struct qdinput *)
 3348             ((((int)event_shared & ~(0x01FF)) + 512)
 3349                 + (EVENT_BUFSIZE * unit));
 3350         eq_header[unit]->curs_pos.x = 0;
 3351         eq_header[unit]->curs_pos.y = 0;
 3352         dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
 3353         dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
 3354         eq_header[unit]->curs_box.left = 0;
 3355         eq_header[unit]->curs_box.right = 0;
 3356         eq_header[unit]->curs_box.top = 0;
 3357         eq_header[unit]->curs_box.bottom = 0;
 3358         /*
 3359          * assign a pointer to the DMA I/O buffer for this QDSS. 
 3360          */
 3361         DMAheader[unit] = (struct DMAreq_header *)
 3362             (((int)(&DMA_shared[0] + 512) & ~0x1FF)
 3363                 + (DMAbuf_size * unit));
 3364         DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
 3365             + sizeof(struct DMAreq_header));
 3366         DMAheader[unit]->QBAreg = 0;
 3367         DMAheader[unit]->status = 0;
 3368         DMAheader[unit]->shared_size = DMAbuf_size;
 3369         DMAheader[unit]->used = 0;
 3370         DMAheader[unit]->size = 10;     /* default = 10 requests */
 3371         DMAheader[unit]->oldest = 0;
 3372         DMAheader[unit]->newest = 0;
 3373         /*
 3374         * assign a pointer to the scroll structure for this QDSS. 
 3375         */
 3376         scroll[unit] = (struct scroll *)
 3377             (((int)(&scroll_shared[0] + 512) & ~0x1FF)
 3378                 + (sizeof(struct scroll) * unit));
 3379         scroll[unit]->status = 0;
 3380         scroll[unit]->viper_constant = 0;
 3381         scroll[unit]->y_scroll_constant = 0;
 3382         scroll[unit]->y_offset = 0;
 3383         scroll[unit]->x_index_pending = 0;
 3384         scroll[unit]->y_index_pending = 0;
 3385         /*
 3386         * assign a pointer to the color map write buffer for this QDSS 
 3387         */
 3388         color_buf[unit] = (struct color_buf *)
 3389             (((int)(&color_shared[0] + 512) & ~0x1FF)
 3390                 + (COLOR_BUFSIZ * unit));
 3391         color_buf[unit]->status = 0;
 3392         color_buf[unit]->count = 0;
 3393 
 3394 } /* init_shared */
 3395 
 3396 /*
 3397  * init the ADDER, VIPER, bitmaps, & color map
 3398  */
 3399 void
 3400 setup_dragon(unit)
 3401         int unit;
 3402 {
 3403 
 3404         volatile struct adder *adder;
 3405         volatile struct dga *dga;
 3406         volatile short *memcsr;
 3407         int i;
 3408         short top;              /* clipping/scrolling boundaries */
 3409         short bottom;
 3410         short right;
 3411         short left;
 3412         volatile short *red;            /* color map pointers */
 3413         volatile short *green;
 3414         volatile short *blue;
 3415 
 3416         /*
 3417         * init for setup 
 3418         */
 3419         adder = (struct adder *) qdmap[unit].adder;
 3420         dga = (struct dga *) qdmap[unit].dga;
 3421         memcsr = (short *) qdmap[unit].memcsr;
 3422         dga->csr &= ~(DMA_IE | 0x700);  /* halt DMA and kill the intrpts */
 3423         *memcsr = SYNC_ON;              /* blank screen and turn off LED's */
 3424         adder->command = CANCEL;
 3425         /*
 3426         * set monitor timing 
 3427         */
 3428         adder->x_scan_count_0 = 0x2800;
 3429         adder->x_scan_count_1 = 0x1020;
 3430         adder->x_scan_count_2 = 0x003A;
 3431         adder->x_scan_count_3 = 0x38F0;
 3432         adder->x_scan_count_4 = 0x6128;
 3433         adder->x_scan_count_5 = 0x093A;
 3434         adder->x_scan_count_6 = 0x313C;
 3435         adder->sync_phase_adj = 0x0100;
 3436         adder->x_scan_conf = 0x00C8;
 3437         /*
 3438          * got a bug in secound pass ADDER! lets take care of it 
 3439          *
 3440          * normally, just use the code in the following bug fix code, but to
 3441          * make repeated demos look pretty, load the registers as if there was
 3442          * no bug and then test to see if we are getting sync 
 3443          */
 3444         adder->y_scan_count_0 = 0x135F;
 3445         adder->y_scan_count_1 = 0x3363;
 3446         adder->y_scan_count_2 = 0x2366;
 3447         adder->y_scan_count_3 = 0x0388;
 3448         /*
 3449          * if no sync, do the bug fix code 
 3450          */
 3451         if (wait_status(adder, VSYNC) == BAD) {
 3452                 /* first load all Y scan registers with very short frame and
 3453                  * wait for scroll service.  This guarantees at least one SYNC
 3454                  * to fix the pass 2 Adder initialization bug (synchronizes
 3455                  * XCINCH with DMSEEDH) 
 3456                  */
 3457                 adder->y_scan_count_0 = 0x01;
 3458                 adder->y_scan_count_1 = 0x01;
 3459                 adder->y_scan_count_2 = 0x01;
 3460                 adder->y_scan_count_3 = 0x01;
 3461                 /*
 3462                  * delay at least 1 full frame time 
 3463                  */
 3464                 (void)wait_status(adder, VSYNC);        
 3465                 (void)wait_status(adder, VSYNC);
 3466                 /*
 3467                  * now load the REAL sync values (in reverse order just to
 3468                  * be safe.  
 3469                  */
 3470                 adder->y_scan_count_3 = 0x0388;
 3471                 adder->y_scan_count_2 = 0x2366;
 3472                 adder->y_scan_count_1 = 0x3363;
 3473                 adder->y_scan_count_0 = 0x135F;
 3474         }
 3475         *memcsr = SYNC_ON | UNBLANK;    /* turn off leds and turn on video */
 3476         /*
 3477          * zero the index registers 
 3478          */
 3479         adder->x_index_pending = 0;
 3480         adder->y_index_pending = 0;
 3481         adder->x_index_new = 0;
 3482         adder->y_index_new = 0;
 3483         adder->x_index_old = 0;
 3484         adder->y_index_old = 0;
 3485         adder->pause = 0;
 3486         /*
 3487          * set rasterop mode to normal pen down 
 3488          */
 3489         adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
 3490         /*
 3491          * set the rasterop registers to a default values 
 3492          */
 3493         adder->source_1_dx = 1;
 3494         adder->source_1_dy = 1;
 3495         adder->source_1_x = 0;
 3496         adder->source_1_y = 0;
 3497         adder->destination_x = 0;
 3498         adder->destination_y = 0;
 3499         adder->fast_dest_dx = 1;
 3500         adder->fast_dest_dy = 0;
 3501         adder->slow_dest_dx = 0;
 3502         adder->slow_dest_dy = 1;
 3503         adder->error_1 = 0;
 3504         adder->error_2 = 0;
 3505         /*
 3506          * scale factor = UNITY 
 3507          */
 3508         adder->fast_scale = UNITY;
 3509         adder->slow_scale = UNITY;
 3510         /*
 3511          * set the source 2 parameters 
 3512          */
 3513         adder->source_2_x = 0;
 3514         adder->source_2_y = 0;
 3515         adder->source_2_size = 0x0022;
 3516         /*
 3517         * initialize plane addresses for eight vipers 
 3518         */
 3519         write_ID(adder, CS_UPDATE_MASK, 0x0001);
 3520         write_ID(adder, PLANE_ADDRESS, 0x0000);
 3521         write_ID(adder, CS_UPDATE_MASK, 0x0002);
 3522         write_ID(adder, PLANE_ADDRESS, 0x0001);
 3523         write_ID(adder, CS_UPDATE_MASK, 0x0004);
 3524         write_ID(adder, PLANE_ADDRESS, 0x0002);
 3525         write_ID(adder, CS_UPDATE_MASK, 0x0008);
 3526         write_ID(adder, PLANE_ADDRESS, 0x0003);
 3527         write_ID(adder, CS_UPDATE_MASK, 0x0010);
 3528         write_ID(adder, PLANE_ADDRESS, 0x0004);
 3529         write_ID(adder, CS_UPDATE_MASK, 0x0020);
 3530         write_ID(adder, PLANE_ADDRESS, 0x0005);
 3531         write_ID(adder, CS_UPDATE_MASK, 0x0040);
 3532         write_ID(adder, PLANE_ADDRESS, 0x0006);
 3533         write_ID(adder, CS_UPDATE_MASK, 0x0080);
 3534         write_ID(adder, PLANE_ADDRESS, 0x0007);
 3535         /*
 3536          * initialize the external registers. 
 3537          */
 3538         write_ID(adder, CS_UPDATE_MASK, 0x00FF);
 3539         write_ID(adder, CS_SCROLL_MASK, 0x00FF);
 3540         /*
 3541          * initialize resolution mode 
 3542          */
 3543         write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
 3544         write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
 3545         /*
 3546          * initialize viper registers 
 3547          */
 3548         write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
 3549         write_ID(adder, SCROLL_FILL, 0x0000);
 3550         /*
 3551          * set clipping and scrolling limits to full screen 
 3552          */
 3553         for (i = 1000, adder->status = 0; 
 3554              i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
 3555                 ;
 3556         if (i == 0)
 3557             printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
 3558         top = 0;
 3559         bottom = 2048;
 3560         left = 0;
 3561         right = 1024;
 3562         adder->x_clip_min = left;
 3563         adder->x_clip_max = right;
 3564         adder->y_clip_min = top;
 3565         adder->y_clip_max = bottom;
 3566         adder->scroll_x_min = left;
 3567         adder->scroll_x_max = right;
 3568         adder->scroll_y_min = top;
 3569         adder->scroll_y_max = bottom;
 3570         (void)wait_status(adder, VSYNC);        /* wait at LEAST 1 full frame */
 3571         (void)wait_status(adder, VSYNC);
 3572         adder->x_index_pending = left;
 3573         adder->y_index_pending = top;
 3574         adder->x_index_new = left;
 3575         adder->y_index_new = top;
 3576         adder->x_index_old = left;
 3577         adder->y_index_old = top;
 3578 
 3579         for (i = 1000, adder->status = 0; i > 0 && 
 3580              !(adder->status&ADDRESS_COMPLETE) ; --i)
 3581                 ;
 3582         if (i == 0)
 3583                printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
 3584 
 3585         write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
 3586         write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
 3587         /*
 3588         * set source and the mask register to all ones (ie: white) o
 3589         */
 3590         write_ID(adder, SOURCE, 0xFFFF);
 3591         write_ID(adder, MASK_1, 0xFFFF);
 3592         write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
 3593         write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
 3594         /*
 3595         * initialize Operand Control Register banks for fill command 
 3596         */
 3597         write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
 3598         write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
 3599         write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE   | NO_ID | NO_WAIT);
 3600         write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
 3601         write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
 3602         write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
 3603         /*
 3604         * init Logic Unit Function registers, (these are just common values,
 3605         * and may be changed as required).  
 3606         */
 3607         write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
 3608         write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
 3609                  INV_M1_M2);
 3610         write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
 3611         write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
 3612         /*
 3613         * load the color map for black & white 
 3614         */
 3615         for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
 3616                 ;
 3617 
 3618         if (i == 0)
 3619                 printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
 3620 
 3621         red = (short *) qdmap[unit].red;
 3622         green = (short *) qdmap[unit].green;
 3623         blue = (short *) qdmap[unit].blue;
 3624 
 3625         *red++ = 0x00;                  /* black */
 3626         *green++ = 0x00;
 3627         *blue++ = 0x00;
 3628 
 3629         *red-- = 0xFF;                  /* white */
 3630         *green-- = 0xFF;
 3631         *blue-- = 0xFF;
 3632 
 3633         /*
 3634         * set color map for mouse cursor 
 3635         */
 3636 
 3637         red += 254;
 3638         green += 254;
 3639         blue += 254;
 3640 
 3641         *red++ = 0x00;                  /* black */
 3642         *green++ = 0x00;
 3643         *blue++ = 0x00;
 3644 
 3645         *red = 0xFF;                    /* white */
 3646         *green = 0xFF;
 3647         *blue = 0xFF;
 3648 
 3649 } /* setup_dragon */
 3650 
 3651 /*
 3652  * Init the DUART and set defaults in input
 3653  */
 3654 void
 3655 setup_input(unit)
 3656         int unit;
 3657 {
 3658         volatile struct duart *duart;   /* DUART register structure pointer */
 3659         int i, bits;
 3660         char id_byte;
 3661 
 3662         duart = (struct duart *) qdmap[unit].duart;
 3663         duart->imask = 0;
 3664 
 3665         /*
 3666         * setup the DUART for kbd & pointing device 
 3667         */
 3668         duart->cmdA = RESET_M;  /* reset mode reg ptr for kbd */
 3669         duart->modeA = 0x13;    /* 8 bits, no parity, rcv IE, */
 3670                                 /* no RTS control,char error mode */
 3671         duart->modeA = 0x07;    /* 1 stop bit,CTS does not IE XMT */
 3672                                 /* no RTS control,no echo or loop */
 3673         duart->cmdB = RESET_M;  /* reset mode reg pntr for host */
 3674         duart->modeB = 0x07;    /* 8 bits, odd parity, rcv IE.. */
 3675                                 /* ..no RTS cntrl, char error mode */
 3676         duart->modeB = 0x07;    /* 1 stop bit,CTS does not IE XMT */
 3677                                 /* no RTS control,no echo or loop */
 3678         duart->auxctl = 0x00;   /* baud rate set 1 */
 3679         duart->clkselA = 0x99;  /* 4800 baud for kbd */
 3680         duart->clkselB = 0x99;  /* 4800 baud for mouse */
 3681 
 3682         /* reset everything for keyboard */
 3683 
 3684         for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
 3685                 duart->cmdA = bits;
 3686 
 3687         /* reset everything for host */
 3688 
 3689         for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
 3690                 duart->cmdB = bits;
 3691 
 3692         duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
 3693         duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
 3694 
 3695         /*
 3696         * init keyboard defaults (DUART channel A) 
 3697         */
 3698         for (i = 500; i > 0; --i) {
 3699                 if (duart->statusA&XMT_RDY) {
 3700                         duart->dataA = LK_DEFAULTS;
 3701                         break;
 3702                 }
 3703         }
 3704 
 3705         for (i = 100000; i > 0; --i) {
 3706                 if (duart->statusA&RCV_RDY) {
 3707                         break;
 3708                 }
 3709         }
 3710 
 3711         if (duart->dataA)       /* flush the ACK */
 3712                 ;               
 3713 
 3714         /*
 3715         * identify the pointing device 
 3716         */
 3717         for (i = 500; i > 0; --i) {
 3718                 if (duart->statusB&XMT_RDY) {
 3719                         duart->dataB = SELF_TEST;
 3720                         break;
 3721                 }
 3722         }
 3723 
 3724         /*
 3725         * wait for 1st byte of self test report */
 3726 
 3727         for (i = 100000; i > 0; --i) {
 3728                 if (duart->statusB&RCV_RDY) {
 3729                         break;
 3730                 }
 3731         }
 3732 
 3733         if (i == 0) {
 3734                 printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
 3735                        ,unit);
 3736                 goto OUT;
 3737         }
 3738 
 3739         if (duart->dataB)
 3740                 ;
 3741 
 3742         /*
 3743         * wait for ID byte of self test report  
 3744         */
 3745         for (i = 100000; i > 0; --i) {
 3746                 if (duart->statusB&RCV_RDY) {
 3747                         break;
 3748                 }
 3749         }
 3750 
 3751         if (i == 0) {
 3752                 printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
 3753                 goto OUT;
 3754         }
 3755 
 3756         id_byte = duart->dataB;
 3757 
 3758         /*
 3759         * wait for other bytes to come in  
 3760         */
 3761         for (i = 100000; i > 0; --i) {
 3762                 if (duart->statusB & RCV_RDY) {
 3763                         if (duart->dataB)
 3764                                 ;
 3765                         break;
 3766                 }
 3767         }
 3768         if (i == 0) {
 3769                 printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
 3770                 goto OUT;
 3771         }
 3772         for (i = 100000; i > 0; --i) {
 3773                 if (duart->statusB&RCV_RDY) {
 3774                         if (duart->dataB)
 3775                                 ;
 3776                         break;
 3777                 }
 3778         }
 3779         if (i == 0) {
 3780                 printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
 3781                 goto OUT;
 3782         }
 3783         /*
 3784         * flag pointing device type and set defaults 
 3785         */
 3786         for (i=100000; i>0; --i)
 3787                 ;               /*XXX*/
 3788 
 3789         if ((id_byte & 0x0F) != TABLET_ID) {
 3790                 qdflags[unit].pntr_id = MOUSE_ID;
 3791 
 3792                 for (i = 500; i > 0; --i) {
 3793                         if (duart->statusB&XMT_RDY) {
 3794                                 duart->dataB = INC_STREAM_MODE;
 3795                                 break;
 3796                         }
 3797                 }
 3798         } 
 3799         else {
 3800                 qdflags[unit].pntr_id = TABLET_ID;
 3801 
 3802                 for (i = 500; i > 0; --i) {
 3803                         if (duart->statusB&XMT_RDY) {
 3804                                 duart->dataB = T_STREAM;
 3805                                 break;
 3806                         }
 3807                 }
 3808         }
 3809 OUT:
 3810         duart->imask = qdflags[unit].duart_imask;
 3811 
 3812 } /* setup_input */
 3813 
 3814 /*
 3815  * delay for at least one display frame time
 3816  *
 3817  *      return: BAD means that we timed out without ever seeing the
 3818  *                    vertical sync status bit
 3819  *              GOOD otherwise
 3820  */
 3821 int
 3822 wait_status(adder, mask)
 3823         volatile struct adder *adder;
 3824         int mask;
 3825 {
 3826         int i;
 3827 
 3828         for (i = 10000, adder->status = 0 ; i > 0  &&  
 3829              !(adder->status&mask) ; --i)
 3830                 ;
 3831 
 3832         if (i == 0) {
 3833                 printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
 3834                 return(BAD);
 3835         }
 3836 
 3837         return(GOOD);
 3838 
 3839 } /* wait_status */
 3840 
 3841 /*
 3842  * write out onto the ID bus
 3843  */
 3844 void
 3845 write_ID(adder, adrs, data)
 3846         volatile struct adder *adder;
 3847         short adrs;
 3848         short data;
 3849 {
 3850         int i;
 3851 
 3852         for (i = 100000, adder->status = 0 ; 
 3853               i > 0  &&  !(adder->status&ADDRESS_COMPLETE) ; --i)
 3854                 ;
 3855 
 3856         if (i == 0)
 3857                 goto ERR;
 3858 
 3859         for (i = 100000, adder->status = 0 ; 
 3860               i > 0  &&  !(adder->status&TX_READY) ; --i)
 3861                 ;
 3862 
 3863         if (i > 0) {
 3864                 adder->id_data = data;
 3865                 adder->command = ID_LOAD | adrs;
 3866                 return ;
 3867         }
 3868 
 3869 ERR:
 3870         printf("write_ID: timeout trying to write to VIPER\n");
 3871         return ;
 3872 
 3873 } /* write_ID */

Cache object: cf765eee1bcf06324e80229dbdd33dcb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.