📄 qd.c
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)qd.c 7.1 (Berkeley) 6/28/91 *//************************************************************************* ** Copyright (c) 1985-1988 by ** Digital Equipment Corporation, Maynard, MA ** All rights reserved. ** ** This software is furnished under a license and may be used and ** copied only in accordance with the terms of such license and ** with the inclusion of the above copyright notice. This ** software or any other copies thereof may not be provided or ** otherwise made available to any other person. No title to and ** ownership of the software is hereby transferred. ** ** The information in this software is subject to change without ** notice and should not be construed as a commitment by Digital ** Equipment Corporation. ** ** Digital assumes no responsibility for the use or reliability ** of its software on equipment which is not supplied by Digital. ** **************************************************************************//* * qd.c - QDSS display driver for VAXSTATION-II GPX workstation */#include "qd.h"#if NQD > 0#include "../include/pte.h"#include "../include/mtpr.h"#include "sys/param.h"#include "../include/cpu.h"#include "sys/conf.h"#include "sys/user.h"#include "qdioctl.h"#include "sys/tty.h"#include "sys/map.h"#include "sys/buf.h"#include "sys/vm.h"#include "sys/clist.h"#include "sys/file.h"#include "sys/uio.h"#include "sys/kernel.h"#include "sys/exec.h"#include "sys/proc.h"#include "ubareg.h"#include "ubavar.h"#include "sys/syslog.h"#include "qduser.h" /* definitions shared with user level client */#include "qdreg.h" /* QDSS device register structures *//* * QDSS driver status flags for tracking operational state */struct qdflags { u_int inuse; /* which minor dev's are in use now */ u_int config; /* I/O page register content */ u_int mapped; /* user mapping status word */ u_int kernel_loop; /* if kernel console is redirected */ u_int user_dma; /* DMA from user space in progress */ u_short pntr_id; /* type code of pointing device */ u_short duart_imask; /* shadowing for duart intrpt mask reg */ u_short adder_ie; /* shadowing for adder intrpt enbl reg */ u_short curs_acc; /* cursor acceleration factor */ u_short curs_thr; /* cursor acceleration threshold level */ u_short tab_res; /* tablet resolution factor */ u_short selmask; /* mask for active qd select entries */};/* * bit definitions for 'inuse' entry */#define CONS_DEV 0x01#define GRAPHIC_DEV 0x04/* * bit definitions for 'mapped' member of flag structure */#define MAPDEV 0x01 /* hardware is mapped */#define MAPDMA 0x02 /* DMA buffer mapped */#define MAPEQ 0x04 /* event queue buffer mapped */#define MAPSCR 0x08 /* scroll param area mapped */#define MAPCOLOR 0x10 /* color map writing buffer mapped *//* * bit definitions for 'selmask' member of qdflag structure */#define SEL_READ 0x01 /* read select is active */#define SEL_WRITE 0x02 /* write select is active *//* * constants used in shared memory operations */#define EVENT_BUFSIZE 1024 /* # of bytes per device's event buffer */#define MAXEVENTS ( (EVENT_BUFSIZE - sizeof(struct qdinput)) \ / sizeof(struct _vs_event) )#define DMA_BUFSIZ (1024 * 10)#define COLOR_BUFSIZ ((sizeof(struct color_buf) + 512) & ~0x01FF)/* * reference to an array of "uba_device" structures built by the auto * configuration program. The uba_device structure decribes the device * sufficiently for the driver to talk to it. The auto configuration code * fills in the uba_device structures (located in ioconf.c) from user * maintained info. */struct uba_device *qdinfo[NQD]; /* array of pntrs to each QDSS's */struct tty qd_tty[NQD*4]; /* teletype structures for each.. */extern char qvmem[][128*NBPG];extern struct pte QVmap[][128];#define CHUNK (64 * 1024)#define QMEMSIZE (1024 * 1024 * 4) /* 4 meg *//* * static storage used by multiple functions in this code */int Qbus_unmap[NQD]; /* Qbus mapper release code */struct qdflags qdflags[NQD]; /* QDSS device status flags */struct qdmap qdmap[NQD]; /* QDSS register map structure */caddr_t qdbase[NQD]; /* base address of each QDSS unit */struct buf qdbuf[NQD]; /* buf structs used by strategy */short qdopened[NQD]; /* graphics device is open exclusive use *//* * the array "event_shared[]" is made up of a number of event queue buffers * equal to the number of QDSS's configured into the running kernel (NQD). * Each event queue buffer begins with an event queue header (struct qdinput) * followed by a group of event queue entries (struct _vs_event). The array * "*eq_header[]" is an array of pointers to the start of each event queue * buffer in "event_shared[]". */#define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)char event_shared[EQSIZE]; /* reserve space for event bufs */struct qdinput *eq_header[NQD]; /* event queue header pntrs *//* * This allocation method reserves enough memory pages for NQD shared DMA I/O * buffers. Each buffer must consume an integral number of memory pages to * guarantee that a following buffer will begin on a page boundary. Also, * enough space is allocated so that the FIRST I/O buffer can start at the * 1st page boundary after "&DMA_shared". Page boundaries are used so that * memory protections can be turned on/off for individual buffers. */#define IOBUFSIZE ((DMA_BUFSIZ * NQD) + 512)char DMA_shared[IOBUFSIZE]; /* reserve I/O buffer space */struct DMAreq_header *DMAheader[NQD]; /* DMA buffer header pntrs *//* * The driver assists a client in scroll operations by loading dragon * registers from an interrupt service routine. The loading is done using * parameters found in memory shrade between the driver and it's client. * The scroll parameter structures are ALL loacted in the same memory page * for reasons of memory economy. */char scroll_shared[2 * 512]; /* reserve space for scroll structs */struct scroll *scroll[NQD]; /* pointers to scroll structures *//* * the driver is programmable to provide the user with color map write * services at VSYNC interrupt time. At interrupt time the driver loads * the color map with any user-requested load data found in shared memory */#define COLOR_SHARED ((COLOR_BUFSIZ * NQD) + 512)char color_shared[COLOR_SHARED]; /* reserve space: color bufs */struct color_buf *color_buf[NQD]; /* pointers to color bufs *//* * mouse input event structures */struct mouse_report last_rep[NQD];struct mouse_report current_rep[NQD];struct proc *qdrsel[NQD]; /* process waiting for select */struct _vs_cursor cursor[NQD]; /* console cursor */int qdcount = 0; /* count of successfully probed qd's */int nNQD = NQD;int DMAbuf_size = DMA_BUFSIZ;int QDlast_DMAtype; /* type of the last DMA operation */#define QDSSMAJOR 41 /* QDSS major device number *//* * macro to get system time. Used to time stamp event queue entries */#define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))int qdprobe();int qdattach();int qddint(); /* DMA gate array intrpt service */int qdaint(); /* Dragon ADDER intrpt service */int qdiint();u_short qdstd[] = { 0 };struct uba_driver qddriver = { qdprobe, /* device probe entry */ 0, /* no slave device */ qdattach, /* device attach entry */ 0, /* no "fill csr/ba to start" */ qdstd, /* device addresses */ "qd", /* device name string */ qdinfo /* ptr to QDSS's uba_device struct */};#define QDPRIOR (PZERO-1) /* must be negative */#define FALSE 0#define TRUE ~FALSE#define BAD -1#define GOOD 0/* * macro to create a system virtual page number from system virtual adrs */#define VTOP(x) (((int)x & ~0xC0000000) >> PGSHIFT)/* * QDSS register address offsets from start of QDSS address space */#define QDSIZE (52 * 1024) /* size of entire QDSS foot print */#define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */#define TMPSTART 0x8000 /* offset of template RAM from base adrs */#define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */#define REGSTART 0xC000 /* offset of reg pages from base adrs */#define ADDER (REGSTART+0x000)#define DGA (REGSTART+0x200)#define DUART (REGSTART+0x400)#define MEMCSR (REGSTART+0x800)#define CLRSIZE (3 * 512) /* color map size */#define CLRSTART (REGSTART+0xA00) /* color map start offset from base *//* 0x0C00 really */#define RED (CLRSTART+0x000)#define BLUE (CLRSTART+0x200)#define GREEN (CLRSTART+0x400)/* * QDSS minor device numbers. The *real* minor device numbers are in * the bottom two bits of the major/minor device spec. Bits 2 and up are * used to specify the QDSS device number (ie: which one?) */#define CONS 0#define GRAPHIC 2/* * console cursor bitmap (white block cursor) */short cons_cursor[32] = { /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF};/* * constants used in font operations */#define CHARS 190 /* # of chars in the font */#define CHAR_HEIGHT 15 /* char height in pixels */#define CHAR_WIDTH 8 /* char width in pixels*/#define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */#define ROWS CHAR_HEIGHT#define FONT_X 0 /* font's off screen adrs */#define FONT_Y (2048 - CHAR_HEIGHT)/* Offset to second row characters (XXX - should remove) */#define FONT_OFFSET ((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)extern char q_font[]; /* reference font object code */extern u_short q_key[]; /* reference key xlation tables */extern u_short q_shift_key[];extern char *q_special[];/* * definitions for cursor acceleration reporting */#define ACC_OFF 0x01 /* acceleration is inactive *//* * virtual console support. */extern (*v_putc)();#ifdef KADBextern (*v_getc)();extern (*v_poll)();#endifextern struct cdevsw *consops;int qdputc();int qdgetc();int qdpoll();int qdstart();int qdpolling = 0;/* * LK-201 state storage for input console keyboard conversion to ASCII */struct q_keyboard { int shift; /* state variables */ int cntrl; int lock; int lastcode; /* last keycode typed */ unsigned kup[8]; /* bits for each keycode*/ unsigned dkeys[8]; /* down/up mode keys */ char last; /* last character */} q_keyboard;/* * tty settings on first open */#define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)#define OFLAG (OPOST|OXTABS|ONLCR)#define LFLAG (ISIG|ICANON|ECHO|IEXTEN)#define CFLAG (PARENB|CREAD|CS7|CLOCAL)/* * Init QDSS as console (before probe routine) */qdcons_init(){ register unit; caddr_t phys_adr; /* physical QDSS base adrs */ u_int mapix; /* index into QVmap[] array */ struct percpu *pcpu; /* pointer to cpusw structure */ register struct qbus *qb; u_short *qdaddr; /* address of QDSS IO page CSR */ u_short *devptr; /* vitual device space */ extern cnputc();#define QDSSCSR 0x1F00 if (v_putc != cnputc) return 0; unit = 0; /* * find the cpusw entry that matches this machine. */ for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++) ; if (pcpu == NULL) return 0; if (pcpu->pc_io->io_type != IO_QBUS) return 0; /* * Map device registers - the last 8K of qvmem. */ qb = (struct qbus *)pcpu->pc_io->io_details; ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize, UBAIOPAGES * NBPG); devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG)); qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR)); if (badaddr((caddr_t)qdaddr, sizeof(short))) return 0; /* * Map q-bus memory used by qdss. (separate map) */ mapix = QMEMSIZE - (CHUNK * (unit + 1)); phys_adr = qb->qb_maddr + mapix; ioaccess(phys_adr, QVmap[0], (CHUNK*NQD)); /* * tell QDSS which Q memory address base to decode * (shifted right 16 bits - its in 64K units) */ *qdaddr = (u_short)((int)mapix >> 16); qdflags[unit].config = *(u_short *)qdaddr; /* * load qdmap struct with the virtual addresses of the QDSS elements */ qdbase[unit] = (caddr_t) (qvmem[0]); qdmap[unit].template = qdbase[unit] + TMPSTART; qdmap[unit].adder = qdbase[unit] + ADDER; qdmap[unit].dga = qdbase[unit] + DGA; qdmap[unit].duart = qdbase[unit] + DUART; qdmap[unit].memcsr = qdbase[unit] + MEMCSR; qdmap[unit].red = qdbase[unit] + RED; qdmap[unit].blue = qdbase[unit] + BLUE; qdmap[unit].green = qdbase[unit] + GREEN; qdflags[unit].duart_imask = 0; /* init shadow variables */ /* * init the QDSS */ /* printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n", (char *)qdbase[0], qdmap[0].memcsr); */ *(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */ cursor[unit].x = 0; cursor[unit].y = 0; init_shared(unit); /* init shared memory */ setup_dragon(unit); /* init the ADDER/VIPER stuff */ clear_qd_screen(unit); /* clear the screen */ ldfont(unit); /* load the console font */ ldcursor(unit, cons_cursor); /* load default cursor map */ setup_input(unit); /* init the DUART */ v_putc = qdputc; /* kernel console output to qdss */#ifdef KADB v_getc = qdgetc; /* kernel console input from qdss */ v_poll = qdpoll; /* kdb hook to disable char intr */#endif consops = &cdevsw[QDSSMAJOR]; /* virtual console is qdss */ return 1;} /* qdcons_init *//* * Configure QDSS into Q memory and make it intrpt. * * side effects: QDSS gets mapped into Qbus memory space at the first * vacant 64kb boundary counting back from the top of * Qbus memory space (qvmem+4mb) * * return: QDSS bus request level and vector address returned in * registers by UNIX convention. * */qdprobe(reg) caddr_t reg; /* character pointer to the QDSS I/O page register */{ register int br, cvec; register int unit; struct dga *dga; /* pointer to gate array structure */ int vector;#ifdef notdef int *ptep; /* page table entry pointer */ caddr_t phys_adr; /* physical QDSS base adrs */ u_int mapix;#endif#ifdef lint br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD; qddint(0); qdaint(0); qdiint(0); (void)qdgetc();#endif /* * calculate board unit number from I/O page register address */ unit = (int) (((int)reg >> 1) & 0x0007); /* * QDSS regs must be mapped to Qbus memory space at a 64kb * physical boundary. The Qbus memory space is mapped into * the system memory space at config time. After config * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs * of the start of Qbus memory. The Qbus memory page table * is found via an array of pte ptrs called "QVmap[]" (ubavar.h) * which is also loaded at config time. These are the * variables used below to find a vacant 64kb boundary in * Qbus memory, and load it's corresponding physical adrs * into the QDSS's I/O page CSR. */ /* * Only if QD is the graphics device. */ /* if this QDSS is NOT the console, then do init here.. */ if (unit != 0) { printf("qd: can't support two qdss's (yet)\n");#ifdef notdef /* can't test */ if (v_consputc != qdputc || unit != 0) { /* * read QDSS config info
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -