-/* $OpenBSD: if_de.c,v 1.10 1997/09/10 08:28:39 maja Exp $ */
+/* $OpenBSD: if_de.c,v 1.11 2000/04/27 03:14:42 bjc Exp $ */
/* $NetBSD: if_de.c,v 1.27 1997/04/19 15:02:29 ragge Exp $ */
/*
#include <machine/sid.h>
#include <net/if.h>
-#include <net/netisr.h>
-#include <net/route.h>
+#include <net/if_dl.h>
#ifdef INET
#include <netinet/in.h>
struct device ds_dev; /* Configuration common part */
struct arpcom ds_ac; /* Ethernet common part */
struct dedevice *ds_vaddr; /* Virtual address of this interface */
-#define ds_if ds_ac.ac_if /* network-visible interface */
-#define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */
+#define ds_if ds_ac.ac_if /* network-visible interface */
int ds_flags;
#define DSF_RUNNING 2 /* board is enabled */
#define DSF_SETADDR 4 /* physical address is changed */
struct dedevice *addr;
char *c;
int csr1;
+ u_int8_t myaddr[ETHER_ADDR_LEN];
addr = (struct dedevice *)ua->ua_addr;
ds->ds_vaddr = addr;
(void)dewait(ds, "read addr ");
ubarelse((void *)ds->ds_dev.dv_parent, &ds->ds_ubaddr);
- bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
- sizeof (ds->ds_addr));
+ bcopy((caddr_t)&ds->ds_pcbb.pcbb2, myaddr, sizeof (myaddr));
printf("%s: hardware address %s\n", ds->ds_dev.dv_xname,
- ether_sprintf(ds->ds_addr));
+ ether_sprintf(myaddr));
ifp->if_ioctl = deioctl;
ifp->if_start = destart;
ds->ds_deuba.iff_flags = UBA_CANTWAIT;
return;
if ((ifp->if_flags & IFF_RUNNING) == 0) {
if (if_ubaminit(&ds->ds_deuba, (void *)ds->ds_dev.dv_parent,
- sizeof (struct ether_header), (int)btoc(ETHERMTU),
+ sizeof (struct ether_header), (int)vax_btoc(ETHERMTU),
ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) {
printf("%s: can't initialize\n", ds->ds_dev.dv_xname);
ds->ds_if.if_flags &= ~IFF_UP;
destart(&ds->ds_if); /* queue output packets */
ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */
if (ds->ds_flags & DSF_SETADDR)
- de_setaddr(ds->ds_addr, ds);
+ de_setaddr(ds->ds_ac.ac_enaddr, ds);
addr->pclow = CMD_START | PCSR0_INTE;
splx(s);
}
register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
if (ns_nullhost(*ina))
- ina->x_host = *(union ns_host *)(ds->ds_addr);
+ ina->x_host =
+ *(union ns_host *)ds->ds_ac.ac_enaddr;
else
de_setaddr(ina->x_host.c_host, ds);
break;
addr->pclow = PCSR0_INTE|CMD_GETCMD;
if (dewait(ds, "address change") == 0) {
ds->ds_flags |= DSF_SETADDR;
- bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6);
+ bcopy((caddr_t) physaddr, ds->ds_ac.ac_enaddr, 6);
}
}
char *fn;
{
volatile struct dedevice *addr = ds->ds_vaddr;
- register csr0;
+ register int csr0;
while ((addr->pcsr0 & PCSR0_INTR) == 0)
;
}
int
-dematch(parent, match, aux)
+dematch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ void *cf, *aux;
{
struct uba_attach_args *ua = aux;
volatile struct dedevice *addr = (struct dedevice *)ua->ua_addr;
-/* $OpenBSD: if_le.c,v 1.4 1998/09/16 22:41:19 jason Exp $ */
-/* $NetBSD: if_le.c,v 1.8 1997/04/21 22:04:23 ragge Exp $ */
+/* $OpenBSD: if_le.c,v 1.5 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_le.c,v 1.14 1999/08/14 18:40:23 ragge Exp $ */
-/* #define LE_CHIP_IS_POKEY /* does VS2000 need this ??? */
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
/*-
- * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
#include <sys/device.h>
#include <sys/reboot.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
#include <net/if.h>
+#include <net/if_media.h>
#if INET
#include <netinet/in.h>
-#include <netinet/if_ether.h>
#endif
+#include <netinet/if_ether.h>
-#include <net/if_media.h>
-
-/*
- * This would be nice, but it's not yet there...
- *
- * #include <machine/autoconf.h>
- */
-
-#include <machine/pte.h>
#include <machine/cpu.h>
-#include <machine/mtpr.h>
-#include <machine/uvax.h>
-#include <machine/ka410.h>
-#include <machine/vsbus.h>
+#include <machine/nexus.h>
#include <machine/rpb.h>
+#include <machine/scb.h>
#include <dev/ic/am7990reg.h>
-#define LE_NEED_BUF_CONTIG
#include <dev/ic/am7990var.h>
-#include <dev/tc/if_levar.h>
-
-#define xdebug(x)
-
-#ifdef LE_CHIP_IS_POKEY
-/*
- * access LANCE registers and double-check their contents
- */
-#define wbflush() /* do nothing */
-void lewritereg();
-#define LERDWR(cntl, src, dst) { (dst) = (src); wbflush(); }
-#define LEWREG(src, dst) lewritereg(&(dst), (src))
-#endif
-
-#define LE_IOSIZE 64*1024 /* 64K of real-mem are reserved and already */
-extern void *le_iomem; /* mapped into virt-mem by cpu_steal_pages */
-extern u_long le_ioaddr; /* le_iomem is virt, le_ioaddr is phys */
-
-#define LE_SOFTC(unit) le_cd.cd_devs[unit]
-#define LE_DELAY(x) DELAY(x)
+#define ETHER_MIN_LEN 64 /* minimum frame length, including CRC */
+#define LEVEC 0xd4 /* Interrupt vector on 3300/3400 */
-int lematch __P((struct device *, void *, void *));
-void leattach __P((struct device *, struct device *, void *));
-
-int leintr __P((void *sc));
-
-struct cfattach le_ca = {
- sizeof(struct le_softc), lematch, leattach
+struct le_softc {
+ struct am7990_softc sc_am7990; /* Must be first */
+ volatile u_short *sc_rap;
+ volatile u_short *sc_rdp;
};
-hide void lewrcsr __P ((struct am7990_softc *, u_int16_t, u_int16_t));
-hide u_int16_t lerdcsr __P ((struct am7990_softc *, u_int16_t));
+int le_ibus_match __P((struct device *, void *, void *));
+void le_ibus_attach __P((struct device *, struct device *, void *));
+void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t));
+void lance_copytobuf_gap2 __P((struct am7990_softc *, void *, int, int));
+void lance_copyfrombuf_gap2 __P((struct am7990_softc *, void *, int, int));
+void lance_zerobuf_gap2 __P((struct am7990_softc *, int, int));
+void leintr __P((void *));
+
+struct cfattach le_ibus_ca = {
+ sizeof(struct le_softc), le_ibus_match, le_ibus_attach
+};
-hide void
-lewrcsr(sc, port, val)
- struct am7990_softc *sc;
+void
+lewrcsr(ls, port, val)
+ struct am7990_softc *ls;
u_int16_t port, val;
{
- struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
-
-#ifdef LE_CHIP_IS_POKEY
- LEWREG(port, ler1->ler1_rap);
- LERDWR(port, val, ler1->ler1_rdp);
-#else
- ler1->ler1_rap = port;
- ler1->ler1_rdp = val;
-#endif
+ struct le_softc *sc = (void *)ls;
+
+ *sc->sc_rap = port;
+ *sc->sc_rdp = val;
}
-hide u_int16_t
-lerdcsr(sc, port)
- struct am7990_softc *sc;
+u_int16_t
+lerdcsr(ls, port)
+ struct am7990_softc *ls;
u_int16_t port;
{
- struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
- u_int16_t val;
-
-#ifdef LE_CHIP_IS_POKEY
- LEWREG(port, ler1->ler1_rap);
- LERDWR(0, ler1->ler1_rdp, val);
-#else
- ler1->ler1_rap = port;
- val = ler1->ler1_rdp;
-#endif
- return (val);
-}
+ struct le_softc *sc = (void *)ls;
-integrate void
-lehwinit(sc)
- struct am7990_softc *sc;
-{
+ *sc->sc_rap = port;
+ return *sc->sc_rdp;
}
int
-lematch(parent, match, aux)
+le_ibus_match(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ void *cf;
+ void *aux;
{
- struct cfdata *cf = match;
- struct confargs *ca = aux;
-
- /*
- * There could/should be more checks, but for now...
- */
- if (strcmp(ca->ca_name, "le") &&
- strcmp(ca->ca_name, "am7990") &&
- strcmp(ca->ca_name, "AM7990"))
- return (0);
+ struct bp_conf *bp = aux;
- return (1);
+ if (strcmp("lance", bp->type))
+ return 0;
+ return 1;
}
-/*
- *
- */
void
-leattach(parent, self, aux)
+le_ibus_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- register struct le_softc *sc = (void *)self;
- struct confargs *ca = aux;
- u_char *cp; /* pointer to MAC address */
- int i;
+ struct le_softc *sc = (void *)self;
+ int *lance_addr;
+ int i, vec, br;
- sc->sc_r1 = (void*)uvax_phys2virt(ca->ca_ioaddr);
+ sc->sc_rdp = (short *)vax_map_physmem(0x20084400, 1);
+ sc->sc_rap = sc->sc_rdp + 2;
- sc->sc_am7990.sc_conf3 = 0;
- sc->sc_am7990.sc_mem = le_iomem;
- sc->sc_am7990.sc_addr = le_ioaddr;
- sc->sc_am7990.sc_memsize = LE_IOSIZE;
- sc->sc_am7990.sc_wrcsr = lewrcsr;
+ /*
+ * Set interrupt vector, by forcing an interrupt.
+ */
+ scb_vecref(0, 0); /* Clear vector ref */
+ *sc->sc_rap = LE_CSR0;
+ *sc->sc_rdp = LE_C0_STOP;
+ DELAY(100);
+ *sc->sc_rdp = LE_C0_INIT|LE_C0_INEA;
+ DELAY(100000);
+ i = scb_vecref(&vec, &br);
+ if (i == 0 || vec == 0)
+ return;
+ scb_vecalloc(vec, (void *)am7990_intr, sc, SCB_ISTACK);
+
+ printf(": vec %o ipl %x\n%s", vec, br, self->dv_xname);
+ /*
+ * MD functions.
+ */
sc->sc_am7990.sc_rdcsr = lerdcsr;
- sc->sc_am7990.sc_hwinit = lehwinit;
+ sc->sc_am7990.sc_wrcsr = lewrcsr;
sc->sc_am7990.sc_nocarrier = NULL;
- xdebug(("leattach: mem=%x, addr=%x, size=%x (%d)\n",
- sc->sc_am7990.sc_mem, sc->sc_am7990.sc_addr,
- sc->sc_am7990.sc_memsize, sc->sc_am7990.sc_memsize));
+ sc->sc_am7990.sc_mem =
+ (void *)uvm_km_valloc(kernel_map, (128 * 1024));
+ if (sc->sc_am7990.sc_mem == 0)
+ return;
+
+ ioaccess((vaddr_t)sc->sc_am7990.sc_mem, 0x20120000,
+ (128 * 1024) >> VAX_PGSHIFT);
- sc->sc_am7990.sc_copytodesc = am7990_copytobuf_contig;
- sc->sc_am7990.sc_copyfromdesc = am7990_copyfrombuf_contig;
- sc->sc_am7990.sc_copytobuf = am7990_copytobuf_contig;
- sc->sc_am7990.sc_copyfrombuf = am7990_copyfrombuf_contig;
- sc->sc_am7990.sc_zerobuf = am7990_zerobuf_contig;
+
+ sc->sc_am7990.sc_addr = 0;
+ sc->sc_am7990.sc_memsize = (64 * 1024);
+
+ sc->sc_am7990.sc_copytodesc = lance_copytobuf_gap2;
+ sc->sc_am7990.sc_copyfromdesc = lance_copyfrombuf_gap2;
+ sc->sc_am7990.sc_copytobuf = lance_copytobuf_gap2;
+ sc->sc_am7990.sc_copyfrombuf = lance_copyfrombuf_gap2;
+ sc->sc_am7990.sc_zerobuf = lance_zerobuf_gap2;
/*
* Get the ethernet address out of rom
*/
- for (i = 0; i < sizeof(sc->sc_am7990.sc_arpcom.ac_enaddr); i++) {
- int *eaddr = (void*)uvax_phys2virt(ca->ca_enaddr);
- sc->sc_am7990.sc_arpcom.ac_enaddr[i] = (u_char)eaddr[i];
- }
+ lance_addr = (int *)vax_map_physmem(0x20084200, 1);
+ for (i = 0; i < 6; i++)
+ sc->sc_am7990.sc_arpcom.ac_enaddr[i] = (u_char)lance_addr[i];
+ vax_unmap_physmem((vaddr_t)lance_addr, 1);
- bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, IFNAMSIZ);
+ bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname,
+ IFNAMSIZ);
am7990_config(&sc->sc_am7990);
-#ifdef LEDEBUG
- sc->sc_am7990.sc_debug = LEDEBUG;
-#endif
-
- vsbus_intr_register(ca, am7990_intr, &sc->sc_am7990);
- vsbus_intr_enable(ca);
-
/*
* Register this device as boot device if we booted from it.
* This will fail if there are more than one le in a machine,
booted_from = self;
}
-#ifdef LE_CHIP_IS_POKEY
/*
- * Write a lance register port, reading it back to ensure success. This seems
- * to be necessary during initialization, since the chip appears to be a bit
- * pokey sometimes.
+ * gap2: two bytes of data followed by two bytes of pad.
+ *
+ * Buffers must be 4-byte aligned. The code doesn't worry about
+ * doing an extra byte.
*/
+
void
-lewritereg(regptr, val)
- register volatile u_short *regptr;
- register u_short val;
+lance_copytobuf_gap2(sc, fromv, boff, len)
+ struct am7990_softc *sc;
+ void *fromv;
+ int boff;
+ register int len;
{
- register int i = 0;
-
- while (*regptr != val) {
- *regptr = val;
- wbflush();
- if (++i > 10000) {
- printf("le: Reg did not settle (to x%x): x%x\n", val,
- *regptr);
- return;
- }
- DELAY(100);
+ volatile caddr_t buf = sc->sc_mem;
+ register caddr_t from = fromv;
+ register volatile u_int16_t *bptr;
+
+ if (boff & 0x1) {
+ /* handle unaligned first byte */
+ bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+ *bptr = (*from++ << 8) | (*bptr & 0xff);
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_int16_t *)buf) + boff;
+ while (len > 1) {
+ *bptr = (from[1] << 8) | (from[0] & 0xff);
+ bptr += 2;
+ from += 2;
+ len -= 2;
}
+ if (len == 1)
+ *bptr = (u_int16_t)*from;
+}
+
+void
+lance_copyfrombuf_gap2(sc, tov, boff, len)
+ struct am7990_softc *sc;
+ void *tov;
+ int boff, len;
+{
+ volatile caddr_t buf = sc->sc_mem;
+ register caddr_t to = tov;
+ register volatile u_int16_t *bptr;
+ register u_int16_t tmp;
+
+ if (boff & 0x1) {
+ /* handle unaligned first byte */
+ bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+ *to++ = (*bptr >> 8) & 0xff;
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_int16_t *)buf) + boff;
+ while (len > 1) {
+ tmp = *bptr;
+ *to++ = tmp & 0xff;
+ *to++ = (tmp >> 8) & 0xff;
+ bptr += 2;
+ len -= 2;
+ }
+ if (len == 1)
+ *to = *bptr & 0xff;
+}
+
+void
+lance_zerobuf_gap2(sc, boff, len)
+ struct am7990_softc *sc;
+ int boff, len;
+{
+ volatile caddr_t buf = sc->sc_mem;
+ register volatile u_int16_t *bptr;
+
+ if ((unsigned)boff & 0x1) {
+ bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+ *bptr &= 0xff;
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_int16_t *)buf) + boff;
+ while (len > 0) {
+ *bptr = 0;
+ bptr += 2;
+ len -= 2;
+ }
+}
+
+void
+leintr(arg)
+ void *arg;
+{
+ int unit = (int)arg;
+ am7990_intr(le_cd.cd_devs[unit]);
}
-#endif
-/* $OpenBSD: if_qe.c,v 1.10 1999/05/13 15:44:50 jason Exp $ */
-/* $NetBSD: if_qe.c,v 1.22 1997/05/02 17:11:24 ragge Exp $ */
-
+/* $OpenBSD: if_qe.c,v 1.11 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_qe.c,v 1.39 2000/01/24 02:40:29 matt Exp $ */
/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Digital Equipment Corp.
+ * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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.
- *
- * @(#)if_qe.c 7.20 (Berkeley) 3/28/91
- */
-
-/* from @(#)if_qe.c 1.15 (ULTRIX) 4/16/86 */
-
-/****************************************************************
- * *
- * Licensed from Digital Equipment Corporation *
- * Copyright (c) *
- * Digital Equipment Corporation *
- * Maynard, Massachusetts *
- * 1985, 1986 *
- * All rights reserved. *
- * *
- * The Information in this software is subject to change *
- * without notice and should not be construed as a commitment *
- * by Digital Equipment Corporation. Digital makes no *
- * representations about the suitability of this software for *
- * any purpose. It is supplied "As Is" without expressed or *
- * implied warranty. *
- * *
- * If the Regents of the University of California or its *
- * licensees modify the software in a manner creating *
- * derivative copyright rights, appropriate copyright *
- * legends may be placed on the derivative work in addition *
- * to that set forth above. *
- * *
- ****************************************************************/
-/* ---------------------------------------------------------------------
- * Modification History
- *
- * 15-Apr-86 -- afd
- * Rename "unused_multi" to "qunused_multi" for extending Generic
- * kernel to MicroVAXen.
- *
- * 18-mar-86 -- jaw br/cvec changed to NOT use registers.
- *
- * 12 March 86 -- Jeff Chase
- * Modified to handle the new MCLGET macro
- * Changed if_qe_data.c to use more receive buffers
- * Added a flag to poke with adb to log qe_restarts on console
- *
- * 19 Oct 85 -- rjl
- * Changed the watch dog timer from 30 seconds to 3. VMS is using
- * less than 1 second in their's. Also turned the printf into an
- * mprintf.
- *
- * 09/16/85 -- Larry Cohen
- * Add 43bsd alpha tape changes for subnet routing
- *
- * 1 Aug 85 -- rjl
- * Panic on a non-existent memory interrupt and the case where a packet
- * was chained. The first should never happen because non-existant
- * memory interrupts cause a bus reset. The second should never happen
- * because we hang 2k input buffers on the device.
- *
- * 1 Aug 85 -- rich
- * Fixed the broadcast loopback code to handle Clusters without
- * wedging the system.
- *
- * 27 Feb. 85 -- ejf
- * Return default hardware address on ioctl request.
- *
- * 12 Feb. 85 -- ejf
- * Added internal extended loopback capability.
- *
- * 27 Dec. 84 -- rjl
- * Fixed bug that caused every other transmit descriptor to be used
- * instead of every descriptor.
- *
- * 21 Dec. 84 -- rjl
- * Added watchdog timer to mask hardware bug that causes device lockup.
+ * This product includes software developed at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
*
- * 18 Dec. 84 -- rjl
- * Reworked driver to use q-bus mapping routines. MicroVAX-I now does
- * copying instead of m-buf shuffleing.
- * A number of deficencies in the hardware/firmware were compensated
- * for. See comments in qestart and qerint.
- *
- * 14 Nov. 84 -- jf
- * Added usage counts for multicast addresses.
- * Updated general protocol support to allow access to the Ethernet
- * header.
- *
- * 04 Oct. 84 -- jf
- * Added support for new ioctls to add and delete multicast addresses
- * and set the physical address.
- * Add support for general protocols.
- *
- * 14 Aug. 84 -- rjl
- * Integrated Shannon changes. (allow arp above 1024 and ? )
- *
- * 13 Feb. 84 -- rjl
- *
- * Initial version of driver. derived from IL driver.
- *
- * ---------------------------------------------------------------------
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*
- * Digital Q-BUS to NI Adapter
- * supports DEQNA and DELQA in DEQNA-mode.
+ * Driver for DEQNA/DELQA ethernet cards.
+ * Things that is still to do:
+ * Have a timeout check for hang transmit logic.
+ * Handle ubaresets. Does not work at all right now.
+ * Fix ALLMULTI reception. But someone must tell me how...
+ * Collect statistics.
*/
#include "bpfilter.h"
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/mbuf.h>
-#include <sys/buf.h>
-#include <sys/protosw.h>
#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/errno.h>
-#include <sys/syslog.h>
#include <sys/device.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
#include <net/if.h>
-#include <net/netisr.h>
-#include <net/route.h>
-
-#ifdef INET
+#include <net/if_dl.h>
#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
#include <netinet/if_ether.h>
-#endif
-
-#ifdef NS
-#include <netns/ns.h>
-#include <netns/ns_if.h>
-#endif
-
-#ifdef ISO
-#include <netiso/iso.h>
-#include <netiso/iso_var.h>
-extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
-#endif
-
-#if defined(CCITT) && defined(LLC)
-#include <sys/socketvar.h>
-#include <netccitt/x25.h>
-#include <netccitt/pk.h>
-#include <netccitt/pk_var.h>
-#include <netccitt/pk_extern.h>
-#endif
#if NBPFILTER > 0
#include <net/bpf.h>
#include <net/bpfdesc.h>
#endif
-
-#include <machine/pte.h>
-#include <machine/cpu.h>
-#include <vax/if/if_qereg.h>
-#include <vax/if/if_uba.h>
-#include <vax/uba/ubareg.h>
-#include <vax/uba/ubavar.h>
+#include <machine/bus.h>
-#define NRCV 15 /* Receive descriptors */
-#define NXMT 5 /* Transmit descriptors */
-#define NTOT (NXMT + NRCV)
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/qbus/if_qereg.h>
-#define QETIMEOUT 2 /* transmit timeout, must be > 1 */
-#define QESLOWTIMEOUT 40 /* timeout when no xmits in progress */
-
-#define MINDATA 60
+#define RXDESCS 30 /* # of receive descriptors */
+#define TXDESCS 60 /* # transmit descs */
+#define ETHER_MINLEN 64 /* min frame + crc */
/*
- * Ethernet software status per interface.
- *
- * Each interface is referenced by a network interface structure,
- * qe_if, which the routing code uses to locate the interface.
- * This structure contains the output queue for the interface, its address, ...
+ * Structure containing the elements that must be in DMA-safe memory.
*/
-struct qe_softc {
- struct device qe_dev; /* Configuration common part */
- struct arpcom qe_ac; /* Ethernet common part */
-#define qe_if qe_ac.ac_if /* network-visible interface */
-#define qe_addr qe_ac.ac_enaddr /* hardware Ethernet address */
- struct ifubinfo qe_uba; /* Q-bus resources */
- struct ifrw qe_ifr[NRCV]; /* for receive buffers; */
- struct ifxmt qe_ifw[NXMT]; /* for xmit buffers; */
- struct qedevice *qe_vaddr;
- int qe_flags; /* software state */
-#define QEF_RUNNING 0x01
-#define QEF_SETADDR 0x02
-#define QEF_FASTTIMEO 0x04
- int setupaddr; /* mapping info for setup pkts */
- int ipl; /* interrupt priority */
- struct qe_ring *rringaddr; /* mapping info for rings */
- struct qe_ring *tringaddr; /* "" */
- struct qe_ring rring[NRCV+1]; /* Receive ring descriptors */
- struct qe_ring tring[NXMT+1]; /* Xmit ring descriptors */
- u_char setup_pkt[16][8]; /* Setup packet */
- int rindex; /* Receive index */
- int tindex; /* Transmit index */
- int otindex; /* Old transmit index */
- int qe_intvec; /* Interrupt vector */
- struct qedevice *addr; /* device addr */
- int setupqueued; /* setup packet queued */
- int setuplength; /* length if setup packet */
- int nxmit; /* Transmits in progress */
- int qe_restarts; /* timeouts */
+struct qe_cdata {
+ struct qe_ring qc_recv[RXDESCS+1]; /* Receive descriptors */
+ struct qe_ring qc_xmit[TXDESCS+1]; /* Transmit descriptors */
+ u_int8_t qc_setup[128]; /* Setup packet layout */
};
-int qematch __P((struct device *, void *, void *));
-void qeattach __P((struct device *, struct device *, void *));
-void qereset __P((int));
-void qeinit __P((struct qe_softc *));
-void qestart __P((struct ifnet *));
-void qeintr __P((int));
-void qetint __P((int));
-void qerint __P((int));
-int qeioctl __P((struct ifnet *, u_long, caddr_t));
-void qe_setaddr __P((u_char *, struct qe_softc *));
-void qeinitdesc __P((struct qe_ring *, caddr_t, int));
-void qesetup __P((struct qe_softc *));
-void qeread __P((struct qe_softc *, struct ifrw *, int));
-void qetimeout __P((struct ifnet *));
-void qerestart __P((struct qe_softc *));
-
-struct cfdriver qe_cd = {
- NULL, "qe", DV_IFNET
+struct qe_softc {
+ struct device sc_dev; /* Configuration common part */
+ struct arpcom sc_ac; /* Ethernet common part */
+#define sc_if sc_ac.ac_if /* network-visible interface */
+ bus_space_tag_t sc_iot;
+ bus_addr_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+ struct qe_cdata *sc_qedata; /* Descriptor struct */
+ struct qe_cdata *sc_pqedata; /* Unibus address of above */
+ bus_dmamap_t sc_cmap; /* Map for control structures */
+ struct mbuf* sc_txmbuf[TXDESCS];
+ struct mbuf* sc_rxmbuf[RXDESCS];
+ bus_dmamap_t sc_xmtmap[TXDESCS];
+ bus_dmamap_t sc_rcvmap[RXDESCS];
+ int sc_intvec; /* Interrupt vector */
+ int sc_nexttx;
+ int sc_inq;
+ int sc_lastack;
+ int sc_nextrx;
+ int sc_setup; /* Setup packet in queue */
};
+static int qematch __P((struct device *, struct cfdata *, void *));
+static void qeattach __P((struct device *, struct device *, void *));
+static void qeinit __P((struct qe_softc *));
+static void qestart __P((struct ifnet *));
+static void qeintr __P((void *));
+static int qeioctl __P((struct ifnet *, u_long, caddr_t));
+static int qe_add_rxbuf __P((struct qe_softc *, int));
+static void qe_setup __P((struct qe_softc *));
+static void qetimeout __P((struct ifnet *));
+
struct cfattach qe_ca = {
- sizeof(struct qe_softc), qematch, qeattach
+ sizeof(struct qe_softc), (cfmatch_t)qematch, qeattach
};
-#define QEUNIT(x) minor(x)
-/*
- * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header)
- * but will actually take in up to 2048 bytes. To guard against the receiver
- * chaining buffers (which we aren't prepared to handle) we allocate 2kb
- * size buffers.
- */
-#define MAXPACKETSIZE 2048 /* Should really be ETHERMTU */
+#define QE_WCSR(csr, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
+#define QE_RCSR(csr) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
+
+#define LOWORD(x) ((int)(x) & 0xffff)
+#define HIWORD(x) (((int)(x) >> 16) & 0x3f)
/*
- * Probe the QNA to see if it's there
+ * Check for present DEQNA. Done by sending a fake setup packet
+ * and wait for interrupt.
*/
int
-qematch(parent, match, aux)
+qematch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct qe_softc *sc = match;
+ bus_dmamap_t cmap;
+ struct qe_softc ssc;
+ struct qe_softc *sc = &ssc;
struct uba_attach_args *ua = aux;
struct uba_softc *ubasc = (struct uba_softc *)parent;
+
+#define PROBESIZE (sizeof(struct qe_ring) * 4 + 128)
+ struct qe_ring ring[15]; /* For diag purposes only */
struct qe_ring *rp;
- struct qe_ring *prp; /* physical rp */
- volatile struct qedevice *addr = (struct qedevice *)ua->ua_addr;
- int i;
+ int error;
- /*
- * The QNA interrupts on i/o operations. To do an I/O operation
- * we have to setup the interface by transmitting a setup packet.
- */
+ bzero(sc, sizeof(struct qe_softc));
+ bzero(ring, PROBESIZE);
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
- addr->qe_csr = QE_RESET;
- addr->qe_csr &= ~QE_RESET;
- addr->qe_vector = (ubasc->uh_lastiv -= 4);
+ ubasc->uh_lastiv -= 4;
+ QE_WCSR(QE_CSR_CSR, QE_RESET);
+ QE_WCSR(QE_CSR_VECTOR, ubasc->uh_lastiv);
/*
- * Map the communications area and the setup packet.
+ * Map the ring area. Actually this is done only to be able to
+ * send and receive a internal packet; some junk is loopbacked
+ * so that the DEQNA has a reason to interrupt.
*/
- sc->setupaddr =
- uballoc(ubasc, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0);
- sc->rringaddr = (struct qe_ring *) uballoc(ubasc, (caddr_t)sc->rring,
- sizeof(struct qe_ring) * (NTOT+2), 0);
- prp = (struct qe_ring *)UBAI_ADDR((int)sc->rringaddr);
+ if ((error = bus_dmamap_create(sc->sc_dmat, PROBESIZE, 1, PROBESIZE, 0,
+ BUS_DMA_NOWAIT, &cmap))) {
+ printf("qematch: bus_dmamap_create failed = %d\n", error);
+ return 0;
+ }
+ if ((error = bus_dmamap_load(sc->sc_dmat, cmap, ring, PROBESIZE, 0,
+ BUS_DMA_NOWAIT))) {
+ printf("qematch: bus_dmamap_load failed = %d\n", error);
+ bus_dmamap_destroy(sc->sc_dmat, cmap);
+ return 0;
+ }
/*
- * The QNA will loop the setup packet back to the receive ring
- * for verification, therefore we initialize the first
- * receive & transmit ring descriptors and link the setup packet
- * to them.
+ * Init a simple "fake" receive and transmit descriptor that
+ * points to some unused area. Send a fake setup packet.
*/
- qeinitdesc(sc->tring, (caddr_t)UBAI_ADDR(sc->setupaddr),
- sizeof(sc->setup_pkt));
- qeinitdesc(sc->rring, (caddr_t)UBAI_ADDR(sc->setupaddr),
- sizeof(sc->setup_pkt));
-
- rp = (struct qe_ring *)sc->tring;
- rp->qe_setup = 1;
- rp->qe_eomsg = 1;
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
+ rp = (void *)cmap->dm_segs[0].ds_addr;
+ ring[0].qe_flag = ring[0].qe_status1 = QE_NOTYET;
+ ring[0].qe_addr_lo = LOWORD(&rp[4]);
+ ring[0].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID | QE_EOMSG | QE_SETUP;
+ ring[0].qe_buf_len = 128;
- rp = (struct qe_ring *)sc->rring;
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
+ ring[2].qe_flag = ring[2].qe_status1 = QE_NOTYET;
+ ring[2].qe_addr_lo = LOWORD(&rp[4]);
+ ring[2].qe_addr_hi = HIWORD(&rp[4]) | QE_VALID;
+ ring[2].qe_buf_len = 128;
- /*
- * Get the addr off of the interface and place it into the setup
- * packet. This code looks strange due to the fact that the address
- * is placed in the setup packet in col. major order.
- */
- for (i = 0; i < 6; i++)
- sc->setup_pkt[i][1] = addr->qe_sta_addr[i];
+ QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
+ DELAY(1000);
- qesetup(sc);
/*
* Start the interface and wait for the packet.
*/
- addr->qe_csr = QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT;
- addr->qe_rcvlist_lo = (short)((int)prp);
- addr->qe_rcvlist_hi = (short)((int)prp >> 16);
- prp += NRCV+1;
- addr->qe_xmtlist_lo = (short)((int)prp);
- addr->qe_xmtlist_hi = (short)((int)prp >> 16);
+ QE_WCSR(QE_CSR_CSR, QE_INT_ENABLE|QE_XMIT_INT|QE_RCV_INT);
+ QE_WCSR(QE_CSR_RCLL, LOWORD(&rp[2]));
+ QE_WCSR(QE_CSR_RCLH, HIWORD(&rp[2]));
+ QE_WCSR(QE_CSR_XMTL, LOWORD(rp));
+ QE_WCSR(QE_CSR_XMTH, HIWORD(rp));
DELAY(10000);
+
/*
* All done with the bus resources.
*/
- ubarelse(ubasc, &sc->setupaddr);
- ubarelse(ubasc, (int *)&sc->rringaddr);
- sc->ipl = 0x15;
- ua->ua_ivec = qeintr;
+ bus_dmamap_unload(sc->sc_dmat, cmap);
+ bus_dmamap_destroy(sc->sc_dmat, cmap);
return 1;
}
void *aux;
{
struct uba_attach_args *ua = aux;
+ struct uba_softc *ubasc = (struct uba_softc *)parent;
struct qe_softc *sc = (struct qe_softc *)self;
- struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
- struct qedevice *addr =(struct qedevice *)ua->ua_addr;
- int i;
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct qe_ring *rp;
+ u_int8_t enaddr[ETHER_ADDR_LEN];
+ bus_dma_segment_t seg;
+ int i, rseg, error;
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
+
+ /*
+ * Allocate DMA safe memory for descriptors and setup memory.
+ */
+ if ((error = bus_dmamem_alloc(sc->sc_dmat,
+ sizeof(struct qe_cdata), NBPG, 0, &seg, 1, &rseg,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to allocate control data, error = %d\n",
+ error);
+ goto fail_0;
+ }
+
+ if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
+ sizeof(struct qe_cdata), (caddr_t *)&sc->sc_qedata,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf(": unable to map control data, error = %d\n", error);
+ goto fail_1;
+ }
+
+ if ((error = bus_dmamap_create(sc->sc_dmat,
+ sizeof(struct qe_cdata), 1,
+ sizeof(struct qe_cdata), 0, BUS_DMA_NOWAIT,
+ &sc->sc_cmap)) != 0) {
+ printf(": unable to create control data DMA map, error = %d\n",
+ error);
+ goto fail_2;
+ }
+
+ if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
+ sc->sc_qedata, sizeof(struct qe_cdata), NULL,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to load control data DMA map, error = %d\n",
+ error);
+ goto fail_3;
+ }
- printf("\n");
- sc->qe_vaddr = addr;
- bcopy(sc->qe_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
- ifp->if_softc = sc;
/*
- * The Deqna is cable of transmitting broadcasts, but
- * doesn't listen to its own.
+ * Zero the newly allocated memory.
*/
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
- IFF_MULTICAST;
+ bzero(sc->sc_qedata, sizeof(struct qe_cdata));
+ /*
+ * Create the transmit descriptor DMA maps. We take advantage
+ * of the fact that the Qbus address space is big, and therefore
+ * allocate map registers for all transmit descriptors also,
+ * so that we can avoid this each time we send a packet.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+ 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
+ &sc->sc_xmtmap[i]))) {
+ printf(": unable to create tx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_4;
+ }
+ }
/*
- * Read the address from the prom and save it.
+ * Create receive buffer DMA maps.
*/
- for (i = 0; i < 6; i++)
- sc->setup_pkt[i][1] = sc->qe_addr[i] =
- addr->qe_sta_addr[i] & 0xff;
- addr->qe_vector |= 1;
- printf("qe%d: %s, hardware address %s\n", sc->qe_dev.dv_unit,
- addr->qe_vector&01 ? "delqa":"deqna",
- ether_sprintf(sc->qe_addr));
- addr->qe_vector &= ~1;
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
+ MCLBYTES, 0, BUS_DMA_NOWAIT,
+ &sc->sc_rcvmap[i]))) {
+ printf(": unable to create rx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_5;
+ }
+ }
+ /*
+ * Pre-allocate the receive buffers.
+ */
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = qe_add_rxbuf(sc, i)) != 0) {
+ printf(": unable to allocate or map rx buffer %d\n,"
+ " error = %d\n", i, error);
+ goto fail_6;
+ }
+ }
+
+ /*
+ * Create ring loops of the buffer chains.
+ * This is only done once.
+ */
+ sc->sc_pqedata = (struct qe_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
+
+ rp = sc->sc_qedata->qc_recv;
+ rp[RXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_recv[0]);
+ rp[RXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_recv[0]) |
+ QE_VALID | QE_CHAIN;
+ rp[RXDESCS].qe_flag = rp[RXDESCS].qe_status1 = QE_NOTYET;
+
+ rp = sc->sc_qedata->qc_xmit;
+ rp[TXDESCS].qe_addr_lo = LOWORD(&sc->sc_pqedata->qc_xmit[0]);
+ rp[TXDESCS].qe_addr_hi = HIWORD(&sc->sc_pqedata->qc_xmit[0]) |
+ QE_VALID | QE_CHAIN;
+ rp[TXDESCS].qe_flag = rp[TXDESCS].qe_status1 = QE_NOTYET;
/*
- * Save the vector for initialization at reset time.
+ * Get the vector that were set at match time, and remember it.
*/
- sc->qe_intvec = addr->qe_vector;
+ sc->sc_intvec = ubasc->uh_lastiv;
+ QE_WCSR(QE_CSR_CSR, QE_RESET);
+ DELAY(1000);
+ QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
+ /*
+ * Read out ethernet address and tell which type this card is.
+ */
+ for (i = 0; i < 6; i++)
+ enaddr[i] = QE_RCSR(i * 2) & 0xff;
+
+ QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec | 1);
+ printf("\n%s: %s, hardware address %s\n", sc->sc_dev.dv_xname,
+ QE_RCSR(QE_CSR_VECTOR) & 1 ? "delqa":"deqna",
+ ether_sprintf(enaddr));
+
+ QE_WCSR(QE_CSR_VECTOR, QE_RCSR(QE_CSR_VECTOR) & ~1); /* ??? */
+
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, qeintr, sc);
+
+ strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_start = qestart;
ifp->if_ioctl = qeioctl;
ifp->if_watchdog = qetimeout;
- sc->qe_uba.iff_flags = UBA_CANTWAIT;
+
+ /*
+ * Attach the interface.
+ */
if_attach(ifp);
ether_ifattach(ifp);
#if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
-}
-
-/*
- * Reset of interface after UNIBUS reset.
- */
-void
-qereset(unit)
- int unit;
-{
- struct qe_softc *sc = qe_cd.cd_devs[unit];
+ return;
- printf(" %s", sc->qe_dev.dv_xname);
- sc->qe_if.if_flags &= ~IFF_RUNNING;
- qeinit(sc);
+ /*
+ * Free any resources we've allocated during the failed attach
+ * attempt. Do this in reverse order and fall through.
+ */
+ fail_6:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_rxmbuf[i] != NULL) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_rxmbuf[i]);
+ }
+ }
+ fail_5:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_xmtmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
+ }
+ fail_4:
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_rcvmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
+ }
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
+ fail_3:
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
+ fail_2:
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_qedata,
+ sizeof(struct qe_cdata));
+ fail_1:
+ bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ fail_0:
+ return;
}
/*
qeinit(sc)
struct qe_softc *sc;
{
- struct qedevice *addr = sc->qe_vaddr;
- struct uba_softc *ubasc = (void *)sc->qe_dev.dv_parent;
- struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct qe_cdata *qc = sc->sc_qedata;
int i;
- int s;
- /* address not known */
- if (ifp->if_addrlist.tqh_first == (struct ifaddr *)0)
- return;
- if (sc->qe_flags & QEF_RUNNING)
- return;
- if ((ifp->if_flags & IFF_RUNNING) == 0) {
- /*
- * map the communications area onto the device
- */
- i = uballoc(ubasc, (caddr_t)sc->rring,
- sizeof(struct qe_ring) * (NTOT+2), 0);
- if (i == 0)
- goto fail;
- sc->rringaddr = (struct qe_ring *)UBAI_ADDR(i);
- sc->tringaddr = sc->rringaddr + NRCV + 1;
- i = uballoc(ubasc, (caddr_t)sc->setup_pkt,
- sizeof(sc->setup_pkt), 0);
- if (i == 0)
- goto fail;
- sc->setupaddr = UBAI_ADDR(i);
- /*
- * init buffers and maps
- */
- if (if_ubaminit(&sc->qe_uba, (void *)sc->qe_dev.dv_parent,
- sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE),
- sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) {
- fail:
- printf("%s: can't allocate uba resources\n",
- sc->qe_dev.dv_xname);
- sc->qe_if.if_flags &= ~IFF_UP;
- return;
- }
- }
/*
- * Init the buffer descriptors and indexes for each of the lists and
- * loop them back to form a ring.
+ * Reset the interface.
*/
- for (i = 0; i < NRCV; i++) {
- qeinitdesc( &sc->rring[i],
- (caddr_t)UBAI_ADDR(sc->qe_ifr[i].ifrw_info), MAXPACKETSIZE);
- sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;
- sc->rring[i].qe_valid = 1;
+ QE_WCSR(QE_CSR_CSR, QE_RESET);
+ DELAY(1000);
+ QE_WCSR(QE_CSR_CSR, QE_RCSR(QE_CSR_CSR) & ~QE_RESET);
+ QE_WCSR(QE_CSR_VECTOR, sc->sc_intvec);
+
+ sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0;
+ /*
+ * Release and init transmit descriptors.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_txmbuf[i]) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_txmbuf[i]);
+ sc->sc_txmbuf[i] = 0;
+ }
+ qc->qc_xmit[i].qe_addr_hi = 0; /* Clear valid bit */
+ qc->qc_xmit[i].qe_status1 = qc->qc_xmit[i].qe_flag = QE_NOTYET;
}
- qeinitdesc(&sc->rring[i], (caddr_t)NULL, 0);
- sc->rring[i].qe_addr_lo = (short)((int)sc->rringaddr);
- sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16);
- sc->rring[i].qe_chain = 1;
- sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;
- sc->rring[i].qe_valid = 1;
- for( i = 0 ; i <= NXMT ; i++ )
- qeinitdesc(&sc->tring[i], (caddr_t)NULL, 0);
- i--;
+ /*
+ * Init receive descriptors.
+ */
+ for (i = 0; i < RXDESCS; i++)
+ qc->qc_recv[i].qe_status1 = qc->qc_recv[i].qe_flag = QE_NOTYET;
+ sc->sc_nextrx = 0;
- sc->tring[i].qe_addr_lo = (short)((int)sc->tringaddr);
- sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16);
- sc->tring[i].qe_chain = 1;
- sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET;
- sc->tring[i].qe_valid = 1;
+ /*
+ * Write the descriptor addresses to the device.
+ * Receiving packets will be enabled in the interrupt routine.
+ */
+ QE_WCSR(QE_CSR_CSR, QE_INT_ENABLE|QE_XMIT_INT|QE_RCV_INT);
+ QE_WCSR(QE_CSR_RCLL, LOWORD(sc->sc_pqedata->qc_recv));
+ QE_WCSR(QE_CSR_RCLH, HIWORD(sc->sc_pqedata->qc_recv));
- sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
/*
- * Take the interface out of reset, program the vector,
- * enable interrupts, and tell the world we are up.
+ * Send a setup frame.
+ * This will start the transmit machinery as well.
*/
- s = splnet();
- addr->qe_vector = sc->qe_intvec;
- sc->addr = addr;
- addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |
- QE_RCV_INT | QE_ILOOP;
- addr->qe_rcvlist_lo = (short)((int)sc->rringaddr);
- addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16);
- ifp->if_flags |= IFF_UP | IFF_RUNNING;
- sc->qe_flags |= QEF_RUNNING;
- qesetup( sc );
- qestart( ifp );
- sc->qe_if.if_timer = QESLOWTIMEOUT; /* Start watchdog */
- splx( s );
+ qe_setup(sc);
+
}
/*
* Start output on interface.
- *
*/
void
qestart(ifp)
struct ifnet *ifp;
{
- register struct qe_softc *sc = ifp->if_softc;
- volatile struct qedevice *addr = sc->qe_vaddr;
- register struct qe_ring *rp;
- register index;
- struct mbuf *m;
- int buf_addr, len, s;
+ struct qe_softc *sc = ifp->if_softc;
+ struct qe_cdata *qc = sc->sc_qedata;
+ paddr_t buffer;
+ struct mbuf *m, *m0;
+ int idx, len, s, i, totlen, error;
+ short orword;
+ if ((QE_RCSR(QE_CSR_CSR) & QE_RCV_ENABLE) == 0)
+ return;
- s = splnet();
- /*
- * The deqna doesn't look at anything but the valid bit
- * to determine if it should transmit this packet. If you have
- * a ring and fill it the device will loop indefinately on the
- * packet and continue to flood the net with packets until you
- * break the ring. For this reason we never queue more than n-1
- * packets in the transmit ring.
- *
- * The microcoders should have obeyed their own defination of the
- * flag and status words, but instead we have to compensate.
- */
- for( index = sc->tindex;
- sc->tring[index].qe_valid == 0 && sc->nxmit < (NXMT-1) ;
- sc->tindex = index = ++index % NXMT){
- rp = &sc->tring[index];
- if( sc->setupqueued ) {
- buf_addr = sc->setupaddr;
- len = sc->setuplength;
- rp->qe_setup = 1;
- sc->setupqueued = 0;
- } else {
- IF_DEQUEUE(&sc->qe_if.if_snd, m);
- if (m == 0) {
- splx(s);
- return;
- }
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m);
-#endif
- buf_addr = sc->qe_ifw[index].ifw_info;
- len = if_ubaput(&sc->qe_uba, &sc->qe_ifw[index], m);
+ s = splimp();
+ while (sc->sc_inq < (TXDESCS - 1)) {
+
+ if (sc->sc_setup) {
+ qe_setup(sc);
+ continue;
}
- if( len < MINDATA )
- len = MINDATA;
+ idx = sc->sc_nexttx;
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if (m == 0)
+ goto out;
/*
- * Does buffer end on odd byte ?
+ * Count number of mbufs in chain.
+ * Always do DMA directly from mbufs, therefore the transmit
+ * ring is really big.
*/
- if( len & 1 ) {
- len++;
- rp->qe_odd_end = 1;
+ for (m0 = m, i = 0; m0; m0 = m0->m_next)
+ if (m0->m_len)
+ i++;
+ if (i >= TXDESCS)
+ panic("qestart");
+
+ if ((i + sc->sc_inq) >= (TXDESCS - 1)) {
+ IF_PREPEND(&sc->sc_if.if_snd, m);
+ ifp->if_flags |= IFF_OACTIVE;
+ goto out;
}
- rp->qe_buf_len = -(len/2);
- buf_addr = UBAI_ADDR(buf_addr);
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_addr_lo = (short)buf_addr;
- rp->qe_addr_hi = (short)(buf_addr >> 16);
- rp->qe_eomsg = 1;
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
- if (sc->nxmit++ == 0) {
- sc->qe_flags |= QEF_FASTTIMEO;
- sc->qe_if.if_timer = QETIMEOUT;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ /*
+ * m now points to a mbuf chain that can be loaded.
+ * Loop around and set it.
+ */
+ totlen = 0;
+ for (m0 = m; m0; m0 = m0->m_next) {
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx],
+ mtod(m0, void *), m0->m_len, 0, 0);
+ buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr;
+ len = m0->m_len;
+ if (len == 0)
+ continue;
+
+ totlen += len;
+ /* Word alignment calc */
+ orword = 0;
+ if (totlen == m->m_pkthdr.len) {
+ if (totlen < ETHER_MINLEN)
+ len += (ETHER_MINLEN - totlen);
+ orword |= QE_EOMSG;
+ sc->sc_txmbuf[idx] = m;
+ }
+ if ((buffer & 1) || (len & 1))
+ len += 2;
+ if (buffer & 1)
+ orword |= QE_ODDBEGIN;
+ if ((buffer + len) & 1)
+ orword |= QE_ODDEND;
+ qc->qc_xmit[idx].qe_buf_len = -(len/2);
+ qc->qc_xmit[idx].qe_addr_lo = LOWORD(buffer);
+ qc->qc_xmit[idx].qe_addr_hi = HIWORD(buffer);
+ qc->qc_xmit[idx].qe_flag =
+ qc->qc_xmit[idx].qe_status1 = QE_NOTYET;
+ qc->qc_xmit[idx].qe_addr_hi |= (QE_VALID | orword);
+ if (++idx == TXDESCS)
+ idx = 0;
+ sc->sc_inq++;
}
+#ifdef DIAGNOSTIC
+ if (totlen != m->m_pkthdr.len)
+ panic("qestart: len fault");
+#endif
/*
- * See if the xmit list is invalid.
+ * Kick off the transmit logic, if it is stopped.
*/
- if( addr->qe_csr & QE_XL_INVALID ) {
- buf_addr = (int)(sc->tringaddr+index);
- addr->qe_xmtlist_lo = (short)buf_addr;
- addr->qe_xmtlist_hi = (short)(buf_addr >> 16);
+ if (QE_RCSR(QE_CSR_CSR) & QE_XL_INVALID) {
+ QE_WCSR(QE_CSR_XMTL,
+ LOWORD(&sc->sc_pqedata->qc_xmit[sc->sc_nexttx]));
+ QE_WCSR(QE_CSR_XMTH,
+ HIWORD(&sc->sc_pqedata->qc_xmit[sc->sc_nexttx]));
}
+ sc->sc_nexttx = idx;
}
+ if (sc->sc_inq == (TXDESCS - 1))
+ ifp->if_flags |= IFF_OACTIVE;
+
+out: if (sc->sc_inq)
+ ifp->if_timer = 5; /* If transmit logic dies */
splx(s);
- return;
}
-/*
- * Ethernet interface interrupt processor
- */
-void
-qeintr(unit)
- int unit;
+static void
+qeintr(arg)
+ void *arg;
{
- register struct qe_softc *sc;
- volatile struct qedevice *addr;
- int buf_addr, csr;
-
- sc = qe_cd.cd_devs[unit];
- addr = sc->qe_vaddr;
- splx(sc->ipl);
- if (!(sc->qe_flags & QEF_FASTTIMEO))
- sc->qe_if.if_timer = QESLOWTIMEOUT; /* Restart timer clock */
- csr = addr->qe_csr;
- addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE |
- QE_XMIT_INT | QE_RCV_INT | QE_ILOOP;
- if (csr & QE_RCV_INT)
- qerint(unit);
- if (csr & QE_XMIT_INT)
- qetint(unit );
- if (csr & QE_NEX_MEM_INT)
- printf("qe%d: Nonexistent memory interrupt\n", unit);
-
- if (addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 ==
- QE_NOTYET) {
- buf_addr = (int)&sc->rringaddr[sc->rindex];
- addr->qe_rcvlist_lo = (short)buf_addr;
- addr->qe_rcvlist_hi = (short)(buf_addr >> 16);
- }
-}
+ struct qe_softc *sc = arg;
+ struct qe_cdata *qc = sc->sc_qedata;
+ struct ifnet *ifp = &sc->sc_if;
+ struct ether_header *eh;
+ struct mbuf *m;
+ int csr, status1, status2, len;
-/*
- * Ethernet interface transmit interrupt.
- */
-void
-qetint(unit)
- int unit;
-{
- register struct qe_softc *sc = qe_cd.cd_devs[unit];
- register struct qe_ring *rp;
- register struct ifxmt *ifxp;
- int status1, setupflag;
- short len;
+ csr = QE_RCSR(QE_CSR_CSR);
+ QE_WCSR(QE_CSR_CSR, QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |
+ QE_RCV_INT | QE_ILOOP);
- while (sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1
- != QE_NOTYET && sc->nxmit > 0) {
- /*
- * Save the status words from the descriptor so that it can
- * be released.
- */
- rp = &sc->tring[sc->otindex];
- status1 = rp->qe_status1;
- setupflag = rp->qe_setup;
- len = (-rp->qe_buf_len) * 2;
- if( rp->qe_odd_end )
- len++;
- /*
- * Init the buffer descriptor
- */
- bzero((caddr_t)rp, sizeof(struct qe_ring));
- if( --sc->nxmit == 0 ) {
- sc->qe_flags &= ~QEF_FASTTIMEO;
- sc->qe_if.if_timer = QESLOWTIMEOUT;
- }
- if( !setupflag ) {
+ if (csr & QE_RCV_INT)
+ while (qc->qc_recv[sc->sc_nextrx].qe_status1 != QE_NOTYET) {
+ status1 = qc->qc_recv[sc->sc_nextrx].qe_status1;
+ status2 = qc->qc_recv[sc->sc_nextrx].qe_status2;
+ m = sc->sc_rxmbuf[sc->sc_nextrx];
+ len = ((status1 & QE_RBL_HI) |
+ (status2 & QE_RBL_LO)) + 60;
+ qe_add_rxbuf(sc, sc->sc_nextrx);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = len;
+ if (++sc->sc_nextrx == RXDESCS)
+ sc->sc_nextrx = 0;
+ eh = mtod(m, struct ether_header *);
+#if NBPFILTER > 0
+ if (ifp->if_bpf) {
+ bpf_mtap(ifp->if_bpf, m);
+ if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN) != 0 &&
+ ((eh->ether_dhost[0] & 1) == 0)) {
+ m_freem(m);
+ continue;
+ }
+ }
+#endif
/*
- * Do some statistics.
+ * ALLMULTI means PROMISC in this driver.
*/
- sc->qe_if.if_opackets++;
- sc->qe_if.if_collisions += ( status1 & QE_CCNT ) >> 4;
- if (status1 & QE_ERROR)
- sc->qe_if.if_oerrors++;
- ifxp = &sc->qe_ifw[sc->otindex];
- if (ifxp->ifw_xtofree) {
- m_freem(ifxp->ifw_xtofree);
- ifxp->ifw_xtofree = 0;
+ if ((ifp->if_flags & IFF_ALLMULTI) &&
+ ((eh->ether_dhost[0] & 1) == 0) &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN)) {
+ m_freem(m);
+ continue;
}
+ ether_input(ifp, eh, m);
}
- sc->otindex = ++sc->otindex % NXMT;
- }
- qestart(&sc->qe_if);
-}
-
-/*
- * Ethernet interface receiver interrupt.
- * If can't determine length from type, then have to drop packet.
- * Othewise decapsulate packet based on type and pass to type specific
- * higher-level input routine.
- */
-void
-qerint(unit)
- int unit;
-{
- register struct qe_softc *sc = qe_cd.cd_devs[unit];
- register struct qe_ring *rp;
- register int nrcv = 0;
- int len, status1, status2;
- int bufaddr;
+ if (csr & QE_XMIT_INT) {
+ while (qc->qc_xmit[sc->sc_lastack].qe_status1 != QE_NOTYET) {
+ int idx = sc->sc_lastack;
+
+ sc->sc_inq--;
+ if (++sc->sc_lastack == TXDESCS)
+ sc->sc_lastack = 0;
+
+ /* XXX collect statistics */
+ qc->qc_xmit[idx].qe_addr_hi &= ~QE_VALID;
+ qc->qc_xmit[idx].qe_status1 =
+ qc->qc_xmit[idx].qe_flag = QE_NOTYET;
+
+ if (qc->qc_xmit[idx].qe_addr_hi & QE_SETUP)
+ continue;
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]);
+ if (sc->sc_txmbuf[idx]) {
+ m_freem(sc->sc_txmbuf[idx]);
+ sc->sc_txmbuf[idx] = 0;
+ }
+ }
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ qestart(ifp); /* Put in more in queue */
+ }
/*
- * Traverse the receive ring looking for packets to pass back.
- * The search is complete when we find a descriptor not in use.
- *
- * As in the transmit case the deqna doesn't honor it's own protocols
- * so there exists the possibility that the device can beat us around
- * the ring. The proper way to guard against this is to insure that
- * there is always at least one invalid descriptor. We chose instead
- * to make the ring large enough to minimize the problem. With a ring
- * size of 4 we haven't been able to see the problem. To be safe we
- * doubled that to 8.
- *
+ * How can the receive list get invalid???
+ * Verified that it happens anyway.
*/
- while (sc->rring[sc->rindex].qe_status1 == QE_NOTYET && nrcv < NRCV) {
- /*
- * We got an interrupt but did not find an input packet
- * where we expected one to be, probably because the ring
- * was overrun.
- * We search forward to find a valid packet and start
- * processing from there. If no valid packet is found it
- * means we processed all the packets during a previous
- * interrupt and that the QE_RCV_INT bit was set while
- * we were processing one of these earlier packets. In
- * this case we can safely ignore the interrupt (by dropping
- * through the code below).
- */
- sc->rindex = (sc->rindex + 1) % NRCV;
- nrcv++;
- }
- if (nrcv && nrcv < NRCV)
- log(LOG_ERR, "qe%d: ring overrun, resync'd by skipping %d\n",
- unit, nrcv);
-
- for (; sc->rring[sc->rindex].qe_status1 != QE_NOTYET;
- sc->rindex = ++sc->rindex % NRCV) {
- rp = &sc->rring[sc->rindex];
- status1 = rp->qe_status1;
- status2 = rp->qe_status2;
- bzero((caddr_t)rp, sizeof(struct qe_ring));
- if( (status1 & QE_MASK) == QE_MASK )
- panic("qe: chained packet");
- len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60;
- sc->qe_if.if_ipackets++;
-
- if (status1 & QE_ERROR) {
- if ((status1 & QE_RUNT) == 0)
- sc->qe_if.if_ierrors++;
- } else {
- /*
- * We don't process setup packets.
- */
- if (!(status1 & QE_ESETUP))
- qeread(sc, &sc->qe_ifr[sc->rindex],
- len - sizeof(struct ether_header));
- }
- /*
- * Return the buffer to the ring
- */
- bufaddr = (int)UBAI_ADDR(sc->qe_ifr[sc->rindex].ifrw_info);
- rp->qe_buf_len = -((MAXPACKETSIZE)/2);
- rp->qe_addr_lo = (short)bufaddr;
- rp->qe_addr_hi = (short)((int)bufaddr >> 16);
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 1;
+ if ((qc->qc_recv[sc->sc_nextrx].qe_status1 == QE_NOTYET) &&
+ (QE_RCSR(QE_CSR_CSR) & QE_RL_INVALID)) {
+ QE_WCSR(QE_CSR_RCLL,
+ LOWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx]));
+ QE_WCSR(QE_CSR_RCLH,
+ HIWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx]));
}
}
caddr_t data;
{
struct qe_softc *sc = ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
+ struct ifaddr *ifa = (struct ifaddr *)data;
int s = splnet(), error = 0;
switch (cmd) {
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
- qeinit(sc);
switch(ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
- arp_ifinit(&sc->qe_ac, ifa);
- break;
-#endif
-#ifdef NS
- case AF_NS:
- {
- register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
-
- if (ns_nullhost(*ina))
- ina->x_host = *(union ns_host *)(sc->qe_addr);
- else
- qe_setaddr(ina->x_host.c_host, sc);
+ qeinit(sc);
+ arp_ifinit(&sc->sc_ac, ifa);
break;
- }
#endif
}
break;
case SIOCSIFFLAGS:
if ((ifp->if_flags & IFF_UP) == 0 &&
- sc->qe_flags & QEF_RUNNING) {
- sc->qe_vaddr->qe_csr = QE_RESET;
- sc->qe_flags &= ~QEF_RUNNING;
- } else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
- IFF_RUNNING && (sc->qe_flags & QEF_RUNNING) == 0)
- qerestart(sc);
- else
+ (ifp->if_flags & IFF_RUNNING) != 0) {
+ /*
+ * If interface is marked down and it is running,
+ * stop it. (by disabling receive mechanism).
+ */
+ QE_WCSR(QE_CSR_CSR,
+ QE_RCSR(QE_CSR_CSR) & ~QE_RCV_ENABLE);
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If interface it marked up and it is stopped, then
+ * start it.
+ */
qeinit(sc);
-
+ } else if ((ifp->if_flags & IFF_UP) != 0) {
+ /*
+ * Send a new setup packet to match any new changes.
+ * (Like IFF_PROMISC etc)
+ */
+ qe_setup(sc);
+ }
break;
case SIOCADDMULTI:
* Update our multicast list.
*/
error = (cmd == SIOCADDMULTI) ?
- ether_addmulti(ifr, &sc->qe_ac):
- ether_delmulti(ifr, &sc->qe_ac);
+ ether_addmulti(ifr, &sc->sc_ac):
+ ether_delmulti(ifr, &sc->sc_ac);
if (error == ENETRESET) {
/*
* Multicast list has changed; set the hardware filter
* accordingly.
*/
- qeinit(sc);
+ qe_setup(sc);
error = 0;
}
break;
}
/*
- * set ethernet address for unit
+ * Add a receive buffer to the indicated descriptor.
*/
-void
-qe_setaddr(physaddr, sc)
- u_char *physaddr;
+int
+qe_add_rxbuf(sc, i)
struct qe_softc *sc;
+ int i;
{
- register int i;
+ struct mbuf *m;
+ struct qe_ring *rp;
+ vaddr_t addr;
+ int error;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return (ENOBUFS);
+
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
- for (i = 0; i < 6; i++)
- sc->setup_pkt[i][1] = sc->qe_addr[i] = physaddr[i];
- sc->qe_flags |= QEF_SETADDR;
- if (sc->qe_if.if_flags & IFF_RUNNING)
- qesetup(sc);
- qeinit(sc);
-}
+ if (sc->sc_rxmbuf[i] != NULL)
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]);
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i],
+ m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
+ if (error)
+ panic("%s: can't load rx DMA map %d, error = %d\n",
+ sc->sc_dev.dv_xname, i, error);
+ sc->sc_rxmbuf[i] = m;
-/*
- * Initialize a ring descriptor with mbuf allocation side effects
- */
-void
-qeinitdesc(rp, addr, len)
- register struct qe_ring *rp;
- caddr_t addr; /* mapped address */
- int len;
-{
- /*
- * clear the entire descriptor
- */
- bzero((caddr_t)rp, sizeof(struct qe_ring));
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0,
+ sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD);
- if (len) {
- rp->qe_buf_len = -(len/2);
- rp->qe_addr_lo = (short)((int)addr);
- rp->qe_addr_hi = (short)((int)addr >> 16);
- }
-}
-/*
- * Build a setup packet - the physical address will already be present
- * in first column.
- */
-void
-qesetup(sc)
- struct qe_softc *sc;
-{
- register i, j;
-
- /*
- * Copy the target address to the rest of the entries in this row.
- */
- for (j = 0; j < 6; j++)
- for (i = 2; i < 8; i++)
- sc->setup_pkt[j][i] = sc->setup_pkt[j][1];
- /*
- * Duplicate the first half.
- */
- bcopy((caddr_t)sc->setup_pkt[0], (caddr_t)sc->setup_pkt[8], 64);
/*
- * Fill in the broadcast (and ISO multicast) address(es).
+ * We know that the mbuf cluster is page aligned. Also, be sure
+ * that the IP header will be longword aligned.
*/
- for (i = 0; i < 6; i++) {
- sc->setup_pkt[i][2] = 0xff;
-#ifdef ISO
- /*
- * XXX layer violation, should use SIOCADDMULTI.
- * Will definitely break with IPmulticast.
- */
+ m->m_data += 2;
+ addr = sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2;
+ rp = &sc->sc_qedata->qc_recv[i];
+ rp->qe_flag = rp->qe_status1 = QE_NOTYET;
+ rp->qe_addr_lo = LOWORD(addr);
+ rp->qe_addr_hi = HIWORD(addr) | QE_VALID;
+ rp->qe_buf_len = -(m->m_ext.ext_size - 2)/2;
- sc->setup_pkt[i][3] = all_es_snpa[i];
- sc->setup_pkt[i][4] = all_is_snpa[i];
- sc->setup_pkt[i][5] = all_l1is_snpa[i];
- sc->setup_pkt[i][6] = all_l2is_snpa[i];
-#endif
- }
- if (sc->qe_if.if_flags & IFF_PROMISC) {
- sc->setuplength = QE_PROMISC;
- /* XXX no IFF_ALLMULTI support in 4.4bsd */
- } else if (sc->qe_if.if_flags & IFF_ALLMULTI) {
- sc->setuplength = QE_ALLMULTI;
- } else {
- register k;
- struct ether_multi *enm;
- struct ether_multistep step;
- /*
- * Step through our list of multicast addresses, putting them
- * in the third through fourteenth address slots of the setup
- * packet. (See the DEQNA manual to understand the peculiar
- * layout of the bytes within the setup packet.) If we have
- * too many multicast addresses, or if we have to listen to
- * a range of multicast addresses, turn on reception of all
- * multicasts.
- */
- sc->setuplength = QE_SOMEMULTI;
- i = 2;
- k = 0;
- ETHER_FIRST_MULTI(step, &sc->qe_ac, enm);
- while (enm != NULL) {
- if ((++i > 7 && k != 0) ||
- bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
- sc->setuplength = QE_ALLMULTI;
- break;
- }
- if (i > 7) {
- i = 1;
- k = 8;
- }
- for (j = 0; j < 6; j++)
- sc->setup_pkt[j+k][i] = enm->enm_addrlo[j];
- ETHER_NEXT_MULTI(step, enm);
- }
- }
- sc->setupqueued++;
+ return (0);
}
/*
- * Pass a packet to the higher levels.
- * We deal with the trailer protocol here.
+ * Create a setup packet and put in queue for sending.
*/
void
-qeread(sc, ifrw, len)
- register struct qe_softc *sc;
- struct ifrw *ifrw;
- int len;
+qe_setup(sc)
+ struct qe_softc *sc;
{
- struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
- struct ether_header *eh;
- struct mbuf *m;
-
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ struct qe_cdata *qc = sc->sc_qedata;
+ struct ifnet *ifp = &sc->sc_if;
+ u_int8_t *enaddr = sc->sc_ac.ac_enaddr;
+ int i, j, k, idx, s;
+
+ s = splimp();
+ if (sc->sc_inq == (TXDESCS - 1)) {
+ sc->sc_setup = 1;
+ splx(s);
+ return;
+ }
+ sc->sc_setup = 0;
/*
- * Deal with trailer protocol: if type is INET trailer
- * get true type from first 16-bit word past data.
- * Remember that type was trailer by setting off.
+ * Init the setup packet with valid info.
*/
-
- eh = (struct ether_header *)ifrw->ifrw_addr;
- if (len == 0)
- return;
+ memset(qc->qc_setup, 0xff, sizeof(qc->qc_setup)); /* Broadcast */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ qc->qc_setup[i * 8 + 1] = enaddr[i]; /* Own address */
/*
- * Pull packet off interface. Off is nonzero if packet
- * has trailing header; qeget will then force this header
- * information to be at the front, but we still have to drop
- * the type and length which are at the front of any trailer data.
+ * Multicast handling. The DEQNA can handle up to 12 direct
+ * ethernet addresses.
*/
- m = if_ubaget(&sc->qe_uba, ifrw, len, &sc->qe_if);
-#ifdef notdef
-if (m) {
-*(((u_long *)m->m_data)+0),
-*(((u_long *)m->m_data)+1),
-*(((u_long *)m->m_data)+2),
-*(((u_long *)m->m_data)+3)
-; }
-#endif
+ j = 3; k = 0;
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
+ while (enm != NULL) {
+ if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ qc->qc_setup[i * 8 + j + k] = enm->enm_addrlo[i];
+ j++;
+ if (j == 8) {
+ j = 1; k += 64;
+ }
+ if (k > 64) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ idx = sc->sc_nexttx;
+ qc->qc_xmit[idx].qe_buf_len = -64;
-#if NBPFILTER > 0
/*
- * Check for a BPF filter; if so, hand it up.
- * Note that we have to stick an extra mbuf up front, because
- * bpf_mtap expects to have the ether header at the front.
- * It doesn't matter that this results in an ill-formatted mbuf chain,
- * since BPF just looks at the data. (It doesn't try to free the mbuf,
- * tho' it will make a copy for tcpdump.)
+ * How is the DEQNA turned in ALLMULTI mode???
+ * Until someone tells me, fall back to PROMISC when more than
+ * 12 ethernet addresses.
*/
- if (sc->qe_if.if_bpf) {
- struct mbuf m0;
- m0.m_len = sizeof (struct ether_header);
- m0.m_data = (caddr_t)eh;
- m0.m_next = m;
-
- /* Pass it up */
- bpf_mtap(sc->qe_if.if_bpf, &m0);
+ if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI))
+ qc->qc_xmit[idx].qe_buf_len = -65;
+
+ qc->qc_xmit[idx].qe_addr_lo = LOWORD(sc->sc_pqedata->qc_setup);
+ qc->qc_xmit[idx].qe_addr_hi =
+ HIWORD(sc->sc_pqedata->qc_setup) | QE_SETUP | QE_EOMSG;
+ qc->qc_xmit[idx].qe_status1 = qc->qc_xmit[idx].qe_flag = QE_NOTYET;
+ qc->qc_xmit[idx].qe_addr_hi |= QE_VALID;
+
+ if (QE_RCSR(QE_CSR_CSR) & QE_XL_INVALID) {
+ QE_WCSR(QE_CSR_XMTL,
+ LOWORD(&sc->sc_pqedata->qc_xmit[idx]));
+ QE_WCSR(QE_CSR_XMTH,
+ HIWORD(&sc->sc_pqedata->qc_xmit[idx]));
}
-#endif /* NBPFILTER > 0 */
- if (m)
- ether_input((struct ifnet *)&sc->qe_if, eh, m);
+ sc->sc_inq++;
+ if (++sc->sc_nexttx == TXDESCS)
+ sc->sc_nexttx = 0;
+ splx(s);
}
/*
- * Watchdog timeout routine. There is a condition in the hardware that
- * causes the board to lock up under heavy load. This routine detects
- * the hang up and restarts the device.
+ * Check for dead transmit logic. Not uncommon.
*/
void
qetimeout(ifp)
struct ifnet *ifp;
{
- register struct qe_softc *sc = ifp->if_softc;
+ struct qe_softc *sc = ifp->if_softc;
-#ifdef notdef
- log(LOG_ERR, "%s: transmit timeout, restarted %d\n",
- sc->sc_dev.dv_xname, sc->qe_restarts++);
-#endif
- qerestart(sc);
-}
-/*
- * Restart for board lockup problem.
- */
-void
-qerestart(sc)
- struct qe_softc *sc;
-{
- register struct ifnet *ifp = (struct ifnet *)&sc->qe_if;
- register struct qedevice *addr = sc->addr;
- register struct qe_ring *rp;
- register i;
-
- addr->qe_csr = QE_RESET;
- addr->qe_csr &= ~QE_RESET;
- qesetup(sc);
- for (i = 0, rp = sc->tring; i < NXMT; rp++, i++) {
- rp->qe_flag = rp->qe_status1 = QE_NOTYET;
- rp->qe_valid = 0;
- }
- sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;
- addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |
- QE_RCV_INT | QE_ILOOP;
- addr->qe_rcvlist_lo = (short)((int)sc->rringaddr);
- addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16);
- sc->qe_flags |= QEF_RUNNING;
- qestart(ifp);
+ if (sc->sc_inq == 0)
+ return;
+
+ printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname);
+ /*
+ * Do a reset of interface, to get it going again.
+ * Will it work by just restart the transmit logic?
+ */
+ qeinit(sc);
}
-/* $OpenBSD: if_qereg.h,v 1.3 1997/09/10 08:28:42 maja Exp $ */
-/* $NetBSD: if_qereg.h,v 1.2 1997/05/15 20:10:23 ragge Exp $ */
+/* $OpenBSD: if_qereg.h,v 1.4 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_qereg.h,v 1.5 1999/06/20 00:04:47 ragge Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
* *
* If the Regents of the University of California or its *
* licensees modify the software in a manner creating *
- * diriviative copyright rights, appropriate copyright *
- * legends may be placed on the drivative work in addition *
+ * derivative copyright rights, appropriate copyright *
+ * legends may be placed on the derivative work in addition *
* to that set forth above. *
* *
****************************************************************/
/*
* Digital Q-BUS to NI Adapter
*/
+#ifdef notdef
struct qedevice {
u_short qe_sta_addr[2]; /* Station address (actually 6 */
u_short qe_rcvlist_lo; /* Receive list lo address */
u_short qe_vector; /* Interrupt vector */
u_short qe_csr; /* Command and Status Register */
};
+#endif
+
+/*
+ * Register offsets in register space.
+ */
+#define QE_CSR_ADDR1 0
+#define QE_CSR_ADDR2 2
+#define QE_CSR_RCLL 4
+#define QE_CSR_RCLH 6
+#define QE_CSR_XMTL 8
+#define QE_CSR_XMTH 10
+#define QE_CSR_VECTOR 12
+#define QE_CSR_CSR 14
/*
* Command and status bits (csr)
*/
struct qe_ring {
u_short qe_flag; /* Buffer utilization flags */
- u_short qe_addr_hi:6, /* Hi order bits of buffer addr */
- qe_odd_begin:1, /* Odd byte begin and end (xmit)*/
- qe_odd_end:1,
- qe_fill1:4,
- qe_setup:1, /* Setup packet */
- qe_eomsg:1, /* End of message flag */
- qe_chain:1, /* Chain address instead of buf */
- qe_valid:1; /* Address field is valid */
+ u_short qe_addr_hi;
u_short qe_addr_lo; /* Low order bits of address */
short qe_buf_len; /* Negative buffer length */
u_short qe_status1; /* Status word one */
u_short qe_status2; /* Status word two */
};
+
+/*
+ * High word address control bits.
+ */
+#define QE_VALID 0x8000
+#define QE_CHAIN 0x4000
+#define QE_EOMSG 0x2000
+#define QE_SETUP 0x1000
+#define QE_ODDEND 0x0080
+#define QE_ODDBEGIN 0x0040
/*
* Status word definations (receive)
/*
* Values for the length of the setup packet that control reception filter.
*/
-#define QE_SOMEMULTI 128 /* Receive up to 12 multicasts */
-#define QE_ALLMULTI 129 /* Receive all multicasts */
-#define QE_PROMISC 130 /* Receive all packets */
+#define QE_SETUPLEN 128 /* Size of setup packet */
+#define QE_ALLMULTI 1 /* Receive all multicasts */
+#define QE_PROMISC 2 /* Receive all packets */
-/* $OpenBSD: if_uba.c,v 1.5 1997/05/29 00:04:33 niklas Exp $ */
-/* $NetBSD: if_uba.c,v 1.12 1996/08/20 14:07:46 ragge Exp $ */
+/* $OpenBSD: if_uba.c,v 1.6 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_uba.c,v 1.15 1999/01/01 21:43:18 ragge Exp $ */
/*
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
off = MCLBYTES - hlen;
else
off = 0;
- nclbytes = roundup(nmr * NBPG, MCLBYTES);
+ nclbytes = roundup(nmr * VAX_NBPG, MCLBYTES);
if (hlen)
nclbytes += MCLBYTES;
if (ifr[0].ifrw_addr)
register int info;
info =
- uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*NBPG + ifu->iff_hlen,
+ uballoc(ifu->iff_softc, ifrw->ifrw_addr, nmr*VAX_NBPG + ifu->iff_hlen,
ifu->iff_flags);
if (info == 0)
return (0);
pp = mtod(m, char *);
cpte = (struct pte *)kvtopte(cp);
ppte = (struct pte *)kvtopte(pp);
- x = btop(cp - ifr->ifrw_addr);
+ x = vax_btop(cp - ifr->ifrw_addr);
ip = (int *)&ifr->ifrw_mr[x];
- for (i = 0; i < MCLBYTES/NBPG; i++) {
+ for (i = 0; i < MCLBYTES/VAX_NBPG; i++) {
struct pte t;
t = *ppte; *ppte++ = *cpte; *cpte = t;
*ip++ = cpte++->pg_pfn|ifr->ifrw_proto;
mtpr(cp,PR_TBIS);
- cp += NBPG;
+ cp += VAX_NBPG;
mtpr((caddr_t)pp,PR_TBIS);
- pp += NBPG;
+ pp += VAX_NBPG;
}
goto nocopy;
}
{
register struct mbuf *m;
struct mbuf **mprev;
- register i;
+ register int i;
char *cp;
while ((i = ffs((long)ifw->ifw_xswapd)) != 0) {
restor_xmtbuf(ifw)
register struct ifxmt *ifw;
{
- register i;
+ register int i;
for (i = 0; i < ifw->ifw_nmr; i++)
ifw->ifw_wmap[i] = ifw->ifw_mr[i];
int *ip;
pte = (struct pte *)kvtopte(dp);
- x = btop(cp - ifw->ifw_addr);
+ x = vax_btop(cp - ifw->ifw_addr);
ip = (int *)&ifw->ifw_mr[x];
- for (i = 0; i < MCLBYTES/NBPG; i++)
+ for (i = 0; i < MCLBYTES/VAX_NBPG; i++)
*ip++ = ifw->ifw_proto | pte++->pg_pfn;
- xswapd |= 1 << (x>>(MCLSHIFT-PGSHIFT));
+ xswapd |= 1 << (x>>(MCLSHIFT-VAX_PGSHIFT));
mp = m->m_next;
m->m_next = ifw->ifw_xtofree;
ifw->ifw_xtofree = m;
if (i >= x)
break;
ifw->ifw_xswapd &= ~(1<<i);
- i *= MCLBYTES/NBPG;
- for (t = 0; t < MCLBYTES/NBPG; t++) {
+ i *= MCLBYTES/VAX_NBPG;
+ for (t = 0; t < MCLBYTES/VAX_NBPG; t++) {
ifw->ifw_mr[i] = ifw->ifw_wmap[i];
i++;
}
--- /dev/null
+/* $OpenBSD: if_ze.c,v 1.1 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_ze.c,v 1.3 2000/01/24 02:54:03 matt Exp $ */
+/*
+ * Copyright (c) 1999 Ludd, University of Lule}, Sweden. 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 at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/scb.h>
+
+#include <arch/vax/if/sgecreg.h>
+#include <arch/vax/if/sgecvar.h>
+
+/*
+ * Adresses.
+ */
+#define SGECADDR 0x20008000
+#define NISA_ROM 0x20084000
+#define SGECVEC 0x108
+
+static int zematch __P((struct device *, struct cfdata *, void *));
+static void zeattach __P((struct device *, struct device *, void *));
+
+struct cfattach ze_ibus_ca = {
+ sizeof(struct ze_softc), (cfmatch_t)zematch, zeattach
+};
+
+struct cfdriver ze_cd = {
+ NULL, "ze", DV_IFNET
+};
+
+/*
+ * Check for present SGEC.
+ */
+int
+zematch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct bp_conf *bp = aux;
+
+ /*
+ * Should some more intelligent checking be done???
+ */
+ if (strcmp(bp->type, "sgec") == 0)
+ return 1;
+ return 0;
+}
+
+/*
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
+ */
+void
+zeattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ extern struct vax_bus_dma_tag vax_bus_dma_tag;
+ struct ze_softc *sc = (struct ze_softc *)self;
+ int *ea, i;
+
+ /*
+ * Map in SGEC registers.
+ */
+ sc->sc_ioh = vax_map_physmem(SGECADDR, 1);
+ sc->sc_iot = 0; /* :-) */
+ sc->sc_dmat = &vax_bus_dma_tag;
+
+ sc->sc_intvec = SGECVEC;
+
+ /*
+ * Map in, read and release ethernet rom address.
+ */
+ ea = (int *)vax_map_physmem(NISA_ROM, 1);
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->sc_ac.ac_enaddr[i] = (ea[i] >> 8) & 0377;
+ vax_unmap_physmem((vaddr_t)ea, 1);
+
+ scb_vecalloc(SGECVEC, (void (*)(void *)) sgec_intr, sc, SCB_ISTACK);
+
+ sgec_attach(sc);
+}
--- /dev/null
+/* $OpenBSD: if_zereg.h,v 1.1 2000/04/27 03:14:43 bjc Exp $ */
+/* $NetBSD: if_zereg.h,v 1.1 1998/07/01 10:52:10 ragge Exp $ */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Digital Equipment Corp.
+ *
+ * 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.
+ *
+ */
+
+
+/* Driver for SGEC (second generation Ethernet controller) chip, type DC-541,
+ found on the KA670 (and prob ably other) CPU.
+
+ 17 May 1998...Jay Maynard, jmaynard@phoenix.net
+*/
+
+/* SGEC CSRs */
+struct zedevice {
+ u_long ze_nicsr0; /* vector address, IPL, sync mode */
+ u_long ze_nicsr1; /* TX poll demand */
+ u_long ze_nicsr2; /* RX poll demand */
+ struct ze_rdes *ze_nicsr3; /* RX descriptor list address */
+ struct ze_tdes *ze_nicsr4; /* TX descriptor list address */
+ u_long ze_nicsr5; /* SGEC status */
+ u_long ze_nicsr6; /* SGEC command/mode */
+ u_long ze_nicsr7; /* system page table base address */
+ u_long ze_nivcsr8; /* reserved virtual CSR */
+ u_long ze_nivcsr9; /* watchdog timers (virtual) */
+ u_long ze_nivcsr10; /* revision, missed frame count (v) */
+ u_long ze_nivcsr11; /* boot message verification (low) (v) */
+ u_long ze_nivcsr12; /* boot message verification (high) (v) */
+ u_long ze_nivcsr13; /* boot message processor (v) */
+ u_long ze_nivcsr14; /* diagnostic breakpoint (v) */
+ u_long ze_nicsr15; /* monitor command */
+};
+
+/* SGEC bit definitions */
+/* NICSR0: */
+#define ZE_NICSR0_IPL 0xc0000000 /* interrupt priority level: */
+#define ZE_NICSR0_IPL14 0x00000000 /* 0x14 */
+#define ZE_NICSR0_IPL15 0x40000000 /* 0x15 */
+#define ZE_NICSR0_IPL16 0x80000000 /* 0x16 */
+#define ZE_NICSR0_IPL17 0xc0000000 /* 0x17 */
+#define ZE_NICSR0_SA 0x20000000 /* sync(1)/async mode */
+#define ZE_NICSR0_MBO 0x1fff0003 /* must be set to one on write */
+#define ZE_NICSR0_IV_MASK 0x0000fffc /* bits for the interrupt vector */
+
+/* NICSR1: */
+#define ZE_NICSR1_TXPD 0xffffffff /* transmit polling demand */
+
+/* NICSR2: */
+#define ZE_NICSR2_RXPD 0xffffffff /* receive polling demand */
+
+/* NICSR3 and NICSR4 are pure addresses */
+/* NICSR5: */
+#define ZE_NICSR5_ID 0x80000000 /* init done */
+#define ZE_NICSR5_SF 0x40000000 /* self-test failed */
+#define ZE_NICSR5_SS 0x3c000000 /* self-test status field */
+#define ZE_NICSR5_TS 0x03000000 /* transmission state: */
+#define ZE_NICSR5_TS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_TS_RUN 0x01000000 /* running */
+#define ZE_NICSR5_TS_SUSP 0x02000000 /* suspended */
+#define ZE_NICSR5_RS 0x00c00000 /* reception state: */
+#define ZE_NICSR5_RS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_RS_RUN 0x00400000 /* running */
+#define ZE_NICSR5_RS_SUSP 0x00800000 /* suspended */
+#define ZE_NICSR5_OM 0x00060000 /* operating mode: */
+#define ZE_NICSR5_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR5_OM_ILBK 0x00020000 /* internal loopback */
+#define ZE_NICSR5_OM_ELBK 0x00040000 /* external loopback */
+#define ZE_NICSR5_OM_DIAG 0x00060000 /* reserved for diags */
+#define ZE_NICSR5_DN 0x00010000 /* virtual CSR access done */
+#define ZE_NICSR5_MBO 0x0038ff00 /* must be one */
+#define ZE_NICSR5_BO 0x00000080 /* boot message received */
+#define ZE_NICSR5_TW 0x00000040 /* transmit watchdog timeout */
+#define ZE_NICSR5_RW 0x00000020 /* receive watchdog timeout */
+#define ZE_NICSR5_ME 0x00000010 /* memory error */
+#define ZE_NICSR5_RU 0x00000008 /* receive buffer unavailable */
+#define ZE_NICSR5_RI 0x00000004 /* receiver interrupt */
+#define ZE_NICSR5_TI 0x00000002 /* transmitter interrupt */
+#define ZE_NICSR5_IS 0x00000001 /* interrupt summary */
+/* whew! */
+
+/* NICSR6: */
+#define ZE_NICSR6_RE 0x80000000 /* reset */
+#define ZE_NICSR6_IE 0x40000000 /* interrupt enable */
+#define ZE_NICSR6_MBO 0x01e7f000 /* must be one */
+#define ZE_NICSR6_BL 0x1e000000 /* burst limit mask */
+#define ZE_NICSR6_BL_8 0x10000000 /* 8 longwords */
+#define ZE_NICSR6_BL_4 0x08000000 /* 4 longwords */
+#define ZE_NICSR6_BL_2 0x04000000 /* 2 longwords */
+#define ZE_NICSR6_BL_1 0x02000000 /* 1 longword */
+#define ZE_NICSR6_BE 0x00100000 /* boot message enable */
+#define ZE_NICSR6_SE 0x00080000 /* single cycle enable */
+#define ZE_NICSR6_ST 0x00000800 /* start(1)/stop(0) transmission */
+#define ZE_NICSR6_SR 0x00000400 /* start(1)/stop(0) reception */
+#define ZE_NICSR6_OM 0x00000300 /* operating mode: */
+#define ZE_NICSR6_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR6_OM_ILBK 0x00000100 /* internal loopback */
+#define ZE_NICSR6_OM_ELBK 0x00000200 /* external loopback */
+#define ZE_NICSR6_OM_DIAG 0x00000300 /* reserved for diags */
+#define ZE_NICSR6_DC 0x00000080 /* disable data chaining */
+#define ZE_NICSR6_FC 0x00000040 /* force collision mode */
+#define ZE_NICSR6_PB 0x00000008 /* pass bad frames */
+#define ZE_NICSR6_AF 0x00000006 /* address filtering mode: */
+#define ZE_NICSR6_AF_NORM 0x00000000 /* normal filtering */
+#define ZE_NICSR6_AF_PROM 0x00000002 /* promiscuous mode */
+#define ZE_NICSR6_AF_ALLM 0x00000004 /* all multicasts */
+
+/* NICSR7 is an address, NICSR8 is reserved */
+/* NICSR9: */
+#define ZE_VNICSR9_RT 0xffff0000 /* receiver timeout, *1.6 us */
+#define ZE_VNICSR9_TT 0x0000ffff /* transmitter timeout */
+
+/* NICSR10: */
+#define ZE_VNICSR10_RN 0x001f0000 /* SGEC version */
+#define ZE_VNICSR10_MFC 0x0000ffff /* missed frame counter */
+
+/* if you want to know what's in NICSRs 11-15, define them yourself! */
+
+/* Descriptors: */
+/* Receive descriptor */
+struct ze_rdes {
+ u_short ze_rdes0; /* descriptor word 0 flags */
+ u_short ze_framelen; /* received frame length */
+ u_char ze_rsvd1[3]; /* unused bytes */
+ u_char ze_rdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_FRAMELEN_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_RDES0_ES 0x8000 /* an error has occurred */
+#define ZE_RDES0_LE 0x4000 /* length error */
+#define ZE_RDES0_DT 0x3000 /* data type: */
+#define ZE_RDES0_DT_NORM 0x0000 /* normal frame */
+#define ZE_RDES0_DT_ILBK 0x1000 /* internally looped back frame */
+#define ZE_RDES0_DT_ELBK 0x2000 /* externally looped back frame */
+#define ZE_RDES0_RF 0x0800 /* runt frame */
+#define ZE_RDES0_BO 0x0400 /* buffer overflow */
+#define ZE_RDES0_FS 0x0200 /* first segment */
+#define ZE_RDES0_LS 0x0100 /* last segment */
+#define ZE_RDES0_TL 0x0080 /* frame too long */
+#define ZE_RDES0_CS 0x0040 /* collision seen */
+#define ZE_RDES0_FT 0x0020 /* Ethernet frame type */
+#define ZE_RDES0_TN 0x0008 /* address translation not valid */
+#define ZE_RDES0_DB 0x0004 /* dribbling bits seen */
+#define ZE_RDES0_CE 0x0002 /* CRC error */
+#define ZE_RDES0_OF 0x0001 /* internal FIFO overflow */
+#define ZE_RDES1_CA 0x80 /* chain address */
+#define ZE_RDES1_VA 0x40 /* virtual address */
+#define ZE_RDES1_VT 0x20 /* virtual(1)/phys PTE address */
+
+/* Transmit descriptor */
+struct ze_tdes {
+ u_short ze_tdes0; /* descriptor word 0 flags */
+ u_short ze_tdr; /* TDR count of cable fault */
+ u_char ze_rsvd1[2]; /* unused bytes */
+ u_short ze_tdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_TDR_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_TDES0_ES 0x8000 /* an error has occurred */
+#define ZE_TDES0_TO 0x4000 /* transmit watchdog timeout */
+#define ZE_TDES0_LE 0x1000 /* length error */
+#define ZE_TDES0_LO 0x0800 /* loss of carrier */
+#define ZE_TDES0_NC 0x0400 /* no carrier */
+#define ZE_TDES0_LC 0x0200 /* late collision */
+#define ZE_TDES0_EC 0x0100 /* excessive collisions */
+#define ZE_TDES0_HF 0x0080 /* heartbeat fail */
+#define ZE_TDES0_CC 0x0078 /* collision count mask */
+#define ZE_TDES0_TN 0x0004 /* address translation invalid */
+#define ZE_TDES0_UF 0x0002 /* underflow */
+#define ZE_TDES0_DE 0x0001 /* transmission deferred */
+#define ZE_TDES1_CA 0x8000 /* chain address */
+#define ZE_TDES1_VA 0x4000 /* virtual address */
+#define ZE_TDES1_DT 0x3000 /* data type: */
+#define ZE_TDES1_DT_NORM 0x0000 /* normal transmit frame */
+#define ZE_TDES1_DT_SETUP 0x2000 /* setup frame */
+#define ZE_TDES1_DT_DIAG 0x3000 /* diagnostic frame */
+#define ZE_TDES1_AC 0x0800 /* CRC disable */
+#define ZE_TDES1_FS 0x0400 /* first segment */
+#define ZE_TDES1_LS 0x0200 /* last segment */
+#define ZE_TDES1_IC 0x0100 /* interrupt on completion */
+#define ZE_TDES1_VT 0x0080 /* virtual(1)/phys PTE address */
+
--- /dev/null
+/* $OpenBSD: sgec.c,v 1.1 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: sgec.c,v 1.1 1999/08/08 11:41:29 ragge Exp $ */
+/*
+ * Copyright (c) 1999 Ludd, University of Lule}, Sweden. 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 at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * Driver for the SGEC (Second Generation Ethernet Controller), sitting
+ * on for example the VAX 4000/300 (KA670).
+ *
+ * The SGEC looks like a mixture of the DEQNA and the TULIP. Fun toy.
+ *
+ * Even though the chip is capable to use virtual addresses (read the
+ * System Page Table directly) this driver doesn't do so, and there
+ * is no benefit in doing it either in NetBSD of today.
+ *
+ * Things that is still to do:
+ * Collect statistics.
+ * Use imperfect filtering when many multicast addresses.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/bus.h>
+
+#include <vax/if/sgecreg.h>
+#include <vax/if/sgecvar.h>
+
+static void zeinit __P((struct ze_softc *));
+static void zestart __P((struct ifnet *));
+static int zeioctl __P((struct ifnet *, u_long, caddr_t));
+static int ze_add_rxbuf __P((struct ze_softc *, int));
+static void ze_setup __P((struct ze_softc *));
+static void zetimeout __P((struct ifnet *));
+static int zereset __P((struct ze_softc *));
+
+#define ZE_WCSR(csr, val) \
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, csr, val)
+#define ZE_RCSR(csr) \
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, csr)
+
+/*
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
+ */
+void
+sgec_attach(sc)
+ struct ze_softc *sc;
+{
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct ze_tdes *tp;
+ struct ze_rdes *rp;
+ bus_dma_segment_t seg;
+ int i, rseg, error;
+
+ /*
+ * Allocate DMA safe memory for descriptors and setup memory.
+ */
+ if ((error = bus_dmamem_alloc(sc->sc_dmat,
+ sizeof(struct ze_cdata), NBPG, 0, &seg, 1, &rseg,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to allocate control data, error = %d\n",
+ error);
+ goto fail_0;
+ }
+
+ if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
+ sizeof(struct ze_cdata), (caddr_t *)&sc->sc_zedata,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf(": unable to map control data, error = %d\n", error);
+ goto fail_1;
+ }
+
+ if ((error = bus_dmamap_create(sc->sc_dmat,
+ sizeof(struct ze_cdata), 1,
+ sizeof(struct ze_cdata), 0, BUS_DMA_NOWAIT,
+ &sc->sc_cmap)) != 0) {
+ printf(": unable to create control data DMA map, error = %d\n",
+ error);
+ goto fail_2;
+ }
+
+ if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
+ sc->sc_zedata, sizeof(struct ze_cdata), NULL,
+ BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to load control data DMA map, error = %d\n",
+ error);
+ goto fail_3;
+ }
+
+ /*
+ * Zero the newly allocated memory.
+ */
+ bzero(sc->sc_zedata, sizeof(struct ze_cdata));
+ /*
+ * Create the transmit descriptor DMA maps.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+ 1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
+ &sc->sc_xmtmap[i]))) {
+ printf(": unable to create tx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_4;
+ }
+ }
+
+ /*
+ * Create receive buffer DMA maps.
+ */
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
+ MCLBYTES, 0, BUS_DMA_NOWAIT,
+ &sc->sc_rcvmap[i]))) {
+ printf(": unable to create rx DMA map %d, error = %d\n",
+ i, error);
+ goto fail_5;
+ }
+ }
+ /*
+ * Pre-allocate the receive buffers.
+ */
+ for (i = 0; i < RXDESCS; i++) {
+ if ((error = ze_add_rxbuf(sc, i)) != 0) {
+ printf(": unable to allocate or map rx buffer %d\n,"
+ " error = %d\n", i, error);
+ goto fail_6;
+ }
+ }
+
+ /*
+ * Create ring loops of the buffer chains.
+ * This is only done once.
+ */
+ sc->sc_pzedata = (struct ze_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
+
+ rp = sc->sc_zedata->zc_recv;
+ rp[RXDESCS].ze_framelen = ZE_FRAMELEN_OW;
+ rp[RXDESCS].ze_rdes1 = ZE_RDES1_CA;
+ rp[RXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_recv;
+
+ tp = sc->sc_zedata->zc_xmit;
+ tp[TXDESCS].ze_tdr = ZE_TDR_OW;
+ tp[TXDESCS].ze_tdes1 = ZE_TDES1_CA;
+ tp[TXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_xmit;
+
+ if (zereset(sc))
+ return;
+
+ strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = zestart;
+ ifp->if_ioctl = zeioctl;
+ ifp->if_watchdog = zetimeout;
+
+ /*
+ * Attach the interface.
+ */
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+#if NBPFILTER > 0
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+ printf("\n%s: hardware address %s\n", sc->sc_dev.dv_xname,
+ ether_sprintf(sc->sc_ac.ac_enaddr));
+ return;
+
+ /*
+ * Free any resources we've allocated during the failed attach
+ * attempt. Do this in reverse order and fall through.
+ */
+ fail_6:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_rxmbuf[i] != NULL) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_rxmbuf[i]);
+ }
+ }
+ fail_5:
+ for (i = 0; i < RXDESCS; i++) {
+ if (sc->sc_xmtmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
+ }
+ fail_4:
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_rcvmap[i] != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
+ }
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
+ fail_3:
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
+ fail_2:
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_zedata,
+ sizeof(struct ze_cdata));
+ fail_1:
+ bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ fail_0:
+ return;
+}
+
+/*
+ * Initialization of interface.
+ */
+void
+zeinit(sc)
+ struct ze_softc *sc;
+{
+ struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
+ struct ze_cdata *zc = sc->sc_zedata;
+ int i;
+
+ /*
+ * Reset the interface.
+ */
+ if (zereset(sc))
+ return;
+
+ sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0;
+ /*
+ * Release and init transmit descriptors.
+ */
+ for (i = 0; i < TXDESCS; i++) {
+ if (sc->sc_txmbuf[i]) {
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
+ m_freem(sc->sc_txmbuf[i]);
+ sc->sc_txmbuf[i] = 0;
+ }
+ zc->zc_xmit[i].ze_tdr = 0; /* Clear valid bit */
+ }
+
+
+ /*
+ * Init receive descriptors.
+ */
+ for (i = 0; i < RXDESCS; i++)
+ zc->zc_recv[i].ze_framelen = ZE_FRAMELEN_OW;
+ sc->sc_nextrx = 0;
+
+ ZE_WCSR(ZE_CSR6, ZE_NICSR6_IE|ZE_NICSR6_BL_8|ZE_NICSR6_ST|
+ ZE_NICSR6_SR|ZE_NICSR6_DC);
+
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ /*
+ * Send a setup frame.
+ * This will start the transmit machinery as well.
+ */
+ ze_setup(sc);
+
+}
+
+/*
+ * Start output on interface.
+ */
+void
+zestart(ifp)
+ struct ifnet *ifp;
+{
+ struct ze_softc *sc = ifp->if_softc;
+ struct ze_cdata *zc = sc->sc_zedata;
+ paddr_t buffer;
+ struct mbuf *m, *m0;
+ int idx, len, s, i, totlen, error;
+ short orword;
+
+ s = splimp();
+ while (sc->sc_inq < (TXDESCS - 1)) {
+
+ if (sc->sc_setup) {
+ ze_setup(sc);
+ continue;
+ }
+ idx = sc->sc_nexttx;
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if (m == 0)
+ goto out;
+ /*
+ * Count number of mbufs in chain.
+ * Always do DMA directly from mbufs, therefore the transmit
+ * ring is really big.
+ */
+ for (m0 = m, i = 0; m0; m0 = m0->m_next)
+ if (m0->m_len)
+ i++;
+ if (i >= TXDESCS)
+ panic("zestart"); /* XXX */
+
+ if ((i + sc->sc_inq) >= (TXDESCS - 1)) {
+ IF_PREPEND(&sc->sc_if.if_snd, m);
+ ifp->if_flags |= IFF_OACTIVE;
+ goto out;
+ }
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ /*
+ * m now points to a mbuf chain that can be loaded.
+ * Loop around and set it.
+ */
+ totlen = 0;
+ for (m0 = m; m0; m0 = m0->m_next) {
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx],
+ mtod(m0, void *), m0->m_len, 0, 0);
+ buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr;
+ len = m0->m_len;
+ if (len == 0)
+ continue;
+
+ totlen += len;
+ /* Word alignment calc */
+ orword = 0;
+ if (totlen == len)
+ orword = ZE_TDES1_FS;
+ if (totlen == m->m_pkthdr.len) {
+ if (totlen < ETHER_ADDR_LEN)
+ len += (ETHER_ADDR_LEN - totlen);
+ orword |= ZE_TDES1_LS;
+ sc->sc_txmbuf[idx] = m;
+ }
+ zc->zc_xmit[idx].ze_bufsize = len;
+ zc->zc_xmit[idx].ze_bufaddr = (char *)buffer;
+ zc->zc_xmit[idx].ze_tdes1 = orword | ZE_TDES1_IC;
+ zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
+
+ if (++idx == TXDESCS)
+ idx = 0;
+ sc->sc_inq++;
+ }
+#ifdef DIAGNOSTIC
+ if (totlen != m->m_pkthdr.len)
+ panic("zestart: len fault");
+#endif
+
+ /*
+ * Kick off the transmit logic, if it is stopped.
+ */
+ if ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN)
+ ZE_WCSR(ZE_CSR1, -1);
+ sc->sc_nexttx = idx;
+ }
+ if (sc->sc_inq == (TXDESCS - 1))
+ ifp->if_flags |= IFF_OACTIVE;
+
+out: if (sc->sc_inq)
+ ifp->if_timer = 5; /* If transmit logic dies */
+ splx(s);
+}
+
+int
+sgec_intr(sc)
+ struct ze_softc *sc;
+{
+ struct ze_cdata *zc = sc->sc_zedata;
+ struct ifnet *ifp = &sc->sc_if;
+ struct ether_header *eh;
+ struct mbuf *m;
+ int csr, len;
+
+ csr = ZE_RCSR(ZE_CSR5);
+ if ((csr & ZE_NICSR5_IS) == 0) /* Wasn't we */
+ return 0;
+ ZE_WCSR(ZE_CSR5, csr);
+
+ if (csr & ZE_NICSR5_RI)
+ while ((zc->zc_recv[sc->sc_nextrx].ze_framelen &
+ ZE_FRAMELEN_OW) == 0) {
+
+ m = sc->sc_rxmbuf[sc->sc_nextrx];
+ len = zc->zc_recv[sc->sc_nextrx].ze_framelen;
+ ze_add_rxbuf(sc, sc->sc_nextrx);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = len;
+ if (++sc->sc_nextrx == RXDESCS)
+ sc->sc_nextrx = 0;
+ eh = mtod(m, struct ether_header *);
+#if NBPFILTER > 0
+ if (ifp->if_bpf) {
+ bpf_mtap(ifp->if_bpf, m);
+ if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN) != 0 &&
+ ((eh->ether_dhost[0] & 1) == 0)) {
+ m_freem(m);
+ continue;
+ }
+ }
+#endif
+ /*
+ * ALLMULTI means PROMISC in this driver.
+ */
+ if ((ifp->if_flags & IFF_ALLMULTI) &&
+ ((eh->ether_dhost[0] & 1) == 0) &&
+ bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN)) {
+ m_freem(m);
+ continue;
+ }
+
+ /* m_adj() the ethernet header out of the way and pass up */
+ m_adj(m, sizeof(struct ether_header));
+ ether_input(ifp, eh, m);
+ }
+
+ if (csr & ZE_NICSR5_TI) {
+ while ((zc->zc_xmit[sc->sc_lastack].ze_tdr & ZE_TDR_OW) == 0) {
+ int idx = sc->sc_lastack;
+
+ if (sc->sc_lastack == sc->sc_nexttx)
+ break;
+ sc->sc_inq--;
+ if (++sc->sc_lastack == TXDESCS)
+ sc->sc_lastack = 0;
+
+ /* XXX collect statistics */
+ if ((zc->zc_xmit[idx].ze_tdes1 & ZE_TDES1_DT) ==
+ ZE_TDES1_DT_SETUP)
+ continue;
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]);
+ if (sc->sc_txmbuf[idx]) {
+ m_freem(sc->sc_txmbuf[idx]);
+ sc->sc_txmbuf[idx] = 0;
+ }
+ }
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ zestart(ifp); /* Put in more in queue */
+ }
+ return 1;
+}
+
+/*
+ * Process an ioctl request.
+ */
+int
+zeioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ze_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ int s = splnet(), error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ switch(ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ zeinit(sc);
+ arp_ifinit(&sc->sc_ac, ifa);
+ break;
+#endif
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ (ifp->if_flags & IFF_RUNNING) != 0) {
+ /*
+ * If interface is marked down and it is running,
+ * stop it. (by disabling receive mechanism).
+ */
+ ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) &
+ ~(ZE_NICSR6_ST|ZE_NICSR6_SR));
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If interface it marked up and it is stopped, then
+ * start it.
+ */
+ zeinit(sc);
+ } else if ((ifp->if_flags & IFF_UP) != 0) {
+ /*
+ * Send a new setup packet to match any new changes.
+ * (Like IFF_PROMISC etc)
+ */
+ ze_setup(sc);
+ }
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ /*
+ * Update our multicast list.
+ */
+ error = (cmd == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &sc->sc_ac):
+ ether_delmulti(ifr, &sc->sc_ac);
+
+ if (error == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware filter
+ * accordingly.
+ */
+ ze_setup(sc);
+ error = 0;
+ }
+ break;
+
+ default:
+ error = EINVAL;
+
+ }
+ splx(s);
+ return (error);
+}
+
+/*
+ * Add a receive buffer to the indicated descriptor.
+ */
+int
+ze_add_rxbuf(sc, i)
+ struct ze_softc *sc;
+ int i;
+{
+ struct mbuf *m;
+ struct ze_rdes *rp;
+ int error;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return (ENOBUFS);
+
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+
+ if (sc->sc_rxmbuf[i] != NULL)
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]);
+
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i],
+ m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
+ if (error)
+ panic("%s: can't load rx DMA map %d, error = %d\n",
+ sc->sc_dev.dv_xname, i, error);
+ sc->sc_rxmbuf[i] = m;
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0,
+ sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD);
+
+ /*
+ * We know that the mbuf cluster is page aligned. Also, be sure
+ * that the IP header will be longword aligned.
+ */
+ m->m_data += 2;
+ rp = &sc->sc_zedata->zc_recv[i];
+ rp->ze_bufsize = (m->m_ext.ext_size - 2);
+ rp->ze_bufaddr = (char *)sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2;
+ rp->ze_framelen = ZE_FRAMELEN_OW;
+
+ return (0);
+}
+
+/*
+ * Create a setup packet and put in queue for sending.
+ */
+void
+ze_setup(sc)
+ struct ze_softc *sc;
+{
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ struct ze_cdata *zc = sc->sc_zedata;
+ struct ifnet *ifp = &sc->sc_if;
+ u_int8_t *enaddr = sc->sc_ac.ac_enaddr;
+ int j, idx, s, reg;
+
+ s = splimp();
+ if (sc->sc_inq == (TXDESCS - 1)) {
+ sc->sc_setup = 1;
+ splx(s);
+ return;
+ }
+ sc->sc_setup = 0;
+ /*
+ * Init the setup packet with valid info.
+ */
+ memset(zc->zc_setup, 0xff, sizeof(zc->zc_setup)); /* Broadcast */
+ bcopy(enaddr, zc->zc_setup, ETHER_ADDR_LEN);
+
+ /*
+ * Multicast handling. The SGEC can handle up to 16 direct
+ * ethernet addresses.
+ */
+ j = 16;
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
+ while (enm != NULL) {
+ if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ bcopy(enm->enm_addrlo, &zc->zc_setup[j], ETHER_ADDR_LEN);
+ j += 8;
+ ETHER_NEXT_MULTI(step, enm);
+ if ((enm != NULL)&& (j == 128)) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ break;
+ }
+ }
+
+ /*
+ * Fiddle with the receive logic.
+ */
+ reg = ZE_RCSR(ZE_CSR6);
+ DELAY(10);
+ ZE_WCSR(ZE_CSR6, reg & ~ZE_NICSR6_SR); /* Stop rx */
+ reg &= ~ZE_NICSR6_AF;
+ if (ifp->if_flags & IFF_PROMISC)
+ reg |= ZE_NICSR6_AF_PROM;
+ else if (ifp->if_flags & IFF_ALLMULTI)
+ reg |= ZE_NICSR6_AF_ALLM;
+ DELAY(10);
+ ZE_WCSR(ZE_CSR6, reg);
+ /*
+ * Only send a setup packet if needed.
+ */
+ if ((ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) == 0) {
+ idx = sc->sc_nexttx;
+ zc->zc_xmit[idx].ze_tdes1 = ZE_TDES1_DT_SETUP;
+ zc->zc_xmit[idx].ze_bufsize = 128;
+ zc->zc_xmit[idx].ze_bufaddr = sc->sc_pzedata->zc_setup;
+ zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
+
+ if ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN)
+ ZE_WCSR(ZE_CSR1, -1);
+
+ sc->sc_inq++;
+ if (++sc->sc_nexttx == TXDESCS)
+ sc->sc_nexttx = 0;
+ }
+ splx(s);
+}
+
+/*
+ * Check for dead transmit logic.
+ */
+void
+zetimeout(ifp)
+ struct ifnet *ifp;
+{
+ struct ze_softc *sc = ifp->if_softc;
+
+ if (sc->sc_inq == 0)
+ return;
+
+ printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname);
+ /*
+ * Do a reset of interface, to get it going again.
+ * Will it work by just restart the transmit logic?
+ */
+ zeinit(sc);
+}
+
+/*
+ * Reset chip:
+ * Set/reset the reset flag.
+ * Write interrupt vector.
+ * Write ring buffer addresses.
+ * Write SBR.
+ */
+int
+zereset(sc)
+ struct ze_softc *sc;
+{
+ int reg, i, s;
+
+ ZE_WCSR(ZE_CSR6, ZE_NICSR6_RE);
+ DELAY(50000);
+ if (ZE_RCSR(ZE_CSR6) & ZE_NICSR5_SF) {
+ printf("%s: selftest failed\n", sc->sc_dev.dv_xname);
+ return 1;
+ }
+
+ /*
+ * Get the vector that were set at match time, and remember it.
+ * WHICH VECTOR TO USE? Take one unused. XXX
+ * Funny way to set vector described in the programmers manual.
+ */
+ reg = ZE_NICSR0_IPL14 | sc->sc_intvec | 0x1fff0003; /* SYNC/ASYNC??? */
+ i = 10;
+ s = splimp();
+ do {
+ if (i-- == 0) {
+ printf("Failing SGEC CSR0 init\n");
+ splx(s);
+ return 1;
+ }
+ ZE_WCSR(ZE_CSR0, reg);
+ } while (ZE_RCSR(ZE_CSR0) != reg);
+ splx(s);
+
+ ZE_WCSR(ZE_CSR3, (vaddr_t)sc->sc_pzedata->zc_recv);
+ ZE_WCSR(ZE_CSR4, (vaddr_t)sc->sc_pzedata->zc_xmit);
+ return 0;
+}
--- /dev/null
+/* $OpenBSD: sgecreg.h,v 1.1 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: sgecreg.h,v 1.1 1999/08/08 11:41:29 ragge Exp $ */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Digital Equipment Corp.
+ *
+ * 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.
+ *
+ */
+
+
+/* Driver for SGEC (second generation Ethernet controller) chip, type DC-541,
+ found on the KA670 (and prob ably other) CPU.
+
+ 17 May 1998...Jay Maynard, jmaynard@phoenix.net
+*/
+
+/* SGEC CSRs */
+struct zedevice {
+ u_long ze_nicsr0; /* vector address, IPL, sync mode */
+ u_long ze_nicsr1; /* TX poll demand */
+ u_long ze_nicsr2; /* RX poll demand */
+ struct ze_rdes *ze_nicsr3; /* RX descriptor list address */
+ struct ze_tdes *ze_nicsr4; /* TX descriptor list address */
+ u_long ze_nicsr5; /* SGEC status */
+ u_long ze_nicsr6; /* SGEC command/mode */
+ u_long ze_nicsr7; /* system page table base address */
+ u_long ze_nivcsr8; /* reserved virtual CSR */
+ u_long ze_nivcsr9; /* watchdog timers (virtual) */
+ u_long ze_nivcsr10; /* revision, missed frame count (v) */
+ u_long ze_nivcsr11; /* boot message verification (low) (v) */
+ u_long ze_nivcsr12; /* boot message verification (high) (v) */
+ u_long ze_nivcsr13; /* boot message processor (v) */
+ u_long ze_nivcsr14; /* diagnostic breakpoint (v) */
+ u_long ze_nicsr15; /* monitor command */
+};
+
+/*
+ * Register offsets.
+ */
+#define ZE_CSR0 0
+#define ZE_CSR1 4
+#define ZE_CSR2 8
+#define ZE_CSR3 12
+#define ZE_CSR4 16
+#define ZE_CSR5 20
+#define ZE_CSR6 24
+#define ZE_CSR7 28
+#define ZE_CSR8 32
+#define ZE_CSR9 36
+#define ZE_CSR10 40
+#define ZE_CSR11 44
+#define ZE_CSR12 48
+#define ZE_CSR13 52
+#define ZE_CSR14 56
+#define ZE_CSR15 60
+
+/* SGEC bit definitions */
+/* NICSR0: */
+#define ZE_NICSR0_IPL 0xc0000000 /* interrupt priority level: */
+#define ZE_NICSR0_IPL14 0x00000000 /* 0x14 */
+#define ZE_NICSR0_IPL15 0x40000000 /* 0x15 */
+#define ZE_NICSR0_IPL16 0x80000000 /* 0x16 */
+#define ZE_NICSR0_IPL17 0xc0000000 /* 0x17 */
+#define ZE_NICSR0_SA 0x20000000 /* sync(1)/async mode */
+#define ZE_NICSR0_MBO 0x1fff0003 /* must be set to one on write */
+#define ZE_NICSR0_IV_MASK 0x0000fffc /* bits for the interrupt vector */
+
+/* NICSR1: */
+#define ZE_NICSR1_TXPD 0xffffffff /* transmit polling demand */
+
+/* NICSR2: */
+#define ZE_NICSR2_RXPD 0xffffffff /* receive polling demand */
+
+/* NICSR3 and NICSR4 are pure addresses */
+/* NICSR5: */
+#define ZE_NICSR5_ID 0x80000000 /* init done */
+#define ZE_NICSR5_SF 0x40000000 /* self-test failed */
+#define ZE_NICSR5_SS 0x3c000000 /* self-test status field */
+#define ZE_NICSR5_TS 0x03000000 /* transmission state: */
+#define ZE_NICSR5_TS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_TS_RUN 0x01000000 /* running */
+#define ZE_NICSR5_TS_SUSP 0x02000000 /* suspended */
+#define ZE_NICSR5_RS 0x00c00000 /* reception state: */
+#define ZE_NICSR5_RS_STOP 0x00000000 /* stopped */
+#define ZE_NICSR5_RS_RUN 0x00400000 /* running */
+#define ZE_NICSR5_RS_SUSP 0x00800000 /* suspended */
+#define ZE_NICSR5_OM 0x00060000 /* operating mode: */
+#define ZE_NICSR5_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR5_OM_ILBK 0x00020000 /* internal loopback */
+#define ZE_NICSR5_OM_ELBK 0x00040000 /* external loopback */
+#define ZE_NICSR5_OM_DIAG 0x00060000 /* reserved for diags */
+#define ZE_NICSR5_DN 0x00010000 /* virtual CSR access done */
+#define ZE_NICSR5_MBO 0x0038ff00 /* must be one */
+#define ZE_NICSR5_BO 0x00000080 /* boot message received */
+#define ZE_NICSR5_TW 0x00000040 /* transmit watchdog timeout */
+#define ZE_NICSR5_RW 0x00000020 /* receive watchdog timeout */
+#define ZE_NICSR5_ME 0x00000010 /* memory error */
+#define ZE_NICSR5_RU 0x00000008 /* receive buffer unavailable */
+#define ZE_NICSR5_RI 0x00000004 /* receiver interrupt */
+#define ZE_NICSR5_TI 0x00000002 /* transmitter interrupt */
+#define ZE_NICSR5_IS 0x00000001 /* interrupt summary */
+/* whew! */
+
+/* NICSR6: */
+#define ZE_NICSR6_RE 0x80000000 /* reset */
+#define ZE_NICSR6_IE 0x40000000 /* interrupt enable */
+#define ZE_NICSR6_MBO 0x01e7f000 /* must be one */
+#define ZE_NICSR6_BL 0x1e000000 /* burst limit mask */
+#define ZE_NICSR6_BL_8 0x10000000 /* 8 longwords */
+#define ZE_NICSR6_BL_4 0x08000000 /* 4 longwords */
+#define ZE_NICSR6_BL_2 0x04000000 /* 2 longwords */
+#define ZE_NICSR6_BL_1 0x02000000 /* 1 longword */
+#define ZE_NICSR6_BE 0x00100000 /* boot message enable */
+#define ZE_NICSR6_SE 0x00080000 /* single cycle enable */
+#define ZE_NICSR6_ST 0x00000800 /* start(1)/stop(0) transmission */
+#define ZE_NICSR6_SR 0x00000400 /* start(1)/stop(0) reception */
+#define ZE_NICSR6_OM 0x00000300 /* operating mode: */
+#define ZE_NICSR6_OM_NORM 0x00000000 /* normal */
+#define ZE_NICSR6_OM_ILBK 0x00000100 /* internal loopback */
+#define ZE_NICSR6_OM_ELBK 0x00000200 /* external loopback */
+#define ZE_NICSR6_OM_DIAG 0x00000300 /* reserved for diags */
+#define ZE_NICSR6_DC 0x00000080 /* disable data chaining */
+#define ZE_NICSR6_FC 0x00000040 /* force collision mode */
+#define ZE_NICSR6_PB 0x00000008 /* pass bad frames */
+#define ZE_NICSR6_AF 0x00000006 /* address filtering mode: */
+#define ZE_NICSR6_AF_NORM 0x00000000 /* normal filtering */
+#define ZE_NICSR6_AF_PROM 0x00000002 /* promiscuous mode */
+#define ZE_NICSR6_AF_ALLM 0x00000004 /* all multicasts */
+
+/* NICSR7 is an address, NICSR8 is reserved */
+/* NICSR9: */
+#define ZE_VNICSR9_RT 0xffff0000 /* receiver timeout, *1.6 us */
+#define ZE_VNICSR9_TT 0x0000ffff /* transmitter timeout */
+
+/* NICSR10: */
+#define ZE_VNICSR10_RN 0x001f0000 /* SGEC version */
+#define ZE_VNICSR10_MFC 0x0000ffff /* missed frame counter */
+
+/* if you want to know what's in NICSRs 11-15, define them yourself! */
+
+/* Descriptors: */
+/* Receive descriptor */
+struct ze_rdes {
+ u_short ze_rdes0; /* descriptor word 0 flags */
+ u_short ze_framelen; /* received frame length */
+ u_char ze_rsvd1[3]; /* unused bytes */
+ u_char ze_rdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_FRAMELEN_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_RDES0_ES 0x8000 /* an error has occurred */
+#define ZE_RDES0_LE 0x4000 /* length error */
+#define ZE_RDES0_DT 0x3000 /* data type: */
+#define ZE_RDES0_DT_NORM 0x0000 /* normal frame */
+#define ZE_RDES0_DT_ILBK 0x1000 /* internally looped back frame */
+#define ZE_RDES0_DT_ELBK 0x2000 /* externally looped back frame */
+#define ZE_RDES0_RF 0x0800 /* runt frame */
+#define ZE_RDES0_BO 0x0400 /* buffer overflow */
+#define ZE_RDES0_FS 0x0200 /* first segment */
+#define ZE_RDES0_LS 0x0100 /* last segment */
+#define ZE_RDES0_TL 0x0080 /* frame too long */
+#define ZE_RDES0_CS 0x0040 /* collision seen */
+#define ZE_RDES0_FT 0x0020 /* Ethernet frame type */
+#define ZE_RDES0_TN 0x0008 /* address translation not valid */
+#define ZE_RDES0_DB 0x0004 /* dribbling bits seen */
+#define ZE_RDES0_CE 0x0002 /* CRC error */
+#define ZE_RDES0_OF 0x0001 /* internal FIFO overflow */
+#define ZE_RDES1_CA 0x80 /* chain address */
+#define ZE_RDES1_VA 0x40 /* virtual address */
+#define ZE_RDES1_VT 0x20 /* virtual(1)/phys PTE address */
+
+/* Transmit descriptor */
+struct ze_tdes {
+ u_short ze_tdes0; /* descriptor word 0 flags */
+ u_short ze_tdr; /* TDR count of cable fault */
+ u_char ze_rsvd1[2]; /* unused bytes */
+ u_short ze_tdes1; /* descriptor word 1 flags */
+ short ze_pageoffset; /* offset of buffer in page */
+ short ze_bufsize; /* length of data buffer */
+ u_char *ze_bufaddr; /* address of data buffer */
+};
+
+/* Receive descriptor bits */
+#define ZE_TDR_OW 0x8000 /* SGEC owns this descriptor */
+#define ZE_TDES0_ES 0x8000 /* an error has occurred */
+#define ZE_TDES0_TO 0x4000 /* transmit watchdog timeout */
+#define ZE_TDES0_LE 0x1000 /* length error */
+#define ZE_TDES0_LO 0x0800 /* loss of carrier */
+#define ZE_TDES0_NC 0x0400 /* no carrier */
+#define ZE_TDES0_LC 0x0200 /* late collision */
+#define ZE_TDES0_EC 0x0100 /* excessive collisions */
+#define ZE_TDES0_HF 0x0080 /* heartbeat fail */
+#define ZE_TDES0_CC 0x0078 /* collision count mask */
+#define ZE_TDES0_TN 0x0004 /* address translation invalid */
+#define ZE_TDES0_UF 0x0002 /* underflow */
+#define ZE_TDES0_DE 0x0001 /* transmission deferred */
+#define ZE_TDES1_CA 0x8000 /* chain address */
+#define ZE_TDES1_VA 0x4000 /* virtual address */
+#define ZE_TDES1_DT 0x3000 /* data type: */
+#define ZE_TDES1_DT_NORM 0x0000 /* normal transmit frame */
+#define ZE_TDES1_DT_SETUP 0x2000 /* setup frame */
+#define ZE_TDES1_DT_DIAG 0x3000 /* diagnostic frame */
+#define ZE_TDES1_AC 0x0800 /* CRC disable */
+#define ZE_TDES1_FS 0x0400 /* first segment */
+#define ZE_TDES1_LS 0x0200 /* last segment */
+#define ZE_TDES1_IC 0x0100 /* interrupt on completion */
+#define ZE_TDES1_VT 0x0080 /* virtual(1)/phys PTE address */
+
--- /dev/null
+/* $OpenBSD: sgecvar.h,v 1.1 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: sgecvar.h,v 1.1 1999/08/08 11:41:30 ragge Exp $ */
+/*
+ * Copyright (c) 1999 Ludd, University of Lule}, Sweden. 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 at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#define RXDESCS 30 /* # of receive descriptors */
+#define TXDESCS 60 /* # transmit descs */
+
+/*
+ * Descriptors must be an even number; optimisation thing.
+ */
+struct ze_cdata {
+ struct ze_rdes zc_recv[RXDESCS+2]; /* Receive descriptors */
+ struct ze_tdes zc_xmit[TXDESCS+2]; /* Transmit descriptors */
+ u_int8_t zc_setup[128]; /* Setup packet layout */
+};
+
+struct ze_softc {
+ struct device sc_dev; /* Configuration common part */
+ struct arpcom sc_ac; /* Ethernet common part */
+#define sc_if sc_ac.ac_if /* network-visible interface */
+ bus_space_tag_t sc_iot;
+ bus_addr_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+ struct ze_cdata *sc_zedata; /* Descriptor struct */
+ struct ze_cdata *sc_pzedata; /* Physical address of above */
+ bus_dmamap_t sc_cmap; /* Map for control structures */
+ struct mbuf* sc_txmbuf[TXDESCS];
+ struct mbuf* sc_rxmbuf[RXDESCS];
+ bus_dmamap_t sc_xmtmap[TXDESCS];
+ bus_dmamap_t sc_rcvmap[RXDESCS];
+ int sc_intvec; /* Interrupt vector */
+ int sc_nexttx;
+ int sc_inq;
+ int sc_lastack;
+ int sc_nextrx;
+ int sc_setup; /* Setup packet in queue */
+};
+
+void sgec_attach __P((struct ze_softc *));
+int sgec_intr __P((struct ze_softc *));
-/* $OpenBSD: hp.c,v 1.9 1998/10/03 21:18:59 millert Exp $ */
-/* $NetBSD: hp.c,v 1.15 1997/06/24 01:09:37 thorpej Exp $ */
+/* $OpenBSD: hp.c,v 1.10 2000/04/27 03:14:44 bjc Exp $ */
+/* $NetBSD: hp.c,v 1.22 2000/02/12 16:09:33 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
int sc_physnr; /* Physical disk number */
};
-int hpmatch __P((struct device *, void *, void *));
+int hpmatch __P((struct device *, struct cfdata *, void *));
void hpattach __P((struct device *, struct device *, void *));
void hpstrategy __P((struct buf *));
void hpstart __P((struct mba_device *));
int hpwrite __P((dev_t, struct uio *));
int hpsize __P((dev_t));
-struct cfdriver hp_cd = {
- NULL, "hp", DV_DISK
-};
-
struct cfattach hp_ca = {
sizeof(struct hp_softc), hpmatch, hpattach
};
+extern struct cfdriver hp_cd;
+
/*
* Check if this is a disk drive; done by checking type from mbaattach.
*/
int
-hpmatch(parent, match, aux)
+hpmatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct cfdata *cf = match;
struct mba_attach_args *ma = aux;
- if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ma->unit)
+ if (cf->cf_loc[MBACF_DRIVE] != MBACF_DRIVE_DEFAULT &&
+ cf->cf_loc[MBACF_DRIVE] != ma->unit)
return 0;
if (ma->devtyp != MB_RP)
/*
* Init the common struct for both the adapter and its slaves.
*/
+ BUFQ_INIT(&sc->sc_md.md_q);
sc->sc_md.md_softc = (void *)sc; /* Pointer to this softc */
sc->sc_md.md_mba = (void *)parent; /* Pointer to parent softc */
sc->sc_md.md_start = hpstart; /* Disk start routine */
* Read in label.
*/
if ((msg = readdisklabel(makedev(0, self->dv_unit * 8), hpstrategy,
- dl, NULL, 0)) != NULL)
+ dl, NULL)) != NULL)
printf(": %s", msg);
printf(": %s, size = %d sectors\n", dl->d_typename, dl->d_secperunit);
/*
{
struct hp_softc *sc;
struct buf *gp;
- int unit, s;
+ int unit, s, err;
+ struct disklabel *lp;
unit = DISKUNIT(bp->b_dev);
sc = hp_cd.cd_devs[unit];
+ lp = sc->sc_disk.dk_label;
- if (bounds_check_with_label(bp, sc->sc_disk.dk_label,
- sc->sc_disk.dk_cpulabel, sc->sc_wlabel) <= 0)
+ err = bounds_check_with_label(bp, lp, sc->sc_wlabel);
+ if (err < 0)
goto done;
+
+ bp->b_rawblkno =
+ bp->b_blkno + lp->d_partitions[DISKPART(bp->b_dev)].p_offset;
+ bp->b_cylinder = bp->b_rawblkno / lp->d_secpercyl;
+
s = splbio();
- gp = sc->sc_md.md_q.b_actf;
- disksort(&sc->sc_md.md_q, bp);
+ gp = BUFQ_FIRST(&sc->sc_md.md_q);
+ disksort_cylinder(&sc->sc_md.md_q, bp);
if (gp == 0)
mbaqueue(&sc->sc_md);
struct mba_regs *mr = md->md_mba->sc_mbareg;
volatile struct hp_regs *hr;
struct disklabel *lp = sc->sc_disk.dk_label;
- struct buf *bp = md->md_q.b_actf;
+ struct buf *bp = BUFQ_FIRST(&md->md_q);
unsigned bn, cn, sn, tn;
- int part = DISKPART(bp->b_dev);
/*
* Collect statistics.
hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)];
- bn = bp->b_blkno + lp->d_partitions[part].p_offset;
+ bn = bp->b_rawblkno;
if (bn) {
cn = bn / lp->d_secpercyl;
sn = bn % lp->d_secpercyl;
int mbasr, *attn;
{
struct hp_softc *sc = md->md_softc;
- struct buf *bp = md->md_q.b_actf;
+ struct buf *bp = BUFQ_FIRST(&md->md_q);
volatile struct mba_regs *mr = md->md_mba->sc_mbareg;
volatile struct hp_regs *hr = (void *)&mr->mba_md[DISKUNIT(bp->b_dev)];
int er1, er2;
printf("massbuss error :%s %x\n",
sc->sc_dev.dv_xname, mbasr);
- md->md_q.b_actf->b_resid = 0;
- disk_unbusy(&sc->sc_disk, md->md_q.b_actf->b_bcount);
+ BUFQ_FIRST(&md->md_q)->b_resid = 0;
+ disk_unbusy(&sc->sc_disk, BUFQ_FIRST(&md->md_q)->b_bcount);
return XFER_FINISH;
}
return -1;
sc = hp_cd.cd_devs[unit];
- size = sc->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size;
+ size = sc->sc_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
+ (sc->sc_disk.dk_label->d_secsize / DEV_BSIZE);
return size;
}
{
return (physio(hpstrategy, NULL, dev, B_WRITE, minphys, uio));
}
-
-/*
- * Convert physical adapternr and unit to the unit number used by kernel.
- */
-int
-hp_getdev(mbanr, unit, uname)
- int mbanr, unit;
- char **uname;
-{
- struct mba_softc *ms;
- struct hp_softc *sc;
- int i;
-
- for (i = 0; i < hp_cd.cd_ndevs; i++) {
- if (hp_cd.cd_devs[i] == 0)
- continue;
-
- sc = hp_cd.cd_devs[i];
- ms = (void *)sc->sc_dev.dv_parent;
- if (ms->sc_physnr == mbanr && sc->sc_physnr == unit) {
- *uname = sc->sc_dev.dv_xname;
- return i;
- }
- }
- return -1;
-}
-/* $OpenBSD: mba.c,v 1.5 1997/05/29 00:04:59 niklas Exp $ */
-/* $NetBSD: mba.c,v 1.10 1996/10/13 03:35:00 christos Exp $ */
+/* $OpenBSD: mba.c,v 1.6 2000/04/27 03:14:45 bjc Exp $ */
+/* $NetBSD: mba.c,v 1.18 2000/01/24 02:40:36 matt Exp $ */
/*
* Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
#include <machine/pte.h>
#include <machine/pcb.h>
#include <machine/sid.h>
+#include <machine/cpu.h>
#include <vax/mba/mbareg.h>
#include <vax/mba/mbavar.h>
{0, 0, 0}
};
-int mbamatch __P((struct device *, void *, void *));
+int mbamatch __P((struct device *, struct cfdata *, void *));
void mbaattach __P((struct device *, struct device *, void *));
-void mbaintr __P((int));
+void mbaintr __P((void *));
int mbaprint __P((void *, const char *));
void mbaqueue __P((struct mba_device *));
void mbastart __P((struct mba_softc *));
void mbamapregs __P((struct mba_softc *));
-struct cfdriver mba_cd = {
- NULL, "mba", DV_DULL
-};
-
struct cfattach mba_cmi_ca = {
sizeof(struct mba_softc), mbamatch, mbaattach
};
sizeof(struct mba_softc), mbamatch, mbaattach
};
+extern struct cfdriver mba_cd;
+
/*
* Look if this is a massbuss adapter.
*/
int
-mbamatch(parent, match, aux)
+mbamatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
- struct cfdata *cf = match;
if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
return 0;
struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
volatile struct mba_regs *mbar = (struct mba_regs *)sa->nexaddr;
struct mba_attach_args ma;
- extern struct ivec_dsp idsptch;
int i, j;
printf("\n");
/*
* Set up interrupt vectors for this MBA.
*/
- bcopy(&idsptch, &sc->sc_dsp, sizeof(struct ivec_dsp));
+ sc->sc_dsp = idsptch;
+ sc->sc_dsp.pushlarg = sc;
+ sc->sc_dsp.hoppaddr = mbaintr;
scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum] =
scb->scb_nexvec[2][sa->nexnum] = scb->scb_nexvec[3][sa->nexnum] =
&sc->sc_dsp;
- sc->sc_dsp.pushlarg = sc->sc_dev.dv_unit;
- sc->sc_dsp.hoppaddr = mbaintr;
sc->sc_physnr = sa->nexnum - 8; /* MBA's have TR between 8 - 11... */
-#ifdef VAX750
+#if VAX750
if (vax_cputype == VAX_750)
sc->sc_physnr += 4; /* ...but not on 11/750 */
#endif
*/
void
mbaintr(mba)
- int mba;
+ void *mba;
{
- struct mba_softc *sc = mba_cd.cd_devs[mba];
+ struct mba_softc *sc = mba;
volatile struct mba_regs *mr = sc->sc_mbareg;
struct mba_device *md;
struct buf *bp;
return; /* During autoconfig */
md = sc->sc_first;
- bp = md->md_q.b_actf;
+ bp = BUFQ_FIRST(&md->md_q);
/*
* A data-transfer interrupt. Current operation is finished,
* call that device's finish routine to see what to do next.
* If more to transfer, start the adapter again
* by calling mbastart().
*/
- md->md_q.b_actf = bp->b_actf;
+ BUFQ_REMOVE(&md->md_q, bp);
sc->sc_first = md->md_back;
md->md_back = 0;
if (sc->sc_first == 0)
sc->sc_last = (void *)&sc->sc_first;
- if (md->md_q.b_actf) {
+ if (BUFQ_FIRST(&md->md_q) != NULL) {
sc->sc_last->md_back = md;
sc->sc_last = md;
}
{
struct mba_device *md = sc->sc_first;
volatile struct mba_regs *mr = sc->sc_mbareg;
- struct buf *bp = md->md_q.b_actf;
+ struct buf *bp = BUFQ_FIRST(&md->md_q);
- disk_reallymapin(md->md_q.b_actf, sc->sc_mbareg->mba_map, 0, PG_V);
+ disk_reallymapin(BUFQ_FIRST(&md->md_q), sc->sc_mbareg->mba_map,
+ 0, PG_V);
sc->sc_state = SC_ACTIVE;
- mr->mba_var = ((u_int)bp->b_un.b_addr & PGOFSET);
+ mr->mba_var = ((u_int)bp->b_un.b_addr & VAX_PGOFSET);
mr->mba_bc = (~bp->b_bcount) + 1;
(*md->md_start)(md); /* machine-dependent start */
}
-/* $OpenBSD: mbavar.h,v 1.3 1997/05/29 00:05:00 niklas Exp $ */
-/* $NetBSD: mbavar.h,v 1.4 1996/04/08 18:39:01 ragge Exp $ */
+/* $OpenBSD: mbavar.h,v 1.4 2000/04/27 03:14:45 bjc Exp $ */
+/* $NetBSD: mbavar.h,v 1.5 2000/01/21 23:39:56 thorpej Exp $ */
/*
* Copyright (c) 1994 Ludd, University of Lule}, Sweden
* All rights reserved.
enum xfer_action (*md_finish) __P((struct mba_device *, int, int *));
void *md_softc; /* Backpointer to this units softc. */
struct mba_softc *md_mba;
- struct buf md_q; /* Buffer head for transfers */
+ struct buf_queue md_q; /* queue of I/O requests */
};
struct mba_softc {
-# $OpenBSD: files.mscp,v 1.2 1997/05/29 00:05:01 niklas Exp $
-# $NetBSD: files.mscp,v 1.1 1996/07/01 20:41:30 ragge Exp $
+# $OpenBSD: files.mscp,v 1.3 2000/04/27 03:14:45 bjc Exp $
+# $NetBSD: files.mscp,v 1.7 1999/06/06 19:16:18 ragge Exp $
#
# File and device description for MSCP devices.
#
define mscp {}
-file arch/vax/mscp/mscp.c
-file arch/vax/mscp/mscp_subr.c
+file arch/vax/mscp/mscp.c mscp
+file arch/vax/mscp/mscp_subr.c mscp
device mscpbus {drive = -1}
attach mscpbus at mscp
+device rx: disk
+attach rx at mscpbus
+
device ra: disk
attach ra at mscpbus
-file arch/vax/mscp/mscp_disk.c ra needs-flag
+file arch/vax/mscp/mscp_disk.c ra | rx needs-flag
device mt: tape
attach mt at mscpbus
-/* $OpenBSD: mscp.c,v 1.3 1997/09/12 09:25:47 maja Exp $ */
-/* $NetBSD: mscp.c,v 1.6 1997/07/04 11:58:20 ragge Exp $ */
+/* $OpenBSD: mscp.c,v 1.4 2000/04/27 03:14:45 bjc Exp $ */
+/* $NetBSD: mscp.c,v 1.11 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpvar.h>
+#include <machine/bus.h>
-#define PCMD PSWP /* priority for command packet waits */
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
-/*
- * During transfers, mapping info is saved in the buffer's b_resid.
- */
-#define b_info b_resid
+#define PCMD PSWP /* priority for command packet waits */
/*
* Get a command packet. Second argument is true iff we are
register struct mscp_softc *mi;
int canwait;
{
-#define mri (&mi->mi_cmd)
+#define mri (&mi->mi_cmd)
register struct mscp *mp;
register int i;
- int s = splbio();
+ int s = splimp();
again:
/*
mp->mscp_seq.seq_bytecount = 0;
mp->mscp_seq.seq_buffer = 0;
mp->mscp_seq.seq_mapbase = 0;
-/*???*/ mp->mscp_sccc.sccc_errlgfl = 0;
-/*???*/ mp->mscp_sccc.sccc_copyspd = 0;
+/*???*/ mp->mscp_sccc.sccc_errlgfl = 0;
+/*???*/ mp->mscp_sccc.sccc_copyspd = 0;
return (mp);
#undef mri
}
struct device *drive;
struct mscp_device *me = mi->mi_me;
struct mscp_ctlr *mc = mi->mi_mc;
- register struct buf *bp;
- register struct mscp *mp;
- register int nextrsp;
- int st, error, info;
+ struct buf *bp;
+ struct mscp *mp;
+ struct mscp_xi *mxi;
+ int nextrsp;
+ int st, error;
extern int cold;
extern struct mscp slavereply;
case M_OP_ONLINE | M_OP_END:
/*
- * Finished an ON LINE request. Call the driver to
+ * Finished an ON LINE request. Call the driver to
* find out whether it succeeded. If so, mark it on
* line.
*/
case M_OP_POS | M_OP_END:
case M_OP_WRITM | M_OP_END:
+ case M_OP_AVAILABLE | M_OP_END:
/*
* A non-data transfer operation completed.
*/
case M_OP_READ | M_OP_END:
case M_OP_WRITE | M_OP_END:
/*
- * A transfer finished. Get the buffer, and release its
- * map registers via ubadone(). If the command finished
+ * A transfer finished. Get the buffer, and release its
+ * map registers via ubadone(). If the command finished
* with an off line or available status, the drive went
* off line (the idiot controller does not tell us until
* it comes back *on* line, or until we try to use it).
*/
rwend:
#ifdef DIAGNOSTIC
- if (mp->mscp_cmdref == 0) {
+ if (mp->mscp_cmdref >= NCMD) {
/*
* No buffer means there is a bug somewhere!
*/
- printf("%s: io done, but no buffer?\n",
+ printf("%s: io done, but bad xfer number?\n",
drive->dv_xname);
mscp_hexdump(mp);
break;
}
#endif
- bp = (struct buf *) mp->mscp_cmdref;
if (mp->mscp_cmdref == -1) {
(*me->me_cmddone)(drive, mp);
break;
}
+ mxi = &mi->mi_xi[mp->mscp_cmdref];
+ if (mxi->mxi_inuse == 0)
+ panic("mxi not inuse");
+ bp = mxi->mxi_bp;
/*
* Mark any error-due-to-bad-LBN (via `goto rwend').
- * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE
+ * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE
* IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
*/
if (error) {
#endif
}
- /*
- * Unlink the transfer from the wait queue.
- */
- _remque(&bp->b_actf);
-
/*
* If the transfer has something to do with bad
* block forwarding, let the driver handle the
* done. If the I/O wait queue is now empty, release
* the shared BDP, if any.
*/
- info = bp->b_info; /* we are about to clobber it */
bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount;
+ bus_dmamap_unload(mi->mi_dmat, mxi->mxi_dmam);
- (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent, info);
+ (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent);
(*me->me_iodone)(drive, bp);
out:
+ mxi->mxi_inuse = 0;
+ mi->mi_mxiuse |= (1 << mp->mscp_cmdref);
break;
case M_OP_REPLACE | M_OP_END:
/*
* If the drive needs to be put back in the controller queue,
- * do that now. (`bp' below ought to be `dp', but they are all
+ * do that now. (`bp' below ought to be `dp', but they are all
* struct buf *.) Note that b_active was cleared in the driver;
* we presume that there is something to be done, hence reassert it.
*/
#ifdef notyet /* XXX */
if (ui->ui_flags & UNIT_REQUEUE) {
- bp = &md->md_utab[ui->ui_unit];
- if (bp->b_active) panic("mscp_dorsp requeue");
- MSCP_APPEND(bp, mi->mi_XXXtab, b_hash.le_next);
-/* Was: MSCP_APPEND(bp, mi->mi_XXXtab, b_forw); */
- bp->b_active = 1;
- ui->ui_flags &= ~UNIT_REQUEUE;
+ ...
}
#endif
done:
mscp_requeue(mi)
struct mscp_softc *mi;
{
- register struct mscp_device *me = mi->mi_me;
- register struct buf *bp, *dp;
- register int unit;
- struct buf *nextbp;
-
-panic("mscp_requeue");
- /*
- * Clear the controller chain. Mark everything un-busy; we
- * will soon fix any that are in fact busy.
- */
-#ifdef notyet /* XXX */
- mi->mi_XXXtab->b_actf = NULL;
- mi->mi_XXXtab->b_active = 0;
- for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
- ui = md->md_dinfo[unit];
- if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
- continue; /* not ours */
- dp->b_hash.le_next = NULL;
- dp->b_active = 0;
- }
- /*
- * Scan the wait queue, linking buffers onto drive queues.
- * Note that these must be put at the front of the drive queue,
- * lest we reorder I/O operations.
- */
- for (bp = *mi->mi_XXXwtab.b_actb; bp != &mi->mi_XXXwtab; bp = nextbp) {
- nextbp = *bp->b_actb;
- dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift];
- bp->b_actf = dp->b_actf;
- if (dp->b_actf == NULL)
- dp->b_actb = (void *)bp;
- dp->b_actf = bp;
- }
- mi->mi_XXXwtab.b_actf = *mi->mi_XXXwtab.b_actb = &mi->mi_XXXwtab;
-
- /*
- * Scan for drives waiting for on line or status responses,
- * and for drives with pending transfers. Put these on the
- * controller queue, and mark the controller busy.
- */
- for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) {
- ui = md->md_dinfo[unit];
- if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr)
- continue;
- ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE);
- if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL)
- continue;
- ui->ui_flags &= ~UNIT_REQUEUE;
- MSCP_APPEND(dp, mi->mi_XXXtab, b_hash.le_next);
-
- dp->b_active = 1;
- mi->mi_XXXtab->b_active = 1;
- }
-
-#endif
-#ifdef AVOID_EMULEX_BUG
- /*
- * ... and clear the index-to-buffer table.
- */
- for (unit = 0; unit < AEB_MAX_BP; unit++)
- mi->mi_bp[unit] = 0;
-#endif
+ panic("mscp_requeue");
}
-/* $OpenBSD: mscp.h,v 1.3 1997/09/12 09:25:51 maja Exp $ */
-/* $NetBSD: mscp.h,v 1.3 1997/07/04 11:58:21 ragge Exp $ */
+/* $OpenBSD: mscp.h,v 1.4 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp.h,v 1.6 1999/05/29 19:11:16 ragge Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
/*
* Control message opcodes
*/
-#define M_OP_ABORT 0x01 /* Abort command */
-#define M_OP_GETCMDST 0x02 /* Get command status command */
-#define M_OP_GETUNITST 0x03 /* Get unit status command */
-#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */
-#define M_OP_SEREX 0x07 /* Serious exception end message */
-#define M_OP_AVAILABLE 0x08 /* Available command */
-#define M_OP_ONLINE 0x09 /* Online command */
-#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */
-#define M_OP_DTACCPATH 0x0b /* Determine access paths command */
-#define M_OP_ACCESS 0x10 /* Access command */
-#define M_OP_COMPCD 0x11 /* Compare controller data command */
-#define M_OP_ERASE 0x12 /* Erase command */
-#define M_OP_FLUSH 0x13 /* Flush command */
-#define M_OP_REPLACE 0x14 /* Replace command */
-#define M_OP_COMPHD 0x20 /* Compare host data command */
-#define M_OP_READ 0x21 /* Read command */
-#define M_OP_WRITE 0x22 /* Write command */
-#define M_OP_WRITM 0x24 /* Write mark command */
-#define M_OP_POS 0x25 /* Positioning command */
-#define M_OP_AVAILATTN 0x40 /* Available attention message */
-#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */
-#define M_OP_ACCPATH 0x42 /* Access path attention message */
-#define M_OP_END 0x80 /* End message flag */
+#define M_OP_ABORT 0x01 /* Abort command */
+#define M_OP_GETCMDST 0x02 /* Get command status command */
+#define M_OP_GETUNITST 0x03 /* Get unit status command */
+#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */
+#define M_OP_SEREX 0x07 /* Serious exception end message */
+#define M_OP_AVAILABLE 0x08 /* Available command */
+#define M_OP_ONLINE 0x09 /* Online command */
+#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */
+#define M_OP_DTACCPATH 0x0b /* Determine access paths command */
+#define M_OP_ACCESS 0x10 /* Access command */
+#define M_OP_COMPCD 0x11 /* Compare controller data command */
+#define M_OP_ERASE 0x12 /* Erase command */
+#define M_OP_FLUSH 0x13 /* Flush command */
+#define M_OP_REPLACE 0x14 /* Replace command */
+#define M_OP_COMPHD 0x20 /* Compare host data command */
+#define M_OP_READ 0x21 /* Read command */
+#define M_OP_WRITE 0x22 /* Write command */
+#define M_OP_WRITM 0x24 /* Write mark command */
+#define M_OP_POS 0x25 /* Positioning command */
+#define M_OP_AVAILATTN 0x40 /* Available attention message */
+#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */
+#define M_OP_ACCPATH 0x42 /* Access path attention message */
+#define M_OP_END 0x80 /* End message flag */
/*
* Generic command modifiers
*/
-#define M_MD_EXPRS 0x8000 /* Express request */
-#define M_MD_COMP 0x4000 /* Compare */
-#define M_MD_CLSEX 0x2000 /* Clear serious exception */
-#define M_MD_ERROR 0x1000 /* Force error */
-#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */
-#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */
-#define M_MD_SECOR 0x0200 /* Suppress error correction */
-#define M_MD_SEREC 0x0100 /* Suppress error recovery */
-#define M_MD_SSHDW 0x0080 /* Suppress shadowing */
-#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */
-#define M_MD_WBKVL 0x0020 /* Write back (volatile) */
-#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */
+#define M_MD_EXPRS 0x8000 /* Express request */
+#define M_MD_COMP 0x4000 /* Compare */
+#define M_MD_CLSEX 0x2000 /* Clear serious exception */
+#define M_MD_ERROR 0x1000 /* Force error */
+#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */
+#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */
+#define M_MD_SECOR 0x0200 /* Suppress error correction */
+#define M_MD_SEREC 0x0100 /* Suppress error recovery */
+#define M_MD_SSHDW 0x0080 /* Suppress shadowing */
+#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */
+#define M_MD_WBKVL 0x0020 /* Write back (volatile) */
+#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */
/*
* tape command modifiers
*/
-#define M_MD_IMMEDIATE 0x0040 /* Immediate completion */
-#define M_MD_UNLOAD 0x0010 /* Unload tape */
-#define M_MD_REVERSE 0x0008 /* Reverse action */
-#define M_MD_OBJCOUNT 0x0004 /* Object count */
-#define M_MD_REWIND 0x0002 /* Rewind */
+#define M_MD_IMMEDIATE 0x0040 /* Immediate completion */
+#define M_MD_UNLOAD 0x0010 /* Unload tape */
+#define M_MD_REVERSE 0x0008 /* Reverse action */
+#define M_MD_OBJCOUNT 0x0004 /* Object count */
+#define M_MD_REWIND 0x0002 /* Rewind */
/*
* AVAILABLE command modifiers
*/
-#define M_AVM_ALLCD 0x0002 /* All class drivers */
-#define M_AVM_SPINDOWN 0x0001 /* Spin down */
+#define M_AVM_ALLCD 0x0002 /* All class drivers */
+#define M_AVM_SPINDOWN 0x0001 /* Spin down */
/*
* FLUSH command modifiers
*/
-#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */
-#define M_FLM_VOLATILE 0x0002 /* Volatile only */
+#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */
+#define M_FLM_VOLATILE 0x0002 /* Volatile only */
/*
* GET UNIT STATUS command modifiers
*/
-#define M_GUM_NEXTUNIT 0x0001 /* Next unit */
+#define M_GUM_NEXTUNIT 0x0001 /* Next unit */
/*
* ONLINE command modifiers
*/
-#define M_OLM_RIP 0x0001 /* Allow self destruction */
-#define M_OLM_IGNMF 0x0002 /* Ignore media format error */
+#define M_OLM_RIP 0x0001 /* Allow self destruction */
+#define M_OLM_IGNMF 0x0002 /* Ignore media format error */
/*
* ONLINE and SET UNIT CHARACTERISTICS command modifiers
*/
-#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */
-#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */
-#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */
-#define M_OSM_SETWRPROT 0x0004 /* Set write protect */
+#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */
+#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */
+#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */
+#define M_OSM_SETWRPROT 0x0004 /* Set write protect */
/*
* REPLACE command modifiers
*/
-#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */
+#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */
/*
* End message flags
*/
-#define M_EF_BBLKR 0x80 /* Bad block reported */
-#define M_EF_BBLKU 0x40 /* Bad block unreported */
-#define M_EF_ERLOG 0x20 /* Error log generated */
-#define M_EF_SEREX 0x10 /* Serious exception */
-#define M_EF_EOT 0x08 /* at end-of-tape */
-#define M_EF_POSLOST 0x04 /* position lost */
+#define M_EF_BBLKR 0x80 /* Bad block reported */
+#define M_EF_BBLKU 0x40 /* Bad block unreported */
+#define M_EF_ERLOG 0x20 /* Error log generated */
+#define M_EF_SEREX 0x10 /* Serious exception */
+#define M_EF_EOT 0x08 /* at end-of-tape */
+#define M_EF_POSLOST 0x04 /* position lost */
/*
* Controller flags
*/
-#define M_CF_ATTN 0x80 /* Enable attention messages */
-#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */
-#define M_CF_OTHER 0x20 /* Enable other host's error log messages */
-#define M_CF_THIS 0x10 /* Enable this host's error log messages */
-#define M_CF_MLTHS 0x04 /* Multi-host */
-#define M_CF_SHADW 0x02 /* Shadowing */
-#define M_CF_576 0x01 /* 576 byte sectors */
+#define M_CF_ATTN 0x80 /* Enable attention messages */
+#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */
+#define M_CF_OTHER 0x20 /* Enable other host's error log messages */
+#define M_CF_THIS 0x10 /* Enable this host's error log messages */
+#define M_CF_MLTHS 0x04 /* Multi-host */
+#define M_CF_SHADW 0x02 /* Shadowing */
+#define M_CF_576 0x01 /* 576 byte sectors */
/*
* Unit flags
*/
-#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */
-#define M_UF_INACT 0x4000 /* Inactive shadow set unit */
-#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */
-#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */
-#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */
-#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */
-#define M_UF_RMVBL 0x0080 /* Removable media */
-#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */
-#define M_UF_576 0x0004 /* 576 byte sectors */
-#define M_UF_CMPWR 0x0002 /* Compare writes */
-#define M_UF_CMPRD 0x0001 /* Compare reads */
+#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */
+#define M_UF_INACT 0x4000 /* Inactive shadow set unit */
+#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */
+#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */
+#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */
+#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */
+#define M_UF_RMVBL 0x0080 /* Removable media */
+#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */
+#define M_UF_576 0x0004 /* 576 byte sectors */
+#define M_UF_CMPWR 0x0002 /* Compare writes */
+#define M_UF_CMPRD 0x0001 /* Compare reads */
/*
* Error Log message format codes
*/
-#define M_FM_CTLRERR 0x00 /* Controller error */
-#define M_FM_BUSADDR 0x01 /* Host memory access error */
-#define M_FM_DISKTRN 0x02 /* Disk transfer error */
-#define M_FM_SDI 0x03 /* SDI error */
-#define M_FM_SMLDSK 0x04 /* Small disk error */
-#define M_FM_TAPETRN 0x05 /* Tape transfer error */
-#define M_FM_STIERR 0x06 /* STI communication or command failure */
-#define M_FM_STIDEL 0x07 /* STI drive error log */
-#define M_FM_STIFEL 0x08 /* STI formatter error log */
+#define M_FM_CTLRERR 0x00 /* Controller error */
+#define M_FM_BUSADDR 0x01 /* Host memory access error */
+#define M_FM_DISKTRN 0x02 /* Disk transfer error */
+#define M_FM_SDI 0x03 /* SDI error */
+#define M_FM_SMLDSK 0x04 /* Small disk error */
+#define M_FM_TAPETRN 0x05 /* Tape transfer error */
+#define M_FM_STIERR 0x06 /* STI communication or command failure */
+#define M_FM_STIDEL 0x07 /* STI drive error log */
+#define M_FM_STIFEL 0x08 /* STI formatter error log */
/*
* Error Log message flags
*/
-#define M_LF_SUCC 0x80 /* Operation successful */
-#define M_LF_CONT 0x40 /* Operation continuing */
-#define M_LF_SQNRS 0x01 /* Sequence number reset */
+#define M_LF_SUCC 0x80 /* Operation successful */
+#define M_LF_CONT 0x40 /* Operation continuing */
+#define M_LF_SQNRS 0x01 /* Sequence number reset */
/*
* Status codes
*/
-#define M_ST_MASK 0x1f /* Status code mask */
-#define M_ST_SUCCESS 0x00 /* Success */
-#define M_ST_INVALCMD 0x01 /* Invalid command */
-#define M_ST_ABORTED 0x02 /* Command aborted */
-#define M_ST_OFFLINE 0x03 /* Unit offline */
-#define M_ST_AVAILABLE 0x04 /* Unit available */
-#define M_ST_MFMTERR 0x05 /* Media format error */
-#define M_ST_WRPROT 0x06 /* Write protected */
-#define M_ST_COMPERR 0x07 /* Compare error */
-#define M_ST_DATAERR 0x08 /* Data error */
-#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */
-#define M_ST_CTLRERR 0x0a /* Controller error */
-#define M_ST_DRIVEERR 0x0b /* Drive error */
-#define M_ST_FORMATTERR 0x0c /* Formatter error */
-#define M_ST_BOT 0x0d /* Beginning-of-tape */
-#define M_ST_TAPEMARK 0x0e /* Tape mark encountered */
-#define M_ST_RDTRUNC 0x10 /* Record data truncated */
-#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */
+#define M_ST_MASK 0x1f /* Status code mask */
+#define M_ST_SUCCESS 0x00 /* Success */
+#define M_ST_INVALCMD 0x01 /* Invalid command */
+#define M_ST_ABORTED 0x02 /* Command aborted */
+#define M_ST_OFFLINE 0x03 /* Unit offline */
+#define M_ST_AVAILABLE 0x04 /* Unit available */
+#define M_ST_MFMTERR 0x05 /* Media format error */
+#define M_ST_WRPROT 0x06 /* Write protected */
+#define M_ST_COMPERR 0x07 /* Compare error */
+#define M_ST_DATAERR 0x08 /* Data error */
+#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */
+#define M_ST_CTLRERR 0x0a /* Controller error */
+#define M_ST_DRIVEERR 0x0b /* Drive error */
+#define M_ST_FORMATTERR 0x0c /* Formatter error */
+#define M_ST_BOT 0x0d /* Beginning-of-tape */
+#define M_ST_TAPEMARK 0x0e /* Tape mark encountered */
+#define M_ST_RDTRUNC 0x10 /* Record data truncated */
+#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */
/*
* Subcodes of M_ST_OFFLINE
*/
-#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */
-#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */
-#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */
-#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */
-#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */
+#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */
+#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */
+#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */
+#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */
+#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */
/*
* An MSCP packet begins with a header giving the length of
*/
struct mscpv_seq {
long seq_bytecount; /* byte count */
-#define seq_rbn seq_bytecount /* aka RBN (replace) */
-#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */
+#define seq_rbn seq_bytecount /* aka RBN (replace) */
+#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */
long seq_buffer; /* buffer descriptor */
long seq_mapbase; /* page map (first PTE) phys address */
- long seq_xxx1; /* ? */ /* unused */
+ long seq_xxx1; /* ? */ /* unused */
long seq_lbn; /* logical block number */
- long seq_xxx2; /* ? */ /* unused */
+ long seq_xxx2; /* ? */ /* unused */
long *seq_addr; /* pointer to cmd descriptor */
long seq_software[4]; /* reserved to software; unused */
};
* Set Controller Characteristics command variant
*/
struct mscpv_sccc {
- u_short sccc_version; /* MSCP version number */
- u_short sccc_ctlrflags; /* controller flags */
- u_short sccc_hosttimo; /* host timeout */
- u_short sccc_usefrac; /* use fraction */
+ u_short sccc_version; /* MSCP version number */
+ u_short sccc_ctlrflags; /* controller flags */
+ u_short sccc_hosttimo; /* host timeout */
+ u_short sccc_usefrac; /* use fraction */
long sccc_time; /* time and date */
long sccc_time1; /* it's a quad field */
long sccc_errlgfl; /* ? */
* Set Controller Characteristics end variant
*/
struct mscpv_scce {
- u_short scce_version; /* MSCP version number */
- u_short scce_ctlrflags; /* controller flags */
- u_short scce_ctlrtimo; /* controller timeout */
- u_short scce_ctlrcmdl; /* ??? */
+ u_short scce_version; /* MSCP version number */
+ u_short scce_ctlrflags; /* controller flags */
+ u_short scce_ctlrtimo; /* controller timeout */
+ u_short scce_ctlrcmdl; /* ??? */
quad_t scce_ctlrid; /* controller ID */
long scce_xxx[3]; /* ? */
long scce_volser; /* volume serial number */
*/
struct mscpv_onle {
long onle_xxx1[3]; /* ? */
-/*???*/ short onle_xxx2; /* ? */
+/*???*/ short onle_xxx2; /* ? */
u_char onle_drivetype; /* drive type index (same in guse) */
char onle_xxx3; /* ? */
long onle_mediaid; /* media type id (same in guse) */
* Get Unit Status end variant (and Avail Attn?)
*/
struct mscpv_guse {
- u_short guse_multunit; /* multi-unit code */
- u_short guse_unitflags; /* unit flags */
+ u_short guse_multunit; /* multi-unit code */
+ u_short guse_unitflags; /* unit flags */
long guse_hostid; /* host id */
long guse_unitid0; /*???*/
short guse_unitid1; /*???*/
long guse_mediaid; /* media type id (encoded) */
short guse_shadowunit; /* shadow unit */
short guse_shadowstat; /* shadow status */
- u_short guse_nspt; /* sectors per track */
- u_short guse_group; /* track group size */
- u_short guse_ngpc; /* groups per cylinder */
- u_short guse_xxx; /* reserved */
- u_short guse_rctsize; /* RCT size (sectors) */
+ u_short guse_nspt; /* sectors per track */
+ u_short guse_group; /* track group size */
+ u_short guse_ngpc; /* groups per cylinder */
+ u_short guse_xxx; /* reserved */
+ u_short guse_rctsize; /* RCT size (sectors) */
u_char guse_nrpt; /* RBNs per track */
u_char guse_nrct; /* number of RCTs */
};
* type in the top 10 bits, and the drive type in the remaining 22.
* The 10 bits, and 15 of the 22, are in groups of 5, with the value
* 0 representing space and values 1..26 representing A..Z. The low
- * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50
- * is <D><U><R><A>< >81, or 0x25641051. This encoding scheme is known
+ * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50
+ * is <D><U><R><A>< >81, or 0x25641051. This encoding scheme is known
* in part in uda.c.
*
* The casts below are just to make pcc generate better code.
*/
-#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */
-#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */
-#define MSCP_MID_ECH(n, id) (((long)(id) >> ((n) * 5 + 7)) & 0x1f)
-#define MSCP_MID_CHAR(n, id) \
+#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */
+#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */
+#define MSCP_MID_ECH(n, id) (((int)(id) >> ((n) * 5 + 7)) & 0x1f)
+#define MSCP_MID_CHAR(n, id) \
(MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ')
-#define MSCP_MID_NUM(id) ((id) & 0x7f)
+#define MSCP_MID_NUM(id) ((id) & 0x7f)
/* for, e.g., RA81 */
-#define MSCP_MKDRIVE2(a, b, n) \
+#define MSCP_MKDRIVE2(a, b, n) \
(((a) - '@') << 17 | ((b) - '@') << 12 | (n))
/* for, e.g., RRD50 */
-#define MSCP_MKDRIVE3(a, b, c, n) \
+#define MSCP_MKDRIVE3(a, b, c, n) \
(((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n))
/*
quad_t erd_ctlrid; /* controller ID */
u_char erd_ctlrsoftware; /* controller software version */
u_char erd_ctlrhardware; /* controller hardware version */
- u_short erd_multiunit; /* multi-unit code (?) */
+ u_short erd_multiunit; /* multi-unit code (?) */
union {
u_long un_busaddr; /* bus address, if mem access err */
quad_t un_unitid; /* unit id, otherwise */
} erd_un1;
-#define erd_busaddr erd_un1.un_busaddr
-#define erd_unitid erd_un1.un_unitid
+#define erd_busaddr erd_un1.un_busaddr
+#define erd_unitid erd_un1.un_unitid
u_char erd_unitsoftware; /* unit software version */
u_char erd_unithardware; /* unit hardware version */
union {
u_char un_b[2]; /* level, retry (if disk xfer err) */
- u_short un_s; /* cylinder (if small disk error) */
+ u_short un_s; /* cylinder (if small disk error) */
} erd_un2;
-#define erd_level erd_un2.un_b[0]
-#define erd_retry erd_un2.un_b[1]
-#define erd_sdecyl erd_un2.un_s
+#define erd_level erd_un2.un_b[0]
+#define erd_retry erd_un2.un_b[1]
+#define erd_sdecyl erd_un2.un_s
long erd_volser; /* volume serial number */
u_long erd_hdr; /* `header' (block number) */
u_char erd_sdistat[12]; /* SDI status information (?) */
/*
* I am making brash assumptions about the first four bytes of all
* MSCP packets. These appear to be true for both UDA50s and TMSCP
- * devices (TU81, TA81, TK50). DEC claim that these four bytes are
+ * devices (TU81, TA81, TK50). DEC claim that these four bytes are
* not part of MSCP itself, yet at least the length is necessary
* for, e.g., error checking.
*/
struct mscp {
- u_short mscp_msglen; /* length in bytes */
+ u_short mscp_msglen; /* length in bytes */
u_char mscp_msgtc; /* type (high 4 bits) and credits */
u_char mscp_vcid; /* virtual circuit ID */
long mscp_cmdref; /* command reference number */
- u_short mscp_unit; /* unit number */
- u_short mscp_seqnum; /* sequence number */
+ u_short mscp_unit; /* unit number */
+ u_short mscp_seqnum; /* sequence number */
u_char mscp_opcode; /* opcode */
-#define mscp_format mscp_opcode /* aka format (datagrams) */
+#define mscp_format mscp_opcode /* aka format (datagrams) */
u_char mscp_flags; /* flags */
- u_short mscp_modifier; /* modifier (commands) */
-#define mscp_status mscp_modifier /* aka status (ends) */
-#define mscp_event mscp_modifier /* aka event (datagrams) */
+ u_short mscp_modifier; /* modifier (commands) */
+#define mscp_status mscp_modifier /* aka status (ends) */
+#define mscp_event mscp_modifier /* aka event (datagrams) */
union {
struct mscpv_seq un_seq; /* generic sequential msg */
struct mscpv_sccc un_sccc; /* SCC command */
struct mscpv_guse un_guse; /* get unit status */
struct mscpv_erd un_erd; /* error datagram */
} mscp_un;
-/*???*/ long mscp_xxx; /* pad to 64 bytes */
+/*???*/ long mscp_xxx; /* pad to 64 bytes */
};
/*
* Define message length according to the DEC specifications by dropping
* the four byte header.
*/
-#define MSCP_MSGLEN (sizeof (struct mscp) - 4)
+#define MSCP_MSGLEN (sizeof (struct mscp) - 4)
/*
* Shorthand
/*
* Generic packet
*/
-#define mscp_seq mscp_un.un_seq
+#define mscp_seq mscp_un.un_seq
/*
* Set Controller Characteristics packet
*/
-#define mscp_sccc mscp_un.un_sccc
+#define mscp_sccc mscp_un.un_sccc
/*
* Set Controller Characteristics end packet
*/
-#define mscp_scce mscp_un.un_scce
+#define mscp_scce mscp_un.un_scce
/*
* Online / Set Unit Characteristics command packet
*/
-#define mscp_onlc mscp_un.un_onlc
+#define mscp_onlc mscp_un.un_onlc
/*
* Online end packet
*/
-#define mscp_onle mscp_un.un_onle
+#define mscp_onle mscp_un.un_onle
/*
* Get Unit Status end packet
*/
-#define mscp_guse mscp_un.un_guse
+#define mscp_guse mscp_un.un_guse
/*
* MSCP Error Log packet
*/
-#define mscp_erd mscp_un.un_erd
+#define mscp_erd mscp_un.un_erd
/*
* MSCP seq_addr field actually belongs to overall packet.
*/
-#define mscp_addr mscp_seq.seq_addr
+#define mscp_addr mscp_seq.seq_addr
/*
* Macros to break up mscp_msgtc, and types.
*/
-#define MSCP_MSGTYPE(m) ((m) & 0xf0)
-#define MSCP_CREDITS(m) ((m) & 0x0f)
+#define MSCP_MSGTYPE(m) ((m) & 0xf0)
+#define MSCP_CREDITS(m) ((m) & 0x0f)
-#define MSCPT_SEQ 0x00 /* sequential message */
-#define MSCPT_DATAGRAM 0x10 /* error datagram */
-#define MSCPT_CREDITS 0x20 /* credit notification */
-#define MSCPT_MAINTENANCE 0xf0 /* who knows */
+#define MSCPT_SEQ 0x00 /* sequential message */
+#define MSCPT_DATAGRAM 0x10 /* error datagram */
+#define MSCPT_CREDITS 0x20 /* credit notification */
+#define MSCPT_MAINTENANCE 0xf0 /* who knows */
/*
*/
/*
- * MSCP controllers have `command rings' and `response rings'. A
+ * MSCP controllers have `command rings' and `response rings'. A
* command ring is a pool of MSCP packets that the host uses to give
* commands to the controller; a response ring is a pool of MSCP
* packets that the controller uses to give back responses. Entries
* The pool is `described' by a set of pointers to the packets, along
* with the two flags below.
*/
-#define MSCP_OWN 0x80000000 /* controller owns this packet */
-#define MSCP_INT 0x40000000 /* controller should interrupt */
+#define MSCP_OWN 0x80000000 /* controller owns this packet */
+#define MSCP_INT 0x40000000 /* controller should interrupt */
-/* $OpenBSD: mscp_disk.c,v 1.6 1998/10/03 21:18:59 millert Exp $ */
-/* $NetBSD: mscp_disk.c,v 1.13 1997/06/24 01:12:40 thorpej Exp $ */
+/* $OpenBSD: mscp_disk.c,v 1.7 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp_disk.c,v 1.21 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
/*
* RA disk device driver
+ * RX MSCP floppy disk device driver
*/
/*
* TODO
* write bad block forwarding code
- * split the file into a separate floppy file
*/
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
+#include <sys/reboot.h>
#include <sys/proc.h>
#include <sys/systm.h>
-#include <sys/reboot.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/rpb.h>
-#include <ufs/ffs/fs.h> /* For some disklabel stuff */
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
+
+#include "ra.h"
+
+struct cfdriver ra_cd = {
+ NULL, "ra", DV_DISK
+};
+
+struct cfdriver rx_cd = {
+ NULL, "rx", DV_DISK
+};
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpvar.h>
+#define RAMAJOR 9 /* RA major device number XXX */
/*
* Drive status, per drive
int ra_hwunit; /* Hardware unit number */
int ra_havelabel; /* true if we have a label */
int ra_wlabel; /* label sector is currently writable */
- int ra_isafloppy; /* unit is a floppy disk */
};
-int ramatch __P((struct device *, void *, void *));
+#define rx_softc ra_softc
+
+void rxattach __P((struct device *, struct device *, void *));
+int rx_putonline __P((struct rx_softc *));
+void rrmakelabel __P((struct disklabel *, long));
+
+#if NRA
+
+int ramatch __P((struct device *, struct cfdata *, void *));
void raattach __P((struct device *, struct device *, void *));
-void radgram __P((struct device *, struct mscp *, struct mscp_softc *));
-void raiodone __P((struct device *, struct buf *));
-int raonline __P((struct device *, struct mscp *));
-int ragotstatus __P((struct device *, struct mscp *));
-void rareplace __P((struct device *, struct mscp *));
-int raioerror __P((struct device *, struct mscp *, struct buf *));
-void rafillin __P((struct buf *, struct mscp *));
-void rabb __P((struct device *, struct mscp *, struct buf *));
int raopen __P((dev_t, int, int, struct proc *));
int raclose __P((dev_t, int, int, struct proc *));
void rastrategy __P((struct buf *));
-void rastrat1 __P((struct buf *));
int raread __P((dev_t, struct uio *));
int rawrite __P((dev_t, struct uio *));
int raioctl __P((dev_t, int, caddr_t, int, struct proc *));
int rasize __P((dev_t));
int ra_putonline __P((struct ra_softc *));
-
-struct mscp_device ra_device = {
- radgram,
- raiodone,
- raonline,
- ragotstatus,
- rareplace,
- raioerror,
- rabb,
- rafillin,
-};
-
-/*
- * Device to unit number and partition and back
- */
-#define UNITSHIFT 3
-#define UNITMASK 7
-#define raunit(dev) (minor(dev) >> UNITSHIFT)
-#define rapart(dev) (minor(dev) & UNITMASK)
-#define raminor(u, p) (((u) << UNITSHIFT) | (p))
-
-struct cfdriver ra_cd = {
- NULL, "ra", DV_DISK
-};
-
struct cfattach ra_ca = {
- sizeof(struct ra_softc), ramatch, raattach
+ sizeof(struct ra_softc), (cfmatch_t)ramatch, raattach
};
-/*
- * Software state, per drive
- */
-#define RA_OFFLINE 0
-#define RA_WANTOPEN 1
-#define RA_ONLINE 3
-
/*
* More driver definitions, for generic MSCP code.
*/
-extern int cold;
int
-ramatch(parent, match, aux)
+ramatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct cfdata *cf = match;
struct drive_attach_args *da = aux;
struct mscp *mp = da->da_mp;
if ((da->da_typ & MSCPBUS_DISK) == 0)
return 0;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit)
+ return 0;
+ /*
+ * Check if this disk is a floppy; then don't configure it.
+ * Seems to be a safe way to test it per Chris Torek.
+ */
+ if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
return 0;
return 1;
}
void *aux;
{
struct ra_softc *ra = (void *)self;
- struct drive_attach_args *da = aux;
- struct mscp *mp = da->da_mp;
struct mscp_softc *mi = (void *)parent;
- struct disklabel *dl;
-
- ra->ra_mediaid = mp->mscp_guse.guse_mediaid;
- ra->ra_state = RA_OFFLINE;
- ra->ra_havelabel = 0;
- ra->ra_hwunit = mp->mscp_unit;
- mi->mi_dp[mp->mscp_unit] = self;
- ra->ra_disk.dk_name = ra->ra_dev.dv_xname;
- disk_attach((struct disk *)&ra->ra_disk);
-
- /* Fill in what we know. The actual size is gotten later */
- dl = ra->ra_disk.dk_label;
-
- dl->d_secsize = DEV_BSIZE;
- dl->d_nsectors = mp->mscp_guse.guse_nspt;
- dl->d_ntracks = mp->mscp_guse.guse_ngpc;
- dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
- disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
+ rxattach(parent, self, aux);
/*
* Find out if we booted from this disk.
*/
ra_putonline(ra)
struct ra_softc *ra;
{
- struct mscp *mp;
- struct mscp_softc *mi = (struct mscp_softc *)ra->ra_dev.dv_parent;
struct disklabel *dl;
- volatile int i;
char *msg;
- dl = ra->ra_disk.dk_label;
-
- ra->ra_state = RA_WANTOPEN;
- mp = mscp_getcp(mi, MSCP_WAIT);
- mp->mscp_opcode = M_OP_ONLINE;
- mp->mscp_unit = ra->ra_hwunit;
- mp->mscp_cmdref = (long)&ra->ra_state;
- *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-
- /* Poll away */
- i = *mi->mi_ip;
- if (tsleep(&ra->ra_state, PRIBIO, "raonline", 100*100)) {
- ra->ra_state = RA_OFFLINE;
+ if (rx_putonline(ra) != MSCP_DONE)
return MSCP_FAILED;
- }
- if (ra->ra_state == RA_OFFLINE)
- return MSCP_FAILED;
- if (ra->ra_isafloppy)
- return MSCP_DONE;
+ dl = ra->ra_disk.dk_label;
+ ra->ra_state = DK_RDLABEL;
printf("%s", ra->ra_dev.dv_xname);
- if ((msg = readdisklabel(raminor(ra->ra_dev.dv_unit, 0),
- rastrategy, dl, NULL, 0)) != NULL)
+ if ((msg = readdisklabel(MAKEDISKDEV(RAMAJOR, ra->ra_dev.dv_unit,
+ RAW_PART), rastrategy, dl, NULL, 0)) != NULL)
printf(": %s", msg);
- else
+ else {
ra->ra_havelabel = 1;
- ra->ra_state = RA_ONLINE;
+ ra->ra_state = DK_OPEN;
+ }
printf(": size %d sectors\n", dl->d_secperunit);
return MSCP_DONE;
}
+
/*
* Open a drive.
*/
{
register struct ra_softc *ra;
int part, unit, mask;
-
/*
* Make sure this is a reasonable open request.
*/
- unit = raunit(dev);
+ unit = DISKUNIT(dev);
if (unit >= ra_cd.cd_ndevs)
return ENXIO;
ra = ra_cd.cd_devs[unit];
* If this is the first open; we must first try to put
* the disk online (and read the label).
*/
- if (ra->ra_state == RA_OFFLINE)
+ if (ra->ra_state == DK_CLOSED)
if (ra_putonline(ra) == MSCP_FAILED)
- return EIO;
+ return ENXIO;
/* If the disk has no label; allow writing everywhere */
if (ra->ra_havelabel == 0)
ra->ra_wlabel = 1;
- part = rapart(dev);
- if (ra->ra_isafloppy == 0)
- if (part >= ra->ra_disk.dk_label->d_npartitions)
- return ENXIO;
+ part = DISKPART(dev);
+ if (part >= ra->ra_disk.dk_label->d_npartitions)
+ return ENXIO;
/*
* Wait for the state to settle
*/
#if notyet
- while (ra->ra_state != RA_ONLINE)
+ while (ra->ra_state != DK_OPEN)
if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH,
devopn, 0))) {
splx(s);
int flags, fmt;
struct proc *p;
{
- register int unit = raunit(dev);
+ register int unit = DISKUNIT(dev);
register struct ra_softc *ra = ra_cd.cd_devs[unit];
- int mask = (1 << rapart(dev));
+ int mask = (1 << DISKPART(dev));
switch (fmt) {
case S_IFCHR:
*/
#if notyet
if (ra->ra_openpart == 0) {
- s = splbio();
+ s = splimp();
while (udautab[unit].b_actf)
sleep((caddr_t)&udautab[unit], PZERO - 1);
splx(s);
/*
* Queue a transfer request, and if possible, hand it to the controller.
- *
- * This routine is broken into two so that the internal version
- * udastrat1() can be called by the (nonexistent, as yet) bad block
- * revectoring routine.
*/
void
rastrategy(bp)
{
register int unit;
register struct ra_softc *ra;
- int p;
/*
* Make sure this is a reasonable drive to use.
*/
- unit = raunit(bp->b_dev);
+ unit = DISKUNIT(bp->b_dev);
if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) {
bp->b_error = ENXIO;
bp->b_flags |= B_ERROR;
/*
* If drive is open `raw' or reading label, let it at it.
*/
- if (ra->ra_state < RA_ONLINE) {
+ if (ra->ra_state == DK_RDLABEL) {
mscp_strategy(bp, ra->ra_dev.dv_parent);
return;
}
- p = rapart(bp->b_dev);
+
+ /* If disk is not online, try to put it online */
+ if (ra->ra_state == DK_CLOSED)
+ if (ra_putonline(ra) == MSCP_FAILED) {
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ goto done;
+ }
/*
* Determine the size of the transfer, and make sure it is
* within the boundaries of the partition.
*/
- if (ra->ra_isafloppy) {
- if (bp->b_blkno >= ra->ra_disk.dk_label->d_secperunit) {
- bp->b_resid = bp->b_bcount;
- goto done;
- }
- } else
- if (bounds_check_with_label(bp, ra->ra_disk.dk_label,
- ra->ra_disk.dk_cpulabel, ra->ra_wlabel) <= 0)
- goto done;
+ if (bounds_check_with_label(bp, ra->ra_disk.dk_label,
+ ra->ra_disk.dk_cpulabel, ra->ra_wlabel) <= 0)
+ goto done;
/* Make some statistics... /bqt */
ra->ra_disk.dk_xfer++;
int
raread(dev, uio)
- dev_t dev;
- struct uio *uio;
+ dev_t dev;
+ struct uio *uio;
{
- return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
+ return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
}
int
rawrite(dev, uio)
- dev_t dev;
- struct uio *uio;
-{
-
- return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
-}
-
-void
-raiodone(usc, bp)
- struct device *usc;
- struct buf *bp;
-{
-
- biodone(bp);
-}
-
-/*
- * Fill in disk addresses in a mscp packet waiting for transfer.
- */
-void
-rafillin(bp, mp)
- struct buf *bp;
- struct mscp *mp;
-{
- int unit = raunit(bp->b_dev);
- int part = rapart(bp->b_dev);
- struct ra_softc *ra = ra_cd.cd_devs[unit];
- struct disklabel *lp = ra->ra_disk.dk_label;
-
-
- /* XXX more checks needed */
- mp->mscp_unit = ra->ra_hwunit;
- mp->mscp_seq.seq_lbn = bp->b_blkno + lp->d_partitions[part].p_offset;
- mp->mscp_seq.seq_bytecount = bp->b_bcount;
-}
-
-/*
- * Handle an error datagram.
- * This can come from an unconfigured drive as well.
- */
-void
-radgram(usc, mp, mi)
- struct device *usc;
- struct mscp *mp;
- struct mscp_softc *mi;
-{
- if (mscp_decodeerror(usc == NULL?"unconf ra" : usc->dv_xname, mp, mi))
- return;
- /*
- * SDI status information bytes 10 and 11 are the microprocessor
- * error code and front panel code respectively. These vary per
- * drive type and are printed purely for field service information.
- */
- if (mp->mscp_format == M_FM_SDI)
- printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
- mp->mscp_erd.erd_sdistat[10],
- mp->mscp_erd.erd_sdistat[11]);
-}
-
-/*
- * A drive came on line. Check its type and size. Return DONE if
- * we think the drive is truly on line. In any case, awaken anyone
- * sleeping on the drive on-line-ness.
- */
-int
-raonline(usc, mp)
- struct device *usc;
- struct mscp *mp;
-{
- register struct ra_softc *ra = (void *)usc;
- struct disklabel *dl;
- int p = 0, d, n;
-
- wakeup((caddr_t)&ra->ra_state);
- if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
- printf("%s: attempt to bring on line failed: ",
- ra->ra_dev.dv_xname);
- mscp_printevent(mp);
- ra->ra_state = RA_OFFLINE;
- return (MSCP_FAILED);
- }
-
- /*
- * Fill in the rest of disk size.
- */
- ra->ra_state = RA_WANTOPEN;
- dl = ra->ra_disk.dk_label;
- dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
-
- if (dl->d_secpercyl != 0)
- dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
- else
- ra->ra_isafloppy = 1;
- dl->d_type = DTYPE_MSCP;
- dl->d_rpm = 3600;
- dl->d_bbsize = BBSIZE;
- dl->d_sbsize = SBSIZE;
-
- /* Create the disk name for disklabel. Phew... */
- d = ra->ra_mediaid;
- dl->d_typename[p++] = MSCP_MID_CHAR(2, d);
- dl->d_typename[p++] = MSCP_MID_CHAR(1, d);
- if (MSCP_MID_ECH(0, d))
- dl->d_typename[p++] = MSCP_MID_CHAR(0, d);
- n = MSCP_MID_NUM(d);
- if (n > 99) {
- dl->d_typename[p++] = '1';
- n -= 100;
- }
- if (n > 9) {
- dl->d_typename[p++] = (n / 10) + '0';
- n %= 10;
- }
- dl->d_typename[p++] = n + '0';
- dl->d_typename[p] = 0;
- dl->d_npartitions = MAXPARTITIONS;
- dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
- dl->d_secperunit;
- dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
- dl->d_interleave = dl->d_headswitch = 1;
- dl->d_magic = dl->d_magic2 = DISKMAGIC;
- dl->d_checksum = dkcksum(dl);
-
- return (MSCP_DONE);
-}
-
-/*
- * We got some (configured) unit's status. Return DONE if it succeeded.
- */
-int
-ragotstatus(usc, mp)
- register struct device *usc;
- register struct mscp *mp;
-{
- if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
- printf("%s: attempt to get status failed: ", usc->dv_xname);
- mscp_printevent(mp);
- return (MSCP_FAILED);
- }
- /* record for (future) bad block forwarding and whatever else */
-#ifdef notyet
- uda_rasave(ui->ui_unit, mp, 1);
-#endif
- return (MSCP_DONE);
-}
-
-/*
- * A transfer failed. We get a chance to fix or restart it.
- * Need to write the bad block forwaring code first....
- */
-/*ARGSUSED*/
-int
-raioerror(usc, mp, bp)
- register struct device *usc;
- register struct mscp *mp;
- struct buf *bp;
-{
-printf("raioerror\n");
-#if 0
- if (mp->mscp_flags & M_EF_BBLKR) {
- /*
- * A bad block report. Eventually we will
- * restart this transfer, but for now, just
- * log it and give up.
- */
- log(LOG_ERR, "ra%d: bad block report: %d%s\n",
- ui->ui_unit, (int)mp->mscp_seq.seq_lbn,
- mp->mscp_flags & M_EF_BBLKU ? " + others" : "");
- } else {
- /*
- * What the heck IS a `serious exception' anyway?
- * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION
- * FOR THEIR OWN CONTROLLERS.
- */
- if (mp->mscp_flags & M_EF_SEREX)
- log(LOG_ERR, "ra%d: serious exception reported\n",
- ui->ui_unit);
- }
-#endif
- return (MSCP_FAILED);
-}
-
-/*
- * A replace operation finished.
- */
-/*ARGSUSED*/
-void
-rareplace(usc, mp)
- struct device *usc;
- struct mscp *mp;
-{
-
- panic("udareplace");
-}
-
-/*
- * A bad block related operation finished.
- */
-/*ARGSUSED*/
-void
-rabb(usc, mp, bp)
- struct device *usc;
- struct mscp *mp;
- struct buf *bp;
+ dev_t dev;
+ struct uio *uio;
{
- panic("udabb");
+ return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
}
-
/*
* I/O controls.
*/
int flag;
struct proc *p;
{
- register int unit = raunit(dev);
- register struct disklabel *lp;
+ register int unit = DISKUNIT(dev);
+ register struct disklabel *lp, *tp;
register struct ra_softc *ra = ra_cd.cd_devs[unit];
int error = 0;
case DIOCGPART:
((struct partinfo *)data)->disklab = lp;
((struct partinfo *)data)->part =
- &lp->d_partitions[rapart(dev)];
+ &lp->d_partitions[DISKPART(dev)];
break;
case DIOCWDINFO:
ra->ra_wlabel = 1;
break;
+#ifdef __NetBSD__
+ case DIOCGDEFLABEL:
+ tp = (struct disklabel *)data;
+ bzero(data, sizeof(struct disklabel));
+ tp->d_secsize = lp->d_secsize;
+ tp->d_nsectors = lp->d_nsectors;
+ tp->d_ntracks = lp->d_ntracks;
+ tp->d_ncylinders = lp->d_ncylinders;
+ tp->d_secpercyl = lp->d_secpercyl;
+ tp->d_secperunit = lp->d_secperunit;
+ tp->d_type = DTYPE_MSCP;
+ tp->d_rpm = 3600;
+ rrmakelabel(tp, ra->ra_mediaid);
+ break;
+#endif
+
default:
error = ENOTTY;
break;
return (error);
}
-#if 0
-/*
- * Do a panic dump. We set up the controller for one command packet
- * and one response packet, for which we use `struct uda1'.
- */
-struct uda1 {
- struct uda1ca uda1_ca; /* communications area */
- struct mscp uda1_rsp; /* response packet */
- struct mscp uda1_cmd; /* command packet */
-} uda1;
-#endif
-
-#define DBSIZE 32 /* dump 16K at a time */
int
radump(dev, blkno, va, size)
dev_t dev;
- daddr_t blkno;
- caddr_t va;
+ daddr_t blkno;
+ caddr_t va;
size_t size;
{
-#if 0
- struct udadevice *udaddr;
- struct uda1 *ud_ubaddr;
- char *start;
- int num, blk, unit, maxsz, blkoff, reg;
- struct partition *pp;
- struct uba_regs *uba;
- struct uba_device *ui;
- struct uda1 *ud;
- struct pte *io;
- int i;
-
- /*
- * Make sure the device is a reasonable place on which to dump.
- */
- unit = udaunit(dev);
- if (unit >= NRA)
- return (ENXIO);
-#define phys(cast, addr) ((cast) ((int)addr & 0x7fffffff))
- ui = phys(struct uba_device *, udadinfo[unit]);
- if (ui == NULL || ui->ui_alive == 0)
- return (ENXIO);
+ return ENXIO;
+}
- /*
- * Find and initialise the UBA; get the physical address of the
- * device registers, and of communications area and command and
- * response packet.
- */
- uba = phys(struct uba_softc *, ui->ui_hd)->uh_physuba;
- ubainit(ui->ui_hd);
- udaddr = (struct udadevice *)ui->ui_physaddr;
- ud = phys(struct uda1 *, &uda1);
- /*
- * Map the ca+packets into Unibus I/O space so the UDA50 can get
- * at them. Use the registers at the end of the Unibus map (since
- * we will use the registers at the beginning to map the memory
- * we are dumping).
- */
- num = btoc(sizeof(struct uda1)) + 1;
- reg = NUBMREG - num;
- io = (void *)&uba->uba_map[reg];
- for (i = 0; i < num; i++)
- *(int *)io++ = UBAMR_MRV | (btop(ud) + i);
- ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9));
+/*
+ * Return the size of a partition, if known, or -1 if not.
+ */
+int
+rasize(dev)
+ dev_t dev;
+{
+ register int unit = DISKUNIT(dev);
+ struct ra_softc *ra;
- /*
- * Initialise the controller, with one command and one response
- * packet.
- */
- udaddr->udaip = 0;
- if (udadumpwait(udaddr, UDA_STEP1))
- return (EFAULT);
- udaddr->udasa = UDA_ERR;
- if (udadumpwait(udaddr, UDA_STEP2))
- return (EFAULT);
- udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc;
- if (udadumpwait(udaddr, UDA_STEP3))
- return (EFAULT);
- udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16;
- if (udadumpwait(udaddr, UDA_STEP4))
- return (EFAULT);
- ((struct uda_softc *)uda_cd.cd_devs[ui->ui_ctlr])->sc_micro = udaddr->udasa & 0xff;
- udaddr->udasa = UDA_GO;
+ if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
+ return -1;
- /*
- * Set up the command and response descriptor, then set the
- * controller characteristics and bring the drive on line.
- * Note that all uninitialised locations in uda1_cmd are zero.
- */
- ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref;
- ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref;
- /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */
- /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */
- if (udadumpcmd(M_OP_SETCTLRC, ud, ui))
- return (EFAULT);
- ud->uda1_cmd.mscp_unit = ui->ui_slave;
- if (udadumpcmd(M_OP_ONLINE, ud, ui))
- return (EFAULT);
-
- pp = phys(struct partition *,
- &udalabel[unit].d_partitions[udapart(dev)]);
- maxsz = pp->p_size;
- blkoff = pp->p_offset;
+ ra = ra_cd.cd_devs[unit];
- /*
- * Dump all of physical memory, or as much as will fit in the
- * space provided.
- */
- start = 0;
- printf("Dumpar {r inte implementerade {n :) \n");
- asm("halt");
-/* num = maxfree; */
- if (dumplo + num >= maxsz)
- num = maxsz - dumplo;
- blkoff += dumplo;
+ if (ra->ra_state == DK_CLOSED)
+ if (ra_putonline(ra) == MSCP_FAILED)
+ return -1;
- /*
- * Write out memory, DBSIZE pages at a time.
- * N.B.: this code depends on the fact that the sector
- * size == the page size.
- */
- while (num > 0) {
- blk = num > DBSIZE ? DBSIZE : num;
- io = (void *)uba->uba_map;
- /*
- * Map in the pages to write, leaving an invalid entry
- * at the end to guard against wild Unibus transfers.
- * Then do the write.
- */
- for (i = 0; i < blk; i++)
- *(int *)io++ = UBAMR_MRV | (btop(start) + i);
- *(int *)io = 0;
- ud->uda1_cmd.mscp_unit = ui->ui_slave;
- ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff;
- ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT;
- if (udadumpcmd(M_OP_WRITE, ud, ui))
- return (EIO);
- start += blk << PGSHIFT;
- num -= blk;
- }
- return (0); /* made it! */
+ return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
+ (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
}
-/*
- * Wait for some of the bits in `bits' to come on. If the error bit
- * comes on, or ten seconds pass without response, return true (error).
- */
int
-udadumpwait(udaddr, bits)
- struct udadevice *udaddr;
- register int bits;
+ra_getdev(adaptor, controller, unit, uname)
+ int adaptor, controller, unit;
+ char **uname;
{
- register int timo = todr() + 1000;
-
- while ((udaddr->udasa & bits) == 0) {
- if (udaddr->udasa & UDA_ERR) {
- char bits[64];
- printf("udasa=%s\ndump ",
- bitmask_snprintf(udaddr->udasa, udasr_bits,
- bits, sizeof(bits)));
- return (1);
- }
- if (todr() >= timo) {
- printf("timeout\ndump ");
- return (1);
- }
- }
- return (0);
+ struct mscp_softc *mi;
+ struct ra_softc *ra;
+ int i;
+
+ for (i = 0; i < ra_cd.cd_ndevs; i++) {
+ if ((ra = ra_cd.cd_devs[i]) == 0)
+ continue;
+
+ mi = (void *)ra->ra_dev.dv_parent;
+ if (mi->mi_ctlrnr == controller && mi->mi_adapnr == adaptor &&
+ ra->ra_hwunit == unit) {
+ *uname = ra->ra_dev.dv_xname;
+ return i;
+ }
+ }
+ return -1;
+}
+
+#endif /* NRA */
+
+#if NRX
+
+int rxmatch __P((struct device *, struct cfdata *, void *));
+int rxopen __P((dev_t, int, int, struct proc *));
+int rxclose __P((dev_t, int, int, struct proc *));
+void rxstrategy __P((struct buf *));
+int rxread __P((dev_t, struct uio *));
+int rxwrite __P((dev_t, struct uio *));
+int rxioctl __P((dev_t, int, caddr_t, int, struct proc *));
+int rxdump __P((dev_t, daddr_t, caddr_t, size_t));
+int rxsize __P((dev_t));
+
+struct cfattach rx_ca = {
+ sizeof(struct rx_softc), (cfmatch_t)rxmatch, rxattach
+};
+
+/*
+ * More driver definitions, for generic MSCP code.
+ */
+
+int
+rxmatch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct drive_attach_args *da = aux;
+ struct mscp *mp = da->da_mp;
+
+ if ((da->da_typ & MSCPBUS_DISK) == 0)
+ return 0;
+ if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit)
+ return 0;
+ /*
+ * Check if this disk is a floppy; then configure it.
+ * Seems to be a safe way to test it per Chris Torek.
+ */
+ if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
+ return 1;
+ return 0;
+}
+
+#endif /* NRX */
+
+/*
+ * The attach routine only checks and prints drive type.
+ * Bringing the disk online is done when the disk is accessed
+ * the first time.
+ */
+void
+rxattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct rx_softc *rx = (void *)self;
+ struct drive_attach_args *da = aux;
+ struct mscp *mp = da->da_mp;
+ struct mscp_softc *mi = (void *)parent;
+ struct disklabel *dl;
+
+ rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
+ rx->ra_state = DK_CLOSED;
+ rx->ra_hwunit = mp->mscp_unit;
+ mi->mi_dp[mp->mscp_unit] = self;
+
+ rx->ra_disk.dk_name = rx->ra_dev.dv_xname;
+ disk_attach((struct disk *)&rx->ra_disk);
+
+ /* Fill in what we know. The actual size is gotten later */
+ dl = rx->ra_disk.dk_label;
+
+ dl->d_secsize = DEV_BSIZE;
+ dl->d_nsectors = mp->mscp_guse.guse_nspt;
+ dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
+ dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
+ disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
+#ifdef DEBUG
+ printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
+ self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
+ mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
+ mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
+#endif
+}
+
+/*
+ * (Try to) put the drive online. This is done the first time the
+ * drive is opened, or if it har fallen offline.
+ */
+int
+rx_putonline(rx)
+ struct rx_softc *rx;
+{
+ struct mscp *mp;
+ struct mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent;
+ volatile int i;
+
+ rx->ra_state = DK_CLOSED;
+ mp = mscp_getcp(mi, MSCP_WAIT);
+ mp->mscp_opcode = M_OP_ONLINE;
+ mp->mscp_unit = rx->ra_hwunit;
+ mp->mscp_cmdref = 1;
+ *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
+
+ /* Poll away */
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
+ if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100))
+ rx->ra_state = DK_CLOSED;
+
+ if (rx->ra_state == DK_CLOSED)
+ return MSCP_FAILED;
+
+ return MSCP_DONE;
}
+#if NRX
+
/*
- * Feed a command to the UDA50, wait for its response, and return
- * true iff something went wrong.
+ * Open a drive.
*/
+/*ARGSUSED*/
+int
+rxopen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+ struct proc *p;
+{
+ register struct rx_softc *rx;
+ int unit;
+
+ /*
+ * Make sure this is a reasonable open request.
+ */
+ unit = DISKUNIT(dev);
+ if (unit >= rx_cd.cd_ndevs)
+ return ENXIO;
+ rx = rx_cd.cd_devs[unit];
+ if (rx == 0)
+ return ENXIO;
+
+ /*
+ * If this is the first open; we must first try to put
+ * the disk online (and read the label).
+ */
+ if (rx->ra_state == DK_CLOSED)
+ if (rx_putonline(rx) == MSCP_FAILED)
+ return ENXIO;
+
+ return 0;
+}
+
+/* ARGSUSED */
int
-udadumpcmd(op, ud, ui)
- int op;
- struct uda1 *ud;
- struct uba_device *ui;
+rxclose(dev, flags, fmt, p)
+ dev_t dev;
+ int flags, fmt;
+ struct proc *p;
+{
+ return (0);
+}
+
+/*
+ * Queue a transfer request, and if possible, hand it to the controller.
+ *
+ * This routine is broken into two so that the internal version
+ * udastrat1() can be called by the (nonexistent, as yet) bad block
+ * revectoring routine.
+ */
+void
+rxstrategy(bp)
+ register struct buf *bp;
{
- volatile struct udadevice *udaddr;
- volatile int n;
-#define mp (&ud->uda1_rsp)
-
- udaddr = (struct udadevice *)ui->ui_physaddr;
- ud->uda1_cmd.mscp_opcode = op;
- ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN;
- ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN;
- ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
- ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT;
- if (udaddr->udasa & UDA_ERR) {
- char bits[64];
- printf("udasa=%s\ndump ", bitmask_snprintf(udaddr->udasa,
- udasr_bits, bits, sizeof(bits)));
- return (1);
+ register int unit;
+ register struct rx_softc *rx;
+
+ /*
+ * Make sure this is a reasonable drive to use.
+ */
+ unit = DISKUNIT(bp->b_dev);
+ if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) {
+ bp->b_error = ENXIO;
+ bp->b_flags |= B_ERROR;
+ goto done;
}
- n = udaddr->udaip;
- n = todr() + 1000;
- for (;;) {
- if (todr() > n) {
- printf("timeout\ndump ");
- return (1);
- }
- if (ud->uda1_ca.ca_cmdint)
- ud->uda1_ca.ca_cmdint = 0;
- if (ud->uda1_ca.ca_rspint == 0)
- continue;
- ud->uda1_ca.ca_rspint = 0;
- if (mp->mscp_opcode == (op | M_OP_END))
- break;
- printf("\n");
- switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
-
- case MSCPT_SEQ:
- printf("sequential");
- break;
-
- case MSCPT_DATAGRAM:
- mscp_decodeerror("uda", ui->ui_ctlr, mp);
- printf("datagram");
- break;
-
- case MSCPT_CREDITS:
- printf("credits");
- break;
-
- case MSCPT_MAINTENANCE:
- printf("maintenance");
- break;
-
- default:
- printf("unknown (type 0x%x)",
- MSCP_MSGTYPE(mp->mscp_msgtc));
- break;
+
+ /* If disk is not online, try to put it online */
+ if (rx->ra_state == DK_CLOSED)
+ if (rx_putonline(rx) == MSCP_FAILED) {
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ goto done;
}
- printf(" ignored\ndump ");
- ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
- }
- if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
- printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op,
- mp->mscp_opcode, mp->mscp_status);
- return (1);
+
+ /*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition.
+ */
+ if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) {
+ bp->b_resid = bp->b_bcount;
+ goto done;
}
-#endif
- return (0);
-#undef mp
+
+ /* Make some statistics... /bqt */
+ rx->ra_disk.dk_xfer++;
+ rx->ra_disk.dk_bytes += bp->b_bcount;
+ mscp_strategy(bp, rx->ra_dev.dv_parent);
+ return;
+
+done:
+ biodone(bp);
+}
+
+int
+rxread(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+
+ return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+rxwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+
+ return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
}
/*
- * Return the size of a partition, if known, or -1 if not.
+ * I/O controls.
*/
int
-rasize(dev)
+rxioctl(dev, cmd, data, flag, p)
dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
{
- register int unit = raunit(dev);
- struct ra_softc *ra;
+ register int unit = DISKUNIT(dev);
+ register struct disklabel *lp;
+ register struct rx_softc *rx = rx_cd.cd_devs[unit];
+ int error = 0;
- if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
- return -1;
+ lp = rx->ra_disk.dk_label;
- ra = ra_cd.cd_devs[unit];
+ switch (cmd) {
- if (ra->ra_state == RA_OFFLINE)
- if (ra_putonline(ra) == MSCP_FAILED)
- return -1;
+ case DIOCGDINFO:
+ bcopy(lp, data, sizeof (struct disklabel));
+ break;
- return ra->ra_disk.dk_label->d_partitions[rapart(dev)].p_size;
+ case DIOCGPART:
+ ((struct partinfo *)data)->disklab = lp;
+ ((struct partinfo *)data)->part =
+ &lp->d_partitions[DISKPART(dev)];
+ break;
+
+
+ case DIOCWDINFO:
+ case DIOCSDINFO:
+ case DIOCWLABEL:
+ break;
+
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return (error);
}
int
-ra_getdev(adaptor, controller, unit, uname)
- int adaptor, controller, unit;
- char **uname;
+rxdump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
{
+
+ /* Not likely. */
+ return ENXIO;
+}
+
+int
+rxsize(dev)
+ dev_t dev;
+{
+
+ return -1;
+}
+
+#endif /* NRX */
+
+void rrdgram __P((struct device *, struct mscp *, struct mscp_softc *));
+void rriodone __P((struct device *, struct buf *));
+int rronline __P((struct device *, struct mscp *));
+int rrgotstatus __P((struct device *, struct mscp *));
+void rrreplace __P((struct device *, struct mscp *));
+int rrioerror __P((struct device *, struct mscp *, struct buf *));
+void rrfillin __P((struct buf *, struct mscp *));
+void rrbb __P((struct device *, struct mscp *, struct buf *));
+
+
+struct mscp_device ra_device = {
+ rrdgram,
+ rriodone,
+ rronline,
+ rrgotstatus,
+ rrreplace,
+ rrioerror,
+ rrbb,
+ rrfillin,
+};
+
+/*
+ * Handle an error datagram.
+ * This can come from an unconfigured drive as well.
+ */
+void
+rrdgram(usc, mp, mi)
+ struct device *usc;
+ struct mscp *mp;
struct mscp_softc *mi;
- struct ra_softc *ra;
- int i;
+{
+ if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi))
+ return;
+ /*
+ * SDI status information bytes 10 and 11 are the microprocessor
+ * error code and front panel code respectively. These vary per
+ * drive type and are printed purely for field service information.
+ */
+ if (mp->mscp_format == M_FM_SDI)
+ printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
+ mp->mscp_erd.erd_sdistat[10],
+ mp->mscp_erd.erd_sdistat[11]);
+}
- for (i = 0; i < ra_cd.cd_ndevs; i++) {
- if ((ra = ra_cd.cd_devs[i]) == 0)
- continue;
+void
+rriodone(usc, bp)
+ struct device *usc;
+ struct buf *bp;
+{
- mi = (void *)ra->ra_dev.dv_parent;
- if (mi->mi_ctlrnr == controller && mi->mi_adapnr == adaptor &&
- ra->ra_hwunit == unit) {
- *uname = ra->ra_dev.dv_xname;
- return i;
- }
+ biodone(bp);
+}
+
+/*
+ * A drive came on line. Check its type and size. Return DONE if
+ * we think the drive is truly on line. In any case, awaken anyone
+ * sleeping on the drive on-line-ness.
+ */
+int
+rronline(usc, mp)
+ struct device *usc;
+ struct mscp *mp;
+{
+ struct rx_softc *rx = (struct rx_softc *)usc;
+ struct disklabel *dl;
+
+ wakeup((caddr_t)&usc->dv_unit);
+ if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
+ printf("%s: attempt to bring on line failed: ", usc->dv_xname);
+ mscp_printevent(mp);
+ return (MSCP_FAILED);
}
- return -1;
+
+ rx->ra_state = DK_OPEN;
+
+ dl = rx->ra_disk.dk_label;
+ dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
+
+ if (dl->d_secpercyl) {
+ dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
+ dl->d_type = DTYPE_MSCP;
+ dl->d_rpm = 3600;
+ } else {
+ dl->d_type = DTYPE_FLOPPY;
+ dl->d_rpm = 300;
+ }
+ rrmakelabel(dl, rx->ra_mediaid);
+
+ return (MSCP_DONE);
+}
+
+void
+rrmakelabel(dl, type)
+ struct disklabel *dl;
+ long type;
+{
+ int n, p = 0;
+
+ dl->d_bbsize = BBSIZE;
+ dl->d_sbsize = SBSIZE;
+
+ /* Create the disk name for disklabel. Phew... */
+ dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
+ dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
+ if (MSCP_MID_ECH(0, type))
+ dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
+ n = MSCP_MID_NUM(type);
+ if (n > 99) {
+ dl->d_typename[p++] = '1';
+ n -= 100;
+ }
+ if (n > 9) {
+ dl->d_typename[p++] = (n / 10) + '0';
+ n %= 10;
+ }
+ dl->d_typename[p++] = n + '0';
+ dl->d_typename[p] = 0;
+ dl->d_npartitions = MAXPARTITIONS;
+ dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
+ dl->d_secperunit;
+ dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
+ dl->d_interleave = dl->d_headswitch = 1;
+ dl->d_magic = dl->d_magic2 = DISKMAGIC;
+ dl->d_checksum = dkcksum(dl);
+}
+
+/*
+ * We got some (configured) unit's status. Return DONE if it succeeded.
+ */
+int
+rrgotstatus(usc, mp)
+ register struct device *usc;
+ register struct mscp *mp;
+{
+ if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
+ printf("%s: attempt to get status failed: ", usc->dv_xname);
+ mscp_printevent(mp);
+ return (MSCP_FAILED);
+ }
+ /* record for (future) bad block forwarding and whatever else */
+#ifdef notyet
+ uda_rasave(ui->ui_unit, mp, 1);
+#endif
+ return (MSCP_DONE);
+}
+
+/*
+ * A replace operation finished.
+ */
+/*ARGSUSED*/
+void
+rrreplace(usc, mp)
+ struct device *usc;
+ struct mscp *mp;
+{
+
+ panic("udareplace");
+}
+
+/*
+ * A transfer failed. We get a chance to fix or restart it.
+ * Need to write the bad block forwaring code first....
+ */
+/*ARGSUSED*/
+int
+rrioerror(usc, mp, bp)
+ register struct device *usc;
+ register struct mscp *mp;
+ struct buf *bp;
+{
+ struct ra_softc *ra = (void *)usc;
+ int code = mp->mscp_event;
+
+ switch (code & M_ST_MASK) {
+ /* The unit has fallen offline. Try to figure out why. */
+ case M_ST_OFFLINE:
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ ra->ra_state = DK_CLOSED;
+ if (code & M_OFFLINE_UNMOUNTED)
+ printf("%s: not mounted/spun down\n", usc->dv_xname);
+ if (code & M_OFFLINE_DUPLICATE)
+ printf("%s: duplicate unit number!!!\n", usc->dv_xname);
+ return MSCP_DONE;
+
+ case M_ST_AVAILABLE:
+ ra->ra_state = DK_CLOSED; /* Force another online */
+ return MSCP_DONE;
+
+ default:
+ printf("%s:", usc->dv_xname);
+ break;
+ }
+ return (MSCP_FAILED);
+}
+
+/*
+ * Fill in disk addresses in a mscp packet waiting for transfer.
+ */
+void
+rrfillin(bp, mp)
+ struct buf *bp;
+ struct mscp *mp;
+{
+ struct rx_softc *rx = 0; /* Wall */
+ struct disklabel *lp;
+ int unit = DISKUNIT(bp->b_dev);
+ int part = DISKPART(bp->b_dev);
+
+#if NRA
+ if (major(bp->b_dev) == RAMAJOR)
+ rx = ra_cd.cd_devs[unit];
+#endif
+#if NRX
+ if (major(bp->b_dev) != RAMAJOR)
+ rx = rx_cd.cd_devs[unit];
+#endif
+ lp = rx->ra_disk.dk_label;
+
+ mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno;
+ mp->mscp_unit = rx->ra_hwunit;
+ mp->mscp_seq.seq_bytecount = bp->b_bcount;
+}
+
+/*
+ * A bad block related operation finished.
+ */
+/*ARGSUSED*/
+void
+rrbb(usc, mp, bp)
+ struct device *usc;
+ struct mscp *mp;
+ struct buf *bp;
+{
+
+ panic("udabb");
}
-/* $OpenBSD: mscp_subr.c,v 1.2 1997/05/29 00:05:03 niklas Exp $ */
-/* $NetBSD: mscp_subr.c,v 1.6 1997/01/11 11:20:34 ragge Exp $ */
+/* $OpenBSD: mscp_subr.c,v 1.3 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp_subr.c,v 1.12 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
#include <sys/systm.h>
#include <sys/proc.h>
+#include <machine/bus.h>
#include <machine/sid.h>
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpreg.h>
-#include <vax/mscp/mscpvar.h>
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
#include "ra.h"
#include "mt.h"
-#define b_forw b_hash.le_next
+#define b_forw b_hash.le_next
-int mscp_match __P((struct device *, void *, void *));
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+int mscp_match __P((struct device *, struct cfdata *, void *));
void mscp_attach __P((struct device *, struct device *, void *));
-void mscp_start __P((struct mscp_softc *));
+void mscp_start __P((struct mscp_softc *));
int mscp_init __P((struct mscp_softc *));
void mscp_initds __P((struct mscp_softc *));
int mscp_waitstep __P((struct mscp_softc *, int, int));
struct cfattach mscpbus_ca = {
- sizeof(struct mscp_softc), mscp_match, mscp_attach
+ sizeof(struct mscp_softc), (cfmatch_t)mscp_match, mscp_attach
};
struct cfdriver mscpbus_cd = {
NULL, "mscpbus", DV_DULL
};
+#define READ_SA (bus_space_read_2(mi->mi_iot, mi->mi_sah, 0))
+#define READ_IP (bus_space_read_2(mi->mi_iot, mi->mi_iph, 0))
+#define WRITE_IP(x) bus_space_write_2(mi->mi_iot, mi->mi_iph, 0, (x))
+#define WRITE_SW(x) bus_space_write_2(mi->mi_iot, mi->mi_swh, 0, (x))
+
struct mscp slavereply;
/*
{
int status = 1;
- if ((*mi->mi_sa & mask) != result) {
+ if ((READ_SA & mask) != result) {
volatile int count = 0;
- while ((*mi->mi_sa & mask) != result) {
+ while ((READ_SA & mask) != result) {
DELAY(10000);
count += 1;
if (count > DELAYTEN)
int
mscp_match(parent, match, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *match;
+ void *aux;
{
struct mscp_attach_args *ma = aux;
-#if NRA
+#if NRA || NRX
if (ma->ma_type & MSCPBUS_DISK)
return 1;
#endif
{
struct mscp_attach_args *ma = aux;
struct mscp_softc *mi = (void *)self;
- volatile struct mscp *mp;
+ volatile struct mscp *mp;
volatile int i;
int timeout, next = 0;
mi->mi_mc = ma->ma_mc;
mi->mi_me = NULL;
mi->mi_type = ma->ma_type;
- mi->mi_uuda = ma->ma_uuda;
mi->mi_uda = ma->ma_uda;
- mi->mi_ip = ma->ma_ip;
- mi->mi_sa = ma->ma_sa;
- mi->mi_sw = ma->ma_sw;
+ mi->mi_dmat = ma->ma_dmat;
+ mi->mi_dmam = ma->ma_dmam;
+ mi->mi_iot = ma->ma_iot;
+ mi->mi_iph = ma->ma_iph;
+ mi->mi_sah = ma->ma_sah;
+ mi->mi_swh = ma->ma_swh;
mi->mi_ivec = ma->ma_ivec;
mi->mi_adapnr = ma->ma_adapnr;
mi->mi_ctlrnr = ma->ma_ctlrnr;
* Go out to init the bus, so that we can give commands
* to its devices.
*/
- mi->mi_cmd.mri_size = NCMD;
- mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
- mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
- mi->mi_rsp.mri_size = NRSP;
- mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
- mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
- mi->mi_actf = (void *)&mi->mi_actf; /* Circular wait queue */
- mi->mi_actb = (void *)&mi->mi_actf;
+ mi->mi_cmd.mri_size = NCMD;
+ mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
+ mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
+ mi->mi_rsp.mri_size = NRSP;
+ mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
+ mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
+ SIMPLEQ_INIT(&mi->mi_resq);
if (mscp_init(mi)) {
printf("%s: can't init, controller hung\n",
mi->mi_dev.dv_xname);
return;
}
+ for (i = 0; i < NCMD; i++) {
+ mi->mi_mxiuse |= (1 << i);
+ if (bus_dmamap_create(mi->mi_dmat, (64*1024), 1, (64*1024),
+ 0, BUS_DMA_NOWAIT, &mi->mi_xi[i].mxi_dmam)) {
+ printf("Couldn't alloc dmamap %d\n", i);
+ return;
+ }
+ }
+
#if NRA
if (ma->ma_type & MSCPBUS_DISK) {
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
slavereply.mscp_opcode = 0;
- i = *mi->mi_ip; /* Kick off polling */
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
mp = &slavereply;
timeout = 1000;
while (timeout-- > 0) {
*/
switch (mp->mscp_status & M_ST_MASK) {
- case M_ST_SUCCESS: /* worked */
- case M_ST_AVAILABLE: /* found another drive */
- break; /* use it */
+ case M_ST_SUCCESS: /* worked */
+ case M_ST_AVAILABLE: /* found another drive */
+ break; /* use it */
case M_ST_OFFLINE:
/*
* Figure out why it is off line. It may be because
- * it is nonexistent, or because it is spun down, or
- * for some other reason.
- */
- switch (mp->mscp_status & ~M_ST_MASK) {
-
- case M_OFFLINE_UNKNOWN:
- /*
- * No such drive, and there are none with
- * higher unit numbers either, if we are
- * using M_GUM_NEXTUNIT.
- */
+ * it is nonexistent, or because it is spun down, or
+ * for some other reason.
+ */
+ switch (mp->mscp_status & ~M_ST_MASK) {
+
+ case M_OFFLINE_UNKNOWN:
+ /*
+ * No such drive, and there are none with
+ * higher unit numbers either, if we are
+ * using M_GUM_NEXTUNIT.
+ */
mi->mi_ierr = 3;
- return;
-
- case M_OFFLINE_UNMOUNTED:
- /*
- * The drive is not spun up. Use it anyway.
- *
- * N.B.: this seems to be a common occurrance
- * after a power failure. The first attempt
- * to bring it on line seems to spin it up
- * (and thus takes several minutes). Perhaps
- * we should note here that the on-line may
- * take longer than usual.
- */
- break;
-
- default:
- /*
- * In service, or something else equally unusable.
- */
- printf("%s: unit %d off line: ", mi->mi_dev.dv_xname,
- mp->mscp_unit);
- mscp_printevent((struct mscp *)mp);
+ return;
+
+ case M_OFFLINE_UNMOUNTED:
+ /*
+ * The drive is not spun up. Use it anyway.
+ *
+ * N.B.: this seems to be a common occurrance
+ * after a power failure. The first attempt
+ * to bring it on line seems to spin it up
+ * (and thus takes several minutes). Perhaps
+ * we should note here that the on-line may
+ * take longer than usual.
+ */
+ break;
+
+ default:
+ /*
+ * In service, or something else equally unusable.
+ */
+ printf("%s: unit %d off line: ", mi->mi_dev.dv_xname,
+ mp->mscp_unit);
+ mscp_printevent((struct mscp *)mp);
next++;
- goto findunit;
- }
- break;
-
- default:
- printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname);
- mscp_printevent((struct mscp *)mp);
- return;
- }
-
- /*
- * If we get a lower number, we have circulated around all
+ goto findunit;
+ }
+ break;
+
+ default:
+ printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname);
+ mscp_printevent((struct mscp *)mp);
+ return;
+ }
+
+ /*
+ * If we get a lower number, we have circulated around all
* devices and are finished, otherwise try to find next unit.
* We shouldn't ever get this, it's a workaround.
- */
- if (mp->mscp_unit < next)
- return;
+ */
+ if (mp->mscp_unit < next)
+ return;
next = mp->mscp_unit + 1;
goto findunit;
int status, count;
unsigned int j = 0;
- /*
- * While we are thinking about it, reset the next command
- * and response indicies.
- */
+ /*
+ * While we are thinking about it, reset the next command
+ * and response indicies.
+ */
mi->mi_cmd.mri_next = 0;
mi->mi_rsp.mri_next = 0;
mi->mi_flags |= MSC_IGNOREINTR;
if ((mi->mi_type & MSCPBUS_KDB) == 0)
- *mi->mi_ip = 0; /* Kick off */
+ WRITE_IP(0); /* Kick off */;
status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */
if (status == 0)
return 1; /* Init failed */
- if (*mi->mi_sa & MP_ERR) {
+ if (READ_SA & MP_ERR) {
(*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
return 1;
}
/* step1 */
- *mi->mi_sw = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
- MP_IE | (mi->mi_ivec >> 2);
+ WRITE_SW(MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
+ MP_IE | (mi->mi_ivec >> 2));
status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD);
if (status == 0) {
(*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
}
/* step2 */
- *mi->mi_sw = (int)&mi->mi_uuda->mp_ca.ca_rspdsc[0] |
- (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0);
+ WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) +
+ offsetof(struct mscp_pack, mp_ca.ca_rspdsc[0])) |
+ (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0));
status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2));
- if (status == 0) {
- (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
- return 1;
- }
+ if (status == 0) {
+ (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+ return 1;
+ }
/* step3 */
- *mi->mi_sw = ((int)&mi->mi_uuda->mp_ca.ca_rspdsc[0]) >> 16;
+
+ WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16));
status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
- if (status == 0) {
- (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
- return 1;
- }
- i = *mi->mi_sa & 0377;
+ if (status == 0) {
+ (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+ return 1;
+ }
+ i = READ_SA & 0377;
printf(": version %d model %d\n", i & 15, i >> 4);
-#define BURST 4 /* XXX */
+#define BURST 4 /* XXX */
if (mi->mi_type & MSCPBUS_UDA) {
- *mi->mi_sw = MP_GO | (BURST - 1) << 2;
+ WRITE_SW(MP_GO | (BURST - 1) << 2);
printf("%s: DMA burst size set to %d\n",
mi->mi_dev.dv_xname, BURST);
}
- *mi->mi_sw = MP_GO;
+ WRITE_SW(MP_GO);
mscp_initds(mi);
mi->mi_flags &= ~MSC_IGNOREINTR;
mp->mscp_sccc.sccc_errlgfl = 0;
mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
- i = *mi->mi_ip;
+ i = READ_IP;
- count = 0;
- while (count < DELAYTEN) {
- if (((volatile)mi->mi_flags & MSC_READY) != 0)
- break;
- if ((j = *mi->mi_sa) & MP_ERR)
+ count = 0;
+ while (count < DELAYTEN) {
+ if (((volatile int)mi->mi_flags & MSC_READY) != 0)
+ break;
+ if ((j = READ_SA) & MP_ERR)
goto out;
- DELAY(10000);
- count += 1;
- }
+ DELAY(10000);
+ count += 1;
+ }
if (count == DELAYTEN) {
out:
printf("%s: couldn't set ctlr characteristics, sa=%x\n",
mscp_initds(mi)
struct mscp_softc *mi;
{
- struct mscp_pack *uud = mi->mi_uuda;
struct mscp_pack *ud = mi->mi_uda;
struct mscp *mp;
int i;
for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) {
ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
- (long)&uud->mp_rsp[i].mscp_cmdref;
+ (mi->mi_dmam->dm_segs[0].ds_addr +
+ offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref));
mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i];
mp->mscp_msglen = MSCP_MSGLEN;
}
for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) {
ud->mp_ca.ca_cmddsc[i] = MSCP_INT |
- (long)&uud->mp_cmd[i].mscp_cmdref;
+ (mi->mi_dmam->dm_segs[0].ds_addr +
+ offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref));
mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i];
mp->mscp_msglen = MSCP_MSGLEN;
if (mi->mi_type & MSCPBUS_TAPE)
}
}
+static void mscp_kickaway(struct mscp_softc *);
+
void
mscp_intr(mi)
struct mscp_softc *mi;
if (mi->mi_flags & MSC_IGNOREINTR)
return;
- /*
- * Check for response and command ring transitions.
- */
- if (ud->mp_ca.ca_rspint) {
- ud->mp_ca.ca_rspint = 0;
- mscp_dorsp(mi);
- }
- if (ud->mp_ca.ca_cmdint) {
- ud->mp_ca.ca_cmdint = 0;
- MSCP_DOCMD(mi);
- }
-
/*
- * If there are any not-yet-handled requeset, try them now.
- * XXX - We handles them (erroneous) in last-in first-handled order.
- * Must we fix this???
+ * Check for response and command ring transitions.
*/
- while (mi->mi_w) {
- struct buf *bp = mi->mi_w;
-
- mi->mi_w = (void *)bp->b_actb;
- mscp_strategy(bp, (struct device *)mi);
- if (mi->mi_w == bp)
- break;
+ if (ud->mp_ca.ca_rspint) {
+ ud->mp_ca.ca_rspint = 0;
+ mscp_dorsp(mi);
+ }
+ if (ud->mp_ca.ca_cmdint) {
+ ud->mp_ca.ca_cmdint = 0;
+ MSCP_DOCMD(mi);
}
+
+ /*
+ * If there are any not-yet-handled request, try them now.
+ */
+ if (SIMPLEQ_FIRST(&mi->mi_resq))
+ mscp_kickaway(mi);
}
int
void *aux;
const char *name;
{
+ struct drive_attach_args *da = aux;
+ struct mscp *mp = da->da_mp;
+ int type = mp->mscp_guse.guse_mediaid;
+
+ if (name) {
+ printf("%c%c", MSCP_MID_CHAR(2, type), MSCP_MID_CHAR(1, type));
+ if (MSCP_MID_ECH(0, type))
+ printf("%c", MSCP_MID_CHAR(0, type));
+ printf("%d at %s drive %d", MSCP_MID_NUM(type), name,
+ mp->mscp_unit);
+ }
return UNCONF;
}
/*
* common strategy routine for all types of MSCP devices.
- * bp is the current buf, dp is the drive queue.
*/
void
mscp_strategy(bp, usc)
struct device *usc;
{
struct mscp_softc *mi = (void *)usc;
+ int s = splimp();
+
+/* SIMPLEQ_INSERT_TAIL(&mi->mi_resq, bp, xxx) */
+ bp->b_actf = NULL;
+ *mi->mi_resq.sqh_last = bp;
+ mi->mi_resq.sqh_last = &bp->b_actf;
+ mscp_kickaway(mi);
+ splx(s);
+}
+
+
+void
+mscp_kickaway(mi)
+ struct mscp_softc *mi;
+{
+ struct buf *bp;
struct mscp *mp;
- int s = spl6();
+ int next;
- /*
- * Ok; we are ready to try to start a xfer. Get a MSCP packet
- * and try to start...
- */
- if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
- if (mi->mi_credits > MSCP_MINCREDITS)
- printf("%s: command ring too small\n",
- mi->mi_dev.dv_parent->dv_xname);
+ while ((bp = SIMPLEQ_FIRST(&mi->mi_resq))) {
/*
- * By some (strange) reason we didn't get a MSCP packet.
- * Put it on queue and wait for free packets.
+ * Ok; we are ready to try to start a xfer. Get a MSCP packet
+ * and try to start...
*/
- (void *)bp->b_actb = mi->mi_w;
- mi->mi_w = bp;
- splx(s);
- return;
+ if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
+ if (mi->mi_credits > MSCP_MINCREDITS)
+ printf("%s: command ring too small\n",
+ mi->mi_dev.dv_parent->dv_xname);
+ /*
+ * By some (strange) reason we didn't get a MSCP packet.
+ * Just return and wait for free packets.
+ */
+ return;
+ }
+
+ if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
+ panic("no mxi buffers");
+ mi->mi_mxiuse &= ~(1 << next);
+ if (mi->mi_xi[next].mxi_inuse)
+ panic("mxi inuse");
+ /*
+ * Set up the MSCP packet and ask the ctlr to start.
+ */
+ mp->mscp_opcode =
+ (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
+ mp->mscp_cmdref = next;
+ mi->mi_xi[next].mxi_bp = bp;
+ mi->mi_xi[next].mxi_mp = mp;
+ mi->mi_xi[next].mxi_inuse = 1;
+ bp->b_resid = next;
+ (*mi->mi_me->me_fillin)(bp, mp);
+ (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]);
+ if ((mi->mi_resq.sqh_first = bp->b_actf) == NULL)
+ mi->mi_resq.sqh_last = &mi->mi_resq.sqh_first;
+#if 0
+ mi->mi_w = bp->b_actf;
+#endif
}
-
- /*
- * Set up the MSCP packet and ask the ctlr to start.
- */
- mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
- (*mi->mi_me->me_fillin)(bp, mp);
- (void *)bp->b_actb = mp; /* b_actb is unused, save mscp packet here */
- (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, bp);
- splx(s);
}
void
-mscp_dgo(mi, buffer, info, bp)
+mscp_dgo(mi, mxi)
struct mscp_softc *mi;
- long buffer, info;
- struct buf *bp;
+ struct mscp_xi *mxi;
{
volatile int i;
struct mscp *mp;
- /*
- * Fill in the MSCP packet and move the buffer to the I/O wait queue.
- */
- mp = (void *)bp->b_actb;
-
- mp->mscp_seq.seq_buffer = buffer;
-
- _insque(&bp->b_actf, &mi->mi_actf);
+ /*
+ * Fill in the MSCP packet and move the buffer to the I/O wait queue.
+ */
+ mp = mxi->mxi_mp;
+ mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
- bp->b_resid = info;
- mp->mscp_cmdref = (long) bp;
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-
- i = *mi->mi_ip;
+ i = READ_IP;
}
#ifdef DIAGNOSTIC
"lost rd/wr ready", /* 4 = Lost R/W Ready Error */
"drive clock dropout", /* 5 = Lost Drive Clock */
"lost recvr ready", /* 6 = Lost Receiver Ready */
- "drive detected error", /* 7 = Drive Error */
+ "drive detected error", /* 7 = Drive Error */
"ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
};
int cdc_nsubcodes;
char **cdc_submsgs;
} code_decode[] = {
-#define SC(m) sizeof (m) / sizeof (m[0]), m
+#define SC(m) sizeof (m) / sizeof (m[0]), m
{"success", SC(succ_msgs)},
{"invalid command", SC(icmd_msgs)},
{"command aborted", 0, 0},
-/* $OpenBSD: mscp_tape.c,v 1.3 1997/09/12 09:25:52 maja Exp $ */
-/* $NetBSD: mscp_tape.c,v 1.5 1997/07/04 11:58:22 ragge Exp $ */
+/* $OpenBSD: mscp_tape.c,v 1.4 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp_tape.c,v 1.14 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
* 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 at Ludd, University of
- * Lule}, Sweden and its contributors.
+ * This product includes software developed at Ludd, University of
+ * Lule}, Sweden and its contributors.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
#include <sys/systm.h>
#include <sys/proc.h>
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpvar.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
/*
* Drive status, per drive
int mt_ioctlerr; /* Error after last ioctl */
};
-#define MT_OFFLINE 0
-#define MT_ONLINE 1
+#define MT_OFFLINE 0
+#define MT_ONLINE 1
-int mtmatch __P((struct device *, void *, void *));
+int mtmatch __P((struct device *, struct cfdata *, void *));
void mtattach __P((struct device *, struct device *, void *));
void mtdgram __P((struct device *, struct mscp *, struct mscp_softc *));
void mtiodone __P((struct device *, struct buf *));
int mtdump __P((dev_t, daddr_t, caddr_t, size_t));
int mtcmd __P((struct mt_softc *, int, int, int));
void mtcmddone __P((struct device *, struct mscp *));
+int mt_putonline __P((struct mt_softc *));
struct mscp_device mt_device = {
mtdgram,
};
/* This is not good, should allow more than 4 tapes/device type */
-#define mtunit(dev) (minor(dev) & T_UNIT)
-#define mtnorewind(dev) (dev & T_NOREWIND)
-#define mthdensity(dev) (dev & T_1600BPI)
+#define mtunit(dev) (minor(dev) & T_UNIT)
+#define mtnorewind(dev) (dev & T_NOREWIND)
+#define mthdensity(dev) (dev & T_1600BPI)
-struct cfdriver mt_cd = {
- NULL, "mt", DV_DULL
+struct cfattach mt_ca = {
+ sizeof(struct mt_softc), (cfmatch_t)mtmatch, mtattach
};
-struct cfattach mt_ca = {
- sizeof(struct mt_softc), mtmatch, mtattach
+struct cfdriver mt_cd = {
+ NULL, "mt", DV_TAPE
};
/*
*/
int
-mtmatch(parent, match, aux)
+mtmatch(parent, cf, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *cf;
+ void *aux;
{
- struct cfdata *cf = match;
struct drive_attach_args *da = aux;
struct mscp *mp = da->da_mp;
struct mscp_softc *mi = (struct mscp_softc *)mt->mt_dev.dv_parent;
volatile int i;
- (volatile)mt->mt_state = MT_OFFLINE;
+ (volatile int)mt->mt_state = MT_OFFLINE;
mp = mscp_getcp(mi, MSCP_WAIT);
mp->mscp_opcode = M_OP_ONLINE;
mp->mscp_unit = mt->mt_hwunit;
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
/* Poll away */
- i = *mi->mi_ip;
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz))
return MSCP_FAILED;
- if ((volatile)mt->mt_state != MT_ONLINE)
+ if ((volatile int)mt->mt_state != MT_ONLINE)
return MSCP_FAILED;
return MSCP_DONE;
return EBUSY;
mt->mt_inuse = 1;
- if (mt_putonline(mt) == MSCP_FAILED)
+ if (mt_putonline(mt) == MSCP_FAILED) {
+ mt->mt_inuse = 0;
return EIO;
+ }
return 0;
}
int
mtread(dev, uio)
- dev_t dev;
- struct uio *uio;
+ dev_t dev;
+ struct uio *uio;
{
- return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
+ return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
}
int
mtwrite(dev, uio)
- dev_t dev;
- struct uio *uio;
+ dev_t dev;
+ struct uio *uio;
{
- return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
+ return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
}
void
"unit offline", /* 3 M_ST_OFFLINE */
"unknown", /* 4 M_ST_AVAILABLE */
"unknown", /* 5 M_ST_MFMTERR */
- "unit write protected", /* 6 M_ST_WRPROT */
+ "unit write protected", /* 6 M_ST_WRPROT */
"compare error", /* 7 M_ST_COMPERR */
- "data error", /* 8 M_ST_DATAERR */
- "host buffer access error", /* 9 M_ST_HOSTBUFERR */
+ "data error", /* 8 M_ST_DATAERR */
+ "host buffer access error", /* 9 M_ST_HOSTBUFERR */
"controller error", /* 10 M_ST_CTLRERR */
- "drive error", /* 11 M_ST_DRIVEERR */
+ "drive error", /* 11 M_ST_DRIVEERR */
"formatter error", /* 12 M_ST_FORMATTERR */
"BOT encountered", /* 13 M_ST_BOT */
"tape mark encountered",/* 14 M_ST_TAPEMARK */
else
printf("%s: error %d\n", mt->mt_dev.dv_xname, st);
bp->b_flags |= B_ERROR;
+ bp->b_error = EROFS;
}
return (MSCP_DONE);
register struct mt_softc *mt = mt_cd.cd_devs[unit];
struct mtop *mtop;
struct mtget *mtget;
- int error = 0, i, count;
+ int error = 0, count;
count = mtop->mt_count;
int
mtdump(dev, blkno, va, size)
dev_t dev;
- daddr_t blkno;
- caddr_t va;
+ daddr_t blkno;
+ caddr_t va;
size_t size;
{
return -1;
break;
}
- i = *mi->mi_ip;
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0);
return mt->mt_ioctlerr;
}
-/* $OpenBSD: mscpreg.h,v 1.3 1997/09/10 11:54:42 maja Exp $ */
-/* $NetBSD: mscpreg.h,v 1.2 1997/03/15 16:39:20 ragge Exp $ */
+/* $OpenBSD: mscpreg.h,v 1.4 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscpreg.h,v 1.4 1999/05/29 19:12:53 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
* If you get warnings about your command ring being too small,
* try increasing the values by one.
*/
-#ifndef NRSP
-#define NRSPL2 5
-#define NCMDL2 5
-#define NRSP (1 << NRSPL2)
-#define NCMD (1 << NCMDL2)
+#ifndef NRSP
+#define NRSPL2 5
+#define NCMDL2 5
+#define NRSP (1 << NRSPL2)
+#define NCMD (1 << NCMDL2)
#endif
/*
/*
* Bits in UDA status register during initialisation
*/
-#define MP_ERR 0x8000 /* error */
-#define MP_STEP4 0x4000 /* step 4 has started */
-#define MP_STEP3 0x2000 /* step 3 has started */
-#define MP_STEP2 0x1000 /* step 2 has started */
-#define MP_STEP1 0x0800 /* step 1 has started */
-#define MP_NV 0x0400 /* no host settable interrupt vector */
-#define MP_QB 0x0200 /* controller supports Q22 bus */
-#define MP_DI 0x0100 /* controller implements diagnostics */
-#define MP_IE 0x0080 /* interrupt enable */
-#define MP_NCNRMASK 0x003f /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */
-#define MP_IVECMASK 0x007f /* in STEP2, bits 0-6 are interruptvec / 4 */
-#define MP_PI 0x0001 /* host requests adapter purge interrupts */
-#define MP_GO 0x0001 /* Go command to ctlr */
+#define MP_ERR 0x8000 /* error */
+#define MP_STEP4 0x4000 /* step 4 has started */
+#define MP_STEP3 0x2000 /* step 3 has started */
+#define MP_STEP2 0x1000 /* step 2 has started */
+#define MP_STEP1 0x0800 /* step 1 has started */
+#define MP_NV 0x0400 /* no host settable interrupt vector */
+#define MP_QB 0x0200 /* controller supports Q22 bus */
+#define MP_DI 0x0100 /* controller implements diagnostics */
+#define MP_IE 0x0080 /* interrupt enable */
+#define MP_NCNRMASK 0x003f /* in STEP1, bits 0-2=NCMDL2, 3-5=NRSPL2 */
+#define MP_IVECMASK 0x007f /* in STEP2, bits 0-6 are interruptvec / 4 */
+#define MP_PI 0x0001 /* host requests adapter purge interrupts */
+#define MP_GO 0x0001 /* Go command to ctlr */
#define ALLSTEPS (MP_ERR | MP_STEP4 | MP_STEP3 | MP_STEP2 | MP_STEP1)
#define STEP0MASK (ALLSTEPS | MP_NV)
-#define STEP1MASK (ALLSTEPS | MP_IE | MP_NCNRMASK)
-#define STEP1GOOD (MP_STEP2 | MP_IE | (NCMDL2 << 3) | NRSPL2)
+#define STEP1MASK (ALLSTEPS | MP_IE | MP_NCNRMASK)
+#define STEP1GOOD (MP_STEP2 | MP_IE | (NCMDL2 << 3) | NRSPL2)
-#define STEP2MASK (ALLSTEPS | MP_IE | MP_IVECMASK)
-#define STEP2GOOD(iv) (MP_STEP3 | MP_IE | (iv))
+#define STEP2MASK (ALLSTEPS | MP_IE | MP_IVECMASK)
+#define STEP2GOOD(iv) (MP_STEP3 | MP_IE | (iv))
-#define STEP3MASK ALLSTEPS
-#define STEP3GOOD MP_STEP4
+#define STEP3MASK ALLSTEPS
+#define STEP3GOOD MP_STEP4
-/* $OpenBSD: mscpvar.h,v 1.2 1997/05/29 00:05:04 niklas Exp $ */
-/* $NetBSD: mscpvar.h,v 1.4 1997/01/11 11:20:36 ragge Exp $ */
+/* $OpenBSD: mscpvar.h,v 1.3 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscpvar.h,v 1.7 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
struct mscp *mri_ring; /* base address of packets */
};
+/*
+ * Transfer info, one per command packet.
+ */
+struct mscp_xi {
+ bus_dmamap_t mxi_dmam; /* Allocated DMA map for this entry */
+ struct buf * mxi_bp; /* Buffer used in this command */
+ struct mscp * mxi_mp; /* Packet used in this command */
+ int mxi_inuse;
+};
+
struct mscp_ctlr {
void (*mc_ctlrdone) /* controller operation complete */
- __P((struct device *, int));
- int (*mc_go) /* device-specific start routine */
- __P((struct device *, struct buf *));
+ __P((struct device *));
+ void (*mc_go) /* device-specific start routine */
+ __P((struct device *, struct mscp_xi *));
void (*mc_saerror) /* ctlr error handling */
__P((struct device *, int));
};
__P((struct device *, struct buf *));
int (*me_online) /* drive on line */
__P((struct device *, struct mscp *));
- int (*me_gotstatus) /* got unit status */
+ int (*me_gotstatus) /* got unit status */
__P((struct device *, struct mscp *));
void (*me_replace) /* replace done */
__P((struct device *, struct mscp *));
struct mscp_ctlr *ma_mc; /* Pointer to ctlr's mscp_ctlr */
int ma_type; /* disk/tape bus type */
struct mscp_pack *ma_uda; /* comm area virtual */
- struct mscp_pack *ma_uuda; /* comm area on bus */
struct mscp_softc **ma_softc; /* backpointer to bus softc */
- short *ma_ip; /* initialisation and polling */
- short *ma_sa; /* status & address (read part) */
- short *ma_sw; /* status & address (write part) */
+ bus_dmamap_t ma_dmam; /* This comm area dma info */
+ bus_dma_tag_t ma_dmat;
+ bus_space_tag_t ma_iot;
+ bus_space_handle_t ma_iph; /* initialisation and polling */
+ bus_space_handle_t ma_sah; /* status & address (read part) */
+ bus_space_handle_t ma_swh; /* status & address (write part) */
short ma_ivec; /* Interrupt vector to use */
char ma_ctlrnr; /* Phys ctlr nr */
char ma_adapnr; /* Phys adapter nr */
};
#define MSCPBUS_DISK 001 /* Bus is used for disk mounts */
#define MSCPBUS_TAPE 002 /* Bus is used for tape mounts */
-#define MSCPBUS_UDA 004 /* ctlr is disk on unibus/qbus */
-#define MSCPBUS_KDB 010 /* ctlr is disk on BI */
-#define MSCPBUS_KLE 020 /* ctlr is tape on unibus/qbus */
+#define MSCPBUS_UDA 004 /* ctlr is disk on unibus/qbus */
+#define MSCPBUS_KDB 010 /* ctlr is disk on BI */
+#define MSCPBUS_KLE 020 /* ctlr is tape on unibus/qbus */
/*
* Used when going for child devices.
struct device mi_dev; /* Autoconf stuff */
struct mscp_ri mi_cmd; /* MSCP command ring info */
struct mscp_ri mi_rsp; /* MSCP response ring info */
+ bus_dma_tag_t mi_dmat;
+ bus_dmamap_t mi_dmam;
+ struct mscp_xi mi_xi[NCMD];
+ int mi_mxiuse; /* Bitfield of inuse mxi packets */
short mi_credits; /* transfer credits */
char mi_wantcmd; /* waiting for command packet */
char mi_wantcredits; /* waiting for transfer credits */
- struct buf *mi_actf; /* Pointer to buffers in */
- struct buf *mi_actb; /* circular wait queue */
struct mscp_ctlr *mi_mc; /* Pointer to parent's mscp_ctlr */
struct mscp_device *mi_me; /* Pointer to child's mscp_device */
struct device **mi_dp; /* array of backpointers */
char mi_adapnr; /* Phys adapter nr */
int mi_flags;
struct mscp_pack *mi_uda; /* virtual address */
- struct mscp_pack *mi_uuda; /* (device-specific) address */
int mi_type;
short mi_ivec; /* Interrupt vector to use */
short mi_ierr; /* Init err counter */
- volatile short *mi_ip; /* initialisation and polling */
- volatile short *mi_sa; /* status & address (read part) */
- volatile short *mi_sw; /* status & address (write part) */
- struct buf *mi_w; /* While waiting for packets */
+ bus_space_tag_t mi_iot;
+ bus_space_handle_t mi_iph; /* initialisation and polling */
+ bus_space_handle_t mi_sah; /* status & address (read part) */
+ bus_space_handle_t mi_swh; /* status & address (write part) */
+ SIMPLEQ_HEAD(, buf) mi_resq; /* While waiting for packets */
};
/* mi_flags */
-#define MSC_STARTPOLL 1
-#define MSC_INSTART 2
-#define MSC_IGNOREINTR 4
-#define MSC_READY 8
+#define MSC_STARTPOLL 1
+#define MSC_INSTART 2
+#define MSC_IGNOREINTR 4
+#define MSC_READY 8
/*
* We have run out of credits when mi_credits is <= MSCP_MINCREDITS.
} \
}
-/*
- * The following macro appends a buffer to a drive queue or a drive to
- * a controller queue, given the name of the forward link. Use as
- * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)',
- * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab'
- * is a controller queue. (That is, the forward link for controller
- * queues is `b_forw'; for drive queues, it is `av_forw'.)
- */
-
-#define MSCP_APPEND(bp, queue, link) { \
- (bp)->link = NULL; \
- if ((queue)->link == NULL) \
- (queue)->link = (bp); \
- else \
- *(queue)->b_actb = (bp); \
- (queue)->b_actb = &(bp)->link; \
-}
-
/* Prototypes */
struct mscp *mscp_getcp __P((struct mscp_softc *, int));
void mscp_printevent __P((struct mscp *));
void mscp_strategy __P((struct buf *, struct device *));
void mscp_printtype __P((int, int));
int mscp_waitstep __P((struct mscp_softc *, int, int));
-void mscp_dgo __P((struct mscp_softc *, long, long, struct buf *));
+void mscp_dgo __P((struct mscp_softc *, struct mscp_xi *));
void mscp_intr __P((struct mscp_softc *));
--- /dev/null
+/* $OpenBSD: dhu.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dhu.c,v 1.17 2000/01/24 02:40:28 matt Exp $ */
+/*
+ * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/scb.h>
+
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/qbus/dhureg.h>
+
+/* A DHU-11 has 16 ports while a DHV-11 has only 8. We use 16 by default */
+
+#define NDHULINE 16
+
+#define DHU_M2U(c) ((c)>>4) /* convert minor(dev) to unit # */
+#define DHU_LINE(u) ((u)&0xF) /* extract line # from minor(dev) */
+
+struct dhu_softc {
+ struct device sc_dev; /* Device struct used by config */
+ int sc_type; /* controller type, DHU or DHV */
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+ struct {
+ struct tty *dhu_tty; /* what we work on */
+ bus_dmamap_t dhu_dmah;
+ int dhu_state; /* to manage TX output status */
+ short dhu_cc; /* character count on TX */
+ short dhu_modem; /* modem bits state */
+ } sc_dhu[NDHULINE];
+};
+
+#define IS_DHU 16 /* Unibus DHU-11 board linecount */
+#define IS_DHV 8 /* Q-bus DHV-11 or DHQ-11 */
+
+#define STATE_IDLE 000 /* no current output in progress */
+#define STATE_DMA_RUNNING 001 /* DMA TX in progress */
+#define STATE_DMA_STOPPED 002 /* DMA TX was aborted */
+#define STATE_TX_ONE_CHAR 004 /* did a single char directly */
+
+/* Flags used to monitor modem bits, make them understood outside driver */
+
+#define DML_DTR TIOCM_DTR
+#define DML_RTS TIOCM_RTS
+#define DML_CTS TIOCM_CTS
+#define DML_DCD TIOCM_CD
+#define DML_RI TIOCM_RI
+#define DML_DSR TIOCM_DSR
+#define DML_BRK 0100000 /* no equivalent, we will mask */
+
+#define DHU_READ_WORD(reg) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
+#define DHU_WRITE_WORD(reg, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
+#define DHU_READ_BYTE(reg) \
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg)
+#define DHU_WRITE_BYTE(reg, val) \
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
+
+
+/* On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */
+/* a baud rate from the same group. So limiting to B is likely */
+/* best, although clone boards like the ABLE QHV allow all settings. */
+
+static struct speedtab dhuspeedtab[] = {
+ { 0, 0 }, /* Groups */
+ { 50, DHU_LPR_B50 }, /* A */
+ { 75, DHU_LPR_B75 }, /* B */
+ { 110, DHU_LPR_B110 }, /* A and B */
+ { 134, DHU_LPR_B134 }, /* A and B */
+ { 150, DHU_LPR_B150 }, /* B */
+ { 300, DHU_LPR_B300 }, /* A and B */
+ { 600, DHU_LPR_B600 }, /* A and B */
+ { 1200, DHU_LPR_B1200 }, /* A and B */
+ { 1800, DHU_LPR_B1800 }, /* B */
+ { 2000, DHU_LPR_B2000 }, /* B */
+ { 2400, DHU_LPR_B2400 }, /* A and B */
+ { 4800, DHU_LPR_B4800 }, /* A and B */
+ { 7200, DHU_LPR_B7200 }, /* A */
+ { 9600, DHU_LPR_B9600 }, /* A and B */
+ { 19200, DHU_LPR_B19200 }, /* B */
+ { 38400, DHU_LPR_B38400 }, /* A */
+ { -1, -1 }
+};
+
+static int dhu_match __P((struct device *, struct cfdata *, void *));
+static void dhu_attach __P((struct device *, struct device *, void *));
+static void dhurint __P((void *));
+static void dhuxint __P((void *));
+static void dhustart __P((struct tty *));
+static int dhuparam __P((struct tty *, struct termios *));
+static int dhuiflow __P((struct tty *, int));
+static unsigned dhumctl __P((struct dhu_softc *,int, int, int));
+ int dhuopen __P((dev_t, int, int, struct proc *));
+ int dhuclose __P((dev_t, int, int, struct proc *));
+ int dhuread __P((dev_t, struct uio *, int));
+ int dhuwrite __P((dev_t, struct uio *, int));
+ int dhuioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+ void dhustop __P((struct tty *, int));
+struct tty * dhutty __P((dev_t));
+
+struct cfattach dhu_ca = {
+ sizeof(struct dhu_softc), (cfmatch_t)dhu_match, dhu_attach
+};
+
+struct cfdriver dhu_cd = {
+ NULL, "dhu", DV_TTY
+};
+
+/* Autoconfig handles: setup the controller to interrupt, */
+/* then complete the housecleaning for full operation */
+
+static int
+dhu_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_attach_args *ua = aux;
+ register int n;
+
+ /* Reset controller to initialize, enable TX/RX interrupts */
+ /* to catch floating vector info elsewhere when completed */
+
+ bus_space_write_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR,
+ DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE);
+
+ /* Now wait up to 3 seconds for self-test to complete. */
+
+ for (n = 0; n < 300; n++) {
+ DELAY(10000);
+ if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) &
+ DHU_CSR_MASTER_RESET) == 0)
+ break;
+ }
+
+ /* If the RESET did not clear after 3 seconds, */
+ /* the controller must be broken. */
+
+ if (n >= 300)
+ return 0;
+
+ /* Check whether diagnostic run has signalled a failure. */
+
+ if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) &
+ DHU_CSR_DIAG_FAIL) != 0)
+ return 0;
+
+ return 1;
+}
+
+static void
+dhu_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ register struct dhu_softc *sc = (void *)self;
+ register struct uba_attach_args *ua = aux;
+ register unsigned c;
+ register int n, i;
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
+ /* Process the 8 bytes of diagnostic info put into */
+ /* the FIFO following the master reset operation. */
+
+ printf("\n%s:", self->dv_xname);
+ for (n = 0; n < 8; n++) {
+ c = DHU_READ_WORD(DHU_UBA_RBUF);
+
+ if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) {
+ if ((c&0200) == 0000)
+ printf(" rom(%d) version %d",
+ ((c>>1)&01), ((c>>2)&037));
+ else if (((c>>2)&07) != 0)
+ printf(" diag-error(proc%d)=%x",
+ ((c>>1)&01), ((c>>2)&07));
+ }
+ }
+
+ c = DHU_READ_WORD(DHU_UBA_STAT);
+
+ sc->sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV;
+ printf("\n%s: DH%s-11\n", self->dv_xname, (c & DHU_STAT_DHU)?"U":"V");
+
+ for (i = 0; i < sc->sc_type; i++) {
+ struct tty *tp;
+ tp = sc->sc_dhu[i].dhu_tty = ttymalloc();
+ sc->sc_dhu[i].dhu_state = STATE_IDLE;
+ bus_dmamap_create(sc->sc_dmat, tp->t_outq.c_cn, 1,
+ tp->t_outq.c_cn, 0, BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT,
+ &sc->sc_dhu[i].dhu_dmah);
+ bus_dmamap_load(sc->sc_dmat, sc->sc_dhu[i].dhu_dmah,
+ tp->t_outq.c_cs, tp->t_outq.c_cn, 0, BUS_DMA_NOWAIT);
+
+ }
+
+ /* Now establish RX & TX interrupt handlers */
+
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dhurint, sc);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, dhuxint, sc);
+}
+
+/* Receiver Interrupt */
+
+static void
+dhurint(arg)
+ void *arg;
+{
+ struct dhu_softc *sc = arg;
+ register struct tty *tp;
+ register int cc, line;
+ register unsigned c, delta;
+ int overrun = 0;
+
+ while ((c = DHU_READ_WORD(DHU_UBA_RBUF)) & DHU_RBUF_DATA_VALID) {
+
+ /* Ignore diagnostic FIFO entries. */
+
+ if ((c & DHU_DIAG_CODE) == DHU_DIAG_CODE)
+ continue;
+
+ cc = c & 0xFF;
+ line = DHU_LINE(c>>8);
+ tp = sc->sc_dhu[line].dhu_tty;
+
+ /* LINK.TYPE is set so we get modem control FIFO entries */
+
+ if ((c & DHU_DIAG_CODE) == DHU_MODEM_CODE) {
+ c = (c << 8);
+ /* Do MDMBUF flow control, wakeup sleeping opens */
+ if (c & DHU_STAT_DCD) {
+ if (!(tp->t_state & TS_CARR_ON))
+ (void)(*linesw[tp->t_line].l_modem)(tp, 1);
+ }
+ else if ((tp->t_state & TS_CARR_ON) &&
+ (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
+ (void) dhumctl(sc, line, 0, DMSET);
+
+ /* Do CRTSCTS flow control */
+ delta = c ^ sc->sc_dhu[line].dhu_modem;
+ sc->sc_dhu[line].dhu_modem = c;
+ if ((delta & DHU_STAT_CTS) &&
+ (tp->t_state & TS_ISOPEN) &&
+ (tp->t_cflag & CRTSCTS)) {
+ if (c & DHU_STAT_CTS) {
+ tp->t_state &= ~TS_TTSTOP;
+ ttstart(tp);
+ } else {
+ tp->t_state |= TS_TTSTOP;
+ dhustop(tp, 0);
+ }
+ }
+ continue;
+ }
+
+ if (!(tp->t_state & TS_ISOPEN)) {
+ wakeup((caddr_t)&tp->t_rawq);
+ continue;
+ }
+
+ if ((c & DHU_RBUF_OVERRUN_ERR) && overrun == 0) {
+ log(LOG_WARNING, "%s: silo overflow, line %d\n",
+ sc->sc_dev.dv_xname, line);
+ overrun = 1;
+ }
+ /* A BREAK key will appear as a NULL with a framing error */
+ if (c & DHU_RBUF_FRAMING_ERR)
+ cc |= TTY_FE;
+ if (c & DHU_RBUF_PARITY_ERR)
+ cc |= TTY_PE;
+
+ (*linesw[tp->t_line].l_rint)(cc, tp);
+ }
+}
+
+/* Transmitter Interrupt */
+
+static void
+dhuxint(arg)
+ void *arg;
+{
+ register struct dhu_softc *sc = arg;
+ register struct tty *tp;
+ register int line;
+
+ line = DHU_LINE(DHU_READ_BYTE(DHU_UBA_CSR_HI));
+
+ tp = sc->sc_dhu[line].dhu_tty;
+
+ tp->t_state &= ~TS_BUSY;
+ if (tp->t_state & TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
+ else {
+ if (sc->sc_dhu[line].dhu_state == STATE_DMA_STOPPED)
+ sc->sc_dhu[line].dhu_cc -=
+ DHU_READ_WORD(DHU_UBA_TBUFCNT);
+ ndflush(&tp->t_outq, sc->sc_dhu[line].dhu_cc);
+ sc->sc_dhu[line].dhu_cc = 0;
+ }
+
+ sc->sc_dhu[line].dhu_state = STATE_IDLE;
+
+ if (tp->t_line)
+ (*linesw[tp->t_line].l_start)(tp);
+ else
+ dhustart(tp);
+}
+
+int
+dhuopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ register struct tty *tp;
+ register int unit, line;
+ struct dhu_softc *sc;
+ int s, error = 0;
+
+ unit = DHU_M2U(minor(dev));
+ line = DHU_LINE(minor(dev));
+
+ if (unit >= dhu_cd.cd_ndevs || dhu_cd.cd_devs[unit] == NULL)
+ return (ENXIO);
+
+ sc = dhu_cd.cd_devs[unit];
+
+ if (line >= sc->sc_type)
+ return ENXIO;
+
+ s = spltty();
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
+ sc->sc_dhu[line].dhu_modem = DHU_READ_WORD(DHU_UBA_STAT);
+ (void) splx(s);
+
+ tp = sc->sc_dhu[line].dhu_tty;
+
+ tp->t_oproc = dhustart;
+ tp->t_param = dhuparam;
+ tp->t_hwiflow = dhuiflow;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ if (tp->t_ispeed == 0) {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ }
+ (void) dhuparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
+ return (EBUSY);
+ /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
+ if (dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS) & DML_DCD)
+ tp->t_state |= TS_CARR_ON;
+ s = spltty();
+ while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
+ !(tp->t_state & TS_CARR_ON)) {
+ error = ttysleep(tp, (caddr_t)&tp->t_rawq,
+ TTIPRI | PCATCH, ttopen, 0);
+ if (error)
+ break;
+ }
+ (void) splx(s);
+ if (error)
+ return (error);
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+/*ARGSUSED*/
+int
+dhuclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ register struct tty *tp;
+ register int unit, line;
+ struct dhu_softc *sc;
+
+ unit = DHU_M2U(minor(dev));
+ line = DHU_LINE(minor(dev));
+
+ sc = dhu_cd.cd_devs[unit];
+
+ tp = sc->sc_dhu[line].dhu_tty;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+
+ /* Make sure a BREAK state is not left enabled. */
+
+ (void) dhumctl(sc, line, DML_BRK, DMBIC);
+
+ /* Do a hangup if so required. */
+
+ if ((tp->t_cflag & HUPCL) || !(tp->t_state & TS_ISOPEN))
+ (void) dhumctl(sc, line, 0, DMSET);
+
+ return (ttyclose(tp));
+}
+
+int
+dhuread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct dhu_softc *sc;
+ register struct tty *tp;
+
+ sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
+
+ tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+dhuwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct dhu_softc *sc;
+ register struct tty *tp;
+
+ sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
+
+ tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+/*ARGSUSED*/
+int
+dhuioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ register struct dhu_softc *sc;
+ register struct tty *tp;
+ register int unit, line;
+ int error;
+
+ unit = DHU_M2U(minor(dev));
+ line = DHU_LINE(minor(dev));
+ sc = dhu_cd.cd_devs[unit];
+ tp = sc->sc_dhu[line].dhu_tty;
+
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+
+ switch (cmd) {
+
+ case TIOCSBRK:
+ (void) dhumctl(sc, line, DML_BRK, DMBIS);
+ break;
+
+ case TIOCCBRK:
+ (void) dhumctl(sc, line, DML_BRK, DMBIC);
+ break;
+
+ case TIOCSDTR:
+ (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS);
+ break;
+
+ case TIOCCDTR:
+ (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIC);
+ break;
+
+ case TIOCMSET:
+ (void) dhumctl(sc, line, *(int *)data, DMSET);
+ break;
+
+ case TIOCMBIS:
+ (void) dhumctl(sc, line, *(int *)data, DMBIS);
+ break;
+
+ case TIOCMBIC:
+ (void) dhumctl(sc, line, *(int *)data, DMBIC);
+ break;
+
+ case TIOCMGET:
+ *(int *)data = (dhumctl(sc, line, 0, DMGET) & ~DML_BRK);
+ break;
+
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+struct tty *
+dhutty(dev)
+ dev_t dev;
+{
+ struct dhu_softc *sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
+ struct tty *tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
+ return (tp);
+}
+
+/*ARGSUSED*/
+void
+dhustop(tp, flag)
+ register struct tty *tp;
+{
+ register struct dhu_softc *sc;
+ register int line;
+ int s;
+
+ s = spltty();
+
+ if (tp->t_state & TS_BUSY) {
+
+ sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
+ line = DHU_LINE(minor(tp->t_dev));
+
+ if (sc->sc_dhu[line].dhu_state == STATE_DMA_RUNNING) {
+
+ sc->sc_dhu[line].dhu_state = STATE_DMA_STOPPED;
+
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL,
+ DHU_READ_WORD(DHU_UBA_LNCTRL) |
+ DHU_LNCTRL_DMA_ABORT);
+ }
+
+ if (!(tp->t_state & TS_TTSTOP))
+ tp->t_state |= TS_FLUSH;
+ }
+ (void) splx(s);
+}
+
+static void
+dhustart(tp)
+ register struct tty *tp;
+{
+ register struct dhu_softc *sc;
+ register int line, cc;
+ register int addr;
+ int s;
+
+ s = spltty();
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ goto out;
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)&tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ if (tp->t_outq.c_cc == 0)
+ goto out;
+ cc = ndqb(&tp->t_outq, 0);
+ if (cc == 0)
+ goto out;
+
+ tp->t_state |= TS_BUSY;
+
+ sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
+
+ line = DHU_LINE(minor(tp->t_dev));
+
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
+
+ sc->sc_dhu[line].dhu_cc = cc;
+
+ if (cc == 1) {
+
+ sc->sc_dhu[line].dhu_state = STATE_TX_ONE_CHAR;
+
+ DHU_WRITE_WORD(DHU_UBA_TXCHAR,
+ DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf);
+
+ } else {
+
+ sc->sc_dhu[line].dhu_state = STATE_DMA_RUNNING;
+
+ addr = sc->sc_dhu[line].dhu_dmah->dm_segs[0].ds_addr +
+ (tp->t_outq.c_cf - tp->t_outq.c_cs);
+
+ DHU_WRITE_WORD(DHU_UBA_TBUFCNT, cc);
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD1, addr & 0xFFFF);
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD2, ((addr>>16) & 0x3F) |
+ DHU_TBUFAD2_TX_ENABLE);
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL,
+ DHU_READ_WORD(DHU_UBA_LNCTRL) & ~DHU_LNCTRL_DMA_ABORT);
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD2,
+ DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_DMA_START);
+ }
+out:
+ (void) splx(s);
+ return;
+}
+
+static int
+dhuparam(tp, t)
+ register struct tty *tp;
+ register struct termios *t;
+{
+ struct dhu_softc *sc;
+ register int cflag = t->c_cflag;
+ int ispeed = ttspeedtab(t->c_ispeed, dhuspeedtab);
+ int ospeed = ttspeedtab(t->c_ospeed, dhuspeedtab);
+ register unsigned lpr, lnctrl;
+ int unit, line;
+ int s;
+
+ unit = DHU_M2U(minor(tp->t_dev));
+ line = DHU_LINE(minor(tp->t_dev));
+
+ sc = dhu_cd.cd_devs[unit];
+
+ /* check requested parameters */
+ if (ospeed < 0 || ispeed < 0)
+ return (EINVAL);
+
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = cflag;
+
+ if (ospeed == 0) {
+ (void) dhumctl(sc, line, 0, DMSET); /* hang up line */
+ return (0);
+ }
+
+ s = spltty();
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
+
+ lpr = ((ispeed&017)<<8) | ((ospeed&017)<<12) ;
+
+ switch (cflag & CSIZE) {
+
+ case CS5:
+ lpr |= DHU_LPR_5_BIT_CHAR;
+ break;
+
+ case CS6:
+ lpr |= DHU_LPR_6_BIT_CHAR;
+ break;
+
+ case CS7:
+ lpr |= DHU_LPR_7_BIT_CHAR;
+ break;
+
+ default:
+ lpr |= DHU_LPR_8_BIT_CHAR;
+ break;
+ }
+
+ if (cflag & PARENB)
+ lpr |= DHU_LPR_PARENB;
+ if (!(cflag & PARODD))
+ lpr |= DHU_LPR_EPAR;
+ if (cflag & CSTOPB)
+ lpr |= DHU_LPR_2_STOP;
+
+ DHU_WRITE_WORD(DHU_UBA_LPR, lpr);
+
+ DHU_WRITE_WORD(DHU_UBA_TBUFAD2,
+ DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_TX_ENABLE);
+
+ lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL);
+
+ /* Setting LINK.TYPE enables modem signal change interrupts. */
+
+ lnctrl |= (DHU_LNCTRL_RX_ENABLE | DHU_LNCTRL_LINK_TYPE);
+
+ /* Enable the auto XON/XOFF feature on the controller */
+
+ if (t->c_iflag & IXON)
+ lnctrl |= DHU_LNCTRL_OAUTO;
+ else
+ lnctrl &= ~DHU_LNCTRL_OAUTO;
+
+ if (t->c_iflag & IXOFF)
+ lnctrl |= DHU_LNCTRL_IAUTO;
+ else
+ lnctrl &= ~DHU_LNCTRL_IAUTO;
+
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl);
+
+ (void) splx(s);
+ return (0);
+}
+
+static int
+dhuiflow(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+ register struct dhu_softc *sc;
+ register int line = DHU_LINE(minor(tp->t_dev));
+
+ if (tp->t_cflag & CRTSCTS) {
+ sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
+ (void) dhumctl(sc, line, DML_RTS, ((flag)? DMBIC: DMBIS));
+ return (1);
+ }
+ return (0);
+}
+
+static unsigned
+dhumctl(sc, line, bits, how)
+ struct dhu_softc *sc;
+ int line, bits, how;
+{
+ register unsigned status;
+ register unsigned lnctrl;
+ register unsigned mbits;
+ int s;
+
+ s = spltty();
+
+ DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
+
+ mbits = 0;
+
+ /* external signals as seen from the port */
+
+ status = DHU_READ_WORD(DHU_UBA_STAT);
+
+ if (status & DHU_STAT_CTS)
+ mbits |= DML_CTS;
+
+ if (status & DHU_STAT_DCD)
+ mbits |= DML_DCD;
+
+ if (status & DHU_STAT_DSR)
+ mbits |= DML_DSR;
+
+ if (status & DHU_STAT_RI)
+ mbits |= DML_RI;
+
+ /* internal signals/state delivered to port */
+
+ lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL);
+
+ if (lnctrl & DHU_LNCTRL_RTS)
+ mbits |= DML_RTS;
+
+ if (lnctrl & DHU_LNCTRL_DTR)
+ mbits |= DML_DTR;
+
+ if (lnctrl & DHU_LNCTRL_BREAK)
+ mbits |= DML_BRK;
+
+ switch (how) {
+
+ case DMSET:
+ mbits = bits;
+ break;
+
+ case DMBIS:
+ mbits |= bits;
+ break;
+
+ case DMBIC:
+ mbits &= ~bits;
+ break;
+
+ case DMGET:
+ (void) splx(s);
+ return (mbits);
+ }
+
+ if (mbits & DML_RTS)
+ lnctrl |= DHU_LNCTRL_RTS;
+ else
+ lnctrl &= ~DHU_LNCTRL_RTS;
+
+ if (mbits & DML_DTR)
+ lnctrl |= DHU_LNCTRL_DTR;
+ else
+ lnctrl &= ~DHU_LNCTRL_DTR;
+
+ if (mbits & DML_BRK)
+ lnctrl |= DHU_LNCTRL_BREAK;
+ else
+ lnctrl &= ~DHU_LNCTRL_BREAK;
+
+ DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl);
+
+ (void) splx(s);
+ return (mbits);
+}
--- /dev/null
+/* $OpenBSD: dhureg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dhureg.h,v 1.4 1999/05/28 20:17:29 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ken C. Wellsch. 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.
+ */
+
+#ifdef notdef
+union w_b
+{
+ u_short word;
+ struct {
+ u_char byte_lo;
+ u_char byte_hi;
+ } bytes;
+};
+
+struct DHUregs
+{
+ volatile union w_b u_csr; /* Control/Status Register (R/W) */
+ volatile u_short dhu_rbuf; /* Receive Buffer (R only) */
+#define dhu_txchar dhu_rbuf /* Transmit Character (W only) */
+ volatile u_short dhu_lpr; /* Line Parameter Register (R/W) */
+ volatile u_short dhu_stat; /* Line Status (R only) */
+ volatile u_short dhu_lnctrl; /* Line Control (R/W) */
+ volatile u_short dhu_tbufad1; /* Transmit Buffer Address 1 (R/W) */
+ volatile u_short dhu_tbufad2; /* Transmit Buffer Address 2 (R/W) */
+ volatile u_short dhu_tbufcnt; /* Transmit Buffer Count (R/W) */
+};
+
+#define dhu_csr u_csr.word
+#define dhu_csr_lo u_csr.bytes.byte_lo
+#define dhu_csr_hi u_csr.bytes.byte_hi
+
+typedef struct DHUregs dhuregs;
+#endif
+
+#define DHU_UBA_CSR 0
+#define DHU_UBA_CSR_HI 1
+#define DHU_UBA_RBUF 2
+#define DHU_UBA_TXCHAR 2
+#define DHU_UBA_LPR 4
+#define DHU_UBA_STAT 6
+#define DHU_UBA_LNCTRL 8
+#define DHU_UBA_TBUFAD1 10
+#define DHU_UBA_TBUFAD2 12
+#define DHU_UBA_TBUFCNT 14
+
+/* CSR bits */
+
+#define DHU_CSR_TX_ACTION 0100000
+#define DHU_CSR_TXIE 0040000
+#define DHU_CSR_DIAG_FAIL 0020000
+#define DHU_CSR_TX_DMA_ERROR 0010000
+#define DHU_CSR_TX_LINE_MASK 0007400
+#define DHU_CSR_RX_DATA_AVAIL 0000200
+#define DHU_CSR_RXIE 0000100
+#define DHU_CSR_MASTER_RESET 0000040
+#define DHU_CSR_UNUSED 0000020
+#define DHU_CSR_CHANNEL_MASK 0000017
+
+/* RBUF bits */
+
+#define DHU_RBUF_DATA_VALID 0100000
+#define DHU_RBUF_OVERRUN_ERR 0040000
+#define DHU_RBUF_FRAMING_ERR 0020000
+#define DHU_RBUF_PARITY_ERR 0010000
+#define DHU_RBUF_RX_LINE_MASK 0007400
+
+#define DHU_DIAG_CODE 0070001
+#define DHU_MODEM_CODE 0070000
+
+/* TXCHAR bits */
+
+#define DHU_TXCHAR_DATA_VALID 0100000
+
+/* LPR bits */
+
+#define DHU_LPR_B50 0x0
+#define DHU_LPR_B75 0x1
+#define DHU_LPR_B110 0x2
+#define DHU_LPR_B134 0x3
+#define DHU_LPR_B150 0x4
+#define DHU_LPR_B300 0x5
+#define DHU_LPR_B600 0x6
+#define DHU_LPR_B1200 0x7
+#define DHU_LPR_B1800 0x8
+#define DHU_LPR_B2000 0x9
+#define DHU_LPR_B2400 0xA
+#define DHU_LPR_B4800 0xB
+#define DHU_LPR_B7200 0xC
+#define DHU_LPR_B9600 0xD
+#define DHU_LPR_B19200 0xE
+#define DHU_LPR_B38400 0xF
+
+#define DHU_LPR_5_BIT_CHAR 0000000
+#define DHU_LPR_6_BIT_CHAR 0000010
+#define DHU_LPR_7_BIT_CHAR 0000020
+#define DHU_LPR_8_BIT_CHAR 0000030
+#define DHU_LPR_PARENB 0000040
+#define DHU_LPR_EPAR 0000100
+#define DHU_LPR_2_STOP 0000200
+
+/* STAT bits */
+
+#define DHU_STAT_DSR 0100000
+#define DHU_STAT_RI 0020000
+#define DHU_STAT_DCD 0010000
+#define DHU_STAT_CTS 0004000
+#define DHU_STAT_DHU 0000400
+
+/* LNCTRL bits */
+
+#define DHU_LNCTRL_DMA_ABORT 0000001
+#define DHU_LNCTRL_IAUTO 0000002
+#define DHU_LNCTRL_RX_ENABLE 0000004
+#define DHU_LNCTRL_BREAK 0000010
+#define DHU_LNCTRL_OAUTO 0000020
+#define DHU_LNCTRL_FORCE_XOFF 0000040
+#define DHU_LNCTRL_LINK_TYPE 0000400
+#define DHU_LNCTRL_DTR 0001000
+#define DHU_LNCTRL_RTS 0010000
+
+/* TBUFAD2 bits */
+
+#define DHU_TBUFAD2_DMA_START 0000200
+#define DHU_TBUFAD2_TX_ENABLE 0100000
--- /dev/null
+/* $OpenBSD: dl.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dl.c,v 1.11 2000/01/24 02:40:29 matt Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Copyright (c) 1997 Ben Harris. All rights reserved.
+ * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
+ * Copyright (c) 1982, 1986, 1990, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ */
+
+/*
+ * dl.c -- Device driver for the DL11 and DLV11 serial cards.
+ *
+ * OS-interface code derived from the dz and dca (hp300) drivers.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/scb.h>
+
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/qbus/dlreg.h>
+
+struct dl_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ struct tty *sc_tty;
+};
+
+static int dl_match __P((struct device *, struct cfdata *, void *));
+static void dl_attach __P((struct device *, struct device *, void *));
+static void dlrint __P((void *));
+static void dlxint __P((void *));
+static void dlstart __P((struct tty *));
+static int dlparam __P((struct tty *, struct termios *));
+static void dlbrk __P((struct dl_softc *, int));
+struct tty * dltty __P((dev_t));
+ int dlopen __P((dev_t, int, int, struct proc *));
+ int dlclose __P((dev_t, int, int, struct proc *));
+ int dlread __P((dev_t, struct uio *, int));
+ int dlwrite __P((dev_t, struct uio *, int));
+ int dlioctl __P((dev_t, int, caddr_t, int, struct proc *));
+ void dlstop __P((struct tty *, int));
+
+struct cfattach dl_ca = {
+ sizeof(struct dl_softc), (cfmatch_t)dl_match, dl_attach
+};
+
+struct cfdriver dl_cd = {
+ NULL, "dl", DV_TTY
+};
+
+#define DL_READ_WORD(reg) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
+#define DL_WRITE_WORD(reg, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
+#define DL_WRITE_BYTE(reg, val) \
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
+
+/* Autoconfig handles: setup the controller to interrupt, */
+/* then complete the housecleaning for full operation */
+
+static int
+dl_match (parent, cf, aux)
+ struct device * parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_attach_args *ua = aux;
+
+#ifdef DL_DEBUG
+ printf("Probing for dl at %lo ... ", (long)ua->ua_iaddr);
+#endif
+
+ bus_space_write_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR, DL_XCSR_TXIE);
+ if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
+ (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
+#ifdef DL_DEBUG
+ printf("failed (step 1; XCSR = %.4b)\n",
+ bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
+ DL_XCSR_BITS);
+#endif
+ return 0;
+ }
+
+ /*
+ * We have to force an interrupt so the uba driver can work
+ * out where we are. Unfortunately, the only way to make a
+ * DL11 interrupt is to get it to send or receive a
+ * character. We'll send a NUL and hope it doesn't hurt
+ * anything.
+ */
+
+ bus_space_write_1(ua->ua_iot, ua->ua_ioh, DL_UBA_XBUFL, '\0');
+#if 0 /* This test seems to fail 2/3 of the time :-( */
+ if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) {
+#ifdef DL_DEBUG
+ printf("failed (step 2; XCSR = %.4b)\n", dladdr->dl_xcsr,
+ DL_XCSR_BITS);
+#endif
+ return 0;
+ }
+#endif
+ DELAY(100000); /* delay 1/10 s for character to transmit */
+ if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
+ (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
+#ifdef DL_DEBUG
+ printf("failed (step 3; XCSR = %.4b)\n",
+ bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
+ DL_XCSR_BITS);
+#endif
+ return 0;
+ }
+
+
+ /* What else do I need to do? */
+
+ return 1;
+
+}
+
+static void
+dl_attach (parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct dl_softc *sc = (void *)self;
+ register struct uba_attach_args *ua = aux;
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+
+ /* Tidy up the device */
+
+ DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE);
+ DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE);
+
+ /* Initialize our softc structure. Should be done in open? */
+
+ sc->sc_tty = ttymalloc();
+ tty_attach(sc->sc_tty);
+
+ /* Now register the TX & RX interrupt handlers */
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dlxint, sc);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dlrint, sc);
+
+ printf("\n");
+}
+
+/* Receiver Interrupt Handler */
+
+static void
+dlrint(arg)
+ void *arg;
+{
+ struct dl_softc *sc = arg;
+ register struct tty *tp;
+ register int cc;
+ register unsigned c;
+
+ if (DL_READ_WORD(DL_UBA_RCSR) & DL_RCSR_RX_DONE) {
+ c = DL_READ_WORD(DL_UBA_RBUF);
+ cc = c & 0xFF;
+ tp = sc->sc_tty;
+
+ if (!(tp->t_state & TS_ISOPEN)) {
+ wakeup((caddr_t)&tp->t_rawq);
+ return;
+ }
+
+ if (c & DL_RBUF_OVERRUN_ERR)
+ /*
+ * XXX: This should really be logged somwhere
+ * else where we can afford the time.
+ */
+ log(LOG_WARNING, "%s: rx overrun\n",
+ sc->sc_dev.dv_xname);
+ if (c & DL_RBUF_FRAMING_ERR)
+ cc |= TTY_FE;
+ if (c & DL_RBUF_PARITY_ERR)
+ cc |= TTY_PE;
+
+ (*linesw[tp->t_line].l_rint)(cc, tp);
+ } else
+ log(LOG_WARNING, "%s: stray rx interrupt\n",
+ sc->sc_dev.dv_xname);
+ return;
+}
+
+/* Transmitter Interrupt Handler */
+
+static void
+dlxint(arg)
+ void *arg;
+{
+ struct dl_softc *sc = arg;
+ register struct tty *tp;
+
+ tp = sc->sc_tty;
+ tp->t_state &= ~(TS_BUSY | TS_FLUSH);
+ if (tp->t_line)
+ (*linesw[tp->t_line].l_start)(tp);
+ else
+ dlstart(tp);
+
+ return;
+}
+
+int
+dlopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ register struct tty *tp;
+ register int unit;
+ struct dl_softc *sc;
+
+ unit = minor(dev);
+
+ if (unit >= dl_cd.cd_ndevs || dl_cd.cd_devs[unit] == NULL)
+ return ENXIO;
+ sc = dl_cd.cd_devs[unit];
+
+ tp = sc->sc_tty;
+ if (tp == NULL)
+ return ENODEV;
+ tp->t_oproc = dlstart;
+ tp->t_param = dlparam;
+ tp->t_dev = dev;
+
+ if (!(tp->t_state & TS_ISOPEN)) {
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ /* No modem control, so set CLOCAL. */
+ tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+
+ dlparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
+ return EBUSY;
+
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+/*ARGSUSED*/
+int
+dlclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct dl_softc *sc;
+ register struct tty *tp;
+ register int unit;
+
+ unit = minor(dev);
+ sc = dl_cd.cd_devs[unit];
+ tp = sc->sc_tty;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+
+ /* Make sure a BREAK state is not left enabled. */
+ dlbrk(sc, 0);
+
+ return (ttyclose(tp));
+}
+
+int
+dlread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ register struct tty *tp;
+ struct dl_softc *sc;
+ register int unit;
+
+ unit = minor(dev);
+ sc = dl_cd.cd_devs[unit];
+ tp = sc->sc_tty;
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+dlwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ register struct tty *tp;
+ struct dl_softc *sc;
+ register int unit;
+
+ unit = minor(dev);
+ sc = dl_cd.cd_devs[unit];
+ tp = sc->sc_tty;
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+int
+dlioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct dl_softc *sc;
+ register struct tty *tp;
+ register int unit;
+ int error;
+
+ unit = minor(dev);
+ sc = dl_cd.cd_devs[unit];
+ tp = sc->sc_tty;
+
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+
+ switch (cmd) {
+
+ case TIOCSBRK:
+ dlbrk(sc, 1);
+ break;
+
+ case TIOCCBRK:
+ dlbrk(sc, 0);
+ break;
+
+ case TIOCMGET:
+ /* No modem control, assume they're all low. */
+ *(int *)data = 0;
+ break;
+
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+struct tty *
+dltty(dev)
+ dev_t dev;
+{
+ register struct dl_softc* sc;
+
+ sc = dl_cd.cd_devs[minor(dev)];
+ return sc->sc_tty;
+}
+
+void
+dlstop(tp, flag)
+ register struct tty *tp;
+ int flag;
+{
+ register struct dl_softc *sc;
+ int unit, s;
+
+ unit = minor(tp->t_dev);
+ sc = dl_cd.cd_devs[unit];
+
+ s = spltty();
+
+ if (tp->t_state & TS_BUSY)
+ if (!(tp->t_state & TS_TTSTOP))
+ tp->t_state |= TS_FLUSH;
+ splx(s);
+}
+
+static void
+dlstart(tp)
+ register struct tty *tp;
+{
+ register struct dl_softc *sc;
+ register int unit;
+ int s;
+
+ unit = minor(tp->t_dev);
+ sc = dl_cd.cd_devs[unit];
+
+ s = spltty();
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ goto out;
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)&tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ if (tp->t_outq.c_cc == 0)
+ goto out;
+
+
+ if (DL_READ_WORD(DL_UBA_XCSR) & DL_XCSR_TX_READY) {
+ tp->t_state |= TS_BUSY;
+ DL_WRITE_BYTE(DL_UBA_XBUFL, getc(&tp->t_outq));
+ }
+out:
+ splx(s);
+ return;
+}
+
+/*ARGSUSED*/
+static int
+dlparam(tp, t)
+ register struct tty *tp;
+ register struct termios *t;
+{
+ /*
+ * All this kind of stuff (speed, character format, whatever)
+ * is set by jumpers on the card. Changing it is thus rather
+ * tricky for a mere device driver.
+ */
+ return 0;
+}
+
+static void
+dlbrk(sc, state)
+ register struct dl_softc *sc;
+ int state;
+{
+ int s = spltty();
+
+ if (state) {
+ DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) |
+ DL_XCSR_TX_BREAK);
+ } else {
+ DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) &
+ ~DL_XCSR_TX_BREAK);
+ }
+ splx(s);
+}
--- /dev/null
+/* $OpenBSD: dlreg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dlreg.h,v 1.3 1999/05/27 16:02:04 ragge Exp $ */
+/*
+ * Copyright (c) 1997 Ben Harris. 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 Ben Harris.
+ * 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.
+ */
+
+/*
+ * dlreg.h -- Definitions for the DL11 and DLV11 serial cards.
+ *
+ * Style in imitation of dzreg.h.
+ */
+
+#ifdef notdef
+union w_b
+{
+ u_short word;
+ struct {
+ u_char byte_lo;
+ u_char byte_hi;
+ } bytes;
+};
+
+struct DLregs
+{
+ volatile u_short dl_rcsr; /* Receive Control/Status Register (R/W) */
+ volatile u_short dl_rbuf; /* Receive Buffer (R) */
+ volatile u_short dl_xcsr; /* Transmit Control/Status Register (R/W) */
+ volatile union w_b u_xbuf; /* Transmit Buffer (W) */
+#define dl_xbuf u_xbuf.bytes.byte_lo
+};
+
+typedef struct DLregs dlregs;
+#endif
+
+#define DL_UBA_RCSR 0
+#define DL_UBA_RBUF 2
+#define DL_UBA_XCSR 4
+#define DL_UBA_XBUFL 6
+
+/* RCSR bits */
+
+#define DL_RCSR_RX_DONE 0x0080 /* Receiver Done (R) */
+#define DL_RCSR_RXIE 0x0040 /* Receiver Interrupt Enable (R/W) */
+#define DL_RCSR_READER_ENABLE 0x0001 /* [paper-tape] Reader Enable (W) */
+#define DL_RCSR_BITS "\20\1READER_ENABLE\7RXIE\10RX_DONE\n"
+
+/* RBUF bits */
+
+#define DL_RBUF_ERR 0x8000 /* Error (R) */
+#define DL_RBUF_OVERRUN_ERR 0x4000 /* Overrun Error (R) */
+#define DL_RBUF_FRAMING_ERR 0x2000 /* Framing Error (R) */
+#define DL_RBUF_PARITY_ERR 0x1000 /* Parity Error (R) */
+#define DL_RBUF_DATA_MASK 0x00FF /* Receive Data (R) */
+#define DL_RBUF_BITS "\20\15PARITY_ERR\16FRAMING_ERR\17OVERRUN_ERR\20ERR\n"
+
+/* XCSR bits */
+
+#define DL_XCSR_TX_READY 0x0080 /* Transmitter Ready (R) */
+#define DL_XCSR_TXIE 0x0040 /* Transmit Interrupt Enable (R/W) */
+#define DL_XCSR_TX_BREAK 0x0001 /* Transmit Break (R/W) */
+#define DL_XCSR_BITS "\20\1TX_BREAK\7TXIE\10TX_READY\n"
+
+/* XBUF is just data byte right justified. */
--- /dev/null
+/* $OpenBSD: dz.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dz.c,v 1.19 2000/01/24 02:40:29 matt Exp $ */
+/*
+ * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#ifdef DDB
+#include <dev/cons.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/pte.h>
+#include <machine/trap.h>
+#include <machine/cpu.h>
+
+#include <arch/vax/qbus/dzreg.h>
+#include <arch/vax/qbus/dzvar.h>
+
+#define DZ_READ_BYTE(adr) \
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
+#define DZ_READ_WORD(adr) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
+#define DZ_WRITE_BYTE(adr, val) \
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
+#define DZ_WRITE_WORD(adr, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
+
+/* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */
+
+#define NDZLINE 8
+
+#define DZ_C2I(c) ((c)<<3) /* convert controller # to index */
+#define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */
+#define DZ_PORT(u) ((u)&07) /* extract the port # */
+
+/* Flags used to monitor modem bits, make them understood outside driver */
+
+#define DML_DTR TIOCM_DTR
+#define DML_DCD TIOCM_CD
+#define DML_RI TIOCM_RI
+#define DML_BRK 0100000 /* no equivalent, we will mask */
+
+static struct speedtab dzspeedtab[] =
+{
+ { 0, 0 },
+ { 50, DZ_LPR_B50 },
+ { 75, DZ_LPR_B75 },
+ { 110, DZ_LPR_B110 },
+ { 134, DZ_LPR_B134 },
+ { 150, DZ_LPR_B150 },
+ { 300, DZ_LPR_B300 },
+ { 600, DZ_LPR_B600 },
+ { 1200, DZ_LPR_B1200 },
+ { 1800, DZ_LPR_B1800 },
+ { 2000, DZ_LPR_B2000 },
+ { 2400, DZ_LPR_B2400 },
+ { 3600, DZ_LPR_B3600 },
+ { 4800, DZ_LPR_B4800 },
+ { 7200, DZ_LPR_B7200 },
+ { 9600, DZ_LPR_B9600 },
+ { 19200, DZ_LPR_B19200 },
+ { -1, -1 }
+};
+
+static void dzstart __P((struct tty *));
+static int dzparam __P((struct tty *, struct termios *));
+static unsigned dzmctl __P((struct dz_softc *, int, int, int));
+static void dzscan __P((void *));
+
+struct cfdriver dz_cd = {
+ NULL, "dz", DV_TTY
+};
+
+cdev_decl(dz);
+
+/*
+ * The DZ series doesn't interrupt on carrier transitions,
+ * so we have to use a timer to watch it.
+ */
+int dz_timer = 0; /* true if timer started */
+
+#define DZ_DZ 8 /* Unibus DZ-11 board linecount */
+#define DZ_DZV 4 /* Q-bus DZV-11 or DZQ-11 */
+
+void
+dzattach(sc)
+ struct dz_softc *sc;
+{
+ register int n;
+
+ sc->sc_rxint = sc->sc_brk = 0;
+
+ sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
+ DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
+ DZ_WRITE_BYTE(dr_dtr, 0);
+ DZ_WRITE_BYTE(dr_break, 0);
+
+ /* Initialize our softc structure. Should be done in open? */
+
+ for (n = 0; n < sc->sc_type; n++)
+ sc->sc_dz[n].dz_tty = ttymalloc();
+
+ /* Alas no interrupt on modem bit changes, so we manually scan */
+
+ if (dz_timer == 0) {
+ dz_timer = 1;
+ timeout(dzscan, (void *)0, hz);
+ }
+ printf("\n");
+ return;
+}
+
+/* Receiver Interrupt */
+
+void
+dzrint(arg)
+ void *arg;
+{
+ struct dz_softc *sc = arg;
+ register struct tty *tp;
+ register int cc, line;
+ register unsigned c;
+ int overrun = 0;
+
+ sc->sc_rxint++;
+
+ while ((c = DZ_READ_WORD(dr_rbuf)) & DZ_RBUF_DATA_VALID) {
+ cc = c & 0xFF;
+ line = DZ_PORT(c>>8);
+ tp = sc->sc_dz[line].dz_tty;
+
+ /* Must be caught early */
+ if (sc->sc_catch && (*sc->sc_catch)(line, cc))
+ continue;
+
+ if (!(tp->t_state & TS_ISOPEN)) {
+ wakeup((caddr_t)&tp->t_rawq);
+ continue;
+ }
+
+ if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
+ log(LOG_WARNING, "%s: silo overflow, line %d\n",
+ sc->sc_dev.dv_xname, line);
+ overrun = 1;
+ }
+
+ /* A BREAK key will appear as a NULL with a framing error */
+ if (c & DZ_RBUF_FRAMING_ERR)
+ cc |= TTY_FE;
+ if (c & DZ_RBUF_PARITY_ERR)
+ cc |= TTY_PE;
+
+#if defined(DDB) && (defined(VAX410) || defined(VAX43) || defined(VAX46))
+ if (tp->t_dev == cn_tab->cn_dev) {
+ int j = kdbrint(cc);
+
+ if (j == 1) /* Escape received, just return */
+ continue;
+
+ if (j == 2) /* Second char wasn't 'D' */
+ (*linesw[tp->t_line].l_rint)(27, tp);
+ }
+#endif
+ (*linesw[tp->t_line].l_rint)(cc, tp);
+ }
+}
+
+/* Transmitter Interrupt */
+
+void
+dzxint(arg)
+ void *arg;
+{
+ register struct dz_softc *sc = arg;
+ register struct tty *tp;
+ register struct clist *cl;
+ register int line, ch, csr;
+ u_char tcr;
+
+ /*
+ * Switch to POLLED mode.
+ * Some simple measurements indicated that even on
+ * one port, by freeing the scanner in the controller
+ * by either providing a character or turning off
+ * the port when output is complete, the transmitter
+ * was ready to accept more output when polled again.
+ * With just two ports running the game "worms,"
+ * almost every interrupt serviced both transmitters!
+ * Each UART is double buffered, so if the scanner
+ * is quick enough and timing works out, we can even
+ * feed the same port twice.
+ *
+ * Ragge 980517:
+ * Do not need to turn off interrupts, already at interrupt level.
+ * Remove the pdma stuff; no great need of it right now.
+ */
+
+ while (((csr = DZ_READ_WORD(dr_csr)) & DZ_CSR_TX_READY) != 0) {
+
+ line = DZ_PORT(csr>>8);
+
+ tp = sc->sc_dz[line].dz_tty;
+ cl = &tp->t_outq;
+ tp->t_state &= ~TS_BUSY;
+
+ /* Just send out a char if we have one */
+ /* As long as we can fill the chip buffer, we just loop here */
+ if (cl->c_cc) {
+ tp->t_state |= TS_BUSY;
+ ch = getc(cl);
+ DZ_WRITE_BYTE(dr_tbuf, ch);
+ continue;
+ }
+ /* Nothing to send; clear the scan bit */
+ /* Clear xmit scanner bit; dzstart may set it again */
+ tcr = DZ_READ_WORD(dr_tcrw);
+ tcr &= 255;
+ tcr &= ~(1 << line);
+ DZ_WRITE_BYTE(dr_tcr, tcr);
+
+ if (tp->t_state & TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
+ else
+ ndflush (&tp->t_outq, cl->c_cc);
+
+ if (tp->t_line)
+ (*linesw[tp->t_line].l_start)(tp);
+ else
+ dzstart(tp);
+ }
+}
+
+int
+dzopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ register struct tty *tp;
+ register int unit, line;
+ struct dz_softc *sc;
+ int s, error = 0;
+
+ unit = DZ_I2C(minor(dev));
+ line = DZ_PORT(minor(dev));
+ if (unit >= dz_cd.cd_ndevs || dz_cd.cd_devs[unit] == NULL)
+ return (ENXIO);
+
+ sc = dz_cd.cd_devs[unit];
+
+ if (line >= sc->sc_type)
+ return ENXIO;
+
+ tp = sc->sc_dz[line].dz_tty;
+ if (tp == NULL)
+ return (ENODEV);
+ tp->t_oproc = dzstart;
+ tp->t_param = dzparam;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ if (tp->t_ispeed == 0) {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ }
+ (void) dzparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
+ return (EBUSY);
+ /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
+ if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
+ tp->t_state |= TS_CARR_ON;
+ s = spltty();
+ while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
+ !(tp->t_state & TS_CARR_ON)) {
+ error = ttysleep(tp, (caddr_t)&tp->t_rawq,
+ TTIPRI | PCATCH, ttopen, 0);
+ if (error)
+ break;
+ }
+ (void) splx(s);
+ if (error)
+ return (error);
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+/*ARGSUSED*/
+int
+dzclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct dz_softc *sc;
+ register struct tty *tp;
+ register int unit, line;
+
+
+ unit = DZ_I2C(minor(dev));
+ line = DZ_PORT(minor(dev));
+ sc = dz_cd.cd_devs[unit];
+
+ tp = sc->sc_dz[line].dz_tty;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+
+ /* Make sure a BREAK state is not left enabled. */
+ (void) dzmctl(sc, line, DML_BRK, DMBIC);
+
+ /* Do a hangup if so required. */
+ if ((tp->t_cflag & HUPCL) || !(tp->t_state & TS_ISOPEN))
+ (void) dzmctl(sc, line, 0, DMSET);
+
+ return (ttyclose(tp));
+}
+
+int
+dzread (dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct tty *tp;
+ struct dz_softc *sc;
+
+ sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
+
+ tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+dzwrite (dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct tty *tp;
+ struct dz_softc *sc;
+
+ sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
+
+ tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+/*ARGSUSED*/
+int
+dzioctl (dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct dz_softc *sc;
+ register struct tty *tp;
+ register int unit, line;
+ int error;
+
+ unit = DZ_I2C(minor(dev));
+ line = DZ_PORT(minor(dev));
+ sc = dz_cd.cd_devs[unit];
+ tp = sc->sc_dz[line].dz_tty;
+
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return (error);
+
+ switch (cmd) {
+
+ case TIOCSBRK:
+ (void) dzmctl(sc, line, DML_BRK, DMBIS);
+ break;
+
+ case TIOCCBRK:
+ (void) dzmctl(sc, line, DML_BRK, DMBIC);
+ break;
+
+ case TIOCSDTR:
+ (void) dzmctl(sc, line, DML_DTR, DMBIS);
+ break;
+
+ case TIOCCDTR:
+ (void) dzmctl(sc, line, DML_DTR, DMBIC);
+ break;
+
+ case TIOCMSET:
+ (void) dzmctl(sc, line, *(int *)data, DMSET);
+ break;
+
+ case TIOCMBIS:
+ (void) dzmctl(sc, line, *(int *)data, DMBIS);
+ break;
+
+ case TIOCMBIC:
+ (void) dzmctl(sc, line, *(int *)data, DMBIC);
+ break;
+
+ case TIOCMGET:
+ *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
+ break;
+
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+struct tty *
+dztty (dev)
+ dev_t dev;
+{
+ struct dz_softc *sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
+ struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
+
+ return (tp);
+}
+
+/*ARGSUSED*/
+int
+dzstop(tp, flag)
+ register struct tty *tp;
+{
+ if (tp->t_state & TS_BUSY)
+ if (!(tp->t_state & TS_TTSTOP))
+ tp->t_state |= TS_FLUSH;
+}
+
+void
+dzstart(tp)
+ register struct tty *tp;
+{
+ register struct dz_softc *sc;
+ register struct clist *cl;
+ register int unit, line, s;
+ char state;
+
+ unit = DZ_I2C(minor(tp->t_dev));
+ line = DZ_PORT(minor(tp->t_dev));
+ sc = dz_cd.cd_devs[unit];
+
+ s = spltty();
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ return;
+ cl = &tp->t_outq;
+ if (cl->c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)cl);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ if (cl->c_cc == 0)
+ return;
+
+ tp->t_state |= TS_BUSY;
+
+ state = DZ_READ_WORD(dr_tcrw) & 255;
+ if ((state & (1 << line)) == 0) {
+ DZ_WRITE_BYTE(dr_tcr, state | (1 << line));
+ }
+ dzxint(sc);
+ splx(s);
+}
+
+static int
+dzparam(tp, t)
+ register struct tty *tp;
+ register struct termios *t;
+{
+ struct dz_softc *sc;
+ register int cflag = t->c_cflag;
+ int unit, line;
+ int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
+ int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
+ register unsigned lpr;
+ int s;
+
+ unit = DZ_I2C(minor(tp->t_dev));
+ line = DZ_PORT(minor(tp->t_dev));
+ sc = dz_cd.cd_devs[unit];
+
+ /* check requested parameters */
+ if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
+ return (EINVAL);
+
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = cflag;
+
+ if (ospeed == 0) {
+ (void) dzmctl(sc, line, 0, DMSET); /* hang up line */
+ return (0);
+ }
+
+ s = spltty();
+
+ lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
+
+ switch (cflag & CSIZE)
+ {
+ case CS5:
+ lpr |= DZ_LPR_5_BIT_CHAR;
+ break;
+ case CS6:
+ lpr |= DZ_LPR_6_BIT_CHAR;
+ break;
+ case CS7:
+ lpr |= DZ_LPR_7_BIT_CHAR;
+ break;
+ default:
+ lpr |= DZ_LPR_8_BIT_CHAR;
+ break;
+ }
+ if (cflag & PARENB)
+ lpr |= DZ_LPR_PARENB;
+ if (cflag & PARODD)
+ lpr |= DZ_LPR_OPAR;
+ if (cflag & CSTOPB)
+ lpr |= DZ_LPR_2_STOP;
+
+ DZ_WRITE_WORD(dr_lpr, lpr);
+
+ (void) splx(s);
+ return (0);
+}
+
+static unsigned
+dzmctl(sc, line, bits, how)
+ register struct dz_softc *sc;
+ int line, bits, how;
+{
+ register unsigned status;
+ register unsigned mbits;
+ register unsigned bit;
+ int s;
+
+ s = spltty();
+
+ mbits = 0;
+
+ bit = (1 << line);
+
+ /* external signals as seen from the port */
+
+ status = DZ_READ_BYTE(dr_dcd) | sc->sc_dsr;
+
+ if (status & bit)
+ mbits |= DML_DCD;
+
+ status = DZ_READ_BYTE(dr_ring);
+
+ if (status & bit)
+ mbits |= DML_RI;
+
+ /* internal signals/state delivered to port */
+
+ status = DZ_READ_BYTE(dr_dtr);
+
+ if (status & bit)
+ mbits |= DML_DTR;
+
+ if (sc->sc_brk & bit)
+ mbits |= DML_BRK;
+
+ switch (how)
+ {
+ case DMSET:
+ mbits = bits;
+ break;
+
+ case DMBIS:
+ mbits |= bits;
+ break;
+
+ case DMBIC:
+ mbits &= ~bits;
+ break;
+
+ case DMGET:
+ (void) splx(s);
+ return (mbits);
+ }
+
+ if (mbits & DML_DTR) {
+ DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) | bit);
+ } else {
+ DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) & ~bit);
+ }
+
+ if (mbits & DML_BRK) {
+ sc->sc_brk |= bit;
+ DZ_WRITE_BYTE(dr_break, sc->sc_brk);
+ } else {
+ sc->sc_brk &= ~bit;
+ DZ_WRITE_BYTE(dr_break, sc->sc_brk);
+ }
+
+ (void) splx(s);
+ return (mbits);
+}
+
+/*
+ * This is called by timeout() periodically.
+ * Check to see if modem status bits have changed.
+ */
+static void
+dzscan(arg)
+ void *arg;
+{
+ register struct dz_softc *sc;
+ register struct tty *tp;
+ register int n, bit, port;
+ unsigned csr;
+ int s;
+
+ s = spltty();
+
+ for (n = 0; n < dz_cd.cd_ndevs; n++) {
+
+ if (dz_cd.cd_devs[n] == NULL)
+ continue;
+
+ sc = dz_cd.cd_devs[n];
+
+ for (port = 0; port < sc->sc_type; port++) {
+
+ tp = sc->sc_dz[port].dz_tty;
+ bit = (1 << port);
+
+ if ((DZ_READ_BYTE(dr_dcd) | sc->sc_dsr) & bit) {
+ if (!(tp->t_state & TS_CARR_ON))
+ (*linesw[tp->t_line].l_modem) (tp, 1);
+ } else if ((tp->t_state & TS_CARR_ON) &&
+ (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+ DZ_WRITE_BYTE(dr_tcr,
+ (DZ_READ_WORD(dr_tcrw) & 255) & ~bit);
+ }
+ }
+
+ /*
+ * If the RX interrupt rate is this high, switch
+ * the controller to Silo Alarm - which means don't
+ * interrupt until the RX silo has 16 characters in
+ * it (the silo is 64 characters in all).
+ * Avoid oscillating SA on and off by not turning
+ * if off unless the rate is appropriately low.
+ */
+
+ csr = DZ_READ_WORD(dr_csr);
+
+ if (sc->sc_rxint > (16*10)) {
+ if ((csr & DZ_CSR_SAE) == 0)
+ DZ_WRITE_WORD(dr_csr, csr | DZ_CSR_SAE);
+ } else if ((csr & DZ_CSR_SAE) != 0)
+ if (sc->sc_rxint < 10)
+ DZ_WRITE_WORD(dr_csr, csr & ~(DZ_CSR_SAE));
+
+ sc->sc_rxint = 0;
+ }
+ (void) splx(s);
+ timeout(dzscan, (void *)0, hz);
+ return;
+}
--- /dev/null
+/* $OpenBSD: dz_uba.c,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dz_uba.c,v 1.8 2000/01/24 02:40:29 matt Exp $ */
+/*
+ * Copyright (c) 1998 Ludd, University of Lule}, Sweden. All rights reserved.
+ * Copyright (c) 1996 Ken C. Wellsch. 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 at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/pte.h>
+#include <machine/trap.h>
+#include <machine/scb.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/qbus/dzreg.h>
+#include <arch/vax/qbus/dzvar.h>
+
+static int dz_uba_match __P((struct device *, struct cfdata *, void *));
+static void dz_uba_attach __P((struct device *, struct device *, void *));
+
+struct cfattach dz_uba_ca = {
+ sizeof(struct dz_softc), (cfmatch_t)dz_uba_match, dz_uba_attach
+};
+
+/* Autoconfig handles: setup the controller to interrupt, */
+/* then complete the housecleaning for full operation */
+
+static int
+dz_uba_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_attach_args *ua = aux;
+ bus_space_tag_t iot = ua->ua_iot;
+ bus_space_handle_t ioh = ua->ua_ioh;
+ register int n;
+
+ iot = iot; /* Silly GCC */
+ /* Reset controller to initialize, enable TX interrupts */
+ /* to catch floating vector info elsewhere when completed */
+
+ bus_space_write_2(iot, ioh, DZ_UBA_CSR, DZ_CSR_MSE | DZ_CSR_TXIE);
+ bus_space_write_1(iot, ioh, DZ_UBA_TCR, 1);
+
+ DELAY(100000); /* delay 1/10 second */
+
+ bus_space_write_2(iot, ioh, DZ_UBA_CSR, DZ_CSR_RESET);
+
+ /* Now wait up to 3 seconds for reset/clear to complete. */
+
+ for (n = 0; n < 300; n++) {
+ DELAY(10000);
+ if ((bus_space_read_2(iot, ioh, DZ_UBA_CSR)&DZ_CSR_RESET) == 0)
+ break;
+ }
+
+ /* If the RESET did not clear after 3 seconds, */
+ /* the controller must be broken. */
+
+ if (n >= 300)
+ return (0);
+
+ /* Register the TX interrupt handler */
+
+
+ return (1);
+}
+
+static void
+dz_uba_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct dz_softc *sc = (void *)self;
+ register struct uba_attach_args *ua = aux;
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+
+ sc->sc_dr.dr_csr = DZ_UBA_CSR;
+ sc->sc_dr.dr_rbuf = DZ_UBA_RBUF;
+ sc->sc_dr.dr_dtr = DZ_UBA_DTR;
+ sc->sc_dr.dr_break = DZ_UBA_BREAK;
+ sc->sc_dr.dr_tbuf = DZ_UBA_TBUF;
+ sc->sc_dr.dr_tcr = DZ_UBA_TCR;
+ sc->sc_dr.dr_dcd = DZ_UBA_DCD;
+ sc->sc_dr.dr_ring = DZ_UBA_RING;
+
+ sc->sc_type = DZ_DZ;
+
+ /* Now register the TX & RX interrupt handlers */
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, dzxint, sc);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dzrint, sc);
+
+ dzattach(sc);
+}
--- /dev/null
+/* $OpenBSD: dzreg.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dzreg.h,v 1.4 1999/05/27 16:03:13 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ken C. Wellsch. 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+union w_b
+{
+ u_short word;
+ struct {
+ u_char byte_lo;
+ u_char byte_hi;
+ } bytes;
+};
+
+struct DZregs
+{
+ volatile u_short dz_csr; /* Control/Status Register (R/W) */
+ volatile u_short dz_rbuf; /* Receive Buffer (R only) */
+#define dz_lpr dz_rbuf /* Line Parameter Register (W only) */
+ volatile union w_b u_tcr; /* Transmit Control Register (R/W) */
+ volatile union w_b u_msr; /* Modem Status Register (R only) */
+#define u_tdr u_msr /* Transmit Data Register (W only) */
+};
+
+#define dz_tcr u_tcr.bytes.byte_lo /* tx enable bits */
+#define dz_dtr u_tcr.bytes.byte_hi /* DTR status bits */
+#define dz_ring u_msr.bytes.byte_lo /* RI status bits */
+#define dz_dcd u_msr.bytes.byte_hi /* DCD status bits */
+#define dz_tbuf u_tdr.bytes.byte_lo /* transmit character */
+#define dz_break u_tdr.bytes.byte_hi /* BREAK set/clr bits */
+
+typedef struct DZregs dzregs;
+
+#if 0
+struct dz_regs {
+ volatile unsigned short *dr_csr;
+ volatile unsigned short *dr_rbuf;
+#define dr_lpr dr_rbuf
+ volatile unsigned char *dr_dtr;
+ volatile unsigned char *dr_break;
+ volatile unsigned char *dr_tbuf;
+ volatile unsigned char *dr_tcr;
+ volatile unsigned short *dr_tcrw;
+ volatile unsigned char *dr_ring;
+ volatile unsigned char *dr_dcd;
+};
+#else
+struct dz_regs {
+ bus_addr_t dr_csr;
+ bus_addr_t dr_rbuf;
+#define dr_lpr dr_rbuf
+ bus_addr_t dr_dtr;
+ bus_addr_t dr_break;
+ bus_addr_t dr_tbuf;
+ bus_addr_t dr_tcr;
+ bus_addr_t dr_tcrw;
+ bus_addr_t dr_ring;
+ bus_addr_t dr_dcd;
+};
+#define DZ_UBA_CSR 0
+#define DZ_UBA_RBUF 2
+#define DZ_UBA_DTR 5
+#define DZ_UBA_BREAK 7
+#define DZ_UBA_TBUF 6
+#define DZ_UBA_TCR 4
+#define DZ_UBA_DCD 7
+#define DZ_UBA_RING 6
+
+#endif
+
+/* CSR bits */
+
+#define DZ_CSR_TX_READY 0100000 /* Transmitter Ready */
+#define DZ_CSR_TXIE 0040000 /* Transmitter Interrupt Enable */
+#define DZ_CSR_SA 0020000 /* Silo Alarm */
+#define DZ_CSR_SAE 0010000 /* Silo Alarm Enable */
+#define DZ_CSR_TX_LINE_MASK 0007400 /* Which TX line */
+
+#define DZ_CSR_RX_DONE 0000200 /* Receiver Done */
+#define DZ_CSR_RXIE 0000100 /* Receiver Interrupt Enable */
+#define DZ_CSR_MSE 0000040 /* Master Scan Enable */
+#define DZ_CSR_RESET 0000020 /* Clear (reset) Controller */
+#define DZ_CSR_MAINTENANCE 0000010
+#define DZ_CSR_UNUSED 0000007
+
+/* RBUF bits */
+
+#define DZ_RBUF_DATA_VALID 0100000
+#define DZ_RBUF_OVERRUN_ERR 0040000
+#define DZ_RBUF_FRAMING_ERR 0020000
+#define DZ_RBUF_PARITY_ERR 0010000
+#define DZ_RBUF_RX_LINE_MASK 0007400
+
+/* LPR bits */
+
+#define DZ_LPR_UNUSED 0160000
+#define DZ_LPR_RX_ENABLE 0010000
+
+#define DZ_LPR_B50 0x0
+#define DZ_LPR_B75 0x1
+#define DZ_LPR_B110 0x2
+#define DZ_LPR_B134 0x3
+#define DZ_LPR_B150 0x4
+#define DZ_LPR_B300 0x5
+#define DZ_LPR_B600 0x6
+#define DZ_LPR_B1200 0x7
+#define DZ_LPR_B1800 0x8
+#define DZ_LPR_B2000 0x9
+#define DZ_LPR_B2400 0xA
+#define DZ_LPR_B3600 0xB
+#define DZ_LPR_B4800 0xC
+#define DZ_LPR_B7200 0xD
+#define DZ_LPR_B9600 0xE
+#define DZ_LPR_B19200 0xF
+
+#define DZ_LPR_OPAR 0000200
+#define DZ_LPR_PARENB 0000100
+#define DZ_LPR_2_STOP 0000040
+
+#define DZ_LPR_5_BIT_CHAR 0000000
+#define DZ_LPR_6_BIT_CHAR 0000010
+#define DZ_LPR_7_BIT_CHAR 0000020
+#define DZ_LPR_8_BIT_CHAR 0000030
+
+#define DZ_LPR_CHANNEL_MASK 0000007
--- /dev/null
+/* $OpenBSD: dzvar.h,v 1.1 2000/04/27 03:14:47 bjc Exp $ */
+/* $NetBSD: dzvar.h,v 1.6 2000/01/24 02:40:29 matt Exp $ */
+/*
+ * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ */
+
+/* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */
+
+#define NDZLINE 8
+
+#define DZ_DZ 8
+#define DZ_DZV 4
+#define DZ_DC 4
+
+#define DZ_C2I(c) ((c)<<3) /* convert controller # to index */
+#define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */
+#define DZ_PORT(u) ((u)&07) /* extract the port # */
+
+struct dz_softc {
+ struct device sc_dev; /* Autoconf blaha */
+ struct dz_regs sc_dr; /* reg pointers */
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ int sc_type; /* DZ11 or DZV11? */
+ int sc_rxint; /* Receive interrupt count XXX */
+ u_char sc_brk; /* Break asserted on some lines */
+ u_char sc_dsr; /* DSR set bits if no mdm ctrl */
+ int (*sc_catch) __P((int, int)); /* Fast catch recv */
+ struct {
+ struct tty * dz_tty; /* what we work on */
+#ifdef notyet
+ caddr_t dz_mem; /* pointers to clist output */
+ caddr_t dz_end; /* allowing pdma action */
+#endif
+ } sc_dz[NDZLINE];
+};
+
+void dzattach __P((struct dz_softc *));
+void dzrint __P((void *));
+void dzxint __P((void *));
--- /dev/null
+# $OpenBSD: files.uba,v 1.1 2000/04/27 03:14:48 bjc Exp $
+# $NetBSD: files.uba,v 1.6 1999/06/20 18:09:22 ragge Exp $
+#
+# Config file and device description for machine-independent
+# code for devices Digital Equipment Corp. Unibus and Q22 bus.
+# Included by ports that need it.
+device uba { csr }
+
+define qfont
+
+file arch/vax/qbus/uba.c uba
+
+# DZ-11 (-compatible) tty device driver.
+device dz { }: tty
+attach dz at uba with dz_uba
+file arch/vax/qbus/dz.c dz needs-flag
+file arch/vax/qbus/dz_uba.c dz_uba
+
+# DL-11 at UBA
+device dl: tty
+attach dl at uba
+file arch/vax/qbus/dl.c dl needs-flag
+
+# DHU-11 at UBA
+device dhu: tty
+attach dhu at uba
+file arch/vax/qbus/dhu.c dhu needs-flag
+
+# UDA50/whatever disk/tape MSCP controller
+device mtc: mscp
+attach mtc at uba
+device uda: mscp
+attach uda at uba
+file arch/vax/qbus/uda.c uda | mtc
+
+# DEQNA/DELQA Ethernet controller
+device qe: ifnet, ether
+attach qe at uba
+file arch/vax/if/if_qe.c qe
+
+# DEUNA/DELUA Ethernet controller
+device de: ifnet, ether
+attach de at uba
+file arch/vax/if/if_de.c de
+
+# QDSS at UBA
+device qd: qfont
+attach qd at uba
+file arch/vax/qbus/qd.c qd needs-count
+
+# Fontfile for DEC framebuffers, soon to die in favour for MI fontfiles.
+file arch/vax/qbus/qfont.c qfont
--- /dev/null
+/* $OpenBSD: qd.c,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qd.c,v 1.17 2000/01/24 02:40:29 matt Exp $ */
+
+/*-
+ * 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"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/poll.h>
+#include <sys/buf.h>
+
+#include <vm/vm.h>
+
+#include <dev/cons.h>
+
+#include <machine/bus.h>
+#include <machine/scb.h>
+
+#ifdef __vax__
+#include <machine/sid.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#endif
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/qbus/qduser.h>
+#include <arch/vax/qbus/qdreg.h>
+#include <arch/vax/qbus/qdioctl.h>
+
+/*
+ * 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 */
+};
+
+/*
+ * Softc struct to keep track of all states in this driver.
+ */
+struct qd_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+};
+
+/*
+ * 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.. */
+volatile char *qvmem[NQD];
+volatile struct pte *QVmap[NQD];
+#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 qdmap qdmap[NQD]; /* QDSS register map structure */
+struct qdflags qdflags[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 selinfo 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. We don't care! */
+
+/*
+ * macro to get system time. Used to time stamp event queue entries
+ */
+#define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
+
+void qd_attach __P((struct device *, struct device *, void *));
+static int qd_match __P((struct device *, struct cfdata *, void *));
+
+static void qddint __P((void *)); /* DMA gate array intrpt service */
+static void qdaint __P((void *)); /* Dragon ADDER intrpt service */
+static void qdiint __P((void *));
+
+#define QDPRIOR (PZERO-1) /* must be negative */
+#define FALSE 0
+#ifdef TRUE
+#undef TRUE
+#endif
+#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) >> VAX_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 struct cdevsw *consops;
+cons_decl(qd);
+cdev_decl(qd);
+void setup_dragon __P((int));
+void init_shared __P((int));
+void clear_qd_screen __P((int));
+void ldfont __P((int));
+void ldcursor __P((int, short *));
+void setup_input __P((int));
+void blitc __P((int, u_char));
+void scroll_up __P((volatile struct adder *));
+void write_ID __P((volatile struct adder *, short, short));
+int wait_status __P((volatile struct adder *, int));
+void led_control __P((int, int, int));
+void qdstart(struct tty *);
+void qdearly(void);
+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)
+
+/*
+ * Kernel virtual addresses where we can map in the QBUS io page and the
+ * QDSS memory during qdcninit. pmap_bootstrap fills this in.
+ */
+void *qd_ubaio;
+
+/* This is the QDSS unit 0 CSR. It is hard-coded in here so that the
+ * QDSS can be used as the console. The console routines don't get
+ * any config info. The ROM also autodetects at this address, so
+ * the console QDSS should be at this address. Furthermore, nothing
+ * else shuld be at this address instead because that would confuse the
+ * ROM and this driver.
+ */
+#define QDSSCSR 0x1F00
+
+volatile u_short *qdaddr; /* Virtual address for QDSS CSR */
+
+/*
+ * This flag is set to 1 if the console initialization (qdcninit)
+ * has been performed on qd0. That initialization is required and must
+ * be done before the device probe routine.
+ */
+int qd0cninited = 0, qd0iscons = 0;
+
+/*
+ * Do early check if the qdss is console. If not; don't allocate
+ * any memory for it in bootstrap.
+ */
+void
+qdearly()
+{
+ extern vaddr_t virtual_avail;
+ int tmp;
+
+ /* Make sure we're running on a system that can have a QDSS */
+ if (vax_boardtype == VAX_BTYP_630) {
+ /* Now check some undocumented flag */
+ if ((*(int *)(0x200B801E) & 0x60) == 0)
+ /* The KA630 isn't using a QDSS as the console,
+ * so we won't either */
+ return;
+ } else if (vax_boardtype != VAX_BTYP_650)
+ return;
+
+ /* How to check for console on KA650? We assume that if there is a
+ * QDSS, it is console.
+ */
+#define QIOPAGE 0x20000000 /* XXX */
+#define UBAIOPAGES 16
+ tmp = QIOPAGE + ubdevreg(QDSSCSR);
+ if (badaddr((caddr_t)tmp, sizeof(short)))
+ return;
+
+ MAPVIRT(qvmem[0], 64 * 1024 * NQD / VAX_NBPG);
+ MAPVIRT(qd_ubaio, 16);
+ pmap_map((int)qd_ubaio, QIOPAGE, QIOPAGE + UBAIOPAGES * VAX_NBPG,
+ VM_PROT_READ|VM_PROT_WRITE);
+ qdaddr = (u_short *)((u_int)qd_ubaio + ubdevreg(QDSSCSR));
+ qd0iscons = 1;
+}
+
+void
+qdcnprobe(cndev)
+ struct consdev *cndev;
+{
+ int i;
+
+ cndev->cn_pri = CN_DEAD;
+
+ if (mfpr(PR_MAPEN) == 0)
+ return; /* Cannot use qd if vm system is OFF */
+
+ if (!qd0iscons)
+ return;
+
+ /* Find the console device corresponding to the console QDSS */
+ for (i = 0; i < nchrdev; i++)
+ if (cdevsw[i].d_open == qdopen) {
+ cndev->cn_dev = makedev(i,0);
+ cndev->cn_pri = CN_INTERNAL;
+ return;
+ }
+ return;
+}
+
+
+/*
+ * Init QDSS as console (before probe routine)
+ */
+void
+qdcninit(cndev)
+ struct consdev *cndev;
+{
+ caddr_t phys_adr; /* physical QDSS base adrs */
+ u_int mapix; /* index into QVmap[] array */
+ int unit;
+
+ /* qdaddr must point to CSR for this unit! */
+
+ /* The console QDSS is QDSS unit 0 */
+ unit = 0;
+
+ /*
+ * Map q-bus memory used by qdss. (separate map)
+ */
+ mapix = QMEMSIZE - (CHUNK * (unit + 1));
+#define QMEM 0x30000000
+ (int)phys_adr = QMEM + mapix;
+ pmap_map((int)(qvmem[0]), (int)phys_adr, (int)(phys_adr + (CHUNK*NQD)),
+ VM_PROT_READ|VM_PROT_WRITE);
+
+ /*
+ * Set QVmap to point to page table entries for what we just
+ * mapped.
+ */
+ QVmap[0] = (struct pte *)kvtopte(qvmem[0]);
+
+ /*
+ * 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
+ */
+
+ *(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 */
+
+ /* Set flag so probe knows */
+ qd0cninited = 1;
+} /* qdcninit */
+
+/* see <sys/device.h> */
+struct cfattach qd_ca = {
+ sizeof(struct qd_softc), qd_match, qd_attach
+};
+
+#define QD_RCSR(reg) \
+ bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
+#define QD_WCSR(reg, val) \
+ bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
+
+/*
+ * 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.
+ *
+ */
+static int
+qd_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct qd_softc ssc;
+ struct qd_softc *sc = &ssc;
+ struct uba_attach_args *ua = aux;
+ struct uba_softc *uh = (void *)parent;
+ register int unit;
+ volatile 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
+
+ /* Create a "fake" softc with only a few fields used. */
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_ioh = ua->ua_ioh;
+ sc->sc_dmat = ua->ua_dmat;
+ /*
+ * calculate board unit number from I/O page register address
+ */
+ unit = (int) (((int)sc->sc_ioh >> 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
+ */
+ qdflags[unit].config = *(u_short *)reg;
+
+ /*
+ * find an empty 64kb adrs boundary
+ */
+
+ qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
+
+ /*
+ * find the cpusw entry that matches this machine.
+ */
+ cpup = &cpusw[cpu];
+ while (!(BADADDR(qdbase[unit], sizeof(short))))
+ qdbase[unit] -= CHUNK;
+
+ /*
+ * tell QDSS which Q memory address base to decode
+ */
+ mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
+ ptep = (int *) QVmap[0] + mapix;
+ phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<VAX_PGSHIFT);
+ *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
+
+ /*
+ * load QDSS adrs map with system addresses
+ * of device regs
+ */
+ 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;
+
+ /* device init */
+
+ cursor[unit].x = 0;
+ cursor[unit].y = 0;
+ init_shared(unit); /* init shared memory */
+ setup_dragon(unit); /* init the ADDER/VIPER stuff */
+ ldcursor(unit, cons_cursor); /* load default cursor map */
+ setup_input(unit); /* init the DUART */
+ clear_qd_screen(unit);
+ ldfont(unit); /* load the console font */
+
+ /* once only: turn on sync */
+
+ *(short *)qdmap[unit].memcsr |= SYNC_ON;
+ }
+#endif /*notdef*/
+ } else {
+ /* We are dealing with qd0 */
+
+ if (!qd0cninited) {
+ /*
+ * qd0 has not been initiallized as the console.
+ * We need to do some initialization now
+ *
+ * XXX
+ * However, if the QDSS is not the console then
+ * that stupid undocumented bit (see qdcnprobe)
+ * is cleared. Then the QDSS refuses to work.
+ * (What did the ROM do to it!?)
+ * XXX
+ */
+ return 0;
+
+#if 0
+ qdaddr = (void *)reg;
+
+ /* Lame probe for QDSS. Should be ok for qd0 */
+ if (badaddr((caddr_t)qdaddr, sizeof(short)))
+ return 0;
+
+ qdcninit(NULL);
+#endif
+ }
+ }
+
+
+ /*
+ * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
+ * (ADDER) and xx8 (DUART). Therefore, we take three
+ * vectors from the vector pool, and then continue
+ * to take them until we get a xx0 HEX vector. The
+ * pool provides vectors in contiguous decending
+ * order.
+ */
+
+ vector = (uh->uh_lastiv -= 4*3); /* take three vectors */
+
+ while (vector & 0x0F) { /* if lo nibble != 0.. */
+ /* ..take another vector */
+ vector = (uh->uh_lastiv -= 4);
+ }
+
+ /*
+ * setup DGA to do a DMA interrupt (transfer count = 0)
+ */
+ dga = (struct dga *) qdmap[unit].dga;
+ dga->csr = (short) HALT; /* disable everything */
+ dga->ivr = (short) vector; /* load intrpt base vector */
+ dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */
+ dga->bytcnt_hi = (short) 0;
+
+ /*
+ * turn on DMA interrupts
+ */
+ dga->csr &= ~SET_DONE_FIFO;
+ dga->csr |= DMA_IE | DL_ENB;
+
+ DELAY(20000); /* wait for the intrpt */
+ dga->csr = HALT; /* stop the wheels */
+
+ /*
+ * score this as an existing qdss
+ */
+ qdcount++;
+
+ return 1;
+} /* qdprobe */
+
+
+void qd_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+ {
+ register struct uba_attach_args *ua = aux;
+ register int unit; /* QDSS module # for this call */
+
+ printf("\n");
+
+ unit = self->dv_unit; /* get QDSS number */
+
+ /* Set interrupt vectors for interrupt handlers */
+
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec , qddint, self);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4, qdaint, self);
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 8, qdiint, self);
+
+ /*
+ * init "qdflags[]" for this QDSS
+ */
+ qdflags[unit].inuse = 0; /* init inuse variable EARLY! */
+ qdflags[unit].mapped = 0;
+ qdflags[unit].kernel_loop = -1;
+ qdflags[unit].user_dma = 0;
+ qdflags[unit].curs_acc = ACC_OFF;
+ qdflags[unit].curs_thr = 128;
+ qdflags[unit].tab_res = 2; /* default tablet resolution factor */
+ qdflags[unit].duart_imask = 0; /* init shadow variables */
+ qdflags[unit].adder_ie = 0;
+
+ /*
+ * init structures used in kbd/mouse interrupt service. This code must
+ * come after the "init_shared()" routine has run since that routine
+ * inits the eq_header[unit] structure used here.
+ */
+
+ /*
+ * init the "latest mouse report" structure
+ */
+ last_rep[unit].state = 0;
+ last_rep[unit].dx = 0;
+ last_rep[unit].dy = 0;
+ last_rep[unit].bytcnt = 0;
+
+ /*
+ * init the event queue (except mouse position)
+ */
+ eq_header[unit]->header.events =
+ (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
+
+ eq_header[unit]->header.size = MAXEVENTS;
+ eq_header[unit]->header.head = 0;
+ eq_header[unit]->header.tail = 0;
+
+ /*
+ * open exclusive for graphics device.
+ */
+ qdopened[unit] = 0;
+
+} /* qdattach */
+
+
+/*ARGSUSED*/
+int
+qdopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ volatile register struct dga *dga; /* ptr to gate array struct */
+ register struct tty *tp;
+ volatile struct duart *duart;
+ int unit;
+ int minor_dev;
+
+ minor_dev = minor(dev); /* get QDSS minor device number */
+ unit = minor_dev >> 2;
+
+ /*
+ * check for illegal conditions
+ */
+ if (unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[unit] == NULL)
+ return (ENXIO); /* no such device or address */
+
+ duart = (struct duart *) qdmap[unit].duart;
+ dga = (struct dga *) qdmap[unit].dga;
+
+ if ((minor_dev & 0x03) == 2) {
+ /*
+ * this is the graphic device...
+ */
+ if (qdopened[unit] != 0)
+ return(EBUSY);
+ else
+ qdopened[unit] = 1;
+ qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */
+ /*
+ * enble kbd & mouse intrpts in DUART mask reg
+ */
+ qdflags[unit].duart_imask |= 0x22;
+ duart->imask = qdflags[unit].duart_imask;
+ } else {
+ /* Only one console */
+ if (minor_dev) return ENXIO;
+
+ /* If not done already, allocate tty structure */
+ if (qd_tty[minor_dev] == NULL)
+ qd_tty[minor_dev] = ttymalloc();
+
+ if (qd_tty[minor_dev] == NULL)
+ return ENXIO;
+
+ /*
+ * this is the console
+ */
+ qdflags[unit].inuse |= CONS_DEV; /* mark console as open */
+ dga->csr |= CURS_ENB;
+ qdflags[unit].duart_imask |= 0x02;
+ duart->imask = qdflags[unit].duart_imask;
+ /*
+ * some setup for tty handling
+ */
+ tp = qd_tty[minor_dev];
+ /* tp->t_addr = ui->ui_addr; */
+ tp->t_oproc = qdstart;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ tp->t_ispeed = B9600;
+ tp->t_ospeed = B9600;
+ tp->t_state = TS_ISOPEN | TS_CARR_ON;
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ ttsetwater(tp);
+ }
+ /*
+ * enable intrpts, open line discipline
+ */
+ dga->csr |= GLOBAL_IE; /* turn on the interrupts */
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+ }
+ dga->csr |= GLOBAL_IE; /* turn on the interrupts */
+ return(0);
+
+} /* qdopen */
+
+/*ARGSUSED*/
+int
+qdclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ register struct tty *tp;
+ register struct qdmap *qd;
+ volatile register int *ptep;
+ volatile struct dga *dga; /* gate array register map pointer */
+ volatile struct duart *duart;
+ volatile struct adder *adder;
+ int unit;
+ int minor_dev;
+ u_int mapix;
+ int i; /* SIGNED index */
+ struct uba_softc *uh;
+
+ minor_dev = minor(dev); /* get minor device number */
+ unit = minor_dev >> 2; /* get QDSS number */
+ qd = &qdmap[unit];
+
+ uh = (struct uba_softc *)
+ (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
+
+
+ if ((minor_dev & 0x03) == 2) {
+ /*
+ * this is the graphic device...
+ */
+ if (qdopened[unit] != 1)
+ return(EBUSY);
+ else
+ qdopened[unit] = 0; /* allow it to be re-opened */
+ /*
+ * re-protect device memory
+ */
+ if (qdflags[unit].mapped & MAPDEV) {
+ /*
+ * TEMPLATE RAM
+ */
+ mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
+ ptep = (int *)(QVmap[0] + mapix);
+ for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+ /*
+ * ADDER
+ */
+ mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
+ ptep = (int *)(QVmap[0] + mapix);
+ for (i = 0; i < vax_btop(REGSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+ /*
+ * COLOR MAPS
+ */
+ mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
+ ptep = (int *)(QVmap[0] + mapix);
+ for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+ }
+
+ /*
+ * re-protect DMA buffer and free the map registers
+ */
+ if (qdflags[unit].mapped & MAPDMA) {
+ panic("Unmapping unmapped buffer");
+#ifdef notyet
+/*
+ * Ragge 990620:
+ * Can't happen because the buffer can't be mapped.
+ */
+ dga = (struct dga *) qdmap[unit].dga;
+ adder = (struct adder *) qdmap[unit].adder;
+ dga->csr &= ~DMA_IE;
+ dga->csr &= ~0x0600; /* kill DMA */
+ adder->command = CANCEL;
+ /*
+ * if DMA was running, flush spurious intrpt
+ */
+ if (dga->bytcnt_lo != 0) {
+ dga->bytcnt_lo = 0;
+ dga->bytcnt_hi = 0;
+ DMA_SETIGNORE(DMAheader[unit]);
+ dga->csr |= DMA_IE;
+ dga->csr &= ~DMA_IE;
+ }
+ ptep = (int *)
+ ((VTOP(DMAheader[unit]*4)) + (mfpr(PR_SBR)|0x80000000));
+ for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
+ ubarelse(uh, &Qbus_unmap[unit]);
+#endif
+ }
+
+ /*
+ * re-protect 1K (2 pages) event queue
+ */
+ if (qdflags[unit].mapped & MAPEQ) {
+ ptep = (int *)
+ ((VTOP(eq_header[unit])*4) + (mfpr(PR_SBR)|0x80000000));
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+ }
+ /*
+ * re-protect scroll param area and disable scroll intrpts
+ */
+ if (qdflags[unit].mapped & MAPSCR) {
+ ptep = (int *) ((VTOP(scroll[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ /*
+ * re-protect 512 scroll param area
+ */
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+ adder = (struct adder *) qdmap[unit].adder;
+ qdflags[unit].adder_ie &= ~FRAME_SYNC;
+ adder->interrupt_enable = qdflags[unit].adder_ie;
+ }
+ /*
+ * re-protect color map write buffer area and kill intrpts
+ */
+ if (qdflags[unit].mapped & MAPCOLOR) {
+ ptep = (int *) ((VTOP(color_buf[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+ color_buf[unit]->status = 0;
+ adder = (struct adder *) qdmap[unit].adder;
+ qdflags[unit].adder_ie &= ~VSYNC;
+ adder->interrupt_enable = qdflags[unit].adder_ie;
+ }
+ mtpr(0, PR_TBIA);
+ /* flag everything now unmapped */
+ qdflags[unit].mapped = 0;
+ qdflags[unit].inuse &= ~GRAPHIC_DEV;
+ qdflags[unit].curs_acc = ACC_OFF;
+ qdflags[unit].curs_thr = 128;
+ /*
+ * restore the console
+ */
+ dga = (struct dga *) qdmap[unit].dga;
+ adder = (struct adder *) qdmap[unit].adder;
+ dga->csr &= ~DMA_IE;
+ dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */
+ dga->csr |= DMA_ERR; /* clear error condition */
+ adder->command = CANCEL;
+ /*
+ * if DMA was running, flush spurious intrpt
+ */
+ if (dga->bytcnt_lo != 0) {
+ dga->bytcnt_lo = 0;
+ dga->bytcnt_hi = 0;
+ DMA_SETIGNORE(DMAheader[unit]);
+ dga->csr |= DMA_IE;
+ dga->csr &= ~DMA_IE;
+ }
+ init_shared(unit); /* init shared memory */
+ setup_dragon(unit); /* init ADDER/VIPER */
+ ldcursor(unit, cons_cursor); /* load default cursor map */
+ setup_input(unit); /* init the DUART */
+ ldfont(unit);
+ cursor[unit].x = 0;
+ cursor[unit].y = 0;
+ /*
+ * shut off the mouse rcv intrpt and turn on kbd intrpts
+ */
+ duart = (struct duart *) qdmap[unit].duart;
+ qdflags[unit].duart_imask &= ~(0x20);
+ qdflags[unit].duart_imask |= 0x02;
+ duart->imask = qdflags[unit].duart_imask;
+ /*
+ * shut off interrupts if all is closed
+ */
+ if (!(qdflags[unit].inuse & CONS_DEV)) {
+ dga = (struct dga *) qdmap[unit].dga;
+ dga->csr &= ~(GLOBAL_IE | DMA_IE);
+ }
+ } else {
+ /*
+ * this is the console
+ */
+ tp = qd_tty[minor_dev];
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+ tp->t_state = 0;
+ qdflags[unit].inuse &= ~CONS_DEV;
+ /*
+ * if graphics device is closed, kill interrupts
+ */
+ if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
+ dga = (struct dga *) qdmap[unit].dga;
+ dga->csr &= ~(GLOBAL_IE | DMA_IE);
+ }
+ }
+
+ return(0);
+
+} /* qdclose */
+
+int
+qdioctl(dev, cmd, datap, flags, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t datap;
+ int flags;
+ struct proc *p;
+{
+ volatile register int *ptep; /* page table entry pointer */
+ register int mapix; /* QVmap[] page table index */
+ register struct _vs_event *event;
+ register struct tty *tp;
+ register int i;
+ struct qdmap *qd; /* pointer to device map struct */
+ volatile struct dga *dga; /* Gate Array reg structure pntr */
+ volatile struct duart *duart; /* DUART reg structure pointer */
+ volatile struct adder *adder; /* ADDER reg structure pointer */
+ struct prgkbd *cmdbuf;
+ struct prg_cursor *curs;
+ struct _vs_cursor *pos;
+ int unit = minor(dev) >> 2; /* number of caller's QDSS */
+ u_int minor_dev = minor(dev);
+ int error;
+ int s;
+ short *temp; /* a pointer to template RAM */
+ struct uba_softc *uh;
+
+ uh = (struct uba_softc *)
+ (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
+
+ /*
+ * service graphic device ioctl commands
+ */
+ switch (cmd) {
+
+ case QD_GETEVENT:
+ /*
+ * extract the oldest event from the event queue
+ */
+ if (ISEMPTY(eq_header[unit])) {
+ event = (struct _vs_event *) datap;
+ event->vse_device = VSE_NULL;
+ break;
+ }
+ event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
+ s = spl5();
+ GETEND(eq_header[unit]);
+ splx(s);
+ bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
+ break;
+
+ case QD_RESET:
+ /*
+ * init the dragon stuff, DUART, and driver variables
+ */
+ init_shared(unit); /* init shared memory */
+ setup_dragon(unit); /* init the ADDER/VIPER stuff */
+ clear_qd_screen(unit);
+ ldcursor(unit, cons_cursor); /* load default cursor map */
+ ldfont(unit); /* load the console font */
+ setup_input(unit); /* init the DUART */
+ break;
+
+ case QD_SET:
+ /*
+ * init the DUART and driver variables
+ */
+ init_shared(unit);
+ setup_input(unit);
+ break;
+
+ case QD_CLRSCRN:
+ /*
+ * clear the QDSS screen. (NOTE that this reinits the dragon)
+ */
+#ifdef notdef /* has caused problems and isn't necessary */
+ setup_dragon(unit);
+ clear_qd_screen(unit);
+#endif
+ break;
+
+ case QD_WTCURSOR:
+ /*
+ * load a cursor into template RAM
+ */
+ ldcursor(unit, (short *)datap);
+ break;
+
+ case QD_RDCURSOR:
+
+ temp = (short *) qdmap[unit].template;
+ /*
+ * cursor is 32 WORDS from the end of the 8k WORD...
+ * ...template space
+ */
+ temp += (8 * 1024) - 32;
+ for (i = 0; i < 32; ++i, datap += sizeof(short))
+ *(short *)datap = *temp++;
+ break;
+
+ case QD_POSCURSOR:
+ /*
+ * position the mouse cursor
+ */
+ dga = (struct dga *) qdmap[unit].dga;
+ pos = (struct _vs_cursor *) datap;
+ s = spl5();
+ dga->x_cursor = TRANX(pos->x);
+ dga->y_cursor = TRANY(pos->y);
+ eq_header[unit]->curs_pos.x = pos->x;
+ eq_header[unit]->curs_pos.y = pos->y;
+ splx(s);
+ break;
+
+ case QD_PRGCURSOR:
+ /*
+ * set the cursor acceleration factor
+ */
+ curs = (struct prg_cursor *) datap;
+ s = spl5();
+ qdflags[unit].curs_acc = curs->acc_factor;
+ qdflags[unit].curs_thr = curs->threshold;
+ splx(s);
+ break;
+
+ case QD_MAPDEVICE:
+ /*
+ * enable 'user write' to device pages
+ */
+ qdflags[unit].mapped |= MAPDEV;
+ qd = (struct qdmap *) &qdmap[unit];
+ /*
+ * enable user write to template RAM
+ */
+ mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
+ ptep = (int *)(QVmap[0] + mapix);
+ for (i = 0; i < vax_btop(TMPSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+
+ /*
+ * enable user write to registers
+ */
+ mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
+ ptep = (int *)(QVmap[0] + mapix);
+ for (i = 0; i < vax_btop(REGSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+
+ /*
+ * enable user write to color maps
+ */
+ mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
+ ptep = (int *)(QVmap[0] + mapix);
+ for (i = 0; i < vax_btop(CLRSIZE); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+
+ /*
+ * enable user write to DUART
+ */
+ mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
+ ptep = (int *)(QVmap[0] + mapix);
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; /* duart page */
+
+ mtpr(0, PR_TBIA); /* invalidate translation buffer */
+
+ /*
+ * stuff qdmap structure in return buffer
+ */
+ bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
+
+ break;
+
+#ifdef notyet
+/*
+ * Ragge 999620:
+ * Can't map in the graphic buffer into user space for now.
+ * The best way to fix this is to convert this driver to wscons.
+ */
+ case QD_MAPIOBUF:
+ /*
+ * do setup for DMA by user process
+ *
+ * set 'user write enable' bits for DMA buffer
+ */
+ qdflags[unit].mapped |= MAPDMA;
+ ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ for (i = 0; i < vax_btop(DMAbuf_size); i++, ptep++)
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* invalidate translation buffer */
+ /*
+ * set up QBUS map registers for DMA
+ */
+ DMAheader[unit]->QBAreg =
+ uballoc(uh, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
+ if (DMAheader[unit]->QBAreg == 0)
+ printf("qd%d: qdioctl: QBA setup error\n", unit);
+ Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
+ DMAheader[unit]->QBAreg &= 0x3FFFF;
+ /*
+ * return I/O buf adr
+ */
+ *(int *)datap = (int) DMAheader[unit];
+ break;
+#endif
+
+ case QD_MAPSCROLL:
+ /*
+ * map the shared scroll param area and enable scroll interpts
+ */
+ qdflags[unit].mapped |= MAPSCR;
+ ptep = (int *) ((VTOP(scroll[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ /*
+ * allow user write to scroll area
+ */
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* invalidate translation buf */
+ scroll[unit]->status = 0;
+ adder = (struct adder *) qdmap[unit].adder;
+ qdflags[unit].adder_ie |= FRAME_SYNC;
+ adder->interrupt_enable = qdflags[unit].adder_ie;
+ *(int *)datap = (int) scroll[unit]; /* return scroll area */
+ break;
+
+ case QD_UNMAPSCROLL:
+ /*
+ * unmap shared scroll param area and disable scroll intrpts
+ */
+ if (qdflags[unit].mapped & MAPSCR) {
+ qdflags[unit].mapped &= ~MAPSCR;
+ ptep = (int *) ((VTOP(scroll[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ /*
+ * re-protect 512 scroll param area
+ */
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+ mtpr(0, PR_TBIA); /* smash CPU's translation buf */
+ adder = (struct adder *) qdmap[unit].adder;
+ qdflags[unit].adder_ie &= ~FRAME_SYNC;
+ adder->interrupt_enable = qdflags[unit].adder_ie;
+ }
+ break;
+
+ case QD_MAPCOLOR:
+ /*
+ * map shared color map write buf and turn on vsync intrpt
+ */
+ qdflags[unit].mapped |= MAPCOLOR;
+ ptep = (int *) ((VTOP(color_buf[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ /*
+ * allow user write to color map write buffer
+ */
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* clr CPU translation buf */
+ adder = (struct adder *) qdmap[unit].adder;
+ qdflags[unit].adder_ie |= VSYNC;
+ adder->interrupt_enable = qdflags[unit].adder_ie;
+ /*
+ * return color area address
+ */
+ *(int *)datap = (int) color_buf[unit];
+ break;
+
+ case QD_UNMAPCOLOR:
+ /*
+ * unmap shared color map write buffer and kill VSYNC intrpts
+ */
+ if (qdflags[unit].mapped & MAPCOLOR) {
+ qdflags[unit].mapped &= ~MAPCOLOR;
+ ptep = (int *) ((VTOP(color_buf[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ /*
+ * re-protect color map write buffer
+ */
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
+ *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
+ mtpr(0, PR_TBIA);
+ adder = (struct adder *) qdmap[unit].adder;
+ qdflags[unit].adder_ie &= ~VSYNC;
+ adder->interrupt_enable = qdflags[unit].adder_ie;
+ }
+ break;
+
+ case QD_MAPEVENT:
+ /*
+ * give user write access to the event queue
+ */
+ qdflags[unit].mapped |= MAPEQ;
+ ptep = (int *) ((VTOP(eq_header[unit]) * 4)
+ + (mfpr(PR_SBR) | 0x80000000));
+ /*
+ * allow user write to 1K event queue
+ */
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V; ptep++;
+ *ptep = (*ptep & ~PG_PROT) | PG_RW | PG_V;
+ mtpr(0, PR_TBIA); /* clr CPU translation buf */
+ /*
+ * return event queue address
+ */
+ *(int *)datap = (int)eq_header[unit];
+ break;
+
+ case QD_PRGKBD:
+ /*
+ * pass caller's programming commands to LK201
+ */
+ duart = (struct duart *)qdmap[unit].duart;
+ cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */
+ /*
+ * send command
+ */
+ for (i = 1000; i > 0; --i) {
+ if (duart->statusA&XMT_RDY) {
+ duart->dataA = cmdbuf->cmd;
+ break;
+ }
+ }
+ if (i == 0) {
+ printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
+ break;
+ }
+ /*
+ * send param1?
+ */
+ if (cmdbuf->cmd & LAST_PARAM)
+ break;
+ for (i = 1000; i > 0; --i) {
+ if (duart->statusA&XMT_RDY) {
+ duart->dataA = cmdbuf->param1;
+ break;
+ }
+ }
+ if (i == 0) {
+ printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
+ break;
+ }
+ /*
+ * send param2?
+ */
+ if (cmdbuf->param1 & LAST_PARAM)
+ break;
+ for (i = 1000; i > 0; --i) {
+ if (duart->statusA&XMT_RDY) {
+ duart->dataA = cmdbuf->param2;
+ break;
+ }
+ }
+ if (i == 0) {
+ printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
+ break;
+ }
+ break;
+
+ case QD_PRGMOUSE:
+ /*
+ * pass caller's programming commands to the mouse
+ */
+ duart = (struct duart *) qdmap[unit].duart;
+ for (i = 1000; i > 0; --i) {
+ if (duart->statusB&XMT_RDY) {
+ duart->dataB = *datap;
+ break;
+ }
+ }
+ if (i == 0) {
+ printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
+ }
+ break;
+
+ case QD_RDCONFIG:
+ /*
+ * get QDSS configuration word and return it
+ */
+ *(short *)datap = qdflags[unit].config;
+ break;
+
+ case QD_KERN_LOOP:
+ case QD_KERN_UNLOOP:
+ /*
+ * vestige from ultrix. BSD uses TIOCCONS to redirect
+ * kernel console output.
+ */
+ break;
+
+ case QD_PRGTABLET:
+ /*
+ * program the tablet
+ */
+ duart = (struct duart *) qdmap[unit].duart;
+ for (i = 1000; i > 0; --i) {
+ if (duart->statusB&XMT_RDY) {
+ duart->dataB = *datap;
+ break;
+ }
+ }
+ if (i == 0) {
+ printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
+ }
+ break;
+
+ case QD_PRGTABRES:
+ /*
+ * program the tablet report resolution factor
+ */
+ qdflags[unit].tab_res = *(short *)datap;
+ break;
+
+ default:
+ /*
+ * service tty ioctl's
+ */
+ if (!(minor_dev & 0x02)) {
+ tp = qd_tty[minor_dev];
+ error =
+
+ (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags, p);
+ if (error >= 0) {
+ return(error);
+ }
+ error = ttioctl(tp, cmd, datap, flags, p);
+ if (error >= 0) {
+ return(error);
+ }
+ }
+ break;
+ }
+
+ return(0);
+
+} /* qdioctl */
+
+
+int
+qdpoll(dev, events, p)
+ dev_t dev;
+ int events;
+ struct proc *p;
+{
+ register int s;
+ register int unit;
+ register struct tty *tp;
+ u_int minor_dev = minor(dev);
+ int revents = 0;
+
+ s = spl5();
+ unit = minor_dev >> 2;
+
+ if ((minor_dev & 0x03) == 2) {
+ /*
+ * This is a graphics device, so check for events.
+ */
+
+ if (events & (POLLIN | POLLRDNORM))
+ if(!(ISEMPTY(eq_header[unit])))
+ revents |= events & (POLLIN | POLLRDNORM);
+
+ if (events & (POLLOUT | POLLWRNORM))
+ if (DMA_ISEMPTY(DMAheader[unit]))
+ revents |= events & (POLLOUT | POLLWRNORM);
+
+ if (revents == 0) {
+ if (events & (POLLIN | POLLRDNORM)) {
+ selrecord(p, &qdrsel[unit]);
+ qdflags[unit].selmask |= SEL_READ;
+ }
+
+ if (events & (POLLOUT | POLLWRNORM)) {
+ selrecord(p, &qdrsel[unit]);
+ qdflags[unit].selmask |= SEL_WRITE;
+ }
+ }
+ } else {
+ /*
+ * this is a tty device
+ */
+ tp = qd_tty[minor_dev];
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ /* This is ttnread. It's static and I don't feel
+ * like altering platform independant parts of NetBSD
+ */
+ int nread;
+ /* if (tp->t_lflag & PENDIN)
+ ttypend(tp); */
+ nread = tp->t_canq.c_cc;
+ if (!(tp->t_lflag & ICANON)) {
+ nread += tp->t_rawq.c_cc;
+ if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME])
+ nread = 0;
+ }
+ if (nread > 0)
+ revents |= events & (POLLIN | POLLRDNORM);
+ }
+
+ if (events & (POLLOUT | POLLWRNORM))
+ if (tp->t_outq.c_cc <= tp->t_lowat)
+ revents |= events & (POLLOUT | POLLWRNORM);
+
+ if (revents == 0) {
+ if (events & (POLLIN | POLLRDNORM))
+ selrecord(p, &tp->t_rsel);
+
+ if (events & (POLLOUT | POLLWRNORM))
+ selrecord(p, &tp->t_wsel);
+ }
+ }
+
+ splx(s);
+ return (revents);
+} /* qdpoll() */
+
+
+void qd_strategy(struct buf *bp);
+
+/*ARGSUSED*/
+int
+qdwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct tty *tp;
+ register int minor_dev;
+ register int unit;
+
+ minor_dev = minor(dev);
+ unit = (minor_dev >> 2) & 0x07;
+
+ if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
+ /*
+ * this is the console...
+ */
+ tp = qd_tty[minor_dev];
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+ } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
+ /*
+ * this is a DMA xfer from user space
+ */
+ return (physio(qd_strategy, &qdbuf[unit],
+ dev, B_WRITE, minphys, uio));
+ }
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+int
+qdread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+{
+ register struct tty *tp;
+ register int minor_dev;
+ register int unit;
+
+ minor_dev = minor(dev);
+ unit = (minor_dev >> 2) & 0x07;
+
+ if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
+ /*
+ * this is the console
+ */
+ tp = qd_tty[minor_dev];
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+ } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
+ /*
+ * this is a bitmap-to-processor xfer
+ */
+ return (physio(qd_strategy, &qdbuf[unit],
+ dev, B_READ, minphys, uio));
+ }
+ return (ENXIO);
+}
+
+/***************************************************************
+*
+* qd_strategy()... strategy routine to do DMA
+*
+***************************************************************/
+
+void
+qd_strategy(bp)
+ register struct buf *bp;
+{
+ volatile register struct dga *dga;
+ volatile register struct adder *adder;
+ register int unit;
+ int QBAreg;
+ int s;
+ int cookie;
+ struct uba_softc *uh;
+
+ unit = (minor(bp->b_dev) >> 2) & 0x07;
+
+ uh = (struct uba_softc *)
+ (((struct device *)(qd_cd.cd_devs[unit]))->dv_parent);
+
+ /*
+ * init pointers
+ */
+ dga = (struct dga *) qdmap[unit].dga;
+panic("qd_strategy");
+#ifdef notyet
+ if ((QBAreg = ubasetup(uh, bp, 0)) == 0) {
+ printf("qd%d: qd_strategy: QBA setup error\n", unit);
+ goto STRAT_ERR;
+ }
+#endif
+ s = spl5();
+ qdflags[unit].user_dma = -1;
+ dga->csr |= DMA_IE;
+ cookie = QBAreg & 0x3FFFF;
+ dga->adrs_lo = (short) cookie;
+ dga->adrs_hi = (short) (cookie >> 16);
+ dga->bytcnt_lo = (short) bp->b_bcount;
+ dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
+
+ while (qdflags[unit].user_dma) {
+ sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
+ }
+ splx(s);
+#ifdef notyet
+ ubarelse(uh, &QBAreg);
+#endif
+ if (!(dga->csr & DMA_ERR)) {
+ biodone(bp);
+ return;
+ }
+
+/* STRAT_ERR: */
+ adder = (struct adder *) qdmap[unit].adder;
+ adder->command = CANCEL; /* cancel adder activity */
+ dga->csr &= ~DMA_IE;
+ dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
+ dga->csr |= DMA_ERR; /* clear error condition */
+ bp->b_flags |= B_ERROR; /* flag an error to physio() */
+
+ /*
+ * if DMA was running, flush spurious intrpt
+ */
+ if (dga->bytcnt_lo != 0) {
+ dga->bytcnt_lo = 0;
+ dga->bytcnt_hi = 0;
+ DMA_SETIGNORE(DMAheader[unit]);
+ dga->csr |= DMA_IE;
+ }
+ biodone(bp);
+} /* qd_strategy */
+
+
+/*
+ * Start output to the console screen
+ */
+void qdstart(tp)
+ struct tty *tp;
+{
+ register int which_unit, unit, c;
+ int s;
+
+ unit = minor(tp->t_dev);
+ which_unit = (unit >> 2) & 0x3;
+ unit &= 0x03;
+
+ s = spl5();
+
+ /*
+ * If it's currently active, or delaying, no need to do anything.
+ */
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ goto out;
+
+ /*
+ * Display chars until the queue is empty.
+ * Drop input from anything but the console
+ * device on the floor.
+ *
+ * XXX - this loop is done at spltty.
+ *
+ */
+ while (tp->t_outq.c_cc) {
+ c = getc(&tp->t_outq);
+ if (unit == 0)
+ blitc(which_unit, (u_char)c);
+ }
+ /*
+ * If there are sleepers, and output has drained below low
+ * water mark, wake up the sleepers.
+ */
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP){
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t) &tp->t_outq);
+ }
+ }
+
+ tp->t_state &= ~TS_BUSY;
+
+out:
+ splx(s);
+
+} /* qdstart */
+
+/*ARGSUSED*/
+void
+qdstop(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+ register int s;
+
+ s = spl5(); /* block intrpts during state modification */
+ if (tp->t_state & TS_BUSY) {
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ else
+ tp->t_state &= ~TS_BUSY;
+ }
+ splx(s);
+}
+
+/*
+ * Output a character to the QDSS screen
+ */
+void
+blitc(unit, chr)
+ int unit;
+ u_char chr;
+{
+ volatile register struct adder *adder;
+ volatile register struct dga *dga;
+ register int i;
+ int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
+ static short inescape[NQD];
+
+ adder = (struct adder *)qdmap[unit].adder;
+ dga = (struct dga *) qdmap[unit].dga;
+ /*
+ * BSD comment: this (&=0177) defeats the extended character
+ * set code for the glass tty, but if i had the time i would
+ * spend it ripping out the code completely. This driver
+ * is too big for its own good.
+ */
+ chr &= 0177;
+ /*
+ * Cursor addressing (so vi will work).
+ * Decode for "\E=%.%." cursor motion description.
+ * Corresponds to type "qdcons" in /etc/termcap:
+ *
+ * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
+ * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
+ *
+ */
+ if (inescape[unit] && nograph) {
+ switch (inescape[unit]++) {
+ case 1:
+ if (chr != '=') {
+ /* abort escape sequence */
+ inescape[unit] = 0;
+ blitc(unit, chr);
+ }
+ return;
+ case 2:
+ /* position row */
+ cursor[unit].y = CHAR_HEIGHT * chr;
+ if (cursor[unit].y > 863 - CHAR_HEIGHT)
+ cursor[unit].y = 863 - CHAR_HEIGHT;
+ dga->y_cursor = TRANY(cursor[unit].y);
+ return;
+ case 3:
+ /* position column */
+ cursor[unit].x = CHAR_WIDTH * chr;
+ if (cursor[unit].x > 1024 - CHAR_WIDTH)
+ cursor[unit].x = 1023 - CHAR_WIDTH;
+ dga->x_cursor = TRANX(cursor[unit].x);
+ inescape[unit] = 0;
+ return;
+ default:
+ inescape[unit] = 0;
+ blitc(unit, chr);
+ }
+ }
+
+ switch (chr) {
+ case '\r': /* return char */
+ cursor[unit].x = 0;
+ if (nograph)
+ dga->x_cursor = TRANX(cursor[unit].x);
+ return;
+
+ case '\t': /* tab char */
+ for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
+ blitc(unit, ' ');
+ }
+ return;
+
+ case '\n': /* line feed char */
+ if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
+ if (nograph) {
+ cursor[unit].y -= CHAR_HEIGHT;
+ scroll_up(adder);
+ } else
+ cursor[unit].y = 0;
+ }
+ if (nograph)
+ dga->y_cursor = TRANY(cursor[unit].y);
+ return;
+
+ case '\b': /* backspace char */
+ if (cursor[unit].x > 0) {
+ cursor[unit].x -= CHAR_WIDTH;
+ if (nograph)
+ dga->x_cursor = TRANX(cursor[unit].x);
+ }
+ return;
+ case CTRL('k'): /* cursor up */
+ if (nograph && cursor[unit].y > 0) {
+ cursor[unit].y -= CHAR_HEIGHT;
+ dga->y_cursor = TRANY(cursor[unit].y);
+ }
+ return;
+
+ case CTRL('^'): /* home cursor */
+ if (nograph) {
+ cursor[unit].x = 0;
+ dga->x_cursor = TRANX(cursor[unit].x);
+ cursor[unit].y = 0;
+ dga->y_cursor = TRANY(cursor[unit].y);
+ }
+ return;
+
+ case CTRL('l'): /* cursor right */
+ if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
+ cursor[unit].x += CHAR_WIDTH;
+ dga->x_cursor = TRANX(cursor[unit].x);
+ }
+ return;
+
+ case CTRL('z'): /* clear screen */
+ if (nograph) {
+ setup_dragon(unit);
+ clear_qd_screen(unit);
+ /* home cursor - termcap seems to assume this */
+ cursor[unit].x = 0;
+ dga->x_cursor = TRANX(cursor[unit].x);
+ cursor[unit].y = 0;
+ dga->y_cursor = TRANY(cursor[unit].y);
+ }
+ return;
+
+ case '\033': /* start escape sequence */
+ if (nograph)
+ inescape[unit] = 1;
+ return;
+
+ default:
+ if ((chr < ' ') || (chr > '~'))
+ return;
+ }
+ /*
+ * setup VIPER operand control registers
+ */
+ write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */
+ write_ID(adder, SRC1_OCR_B,
+ EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
+ write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */
+ write_ID(adder, SRC1_OCR_B,
+ EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
+ write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
+ write_ID(adder, DST_OCR_B,
+ EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
+ write_ID(adder, MASK_1, 0xFFFF);
+ write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
+ write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+ adder->x_clip_min = 0;
+ adder->x_clip_max = 1024;
+ adder->y_clip_min = 0;
+ adder->y_clip_max = 864;
+ /*
+ * load DESTINATION origin and vectors
+ */
+ adder->fast_dest_dy = 0;
+ adder->slow_dest_dx = 0;
+ adder->error_1 = 0;
+ adder->error_2 = 0;
+ adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
+ (void)wait_status(adder, RASTEROP_COMPLETE);
+ adder->destination_x = cursor[unit].x;
+ adder->fast_dest_dx = CHAR_WIDTH;
+ adder->destination_y = cursor[unit].y;
+ adder->slow_dest_dy = CHAR_HEIGHT;
+ /*
+ * load SOURCE origin and vectors
+ */
+ if ((chr - ' ') > (CHARS - 1)) {
+ printf("Invalid character (x)%x in blitc\n",chr);
+ chr = ' ';
+ }
+ /*
+ * X position is modulo the number of characters per line
+ */
+ adder->source_1_x = FONT_X +
+ (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
+ /*
+ * Point to either first or second row
+ */
+ adder->source_1_y = 2048 - 15 *
+ (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
+ adder->source_1_dx = CHAR_WIDTH;
+ adder->source_1_dy = CHAR_HEIGHT;
+ write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
+ adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
+ /*
+ * update console cursor coordinates
+ */
+ cursor[unit].x += CHAR_WIDTH;
+ if (nograph)
+ dga->x_cursor = TRANX(cursor[unit].x);
+ if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
+ blitc(unit, '\r');
+ blitc(unit, '\n');
+ }
+
+} /* blitc */
+
+/*
+ * INTERRUPT SERVICE ROUTINES
+ */
+
+/*
+ * Service "DMA DONE" interrupt condition
+ */
+
+static void
+qddint(arg)
+ void *arg;
+{
+ struct device *dv = arg;
+ register struct DMAreq_header *header;
+ register struct DMAreq *request;
+ volatile register struct dga *dga;
+ volatile struct adder *adder;
+ int cookie; /* DMA adrs for QDSS */
+
+ (void)spl4(); /* allow interval timer in */
+
+ /*
+ * init pointers
+ */
+ header = DMAheader[dv->dv_unit]; /* register for optimization */
+ dga = (struct dga *) qdmap[dv->dv_unit].dga;
+ adder = (struct adder *) qdmap[dv->dv_unit].adder;
+
+ /*
+ * if this interrupt flagged as bogus for interrupt flushing purposes..
+ */
+ if (DMA_ISIGNORE(header)) {
+ DMA_CLRIGNORE(header);
+ return;
+ }
+
+ /*
+ * dump a DMA hardware error message if appropriate
+ */
+ if (dga->csr & DMA_ERR) {
+
+ if (dga->csr & PARITY_ERR)
+ printf("qd%d: qddint: DMA hardware parity fault.\n", dv->dv_unit);
+
+ if (dga->csr & BUS_ERR)
+ printf("qd%d: qddint: DMA hardware bus error.\n", dv->dv_unit);
+ }
+
+ /*
+ * if this was a DMA from user space...
+ */
+ if (qdflags[dv->dv_unit].user_dma) {
+ qdflags[dv->dv_unit].user_dma = 0;
+ wakeup((caddr_t)&qdflags[dv->dv_unit].user_dma);
+ return;
+ }
+
+ /*
+ * if we're doing DMA request queue services, field the error condition
+ */
+ if (dga->csr & DMA_ERR) {
+
+ dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
+ dga->csr |= DMA_ERR; /* clear error condition */
+ adder->command = CANCEL; /* cancel adder activity */
+
+ DMA_SETERROR(header); /* flag error in header status word */
+ DMA_CLRACTIVE(header);
+ header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
+ header->newest = header->oldest;
+ header->used = 0;
+
+ if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_WRITE;
+ }
+
+ if (dga->bytcnt_lo != 0) {
+ dga->bytcnt_lo = 0;
+ dga->bytcnt_hi = 0;
+ DMA_SETIGNORE(header);
+ }
+ return;
+ }
+
+ /*
+ * if the DMA request queue is now becoming non-full,
+ * wakeup "select" client.
+ */
+ if (DMA_ISFULL(header)) {
+ if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_WRITE;
+ }
+ }
+
+ header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
+ QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
+
+ /* check for unexpected interrupt */
+ if (DMA_ISEMPTY(header))
+ return;
+
+ DMA_GETEND(header); /* update request queue indices */
+
+ /*
+ * if no more DMA pending, wake up "select" client and exit
+ */
+ if (DMA_ISEMPTY(header)) {
+ if (qdrsel[dv->dv_unit].si_pid && qdflags[dv->dv_unit].selmask & SEL_WRITE) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_WRITE;
+ }
+ DMA_CLRACTIVE(header); /* flag DMA done */
+ return;
+ }
+
+ /*
+ * initiate next DMA xfer
+ */
+ request = DMA_GETBEGIN(header);
+ if (request->DMAtype != QDlast_DMAtype) {
+ dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
+ adder->command = CANCEL; /* cancel adder activity */
+ }
+
+
+ switch (request->DMAtype) {
+
+ case DISPLIST:
+ if (request->DMAtype != QDlast_DMAtype) {
+ dga->csr |= DL_ENB;
+ dga->csr &= ~(BTOP_ENB | BYTE_DMA);
+ }
+ break;
+
+ case PTOB:
+ if (request->DMAtype != QDlast_DMAtype) {
+ if (request->DMAdone & BYTE_PACK)
+ dga->csr |= (PTOB_ENB | BYTE_DMA);
+ else {
+ dga->csr |= PTOB_ENB;
+ dga->csr &= ~BYTE_DMA;
+ }
+ }
+ break;
+
+ case BTOP:
+ if (request->DMAtype != QDlast_DMAtype) {
+ if (request->DMAdone & BYTE_PACK) {
+ dga->csr &= ~DL_ENB;
+ dga->csr |= (BTOP_ENB | BYTE_DMA);
+ }
+ else {
+ dga->csr |= BTOP_ENB;
+ dga->csr &= ~(BYTE_DMA | DL_ENB);
+ }
+ }
+ break;
+ default:
+ printf("qd%d: qddint: illegal DMAtype parameter.\n", dv->dv_unit);
+ DMA_CLRACTIVE(header); /* flag DMA done */
+ return;
+ }
+
+ if (request->DMAdone & COUNT_ZERO) {
+ dga->csr &= ~SET_DONE_FIFO;
+ }
+ else if (request->DMAdone & FIFO_EMPTY) {
+ dga->csr |= SET_DONE_FIFO;
+ }
+
+ if (request->DMAdone & WORD_PACK)
+ dga->csr &= ~BYTE_DMA;
+ else if (request->DMAdone & BYTE_PACK)
+ dga->csr |= BYTE_DMA;
+
+ dga->csr |= DMA_IE;
+ QDlast_DMAtype = request->DMAtype;
+
+ cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
+
+ dga->adrs_lo = (short) cookie;
+ dga->adrs_hi = (short) (cookie >> 16);
+
+ dga->bytcnt_lo = (short) request->length;
+ dga->bytcnt_hi = (short) (request->length >> 16);
+
+ return;
+}
+
+/*
+ * ADDER interrupt service routine
+ */
+static void
+qdaint(arg)
+ void *arg;
+{
+ struct device *dv = arg;
+ volatile register struct adder *adder;
+ struct color_buf *cbuf;
+ int i;
+ register struct rgb *rgbp;
+ volatile register short *red;
+ volatile register short *green;
+ volatile register short *blue;
+
+ (void)spl4(); /* allow interval timer in */
+
+ adder = (struct adder *) qdmap[dv->dv_unit].adder;
+
+ /*
+ * service the vertical blank interrupt (VSYNC bit) by loading
+ * any pending color map load request
+ */
+ if (adder->status & VSYNC) {
+ adder->status &= ~VSYNC; /* clear the interrupt */
+ cbuf = color_buf[dv->dv_unit];
+ if (cbuf->status & LOAD_COLOR_MAP) {
+
+ red = (short *) qdmap[dv->dv_unit].red;
+ green = (short *) qdmap[dv->dv_unit].green;
+ blue = (short *) qdmap[dv->dv_unit].blue;
+
+ for (i = cbuf->count, rgbp = cbuf->rgb;
+ --i >= 0; rgbp++) {
+ red[rgbp->offset] = (short) rgbp->red;
+ green[rgbp->offset] = (short) rgbp->green;
+ blue[rgbp->offset] = (short) rgbp->blue;
+ }
+
+ cbuf->status &= ~LOAD_COLOR_MAP;
+ }
+ }
+
+ /*
+ * service the scroll interrupt (FRAME_SYNC bit)
+ */
+ if (adder->status & FRAME_SYNC) {
+ adder->status &= ~FRAME_SYNC; /* clear the interrupt */
+
+ if (scroll[dv->dv_unit]->status & LOAD_REGS) {
+
+ for (i = 1000, adder->status = 0; i > 0 &&
+ !(adder->status&ID_SCROLL_READY); --i)
+ ;
+
+ if (i == 0) {
+ printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
+ qd);
+ return;
+ }
+
+ adder->ID_scroll_data = scroll[dv->dv_unit]->viper_constant;
+ adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
+
+ adder->y_scroll_constant =
+ scroll[dv->dv_unit]->y_scroll_constant;
+ adder->y_offset_pending = scroll[dv->dv_unit]->y_offset;
+
+ if (scroll[dv->dv_unit]->status & LOAD_INDEX) {
+
+ adder->x_index_pending =
+ scroll[dv->dv_unit]->x_index_pending;
+ adder->y_index_pending =
+ scroll[dv->dv_unit]->y_index_pending;
+ }
+
+ scroll[dv->dv_unit]->status = 0x00;
+ }
+ }
+}
+
+/*
+ * DUART input interrupt service routine
+ *
+ * XXX - this routine should be broken out - it is essentially
+ * straight line code.
+ */
+
+static void
+qdiint(arg)
+ void *arg;
+{
+ struct device *dv = arg;
+ register struct _vs_event *event;
+ register struct qdinput *eqh;
+ volatile struct dga *dga;
+ volatile struct duart *duart;
+ struct mouse_report *new_rep;
+ struct tty *tp;
+ u_short chr;
+ u_short status;
+ u_short data;
+ u_short key;
+ char do_wakeup = 0; /* flag to do a select wakeup call */
+ char a, b, c; /* mouse button test variables */
+
+ (void)spl4(); /* allow interval timer in */
+
+ eqh = eq_header[dv->dv_unit]; /* optimized as a register */
+ new_rep = ¤t_rep[dv->dv_unit];
+ duart = (struct duart *) qdmap[dv->dv_unit].duart;
+
+ /*
+ * if the graphic device is turned on..
+ */
+ if (qdflags[dv->dv_unit].inuse & GRAPHIC_DEV) {
+ /*
+ * empty DUART
+ */
+ while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
+ /*
+ * pick up LK-201 input (if any)
+ */
+ if (duart->statusA&RCV_RDY) {
+
+ /* if error condition, then reset it */
+
+ if (duart->statusA&0x70) {
+ duart->cmdA = 0x40;
+ continue;
+ }
+
+ /* event queue full now? (overflow condition) */
+
+ if (ISFULL(eqh) == TRUE) {
+ printf(
+ "qd%d: qdiint: event queue overflow\n",
+ qd);
+ break;
+ }
+
+ /*
+ * Check for various keyboard errors */
+
+ key = duart->dataA & 0xFF;
+
+ if (key==LK_POWER_ERROR ||
+ key==LK_KDOWN_ERROR ||
+ key == LK_INPUT_ERROR ||
+ key == LK_OUTPUT_ERROR) {
+ printf(
+ "qd%d: qdiint: keyboard error, code = %x\n",
+ qd,key);
+ return;
+ }
+
+ if (key < LK_LOWEST)
+ return;
+
+ ++do_wakeup; /* request a select wakeup call */
+
+ event = PUTBEGIN(eqh);
+ PUTEND(eqh);
+
+ event->vse_key = key;
+ event->vse_key &= 0x00FF;
+ event->vse_x = eqh->curs_pos.x;
+ event->vse_y = eqh->curs_pos.y;
+ event->vse_time = TOY;
+ event->vse_type = VSE_BUTTON;
+ event->vse_direction = VSE_KBTRAW;
+ event->vse_device = VSE_DKB;
+ }
+
+ /*
+ * pick up the mouse input (if any) */
+
+ if ((status = duart->statusB) & RCV_RDY &&
+ qdflags[dv->dv_unit].pntr_id == MOUSE_ID) {
+
+ if (status & 0x70) {
+ duart->cmdB = 0x40;
+ continue;
+ }
+
+ /* event queue full now? (overflow condition) */
+
+ if (ISFULL(eqh) == TRUE) {
+ printf(
+ "qd%d: qdiint: event queue overflow\n",
+ qd);
+ break;
+ }
+
+ data = duart->dataB; /* get report byte */
+ ++new_rep->bytcnt; /* bump report byte count */
+
+ /*
+ * if 1st byte of report.. */
+
+ if ( data & START_FRAME) {
+ new_rep->state = data;
+ if (new_rep->bytcnt > 1) {
+ /* start of new frame */
+ new_rep->bytcnt = 1;
+ /* ..continue looking */
+ continue;
+ }
+ }
+
+ /*
+ * if 2nd byte of report.. */
+
+ else if (new_rep->bytcnt == 2) {
+ new_rep->dx = data & 0x00FF;
+ }
+
+ /*
+ * if 3rd byte of report, load input event queue */
+
+ else if (new_rep->bytcnt == 3) {
+
+ new_rep->dy = data & 0x00FF;
+ new_rep->bytcnt = 0;
+
+ /*
+ * if mouse position has changed.. */
+
+ if (new_rep->dx != 0 || new_rep->dy != 0) {
+
+ /*
+ * calculate acceleration factor, if needed */
+
+ if (qdflags[dv->dv_unit].curs_acc > ACC_OFF) {
+
+ if (qdflags[dv->dv_unit].curs_thr <= new_rep->dx)
+ new_rep->dx +=
+ (new_rep->dx - qdflags[dv->dv_unit].curs_thr)
+ * qdflags[dv->dv_unit].curs_acc;
+
+ if (qdflags[dv->dv_unit].curs_thr <= new_rep->dy)
+ new_rep->dy +=
+ (new_rep->dy - qdflags[dv->dv_unit].curs_thr)
+ * qdflags[dv->dv_unit].curs_acc;
+ }
+
+ /*
+ * update cursor position coordinates */
+
+ if (new_rep->state & X_SIGN) {
+ eqh->curs_pos.x += new_rep->dx;
+ if (eqh->curs_pos.x > 1023)
+ eqh->curs_pos.x = 1023;
+ }
+ else {
+ eqh->curs_pos.x -= new_rep->dx;
+ if (eqh->curs_pos.x < -15)
+ eqh->curs_pos.x = -15;
+ }
+
+ if (new_rep->state & Y_SIGN) {
+ eqh->curs_pos.y -= new_rep->dy;
+ if (eqh->curs_pos.y < -15)
+ eqh->curs_pos.y = -15;
+ }
+ else {
+ eqh->curs_pos.y += new_rep->dy;
+ if (eqh->curs_pos.y > 863)
+ eqh->curs_pos.y = 863;
+ }
+
+ /*
+ * update cursor screen position */
+
+ dga = (struct dga *) qdmap[dv->dv_unit].dga;
+ dga->x_cursor = TRANX(eqh->curs_pos.x);
+ dga->y_cursor = TRANY(eqh->curs_pos.y);
+
+ /*
+ * if cursor is in the box, no event report */
+
+ if (eqh->curs_pos.x <= eqh->curs_box.right &&
+ eqh->curs_pos.x >= eqh->curs_box.left &&
+ eqh->curs_pos.y >= eqh->curs_box.top &&
+ eqh->curs_pos.y <= eqh->curs_box.bottom ) {
+ goto GET_MBUTTON;
+ }
+
+ /*
+ * report the mouse motion event */
+
+ event = PUTBEGIN(eqh);
+ PUTEND(eqh);
+
+ ++do_wakeup; /* request a select wakeup call */
+
+ event->vse_x = eqh->curs_pos.x;
+ event->vse_y = eqh->curs_pos.y;
+
+ event->vse_device = VSE_MOUSE; /* mouse */
+ event->vse_type = VSE_MMOTION; /* pos changed */
+ event->vse_key = 0;
+ event->vse_direction = 0;
+ event->vse_time = TOY; /* time stamp */
+ }
+
+GET_MBUTTON:
+ /*
+ * if button state has changed */
+
+ a = new_rep->state & 0x07; /*mask nonbutton bits */
+ b = last_rep[dv->dv_unit].state & 0x07;
+
+ if (a ^ b) {
+
+ for ( c = 1; c < 8; c <<= 1) {
+
+ if (!( c & (a ^ b))) /* this button change? */
+ continue;
+
+ /* event queue full? (overflow condition) */
+
+ if (ISFULL(eqh) == TRUE) {
+ printf("qd%d: qdiint: event queue overflow\n", qd);
+ break;
+ }
+
+ event = PUTBEGIN(eqh); /* get new event */
+ PUTEND(eqh);
+
+ ++do_wakeup; /* request select wakeup */
+
+ event->vse_x = eqh->curs_pos.x;
+ event->vse_y = eqh->curs_pos.y;
+
+ event->vse_device = VSE_MOUSE; /* mouse */
+ event->vse_type = VSE_BUTTON; /* new button */
+ event->vse_time = TOY; /* time stamp */
+
+ /* flag changed button and if up or down */
+
+ if (c == RIGHT_BUTTON)
+ event->vse_key = VSE_RIGHT_BUTTON;
+ else if (c == MIDDLE_BUTTON)
+ event->vse_key = VSE_MIDDLE_BUTTON;
+ else if (c == LEFT_BUTTON)
+ event->vse_key = VSE_LEFT_BUTTON;
+
+ /* set bit = button depressed */
+
+ if (c & a)
+ event->vse_direction = VSE_KBTDOWN;
+ else
+ event->vse_direction = VSE_KBTUP;
+ }
+ }
+
+ /* refresh last report */
+
+ last_rep[dv->dv_unit] = current_rep[dv->dv_unit];
+
+ } /* get last byte of report */
+ } else if ((status = duart->statusB)&RCV_RDY &&
+ qdflags[dv->dv_unit].pntr_id == TABLET_ID) {
+ /*
+ * pickup tablet input, if any
+ */
+ if (status&0x70) {
+ duart->cmdB = 0x40;
+ continue;
+ }
+ /*
+ * event queue full now? (overflow condition)
+ */
+ if (ISFULL(eqh) == TRUE) {
+ printf("qd%d: qdiint: event queue overflow\n", qd);
+ break;
+ }
+
+ data = duart->dataB; /* get report byte */
+ ++new_rep->bytcnt; /* bump report byte count */
+
+ /*
+ * if 1st byte of report.. */
+
+ if (data & START_FRAME) {
+ new_rep->state = data;
+ if (new_rep->bytcnt > 1) {
+ new_rep->bytcnt = 1; /* start of new frame */
+ continue; /* ..continue looking */
+ }
+ }
+
+ /*
+ * if 2nd byte of report.. */
+
+ else if (new_rep->bytcnt == 2) {
+ new_rep->dx = data & 0x3F;
+ }
+
+ /*
+ * if 3rd byte of report.. */
+
+ else if (new_rep->bytcnt == 3) {
+ new_rep->dx |= (data & 0x3F) << 6;
+ }
+
+ /*
+ * if 4th byte of report.. */
+
+ else if (new_rep->bytcnt == 4) {
+ new_rep->dy = data & 0x3F;
+ }
+
+ /*
+ * if 5th byte of report, load input event queue */
+
+ else if (new_rep->bytcnt == 5) {
+
+ new_rep->dy |= (data & 0x3F) << 6;
+ new_rep->bytcnt = 0;
+
+ /*
+ * update cursor position coordinates */
+
+ new_rep->dx /= qdflags[dv->dv_unit].tab_res;
+ new_rep->dy = (2200 - new_rep->dy)
+ / qdflags[dv->dv_unit].tab_res;
+
+ if (new_rep->dx > 1023) {
+ new_rep->dx = 1023;
+ }
+ if (new_rep->dy > 863) {
+ new_rep->dy = 863;
+ }
+
+ /*
+ * report an event if the puck/stylus has moved
+ */
+
+ if (eqh->curs_pos.x != new_rep->dx ||
+ eqh->curs_pos.y != new_rep->dy) {
+
+ eqh->curs_pos.x = new_rep->dx;
+ eqh->curs_pos.y = new_rep->dy;
+
+ /*
+ * update cursor screen position */
+
+ dga = (struct dga *) qdmap[dv->dv_unit].dga;
+ dga->x_cursor = TRANX(eqh->curs_pos.x);
+ dga->y_cursor = TRANY(eqh->curs_pos.y);
+
+ /*
+ * if cursor is in the box, no event report
+ */
+
+ if (eqh->curs_pos.x <= eqh->curs_box.right &&
+ eqh->curs_pos.x >= eqh->curs_box.left &&
+ eqh->curs_pos.y >= eqh->curs_box.top &&
+ eqh->curs_pos.y <= eqh->curs_box.bottom ) {
+ goto GET_TBUTTON;
+ }
+
+ /*
+ * report the tablet motion event */
+
+ event = PUTBEGIN(eqh);
+ PUTEND(eqh);
+
+ ++do_wakeup; /* request a select wakeup call */
+
+ event->vse_x = eqh->curs_pos.x;
+ event->vse_y = eqh->curs_pos.y;
+
+ event->vse_device = VSE_TABLET; /* tablet */
+ /*
+ * right now, X handles tablet motion the same
+ * as mouse motion
+ */
+ event->vse_type = VSE_MMOTION; /* pos changed */
+ event->vse_key = 0;
+ event->vse_direction = 0;
+ event->vse_time = TOY; /* time stamp */
+ }
+GET_TBUTTON:
+ /*
+ * if button state has changed */
+
+ a = new_rep->state & 0x1E; /* mask nonbutton bits */
+ b = last_rep[dv->dv_unit].state & 0x1E;
+
+ if (a ^ b) {
+
+ /* event queue full now? (overflow condition) */
+
+ if (ISFULL(eqh) == TRUE) {
+ printf("qd%d: qdiint: event queue overflow\n",qd);
+ break;
+ }
+
+ event = PUTBEGIN(eqh); /* get new event */
+ PUTEND(eqh);
+
+ ++do_wakeup; /* request a select wakeup call */
+
+ event->vse_x = eqh->curs_pos.x;
+ event->vse_y = eqh->curs_pos.y;
+
+ event->vse_device = VSE_TABLET; /* tablet */
+ event->vse_type = VSE_BUTTON; /* button changed */
+ event->vse_time = TOY; /* time stamp */
+
+ /* define the changed button and if up or down */
+
+ for ( c = 1; c <= 0x10; c <<= 1) {
+ if (c & (a ^ b)) {
+ if (c == T_LEFT_BUTTON)
+ event->vse_key = VSE_T_LEFT_BUTTON;
+ else if (c == T_FRONT_BUTTON)
+ event->vse_key = VSE_T_FRONT_BUTTON;
+ else if (c == T_RIGHT_BUTTON)
+ event->vse_key = VSE_T_RIGHT_BUTTON;
+ else if (c == T_BACK_BUTTON)
+ event->vse_key = VSE_T_BACK_BUTTON;
+ break;
+ }
+ }
+
+ /* set bit = button depressed */
+
+ if (c & a)
+ event->vse_direction = VSE_KBTDOWN;
+ else
+ event->vse_direction = VSE_KBTUP;
+ }
+
+ /* refresh last report */
+
+ last_rep[dv->dv_unit] = current_rep[dv->dv_unit];
+
+ } /* get last byte of report */
+ } /* pick up tablet input */
+
+ } /* while input available.. */
+
+ /*
+ * do select wakeup
+ */
+ if (qdrsel[dv->dv_unit].si_pid && do_wakeup && qdflags[dv->dv_unit].selmask & SEL_READ) {
+ selwakeup(&qdrsel[dv->dv_unit]);
+ qdrsel[dv->dv_unit].si_pid = 0;
+ qdflags[dv->dv_unit].selmask &= ~SEL_READ;
+ do_wakeup = 0;
+ }
+ } else {
+ /*
+ * if the graphic device is not turned on, this is console input
+ */
+ if (qdpolling)
+ return;
+
+ if (dv->dv_unit >= qd_cd.cd_ndevs || qd_cd.cd_devs[dv->dv_unit] == NULL)
+ return; /* no such device or address */
+
+ tp = qd_tty[dv->dv_unit << 2];
+
+ /*
+ * Get a character from the keyboard.
+ */
+ while (duart->statusA&RCV_RDY) {
+ key = duart->dataA;
+ key &= 0xFF;
+ /*
+ * Check for various keyboard errors
+ */
+ if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
+ key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
+ printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
+ return;
+ }
+
+ if (key < LK_LOWEST)
+ return;
+
+ /*
+ * See if its a state change key */
+
+ switch (key) {
+
+ case LOCK:
+ q_keyboard.lock ^= 0xffff; /* toggle */
+ if (q_keyboard.lock)
+ led_control(qd, LK_LED_ENABLE,
+ LK_LED_LOCK);
+ else
+ led_control(qd, LK_LED_DISABLE,
+ LK_LED_LOCK);
+ return;
+
+ case SHIFT:
+ q_keyboard.shift ^= 0xFFFF;
+ return;
+
+ case CNTRL:
+ q_keyboard.cntrl ^= 0xFFFF;
+ return;
+
+ case ALLUP:
+ q_keyboard.cntrl = 0;
+ q_keyboard.shift = 0;
+ return;
+
+ case REPEAT:
+ chr = q_keyboard.last;
+ break;
+
+ /*
+ * Test for cntrl characters. If set, see if the character
+ * is elligible to become a control character. */
+
+ default:
+
+ if (q_keyboard.cntrl) {
+ chr = q_key[key];
+ if (chr >= ' ' && chr <= '~')
+ chr &= 0x1F;
+ else if (chr >= 0xA1 && chr <= 0xFE)
+ chr &= 0x9F;
+ }
+ else if( q_keyboard.lock || q_keyboard.shift )
+ chr = q_shift_key[key];
+ else
+ chr = q_key[key];
+ break;
+ }
+
+ q_keyboard.last = chr;
+
+ /*
+ * Check for special function keys */
+
+ if (chr & 0x100) {
+ char *string;
+ string = q_special[chr & 0x7F];
+ while(*string)
+ (*linesw[tp->t_line].l_rint)(*string++, tp);
+ }
+ else {
+#ifdef DDB
+ /* Check for kernel debugger escape here */
+ int j;
+
+ j = kdbrint(chr&0177);
+
+ if (j == 1) /* Escape received, just return */
+ return;
+
+ if (j == 2) /* Second char wasn't 'D' */
+ (*linesw[tp->t_line].l_rint)(27, tp);
+#endif
+ (*linesw[tp->t_line].l_rint)(chr&0177, tp);
+ }
+ }
+ }
+} /* qdiint */
+
+/*
+ *
+ * Clear the QDSS screen
+ *
+ * >>> NOTE <<<
+ *
+ * This code requires that certain adder initialization be valid. To
+ * assure that this requirement is satisfied, this routine should be
+ * called only after calling the "setup_dragon()" function.
+ *
+ * Clear the bitmap a piece at a time. Since the fast scroll clear
+ * only clears the current displayed portion of the bitmap put a
+ * temporary value in the y limit register so we can access whole
+ * bitmap
+ *
+ */
+void
+clear_qd_screen(unit)
+ int unit;
+{
+ volatile register struct adder *adder;
+ adder = (struct adder *) qdmap[unit].adder;
+
+ adder->x_limit = 1024;
+ adder->y_limit = 2048 - CHAR_HEIGHT;
+ adder->y_offset_pending = 0;
+#define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
+ WSV;
+ adder->y_scroll_constant = SCROLL_ERASE;
+ WSV;
+ adder->y_offset_pending = 864;
+ WSV;
+ adder->y_scroll_constant = SCROLL_ERASE;
+ WSV;
+ adder->y_offset_pending = 1728;
+ WSV;
+ adder->y_scroll_constant = SCROLL_ERASE;
+ WSV;
+ adder->y_offset_pending = 0; /* back to normal */
+ WSV;
+ adder->x_limit = MAX_SCREEN_X;
+ adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
+#undef WSV
+
+} /* clear_qd_screen */
+
+/*
+ * kernel console output to the glass tty
+ */
+void
+qdcnputc(dev, chr)
+ dev_t dev;
+ int chr;
+{
+
+ /*
+ * if system is now physical, forget it (ie: crash DUMP)
+ */
+ if ((mfpr(PR_MAPEN) & 1) == 0)
+ return;
+
+ blitc(0, (u_char)(chr & 0xff));
+ if ((chr & 0177) == '\n')
+ blitc(0, '\r');
+
+} /* qdputc */
+
+/*
+ * load the mouse cursor's template RAM bitmap
+ */
+void
+ldcursor(unit, bitmap)
+ int unit;
+ short *bitmap;
+{
+ volatile register struct dga *dga;
+ volatile register short *temp;
+ register int i;
+ int curs;
+
+ dga = (struct dga *) qdmap[unit].dga;
+ temp = (short *) qdmap[unit].template;
+
+ if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */
+ curs = -1; /* ..note that.. */
+ dga->csr &= ~CURS_ENB; /* ..and shut it off */
+ } else
+ curs = 0;
+
+ dga->csr &= ~CURS_ENB; /* shut off the cursor */
+
+ temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */
+ /* ..of the 8k WORD template space */
+ for (i = 0; i < 32; ++i)
+ *temp++ = *bitmap++;
+
+ if (curs) { /* if cursor was enabled.. */
+ dga->csr |= CURS_ENB; /* ..turn it back on */
+ }
+
+} /* ldcursor */
+
+/*
+ * Put the console font in the QDSS off-screen memory
+ */
+void
+ldfont(unit)
+ int unit;
+{
+ volatile register struct adder *adder;
+
+ register int i, j, k, max_chars_line;
+ register short packed;
+
+ adder = (struct adder *) qdmap[unit].adder;
+
+ /*
+ * setup VIPER operand control registers
+ */
+ write_ID(adder, MASK_1, 0xFFFF);
+ write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
+ write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+
+ write_ID(adder, SRC1_OCR_B,
+ EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
+ write_ID(adder, SRC2_OCR_B,
+ EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
+ write_ID(adder, DST_OCR_B,
+ EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
+
+ adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
+
+ /*
+ * load destination data
+ */
+ (void)wait_status(adder, RASTEROP_COMPLETE);
+
+ adder->destination_x = FONT_X;
+ adder->destination_y = FONT_Y;
+#if FONT_WIDTH > MAX_SCREEN_X
+ adder->fast_dest_dx = MAX_SCREEN_X;
+#else
+ adder->fast_dest_dx = FONT_WIDTH;
+#endif
+ adder->slow_dest_dy = CHAR_HEIGHT;
+
+ /*
+ * setup for processor to bitmap xfer */
+
+ write_ID(adder, CS_UPDATE_MASK, 0x0001);
+ adder->cmd = PBT | OCRB | 2 | DTE | 2;
+
+ /*
+ * Figure out how many characters can be stored on one "line" of
+ * offscreen memory.
+ */
+ max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
+ if ((CHARS/2 + CHARS%2) < max_chars_line)
+ max_chars_line = CHARS/2 + CHARS%2;
+
+ /*
+ * iteratively do the processor to bitmap xfer */
+
+ for (i = 0; i < ROWS; ++i) {
+
+ /* PTOB a scan line */
+
+ for (j = 0, k = i; j < max_chars_line; ++j) {
+ /* PTOB one scan of a char cell */
+
+ packed = q_font[k];
+ k += ROWS;
+ packed |= ((short)q_font[k] << 8);
+ k += ROWS;
+
+ (void)wait_status(adder, TX_READY);
+ adder->id_data = packed;
+ }
+ }
+
+ /*
+ * (XXX XXX XXX - should remove)
+ *
+ * Copy the second row of characters. Subtract the first
+ * row from the total number. Divide this quantity by 2
+ * because 2 chars are stored in a short in the PTOB loop
+ * below. Figure out how many characters can be stored on
+ * one "line" of offscreen memory
+ */
+
+ max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
+ if ((CHARS/2 + CHARS%2) < max_chars_line)
+ return;
+ max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
+ /* Paranoia check to see if 3rd row may be needed */
+ if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
+ max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
+
+ adder->destination_x = FONT_X;
+ adder->destination_y = FONT_Y - CHAR_HEIGHT;
+ adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
+ adder->slow_dest_dy = CHAR_HEIGHT;
+
+ /*
+ * setup for processor to bitmap xfer
+ */
+ write_ID(adder, CS_UPDATE_MASK, 0x0001);
+ adder->cmd = PBT | OCRB | 2 | DTE | 2;
+
+ /*
+ * iteratively do the processor to bitmap xfer
+ */
+ for (i = 0; i < ROWS; ++i) {
+ /*
+ * PTOB a scan line
+ */
+ for (j = 0, k = i; j < max_chars_line; ++j) {
+ /*
+ * PTOB one scan of a char cell
+ */
+ packed = q_font[k + FONT_OFFSET];
+ k += ROWS;
+ packed |= ((short)q_font[k + FONT_OFFSET] << 8);
+ k += ROWS;
+ (void)wait_status(adder, TX_READY);
+ adder->id_data = packed;
+ }
+ }
+
+} /* ldfont */
+
+
+/*
+ * Disable or enable polling. This is used when entering or leaving the
+ * kernel debugger.
+ */
+void
+qdcnpollc(dev, onoff)
+ dev_t dev;
+ int onoff;
+{
+ qdpolling = onoff;
+}
+
+
+/*
+ * Get a character from the LK201 (polled)
+ */
+int
+qdcngetc(dev)
+ dev_t dev;
+{
+ register short key;
+ register char chr;
+ volatile register struct duart *duart;
+
+ duart = (struct duart *) qdmap[0].duart;
+
+ /*
+ * Get a character from the keyboard.
+ */
+LOOP:
+ while (!(duart->statusA&RCV_RDY))
+ ;
+
+ key = duart->dataA;
+ key &= 0xFF;
+
+ /*
+ * Check for various keyboard errors */
+
+ if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
+ key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
+ printf("Keyboard error, code = %x\n", key);
+ return(0);
+ }
+
+ if (key < LK_LOWEST)
+ return(0);
+
+ /*
+ * See if its a state change key
+ */
+ switch (key) {
+
+ case LOCK:
+ q_keyboard.lock ^= 0xffff; /* toggle */
+ if (q_keyboard.lock)
+ led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
+ else
+ led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
+ goto LOOP;
+
+ case SHIFT:
+ q_keyboard.shift ^= 0xFFFF;
+ goto LOOP;
+
+ case CNTRL:
+ q_keyboard.cntrl ^= 0xFFFF;
+ goto LOOP;
+
+ case ALLUP:
+ q_keyboard.cntrl = 0;
+ q_keyboard.shift = 0;
+ goto LOOP;
+
+ case REPEAT:
+ chr = q_keyboard.last;
+ break;
+
+ /*
+ * Test for cntrl characters. If set, see if the character
+ * is elligible to become a control character.
+ */
+ default:
+
+ if (q_keyboard.cntrl) {
+ chr = q_key[key];
+ if (chr >= ' ' && chr <= '~')
+ chr &= 0x1F;
+ }
+ else if ( q_keyboard.lock || q_keyboard.shift )
+ chr = q_shift_key[key];
+ else
+ chr = q_key[key];
+ break;
+ }
+
+ if (chr < ' ' && chr > '~') /* if input is non-displayable */
+ return(0); /* ..then pitch it! */
+
+ q_keyboard.last = chr;
+
+ /*
+ * Check for special function keys */
+
+ if (chr & 0x80) /* pitch the function keys */
+ return(0);
+ else
+ return(chr);
+
+} /* qdgetc */
+
+/*
+ * led_control()... twiddle LK-201 LED's
+ */
+void
+led_control(unit, cmd, led_mask)
+ int unit, cmd, led_mask;
+{
+ register int i;
+ volatile register struct duart *duart;
+
+ duart = (struct duart *)qdmap[unit].duart;
+
+ for (i = 1000; i > 0; --i) {
+ if (duart->statusA&XMT_RDY) {
+ duart->dataA = cmd;
+ break;
+ }
+ }
+ for (i = 1000; i > 0; --i) {
+ if (duart->statusA&XMT_RDY) {
+ duart->dataA = led_mask;
+ break;
+ }
+ }
+ return;
+
+} /* led_control */
+
+/*
+ * scroll_up()... move the screen up one character height
+ */
+void
+scroll_up(adder)
+ volatile struct adder *adder;
+{
+ /*
+ * setup VIPER operand control registers
+ */
+ (void)wait_status(adder, ADDRESS_COMPLETE);
+ write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
+ write_ID(adder, MASK_1, 0xFFFF);
+ write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
+ write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+ write_ID(adder, SRC1_OCR_B,
+ EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
+ write_ID(adder, DST_OCR_B,
+ EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
+ /*
+ * load DESTINATION origin and vectors
+ */
+ adder->fast_dest_dy = 0;
+ adder->slow_dest_dx = 0;
+ adder->error_1 = 0;
+ adder->error_2 = 0;
+ adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
+ adder->destination_x = 0;
+ adder->fast_dest_dx = 1024;
+ adder->destination_y = 0;
+ adder->slow_dest_dy = 864 - CHAR_HEIGHT;
+ /*
+ * load SOURCE origin and vectors
+ */
+ adder->source_1_x = 0;
+ adder->source_1_dx = 1024;
+ adder->source_1_y = 0 + CHAR_HEIGHT;
+ adder->source_1_dy = 864 - CHAR_HEIGHT;
+ write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
+ adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
+ /*
+ * do a rectangle clear of last screen line
+ */
+ write_ID(adder, MASK_1, 0xffff);
+ write_ID(adder, SOURCE, 0xffff);
+ write_ID(adder,DST_OCR_B,
+ (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
+ write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
+ adder->error_1 = 0;
+ adder->error_2 = 0;
+ adder->slow_dest_dx = 0; /* set up the width of */
+ adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */
+ adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
+ (void)wait_status(adder, RASTEROP_COMPLETE);
+ adder->destination_x = 0;
+ adder->destination_y = 864 - CHAR_HEIGHT;
+ adder->fast_dest_dx = 1024; /* set up the height */
+ adder->fast_dest_dy = 0; /* of rectangle */
+ write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
+ adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
+
+} /* scroll_up */
+
+/*
+ * init shared memory pointers and structures
+ */
+void
+init_shared(unit)
+ int unit;
+{
+ volatile register struct dga *dga;
+
+ dga = (struct dga *) qdmap[unit].dga;
+
+ /*
+ * initialize the event queue pointers and header */
+
+ eq_header[unit] = (struct qdinput *)
+ ((((int)event_shared & ~(0x01FF)) + 512)
+ + (EVENT_BUFSIZE * unit));
+ eq_header[unit]->curs_pos.x = 0;
+ eq_header[unit]->curs_pos.y = 0;
+ dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
+ dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
+ eq_header[unit]->curs_box.left = 0;
+ eq_header[unit]->curs_box.right = 0;
+ eq_header[unit]->curs_box.top = 0;
+ eq_header[unit]->curs_box.bottom = 0;
+ /*
+ * assign a pointer to the DMA I/O buffer for this QDSS.
+ */
+ DMAheader[unit] = (struct DMAreq_header *)
+ (((int)(&DMA_shared[0] + 512) & ~0x1FF)
+ + (DMAbuf_size * unit));
+ DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
+ + sizeof(struct DMAreq_header));
+ DMAheader[unit]->QBAreg = 0;
+ DMAheader[unit]->status = 0;
+ DMAheader[unit]->shared_size = DMAbuf_size;
+ DMAheader[unit]->used = 0;
+ DMAheader[unit]->size = 10; /* default = 10 requests */
+ DMAheader[unit]->oldest = 0;
+ DMAheader[unit]->newest = 0;
+ /*
+ * assign a pointer to the scroll structure for this QDSS.
+ */
+ scroll[unit] = (struct scroll *)
+ (((int)(&scroll_shared[0] + 512) & ~0x1FF)
+ + (sizeof(struct scroll) * unit));
+ scroll[unit]->status = 0;
+ scroll[unit]->viper_constant = 0;
+ scroll[unit]->y_scroll_constant = 0;
+ scroll[unit]->y_offset = 0;
+ scroll[unit]->x_index_pending = 0;
+ scroll[unit]->y_index_pending = 0;
+ /*
+ * assign a pointer to the color map write buffer for this QDSS
+ */
+ color_buf[unit] = (struct color_buf *)
+ (((int)(&color_shared[0] + 512) & ~0x1FF)
+ + (COLOR_BUFSIZ * unit));
+ color_buf[unit]->status = 0;
+ color_buf[unit]->count = 0;
+
+} /* init_shared */
+
+/*
+ * init the ADDER, VIPER, bitmaps, & color map
+ */
+void
+setup_dragon(unit)
+ int unit;
+{
+
+ volatile register struct adder *adder;
+ volatile register struct dga *dga;
+ volatile short *memcsr;
+ register int i;
+ short top; /* clipping/scrolling boundaries */
+ short bottom;
+ short right;
+ short left;
+ volatile short *red; /* color map pointers */
+ volatile short *green;
+ volatile short *blue;
+
+ /*
+ * init for setup
+ */
+ adder = (struct adder *) qdmap[unit].adder;
+ dga = (struct dga *) qdmap[unit].dga;
+ memcsr = (short *) qdmap[unit].memcsr;
+ dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */
+ *memcsr = SYNC_ON; /* blank screen and turn off LED's */
+ adder->command = CANCEL;
+ /*
+ * set monitor timing
+ */
+ adder->x_scan_count_0 = 0x2800;
+ adder->x_scan_count_1 = 0x1020;
+ adder->x_scan_count_2 = 0x003A;
+ adder->x_scan_count_3 = 0x38F0;
+ adder->x_scan_count_4 = 0x6128;
+ adder->x_scan_count_5 = 0x093A;
+ adder->x_scan_count_6 = 0x313C;
+ adder->sync_phase_adj = 0x0100;
+ adder->x_scan_conf = 0x00C8;
+ /*
+ * got a bug in secound pass ADDER! lets take care of it
+ *
+ * normally, just use the code in the following bug fix code, but to
+ * make repeated demos look pretty, load the registers as if there was
+ * no bug and then test to see if we are getting sync
+ */
+ adder->y_scan_count_0 = 0x135F;
+ adder->y_scan_count_1 = 0x3363;
+ adder->y_scan_count_2 = 0x2366;
+ adder->y_scan_count_3 = 0x0388;
+ /*
+ * if no sync, do the bug fix code
+ */
+ if (wait_status(adder, VSYNC) == BAD) {
+ /* first load all Y scan registers with very short frame and
+ * wait for scroll service. This guarantees at least one SYNC
+ * to fix the pass 2 Adder initialization bug (synchronizes
+ * XCINCH with DMSEEDH)
+ */
+ adder->y_scan_count_0 = 0x01;
+ adder->y_scan_count_1 = 0x01;
+ adder->y_scan_count_2 = 0x01;
+ adder->y_scan_count_3 = 0x01;
+ /*
+ * delay at least 1 full frame time
+ */
+ (void)wait_status(adder, VSYNC);
+ (void)wait_status(adder, VSYNC);
+ /*
+ * now load the REAL sync values (in reverse order just to
+ * be safe.
+ */
+ adder->y_scan_count_3 = 0x0388;
+ adder->y_scan_count_2 = 0x2366;
+ adder->y_scan_count_1 = 0x3363;
+ adder->y_scan_count_0 = 0x135F;
+ }
+ *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */
+ /*
+ * zero the index registers
+ */
+ adder->x_index_pending = 0;
+ adder->y_index_pending = 0;
+ adder->x_index_new = 0;
+ adder->y_index_new = 0;
+ adder->x_index_old = 0;
+ adder->y_index_old = 0;
+ adder->pause = 0;
+ /*
+ * set rasterop mode to normal pen down
+ */
+ adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
+ /*
+ * set the rasterop registers to a default values
+ */
+ adder->source_1_dx = 1;
+ adder->source_1_dy = 1;
+ adder->source_1_x = 0;
+ adder->source_1_y = 0;
+ adder->destination_x = 0;
+ adder->destination_y = 0;
+ adder->fast_dest_dx = 1;
+ adder->fast_dest_dy = 0;
+ adder->slow_dest_dx = 0;
+ adder->slow_dest_dy = 1;
+ adder->error_1 = 0;
+ adder->error_2 = 0;
+ /*
+ * scale factor = UNITY
+ */
+ adder->fast_scale = UNITY;
+ adder->slow_scale = UNITY;
+ /*
+ * set the source 2 parameters
+ */
+ adder->source_2_x = 0;
+ adder->source_2_y = 0;
+ adder->source_2_size = 0x0022;
+ /*
+ * initialize plane addresses for eight vipers
+ */
+ write_ID(adder, CS_UPDATE_MASK, 0x0001);
+ write_ID(adder, PLANE_ADDRESS, 0x0000);
+ write_ID(adder, CS_UPDATE_MASK, 0x0002);
+ write_ID(adder, PLANE_ADDRESS, 0x0001);
+ write_ID(adder, CS_UPDATE_MASK, 0x0004);
+ write_ID(adder, PLANE_ADDRESS, 0x0002);
+ write_ID(adder, CS_UPDATE_MASK, 0x0008);
+ write_ID(adder, PLANE_ADDRESS, 0x0003);
+ write_ID(adder, CS_UPDATE_MASK, 0x0010);
+ write_ID(adder, PLANE_ADDRESS, 0x0004);
+ write_ID(adder, CS_UPDATE_MASK, 0x0020);
+ write_ID(adder, PLANE_ADDRESS, 0x0005);
+ write_ID(adder, CS_UPDATE_MASK, 0x0040);
+ write_ID(adder, PLANE_ADDRESS, 0x0006);
+ write_ID(adder, CS_UPDATE_MASK, 0x0080);
+ write_ID(adder, PLANE_ADDRESS, 0x0007);
+ /*
+ * initialize the external registers.
+ */
+ write_ID(adder, CS_UPDATE_MASK, 0x00FF);
+ write_ID(adder, CS_SCROLL_MASK, 0x00FF);
+ /*
+ * initialize resolution mode
+ */
+ write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */
+ write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */
+ /*
+ * initialize viper registers
+ */
+ write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
+ write_ID(adder, SCROLL_FILL, 0x0000);
+ /*
+ * set clipping and scrolling limits to full screen
+ */
+ for (i = 1000, adder->status = 0;
+ i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
+ ;
+ if (i == 0)
+ printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
+ top = 0;
+ bottom = 2048;
+ left = 0;
+ right = 1024;
+ adder->x_clip_min = left;
+ adder->x_clip_max = right;
+ adder->y_clip_min = top;
+ adder->y_clip_max = bottom;
+ adder->scroll_x_min = left;
+ adder->scroll_x_max = right;
+ adder->scroll_y_min = top;
+ adder->scroll_y_max = bottom;
+ (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */
+ (void)wait_status(adder, VSYNC);
+ adder->x_index_pending = left;
+ adder->y_index_pending = top;
+ adder->x_index_new = left;
+ adder->y_index_new = top;
+ adder->x_index_old = left;
+ adder->y_index_old = top;
+
+ for (i = 1000, adder->status = 0; i > 0 &&
+ !(adder->status&ADDRESS_COMPLETE) ; --i)
+ ;
+ if (i == 0)
+ printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
+
+ write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
+ write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
+ /*
+ * set source and the mask register to all ones (ie: white) o
+ */
+ write_ID(adder, SOURCE, 0xFFFF);
+ write_ID(adder, MASK_1, 0xFFFF);
+ write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
+ write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
+ /*
+ * initialize Operand Control Register banks for fill command
+ */
+ write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT);
+ write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
+ write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
+ write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
+ write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT);
+ write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
+ /*
+ * init Logic Unit Function registers, (these are just common values,
+ * and may be changed as required).
+ */
+ write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
+ write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
+ INV_M1_M2);
+ write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
+ write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
+ /*
+ * load the color map for black & white
+ */
+ for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
+ ;
+
+ if (i == 0)
+ printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
+
+ red = (short *) qdmap[unit].red;
+ green = (short *) qdmap[unit].green;
+ blue = (short *) qdmap[unit].blue;
+
+ *red++ = 0x00; /* black */
+ *green++ = 0x00;
+ *blue++ = 0x00;
+
+ *red-- = 0xFF; /* white */
+ *green-- = 0xFF;
+ *blue-- = 0xFF;
+
+ /*
+ * set color map for mouse cursor
+ */
+
+ red += 254;
+ green += 254;
+ blue += 254;
+
+ *red++ = 0x00; /* black */
+ *green++ = 0x00;
+ *blue++ = 0x00;
+
+ *red = 0xFF; /* white */
+ *green = 0xFF;
+ *blue = 0xFF;
+
+} /* setup_dragon */
+
+/*
+ * Init the DUART and set defaults in input
+ */
+void
+setup_input(unit)
+ int unit;
+{
+ volatile register struct duart *duart; /* DUART register structure pointer */
+ register int i, bits;
+ char id_byte;
+
+ duart = (struct duart *) qdmap[unit].duart;
+ duart->imask = 0;
+
+ /*
+ * setup the DUART for kbd & pointing device
+ */
+ duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */
+ duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */
+ /* no RTS control,char error mode */
+ duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */
+ /* no RTS control,no echo or loop */
+ duart->cmdB = RESET_M; /* reset mode reg pntr for host */
+ duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */
+ /* ..no RTS cntrl, char error mode */
+ duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */
+ /* no RTS control,no echo or loop */
+ duart->auxctl = 0x00; /* baud rate set 1 */
+ duart->clkselA = 0x99; /* 4800 baud for kbd */
+ duart->clkselB = 0x99; /* 4800 baud for mouse */
+
+ /* reset everything for keyboard */
+
+ for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
+ duart->cmdA = bits;
+
+ /* reset everything for host */
+
+ for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
+ duart->cmdB = bits;
+
+ duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
+ duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
+
+ /*
+ * init keyboard defaults (DUART channel A)
+ */
+ for (i = 500; i > 0; --i) {
+ if (duart->statusA&XMT_RDY) {
+ duart->dataA = LK_DEFAULTS;
+ break;
+ }
+ }
+
+ for (i = 100000; i > 0; --i) {
+ if (duart->statusA&RCV_RDY) {
+ break;
+ }
+ }
+
+ if (duart->dataA) /* flush the ACK */
+ ;
+
+ /*
+ * identify the pointing device
+ */
+ for (i = 500; i > 0; --i) {
+ if (duart->statusB&XMT_RDY) {
+ duart->dataB = SELF_TEST;
+ break;
+ }
+ }
+
+ /*
+ * wait for 1st byte of self test report */
+
+ for (i = 100000; i > 0; --i) {
+ if (duart->statusB&RCV_RDY) {
+ break;
+ }
+ }
+
+ if (i == 0) {
+ printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
+ ,unit);
+ goto OUT;
+ }
+
+ if (duart->dataB)
+ ;
+
+ /*
+ * wait for ID byte of self test report
+ */
+ for (i = 100000; i > 0; --i) {
+ if (duart->statusB&RCV_RDY) {
+ break;
+ }
+ }
+
+ if (i == 0) {
+ printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
+ goto OUT;
+ }
+
+ id_byte = duart->dataB;
+
+ /*
+ * wait for other bytes to come in
+ */
+ for (i = 100000; i > 0; --i) {
+ if (duart->statusB & RCV_RDY) {
+ if (duart->dataB)
+ ;
+ break;
+ }
+ }
+ if (i == 0) {
+ printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
+ goto OUT;
+ }
+ for (i = 100000; i > 0; --i) {
+ if (duart->statusB&RCV_RDY) {
+ if (duart->dataB)
+ ;
+ break;
+ }
+ }
+ if (i == 0) {
+ printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
+ goto OUT;
+ }
+ /*
+ * flag pointing device type and set defaults
+ */
+ for (i=100000; i>0; --i)
+ ; /*XXX*/
+
+ if ((id_byte & 0x0F) != TABLET_ID) {
+ qdflags[unit].pntr_id = MOUSE_ID;
+
+ for (i = 500; i > 0; --i) {
+ if (duart->statusB&XMT_RDY) {
+ duart->dataB = INC_STREAM_MODE;
+ break;
+ }
+ }
+ }
+ else {
+ qdflags[unit].pntr_id = TABLET_ID;
+
+ for (i = 500; i > 0; --i) {
+ if (duart->statusB&XMT_RDY) {
+ duart->dataB = T_STREAM;
+ break;
+ }
+ }
+ }
+OUT:
+ duart->imask = qdflags[unit].duart_imask;
+
+} /* setup_input */
+
+/*
+ * delay for at least one display frame time
+ *
+ * return: BAD means that we timed out without ever seeing the
+ * vertical sync status bit
+ * GOOD otherwise
+ */
+int
+wait_status(adder, mask)
+ volatile struct adder *adder;
+ int mask;
+{
+ register int i;
+
+ for (i = 10000, adder->status = 0 ; i > 0 &&
+ !(adder->status&mask) ; --i)
+ ;
+
+ if (i == 0) {
+ printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
+ return(BAD);
+ }
+
+ return(GOOD);
+
+} /* wait_status */
+
+/*
+ * write out onto the ID bus
+ */
+void
+write_ID(adder, adrs, data)
+ volatile struct adder *adder;
+ short adrs;
+ short data;
+{
+ register int i;
+
+ for (i = 100000, adder->status = 0 ;
+ i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i)
+ ;
+
+ if (i == 0)
+ goto ERR;
+
+ for (i = 100000, adder->status = 0 ;
+ i > 0 && !(adder->status&TX_READY) ; --i)
+ ;
+
+ if (i > 0) {
+ adder->id_data = data;
+ adder->command = ID_LOAD | adrs;
+ return ;
+ }
+
+ERR:
+ printf("write_ID: timeout trying to write to VIPER\n");
+ return ;
+
+} /* write_ID */
--- /dev/null
+/* $OpenBSD: qdioctl.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qdioctl.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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.
+ *
+ * @(#)qdioctl.h 7.2 (Berkeley) 1/21/94
+ */
+
+/*
+ * derived from: qdioctl.h 1.1 (ULTRIX) 8/22/85
+ */
+/*
+ * QDSS IOCTL definitions
+ */
+
+
+/************************************************************************
+ * *
+ * Copyright (c) 1985 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. *
+ * *
+ * This software is derived from software received from the *
+ * University of California, Berkeley, and from Bell *
+ * Laboratories. Use, duplication, or disclosure is subject to *
+ * restrictions under license agreements with University of *
+ * California and with AT&T. *
+ * *
+ * 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. *
+ * *
+ ************************************************************************/
+/***************************************************************************
+* revision history: (belongs in sccs)
+****************************************************************************
+*
+* 22 oct 85 longo fixed QD_PRGTABRES cmd number to be 22 instead of 12
+* 14 oct 85 longo added QD_KERN_LOOP and QD_KERN_UNLOOP
+* 02 oct 85 longo added QD_MAPCOLOR and QD_UNMAPCOLOR
+* 17 sep 85 longo made QD_MAPIOBUF a read/write command type
+*
+***************************************************************************/
+
+
+#ifdef KERNEL
+#include "sys/ioctl.h"
+#else
+#include <sys/ioctl.h>
+#endif
+
+
+#define QD_GETEVENT _IOR('g', 1, struct _vs_event) /* get oldest event */
+#define QD_WTCURSOR _IOW('g', 2, short[32]) /* write cursor bitmap */
+#define QD_RDCURSOR _IOR('g', 3, 64) /* read cursor bitmap */
+#define QD_CLRSCRN _IO('g', 4) /* clear the screen */
+#define QD_RDCONFIG _IOR('g', 5, short) /* read QDSS configuration */
+#define QD_PRGMOUSE _IOW('g', 6, char) /* program mouse */
+#define QD_PRGTABLET _IOW('g', 7, char) /* program tablet */
+#define QD_PRGKBD _IOW('g', 8, struct prgkbd) /* program LK201 kbd */
+#define QD_MAPDEVICE _IOR('g', 9, struct qdmap) /* map device to user */
+#define QD_MAPIOBUF _IOWR('g', 10, caddr_t) /* map DMA iobuf to user */
+#define QD_MAPEVENT _IOR('g', 11, caddr_t) /* map event queue to user */
+#define QD_PRGCURSOR _IOW('g', 12, struct prg_cursor) /* program cursor */
+#define QD_RESET _IO('g', 13) /* set device & driver defaults */
+#define QD_POSCURSOR _IOW('g', 14, struct _vs_cursor) /* position cursor */
+#define QD_SET _IO('g', 15) /* set DUART & driver defaults */
+#define QD_MAPSCROLL _IOR('g', 16, caddr_t) /* map scroll param area */
+#define QD_UNMAPSCROLL _IO('g', 17) /* unmap scroll param area */
+#define QD_MAPCOLOR _IOR('g', 18, caddr_t) /* map color map write buf */
+#define QD_UNMAPCOLOR _IO('g', 19) /* unmap color map write buf */
+#define QD_KERN_LOOP _IO('g', 20) /* detour kernel console output */
+#define QD_KERN_UNLOOP _IO('g', 21) /* un-detour kernel console output */
+#define QD_PRGTABRES _IOW('g', 22, short) /* program tablet resolution */
--- /dev/null
+/* $OpenBSD: qdreg.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qdreg.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)qdreg.h 7.1 (Berkeley) 5/9/91
+ */
+
+/************************************************************************
+ * *
+ * Copyright (c) 1985, 1986 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. *
+ * *
+ ************************************************************************/
+
+/* Dragon ADDER reg map */
+/* ADDER register bit definitions */
+/* Y_SCROLL_CONSTANT */
+
+#define SCROLL_ERASE 0x2000
+#define ADDER_SCROLL_DOWN 0x1000
+
+/* ADDER status and interrupt enable registers [1], [2], [3] */
+
+#define DISABLE 0x0000
+#define PAUSE_COMPLETE 0x0001
+#define FRAME_SYNC 0x0002
+#define INIT_COMPLETE 0x0004
+#define RASTEROP_COMPLETE 0x0008
+
+#define ADDRESS_COMPLETE 0x0010
+#define RX_READY 0x0020
+#define TX_READY 0x0040
+#define ID_SCROLL_READY 0x0080
+
+#define TOP_CLIP 0x0100
+#define BOTTOM_CLIP 0x0200
+#define LEFT_CLIP 0x0400
+#define RIGHT_CLIP 0x0800
+#define NO_CLIP 0x1000
+#define VSYNC 0x2000
+
+/* ADDER command register [8], [10] */
+
+#define OCR_zero 0x0000
+#define Z_BLOCK0 0x0000
+#define OCRA 0x0000
+#define OCRB 0x0004
+#define RASTEROP 0x02c0
+#define PBT 0x03c0
+#define BTPZ 0x0bb0
+#define PTBZ 0x07a0
+#define DTE 0x0400
+#define S1E 0x0800
+#define S2E 0x1000
+#define VIPER_Z_LOAD 0x01A0
+#define ID_LOAD 0x0100
+#define CANCEL 0x0000
+#define LF_R1 0x0000
+#define LF_R2 0x0010
+#define LF_R3 0x0020
+#define LF_R4 0x0030
+
+/* ADDER rasterop mode register [9] */
+
+#define NORMAL 0x0000
+#define LINEAR_PATTERN 0x0002
+#define X_FILL 0x0003
+#define Y_FILL 0x0007
+#define BASELINE 0x0008
+#define HOLE_ENABLE 0x0010
+#define SRC_1_INDEX_ENABLE 0x0020
+#define DST_INDEX_ENABLE 0x0040
+#define DST_WRITE_ENABLE 0x0080
+
+/* ADDER source 2 size register */
+
+#define NO_TILE 0x0080
+
+/* External registers base addresses */
+
+#define CS_UPDATE_MASK 0x0060
+#define CS_SCROLL_MASK 0x0040
+
+/* VIPER registers */
+
+#define RESOLUTION_MODE 0x0080
+#define MEMORY_BUS_WIDTH 0x0081
+#define PLANE_ADDRESS 0x0083
+#define LU_FUNCTION_R1 0x0084
+#define LU_FUNCTION_R2 0x0085
+#define LU_FUNCTION_R3 0x0086
+#define LU_FUNCTION_R4 0x0087
+#define MASK_1 0x0088
+#define MASK_2 0x0089
+#define SOURCE 0x008a
+#define SOURCE_Z 0x0000
+#define BACKGROUND_COLOR 0x008e
+#define BACKGROUND_COLOR_Z 0x000C
+#define FOREGROUND_COLOR 0x008f
+#define FOREGROUND_COLOR_Z 0x0004
+#define SRC1_OCR_A 0x0090
+#define SRC2_OCR_A 0x0091
+#define DST_OCR_A 0x0092
+#define SRC1_OCR_B 0x0094
+#define SRC2_OCR_B 0x0095
+#define DST_OCR_B 0x0096
+
+/* VIPER scroll registers */
+
+#define SCROLL_CONSTANT 0x0082
+#define SCROLL_FILL 0x008b
+#define SCROLL_FILL_Z 0x0008
+#define LEFT_SCROLL_MASK 0x008c
+#define RIGHT_SCROLL_MASK 0x008d
+
+/* VIPER register bit definitions */
+
+#define EXT_NONE 0x0000
+#define EXT_SOURCE 0x0001
+#define EXT_M1_M2 0x0002
+#define INT_NONE 0x0000
+#define INT_SOURCE 0x0004
+#define INT_M1_M2 0x0008
+#define ID 0x0010
+#define NO_ID 0x0000
+#define WAIT 0x0020
+#define NO_WAIT 0x0000
+#define BAR_SHIFT_DELAY WAIT
+#define NO_BAR_SHIFT_DELAY NO_WAIT
+
+
+/* VIPER logical function unit codes */
+
+#define LF_ZEROS 0x0000
+#define LF_D_XOR_S 0x0006
+#define LF_SOURCE 0x000A
+#define LF_D_OR_S 0x000E
+#define LF_ONES 0x000F
+#define INV_M1_M2 0x0030
+#define FULL_SRC_RESOLUTION 0X00C0 /* makes second pass like first pass */
+
+/* VIPER scroll register [2] */
+
+#define SCROLL_DISABLE 0x0040
+#define SCROLL_ENABLE 0x0020
+#define VIPER_LEFT 0x0000
+#define VIPER_RIGHT 0x0010
+#define VIPER_UP 0x0040
+#define VIPER_DOWN 0x0000
+
+/* Adder scroll register */
+
+#define ADDER_UP 0x0000
+#define ADDER_DOWN 0x1000
+
+/* Misc scroll definitions */
+
+#define UP 0
+#define DOWN 1
+#define LEFT 2
+#define RIGHT 3
+#define NODIR 4
+#define SCROLL_VMAX 31
+#define SCROLL_HMAX 15
+#define NEW 2
+#define OLD 1
+#define BUSY 1
+#define DRAG 1
+#define SCROLL 0
+
+/* miscellaneous defines */
+
+#define ALL_PLANES 0xffffffff
+#define UNITY 0x1fff /* Adder scale factor */
+#define MAX_SCREEN_X 1024
+#define MAX_SCREEN_Y 864
+#define FONT_HEIGHT 32
+
+ struct adder {
+
+ /* adder control registers */
+
+ u_short register_address; /* ADDER reg pntr for use by DGA */
+ u_short request_enable; /* DMA request enables */
+ u_short interrupt_enable; /* interrupt enables */
+ u_short status; /* ADDER status bits */
+ u_short reserved1; /* test function only */
+ u_short spare1; /* spare address (what else?) */
+
+ u_short reserved2; /* test function only */
+ u_short id_data; /* data path to I/D bus */
+ u_short command; /* ADDER chip command register */
+ u_short rasterop_mode; /* sets rasterop execution modes */
+ u_short cmd; /* duplicate path to above cmd reg */
+ u_short reserved3; /* test function only */
+
+ /* scroll registers */
+
+ u_short ID_scroll_data; /* I/D bus scroll data */
+ u_short ID_scroll_command; /* I/D bus scroll command */
+ u_short scroll_x_min; /* X scroll min - left boundary */
+ u_short scroll_x_max; /* X scroll max - right boundary */
+ u_short scroll_y_min; /* Y scroll min - upper boundary */
+ u_short scroll_y_max; /* Y scroll max - lower boundary */
+ u_short pause; /* Y coord to set stat when scanned */
+ u_short y_offset_pending; /* vertical scroll control */
+ u_short y_scroll_constant;
+
+ /* update control registers */
+
+ u_short x_index_pending; /* x pending index */
+ u_short y_index_pending; /* y pending index */
+ u_short x_index_new; /* new x index */
+ u_short y_index_new; /* new y index */
+ u_short x_index_old; /* old x index */
+ u_short y_index_old; /* old y index */
+ u_short x_clip_min; /* left clipping boundary */
+ u_short x_clip_max; /* right clipping boundary */
+ u_short y_clip_min; /* upper clipping boundary */
+ u_short y_clip_max; /* lower clipping boundary */
+ u_short spare2; /* spare address (another!) */
+
+ /* rasterop control registers */
+
+ u_short source_1_dx; /* source #1 x vector */
+ u_short source_1_dy; /* source #1 y vector*/
+ u_short source_1_x; /* source #1 x origin */
+ u_short source_1_y; /* source #1 y origin */
+ u_short destination_x; /* destination x origin */
+ u_short destination_y; /* destination y origin */
+ u_short fast_dest_dx; /* destination x fast vector */
+ u_short fast_dest_dy; /* destination y fast vector */
+ u_short slow_dest_dx; /* destination x slow vector */
+ u_short slow_dest_dy; /* destination y slow vector */
+ u_short fast_scale; /* scale factor for fast vector */
+ u_short slow_scale; /* scale factor for slow vector */
+ u_short source_2_x; /* source #2 x origin */
+ u_short source_2_y; /* source #2 y origin */
+ u_short source_2_size; /* source #2 height & width */
+ u_short error_1; /* error regs (?) */
+ u_short error_2;
+
+ /* screen format control registers */
+
+ u_short y_scan_count_0; /* y scan counts for vert timing */
+ u_short y_scan_count_1;
+ u_short y_scan_count_2;
+ u_short y_scan_count_3;
+ u_short x_scan_conf; /* x scan configuration */
+ u_short x_limit;
+ u_short y_limit;
+ u_short x_scan_count_0; /* x scan count for horiz timing */
+ u_short x_scan_count_1;
+ u_short x_scan_count_2;
+ u_short x_scan_count_3;
+ u_short x_scan_count_4;
+ u_short x_scan_count_5;
+ u_short x_scan_count_6;
+ u_short sync_phase_adj; /* sync phase (horiz sync count) */
+ };
+
+/*---------------------
+* DUART definitions */
+
+ /* command definitions */
+
+#define EN_RCV 0x01
+#define DIS_RCV 0x02
+#define EN_XMT 0x04
+#define DIS_XMT 0x08
+#define RESET_M 0x10
+#define RESET_RCV 0x20
+#define RESET_XMT 0x30
+#define RESET_ERR 0x40
+#define RESET_BD 0x50
+#define START_BREAK 0x60
+#define STOP_BREAK 0x70
+
+ /* interupt bit definitions */
+
+#define EI_XMT_A 0x01
+#define EI_RCV_A 0x02
+#define EI_XMT_B 0x10
+#define EI_RCV_B 0x20
+
+#define XMT_RDY_A 0x01
+#define RCV_RDY_A 0x02
+#define XMT_RDY_B 0x10
+#define RCV_RDY_B 0x20
+
+ /* status register bit defintions */
+
+#define RCV_RDY 0x01
+#define FIFO_FULL 0x02
+#define XMT_RDY 0x04
+#define XMT_EMT 0x08
+#define OVER_ERR 0x10
+#define ERR_PARITY 0x20
+#define FRAME_ERR 0x40
+#define RCVD_BREAK 0x80
+
+
+ struct duart {
+
+ /* channel A - LK201 */
+
+ short modeA; /* ch.A mode reg (read/write) */
+ short statusA; /* ch.A status reg (read) */
+#define clkselA statusA /* ch.A clock slect reg (write) */
+ short cmdA; /* ch.A command reg (write) */
+ short dataA; /* rcv/xmt data ch.A (read/write) */
+ short inchng; /* input change state reg (read) */
+#define auxctl inchng /* auxiliary control reg (write) */
+ short istatus; /* interrupt status reg (read) */
+#define imask istatus /* interrupt mask reg (write) */
+ short CThi; /* counter/timer hi byte (read) */
+#define CTRhi CThi /* counter/timer hi reg (write) */
+ short CTlo; /* counter/timer lo byte (read) */
+#define CTRlo CTlo /* counter/timer lo reg (write) */
+
+ /* channel B - pointing device */
+
+ short modeB; /* ch.B mode reg (read/write) */
+ short statusB; /* ch.B status reg (read) */
+#define clkselB statusB /* ch.B clock select reg (write) */
+ short cmdB; /* ch.B command reg (write) */
+ short dataB; /* ch.B rcv/xmt data (read/write) */
+ short rsrvd;
+ short inport; /* input port (read) */
+#define outconf inport /* output port config reg (write) */
+ short strctr; /* start counter command (read) */
+#define setbits setctr /* output bits set command (write) */
+ short stpctr; /* stop counter command (read) */
+#define resetbits stpctr /* output bits reset cmd (write) */
+
+};
--- /dev/null
+/* $OpenBSD: qduser.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qduser.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)qduser.h 7.1 (Berkeley) 5/9/91
+ */
+
+/* derived from: @(#)qduser.h 6.1 (ULTRIX) 11/24/87 */
+/************************************************************************
+ * *
+ * Copyright (c) 1986 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. *
+ * *
+ ************************************************************************/
+
+/***************************************************************************
+*
+* QDUSER...
+* This file defines values shared between the driver and a client
+*
+***************************************************************************/
+
+/***************************************************************************
+* revision history:
+****************************************************************************
+*
+* 21 jul 86 ram fixed define of CURSOR_MIN_Y
+* 25 nov 85 longo added macro and bit defines for DMA error flags
+* 11 nov 85 longo renamed _vs_eventqueue to "qdinput" struct
+* 23 oct 85 longo added more defines to the DMA stuff
+* 17 oct 85 longo changed "struct rgb" chars to be unsigned
+* 16 oct 85 longo added new TABLET support definitions
+* 15 oct 85 longo re-wrote DMA queue access macros
+* 08 oct 85 longo added status flag manipulation macros to DMA stuff
+* 02 oct 85 longo added support for color map write buffer loading
+* 26 sep 85 longo removed adder sertup params from DMA request struct
+* 23 sep 85 longo added DMA queue access macros
+* 30 aug 85 longo fixed crock in "qdiobuf" struct compile-time sizing. Also
+* removed DMAcontrol struct from DMA buffer for field test
+* 26 aug 85 longo put in conditional include of "qevent.h" for user prg's
+* 18 jul 85 longo changed semantics so that head is tail and tail is head
+* 12 jul 85 longo moved "mouse_report" struct and defs over to qd_data.c
+* 11 jul 85 longo added device coordinate to gate array cursor coordinate
+* transformation macros
+* 03 jul 85 longo changed kernel typdef's for data types to long-hand
+* 10 may 85 longo created
+*
+***************************************************************************/
+
+#ifdef KERNEL
+#include "../include/qevent.h" /* include event struct defs */
+#else
+#include <vax/uba/qevent.h>
+#endif
+
+/*---------------------
+* QDSS device map */
+
+ struct qdmap { /* map of register blocks in QDSS */
+
+ char *template;
+ char *adder;
+ char *dga;
+ char *duart;
+ char *memcsr;
+ char *red;
+ char *blue;
+ char *green;
+ };
+
+/*--------------------------------------------
+* DGA CSR bit definitions and register map */
+
+#define DMADONE 0x8000 /* DMA done status */
+#define SET_DONE_FIFO 0x4000 /* set DMADONE when FIFO empty.. */
+ /* ..AND count = 0 */
+
+#define PTOB_ENB 0x0600 /* host-to-bitmap DMA xfer */
+#define BTOP_ENB 0x0400 /* bitmap-to-host DMA xfer */
+#define DL_ENB 0x0200 /* display list DMA xfer */
+#define HALT 0x0000 /* halt DGA */
+
+#define BYTE_DMA 0x0100 /* byte/word DMA xfer */
+
+#define DMA_ERR 0x0080 /* DMA error bits */
+#define PARITY_ERR 0x0040 /* memory parity error in DMA */
+#define BUS_ERR 0x0020 /* bus timeout error in DMA */
+
+#define GLOBAL_IE 0x0004 /* global interrupt enable */
+#define DMA_IE 0x0002 /* DMA interrupt enable */
+#define CURS_ENB 0x0001 /* cursor enable */
+
+/* QDSS memcsr bit definitions */
+
+#define UNBLANK 0x0020
+#define SYNC_ON 0x0008
+
+ struct dga {
+
+ unsigned short csr;
+ unsigned short adrs_lo; /* destination address of bitmap to */
+ unsigned short adrs_hi; /* host DMA */
+ unsigned short bytcnt_lo; /* byte length of requested DMA */
+ unsigned short bytcnt_hi; /* (WO = bytcnt) (RO = fifo count) */
+ unsigned short fifo; /* FIFO register */
+ unsigned short x_cursor; /* cursor position registers */
+ unsigned short y_cursor;
+ unsigned short ivr; /* interrupt vector register */
+ unsigned short memadr; /* memory base address register */
+ };
+
+/*-------------------------------------------------------------------------
+* macros to transform device coordinates to hardware cursor coordinates */
+
+#define CURS_MIN_X 232 /* device coordinate x = 0 */
+#define CURS_MIN_Y 16 /* device coordinate y = 0 */
+
+#define TRANX(x) ( -(((int)(x)+CURS_MIN_X) & ~0x0003) | \
+ (((int)(x)+CURS_MIN_X) & 0x0003) )
+
+#define TRANY(y) ( -((y)+CURS_MIN_Y) )
+
+/*********************************************************************
+*
+* EVENT QUEUE DEFINITIONS
+*
+**********************************************************************
+* most of the event queue definitions are found in "qevent.h". But a
+* few things not found there are here. */
+
+/* The event queue header */
+
+struct qdinput {
+
+ struct _vs_eventqueue header; /* event queue ring handling */
+
+ /* for VS100 and QVSS compatability reasons, additions to this
+ * structure must be made below this point. */
+
+ struct _vs_cursor curs_pos; /* current mouse position */
+ struct _vs_box curs_box; /* cursor reporting box */
+
+ };
+
+/* vse_key field. definitions for mouse buttons */
+
+#define VSE_LEFT_BUTTON 0
+#define VSE_MIDDLE_BUTTON 1
+#define VSE_RIGHT_BUTTON 2
+
+/* vse_key field. definitions for mouse buttons */
+
+#define VSE_T_LEFT_BUTTON 0
+#define VSE_T_FRONT_BUTTON 1
+#define VSE_T_RIGHT_BUTTON 2
+#define VSE_T_BACK_BUTTON 4
+
+#define VSE_T_BARREL_BUTTON VSE_T_LEFT_BUTTON
+#define VSE_T_TIP_BUTTON VSE_T_FRONT_BUTTON
+
+/*--------------------------------------------------------------------------
+* These are the macros to be used for loading and extracting from the event
+* queue. It is presumed that the macro user will only use the access macros
+* if the event queue is non-empty ( ISEMPTY(eq) == FALSE ), and that the
+* driver will only load the event queue after checking that it is not full
+* ( ISFULL(eq) == FALSE ). ("eq" is a pointer to the event queue header.)
+*
+* Before an event access session for a particular event, the macro users
+* must use the xxxBEGIN macro, and the xxxEND macro after an event is through
+* with. As seen below, the xxxBEGIN and xxxEND macros maintain the event
+* queue access mechanism.
+*
+* First, the macros to be used by the event queue reader
+*/
+
+#define ISEMPTY(eq) ((eq)->header.head == (eq)->header.tail)
+#define GETBEGIN(eq) (&(eq)->header.events[(eq)->header.head])
+
+#define GET_X(event) ((event)->vse_x) /* get x position */
+#define GET_Y(event) ((event)->vse_y) /* get y position */
+#define GET_TIME(event) ((event)->vse_time) /* get time */
+#define GET_TYPE(event) ((event)->vse_type) /* get entry type */
+#define GET_KEY(event) ((event)->vse_key) /* get keycode */
+#define GET_DIR(event) ((event)->vse_direction) /* get direction */
+#define GET_DEVICE(event) ((event)->vse_device) /* get device */
+
+#define GETEND(eq) (++(eq)->header.head >= (eq)->header.size ? \
+ (eq)->header.head = 0 : 0 )
+
+/*------------------------------------------------
+* macros to be used by the event queue loader */
+
+ /* ISFULL yields TRUE if queue is full */
+
+#define ISFULL(eq) ((eq)->header.tail+1 == (eq)->header.head || \
+ ((eq)->header.tail+1 == (eq)->header.size && \
+ (eq)->header.head == 0))
+
+ /* get address of the billet for NEXT event */
+
+#define PUTBEGIN(eq) (&(eq)->header.events[(eq)->header.tail])
+
+#define PUT_X(event, value) ((event)->vse_x = value) /* put X pos */
+#define PUT_Y(event, value) ((event)->vse_y = value) /* put Y pos */
+#define PUT_TIME(event, value) ((event)->vse_time = value) /* put time */
+#define PUT_TYPE(event, value) ((event)->vse_type = value) /* put type */
+#define PUT_KEY(event, value) ((event)->vse_key = value) /* put input key */
+#define PUT_DIR(event, value) ((event)->vse_direction = value) /* put dir */
+#define PUT_DEVICE(event, value) ((event)->vse_device = value) /* put dev */
+
+#define PUTEND(eq) (++(eq)->header.tail >= (eq)->header.size ? \
+ (eq)->header.tail = 0 : 0)
+
+/******************************************************************
+*
+* DMA I/O DEFINITIONS
+*
+******************************************************************/
+
+/*---------------------------------------------------------------------
+* The DMA request queue is implemented as a ring buffer of "DMAreq"
+ structures. The queue is accessed using ring indices located in the
+ "DMAreq_header" structure. Access is implemented using access macros
+ similar to the event queue access macros above. */
+
+ struct DMAreq {
+
+ short DMAtype; /* DMA type code (for QDSS) */
+ short DMAdone; /* DMA done parameter */
+ char *bufp; /* virtual adrs of buffer */
+ int length; /* transfer buffer length */
+ };
+
+/* DMA type command codes */
+
+#define DISPLIST 1 /* display list DMA */
+#define PTOB 2 /* 1 plane Qbus to bitmap DMA */
+#define BTOP 3 /* 1 plane bitmap to Qbus DMA */
+
+/* DMA done notification code */
+
+#define FIFO_EMPTY 0x01 /* DONE when FIFO becomes empty */
+#define COUNT_ZERO 0x02 /* DONE when count becomes zero */
+#define WORD_PACK 0x04 /* program the gate array for word packing */
+#define BYTE_PACK 0x08 /* program gate array for byte packing */
+#define REQUEST_DONE 0x100 /* clear when driver has processed request */
+#define HARD_ERROR 0x200 /* DMA hardware error occurred */
+
+/* DMA request queue is a ring buffer of request structures */
+
+ struct DMAreq_header {
+
+ int QBAreg; /* cookie Qbus map reg for this buffer */
+ short status; /* master DMA status word */
+ int shared_size; /* size of shared memory in bytes */
+ struct DMAreq *DMAreq; /* start address of request queue */
+ int used; /* # of queue entries currently used */
+ int size; /* # of "DMAreq"'s in the request queue */
+ int oldest; /* index to oldest queue'd request */
+ int newest; /* index to newest queue'd request */
+ };
+
+/* bit definitions for DMAstatus word in DMAreq_header */
+
+#define DMA_ACTIVE 0x0004 /* DMA in progress */
+#define DMA_ERROR 0x0080 /* DMA hardware error */
+#define DMA_IGNORE 0x0002 /* flag to ignore this interrupt */
+
+/*------------------------------------------
+* macros for DMA request queue fiddling */
+
+ /* DMA status set/check macros */
+
+#define DMA_SETACTIVE(header) ((header)->status |= DMA_ACTIVE)
+#define DMA_CLRACTIVE(header) ((header)->status &= ~DMA_ACTIVE)
+#define DMA_ISACTIVE(header) ((header)->status & DMA_ACTIVE)
+
+#define DMA_SETERROR(header) ((header)->status |= DMA_ERROR)
+#define DMA_CLRERROR(header) ((header)->status &= ~DMA_ERROR)
+#define DMA_ISERROR(header) ((header)->status & DMA_ERROR)
+
+#define DMA_SETIGNORE(header) ((header)->status |= DMA_IGNORE)
+#define DMA_CLRIGNORE(header) ((header)->status &= ~DMA_IGNORE)
+#define DMA_ISIGNORE(header) ((header)->status & DMA_IGNORE)
+
+ /* yields TRUE if queue is empty (ISEMPTY) or full (ISFULL) */
+
+#define DMA_ISEMPTY(header) ((header)->used == 0)
+#define DMA_ISFULL(header) ((header)->used >= (header)->size)
+
+ /* returns address of the billet for next (PUT)
+ * or oldest (GET) request */
+
+#define DMA_PUTBEGIN(header) (&(header)->DMAreq[(header)->newest])
+#define DMA_GETBEGIN(header) (&(header)->DMAreq[(header)->oldest])
+
+ /* does queue access pointer maintenance */
+
+#define DMA_GETEND(header) (++(header)->oldest >= (header)->size \
+ ? (header)->oldest = 0 : 0); \
+ --(header)->used;
+
+#define DMA_PUTEND(header) (++(header)->newest >= (header)->size \
+ ? (header)->newest = 0 : 0); \
+ ++(header)->used;
+
+/******************************************************************
+*
+* COLOR MAP WRITE BUFFER DEFINITIONS
+*
+******************************************************************/
+
+ struct rgb {
+
+ unsigned char offset; /* color map address for load */
+ unsigned char red; /* data for red map */
+ unsigned char green; /* data for green map */
+ unsigned char blue; /* data for blue map */
+ };
+
+ struct color_buf {
+
+ char status; /* load request/service status */
+ short count; /* number of entries to br loaded */
+ struct rgb rgb[256];
+ };
+
+#define LOAD_COLOR_MAP 0x0001
+
+/******************************************************************
+*
+* SCROLL ASSIST DEFINITIONS
+*
+******************************************************************/
+
+ struct scroll {
+
+ short status;
+ short viper_constant;
+ short y_scroll_constant;
+ short y_offset;
+ short x_index_pending;
+ short y_index_pending;
+ };
+
+#define LOAD_REGS 0x0001
+#define LOAD_INDEX 0x0002
+
+/******************************************************************
+*
+* MOUSE/TABLET/KBD PROGRAMMING DEFINITIONS
+*
+******************************************************************/
+
+/*-----------------------------------
+* LK201 programmming definitions */
+
+#define LK_UPDOWN 0x86 /* bits for setting lk201 modes */
+#define LK_AUTODOWN 0x82
+#define LK_DOWN 0x80
+#define LK_DEFAULTS 0xD3 /* reset (some) default settings */
+#define LK_AR_ENABLE 0xE3 /* global auto repeat enable */
+#define LK_CL_ENABLE 0x1B /* keyclick enable */
+#define LK_KBD_ENABLE 0x8B /* keyboard enable */
+#define LK_BELL_ENABLE 0x23 /* the bell */
+#define LK_RING_BELL 0xA7 /* ring keyboard bell */
+
+#define LK_LED_ENABLE 0x13 /* light led */
+#define LK_LED_DISABLE 0x11 /* turn off led */
+#define LED_1 0x81 /* led bits */
+#define LED_2 0x82
+#define LED_3 0x84
+#define LED_4 0x88
+#define LED_ALL 0x8F
+#define LK_LED_HOLD LED_4
+#define LK_LED_LOCK LED_3
+#define LK_LED_COMPOSE LED_2
+#define LK_LED_WAIT LED_1
+
+#define LK_KDOWN_ERROR 0x3D /* key down on powerup error */
+#define LK_POWER_ERROR 0x3E /* keyboard failure on powerup test */
+#define LK_OUTPUT_ERROR 0xB5 /* keystrokes lost during inhibit */
+#define LK_INPUT_ERROR 0xB6 /* garbage command to keyboard */
+#define LK_LOWEST 0x56 /* lowest significant keycode */
+#define LK_DIV6_START 0xAD /* start of div 6 */
+#define LK_DIV5_END 0xB2 /* end of div 5 */
+
+#define LAST_PARAM 0x80 /* "no more params" bit */
+
+ struct prgkbd {
+
+ short cmd; /* LK201 command opcode */
+ short param1; /* 1st cmd parameter (can be null) */
+ short param2; /* 2nd cmd parameter (can be null) */
+ };
+
+/*-------------------------
+* "special" LK-201 keys */
+
+#define SHIFT 174
+#define LOCK 176
+#define REPEAT 180
+#define CNTRL 175
+#define ALLUP 179
+
+/*--------------------------------
+* cursor programming structure */
+
+ struct prg_cursor {
+
+ unsigned short acc_factor; /* cursor aceleration factor */
+ unsigned short threshold; /* threshold to trigger acc at */
+ };
+
+/*---------------------
+* mouse definitions */
+
+#define INC_STREAM_MODE 'R' /* stream mode reports (55 hz) */
+#define PROMPT_MODE 'D' /* report when prompted */
+#define REQUEST_POS 'P' /* request position report */
+#define SELF_TEST 'T' /* request self test */
+
+#define MOUSE_ID 0x2 /* mouse ID in lo 4 bits */
+
+#define START_FRAME 0x80 /* start of report frame bit */
+#define X_SIGN 0x10 /* position sign bits */
+#define Y_SIGN 0x08
+
+#define RIGHT_BUTTON 0x01 /* mouse buttons */
+#define MIDDLE_BUTTON 0x02
+#define LEFT_BUTTON 0x04
+
+ /* mouse report structure definition */
+
+ struct mouse_report {
+
+ char state; /* buttons and sign bits */
+ short dx; /* delta X since last change */
+ short dy; /* delta Y since last change */
+ char bytcnt; /* mouse report byte count */
+ };
+
+/*-----------------------------------------
+* tablet command/interface definitions */
+
+#define T_STREAM 'R' /* continuous stream report mode */
+#define T_POINT 'D' /* enter report-on-request mode */
+#define T_REQUEST 'P' /* request position report */
+
+#define T_BAUD 'B' /* increase baud to 9600 from 4800 */
+#define T_RATE_55 'K' /* report rate: 55/sec */
+#define T_RATE_72 'L' /* report rate: 72/sec */
+#define T_RATE_120 'M' /* report rate: 120/sec (9600 only) */
+
+#define T_TEST SELF_TEST /* do self test */
+
+#define TABLET_ID 0x4 /* tablet ID in lo 4 bits */
+
+#define T_START_FRAME 0x80 /* start of report frame bit */
+#define T_PROXIMITY 0x01 /* state pointer in proximity */
+
+#define T_LEFT_BUTTON 0x02 /* puck buttons */
+#define T_FRONT_BUTTON 0x04
+#define T_RIGHT_BUTTON 0x08
+#define T_BACK_BUTTON 0x10
+
+#define T_BARREL_BUTTON T_LEFT_BUTTON /* stylus buttons */
+#define T_TIP_BUTTON T_FRONT_BUTTON
+
--- /dev/null
+/* $OpenBSD: qevent.h,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qevent.h,v 1.1 1998/03/21 10:02:39 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)qevent.h 7.1 (Berkeley) 5/9/91
+ */
+
+/************************************************************************
+* *
+* Copyright (c) 1985 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. *
+* *
+************************************************************************/
+
+/*
+ * Event queue entries
+ */
+
+#ifndef _QEVENT_
+#define _QEVENT_
+
+typedef struct _vs_event {
+ unsigned short vse_x; /* x position */
+ unsigned short vse_y; /* y position */
+ unsigned short vse_time;/* 10 millisecond units (button only) */
+ char vse_type; /* button or motion? */
+ unsigned char vse_key; /* the key (button only) */
+ char vse_direction; /* which direction (button only) */
+ char vse_device; /* which device (button only) */
+} vsEvent;
+
+/* vse_type field */
+#define VSE_BUTTON 0 /* button moved */
+#define VSE_MMOTION 1 /* mouse moved */
+#define VSE_TMOTION 2 /* tablet moved */
+
+/* vse_direction field */
+#define VSE_KBTUP 0 /* up */
+#define VSE_KBTDOWN 1 /* down */
+#define VSE_KBTRAW 2 /* undetermined */
+
+/* vse_device field */
+#define VSE_NULL 0 /* NULL event (for QD_GETEVENT ret) */
+#define VSE_MOUSE 1 /* mouse */
+#define VSE_DKB 2 /* main keyboard */
+#define VSE_TABLET 3 /* graphics tablet */
+#define VSE_AUX 4 /* auxiliary */
+#define VSE_CONSOLE 5 /* console */
+
+/* The event queue */
+
+typedef struct _vs_eventqueue {
+ vsEvent *events; /* input event buffer */
+ int size; /* size of event buffer */
+ int head; /* index into events */
+ int tail; /* index into events */
+} vsEventQueue;
+
+/* mouse cursor position */
+
+typedef struct _vs_cursor {
+ short x;
+ short y;
+} vsCursor;
+
+/* mouse motion rectangle */
+
+typedef struct _vs_box {
+ short bottom;
+ short right;
+ short left;
+ short top;
+} vsBox;
+
+#endif /*_QEVENT_*/
--- /dev/null
+/* $OpenBSD: qfont.c,v 1.1 2000/04/27 03:14:48 bjc Exp $ */
+/* $NetBSD: qfont.c,v 1.4 1999/06/20 17:58:57 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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.
+ *
+ * @(#)qfont.c 7.2 (Berkeley) 1/21/94
+ */
+
+/*
+ * derived from: "@(#)qfont.c 6.2 ULTRIX 2/4/88"
+ */
+
+/************************************************************************
+ * *
+ * Copyright (c) 1984, 1987 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. *
+ * *
+ * This software is derived from software received from the *
+ * University of California, Berkeley, and from Bell *
+ * Laboratories. Use, duplication, or disclosure is subject to *
+ * restrictions under license agreements with University of *
+ * California and with AT&T. *
+ * *
+ * 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. *
+ * *
+ ************************************************************************/
+
+/*
+ * The following tables are used to translate LK201 key strokes
+ * into ascii characters. The tables also support the special
+ * function keys.
+ */
+
+unsigned short q_key[]={
+ 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 0 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 8 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 16 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 24 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 32 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 40 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 48 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 56 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 64 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 72 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x101 ,0x102 /* 80 */
+ ,0x103 ,0x104 ,0x105 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 88 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x106 ,0x107 ,0x108 ,0x109 /* 96 */
+ ,0x10a ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 104 */
+ ,0x00 ,0x1b ,0x08 ,0x0a ,0x10b ,0x00 ,0x00 ,0x00 /* 112 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x10c ,0x10d ,0x00 ,0x00 /* 120 */
+ ,0x10e ,0x10f ,0x110 ,0x111 ,0x00 ,0x00 ,0x00 ,0x00 /* 128 */
+ ,0x00 ,0x00 ,0x112 ,0x113 ,0x114 ,0x115 ,0x116 ,0x117 /* 136 */
+ ,0x00 ,0x00 ,0x120 ,0x00 ,0x121 ,0x122 ,0x123 ,0x124 /* 144 */
+ ,0x125 ,0x126 ,0x127 ,0x128 ,0x129 ,0x12a ,0x12b ,0x12c /* 152 */
+ ,0x12d ,0x118 ,0x119 ,0x11a ,0x11b ,0x00 ,0x00 ,0x11c /* 160 */
+ ,0x11d ,0x11e ,0x11f ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 168 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 176 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,'\r' ,0x09 ,'`' /* 184 */
+ ,'1' ,'q' ,'a' ,'z' ,0x00 ,'2' ,'w' ,'s' /* 192 */
+ ,'x' ,'<' ,0x00 ,'3' ,'e' ,'d' ,'c' ,0x00 /* 200 */
+ ,'4' ,'r' ,'f' ,'v' ,' ' ,0x00 ,'5' ,'t' /* 208 */
+ ,'g' ,'b' ,0x00 ,'6' ,'y' ,'h' ,'n' ,0x00 /* 216 */
+ ,'7' ,'u' ,'j' ,'m' ,0x00 ,'8' ,'i' ,'k' /* 224 */
+ ,',' ,0x00 ,'9' ,'o' ,'l' ,'.' ,0x00 ,'0' /* 232 */
+ ,'p' ,0x00 ,';' ,'/' ,0x00 ,'=' ,']' ,'\\' /* 240 */
+ ,0x00 ,'-' ,'[' ,'\'' ,0x00 ,0x00 ,0x00 ,0x00 /* 248 */
+};
+
+unsigned short q_shift_key[]={
+ 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 0 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 8 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 16 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 24 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 32 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 40 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 48 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 56 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 64 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 72 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x101 ,0x102 /* 80 */
+ ,0x103 ,0x104 ,0x105 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 88 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x106 ,0x107 ,0x108 ,0x109 /* 96 */
+ ,0x10a ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 104 */
+ ,0x00 ,0x1b ,0x08 ,0x0a ,0x10b ,0x00 ,0x00 ,0x00 /* 112 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x10c ,0x10d ,0x00 ,0x00 /* 120 */
+ ,0x10e ,0x10f ,0x110 ,0x111 ,0x00 ,0x00 ,0x00 ,0x00 /* 128 */
+ ,0x00 ,0x00 ,0x112 ,0x113 ,0x114 ,0x115 ,0x116 ,0x117 /* 136 */
+ ,0x00 ,0x00 ,0x120 ,0x00 ,0x121 ,0x122 ,0x123 ,0x124 /* 144 */
+ ,0x125 ,0x126 ,0x127 ,0x128 ,0x129 ,0x12a ,0x12b ,0x12c /* 152 */
+ ,0x12d ,0x118 ,0x119 ,0x11a ,0x11b ,0x00 ,0x00 ,0x11c /* 160 */
+ ,0x11d ,0x11e ,0x11f ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 168 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 /* 176 */
+ ,0x00 ,0x00 ,0x00 ,0x00 ,0x7f ,'\r' ,0x09 ,'~' /* 184 */
+ ,'!' ,'Q' ,'A' ,'Z' ,0x00 ,'@' ,'W' ,'S' /* 192 */
+ ,'X' ,'>' ,0x00 ,'#' ,'E' ,'D' ,'C' ,0x00 /* 200 */
+ ,'$' ,'R' ,'F' ,'V' ,' ' ,0x00 ,'%' ,'T' /* 208 */
+ ,'G' ,'B' ,0x00 ,'^' ,'Y' ,'H' ,'N' ,0x00 /* 216 */
+ ,'&' ,'U' ,'J' ,'M' ,0x00 ,'*' ,'I' ,'K' /* 224 */
+ ,',' ,0x00 ,'(' ,'O' ,'L' ,'.' ,0x00 ,')' /* 232 */
+ ,'P' ,0x00 ,':' ,'?' ,0x00 ,'+' ,'}' ,'|' /* 240 */
+ ,0x00 ,'_' ,'{' ,'"' ,0x00 ,0x00 ,0x00 ,0x00 /* 248 */
+};
+
+/*
+ * LK201 special purpose keys. Translations from the tables above
+ * includes codes for the function keys and other goodies. They can
+ * be determined by the presence of the 8th bit being set. The
+ * following table is accessed by removing that bit and using the
+ * result as the index to the following table. Note that table begins
+ * a null entry.
+ */
+char *q_special[]={ 0,
+ "\33[11~", /* f1 */
+ "\33[12~", /* f2 */
+ "\33[13~", /* f3 */
+ "\33[14~", /* f4 */
+ "\33[15~", /* f5 */
+ "\33[17~", /* f6 */
+ "\33[18~", /* f7 */
+ "\33[19~", /* f8 */
+ "\33[20~", /* f9 */
+ "\33[21~", /* f10 */
+ "\33[26~", /* f14 */
+ "\33[28~", /* f15 */
+ "\33[29~", /* f16 */
+ "\33[31~", /* f17 */
+ "\33[32~", /* f18 */
+ "\33[33~", /* f19 */
+ "\33[34~", /* f20 */
+ "\33[1~", /* find */
+ "\33[2~", /* insert */
+ "\33[3~", /* remove */
+ "\33[4~", /* select */
+ "\33[5~", /* prev */
+ "\33[6~", /* next */
+ "\33OP", /* pf1 */
+ "\33OQ", /* pf2 */
+ "\33OR", /* pf3 */
+ "\33OS", /* pf4 */
+ "\33[D", /* left */
+ "\33[C", /* right */
+ "\33[B", /* down */
+ "\33[A", /* up */
+ "\33Op", /* key pad 0 */
+ "\33On", /* key pad . */
+ "\33OM", /* key pad enter */
+ "\33Oq", /* key pad 1 */
+ "\33Or", /* key pad 2 */
+ "\33Os", /* key pad 3 */
+ "\33Ot", /* key pad 4 */
+ "\33Ou", /* key pad 5 */
+ "\33Ov", /* key pad 6 */
+ "\33O/*", /* key pad , */
+ "\33Ow", /* key pad 7 */
+ "\33Ox", /* key pad 8 */
+ "\33Oy", /* key pad 9 */
+ "\33Om", /* key pad - */
+ /*
+ * The following strings are to allow a numeric keypad
+ * mode and still use the same translation tables
+ */
+ "0",
+ ".",
+ "\r",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ ",",
+ "7",
+ "8",
+ "9",
+ "-"
+};
+
+
+/*
+ * QVSS font table of displayable characters.
+ */
+char q_font[]={
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+ 0x00, /* 0x00000000 */
+/* */
+ 0x00, /* 0x00000000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x08, /* 0x00001000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x00, /* 0x00000000 ! */
+ 0x00, /* 0x00000000 ! */
+/* */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x24, /* 0x00100100 " */
+ 0x24, /* 0x00100100 " */
+ 0x24, /* 0x00100100 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+ 0x00, /* 0x00000000 " */
+/* */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x12, /* 0x00010010 # */
+ 0x12, /* 0x00010010 # */
+ 0x3f, /* 0x00111111 # */
+ 0x12, /* 0x00010010 # */
+ 0x12, /* 0x00010010 # */
+ 0x3f, /* 0x00111111 # */
+ 0x12, /* 0x00010010 # */
+ 0x12, /* 0x00010010 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+ 0x00, /* 0x00000000 # */
+/* */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x08, /* 0x00001000 $ */
+ 0x3e, /* 0x00111110 $ */
+ 0x09, /* 0x00001001 $ */
+ 0x09, /* 0x00001001 $ */
+ 0x3e, /* 0x00111110 $ */
+ 0x48, /* 0x01001000 $ */
+ 0x48, /* 0x01001000 $ */
+ 0x3e, /* 0x00111110 $ */
+ 0x08, /* 0x00001000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+ 0x00, /* 0x00000000 $ */
+/* */
+ 0x00, /* 0x00000000 % */
+ 0x00, /* 0x00000000 % */
+ 0x42, /* 0x01000010 % */
+ 0x25, /* 0x00100101 % */
+ 0x25, /* 0x00100101 % */
+ 0x12, /* 0x00010010 % */
+ 0x08, /* 0x00001000 % */
+ 0x08, /* 0x00001000 % */
+ 0x24, /* 0x00100100 % */
+ 0x52, /* 0x01010010 % */
+ 0x52, /* 0x01010010 % */
+ 0x21, /* 0x00100001 % */
+ 0x00, /* 0x00000000 % */
+ 0x00, /* 0x00000000 % */
+ 0x00, /* 0x00000000 % */
+/* */
+ 0x00, /* 0x00000000 & */
+ 0x00, /* 0x00000000 & */
+ 0x0e, /* 0x00001110 & */
+ 0x11, /* 0x00010001 & */
+ 0x11, /* 0x00010001 & */
+ 0x11, /* 0x00010001 & */
+ 0x0e, /* 0x00001110 & */
+ 0x11, /* 0x00010001 & */
+ 0x51, /* 0x01010001 & */
+ 0x21, /* 0x00100001 & */
+ 0x31, /* 0x00110001 & */
+ 0x4e, /* 0x01001110 & */
+ 0x00, /* 0x00000000 & */
+ 0x00, /* 0x00000000 & */
+ 0x00, /* 0x00000000 & */
+/* */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x38, /* 0x00111000 ' */
+ 0x18, /* 0x00011000 ' */
+ 0x04, /* 0x00000100 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+ 0x00, /* 0x00000000 ' */
+/* */
+ 0x00, /* 0x00000000 ( */
+ 0x00, /* 0x00000000 ( */
+ 0x10, /* 0x00010000 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x04, /* 0x00000100 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x08, /* 0x00001000 ( */
+ 0x10, /* 0x00010000 ( */
+ 0x00, /* 0x00000000 ( */
+ 0x00, /* 0x00000000 ( */
+ 0x00, /* 0x00000000 ( */
+/* */
+ 0x00, /* 0x00000000 ) */
+ 0x00, /* 0x00000000 ) */
+ 0x04, /* 0x00000100 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x10, /* 0x00010000 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x08, /* 0x00001000 ) */
+ 0x04, /* 0x00000100 ) */
+ 0x00, /* 0x00000000 ) */
+ 0x00, /* 0x00000000 ) */
+ 0x00, /* 0x00000000 ) */
+/* */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x22, /* 0x00100010 * */
+ 0x14, /* 0x00010100 * */
+ 0x7f, /* 0x01111111 * */
+ 0x14, /* 0x00010100 * */
+ 0x22, /* 0x00100010 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+ 0x00, /* 0x00000000 * */
+/* */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x7f, /* 0x01111111 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x08, /* 0x00001000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+ 0x00, /* 0x00000000 + */
+/* */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+ 0x1c, /* 0x00011100 , */
+ 0x0c, /* 0x00001100 , */
+ 0x02, /* 0x00000010 , */
+ 0x00, /* 0x00000000 , */
+ 0x00, /* 0x00000000 , */
+/* */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x7f, /* 0x01111111 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+ 0x00, /* 0x00000000 - */
+/* */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+ 0x08, /* 0x00001000 . */
+ 0x1c, /* 0x00011100 . */
+ 0x08, /* 0x00001000 . */
+ 0x00, /* 0x00000000 . */
+ 0x00, /* 0x00000000 . */
+/* */
+ 0x00, /* 0x00000000 / */
+ 0x00, /* 0x00000000 / */
+ 0x40, /* 0x01000000 / */
+ 0x40, /* 0x01000000 / */
+ 0x20, /* 0x00100000 / */
+ 0x10, /* 0x00010000 / */
+ 0x08, /* 0x00001000 / */
+ 0x04, /* 0x00000100 / */
+ 0x02, /* 0x00000010 / */
+ 0x01, /* 0x00000001 / */
+ 0x01, /* 0x00000001 / */
+ 0x01, /* 0x00000001 / */
+ 0x00, /* 0x00000000 / */
+ 0x00, /* 0x00000000 / */
+ 0x00, /* 0x00000000 / */
+/* */
+ 0x00, /* 0x00000000 0 */
+ 0x00, /* 0x00000000 0 */
+ 0x0c, /* 0x00001100 0 */
+ 0x12, /* 0x00010010 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x21, /* 0x00100001 0 */
+ 0x12, /* 0x00010010 0 */
+ 0x0c, /* 0x00001100 0 */
+ 0x00, /* 0x00000000 0 */
+ 0x00, /* 0x00000000 0 */
+ 0x00, /* 0x00000000 0 */
+/* */
+ 0x00, /* 0x00000000 1 */
+ 0x00, /* 0x00000000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x0c, /* 0x00001100 1 */
+ 0x0a, /* 0x00001010 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x08, /* 0x00001000 1 */
+ 0x3e, /* 0x00111110 1 */
+ 0x00, /* 0x00000000 1 */
+ 0x00, /* 0x00000000 1 */
+ 0x00, /* 0x00000000 1 */
+/* */
+ 0x00, /* 0x00000000 2 */
+ 0x00, /* 0x00000000 2 */
+ 0x3e, /* 0x00111110 2 */
+ 0x41, /* 0x01000001 2 */
+ 0x41, /* 0x01000001 2 */
+ 0x40, /* 0x01000000 2 */
+ 0x20, /* 0x00100000 2 */
+ 0x10, /* 0x00010000 2 */
+ 0x0c, /* 0x00001100 2 */
+ 0x02, /* 0x00000010 2 */
+ 0x01, /* 0x00000001 2 */
+ 0x7f, /* 0x01111111 2 */
+ 0x00, /* 0x00000000 2 */
+ 0x00, /* 0x00000000 2 */
+ 0x00, /* 0x00000000 2 */
+/* */
+ 0x00, /* 0x00000000 3 */
+ 0x00, /* 0x00000000 3 */
+ 0x7f, /* 0x01111111 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x20, /* 0x00100000 3 */
+ 0x10, /* 0x00010000 3 */
+ 0x38, /* 0x00111000 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x40, /* 0x01000000 3 */
+ 0x41, /* 0x01000001 3 */
+ 0x3e, /* 0x00111110 3 */
+ 0x00, /* 0x00000000 3 */
+ 0x00, /* 0x00000000 3 */
+ 0x00, /* 0x00000000 3 */
+/* */
+ 0x00, /* 0x00000000 4 */
+ 0x00, /* 0x00000000 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x30, /* 0x00110000 4 */
+ 0x28, /* 0x00101000 4 */
+ 0x24, /* 0x00100100 4 */
+ 0x22, /* 0x00100010 4 */
+ 0x21, /* 0x00100001 4 */
+ 0x7f, /* 0x01111111 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x20, /* 0x00100000 4 */
+ 0x00, /* 0x00000000 4 */
+ 0x00, /* 0x00000000 4 */
+ 0x00, /* 0x00000000 4 */
+/* */
+ 0x00, /* 0x00000000 5 */
+ 0x00, /* 0x00000000 5 */
+ 0x7f, /* 0x01111111 5 */
+ 0x01, /* 0x00000001 5 */
+ 0x01, /* 0x00000001 5 */
+ 0x3d, /* 0x00111101 5 */
+ 0x43, /* 0x01000011 5 */
+ 0x40, /* 0x01000000 5 */
+ 0x40, /* 0x01000000 5 */
+ 0x40, /* 0x01000000 5 */
+ 0x41, /* 0x01000001 5 */
+ 0x3e, /* 0x00111110 5 */
+ 0x00, /* 0x00000000 5 */
+ 0x00, /* 0x00000000 5 */
+ 0x00, /* 0x00000000 5 */
+/* */
+ 0x00, /* 0x00000000 6 */
+ 0x00, /* 0x00000000 6 */
+ 0x3c, /* 0x00111100 6 */
+ 0x02, /* 0x00000010 6 */
+ 0x01, /* 0x00000001 6 */
+ 0x01, /* 0x00000001 6 */
+ 0x3d, /* 0x00111101 6 */
+ 0x43, /* 0x01000011 6 */
+ 0x41, /* 0x01000001 6 */
+ 0x41, /* 0x01000001 6 */
+ 0x41, /* 0x01000001 6 */
+ 0x3e, /* 0x00111110 6 */
+ 0x00, /* 0x00000000 6 */
+ 0x00, /* 0x00000000 6 */
+ 0x00, /* 0x00000000 6 */
+/* */
+ 0x00, /* 0x00000000 7 */
+ 0x00, /* 0x00000000 7 */
+ 0x7f, /* 0x01111111 7 */
+ 0x40, /* 0x01000000 7 */
+ 0x40, /* 0x01000000 7 */
+ 0x20, /* 0x00100000 7 */
+ 0x10, /* 0x00010000 7 */
+ 0x08, /* 0x00001000 7 */
+ 0x04, /* 0x00000100 7 */
+ 0x04, /* 0x00000100 7 */
+ 0x02, /* 0x00000010 7 */
+ 0x02, /* 0x00000010 7 */
+ 0x00, /* 0x00000000 7 */
+ 0x00, /* 0x00000000 7 */
+ 0x00, /* 0x00000000 7 */
+/* */
+ 0x00, /* 0x00000000 8 */
+ 0x00, /* 0x00000000 8 */
+ 0x3e, /* 0x00111110 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x3e, /* 0x00111110 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x41, /* 0x01000001 8 */
+ 0x3e, /* 0x00111110 8 */
+ 0x00, /* 0x00000000 8 */
+ 0x00, /* 0x00000000 8 */
+ 0x00, /* 0x00000000 8 */
+/* */
+ 0x00, /* 0x00000000 9 */
+ 0x00, /* 0x00000000 9 */
+ 0x3e, /* 0x00111110 9 */
+ 0x41, /* 0x01000001 9 */
+ 0x41, /* 0x01000001 9 */
+ 0x41, /* 0x01000001 9 */
+ 0x61, /* 0x01100001 9 */
+ 0x5e, /* 0x01011110 9 */
+ 0x40, /* 0x01000000 9 */
+ 0x40, /* 0x01000000 9 */
+ 0x20, /* 0x00100000 9 */
+ 0x1e, /* 0x00011110 9 */
+ 0x00, /* 0x00000000 9 */
+ 0x00, /* 0x00000000 9 */
+ 0x00, /* 0x00000000 9 */
+/* */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x08, /* 0x00001000 : */
+ 0x1c, /* 0x00011100 : */
+ 0x08, /* 0x00001000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+ 0x08, /* 0x00001000 : */
+ 0x1c, /* 0x00011100 : */
+ 0x08, /* 0x00001000 : */
+ 0x00, /* 0x00000000 : */
+ 0x00, /* 0x00000000 : */
+/* */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x08, /* 0x00001000 ; */
+ 0x1c, /* 0x00011100 ; */
+ 0x08, /* 0x00001000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x1c, /* 0x00011100 ; */
+ 0x0c, /* 0x00001100 ; */
+ 0x02, /* 0x00000010 ; */
+ 0x00, /* 0x00000000 ; */
+ 0x00, /* 0x00000000 ; */
+/* */
+ 0x00, /* 0x00000000 < */
+ 0x00, /* 0x00000000 < */
+ 0x20, /* 0x00100000 < */
+ 0x10, /* 0x00010000 < */
+ 0x08, /* 0x00001000 < */
+ 0x04, /* 0x00000100 < */
+ 0x02, /* 0x00000010 < */
+ 0x02, /* 0x00000010 < */
+ 0x04, /* 0x00000100 < */
+ 0x08, /* 0x00001000 < */
+ 0x10, /* 0x00010000 < */
+ 0x20, /* 0x00100000 < */
+ 0x00, /* 0x00000000 < */
+ 0x00, /* 0x00000000 < */
+ 0x00, /* 0x00000000 < */
+/* */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x7f, /* 0x01111111 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x7f, /* 0x01111111 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+ 0x00, /* 0x00000000 = */
+/* */
+ 0x00, /* 0x00000000 > */
+ 0x00, /* 0x00000000 > */
+ 0x02, /* 0x00000010 > */
+ 0x04, /* 0x00000100 > */
+ 0x08, /* 0x00001000 > */
+ 0x10, /* 0x00010000 > */
+ 0x20, /* 0x00100000 > */
+ 0x20, /* 0x00100000 > */
+ 0x10, /* 0x00010000 > */
+ 0x08, /* 0x00001000 > */
+ 0x04, /* 0x00000100 > */
+ 0x02, /* 0x00000010 > */
+ 0x00, /* 0x00000000 > */
+ 0x00, /* 0x00000000 > */
+ 0x00, /* 0x00000000 > */
+/* */
+ 0x00, /* 0x00000000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x3e, /* 0x00111110 ? */
+ 0x41, /* 0x01000001 ? */
+ 0x41, /* 0x01000001 ? */
+ 0x40, /* 0x01000000 ? */
+ 0x20, /* 0x00100000 ? */
+ 0x10, /* 0x00010000 ? */
+ 0x08, /* 0x00001000 ? */
+ 0x08, /* 0x00001000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x08, /* 0x00001000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x00, /* 0x00000000 ? */
+ 0x00, /* 0x00000000 ? */
+/* */
+ 0x00, /* 0x00000000 @ */
+ 0x00, /* 0x00000000 @ */
+ 0x3e, /* 0x00111110 @ */
+ 0x41, /* 0x01000001 @ */
+ 0x41, /* 0x01000001 @ */
+ 0x79, /* 0x01111001 @ */
+ 0x45, /* 0x01000101 @ */
+ 0x65, /* 0x01100101 @ */
+ 0x59, /* 0x01011001 @ */
+ 0x01, /* 0x00000001 @ */
+ 0x01, /* 0x00000001 @ */
+ 0x3e, /* 0x00111110 @ */
+ 0x00, /* 0x00000000 @ */
+ 0x00, /* 0x00000000 @ */
+ 0x00, /* 0x00000000 @ */
+/* */
+ 0x00, /* 0x00000000 A */
+ 0x00, /* 0x00000000 A */
+ 0x08, /* 0x00001000 A */
+ 0x14, /* 0x00010100 A */
+ 0x22, /* 0x00100010 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x7f, /* 0x01111111 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x41, /* 0x01000001 A */
+ 0x00, /* 0x00000000 A */
+ 0x00, /* 0x00000000 A */
+ 0x00, /* 0x00000000 A */
+/* */
+ 0x00, /* 0x00000000 B */
+ 0x00, /* 0x00000000 B */
+ 0x3f, /* 0x00111111 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x3e, /* 0x00111110 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x42, /* 0x01000010 B */
+ 0x3f, /* 0x00111111 B */
+ 0x00, /* 0x00000000 B */
+ 0x00, /* 0x00000000 B */
+ 0x00, /* 0x00000000 B */
+/* */
+ 0x00, /* 0x00000000 C */
+ 0x00, /* 0x00000000 C */
+ 0x3e, /* 0x00111110 C */
+ 0x41, /* 0x01000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x01, /* 0x00000001 C */
+ 0x41, /* 0x01000001 C */
+ 0x3e, /* 0x00111110 C */
+ 0x00, /* 0x00000000 C */
+ 0x00, /* 0x00000000 C */
+ 0x00, /* 0x00000000 C */
+/* */
+ 0x00, /* 0x00000000 D */
+ 0x00, /* 0x00000000 D */
+ 0x3f, /* 0x00111111 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x42, /* 0x01000010 D */
+ 0x3f, /* 0x00111111 D */
+ 0x00, /* 0x00000000 D */
+ 0x00, /* 0x00000000 D */
+ 0x00, /* 0x00000000 D */
+/* */
+ 0x00, /* 0x00000000 E */
+ 0x00, /* 0x00000000 E */
+ 0x7e, /* 0x01111110 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x1e, /* 0x00011110 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x02, /* 0x00000010 E */
+ 0x7e, /* 0x01111110 E */
+ 0x00, /* 0x00000000 E */
+ 0x00, /* 0x00000000 E */
+ 0x00, /* 0x00000000 E */
+/* */
+ 0x00, /* 0x00000000 F */
+ 0x00, /* 0x00000000 F */
+ 0x7e, /* 0x01111110 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x1e, /* 0x00011110 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x02, /* 0x00000010 F */
+ 0x00, /* 0x00000000 F */
+ 0x00, /* 0x00000000 F */
+ 0x00, /* 0x00000000 F */
+/* */
+ 0x00, /* 0x00000000 G */
+ 0x00, /* 0x00000000 G */
+ 0x3e, /* 0x00111110 G */
+ 0x41, /* 0x01000001 G */
+ 0x01, /* 0x00000001 G */
+ 0x01, /* 0x00000001 G */
+ 0x01, /* 0x00000001 G */
+ 0x71, /* 0x01110001 G */
+ 0x41, /* 0x01000001 G */
+ 0x41, /* 0x01000001 G */
+ 0x41, /* 0x01000001 G */
+ 0x3e, /* 0x00111110 G */
+ 0x00, /* 0x00000000 G */
+ 0x00, /* 0x00000000 G */
+ 0x00, /* 0x00000000 G */
+/* */
+ 0x00, /* 0x00000000 H */
+ 0x00, /* 0x00000000 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x7f, /* 0x01111111 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x41, /* 0x01000001 H */
+ 0x00, /* 0x00000000 H */
+ 0x00, /* 0x00000000 H */
+ 0x00, /* 0x00000000 H */
+/* */
+ 0x00, /* 0x00000000 I */
+ 0x00, /* 0x00000000 I */
+ 0x3e, /* 0x00111110 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x08, /* 0x00001000 I */
+ 0x3e, /* 0x00111110 I */
+ 0x00, /* 0x00000000 I */
+ 0x00, /* 0x00000000 I */
+ 0x00, /* 0x00000000 I */
+/* */
+ 0x00, /* 0x00000000 J */
+ 0x00, /* 0x00000000 J */
+ 0x78, /* 0x01111000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x20, /* 0x00100000 J */
+ 0x21, /* 0x00100001 J */
+ 0x1e, /* 0x00011110 J */
+ 0x00, /* 0x00000000 J */
+ 0x00, /* 0x00000000 J */
+ 0x00, /* 0x00000000 J */
+/* */
+ 0x00, /* 0x00000000 K */
+ 0x00, /* 0x00000000 K */
+ 0x41, /* 0x01000001 K */
+ 0x21, /* 0x00100001 K */
+ 0x11, /* 0x00010001 K */
+ 0x09, /* 0x00001001 K */
+ 0x07, /* 0x00000111 K */
+ 0x05, /* 0x00000101 K */
+ 0x09, /* 0x00001001 K */
+ 0x11, /* 0x00010001 K */
+ 0x21, /* 0x00100001 K */
+ 0x41, /* 0x01000001 K */
+ 0x00, /* 0x00000000 K */
+ 0x00, /* 0x00000000 K */
+ 0x00, /* 0x00000000 K */
+/* */
+ 0x00, /* 0x00000000 L */
+ 0x00, /* 0x00000000 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x01, /* 0x00000001 L */
+ 0x7f, /* 0x01111111 L */
+ 0x00, /* 0x00000000 L */
+ 0x00, /* 0x00000000 L */
+ 0x00, /* 0x00000000 L */
+/* */
+ 0x00, /* 0x00000000 M */
+ 0x00, /* 0x00000000 M */
+ 0x41, /* 0x01000001 M */
+ 0x41, /* 0x01000001 M */
+ 0x63, /* 0x01100011 M */
+ 0x55, /* 0x01010101 M */
+ 0x55, /* 0x01010101 M */
+ 0x49, /* 0x01001001 M */
+ 0x49, /* 0x01001001 M */
+ 0x41, /* 0x01000001 M */
+ 0x41, /* 0x01000001 M */
+ 0x41, /* 0x01000001 M */
+ 0x00, /* 0x00000000 M */
+ 0x00, /* 0x00000000 M */
+ 0x00, /* 0x00000000 M */
+/* */
+ 0x00, /* 0x00000000 N */
+ 0x00, /* 0x00000000 N */
+ 0x41, /* 0x01000001 N */
+ 0x41, /* 0x01000001 N */
+ 0x43, /* 0x01000011 N */
+ 0x45, /* 0x01000101 N */
+ 0x49, /* 0x01001001 N */
+ 0x51, /* 0x01010001 N */
+ 0x61, /* 0x01100001 N */
+ 0x41, /* 0x01000001 N */
+ 0x41, /* 0x01000001 N */
+ 0x41, /* 0x01000001 N */
+ 0x00, /* 0x00000000 N */
+ 0x00, /* 0x00000000 N */
+ 0x00, /* 0x00000000 N */
+/* */
+ 0x00, /* 0x00000000 O */
+ 0x00, /* 0x00000000 O */
+ 0x3e, /* 0x00111110 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x41, /* 0x01000001 O */
+ 0x3e, /* 0x00111110 O */
+ 0x00, /* 0x00000000 O */
+ 0x00, /* 0x00000000 O */
+ 0x00, /* 0x00000000 O */
+/* */
+ 0x00, /* 0x00000000 P */
+ 0x00, /* 0x00000000 P */
+ 0x3f, /* 0x00111111 P */
+ 0x41, /* 0x01000001 P */
+ 0x41, /* 0x01000001 P */
+ 0x41, /* 0x01000001 P */
+ 0x3f, /* 0x00111111 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x01, /* 0x00000001 P */
+ 0x00, /* 0x00000000 P */
+ 0x00, /* 0x00000000 P */
+ 0x00, /* 0x00000000 P */
+/* */
+ 0x00, /* 0x00000000 Q */
+ 0x00, /* 0x00000000 Q */
+ 0x3e, /* 0x00111110 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x41, /* 0x01000001 Q */
+ 0x49, /* 0x01001001 Q */
+ 0x51, /* 0x01010001 Q */
+ 0x3e, /* 0x00111110 Q */
+ 0x40, /* 0x01000000 Q */
+ 0x00, /* 0x00000000 Q */
+ 0x00, /* 0x00000000 Q */
+/* */
+ 0x00, /* 0x00000000 R */
+ 0x00, /* 0x00000000 R */
+ 0x3f, /* 0x00111111 R */
+ 0x41, /* 0x01000001 R */
+ 0x41, /* 0x01000001 R */
+ 0x41, /* 0x01000001 R */
+ 0x3f, /* 0x00111111 R */
+ 0x09, /* 0x00001001 R */
+ 0x11, /* 0x00010001 R */
+ 0x21, /* 0x00100001 R */
+ 0x41, /* 0x01000001 R */
+ 0x41, /* 0x01000001 R */
+ 0x00, /* 0x00000000 R */
+ 0x00, /* 0x00000000 R */
+ 0x00, /* 0x00000000 R */
+/* */
+ 0x00, /* 0x00000000 S */
+ 0x00, /* 0x00000000 S */
+ 0x3e, /* 0x00111110 S */
+ 0x41, /* 0x01000001 S */
+ 0x01, /* 0x00000001 S */
+ 0x01, /* 0x00000001 S */
+ 0x3e, /* 0x00111110 S */
+ 0x40, /* 0x01000000 S */
+ 0x40, /* 0x01000000 S */
+ 0x40, /* 0x01000000 S */
+ 0x41, /* 0x01000001 S */
+ 0x3e, /* 0x00111110 S */
+ 0x00, /* 0x00000000 S */
+ 0x00, /* 0x00000000 S */
+ 0x00, /* 0x00000000 S */
+/* */
+ 0x00, /* 0x00000000 T */
+ 0x00, /* 0x00000000 T */
+ 0x7f, /* 0x01111111 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x08, /* 0x00001000 T */
+ 0x00, /* 0x00000000 T */
+ 0x00, /* 0x00000000 T */
+ 0x00, /* 0x00000000 T */
+/* */
+ 0x00, /* 0x00000000 U */
+ 0x00, /* 0x00000000 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x41, /* 0x01000001 U */
+ 0x3e, /* 0x00111110 U */
+ 0x00, /* 0x00000000 U */
+ 0x00, /* 0x00000000 U */
+ 0x00, /* 0x00000000 U */
+/* */
+ 0x00, /* 0x00000000 V */
+ 0x00, /* 0x00000000 V */
+ 0x41, /* 0x01000001 V */
+ 0x41, /* 0x01000001 V */
+ 0x41, /* 0x01000001 V */
+ 0x22, /* 0x00100010 V */
+ 0x22, /* 0x00100010 V */
+ 0x22, /* 0x00100010 V */
+ 0x14, /* 0x00010100 V */
+ 0x14, /* 0x00010100 V */
+ 0x14, /* 0x00010100 V */
+ 0x08, /* 0x00001000 V */
+ 0x00, /* 0x00000000 V */
+ 0x00, /* 0x00000000 V */
+ 0x00, /* 0x00000000 V */
+/* */
+ 0x00, /* 0x00000000 W */
+ 0x00, /* 0x00000000 W */
+ 0x41, /* 0x01000001 W */
+ 0x41, /* 0x01000001 W */
+ 0x41, /* 0x01000001 W */
+ 0x41, /* 0x01000001 W */
+ 0x49, /* 0x01001001 W */
+ 0x49, /* 0x01001001 W */
+ 0x49, /* 0x01001001 W */
+ 0x49, /* 0x01001001 W */
+ 0x55, /* 0x01010101 W */
+ 0x22, /* 0x00100010 W */
+ 0x00, /* 0x00000000 W */
+ 0x00, /* 0x00000000 W */
+ 0x00, /* 0x00000000 W */
+/* */
+ 0x00, /* 0x00000000 X */
+ 0x00, /* 0x00000000 X */
+ 0x41, /* 0x01000001 X */
+ 0x41, /* 0x01000001 X */
+ 0x22, /* 0x00100010 X */
+ 0x14, /* 0x00010100 X */
+ 0x08, /* 0x00001000 X */
+ 0x08, /* 0x00001000 X */
+ 0x14, /* 0x00010100 X */
+ 0x22, /* 0x00100010 X */
+ 0x41, /* 0x01000001 X */
+ 0x41, /* 0x01000001 X */
+ 0x00, /* 0x00000000 X */
+ 0x00, /* 0x00000000 X */
+ 0x00, /* 0x00000000 X */
+/* */
+ 0x00, /* 0x00000000 Y */
+ 0x00, /* 0x00000000 Y */
+ 0x41, /* 0x01000001 Y */
+ 0x41, /* 0x01000001 Y */
+ 0x22, /* 0x00100010 Y */
+ 0x14, /* 0x00010100 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x08, /* 0x00001000 Y */
+ 0x00, /* 0x00000000 Y */
+ 0x00, /* 0x00000000 Y */
+ 0x00, /* 0x00000000 Y */
+/* */
+ 0x00, /* 0x00000000 Z */
+ 0x00, /* 0x00000000 Z */
+ 0x7f, /* 0x01111111 Z */
+ 0x40, /* 0x01000000 Z */
+ 0x20, /* 0x00100000 Z */
+ 0x10, /* 0x00010000 Z */
+ 0x08, /* 0x00001000 Z */
+ 0x04, /* 0x00000100 Z */
+ 0x02, /* 0x00000010 Z */
+ 0x01, /* 0x00000001 Z */
+ 0x01, /* 0x00000001 Z */
+ 0x7f, /* 0x01111111 Z */
+ 0x00, /* 0x00000000 Z */
+ 0x00, /* 0x00000000 Z */
+ 0x00, /* 0x00000000 Z */
+/* */
+ 0x00, /* 0x00000000 [ */
+ 0x00, /* 0x00000000 [ */
+ 0x3c, /* 0x00111100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x04, /* 0x00000100 [ */
+ 0x3c, /* 0x00111100 [ */
+ 0x00, /* 0x00000000 [ */
+ 0x00, /* 0x00000000 [ */
+ 0x00, /* 0x00000000 [ */
+/* */
+ 0x00, /* 0x00000000 \ */
+ 0x00, /* 0x00000000 \ */
+ 0x01, /* 0x00000001 \ */
+ 0x02, /* 0x00000010 \ */
+ 0x02, /* 0x00000010 \ */
+ 0x04, /* 0x00000100 \ */
+ 0x08, /* 0x00001000 \ */
+ 0x08, /* 0x00001000 \ */
+ 0x10, /* 0x00010000 \ */
+ 0x20, /* 0x00100000 \ */
+ 0x20, /* 0x00100000 \ */
+ 0x40, /* 0x01000000 \ */
+ 0x00, /* 0x00000000 \ */
+ 0x00, /* 0x00000000 \ */
+ 0x00, /* 0x00000000 \ */
+/* */
+ 0x00, /* 0x00000000 ] */
+ 0x00, /* 0x00000000 ] */
+ 0x1e, /* 0x00011110 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x10, /* 0x00010000 ] */
+ 0x1e, /* 0x00011110 ] */
+ 0x00, /* 0x00000000 ] */
+ 0x00, /* 0x00000000 ] */
+ 0x00, /* 0x00000000 ] */
+/* */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x08, /* 0x00001000 ^ */
+ 0x14, /* 0x00010100 ^ */
+ 0x22, /* 0x00100010 ^ */
+ 0x41, /* 0x01000001 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+ 0x00, /* 0x00000000 ^ */
+/* */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x7f, /* 0x01111111 _ */
+ 0x00, /* 0x00000000 _ */
+ 0x00, /* 0x00000000 _ */
+/* */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x0e, /* 0x00001110 ` */
+ 0x0c, /* 0x00001100 ` */
+ 0x10, /* 0x00010000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+ 0x00, /* 0x00000000 ` */
+/* */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x3e, /* 0x00111110 a */
+ 0x40, /* 0x01000000 a */
+ 0x40, /* 0x01000000 a */
+ 0x7e, /* 0x01111110 a */
+ 0x41, /* 0x01000001 a */
+ 0x61, /* 0x01100001 a */
+ 0x5e, /* 0x01011110 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+ 0x00, /* 0x00000000 a */
+/* */
+ 0x00, /* 0x00000000 b */
+ 0x00, /* 0x00000000 b */
+ 0x01, /* 0x00000001 b */
+ 0x01, /* 0x00000001 b */
+ 0x01, /* 0x00000001 b */
+ 0x3d, /* 0x00111101 b */
+ 0x43, /* 0x01000011 b */
+ 0x41, /* 0x01000001 b */
+ 0x41, /* 0x01000001 b */
+ 0x41, /* 0x01000001 b */
+ 0x43, /* 0x01000011 b */
+ 0x3d, /* 0x00111101 b */
+ 0x00, /* 0x00000000 b */
+ 0x00, /* 0x00000000 b */
+ 0x00, /* 0x00000000 b */
+/* */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x3e, /* 0x00111110 c */
+ 0x41, /* 0x01000001 c */
+ 0x01, /* 0x00000001 c */
+ 0x01, /* 0x00000001 c */
+ 0x01, /* 0x00000001 c */
+ 0x41, /* 0x01000001 c */
+ 0x3e, /* 0x00111110 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+ 0x00, /* 0x00000000 c */
+/* */
+ 0x00, /* 0x00000000 d */
+ 0x00, /* 0x00000000 d */
+ 0x40, /* 0x01000000 d */
+ 0x40, /* 0x01000000 d */
+ 0x40, /* 0x01000000 d */
+ 0x5e, /* 0x01011110 d */
+ 0x61, /* 0x01100001 d */
+ 0x41, /* 0x01000001 d */
+ 0x41, /* 0x01000001 d */
+ 0x41, /* 0x01000001 d */
+ 0x61, /* 0x01100001 d */
+ 0x5e, /* 0x01011110 d */
+ 0x00, /* 0x00000000 d */
+ 0x00, /* 0x00000000 d */
+ 0x00, /* 0x00000000 d */
+/* */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x3e, /* 0x00111110 e */
+ 0x41, /* 0x01000001 e */
+ 0x41, /* 0x01000001 e */
+ 0x7f, /* 0x01111111 e */
+ 0x01, /* 0x00000001 e */
+ 0x01, /* 0x00000001 e */
+ 0x3e, /* 0x00111110 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+ 0x00, /* 0x00000000 e */
+/* */
+ 0x00, /* 0x00000000 f */
+ 0x00, /* 0x00000000 f */
+ 0x38, /* 0x00111000 f */
+ 0x44, /* 0x01000100 f */
+ 0x44, /* 0x01000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x1f, /* 0x00011111 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x04, /* 0x00000100 f */
+ 0x00, /* 0x00000000 f */
+ 0x00, /* 0x00000000 f */
+ 0x00, /* 0x00000000 f */
+/* */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x00, /* 0x00000000 g */
+ 0x5e, /* 0x01011110 g */
+ 0x21, /* 0x00100001 g */
+ 0x21, /* 0x00100001 g */
+ 0x21, /* 0x00100001 g */
+ 0x1e, /* 0x00011110 g */
+ 0x01, /* 0x00000001 g */
+ 0x3e, /* 0x00111110 g */
+ 0x41, /* 0x01000001 g */
+ 0x41, /* 0x01000001 g */
+ 0x3e, /* 0x00111110 g */
+/* */
+ 0x00, /* 0x00000000 h */
+ 0x00, /* 0x00000000 h */
+ 0x01, /* 0x00000001 h */
+ 0x01, /* 0x00000001 h */
+ 0x01, /* 0x00000001 h */
+ 0x3d, /* 0x00111101 h */
+ 0x43, /* 0x01000011 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x41, /* 0x01000001 h */
+ 0x00, /* 0x00000000 h */
+ 0x00, /* 0x00000000 h */
+ 0x00, /* 0x00000000 h */
+/* */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+ 0x08, /* 0x00001000 i */
+ 0x00, /* 0x00000000 i */
+ 0x0c, /* 0x00001100 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x08, /* 0x00001000 i */
+ 0x3e, /* 0x00111110 i */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+ 0x00, /* 0x00000000 i */
+/* */
+ 0x00, /* 0x00000000 j */
+ 0x00, /* 0x00000000 j */
+ 0x00, /* 0x00000000 j */
+ 0x20, /* 0x00100000 j */
+ 0x00, /* 0x00000000 j */
+ 0x38, /* 0x00111000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x20, /* 0x00100000 j */
+ 0x21, /* 0x00100001 j */
+ 0x21, /* 0x00100001 j */
+ 0x21, /* 0x00100001 j */
+ 0x1e, /* 0x00011110 j */
+/* */
+ 0x00, /* 0x00000000 k */
+ 0x00, /* 0x00000000 k */
+ 0x01, /* 0x00000001 k */
+ 0x01, /* 0x00000001 k */
+ 0x01, /* 0x00000001 k */
+ 0x41, /* 0x01000001 k */
+ 0x31, /* 0x00110001 k */
+ 0x0d, /* 0x00001101 k */
+ 0x03, /* 0x00000011 k */
+ 0x0d, /* 0x00001101 k */
+ 0x31, /* 0x00110001 k */
+ 0x41, /* 0x01000001 k */
+ 0x00, /* 0x00000000 k */
+ 0x00, /* 0x00000000 k */
+ 0x00, /* 0x00000000 k */
+/* */
+ 0x00, /* 0x00000000 l */
+ 0x00, /* 0x00000000 l */
+ 0x0c, /* 0x00001100 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x08, /* 0x00001000 l */
+ 0x3e, /* 0x00111110 l */
+ 0x00, /* 0x00000000 l */
+ 0x00, /* 0x00000000 l */
+ 0x00, /* 0x00000000 l */
+/* */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x37, /* 0x00110111 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x49, /* 0x01001001 m */
+ 0x41, /* 0x01000001 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+ 0x00, /* 0x00000000 m */
+/* */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x3d, /* 0x00111101 n */
+ 0x43, /* 0x01000011 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x41, /* 0x01000001 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+ 0x00, /* 0x00000000 n */
+/* */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x3e, /* 0x00111110 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x41, /* 0x01000001 o */
+ 0x3e, /* 0x00111110 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+ 0x00, /* 0x00000000 o */
+/* */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x00, /* 0x00000000 p */
+ 0x3d, /* 0x00111101 p */
+ 0x43, /* 0x01000011 p */
+ 0x41, /* 0x01000001 p */
+ 0x41, /* 0x01000001 p */
+ 0x41, /* 0x01000001 p */
+ 0x43, /* 0x01000011 p */
+ 0x3d, /* 0x00111101 p */
+ 0x01, /* 0x00000001 p */
+ 0x01, /* 0x00000001 p */
+ 0x01, /* 0x00000001 p */
+/* */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x00, /* 0x00000000 q */
+ 0x5e, /* 0x01011110 q */
+ 0x61, /* 0x01100001 q */
+ 0x41, /* 0x01000001 q */
+ 0x41, /* 0x01000001 q */
+ 0x41, /* 0x01000001 q */
+ 0x61, /* 0x01100001 q */
+ 0x5e, /* 0x01011110 q */
+ 0x40, /* 0x01000000 q */
+ 0x40, /* 0x01000000 q */
+ 0x40, /* 0x01000000 q */
+/* */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x39, /* 0x00111001 r */
+ 0x46, /* 0x01000110 r */
+ 0x42, /* 0x01000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x02, /* 0x00000010 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+ 0x00, /* 0x00000000 r */
+/* */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x3e, /* 0x00111110 s */
+ 0x41, /* 0x01000001 s */
+ 0x01, /* 0x00000001 s */
+ 0x3e, /* 0x00111110 s */
+ 0x40, /* 0x01000000 s */
+ 0x41, /* 0x01000001 s */
+ 0x3e, /* 0x00111110 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+ 0x00, /* 0x00000000 s */
+/* */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x3f, /* 0x00111111 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x04, /* 0x00000100 t */
+ 0x44, /* 0x01000100 t */
+ 0x38, /* 0x00111000 t */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+ 0x00, /* 0x00000000 t */
+/* */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x21, /* 0x00100001 u */
+ 0x5e, /* 0x01011110 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+ 0x00, /* 0x00000000 u */
+/* */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x41, /* 0x01000001 v */
+ 0x41, /* 0x01000001 v */
+ 0x22, /* 0x00100010 v */
+ 0x22, /* 0x00100010 v */
+ 0x14, /* 0x00010100 v */
+ 0x14, /* 0x00010100 v */
+ 0x08, /* 0x00001000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+ 0x00, /* 0x00000000 v */
+/* */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x41, /* 0x01000001 w */
+ 0x41, /* 0x01000001 w */
+ 0x49, /* 0x01001001 w */
+ 0x49, /* 0x01001001 w */
+ 0x49, /* 0x01001001 w */
+ 0x55, /* 0x01010101 w */
+ 0x22, /* 0x00100010 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+ 0x00, /* 0x00000000 w */
+/* */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x41, /* 0x01000001 x */
+ 0x22, /* 0x00100010 x */
+ 0x14, /* 0x00010100 x */
+ 0x08, /* 0x00001000 x */
+ 0x14, /* 0x00010100 x */
+ 0x22, /* 0x00100010 x */
+ 0x41, /* 0x01000001 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+ 0x00, /* 0x00000000 x */
+/* */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x00, /* 0x00000000 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x21, /* 0x00100001 y */
+ 0x31, /* 0x00110001 y */
+ 0x2e, /* 0x00101110 y */
+ 0x20, /* 0x00100000 y */
+ 0x21, /* 0x00100001 y */
+ 0x1e, /* 0x00011110 y */
+/* */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x7f, /* 0x01111111 z */
+ 0x20, /* 0x00100000 z */
+ 0x10, /* 0x00010000 z */
+ 0x08, /* 0x00001000 z */
+ 0x04, /* 0x00000100 z */
+ 0x02, /* 0x00000010 z */
+ 0x7f, /* 0x01111111 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+ 0x00, /* 0x00000000 z */
+/* */
+ 0x00, /* 0x00000000 { */
+ 0x00, /* 0x00000000 { */
+ 0x70, /* 0x01110000 { */
+ 0x08, /* 0x00001000 { */
+ 0x08, /* 0x00001000 { */
+ 0x10, /* 0x00010000 { */
+ 0x0c, /* 0x00001100 { */
+ 0x0c, /* 0x00001100 { */
+ 0x10, /* 0x00010000 { */
+ 0x08, /* 0x00001000 { */
+ 0x08, /* 0x00001000 { */
+ 0x70, /* 0x01110000 { */
+ 0x00, /* 0x00000000 { */
+ 0x00, /* 0x00000000 { */
+ 0x00, /* 0x00000000 { */
+/* */
+ 0x00, /* 0x00000000 | */
+ 0x00, /* 0x00000000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x08, /* 0x00001000 | */
+ 0x00, /* 0x00000000 | */
+ 0x00, /* 0x00000000 | */
+ 0x00, /* 0x00000000 | */
+/* */
+ 0x00, /* 0x00000000 } */
+ 0x00, /* 0x00000000 } */
+ 0x07, /* 0x00000111 } */
+ 0x08, /* 0x00001000 } */
+ 0x08, /* 0x00001000 } */
+ 0x04, /* 0x00000100 } */
+ 0x18, /* 0x00011000 } */
+ 0x18, /* 0x00011000 } */
+ 0x04, /* 0x00000100 } */
+ 0x08, /* 0x00001000 } */
+ 0x08, /* 0x00001000 } */
+ 0x07, /* 0x00000111 } */
+ 0x00, /* 0x00000000 } */
+ 0x00, /* 0x00000000 } */
+ 0x00, /* 0x00000000 } */
+/* */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x46, /* 0x01000110 ~ */
+ 0x49, /* 0x01001001 ~ */
+ 0x31, /* 0x00110001 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+ 0x00, /* 0x00000000 ~ */
+/* */
+/* ascii0241 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0242 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x3c,
+ 0x42,
+ 0x02,
+ 0x02,
+ 0x42,
+ 0x3c,
+ 0x10,
+ 0x10,
+ 0x00,
+/* ascii0243 */
+ 0x00,
+ 0x00,
+ 0x70,
+ 0x88,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3e,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0xdc,
+ 0x76,
+ 0x00,
+ 0x00,
+/* ascii0244 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0245 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x28,
+ 0x10,
+ 0x7c,
+ 0x10,
+ 0x7c,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0246 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0247 */
+ 0x00,
+ 0x1c,
+ 0x22,
+ 0x02,
+ 0x04,
+ 0x1c,
+ 0x22,
+ 0x22,
+ 0x1c,
+ 0x10,
+ 0x20,
+ 0x22,
+ 0x1c,
+ 0x00,
+ 0x00,
+/* ascii0250 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x82,
+ 0x44,
+ 0x38,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x38,
+ 0x44,
+ 0x82,
+ 0x00,
+ 0x00,
+/* ascii0251 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7c,
+ 0x82,
+ 0xb2,
+ 0x8a,
+ 0x8a,
+ 0xb2,
+ 0x82,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0252 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x7c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0253 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x48,
+ 0x24,
+ 0x12,
+ 0x09,
+ 0x12,
+ 0x24,
+ 0x48,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0254 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0255 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0256 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0257 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0260 */
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0261 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3e,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x00,
+ 0x3e,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0262 */
+ 0x00,
+ 0x00,
+ 0x0c,
+ 0x12,
+ 0x08,
+ 0x04,
+ 0x02,
+ 0x1e,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0263 */
+ 0x00,
+ 0x00,
+ 0x1e,
+ 0x10,
+ 0x08,
+ 0x10,
+ 0x12,
+ 0x0c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0264 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0265 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x44,
+ 0x7c,
+ 0xc2,
+ 0x01,
+/* ascii0266 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7c,
+ 0x4e,
+ 0x4e,
+ 0x4e,
+ 0x4e,
+ 0x7c,
+ 0x48,
+ 0x48,
+ 0x48,
+ 0x48,
+ 0x00,
+ 0x00,
+/* ascii0267 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0270 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0271 */
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x0c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x1c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0272 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x3c,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* ascii0273 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x12,
+ 0x24,
+ 0x48,
+ 0x90,
+ 0x48,
+ 0x24,
+ 0x12,
+ 0x00,
+ 0x00,
+/* ascii0274 */
+ 0x00,
+ 0x04,
+ 0x06,
+ 0x04,
+ 0x04,
+ 0x4e,
+ 0x20,
+ 0x10,
+ 0x48,
+ 0x64,
+ 0x52,
+ 0xf8,
+ 0x40,
+ 0x40,
+ 0x00,
+/* ascii0275 */
+ 0x00,
+ 0x04,
+ 0x06,
+ 0x04,
+ 0x04,
+ 0x4e,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x74,
+ 0x82,
+ 0x60,
+ 0x10,
+ 0xf0,
+ 0x00,
+/* ascii0276 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0277 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x02,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0300 */
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0301 */
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0302 */
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0303 */
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0304 */
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0305 */
+ 0x18,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x7e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0306 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xf8,
+ 0x14,
+ 0x12,
+ 0x12,
+ 0x7e,
+ 0x12,
+ 0x12,
+ 0x12,
+ 0xf2,
+ 0x00,
+ 0x00,
+/* ascii0307 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x42,
+ 0x3c,
+ 0x10,
+ 0x0c,
+/* ascii0310 */
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0311 */
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0312 */
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0313 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x1e,
+ 0x02,
+ 0x02,
+ 0x02,
+ 0x7e,
+ 0x00,
+ 0x00,
+/* ascii0314 */
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0315 */
+ 0x40,
+ 0x20,
+ 0x10,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0316 */
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0317 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0320 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0321 */
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x46,
+ 0x4a,
+ 0x52,
+ 0x62,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0322 */
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0323 */
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0324 */
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0325 */
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0326 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0327 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xfc,
+ 0x12,
+ 0x12,
+ 0x12,
+ 0x72,
+ 0x12,
+ 0x12,
+ 0x12,
+ 0xfc,
+ 0x00,
+ 0x00,
+/* ascii0330 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xbc,
+ 0x42,
+ 0x62,
+ 0x52,
+ 0x52,
+ 0x4a,
+ 0x46,
+ 0x42,
+ 0x3d,
+ 0x00,
+ 0x00,
+/* ascii0331 */
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0332 */
+ 0x00,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0333 */
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0334 */
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0335 */
+ 0x00,
+ 0xc6,
+ 0x00,
+ 0x00,
+ 0x82,
+ 0x82,
+ 0x44,
+ 0x28,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0336 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0337 */
+ 0x00,
+ 0x00,
+ 0x70,
+ 0x88,
+ 0x84,
+ 0x84,
+ 0x44,
+ 0x74,
+ 0x84,
+ 0x84,
+ 0x84,
+ 0x94,
+ 0x74,
+ 0x04,
+ 0x02,
+/* ascii0340 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0341 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0342 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0343 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0344 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0345 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x18,
+ 0x00,
+ 0x3c,
+ 0x40,
+ 0x7c,
+ 0x42,
+ 0x42,
+ 0x7c,
+ 0x00,
+ 0x00,
+/* ascii0346 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x6e,
+ 0x90,
+ 0xfc,
+ 0x12,
+ 0x12,
+ 0xec,
+ 0x00,
+ 0x00,
+/* ascii0347 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x02,
+ 0x02,
+ 0x42,
+ 0x3c,
+ 0x10,
+ 0x0c,
+/* ascii0350 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0351 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0352 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0353 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x7e,
+ 0x02,
+ 0x02,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0354 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0355 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0356 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0357 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x08,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0360 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0361 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x00,
+ 0x3e,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x00,
+ 0x00,
+/* ascii0362 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x10,
+ 0x20,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0363 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x10,
+ 0x08,
+ 0x04,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0364 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0365 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4c,
+ 0x32,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0366 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0367 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x6c,
+ 0x92,
+ 0xf2,
+ 0x12,
+ 0x12,
+ 0xec,
+ 0x00,
+ 0x00,
+/* ascii0370 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xbc,
+ 0x62,
+ 0x52,
+ 0x4a,
+ 0x46,
+ 0x3c,
+ 0x02,
+ 0x00,
+/* ascii0371 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0372 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x20,
+ 0x10,
+ 0x08,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0373 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x18,
+ 0x24,
+ 0x42,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0374 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x00,
+ 0x00,
+/* ascii0375 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x42,
+ 0x3c,
+ 0x40,
+ 0x40,
+ 0x3e,
+/* ascii0376 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+/* ascii0377 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3c,
+ 0x42,
+ 0x42,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x10,
+ 0x00,
+ 0x00,
+
+};
+
+/*
+ * Default Cursor
+ */
+unsigned short q_cursor[] = {
+ 0x0000,
+ 0x0000,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x00ff,
+ 0x0000,
+ 0x0000,
+ 0x0000
+};
+
--- /dev/null
+/* $OpenBSD: uba.c,v 1.1 2000/04/27 03:14:49 bjc Exp $ */
+/* $NetBSD: uba.c,v 1.49 2000/01/24 02:40:30 matt Exp $ */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/map.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/dkstat.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/bus.h>
+#include <machine/scb.h>
+#include <machine/cpu.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+static int ubasearch __P((struct device *, struct cfdata *, void *));
+static int ubaprint __P((void *, const char *));
+
+struct cfdriver uba_cd = {
+ NULL, "uba", DV_DULL
+};
+
+/*
+ * If we failed to allocate uba resources, put us on a queue to wait
+ * until there is available resources. Resources to compete about
+ * are map registers and BDPs. This is normally only a problem on
+ * Unibus systems, Qbus systems have more map registers than usable.
+ */
+void
+uba_enqueue(uu)
+ struct uba_unit *uu;
+{
+ struct uba_softc *uh;
+ int s;
+
+ uh = (void *)((struct device *)(uu->uu_softc))->dv_parent;
+
+ s = splimp();
+ SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq);
+ splx(s);
+}
+
+/*
+ * When a routine that uses resources is finished, the next device
+ * in queue for map registers etc is called. If it succeeds to get
+ * resources, call next, and next, and next...
+ * This routine must be called at splimp.
+ */
+void
+uba_done(uh)
+ struct uba_softc *uh;
+{
+ struct uba_unit *uu;
+
+ while ((uu = SIMPLEQ_FIRST(&uh->uh_resq))) {
+ SIMPLEQ_REMOVE_HEAD(&uh->uh_resq, uu, uu_resq);
+ if ((*uu->uu_ready)(uu) == 0) {
+ SIMPLEQ_INSERT_HEAD(&uh->uh_resq, uu, uu_resq);
+ break;
+ }
+ }
+}
+
+/*
+ * Generate a reset on uba number uban. Then
+ * call each device that asked to be called during attach,
+ * giving it a chance to clean up so as to be able to continue.
+ */
+void
+ubareset(uban)
+ int uban;
+{
+ register struct uba_softc *uh = uba_cd.cd_devs[uban];
+ int s, i;
+
+ s = splimp();
+ SIMPLEQ_INIT(&uh->uh_resq);
+ printf("%s: reset", uh->uh_dev.dv_xname);
+ (*uh->uh_ubainit)(uh);
+
+ for (i = 0; i < uh->uh_resno; i++)
+ (*uh->uh_reset[i])(uh->uh_resarg[i]);
+ printf("\n");
+ splx(s);
+}
+
+/*
+ * The common attach routine:
+ * Calls the scan routine to search for uba devices.
+ */
+void
+uba_attach(sc, iopagephys)
+ struct uba_softc *sc;
+ paddr_t iopagephys;
+{
+
+ /*
+ * Set last free interrupt vector for devices with
+ * programmable interrupt vectors. Use is to decrement
+ * this number and use result as interrupt vector.
+ */
+ sc->uh_lastiv = 0x200;
+ SIMPLEQ_INIT(&sc->uh_resq);
+
+ /*
+ * Allocate place for unibus I/O space in virtual space.
+ */
+ if (bus_space_map(sc->uh_iot, iopagephys, UBAIOSIZE, 0, &sc->uh_ioh))
+ return;
+
+ if (sc->uh_beforescan)
+ (*sc->uh_beforescan)(sc);
+ /*
+ * Now start searching for devices.
+ */
+ config_search((cfmatch_t)ubasearch,(struct device *)sc, NULL);
+
+ if (sc->uh_afterscan)
+ (*sc->uh_afterscan)(sc);
+}
+
+int
+ubasearch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_softc *sc = (struct uba_softc *)parent;
+ struct uba_attach_args ua;
+ int i, vec, br;
+
+ ua.ua_ioh = ubdevreg(cf->cf_loc[0]) + sc->uh_ioh;
+ ua.ua_iot = sc->uh_iot;
+ ua.ua_dmat = sc->uh_dmat;
+ ua.ua_reset = NULL;
+
+ if (badaddr((caddr_t)ua.ua_ioh, 2) ||
+ (sc->uh_errchk ? (*sc->uh_errchk)(sc):0))
+ goto forgetit;
+
+ scb_vecref(0, 0); /* Clear vector ref */
+ i = (*cf->cf_attach->ca_match) (parent, cf, &ua);
+
+ if (sc->uh_errchk)
+ if ((*sc->uh_errchk)(sc))
+ goto forgetit;
+ if (i == 0)
+ goto forgetit;
+
+ i = scb_vecref(&vec, &br);
+ if (i == 0)
+ goto fail;
+ if (vec == 0)
+ goto fail;
+
+ if (ua.ua_reset) { /* device wants ubareset */
+ if (sc->uh_resno == 0) {
+#define RESETSIXE 128
+ sc->uh_reset = malloc(sizeof(void *) * RESETSIXE,
+ M_DEVBUF, M_NOWAIT);
+ sc->uh_resarg = malloc(sizeof(void *) * RESETSIXE,
+ M_DEVBUF, M_NOWAIT);
+ }
+ if (sc->uh_resno < RESETSIXE) {
+ sc->uh_resarg[sc->uh_resno] = cf->cf_unit;
+ sc->uh_reset[sc->uh_resno++] = ua.ua_reset;
+ } else {
+ printf("%s: Expand reset table, skipping reset %s%d\n",
+ sc->uh_dev.dv_xname, cf->cf_driver->cd_name,
+ cf->cf_unit);
+ }
+ }
+
+ ua.ua_br = br;
+ ua.ua_cvec = vec;
+ ua.ua_iaddr = cf->cf_loc[0];
+
+ config_attach(parent, cf, &ua, ubaprint);
+ return 0;
+
+fail:
+ printf("%s%d at %s csr %o %s\n",
+ cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname,
+ cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt"));
+
+forgetit:
+ return 0;
+}
+
+/*
+ * Print out some interesting info common to all unibus devices.
+ */
+int
+ubaprint(aux, uba)
+ void *aux;
+ const char *uba;
+{
+ struct uba_attach_args *ua = aux;
+
+ printf(" csr %o vec %o ipl %x", ua->ua_iaddr,
+ ua->ua_cvec & 511, ua->ua_br);
+ return UNCONF;
+}
+
+/*
+ * Move to machdep eventually
+ */
+void
+uba_intr_establish(icookie, vec, ifunc, iarg)
+ void *icookie;
+ int vec;
+ void (*ifunc)(void *iarg);
+ void *iarg;
+{
+ scb_vecalloc(vec, ifunc, iarg, SCB_ISTACK);
+}
--- /dev/null
+/* $OpenBSD: ubavar.h,v 1.1 2000/04/27 03:14:49 bjc Exp $ */
+/* $NetBSD: ubavar.h,v 1.26 2000/01/24 02:40:30 matt Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986 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.
+ *
+ * @(#)ubavar.h 7.7 (Berkeley) 6/28/90
+ */
+#ifndef _QBUS_UBAVAR_H
+#define _QBUS_UBAVAR_H
+
+/*
+ * This file contains definitions related to the kernel structures
+ * for dealing with the unibus adapters.
+ *
+ * Each uba has a uba_softc structure.
+ * Each unibus controller which is not a device has a uba_ctlr structure.
+ * Each unibus device has a uba_device structure.
+ */
+
+/*
+ * Per-uba structure.
+ *
+ * This structure holds the interrupt vector for the uba,
+ * and its address in physical and virtual space. At boot time
+ * we determine the devices attached to the uba's and their
+ * interrupt vectors, filling in uh_vec. We free the map
+ * register and bdp resources of the uba into the structures
+ * defined here.
+ *
+ * During normal operation, resources are allocated and returned
+ * to the structures here. We watch the number of passive releases
+ * on each uba, and if the number is excessive may reset the uba.
+ *
+ * When uba resources are needed and not available, or if a device
+ * which can tolerate no other uba activity (rk07) gets on the bus,
+ * then device drivers may have to wait to get to the bus and are
+ * queued here. It is also possible for processes to block in
+ * the unibus driver in resource wait (mrwant, bdpwant); these
+ * wait states are also recorded here.
+ */
+struct uba_softc {
+ struct device uh_dev; /* Device struct, autoconfig */
+ SIMPLEQ_HEAD(, uba_unit) uh_resq; /* resource wait chain */
+ void (**uh_reset) __P((int));/* UBA reset function array */
+ int *uh_resarg; /* array of ubareset args */
+ int uh_resno; /* Number of devices to reset */
+ int uh_lastiv; /* last free interrupt vector */
+ int (*uh_errchk) __P((struct uba_softc *));
+ void (*uh_beforescan) __P((struct uba_softc *));
+ void (*uh_afterscan) __P((struct uba_softc *));
+ void (*uh_ubainit) __P((struct uba_softc *));
+ void (*uh_ubapurge) __P((struct uba_softc *, int));
+ short uh_nr; /* Unibus sequential number */
+ bus_space_tag_t uh_iot; /* Tag for this Unibus */
+ bus_space_handle_t uh_ioh; /* Handle for I/O space */
+ bus_dma_tag_t uh_dmat;
+};
+
+/*
+ * Per-controller structure.
+ * The unit struct is common to both the adapter and the controller
+ * to which it belongs. It is only used on controllers that handles
+ * BDP's, and calls the adapter queueing subroutines.
+ */
+struct uba_unit {
+ SIMPLEQ_ENTRY(uba_unit) uu_resq;/* Queue while waiting for resources */
+ void *uu_softc; /* Pointer to units softc */
+ int uu_bdp; /* for controllers that hang on to bdp's */
+ int (*uu_ready) __P((struct uba_unit *));
+ void *uu_ref; /* Buffer this is related to */
+ short uu_xclu; /* want exclusive use of bdp's */
+ short uu_keepbdp; /* hang on to bdp's once allocated */
+};
+
+/*
+ * uba_attach_args is used during autoconfiguration. It is sent
+ * from ubascan() to each (possible) device.
+ */
+struct uba_attach_args {
+ bus_space_tag_t ua_iot; /* Tag for this bus I/O-space */
+ bus_addr_t ua_ioh; /* I/O regs addr */
+ bus_dma_tag_t ua_dmat;
+ void *ua_icookie; /* Cookie for interrupt establish */
+ /* UBA reset routine, filled in by probe */
+ void (*ua_reset) __P((int));
+ int ua_iaddr; /* Full CSR address of device */
+ int ua_br; /* IPL this dev interrupted on */
+ int ua_cvec; /* Vector for this device */
+};
+
+/*
+ * Flags to UBA map/bdp allocation routines
+ */
+#define UBA_NEEDBDP 0x01 /* transfer needs a bdp */
+#define UBA_CANTWAIT 0x02 /* don't block me */
+#define UBA_NEED16 0x04 /* need 16 bit addresses only */
+#define UBA_HAVEBDP 0x08 /* use bdp specified in high bits */
+#define UBA_DONTQUE 0x10 /* Do not enqueue xfer */
+
+/*
+ * Some common defines for all subtypes of U/Q-buses/adapters.
+ */
+#define MAXUBAXFER (63*1024) /* Max transfer size in bytes */
+#define UBAIOSIZE (8*1024) /* 8K I/O space */
+#define ubdevreg(addr) ((addr) & 017777)
+
+#ifdef _KERNEL
+#define b_forw b_hash.le_next /* Nice to have when handling uba queues */
+
+void uba_intr_establish __P((void *, int, void (*)(void *), void *));
+void uba_attach __P((struct uba_softc *, unsigned long));
+void uba_enqueue __P((struct uba_unit *));
+void uba_done __P((struct uba_softc *));
+void ubareset __P((int));
+
+#endif /* _KERNEL */
+
+#endif /* _QBUS_UBAVAR_H */
--- /dev/null
+/* $OpenBSD: uda.c,v 1.1 2000/04/27 03:14:49 bjc Exp $ */
+/* $NetBSD: uda.c,v 1.32 2000/01/24 02:40:30 matt Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ * @(#)uda.c 7.32 (Berkeley) 2/13/91
+ */
+
+/*
+ * UDA50 disk device driver
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/sid.h>
+
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
+
+/*
+ * Software status, per controller.
+ */
+struct uda_softc {
+ struct device sc_dev; /* Autoconfig info */
+ struct uba_unit sc_unit; /* Struct common for UBA to communicate */
+ struct mscp_pack *sc_uuda; /* Unibus address of uda struct */
+ struct mscp_pack sc_uda; /* Struct for uda communication */
+ bus_dma_tag_t sc_dmat;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_iph;
+ bus_space_handle_t sc_sah;
+ bus_dmamap_t sc_cmap;/* Control structures */
+ struct mscp *sc_mscp; /* Keep pointer to active mscp */
+ struct mscp_softc *sc_softc; /* MSCP info (per mscpvar.h) */
+ int sc_wticks; /* watchdog timer ticks */
+ int sc_inq;
+};
+
+static int udamatch __P((struct device *, struct cfdata *, void *));
+static void udaattach __P((struct device *, struct device *, void *));
+static void udareset __P((int));
+static void mtcreset __P((int));
+static void reset __P((struct uda_softc *));
+static void intr __P((void *));
+int udaready __P((struct uba_unit *));
+void udactlrdone __P((struct device *));
+int udaprint __P((void *, const char *));
+void udasaerror __P((struct device *, int));
+void udago __P((struct device *, struct mscp_xi *));
+
+struct cfattach mtc_ca = {
+ sizeof(struct uda_softc), (cfmatch_t)udamatch, udaattach
+};
+
+struct cfdriver mtc_cd = {
+ NULL, "mtc", DV_TAPE
+};
+
+struct cfattach uda_ca = {
+ sizeof(struct uda_softc), (cfmatch_t)udamatch, udaattach
+};
+
+struct cfdriver uda_cd = {
+ NULL, "uda", DV_DISK
+};
+
+/*
+ * More driver definitions, for generic MSCP code.
+ */
+struct mscp_ctlr uda_mscp_ctlr = {
+ udactlrdone,
+ udago,
+ udasaerror,
+};
+
+/*
+ * Miscellaneous private variables.
+ */
+static int ivec_no;
+
+int
+udaprint(aux, name)
+ void *aux;
+ const char *name;
+{
+ if (name)
+ printf("%s: mscpbus", name);
+ return UNCONF;
+}
+
+/*
+ * Poke at a supposed UDA50 to see if it is there.
+ */
+int
+udamatch(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct uba_attach_args *ua = aux;
+ struct mscp_softc mi; /* Nice hack */
+ struct uba_softc *ubasc;
+ int tries;
+
+ /* Get an interrupt vector. */
+ ubasc = (void *)parent;
+ ivec_no = ubasc->uh_lastiv - 4;
+
+ mi.mi_iot = ua->ua_iot;
+ mi.mi_iph = ua->ua_ioh;
+ mi.mi_sah = ua->ua_ioh + 2;
+ mi.mi_swh = ua->ua_ioh + 2;
+
+ /*
+ * Initialise the controller (partially). The UDA50 programmer's
+ * manual states that if initialisation fails, it should be retried
+ * at least once, but after a second failure the port should be
+ * considered `down'; it also mentions that the controller should
+ * initialise within ten seconds. Or so I hear; I have not seen
+ * this manual myself.
+ */
+ tries = 0;
+again:
+
+ bus_space_write_2(mi.mi_iot, mi.mi_iph, 0, 0); /* Start init */
+ if (mscp_waitstep(&mi, MP_STEP1, MP_STEP1) == 0)
+ return 0; /* Nothing here... */
+
+ bus_space_write_2(mi.mi_iot, mi.mi_sah, 0,
+ MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | MP_IE | (ivec_no >> 2));
+
+ if (mscp_waitstep(&mi, MP_STEP2, MP_STEP2) == 0) {
+ printf("udaprobe: init step2 no change. sa=%x\n",
+ bus_space_read_2(mi.mi_iot, mi.mi_sah, 0));
+ goto bad;
+ }
+
+ /* should have interrupted by now */
+ if (strcmp(cf->cf_driver->cd_name, mtc_cd.cd_name)) {
+ ua->ua_reset = udareset;
+ } else {
+ ua->ua_reset = mtcreset;
+ }
+
+ return 1;
+bad:
+ if (++tries < 2)
+ goto again;
+ return 0;
+}
+
+void
+udaattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uda_softc *sc = (void *)self;
+ struct uba_attach_args *ua = aux;
+ struct uba_softc *uh = (void *)parent;
+ struct mscp_attach_args ma;
+ int ctlr, error, rseg;
+ bus_dma_segment_t seg;
+
+ printf("\n");
+
+ uh->uh_lastiv -= 4; /* remove dynamic interrupt vector */
+
+ uba_intr_establish(ua->ua_icookie, ua->ua_cvec, intr, sc);
+
+ sc->sc_iot = ua->ua_iot;
+ sc->sc_iph = ua->ua_ioh;
+ sc->sc_sah = ua->ua_ioh + 2;
+ sc->sc_dmat = ua->ua_dmat;
+ ctlr = sc->sc_dev.dv_unit;
+
+ /*
+ * Fill in the uba_unit struct, so we can communicate with the uba.
+ */
+ sc->sc_unit.uu_softc = sc; /* Backpointer to softc */
+ sc->sc_unit.uu_ready = udaready;/* go routine called from adapter */
+ sc->sc_unit.uu_keepbdp = vax_cputype == VAX_750 ? 1 : 0;
+
+ /*
+ * Map the communication area and command and
+ * response packets into Unibus space.
+ */
+ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct mscp_pack),
+ NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
+ printf("Alloc ctrl area %d\n", error);
+ return;
+ }
+ if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
+ sizeof(struct mscp_pack), (caddr_t *) &sc->sc_uda,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf("Map ctrl area %d\n", error);
+err: bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ return;
+ }
+ if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct mscp_pack),
+ 1, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT, &sc->sc_cmap))) {
+ printf("Create DMA map %d\n", error);
+err2: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_uda,
+ sizeof(struct mscp_pack));
+ goto err;
+ }
+ if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
+ &sc->sc_uda, sizeof(struct mscp_pack), 0, BUS_DMA_NOWAIT))) {
+ printf("Load ctrl map %d\n", error);
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
+ goto err2;
+ }
+
+ bzero(&sc->sc_uda, sizeof (struct mscp_pack));
+
+ /*
+ * The only thing that differ UDA's and Tape ctlr's is
+ * their vcid. Beacuse there are no way to determine which
+ * ctlr type it is, we check what is generated and later
+ * set the correct vcid.
+ */
+ ma.ma_type = (strcmp(self->dv_cfdata->cf_driver->cd_name,
+ mtc_cd.cd_name) ? MSCPBUS_DISK : MSCPBUS_TAPE);
+
+ ma.ma_mc = &uda_mscp_ctlr;
+ ma.ma_type |= MSCPBUS_UDA;
+ ma.ma_uda = &sc->sc_uda;
+ ma.ma_softc = &sc->sc_softc;
+ ma.ma_iot = sc->sc_iot;
+ ma.ma_iph = sc->sc_iph;
+ ma.ma_sah = sc->sc_sah;
+ ma.ma_swh = sc->sc_sah;
+ ma.ma_dmat = sc->sc_dmat;
+ ma.ma_dmam = sc->sc_cmap;
+ ma.ma_ivec = ivec_no;
+ ma.ma_ctlrnr = (ua->ua_iaddr == 0172150 ? 0 : 1); /* XXX */
+ ma.ma_adapnr = uh->uh_nr;
+ config_found(&sc->sc_dev, &ma, udaprint);
+}
+
+/*
+ * Start a transfer if there are free resources available, otherwise
+ * let it go in udaready, forget it for now.
+ * Called from mscp routines.
+ */
+void
+udago(usc, mxi)
+ struct device *usc;
+ struct mscp_xi *mxi;
+{
+ struct uda_softc *sc = (void *)usc;
+ struct uba_unit *uu;
+ struct buf *bp = mxi->mxi_bp;
+ int err;
+
+ /*
+ * If we already have transfers queued, don't try to load
+ * the map again.
+ */
+ if (sc->sc_inq == 0) {
+ err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam,
+ bp->b_un.b_addr,
+ bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT);
+ if (err == 0) {
+ mscp_dgo(sc->sc_softc, mxi);
+ return;
+ }
+ }
+ uu = malloc(sizeof(struct uba_unit), M_DEVBUF, M_NOWAIT);
+ if (uu == 0)
+ panic("udago: no mem");
+ uu->uu_ready = udaready;
+ uu->uu_softc = sc;
+ uu->uu_ref = mxi;
+ uba_enqueue(uu);
+ sc->sc_inq++;
+}
+
+/*
+ * Called if we have been blocked for resources, and resources
+ * have been freed again. Return 1 if we could start all
+ * transfers again, 0 if we still are waiting.
+ * Called from uba resource free routines.
+ */
+int
+udaready(uu)
+ struct uba_unit *uu;
+{
+ struct uda_softc *sc = uu->uu_softc;
+ struct mscp_xi *mxi = uu->uu_ref;
+ struct buf *bp = mxi->mxi_bp;
+ int err;
+
+ err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam, bp->b_un.b_addr,
+ bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT);
+ if (err)
+ return 0;
+ mscp_dgo(sc->sc_softc, mxi);
+ sc->sc_inq--;
+ free(uu, M_DEVBUF);
+ return 1;
+}
+
+static struct saerr {
+ int code; /* error code (including UDA_ERR) */
+ char *desc; /* what it means: Efoo => foo error */
+} saerr[] = {
+ { 0100001, "Eunibus packet read" },
+ { 0100002, "Eunibus packet write" },
+ { 0100003, "EUDA ROM and RAM parity" },
+ { 0100004, "EUDA RAM parity" },
+ { 0100005, "EUDA ROM parity" },
+ { 0100006, "Eunibus ring read" },
+ { 0100007, "Eunibus ring write" },
+ { 0100010, " unibus interrupt master failure" },
+ { 0100011, "Ehost access timeout" },
+ { 0100012, " host exceeded command limit" },
+ { 0100013, " unibus bus master failure" },
+ { 0100014, " DM XFC fatal error" },
+ { 0100015, " hardware timeout of instruction loop" },
+ { 0100016, " invalid virtual circuit id" },
+ { 0100017, "Eunibus interrupt write" },
+ { 0104000, "Efatal sequence" },
+ { 0104040, " D proc ALU" },
+ { 0104041, "ED proc control ROM parity" },
+ { 0105102, "ED proc w/no BD#2 or RAM parity" },
+ { 0105105, "ED proc RAM buffer" },
+ { 0105152, "ED proc SDI" },
+ { 0105153, "ED proc write mode wrap serdes" },
+ { 0105154, "ED proc read mode serdes, RSGEN & ECC" },
+ { 0106040, "EU proc ALU" },
+ { 0106041, "EU proc control reg" },
+ { 0106042, " U proc DFAIL/cntl ROM parity/BD #1 test CNT" },
+ { 0106047, " U proc const PROM err w/D proc running SDI test" },
+ { 0106055, " unexpected trap" },
+ { 0106071, "EU proc const PROM" },
+ { 0106072, "EU proc control ROM parity" },
+ { 0106200, "Estep 1 data" },
+ { 0107103, "EU proc RAM parity" },
+ { 0107107, "EU proc RAM buffer" },
+ { 0107115, " test count wrong (BD 12)" },
+ { 0112300, "Estep 2" },
+ { 0122240, "ENPR" },
+ { 0122300, "Estep 3" },
+ { 0142300, "Estep 4" },
+ { 0, " unknown error code" }
+};
+
+/*
+ * If the error bit was set in the controller status register, gripe,
+ * then (optionally) reset the controller and requeue pending transfers.
+ */
+void
+udasaerror(usc, doreset)
+ struct device *usc;
+ int doreset;
+{
+ struct uda_softc *sc = (void *)usc;
+ register int code = bus_space_read_2(sc->sc_iot, sc->sc_sah, 0);
+ register struct saerr *e;
+
+ if ((code & MP_ERR) == 0)
+ return;
+ for (e = saerr; e->code; e++)
+ if (e->code == code)
+ break;
+ printf("%s: controller error, sa=0%o (%s%s)\n",
+ sc->sc_dev.dv_xname, code, e->desc + 1,
+ *e->desc == 'E' ? " error" : "");
+#if 0 /* XXX we just avoid panic when autoconfig non-existent KFQSA devices */
+ if (doreset) {
+ mscp_requeue(sc->sc_softc);
+/* (void) udainit(sc); XXX */
+ }
+#endif
+}
+
+/*
+ * Interrupt routine. Depending on the state of the controller,
+ * continue initialisation, or acknowledge command and response
+ * interrupts, and process responses.
+ */
+static void
+intr(arg)
+ void *arg;
+{
+ struct uda_softc *sc = arg;
+ struct uba_softc *uh;
+ struct mscp_pack *ud;
+
+ sc->sc_wticks = 0; /* reset interrupt watchdog */
+
+ /* ctlr fatal error */
+ if (bus_space_read_2(sc->sc_iot, sc->sc_sah, 0) & MP_ERR) {
+ udasaerror(&sc->sc_dev, 1);
+ return;
+ }
+ ud = &sc->sc_uda;
+ /*
+ * Handle buffer purge requests.
+ * XXX - should be done in bus_dma_sync().
+ */
+ uh = (void *)sc->sc_dev.dv_parent;
+ if (ud->mp_ca.ca_bdp) {
+ if (uh->uh_ubapurge)
+ (*uh->uh_ubapurge)(uh, ud->mp_ca.ca_bdp);
+ ud->mp_ca.ca_bdp = 0;
+ /* signal purge complete */
+ bus_space_write_2(sc->sc_iot, sc->sc_sah, 0, 0);
+ }
+
+ mscp_intr(sc->sc_softc);
+}
+
+/*
+ * A Unibus reset has occurred on UBA uban. Reinitialise the controller(s)
+ * on that Unibus, and requeue outstanding I/O.
+ */
+void
+udareset(ctlr)
+ int ctlr;
+{
+ reset(uda_cd.cd_devs[ctlr]);
+}
+
+void
+mtcreset(ctlr)
+ int ctlr;
+{
+ reset(mtc_cd.cd_devs[ctlr]);
+}
+
+static void
+reset(sc)
+ struct uda_softc *sc;
+{
+ printf(" %s", sc->sc_dev.dv_xname);
+
+ /*
+ * Our BDP (if any) is gone; our command (if any) is
+ * flushed; the device is no longer mapped; and the
+ * UDA50 is not yet initialised.
+ */
+ if (sc->sc_unit.uu_bdp) {
+ /* printf("<%d>", UBAI_BDP(sc->sc_unit.uu_bdp)); */
+ sc->sc_unit.uu_bdp = 0;
+ }
+
+ /* reset queues and requeue pending transfers */
+ mscp_requeue(sc->sc_softc);
+
+ /*
+ * If it fails to initialise we will notice later and
+ * try again (and again...). Do not call udastart()
+ * here; it will be done after the controller finishes
+ * initialisation.
+ */
+/* XXX if (udainit(sc)) */
+ printf(" (hung)");
+}
+
+void
+udactlrdone(usc)
+ struct device *usc;
+{
+ struct uda_softc *sc = (void *)usc;
+
+ uba_done((struct uba_softc *)sc->sc_dev.dv_parent);
+}
+++ /dev/null
-/* $OpenBSD: dhu.c,v 1.4 1997/05/29 00:05:05 niklas Exp $ */
-/* $NetBSD: dhu.c,v 1.9 1997/01/11 11:34:41 ragge Exp $ */
-/*
- * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell and Rick Macklem.
- *
- * 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.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/map.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/kernel.h>
-#include <sys/syslog.h>
-#include <sys/device.h>
-
-#include <machine/trap.h>
-
-#include <vax/uba/ubavar.h>
-
-#include <vax/uba/dhureg.h>
-
-/* A DHU-11 has 16 ports while a DHV-11 has only 8. We use 16 by default */
-
-#define NDHULINE 16
-
-#define DHU_M2U(c) ((c)>>4) /* convert minor(dev) to unit # */
-#define DHU_LINE(u) ((u)&0xF) /* extract line # from minor(dev) */
-
-struct dhu_softc {
- struct device sc_dev; /* Device struct used by config */
- dhuregs * sc_addr; /* controller reg address */
- int sc_type; /* controller type, DHU or DHV */
- struct {
- struct tty *dhu_tty; /* what we work on */
- int dhu_state; /* to manage TX output status */
- int dhu_txaddr; /* UBA map address to TX buf */
- short dhu_cc; /* character count on TX */
- short dhu_modem; /* modem bits state */
- } sc_dhu[NDHULINE];
-};
-
-#define IS_DHU 16 /* Unibus DHU-11 board linecount */
-#define IS_DHV 8 /* Q-bus DHV-11 or DHQ-11 */
-
-#define STATE_IDLE 000 /* no current output in progress */
-#define STATE_DMA_RUNNING 001 /* DMA TX in progress */
-#define STATE_DMA_STOPPED 002 /* DMA TX was aborted */
-#define STATE_TX_ONE_CHAR 004 /* did a single char directly */
-
-/* Flags used to monitor modem bits, make them understood outside driver */
-
-#define DML_DTR TIOCM_DTR
-#define DML_RTS TIOCM_RTS
-#define DML_CTS TIOCM_CTS
-#define DML_DCD TIOCM_CD
-#define DML_RI TIOCM_RI
-#define DML_DSR TIOCM_DSR
-#define DML_BRK 0100000 /* no equivalent, we will mask */
-
-/* On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */
-/* a baud rate from the same group. So limiting to B is likely */
-/* best, although clone boards like the ABLE QHV allow all settings. */
-
-static struct speedtab dhuspeedtab[] = {
- { 0, 0 }, /* Groups */
- { 50, DHU_LPR_B50 }, /* A */
- { 75, DHU_LPR_B75 }, /* B */
- { 110, DHU_LPR_B110 }, /* A and B */
- { 134, DHU_LPR_B134 }, /* A and B */
- { 150, DHU_LPR_B150 }, /* B */
- { 300, DHU_LPR_B300 }, /* A and B */
- { 600, DHU_LPR_B600 }, /* A and B */
- { 1200, DHU_LPR_B1200 }, /* A and B */
- { 1800, DHU_LPR_B1800 }, /* B */
- { 2000, DHU_LPR_B2000 }, /* B */
- { 2400, DHU_LPR_B2400 }, /* A and B */
- { 4800, DHU_LPR_B4800 }, /* A and B */
- { 7200, DHU_LPR_B7200 }, /* A */
- { 9600, DHU_LPR_B9600 }, /* A and B */
- { 19200, DHU_LPR_B19200 }, /* B */
- { 38400, DHU_LPR_B38400 }, /* A */
- { -1, -1 }
-};
-
-static int dhu_match __P((struct device *, void *, void *));
-static void dhu_attach __P((struct device *, struct device *, void *));
-static void dhurint __P((int));
-static void dhuxint __P((int));
-static void dhustart __P((struct tty *));
-static int dhuparam __P((struct tty *, struct termios *));
-static int dhuiflow __P((struct tty *, int));
-static unsigned dhumctl __P((struct dhu_softc *,int, int, int));
- int dhuopen __P((dev_t, int, int, struct proc *));
- int dhuclose __P((dev_t, int, int, struct proc *));
- int dhuread __P((dev_t, struct uio *, int));
- int dhuwrite __P((dev_t, struct uio *, int));
- int dhuioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
- void dhustop __P((struct tty *, int));
-struct tty * dhutty __P((dev_t));
-
-struct cfdriver dhu_cd = {
- NULL, "dhu", DV_TTY
-};
-
-struct cfattach dhu_ca = {
- sizeof(struct dhu_softc), dhu_match, dhu_attach
-};
-
-/* Autoconfig handles: setup the controller to interrupt, */
-/* then complete the housecleaning for full operation */
-
-static int
-dhu_match(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct uba_attach_args *ua = aux;
- register dhuregs *dhuaddr;
- register int n;
-
- dhuaddr = (dhuregs *) ua->ua_addr;
-
- /* Reset controller to initialize, enable TX/RX interrupts */
- /* to catch floating vector info elsewhere when completed */
-
- dhuaddr->dhu_csr = (DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE);
-
- /* Now wait up to 3 seconds for self-test to complete. */
-
- for (n = 0; n < 300; n++) {
- DELAY(10000);
- if ((dhuaddr->dhu_csr & DHU_CSR_MASTER_RESET) == 0)
- break;
- }
-
- /* If the RESET did not clear after 3 seconds, */
- /* the controller must be broken. */
-
- if (n >= 300)
- return 0;
-
- /* Check whether diagnostic run has signalled a failure. */
-
- if ((dhuaddr->dhu_csr & DHU_CSR_DIAG_FAIL) != 0)
- return 0;
-
- /* Register the RX interrupt handler */
-
- ua->ua_ivec = dhurint;
-
- return 1;
-}
-
-static void
-dhu_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- register struct dhu_softc *sc = (void *)self;
- register struct uba_attach_args *ua = aux;
- register dhuregs *dhuaddr;
- register unsigned c;
- register int n;
-
- dhuaddr = (dhuregs *) ua->ua_addr;
-
- /* Process the 8 bytes of diagnostic info put into */
- /* the FIFO following the master reset operation. */
-
- printf("\n%s:", self->dv_xname);
- for (n = 0; n < 8; n++) {
- c = dhuaddr->dhu_rbuf;
-
- if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) {
- if ((c&0200) == 0000)
- printf(" rom(%d) version %d",
- ((c>>1)&01), ((c>>2)&037));
- else if (((c>>2)&07) != 0)
- printf(" diag-error(proc%d)=%x",
- ((c>>1)&01), ((c>>2)&07));
- }
- }
- printf("\n");
-
- c = dhuaddr->dhu_stat; /* get flag to distinguish DHU from DHV */
-
- sc->sc_addr = dhuaddr;
- sc->sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV;
-
- /* Now stuff TX interrupt handler in place */
-
- ubasetvec(self, ua->ua_cvec + 1, dhuxint);
- return;
-}
-
-/* Receiver Interrupt */
-
-static void
-dhurint(unit)
- int unit;
-{
- struct dhu_softc *sc = dhu_cd.cd_devs[unit];
- register dhuregs *dhuaddr;
- register struct tty *tp;
- register int cc, line;
- register unsigned c, delta;
- int overrun = 0;
-
- dhuaddr = sc->sc_addr;
-
- while ((c = dhuaddr->dhu_rbuf) & DHU_RBUF_DATA_VALID) {
-
- /* Ignore diagnostic FIFO entries. */
-
- if ((c & DHU_DIAG_CODE) == DHU_DIAG_CODE)
- continue;
-
- cc = c & 0xFF;
- line = DHU_LINE(c>>8);
- tp = sc->sc_dhu[line].dhu_tty;
-
- /* LINK.TYPE is set so we get modem control FIFO entries */
-
- if ((c & DHU_DIAG_CODE) == DHU_MODEM_CODE) {
- c = (c << 8);
- /* Do MDMBUF flow control, wakeup sleeping opens */
- if (c & DHU_STAT_DCD) {
- if (!(tp->t_state & TS_CARR_ON))
- (void)(*linesw[tp->t_line].l_modem)(tp, 1);
- }
- else if ((tp->t_state & TS_CARR_ON) &&
- (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
- (void) dhumctl(sc, line, 0, DMSET);
-
- /* Do CRTSCTS flow control */
- delta = c ^ sc->sc_dhu[line].dhu_modem;
- sc->sc_dhu[line].dhu_modem = c;
- if ((delta & DHU_STAT_CTS) &&
- (tp->t_state & TS_ISOPEN) &&
- (tp->t_cflag & CRTSCTS)) {
- if (c & DHU_STAT_CTS) {
- tp->t_state &= ~TS_TTSTOP;
- ttstart(tp);
- } else {
- tp->t_state |= TS_TTSTOP;
- dhustop(tp, 0);
- }
- }
- continue;
- }
-
- if (!(tp->t_state & TS_ISOPEN)) {
- wakeup((caddr_t)&tp->t_rawq);
- continue;
- }
-
- if ((c & DHU_RBUF_OVERRUN_ERR) && overrun == 0) {
- log(LOG_WARNING, "%s: silo overflow, line %d\n",
- sc->sc_dev.dv_xname, line);
- overrun = 1;
- }
- /* A BREAK key will appear as a NULL with a framing error */
- if (c & DHU_RBUF_FRAMING_ERR)
- cc |= TTY_FE;
- if (c & DHU_RBUF_PARITY_ERR)
- cc |= TTY_PE;
-
- (*linesw[tp->t_line].l_rint)(cc, tp);
- }
- return;
-}
-
-/* Transmitter Interrupt */
-
-static void
-dhuxint(unit)
- int unit;
-{
- register struct dhu_softc *sc = dhu_cd.cd_devs[unit];
- register dhuregs *dhuaddr;
- register struct tty *tp;
- register int line;
-
- dhuaddr = sc->sc_addr;
-
- line = DHU_LINE(dhuaddr->dhu_csr_hi);
-
- tp = sc->sc_dhu[line].dhu_tty;
-
- tp->t_state &= ~TS_BUSY;
- if (tp->t_state & TS_FLUSH)
- tp->t_state &= ~TS_FLUSH;
- else {
- if (sc->sc_dhu[line].dhu_state == STATE_DMA_STOPPED)
- sc->sc_dhu[line].dhu_cc -= dhuaddr->dhu_tbufcnt;
- ndflush(&tp->t_outq, sc->sc_dhu[line].dhu_cc);
- sc->sc_dhu[line].dhu_cc = 0;
- }
-
- sc->sc_dhu[line].dhu_state = STATE_IDLE;
-
- if (tp->t_line)
- (*linesw[tp->t_line].l_start)(tp);
- else
- dhustart(tp);
-
- return;
-}
-
-int
-dhuopen(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- register dhuregs *dhuaddr;
- register struct tty *tp;
- register int unit, line;
- struct dhu_softc *sc;
- int s, error = 0;
-
- unit = DHU_M2U(minor(dev));
- line = DHU_LINE(minor(dev));
-
- if (unit >= dhu_cd.cd_ndevs || dhu_cd.cd_devs[unit] == NULL)
- return (ENXIO);
-
- sc = dhu_cd.cd_devs[unit];
-
- if (line >= sc->sc_type)
- return ENXIO;
-
- tp = sc->sc_dhu[line].dhu_tty;
- if (tp == NULL) {
-
- tp = sc->sc_dhu[line].dhu_tty = ttymalloc();
- if (tp == NULL)
- return ENXIO;
-
- sc->sc_dhu[line].dhu_state = STATE_IDLE;
-
- sc->sc_dhu[line].dhu_txaddr =
- uballoc((struct uba_softc *)sc->sc_dev.dv_parent,
- tp->t_outq.c_cs, tp->t_outq.c_cn, 0);
-
- dhuaddr = sc->sc_addr;
-
- s = spltty();
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
- sc->sc_dhu[line].dhu_modem = dhuaddr->dhu_stat;
- (void) splx(s);
- }
-
- tp->t_oproc = dhustart;
- tp->t_param = dhuparam;
- tp->t_hwiflow = dhuiflow;
- tp->t_dev = dev;
- if ((tp->t_state & TS_ISOPEN) == 0) {
- tp->t_state |= TS_WOPEN;
- ttychars(tp);
- if (tp->t_ispeed == 0) {
- tp->t_iflag = TTYDEF_IFLAG;
- tp->t_oflag = TTYDEF_OFLAG;
- tp->t_cflag = TTYDEF_CFLAG;
- tp->t_lflag = TTYDEF_LFLAG;
- tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
- }
- (void) dhuparam(tp, &tp->t_termios);
- ttsetwater(tp);
- } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
- return (EBUSY);
- /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
- if (dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS) & DML_DCD)
- tp->t_state |= TS_CARR_ON;
- s = spltty();
- while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
- !(tp->t_state & TS_CARR_ON)) {
- tp->t_state |= TS_WOPEN;
- error = ttysleep(tp, (caddr_t)&tp->t_rawq,
- TTIPRI | PCATCH, ttopen, 0);
- if (error)
- break;
- }
- (void) splx(s);
- if (error)
- return (error);
- return ((*linesw[tp->t_line].l_open)(dev, tp));
-}
-
-/*ARGSUSED*/
-int
-dhuclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- register struct tty *tp;
- register int unit, line;
- struct dhu_softc *sc;
-
- unit = DHU_M2U(minor(dev));
- line = DHU_LINE(minor(dev));
-
- sc = dhu_cd.cd_devs[unit];
-
- tp = sc->sc_dhu[line].dhu_tty;
-
- (*linesw[tp->t_line].l_close)(tp, flag);
-
- /* Make sure a BREAK state is not left enabled. */
-
- (void) dhumctl(sc, line, DML_BRK, DMBIC);
-
- /* Do a hangup if so required. */
-
- if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
- !(tp->t_state & TS_ISOPEN))
- (void) dhumctl(sc, line, 0, DMSET);
-
- return (ttyclose(tp));
-}
-
-int
-dhuread(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
-{
- register struct dhu_softc *sc;
- register struct tty *tp;
-
- sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
-
- tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
- return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
-}
-
-int
-dhuwrite(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
-{
- register struct dhu_softc *sc;
- register struct tty *tp;
-
- sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
-
- tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
- return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
-}
-
-/*ARGSUSED*/
-int
-dhuioctl(dev, cmd, data, flag, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
-{
- register struct dhu_softc *sc;
- register struct tty *tp;
- register int unit, line;
- int error;
-
- unit = DHU_M2U(minor(dev));
- line = DHU_LINE(minor(dev));
- sc = dhu_cd.cd_devs[unit];
- tp = sc->sc_dhu[line].dhu_tty;
-
- error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
- if (error >= 0)
- return (error);
- error = ttioctl(tp, cmd, data, flag, p);
- if (error >= 0)
- return (error);
-
- switch (cmd) {
-
- case TIOCSBRK:
- (void) dhumctl(sc, line, DML_BRK, DMBIS);
- break;
-
- case TIOCCBRK:
- (void) dhumctl(sc, line, DML_BRK, DMBIC);
- break;
-
- case TIOCSDTR:
- (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS);
- break;
-
- case TIOCCDTR:
- (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIC);
- break;
-
- case TIOCMSET:
- (void) dhumctl(sc, line, *(int *)data, DMSET);
- break;
-
- case TIOCMBIS:
- (void) dhumctl(sc, line, *(int *)data, DMBIS);
- break;
-
- case TIOCMBIC:
- (void) dhumctl(sc, line, *(int *)data, DMBIC);
- break;
-
- case TIOCMGET:
- *(int *)data = (dhumctl(sc, line, 0, DMGET) & ~DML_BRK);
- break;
-
- default:
- return (ENOTTY);
- }
- return (0);
-}
-
-struct tty *
-dhutty(dev)
- dev_t dev;
-{
- struct dhu_softc *sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
- struct tty *tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
- return (tp);
-}
-
-/*ARGSUSED*/
-void
-dhustop(tp, flag)
- register struct tty *tp;
-{
- register struct dhu_softc *sc;
- register dhuregs *dhuaddr;
- register int line;
- int s;
-
- s = spltty();
-
- if (tp->t_state & TS_BUSY) {
-
- sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
- line = DHU_LINE(minor(tp->t_dev));
-
- if (sc->sc_dhu[line].dhu_state == STATE_DMA_RUNNING) {
-
- sc->sc_dhu[line].dhu_state = STATE_DMA_STOPPED;
-
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
- dhuaddr->dhu_lnctrl |= DHU_LNCTRL_DMA_ABORT;
- }
-
- if (!(tp->t_state & TS_TTSTOP))
- tp->t_state |= TS_FLUSH;
- }
- (void) splx(s);
-}
-
-static void
-dhustart(tp)
- register struct tty *tp;
-{
- register struct dhu_softc *sc;
- register dhuregs *dhuaddr;
- register int line, cc;
- register int addr;
- int s;
-
- s = spltty();
- if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
- goto out;
- if (tp->t_outq.c_cc <= tp->t_lowat) {
- if (tp->t_state & TS_ASLEEP) {
- tp->t_state &= ~TS_ASLEEP;
- wakeup((caddr_t)&tp->t_outq);
- }
- selwakeup(&tp->t_wsel);
- }
- if (tp->t_outq.c_cc == 0)
- goto out;
- cc = ndqb(&tp->t_outq, 0);
- if (cc == 0)
- goto out;
-
- tp->t_state |= TS_BUSY;
-
- sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
-
- line = DHU_LINE(minor(tp->t_dev));
-
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
-
- sc->sc_dhu[line].dhu_cc = cc;
-
- if (cc == 1) {
-
- sc->sc_dhu[line].dhu_state = STATE_TX_ONE_CHAR;
- dhuaddr->dhu_txchar = DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf;
-
- } else {
-
- sc->sc_dhu[line].dhu_state = STATE_DMA_RUNNING;
-
- addr = UBAI_ADDR(sc->sc_dhu[line].dhu_txaddr) +
- (tp->t_outq.c_cf - tp->t_outq.c_cs);
-
- dhuaddr->dhu_tbufcnt = cc;
- dhuaddr->dhu_tbufad1 = (addr & 0xFFFF);
- dhuaddr->dhu_tbufad2 = ((addr>>16) & 0x3F) |
- DHU_TBUFAD2_TX_ENABLE;
-
- dhuaddr->dhu_lnctrl &= ~DHU_LNCTRL_DMA_ABORT;
- dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_DMA_START;
- }
-out:
- (void) splx(s);
- return;
-}
-
-static int
-dhuparam(tp, t)
- register struct tty *tp;
- register struct termios *t;
-{
- struct dhu_softc *sc;
- register dhuregs *dhuaddr;
- register int cflag = t->c_cflag;
- int ispeed = ttspeedtab(t->c_ispeed, dhuspeedtab);
- int ospeed = ttspeedtab(t->c_ospeed, dhuspeedtab);
- register unsigned lpr, lnctrl;
- int unit, line;
- int s;
-
- unit = DHU_M2U(minor(tp->t_dev));
- line = DHU_LINE(minor(tp->t_dev));
-
- sc = dhu_cd.cd_devs[unit];
-
- /* check requested parameters */
- if (ospeed < 0 || ispeed < 0)
- return (EINVAL);
-
- tp->t_ispeed = t->c_ispeed;
- tp->t_ospeed = t->c_ospeed;
- tp->t_cflag = cflag;
-
- if (ospeed == 0) {
- (void) dhumctl(sc, line, 0, DMSET); /* hang up line */
- return (0);
- }
-
- s = spltty();
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
-
- lpr = ((ispeed&017)<<8) | ((ospeed&017)<<12) ;
-
- switch (cflag & CSIZE) {
-
- case CS5:
- lpr |= DHU_LPR_5_BIT_CHAR;
- break;
-
- case CS6:
- lpr |= DHU_LPR_6_BIT_CHAR;
- break;
-
- case CS7:
- lpr |= DHU_LPR_7_BIT_CHAR;
- break;
-
- default:
- lpr |= DHU_LPR_8_BIT_CHAR;
- break;
- }
-
- if (cflag & PARENB)
- lpr |= DHU_LPR_PARENB;
- if (!(cflag & PARODD))
- lpr |= DHU_LPR_EPAR;
- if (cflag & CSTOPB)
- lpr |= DHU_LPR_2_STOP;
-
- dhuaddr->dhu_lpr = lpr;
-
- dhuaddr->dhu_tbufad2 |= DHU_TBUFAD2_TX_ENABLE;
-
- lnctrl = dhuaddr->dhu_lnctrl;
-
- /* Setting LINK.TYPE enables modem signal change interrupts. */
-
- lnctrl |= (DHU_LNCTRL_RX_ENABLE | DHU_LNCTRL_LINK_TYPE);
-
- /* Enable the auto XON/XOFF feature on the controller */
-
- if (t->c_iflag & IXON)
- lnctrl |= DHU_LNCTRL_OAUTO;
- else
- lnctrl &= ~DHU_LNCTRL_OAUTO;
-
- if (t->c_iflag & IXOFF)
- lnctrl |= DHU_LNCTRL_IAUTO;
- else
- lnctrl &= ~DHU_LNCTRL_IAUTO;
-
- dhuaddr->dhu_lnctrl = lnctrl;
-
- (void) splx(s);
- return (0);
-}
-
-static int
-dhuiflow(tp, flag)
- struct tty *tp;
- int flag;
-{
- register struct dhu_softc *sc;
- register int line = DHU_LINE(minor(tp->t_dev));
-
- if (tp->t_cflag & CRTSCTS) {
- sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
- (void) dhumctl(sc, line, DML_RTS, ((flag)? DMBIC: DMBIS));
- return (1);
- }
- return (0);
-}
-
-static unsigned
-dhumctl(sc, line, bits, how)
- struct dhu_softc *sc;
- int line, bits, how;
-{
- register dhuregs *dhuaddr;
- register unsigned status;
- register unsigned lnctrl;
- register unsigned mbits;
- int s;
-
- s = spltty();
-
- dhuaddr = sc->sc_addr;
- dhuaddr->dhu_csr_lo = (DHU_CSR_RXIE | line);
-
- mbits = 0;
-
- /* external signals as seen from the port */
-
- status = dhuaddr->dhu_stat;
-
- if (status & DHU_STAT_CTS)
- mbits |= DML_CTS;
-
- if (status & DHU_STAT_DCD)
- mbits |= DML_DCD;
-
- if (status & DHU_STAT_DSR)
- mbits |= DML_DSR;
-
- if (status & DHU_STAT_RI)
- mbits |= DML_RI;
-
- /* internal signals/state delivered to port */
-
- lnctrl = dhuaddr->dhu_lnctrl;
-
- if (lnctrl & DHU_LNCTRL_RTS)
- mbits |= DML_RTS;
-
- if (lnctrl & DHU_LNCTRL_DTR)
- mbits |= DML_DTR;
-
- if (lnctrl & DHU_LNCTRL_BREAK)
- mbits |= DML_BRK;
-
- switch (how) {
-
- case DMSET:
- mbits = bits;
- break;
-
- case DMBIS:
- mbits |= bits;
- break;
-
- case DMBIC:
- mbits &= ~bits;
- break;
-
- case DMGET:
- (void) splx(s);
- return (mbits);
- }
-
- if (mbits & DML_RTS)
- lnctrl |= DHU_LNCTRL_RTS;
- else
- lnctrl &= ~DHU_LNCTRL_RTS;
-
- if (mbits & DML_DTR)
- lnctrl |= DHU_LNCTRL_DTR;
- else
- lnctrl &= ~DHU_LNCTRL_DTR;
-
- if (mbits & DML_BRK)
- lnctrl |= DHU_LNCTRL_BREAK;
- else
- lnctrl &= ~DHU_LNCTRL_BREAK;
-
- dhuaddr->dhu_lnctrl = lnctrl;
-
- (void) splx(s);
- return (mbits);
-}
+++ /dev/null
-/* $OpenBSD: dhureg.h,v 1.2 1997/05/29 00:05:05 niklas Exp $ */
-/* $NetBSD: dhureg.h,v 1.2 1996/03/17 22:51:50 ragge Exp $ */
-/*
- * Copyright (c) 1996 Ken C. Wellsch. 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.
- */
-
-union w_b
-{
- u_short word;
- struct {
- u_char byte_lo;
- u_char byte_hi;
- } bytes;
-};
-
-struct DHUregs
-{
- volatile union w_b u_csr; /* Control/Status Register (R/W) */
- volatile u_short dhu_rbuf; /* Receive Buffer (R only) */
-#define dhu_txchar dhu_rbuf /* Transmit Character (W only) */
- volatile u_short dhu_lpr; /* Line Parameter Register (R/W) */
- volatile u_short dhu_stat; /* Line Status (R only) */
- volatile u_short dhu_lnctrl; /* Line Control (R/W) */
- volatile u_short dhu_tbufad1; /* Transmit Buffer Address 1 (R/W) */
- volatile u_short dhu_tbufad2; /* Transmit Buffer Address 2 (R/W) */
- volatile u_short dhu_tbufcnt; /* Transmit Buffer Count (R/W) */
-};
-
-#define dhu_csr u_csr.word
-#define dhu_csr_lo u_csr.bytes.byte_lo
-#define dhu_csr_hi u_csr.bytes.byte_hi
-
-typedef struct DHUregs dhuregs;
-
-/* CSR bits */
-
-#define DHU_CSR_TX_ACTION 0100000
-#define DHU_CSR_TXIE 0040000
-#define DHU_CSR_DIAG_FAIL 0020000
-#define DHU_CSR_TX_DMA_ERROR 0010000
-#define DHU_CSR_TX_LINE_MASK 0007400
-#define DHU_CSR_RX_DATA_AVAIL 0000200
-#define DHU_CSR_RXIE 0000100
-#define DHU_CSR_MASTER_RESET 0000040
-#define DHU_CSR_UNUSED 0000020
-#define DHU_CSR_CHANNEL_MASK 0000017
-
-/* RBUF bits */
-
-#define DHU_RBUF_DATA_VALID 0100000
-#define DHU_RBUF_OVERRUN_ERR 0040000
-#define DHU_RBUF_FRAMING_ERR 0020000
-#define DHU_RBUF_PARITY_ERR 0010000
-#define DHU_RBUF_RX_LINE_MASK 0007400
-
-#define DHU_DIAG_CODE 0070001
-#define DHU_MODEM_CODE 0070000
-
-/* TXCHAR bits */
-
-#define DHU_TXCHAR_DATA_VALID 0100000
-
-/* LPR bits */
-
-#define DHU_LPR_B50 0x0
-#define DHU_LPR_B75 0x1
-#define DHU_LPR_B110 0x2
-#define DHU_LPR_B134 0x3
-#define DHU_LPR_B150 0x4
-#define DHU_LPR_B300 0x5
-#define DHU_LPR_B600 0x6
-#define DHU_LPR_B1200 0x7
-#define DHU_LPR_B1800 0x8
-#define DHU_LPR_B2000 0x9
-#define DHU_LPR_B2400 0xA
-#define DHU_LPR_B4800 0xB
-#define DHU_LPR_B7200 0xC
-#define DHU_LPR_B9600 0xD
-#define DHU_LPR_B19200 0xE
-#define DHU_LPR_B38400 0xF
-
-#define DHU_LPR_5_BIT_CHAR 0000000
-#define DHU_LPR_6_BIT_CHAR 0000010
-#define DHU_LPR_7_BIT_CHAR 0000020
-#define DHU_LPR_8_BIT_CHAR 0000030
-#define DHU_LPR_PARENB 0000040
-#define DHU_LPR_EPAR 0000100
-#define DHU_LPR_2_STOP 0000200
-
-/* STAT bits */
-
-#define DHU_STAT_DSR 0100000
-#define DHU_STAT_RI 0020000
-#define DHU_STAT_DCD 0010000
-#define DHU_STAT_CTS 0004000
-#define DHU_STAT_DHU 0000400
-
-/* LNCTRL bits */
-
-#define DHU_LNCTRL_DMA_ABORT 0000001
-#define DHU_LNCTRL_IAUTO 0000002
-#define DHU_LNCTRL_RX_ENABLE 0000004
-#define DHU_LNCTRL_BREAK 0000010
-#define DHU_LNCTRL_OAUTO 0000020
-#define DHU_LNCTRL_FORCE_XOFF 0000040
-#define DHU_LNCTRL_LINK_TYPE 0000400
-#define DHU_LNCTRL_DTR 0001000
-#define DHU_LNCTRL_RTS 0010000
-
-/* TBUFAD2 bits */
-
-#define DHU_TBUFAD2_DMA_START 0000200
-#define DHU_TBUFAD2_TX_ENABLE 0100000
+++ /dev/null
-/* $OpenBSD: dl.c,v 1.2 1998/05/11 14:59:05 niklas Exp $ */
-/* $NetBSD: dl.c,v 1.1 1997/02/04 19:13:18 ragge Exp $ */
-/*
- * Copyright (c) 1997 Ben Harris. All rights reserved.
- * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
- * Copyright (c) 1995, 1996 Jason R. Thorpe. All rights reserved.
- * Copyright (c) 1982, 1986, 1990, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell and Rick Macklem.
- *
- * 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.
- */
-
-/*
- * dl.c -- Device driver for the DL11 and DLV11 serial cards.
- *
- * OS-interface code derived from the dz and dca (hp300) drivers.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/map.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/kernel.h>
-#include <sys/syslog.h>
-#include <sys/device.h>
-
-#include <machine/pte.h>
-#include <machine/trap.h>
-
-#include <vax/uba/ubareg.h>
-#include <vax/uba/ubavar.h>
-
-#include <vax/uba/dlreg.h>
-
-#define DL_I2C(i) (i)
-#define DL_C2I(c) (c)
-
-struct dl_softc {
- struct device sc_dev;
- dlregs* sc_addr;
- struct tty* sc_tty;
-};
-
-static int dl_match __P((struct device *, void *, void *));
-static void dl_attach __P((struct device *, struct device *, void *));
-static void dlrint __P((int));
-static void dlxint __P((int));
-static void dlstart __P((struct tty *));
-static int dlparam __P((struct tty *, struct termios *));
-static void dlbrk __P((struct dl_softc *, int));
-struct tty * dltty __P((dev_t));
- int dlopen __P((dev_t, int, int, struct proc *));
- int dlclose __P((dev_t, int, int, struct proc *));
- int dlread __P((dev_t, struct uio *, int));
- int dlwrite __P((dev_t, struct uio *, int));
- int dlioctl __P((dev_t, int, caddr_t, int, struct proc *));
- void dlstop __P((struct tty *, int));
-
-struct cfdriver dl_cd = {
- NULL, "dl", DV_TTY
-};
-
-struct cfattach dl_ca = {
- sizeof(struct dl_softc), dl_match, dl_attach
-};
-
-/* Autoconfig handles: setup the controller to interrupt, */
-/* then complete the housecleaning for full operation */
-
-static int
-dl_match (parent, match, aux)
- struct device * parent;
- void *match, *aux;
-{
- struct uba_attach_args *ua = aux;
- register dlregs *dladdr;
-
- dladdr = (dlregs*) ua->ua_addr;
-#ifdef DL_DEBUG
- printf("Probing for dl at %lo ... ", (long)dladdr);
-#endif
-
- dladdr->dl_xcsr = DL_XCSR_TXIE;
- if (dladdr->dl_xcsr != (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
-#ifdef DL_DEBUG
- printf("failed (step 1; XCSR = %.4b)\n", dladdr->dl_xcsr,
- DL_XCSR_BITS);
-#endif
- return 0;
- }
-
- /*
- * We have to force an interrupt so the uba driver can work
- * out where we are. Unfortunately, the only way to make a
- * DL11 interrupt is to get it to send or receive a
- * character. We'll send a NUL and hope it doesn't hurt
- * anything.
- */
-
- dladdr->u_xbuf.bytes.byte_lo = '\0';
-#if 0 /* This test seems to fail 2/3 of the time :-( */
- if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) {
-#ifdef DL_DEBUG
- printf("failed (step 2; XCSR = %.4b)\n", dladdr->dl_xcsr,
- DL_XCSR_BITS);
-#endif
- return 0;
- }
-#endif
- DELAY(100000); /* delay 1/10 s for character to transmit */
- if (dladdr->dl_xcsr != (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
-#ifdef DL_DEBUG
- printf("failed (step 3; XCSR = %.4b)\n", dladdr->dl_xcsr,
- DL_XCSR_BITS);
-#endif
- return 0;
- }
-
- /* Register the TX interrupt handler */
- ua->ua_ivec = dlxint;
-
- /* What else do I need to do? */
-
- return 1;
-
-}
-
-static void
-dl_attach (parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct uba_softc *uh = (void *)parent;
- struct dl_softc *sc = (void *)self;
- register struct uba_attach_args *ua = aux;
- register dlregs *dladdr;
-
- dladdr = (dlregs *) ua->ua_addr;
- sc->sc_addr = dladdr;
-
- /* Tidy up the device */
-
- dladdr->dl_rcsr = DL_RCSR_RXIE;
- dladdr->dl_xcsr = DL_XCSR_TXIE;
-
- /* Initialize our softc structure. Should be done in open? */
-
- sc->sc_tty = ttymalloc();
- tty_attach(sc->sc_tty);
-
- /* Now register the RX interrupt handler */
- ubasetvec(self, ua->ua_cvec-1, dlrint);
-
- printf("\n");
- return;
-}
-
-/* Receiver Interrupt Handler */
-
-static void
-dlrint(cntlr)
- int cntlr;
-{
- struct dl_softc *sc = dl_cd.cd_devs[cntlr];
- volatile dlregs *dladdr;
- register struct tty *tp;
- register int cc;
- register unsigned c;
-
- dladdr = sc->sc_addr;
-
- if (dladdr->dl_rcsr & DL_RCSR_RX_DONE) {
- c = dladdr->dl_rbuf;
- cc = c & 0xFF;
- tp = sc->sc_tty;
-
- if (!(tp->t_state & TS_ISOPEN)) {
- wakeup((caddr_t)&tp->t_rawq);
- return;
- }
-
- if (c & DL_RBUF_OVERRUN_ERR)
- /*
- * XXX: This should really be logged somwhere
- * else where we can afford the time.
- */
- log(LOG_WARNING, "%s: rx overrun\n",
- sc->sc_dev.dv_xname);
- if (c & DL_RBUF_FRAMING_ERR)
- cc |= TTY_FE;
- if (c & DL_RBUF_PARITY_ERR)
- cc |= TTY_PE;
-
- (*linesw[tp->t_line].l_rint)(cc, tp);
- } else
- log(LOG_WARNING, "%s: stray rx interrupt\n",
- sc->sc_dev.dv_xname);
- return;
-}
-
-/* Transmitter Interrupt Handler */
-
-static void
-dlxint(cntlr)
- int cntlr;
-{
- struct dl_softc *sc = dl_cd.cd_devs[cntlr];
- volatile dlregs *dladdr;
- register struct tty *tp;
-
- dladdr = sc->sc_addr;
- tp = sc->sc_tty;
- tp->t_state &= ~(TS_BUSY | TS_FLUSH);
- if (tp->t_line)
- (*linesw[tp->t_line].l_start)(tp);
- else
- dlstart(tp);
-
- return;
-}
-
-int
-dlopen(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- register struct tty *tp;
- register int unit;
- struct dl_softc *sc;
- int s, error = 0;
-
- unit = DL_I2C(minor(dev));
-
- if (unit >= dl_cd.cd_ndevs || dl_cd.cd_devs[unit] == NULL)
- return ENXIO;
- sc = dl_cd.cd_devs[unit];
-
- tp = sc->sc_tty;
- if (tp == NULL)
- return ENODEV;
- tp->t_oproc = dlstart;
- tp->t_param = dlparam;
- tp->t_dev = dev;
-
- if (!(tp->t_state & TS_ISOPEN)) {
- tp->t_state |= TS_WOPEN;
- ttychars(tp);
- tp->t_iflag = TTYDEF_IFLAG;
- tp->t_oflag = TTYDEF_OFLAG;
- /* No modem control, so set CLOCAL. */
- tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
- tp->t_lflag = TTYDEF_LFLAG;
- tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
-
- dlparam(tp, &tp->t_termios);
- ttsetwater(tp);
-
- } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
- return EBUSY;
-
- return ((*linesw[tp->t_line].l_open)(dev, tp));
-}
-
-/*ARGSUSED*/
-int
-dlclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- struct dl_softc *sc;
- register struct tty *tp;
- register int unit;
-
- unit = DL_I2C(minor(dev));
- sc = dl_cd.cd_devs[unit];
- tp = sc->sc_tty;
-
- (*linesw[tp->t_line].l_close)(tp, flag);
-
- /* Make sure a BREAK state is not left enabled. */
- dlbrk(sc, 0);
-
- return (ttyclose(tp));
-}
-
-int
-dlread(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
- int flag;
-{
- register struct tty *tp;
- struct dl_softc *sc;
- register int unit;
-
- unit = DL_I2C(minor(dev));
- sc = dl_cd.cd_devs[unit];
- tp = sc->sc_tty;
- return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
-}
-
-int
-dlwrite(dev, uio, flag)
- dev_t dev;
- struct uio *uio;
- int flag;
-{
- register struct tty *tp;
- struct dl_softc *sc;
- register int unit;
-
- unit = DL_I2C(minor(dev));
- sc = dl_cd.cd_devs[unit];
- tp = sc->sc_tty;
- return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
-}
-
-int
-dlioctl(dev, cmd, data, flag, p)
- dev_t dev;
- int cmd;
- caddr_t data;
- int flag;
- struct proc *p;
-{
- struct dl_softc *sc;
- register struct tty *tp;
- register int unit;
- int error;
-
- unit = DL_I2C(minor(dev));
- sc = dl_cd.cd_devs[unit];
- tp = sc->sc_tty;
-
- error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
- if (error >= 0)
- return (error);
- error = ttioctl(tp, cmd, data, flag, p);
- if (error >= 0)
- return (error);
-
- switch (cmd) {
-
- case TIOCSBRK:
- dlbrk(sc, 1);
- break;
-
- case TIOCCBRK:
- dlbrk(sc, 0);
- break;
-
- case TIOCMGET:
- /* No modem control, assume they're all low. */
- *(int *)data = 0;
- break;
-
- default:
- return (ENOTTY);
- }
- return (0);
-}
-
-struct tty *
-dltty(dev)
- dev_t dev;
-{
- register struct dl_softc* sc;
-
- sc = dl_cd.cd_devs[DL_I2C(minor(dev))];
- return sc->sc_tty;
-}
-
-void
-dlstop(tp, flag)
- register struct tty *tp;
- int flag;
-{
- register struct dl_softc *sc;
- int unit, s;
-
- unit = DL_I2C(minor(tp->t_dev));
- sc = dl_cd.cd_devs[unit];
-
- s = spltty();
-
- if (tp->t_state & TS_BUSY)
- if (!(tp->t_state & TS_TTSTOP))
- tp->t_state |= TS_FLUSH;
- splx(s);
-}
-
-static void
-dlstart(tp)
- register struct tty *tp;
-{
- register struct dl_softc *sc;
- register dlregs *dladdr;
- register int unit, cc;
- int s;
-
- unit = DL_I2C(minor(tp->t_dev));
- sc = dl_cd.cd_devs[unit];
-
- s = spltty();
- if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
- goto out;
- if (tp->t_outq.c_cc <= tp->t_lowat) {
- if (tp->t_state & TS_ASLEEP) {
- tp->t_state &= ~TS_ASLEEP;
- wakeup((caddr_t)&tp->t_outq);
- }
- selwakeup(&tp->t_wsel);
- }
- if (tp->t_outq.c_cc == 0)
- goto out;
-
- dladdr = sc->sc_addr;
-
- if (dladdr->dl_xcsr & DL_XCSR_TX_READY) {
- tp->t_state |= TS_BUSY;
- dladdr->u_xbuf.bytes.byte_lo = getc(&tp->t_outq);
- }
-out:
- splx(s);
- return;
-}
-
-/*ARGSUSED*/
-static int
-dlparam(tp, t)
- register struct tty *tp;
- register struct termios *t;
-{
- /*
- * All this kind of stuff (speed, character format, whatever)
- * is set by jumpers on the card. Changing it is thus rather
- * tricky for a mere device driver.
- */
- return 0;
-}
-
-static void
-dlbrk(sc, state)
- register struct dl_softc *sc;
- int state;
-{
- register dlregs *dladdr;
- int s;
- dladdr = sc->sc_addr;
- s = spltty();
- if (state)
- dladdr->dl_xcsr |= DL_XCSR_TX_BREAK;
- else
- dladdr->dl_xcsr &= ~DL_XCSR_TX_BREAK;
- splx(s);
-}
+++ /dev/null
-/* $OpenBSD: dlreg.h,v 1.2 1998/05/11 14:59:06 niklas Exp $ */
-/* $NetBSD: dlreg.h,v 1.1 1997/02/04 19:13:19 ragge Exp $ */
-/*
- * Copyright (c) 1997 Ben Harris. 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 Ben Harris.
- * 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.
- */
-
-/*
- * dlreg.h -- Definitions for the DL11 and DLV11 serial cards.
- *
- * Style in imitation of dzreg.h.
- */
-
-union w_b
-{
- u_short word;
- struct {
- u_char byte_lo;
- u_char byte_hi;
- } bytes;
-};
-
-struct DLregs
-{
- volatile u_short dl_rcsr; /* Receive Control/Status Register (R/W) */
- volatile u_short dl_rbuf; /* Receive Buffer (R) */
- volatile u_short dl_xcsr; /* Transmit Control/Status Register (R/W) */
- volatile union w_b u_xbuf; /* Transmit Buffer (W) */
-#define dl_xbuf u_xbuf.bytes.byte_lo
-};
-
-typedef struct DLregs dlregs;
-
-/* RCSR bits */
-
-#define DL_RCSR_RX_DONE 0x0080 /* Receiver Done (R) */
-#define DL_RCSR_RXIE 0x0040 /* Receiver Interrupt Enable (R/W) */
-#define DL_RCSR_READER_ENABLE 0x0001 /* [paper-tape] Reader Enable (W) */
-#define DL_RCSR_BITS "\20\1READER_ENABLE\7RXIE\10RX_DONE\n"
-
-/* RBUF bits */
-
-#define DL_RBUF_ERR 0x8000 /* Error (R) */
-#define DL_RBUF_OVERRUN_ERR 0x4000 /* Overrun Error (R) */
-#define DL_RBUF_FRAMING_ERR 0x2000 /* Framing Error (R) */
-#define DL_RBUF_PARITY_ERR 0x1000 /* Parity Error (R) */
-#define DL_RBUF_DATA_MASK 0x00FF /* Receive Data (R) */
-#define DL_RBUF_BITS "\20\15PARITY_ERR\16FRAMING_ERR\17OVERRUN_ERR\20ERR\n"
-
-/* XCSR bits */
-
-#define DL_XCSR_TX_READY 0x0080 /* Transmitter Ready (R) */
-#define DL_XCSR_TXIE 0x0040 /* Transmit Interrupt Enable (R/W) */
-#define DL_XCSR_TX_BREAK 0x0001 /* Transmit Break (R/W) */
-#define DL_XCSR_BITS "\20\1TX_BREAK\7TXIE\10TX_READY\n"
-
-/* XBUF is just data byte right justified. */
+++ /dev/null
-/* $OpenBSD: dz.c,v 1.3 1997/05/29 00:05:06 niklas Exp $ */
-/* $NetBSD: dz.c,v 1.4 1996/10/13 03:35:15 christos Exp $ */
-/*
- * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell and Rick Macklem.
- *
- * 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.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/map.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/kernel.h>
-#include <sys/syslog.h>
-#include <sys/device.h>
-
-#include <machine/pte.h>
-#include <machine/trap.h>
-
-#include <vax/uba/ubareg.h>
-#include <vax/uba/ubavar.h>
-
-#include <vax/uba/dzreg.h>
-
-/* A DZ-11 has 8 ports while a DZV/DZQ-11 has only 4. We use 8 by default */
-
-#define NDZLINE 8
-
-#define DZ_C2I(c) ((c)<<3) /* convert controller # to index */
-#define DZ_I2C(c) ((c)>>3) /* convert minor to controller # */
-#define DZ_PORT(u) ((u)&07) /* extract the port # */
-
-struct dz_softc {
- struct device sc_dev; /* Autoconf blaha */
- dzregs * sc_addr; /* controller reg address */
- int sc_type; /* DZ11 or DZV11? */
- int sc_rxint; /* Receive interrupt count XXX */
- u_char sc_brk; /* Break asserted on some lines */
- struct {
- struct tty * dz_tty; /* what we work on */
- caddr_t dz_mem; /* pointers to clist output */
- caddr_t dz_end; /* allowing pdma action */
- } sc_dz[NDZLINE];
-};
-
-/* Flags used to monitor modem bits, make them understood outside driver */
-
-#define DML_DTR TIOCM_DTR
-#define DML_DCD TIOCM_CD
-#define DML_RI TIOCM_RI
-#define DML_BRK 0100000 /* no equivalent, we will mask */
-
-static struct speedtab dzspeedtab[] =
-{
- { 0, 0 },
- { 50, DZ_LPR_B50 },
- { 75, DZ_LPR_B75 },
- { 110, DZ_LPR_B110 },
- { 134, DZ_LPR_B134 },
- { 150, DZ_LPR_B150 },
- { 300, DZ_LPR_B300 },
- { 600, DZ_LPR_B600 },
- { 1200, DZ_LPR_B1200 },
- { 1800, DZ_LPR_B1800 },
- { 2000, DZ_LPR_B2000 },
- { 2400, DZ_LPR_B2400 },
- { 3600, DZ_LPR_B3600 },
- { 4800, DZ_LPR_B4800 },
- { 7200, DZ_LPR_B7200 },
- { 9600, DZ_LPR_B9600 },
- { -1, -1 }
-};
-
-static int dz_match __P((struct device *, void *, void *));
-static void dz_attach __P((struct device *, struct device *, void *));
-static void dzrint __P((int));
-static void dzxint __P((int));
-static void dzstart __P((struct tty *));
-static int dzparam __P((struct tty *, struct termios *));
-static unsigned dzmctl __P((struct dz_softc *, int, int, int));
-static void dzscan __P((void *));
-struct tty * dztty __P((dev_t));
- int dzopen __P((dev_t, int, int, struct proc *));
- int dzclose __P((dev_t, int, int, struct proc *));
- int dzread __P((dev_t, struct uio *, int));
- int dzwrite __P((dev_t, struct uio *, int));
- int dzioctl __P((dev_t, int, caddr_t, int, struct proc *));
- void dzstop __P((struct tty *, int));
-
-struct cfdriver dz_cd = {
- NULL, "dz", DV_TTY
-};
-
-struct cfattach dz_ca = {
- sizeof(struct dz_softc), dz_match, dz_attach
-};
-
-
-/*
- * The DZ series doesn't interrupt on carrier transitions,
- * so we have to use a timer to watch it.
- */
-static int dz_timer = 0; /* true if timer started */
-
-#define DZ_DZ 8 /* Unibus DZ-11 board linecount */
-#define DZ_DZV 4 /* Q-bus DZV-11 or DZQ-11 */
-
-/* Autoconfig handles: setup the controller to interrupt, */
-/* then complete the housecleaning for full operation */
-
-static int
-dz_match (parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct uba_attach_args *ua = aux;
- register dzregs *dzaddr;
- register int n;
-
- dzaddr = (dzregs *) ua->ua_addr;
-
- /* Reset controller to initialize, enable TX interrupts */
- /* to catch floating vector info elsewhere when completed */
-
- dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_TXIE);
- dzaddr->dz_tcr = 1; /* Force a TX interrupt */
-
- DELAY(100000); /* delay 1/10 second */
-
- dzaddr->dz_csr = DZ_CSR_RESET;
-
- /* Now wait up to 3 seconds for reset/clear to complete. */
-
- for (n = 0; n < 300; n++) {
- DELAY(10000);
- if ((dzaddr->dz_csr & DZ_CSR_RESET) == 0)
- break;
- }
-
- /* If the RESET did not clear after 3 seconds, */
- /* the controller must be broken. */
-
- if (n >= 300)
- return (0);
-
- /* Register the TX interrupt handler */
-
- ua->ua_ivec = dzxint;
-
- return (1);
-}
-
-static void
-dz_attach (parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct uba_softc *uh = (void *)parent;
- struct dz_softc *sc = (void *)self;
- register struct uba_attach_args *ua = aux;
- register dzregs *dzaddr;
- register int n;
-
- dzaddr = (dzregs *) ua->ua_addr;
- sc->sc_addr = dzaddr;
-
-#ifdef QBA
- if (uh->uh_type == QBA)
- sc->sc_type = DZ_DZV;
- else
-#endif
- sc->sc_type = DZ_DZ;
-
- sc->sc_rxint = sc->sc_brk = 0;
-
- dzaddr->dz_csr = (DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
- dzaddr->dz_dtr = 0; /* Make sure DTR bits are zero */
- dzaddr->dz_break = 0; /* Status of BREAK bits, all off */
-
- /* Initialize our softc structure. Should be done in open? */
-
- for (n = 0; n < sc->sc_type; n++)
- sc->sc_dz[n].dz_tty = ttymalloc();
-
- /* Now register the RX interrupt handler */
- ubasetvec(self, ua->ua_cvec-1, dzrint);
-
- /* Alas no interrupt on modem bit changes, so we manually scan */
-
- if (dz_timer == 0) {
- dz_timer = 1;
- timeout(dzscan, (void *)0, hz);
- }
-
- printf("\n");
- return;
-}
-
-/* Receiver Interrupt */
-
-static void
-dzrint(cntlr)
- int cntlr;
-{
- struct dz_softc *sc = dz_cd.cd_devs[cntlr];
- volatile dzregs *dzaddr;
- register struct tty *tp;
- register int cc, line;
- register unsigned c;
- int overrun = 0;
-
- sc->sc_rxint++;
-
- dzaddr = sc->sc_addr;
-
- while ((c = dzaddr->dz_rbuf) & DZ_RBUF_DATA_VALID) {
- cc = c & 0xFF;
- line = DZ_PORT(c>>8);
- tp = sc->sc_dz[line].dz_tty;
-
- if (!(tp->t_state & TS_ISOPEN)) {
- wakeup((caddr_t)&tp->t_rawq);
- continue;
- }
-
- if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
- log(LOG_WARNING, "%s: silo overflow, line %d\n",
- sc->sc_dev.dv_xname, line);
- overrun = 1;
- }
- /* A BREAK key will appear as a NULL with a framing error */
- if (c & DZ_RBUF_FRAMING_ERR)
- cc |= TTY_FE;
- if (c & DZ_RBUF_PARITY_ERR)
- cc |= TTY_PE;
-
- (*linesw[tp->t_line].l_rint)(cc, tp);
- }
- return;
-}
-
-/* Transmitter Interrupt */
-
-static void
-dzxint(cntlr)
- int cntlr;
-{
- volatile dzregs *dzaddr;
- register struct dz_softc *sc = dz_cd.cd_devs[cntlr];
- register struct tty *tp;
- register unsigned csr;
- register int line;
-
- dzaddr = sc->sc_addr;
-
- /*
- * Switch to POLLED mode.
- * Some simple measurements indicated that even on
- * one port, by freeing the scanner in the controller
- * by either providing a character or turning off
- * the port when output is complete, the transmitter
- * was ready to accept more output when polled again.
- * With just two ports running the game "worms,"
- * almost every interrupt serviced both transmitters!
- * Each UART is double buffered, so if the scanner
- * is quick enough and timing works out, we can even
- * feed the same port twice.
- */
-
- dzaddr->dz_csr &= ~(DZ_CSR_TXIE);
-
- while (((csr = dzaddr->dz_csr) & DZ_CSR_TX_READY) != 0) {
-
- line = DZ_PORT(csr>>8);
-
- if (sc->sc_dz[line].dz_mem < sc->sc_dz[line].dz_end) {
- dzaddr->dz_tbuf = *sc->sc_dz[line].dz_mem++;
- continue;
- }
-
- /*
- * Turn off this TX port as all pending output
- * has been completed - thus freeing the scanner
- * on the controller to hopefully find another
- * pending TX operation we can service now.
- * (avoiding the overhead of another interrupt)
- */
-
- dzaddr->dz_tcr &= ~(1 << line);
-
- tp = sc->sc_dz[line].dz_tty;
-
- tp->t_state &= ~TS_BUSY;
-
- if (tp->t_state & TS_FLUSH)
- tp->t_state &= ~TS_FLUSH;
- else {
- ndflush (&tp->t_outq, (sc->sc_dz[line].dz_mem -
- (caddr_t)tp->t_outq.c_cf));
- sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem =
- tp->t_outq.c_cf;
- }
-
- if (tp->t_line)
- (*linesw[tp->t_line].l_start)(tp);
- else
- dzstart(tp);
- }
-
- /*
- * Re-enable TX interrupts.
- */
-
- dzaddr->dz_csr |= (DZ_CSR_TXIE);
- return;
-}
-
-int
-dzopen(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- register struct tty *tp;
- register int unit, line;
- struct dz_softc *sc;
- int s, error = 0;
-
- unit = DZ_I2C(minor(dev));
- line = DZ_PORT(minor(dev));
-
- if (unit >= dz_cd.cd_ndevs || dz_cd.cd_devs[unit] == NULL)
- return (ENXIO);
-
- sc = dz_cd.cd_devs[unit];
-
- if (line >= sc->sc_type)
- return ENXIO;
-
- tp = sc->sc_dz[line].dz_tty;
- if (tp == NULL)
- return (ENODEV);
- tp->t_oproc = dzstart;
- tp->t_param = dzparam;
- tp->t_dev = dev;
- if ((tp->t_state & TS_ISOPEN) == 0) {
- tp->t_state |= TS_WOPEN;
- ttychars(tp);
- if (tp->t_ispeed == 0) {
- tp->t_iflag = TTYDEF_IFLAG;
- tp->t_oflag = TTYDEF_OFLAG;
- tp->t_cflag = TTYDEF_CFLAG;
- tp->t_lflag = TTYDEF_LFLAG;
- tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
- }
- (void) dzparam(tp, &tp->t_termios);
- ttsetwater(tp);
- } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
- return (EBUSY);
- /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
- if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
- tp->t_state |= TS_CARR_ON;
- s = spltty();
- while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
- !(tp->t_state & TS_CARR_ON)) {
- tp->t_state |= TS_WOPEN;
- error = ttysleep(tp, (caddr_t)&tp->t_rawq,
- TTIPRI | PCATCH, ttopen, 0);
- if (error)
- break;
- }
- (void) splx(s);
- if (error)
- return (error);
- return ((*linesw[tp->t_line].l_open)(dev, tp));
-}
-
-/*ARGSUSED*/
-int
-dzclose (dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- struct dz_softc *sc;
- register struct tty *tp;
- register int unit, line;
-
-
- unit = DZ_I2C(minor(dev));
- line = DZ_PORT(minor(dev));
- sc = dz_cd.cd_devs[unit];
-
- tp = sc->sc_dz[line].dz_tty;
-
- (*linesw[tp->t_line].l_close)(tp, flag);
-
- /* Make sure a BREAK state is not left enabled. */
- (void) dzmctl(sc, line, DML_BRK, DMBIC);
-
- /* Do a hangup if so required. */
- if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
- !(tp->t_state & TS_ISOPEN))
- (void) dzmctl(sc, line, 0, DMSET);
-
- return (ttyclose(tp));
-}
-
-int
-dzread (dev, uio, flag)
- dev_t dev;
- struct uio *uio;
-{
- register struct tty *tp;
- struct dz_softc *sc;
-
- sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
-
- tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
- return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
-}
-
-int
-dzwrite (dev, uio, flag)
- dev_t dev;
- struct uio *uio;
-{
- register struct tty *tp;
- struct dz_softc *sc;
-
- sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
-
- tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
- return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
-}
-
-/*ARGSUSED*/
-int
-dzioctl (dev, cmd, data, flag, p)
- dev_t dev;
- int cmd;
- caddr_t data;
- int flag;
- struct proc *p;
-{
- struct dz_softc *sc;
- register struct tty *tp;
- register int unit, line;
- int error;
-
- unit = DZ_I2C(minor(dev));
- line = DZ_PORT(minor(dev));
- sc = dz_cd.cd_devs[unit];
- tp = sc->sc_dz[line].dz_tty;
-
- error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
- if (error >= 0)
- return (error);
- error = ttioctl(tp, cmd, data, flag, p);
- if (error >= 0)
- return (error);
-
- switch (cmd) {
-
- case TIOCSBRK:
- (void) dzmctl(sc, line, DML_BRK, DMBIS);
- break;
-
- case TIOCCBRK:
- (void) dzmctl(sc, line, DML_BRK, DMBIC);
- break;
-
- case TIOCSDTR:
- (void) dzmctl(sc, line, DML_DTR, DMBIS);
- break;
-
- case TIOCCDTR:
- (void) dzmctl(sc, line, DML_DTR, DMBIC);
- break;
-
- case TIOCMSET:
- (void) dzmctl(sc, line, *(int *)data, DMSET);
- break;
-
- case TIOCMBIS:
- (void) dzmctl(sc, line, *(int *)data, DMBIS);
- break;
-
- case TIOCMBIC:
- (void) dzmctl(sc, line, *(int *)data, DMBIC);
- break;
-
- case TIOCMGET:
- *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
- break;
-
- default:
- return (ENOTTY);
- }
- return (0);
-}
-
-struct tty *
-dztty (dev)
- dev_t dev;
-{
- struct dz_softc *sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
- struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
-
- return (tp);
-}
-
-/*ARGSUSED*/
-void
-dzstop(tp, flag)
- register struct tty *tp;
-{
- register struct dz_softc *sc;
- int unit, line, s;
-
- unit = DZ_I2C(minor(tp->t_dev));
- line = DZ_PORT(minor(tp->t_dev));
- sc = dz_cd.cd_devs[unit];
-
- s = spltty();
-
- if (tp->t_state & TS_BUSY) {
- sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem;
- if (!(tp->t_state & TS_TTSTOP))
- tp->t_state |= TS_FLUSH;
- }
- (void) splx(s);
-}
-
-static void
-dzstart (tp)
- register struct tty *tp;
-{
- register struct dz_softc *sc;
- register dzregs *dzaddr;
- register int unit, line;
- register int cc;
- int s;
-
- unit = DZ_I2C(minor(tp->t_dev));
- line = DZ_PORT(minor(tp->t_dev));
- sc = dz_cd.cd_devs[unit];
-
- s = spltty();
- if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
- goto out;
- if (tp->t_outq.c_cc <= tp->t_lowat) {
- if (tp->t_state & TS_ASLEEP) {
- tp->t_state &= ~TS_ASLEEP;
- wakeup((caddr_t)&tp->t_outq);
- }
- selwakeup(&tp->t_wsel);
- }
- if (tp->t_outq.c_cc == 0)
- goto out;
- cc = ndqb(&tp->t_outq, 0);
- if (cc == 0)
- goto out;
-
- tp->t_state |= TS_BUSY;
-
- dzaddr = sc->sc_addr;
-
- sc->sc_dz[line].dz_end = sc->sc_dz[line].dz_mem = tp->t_outq.c_cf;
- sc->sc_dz[line].dz_end += cc;
- dzaddr->dz_tcr |= (1 << line); /* Enable this TX port */
-
-out:
- (void) splx(s);
- return;
-}
-
-static int
-dzparam(tp, t)
- register struct tty *tp;
- register struct termios *t;
-{
- struct dz_softc *sc;
- register dzregs *dzaddr;
- register int cflag = t->c_cflag;
- int unit, line;
- int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
- int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
- register unsigned lpr;
- int s;
-
- unit = DZ_I2C(minor(tp->t_dev));
- line = DZ_PORT(minor(tp->t_dev));
- sc = dz_cd.cd_devs[unit];
-
- /* check requested parameters */
- if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
- return (EINVAL);
-
- tp->t_ispeed = t->c_ispeed;
- tp->t_ospeed = t->c_ospeed;
- tp->t_cflag = cflag;
-
- if (ospeed == 0) {
- (void) dzmctl(sc, line, 0, DMSET); /* hang up line */
- return (0);
- }
-
- s = spltty();
- dzaddr = sc->sc_addr;
-
- lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
-
- switch (cflag & CSIZE)
- {
- case CS5:
- lpr |= DZ_LPR_5_BIT_CHAR;
- break;
- case CS6:
- lpr |= DZ_LPR_6_BIT_CHAR;
- break;
- case CS7:
- lpr |= DZ_LPR_7_BIT_CHAR;
- break;
- default:
- lpr |= DZ_LPR_8_BIT_CHAR;
- break;
- }
- if (cflag & PARENB)
- lpr |= DZ_LPR_PARENB;
- if (cflag & PARODD)
- lpr |= DZ_LPR_OPAR;
- if (cflag & CSTOPB)
- lpr |= DZ_LPR_2_STOP;
-
- dzaddr->dz_lpr = lpr;
-
- (void) splx(s);
- return (0);
-}
-
-static unsigned
-dzmctl(sc, line, bits, how)
- register struct dz_softc *sc;
- int line, bits, how;
-{
- register dzregs *dzaddr;
- register unsigned status;
- register unsigned mbits;
- register unsigned bit;
- int s;
-
- s = spltty();
-
- dzaddr = sc->sc_addr;
-
- mbits = 0;
-
- bit = (1 << line);
-
- /* external signals as seen from the port */
-
- status = dzaddr->dz_dcd;
-
- if (status & bit)
- mbits |= DML_DCD;
-
- status = dzaddr->dz_ring;
-
- if (status & bit)
- mbits |= DML_RI;
-
- /* internal signals/state delivered to port */
-
- status = dzaddr->dz_dtr;
-
- if (status & bit)
- mbits |= DML_DTR;
-
- if (sc->sc_brk & bit)
- mbits |= DML_BRK;
-
- switch (how)
- {
- case DMSET:
- mbits = bits;
- break;
-
- case DMBIS:
- mbits |= bits;
- break;
-
- case DMBIC:
- mbits &= ~bits;
- break;
-
- case DMGET:
- (void) splx(s);
- return (mbits);
- }
-
- if (mbits & DML_DTR)
- dzaddr->dz_dtr |= bit;
- else
- dzaddr->dz_dtr &= ~bit;
-
- if (mbits & DML_BRK)
- dzaddr->dz_break = (sc->sc_brk |= bit);
- else
- dzaddr->dz_break = (sc->sc_brk &= ~bit);
-
- (void) splx(s);
- return (mbits);
-}
-
-/*
- * This is called by timeout() periodically.
- * Check to see if modem status bits have changed.
- */
-static void
-dzscan(arg)
- void *arg;
-{
- register dzregs *dzaddr;
- register struct dz_softc *sc;
- register struct tty *tp;
- register int n, bit, port;
- unsigned csr;
- int s;
-
- s = spltty();
-
- for (n = 0; n < dz_cd.cd_ndevs; n++) {
-
- if (dz_cd.cd_devs[n] == NULL)
- continue;
-
- sc = dz_cd.cd_devs[n];
-
- for (port = 0; port < sc->sc_type; port++) {
-
- dzaddr = sc->sc_addr;
- tp = sc->sc_dz[port].dz_tty;
- bit = (1 << port);
-
- if (dzaddr->dz_dcd & bit) { /* carrier present */
-
- if (!(tp->t_state & TS_CARR_ON))
- (void)(*linesw[tp->t_line].l_modem)
- (tp, 1);
- } else if ((tp->t_state & TS_CARR_ON) &&
- (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
- dzaddr->dz_tcr &= ~bit;
- }
-
- /*
- * If the RX interrupt rate is this high, switch
- * the controller to Silo Alarm - which means don't
- * interrupt until the RX silo has 16 characters in
- * it (the silo is 64 characters in all).
- * Avoid oscillating SA on and off by not turning
- * if off unless the rate is appropriately low.
- */
-
- dzaddr = sc->sc_addr;
-
- csr = dzaddr->dz_csr;
-
- if (sc->sc_rxint > (16*10)) {
- if ((csr & DZ_CSR_SAE) == 0)
- dzaddr->dz_csr = (csr | DZ_CSR_SAE);
- } else if ((csr & DZ_CSR_SAE) != 0)
- if (sc->sc_rxint < 10)
- dzaddr->dz_csr = (csr & ~(DZ_CSR_SAE));
-
- sc->sc_rxint = 0;
- }
- (void) splx(s);
- timeout(dzscan, (void *)0, hz);
- return;
-}
+++ /dev/null
-/* $OpenBSD: dzreg.h,v 1.2 1997/05/29 00:05:06 niklas Exp $ */
-/* $NetBSD: dzreg.h,v 1.1 1996/04/08 17:22:21 ragge Exp $ */
-/*
- * Copyright (c) 1996 Ken C. Wellsch. 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.
- */
-
-union w_b
-{
- u_short word;
- struct {
- u_char byte_lo;
- u_char byte_hi;
- } bytes;
-};
-
-struct DZregs
-{
- volatile u_short dz_csr; /* Control/Status Register (R/W) */
- volatile u_short dz_rbuf; /* Receive Buffer (R only) */
-#define dz_lpr dz_rbuf /* Line Parameter Register (W only) */
- volatile union w_b u_tcr; /* Transmit Control Register (R/W) */
- volatile union w_b u_msr; /* Modem Status Register (R only) */
-#define u_tdr u_msr /* Transmit Data Register (W only) */
-};
-
-#define dz_tcr u_tcr.bytes.byte_lo /* tx enable bits */
-#define dz_dtr u_tcr.bytes.byte_hi /* DTR status bits */
-#define dz_ring u_msr.bytes.byte_lo /* RI status bits */
-#define dz_dcd u_msr.bytes.byte_hi /* DCD status bits */
-#define dz_tbuf u_tdr.bytes.byte_lo /* transmit character */
-#define dz_break u_tdr.bytes.byte_hi /* BREAK set/clr bits */
-
-typedef struct DZregs dzregs;
-
-/* CSR bits */
-
-#define DZ_CSR_TX_READY 0100000 /* Transmitter Ready */
-#define DZ_CSR_TXIE 0040000 /* Transmitter Interrupt Enable */
-#define DZ_CSR_SA 0020000 /* Silo Alarm */
-#define DZ_CSR_SAE 0010000 /* Silo Alarm Enable */
-#define DZ_CSR_TX_LINE_MASK 0007400 /* Which TX line */
-
-#define DZ_CSR_RX_DONE 0000200 /* Receiver Done */
-#define DZ_CSR_RXIE 0000100 /* Receiver Interrupt Enable */
-#define DZ_CSR_MSE 0000040 /* Master Scan Enable */
-#define DZ_CSR_RESET 0000020 /* Clear (reset) Controller */
-#define DZ_CSR_MAINTENANCE 0000010
-#define DZ_CSR_UNUSED 0000007
-
-/* RBUF bits */
-
-#define DZ_RBUF_DATA_VALID 0100000
-#define DZ_RBUF_OVERRUN_ERR 0040000
-#define DZ_RBUF_FRAMING_ERR 0020000
-#define DZ_RBUF_PARITY_ERR 0010000
-#define DZ_RBUF_RX_LINE_MASK 0007400
-
-/* LPR bits */
-
-#define DZ_LPR_UNUSED 0160000
-#define DZ_LPR_RX_ENABLE 0010000
-
-#define DZ_LPR_B50 0x0
-#define DZ_LPR_B75 0x1
-#define DZ_LPR_B110 0x2
-#define DZ_LPR_B134 0x3
-#define DZ_LPR_B150 0x4
-#define DZ_LPR_B300 0x5
-#define DZ_LPR_B600 0x6
-#define DZ_LPR_B1200 0x7
-#define DZ_LPR_B1800 0x8
-#define DZ_LPR_B2000 0x9
-#define DZ_LPR_B2400 0xA
-#define DZ_LPR_B3600 0xB
-#define DZ_LPR_B4800 0xC
-#define DZ_LPR_B7200 0xD
-#define DZ_LPR_B9600 0xE
-#define DZ_LPR_ILLEGAL 0xF
-
-#define DZ_LPR_OPAR 0000200
-#define DZ_LPR_PARENB 0000100
-#define DZ_LPR_2_STOP 0000040
-
-#define DZ_LPR_5_BIT_CHAR 0000000
-#define DZ_LPR_6_BIT_CHAR 0000010
-#define DZ_LPR_7_BIT_CHAR 0000020
-#define DZ_LPR_8_BIT_CHAR 0000030
-
-#define DZ_LPR_CHANNEL_MASK 0000007
+++ /dev/null
-/* $OpenBSD: qd.c,v 1.2 1997/05/29 00:05:07 niklas Exp $ */
-/* $NetBSD: qd.c,v 1.4 1996/10/13 03:35:17 christos Exp $ */
-
-/*-
- * 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 KADB
-extern (*v_getc)();
-extern (*v_poll)();
-#endif
-extern 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
- */
- qdflags[unit].config = *(u_short *)reg;
-
- /*
- * find an empty 64kb adrs boundary
- */
-
- qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
-
- /*
- * find the cpusw entry that matches this machine.
- */
- cpup = &cpusw[cpu];
- while (!(BADADDR(qdbase[unit], sizeof(short))))
- qdbase[unit] -= CHUNK;
-
- /*
- * tell QDSS which Q memory address base to decode
- */
- mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
- ptep = (int *) QVmap[0] + mapix;
- phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
- *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
-
- /*
- * load QDSS adrs map with system addresses
- * of device regs
- */
- 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;
-
- /* device init */
-
- cursor[unit].x = 0;
- cursor[unit].y = 0;
- init_shared(unit); /* init shared memory */
- setup_dragon(unit); /* init the ADDER/VIPER stuff */
- ldcursor(unit, cons_cursor); /* load default cursor map */
- setup_input(unit); /* init the DUART */
- clear_qd_screen(unit);
- ldfont(unit); /* load the console font */
-
- /* once only: turn on sync */
-
- *(short *)qdmap[unit].memcsr |= SYNC_ON;
- }
-#endif /*notdef*/
- }
-
- /*
- * The QDSS interrupts at HEX vectors xx0 (DMA) xx4
- * (ADDER) and xx8 (DUART). Therefore, we take three
- * vectors from the vector pool, and then continue
- * to take them until we get a xx0 HEX vector. The
- * pool provides vectors in contiguous decending
- * order.
- */
-
- vector = (uba_hd[0].uh_lastiv -= 4*3); /* take three vectors */
-
- while (vector & 0x0F) { /* if lo nibble != 0.. */
- /* ..take another vector */
- vector = (uba_hd[0].uh_lastiv -= 4);
- }
-
- /*
- * setup DGA to do a DMA interrupt (transfer count = 0)
- */
- dga = (struct dga *) qdmap[unit].dga;
- dga->csr = (short) HALT; /* disable everything */
- dga->ivr = (short) vector; /* load intrpt base vector */
- dga->bytcnt_lo = (short) 0; /* DMA xfer count = 0 */
- dga->bytcnt_hi = (short) 0;
-
- /*
- * turn on DMA interrupts
- */
- dga->csr &= ~SET_DONE_FIFO;
- dga->csr |= DMA_IE | DL_ENB;
-
- DELAY(20000); /* wait for the intrpt */
- dga->csr = HALT; /* stop the wheels */
-
- if (cvec != vector) /* if vector != base vector.. */
- return(0); /* ..return = 'no device' */
-
- /*
- * score this as an existing qdss
- */
- qdcount++;
-
- return(sizeof(short)); /* return size of QDSS I/O page reg */
-
-} /* qdprobe */
-
-qdattach(ui)
- struct uba_device *ui;
-{
- register unit; /* QDSS module # for this call */
-
- unit = ui->ui_unit; /* get QDSS number */
-
- /*
- * init "qdflags[]" for this QDSS
- */
- qdflags[unit].inuse = 0; /* init inuse variable EARLY! */
- qdflags[unit].mapped = 0;
- qdflags[unit].kernel_loop = -1;
- qdflags[unit].user_dma = 0;
- qdflags[unit].curs_acc = ACC_OFF;
- qdflags[unit].curs_thr = 128;
- qdflags[unit].tab_res = 2; /* default tablet resolution factor */
- qdflags[unit].duart_imask = 0; /* init shadow variables */
- qdflags[unit].adder_ie = 0;
-
- /*
- * init structures used in kbd/mouse interrupt service. This code must
- * come after the "init_shared()" routine has run since that routine
- * inits the eq_header[unit] structure used here.
- */
-
- /*
- * init the "latest mouse report" structure
- */
- last_rep[unit].state = 0;
- last_rep[unit].dx = 0;
- last_rep[unit].dy = 0;
- last_rep[unit].bytcnt = 0;
-
- /*
- * init the event queue (except mouse position)
- */
- eq_header[unit]->header.events =
- (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
-
- eq_header[unit]->header.size = MAXEVENTS;
- eq_header[unit]->header.head = 0;
- eq_header[unit]->header.tail = 0;
-
- /*
- * open exclusive for graphics device.
- */
- qdopened[unit] = 0;
-
-} /* qdattach */
-
-/*ARGSUSED*/
-qdopen(dev, flag)
- dev_t dev;
- int flag;
-{
- register struct uba_device *ui; /* ptr to uba structures */
- register struct dga *dga; /* ptr to gate array struct */
- register struct tty *tp;
- struct duart *duart;
- int unit;
- int minor_dev;
-
- minor_dev = minor(dev); /* get QDSS minor device number */
- unit = minor_dev >> 2;
-
- /*
- * check for illegal conditions
- */
- ui = qdinfo[unit]; /* get ptr to QDSS device struct */
- if (ui == 0 || ui->ui_alive == 0)
- return(ENXIO); /* no such device or address */
-
- duart = (struct duart *) qdmap[unit].duart;
- dga = (struct dga *) qdmap[unit].dga;
-
- if ((minor_dev & 0x03) == 2) {
- /*
- * this is the graphic device...
- */
- if (qdopened[unit] != 0)
- return(EBUSY);
- else
- qdopened[unit] = 1;
- qdflags[unit].inuse |= GRAPHIC_DEV; /* graphics dev is open */
- /*
- * enble kbd & mouse intrpts in DUART mask reg
- */
- qdflags[unit].duart_imask |= 0x22;
- duart->imask = qdflags[unit].duart_imask;
- } else {
- /*
- * this is the console
- */
- qdflags[unit].inuse |= CONS_DEV; /* mark console as open */
- dga->csr |= CURS_ENB;
- qdflags[unit].duart_imask |= 0x02;
- duart->imask = qdflags[unit].duart_imask;
- /*
- * some setup for tty handling
- */
- tp = &qd_tty[minor_dev];
- tp->t_addr = ui->ui_addr;
- tp->t_oproc = qdstart;
- if ((tp->t_state & TS_ISOPEN) == 0) {
- ttychars(tp);
- tp->t_ispeed = B9600;
- tp->t_ospeed = B9600;
- tp->t_state = TS_ISOPEN | TS_CARR_ON;
- tp->t_iflag = TTYDEF_IFLAG;
- tp->t_oflag = TTYDEF_OFLAG;
- tp->t_lflag = TTYDEF_LFLAG;
- tp->t_cflag = TTYDEF_CFLAG;
- }
- /*
- * enable intrpts, open line discipline
- */
- dga->csr |= GLOBAL_IE; /* turn on the interrupts */
- return ((*linesw[tp->t_line].l_open)(dev, tp));
- }
- dga->csr |= GLOBAL_IE; /* turn on the interrupts */
- return(0);
-
-} /* qdopen */
-
-/*ARGSUSED*/
-qdclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- register struct tty *tp;
- register struct qdmap *qd;
- register int *ptep;
- struct dga *dga; /* gate array register map pointer */
- struct duart *duart;
- struct adder *adder;
- int unit;
- int minor_dev;
- u_int mapix;
- int i; /* SIGNED index */
-
- minor_dev = minor(dev); /* get minor device number */
- unit = minor_dev >> 2; /* get QDSS number */
- qd = &qdmap[unit];
-
- if ((minor_dev & 0x03) == 2) {
- /*
- * this is the graphic device...
- */
- if (qdopened[unit] != 1)
- return(EBUSY);
- else
- qdopened[unit] = 0; /* allow it to be re-opened */
- /*
- * re-protect device memory
- */
- if (qdflags[unit].mapped & MAPDEV) {
- /*
- * TEMPLATE RAM
- */
- mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
- ptep = (int *)(QVmap[0] + mapix);
- for (i = 0; i < btop(TMPSIZE); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
- /*
- * ADDER
- */
- mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
- ptep = (int *)(QVmap[0] + mapix);
- for (i = 0; i < btop(REGSIZE); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
- /*
- * COLOR MAPS
- */
- mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
- ptep = (int *)(QVmap[0] + mapix);
- for (i = 0; i < btop(CLRSIZE); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
- }
-
- /*
- * re-protect DMA buffer and free the map registers
- */
- if (qdflags[unit].mapped & MAPDMA) {
- dga = (struct dga *) qdmap[unit].dga;
- adder = (struct adder *) qdmap[unit].adder;
- dga->csr &= ~DMA_IE;
- dga->csr &= ~0x0600; /* kill DMA */
- adder->command = CANCEL;
- /*
- * if DMA was running, flush spurious intrpt
- */
- if (dga->bytcnt_lo != 0) {
- dga->bytcnt_lo = 0;
- dga->bytcnt_hi = 0;
- DMA_SETIGNORE(DMAheader[unit]);
- dga->csr |= DMA_IE;
- dga->csr &= ~DMA_IE;
- }
- ptep = (int *)
- ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
- for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
- ubarelse(0, &Qbus_unmap[unit]);
- }
-
- /*
- * re-protect 1K (2 pages) event queue
- */
- if (qdflags[unit].mapped & MAPEQ) {
- ptep = (int *)
- ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
- }
- /*
- * re-protect scroll param area and disable scroll intrpts
- */
- if (qdflags[unit].mapped & MAPSCR) {
- ptep = (int *) ((VTOP(scroll[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- /*
- * re-protect 512 scroll param area
- */
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
- adder = (struct adder *) qdmap[unit].adder;
- qdflags[unit].adder_ie &= ~FRAME_SYNC;
- adder->interrupt_enable = qdflags[unit].adder_ie;
- }
- /*
- * re-protect color map write buffer area and kill intrpts
- */
- if (qdflags[unit].mapped & MAPCOLOR) {
- ptep = (int *) ((VTOP(color_buf[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
- color_buf[unit]->status = 0;
- adder = (struct adder *) qdmap[unit].adder;
- qdflags[unit].adder_ie &= ~VSYNC;
- adder->interrupt_enable = qdflags[unit].adder_ie;
- }
- mtpr(TBIA, 0);
- /* flag everything now unmapped */
- qdflags[unit].mapped = 0;
- qdflags[unit].inuse &= ~GRAPHIC_DEV;
- qdflags[unit].curs_acc = ACC_OFF;
- qdflags[unit].curs_thr = 128;
- /*
- * restore the console
- */
- dga = (struct dga *) qdmap[unit].dga;
- adder = (struct adder *) qdmap[unit].adder;
- dga->csr &= ~DMA_IE;
- dga->csr &= ~0x0600; /* halt the DMA! (just in case...) */
- dga->csr |= DMA_ERR; /* clear error condition */
- adder->command = CANCEL;
- /*
- * if DMA was running, flush spurious intrpt
- */
- if (dga->bytcnt_lo != 0) {
- dga->bytcnt_lo = 0;
- dga->bytcnt_hi = 0;
- DMA_SETIGNORE(DMAheader[unit]);
- dga->csr |= DMA_IE;
- dga->csr &= ~DMA_IE;
- }
- init_shared(unit); /* init shared memory */
- setup_dragon(unit); /* init ADDER/VIPER */
- ldcursor(unit, cons_cursor); /* load default cursor map */
- setup_input(unit); /* init the DUART */
- ldfont(unit);
- cursor[unit].x = 0;
- cursor[unit].y = 0;
- /*
- * shut off the mouse rcv intrpt and turn on kbd intrpts
- */
- duart = (struct duart *) qdmap[unit].duart;
- qdflags[unit].duart_imask &= ~(0x20);
- qdflags[unit].duart_imask |= 0x02;
- duart->imask = qdflags[unit].duart_imask;
- /*
- * shut off interrupts if all is closed
- */
- if (!(qdflags[unit].inuse & CONS_DEV)) {
- dga = (struct dga *) qdmap[unit].dga;
- dga->csr &= ~(GLOBAL_IE | DMA_IE);
- }
- } else {
- /*
- * this is the console
- */
- tp = &qd_tty[minor_dev];
- (*linesw[tp->t_line].l_close)(tp, flag);
- ttyclose(tp);
- tp->t_state = 0;
- qdflags[unit].inuse &= ~CONS_DEV;
- /*
- * if graphics device is closed, kill interrupts
- */
- if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
- dga = (struct dga *) qdmap[unit].dga;
- dga->csr &= ~(GLOBAL_IE | DMA_IE);
- }
- }
-
- return(0);
-
-} /* qdclose */
-
-qdioctl(dev, cmd, datap, flags)
- dev_t dev;
- int cmd;
- register caddr_t datap;
- int flags;
-{
- register int *ptep; /* page table entry pointer */
- register int mapix; /* QVmap[] page table index */
- register struct _vs_event *event;
- register struct tty *tp;
- register i;
- struct qdmap *qd; /* pointer to device map struct */
- struct dga *dga; /* Gate Array reg structure pntr */
- struct duart *duart; /* DUART reg structure pointer */
- struct adder *adder; /* ADDER reg structure pointer */
- struct prgkbd *cmdbuf;
- struct prg_cursor *curs;
- struct _vs_cursor *pos;
- int unit = minor(dev) >> 2; /* number of caller's QDSS */
- u_int minor_dev = minor(dev);
- int error;
- int s;
- short *temp; /* a pointer to template RAM */
-
- /*
- * service graphic device ioctl commands
- */
- switch (cmd) {
-
- case QD_GETEVENT:
- /*
- * extract the oldest event from the event queue
- */
- if (ISEMPTY(eq_header[unit])) {
- event = (struct _vs_event *) datap;
- event->vse_device = VSE_NULL;
- break;
- }
- event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
- s = spl5();
- GETEND(eq_header[unit]);
- splx(s);
- bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
- break;
-
- case QD_RESET:
- /*
- * init the dragon stuff, DUART, and driver variables
- */
- init_shared(unit); /* init shared memory */
- setup_dragon(unit); /* init the ADDER/VIPER stuff */
- clear_qd_screen(unit);
- ldcursor(unit, cons_cursor); /* load default cursor map */
- ldfont(unit); /* load the console font */
- setup_input(unit); /* init the DUART */
- break;
-
- case QD_SET:
- /*
- * init the DUART and driver variables
- */
- init_shared(unit);
- setup_input(unit);
- break;
-
- case QD_CLRSCRN:
- /*
- * clear the QDSS screen. (NOTE that this reinits the dragon)
- */
-#ifdef notdef /* has caused problems and isn't necessary */
- setup_dragon(unit);
- clear_qd_screen(unit);
-#endif
- break;
-
- case QD_WTCURSOR:
- /*
- * load a cursor into template RAM
- */
- ldcursor(unit, (short *)datap);
- break;
-
- case QD_RDCURSOR:
-
- temp = (short *) qdmap[unit].template;
- /*
- * cursor is 32 WORDS from the end of the 8k WORD...
- * ...template space
- */
- temp += (8 * 1024) - 32;
- for (i = 0; i < 32; ++i, datap += sizeof(short))
- *(short *)datap = *temp++;
- break;
-
- case QD_POSCURSOR:
- /*
- * position the mouse cursor
- */
- dga = (struct dga *) qdmap[unit].dga;
- pos = (struct _vs_cursor *) datap;
- s = spl5();
- dga->x_cursor = TRANX(pos->x);
- dga->y_cursor = TRANY(pos->y);
- eq_header[unit]->curs_pos.x = pos->x;
- eq_header[unit]->curs_pos.y = pos->y;
- splx(s);
- break;
-
- case QD_PRGCURSOR:
- /*
- * set the cursor acceleration factor
- */
- curs = (struct prg_cursor *) datap;
- s = spl5();
- qdflags[unit].curs_acc = curs->acc_factor;
- qdflags[unit].curs_thr = curs->threshold;
- splx(s);
- break;
-
- case QD_MAPDEVICE:
- /*
- * enable 'user write' to device pages
- */
- qdflags[unit].mapped |= MAPDEV;
- qd = (struct qdmap *) &qdmap[unit];
- /*
- * enable user write to template RAM
- */
- mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
- ptep = (int *)(QVmap[0] + mapix);
- for (i = 0; i < btop(TMPSIZE); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- /*
- * enable user write to registers
- */
- mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
- ptep = (int *)(QVmap[0] + mapix);
- for (i = 0; i < btop(REGSIZE); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- /*
- * enable user write to color maps
- */
- mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
- ptep = (int *)(QVmap[0] + mapix);
- for (i = 0; i < btop(CLRSIZE); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- /*
- * enable user write to DUART
- */
- mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
- ptep = (int *)(QVmap[0] + mapix);
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
-
- mtpr(TBIA, 0); /* invalidate translation buffer */
-
- /*
- * stuff qdmap structure in return buffer
- */
- bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
- break;
-
- case QD_MAPIOBUF:
- /*
- * do setup for DMA by user process
- *
- * set 'user write enable' bits for DMA buffer
- */
- qdflags[unit].mapped |= MAPDMA;
- ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- mtpr(TBIA, 0); /* invalidate translation buffer */
- /*
- * set up QBUS map registers for DMA
- */
- DMAheader[unit]->QBAreg =
- uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
- if (DMAheader[unit]->QBAreg == 0)
- printf("qd%d: qdioctl: QBA setup error\n", unit);
- Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
- DMAheader[unit]->QBAreg &= 0x3FFFF;
- /*
- * return I/O buf adr
- */
- *(int *)datap = (int) DMAheader[unit];
- break;
-
- case QD_MAPSCROLL:
- /*
- * map the shared scroll param area and enable scroll interpts
- */
- qdflags[unit].mapped |= MAPSCR;
- ptep = (int *) ((VTOP(scroll[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- /*
- * allow user write to scroll area
- */
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- mtpr(TBIA, 0); /* invalidate translation buf */
- scroll[unit]->status = 0;
- adder = (struct adder *) qdmap[unit].adder;
- qdflags[unit].adder_ie |= FRAME_SYNC;
- adder->interrupt_enable = qdflags[unit].adder_ie;
- *(int *)datap = (int) scroll[unit]; /* return scroll area */
- break;
-
- case QD_UNMAPSCROLL:
- /*
- * unmap shared scroll param area and disable scroll intrpts
- */
- if (qdflags[unit].mapped & MAPSCR) {
- qdflags[unit].mapped &= ~MAPSCR;
- ptep = (int *) ((VTOP(scroll[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- /*
- * re-protect 512 scroll param area
- */
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
- mtpr(TBIA, 0); /* smash CPU's translation buf */
- adder = (struct adder *) qdmap[unit].adder;
- qdflags[unit].adder_ie &= ~FRAME_SYNC;
- adder->interrupt_enable = qdflags[unit].adder_ie;
- }
- break;
-
- case QD_MAPCOLOR:
- /*
- * map shared color map write buf and turn on vsync intrpt
- */
- qdflags[unit].mapped |= MAPCOLOR;
- ptep = (int *) ((VTOP(color_buf[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- /*
- * allow user write to color map write buffer
- */
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- mtpr(TBIA, 0); /* clr CPU translation buf */
- adder = (struct adder *) qdmap[unit].adder;
- qdflags[unit].adder_ie |= VSYNC;
- adder->interrupt_enable = qdflags[unit].adder_ie;
- /*
- * return color area address
- */
- *(int *)datap = (int) color_buf[unit];
- break;
-
- case QD_UNMAPCOLOR:
- /*
- * unmap shared color map write buffer and kill VSYNC intrpts
- */
- if (qdflags[unit].mapped & MAPCOLOR) {
- qdflags[unit].mapped &= ~MAPCOLOR;
- ptep = (int *) ((VTOP(color_buf[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- /*
- * re-protect color map write buffer
- */
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
- *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
- mtpr(TBIA, 0);
- adder = (struct adder *) qdmap[unit].adder;
- qdflags[unit].adder_ie &= ~VSYNC;
- adder->interrupt_enable = qdflags[unit].adder_ie;
- }
- break;
-
- case QD_MAPEVENT:
- /*
- * give user write access to the event queue
- */
- qdflags[unit].mapped |= MAPEQ;
- ptep = (int *) ((VTOP(eq_header[unit]) * 4)
- + (mfpr(SBR) | 0x80000000));
- /*
- * allow user write to 1K event queue
- */
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
- *ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
- mtpr(TBIA, 0); /* clr CPU translation buf */
- /*
- * return event queue address
- */
- *(int *)datap = (int)eq_header[unit];
- break;
-
- case QD_PRGKBD:
- /*
- * pass caller's programming commands to LK201
- */
- duart = (struct duart *)qdmap[unit].duart;
- cmdbuf = (struct prgkbd *)datap; /* pnt to kbd cmd buf */
- /*
- * send command
- */
- for (i = 1000; i > 0; --i) {
- if (duart->statusA&XMT_RDY) {
- duart->dataA = cmdbuf->cmd;
- break;
- }
- }
- if (i == 0) {
- printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
- break;
- }
- /*
- * send param1?
- */
- if (cmdbuf->cmd & LAST_PARAM)
- break;
- for (i = 1000; i > 0; --i) {
- if (duart->statusA&XMT_RDY) {
- duart->dataA = cmdbuf->param1;
- break;
- }
- }
- if (i == 0) {
- printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
- break;
- }
- /*
- * send param2?
- */
- if (cmdbuf->param1 & LAST_PARAM)
- break;
- for (i = 1000; i > 0; --i) {
- if (duart->statusA&XMT_RDY) {
- duart->dataA = cmdbuf->param2;
- break;
- }
- }
- if (i == 0) {
- printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
- break;
- }
- break;
-
- case QD_PRGMOUSE:
- /*
- * pass caller's programming commands to the mouse
- */
- duart = (struct duart *) qdmap[unit].duart;
- for (i = 1000; i > 0; --i) {
- if (duart->statusB&XMT_RDY) {
- duart->dataB = *datap;
- break;
- }
- }
- if (i == 0) {
- printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
- }
- break;
-
- case QD_RDCONFIG:
- /*
- * get QDSS configuration word and return it
- */
- *(short *)datap = qdflags[unit].config;
- break;
-
- case QD_KERN_LOOP:
- case QD_KERN_UNLOOP:
- /*
- * vestige from ultrix. BSD uses TIOCCONS to redirect
- * kernel console output.
- */
- break;
-
- case QD_PRGTABLET:
- /*
- * program the tablet
- */
- duart = (struct duart *) qdmap[unit].duart;
- for (i = 1000; i > 0; --i) {
- if (duart->statusB&XMT_RDY) {
- duart->dataB = *datap;
- break;
- }
- }
- if (i == 0) {
- printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
- }
- break;
-
- case QD_PRGTABRES:
- /*
- * program the tablet report resolution factor
- */
- qdflags[unit].tab_res = *(short *)datap;
- break;
-
- default:
- /*
- * service tty ioctl's
- */
- if (!(minor_dev & 0x02)) {
- tp = &qd_tty[minor_dev];
- error =
- (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
- if (error >= 0) {
- return(error);
- }
- error = ttioctl(tp, cmd, datap, flags);
- if (error >= 0) {
- return(error);
- }
- }
- break;
- }
-
- return(0);
-
-} /* qdioctl */
-
-qdselect(dev, rw)
- dev_t dev;
- int rw;
-{
- register s;
- register unit;
- register struct tty *tp;
- u_int minor_dev = minor(dev);
-
- s = spl5();
- unit = minor_dev >> 2;
-
- switch (rw) {
- case FREAD:
- if ((minor_dev & 0x03) == 2) {
- /*
- * this is a graphics device, so check for events
- */
- if(!(ISEMPTY(eq_header[unit]))) {
- splx(s);
- return(1);
- }
- qdrsel[unit] = u.u_procp;
- qdflags[unit].selmask |= SEL_READ;
- splx(s);
- return(0);
- } else {
- /*
- * this is a tty device
- */
- tp = &qd_tty[minor_dev];
- if (ttnread(tp))
- return(1);
- tp->t_rsel = u.u_procp;
- splx(s);
- return(0);
- }
-
- case FWRITE:
- if ((minor(dev) & 0x03) == 2) {
- /*
- * this is a graphics device, so check for dma buffers
- */
- if (DMA_ISEMPTY(DMAheader[unit]))
- {
- splx(s);
- return(1);
- }
- qdrsel[unit] = u.u_procp;
- qdflags[unit].selmask |= SEL_WRITE;
- splx(s);
- return(0);
- } else {
- /*
- * this is a tty device
- */
- tp = &qd_tty[minor_dev];
- if (tp->t_outq.c_cc <= tp->t_lowat)
- return(1);
- tp->t_wsel = u.u_procp;
- splx(s);
- return(0);
- }
- }
- splx(s);
- return(0);
-
-} /* qdselect() */
-
-extern qd_strategy();
-
-qdwrite(dev, uio)
- dev_t dev;
- struct uio *uio;
-{
- register struct tty *tp;
- register minor_dev;
- register unit;
-
- minor_dev = minor(dev);
- unit = (minor_dev >> 2) & 0x07;
-
- if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
- /*
- * this is the console...
- */
- tp = &qd_tty[minor_dev];
- return ((*linesw[tp->t_line].l_write)(tp, uio));
- } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
- /*
- * this is a DMA xfer from user space
- */
- return (physio(qd_strategy, &qdbuf[unit],
- dev, B_WRITE, minphys, uio));
- }
- return (ENXIO);
-}
-
-qdread(dev, uio)
- dev_t dev;
- struct uio *uio;
-{
- register struct tty *tp;
- register minor_dev;
- register unit;
-
- minor_dev = minor(dev);
- unit = (minor_dev >> 2) & 0x07;
-
- if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
- /*
- * this is the console
- */
- tp = &qd_tty[minor_dev];
- return ((*linesw[tp->t_line].l_read)(tp, uio));
- } else if (qdflags[unit].inuse & GRAPHIC_DEV) {
- /*
- * this is a bitmap-to-processor xfer
- */
- return (physio(qd_strategy, &qdbuf[unit],
- dev, B_READ, minphys, uio));
- }
- return (ENXIO);
-}
-
-/***************************************************************
-*
-* qd_strategy()... strategy routine to do DMA
-*
-***************************************************************/
-
-qd_strategy(bp)
- register struct buf *bp;
-{
- register struct dga *dga;
- register struct adder *adder;
- register unit;
- int QBAreg;
- int s;
- int cookie;
-
- unit = (minor(bp->b_dev) >> 2) & 0x07;
-
- /*
- * init pointers
- */
- if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
- printf("qd%d: qd_strategy: QBA setup error\n", unit);
- goto STRAT_ERR;
- }
- dga = (struct dga *) qdmap[unit].dga;
- s = spl5();
- qdflags[unit].user_dma = -1;
- dga->csr |= DMA_IE;
- cookie = QBAreg & 0x3FFFF;
- dga->adrs_lo = (short) cookie;
- dga->adrs_hi = (short) (cookie >> 16);
- dga->bytcnt_lo = (short) bp->b_bcount;
- dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
-
- while (qdflags[unit].user_dma) {
- sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
- }
- splx(s);
- ubarelse(0, &QBAreg);
- if (!(dga->csr & DMA_ERR)) {
- iodone(bp);
- return;
- }
-
-STRAT_ERR:
- adder = (struct adder *) qdmap[unit].adder;
- adder->command = CANCEL; /* cancel adder activity */
- dga->csr &= ~DMA_IE;
- dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
- dga->csr |= DMA_ERR; /* clear error condition */
- bp->b_flags |= B_ERROR; /* flag an error to physio() */
-
- /*
- * if DMA was running, flush spurious intrpt
- */
- if (dga->bytcnt_lo != 0) {
- dga->bytcnt_lo = 0;
- dga->bytcnt_hi = 0;
- DMA_SETIGNORE(DMAheader[unit]);
- dga->csr |= DMA_IE;
- }
- iodone(bp);
-
-} /* qd_strategy */
-
-/*
- * Start output to the console screen
- */
-qdstart(tp)
- register struct tty *tp;
-{
- register which_unit, unit, c;
- int s;
-
- unit = minor(tp->t_dev);
- which_unit = (unit >> 2) & 0x3;
- unit &= 0x03;
-
- s = spl5();
-
- /*
- * If it's currently active, or delaying, no need to do anything.
- */
- if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
- goto out;
-
- /*
- * Display chars until the queue is empty.
- * Drop input from anything but the console
- * device on the floor.
- *
- * XXX - this loop is done at spltty.
- *
- */
- while (tp->t_outq.c_cc) {
- c = getc(&tp->t_outq);
- if (unit == 0)
- blitc(which_unit, (u_char)c);
- }
- /*
- * If there are sleepers, and output has drained below low
- * water mark, wake up the sleepers.
- */
- if (tp->t_outq.c_cc <= tp->t_lowat) {
- if (tp->t_state & TS_ASLEEP){
- tp->t_state &= ~TS_ASLEEP;
- wakeup((caddr_t) &tp->t_outq);
- }
- }
-
- tp->t_state &= ~TS_BUSY;
-
-out:
- splx(s);
-
-} /* qdstart */
-
-/*ARGSUSED*/
-void
-qdstop(tp, flag)
- register struct tty *tp;
- int flag;
-{
- register int s;
-
- s = spl5(); /* block intrpts during state modification */
- if (tp->t_state & TS_BUSY)
- if ((tp->t_state & TS_TTSTOP) == 0)
- tp->t_state |= TS_FLUSH;
- else
- tp->t_state &= ~TS_BUSY;
- splx(s);
-}
-
-/*
- * Output a character to the QDSS screen
- */
-
-blitc(unit, chr)
- register unit;
- register u_char chr;
-{
- register struct adder *adder;
- register struct dga *dga;
- register int i;
- int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
- static short inescape[NQD];
-
- adder = (struct adder *)qdmap[unit].adder;
- dga = (struct dga *) qdmap[unit].dga;
- /*
- * BSD comment: this (&=0177) defeats the extended character
- * set code for the glass tty, but if i had the time i would
- * spend it ripping out the code completely. This driver
- * is too big for its own good.
- */
- chr &= 0177;
- /*
- * Cursor addressing (so vi will work).
- * Decode for "\E=%.%." cursor motion description.
- * Corresponds to type "qdcons" in /etc/termcap:
- *
- * qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
- * :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
- *
- */
- if (inescape[unit] && nograph) {
- switch (inescape[unit]++) {
- case 1:
- if (chr != '=') {
- /* abort escape sequence */
- inescape[unit] = 0;
- blitc(unit, chr);
- }
- return;
- case 2:
- /* position row */
- cursor[unit].y = CHAR_HEIGHT * chr;
- if (cursor[unit].y > 863 - CHAR_HEIGHT)
- cursor[unit].y = 863 - CHAR_HEIGHT;
- dga->y_cursor = TRANY(cursor[unit].y);
- return;
- case 3:
- /* position column */
- cursor[unit].x = CHAR_WIDTH * chr;
- if (cursor[unit].x > 1024 - CHAR_WIDTH)
- cursor[unit].x = 1023 - CHAR_WIDTH;
- dga->x_cursor = TRANX(cursor[unit].x);
- inescape[unit] = 0;
- return;
- default:
- inescape[unit] = 0;
- blitc(unit, chr);
- }
- }
-
- switch (chr) {
- case '\r': /* return char */
- cursor[unit].x = 0;
- if (nograph)
- dga->x_cursor = TRANX(cursor[unit].x);
- return;
-
- case '\t': /* tab char */
- for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
- blitc(unit, ' ');
- }
- return;
-
- case '\n': /* line feed char */
- if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
- if (nograph) {
- cursor[unit].y -= CHAR_HEIGHT;
- scroll_up(adder);
- } else
- cursor[unit].y = 0;
- }
- if (nograph)
- dga->y_cursor = TRANY(cursor[unit].y);
- return;
-
- case '\b': /* backspace char */
- if (cursor[unit].x > 0) {
- cursor[unit].x -= CHAR_WIDTH;
- if (nograph)
- dga->x_cursor = TRANX(cursor[unit].x);
- }
- return;
- case CTRL('k'): /* cursor up */
- if (nograph && cursor[unit].y > 0) {
- cursor[unit].y -= CHAR_HEIGHT;
- dga->y_cursor = TRANY(cursor[unit].y);
- }
- return;
-
- case CTRL('^'): /* home cursor */
- if (nograph) {
- cursor[unit].x = 0;
- dga->x_cursor = TRANX(cursor[unit].x);
- cursor[unit].y = 0;
- dga->y_cursor = TRANY(cursor[unit].y);
- }
- return;
-
- case CTRL('l'): /* cursor right */
- if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
- cursor[unit].x += CHAR_WIDTH;
- dga->x_cursor = TRANX(cursor[unit].x);
- }
- return;
-
- case CTRL('z'): /* clear screen */
- if (nograph) {
- setup_dragon(unit);
- clear_qd_screen(unit);
- /* home cursor - termcap seems to assume this */
- cursor[unit].x = 0;
- dga->x_cursor = TRANX(cursor[unit].x);
- cursor[unit].y = 0;
- dga->y_cursor = TRANY(cursor[unit].y);
- }
- return;
-
- case '\033': /* start escape sequence */
- if (nograph)
- inescape[unit] = 1;
- return;
-
- default:
- if ((chr < ' ') || (chr > '~'))
- return;
- }
- /*
- * setup VIPER operand control registers
- */
- write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */
- write_ID(adder, SRC1_OCR_B,
- EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
- write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */
- write_ID(adder, SRC1_OCR_B,
- EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
- write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
- write_ID(adder, DST_OCR_B,
- EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
- write_ID(adder, MASK_1, 0xFFFF);
- write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
- write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
- adder->x_clip_min = 0;
- adder->x_clip_max = 1024;
- adder->y_clip_min = 0;
- adder->y_clip_max = 864;
- /*
- * load DESTINATION origin and vectors
- */
- adder->fast_dest_dy = 0;
- adder->slow_dest_dx = 0;
- adder->error_1 = 0;
- adder->error_2 = 0;
- adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
- (void)wait_status(adder, RASTEROP_COMPLETE);
- adder->destination_x = cursor[unit].x;
- adder->fast_dest_dx = CHAR_WIDTH;
- adder->destination_y = cursor[unit].y;
- adder->slow_dest_dy = CHAR_HEIGHT;
- /*
- * load SOURCE origin and vectors
- */
- if ((chr - ' ') > (CHARS - 1)) {
- printf("Invalid character (x)%x in blitc\n",chr);
- chr = ' ';
- }
- /*
- * X position is modulo the number of characters per line
- */
- adder->source_1_x = FONT_X +
- (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
- /*
- * Point to either first or second row
- */
- adder->source_1_y = 2048 - 15 *
- (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
- adder->source_1_dx = CHAR_WIDTH;
- adder->source_1_dy = CHAR_HEIGHT;
- write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
- adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
- /*
- * update console cursor coordinates
- */
- cursor[unit].x += CHAR_WIDTH;
- if (nograph)
- dga->x_cursor = TRANX(cursor[unit].x);
- if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
- blitc(unit, '\r');
- blitc(unit, '\n');
- }
-
-} /* blitc */
-
-qdreset() { }
-
-/*
- * INTERRUPT SERVICE ROUTINES
- */
-
-/*
- * Service "DMA DONE" interrupt condition
- */
-qddint(qd)
- register qd;
-{
- register struct DMAreq_header *header;
- register struct DMAreq *request;
- register struct dga *dga;
- struct adder *adder;
- int cookie; /* DMA adrs for QDSS */
-
- (void)spl4(); /* allow interval timer in */
-
- /*
- * init pointers
- */
- header = DMAheader[qd]; /* register for optimization */
- dga = (struct dga *) qdmap[qd].dga;
- adder = (struct adder *) qdmap[qd].adder;
-
- /*
- * if this interrupt flagged as bogus for interrupt flushing purposes..
- */
- if (DMA_ISIGNORE(header)) {
- DMA_CLRIGNORE(header);
- return;
- }
-
- /*
- * dump a DMA hardware error message if appropriate
- */
- if (dga->csr & DMA_ERR) {
-
- if (dga->csr & PARITY_ERR)
- printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
-
- if (dga->csr & BUS_ERR)
- printf("qd%d: qddint: DMA hardware bus error.\n", qd);
- }
-
- /*
- * if this was a DMA from user space...
- */
- if (qdflags[qd].user_dma) {
- qdflags[qd].user_dma = 0;
- wakeup((caddr_t)&qdflags[qd].user_dma);
- return;
- }
-
- /*
- * if we're doing DMA request queue services, field the error condition
- */
- if (dga->csr & DMA_ERR) {
-
- dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
- dga->csr |= DMA_ERR; /* clear error condition */
- adder->command = CANCEL; /* cancel adder activity */
-
- DMA_SETERROR(header); /* flag error in header status word */
- DMA_CLRACTIVE(header);
- header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
- header->newest = header->oldest;
- header->used = 0;
-
- if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
- selwakeup(qdrsel[qd], 0);
- qdrsel[qd] = 0;
- qdflags[qd].selmask &= ~SEL_WRITE;
- }
-
- if (dga->bytcnt_lo != 0) {
- dga->bytcnt_lo = 0;
- dga->bytcnt_hi = 0;
- DMA_SETIGNORE(header);
- }
- return;
- }
-
- /*
- * if the DMA request queue is now becoming non-full,
- * wakeup "select" client.
- */
- if (DMA_ISFULL(header)) {
- if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
- selwakeup(qdrsel[qd], 0);
- qdrsel[qd] = 0;
- qdflags[qd].selmask &= ~SEL_WRITE;
- }
- }
-
- header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
- QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
-
- /* check for unexpected interrupt */
- if (DMA_ISEMPTY(header))
- return;
-
- DMA_GETEND(header); /* update request queue indices */
-
- /*
- * if no more DMA pending, wake up "select" client and exit
- */
- if (DMA_ISEMPTY(header)) {
-
- if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
- selwakeup(qdrsel[qd], 0);
- qdrsel[qd] = 0;
- qdflags[qd].selmask &= ~SEL_WRITE;
- }
-
- DMA_CLRACTIVE(header); /* flag DMA done */
- return;
- }
-
- /*
- * initiate next DMA xfer
- */
- request = DMA_GETBEGIN(header);
- if (request->DMAtype != QDlast_DMAtype) {
- dga->csr &= ~0x0600; /* halt DMA (reset fifo) */
- adder->command = CANCEL; /* cancel adder activity */
- }
-
-
- switch (request->DMAtype) {
-
- case DISPLIST:
- if (request->DMAtype != QDlast_DMAtype) {
- dga->csr |= DL_ENB;
- dga->csr &= ~(BTOP_ENB | BYTE_DMA);
- }
- break;
-
- case PTOB:
- if (request->DMAtype != QDlast_DMAtype) {
- if (request->DMAdone & BYTE_PACK)
- dga->csr |= (PTOB_ENB | BYTE_DMA);
- else {
- dga->csr |= PTOB_ENB;
- dga->csr &= ~BYTE_DMA;
- }
- }
- break;
-
- case BTOP:
- if (request->DMAtype != QDlast_DMAtype) {
- if (request->DMAdone & BYTE_PACK) {
- dga->csr &= ~DL_ENB;
- dga->csr |= (BTOP_ENB | BYTE_DMA);
- }
- else {
- dga->csr |= BTOP_ENB;
- dga->csr &= ~(BYTE_DMA | DL_ENB);
- }
- }
- break;
- default:
- printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
- DMA_CLRACTIVE(header); /* flag DMA done */
- return;
- }
-
- if (request->DMAdone & COUNT_ZERO) {
- dga->csr &= ~SET_DONE_FIFO;
- }
- else if (request->DMAdone & FIFO_EMPTY) {
- dga->csr |= SET_DONE_FIFO;
- }
-
- if (request->DMAdone & WORD_PACK)
- dga->csr &= ~BYTE_DMA;
- else if (request->DMAdone & BYTE_PACK)
- dga->csr |= BYTE_DMA;
-
- dga->csr |= DMA_IE;
- QDlast_DMAtype = request->DMAtype;
-
- cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
-
- dga->adrs_lo = (short) cookie;
- dga->adrs_hi = (short) (cookie >> 16);
-
- dga->bytcnt_lo = (short) request->length;
- dga->bytcnt_hi = (short) (request->length >> 16);
-
- return;
-}
-
-/*
- * ADDER interrupt service routine
- */
-qdaint(qd)
- register qd;
-{
- register struct adder *adder;
- struct color_buf *cbuf;
- int i;
- register struct rgb *rgbp;
- register short *red;
- register short *green;
- register short *blue;
-
- (void)spl4(); /* allow interval timer in */
-
- adder = (struct adder *) qdmap[qd].adder;
-
- /*
- * service the vertical blank interrupt (VSYNC bit) by loading
- * any pending color map load request
- */
- if (adder->status & VSYNC) {
- adder->status &= ~VSYNC; /* clear the interrupt */
- cbuf = color_buf[qd];
- if (cbuf->status & LOAD_COLOR_MAP) {
-
- red = (short *) qdmap[qd].red;
- green = (short *) qdmap[qd].green;
- blue = (short *) qdmap[qd].blue;
-
- for (i = cbuf->count, rgbp = cbuf->rgb;
- --i >= 0; rgbp++) {
- red[rgbp->offset] = (short) rgbp->red;
- green[rgbp->offset] = (short) rgbp->green;
- blue[rgbp->offset] = (short) rgbp->blue;
- }
-
- cbuf->status &= ~LOAD_COLOR_MAP;
- }
- }
-
- /*
- * service the scroll interrupt (FRAME_SYNC bit)
- */
- if (adder->status & FRAME_SYNC) {
- adder->status &= ~FRAME_SYNC; /* clear the interrupt */
-
- if (scroll[qd]->status & LOAD_REGS) {
-
- for (i = 1000, adder->status = 0; i > 0 &&
- !(adder->status&ID_SCROLL_READY); --i)
- ;
-
- if (i == 0) {
- printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
- qd);
- return;
- }
-
- adder->ID_scroll_data = scroll[qd]->viper_constant;
- adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
-
- adder->y_scroll_constant =
- scroll[qd]->y_scroll_constant;
- adder->y_offset_pending = scroll[qd]->y_offset;
-
- if (scroll[qd]->status & LOAD_INDEX) {
-
- adder->x_index_pending =
- scroll[qd]->x_index_pending;
- adder->y_index_pending =
- scroll[qd]->y_index_pending;
- }
-
- scroll[qd]->status = 0x00;
- }
- }
-}
-
-/*
- * DUART input interrupt service routine
- *
- * XXX - this routine should be broken out - it is essentially
- * straight line code.
- */
-
-qdiint(qd)
- register qd;
-{
- register struct _vs_event *event;
- register struct qdinput *eqh;
- struct dga *dga;
- struct duart *duart;
- struct mouse_report *new_rep;
- struct uba_device *ui;
- struct tty *tp;
- u_short chr;
- u_short status;
- u_short data;
- u_short key;
- char do_wakeup = 0; /* flag to do a select wakeup call */
- char a, b, c; /* mouse button test variables */
-
- (void)spl4(); /* allow interval timer in */
-
- eqh = eq_header[qd]; /* optimized as a register */
- new_rep = ¤t_rep[qd];
- duart = (struct duart *) qdmap[qd].duart;
-
- /*
- * if the graphic device is turned on..
- */
- if (qdflags[qd].inuse & GRAPHIC_DEV) {
- /*
- * empty DUART
- */
- while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
- /*
- * pick up LK-201 input (if any)
- */
- if (duart->statusA&RCV_RDY) {
-
- /* if error condition, then reset it */
-
- if (duart->statusA&0x70) {
- duart->cmdA = 0x40;
- continue;
- }
-
- /* event queue full now? (overflow condition) */
-
- if (ISFULL(eqh) == TRUE) {
- printf(
- "qd%d: qdiint: event queue overflow\n",
- qd);
- break;
- }
-
- /*
- * Check for various keyboard errors */
-
- key = duart->dataA & 0xFF;
-
- if (key==LK_POWER_ERROR ||
- key==LK_KDOWN_ERROR ||
- key == LK_INPUT_ERROR ||
- key == LK_OUTPUT_ERROR) {
- printf(
- "qd%d: qdiint: keyboard error, code = %x\n",
- qd,key);
- return;
- }
-
- if (key < LK_LOWEST)
- return;
-
- ++do_wakeup; /* request a select wakeup call */
-
- event = PUTBEGIN(eqh);
- PUTEND(eqh);
-
- event->vse_key = key;
- event->vse_key &= 0x00FF;
- event->vse_x = eqh->curs_pos.x;
- event->vse_y = eqh->curs_pos.y;
- event->vse_time = TOY;
- event->vse_type = VSE_BUTTON;
- event->vse_direction = VSE_KBTRAW;
- event->vse_device = VSE_DKB;
- }
-
- /*
- * pick up the mouse input (if any) */
-
- if ((status = duart->statusB) & RCV_RDY &&
- qdflags[qd].pntr_id == MOUSE_ID) {
-
- if (status & 0x70) {
- duart->cmdB = 0x40;
- continue;
- }
-
- /* event queue full now? (overflow condition) */
-
- if (ISFULL(eqh) == TRUE) {
- printf(
- "qd%d: qdiint: event queue overflow\n",
- qd);
- break;
- }
-
- data = duart->dataB; /* get report byte */
- ++new_rep->bytcnt; /* bump report byte count */
-
- /*
- * if 1st byte of report.. */
-
- if ( data & START_FRAME) {
- new_rep->state = data;
- if (new_rep->bytcnt > 1) {
- /* start of new frame */
- new_rep->bytcnt = 1;
- /* ..continue looking */
- continue;
- }
- }
-
- /*
- * if 2nd byte of report.. */
-
- else if (new_rep->bytcnt == 2) {
- new_rep->dx = data & 0x00FF;
- }
-
- /*
- * if 3rd byte of report, load input event queue */
-
- else if (new_rep->bytcnt == 3) {
-
- new_rep->dy = data & 0x00FF;
- new_rep->bytcnt = 0;
-
- /*
- * if mouse position has changed.. */
-
- if (new_rep->dx != 0 || new_rep->dy != 0) {
-
- /*
- * calculate acceleration factor, if needed */
-
- if (qdflags[qd].curs_acc > ACC_OFF) {
-
- if (qdflags[qd].curs_thr <= new_rep->dx)
- new_rep->dx +=
- (new_rep->dx - qdflags[qd].curs_thr)
- * qdflags[qd].curs_acc;
-
- if (qdflags[qd].curs_thr <= new_rep->dy)
- new_rep->dy +=
- (new_rep->dy - qdflags[qd].curs_thr)
- * qdflags[qd].curs_acc;
- }
-
- /*
- * update cursor position coordinates */
-
- if (new_rep->state & X_SIGN) {
- eqh->curs_pos.x += new_rep->dx;
- if (eqh->curs_pos.x > 1023)
- eqh->curs_pos.x = 1023;
- }
- else {
- eqh->curs_pos.x -= new_rep->dx;
- if (eqh->curs_pos.x < -15)
- eqh->curs_pos.x = -15;
- }
-
- if (new_rep->state & Y_SIGN) {
- eqh->curs_pos.y -= new_rep->dy;
- if (eqh->curs_pos.y < -15)
- eqh->curs_pos.y = -15;
- }
- else {
- eqh->curs_pos.y += new_rep->dy;
- if (eqh->curs_pos.y > 863)
- eqh->curs_pos.y = 863;
- }
-
- /*
- * update cursor screen position */
-
- dga = (struct dga *) qdmap[qd].dga;
- dga->x_cursor = TRANX(eqh->curs_pos.x);
- dga->y_cursor = TRANY(eqh->curs_pos.y);
-
- /*
- * if cursor is in the box, no event report */
-
- if (eqh->curs_pos.x <= eqh->curs_box.right &&
- eqh->curs_pos.x >= eqh->curs_box.left &&
- eqh->curs_pos.y >= eqh->curs_box.top &&
- eqh->curs_pos.y <= eqh->curs_box.bottom ) {
- goto GET_MBUTTON;
- }
-
- /*
- * report the mouse motion event */
-
- event = PUTBEGIN(eqh);
- PUTEND(eqh);
-
- ++do_wakeup; /* request a select wakeup call */
-
- event->vse_x = eqh->curs_pos.x;
- event->vse_y = eqh->curs_pos.y;
-
- event->vse_device = VSE_MOUSE; /* mouse */
- event->vse_type = VSE_MMOTION; /* pos changed */
- event->vse_key = 0;
- event->vse_direction = 0;
- event->vse_time = TOY; /* time stamp */
- }
-
-GET_MBUTTON:
- /*
- * if button state has changed */
-
- a = new_rep->state & 0x07; /*mask nonbutton bits */
- b = last_rep[qd].state & 0x07;
-
- if (a ^ b) {
-
- for ( c = 1; c < 8; c <<= 1) {
-
- if (!( c & (a ^ b))) /* this button change? */
- continue;
-
- /* event queue full? (overflow condition) */
-
- if (ISFULL(eqh) == TRUE) {
- printf("qd%d: qdiint: event queue overflow\n", qd);
- break;
- }
-
- event = PUTBEGIN(eqh); /* get new event */
- PUTEND(eqh);
-
- ++do_wakeup; /* request select wakeup */
-
- event->vse_x = eqh->curs_pos.x;
- event->vse_y = eqh->curs_pos.y;
-
- event->vse_device = VSE_MOUSE; /* mouse */
- event->vse_type = VSE_BUTTON; /* new button */
- event->vse_time = TOY; /* time stamp */
-
- /* flag changed button and if up or down */
-
- if (c == RIGHT_BUTTON)
- event->vse_key = VSE_RIGHT_BUTTON;
- else if (c == MIDDLE_BUTTON)
- event->vse_key = VSE_MIDDLE_BUTTON;
- else if (c == LEFT_BUTTON)
- event->vse_key = VSE_LEFT_BUTTON;
-
- /* set bit = button depressed */
-
- if (c & a)
- event->vse_direction = VSE_KBTDOWN;
- else
- event->vse_direction = VSE_KBTUP;
- }
- }
-
- /* refresh last report */
-
- last_rep[qd] = current_rep[qd];
-
- } /* get last byte of report */
- } else if ((status = duart->statusB)&RCV_RDY &&
- qdflags[qd].pntr_id == TABLET_ID) {
- /*
- * pickup tablet input, if any
- */
- if (status&0x70) {
- duart->cmdB = 0x40;
- continue;
- }
- /*
- * event queue full now? (overflow condition)
- */
- if (ISFULL(eqh) == TRUE) {
- printf("qd%d: qdiint: event queue overflow\n", qd);
- break;
- }
-
- data = duart->dataB; /* get report byte */
- ++new_rep->bytcnt; /* bump report byte count */
-
- /*
- * if 1st byte of report.. */
-
- if (data & START_FRAME) {
- new_rep->state = data;
- if (new_rep->bytcnt > 1) {
- new_rep->bytcnt = 1; /* start of new frame */
- continue; /* ..continue looking */
- }
- }
-
- /*
- * if 2nd byte of report.. */
-
- else if (new_rep->bytcnt == 2) {
- new_rep->dx = data & 0x3F;
- }
-
- /*
- * if 3rd byte of report.. */
-
- else if (new_rep->bytcnt == 3) {
- new_rep->dx |= (data & 0x3F) << 6;
- }
-
- /*
- * if 4th byte of report.. */
-
- else if (new_rep->bytcnt == 4) {
- new_rep->dy = data & 0x3F;
- }
-
- /*
- * if 5th byte of report, load input event queue */
-
- else if (new_rep->bytcnt == 5) {
-
- new_rep->dy |= (data & 0x3F) << 6;
- new_rep->bytcnt = 0;
-
- /*
- * update cursor position coordinates */
-
- new_rep->dx /= qdflags[qd].tab_res;
- new_rep->dy = (2200 - new_rep->dy)
- / qdflags[qd].tab_res;
-
- if (new_rep->dx > 1023) {
- new_rep->dx = 1023;
- }
- if (new_rep->dy > 863) {
- new_rep->dy = 863;
- }
-
- /*
- * report an event if the puck/stylus has moved
- */
-
- if (eqh->curs_pos.x != new_rep->dx ||
- eqh->curs_pos.y != new_rep->dy) {
-
- eqh->curs_pos.x = new_rep->dx;
- eqh->curs_pos.y = new_rep->dy;
-
- /*
- * update cursor screen position */
-
- dga = (struct dga *) qdmap[qd].dga;
- dga->x_cursor = TRANX(eqh->curs_pos.x);
- dga->y_cursor = TRANY(eqh->curs_pos.y);
-
- /*
- * if cursor is in the box, no event report
- */
-
- if (eqh->curs_pos.x <= eqh->curs_box.right &&
- eqh->curs_pos.x >= eqh->curs_box.left &&
- eqh->curs_pos.y >= eqh->curs_box.top &&
- eqh->curs_pos.y <= eqh->curs_box.bottom ) {
- goto GET_TBUTTON;
- }
-
- /*
- * report the tablet motion event */
-
- event = PUTBEGIN(eqh);
- PUTEND(eqh);
-
- ++do_wakeup; /* request a select wakeup call */
-
- event->vse_x = eqh->curs_pos.x;
- event->vse_y = eqh->curs_pos.y;
-
- event->vse_device = VSE_TABLET; /* tablet */
- /*
- * right now, X handles tablet motion the same
- * as mouse motion
- */
- event->vse_type = VSE_MMOTION; /* pos changed */
- event->vse_key = 0;
- event->vse_direction = 0;
- event->vse_time = TOY; /* time stamp */
- }
-GET_TBUTTON:
- /*
- * if button state has changed */
-
- a = new_rep->state & 0x1E; /* mask nonbutton bits */
- b = last_rep[qd].state & 0x1E;
-
- if (a ^ b) {
-
- /* event queue full now? (overflow condition) */
-
- if (ISFULL(eqh) == TRUE) {
- printf("qd%d: qdiint: event queue overflow\n",qd);
- break;
- }
-
- event = PUTBEGIN(eqh); /* get new event */
- PUTEND(eqh);
-
- ++do_wakeup; /* request a select wakeup call */
-
- event->vse_x = eqh->curs_pos.x;
- event->vse_y = eqh->curs_pos.y;
-
- event->vse_device = VSE_TABLET; /* tablet */
- event->vse_type = VSE_BUTTON; /* button changed */
- event->vse_time = TOY; /* time stamp */
-
- /* define the changed button and if up or down */
-
- for ( c = 1; c <= 0x10; c <<= 1) {
- if (c & (a ^ b)) {
- if (c == T_LEFT_BUTTON)
- event->vse_key = VSE_T_LEFT_BUTTON;
- else if (c == T_FRONT_BUTTON)
- event->vse_key = VSE_T_FRONT_BUTTON;
- else if (c == T_RIGHT_BUTTON)
- event->vse_key = VSE_T_RIGHT_BUTTON;
- else if (c == T_BACK_BUTTON)
- event->vse_key = VSE_T_BACK_BUTTON;
- break;
- }
- }
-
- /* set bit = button depressed */
-
- if (c & a)
- event->vse_direction = VSE_KBTDOWN;
- else
- event->vse_direction = VSE_KBTUP;
- }
-
- /* refresh last report */
-
- last_rep[qd] = current_rep[qd];
-
- } /* get last byte of report */
- } /* pick up tablet input */
-
- } /* while input available.. */
-
- /*
- * do select wakeup
- */
- if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
- selwakeup(qdrsel[qd], 0);
- qdrsel[qd] = 0;
- qdflags[qd].selmask &= ~SEL_READ;
- do_wakeup = 0;
- }
- } else {
- /*
- * if the graphic device is not turned on, this is console input
- */
- if (qdpolling)
- return;
- ui = qdinfo[qd];
- if (ui == 0 || ui->ui_alive == 0)
- return;
-
- tp = &qd_tty[qd << 2];
-
- /*
- * Get a character from the keyboard.
- */
- while (duart->statusA&RCV_RDY) {
- key = duart->dataA;
- key &= 0xFF;
- /*
- * Check for various keyboard errors
- */
- if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
- key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
- printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
- return;
- }
-
- if (key < LK_LOWEST)
- return;
-
- /*
- * See if its a state change key */
-
- switch (key) {
-
- case LOCK:
- q_keyboard.lock ^= 0xffff; /* toggle */
- if (q_keyboard.lock)
- (void)led_control(qd, LK_LED_ENABLE,
- LK_LED_LOCK);
- else
- (void)led_control(qd, LK_LED_DISABLE,
- LK_LED_LOCK);
- return;
-
- case SHIFT:
- q_keyboard.shift ^= 0xFFFF;
- return;
-
- case CNTRL:
- q_keyboard.cntrl ^= 0xFFFF;
- return;
-
- case ALLUP:
- q_keyboard.cntrl = 0;
- q_keyboard.shift = 0;
- return;
-
- case REPEAT:
- chr = q_keyboard.last;
- break;
-
- /*
- * Test for cntrl characters. If set, see if the character
- * is elligible to become a control character. */
-
- default:
-
- if (q_keyboard.cntrl) {
- chr = q_key[key];
- if (chr >= ' ' && chr <= '~')
- chr &= 0x1F;
- else if (chr >= 0xA1 && chr <= 0xFE)
- chr &= 0x9F;
- }
- else if( q_keyboard.lock || q_keyboard.shift )
- chr = q_shift_key[key];
- else
- chr = q_key[key];
- break;
- }
-
- q_keyboard.last = chr;
-
- /*
- * Check for special function keys */
-
- if (chr & 0x100) {
- char *string;
- string = q_special[chr & 0x7F];
- while(*string)
- (*linesw[tp->t_line].l_rint)(*string++, tp);
- }
- else {
-#ifdef KADB
- if (!kdbrintr(chr&0177, tp))
-#endif
- (*linesw[tp->t_line].l_rint)(chr&0177, tp);
- }
- }
- }
-} /* qdiint */
-
-/*
- *
- * Clear the QDSS screen
- *
- * >>> NOTE <<<
- *
- * This code requires that certain adder initialization be valid. To
- * assure that this requirement is satisfied, this routine should be
- * called only after calling the "setup_dragon()" function.
- *
- * Clear the bitmap a piece at a time. Since the fast scroll clear
- * only clears the current displayed portion of the bitmap put a
- * temporary value in the y limit register so we can access whole
- * bitmap
- *
- */
-clear_qd_screen(unit)
- int unit;
-{
- register struct adder *adder;
- adder = (struct adder *) qdmap[unit].adder;
-
- adder->x_limit = 1024;
- adder->y_limit = 2048 - CHAR_HEIGHT;
- adder->y_offset_pending = 0;
-#define WSV (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
- WSV;
- adder->y_scroll_constant = SCROLL_ERASE;
- WSV;
- adder->y_offset_pending = 864;
- WSV;
- adder->y_scroll_constant = SCROLL_ERASE;
- WSV;
- adder->y_offset_pending = 1728;
- WSV;
- adder->y_scroll_constant = SCROLL_ERASE;
- WSV;
- adder->y_offset_pending = 0; /* back to normal */
- WSV;
- adder->x_limit = MAX_SCREEN_X;
- adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
-#undef WSV
-
-} /* clear_qd_screen */
-
-/*
- * kernel console output to the glass tty
- */
-qdputc(chr)
- register char chr;
-{
-
- /*
- * if system is now physical, forget it (ie: crash DUMP)
- */
- if ((mfpr(MAPEN) & 1) == 0)
- return;
-
- blitc(0, (u_char)(chr & 0xff));
- if ((chr & 0177) == '\n')
- blitc(0, '\r');
-
-} /* qdputc */
-
-/*
- * load the mouse cursor's template RAM bitmap
- */
-ldcursor(unit, bitmap)
- int unit;
- register short *bitmap;
-{
- register struct dga *dga;
- register short *temp;
- register int i;
- int curs;
-
- dga = (struct dga *) qdmap[unit].dga;
- temp = (short *) qdmap[unit].template;
-
- if (dga->csr & CURS_ENB) { /* if the cursor is enabled.. */
- curs = -1; /* ..note that.. */
- dga->csr &= ~CURS_ENB; /* ..and shut it off */
- } else
- curs = 0;
-
- dga->csr &= ~CURS_ENB; /* shut off the cursor */
-
- temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */
- /* ..of the 8k WORD template space */
- for (i = 0; i < 32; ++i)
- *temp++ = *bitmap++;
-
- if (curs) { /* if cursor was enabled.. */
- dga->csr |= CURS_ENB; /* ..turn it back on */
- }
-
-} /* ldcursor */
-
-/*
- * Put the console font in the QDSS off-screen memory
- */
-ldfont(unit)
- int unit;
-{
- register struct adder *adder;
-
- register i, j, k, max_chars_line;
- register short packed;
-
- adder = (struct adder *) qdmap[unit].adder;
-
- /*
- * setup VIPER operand control registers
- */
- write_ID(adder, MASK_1, 0xFFFF);
- write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
- write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
-
- write_ID(adder, SRC1_OCR_B,
- EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
- write_ID(adder, SRC2_OCR_B,
- EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
- write_ID(adder, DST_OCR_B,
- EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
-
- adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
-
- /*
- * load destination data
- */
- (void)wait_status(adder, RASTEROP_COMPLETE);
-
- adder->destination_x = FONT_X;
- adder->destination_y = FONT_Y;
-#if FONT_WIDTH > MAX_SCREEN_X
- adder->fast_dest_dx = MAX_SCREEN_X;
-#else
- adder->fast_dest_dx = FONT_WIDTH;
-#endif
- adder->slow_dest_dy = CHAR_HEIGHT;
-
- /*
- * setup for processor to bitmap xfer */
-
- write_ID(adder, CS_UPDATE_MASK, 0x0001);
- adder->cmd = PBT | OCRB | 2 | DTE | 2;
-
- /*
- * Figure out how many characters can be stored on one "line" of
- * offscreen memory.
- */
- max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
- if ((CHARS/2 + CHARS%2) < max_chars_line)
- max_chars_line = CHARS/2 + CHARS%2;
-
- /*
- * iteratively do the processor to bitmap xfer */
-
- for (i = 0; i < ROWS; ++i) {
-
- /* PTOB a scan line */
-
- for (j = 0, k = i; j < max_chars_line; ++j) {
- /* PTOB one scan of a char cell */
-
- packed = q_font[k];
- k += ROWS;
- packed |= ((short)q_font[k] << 8);
- k += ROWS;
-
- (void)wait_status(adder, TX_READY);
- adder->id_data = packed;
- }
- }
-
- /*
- * (XXX XXX XXX - should remove)
- *
- * Copy the second row of characters. Subtract the first
- * row from the total number. Divide this quantity by 2
- * because 2 chars are stored in a short in the PTOB loop
- * below. Figure out how many characters can be stored on
- * one "line" of offscreen memory
- */
-
- max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
- if ((CHARS/2 + CHARS%2) < max_chars_line)
- return;
- max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
- /* Paranoia check to see if 3rd row may be needed */
- if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
- max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
-
- adder->destination_x = FONT_X;
- adder->destination_y = FONT_Y - CHAR_HEIGHT;
- adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
- adder->slow_dest_dy = CHAR_HEIGHT;
-
- /*
- * setup for processor to bitmap xfer
- */
- write_ID(adder, CS_UPDATE_MASK, 0x0001);
- adder->cmd = PBT | OCRB | 2 | DTE | 2;
-
- /*
- * iteratively do the processor to bitmap xfer
- */
- for (i = 0; i < ROWS; ++i) {
- /*
- * PTOB a scan line
- */
- for (j = 0, k = i; j < max_chars_line; ++j) {
- /*
- * PTOB one scan of a char cell
- */
- packed = q_font[k + FONT_OFFSET];
- k += ROWS;
- packed |= ((short)q_font[k + FONT_OFFSET] << 8);
- k += ROWS;
- (void)wait_status(adder, TX_READY);
- adder->id_data = packed;
- }
- }
-
-} /* ldfont */
-
-qdpoll(onoff)
-{
- qdpolling = onoff;
-}
-
-/*
- * Get a character from the LK201 (polled)
- */
-qdgetc()
-{
- register short key;
- register char chr;
- register struct duart *duart;
-
- duart = (struct duart *) qdmap[0].duart;
-
- /*
- * Get a character from the keyboard.
- */
-LOOP:
- while (!(duart->statusA&RCV_RDY))
- ;
-
- key = duart->dataA;
- key &= 0xFF;
-
- /*
- * Check for various keyboard errors */
-
- if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
- key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
- printf("Keyboard error, code = %x\n", key);
- return(0);
- }
-
- if (key < LK_LOWEST)
- return(0);
-
- /*
- * See if its a state change key
- */
- switch (key) {
-
- case LOCK:
- q_keyboard.lock ^= 0xffff; /* toggle */
- if (q_keyboard.lock)
- (void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
- else
- (void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
- goto LOOP;
-
- case SHIFT:
- q_keyboard.shift ^= 0xFFFF;
- goto LOOP;
-
- case CNTRL:
- q_keyboard.cntrl ^= 0xFFFF;
- goto LOOP;
-
- case ALLUP:
- q_keyboard.cntrl = 0;
- q_keyboard.shift = 0;
- goto LOOP;
-
- case REPEAT:
- chr = q_keyboard.last;
- break;
-
- /*
- * Test for cntrl characters. If set, see if the character
- * is elligible to become a control character.
- */
- default:
-
- if (q_keyboard.cntrl) {
- chr = q_key[key];
- if (chr >= ' ' && chr <= '~')
- chr &= 0x1F;
- }
- else if ( q_keyboard.lock || q_keyboard.shift )
- chr = q_shift_key[key];
- else
- chr = q_key[key];
- break;
- }
-
- if (chr < ' ' && chr > '~') /* if input is non-displayable */
- return(0); /* ..then pitch it! */
-
- q_keyboard.last = chr;
-
- /*
- * Check for special function keys */
-
- if (chr & 0x80) /* pitch the function keys */
- return(0);
- else
- return(chr);
-
-} /* qdgetc */
-
-/*
- * led_control()... twiddle LK-201 LED's
- */
-led_control(unit, cmd, led_mask)
- int unit, cmd, led_mask;
-{
- register i;
- register struct duart *duart;
-
- duart = (struct duart *)qdmap[unit].duart;
-
- for (i = 1000; i > 0; --i) {
- if (duart->statusA&XMT_RDY) {
- duart->dataA = cmd;
- break;
- }
- }
- for (i = 1000; i > 0; --i) {
- if (duart->statusA&XMT_RDY) {
- duart->dataA = led_mask;
- break;
- }
- }
- if (i == 0)
- return(BAD);
- return(GOOD);
-
-} /* led_control */
-
-/*
- * scroll_up()... move the screen up one character height
- */
-scroll_up(adder)
- register struct adder *adder;
-{
- /*
- * setup VIPER operand control registers
- */
- (void)wait_status(adder, ADDRESS_COMPLETE);
- write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */
- write_ID(adder, MASK_1, 0xFFFF);
- write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
- write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
- write_ID(adder, SRC1_OCR_B,
- EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
- write_ID(adder, DST_OCR_B,
- EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
- /*
- * load DESTINATION origin and vectors
- */
- adder->fast_dest_dy = 0;
- adder->slow_dest_dx = 0;
- adder->error_1 = 0;
- adder->error_2 = 0;
- adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
- adder->destination_x = 0;
- adder->fast_dest_dx = 1024;
- adder->destination_y = 0;
- adder->slow_dest_dy = 864 - CHAR_HEIGHT;
- /*
- * load SOURCE origin and vectors
- */
- adder->source_1_x = 0;
- adder->source_1_dx = 1024;
- adder->source_1_y = 0 + CHAR_HEIGHT;
- adder->source_1_dy = 864 - CHAR_HEIGHT;
- write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
- adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
- /*
- * do a rectangle clear of last screen line
- */
- write_ID(adder, MASK_1, 0xffff);
- write_ID(adder, SOURCE, 0xffff);
- write_ID(adder,DST_OCR_B,
- (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
- write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
- adder->error_1 = 0;
- adder->error_2 = 0;
- adder->slow_dest_dx = 0; /* set up the width of */
- adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */
- adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
- (void)wait_status(adder, RASTEROP_COMPLETE);
- adder->destination_x = 0;
- adder->destination_y = 864 - CHAR_HEIGHT;
- adder->fast_dest_dx = 1024; /* set up the height */
- adder->fast_dest_dy = 0; /* of rectangle */
- write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
- adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
-
-} /* scroll_up */
-
-/*
- * init shared memory pointers and structures
- */
-init_shared(unit)
- register unit;
-{
- register struct dga *dga;
-
- dga = (struct dga *) qdmap[unit].dga;
-
- /*
- * initialize the event queue pointers and header */
-
- eq_header[unit] = (struct qdinput *)
- ((((int)event_shared & ~(0x01FF)) + 512)
- + (EVENT_BUFSIZE * unit));
- eq_header[unit]->curs_pos.x = 0;
- eq_header[unit]->curs_pos.y = 0;
- dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
- dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
- eq_header[unit]->curs_box.left = 0;
- eq_header[unit]->curs_box.right = 0;
- eq_header[unit]->curs_box.top = 0;
- eq_header[unit]->curs_box.bottom = 0;
- /*
- * assign a pointer to the DMA I/O buffer for this QDSS.
- */
- DMAheader[unit] = (struct DMAreq_header *)
- (((int)(&DMA_shared[0] + 512) & ~0x1FF)
- + (DMAbuf_size * unit));
- DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
- + sizeof(struct DMAreq_header));
- DMAheader[unit]->QBAreg = 0;
- DMAheader[unit]->status = 0;
- DMAheader[unit]->shared_size = DMAbuf_size;
- DMAheader[unit]->used = 0;
- DMAheader[unit]->size = 10; /* default = 10 requests */
- DMAheader[unit]->oldest = 0;
- DMAheader[unit]->newest = 0;
- /*
- * assign a pointer to the scroll structure for this QDSS.
- */
- scroll[unit] = (struct scroll *)
- (((int)(&scroll_shared[0] + 512) & ~0x1FF)
- + (sizeof(struct scroll) * unit));
- scroll[unit]->status = 0;
- scroll[unit]->viper_constant = 0;
- scroll[unit]->y_scroll_constant = 0;
- scroll[unit]->y_offset = 0;
- scroll[unit]->x_index_pending = 0;
- scroll[unit]->y_index_pending = 0;
- /*
- * assign a pointer to the color map write buffer for this QDSS
- */
- color_buf[unit] = (struct color_buf *)
- (((int)(&color_shared[0] + 512) & ~0x1FF)
- + (COLOR_BUFSIZ * unit));
- color_buf[unit]->status = 0;
- color_buf[unit]->count = 0;
-
-} /* init_shared */
-
-/*
- * init the ADDER, VIPER, bitmaps, & color map
- */
-setup_dragon(unit)
- int unit;
-{
-
- register struct adder *adder;
- register struct dga *dga;
- short *memcsr;
- register i;
- short top; /* clipping/scrolling boundaries */
- short bottom;
- short right;
- short left;
- short *red; /* color map pointers */
- short *green;
- short *blue;
-
- /*
- * init for setup
- */
- adder = (struct adder *) qdmap[unit].adder;
- dga = (struct dga *) qdmap[unit].dga;
- memcsr = (short *) qdmap[unit].memcsr;
- dga->csr &= ~(DMA_IE | 0x700); /* halt DMA and kill the intrpts */
- *memcsr = SYNC_ON; /* blank screen and turn off LED's */
- adder->command = CANCEL;
- /*
- * set monitor timing
- */
- adder->x_scan_count_0 = 0x2800;
- adder->x_scan_count_1 = 0x1020;
- adder->x_scan_count_2 = 0x003A;
- adder->x_scan_count_3 = 0x38F0;
- adder->x_scan_count_4 = 0x6128;
- adder->x_scan_count_5 = 0x093A;
- adder->x_scan_count_6 = 0x313C;
- adder->sync_phase_adj = 0x0100;
- adder->x_scan_conf = 0x00C8;
- /*
- * got a bug in secound pass ADDER! lets take care of it
- *
- * normally, just use the code in the following bug fix code, but to
- * make repeated demos look pretty, load the registers as if there was
- * no bug and then test to see if we are getting sync
- */
- adder->y_scan_count_0 = 0x135F;
- adder->y_scan_count_1 = 0x3363;
- adder->y_scan_count_2 = 0x2366;
- adder->y_scan_count_3 = 0x0388;
- /*
- * if no sync, do the bug fix code
- */
- if (wait_status(adder, VSYNC) == BAD) {
- /* first load all Y scan registers with very short frame and
- * wait for scroll service. This guarantees at least one SYNC
- * to fix the pass 2 Adder initialization bug (synchronizes
- * XCINCH with DMSEEDH)
- */
- adder->y_scan_count_0 = 0x01;
- adder->y_scan_count_1 = 0x01;
- adder->y_scan_count_2 = 0x01;
- adder->y_scan_count_3 = 0x01;
- /*
- * delay at least 1 full frame time
- */
- (void)wait_status(adder, VSYNC);
- (void)wait_status(adder, VSYNC);
- /*
- * now load the REAL sync values (in reverse order just to
- * be safe.
- */
- adder->y_scan_count_3 = 0x0388;
- adder->y_scan_count_2 = 0x2366;
- adder->y_scan_count_1 = 0x3363;
- adder->y_scan_count_0 = 0x135F;
- }
- *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */
- /*
- * zero the index registers
- */
- adder->x_index_pending = 0;
- adder->y_index_pending = 0;
- adder->x_index_new = 0;
- adder->y_index_new = 0;
- adder->x_index_old = 0;
- adder->y_index_old = 0;
- adder->pause = 0;
- /*
- * set rasterop mode to normal pen down
- */
- adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
- /*
- * set the rasterop registers to a default values
- */
- adder->source_1_dx = 1;
- adder->source_1_dy = 1;
- adder->source_1_x = 0;
- adder->source_1_y = 0;
- adder->destination_x = 0;
- adder->destination_y = 0;
- adder->fast_dest_dx = 1;
- adder->fast_dest_dy = 0;
- adder->slow_dest_dx = 0;
- adder->slow_dest_dy = 1;
- adder->error_1 = 0;
- adder->error_2 = 0;
- /*
- * scale factor = UNITY
- */
- adder->fast_scale = UNITY;
- adder->slow_scale = UNITY;
- /*
- * set the source 2 parameters
- */
- adder->source_2_x = 0;
- adder->source_2_y = 0;
- adder->source_2_size = 0x0022;
- /*
- * initialize plane addresses for eight vipers
- */
- write_ID(adder, CS_UPDATE_MASK, 0x0001);
- write_ID(adder, PLANE_ADDRESS, 0x0000);
- write_ID(adder, CS_UPDATE_MASK, 0x0002);
- write_ID(adder, PLANE_ADDRESS, 0x0001);
- write_ID(adder, CS_UPDATE_MASK, 0x0004);
- write_ID(adder, PLANE_ADDRESS, 0x0002);
- write_ID(adder, CS_UPDATE_MASK, 0x0008);
- write_ID(adder, PLANE_ADDRESS, 0x0003);
- write_ID(adder, CS_UPDATE_MASK, 0x0010);
- write_ID(adder, PLANE_ADDRESS, 0x0004);
- write_ID(adder, CS_UPDATE_MASK, 0x0020);
- write_ID(adder, PLANE_ADDRESS, 0x0005);
- write_ID(adder, CS_UPDATE_MASK, 0x0040);
- write_ID(adder, PLANE_ADDRESS, 0x0006);
- write_ID(adder, CS_UPDATE_MASK, 0x0080);
- write_ID(adder, PLANE_ADDRESS, 0x0007);
- /*
- * initialize the external registers.
- */
- write_ID(adder, CS_UPDATE_MASK, 0x00FF);
- write_ID(adder, CS_SCROLL_MASK, 0x00FF);
- /*
- * initialize resolution mode
- */
- write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */
- write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */
- /*
- * initialize viper registers
- */
- write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
- write_ID(adder, SCROLL_FILL, 0x0000);
- /*
- * set clipping and scrolling limits to full screen
- */
- for (i = 1000, adder->status = 0;
- i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
- ;
- if (i == 0)
- printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
- top = 0;
- bottom = 2048;
- left = 0;
- right = 1024;
- adder->x_clip_min = left;
- adder->x_clip_max = right;
- adder->y_clip_min = top;
- adder->y_clip_max = bottom;
- adder->scroll_x_min = left;
- adder->scroll_x_max = right;
- adder->scroll_y_min = top;
- adder->scroll_y_max = bottom;
- (void)wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */
- (void)wait_status(adder, VSYNC);
- adder->x_index_pending = left;
- adder->y_index_pending = top;
- adder->x_index_new = left;
- adder->y_index_new = top;
- adder->x_index_old = left;
- adder->y_index_old = top;
-
- for (i = 1000, adder->status = 0; i > 0 &&
- !(adder->status&ADDRESS_COMPLETE) ; --i)
- ;
- if (i == 0)
- printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
-
- write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
- write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
- /*
- * set source and the mask register to all ones (ie: white) o
- */
- write_ID(adder, SOURCE, 0xFFFF);
- write_ID(adder, MASK_1, 0xFFFF);
- write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
- write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
- /*
- * initialize Operand Control Register banks for fill command
- */
- write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT);
- write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
- write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
- write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
- write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT);
- write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
- /*
- * init Logic Unit Function registers, (these are just common values,
- * and may be changed as required).
- */
- write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
- write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
- INV_M1_M2);
- write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
- write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
- /*
- * load the color map for black & white
- */
- for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
- ;
-
- if (i == 0)
- printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
-
- red = (short *) qdmap[unit].red;
- green = (short *) qdmap[unit].green;
- blue = (short *) qdmap[unit].blue;
-
- *red++ = 0x00; /* black */
- *green++ = 0x00;
- *blue++ = 0x00;
-
- *red-- = 0xFF; /* white */
- *green-- = 0xFF;
- *blue-- = 0xFF;
-
- /*
- * set color map for mouse cursor
- */
-
- red += 254;
- green += 254;
- blue += 254;
-
- *red++ = 0x00; /* black */
- *green++ = 0x00;
- *blue++ = 0x00;
-
- *red = 0xFF; /* white */
- *green = 0xFF;
- *blue = 0xFF;
-
-} /* setup_dragon */
-
-/*
- * Init the DUART and set defaults in input
- */
-setup_input(unit)
- int unit;
-{
- register struct duart *duart; /* DUART register structure pointer */
- register i, bits;
- char id_byte;
-
- duart = (struct duart *) qdmap[unit].duart;
- duart->imask = 0;
-
- /*
- * setup the DUART for kbd & pointing device
- */
- duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */
- duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */
- /* no RTS control,char error mode */
- duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */
- /* no RTS control,no echo or loop */
- duart->cmdB = RESET_M; /* reset mode reg pntr for host */
- duart->modeB = 0x07; /* 8 bits, odd parity, rcv IE.. */
- /* ..no RTS cntrl, char error mode */
- duart->modeB = 0x07; /* 1 stop bit,CTS does not IE XMT */
- /* no RTS control,no echo or loop */
- duart->auxctl = 0x00; /* baud rate set 1 */
- duart->clkselA = 0x99; /* 4800 baud for kbd */
- duart->clkselB = 0x99; /* 4800 baud for mouse */
-
- /* reset everything for keyboard */
-
- for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
- duart->cmdA = bits;
-
- /* reset everything for host */
-
- for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
- duart->cmdB = bits;
-
- duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
- duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
-
- /*
- * init keyboard defaults (DUART channel A)
- */
- for (i = 500; i > 0; --i) {
- if (duart->statusA&XMT_RDY) {
- duart->dataA = LK_DEFAULTS;
- break;
- }
- }
-
- for (i = 100000; i > 0; --i) {
- if (duart->statusA&RCV_RDY) {
- break;
- }
- }
-
- if (duart->dataA) /* flush the ACK */
- ;
-
- /*
- * identify the pointing device
- */
- for (i = 500; i > 0; --i) {
- if (duart->statusB&XMT_RDY) {
- duart->dataB = SELF_TEST;
- break;
- }
- }
-
- /*
- * wait for 1st byte of self test report */
-
- for (i = 100000; i > 0; --i) {
- if (duart->statusB&RCV_RDY) {
- break;
- }
- }
-
- if (i == 0) {
- printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
- ,unit);
- goto OUT;
- }
-
- if (duart->dataB)
- ;
-
- /*
- * wait for ID byte of self test report
- */
- for (i = 100000; i > 0; --i) {
- if (duart->statusB&RCV_RDY) {
- break;
- }
- }
-
- if (i == 0) {
- printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
- goto OUT;
- }
-
- id_byte = duart->dataB;
-
- /*
- * wait for other bytes to come in
- */
- for (i = 100000; i > 0; --i) {
- if (duart->statusB & RCV_RDY) {
- if (duart->dataB)
- ;
- break;
- }
- }
- if (i == 0) {
- printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
- goto OUT;
- }
- for (i = 100000; i > 0; --i) {
- if (duart->statusB&RCV_RDY) {
- if (duart->dataB)
- ;
- break;
- }
- }
- if (i == 0) {
- printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
- goto OUT;
- }
- /*
- * flag pointing device type and set defaults
- */
- for (i=100000; i>0; --i)
- ; /*XXX*/
-
- if ((id_byte & 0x0F) != TABLET_ID) {
- qdflags[unit].pntr_id = MOUSE_ID;
-
- for (i = 500; i > 0; --i) {
- if (duart->statusB&XMT_RDY) {
- duart->dataB = INC_STREAM_MODE;
- break;
- }
- }
- }
- else {
- qdflags[unit].pntr_id = TABLET_ID;
-
- for (i = 500; i > 0; --i) {
- if (duart->statusB&XMT_RDY) {
- duart->dataB = T_STREAM;
- break;
- }
- }
- }
-OUT:
- duart->imask = qdflags[unit].duart_imask;
-
-} /* setup_input */
-
-/*
- * delay for at least one display frame time
- *
- * return: BAD means that we timed out without ever seeing the
- * vertical sync status bit
- * GOOD otherwise
- */
-wait_status(adder, mask)
- register struct adder *adder;
- register int mask;
-{
- register i;
-
- for (i = 10000, adder->status = 0 ; i > 0 &&
- !(adder->status&mask) ; --i)
- ;
-
- if (i == 0) {
- printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
- return(BAD);
- }
-
- return(GOOD);
-
-} /* wait_status */
-
-/*
- * write out onto the ID bus
- */
-write_ID(adder, adrs, data)
- register struct adder *adder;
- register short adrs;
- register short data;
-{
- register i;
-
- for (i = 100000, adder->status = 0 ;
- i > 0 && !(adder->status&ADDRESS_COMPLETE) ; --i)
- ;
-
- if (i == 0)
- goto ERR;
-
- for (i = 100000, adder->status = 0 ;
- i > 0 && !(adder->status&TX_READY) ; --i)
- ;
-
- if (i > 0) {
- adder->id_data = data;
- adder->command = ID_LOAD | adrs;
- return ;
- }
-
-ERR:
- printf("write_ID: timeout trying to write to VIPER\n");
- return ;
-
-} /* write_ID */
-#endif
-/* $OpenBSD: uba.c,v 1.8 1997/05/29 00:05:09 niklas Exp $ */
-/* $NetBSD: uba.c,v 1.29 1996/10/13 03:35:24 christos Exp $ */
+/* $OpenBSD: uba.c,v 1.9 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba.c,v 1.42 1999/02/02 18:37:20 ragge Exp $ */
/*
* Copyright (c) 1996 Jonathan Stone.
* Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
#include <vax/uba/ubareg.h>
#include <vax/uba/ubavar.h>
-volatile int rbr, rcvec, svec;
+volatile int /* rbr, rcvec,*/ svec;
-static void ubascan __P((struct device *, void *));
+static int ubasearch __P((struct device *, struct cfdata *, void *));
static int ubaprint __P((void *, const char *));
+#if 0
static void ubastray __P((int));
+#endif
static void ubainitmaps __P((struct uba_softc *));
-static void uba_attach __P((struct uba_softc *, unsigned long));
-static int ubasetup __P((struct uba_softc *, struct buf *, int));
-
-struct cfdriver uba_cd = {
- NULL, "uba", DV_DULL, 1
-};
+extern struct cfdriver uba_cd;
#define spluba spl7
#if defined(DW780) || defined(DW750)
-int dw_match __P((struct device *, void *, void *));
+int dw_match __P((struct device *, struct cfdata *, void *));
int
-dw_match(parent, vcf, aux)
+dw_match(parent, cf, aux)
struct device *parent;
- void *vcf, *aux;
+ struct cfdata *cf;
+ void *aux;
{
struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
- struct cfdata *cf = vcf;
if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
return 0;
struct uba_softc *sc = (void *)self;
struct sbi_attach_args *sa = aux;
int ubaddr = sa->type & 3;
+ int i;
printf(": DW780\n");
sc->uh_ubainit = dw780_init;
sc->uh_type = DW780;
sc->uh_memsize = UBAPAGES;
- sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG;
+ sc->uh_ibase = VAX_NBPG + ubaddr * VAX_NBPG;
sc->uh_mr = sc->uh_uba->uba_map;
- bcopy(&idsptch, &sc->uh_dw780, sizeof(struct ivec_dsp));
- sc->uh_dw780.pushlarg = sc->uh_dev.dv_unit;
- sc->uh_dw780.hoppaddr = uba_dw780int;
- scb->scb_nexvec[0][sa->nexnum] = scb->scb_nexvec[1][sa->nexnum]
- = scb->scb_nexvec[2][sa->nexnum]
- = scb->scb_nexvec[3][sa->nexnum] = &sc->uh_dw780;
+ for (i = 0; i < 4; i++)
+ scb_vecalloc(256 + i * 64 + sa->nexnum * 4, uba_dw780int,
+ sc->uh_dev.dv_unit, SCB_ISTACK);
uba_attach(sc, (parent->dv_unit ? UMEMB8600(ubaddr) :
- UMEMA8600(ubaddr)) + (UBAPAGES * NBPG));
+ UMEMA8600(ubaddr)) + (UBAPAGES * VAX_NBPG));
}
void
{
volatile int *hej = &sc->uh_uba->uba_sr;
- if (sc->uh_type == DW780) {
- *hej = *hej;
- sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE;
- }
+ *hej = *hej;
+ sc->uh_uba->uba_cr = UBACR_IFS|UBACR_BRIE;
}
void
dw780_afterscan(sc)
struct uba_softc *sc;
{
- if (sc->uh_type == DW780)
- sc->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE |
- UBACR_USEFIE | UBACR_SUEFIE |
- (sc->uh_uba->uba_cr & 0x7c000000);
+ sc->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE |
+ UBACR_USEFIE | UBACR_SUEFIE |
+ (sc->uh_uba->uba_cr & 0x7c000000);
}
/*
{
volatile int *hej = &sc->uh_uba->uba_sr;
- if (sc->uh_type == DW780 && *hej) {
+ if (*hej) {
*hej = *hej;
return 1;
}
void (*func) __P((int));
br = mfpr(PR_IPL);
- svec = ur->uba_brrvr[br - 0x14];
- if (svec <= 0) {
- ubaerror(sc, &br, (int *)&svec);
+ vec = ur->uba_brrvr[br - 0x14];
+ if (vec <= 0) {
+ ubaerror(sc, &br, (int *)&vec);
if (svec == 0)
return;
}
- vec = svec >> 2;
if (cold)
- rcvec = vec;
- func = sc->uh_idsp[vec].hoppaddr;
- arg = sc->uh_idsp[vec].pushlarg;
- (*func)(arg);
+ scb_fake(vec + sc->uh_ibase, br);
+ else {
+ struct ivec_dsp *scb_vec = (struct ivec_dsp *)((int)scb + 512);
+ func = scb_vec[vec/4].hoppaddr;
+ arg = scb_vec[vec/4].pushlarg;
+ (*func)(arg);
+ }
}
void
int *ipl, *uvec;
{
struct uba_regs *uba = uh->uh_uba;
- register sr, s;
+ register int sr, s;
if (*uvec == 0) {
/*
sc->uh_ubainit = dw750_init;
sc->uh_type = DW750;
sc->uh_memsize = UBAPAGES;
- sc->uh_iarea = (void *)scb + NBPG + ubaddr * NBPG;
sc->uh_mr = sc->uh_uba->uba_map;
- uba_attach(sc, UMEM750(ubaddr) + (UBAPAGES * NBPG));
+ uba_attach(sc, UMEM750(ubaddr) + (UBAPAGES * VAX_NBPG));
}
void
* This driver can only handle map registers up to 1MB due to map info
* storage, but that should be enough for normal purposes.
*/
-int qba_match __P((struct device *, void *, void *));
+int qba_match __P((struct device *, struct cfdata *, void *));
void qba_attach __P((struct device *, struct device *, void *));
void qba_beforescan __P((struct uba_softc*));
void qba_init __P((struct uba_softc*));
-struct cfattach uba_backplane_ca = {
+struct cfattach uba_mainbus_ca = {
sizeof(struct uba_softc), qba_match, qba_attach
};
int
qba_match(parent, vcf, aux)
struct device *parent;
- void *vcf, *aux;
+ struct cfdata *vcf;
+ void *aux;
{
struct bp_conf *bp = aux;
void *aux;
{
struct uba_softc *sc = (void *)self;
- vm_offset_t mini, maxi;
printf(": Q22\n");
-
-
/*
* Fill in bus specific data.
*/
sc->uh_ubainit = qba_init;
sc->uh_type = QBA;
sc->uh_memsize = QBAPAGES;
- sc->uh_iarea = (void *)scb + NBPG;
/*
* Map in the UBA page map into kernel space. On other UBAs,
* the map registers are in the bus IO space.
*/
- (void)kmem_suballoc(kernel_map, &mini, &maxi,
- QBAPAGES * sizeof(struct pte), FALSE);
- pmap_map(mini, QBAMAP, QBAMAP + QBAPAGES * sizeof(struct pte),
- VM_PROT_READ | VM_PROT_WRITE);
- sc->uh_mr = (void *)mini;
+ sc->uh_mr = (void *)vax_map_physmem(QBAMAP,
+ (QBAPAGES * sizeof(struct pte)) / VAX_NBPG);
uba_attach(sc, QIOPAGE);
}
qba_beforescan(sc);
}
#endif
-#ifdef DWBUA
-int bua_match __P((struct device *, void *, void *));
-void bua_attach __P((struct device *, struct device *, void *));
-
-struct cfattach uba_bi_ca = {
- sizeof(struct uba_softc), bua_match, bua_attach
-};
-
-bua_beforescan(sc)
- struct uba_softc *sc;
-{
- if (sc->uh_type == DWBUA)
- BUA(ubar)->bua_offset = (int)sc->uh_vec - (int)&scb[0];
-}
-
-void
-bua_init(sc)
- struct uba_softc *sc;
-{
- BUA(uba)->bua_csr |= BUACSR_UPI;
- /* give devices time to recover from power fail */
- DELAY(500000);
- break;
-}
-#endif
#ifdef DW730
struct cfattach uba_dw730_ca = {
sizeof(struct uba_softc), dw730_match, dw730_attach
};
#endif
+#if 0
/*
* Stray interrupt vector handler, used when nowhere else to go to.
*/
printf("uba%d: unexpected interrupt, vector 0x%x, br 0x%x\n",
arg, svec, rbr);
}
-
+#endif
/*
* Do transfer on device argument. The controller
* and uba involved are implied by the device.
if (uh->uh_nbdp == 0)
flags &= ~UBA_NEEDBDP;
- o = (int)bp->b_un.b_addr & PGOFSET;
- npf = btoc(bp->b_bcount + o) + 1;
+ o = (int)bp->b_un.b_addr & VAX_PGOFSET;
+ npf = vax_btoc(bp->b_bcount + o) + 1;
if (npf > UBA_MAXNMR)
panic("uba xfer too big");
a = spluba();
void
uba_attach(sc, iopagephys)
struct uba_softc *sc;
- unsigned long iopagephys;
+ paddr_t iopagephys;
{
- vm_offset_t mini, maxi;
- extern struct ivec_dsp idsptch;
/*
* Set last free interrupt vector for devices with
sc->uh_lastiv = 0x200;
SIMPLEQ_INIT(&sc->uh_resq);
- /*
- * Create interrupt dispatchers for this uba.
- */
-#define NO_IVEC 128
- {
- vm_offset_t iarea;
- int i;
-
- iarea = kmem_alloc(kernel_map,
- NO_IVEC * sizeof(struct ivec_dsp));
- sc->uh_idsp = (struct ivec_dsp *)iarea;
-
- for (i = 0; i < NO_IVEC; i++) {
- bcopy(&idsptch, &sc->uh_idsp[i],
- sizeof(struct ivec_dsp));
- sc->uh_idsp[i].pushlarg = sc->uh_dev.dv_unit;
- sc->uh_idsp[i].hoppaddr = ubastray;
- sc->uh_iarea[i] = (unsigned int)&sc->uh_idsp[i];
- }
- }
/*
* Allocate place for unibus memory in virtual space.
- * This is done with kmem_suballoc() but after that
- * never used in the vm system. Is it OK to do so?
*/
- (void)kmem_suballoc(kernel_map, &mini, &maxi, UBAIOPAGES * NBPG, FALSE);
- pmap_map(mini, iopagephys, iopagephys + UBAIOPAGES * NBPG,
- VM_PROT_READ|VM_PROT_WRITE);
- sc->uh_iopage = (void *)mini;
+ sc->uh_iopage = (caddr_t)vax_map_physmem(iopagephys, UBAIOPAGES);
+ if (sc->uh_iopage == 0)
+ return; /* vax_map_physmem() will complain for us */
/*
* Initialize the UNIBUS, by freeing the map
* registers and the buffered data path registers
/*
* Now start searching for devices.
*/
- config_scan(ubascan,(struct device *)sc);
+ config_search(ubasearch,(struct device *)sc, NULL);
if (sc->uh_afterscan)
(*sc->uh_afterscan)(sc);
}
-void
-ubascan(parent, match)
+int
+ubasearch(parent, cf, aux)
struct device *parent;
- void *match;
+ struct cfdata *cf;
+ void *aux;
{
- struct device *dev = match;
- struct cfdata *cf = dev->dv_cfdata;
struct uba_softc *sc = (struct uba_softc *)parent;
struct uba_attach_args ua;
- int i;
+ int i, vec, br;
ua.ua_addr = (caddr_t)((int)sc->uh_iopage + ubdevreg(cf->cf_loc[0]));
ua.ua_reset = NULL;
if (badaddr(ua.ua_addr, 2) || (sc->uh_errchk ? (*sc->uh_errchk)(sc):0))
goto forgetit;
- rcvec = 0x200;
- i = (*cf->cf_attach->ca_match) (parent, dev, &ua);
+ scb_vecref(0, 0); /* Clear vector ref */
+ i = (*cf->cf_attach->ca_match) (parent, cf, &ua);
if (sc->uh_errchk)
if ((*sc->uh_errchk)(sc))
if (i == 0)
goto forgetit;
- if (rcvec == 0 || rcvec == 0x200)
+ i = scb_vecref(&vec, &br);
+ if (i == 0)
+ goto fail;
+ if (vec == 0)
goto fail;
- sc->uh_idsp[rcvec].hoppaddr = ua.ua_ivec;
- sc->uh_idsp[rcvec].pushlarg = dev->dv_unit;
- if (ua.ua_reset) { /* device wants ubraeset */
+ scb_vecalloc(vec, ua.ua_ivec, cf->cf_unit, SCB_ISTACK);
+ if (ua.ua_reset) { /* device wants ubareset */
if (sc->uh_resno == 0) {
sc->uh_reset = malloc(1024, M_DEVBUF, M_NOWAIT);
sc->uh_resarg = (int *)sc->uh_reset + 128;
}
#ifdef DIAGNOSTIC
if (sc->uh_resno > 127) {
- printf("%s: Expand reset table, skipping reset %s\n",
- sc->uh_dev.dv_xname, dev->dv_xname);
+ printf("%s: Expand reset table, skipping reset %s%d\n",
+ sc->uh_dev.dv_xname, cf->cf_driver->cd_name,
+ cf->cf_unit);
} else
#endif
{
- sc->uh_resarg[sc->uh_resno] = dev->dv_unit;
+ sc->uh_resarg[sc->uh_resno] = cf->cf_unit;
sc->uh_reset[sc->uh_resno++] = ua.ua_reset;
}
}
- ua.ua_br = rbr;
- ua.ua_cvec = rcvec;
- ua.ua_iaddr = dev->dv_cfdata->cf_loc[0];
+ ua.ua_br = br;
+ ua.ua_cvec = vec;
+ ua.ua_iaddr = cf->cf_loc[0];
- config_attach(parent, dev, &ua, ubaprint);
- return;
+ config_attach(parent, cf, &ua, ubaprint);
+ return 0;
fail:
- printf("%s at %s csr %o %s\n", dev->dv_cfdata->cf_driver->cd_name,
- parent->dv_xname, dev->dv_cfdata->cf_loc[0],
- rcvec ? "didn't interrupt\n" : "zero vector\n");
+ printf("%s%d at %s csr %o %s\n",
+ cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname,
+ cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt"));
forgetit:
- free(dev, M_DEVBUF);
-}
-
-/*
- * Called when a device needs more than one interrupt vector.
- * (Like DHU11, DMF32). Argument is the device's softc, vector
- * number and a function pointer to the interrupt catcher.
- */
-void
-ubasetvec(dev, vec, func)
- struct device *dev;
- int vec;
- void (*func) __P((int));
-{
- struct uba_softc *sc = (void *)dev->dv_parent;
-
- sc->uh_idsp[vec].hoppaddr = func;
- sc->uh_idsp[vec].pushlarg = dev->dv_unit;
+ return 0;
}
/*
struct uba_attach_args *ua = aux;
printf(" csr %o vec %o ipl %x", ua->ua_iaddr,
- ua->ua_cvec << 2, ua->ua_br);
+ ua->ua_cvec & 511, ua->ua_br);
return UNCONF;
}
--- /dev/null
+/* $OpenBSD: uba_cmi.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_cmi.c,v 1.2 1999/08/14 11:31:48 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some CMI-specific defines */
+#define UBASIZE ((UBAPAGES + UBAIOPAGES) * VAX_NBPG)
+#define UMEM750(i) (0xfc0000 - (i) * UBASIZE)
+#define UIOPAGE(x) (UMEM750(x) + (UBAPAGES * VAX_NBPG))
+
+/*
+ * The DW780 and DW750 are quite similar to their function from
+ * a programmers point of view. Differencies are number of BDP's
+ * and bus status/command registers, the latter are (partly) IPR's
+ * on 750.
+ */
+static int dw750_match __P((struct device *, struct cfdata *, void *));
+static void dw750_attach __P((struct device *, struct device *, void *));
+static void dw750_init __P((struct uba_softc*));
+#ifdef notyet
+static void dw750_purge __P((struct uba_softc *, int));
+#endif
+
+struct cfattach uba_cmi_ca = {
+ sizeof(struct uba_vsoftc), dw750_match, dw750_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+dw750_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
+
+ if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
+ return 0;
+ /*
+ * The uba type is actually only telling where the uba
+ * space is in nexus space.
+ */
+ if ((sa->type & ~3) != NEX_UBA0)
+ return 0;
+
+ return 1;
+}
+
+void
+dw750_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uba_vsoftc *sc = (void *)self;
+ struct sbi_attach_args *sa = aux;
+ struct uba_regs *uh_uba = (void *)sa->nexaddr;
+ int ubaddr = sa->nexinfo & 1;
+
+ printf(": DW750\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_ubainit = dw750_init;
+#ifdef notyet
+ sc->uv_sc.uh_ubapurge = dw750_purge;
+#endif
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = UBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = (paddr_t)uh_uba->uba_map; /* Map regs physical address */
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_sc, UIOPAGE(ubaddr));
+}
+
+void
+dw750_init(sc)
+ struct uba_softc *sc;
+{
+ mtpr(0, PR_IUR);
+ DELAY(500000);
+}
+
+#ifdef notyet
+void
+dw750_purge(sc, bdp)
+ struct uba_softc *sc;
+ int bdp;
+{
+ sc->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE | UBADPR_NXM | UBADPR_UCE;
+}
+#endif
--- /dev/null
+/* $OpenBSD: uba_common.h,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_common.h,v 1.2 1999/06/21 16:23:01 ragge Exp $ */
+/*-
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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.
+ *
+ * @(#)ubareg.h 7.8 (Berkeley) 5/9/91
+ */
+
+/*
+ * VAX-specific parts of the Unibus softc.
+ */
+struct uba_regs;
+
+struct uba_vsoftc {
+ struct uba_softc uv_sc;/* Common vars from arch/vax/qbus/ubavar.h */
+ struct vax_bus_dma_tag uv_dmat;
+ struct vax_sgmap uv_sgmap;
+ int uv_size; /* Size of UBA addressable memory */
+ paddr_t uv_addr; /* Physical address of map registers */
+ struct uba_regs *uv_uba;/* Where applicable */
+ int uh_ibase;
+ int uh_zvtime;
+ int uh_zvtotal;
+ int uh_zvcnt;
+};
+
+/*
+ * Size of unibus memory address space in pages
+ * (also number of map registers).
+ */
+#define UBAPAGES 496
+#define UBAIOADDR 0760000 /* start of I/O page */
+#define UBAIOPAGES 16
+
+/*
+ * DW780/DW750 hardware registers
+ */
+struct uba_regs {
+ int uba_cnfgr; /* configuration register */
+ int uba_cr; /* control register */
+ int uba_sr; /* status register */
+ int uba_dcr; /* diagnostic control register */
+ int uba_fmer; /* failed map entry register */
+ int uba_fubar; /* failed UNIBUS address register */
+ int pad1[2];
+ int uba_brsvr[4];
+ int uba_brrvr[4]; /* receive vector registers */
+ int uba_dpr[16]; /* buffered data path register */
+ int pad2[480];
+ struct pte uba_map[UBAPAGES]; /* unibus map register */
+ int pad3[UBAIOPAGES]; /* no maps for device address space */
+};
+
+void uba_dma_init __P((struct uba_vsoftc *));
--- /dev/null
+/* $OpenBSD: uba_dma.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_dma.c,v 1.2 1999/06/20 00:59:55 ragge Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPEUBAL, 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.
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <vm/vm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+int uba_bus_dmamap_create_sgmap __P((bus_dma_tag_t, bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *));
+
+void uba_bus_dmamap_destroy_sgmap __P((bus_dma_tag_t, bus_dmamap_t));
+
+int uba_bus_dmamap_load_sgmap __P((bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int));
+
+int uba_bus_dmamap_load_mbuf_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int));
+
+int uba_bus_dmamap_load_uio_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int));
+
+int uba_bus_dmamap_load_raw_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int));
+
+void uba_bus_dmamap_unload_sgmap __P((bus_dma_tag_t, bus_dmamap_t));
+
+void uba_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
+ bus_size_t, int));
+
+void
+uba_dma_init(sc)
+ struct uba_vsoftc *sc;
+{
+ bus_dma_tag_t t;
+ struct pte *pte;
+
+ /*
+ * Initialize the DMA tag used for sgmap-mapped DMA.
+ */
+ t = &sc->uv_dmat;
+ t->_cookie = sc;
+ t->_wbase = 0;
+ t->_wsize = sc->uv_size;
+ t->_boundary = 0;
+ t->_sgmap = &sc->uv_sgmap;
+ t->_dmamap_create = uba_bus_dmamap_create_sgmap;
+ t->_dmamap_destroy = uba_bus_dmamap_destroy_sgmap;
+ t->_dmamap_load = uba_bus_dmamap_load_sgmap;
+ t->_dmamap_load_mbuf = uba_bus_dmamap_load_mbuf_sgmap;
+ t->_dmamap_load_uio = uba_bus_dmamap_load_uio_sgmap;
+ t->_dmamap_load_raw = uba_bus_dmamap_load_raw_sgmap;
+ t->_dmamap_unload = uba_bus_dmamap_unload_sgmap;
+ t->_dmamap_sync = uba_bus_dmamap_sync;
+
+ t->_dmamem_alloc = _bus_dmamem_alloc;
+ t->_dmamem_free = _bus_dmamem_free;
+ t->_dmamem_map = _bus_dmamem_map;
+ t->_dmamem_unmap = _bus_dmamem_unmap;
+ t->_dmamem_mmap = _bus_dmamem_mmap;
+
+ /*
+ * Map in Unibus map registers.
+ */
+ pte = (struct pte *)vax_map_physmem(sc->uv_addr, sc->uv_size/VAX_NBPG);
+ if (pte == 0)
+ panic("uba_dma_init");
+ /*
+ * Initialize the SGMAP.
+ */
+ vax_sgmap_init(t, &sc->uv_sgmap, "uba_sgmap", 0, sc->uv_size, pte, 0);
+
+}
+
+/*
+ * Create a UBA SGMAP-mapped DMA map.
+ */
+int
+uba_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary,
+ flags, dmamp)
+ bus_dma_tag_t t;
+ bus_size_t size;
+ int nsegments;
+ bus_size_t maxsegsz;
+ bus_size_t boundary;
+ int flags;
+ bus_dmamap_t *dmamp;
+{
+ bus_dmamap_t map;
+ int error;
+
+ error = _bus_dmamap_create(t, size, nsegments, maxsegsz,
+ boundary, flags, dmamp);
+ if (error)
+ return (error);
+
+ map = *dmamp;
+
+ if (flags & BUS_DMA_ALLOCNOW) {
+ error = vax_sgmap_alloc(map, vax_round_page(size),
+ t->_sgmap, flags);
+ if (error)
+ uba_bus_dmamap_destroy_sgmap(t, map);
+ }
+
+ return (error);
+}
+
+/*
+ * Destroy a UBA SGMAP-mapped DMA map.
+ */
+void
+uba_bus_dmamap_destroy_sgmap(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ if (map->_dm_flags & DMAMAP_HAS_SGMAP)
+ vax_sgmap_free(map, t->_sgmap);
+
+ _bus_dmamap_destroy(t, map);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with a linear buffer.
+ */
+int
+uba_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ void *buf;
+ bus_size_t buflen;
+ struct proc *p;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load(t, map, buf, buflen, p, flags, t->_sgmap);
+ /*
+ * XXX - Set up BDPs.
+ */
+
+ return (error);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with an mbuf chain.
+ */
+int
+uba_bus_dmamap_load_mbuf_sgmap(t, map, m, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct mbuf *m;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load_mbuf(t, map, m, flags, t->_sgmap);
+
+ return (error);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with a uio.
+ */
+int
+uba_bus_dmamap_load_uio_sgmap(t, map, uio, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct uio *uio;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load_uio(t, map, uio, flags, t->_sgmap);
+
+ return (error);
+}
+
+/*
+ * Load a UBA SGMAP-mapped DMA map with raw memory.
+ */
+int
+uba_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ bus_size_t size;
+ int flags;
+{
+ int error;
+
+ error = vax_sgmap_load_raw(t, map, segs, nsegs, size, flags,
+ t->_sgmap);
+
+ return (error);
+}
+
+/*
+ * Unload a UBA DMA map.
+ */
+void
+uba_bus_dmamap_unload_sgmap(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ /*
+ * Invalidate any SGMAP page table entries used by this
+ * mapping.
+ */
+ vax_sgmap_unload(t, map, t->_sgmap);
+
+ /*
+ * Do the generic bits of the unload.
+ */
+ _bus_dmamap_unload(t, map);
+}
+
+/*
+ * Sync the bus map. This is only needed if BDP's are used.
+ */
+void
+uba_bus_dmamap_sync(tag, dmam, offset, len, ops)
+ bus_dma_tag_t tag;
+ bus_dmamap_t dmam;
+ bus_addr_t offset;
+ bus_size_t len;
+ int ops;
+{
+ /* Only BDP handling, but not yet. */
+}
--- /dev/null
+/* $OpenBSD: uba_ibus.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_ibus.c,v 1.1 1999/08/07 10:36:47 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some Qbus-specific defines */
+#define QBASIZE (8192 * VAX_NBPG)
+#define QBAMAP 0x20088000
+#define QIOPAGE 0x20000000
+
+/*
+ * The Q22 bus is the main IO bus on MicroVAX II/MicroVAX III systems.
+ * It has an address space of 4MB (22 address bits), therefore the name,
+ * and is hardware compatible with all 16 and 18 bits Q-bus devices.
+ */
+static int qba_match __P((struct device *, struct cfdata *, void *));
+static void qba_attach __P((struct device *, struct device *, void *));
+static void qba_beforescan __P((struct uba_softc*));
+static void qba_init __P((struct uba_softc*));
+
+struct cfattach uba_ibus_ca = {
+ sizeof(struct uba_vsoftc), (cfmatch_t)qba_match, qba_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+qba_match(parent, vcf, aux)
+ struct device *parent;
+ struct cfdata *vcf;
+ void *aux;
+{
+ struct bp_conf *bp = aux;
+
+ if (strcmp(bp->type, "uba"))
+ return 0;
+
+ return 1;
+}
+
+void
+qba_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uba_vsoftc *sc = (void *)self;
+
+ printf(": Q22\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_beforescan = qba_beforescan;
+ sc->uv_sc.uh_ubainit = qba_init;
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = QBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = QBAMAP; /* Physical address of map registers */
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_sc, QIOPAGE);
+}
+
+/*
+ * Called when the QBA is set up; to enable DMA access from
+ * QBA devices to main memory.
+ */
+void
+qba_beforescan(sc)
+ struct uba_softc *sc;
+{
+#define QIPCR 0x1f40
+#define Q_LMEAE 0x20
+ bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE);
+}
+
+void
+qba_init(sc)
+ struct uba_softc *sc;
+{
+ mtpr(0, PR_IUR);
+ DELAY(500000);
+ qba_beforescan(sc);
+}
--- /dev/null
+/* $OpenBSD: uba_mainbus.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_mainbus.c,v 1.2 1999/06/06 19:00:53 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some Qbus-specific defines */
+#define QBASIZE (8192 * VAX_NBPG)
+#define QBAMAP 0x20088000
+#define QIOPAGE 0x20000000
+
+/*
+ * The Q22 bus is the main IO bus on MicroVAX II/MicroVAX III systems.
+ * It has an address space of 4MB (22 address bits), therefore the name,
+ * and is hardware compatible with all 16 and 18 bits Q-bus devices.
+ */
+static int qba_match __P((struct device *, struct cfdata *, void *));
+static void qba_attach __P((struct device *, struct device *, void *));
+static void qba_beforescan __P((struct uba_softc*));
+static void qba_init __P((struct uba_softc*));
+
+struct cfattach uba_mainbus_ca = {
+ sizeof(struct uba_vsoftc), qba_match, qba_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+qba_match(parent, vcf, aux)
+ struct device *parent;
+ struct cfdata *vcf;
+ void *aux;
+{
+ struct bp_conf *bp = aux;
+
+ if (strcmp(bp->type, "uba"))
+ return 0;
+
+ return 1;
+}
+
+void
+qba_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uba_vsoftc *sc = (void *)self;
+
+ printf(": Q22\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_beforescan = qba_beforescan;
+ sc->uv_sc.uh_ubainit = qba_init;
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = QBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = QBAMAP; /* Physical address of map registers */
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_sc, QIOPAGE);
+}
+
+/*
+ * Called when the QBA is set up; to enable DMA access from
+ * QBA devices to main memory.
+ */
+void
+qba_beforescan(sc)
+ struct uba_softc *sc;
+{
+#define QIPCR 0x1f40
+#define Q_LMEAE 0x20
+ bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE);
+}
+
+void
+qba_init(sc)
+ struct uba_softc *sc;
+{
+ mtpr(0, PR_IUR);
+ DELAY(500000);
+ qba_beforescan(sc);
+}
--- /dev/null
+/* $OpenBSD: uba_sbi.c,v 1.1 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: uba_sbi.c,v 1.1 1999/06/21 16:23:01 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The 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.
+ *
+ * @(#)uba.c 7.10 (Berkeley) 12/16/90
+ * @(#)autoconf.c 7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#define _VAX_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/cpu.h>
+#include <machine/sgmap.h>
+#include <machine/scb.h>
+
+#include <arch/vax/qbus/ubavar.h>
+
+#include <arch/vax/uba/uba_common.h>
+
+/* Some SBI-specific defines */
+#define UBASIZE (UBAPAGES * VAX_NBPG)
+#define UMEMA8600(i) (0x20100000+(i)*0x40000)
+#define UMEMB8600(i) (0x22100000+(i)*0x40000)
+
+/*
+ * Some status registers.
+ */
+#define UBACNFGR_UBIC 0x00010000 /* unibus init complete */
+#define UBACNFGR_BITS \
+"\40\40PARFLT\37WSQFLT\36URDFLT\35ISQFLT\34MXTFLT\33XMTFLT\30ADPDN\27ADPUP\23UBINIT\22UBPDN\21UBIC"
+
+#define UBACR_IFS 0x00000040 /* interrupt field switch */
+#define UBACR_BRIE 0x00000020 /* BR interrupt enable */
+#define UBACR_USEFIE 0x00000010 /* UNIBUS to SBI error field IE */
+#define UBACR_SUEFIE 0x00000008 /* SBI to UNIBUS error field IE */
+#define UBACR_ADINIT 0x00000001 /* adapter init */
+
+#define UBADPR_BNE 0x80000000 /* buffer not empty - purge */
+
+#define UBABRRVR_DIV 0x0000ffff /* device interrupt vector field */
+
+#define UBASR_BITS \
+"\20\13RDTO\12RDS\11CRD\10CXTER\7CXTMO\6DPPE\5IVMR\4MRPF\3LEB\2UBSTO\1UBSSYNTO"
+
+char ubasr_bits[] = UBASR_BITS;
+
+/*
+ * The DW780 are directly connected to the SBI on 11/780 and 8600.
+ */
+static int dw780_match __P((struct device *, struct cfdata *, void *));
+static void dw780_attach __P((struct device *, struct device *, void *));
+static void dw780_init __P((struct uba_softc*));
+static void dw780_beforescan __P((struct uba_softc *));
+static void dw780_afterscan __P((struct uba_softc *));
+static int dw780_errchk __P((struct uba_softc *));
+static void uba_dw780int __P((int));
+static void ubaerror __P((struct uba_softc *, int *, int *));
+#ifdef notyet
+static void dw780_purge __P((struct uba_softc *, int));
+#endif
+
+struct cfattach uba_sbi_ca = {
+ sizeof(struct uba_vsoftc), dw780_match, dw780_attach
+};
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+volatile int svec;
+
+int
+dw780_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct sbi_attach_args *sa = (struct sbi_attach_args *)aux;
+
+ if ((cf->cf_loc[0] != sa->nexnum) && (cf->cf_loc[0] > -1 ))
+ return 0;
+ /*
+ * The uba type is actually only telling where the uba
+ * space is in nexus space.
+ */
+ if ((sa->type & ~3) != NEX_UBA0)
+ return 0;
+
+ return 1;
+}
+
+void
+dw780_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct uba_vsoftc *sc = (void *)self;
+ struct sbi_attach_args *sa = aux;
+ int ubaddr = sa->type & 3;
+ int i;
+
+ printf(": DW780\n");
+ /*
+ * Fill in bus specific data.
+ */
+ sc->uv_sc.uh_ubainit = dw780_init;
+#ifdef notyet
+ sc->uv_sc.uh_ubapurge = dw780_purge;
+#endif
+ sc->uv_sc.uh_beforescan = dw780_beforescan;
+ sc->uv_sc.uh_afterscan = dw780_afterscan;
+ sc->uv_sc.uh_errchk = dw780_errchk;
+ sc->uv_sc.uh_iot = &vax_mem_bus_space;
+ sc->uv_sc.uh_dmat = &sc->uv_dmat;
+ sc->uv_uba = (void *)sa->nexaddr;
+ sc->uh_ibase = VAX_NBPG + ubaddr * VAX_NBPG;
+
+ /*
+ * Set up dispatch vectors for DW780.
+ */
+ for (i = 0; i < 4; i++)
+ scb_vecalloc(256 + i * 64 + sa->nexnum * 4, uba_dw780int,
+ sc->uv_sc.uh_dev.dv_unit, SCB_ISTACK);
+ /*
+ * Fill in variables used by the sgmap system.
+ */
+ sc->uv_size = UBASIZE; /* Size in bytes of Qbus space */
+ sc->uv_addr = (paddr_t)sc->uv_uba->uba_map;
+
+ uba_dma_init(sc);
+ uba_attach(&sc->uv_sc, (parent->dv_unit ? UMEMB8600(ubaddr) :
+ UMEMA8600(ubaddr)) + (UBAPAGES * VAX_NBPG));
+}
+
+void
+dw780_beforescan(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+ volatile int *hej = &vc->uv_uba->uba_sr;
+
+ *hej = *hej;
+ vc->uv_uba->uba_cr = UBACR_IFS|UBACR_BRIE;
+}
+
+void
+dw780_afterscan(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+
+ vc->uv_uba->uba_cr = UBACR_IFS | UBACR_BRIE |
+ UBACR_USEFIE | UBACR_SUEFIE |
+ (vc->uv_uba->uba_cr & 0x7c000000);
+}
+
+
+int
+dw780_errchk(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+ volatile int *hej = &vc->uv_uba->uba_sr;
+
+ if (*hej) {
+ *hej = *hej;
+ return 1;
+ }
+ return 0;
+}
+
+void
+uba_dw780int(uba)
+ int uba;
+{
+ int br, vec, arg;
+ struct uba_vsoftc *vc = uba_cd.cd_devs[uba];
+ struct uba_regs *ur = vc->uv_uba;
+ void (*func) __P((int));
+
+ br = mfpr(PR_IPL);
+ vec = ur->uba_brrvr[br - 0x14];
+ if (vec <= 0) {
+ ubaerror(&vc->uv_sc, &br, (int *)&vec);
+ if (svec == 0)
+ return;
+ }
+ if (cold)
+ scb_fake(vec + vc->uh_ibase, br);
+ else {
+ struct ivec_dsp *scb_vec = (struct ivec_dsp *)((int)scb + 512);
+ func = scb_vec[vec/4].hoppaddr;
+ arg = scb_vec[vec/4].pushlarg;
+ (*func)(arg);
+ }
+}
+
+void
+dw780_init(sc)
+ struct uba_softc *sc;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+
+ vc->uv_uba->uba_cr = UBACR_ADINIT;
+ vc->uv_uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE;
+ while ((vc->uv_uba->uba_cnfgr & UBACNFGR_UBIC) == 0)
+ ;
+}
+
+#ifdef notyet
+void
+dw780_purge(sc, bdp)
+ struct uba_softc *sc;
+ int bdp;
+{
+ struct uba_vsoftc *vc = (void *)sc;
+
+ vc->uv_uba->uba_dpr[bdp] |= UBADPR_BNE;
+}
+#endif
+
+int ubawedgecnt = 10;
+int ubacrazy = 500;
+int zvcnt_max = 5000; /* in 8 sec */
+int ubaerrcnt;
+/*
+ * This routine is called by the locore code to process a UBA
+ * error on an 11/780 or 8600. The arguments are passed
+ * on the stack, and value-result (through some trickery).
+ * In particular, the uvec argument is used for further
+ * uba processing so the result aspect of it is very important.
+ * It must not be declared register.
+ */
+/*ARGSUSED*/
+void
+ubaerror(uh, ipl, uvec)
+ register struct uba_softc *uh;
+ int *ipl, *uvec;
+{
+ struct uba_vsoftc *vc = (void *)uh;
+ struct uba_regs *uba = vc->uv_uba;
+ register int sr, s;
+
+ if (*uvec == 0) {
+ /*
+ * Declare dt as unsigned so that negative values
+ * are handled as >8 below, in case time was set back.
+ */
+ u_long dt = time.tv_sec - vc->uh_zvtime;
+
+ vc->uh_zvtotal++;
+ if (dt > 8) {
+ vc->uh_zvtime = time.tv_sec;
+ vc->uh_zvcnt = 0;
+ }
+ if (++vc->uh_zvcnt > zvcnt_max) {
+ printf("%s: too many zero vectors (%d in <%d sec)\n",
+ vc->uv_sc.uh_dev.dv_xname, vc->uh_zvcnt, (int)dt + 1);
+ printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n",
+ *ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS,
+ uba->uba_cnfgr&0xff);
+ printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n",
+ uba->uba_sr, ubasr_bits, uba->uba_dcr,
+ (uba->uba_dcr&0x8000000)?"":"NOT ");
+ ubareset(vc->uv_sc.uh_dev.dv_unit);
+ }
+ return;
+ }
+ if (uba->uba_cnfgr & NEX_CFGFLT) {
+ printf("%s: sbi fault sr=%b cnfgr=%b\n",
+ vc->uv_sc.uh_dev.dv_xname, uba->uba_sr, ubasr_bits,
+ uba->uba_cnfgr, NEXFLT_BITS);
+ ubareset(vc->uv_sc.uh_dev.dv_unit);
+ *uvec = 0;
+ return;
+ }
+ sr = uba->uba_sr;
+ s = splimp();
+ printf("%s: uba error sr=%b fmer=%x fubar=%o\n", vc->uv_sc.uh_dev.dv_xname,
+ uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar);
+ splx(s);
+ uba->uba_sr = sr;
+ *uvec &= UBABRRVR_DIV;
+ if (++ubaerrcnt % ubawedgecnt == 0) {
+ if (ubaerrcnt > ubacrazy)
+ panic("uba crazy");
+ printf("ERROR LIMIT ");
+ ubareset(vc->uv_sc.uh_dev.dv_unit);
+ *uvec = 0;
+ }
+}
-/* $OpenBSD: ubareg.h,v 1.7 1997/05/29 00:05:10 niklas Exp $ */
-/* $NetBSD: ubareg.h,v 1.9 1996/08/20 13:38:02 ragge Exp $ */
+/* $OpenBSD: ubareg.h,v 1.8 2000/04/27 03:14:51 bjc Exp $ */
+/* $NetBSD: ubareg.h,v 1.10 1998/10/18 18:51:30 ragge Exp $ */
/*-
* Copyright (c) 1982, 1986 The Regents of the University of California.
#define QBA 4 /* 22-bit Q-bus, no adaptor regs: uVAX II */
#endif
-#if 0 /* XXX VAX8200 || VAX8500 || VAX8800 */
-#define DWBUA 5 /* BI UNIBUS adaptor: 8200/8500/8800 */
-#endif
-
/*
* Size of unibus memory address space in pages
* (also number of map registers).
#define UBAIOPAGES 16
#ifndef _LOCORE
-/*
- * DWBUA hardware registers.
- */
-struct dwbua_regs {
- int pad1[456]; /* actually bii regs + pad */
- int bua_csr; /* control and status register */
- int bua_offset; /* vector offset register */
- int bua_fubar; /* failed UNIBUS address register */
- int bua_bifar; /* BI failed address register */
- int bua_udiag[5]; /* micro diagnostics (R/O) */
- int pad2[3];
-/* dpr[0] is for DDP; dpr's 1 through 5 are for BPD's 1 through 5 */
- int bua_dpr[6]; /* data path registers */
- int pad3[10];
- int bua_bdps[20]; /* buffered data path space *//*???*/
- int pad4[8];
- struct pte bua_map[UBAPAGES]; /* unibus map registers */
- int pad5[UBAIOPAGES]; /* no maps for device address space */
-};
-
-#ifdef DWBUA
-/* bua_csr */
-#define BUACSR_ERR 0x80000000 /* composite error */
-#define BUACSR_BIF 0x10000000 /* BI failure */
-#define BUACSR_SSYNTO 0x08000000 /* slave sync timeout */
-#define BUACSR_UIE 0x04000000 /* unibus interlock error */
-#define BUACSR_IVMR 0x02000000 /* invalid map register */
-#define BUACSR_BADBDP 0x01000000 /* bad BDP select */
-#define BUACSR_BUAEIE 0x00100000 /* bua error interrupt enable (?) */
-#define BUACSR_UPI 0x00020000 /* unibus power init */
-#define BUACSR_UREGDUMP 0x00010000 /* microdiag register dump */
-#define BUACSR_IERRNO 0x000000ff /* mask for internal errror number */
-
-/* bua_offset */
-#define BUAOFFSET_MASK 0x00003e00 /* hence max offset = 15872 */
-
-/* bua_dpr */
-#define BUADPR_DPSEL 0x00e00000 /* data path select (?) */
-#define BUADPR_PURGE 0x00000001 /* purge bdp */
-
-/* bua_map -- in particular, those bits that are not in DW780s & DW750s */
-#define BUAMR_IOADR 0x40000000 /* I/O address space */
-#define BUAMR_LAE 0x04000000 /* longword access enable */
- /* I see no reason to use either one, though ... act 6 Aug 1987 */
-
-#define UBA_PURGEBUA(uba, bdp) \
- (((struct dwbua_regs *)(uba))->bua_dpr[bdp] |= BUADPR_PURGE)
-#else
-#define UBA_PURGEBUA(uba, bdp)
-#endif
-
/*
* DW780/DW750 hardware registers
*/
-/* $OpenBSD: ubavar.h,v 1.7 1997/05/29 00:05:10 niklas Exp $ */
-/* $NetBSD: ubavar.h,v 1.18 1996/08/20 13:38:04 ragge Exp $ */
+/* $OpenBSD: ubavar.h,v 1.8 2000/04/27 03:14:52 bjc Exp $ */
+/* $NetBSD: ubavar.h,v 1.21 1999/01/19 21:04:48 ragge Exp $ */
/*
* Copyright (c) 1982, 1986 Regents of the University of California.
void (**uh_reset) __P((int));/* UBA reset function array */
int *uh_resarg; /* array of ubareset args */
int uh_resno; /* Number of devices to reset */
- struct ivec_dsp *uh_idsp; /* Interrupt dispatch area */
- u_int *uh_iarea; /* Interrupt vector array */
short uh_mrwant; /* someone is waiting for map reg */
short uh_bdpwant; /* someone awaits bdp's */
int uh_bdpfree; /* free bdp's */
void (*uh_afterscan) __P((struct uba_softc *));
void (*uh_ubainit) __P((struct uba_softc *));
void (*uh_ubapurge) __P((struct uba_softc *, int));
-#ifdef DW780
- struct ivec_dsp uh_dw780; /* Interrupt handles for DW780 */
-#endif
short uh_nr; /* Unibus sequential number */
short uh_nbdp; /* # of BDP's */
+ int uh_ibase; /* Base address for vectors */
};
#define UAMSIZ 100
-/* given a pointer to uba_regs, find DWBUA registers */
-/* this should be replaced with a union in uba_softc */
-#define BUA(uba) ((struct dwbua_regs *)(uba))
-
/*
* Per-controller structure.
* The unit struct is common to both the adapter and the controller
#define ubago(ui) ubaqueue(ui)
#define b_forw b_hash.le_next /* Nice to have when handling uba queues */
-extern struct cfdriver uba_cd;
-
-void ubasetvec __P((struct device *, int, void (*) __P((int))));
+void uba_attach __P((struct uba_softc *, unsigned long));
int uballoc __P((struct uba_softc *, caddr_t, int, int));
void ubarelse __P((struct uba_softc *, int *));
int ubaqueue __P((struct uba_unit *, struct buf *));
void ubadone __P((struct uba_unit *));
void ubareset __P((int));
+int ubasetup __P((struct uba_softc *, struct buf *, int));
#endif /* _KERNEL */
#endif !_LOCORE
+++ /dev/null
-/* $OpenBSD: udareg.h,v 1.3 1997/05/29 00:05:11 niklas Exp $ */
-/* $NetBSD: udareg.h,v 1.3 1996/07/01 21:24:50 ragge Exp $ */
-
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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.
- *
- * @(#)udareg.h 7.3 (Berkeley) 5/8/91
- */
-
-/*
- * UDA50 registers and structures
- */
-
-/*
- * Writing any value to udaip starts initialisation. Reading from it
- * when the UDA is running makes the UDA look through the command ring
- * to find any new commands. Reading udasa gives status; writing it
- * during initialisation sets things up.
- */
-struct udadevice {
- u_short udaip; /* initialisation and polling */
- u_short udasa; /* status and address */
-};
-
-/*
- * Bits in UDA status register after initialisation
- */
-#define UDA_GO 0x0001 /* run */
-
-#define UDASR_BITS \
-"\20\20ERR\17STEP4\16STEP3\15STEP2\14STEP1\13NV\12QB\11DI\10IE\1GO"
-