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

Cache object: 4e5f39c5d6f7c19a92c698447381ba29


[ 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.