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

Cache object: 7f59365b91e5521530139b8771d431ef


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