summaryrefslogtreecommitdiff
path: root/chips
diff options
context:
space:
mode:
authorThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
committerThomas Bushnell <thomas@gnu.org>1997-02-25 21:28:37 +0000
commitf07a4c844da9f0ecae5bbee1ab94be56505f26f7 (patch)
tree12b07c7e578fc1a5f53dbfde2632408491ff2a70 /chips
Initial source
Diffstat (limited to 'chips')
-rw-r--r--chips/atm.c302
-rw-r--r--chips/atmreg.h89
-rw-r--r--chips/audio.c733
-rw-r--r--chips/audio_config.h130
-rw-r--r--chips/audio_defs.h129
-rw-r--r--chips/bt431.c239
-rw-r--r--chips/bt431.h78
-rw-r--r--chips/bt455.c222
-rw-r--r--chips/bt455.h43
-rw-r--r--chips/bt459.c384
-rw-r--r--chips/bt459.h82
-rw-r--r--chips/bt478.c243
-rw-r--r--chips/bt478.h44
-rw-r--r--chips/build_font.c132
-rw-r--r--chips/busses.c230
-rw-r--r--chips/busses.h154
-rw-r--r--chips/cfb_hdw.c188
-rw-r--r--chips/cfb_misc.c249
-rw-r--r--chips/dc503.c189
-rw-r--r--chips/dc503.h69
-rw-r--r--chips/dtop.h241
-rw-r--r--chips/dtop_handlers.c441
-rw-r--r--chips/dtop_hdw.c644
-rw-r--r--chips/dz_7085.h153
-rw-r--r--chips/dz_defs.h65
-rw-r--r--chips/dz_hdw.c649
-rw-r--r--chips/eccreg.h110
-rw-r--r--chips/fb_hdw.c219
-rw-r--r--chips/fb_misc.c242
-rw-r--r--chips/fdc_82077.h525
-rw-r--r--chips/fdc_82077_hdw.c821
-rw-r--r--chips/frc.c150
-rw-r--r--chips/ims332.c312
-rw-r--r--chips/ims332.h137
-rw-r--r--chips/isdn_79c30.h165
-rw-r--r--chips/isdn_79c30_hdw.c602
-rw-r--r--chips/kernel_font.c3083
-rw-r--r--chips/kernel_font.data3108
-rw-r--r--chips/lance.c1570
-rw-r--r--chips/lance.h284
-rw-r--r--chips/lance_mapped.c417
-rw-r--r--chips/lk201.c695
-rw-r--r--chips/lk201.h241
-rw-r--r--chips/mc_clock.c516
-rw-r--r--chips/mc_clock.h147
-rw-r--r--chips/mouse.c321
-rw-r--r--chips/nc.c851
-rw-r--r--chips/nc.h232
-rw-r--r--chips/nw.h494
-rw-r--r--chips/nw_mk.c1323
-rw-r--r--chips/nw_mk.h97
-rw-r--r--chips/pm_defs.h57
-rw-r--r--chips/pm_hdw.c201
-rw-r--r--chips/pm_misc.c594
-rw-r--r--chips/scc_8530.h355
-rw-r--r--chips/scc_8530_hdw.c1145
-rw-r--r--chips/screen.c1103
-rw-r--r--chips/screen.h289
-rw-r--r--chips/screen_defs.h97
-rw-r--r--chips/screen_switch.c154
-rw-r--r--chips/screen_switch.h85
-rw-r--r--chips/serial_console.c694
-rw-r--r--chips/serial_defs.h53
-rw-r--r--chips/sfb_hdw.c253
-rw-r--r--chips/sfb_misc.c133
-rw-r--r--chips/spans.c114
-rw-r--r--chips/spans.h58
-rw-r--r--chips/tca100.c360
-rw-r--r--chips/tca100.h200
-rw-r--r--chips/tca100_if.c1377
-rw-r--r--chips/tca100_if.h89
-rw-r--r--chips/vs42x_rb.h267
-rw-r--r--chips/xcfb_hdw.c230
-rw-r--r--chips/xcfb_misc.c246
-rw-r--r--chips/xcfb_monitor.h56
75 files changed, 30994 insertions, 0 deletions
diff --git a/chips/atm.c b/chips/atm.c
new file mode 100644
index 00000000..165cd233
--- /dev/null
+++ b/chips/atm.c
@@ -0,0 +1,302 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <atm.h>
+
+#if NATM > 0
+
+#include <vm/vm_kern.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <kern/time_out.h> /* ? maybe */
+#include <device/errno.h>
+#include <device/io_req.h>
+#include <device/net_status.h>
+
+#include <chips/busses.h>
+#include <chips/atmreg.h>
+
+#include <kern/eventcount.h>
+
+#include <mips/mips_cpu.h>
+
+
+struct bus_device *atm_info[NATM];
+int atm_probe();
+static void atm_attach();
+
+struct bus_driver atm_driver =
+ { atm_probe, 0, atm_attach, 0, /* csr */ 0, "atm", atm_info,
+ "", 0, /* flags */ 0 }; /* ENABLED BUS INTR? */
+
+/* XX "", 0, BUS_INTR_DISABLED}; */
+
+typedef struct atm_softc {
+ struct atm_device *atm_dev;
+ struct evc atm_eventcounter;
+ mapped_atm_info_t atm_mapped_info;
+} atm_softc_t;
+
+
+natural_t atm_nintrs = 0;
+
+atm_softc_t atm_softc[NATM];
+
+atm_probe(reg, ui)
+ vm_offset_t reg;
+ register struct bus_device *ui;
+{
+ register atm_softc_t *atm;
+ mapped_atm_info_t info; /* info struct to hand to users */
+ vm_offset_t addr;
+ int unit = ui->unit;
+
+ if (check_memory(reg, 0)) {
+ return 0;
+ }
+
+ atm_info[unit] = ui;
+ atm = &atm_softc[unit];
+ atm->atm_dev = (struct atm_device *) reg; /* k1 address */
+
+ evc_init(&atm->atm_eventcounter);
+
+printf("evc_init of atm: event counter id is %d\n", atm->atm_eventcounter.ev_id);
+
+ /* initialize the interface to deliver. No interrupts by default */
+ atm->atm_dev->sreg = 0;
+ atm->atm_dev->creg = (CR_RX_RESET | CR_TX_RESET);
+ atm->atm_dev->creg = 0;
+ atm->atm_dev->creg_set = (CR_RX_ENABLE | CR_TX_ENABLE);
+#ifdef notdef
+ atm->atm_dev->rxthresh = 0;
+ atm->atm_dev->rxtimerv = 0;
+ atm->atm_dev->creg_s = RX_EOM_INTR; /* enable interrupt on end of message */
+#endif
+
+ /*
+ * Grab a page to be mapped later to users
+ */
+ (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE); /* kseg2 */
+ bzero(addr, PAGE_SIZE);
+ addr = pmap_extract(pmap_kernel(), addr); /* phys */
+ info = (mapped_atm_info_t) PHYS_TO_K0SEG(addr);
+ atm->atm_mapped_info = info;
+
+ /*
+ * Set some permanent info
+ */
+ info->hello_world = 0xdeadbeef;
+ info->interrupt_count = 0;
+ info->wait_event = atm->atm_eventcounter.ev_id;
+ info->saved_status_reg = 0;
+
+ return 1;
+}
+
+static void
+atm_attach(ui)
+register struct bus_device *ui;
+{
+}
+
+int atm_disable_interrupts_after_each = 1;
+
+
+#define ATM_INTERRUPTS (RX_COUNT_INTR | RX_EOM_INTR | RX_TIME_INTR)
+
+atm_intr(unit, spllevel)
+int unit;
+int spllevel;
+{
+ register struct atm_softc *atm = &atm_softc[unit];
+ struct atm_device *atm_dev = atm->atm_dev;
+ unsigned int intr;
+
+ if (atm_dev == 0) {
+ printf("atm: stray interrupt\n");
+ return;
+ }
+
+ /* Acknowledge interrupt request */
+ intr = ATM_READ_REG(atm_dev->sreg);
+ atm_dev->sreg = ~(intr & ATM_INTERRUPTS);
+
+ /* clear the reason for the interrupt */
+ if (atm_disable_interrupts_after_each)
+ atm_dev->creg &= ~intr;
+
+ splx(spllevel); /* drop priority now */
+
+ atm_intr_occurred();
+
+
+ /* Pass status info up to user */
+ if (atm->atm_mapped_info) {
+ atm->atm_mapped_info->interrupt_count++;
+ atm->atm_mapped_info->saved_status_reg = intr;
+ }
+
+ /* Awake user thread */
+
+ evc_signal(&atm->atm_eventcounter);
+
+ /* NOTE: INTERRUPTS ARE DISABLED. */
+}
+
+atm_intr_occurred()
+{
+ atm_nintrs++;
+}
+
+
+atm_output(dev, ior)
+int dev;
+io_req_t ior;
+{
+}
+
+atm_start(unit)
+int unit;
+{
+}
+
+atm_open(dev, flag, ior)
+ int dev;
+ int flag;
+ io_req_t ior;
+{
+ register int unit = dev;
+ register atm_softc_t *atm = &atm_softc[unit];
+
+ if (unit >= NATM)
+ return EINVAL;
+ if (!atm->atm_dev)
+ return ENXIO;
+
+ return KERN_SUCCESS;
+}
+
+atm_close(dev, flag)
+int dev;
+{
+}
+
+atm_read(dev, ior)
+int dev;
+io_req_t ior;
+{
+}
+
+atm_write(dev, ior)
+int dev;
+io_req_t ior;
+{
+}
+
+atm_get_status(dev, flavor, status, status_count)
+ int dev;
+ int flavor;
+ dev_status_t status; /* pointer to OUT array */
+ natural_t *status_count; /* out */
+{
+ switch (flavor) {
+ case NET_STATUS:
+ {
+ register struct net_status *ns = (struct net_status *)status;
+
+ ns->min_packet_size = sizeof(struct sar_data);
+ ns->max_packet_size = sizeof(struct sar_data);
+ ns->header_format = 999; /* XX */
+ ns->header_size = sizeof(int); /* XX */
+ ns->address_size = 0;
+ ns->flags = 0;
+ ns->mapped_size = sizeof(struct atm_device) + PAGE_SIZE;
+ *status_count = NET_STATUS_COUNT;
+ break;
+ }
+ case NET_ADDRESS:
+ /* This would be a good place for it */
+ default:
+ return (D_INVALID_OPERATION);
+ }
+ return (D_SUCCESS);
+}
+
+atm_set_status(dev, flavor, status, status_count)
+ int dev;
+ int flavor;
+ dev_status_t status;
+ natural_t status_count;
+{
+}
+
+atm_mmap(dev, off, prot)
+ int dev;
+ vm_offset_t off;
+ int prot;
+{
+ int unit = dev;
+ vm_offset_t addr;
+
+ /*
+ * Layout of mapped area is:
+ * 000 -- FA_END: DEVICE
+ * FA_END -- FA_END + PAGE_SIZE: SHARED STATE
+ */
+ if (off < sizeof(struct atm_device)) {
+ addr = K1SEG_TO_PHYS((vm_offset_t)(atm_softc[unit].atm_dev)) + off;
+ } else if (off < sizeof(struct atm_device) + PAGE_SIZE) {
+ addr = K0SEG_TO_PHYS(atm_softc[unit].atm_mapped_info);
+ } else return -1;
+ return mips_btop(addr);
+}
+
+atm_setinput(dev, receive_port, priority, filter, filter_count)
+ int dev;
+ ipc_port_t receive_port;
+ int priority;
+ /*filter_t *filter;*/
+ natural_t filter_count;
+{
+}
+
+atm_restart(ifp)
+/* register struct ifnet *ifp; */
+{
+}
+
+atm_portdeath(dev, port)
+ int dev;
+ mach_port_t port;
+{
+}
+
+#endif NATM > 0
+
+
+
+
+
diff --git a/chips/atmreg.h b/chips/atmreg.h
new file mode 100644
index 00000000..a8957837
--- /dev/null
+++ b/chips/atmreg.h
@@ -0,0 +1,89 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** FORE TCA-100 Turbochannel ATM computer interface ***/
+
+#define RX_COUNT_INTR 0x0001
+#define RX_EOM_INTR 0x0002
+#define RX_TIME_INTR 0x0004
+#define TX_COUNT_INTR 0x0008
+#define RX_CELL_LOST 0x0010
+#define RX_NO_CARRIER 0x0020
+#define CR_RX_ENABLE 0x0040
+#define CR_TX_ENABLE 0x0080
+#define CR_RX_RESET 0x0100
+#define CR_TX_RESET 0x0200
+
+#define ATM_READ_REG(reg) ((reg) & 0x3ff) /* 10 bit register mask */
+
+
+struct atm_device {
+ unsigned int prom[64 * 1024 / 4];
+ volatile unsigned int sreg;
+ volatile unsigned int creg_set;
+ volatile unsigned int creg_clr;
+ volatile unsigned int creg;
+ volatile unsigned int rxtimer;
+ unsigned int pad1;
+ volatile unsigned int rxtimerv;
+ unsigned int pad2;
+ volatile unsigned int rxcount;
+ unsigned int pad3;
+ volatile unsigned int rxthresh;
+ unsigned int pad4;
+ volatile unsigned int txcount;
+ unsigned int pad5;
+ volatile unsigned int txthresh;
+ unsigned int pad6[64*1024/4 - 15];
+ volatile unsigned int rxfifo[14];
+ unsigned int pad7[64*1024/4 - 14];
+ volatile unsigned int txfifo[14];
+ unsigned int pad8[64*1024/4 - 14];
+};
+/* MUST BE PAGE ALIGNED OR YOU WILL GET KILLED BELOW WITH ATM_INFO */
+
+struct sar_data {
+ int header;
+ int payload[12];
+ int trailer;
+};
+
+
+/*
+ * Information for mapped atm device
+ */
+typedef struct mapped_atm_info {
+ volatile unsigned int interrupt_count; /* tot interrupts received */
+ volatile unsigned short saved_status_reg; /* copy of status reg from last interrupt */
+ unsigned int hello_world;
+ unsigned wait_event;
+} *mapped_atm_info_t;
+
+
+
+#define ATM_DEVICE(p) (struct atm_device*)(p)
+#define ATM_INFO(p) (mapped_atm_info_t)( (p) + sizeof(struct atm_device) )
+
diff --git a/chips/audio.c b/chips/audio.c
new file mode 100644
index 00000000..00bf2be9
--- /dev/null
+++ b/chips/audio.c
@@ -0,0 +1,733 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*-
+ * Copyright (c) 1991, 1992 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 Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. The name of the Laboratory may not 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 <audio.h>
+#if NAUDIO > 0
+
+#include <mach_kdb.h>
+#include <platforms.h>
+
+#include <mach/std_types.h>
+#include <machine/machspl.h>
+#include <kern/kalloc.h>
+#include <kern/sched_prim.h>
+#include <chips/busses.h>
+
+#include <device/device_types.h>
+#include <device/io_req.h>
+#include <device/ds_routines.h>
+#include <device/audio_status.h> /* user interface */
+#include <chips/audio_defs.h> /* chip interface */
+#include <chips/audio_config.h> /* machdep config */
+
+#define private static
+
+/*
+ * Exported functions and data structures
+ * [see header file for listing]
+ */
+int audio_blocksize = DEFBLKSIZE; /* patchable */
+int audio_backlog = 400; /* 50ms in samples */
+
+/*
+ * Software state, per AMD79C30 audio chip.
+ */
+private
+struct audio_softc {
+ void *hw; /* chip status */
+ audio_switch_t *ops; /* chip operations */
+ au_io_t *sc_au; /* recv and xmit buffers, etc */
+
+
+ unsigned int sc_wseek; /* timestamp of last frame written */
+ unsigned int sc_rseek; /* timestamp of last frame read */
+#if 0
+ struct selinfo sc_wsel; /* write selector */
+ struct selinfo sc_rsel; /* read selector */
+#endif
+
+} audio_softc_data[NAUDIO];
+
+#define unit_to_softc(u) &audio_softc_data[u]
+
+
+/* forward declarations */
+private int audio_sleep (au_cb_t *cb, int thresh);
+private void audio_swintr (struct audio_softc *sc);
+
+/*
+ * Audio chip found.
+ */
+void
+audio_attach(
+ void *hw, /* IN, chip status */
+ audio_switch_t *ops,
+ void **audio_status) /* OUT, audio status */
+{
+ register struct audio_softc *sc;
+ static int next = 0;
+
+ if (next >= NAUDIO)
+ panic("Please configure more than %d audio devices\n", NAUDIO);
+ sc = &audio_softc_data[next++];
+
+ printf(" audio");
+
+ sc->hw = hw;
+ sc->ops = ops;
+
+ *audio_status = (void *)sc;
+}
+
+
+private int audio_setinfo (struct audio_softc *, audio_info_t *);
+private int audio_getinfo (struct audio_softc *, audio_info_t *);
+
+io_return_t
+audio_open(
+ int unit,
+ int mode,
+ io_req_t req)
+{
+ register struct audio_softc *sc;
+ register au_io_t *au;
+
+ sc = unit_to_softc(unit);
+ if (unit > NAUDIO || (!sc->hw))
+ return (D_NO_SUCH_DEVICE);
+
+ if (!sc->sc_au) {
+ sc->sc_au = (au_io_t *) kalloc(sizeof(au_io_t));
+ bzero(sc->sc_au, sizeof(au_io_t));
+ }
+ au = sc->sc_au;
+
+ au->au_lowat = audio_blocksize;
+ au->au_hiwat = AUCB_SIZE - au->au_lowat;
+ au->au_blksize = audio_blocksize;
+ au->au_backlog = audio_backlog;
+
+ /* set up read and write blocks and `dead sound' zero value. */
+ AUCB_INIT(&au->au_rb);
+ au->au_rb.cb_thresh = AUCB_SIZE;
+ AUCB_INIT(&au->au_wb);
+ au->au_wb.cb_thresh = -1;
+
+ /* nothing read or written yet */
+ sc->sc_rseek = 0;
+ sc->sc_wseek = 0;
+
+ (*sc->ops->init)(sc->hw);
+
+ return (0);
+}
+
+private int
+audio_drain(
+ register au_io_t *au)
+{
+ register int error;
+
+ while (!AUCB_EMPTY(&au->au_wb))
+ if ((error = audio_sleep(&au->au_wb, 0)) != 0)
+ return (error);
+ return (0);
+}
+
+/*
+ * Close an audio chip.
+ */
+/* ARGSUSED */
+io_return_t
+audio_close(
+ int unit)
+{
+ register struct audio_softc *sc = unit_to_softc(unit);
+ register au_cb_t *cb;
+ register spl_t s;
+
+ /*
+ * Block until output drains, but allow ^C interrupt.
+ */
+ sc->sc_au->au_lowat = 0; /* avoid excessive wakeups */
+
+ /*
+ * If there is pending output, let it drain (unless
+ * the output is paused).
+ */
+ cb = &sc->sc_au->au_wb;
+ s = splaudio();
+ if (!AUCB_EMPTY(cb) && !cb->cb_pause)
+ (void)audio_drain(sc->sc_au);
+ /*
+ * Disable interrupts, and done.
+ */
+ (*sc->ops->close)(sc->hw);
+ splx(s);
+ return (D_SUCCESS);
+}
+
+private int
+audio_sleep(
+ register au_cb_t *cb,
+ register int thresh)
+{
+ register spl_t s = splaudio();
+
+ cb->cb_thresh = thresh;
+ assert_wait((event_t)cb, TRUE);
+ splx(s);
+ thread_block((void (*)()) 0);
+ return (0); /* XXXX */
+}
+
+io_return_t
+audio_read(
+ int unit,
+ io_req_t ior)
+{
+ register struct audio_softc *sc = unit_to_softc(unit);
+ register au_cb_t *cb;
+ register int n, head, taildata;
+ register int blocksize = sc->sc_au->au_blksize;
+ io_return_t rc;
+ unsigned char *data;
+
+ /*
+ * Allocate read buffer
+ */
+ rc = device_read_alloc(ior, (vm_size_t)ior->io_count);
+ if (rc != KERN_SUCCESS)
+ return rc;
+ data = (unsigned char *) ior->io_data;
+ ior->io_residual = ior->io_count;
+
+ cb = &sc->sc_au->au_rb;
+ cb->cb_drops = 0;
+ sc->sc_rseek = sc->sc_au->au_stamp - AUCB_LEN(cb);
+ do {
+ while (AUCB_LEN(cb) < blocksize) {
+
+ if (ior->io_mode & D_NODELAY)
+ return (D_WOULD_BLOCK);
+
+ if ((rc = audio_sleep(cb, blocksize)) != 0)
+ return(rc);
+ }
+ /*
+ * The space calculation can only err on the short
+ * side if an interrupt occurs during processing:
+ * only cb_tail is altered in the interrupt code.
+ */
+ head = cb->cb_head;
+ if ((n = AUCB_LEN(cb)) > ior->io_residual)
+ n = ior->io_residual;
+ taildata = AUCB_SIZE - head;
+
+ if (n > taildata) {
+ bcopy(cb->cb_data + head, data, taildata);
+ bcopy(cb->cb_data, data + taildata, n - taildata);
+ } else
+ bcopy(cb->cb_data + head, data, n);
+ data += n;
+ ior->io_residual -= n;
+
+ head = AUCB_MOD(head + n);
+ cb->cb_head = head;
+ } while (ior->io_residual >= blocksize);
+
+ return (rc);
+}
+
+io_return_t
+audio_write(
+ int unit,
+ io_req_t ior)
+{
+ register struct audio_softc *sc = unit_to_softc(unit);
+ register au_io_t *au = sc->sc_au;
+ register au_cb_t *cb = &au->au_wb;
+ register int n, tail, tailspace, first, watermark;
+ io_return_t rc;
+ unsigned char *data;
+ vm_offset_t addr = 0;
+
+ if (!(ior->io_op & IO_INBAND)) {
+ /*
+ * Copy out-of-line data into kernel address space.
+ * Since data is copied as page list, it will be
+ * accessible.
+ */
+ vm_map_copy_t copy = (vm_map_copy_t) ior->io_data;
+ kern_return_t kr;
+
+ kr = vm_map_copyout(device_io_map, &addr, copy);
+ if (kr != KERN_SUCCESS)
+ return kr;
+ data = (unsigned char *) addr;
+ } else
+ data = (unsigned char *) ior->io_data;
+ ior->io_residual = ior->io_count;
+
+ rc = D_SUCCESS;
+ first = 1;
+ while (ior->io_residual > 0) {
+ watermark = au->au_hiwat;
+ while (AUCB_LEN(cb) > watermark) {
+
+ if (ior->io_mode & D_NODELAY) {
+ rc = D_WOULD_BLOCK;
+ goto out;
+ }
+
+ if ((rc = audio_sleep(cb, watermark)) != 0)
+ goto out;
+
+ watermark = au->au_lowat;
+ }
+ /*
+ * The only value that can change on an interrupt is
+ * cb->cb_head. We only pull that out once to decide
+ * how much to write into cb_data; if we lose a race
+ * and cb_head changes, we will merely be overly
+ * conservative. For a legitimate time stamp,
+ * however, we need to synchronize the accesses to
+ * au_stamp and cb_head at a high ipl below.
+ */
+ tail = cb->cb_tail;
+ if ((n = (AUCB_SIZE - 1) - AUCB_LEN(cb)) > ior->io_residual) {
+ n = ior->io_residual;
+ if (cb->cb_head == tail &&
+ n <= au->au_blksize &&
+ au->au_stamp - sc->sc_wseek > 400) {
+ /*
+ * the write is 'small', the buffer is empty
+ * and we have been silent for at least 50ms
+ * so we might be dealing with an application
+ * that writes frames synchronously with
+ * reading them. If so, we need an output
+ * backlog to cover scheduling delays or
+ * there will be gaps in the sound output.
+ * Also take this opportunity to reset the
+ * buffer pointers in case we ended up on
+ * a bad boundary (odd byte, blksize bytes
+ * from end, etc.).
+ */
+ register unsigned long *ip;
+ register unsigned long muzero;
+ spl_t s;
+ register int i;
+
+ s = splaudio();
+ cb->cb_head = cb->cb_tail = 0;
+ splx(s);
+
+ tail = au->au_backlog;
+ ip = (unsigned long *)cb->cb_data;
+ muzero = sample_rpt_long(0x7fL);
+ for (i = tail / sizeof muzero; --i >= 0; )
+ *ip++ = muzero;
+ }
+ }
+ tailspace = AUCB_SIZE - tail;
+ if (n > tailspace) {
+ /* write first part at tail and rest at head */
+ bcopy(data, cb->cb_data + tail, tailspace);
+ bcopy(data + tailspace, cb->cb_data,
+ n - tailspace);
+ } else
+ bcopy(data, cb->cb_data + tail, n);
+ data += n;
+ ior->io_residual -= n;
+
+ tail = AUCB_MOD(tail + n);
+ if (first) {
+ register spl_t s = splaudio();
+ sc->sc_wseek = AUCB_LEN(cb) + au->au_stamp + 1;
+ /*
+ * To guarantee that a write is contiguous in the
+ * sample space, we clear the drop count the first
+ * time through. If we later get drops, we will
+ * break out of the loop below, before writing
+ * a new frame.
+ */
+ cb->cb_drops = 0;
+ cb->cb_tail = tail;
+ splx(s);
+ first = 0;
+ } else {
+#if 0
+ if (cb->cb_drops != 0)
+ break;
+#endif
+ cb->cb_tail = tail;
+ }
+ }
+out:
+ if (!(ior->io_op & IO_INBAND))
+ (void) vm_deallocate(device_io_map, addr, ior->io_count);
+ return (rc);
+}
+
+#include <sys/ioctl.h>
+
+io_return_t
+audio_get_status(
+ int unit,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t *status_count)
+{
+ register struct audio_softc *sc = unit_to_softc(unit);
+ register au_io_t *au = sc->sc_au;
+ io_return_t rc = D_SUCCESS;
+ spl_t s;
+
+ switch (flavor) {
+
+ case AUDIO_GETMAP:
+ case AUDIOGETREG:
+ rc = (*sc->ops->getstate)(sc->hw, flavor,
+ (void *)status, status_count);
+ break;
+
+ /*
+ * Number of read samples dropped. We don't know where or
+ * when they were dropped.
+ */
+ case AUDIO_RERROR:
+ *(int *)status = au->au_rb.cb_drops;
+ *status_count = 1;
+ break;
+
+ case AUDIO_WERROR:
+ *(int *)status = au->au_wb.cb_drops;
+ *status_count = 1;
+ break;
+
+ /*
+ * How many samples will elapse until mike hears the first
+ * sample of what we last wrote?
+ */
+ case AUDIO_WSEEK:
+ s = splaudio();
+ *(unsigned int *)status = sc->sc_wseek - au->au_stamp
+ + AUCB_LEN(&au->au_rb);
+ splx(s);
+ *status_count = 1;
+ break;
+
+ case AUDIO_GETINFO:
+ rc = audio_getinfo(sc, (audio_info_t *)status);
+ *status_count = sizeof(audio_info_t) / sizeof(int);
+ break;
+
+ default:
+ rc = D_INVALID_OPERATION;
+ break;
+ }
+ return (rc);
+}
+
+io_return_t
+audio_set_status(
+ int unit,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ register struct audio_softc *sc = unit_to_softc(unit);
+ register au_io_t *au = sc->sc_au;
+ io_return_t rc = D_SUCCESS;
+ spl_t s;
+
+ switch (flavor) {
+
+ case AUDIO_SETMAP:
+ case AUDIOSETREG:
+ rc = (*sc->ops->setstate)(sc->hw, flavor,
+ (void *)status, status_count);
+ break;
+
+ case AUDIO_FLUSH:
+ s = splaudio();
+ AUCB_INIT(&au->au_rb);
+ AUCB_INIT(&au->au_wb);
+ au->au_stamp = 0;
+ splx(s);
+ sc->sc_wseek = 0;
+ sc->sc_rseek = 0;
+ break;
+
+ case AUDIO_SETINFO:
+ rc = audio_setinfo(sc, (audio_info_t *)status);
+ break;
+
+ case AUDIO_DRAIN:
+ rc = audio_drain(au);
+ break;
+
+ default:
+ rc = D_INVALID_OPERATION;
+ break;
+ }
+ return (rc);
+}
+
+
+/*
+ * Interrupt routine
+ */
+boolean_t
+audio_hwintr(
+ void *status,
+ unsigned int s_in,
+ unsigned int *s_out)
+{
+ register au_io_t *au = ((struct audio_softc *) status)->sc_au;
+ register au_cb_t *cb;
+ register int h, t, k;
+ register boolean_t wakeit = FALSE;
+
+ ++au->au_stamp;
+
+ /* receive incoming data */
+ cb = &au->au_rb;
+ h = cb->cb_head;
+ t = cb->cb_tail;
+ k = AUCB_MOD(t + 1);
+ if (h == k)
+ cb->cb_drops++;
+ else if (cb->cb_pause != 0)
+ cb->cb_pdrops++;
+ else {
+ cb->cb_data[t] = s_in;
+ cb->cb_tail = t = k;
+ }
+ if (AUCB_MOD(t - h) >= cb->cb_thresh) {
+ cb->cb_thresh = AUCB_SIZE;
+ cb->cb_waking = 1;
+ wakeit = TRUE;
+ }
+ /* send outgoing data */
+ cb = &au->au_wb;
+ h = cb->cb_head;
+ t = cb->cb_tail;
+ k = 0;
+ if (h == t)
+ cb->cb_drops++;
+ else if (cb->cb_pause != 0)
+ cb->cb_pdrops++;
+ else {
+ cb->cb_head = h = AUCB_MOD(h + 1);
+ *s_out = cb->cb_data[h];
+ k = 1;
+ }
+ if (AUCB_MOD(t - h) <= cb->cb_thresh) {
+ cb->cb_thresh = -1;
+ cb->cb_waking = 1;
+ wakeit = TRUE;
+ }
+ if (wakeit)
+ audio_swintr((struct audio_softc *) status);
+ return (k == 1);
+}
+
+private void
+audio_swintr(
+ register struct audio_softc *sc)
+{
+ register au_io_t *au = sc->sc_au;
+
+ if (au->au_rb.cb_waking != 0) {
+ au->au_rb.cb_waking = 0;
+ wakeup(&au->au_rb);
+ }
+ if (au->au_wb.cb_waking != 0) {
+ au->au_wb.cb_waking = 0;
+ wakeup(&au->au_wb);
+ }
+}
+
+private int
+audio_setinfo(
+ struct audio_softc *sc,
+ audio_info_t *ai)
+{
+ struct audio_prinfo *r = &ai->record, *p = &ai->play;
+ register int bsize;
+ register au_io_t *au = sc->sc_au;
+ spl_t s;
+
+ (*sc->ops->setgains)(sc->hw, p->gain, r->gain, ai->monitor_gain );
+
+ if (p->pause != (unsigned char)~0)
+ au->au_wb.cb_pause = p->pause;
+ if (r->pause != (unsigned char)~0)
+ au->au_rb.cb_pause = r->pause;
+
+ if (p->port != ~0)
+ (*sc->ops->setport)(sc->hw, p->port);
+
+ if (ai->blocksize != ~0) {
+ if (ai->blocksize == 0)
+ bsize = ai->blocksize = DEFBLKSIZE;
+ else if (ai->blocksize > MAXBLKSIZE)
+ bsize = ai->blocksize = MAXBLKSIZE;
+ else
+ bsize = ai->blocksize;
+
+ s = splaudio();
+ au->au_blksize = bsize;
+ /* AUDIO_FLUSH */
+ AUCB_INIT(&au->au_rb);
+ AUCB_INIT(&au->au_wb);
+ splx(s);
+
+ }
+ if (ai->hiwat != ~0 && (unsigned)ai->hiwat < AUCB_SIZE)
+ au->au_hiwat = ai->hiwat;
+ if (ai->lowat != ~0 && ai->lowat < AUCB_SIZE)
+ au->au_lowat = ai->lowat;
+ if (ai->backlog != ~0 && ai->backlog < (AUCB_SIZE/2))
+ au->au_backlog = ai->backlog;
+
+ return (0);
+}
+
+private int
+audio_getinfo(
+ struct audio_softc *sc,
+ audio_info_t *ai)
+{
+ struct audio_prinfo *r = &ai->record, *p = &ai->play;
+ register au_io_t *au = sc->sc_au;
+
+ p->sample_rate = r->sample_rate = 8000;
+ p->channels = r->channels = 1;
+ p->precision = r->precision = 8;
+ p->encoding = r->encoding = AUDIO_ENCODING_ULAW;
+
+ (*sc->ops->getgains)(sc->hw, &p->gain, &r->gain, &ai->monitor_gain );
+
+ r->port = AUDIO_MIKE;
+ p->port = (*sc->ops->getport)(sc->hw);
+
+ p->pause = au->au_wb.cb_pause;
+ r->pause = au->au_rb.cb_pause;
+ p->error = au->au_wb.cb_drops != 0;
+ r->error = au->au_rb.cb_drops != 0;
+
+ /* Now this is funny. If you got here it means you must have
+ opened the device, so how could it possibly be closed ?
+ Unless we upgrade the berkeley code to check if the chip
+ is currently playing and/or recording... Later. */
+ p->open = TRUE;
+ r->open = TRUE;
+
+ p->samples = au->au_stamp - au->au_wb.cb_pdrops;
+ r->samples = au->au_stamp - au->au_rb.cb_pdrops;
+
+ p->seek = sc->sc_wseek;
+ r->seek = sc->sc_rseek;
+
+ ai->blocksize = au->au_blksize;
+ ai->hiwat = au->au_hiwat;
+ ai->lowat = au->au_lowat;
+ ai->backlog = au->au_backlog;
+
+ return (0);
+}
+
+#if MACH_KDB
+#include <ddb/db_output.h>
+
+void audio_queue_status( au_cb_t *cb, char *logo)
+{
+ db_printf("%s ring status:\n", logo);
+ db_printf(" h %x t %x sh %x w %d p %d d %x pd %x\n",
+ cb->cb_head, cb->cb_tail, cb->cb_thresh,
+ cb->cb_waking, cb->cb_pause, (long)cb->cb_drops,
+ (long)cb->cb_pdrops);
+}
+
+int audio_status(int unit)
+{
+ struct audio_softc *sc = unit_to_softc(unit);
+ au_io_t *au;
+
+ if (!sc) {
+ db_printf("No such thing\n");
+ return 0;
+ }
+ db_printf("@%lx: wseek %d rseek %d, au @%lx\n",
+ sc, sc->sc_wseek, sc->sc_rseek, sc->sc_au);
+ if (!(au = sc->sc_au)) return 0;
+
+ db_printf("au: stamp %x lo %x hi %x blk %x blg %x\n",
+ au->au_stamp, au->au_lowat, au->au_hiwat,
+ au->au_blksize, au->au_backlog);
+ audio_queue_status(&au->au_rb, "read");
+ audio_queue_status(&au->au_wb, "write");
+
+ return 0;
+}
+#endif /* MACH_KDB */
+
+#endif /* NAUDIO > 0 */
+
diff --git a/chips/audio_config.h b/chips/audio_config.h
new file mode 100644
index 00000000..bd2c0a07
--- /dev/null
+++ b/chips/audio_config.h
@@ -0,0 +1,130 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Here platform specific code to define sample_t & co
+ * [to cope with weird DMA engines], and other customs
+ */
+#ifdef FLAMINGO
+#define splaudio splbio
+#define sample_t unsigned char /* later */
+#define samples_to_chars bcopy
+#define chars_to_samples bcopy
+/* Sparse space ! */
+typedef struct {
+ volatile unsigned long cr; /* command register (wo) */
+/*#define ir cr /* interrupt register (ro) */
+ volatile unsigned long dr; /* data register (rw) */
+ volatile unsigned long dsr1; /* D-channel status register 1 (ro) */
+ volatile unsigned long der; /* D-channel error register (ro) */
+ volatile unsigned long dctb; /* D-channel transmit register (wo) */
+/*#define dcrb dctb /* D-channel receive register (ro) */
+ volatile unsigned long bbtb; /* Bb-channel transmit register (wo) */
+/*#define bbrb bbtb /* Bb-channel receive register (ro) */
+ volatile unsigned long bctb; /* Bc-channel transmit register (wo)*/
+/*#define bcrb bctb /* Bc-channel receive register (ro) */
+ volatile unsigned long dsr2; /* D-channel status register 2 (ro) */
+} amd79c30_padded_regs_t;
+
+/* give the chip 400ns in between accesses */
+#define read_reg(r,v) \
+ { (v) = ((r) >> 8) & 0xff; delay(1); }
+
+#define write_reg(r,v) \
+ { (r) = (((v) & 0xff) << 8) | \
+ 0x200000000L; /*bytemask*/ \
+ delay(1); wbflush(); \
+ }
+
+/* Write 16 bits of data from variable v to the data port of the audio chip */
+#define WAMD16(regs, v) \
+ { write_reg((regs)->dr,v); \
+ write_reg((regs)->dr,v>>8); }
+
+#define mb() wbflush()
+
+#endif /* FLAMINGO */
+
+
+#ifdef MAXINE
+#define splaudio splhigh
+typedef struct {
+ volatile unsigned char cr; /* command register (wo) */
+/*#define ir cr /* interrupt register (ro) */
+ char pad0[63];
+ volatile unsigned char dr; /* data register (rw) */
+ char pad1[63];
+ volatile unsigned char dsr1; /* D-channel status register 1 (ro) */
+ char pad2[63];
+ volatile unsigned char der; /* D-channel error register (ro) */
+ char pad3[63];
+ volatile unsigned char dctb; /* D-channel transmit register (wo) */
+/*#define dcrb dctb /* D-channel receive register (ro) */
+ char pad4[63];
+ volatile unsigned char bbtb; /* Bb-channel transmit register (wo) */
+/*#define bbrb bbtb /* Bb-channel receive register (ro) */
+ char pad5[63];
+ volatile unsigned char bctb; /* Bc-channel transmit register (wo)*/
+/*#define bcrb bctb /* Bc-channel receive register (ro) */
+ char pad6[63];
+ volatile unsigned char dsr2; /* D-channel status register 2 (ro) */
+ char pad7[63];
+} amd79c30_padded_regs_t;
+
+/* give the chip 400ns in between accesses */
+#define read_reg(r,v) \
+ { (v) = (r); delay(1); }
+
+#define write_reg(r,v) \
+ { (r) = (v); delay(1); wbflush(); }
+
+/* Write 16 bits of data from variable v to the data port of the audio chip */
+#define WAMD16(regs, v) \
+ { write_reg((regs)->dr,v); \
+ write_reg((regs)->dr,v>>8); }
+
+#define mb()
+
+#endif /* MAXINE */
+
+
+#ifndef sample_t
+#define sample_t unsigned char
+#define samples_to_chars bcopy
+#define chars_to_samples bcopy
+#endif
+
+/*
+ * More architecture-specific customizations
+ */
+#ifdef alpha
+#define sample_rpt_int(x) (((x)<<24)|((x)<<16)|((x)<<8)|((x)<<0))
+#define sample_rpt_long(x) ((sample_rpt_int(x)<<32)|sample_rpt_int(x))
+#endif
+
+#ifndef sample_rpt_long
+#define sample_rpt_long(x) (((x)<<24)|((x)<<16)|((x)<<8)|((x)<<0))
+#endif
+
diff --git a/chips/audio_defs.h b/chips/audio_defs.h
new file mode 100644
index 00000000..448153e4
--- /dev/null
+++ b/chips/audio_defs.h
@@ -0,0 +1,129 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*-
+ * Copyright (c) 1991, 1992 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 Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. The name of the Laboratory may not 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.
+ */
+
+#define AUCB_SIZE 4096
+#define AUCB_MOD(k) ((k) & (AUCB_SIZE - 1))
+
+#define AUCB_INIT(cb) ((cb)->cb_head = (cb)->cb_tail = (cb)->cb_drops = \
+ (cb)->cb_pdrops = 0)
+
+#define AUCB_EMPTY(cb) ((cb)->cb_head == (cb)->cb_tail)
+#define AUCB_FULL(cb) (AUCB_MOD((cb)->cb_tail + 1) == (cb)->cb_head)
+#define AUCB_LEN(cb) (AUCB_MOD((cb)->cb_tail - (cb)->cb_head))
+
+#define MAXBLKSIZE (AUCB_SIZE / 2)
+#define DEFBLKSIZE 128
+
+#ifndef LOCORE
+
+/*
+ * Our own circular buffers, used if not doing DMA.
+ * [af: with some work we could use the circbuf.c code instead]
+ */
+typedef struct au_cb {
+ int cb_head; /* queue head */
+ int cb_tail; /* queue tail */
+ int cb_thresh; /* threshold for wakeup */
+ unsigned int cb_waking; /* needs wakeup at softint level */
+ unsigned int cb_pause; /* io paused */
+ unsigned int cb_drops; /* missed samples from over/underrun */
+ unsigned int cb_pdrops; /* sun compat -- paused samples */
+ unsigned char cb_data[AUCB_SIZE]; /* data buffer */
+} au_cb_t;
+
+/*
+ * Handle on a bi-directional stream of samples
+ */
+typedef struct au_io {
+ unsigned int au_stamp; /* time stamp */
+ int au_lowat; /* xmit low water mark (for wakeup) */
+ int au_hiwat; /* xmit high water mark (for wakeup) */
+ int au_blksize; /* recv block (chunk) size */
+ int au_backlog; /* # samples of xmit backlog to gen. */
+ struct au_cb au_rb; /* read (recv) buffer */
+ struct au_cb au_wb; /* write (xmit) buffer */
+} au_io_t;
+
+/*
+ * Interface to specific chips
+ */
+typedef struct {
+ void (*init)();
+ void (*close)();
+ void (*setport)();
+ int (*getport)();
+ void (*setgains)();
+ void (*getgains)();
+ io_return_t (*setstate)();
+ io_return_t (*getstate)();
+} audio_switch_t;
+
+/*
+ * Callbacks into audio module, and interface to kernel
+ */
+void audio_attach( void *, audio_switch_t *, void **);
+boolean_t audio_hwintr( void *, unsigned int, unsigned int *);
+
+extern io_return_t audio_open( int, int, io_req_t );
+extern io_return_t audio_close( int );
+extern io_return_t audio_read( int, io_req_t );
+extern io_return_t audio_write( int, io_req_t );
+extern io_return_t audio_get_status( int, dev_flavor_t, dev_status_t, natural_t *);
+extern io_return_t audio_set_status( int, dev_flavor_t, dev_status_t, natural_t);
+
+#endif
diff --git a/chips/bt431.c b/chips/bt431.c
new file mode 100644
index 00000000..0c6368c9
--- /dev/null
+++ b/chips/bt431.c
@@ -0,0 +1,239 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt431.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 8/91
+ *
+ * Routines for the bt431 Cursor
+ */
+
+#include <platforms.h>
+
+#include <chips/bt431.h>
+#include <chips/screen.h>
+
+#ifdef DECSTATION
+/*
+ * This configuration uses two twin 431s
+ */
+#define set_value(x) (((x)<<8)|((x)&0xff))
+#define get_value(x) ((x)&0xff)
+
+typedef struct {
+ volatile unsigned short addr_lo;
+ short pad0;
+ volatile unsigned short addr_hi;
+ short pad1;
+ volatile unsigned short addr_cmap;
+ short pad2;
+ volatile unsigned short addr_reg;
+ short pad3;
+} bt431_padded_regmap_t;
+
+#else /*DECSTATION*/
+
+#define set_value(x) x
+#define get_value(x) x
+typedef bt431_regmap_t bt431_padded_regmap_t;
+#define wbflush()
+
+#endif /*DECSTATION*/
+
+/*
+ * Generic register access
+ */
+void
+bt431_select_reg( regs, regno)
+ bt431_padded_regmap_t *regs;
+{
+ regs->addr_lo = set_value(regno&0xff);
+ regs->addr_hi = set_value((regno >> 8) & 0xff);
+ wbflush();
+}
+
+void
+bt431_write_reg( regs, regno, val)
+ bt431_padded_regmap_t *regs;
+{
+ bt431_select_reg( regs, regno );
+ regs->addr_reg = set_value(val);
+ wbflush();
+}
+
+unsigned char
+bt431_read_reg( regs, regno)
+ bt431_padded_regmap_t *regs;
+{
+ bt431_select_reg( regs, regno );
+ return get_value(regs->addr_reg);
+}
+
+/* when using autoincrement */
+#define bt431_write_reg_autoi( regs, regno, val) \
+ { \
+ (regs)->addr_reg = set_value(val); \
+ wbflush(); \
+ }
+#define bt431_read_reg_autoi( regs, regno) \
+ get_value(((regs)->addr_reg))
+
+#define bt431_write_cmap_autoi( regs, regno, val) \
+ { \
+ (regs)->addr_cmap = (val); \
+ wbflush(); \
+ }
+#define bt431_read_cmap_autoi( regs, regno) \
+ ((regs)->addr_cmap)
+
+
+/*
+ * Cursor ops
+ */
+bt431_cursor_on(regs)
+ bt431_padded_regmap_t *regs;
+{
+ bt431_write_reg( regs, BT431_REG_CMD,
+ BT431_CMD_CURS_ENABLE|BT431_CMD_OR_CURSORS|
+ BT431_CMD_4_1_MUX|BT431_CMD_THICK_1);
+}
+
+bt431_cursor_off(regs)
+ bt431_padded_regmap_t *regs;
+{
+ bt431_write_reg( regs, BT431_REG_CMD, BT431_CMD_4_1_MUX);
+}
+
+bt431_pos_cursor(regs,x,y)
+ bt431_padded_regmap_t *regs;
+ register int x,y;
+{
+#define lo(v) ((v)&0xff)
+#define hi(v) (((v)&0xf00)>>8)
+
+ /*
+ * Cx = x + D + H - P
+ * P = 37 if 1:1, 52 if 4:1, 57 if 5:1
+ * D = pixel skew between outdata and external data
+ * H = pixels between HSYNCH falling and active video
+ *
+ * Cy = y + V - 32
+ * V = scanlines between HSYNCH falling, two or more
+ * clocks after VSYNCH falling, and active video
+ */
+
+ bt431_write_reg( regs, BT431_REG_CXLO, lo(x + 360));
+ /* use autoincr feature */
+ bt431_write_reg_autoi( regs, BT431_REG_CXHI, hi(x + 360));
+ bt431_write_reg_autoi( regs, BT431_REG_CYLO, lo(y + 36));
+ bt431_write_reg_autoi( regs, BT431_REG_CYHI, hi(y + 36));
+}
+
+
+bt431_cursor_sprite( regs, cursor)
+ bt431_padded_regmap_t *regs;
+ register unsigned short *cursor;
+{
+ register int i;
+
+ bt431_select_reg( regs, BT431_REG_CRAM_BASE+0);
+ for (i = 0; i < 512; i++)
+ bt431_write_cmap_autoi( regs, BT431_REG_CRAM_BASE+i, *cursor++);
+}
+
+#if 1
+bt431_print_cursor(regs)
+ bt431_padded_regmap_t *regs;
+{
+ unsigned short curs[512];
+ register int i;
+
+ bt431_select_reg( regs, BT431_REG_CRAM_BASE+0);
+ for (i = 0; i < 512; i++) {
+ curs[i] = bt431_read_cmap_autoi( regs, BT431_REG_CRAM_BASE+i);
+ }
+ for (i = 0; i < 512; i += 16)
+ printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
+ curs[i], curs[i+1], curs[i+2], curs[i+3],
+ curs[i+4], curs[i+5], curs[i+6], curs[i+7],
+ curs[i+8], curs[i+9], curs[i+10], curs[i+11],
+ curs[i+12], curs[i+13], curs[i+14], curs[i+15]);
+}
+
+#endif
+
+/*
+ * Initialization
+ */
+unsigned /*char*/short bt431_default_cursor[64*8] = {
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0xffff, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+};
+
+bt431_init(regs)
+ bt431_padded_regmap_t *regs;
+{
+ register int i;
+
+ /* use 4:1 input mux */
+ bt431_write_reg( regs, BT431_REG_CMD,
+ BT431_CMD_CURS_ENABLE|BT431_CMD_OR_CURSORS|
+ BT431_CMD_4_1_MUX|BT431_CMD_THICK_1);
+
+ /* home cursor */
+ bt431_write_reg_autoi( regs, BT431_REG_CXLO, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_CXHI, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_CYLO, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_CYHI, 0x00);
+
+ /* no crosshair window */
+ bt431_write_reg_autoi( regs, BT431_REG_WXLO, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_WXHI, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_WYLO, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_WYHI, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_WWLO, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_WWHI, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_WHLO, 0x00);
+ bt431_write_reg_autoi( regs, BT431_REG_WHHI, 0x00);
+
+ /* load default cursor */
+ bt431_cursor_sprite( regs, bt431_default_cursor);
+}
diff --git a/chips/bt431.h b/chips/bt431.h
new file mode 100644
index 00000000..d98b08db
--- /dev/null
+++ b/chips/bt431.h
@@ -0,0 +1,78 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt431.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 8/91
+ *
+ * Defines for the bt431 Cursor chip
+ */
+
+
+typedef struct {
+ volatile unsigned char addr_lo;
+ volatile unsigned char addr_hi;
+ volatile unsigned char addr_cmap;
+ volatile unsigned char addr_reg;
+} bt431_regmap_t;
+
+/*
+ * Additional registers addressed indirectly
+ */
+
+#define BT431_REG_CMD 0x0000
+#define BT431_REG_CXLO 0x0001
+#define BT431_REG_CXHI 0x0002
+#define BT431_REG_CYLO 0x0003
+#define BT431_REG_CYHI 0x0004
+#define BT431_REG_WXLO 0x0005
+#define BT431_REG_WXHI 0x0006
+#define BT431_REG_WYLO 0x0007
+#define BT431_REG_WYHI 0x0008
+#define BT431_REG_WWLO 0x0009
+#define BT431_REG_WWHI 0x000a
+#define BT431_REG_WHLO 0x000b
+#define BT431_REG_WHHI 0x000c
+
+#define BT431_REG_CRAM_BASE 0x0000
+#define BT431_REG_CRAM_END 0x01ff
+
+/*
+ * Command register
+ */
+
+#define BT431_CMD_CURS_ENABLE 0x40
+#define BT431_CMD_XHAIR_ENABLE 0x20
+#define BT431_CMD_OR_CURSORS 0x10
+#define BT431_CMD_AND_CURSORS 0x00
+#define BT431_CMD_1_1_MUX 0x00
+#define BT431_CMD_4_1_MUX 0x04
+#define BT431_CMD_5_1_MUX 0x08
+#define BT431_CMD_xxx_MUX 0x0c
+#define BT431_CMD_THICK_1 0x00
+#define BT431_CMD_THICK_3 0x01
+#define BT431_CMD_THICK_5 0x02
+#define BT431_CMD_THICK_7 0x03
diff --git a/chips/bt455.c b/chips/bt455.c
new file mode 100644
index 00000000..12acecb7
--- /dev/null
+++ b/chips/bt455.c
@@ -0,0 +1,222 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt455.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 7/91
+ *
+ * Routines for the bt454/bt455 RAMDAC
+ */
+
+#include <platforms.h>
+
+#include <chips/bt455.h>
+#include <chips/screen.h>
+
+#ifdef DECSTATION
+
+typedef struct {
+ volatile unsigned char addr_cmap;
+ char pad0[3];
+ volatile unsigned char addr_cmap_data;
+ char pad1[3];
+ volatile unsigned char addr_clr;
+ char pad2[3];
+ volatile unsigned char addr_ovly;
+ char pad3[3];
+} bt455_padded_regmap_t;
+
+#else /*DECSTATION*/
+
+typedef bt455_regmap_t bt455_padded_regmap_t;
+#define wbflush()
+
+#endif /*DECSTATION*/
+
+
+/*
+ * Generic register access
+ */
+#define bt455_select_entry(regs, regno) \
+ { \
+ (regs)->addr_cmap = (regno)&0x0f; \
+ wbflush(); \
+ }
+
+
+/*
+ * Color map
+ */
+bt455_load_colormap( regs, map)
+ bt455_padded_regmap_t *regs;
+ color_map_t *map;
+{
+ register int i;
+
+ bt455_select_entry(regs, 0);
+
+ for (i = 0; i < 16; i++, map++) {
+ regs->addr_cmap_data = map->red >> 4;
+ wbflush();
+ regs->addr_cmap_data = map->green >> 4;
+ wbflush();
+ regs->addr_cmap_data = map->blue >> 4;
+ wbflush();
+ }
+}
+
+bt455_load_colormap_entry( regs, entry, map)
+ register bt455_padded_regmap_t *regs;
+ register color_map_t *map;
+{
+ bt455_select_entry(regs, entry);
+
+ regs->addr_cmap_data = map->red >> 4;
+ wbflush();
+ regs->addr_cmap_data = map->green >> 4;
+ wbflush();
+ regs->addr_cmap_data = map->blue >> 4;
+ wbflush();
+}
+
+bt455_init_colormap( regs)
+ bt455_padded_regmap_t *regs;
+{
+ register int i;
+ color_map_t m[2];
+
+ m[0].red = m[0].green = m[0].blue = 0;
+ m[1].red = m[1].green = m[1].blue = 0xff;
+
+ for (i = 0; i < 16; i++)
+ bt455_load_colormap_entry(regs, i, &m[0]);
+
+ bt455_load_colormap_entry(regs, 1, &m[1]);
+
+ bt455_cursor_color( regs, &m[0]);
+}
+
+#if 1/*debug*/
+bt455_print_colormap( regs)
+ bt455_padded_regmap_t *regs;
+{
+ register int i;
+
+ for (i = 0; i < 16; i++) {
+ register unsigned char red, green, blue;
+
+ bt455_select_entry(regs, i);
+ red = regs->addr_cmap_data;
+ green = regs->addr_cmap_data;
+ blue = regs->addr_cmap_data;
+ printf("%x->[x%x x%x x%x]\n", i,
+ red, green, blue);
+
+ }
+}
+#endif
+
+/*
+ * Video on/off
+ */
+bt455_video_off(regs, up)
+ bt455_padded_regmap_t *regs;
+ user_info_t *up;
+{
+ color_map_t m;
+ unsigned char *save;
+
+ /* Yes, this is awful */
+ save = (unsigned char *)up->dev_dep_2.gx.colormap;
+
+ bt455_select_entry( regs, 0);
+
+ *save++ = regs->addr_cmap_data; /* entry 0 */
+ *save++ = regs->addr_cmap_data;
+ *save++ = regs->addr_cmap_data;
+
+ *save++ = regs->addr_cmap_data; /* entry 1 */
+ *save++ = regs->addr_cmap_data;
+ *save++ = regs->addr_cmap_data;
+
+ m.red = m.green = m.blue = 0;
+ bt455_load_colormap_entry(regs, 0, &m);
+ bt455_load_colormap_entry(regs, 1, &m);
+}
+
+bt455_video_on(regs, up)
+ bt455_padded_regmap_t *regs;
+ user_info_t *up;
+{
+ unsigned char *save;
+
+ /* Like I said.. */
+ save = (unsigned char *)up->dev_dep_2.gx.colormap;
+
+ bt455_select_entry( regs, 0);
+
+ regs->addr_cmap_data = *save++; wbflush();
+ regs->addr_cmap_data = *save++; wbflush();
+ regs->addr_cmap_data = *save++; wbflush();
+
+ regs->addr_cmap_data = *save++; wbflush();
+ regs->addr_cmap_data = *save++; wbflush();
+ regs->addr_cmap_data = *save;
+
+}
+
+/*
+ * Cursor 'color' [as used on DEC's board]
+ */
+bt455_cursor_color( regs, color)
+ bt455_padded_regmap_t *regs;
+ color_map_t *color;
+{
+ register int i;
+
+ /* Bg is the first in color */
+ bt455_load_colormap_entry( regs, 8, color);
+ bt455_load_colormap_entry( regs, 9, color);
+
+ /* Fg is overlay */
+ color++;
+ regs->addr_ovly = color->red >> 4;
+ wbflush();
+ regs->addr_ovly = color->green >> 4;
+ wbflush();
+ regs->addr_ovly = color->blue >> 4;
+ wbflush();
+}
+
+/*
+ * Initialization
+ */
+bt455_init(regs)
+ bt455_padded_regmap_t *regs;
+{
+ /* Nothing really needed */
+}
+
diff --git a/chips/bt455.h b/chips/bt455.h
new file mode 100644
index 00000000..10145efc
--- /dev/null
+++ b/chips/bt455.h
@@ -0,0 +1,43 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt455.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 7/91
+ *
+ * Defines for the bt455 RAMDAC
+ */
+
+typedef struct {
+ volatile unsigned char addr_cmap;
+ volatile unsigned char addr_cmap_data;
+ volatile unsigned char addr_clr;
+ volatile unsigned char addr_ovly;
+} bt455_regmap_t;
+
+/*
+ * Color Map entries 00-0f are accessed indirectly
+ */
diff --git a/chips/bt459.c b/chips/bt459.c
new file mode 100644
index 00000000..0bee2f10
--- /dev/null
+++ b/chips/bt459.c
@@ -0,0 +1,384 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt459.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Routines for the bt459 RAMDAC
+ */
+
+#include <platforms.h>
+
+#include <chips/bt459.h>
+#include <chips/screen.h>
+
+#ifdef DECSTATION
+
+typedef struct {
+ volatile unsigned char addr_lo;
+ char pad0[3];
+ volatile unsigned char addr_hi;
+ char pad1[3];
+ volatile unsigned char addr_reg;
+ char pad2[3];
+ volatile unsigned char addr_cmap;
+ char pad3[3];
+} bt459_ds_padded_regmap_t;
+#define bt459_padded_regmap_t bt459_ds_padded_regmap_t
+
+#define mb() /* no write/read reordering problems */
+
+#endif /* DECSTATION */
+
+#ifdef FLAMINGO
+
+/* Sparse space ! */
+typedef struct {
+ volatile unsigned int addr_lo;
+ int pad0;
+ volatile unsigned int addr_hi;
+ int pad1;
+ volatile unsigned int addr_reg;
+ int pad2;
+ volatile unsigned int addr_cmap;
+ int pad3;
+} bt459_fl_padded_regmap_t;
+#define bt459_padded_regmap_t bt459_fl_padded_regmap_t
+
+#define mb() wbflush()
+
+#endif /* FLAMINGO */
+
+
+#ifndef bt459_padded_regmap_t
+typedef bt459_regmap_t bt459_padded_regmap_t;
+#define wbflush()
+#endif
+
+/*
+ * Generic register access
+ */
+#define bt459_select_reg_macro(r,n) \
+ (r)->addr_lo = (n); mb(); \
+ (r)->addr_hi = (n) >> 8; \
+ wbflush();
+
+void
+bt459_select_reg(
+ bt459_padded_regmap_t *regs,
+ int regno)
+{
+ bt459_select_reg_macro( regs, regno);
+}
+
+void
+bt459_write_reg(
+ bt459_padded_regmap_t *regs,
+ int regno,
+ unsigned char val)
+{
+ bt459_select_reg_macro( regs, regno );
+ regs->addr_reg = val;
+ wbflush();
+}
+
+unsigned char
+bt459_read_reg(
+ bt459_padded_regmap_t *regs,
+ int regno)
+{
+ bt459_select_reg_macro( regs, regno );
+ return regs->addr_reg;
+}
+
+
+/*
+ * Color map
+ */
+bt459_load_colormap_entry(
+ bt459_padded_regmap_t *regs,
+ int entry,
+ color_map_t *map)
+{
+ bt459_select_reg(regs, entry & 0xff);
+
+ regs->addr_cmap = map->red;
+ wbflush();
+ regs->addr_cmap = map->green;
+ wbflush();
+ regs->addr_cmap = map->blue;
+ wbflush();
+}
+
+bt459_init_colormap(
+ bt459_padded_regmap_t *regs)
+{
+ register int i;
+
+ bt459_select_reg(regs, 0);
+ regs->addr_cmap = 0;
+ wbflush();
+ regs->addr_cmap = 0;
+ wbflush();
+ regs->addr_cmap = 0;
+ wbflush();
+
+ regs->addr_cmap = 0xff;
+ wbflush();
+ regs->addr_cmap = 0xff;
+ wbflush();
+ regs->addr_cmap = 0xff;
+ wbflush();
+
+ bt459_select_reg(regs, 255);
+ regs->addr_cmap = 0xff;
+ wbflush();
+ regs->addr_cmap = 0xff;
+ wbflush();
+ regs->addr_cmap = 0xff;
+ wbflush();
+
+}
+
+#if 1/*debug*/
+bt459_print_colormap(
+ bt459_padded_regmap_t *regs)
+{
+ register int i;
+
+ for (i = 0; i < 256; i++) {
+ register unsigned char red, green, blue;
+
+ bt459_select_reg(regs, i);
+ red = regs->addr_cmap; wbflush();
+ green = regs->addr_cmap; wbflush();
+ blue = regs->addr_cmap; wbflush();
+ printf("%x->[x%x x%x x%x]\n", i,
+ red, green, blue);
+
+ }
+}
+#endif
+
+/*
+ * Video on/off
+ *
+ * It is unfortunate that X11 goes backward with white@0
+ * and black@1. So we must stash away the zero-th entry
+ * and fix it while screen is off. Also must remember
+ * it, sigh.
+ */
+struct vstate {
+ bt459_padded_regmap_t *regs;
+ unsigned short off;
+};
+
+bt459_video_off(
+ struct vstate *vstate,
+ user_info_t *up)
+{
+ register bt459_padded_regmap_t *regs = vstate->regs;
+ unsigned char *save;
+
+ if (vstate->off)
+ return;
+
+ /* Yes, this is awful */
+ save = (unsigned char *)up->dev_dep_2.gx.colormap;
+
+ bt459_select_reg(regs, 0);
+ *save++ = regs->addr_cmap;
+ *save++ = regs->addr_cmap;
+ *save++ = regs->addr_cmap;
+
+ bt459_select_reg(regs, 0);
+ regs->addr_cmap = 0;
+ wbflush();
+ regs->addr_cmap = 0;
+ wbflush();
+ regs->addr_cmap = 0;
+ wbflush();
+
+ bt459_write_reg( regs, BT459_REG_PRM, 0);
+ bt459_write_reg( regs, BT459_REG_CCR, 0);
+
+ vstate->off = 1;
+}
+
+bt459_video_on(
+ struct vstate *vstate,
+ user_info_t *up)
+{
+ register bt459_padded_regmap_t *regs = vstate->regs;
+ unsigned char *save;
+
+ if (!vstate->off)
+ return;
+
+ /* Like I said.. */
+ save = (unsigned char *)up->dev_dep_2.gx.colormap;
+
+ bt459_select_reg(regs, 0);
+ regs->addr_cmap = *save++;
+ wbflush();
+ regs->addr_cmap = *save++;
+ wbflush();
+ regs->addr_cmap = *save++;
+ wbflush();
+
+ bt459_write_reg( regs, BT459_REG_PRM, 0xff);
+ bt459_write_reg( regs, BT459_REG_CCR, 0xc0);
+
+ vstate->off = 0;
+}
+
+/*
+ * Cursor
+ */
+bt459_pos_cursor(
+ bt459_padded_regmap_t *regs,
+ register int x,
+ register int y)
+{
+#define lo(v) ((v)&0xff)
+#define hi(v) (((v)&0xf00)>>8)
+ bt459_write_reg( regs, BT459_REG_CXLO, lo(x + 219));
+ bt459_write_reg( regs, BT459_REG_CXHI, hi(x + 219));
+ bt459_write_reg( regs, BT459_REG_CYLO, lo(y + 34));
+ bt459_write_reg( regs, BT459_REG_CYHI, hi(y + 34));
+}
+
+
+bt459_cursor_color(
+ bt459_padded_regmap_t *regs,
+ color_map_t *color)
+{
+ register int i;
+
+ bt459_select_reg_macro( regs, BT459_REG_CCOLOR_2);
+ for (i = 0; i < 2; i++) {
+ regs->addr_reg = color->red;
+ wbflush();
+ regs->addr_reg = color->green;
+ wbflush();
+ regs->addr_reg = color->blue;
+ wbflush();
+ color++;
+ }
+}
+
+bt459_cursor_sprite(
+ bt459_padded_regmap_t *regs,
+ unsigned char *cursor)
+{
+ register int i, j;
+
+ /*
+ * As per specs, must run a check to see if we
+ * had contention. If so, re-write the cursor.
+ */
+ for (i = 0, j = 0; j < 2; j++) {
+ /* loop once to write */
+ for ( ; i < 1024; i++)
+ bt459_write_reg( regs, BT459_REG_CRAM_BASE+i, cursor[i]);
+
+ /* loop to check, if fail write again */
+ for (i = 0; i < 1024; i++)
+ if (bt459_read_reg( regs, BT459_REG_CRAM_BASE+i) != cursor[i])
+ break;
+ if (i == 1024)
+ break;/* all is well now */
+ }
+}
+
+/*
+ * Initialization
+ */
+bt459_init(
+ bt459_padded_regmap_t *regs,
+ volatile char *reset,
+ int mux)
+{
+ if (bt459_read_reg(regs, BT459_REG_ID) != 0x4a)
+ panic("bt459");
+
+ if (mux == 4) {
+ /* use 4:1 input mux */
+ bt459_write_reg( regs, BT459_REG_CMD0, 0x40);
+ } else if (mux == 5) {
+ /* use 5:1 input mux */
+ bt459_write_reg( regs, BT459_REG_CMD0, 0xc0);
+ } /* else donno */
+
+ *reset = 0; /* force chip reset */
+
+ /* no zooming, no panning */
+ bt459_write_reg( regs, BT459_REG_CMD1, 0x00);
+
+ /* signature test, X-windows cursor, no overlays, SYNC* PLL,
+ normal RAM select, 7.5 IRE pedestal, do sync */
+ bt459_write_reg( regs, BT459_REG_CMD2, 0xc2);
+
+ /* get all pixel bits */
+ bt459_write_reg( regs, BT459_REG_PRM, 0xff);
+
+ /* no blinking */
+ bt459_write_reg( regs, BT459_REG_PBM, 0x00);
+
+ /* no overlay */
+ bt459_write_reg( regs, BT459_REG_ORM, 0x00);
+
+ /* no overlay blink */
+ bt459_write_reg( regs, BT459_REG_OBM, 0x00);
+
+ /* no interleave, no underlay */
+ bt459_write_reg( regs, BT459_REG_ILV, 0x00);
+
+ /* normal operation, no signature analysis */
+ bt459_write_reg( regs, BT459_REG_TEST, 0x00);
+
+ /* no blinking, 1bit cross hair, XOR reg&crosshair,
+ no crosshair on either plane 0 or 1,
+ regular cursor on both planes */
+ bt459_write_reg( regs, BT459_REG_CCR, 0xc0);
+
+ /* home cursor */
+ bt459_write_reg( regs, BT459_REG_CXLO, 0x00);
+ bt459_write_reg( regs, BT459_REG_CXHI, 0x00);
+ bt459_write_reg( regs, BT459_REG_CYLO, 0x00);
+ bt459_write_reg( regs, BT459_REG_CYHI, 0x00);
+
+ /* no crosshair window */
+ bt459_write_reg( regs, BT459_REG_WXLO, 0x00);
+ bt459_write_reg( regs, BT459_REG_WXHI, 0x00);
+ bt459_write_reg( regs, BT459_REG_WYLO, 0x00);
+ bt459_write_reg( regs, BT459_REG_WYHI, 0x00);
+ bt459_write_reg( regs, BT459_REG_WWLO, 0x00);
+ bt459_write_reg( regs, BT459_REG_WWHI, 0x00);
+ bt459_write_reg( regs, BT459_REG_WHLO, 0x00);
+ bt459_write_reg( regs, BT459_REG_WHHI, 0x00);
+}
diff --git a/chips/bt459.h b/chips/bt459.h
new file mode 100644
index 00000000..66012d2a
--- /dev/null
+++ b/chips/bt459.h
@@ -0,0 +1,82 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt459.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Defines for the bt459 Cursor/RAMDAC chip
+ */
+
+typedef struct {
+ volatile unsigned char addr_lo;
+ volatile unsigned char addr_hi;
+ volatile unsigned char addr_reg;
+ volatile unsigned char addr_cmap;
+} bt459_regmap_t;
+
+/*
+ * Additional registers addressed indirectly
+ */
+
+ /* 0000-00ff Color Map entries */
+ /* 0100-010f Overlay color regs, unsupp */
+#define BT459_REG_CCOLOR_1 0x0181 /* Cursor color regs */
+#define BT459_REG_CCOLOR_2 0x0182
+#define BT459_REG_CCOLOR_3 0x0183
+#define BT459_REG_ID 0x0200 /* read-only, gives "4a" */
+#define BT459_REG_CMD0 0x0201
+#define BT459_REG_CMD1 0x0202
+#define BT459_REG_CMD2 0x0203
+#define BT459_REG_PRM 0x0204
+ /* 0205 reserved */
+#define BT459_REG_PBM 0x0206
+ /* 0207 reserved */
+#define BT459_REG_ORM 0x0208
+#define BT459_REG_OBM 0x0209
+#define BT459_REG_ILV 0x020a
+#define BT459_REG_TEST 0x020b
+#define BT459_REG_RSIG 0x020c
+#define BT459_REG_GSIG 0x020d
+#define BT459_REG_BSIG 0x020e
+ /* 020f-02ff reserved */
+#define BT459_REG_CCR 0x0300
+#define BT459_REG_CXLO 0x0301
+#define BT459_REG_CXHI 0x0302
+#define BT459_REG_CYLO 0x0303
+#define BT459_REG_CYHI 0x0304
+#define BT459_REG_WXLO 0x0305
+#define BT459_REG_WXHI 0x0306
+#define BT459_REG_WYLO 0x0307
+#define BT459_REG_WYHI 0x0308
+#define BT459_REG_WWLO 0x0309
+#define BT459_REG_WWHI 0x030a
+#define BT459_REG_WHLO 0x030b
+#define BT459_REG_WHHI 0x030c
+ /* 030d-03ff reserved */
+#define BT459_REG_CRAM_BASE 0x0400
+#define BT459_REG_CRAM_END 0x07ff
+
diff --git a/chips/bt478.c b/chips/bt478.c
new file mode 100644
index 00000000..841728fd
--- /dev/null
+++ b/chips/bt478.c
@@ -0,0 +1,243 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt478.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Routines for the bt478 Cursor/RAMDAC chip
+ */
+
+#include <platforms.h>
+
+#include <chips/bt478.h>
+#include <chips/screen.h>
+
+#ifdef DECSTATION
+
+typedef struct {
+ volatile unsigned char addr_mapwa;
+ char pad0[3];
+ volatile unsigned char addr_map;
+ char pad1[3];
+ volatile unsigned char addr_mask;
+ char pad2[3];
+ volatile unsigned char addr_mapra;
+ char pad3[3];
+ volatile unsigned char addr_overwa;
+ char pad4[3];
+ volatile unsigned char addr_over;
+ char pad5[3];
+ volatile unsigned char addr_xxxx;
+ char pad6[3];
+ volatile unsigned char addr_overra;
+ char pad7[3];
+} bt478_padded_regmap_t;
+
+#else /*DECSTATION*/
+
+typedef bt478_regmap_t bt478_padded_regmap_t;
+#define wbflush()
+
+#endif /*DECSTATION*/
+
+
+/*
+ * Cursor color
+ */
+static
+bt478_load_cc(bt478, bg, fg)
+ register bt478_padded_regmap_t *bt478;
+ unsigned int *bg, *fg;
+{
+ register int i;
+
+ /* See init function for gotchas */
+
+ bt478->addr_overwa = 4;
+ wbflush();
+ for (i = 0; i < 3; i++) {
+ bt478->addr_over = (*bg++) >> 8;
+ wbflush();
+ }
+
+ bt478->addr_overwa = 8;
+ wbflush();
+ bt478->addr_over = 0x00;
+ wbflush();
+ bt478->addr_over = 0x00;
+ wbflush();
+ bt478->addr_over = 0x7f;
+ wbflush();
+
+ bt478->addr_overwa = 12;
+ wbflush();
+ for (i = 0; i < 3; i++) {
+ bt478->addr_over = (*fg++) >> 8;
+ wbflush();
+ }
+
+}
+
+
+bt478_cursor_color(bt478, color)
+ bt478_padded_regmap_t *bt478;
+ cursor_color_t *color;
+{
+ register int i;
+ register unsigned int *p;
+
+ /* Do it twice, in case of collisions */
+
+ bt478_load_cc(bt478, color->Bg_rgb, color->Fg_rgb);
+
+ p = color->Bg_rgb;
+ for (i = 0; i < 3; i++) {
+ bt478->addr_over = (*p++) >> 8;
+ wbflush();
+ }
+
+ p = color->Fg_rgb;
+ for (i = 0; i < 3; i++) {
+ bt478->addr_over = (*p++) >> 8;
+ wbflush();
+ }
+
+ bt478_load_cc(bt478, color->Bg_rgb, color->Fg_rgb);
+}
+
+/*
+ * Color map
+ */
+bt478_load_colormap( regs, map)
+ bt478_padded_regmap_t *regs;
+ color_map_t *map;
+{
+ register int i;
+
+ regs->addr_mapwa = 0;
+ wbflush();
+ for (i = 0; i < 256; i++, map++) {
+ regs->addr_map = map->red;
+ wbflush();
+ regs->addr_map = map->green;
+ wbflush();
+ regs->addr_map = map->blue;
+ wbflush();
+ }
+}
+
+bt478_load_colormap_entry( regs, entry, map)
+ bt478_padded_regmap_t *regs;
+ color_map_t *map;
+{
+ regs->addr_mapwa = entry & 0xff;
+ wbflush();
+ regs->addr_map = map->red;
+ wbflush();
+ regs->addr_map = map->green;
+ wbflush();
+ regs->addr_map = map->blue;
+ wbflush();
+}
+
+/*
+ * Video on/off (unused)
+ */
+bt478_video_on(pregs, up)
+ bt478_padded_regmap_t **pregs;
+{
+ (*pregs)->addr_mask = 0xff;
+}
+
+bt478_video_off(pregs, up)
+ bt478_padded_regmap_t **pregs;
+{
+ (*pregs)->addr_mask = 0;
+}
+
+/*
+ * Initialization
+ */
+static
+bt478_overlay(regs, plane)
+ bt478_padded_regmap_t *regs;
+ unsigned char *plane;
+{
+ *plane = 0xff;
+
+ /* Overlay planes 0 and 1 are wired zero, overlay plane 2
+ is plane "B" of the cursor (second half of it), plane 3
+ is plane "A" of the cursor. Soo, we get three colors
+ for the cursor, at map entries 4, 8 and 12 */
+# define ovv(i,r,g,b) \
+ regs->addr_overwa = i; wbflush(); \
+ regs->addr_over = r; wbflush(); \
+ regs->addr_over = b; wbflush(); \
+ regs->addr_over = g; wbflush();
+
+ ovv(4,0,0,0); ovv(8,0,0,0x7f); ovv(12,0xff,0xff,0xff);
+
+# undef ovv
+
+ /* enable data input */
+ regs->addr_mask = 0xff;
+}
+
+bt478_init_bw_map(regs, plane)
+ bt478_padded_regmap_t *regs;
+{
+ register int i;
+
+ /* Set overlay color registers */
+ bt478_overlay(regs, plane);
+
+ /* loadup vdac map */
+# define mvv(i,v) { \
+ regs->addr_mapwa = i; wbflush(); \
+ regs->addr_map = v; wbflush(); \
+ regs->addr_map = v; wbflush(); \
+ regs->addr_map = v; wbflush();}
+
+ for (i = 0; i < 128; i++) mvv(i,0x00);
+ for (i = i; i < 256; i++) mvv(i,0xff);
+
+}
+
+bt478_init_color_map( regs, plane)
+ bt478_padded_regmap_t *regs;
+{
+ register int i;
+
+ bt478_overlay(regs, plane);
+
+ mvv(0,0);
+ mvv(1,0xff);
+ mvv(255,0xff);
+
+# undef mvv
+}
+
diff --git a/chips/bt478.h b/chips/bt478.h
new file mode 100644
index 00000000..a60108f3
--- /dev/null
+++ b/chips/bt478.h
@@ -0,0 +1,44 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: bt478.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 10/90
+ *
+ * Defines for the bt478 Cursor/RAMDAC chip
+ */
+
+typedef struct {
+ volatile unsigned char addr_mapwa;
+ volatile unsigned char addr_map;
+ volatile unsigned char addr_mask;
+ volatile unsigned char addr_mapra;
+ volatile unsigned char addr_overwa;
+ volatile unsigned char addr_over;
+ volatile unsigned char addr_xxxx;
+ volatile unsigned char addr_overra;
+} bt478_regmap_t;
+
diff --git a/chips/build_font.c b/chips/build_font.c
new file mode 100644
index 00000000..2542351e
--- /dev/null
+++ b/chips/build_font.c
@@ -0,0 +1,132 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: build_font.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 10/90
+ *
+ *
+ * Takes a font description file and generates a C source
+ * appropriate for use as kernel font on mips/vax boxes.
+ * This basically means encoding and mirroring the bitmaps.
+ */
+
+#include <stdio.h>
+
+main(argc,argv)
+ char **argv;
+{
+ int fd;
+ FILE *fout;
+ int i, j, k, n, l;
+ int first, last;
+ char *fname = "kernel_font.data";
+ char buf[16*9];
+ int verbose = 0;
+
+ if (argc > 1 && argv[1][0] == '+')
+ verbose++, argc--, argv++;
+
+ first = 0;
+ last = 190; /* 8-bit ASCII, offset by 'space' */
+ if (argc > 1) {
+ first = atoi(argv[1]);
+ last = first + 1;
+ }
+ if (argc > 2)
+ last = atoi(argv[2]) + 1;
+ if (argc > 3)
+ fname = argv[3];
+
+ fd = open(fname, 0, 0);
+ fout = fopen("kernel_font.c", "w");
+
+ fprintf(fout, "/* \n\
+ * Mach Operating System\n\
+ * Copyright (c) 1989 Carnegie-Mellon University\n\
+ * All rights reserved. The CMU software License Agreement specifies\n\
+ * the terms and conditions for use and redistribution.\n\
+ */\n\
+/*\n\
+ * THIS FILE WAS GENERATED BY %s FROM %s\n\
+ * IF YOU NEED TO, BE SURE YOU EDIT THE REAL THING!\n\
+ */\n\
+/*\n\
+ * Object:\n\
+ * kfont_7x14 EXPORTED array\n\
+ *\n\
+ * Kernel font for printable ASCII chars\n\
+ *\n\
+ * The smallest index in this array corresponds to a\n\
+ * space. So, we start at 0x20 in the ascii table.\n\
+ * Note that glyphs are mirrored (byteorder, I think)\n\
+ * the commented bitmap shows how they really look like\n\
+ */\n\
+\n\
+unsigned char kfont_7x14[] = {\n", argv[0], fname);
+
+skip_comments:
+ read(fd, buf, 1);
+ if (buf[0] == '#') {
+ do
+ read(fd, buf, 1);
+ while (buf[0] != '\n');
+ goto skip_comments;
+ }
+ lseek(fd, -1, 1); /* put char back */
+
+ /* if must skip some */
+ for (l = 0; l < first; l++)
+ read(fd, buf, 2+(9*15));
+
+ /* scan for real now */
+ for (i = first; i < last; i++) {
+ /* read one full glyph */
+ if (read(fd, buf, 2+(9*15)) < 0)
+ break;
+ if (verbose)
+ printf("Character '%c':\n\t", buf[0]);
+ /* index and char itself in comments */
+ fprintf(fout, "/* %3x '%c' */\n", i, 0x20+i);
+
+ /* encode and mirror each one of the 15 scanlines */
+ for (n = 0; n < 15; n++) {
+ unsigned char cc[8], swap = 0;
+ /* 8 bits per scanline */
+ for (k = 2+(n*9), j = 0; j < 8; k++, j++) {
+ if (verbose)
+ printf("%c", (buf[k] == '1') ? '@' : ' ');
+ swap = ((buf[k] - '0') << 7) | (swap >> 1);
+ cc[j] = buf[k];
+ }
+ fprintf(fout,"\t/* %8s */\t%#2x,\n", cc, (unsigned char)swap);
+ if (verbose)
+ printf("\n\t");
+ }
+ }
+ fprintf(fout, "};\n");
+ fclose(fout);
+}
diff --git a/chips/busses.c b/chips/busses.c
new file mode 100644
index 00000000..dd64f489
--- /dev/null
+++ b/chips/busses.c
@@ -0,0 +1,230 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: busses.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 4/90
+ *
+ * Generic autoconfiguration functions,
+ * usable to probe and attach devices
+ * on any bus that suits the generic bus
+ * structure, such as VME, TURBOChannel,
+ * and all the VAX busses.
+ *
+ */
+
+#include <mach/boolean.h>
+#include <mach/std_types.h>
+#include <chips/busses.h>
+
+
+
+
+/*
+ * configure_bus_master
+ *
+ * Given the name of a bus_ctlr, look it up in the
+ * init table. If found, probe it. If there can be
+ * slaves attached, walk the device's init table
+ * for those that might be attached to this controller.
+ * Call the 'slave' function on each one to see if
+ * ok, then the 'attach' one.
+ *
+ * Returns 0 if the controller is not there.
+ *
+ */
+boolean_t configure_bus_master(
+ char *name,
+ vm_offset_t virt,
+ vm_offset_t phys,
+ int adpt_no,
+ char *bus_name)
+{
+ register struct bus_device *device;
+ register struct bus_ctlr *master;
+ register struct bus_driver *driver;
+
+ int found = 0;
+
+ /*
+ * Match the name in the table, then pick the entry that has the
+ * right adaptor number, or one that has it wildcarded. Entries
+ * already allocated are marked alive, skip them.
+ */
+ for (master = bus_master_init; master->driver; master++) {
+ if (master->alive)
+ continue;
+ if (((master->adaptor == adpt_no) || (master->adaptor == '?')) &&
+ (strcmp(master->name, name) == 0)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return FALSE;
+
+ /*
+ * Found a match, probe it
+ */
+ driver = master->driver;
+ if ((*driver->probe) (virt, master) == 0)
+ return FALSE;
+
+ master->alive = 1;
+ master->adaptor = adpt_no;
+
+ /*
+ * Remember which controller this device is attached to
+ */
+ driver->minfo[master->unit] = master;
+
+ printf("%s%d: at %s%d\n", master->name, master->unit, bus_name, adpt_no);
+
+ /*
+ * Now walk all devices to check those that might be attached to this
+ * controller. We match the unallocated ones that have the right
+ * controller number, or that have a widcarded controller number.
+ */
+ for (device = bus_device_init; device->driver; device++) {
+ int ctlr;
+ if (device->alive || device->driver != driver ||
+ (device->adaptor != '?' && device->adaptor != adpt_no))
+ continue;
+ ctlr = device->ctlr;
+ if (ctlr == '?') device->ctlr = master->unit;
+ /*
+ * A matching entry. See if the slave-probing routine is
+ * happy.
+ */
+ if ((device->ctlr != master->unit) ||
+ ((*driver->slave) (device, virt) == 0)) {
+ device->ctlr = ctlr;
+ continue;
+ }
+
+ device->alive = 1;
+ device->adaptor = adpt_no;
+ device->ctlr = master->unit;
+
+ /*
+ * Save a backpointer to the controller
+ */
+ device->mi = master;
+
+ /*
+ * ..and to the device
+ */
+ driver->dinfo[device->unit] = device;
+
+ if (device->slave >= 0)
+ printf(" %s%d: at %s%d slave %d",
+ device->name, device->unit,
+ driver->mname, master->unit, device->slave);
+ else
+ printf(" %s%d: at %s%d",
+ device->name, device->unit,
+ driver->mname, master->unit);
+
+ /*
+ * Now attach this slave
+ */
+ (*driver->attach) (device);
+ printf("\n");
+ }
+ return TRUE;
+}
+
+/*
+ * configure_bus_device
+ *
+ * Given the name of a bus_device, look it up in the
+ * init table. If found, probe it. If it is present,
+ * call the driver's 'attach' function.
+ *
+ * Returns 0 if the device is not there.
+ *
+ */
+boolean_t configure_bus_device(
+ char *name,
+ vm_offset_t virt,
+ vm_offset_t phys,
+ int adpt_no,
+ char *bus_name)
+{
+ register struct bus_device *device;
+ register struct bus_driver *driver;
+
+ int found = 0;
+
+ /*
+ * Walk all devices to find one with the right name
+ * and adaptor number (or wildcard). The entry should
+ * be unallocated, and also the slave number should
+ * be wildcarded.
+ */
+ for (device = bus_device_init; device->driver; device++) {
+ if (device->alive)
+ continue;
+ if (((device->adaptor == adpt_no) || (device->adaptor == '?')) &&
+ (device->slave == -1) &&
+ ((!device->phys_address) ||
+ ((device->phys_address == phys) && (device->address == virt))) &&
+ (strcmp(device->name, name) == 0)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return FALSE;
+
+ /*
+ * Found an entry, probe the device
+ */
+ driver = device->driver;
+ if ((*driver->probe) (virt, (struct bus_ctlr *)device) == 0)
+ return FALSE;
+
+ device->alive = 1;
+ device->adaptor = adpt_no;
+
+ printf("%s%d: at %s%d", device->name, device->unit, bus_name, adpt_no);
+
+ /*
+ * Remember which driver this device is attached to
+ */
+ driver->dinfo[device->unit] = device;
+
+ /*
+ * Attach the device
+ */
+ (*driver->attach) (device);
+ printf("\n");
+
+ return TRUE;
+}
+
diff --git a/chips/busses.h b/chips/busses.h
new file mode 100644
index 00000000..56a9ed37
--- /dev/null
+++ b/chips/busses.h
@@ -0,0 +1,154 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1994-1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: busses.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 4/90
+ *
+ * Structures used by configuration routines to
+ * explore a given bus structure.
+ */
+
+#ifndef _CHIPS_BUSSES_H_
+#define _CHIPS_BUSSES_H_
+
+#include <mach/boolean.h>
+#include <mach/machine/vm_types.h>
+
+/*
+ *
+ * This is mildly modeled after the Unibus on Vaxen,
+ * one of the most complicated bus structures.
+ * Therefore, let's hope this can be done once and for all.
+ *
+ * At the bottom level there is a "bus_device", which
+ * might exist in isolation (e.g. a clock on the CPU
+ * board) or be a standard component of an architecture
+ * (e.g. the bitmap display on some workstations).
+ *
+ * Disk devices and communication lines support multiple
+ * units, hence the "bus_driver" structure which is more
+ * flexible and allows probing and dynamic configuration
+ * of the number and type of attached devices.
+ *
+ * At the top level there is a "bus_ctlr" structure, used
+ * in systems where the I/O bus(ses) are separate from
+ * the memory bus(ses), and/or when memory boards can be
+ * added to the main bus (and they must be config-ed
+ * and/or can interrupt the processor for ECC errors).
+ *
+ * The autoconfiguration process typically starts at
+ * the top level and walks down tables that are
+ * defined either in a generic file or are specially
+ * created by config.
+ */
+
+/*
+ * Per-controller structure.
+ */
+struct bus_ctlr {
+ struct bus_driver *driver; /* myself, as a device */
+ char *name; /* readability */
+ int unit; /* index in driver */
+ int (*intr)(); /* interrupt handler(s) */
+ vm_offset_t address; /* device virtual address */
+ int am; /* address modifier */
+ vm_offset_t phys_address;/* device phys address */
+ char adaptor; /* slot where found */
+ char alive; /* probed successfully */
+ char flags; /* any special conditions */
+ vm_offset_t sysdep; /* On some systems, queue of
+ * operations in-progress */
+ natural_t sysdep1; /* System dependent */
+};
+
+
+/*
+ * Per-``device'' structure
+ */
+struct bus_device {
+ struct bus_driver *driver; /* autoconf info */
+ char *name; /* my name */
+ int unit;
+ int (*intr)();
+ vm_offset_t address; /* device address */
+ int am; /* address modifier */
+ vm_offset_t phys_address;/* device phys address */
+ char adaptor;
+ char alive;
+ char ctlr;
+ char slave;
+ int flags;
+ struct bus_ctlr *mi; /* backpointer to controller */
+ struct bus_device *next; /* optional chaining */
+ vm_offset_t sysdep; /* System dependent */
+ natural_t sysdep1; /* System dependent */
+};
+
+/*
+ * General flag definitions
+ */
+#define BUS_INTR_B4_PROBE 0x01 /* enable interrupts before probe */
+#define BUS_INTR_DISABLED 0x02 /* ignore all interrupts */
+#define BUS_CTLR 0x04 /* descriptor for a bus adaptor */
+#define BUS_XCLU 0x80 /* want exclusive use of bdp's */
+
+/*
+ * Per-driver structure.
+ *
+ * Each bus driver defines entries for a set of routines
+ * that are used at boot time by the configuration program.
+ */
+struct bus_driver {
+ int (*probe)( /* see if the driver is there */
+ /* vm_offset_t address,
+ struct bus_ctlr * */ );
+ int (*slave)( /* see if any slave is there */
+ /* struct bus_device *,
+ vm_offset_t */ );
+ void (*attach)( /* setup driver after probe */
+ /* struct bus_device * */);
+ int (*dgo)(); /* start transfer */
+ vm_offset_t *addr; /* device csr addresses */
+ char *dname; /* name of a device */
+ struct bus_device **dinfo; /* backpointers to init structs */
+ char *mname; /* name of a controller */
+ struct bus_ctlr **minfo; /* backpointers to init structs */
+ int flags;
+};
+
+#ifdef KERNEL
+extern struct bus_ctlr bus_master_init[];
+extern struct bus_device bus_device_init[];
+
+extern boolean_t configure_bus_master(char *, vm_offset_t, vm_offset_t,
+ int, char * );
+extern boolean_t configure_bus_device(char *, vm_offset_t, vm_offset_t,
+ int, char * );
+#endif /* KERNEL */
+
+
+#endif /* _CHIPS_BUSSES_H_ */
diff --git a/chips/cfb_hdw.c b/chips/cfb_hdw.c
new file mode 100644
index 00000000..78764aab
--- /dev/null
+++ b/chips/cfb_hdw.c
@@ -0,0 +1,188 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: cfb_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Driver for the 3max Color Frame Buffer Display,
+ * hardware-level operations.
+ */
+
+#include <cfb.h>
+#if (NCFB > 0)
+
+#include <platforms.h>
+
+#include <machine/machspl.h>
+#include <mach/std_types.h>
+#include <chips/busses.h>
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+
+typedef pm_softc_t cfb_softc_t;
+
+#ifdef DECSTATION
+#include <mips/PMAX/pmag_ba.h>
+#include <mips/PMAX/tc.h>
+#endif
+
+#ifdef FLAMINGO
+#include <mips/PMAX/pmag_ba.h> /* XXX fixme */
+#include <alpha/DEC/tc.h>
+#endif
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int cfb_probe(), cfb_intr();
+static void cfb_attach();
+
+vm_offset_t cfb_std[NCFB] = { 0 };
+struct bus_device *cfb_info[NCFB];
+struct bus_driver cfb_driver =
+ { cfb_probe, 0, cfb_attach, 0, cfb_std, "cfb", cfb_info,
+ 0, 0, BUS_INTR_DISABLED};
+
+/*
+ * Probe/Attach functions
+ */
+
+cfb_probe( /* reg, ui */)
+{
+ static probed_once = 0;
+
+ /*
+ * Probing was really done sweeping the TC long ago
+ */
+ if (tc_probe("cfb") == 0)
+ return 0;
+ if (probed_once++ > 1)
+ printf("[mappable] ");
+ return 1;
+}
+
+static void
+cfb_attach(ui)
+ struct bus_device *ui;
+{
+ /* ... */
+ printf(": color display");
+}
+
+
+/*
+ * Interrupt routine
+ */
+
+cfb_intr(unit,spllevel)
+ spl_t spllevel;
+{
+ register volatile char *ack;
+
+ /* acknowledge interrupt */
+ ack = (volatile char *) cfb_info[unit]->address + CFB_OFFSET_IREQ;
+ *ack = 0;
+
+#ifdef mips
+ splx(spllevel);
+#endif
+ lk201_led(unit);
+}
+
+cfb_vretrace(cfb, on)
+ cfb_softc_t *cfb;
+{
+ int i;
+
+ for (i = 0; i < NCFB; i++)
+ if (cfb_info[i]->address == (vm_offset_t)cfb->framebuffer)
+ break;
+ if (i == NCFB) return;
+
+ (*tc_enable_interrupt)(cfb_info[i]->adaptor, on, 0);
+}
+
+/*
+ * Boot time initialization: must make device
+ * usable as console asap.
+ */
+extern int
+ cfb_soft_reset(), cfb_set_status(),
+ bt459_pos_cursor(), bt459_video_on(),
+ bt459_video_off(), cfb_vretrace(),
+ pm_get_status(), pm_char_paint(),
+ pm_insert_line(), pm_remove_line(),
+ pm_clear_bitmap(), pm_map_page();
+
+static struct screen_switch cfb_sw = {
+ screen_noop, /* graphic_open */
+ cfb_soft_reset, /* graphic_close */
+ cfb_set_status, /* set_status */
+ pm_get_status, /* get_status */
+ pm_char_paint, /* char_paint */
+ bt459_pos_cursor, /* pos_cursor */
+ pm_insert_line, /* insert_line */
+ pm_remove_line, /* remove_line */
+ pm_clear_bitmap, /* clear_bitmap */
+ bt459_video_on, /* video_on */
+ bt459_video_off, /* video_off */
+ cfb_vretrace, /* intr_enable */
+ pm_map_page /* map_page */
+};
+
+cfb_cold_init(unit, up)
+ user_info_t *up;
+{
+ cfb_softc_t *cfb;
+ screen_softc_t sc = screen(unit);
+ int base = tc_probe("cfb");
+
+ bcopy(&cfb_sw, &sc->sw, sizeof(sc->sw));
+ sc->flags |= COLOR_SCREEN;
+ sc->frame_scanline_width = 1024;
+ sc->frame_height = 1024;
+ sc->frame_visible_width = 1024;
+ sc->frame_visible_height = 864;
+
+ pm_init_screen_params(sc,up);
+ (void) screen_up(unit, up);
+
+ cfb = pm_alloc(unit, base + CFB_OFFSET_BT459, base + CFB_OFFSET_VRAM, -1);
+
+ screen_default_colors(up);
+
+ cfb_soft_reset(sc);
+
+ /*
+ * Clearing the screen at boot saves from scrolling
+ * much, and speeds up booting quite a bit.
+ */
+ screen_blitc( unit, 'C'-'@');/* clear screen */
+}
+
+#endif (NCFB > 0)
diff --git a/chips/cfb_misc.c b/chips/cfb_misc.c
new file mode 100644
index 00000000..2bda86bd
--- /dev/null
+++ b/chips/cfb_misc.c
@@ -0,0 +1,249 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: cfb_misc.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Driver for the PMAG-BA simple color framebuffer
+ *
+ */
+
+#include <cfb.h>
+#include <sfb.h> /* shares code */
+#if ((NCFB > 0) || (NSFB > 0))
+#include <platforms.h>
+
+/*
+ * NOTE: This driver relies heavily on the pm one.
+ */
+
+#include <device/device_types.h>
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+typedef pm_softc_t cfb_softc_t;
+
+#include <chips/bt459.h>
+#define bt459 cursor_registers
+
+#ifdef DECSTATION
+#include <mips/PMAX/pmag_ba.h>
+#endif
+
+#ifdef FLAMINGO
+#include <mips/PMAX/pmag_ba.h> /* XXX fixme */
+#endif
+
+/*
+ * Initialize color map, for kernel use
+ */
+cfb_init_colormap(
+ screen_softc_t sc)
+{
+ cfb_softc_t *cfb = (cfb_softc_t*)sc->hw_state;
+ user_info_t *up = sc->up;
+ color_map_t Bg_Fg[2];
+ register int i;
+
+ bt459_init_colormap( cfb->bt459 );
+
+ /* init bg/fg colors */
+ for (i = 0; i < 3; i++) {
+ up->dev_dep_2.pm.Bg_color[i] = 0x00;
+ up->dev_dep_2.pm.Fg_color[i] = 0xff;
+ }
+
+ Bg_Fg[0].red = Bg_Fg[0].green = Bg_Fg[0].blue = 0x00;
+ Bg_Fg[1].red = Bg_Fg[1].green = Bg_Fg[1].blue = 0xff;
+ bt459_cursor_color( cfb->bt459, Bg_Fg);
+}
+
+/*
+ * Large viz small cursor
+ */
+cfb_small_cursor_to_large(
+ user_info_t *up,
+ cursor_sprite_t cursor)
+{
+ unsigned short new_cursor[32];
+ unsigned char *curbytes, fg, fbg;
+ int i, j, k;
+ char *sprite;
+
+ /* Clear out old cursor */
+ bzero( up->dev_dep_2.pm.cursor_sprite,
+ sizeof(up->dev_dep_2.pm.cursor_sprite));
+
+ /* small cursor is 32x2 bytes, fg first */
+ curbytes = (unsigned char *) cursor;
+
+ /* use the upper left corner of the large cursor
+ * as a 64x1 cursor, fg&bg alternated */
+ for (i = 0; i < 32; i++) {
+ fg = curbytes[i];
+ fbg = fg | curbytes[i + 32];
+ new_cursor[i] = 0;
+ for (j = 0, k = 15; j < 8; j++, k -= 2) {
+ new_cursor[i] |= ((fbg >> j) & 0x1) << (k);
+ new_cursor[i] |= ((fg >> j) & 0x1) << (k - 1);
+ }
+ }
+
+ /* Now stick it in the proper place */
+
+ curbytes = (unsigned char *) new_cursor;
+ sprite = up->dev_dep_2.pm.cursor_sprite;
+ for (i = 0; i < 64; i += 4) {
+ /* butterfly as we go */
+ *sprite++ = curbytes[i + 1];
+ *sprite++ = curbytes[i + 0];
+ *sprite++ = curbytes[i + 3];
+ *sprite++ = curbytes[i + 2];
+ sprite += 12; /* skip rest of the line */
+ }
+}
+
+
+/*
+ * Device-specific set status
+ */
+cfb_set_status(
+ screen_softc_t sc,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ cfb_softc_t *cfb = (cfb_softc_t*) sc->hw_state;
+
+ switch (flavor) {
+
+ case SCREEN_ADJ_MAPPED_INFO:
+ return pm_set_status(sc, flavor, status, status_count);
+
+ case SCREEN_LOAD_CURSOR:
+
+ if (status_count < sizeof(cursor_sprite_t)/sizeof(int))
+ return D_INVALID_SIZE;
+/* cfb_small_cursor_to_large(sc->up, (cursor_sprite_t) status);*/
+ cfb_small_cursor_to_large(sc->up, (unsigned short *) status);
+
+ /* Fall through */
+
+ case SCREEN_LOAD_CURSOR_LONG: /* 3max only */
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt459_cursor_sprite(cfb->bt459, sc->up->dev_dep_2.pm.cursor_sprite);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+
+ case SCREEN_SET_CURSOR_COLOR: {
+ color_map_t c[2];
+ register cursor_color_t *cc = (cursor_color_t*) status;
+
+ c[0].red = cc->Bg_rgb[0];
+ c[0].green = cc->Bg_rgb[1];
+ c[0].blue = cc->Bg_rgb[2];
+ c[1].red = cc->Fg_rgb[0];
+ c[1].green = cc->Fg_rgb[1];
+ c[1].blue = cc->Fg_rgb[2];
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt459_cursor_color (cfb->bt459, c );
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+ case SCREEN_SET_CMAP_ENTRY: {
+ color_map_entry_t *e = (color_map_entry_t*) status;
+
+ if (e->index < 256) {
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt459_load_colormap_entry( cfb->bt459, e->index, &e->value);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+ }
+ break;
+ }
+
+ default:
+ return D_INVALID_OPERATION;
+ }
+ return D_SUCCESS;
+}
+
+#if (NCFB > 0)
+/*
+ * Hardware initialization
+ */
+cfb_init_screen(
+ cfb_softc_t *cfb)
+{
+ bt459_init( cfb->bt459,
+ cfb->bt459 + (CFB_OFFSET_RESET - CFB_OFFSET_BT459),
+ 4 /* 4:1 MUX */);
+}
+
+/*
+ * Do what's needed when X exits
+ */
+cfb_soft_reset(
+ screen_softc_t sc)
+{
+ cfb_softc_t *cfb = (cfb_softc_t*) sc->hw_state;
+ user_info_t *up = sc->up;
+ extern cursor_sprite_t dc503_default_cursor;
+
+ /*
+ * Restore params in mapped structure
+ */
+ pm_init_screen_params(sc,up);
+ up->row = up->max_row - 1;
+
+ up->dev_dep_2.pm.x26 = 2; /* you do not want to know */
+ up->dev_dep_1.pm.x18 = (short*)2;
+
+ /*
+ * Restore RAMDAC chip to default state
+ */
+ cfb_init_screen(cfb);
+
+ /*
+ * Load kernel's cursor sprite: just use the same pmax one
+ */
+ cfb_small_cursor_to_large(up, dc503_default_cursor);
+ bt459_cursor_sprite(cfb->bt459, up->dev_dep_2.pm.cursor_sprite);
+
+ /*
+ * Color map and cursor color
+ */
+ cfb_init_colormap(sc);
+}
+#endif /* NCFB > 0 */
+
+
+
+#endif /* (NCFB > 0) || (NSFB > 0) */
diff --git a/chips/dc503.c b/chips/dc503.c
new file mode 100644
index 00000000..8bfab509
--- /dev/null
+++ b/chips/dc503.c
@@ -0,0 +1,189 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dc503.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Routines for the DEC DC503 Programmable Cursor Chip
+ */
+#include <platforms.h>
+
+#include <chips/pm_defs.h>
+#include <chips/dc503.h>
+
+
+#if defined(DECSTATION) || defined(VAXSTATION)
+
+typedef struct {
+ volatile unsigned short pcc_cmdr; /* all regs are wo */
+ short pad0;
+ volatile unsigned short pcc_xpos;
+ short pad1;
+ volatile unsigned short pcc_ypos;
+ short pad2;
+ volatile unsigned short pcc_xmin1;
+ short pad3;
+ volatile unsigned short pcc_xmax1;
+ short pad4;
+ volatile unsigned short pcc_ymin1;
+ short pad5;
+ volatile unsigned short pcc_ymax1;
+ short pad6[9];
+ volatile unsigned short pcc_xmin2;
+ short pad7;
+ volatile unsigned short pcc_xmax2;
+ short pad8;
+ volatile unsigned short pcc_ymin2;
+ short pad9;
+ volatile unsigned short pcc_ymax2;
+ short pad10;
+ volatile unsigned short pcc_memory;
+ short pad11;
+} dc503_padded_regmap_t;
+
+#else
+
+typedef dc503_regmap_t dc503_padded_regmap_t;
+
+#endif
+
+#ifdef VAXSTATION
+#define X_CSHIFT 216
+#define Y_CSHIFT 34
+#define wbflush()
+#define PCC_STATE (DC503_CMD_ENPA | DC503_CMD_ENPB | DC503_CMD_HSHI)
+#endif /*VAXSTATION*/
+
+/* defaults, for the innocents */
+
+#ifndef X_CSHIFT
+#define X_CSHIFT 212
+#define Y_CSHIFT 34
+#define PCC_STATE (DC503_CMD_ENPA | DC503_CMD_ENPB)
+#endif
+
+/*
+ * Cursor
+ */
+dc503_pos_cursor( regs, x, y)
+ dc503_padded_regmap_t *regs;
+{
+ regs->pcc_xpos = x + X_CSHIFT;
+ regs->pcc_ypos = y + Y_CSHIFT;
+ wbflush();
+}
+
+dc503_load_cursor( pm, cursor)
+ pm_softc_t *pm;
+ unsigned short *cursor;
+{
+ dc503_padded_regmap_t *regs;
+ register int i;
+
+ regs = (dc503_padded_regmap_t*)pm->cursor_registers;
+
+ pm->cursor_state |= DC503_CMD_LODSA;
+ regs->pcc_cmdr = pm->cursor_state;
+ wbflush();
+ for (i = 0; i < 32; i++) {
+ regs->pcc_memory = *cursor++;
+ wbflush();
+ }
+ pm->cursor_state &= ~DC503_CMD_LODSA;
+ regs->pcc_cmdr = pm->cursor_state;
+}
+
+
+unsigned short dc503_default_cursor[16+16] = {
+/* Plane A */
+ 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff,
+ 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff,
+/* Plane B */
+ 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff,
+ 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff
+};
+
+/*
+ * Vert retrace interrupt
+ */
+dc503_vretrace( pm, on)
+ pm_softc_t *pm;
+{
+ if (on)
+ pm->cursor_state |= DC503_CMD_ENRG2;
+ else
+ pm->cursor_state &= ~DC503_CMD_ENRG2;
+ ((dc503_padded_regmap_t*)pm->cursor_registers)->pcc_cmdr = pm->cursor_state;
+}
+
+/*
+ * Video on/off
+ */
+dc503_video_on( pm, up)
+ pm_softc_t *pm;
+{
+ pm->cursor_state = DC503_CMD_ENPA | (pm->cursor_state & ~DC503_CMD_FOPB);
+ ((dc503_padded_regmap_t*)pm->cursor_registers)->pcc_cmdr = pm->cursor_state;
+}
+
+dc503_video_off( pm, up)
+ pm_softc_t *pm;
+{
+ pm->cursor_state = DC503_CMD_FOPB | (pm->cursor_state & ~DC503_CMD_ENPA);
+ ((dc503_padded_regmap_t*)pm->cursor_registers)->pcc_cmdr = pm->cursor_state;
+}
+
+
+/*
+ * Initialization
+ */
+dc503_init( pm )
+ pm_softc_t *pm;
+{
+ dc503_padded_regmap_t *regs;
+
+ regs = (dc503_padded_regmap_t*)pm->cursor_registers;
+
+ dc503_load_cursor( pm, dc503_default_cursor);
+ dc503_pos_cursor( regs, 0, 0); /* XXX off screen */
+
+ regs->pcc_xmin1 = 0; /* test only */
+ regs->pcc_xmax1 = 0;
+ regs->pcc_ymin1 = 0;
+ regs->pcc_ymax1 = 0;
+
+ regs->pcc_xmin2 = 212; /* vert retrace detector */
+ regs->pcc_xmax2 = 212+1023;
+ regs->pcc_ymin2 = 34+863;
+ regs->pcc_ymax2 = 34+863;
+
+#if 0
+ regs->pcc_cmdr = DC503_CMD_FOPB | DC503_CMD_VBHI;/* reset */
+#endif
+ pm->cursor_state = PCC_STATE;
+ regs->pcc_cmdr = pm->cursor_state;
+}
diff --git a/chips/dc503.h b/chips/dc503.h
new file mode 100644
index 00000000..e3c330c4
--- /dev/null
+++ b/chips/dc503.h
@@ -0,0 +1,69 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dc503.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Defines for the DEC DC503 Programmable Cursor
+ */
+
+typedef struct {
+ volatile unsigned short pcc_cmdr; /* all regs are wo */
+ volatile unsigned short pcc_xpos;
+ volatile unsigned short pcc_ypos;
+ volatile unsigned short pcc_xmin1;
+ volatile unsigned short pcc_xmax1;
+ volatile unsigned short pcc_ymin1;
+ volatile unsigned short pcc_ymax1;
+ volatile unsigned short pcc_xmin2;
+ volatile unsigned short pcc_xmax2;
+ volatile unsigned short pcc_ymin2;
+ volatile unsigned short pcc_ymax2;
+ volatile unsigned short pcc_memory;
+} dc503_regmap_t;
+
+/*
+ * Command register bits
+ */
+
+#define DC503_CMD_TEST 0x8000 /* cursor test flip-flop */
+#define DC503_CMD_HSHI 0x4000 /* Hor sync polarity */
+#define DC503_CMD_VBHI 0x2000 /* Ver blank polarity */
+#define DC503_CMD_LODSA 0x1000 /* load sprite array */
+#define DC503_CMD_FORG2 0x0800 /* force detector2 to one */
+#define DC503_CMD_ENRG2 0x0400 /* enable detector2 */
+#define DC503_CMD_FORG1 0x0200 /* force detector1 to one */
+#define DC503_CMD_ENRG1 0x0100 /* enable detector1 */
+#define DC503_CMD_XHWID 0x0080 /* hair cursor (double) width */
+#define DC503_CMD_XHCL1 0x0040 /* hair clip region */
+#define DC503_CMD_XHCLP 0x0020 /* clip hair inside region */
+#define DC503_CMD_XHAIR 0x0010 /* enable hair cursor */
+#define DC503_CMD_FOPB 0x0008 /* force curs plane B to one */
+#define DC503_CMD_ENPB 0x0004 /* enable curs plane B */
+#define DC503_CMD_FOPA 0x0002 /* force curs plane A to one */
+#define DC503_CMD_ENPA 0x0001 /* enable curs plane A */
+
diff --git a/chips/dtop.h b/chips/dtop.h
new file mode 100644
index 00000000..e37ba04e
--- /dev/null
+++ b/chips/dtop.h
@@ -0,0 +1,241 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dtop.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Definitions for the Desktop serial bus (i2c aka ACCESS).
+ */
+
+#ifndef _DTOP_H_
+#define _DTOP_H_
+
+#define DTOP_MAX_DEVICES 14
+#define DTOP_MAX_MSG_SIZE 36 /* 3 hdr + 32 data + 1 checksum */
+
+typedef struct {
+
+ unsigned char dest_address; /* low bit is zero */
+ unsigned char src_address; /* ditto */
+ union {
+ struct {
+ unsigned char len : 5, /* message byte len */
+ sub : 2, /* sub-address */
+ P : 1; /* Control(1)/Data(0) marker */
+ } val;
+ unsigned char bits; /* quick check */
+ } code;
+
+ /* varzise, checksum byte at end */
+ unsigned char body[DTOP_MAX_MSG_SIZE-3];
+
+} dtop_message, *dtop_message_t;
+
+/*
+ * Standard addresses
+ */
+
+#define DTOP_ADDR_HOST 0x50 /* address for the (only) host */
+#define DTOP_ADDR_DEFAULT 0x6e /* power-up default address */
+#define DTOP_ADDR_FIRST 0x52 /* first assignable address */
+#define DTOP_ADDR_LAST 0x6c /* last, inclusive */
+
+#define DTOP_ADDR_KBD 0x6c /* as used by DEC */
+#define DTOP_ADDR_MOUSE 0x6a
+
+/*
+ * Standard messages
+ */
+
+/* from host to devices */
+
+#define DTOP_MSG_RESET 0xf0 /* preceeded by 0x81: P,len 1 */
+
+#define DTOP_MSG_ID_REQUEST 0xf1 /* preceeded by 0x81: P,len 1 */
+
+#define DTOP_MSG_ASSIGN_ADDRESS 0xf2 /* preceeded by 0x9e: P,len 30 */
+ /* followed by a dtop_id_reply_t */
+ /* and by the new_IC_address */
+
+#define DTOP_MSG_CAP_REQUEST 0xf3 /* preceeded by 0x83: P,len 3 */
+ /* followed by a 16 bit u_offset */
+
+#define DTOP_MSG_APPL_TEST 0xb1 /* preceed by P, sub, len 1 */
+
+/* from devices to host */
+
+#define DTOP_MSG_ATTENTION 0xe0 /* preceeded by P, len */
+# define DTOP_ATN_OK_STATUS 0x00 /* anything else bad */
+ /* followed by 0-30 bytes */
+
+#define DTOP_MSG_ID_REPLY 0xe1 /* preceeded by P,len (29..32) */
+
+typedef struct {
+ unsigned char module_revision[8]; /* ascii, blank padded */
+ unsigned char vendor_name[8];
+ unsigned char module_name[8];
+ int device_number; /* 32 bits cpl-2 */
+ /* 0-3 optional bytes follow, ignore */
+} dtop_id_reply_t;
+
+#define DTOP_MSG_CAP_REPLY 0xe3 /* preceeded by P,len (3..32) */
+ /* followed by 16 bit u_offset */
+ /* followed by data */
+
+#define DTOP_MSG_APPL_SIGNAL 0xa0 /* application level signal */
+# define DTOP_SIG_ATTENTION 0x00
+# define DTOP_SIG_RESET 0x01
+# define DTOP_SIG_HALT 0x02
+
+#define DTOP_MSG_APPL_TREPLY 0xa1 /* followed by status (0-->ok) */
+ /* and 0..30 bytes of result data */
+
+/* reserved message codes (testing, manifacturing) */
+
+#define DTOP_MSG_RES0 0xc0
+#define DTOP_MSG_RES1 0xc1
+#define DTOP_MSG_RES2 0xc2
+#define DTOP_MSG_RES3 0xc3
+
+
+/*
+ * Device specific definitions: Keyboard
+ */
+
+/* from host to keyboard */
+
+#define DTOP_KMSG_CLICK 0x01 /* preceeded by P, sub len 2 */
+# define DTOP_CLICK_VOLUME_MAX 0x7 /* followed by one byte */
+
+#define DTOP_KMSG_BELL 0x02 /* preceeded by P, sub len 2 */
+ /* same as above */
+
+#define DTOP_KMSG_LED 0x03 /* preceeded by P, sub len 2 */
+ /* four lower bits turn leds on */
+
+#define DTOP_KMSG_POLL 0x04 /* preceeded by P, sub len 1 */
+
+/* keyboard sends up to 11 codes in a data message, distinguished values: */
+#define DTOP_KBD_EMPTY 0x00
+#define DTOP_KBD_OUT_ERR 0x01
+#define DTOP_KBD_IN_ERR 0x02
+
+#define DTOP_KBD_KEY_MIN 0x08
+#define DTOP_KBD_KEY_MAX 0xff
+
+/* powerup status values: 0 ok, else.. */
+#define DTOP_KBD_ROM_FAIL 0x01
+#define DTOP_KBD_RAM_FAIL 0x02
+#define DTOP_KBD_KEY_DOWN 0x03
+
+
+/*
+ * Device specific definitions: Locators (mouse)
+ */
+
+/* locator sends this type of report data */
+
+typedef struct {
+ unsigned short buttons; /* 1->pressed */
+ short x;
+ short y;
+ short z;
+ /* possibly 3 more dimensions for gloves */
+} dtop_locator_msg_t;
+
+#define DTOP_LMSG_SET_RATE 0x01 /* preceeded by P,sub, len 2 */
+ /* followed by sampling interval,
+ from 8 to 25 msecs (0->polled */
+
+#define DTOP_LMSG_POLL 0x02 /* preceeded by P,sub, len 1 */
+
+/* Powerup codes same as keyboard */
+
+
+/*
+ * Implementation specific definitions
+ */
+
+typedef union {
+
+ dtop_message unknown_report;
+
+ struct {
+ char last_codes_count;
+ unsigned char last_codes[11]; /* max as per specs */
+ unsigned int last_msec; /* autorepeat state */
+ unsigned short poll_frequency;
+ unsigned char k_ar_state;
+# define K_AR_IDLE 0 /* quiescent, no polling */
+# define K_AR_OFF 4 /* turn off polling pls */
+# define K_AR_ACTIVE 2 /* polling, no autos yet */
+# define K_AR_TRIGGER 1 /* sent one autorepeat */
+ unsigned char bell_volume;
+ unsigned char led_status;
+ } keyboard;
+
+ struct {
+ unsigned char type : 7, /* DEV_MOUSE, DEV_TABLET, .. */
+ relative : 1;
+ unsigned char n_coords;
+ unsigned short prev_buttons;
+# define L_BUTTON_MAX 16
+ unsigned char button_code[L_BUTTON_MAX];
+# define L_COORD_MAX 6
+ unsigned int coordinate[L_COORD_MAX]; /* max 6D */
+ } locator;
+
+ /* add more as they come along */
+
+} dtop_device, *dtop_device_t;
+
+/* All handler functions should have this interface */
+extern int
+ dtop_null_device_handler(
+ dtop_device_t dev,
+ dtop_message_t msg,
+ int event,
+ unsigned char outc),
+ dtop_locator_handler(
+ dtop_device_t dev,
+ dtop_message_t msg,
+ int event,
+ unsigned char outc),
+ dtop_keyboard_handler(
+ dtop_device_t dev,
+ dtop_message_t msg,
+ int event,
+ unsigned char outc);
+
+
+#define DTOP_EVENT_RECEIVE_PACKET 1
+#define DTOP_EVENT_BAD_PACKET 2
+#define DTOP_EVENT_PUTC 4
+#define DTOP_EVENT_POLL 8
+
+
+#endif /* _DTOP_H_ */
diff --git a/chips/dtop_handlers.c b/chips/dtop_handlers.c
new file mode 100644
index 00000000..7a83ea29
--- /dev/null
+++ b/chips/dtop_handlers.c
@@ -0,0 +1,441 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dtop_handlers.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Handler functions for devices attached to the DESKTOP bus.
+ */
+
+#include <dtop.h>
+#if NDTOP > 0
+
+#include <mach_kdb.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <mach/std_types.h>
+#include <device/io_req.h>
+#include <device/tty.h>
+
+#include <chips/busses.h>
+#include <chips/serial_defs.h>
+#include <chips/screen_defs.h>
+#include <mips/PMAX/tc.h>
+
+#include <chips/dtop.h>
+#include <chips/lk201.h>
+
+/*
+ * Default handler function
+ */
+int
+dtop_null_device_handler(
+ dtop_device_t dev,
+ dtop_message_t msg,
+ int event,
+ unsigned char outc)
+{
+ /* See if the message was to the default address (powerup) */
+
+ /* Uhmm, donno how to handle this. Drop it */
+ if (event == DTOP_EVENT_RECEIVE_PACKET)
+ dev->unknown_report = *msg;
+ return 0;
+}
+
+/*
+ * Handler for locator devices (mice)
+ */
+int
+dtop_locator_handler(
+ dtop_device_t dev,
+ dtop_message_t msg,
+ int event,
+ unsigned char outc)
+{
+ register unsigned short buttons;
+ register short coord;
+#if BYTE_MSF
+# define get_short(b0,b1) (((b1)<<8)|(b0))
+#else
+# define get_short(b0,b1) (((b0)<<8)|(b1))
+#endif
+
+ /*
+ * Do the position first
+ */
+ {
+ register int i;
+ register boolean_t moved;
+ int delta_coords[L_COORD_MAX];
+
+ /*
+ * Get all coords, see if it moved at all (buttons!)
+ */
+ moved = FALSE;
+ for (i = 0; i < dev->locator.n_coords; i++) {
+
+ coord = get_short(msg->body[2+(i<<1)],
+ msg->body[3+(i<<1)]);
+
+ if (dev->locator.relative) {
+ /*
+ * Flame on
+ * I am getting tired of this, why do they have to
+ * keep this bug around ? Religion ? Damn, they
+ * design a keyboard for X11 use and forget the mouse ?
+ * Flame off
+ */
+#define BOGUS_DEC_X_AXIS
+#ifdef BOGUS_DEC_X_AXIS
+ if (i == 1) coord = - coord;
+#endif /* BOGUS_DEC_X_AXIS */
+ /* dev->locator.coordinate[i] += coord; */
+ } else {
+ register unsigned int old_coord;
+
+ old_coord = dev->locator.coordinate[i];
+ dev->locator.coordinate[i] = coord;
+ coord = old_coord - coord;
+ }
+ delta_coords[i] = coord;
+ if (coord != 0)
+ moved = TRUE;
+ }
+ if (moved) {
+ /* scale and threshold done higher up */
+ screen_motion_event( 0,
+ dev->locator.type,
+ delta_coords[0],
+ delta_coords[1]);
+ }
+ }
+
+ /*
+ * Time for the buttons now
+ */
+#define new_buttons coord
+ new_buttons = get_short(msg->body[0],msg->body[1]);
+ buttons = new_buttons ^ dev->locator.prev_buttons;
+ if (buttons) {
+ register int i, type;
+
+ dev->locator.prev_buttons = new_buttons;
+ for (i = 0; buttons; i++, buttons >>= 1) {
+
+ if ((buttons & 1) == 0) continue;
+
+ type = (new_buttons & (1<<i)) ?
+ EVT_BUTTON_DOWN : EVT_BUTTON_UP;
+ screen_keypress_event( 0,
+ dev->locator.type,
+ dev->locator.button_code[i],
+ type);
+ }
+ }
+#undef new_buttons
+}
+
+/*
+ * Handler for keyboard devices
+ * Special case: outc set for recv packet means
+ * we are inside the kernel debugger
+ */
+int
+dtop_keyboard_handler(
+ dtop_device_t dev,
+ dtop_message_t msg,
+ int event,
+ unsigned char outc)
+{
+ char save[11];
+ register int msg_len, c;
+
+ /*
+ * Well, really this code handles just an lk401 and in
+ * a very primitive way at that. Should at least emulate
+ * an lk201 decently, and make that a pluggable module.
+ * Sigh.
+ */
+
+ if (event != DTOP_EVENT_RECEIVE_PACKET) {
+ switch (event) {
+ case DTOP_EVENT_POLL:
+ {
+ register unsigned int t, t0;
+
+ /*
+ * Note we will always have at least the
+ * end-of-list marker present (a zero)
+ * Here stop and trigger of autorepeat.
+ * Do not repeat shift keys, either.
+ */
+ {
+ register unsigned char uc, i = 0;
+
+rpt_char:
+ uc = dev->keyboard.last_codes[i];
+
+ if (uc == DTOP_KBD_EMPTY) {
+ dev->keyboard.k_ar_state = K_AR_OFF;
+ return 0;
+ }
+ if ((uc >= LK_R_SHIFT) && (uc <= LK_R_ALT)) {
+ /* sometimes swapped. Grrr. */
+ if (++i < dev->keyboard.last_codes_count)
+ goto rpt_char;
+ dev->keyboard.k_ar_state = K_AR_OFF;
+ return 0;
+ }
+ c = uc;
+ }
+
+ /*
+ * Got a char. See if enough time from stroke,
+ * or from last repeat.
+ */
+ t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500;
+ t = approx_time_in_msec();
+ if ((t - dev->keyboard.last_msec) < t0)
+ return 0;
+
+ dev->keyboard.k_ar_state = K_AR_TRIGGER;
+
+ /*
+ * Simplest thing to do is to mimic lk201
+ */
+ outc = lk201_input(0, LK_REPEAT);
+ if ( ! screen_keypress_event( 0,
+ DEV_KEYBD,
+ c,
+ EVT_BUTTON_UP)) {
+ if (outc > 0) cons_input(0, outc, 0);
+ } else
+ screen_keypress_event( 0,
+ DEV_KEYBD,
+ c,
+ EVT_BUTTON_DOWN);
+ return 0;
+ }
+ default: gimmeabreak();/*fornow*/
+ }
+ return -1;
+ }
+
+ msg_len = msg->code.val.len;
+
+ /* Check for errors */
+ c = msg->body[0];
+ if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) {
+ printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]);
+ if (c != DTOP_KBD_OUT_ERR) return -1;
+ /* spec sez if scan list overflow still there is data */
+ msg->body[0] = 0;
+ }
+
+ dev->keyboard.last_msec = approx_time_in_msec();
+
+ switch (dev->keyboard.k_ar_state) {
+ case K_AR_IDLE:
+ /* if from debugger, timeouts might not be working yet */
+ if (outc == 0xff)
+ break;
+ dtop_keyboard_autorepeat( dev );
+ /* fall through */
+ case K_AR_TRIGGER:
+ dev->keyboard.k_ar_state = K_AR_ACTIVE;
+ break;
+ case K_AR_ACTIVE:
+ break;
+ case K_AR_OFF: gimmeabreak(); /* ??? */
+ dev->keyboard.k_ar_state = K_AR_IDLE;
+ }
+
+ /*
+ * We can only assume that pressed keys are reported in the
+ * same order (a minimum of sanity, please) across scans.
+ * To make things readable, do a first pass cancelling out
+ * all keys that are still pressed, and a second one generating
+ * events. While generating events, do the upstrokes first
+ * from oldest to youngest, then the downstrokes from oldest
+ * to youngest. This copes with lost packets and provides
+ * a reasonable model even if scans are too slow.
+ */
+
+ /* make a copy of new state first */
+ {
+ register char *p, *q, *e;
+
+ p = save;
+ q = (char*)msg->body;
+ e = (char*)&msg->body[msg_len];
+
+ while (q < e)
+ *p++ = *q++;
+ }
+
+ /*
+ * Do the cancelling pass
+ */
+ {
+ register char *ls, *le, *ns, *ne, *sync;
+
+ ls = (char*)dev->keyboard.last_codes;
+ le = (char*)&dev->keyboard.last_codes[dev->keyboard.last_codes_count];
+ ns = (char*)msg->body;
+ ne = (char*)&msg->body[msg_len];
+
+ /* sync marks where to restart scanning, saving
+ time thanks to ordering constraints */
+ for (sync = ns; ls < le; ls++) {
+ register char c = *ls;
+ for (ns = sync; ns < ne; ns++)
+ if (c == *ns) {
+ *ls = *ns = 0;
+ sync = ns + 1;
+ break;
+ }
+ /* we could already tell if c is an upstroke,
+ but see the above discussion about errors */
+ }
+ }
+ /*
+ * Now generate all upstrokes
+ */
+ {
+ register char *ls, *le;
+ register unsigned char c;
+
+ le = (char*)dev->keyboard.last_codes;
+ ls = (char*)&dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1];
+
+ for ( ; ls >= le; ls--)
+ if (c = *ls) {
+ /* keep kernel notion of lk201 state consistent */
+ (void) lk201_input(0,c);
+
+ if (outc == 0)
+ screen_keypress_event(0,
+ DEV_KEYBD,
+ c,
+ EVT_BUTTON_UP);
+ }
+ }
+ /*
+ * And finally the downstrokes
+ */
+ {
+ register char *ns, *ne, c, retc;
+
+ ne = (char*)msg->body;
+ ns = (char*)&msg->body[msg_len - 1];
+ retc = 0;
+
+ for ( ; ns >= ne; ns--)
+ if (c = *ns) {
+ register unsigned char data;
+
+ data = c;
+ c = lk201_input(0, data);
+
+ if (c == -2) { /* just returned from kdb */
+ /* NOTE: many things have happened while
+ we were sitting on the stack, now it
+ is last_codes that holds the truth */
+#if 1
+ /* But the truth might not be welcome.
+ If we get out because we hit RETURN
+ on the rconsole line all is well,
+ but if we did it from the keyboard
+ we get here on the downstroke. Then
+ we will get the upstroke which we
+ would give to X11. People complained
+ about this extra keypress.. so they
+ lose everything. */
+
+ dev->keyboard.last_codes_count = 1;
+ dev->keyboard.last_codes[0] = 0;
+#endif
+ return -1;
+ }
+
+ /*
+ * If X11 had better code for the keyboard this
+ * would be an EVT_BUTTON_DOWN. But that would
+ * screwup the REPEAT function. Grrr.
+ */
+ /* outc non zero sez we are in the debugger */
+ if (outc == 0) {
+ if (screen_keypress_event(0,
+ DEV_KEYBD,
+ data,
+ EVT_BUTTON_DOWN))
+ c = -1; /* consumed by X */
+ else
+ if (c > 0) cons_input(0, c, 0);
+ }
+ /* return the xlated keycode anyways */
+ if ((c > 0) && (retc == 0))
+ retc = c;
+ }
+ outc = retc;
+ }
+ /* install new scan state */
+ {
+ register char *p, *q, *e;
+
+ p = (char*)dev->keyboard.last_codes;
+ q = (char*)save;
+ e = (char*)&save[msg_len];
+
+ while (q < e)
+ *p++ = *q++;
+ dev->keyboard.last_codes_count = msg_len;
+ }
+ return outc;
+}
+
+/*
+ * Polled operations: we must do autorepeat by hand. Sigh.
+ */
+dtop_keyboard_autorepeat(
+ dtop_device_t dev)
+{
+ spl_t s = spltty();
+
+ if (dev->keyboard.k_ar_state != K_AR_IDLE)
+ dtop_keyboard_handler( dev, 0, DTOP_EVENT_POLL, 0);
+
+ if (dev->keyboard.k_ar_state == K_AR_OFF)
+ dev->keyboard.k_ar_state = K_AR_IDLE;
+ else
+ timeout( dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency);
+
+ splx(s);
+}
+
+#endif /*NDTOP>0*/
diff --git a/chips/dtop_hdw.c b/chips/dtop_hdw.c
new file mode 100644
index 00000000..6962d709
--- /dev/null
+++ b/chips/dtop_hdw.c
@@ -0,0 +1,644 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dtop_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Hardware-level operations for the Desktop serial line
+ * bus (i2c aka ACCESS).
+ */
+
+#include <dtop.h>
+#if NDTOP > 0
+#include <bm.h>
+#include <platforms.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <mach/std_types.h>
+#include <device/io_req.h>
+#include <device/tty.h>
+
+#include <chips/busses.h>
+#include <chips/serial_defs.h>
+#include <chips/screen_defs.h>
+#include <chips/lk201.h>
+#include <mips/PMAX/tc.h>
+
+#include <chips/dtop.h>
+
+#define DTOP_MAX_POLL 0x7fff /* about half a sec */
+
+#ifdef MAXINE
+
+typedef volatile unsigned int *data_reg_t; /* uC */
+#define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff)
+#define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; }
+
+typedef volatile unsigned int *poll_reg_t; /* SIR */
+#define DTOP_RX_AVAIL(poll) (*(poll) & 1)
+#define DTOP_TX_AVAIL(poll) (*(poll) & 2)
+
+#else
+
+define how to get/put DTOP packets on this box
+
+#endif
+
+/*
+ * Driver status
+ */
+
+struct dtop_softc {
+ data_reg_t data;
+ poll_reg_t poll;
+ char polling_mode;
+ char probed_once;
+ short bad_pkts;
+
+ struct dtop_ds {
+ int (*handler)(dtop_device_t,
+ dtop_message_t,
+ int,
+ unsigned char);
+ dtop_device status;
+ } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1];
+
+# define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1)
+
+} dtop_softc_data[NDTOP];
+
+typedef struct dtop_softc *dtop_softc_t;
+
+dtop_softc_t dtop_softc[NDTOP];
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int dtop_probe(), dtop_intr();
+static void dtop_attach();
+
+vm_offset_t dtop_std[NDTOP] = { 0 };
+struct bus_device *dtop_info[NDTOP];
+struct bus_driver dtop_driver =
+ { dtop_probe, 0, dtop_attach, 0, dtop_std, "dtop", dtop_info,};
+
+
+int dtop_print_debug = 0;
+
+/*
+ * Adapt/Probe/Attach functions
+ */
+
+set_dtop_address( dtopunit, poll_reg)
+ data_reg_t poll_reg;
+{
+ int i;
+
+ extern int dtop_probe(), dtop_param(), dtop_start(),
+ dtop_putc(), dtop_getc(),
+ dtop_pollc(), dtop_mctl(), dtop_softCAR();
+
+ dtop_std[dtopunit] = (vm_offset_t)poll_reg;
+
+ /* Do this here */
+ console_probe = dtop_probe;
+ console_param = dtop_param;
+ console_start = dtop_start;
+ console_putc = dtop_putc;
+ console_getc = dtop_getc;
+ console_pollc = dtop_pollc;
+ console_mctl = dtop_mctl;
+ console_softCAR = dtop_softCAR;
+
+}
+
+dtop_probe( data_reg, ui)
+ data_reg_t data_reg;
+ struct bus_device *ui;
+{
+ int dtopunit = ui->unit, i;
+ dtop_softc_t dtop;
+
+ dtop = &dtop_softc_data[dtopunit];
+ dtop_softc[dtopunit] = dtop;
+
+ dtop->poll = (poll_reg_t)dtop_std[dtopunit];
+ dtop->data = data_reg;
+
+ for (i = 0; i < DTOP_MAX_DEVICES; i++)
+ dtop->device[i].handler = dtop_null_device_handler;
+
+ /* a lot more needed here, fornow: */
+ dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler;
+ dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.type =
+ DEV_MOUSE;
+ dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.relative =
+ 1;
+ dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.button_code[0] =
+ KEY_LEFT_BUTTON;
+ dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.button_code[1] =
+ KEY_RIGHT_BUTTON;
+ dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.button_code[2] =
+ KEY_MIDDLE_BUTTON;
+ dtop->device[DTOP_DEVICE_NO(0x6a)].status.locator.n_coords =
+ 2;
+
+ dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler;
+ dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.poll_frequency =
+ (hz * 5) / 100; /* x0.01 secs */
+ dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.bell_volume =
+ DTOP_CLICK_VOLUME_MAX;
+
+ return 1;
+}
+
+static void
+dtop_attach(ui)
+ struct bus_device *ui;
+{
+ int i;
+
+ /* Initialize all the console ttys */
+ for (i = 0; i < 4; i++)
+ ttychars(console_tty[i]);
+ /* Mark keyboard and mouse present */
+ for (i = 0; i < 2; i++)
+ console_tty[i]->t_addr = (char*)1;
+}
+
+/*
+ * Polled I/O (debugger)
+ */
+dtop_pollc(unit, on)
+ boolean_t on;
+{
+ dtop_softc_t dtop;
+
+ dtop = dtop_softc[unit];
+ if (on) {
+ dtop->polling_mode++;
+#if NBM > 0
+ screen_on_off(unit, TRUE);
+#endif NBM > 0
+ } else
+ dtop->polling_mode--;
+}
+
+/*
+ * Interrupt routine
+ */
+dtop_intr (unit, spllevel, recvd)
+ spl_t spllevel;
+ boolean_t recvd;
+{
+
+ if (recvd) {
+ dtop_message msg;
+ int devno;
+ dtop_softc_t dtop;
+
+ ssaver_bump(unit);
+
+#ifdef mips
+ splx(spllevel);
+#endif
+
+ dtop = dtop_softc[unit];
+ if (dtop_get_packet(dtop, &msg) < 0) {
+ if (dtop_print_debug)
+ printf("%s", "dtop: overrun (or stray)\n");
+ return;
+ }
+
+ devno = DTOP_DEVICE_NO(msg.src_address);
+ if (devno < 0 || devno > 15) return; /* sanity */
+
+ (void) (*dtop->device[devno].handler)
+ (&dtop->device[devno].status, &msg,
+ DTOP_EVENT_RECEIVE_PACKET, 0);
+
+ } else {
+ /* fornow xmit is not intr based */
+ (*tc_enable_interrupt)( dtop_info[unit]->adaptor, FALSE, TRUE);
+ }
+}
+
+boolean_t
+dtop_start(tp)
+ struct tty *tp;
+{
+ register int line, temp;
+
+ /* no, we do not need a char out first */
+ return FALSE;
+}
+
+dtop_w_test(n, a,b,c,d,e,f,g,h)
+{
+ int *p = (int*)0xbc2a0000;
+
+ if (n <= 0) return;
+
+ a <<= 8; *p = a;
+ if (--n == 0) goto out;
+ delay(20);
+ b <<= 8; *p = b;
+ if (--n == 0) goto out;
+ delay(20);
+ c <<= 8; *p = c;
+ if (--n == 0) goto out;
+ delay(20);
+ d <<= 8; *p = d;
+ if (--n == 0) goto out;
+ delay(20);
+ e <<= 8; *p = e;
+ if (--n == 0) goto out;
+ delay(20);
+ f <<= 8; *p = f;
+ if (--n == 0) goto out;
+ delay(20);
+ g <<= 8; *p = g;
+ if (--n == 0) goto out;
+ delay(20);
+ h <<= 8; *p = h;
+out:
+ delay(10000);
+ {
+ int buf[100];
+
+ delay(20);
+ a = *p;
+ buf[0] = a;
+ c = 1;
+ for (n = 0; n < 100; n++) {
+ delay(20);
+ b = *p;
+ if (b != a) {
+ buf[c++] = b;
+ b = a;
+ }
+ }
+ for (n = 0; n < c; n++)
+ db_printf("%x ", ((buf[n])>>8)&0xff);
+ }
+ return c;
+}
+
+/*
+ * Take a packet off dtop interface
+ * A packet MUST be there, this is not checked for.
+ */
+#define DTOP_ESC_CHAR 0xf8
+dtop_escape(c)
+{
+ /* I donno much about this stuff.. */
+ switch (c) {
+ case 0xe8: return 0xf8;
+ case 0xe9: return 0xf9;
+ case 0xea: return 0xfa;
+ case 0xeb: return 0xfb;
+ default: /* printf("{esc %x}", c); */
+ return c;
+ }
+}
+
+dtop_get_packet(dtop, pkt)
+ dtop_softc_t dtop;
+ dtop_message_t pkt;
+{
+ register poll_reg_t poll;
+ register data_reg_t data;
+ register int max, i, len;
+ register unsigned char c;
+
+ poll = dtop->poll;
+ data = dtop->data;
+
+ /*
+ * The interface does not handle us the first byte,
+ * which is our address and cannot ever be anything
+ * else but 0x50. This is a good thing, it makes
+ * the average packet exactly one word long, too.
+ */
+ pkt->src_address = DTOP_GET_BYTE(data);
+
+ for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
+ delay(16);
+ if (max == DTOP_MAX_POLL) goto bad;
+ pkt->code.bits = DTOP_GET_BYTE(data);
+
+ /*
+ * Now get data and checksum
+ */
+ len = pkt->code.val.len + 1;
+ c = 0;
+ for (i = 0; i < len; i++) {
+
+again: for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
+ delay(16);
+ if (max == DTOP_MAX_POLL) goto bad;
+ if (c == DTOP_ESC_CHAR) {
+ c = dtop_escape(DTOP_GET_BYTE(data) & 0xff);
+ } else {
+ c = DTOP_GET_BYTE(data);
+ if (c == DTOP_ESC_CHAR)
+ goto again;
+ }
+
+ pkt->body[i] = c;
+ }
+ return len;
+bad:
+ dtop->bad_pkts++;
+ return -1;
+}
+
+/* Conversely... */
+dtop_put_packet(dtop, pkt)
+ dtop_softc_t dtop;
+ dtop_message_t pkt;
+{
+ register int i, max;
+ register unsigned char *cp;
+ register unsigned int spl;
+ register unsigned char c;
+
+ spl = spltty();
+ pkt->src_address = pkt->dest_address;
+ i = 0;
+ cp = (unsigned char *)&pkt->src_address;
+ while (i < pkt->code.val.len + 2) {
+ for (max = 0; max < DTOP_MAX_POLL && !DTOP_TX_AVAIL(dtop->poll);
+ max++);
+ if (max == DTOP_MAX_POLL)
+ goto bad;
+ DTOP_PUT_BYTE(dtop->data, *cp);
+ cp++;
+ i++;
+ }
+ for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(dtop->poll); max++)
+ delay(16);
+ if (max == DTOP_MAX_POLL)
+ goto bad;
+ c = DTOP_GET_BYTE(dtop->data);
+ if (c == DTOP_ESC_CHAR) {
+ for (max = 0; (max < DTOP_MAX_POLL)
+ && !DTOP_RX_AVAIL(dtop->poll); max++)
+ delay(16);
+ if (max == DTOP_MAX_POLL)
+ goto bad;
+ c = DTOP_GET_BYTE(dtop->data);
+ }
+ splx(spl);
+ switch (c) {
+ case 0xfb: /* XMT, ok */
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+ bad:
+ splx(spl);
+ return 0;
+}
+
+
+/*
+ * Get a char from a specific DTOP line
+ * [this is only used for console&screen purposes]
+ */
+dtop_getc( unit, line, wait, raw )
+ boolean_t wait;
+ boolean_t raw;
+{
+ register int c;
+ dtop_softc_t dtop;
+
+ dtop = dtop_softc[unit];
+again:
+ c = -1;
+
+ /*
+ * Try rconsole first
+ */
+ if (rcline && line == SCREEN_LINE_KEYBOARD) {
+ c = scc_getc( 0, rcline, FALSE, raw);
+ if (c != -1) return c;
+ }
+
+ /*
+ * Now check keyboard
+ */
+ if (DTOP_RX_AVAIL(dtop->poll)) {
+
+ dtop_message msg;
+ struct dtop_ds *ds;
+
+ if (dtop_get_packet(dtop, &msg) >= 0) {
+
+ ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)];
+ if (ds->handler == dtop_keyboard_handler) {
+
+ c = dtop_keyboard_handler(
+ &ds->status, &msg,
+ DTOP_EVENT_RECEIVE_PACKET, -1);
+
+ if (c > 0) return c;
+
+ c = -1;
+ }
+ }
+ }
+
+ if (wait && (c == -1)) {
+ delay(100);
+ goto again;
+ }
+
+ return c;
+}
+
+/*
+ * Put a char on a specific DTOP line
+ */
+dtop_putc( unit, line, c )
+{
+ if (rcline && line == rcline) {
+ scc_putc(0, rcline, c);
+ }
+/* dprintf("%c", c); */
+}
+
+dtop_param(tp, line)
+ struct tty *tp;
+{
+ if (tp->t_ispeed == 0)
+ ttymodem(tp, 0);
+ else
+ /* called too early to invoke ttymodem, sigh */
+ tp->t_state |= TS_CARR_ON;
+}
+
+/*
+ * Modem control functions, we don't need 'em
+ */
+dtop_mctl(dev, bits, how)
+ int dev;
+ int bits, how;
+{
+ return 0;
+}
+
+dtop_softCAR(unit, line, on)
+{
+}
+
+/* Some keyboard specific stuff, probably belongs elsewhere */
+
+dtop_kbd_probe(unit)
+{
+ if (dtop_std[unit]) {
+ lk201_probe(unit);
+ return 1;
+ }
+ return 0;
+}
+
+io_return_t
+dtop_set_status(unit, flavor, status, status_count)
+ int unit;
+ int flavor;
+ dev_status_t status;
+ unsigned int status_count;
+{
+ dtop_device_t dev;
+
+ dev = &dtop_softc[unit]->device[DTOP_DEVICE_NO(0x6c)].status;
+
+ switch (flavor) {
+ case LK201_SEND_CMD: {
+ register lk201_cmd_t *cmd = (lk201_cmd_t *)status;
+ unsigned int cnt;
+
+ if ((status_count < (sizeof(*cmd)/sizeof(int))) ||
+ ((cnt = cmd->len) > 2))
+ return D_INVALID_SIZE;
+ switch (cmd->command) {
+ case LK_CMD_ENB_BELL:
+ cmd->params[0] ^= 0x7;
+ if (dtop_print_debug)
+ printf("LK_CMD_ENB_BELL %d\n", cmd->params[0]);
+ dev->keyboard.bell_volume = cmd->params[0] & 0x7;
+ break;
+ case LK_CMD_DIS_BELL:
+ dev->keyboard.bell_volume = 0;
+ break;
+ case LK_CMD_BELL:
+ dtop_ring_bell(unit);
+ break;
+ case LK_CMD_LEDS_ON:
+ cmd->params[0] &= ~0x80;
+ if (dtop_print_debug)
+ printf("LK_CMD_LEDS_ON %d %x\n",
+ cmd->params[0], cmd->params[0]);
+ dev->keyboard.led_status |= cmd->params[0];
+ dtop_leds(unit, dev->keyboard.led_status);
+ break;
+ case LK_CMD_LEDS_OFF:
+ cmd->params[0] &= ~0x80;
+ dev->keyboard.led_status &= ~cmd->params[0];
+ dtop_leds(unit, dev->keyboard.led_status);
+ break;
+ case LK_CMD_ENB_KEYCLK:
+ case LK_CMD_DIS_KEYCLK:
+ case LK_CMD_SOUND_CLK:
+ case LK_CMD_DIS_CTLCLK:
+ case LK_CMD_ENB_CTLCLK:
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return lk201_set_status(unit, flavor, status, status_count);
+}
+
+dtop_kbd_reset(unit)
+{
+ return lk201_reset(unit);
+}
+
+#define DTOP_BITS(p, len) (((p) << 7) | (len))
+
+dtop_ring_bell(unit)
+{
+ dtop_message msg;
+ dtop_device_t dev;
+ int vol;
+
+ dev = &dtop_softc[unit]->device[DTOP_DEVICE_NO(0x6c)].status;
+ vol = dev->keyboard.bell_volume;
+
+ if (dtop_print_debug)
+ printf("dtop_ring_bell: %d\n", vol);
+ msg.dest_address = DTOP_ADDR_KBD;
+ msg.code.bits = DTOP_BITS(1, 2);
+ msg.body[0] = DTOP_KMSG_BELL;
+ msg.body[1] = vol;
+ if (!dtop_put_packet(dtop_softc[unit], &msg)) {
+ if (dtop_print_debug)
+ printf("dtop_ring_bell: dtop_put_packet failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+dtop_leds(unit, mask)
+{
+ dtop_message msg;
+
+ if (dtop_print_debug)
+ printf("dtop_leds %x\n", mask);
+ msg.dest_address = DTOP_ADDR_KBD;
+ msg.code.bits = DTOP_BITS(1, 2);
+ msg.body[0] = DTOP_KMSG_LED;
+ msg.body[1] = mask;
+ if (!dtop_put_packet(dtop_softc[unit], &msg)) {
+ if (dtop_print_debug)
+ printf("dtop_leds: dtop_put_packet failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+
+
+#endif NDTOP > 0
diff --git a/chips/dz_7085.h b/chips/dz_7085.h
new file mode 100644
index 00000000..66c8916b
--- /dev/null
+++ b/chips/dz_7085.h
@@ -0,0 +1,153 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dz_7085.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Defines for the DEC 7085 Serial Line Controller Chip
+ */
+
+#define NDZ_LINE 4
+
+/*
+ * What's hanging off those 4 lines
+ */
+
+#define DZ_LINE_KEYBOARD 0
+#define DZ_LINE_MOUSE 1
+#define DZ_LINE_MODEM 2
+#define DZ_LINE_PRINTER 3
+
+/*
+ * Register layout, ignoring padding
+ */
+typedef struct {
+ volatile unsigned short dz_csr; /* Control and Status */
+ volatile unsigned short dz_rbuf; /* Rcv buffer (RONLY) */
+ volatile unsigned short dz_tcr; /* Xmt control (R/W)*/
+ volatile unsigned short dz_tbuf; /* Xmt buffer (WONLY)*/
+# define dz_lpr dz_rbuf /* Line parameters (WONLY)*/
+# define dz_msr dz_tbuf /* Modem status (RONLY)*/
+} dz_regmap_t;
+
+/*
+ * CSR bits
+ */
+
+#define DZ_CSR_MBZ 0x3c07 /* Must be zero */
+#define DZ_CSR_MAINT 0x0008 /* rw: Maintenance mode */
+#define DZ_CSR_CLR 0x0010 /* rw: Master clear (init) */
+#define DZ_CSR_MSE 0x0020 /* rw: Master scan enable */
+#define DZ_CSR_RIE 0x0040 /* rw: Rcv Interrupt Enable */
+#define DZ_CSR_RDONE 0x0080 /* ro: Rcv done (silo avail) */
+#define DZ_CSR_TLINE 0x0300 /* ro: Lineno ready for xmt */
+#define DZ_CSR_TIE 0x4000 /* rw: Xmt Interrupt Enable */
+#define DZ_CSR_TRDY 0x8000 /* ro: Xmt ready */
+
+/*
+ * Receiver buffer (top of silo). Read-only.
+ */
+
+#define DZ_SILO_DEEP 64
+
+#define DZ_RBUF_CHAR 0x00ff /* Received character */
+#define DZ_RBUF_RLINE 0x0300 /* Line it came from */
+#define DZ_RBUF_XXXX 0x0c00 /* Reads as zero */
+#define DZ_RBUF_PERR 0x1000 /* Parity error */
+#define DZ_RBUF_FERR 0x2000 /* Framing error (break) */
+#define DZ_RBUF_OERR 0x4000 /* Silo overrun */
+#define DZ_RBUF_VALID 0x8000 /* Info is valid */
+
+/*
+ * Line parameters register. Write-only.
+ */
+
+#define DZ_LPAR_LINE 0x0003 /* Bin encoded line no */
+#define DZ_LPAR_MBZ 0xe004 /* Must be zero */
+#define DZ_LPAR_CLEN 0x0018 /* Character length: */
+# define DZ_LPAR_5BITS 0x0000 /* 5 bits per char */
+# define DZ_LPAR_6BITS 0x0008 /* 6 bits per char */
+# define DZ_LPAR_7BITS 0x0010 /* 7 bits per char */
+# define DZ_LPAR_8BITS 0x0018 /* 8 bits per char */
+#define DZ_LPAR_STOP 0x0020 /* stop bits: off->1, on->2 */
+#define DZ_LPAR_PAR_ENB 0x0040 /* generate/detect parity */
+#define DZ_LPAR_ODD_PAR 0x0080 /* generate/detect ODD parity */
+#define DZ_LPAR_SPEED 0x0f00 /* Speed code: */
+# define DZ_LPAR_50 0x0000 /* 50 baud */
+# define DZ_LPAR_75 0x0100 /* 75 baud */
+# define DZ_LPAR_110 0x0200 /* 110 baud */
+# define DZ_LPAR_134_5 0x0300 /* 134.5 baud */
+# define DZ_LPAR_150 0x0400 /* 150 baud */
+# define DZ_LPAR_300 0x0500 /* 300 baud */
+# define DZ_LPAR_600 0x0600 /* 600 baud */
+# define DZ_LPAR_1200 0x0700 /* 1200 baud */
+# define DZ_LPAR_1800 0x0800 /* 1800 baud */
+# define DZ_LPAR_2000 0x0900 /* 2000 baud */
+# define DZ_LPAR_2400 0x0a00 /* 2400 baud */
+# define DZ_LPAR_3600 0x0b00 /* 3600 baud */
+# define DZ_LPAR_4800 0x0c00 /* 4800 baud */
+# define DZ_LPAR_7200 0x0d00 /* 7200 baud */
+# define DZ_LPAR_9600 0x0e00 /* 9600 baud */
+# define DZ_LPAR_MAX_SPEED 0x0f00 /* 19200/38400 baud */
+#define DZ_LPAR_ENABLE 0x1000 /* Enable receiver */
+
+/*
+ * Xmt control register
+ */
+
+#define DZ_TCR_LNENB 0x000f /* rw: Xmt line enable */
+#define DZ_TCR_MBZ 0xf0f0 /* Must be zero */
+#define DZ_TCR_DTR3 0x0100 /* rw: DTR on printer line */
+#define DZ_TCR_RTS3 0x0200 /* rw: RTS on printer line */
+#define DZ_TCR_DTR2 0x0400 /* rw: DTR on modem line */
+#define DZ_TCR_RTS2 0x0800 /* rw: RTS on modem line */
+
+/*
+ * Modem status register. Read-only.
+ */
+
+#define DZ_MSR_CTS3 0x0001 /* Clear To Send, printer line */
+#define DZ_MSR_DSR3 0x0002 /* Data Set Ready, printer line */
+#define DZ_MSR_CD3 0x0004 /* Carrier Detect, printer line */
+#define DZ_MSR_RI3 0x0008 /* Ring Indicator, printer line */
+#define DZ_MSR_XXXX 0xf0f0 /* Reads as zero */
+#define DZ_MSR_CTS2 0x0100 /* Clear To Send, modem line */
+#define DZ_MSR_DSR2 0x0200 /* Data Set Ready, modem line */
+#define DZ_MSR_CD2 0x0400 /* Carrier Detect, modem line */
+#define DZ_MSR_RI2 0x0800 /* Ring Indicator, modem line */
+
+
+/*
+ * Xmt buffer
+ */
+
+#define DZ_TBUF_CHAR 0x00ff /* Xmt character */
+#define DZ_TBUF_BREAK_0 0x0100 /* set line 0 to space */
+#define DZ_TBUF_BREAK_1 0x0200 /* set line 1 to space */
+#define DZ_TBUF_BREAK_2 0x0400 /* set line 2 to space */
+#define DZ_TBUF_BREAK_3 0x0800 /* set line 3 to space */
+#define DZ_TBUF_MBZ 0xf000 /* Must be zero */
diff --git a/chips/dz_defs.h b/chips/dz_defs.h
new file mode 100644
index 00000000..7c792bb9
--- /dev/null
+++ b/chips/dz_defs.h
@@ -0,0 +1,65 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dz_defs.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Internal definitions for the DZ Serial Line Driver
+ */
+
+#include <mach/std_types.h>
+#include <chips/busses.h>
+
+#include <kern/time_out.h>
+#include <sys/syslog.h>
+
+#include <device/io_req.h>
+#include <device/conf.h>
+#include <device/tty.h>
+#include <device/errno.h>
+
+#include <chips/dz_7085.h>
+
+extern struct tty *dz_tty[];
+
+extern struct pseudo_dma {
+ dz_regmap_t *p_addr;
+ char *p_mem;
+ char *p_end;
+ int p_arg;
+ int (*p_fcn)();
+} dz_pdma[];
+
+extern int rcline, cnline;
+extern int console;
+
+/*
+ * Modem control operations on DZ lines
+ */
+
+extern unsigned dz_mctl(/* int, int, int */);
+
diff --git a/chips/dz_hdw.c b/chips/dz_hdw.c
new file mode 100644
index 00000000..fa472828
--- /dev/null
+++ b/chips/dz_hdw.c
@@ -0,0 +1,649 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: dz_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Hardware-level operations for the DZ Serial Line Driver
+ */
+
+#include <dz_.h>
+#if NDZ_ > 0
+#include <bm.h>
+#include <platforms.h>
+
+#include <mach_kdb.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <device/io_req.h>
+#include <device/tty.h>
+
+#include <chips/busses.h>
+#include <chips/screen_defs.h>
+#include <chips/serial_defs.h>
+
+#include <chips/dz_7085.h>
+
+
+#ifdef DECSTATION
+#include <mips/mips_cpu.h>
+#include <mips/PMAX/kn01.h>
+#define DZ_REGS_DEFAULT (vm_offset_t)PHYS_TO_K1SEG(KN01_SYS_DZ)
+#define PAD(n) char n[6];
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#define DZ_REGS_DEFAULT 0
+#define wbflush()
+#define check_memory(addr,dow) ((dow) ? wbadaddr(addr,4) : badaddr(addr,4))
+#define PAD(n) char n[2];
+#endif /*VAXSTATION*/
+
+#ifndef PAD
+#define PAD(n)
+#endif
+
+typedef struct {
+ volatile unsigned short dz_csr; /* Control and Status */
+ PAD(pad0)
+ volatile unsigned short dz_rbuf; /* Rcv buffer (RONLY) */
+ PAD(pad1)
+ volatile unsigned short dz_tcr; /* Xmt control (R/W)*/
+ PAD(pad2)
+ volatile unsigned short dz_tbuf; /* Xmt buffer (WONLY)*/
+# define dz_lpr dz_rbuf /* Line parameters (WONLY)*/
+# define dz_msr dz_tbuf /* Modem status (RONLY)*/
+ PAD(pad3)
+} dz_padded_regmap_t;
+
+
+/* this is ok both for rcv (char) and xmt (csr) */
+#define LINEOF(x) (((x) >> 8) & 0x3)
+
+/*
+ * Driver status
+ */
+struct dz7085_softc {
+ dz_padded_regmap_t *regs;
+ unsigned short breaks;
+ unsigned short fake; /* missing rs232 bits */
+ int polling_mode;
+ unsigned short prev_msr;
+ char softCAR;
+} dz7085_softc_data[NDZ_];
+
+typedef struct dz7085_softc *dz7085_softc_t;
+
+dz7085_softc_t dz7085_softc[NDZ_];
+
+static void check_car();
+static void check_ring();
+
+dz7085_softCAR(unit, line, on)
+{
+ if (on)
+ dz7085_softc[unit]->softCAR |= 1<<line;
+ else
+ dz7085_softc[unit]->softCAR &= ~(1 << line);
+}
+
+static
+short dz7085_speeds[] =
+ { 0, DZ_LPAR_50, DZ_LPAR_75, DZ_LPAR_110, DZ_LPAR_134_5, DZ_LPAR_150,
+ 0, DZ_LPAR_300, DZ_LPAR_600, DZ_LPAR_1200, DZ_LPAR_1800, DZ_LPAR_2400,
+ DZ_LPAR_4800, DZ_LPAR_9600, DZ_LPAR_MAX_SPEED, 0 };
+
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int dz7085_probe(), dz7085_intr();
+static void dz7085_attach();
+
+vm_offset_t dz7085_std[NDZ_] = { DZ_REGS_DEFAULT, };
+struct bus_device *dz7085_info[NDZ_];
+struct bus_driver dz_driver =
+ { dz7085_probe, 0, dz7085_attach, 0, dz7085_std, "dz", dz7085_info,};
+
+/*
+ * Adapt/Probe/Attach functions
+ */
+
+static boolean_t dz7085_full_modem = FALSE;
+boolean_t dz7085_uses_modem_control = FALSE;/* patch this with adb */
+
+set_dz_address( unit, regs, has_modem)
+ vm_offset_t regs;
+ boolean_t has_modem;
+{
+ extern int dz7085_probe(), dz7085_param(), dz7085_start(),
+ dz7085_putc(), dz7085_getc(),
+ dz7085_pollc(), dz7085_mctl(), dz7085_softCAR();
+
+ dz7085_std[unit] = regs;
+ dz7085_full_modem = has_modem & dz7085_uses_modem_control;
+
+ /* Do this here */
+ console_probe = dz7085_probe;
+ console_param = dz7085_param;
+ console_start = dz7085_start;
+ console_putc = dz7085_putc;
+ console_getc = dz7085_getc;
+ console_pollc = dz7085_pollc;
+ console_mctl = dz7085_mctl;
+ console_softCAR = dz7085_softCAR;
+
+}
+
+dz7085_probe( xxx, ui)
+ struct bus_device *ui;
+{
+ int unit = ui->unit;
+ dz7085_softc_t sc;
+ register int cntr;
+ register dz_padded_regmap_t *regs;
+
+ static int probed_once = 0;
+
+ regs = (dz_padded_regmap_t *)dz7085_std[unit]; /* like the old days! */
+ if (regs == 0)
+ return 0;
+ /*
+ * If this is not there we are toast
+ */
+ if (check_memory(regs, 0))
+ return 0;
+
+ if (probed_once++)
+ return 1;
+
+ sc = &dz7085_softc_data[unit];
+ dz7085_softc[unit] = sc;
+ sc->regs = regs;
+
+ for (cntr = unit*NDZ_LINE; cntr < NDZ_LINE*(unit+1); cntr++) {
+ console_tty[cntr]->t_addr = (char*)regs;
+ console_tty[cntr]->t_state |= TS_MIN;
+ }
+
+ /* pmaxen et al. lack many modem bits */
+ dz7085_set_modem_control(sc, dz7085_full_modem);
+
+ regs->dz_tcr = 0;/* disable all lines, drop RTS,DTR */
+ return 1;
+}
+
+boolean_t dz7085_timer_started = FALSE;
+
+static void
+dz7085_attach(ui)
+ register struct bus_device *ui;
+{
+ int unit = ui->unit;
+ extern dz7085_scan();
+ extern int tty_inq_size;
+ int i;
+
+ /* We only have 4 ttys, but always at 9600
+ * Give em a lot of room
+ */
+ tty_inq_size = 2048;
+ for (i = 0; i < (NDZ_*NDZ_LINE); i++)
+ ttychars(console_tty[i]);
+
+ if (!dz7085_timer_started) {
+ dz7085_timer_started = TRUE;
+ dz7085_scan();
+ }
+
+#if NBM > 0
+ if (SCREEN_ISA_CONSOLE()) {
+ printf("\n sl0: "); lk201_attach(0, unit);
+ printf("\n sl1: "); mouse_attach(0, unit);
+ printf("\n sl2: \n sl3: ");
+ if (rcline == 3) printf("( rconsole )");
+ } else {
+#endif /*NBM > 0*/
+ printf("\n sl0:\n sl1:\n sl2:\n sl3: ( alternate console )");
+#if NBM > 0
+ }
+#endif
+}
+
+/*
+ * Would you like to make a phone call ?
+ */
+dz7085_set_modem_control(sc, on)
+ dz7085_softc_t sc;
+ boolean_t on;
+{
+ if (on)
+ /* your problem if the hardware then is broke */
+ sc->fake = 0;
+ else
+ sc->fake = DZ_MSR_CTS3|DZ_MSR_DSR3|DZ_MSR_CD3|
+ DZ_MSR_CTS2|DZ_MSR_CD2;
+}
+
+/*
+ * Polled I/O (debugger)
+ */
+dz7085_pollc(unit, on)
+ boolean_t on;
+{
+ dz7085_softc_t sc = dz7085_softc[unit];
+
+ if (on) {
+ sc->polling_mode++;
+#if NBM > 0
+ screen_on_off(unit, TRUE);
+#endif NBM > 0
+ } else
+ sc->polling_mode--;
+}
+
+/*
+ * Interrupt routine
+ */
+dz_intr(unit,spllevel)
+ spl_t spllevel;
+{
+ dz7085_softc_t sc = dz7085_softc[unit];
+ register dz_padded_regmap_t *regs = sc->regs;
+ register short csr;
+
+ csr = regs->dz_csr;
+
+ if (csr & DZ_CSR_TRDY) {
+ register int c;
+
+ c = cons_simple_tint(unit*NDZ_LINE + LINEOF(csr), FALSE);
+ if (c == -1) {
+ /* no more data for this line */
+ regs->dz_tcr &= ~(1 << LINEOF(csr));
+ c = cons_simple_tint(unit*NDZ_LINE + LINEOF(csr), TRUE);
+ /* because funny race possible ifnot */
+ }
+ if (c != -1) {
+ regs->dz_tbuf = (c & 0xff) | sc->breaks;
+ /* and leave it enabled */
+ }
+ }
+ if (sc->polling_mode)
+ return;
+
+ while (regs->dz_csr & DZ_CSR_RDONE) {
+ short c = regs->dz_rbuf;
+ spl_t oldspl;
+
+#ifdef DECSTATION
+ oldspl = splhigh();
+ splx(spllevel);
+#endif /*DECSTATION*/
+ cons_simple_rint(unit*NDZ_LINE+LINEOF(c), LINEOF(c),
+ c&0xff, c&0xff00);
+#ifdef DECSTATION
+ splx(oldspl);
+#endif /*DECSTATION*/
+ }
+}
+
+/*
+ * Start transmission on a line
+ */
+dz7085_start(tp)
+ struct tty *tp;
+{
+ register dz_padded_regmap_t *regs;
+ register int line;
+
+ line = tp->t_dev;
+
+ regs = (dz_padded_regmap_t*)tp->t_addr;
+ regs->dz_tcr |= (1<<(line&3));
+
+ /* no, we do not need a char out to interrupt */
+}
+
+/*
+ * Get a char from a specific DZ line
+ */
+dz7085_getc( unit, line, wait, raw )
+ boolean_t wait;
+ boolean_t raw;
+{
+ dz7085_softc_t sc = dz7085_softc[unit];
+ spl_t s = spltty();
+ register dz_padded_regmap_t *regs = sc->regs;
+ unsigned short c;
+ int rl;
+
+again:
+ /*
+ * wait till something in silo
+ */
+ while ((regs->dz_csr & DZ_CSR_RDONE) == 0 && wait)
+ delay(10);
+ c = regs->dz_rbuf;
+
+ /*
+ * check if right line. For keyboard, rconsole is ok too
+ */
+ rl = LINEOF(c);
+ if (wait && (line != rl) &&
+ !((line == DZ_LINE_KEYBOARD) && rcline == rl))
+ goto again;
+ /*
+ * bad chars not ok
+ */
+ if ((c & (DZ_RBUF_PERR | DZ_RBUF_OERR | DZ_RBUF_FERR)) && wait)
+ goto again;
+
+ splx(s);
+
+ /*
+ * if nothing found return -1
+ */
+ if ( ! (c & DZ_RBUF_VALID))
+ return -1;
+
+#if NBM > 0
+ if ((rl == DZ_LINE_KEYBOARD) && !raw && SCREEN_ISA_CONSOLE())
+ return lk201_rint(SCREEN_CONS_UNIT(), c, wait, sc->polling_mode);
+ else
+#endif NBM > 0
+ return c & DZ_RBUF_CHAR;
+}
+
+/*
+ * Put a char on a specific DZ line
+ */
+dz7085_putc( unit, line, c )
+{
+ dz7085_softc_t sc = dz7085_softc[unit];
+ register dz_padded_regmap_t *regs = sc->regs;
+ spl_t s = spltty();
+
+ /*
+ * do not change the break status of other lines
+ */
+ c = (c & 0xff) | sc->breaks;
+
+ /*
+ * Xmit line info only valid if TRDY,
+ * but never TRDY if no xmit enabled
+ */
+ if ((regs->dz_tcr & DZ_TCR_LNENB) == 0)
+ goto select_it;
+
+ while ((regs->dz_csr & DZ_CSR_TRDY) == 0)
+ delay(100);
+
+ /*
+ * see if by any chance we are already on the right line
+ */
+ if (LINEOF(regs->dz_csr) == line)
+ regs->dz_tbuf = c;
+ else {
+ unsigned short tcr;
+select_it:
+ tcr = regs->dz_tcr;
+ regs->dz_tcr = (1 << line) | (tcr & 0xff00);
+ wbflush();
+
+ do
+ delay(2);
+ while ((regs->dz_csr & DZ_CSR_TRDY) == 0 ||
+ (LINEOF(regs->dz_csr) != line));
+
+ regs->dz_tbuf = c;
+ wbflush();
+
+ /* restore previous settings */
+ regs->dz_tcr = tcr;
+ }
+
+ splx(s);
+}
+
+
+dz7085_param(tp, line)
+ register struct tty *tp;
+ register int line;
+{
+ register dz_padded_regmap_t *regs;
+ register int lpr;
+
+ line = tp->t_dev;
+ regs = dz7085_softc[line/NDZ_LINE]->regs;
+
+ /*
+ * Do not let user fool around with kbd&mouse
+ */
+#if NBM > 0
+ if (screen_captures(line)) {
+ tp->t_ispeed = tp->t_ospeed = B4800;
+ tp->t_flags |= TF_LITOUT;
+ }
+#endif NBM > 0
+ regs->dz_csr = DZ_CSR_MSE|DZ_CSR_RIE|DZ_CSR_TIE;
+ if (tp->t_ispeed == 0) {
+ (void) (*console_mctl)(tp->t_dev, TM_HUP, DMSET); /* hang up line */
+ return;
+ }
+/* 19200/38400 here */
+ lpr = dz7085_speeds[tp->t_ispeed] | (line&DZ_LPAR_LINE) | DZ_LPAR_ENABLE;
+ lpr |= DZ_LPAR_8BITS;
+
+ if ((tp->t_flags & (TF_ODDP|TF_EVENP)) == TF_ODDP)
+ lpr |= DZ_LPAR_ODD_PAR;
+
+ if (tp->t_ispeed == B110)
+ lpr |= DZ_LPAR_STOP;
+ regs->dz_lpr = lpr;
+}
+
+/*
+ * This is a total mess: not only are bits spread out in
+ * various registers, but we have to fake some for pmaxen.
+ */
+dz7085_mctl(dev, bits, how)
+ int dev;
+ int bits, how;
+{
+ register dz_padded_regmap_t *regs;
+ register int unit;
+ register int tcr, msr, brk, n_tcr, n_brk;
+ int b;
+ spl_t s;
+ dz7085_softc_t sc;
+
+ unit = dev;
+
+ /* no modem support on lines 0 & 1 */
+/* XXX break on 0&1 */
+ if ((unit & 2) == 0)
+ return TM_LE|TM_DTR|TM_CTS|TM_CAR|TM_DSR;
+
+ b = 1 ^ (unit & 1); /* line 2 ? */
+
+ sc = dz7085_softc[unit>>2];
+ regs = sc->regs;
+ s = spltty();
+
+ tcr = ((regs->dz_tcr | (sc->fake>>4)) & 0xf00) >> (8 + b*2);
+ brk = (sc->breaks >> (8 + (unit&3))) & 1; /* THE break bit */
+
+ n_tcr = (bits & (TM_RTS|TM_DTR)) >> 1;
+ n_brk = (bits & TM_BRK) >> 9;
+
+ /* break transitions, must 'send' a char out */
+ bits = (brk ^ n_brk) & 1;
+
+ switch (how) {
+ case DMSET:
+ tcr = n_tcr;
+ brk = n_brk;
+ break;
+
+ case DMBIS:
+ tcr |= n_tcr;
+ brk |= n_brk;
+ break;
+
+ case DMBIC:
+ tcr &= ~n_tcr;
+ brk = 0;
+ break;
+
+ case DMGET:
+ msr = ((regs->dz_msr|sc->fake) & 0xf0f) >> (b*8);
+ (void) splx(s);
+ return (tcr<<1)|/* DTR, RTS */
+ ((msr&1)<<5)|/* CTS */
+ ((msr&2)<<7)|/* DSR */
+ ((msr&0xc)<<4)|/* CD, RNG */
+ (brk << 9)|/* BRK */
+ TM_LE;
+ }
+ n_tcr = (regs->dz_tcr & ~(3 << (8 + b*2))) |
+ (tcr << (8 + b*2));
+
+ regs->dz_tcr = n_tcr;
+ sc->fake = (sc->fake & 0xf0f) | (n_tcr<<4&0xf000);
+
+ sc->breaks = (sc->breaks & ~(1 << (8 + (unit&3)))) |
+ (brk << (8 + (unit&3)));
+ if(bits) (*console_putc)( unit>>2, unit&3, 0);/* force break, now */
+ (void) splx(s);
+ return 0;/* useless to compute it */
+}
+
+/*
+ * Periodically look at the CD signals:
+ * they do not generate interrupts.
+ */
+dz7085_scan()
+{
+ register i;
+ register dz_padded_regmap_t *regs;
+ register msr;
+ register struct tty *tp;
+
+ for (i = 0; i < NDZ_; i++) {
+ dz7085_softc_t sc = dz7085_softc[i];
+ register int temp;
+
+ if (sc == 0)
+ continue;
+ regs = sc->regs;
+
+ tp = console_tty[i * NDZ_LINE];
+
+ msr = regs->dz_msr | (sc->fake & 0xf0f);
+ if (temp = sc->softCAR) {
+ if (temp & 0x4)
+ msr |= DZ_MSR_CD2 | DZ_MSR_CTS2;
+ if (temp & 0x8)
+ msr |= DZ_MSR_CD3 | DZ_MSR_CTS3;
+ }
+
+ /* Lines 0 and 1 have carrier on by definition */
+ /* [horrid casts cuz compiler stupid] */
+ check_car((char*)tp + 0*sizeof(struct tty), 1);
+ check_car((char*)tp + 1*sizeof(struct tty), 1);
+ check_car((char*)tp + 2*sizeof(struct tty), msr & DZ_MSR_CD2);
+ check_car((char*)tp + 3*sizeof(struct tty), msr & DZ_MSR_CD3);
+
+ /* nothing else to do if no msr transitions */
+ if ((temp = sc->prev_msr) == msr)
+ continue;
+ else
+ sc->prev_msr = msr;
+
+ /* see if we have an incoming call */
+#define RING (DZ_MSR_RI2|DZ_MSR_RI3)
+ if ((msr & RING) != (temp & RING)) {
+/*printf("%s %x->%x\n", "ET Phone RI", temp & RING, msr & RING);*/
+ check_ring((char*)tp + 2*sizeof(struct tty),
+ msr & DZ_MSR_RI2, temp & DZ_MSR_RI2);
+ check_ring((char*)tp + 3*sizeof(struct tty),
+ msr & DZ_MSR_RI3, temp & DZ_MSR_RI3);
+ }
+#undef RING
+ /* see if we must do flow-control */
+ if ((msr ^ temp) & DZ_MSR_CTS2) {
+ tty_cts((char*)tp + 2*sizeof(struct tty),
+ msr & DZ_MSR_CTS2);
+ }
+ if ((msr ^ temp) & DZ_MSR_CTS3) {
+ tty_cts((char*)tp + 3*sizeof(struct tty),
+ msr & DZ_MSR_CTS3);
+ }
+ }
+ timeout(dz7085_scan, (vm_offset_t)0, 2*hz);
+}
+
+static dz7085_hup(tp)
+ register struct tty *tp;
+{
+ (*console_mctl)(tp->t_dev, TM_DTR, DMBIC);
+}
+
+static void check_car(tp, car)
+ register struct tty *tp;
+{
+ if (car) {
+ /* cancel modem timeout if need to */
+ if (car & (DZ_MSR_CD2|DZ_MSR_CD3))
+ untimeout(dz7085_hup, (vm_offset_t)tp);
+
+ /* I think this belongs in the MI code */
+ if (tp->t_state & TS_WOPEN)
+ tp->t_state |= TS_ISOPEN;
+ /* carrier present */
+ if ((tp->t_state & TS_CARR_ON) == 0)
+ (void)ttymodem(tp, 1);
+ } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0)
+ (*console_mctl)( tp->t_dev, TM_DTR, DMBIC);
+}
+
+int dz7085_ring_timeout = 60; /* seconds, patchable */
+
+static void check_ring(tp, ring, oring)
+ register struct tty *tp;
+{
+ if (ring == oring)
+ return;
+ if (ring) {
+ (*console_mctl)( tp->t_dev, TM_DTR, DMBIS);
+ /* give it ample time to find the right carrier */
+ timeout(dz7085_hup, (vm_offset_t)tp, dz7085_ring_timeout*hz);
+ }
+}
+#endif NDZ_ > 0
diff --git a/chips/eccreg.h b/chips/eccreg.h
new file mode 100644
index 00000000..21c8fb02
--- /dev/null
+++ b/chips/eccreg.h
@@ -0,0 +1,110 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#define FA_BLCK 0x10000
+
+#define FA_ROM 0x00000
+
+#define FA_CTL 0x10000
+#define FA_STAT 0x10000
+#define I_RCV_CNT 0x00001
+#define I_RCV_EOM 0x00002
+#define I_RCV_TIM 0x00004
+#define I_XMT_CNT 0x00008
+#define I_RCV_LOS 0x00010
+#define I_RCV_CARRIER 0x00020
+#define FA_CR_S 0x10004
+#define FA_CR_C 0x10008
+#define FA_CR 0x1000C
+#define ENI_RCV_CNT 0x00001
+#define ENI_RCV_END 0x00002
+#define ENI_RCV_TIM 0x00004
+#define ENI_XMT_CNT 0x00008
+#define EN_TEST 0x00010
+#define EN_UNUSED 0x00020
+#define EN_RCV 0x00040
+#define EN_XMT 0x00080
+#define RESET_RCV 0x00100
+#define RESET_XMT 0x00200
+#define FA_TIM 0x10010
+#define FA_TIM_SET 0x10018
+#define FA_RCV_CNT 0x10020
+#define FA_RCV_CMP 0x10028
+#define FA_XMT_CNT 0x10030
+#define FA_XMT_CMP 0x10038
+
+
+#define FA_DISCARD 0x20000
+#define FA_RCV 0x20000
+#define FA_RCV_HD 0x20000
+#define FA_RCV_PAYLD 0x20004
+#define FA_RCV_TR 0x20034
+
+#define FA_XMT 0x30000
+#define FA_XMT_HD 0x30000
+#define FA_XMT_PAYLD 0x30004
+#define FA_XMT_TR 0x30034
+
+#define FA_END 0x40000
+
+
+struct ecc {
+/* 00000 */ char rom[FA_BLCK];
+/* 10000 */ int stat;
+/* 10004 */ int cr_s;
+/* 10008 */ int cr_c;
+/* 1000C */ int cr;
+/* 10010 */ int tim;
+ int fill1;
+/* 10018 */ int tim_set;
+ int fill2;
+/* 10020 */ int rcv_cnt;
+ int fill3;
+/* 10028 */ int rcv_cmp;
+ int fill4;
+/* 10030 */ int xmt_cnt;
+ int fill5;
+/* 10038 */ int xmt_cmp;
+ int fill6;
+ char pad[FA_BLCK-0x40];
+
+/* 20000 */
+/* 20000 */ char rcv[FA_BLCK];
+/* 30000 */ char xmt[FA_BLCK];
+};
+
+struct sar {
+ int header;
+ int payload[12];
+ int trailer;
+};
+
+typedef struct ecc ecc_t;
+typedef struct sar sar_t;
+
+
+
+
diff --git a/chips/fb_hdw.c b/chips/fb_hdw.c
new file mode 100644
index 00000000..7139a864
--- /dev/null
+++ b/chips/fb_hdw.c
@@ -0,0 +1,219 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: fb_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 7/91
+ *
+ * Driver for the 3max Monochrome Frame Buffer Display,
+ * hardware-level operations.
+ */
+
+#include <mfb.h>
+#if (NMFB > 0)
+#include <platforms.h>
+
+#include <machine/machspl.h>
+#include <mach/std_types.h>
+#include <chips/busses.h>
+
+#include <chips/screen_defs.h>
+
+#include <chips/pm_defs.h>
+typedef pm_softc_t fb_softc_t;
+
+
+#ifdef DECSTATION
+#include <mips/PMAX/pmag_aa.h>
+#include <mips/PMAX/tc.h>
+#endif
+
+#ifdef FLAMINGO
+#include <mips/PMAX/pmag_aa.h> /* XXX fixme */
+#include <alpha/DEC/tc.h>
+#endif
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int fb_probe(), fb_intr();
+static void fb_attach();
+
+vm_offset_t fb_std[NMFB] = { 0 };
+struct bus_device *fb_info[NMFB];
+struct bus_driver fb_driver =
+ { fb_probe, 0, fb_attach, 0, fb_std, "fb", fb_info,
+ 0, 0, BUS_INTR_DISABLED};
+
+/*
+ * Probe/Attach functions
+ */
+
+fb_probe( /* reg, ui */)
+{
+ static probed_once = 0;
+
+ /*
+ * Probing was really done sweeping the TC long ago
+ */
+ if (tc_probe("fb") == 0)
+ return 0;
+ if (probed_once++ > 1)
+ printf("[mappable] ");
+ return 1;
+}
+
+static void
+fb_attach(ui)
+ struct bus_device *ui;
+{
+ /* ... */
+ printf(": monochrome display");
+}
+
+
+/*
+ * Interrupt routine
+ */
+
+fb_intr(unit,spllevel)
+ spl_t spllevel;
+{
+ register volatile char *ack;
+
+ /* acknowledge interrupt */
+ ack = (volatile char *) fb_info[unit]->address + FB_OFFSET_IREQ;
+ *ack = 0;
+
+#if mips
+ splx(spllevel);
+#endif
+ lk201_led(unit);
+}
+
+fb_vretrace(fb, on)
+ fb_softc_t *fb;
+{
+ int i;
+
+ for (i = 0; i < NMFB; i++)
+ if (fb_info[i]->address == (vm_offset_t)fb->framebuffer)
+ break;
+ if (i == NMFB) return;
+
+ (*tc_enable_interrupt)(fb_info[i]->adaptor, on, 0);
+}
+
+/*
+ * Video on/off
+ */
+fb_video_on(fb, up)
+ fb_softc_t *fb;
+ user_info_t *up;
+{
+ if (!fb->cursor_state) /* video is "on" at boot */
+ return;
+ bt455_video_on(fb->vdac_registers, up);
+ bt431_cursor_on(fb->cursor_registers);
+ fb->cursor_state = 0;
+}
+
+fb_video_off(fb, up)
+ fb_softc_t *fb;
+ user_info_t *up;
+{
+ if (fb->cursor_state)
+ return;
+ bt455_video_off(fb->vdac_registers, up);
+ bt431_cursor_off(fb->cursor_registers);
+ fb->cursor_state = 1;
+}
+
+/*
+ * Boot time initialization: must make device
+ * usable as console asap.
+ */
+extern int
+ fb_soft_reset(), fb_set_status(),
+ bt431_pos_cursor(), fb_video_on(),
+ fb_video_off(), fb_vretrace(),
+ pm_get_status(), pm_char_paint(),
+ pm_insert_line(), pm_remove_line(),
+ pm_clear_bitmap(), pm_map_page();
+
+static struct screen_switch fb_sw = {
+ screen_noop, /* graphic_open */
+ fb_soft_reset, /* graphic_close */
+ fb_set_status, /* set_status */
+ pm_get_status, /* get_status */
+ pm_char_paint, /* char_paint */
+ bt431_pos_cursor, /* pos_cursor */
+ pm_insert_line, /* insert_line */
+ pm_remove_line, /* remove_line */
+ pm_clear_bitmap, /* clear_bitmap */
+ fb_video_on, /* video_on */
+ fb_video_off, /* video_off */
+ fb_vretrace, /* intr_enable */
+ pm_map_page /* map_page */
+};
+
+fb_cold_init(unit, up)
+ user_info_t *up;
+{
+ fb_softc_t *fb;
+ screen_softc_t sc = screen(unit);
+ vm_offset_t base = tc_probe("fb");
+
+ bcopy(&fb_sw, &sc->sw, sizeof(sc->sw));
+#if 0
+ sc->flags |= MONO_SCREEN;
+#else
+ sc->flags |= COLOR_SCREEN;
+#endif
+ sc->frame_scanline_width = 2048;
+ sc->frame_height = 1024;
+ sc->frame_visible_width = 1280;
+ sc->frame_visible_height = 1024;
+
+ pm_init_screen_params(sc, up);
+ (void) screen_up(unit, up);
+
+ fb = pm_alloc(unit, base+FB_OFFSET_BT431, base+FB_OFFSET_VRAM, -1);
+ fb->vdac_registers = (char*) base + FB_OFFSET_BT455;
+
+ screen_default_colors(up);
+
+ fb_soft_reset(sc);
+
+ /*
+ * Clearing the screen at boot saves from scrolling
+ * much, and speeds up booting quite a bit.
+ */
+ screen_blitc( unit, 'C'-'@');/* clear screen */
+}
+
+#endif (NMFB > 0)
diff --git a/chips/fb_misc.c b/chips/fb_misc.c
new file mode 100644
index 00000000..3a99dcd9
--- /dev/null
+++ b/chips/fb_misc.c
@@ -0,0 +1,242 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: fb_misc.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 7/91
+ *
+ * Driver for the PMAG-AA simple mono framebuffer
+ *
+ */
+
+#include <mfb.h>
+#if (NMFB > 0)
+
+/*
+ * NOTE: This driver relies heavily on the pm one.
+ */
+
+#include <device/device_types.h>
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+typedef pm_softc_t fb_softc_t;
+
+#include <chips/bt455.h>
+
+/*
+ * Initialize color map, for kernel use
+ */
+fb_init_colormap(sc)
+ screen_softc_t sc;
+{
+ fb_softc_t *fb = (fb_softc_t*)sc->hw_state;
+ user_info_t *up = sc->up;
+ color_map_t Bg_Fg[2];
+ register int i;
+
+ bt455_init_colormap( fb->vdac_registers );
+
+ /* init bg/fg colors */
+ for (i = 0; i < 3; i++) {
+ up->dev_dep_2.pm.Bg_color[i] = 0x00;
+ up->dev_dep_2.pm.Fg_color[i] = 0xff;
+ }
+
+ Bg_Fg[0].red = Bg_Fg[0].green = Bg_Fg[0].blue = 0x00;
+ Bg_Fg[1].red = Bg_Fg[1].green = Bg_Fg[1].blue = 0xff;
+ bt455_cursor_color( fb->vdac_registers, Bg_Fg);
+}
+
+/*
+ * Large viz small cursor
+ */
+fb_small_cursor_to_large(up, cursor)
+ user_info_t *up;
+ cursor_sprite_t cursor;
+{
+ unsigned char *curbytes, *sprite;
+ int i;
+ /* Our cursor turns out mirrored, donno why */
+ static unsigned char mirror[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+ };
+
+ /* Clear out old cursor */
+ bzero( up->dev_dep_2.pm.cursor_sprite,
+ sizeof(up->dev_dep_2.pm.cursor_sprite));
+
+ /* small cursor is 32x2 bytes, image(fg) first then mask(bg) */
+ curbytes = (unsigned char *) cursor;
+
+ /* we have even byte --> image, odd byte --> mask;
+ line size is 8 bytes instead of 2 */
+ sprite = (unsigned char *) up->dev_dep_2.pm.cursor_sprite;
+
+ for (i = 0; i < 32; i += 2) {
+ *sprite++ = mirror[curbytes[i]]; /* fg */
+ *sprite++ = mirror[curbytes[i + 32]]; /* bg */
+ *sprite++ = mirror[curbytes[i + 1]]; /* fg */
+ *sprite++ = mirror[curbytes[i + 33]]; /* bg */
+ sprite += 12; /* skip rest of the line */
+ }
+}
+
+/*
+ * Device-specific set status
+ */
+fb_set_status(sc, flavor, status, status_count)
+ screen_softc_t sc;
+ int flavor;
+ dev_status_t status;
+ unsigned int status_count;
+{
+ fb_softc_t *fb = (fb_softc_t*) sc->hw_state;
+
+ switch (flavor) {
+
+ case SCREEN_ADJ_MAPPED_INFO:
+ return pm_set_status(sc, flavor, status, status_count);
+
+ case SCREEN_LOAD_CURSOR:
+
+ if (status_count < sizeof(cursor_sprite_t)/sizeof(int))
+ return D_INVALID_SIZE;
+ fb_small_cursor_to_large(sc->up, (cursor_sprite_t*) status);
+
+ /* Fall through */
+
+ case SCREEN_LOAD_CURSOR_LONG: { /* 3max/3min only */
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt431_cursor_sprite(fb->cursor_registers, sc->up->dev_dep_2.pm.cursor_sprite);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+ case SCREEN_SET_CURSOR_COLOR: {
+ color_map_t c[2];
+ register cursor_color_t *cc = (cursor_color_t*) status;
+
+ c[0].red = cc->Bg_rgb[0];
+ c[0].green = cc->Bg_rgb[1];
+ c[0].blue = cc->Bg_rgb[2];
+ c[1].red = cc->Fg_rgb[0];
+ c[1].green = cc->Fg_rgb[1];
+ c[1].blue = cc->Fg_rgb[2];
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt455_cursor_color (fb->vdac_registers, c );
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+ case SCREEN_SET_CMAP_ENTRY: {
+ color_map_entry_t *e = (color_map_entry_t*) status;
+
+ if (e->index < 8) { /* 8&9 are fg&bg, do not touch */
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt455_load_colormap_entry( fb->vdac_registers, e->index, &e->value);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+ }
+ break;
+ }
+
+ default:
+ return D_INVALID_OPERATION;
+ }
+ return D_SUCCESS;
+}
+
+/*
+ * Do what's needed when X exits
+ */
+fb_soft_reset(sc)
+ screen_softc_t sc;
+{
+ fb_softc_t *fb = (fb_softc_t*) sc->hw_state;
+ user_info_t *up = sc->up;
+ extern cursor_sprite_t bt431_default_cursor;
+
+ /*
+ * Restore params in mapped structure
+ */
+ pm_init_screen_params(sc,up);
+ up->row = up->max_row - 1;
+
+ up->dev_dep_2.pm.x26 = 2; /* you do not want to know */
+ up->dev_dep_1.pm.x18 = (short*)2;
+
+ /*
+ * Restore RAMDAC chip to default state, and init cursor
+ */
+ bt455_init(fb->vdac_registers);
+ bt431_init(fb->cursor_registers);
+
+ /*
+ * Load kernel's cursor sprite
+ */
+ bt431_cursor_sprite(fb->cursor_registers, bt431_default_cursor);
+
+ /*
+ * Color map and cursor color
+ */
+ fb_init_colormap(sc);
+}
+
+#endif (NMFB > 0)
diff --git a/chips/fdc_82077.h b/chips/fdc_82077.h
new file mode 100644
index 00000000..95192183
--- /dev/null
+++ b/chips/fdc_82077.h
@@ -0,0 +1,525 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: fdi_82077_hdw.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Defines for the Intel 82077 Floppy Disk Controller chip.
+ * Includes defines for 8272A and 82072.
+ */
+
+#ifndef _FDC_82077_H_
+#define _FDC_82077_H_
+
+/*
+ * Chips we claim to understand, and their modes
+ */
+#define fdc_8272a 0
+#define fdc_82072 1
+#define fdc_82077aa 2
+
+#define at_mode 0
+#define ps2_mode 1
+#define mod30_mode 2
+
+#define DRIVES_PER_FDC 4
+
+/*
+ * Register maps
+ */
+typedef struct {
+ volatile unsigned char fd_sra; /* r: status register A */
+ volatile unsigned char fd_srb; /* r: status register B */
+ volatile unsigned char fd_dor; /* rw: digital output reg */
+ volatile unsigned char fd_tdr; /* rw: tape drive register */
+ volatile unsigned char fd_msr; /* r: main status register */
+#define fd_dsr fd_msr /* w: data rate select reg */
+ volatile unsigned char fd_data; /* rw: fifo */
+ volatile unsigned char fd_xxx; /* --reserved-- */
+ volatile unsigned char fd_dir; /* r: digital input reg */
+#define fd_ccr fd_dir /* w: config control reg */
+} fd_regmap_t;
+
+typedef struct {
+ volatile unsigned char fd_msr; /* r: main status register */
+ volatile unsigned char fd_data; /* rw: data register */
+} fd_8272a_regmap_t;
+
+typedef fd_8272a_regmap_t fd_82072_regmap_t;
+/*#define fd_dsr fd_msr /* w: data rate select reg */
+
+/*
+ * Status register A (82077AA only)
+ *
+ * Only available in PS/2 (ps2) and Model 30 (m30) modes,
+ * not available in PC/AT (at) mode.
+ * Some signals have inverted polarity (~) on mod30
+ */
+
+#define FD_SRA_INT 0x80 /* interrupt */
+#define FD_SRA_DRV2 0x40 /* 2nd drive installed (ps2) */
+#define FD_SRA_DRQ 0x40 /* dma request (mod30) */
+#define FD_SRA_STEP 0x20 /* step pulse (~mod30) */
+#define FD_SRA_TRK0 0x10 /* Track 0 (~mod30) */
+#define FD_SRA_HDSEL 0x08 /* select head 1 (~mod30) */
+#define FD_SRA_INDX 0x04 /* Index hole (~mod30) */
+#define FD_SRA_WP 0x02 /* write protect (~mod30) */
+#define FD_SRA_DIR 0x01 /* step dir, 1->center (~mod30) */
+
+/*
+ * Status register B (82077AA only)
+ * Not available in at mode.
+ */
+
+#define FD_SRB_DRV2 0x80 /* 2nd drive installed (mod30) */
+ /* wired 1 on ps2 */
+
+#define FD_SRB_DS1 0x40 /* drive select 1 (mod30) */
+ /* wired 1 on ps2 */
+
+#define FD_SRB_DS0 0x20 /* drive select 0 */
+#define FD_SRB_WRDATA 0x10 /* out data (toggle or ~trigger) */
+#define FD_SRB_RDDATA 0x08 /* in data (toggle or ~trigger) */
+#define FD_SRB_WE 0x04 /* write enable (~mod30) */
+#define FD_SRB_MOT_1 0x02 /* motor enable drive 1 (ps2) */
+#define FD_SRB_DS3 0x02 /* drive select 3 (mod30) */
+#define FD_SRB_MOT_0 0x01 /* motor enable drive 0 (ps2) */
+#define FD_SRB_DS2 0x01 /* drive select 2 (mod30) */
+
+/*
+ * Digital output register (82077AA only)
+ */
+
+#define FD_DOR_MOT_3 0x80 /* motor enable drive 3 */
+#define FD_DOR_MOT_2 0x40
+#define FD_DOR_MOT_1 0x20
+#define FD_DOR_MOT_0 0x10
+#define FD_DOR_DMA_GATE 0x08 /* enable dma (mod30,at) */
+#define FD_DOR_ENABLE 0x04 /* chip reset (inverted) */
+#define FD_DOR_DRIVE_0 0x00 /* select drive no 0 */
+#define FD_DOR_DRIVE_1 0x01
+#define FD_DOR_DRIVE_2 0x02
+#define FD_DOR_DRIVE_3 0x03
+
+/*
+ * Tape drive register (82077AA only)
+ */
+
+#define FD_TDR_TAPE_1 0x01 /* unit 1 is a tape */
+#define FD_TDR_TAPE_2 0x02
+#define FD_TDR_TAPE_3 0x03
+#define FD_TDR_xxx 0xfc
+
+/*
+ * Data-rate select register (82077AA and 82072)
+ */
+
+#define FD_DSR_RESET 0x80 /* self-clearing reset */
+#define FD_DSR_POWER_DOWN 0x40 /* stop clocks and oscill */
+#define FD_DSR_zero 0x20 /* wired zero on 82077AA */
+#define FD_DSR_EPLL 0x20 /* enable PLL on 82072 */
+
+#define FD_DSR_PRECOMP_MASK 0x1c /* precompensation value */
+# define FD_DSR_PRECOMP_SHIFT 2
+
+# define FD_DSR_PRECOMP_DEFAULT 0 /* 41.67@1Mbps else 125ns */
+# define FD_DSR_PRECOMP_41_67 1
+# define FD_DSR_PRECOMP_83_34 2
+# define FD_DSR_PRECOMP_125_00 3
+# define FD_DSR_PRECOMP_166_67 4
+# define FD_DSR_PRECOMP_208_33 5
+# define FD_DSR_PRECOMP_250_00 6
+# define FD_DSR_PRECOMP_DISABLE 7 /* 0.00ns */
+
+#define FD_DSR_DATA_RATE_MASK 0x03
+#define FD_DSR_SD_250 0x00 /* fm modulation, 250Kbps bit clock */
+#define FD_DSR_SD_150 0x01
+#define FD_DSR_SD_125 0x02
+
+#define FD_DSR_DD_500 0x00 /* mfm modulation, 500Kbps */
+#define FD_DSR_DD_300 0x01
+#define FD_DSR_DD_250 0x02
+#define FD_DSR_DD_1000 0x03 /* illegal for 82077 */
+
+/*
+ * Main status register (all chips)
+ */
+
+#define FD_MSR_RQM 0x80 /* request from master (allowed) */
+#define FD_MSR_DIO 0x40 /* data in/out, 1->master read */
+#define FD_MSR_NON_DMA 0x20 /* dma disabled */
+#define FD_MSR_CMD_BSY 0x10 /* command in progress */
+#define FD_MSR_DRV_3_BSY 0x08 /* drive busy seeking */
+#define FD_MSR_DRV_2_BSY 0x04
+#define FD_MSR_DRV_1_BSY 0x02
+#define FD_MSR_DRV_0_BSY 0x01
+
+/*
+ * FIFO (82077AA and 82072)
+ *
+ * Service delay is
+ * Threshold * 8
+ * delay = ------------- - 1.5 usecs
+ * Data-rate
+ */
+
+#define FD_FIFO_DEEP 16
+
+/*
+ * Digital input register (82077AA only)
+ */
+
+#define FD_DIR_DSK_CHG 0x80 /* disk was changed (~mod30) */
+
+#define FD_DIR_ones 0x78 /* wired ones for ps2 */
+#define FD_DIR_zeroes 0x70 /* wired zeroes for mod30 */
+#define FD_DIR_undef 0x7f /* undefined for at */
+
+#define FD_DIR_DR_MASK_PS2 0x06 /* current data rate (ps2) */
+# define FD_DIR_DR_SHIFT_PS2 1
+#define FD_DIR_LOW_DENS 0x01 /* zero for 500/1M dr (ps2) */
+
+#define FD_DIR_DMA_GATE 0x08 /* same as DOR (mod30) */
+#define FD_DIR_NOPREC 0x04 /* same as CCR (mod30) */
+#define FD_DIR_DR_MASK_M30 0x03 /* current data rate (mod30) */
+# define FD_DIR_DR_SHIFT_M30 0
+
+/*
+ * Configuration control register (82077AA only)
+ */
+
+#define FD_CCR_DATA_RATE_MASK 0x03 /* see DSR for values */
+#define FD_CCR_NOPREC 0x04 /* "has no function" (mod30) */
+
+
+/*
+ * Programming
+ *
+ * Legend for command bytes, when applicable
+ *
+ * hds bit 2 of byte 1, head select (1 -> head 1)
+ * ds bits 0-1 of byte 1, drive select
+ * c cylinder number (max 76 for 8272A, else 255)
+ * h head number
+ * r sector number
+ * n number of bytes in sector
+ * eot end-of-track, e.g. final sector number
+ * gpl gap length
+ * dtl data length (for partial sectors)
+ * st0-3 status byte
+ * srt step rate time
+ * hut head unload time
+ * hlt head load time
+ * nd disable DMA
+ * mot do not turn motor on before checking drive status
+ * pcn present cylinder number
+ * ncn new cylinder number
+ * rcn relative cylinder number (new=present+rcn)
+ * sc sectors/cylinder
+ * d filler byte
+ * ? undefined
+ * hsda high-speed disk adjust (doubles motor on/off delays)
+ * moff motor off timer, one disk revolution increments
+ * mon motor on timer, ditto
+ * eis enable implied seeks
+ * dfifo disable fifo
+ * poll disable poll
+ * fifthr fifo threshold (1 to 16 bytes)
+ * pretrk precomp starts on this trackno (0-255)
+ * wgate change timings of WE signal, in perpendicular mode
+ * gap change gap2 length, in perpendicular mode
+ * ec in verify, qualify terminating conditions (sc viz eot)
+ */
+
+/* First byte of command, qualifiers */
+#define FD_CMD_MT 0x80 /* Multi-track */
+#define FD_CMD_MFM 0x40 /* Double density */
+#define FD_CMD_SK 0x20 /* skip deleted data address mark */
+#define FD_CMD_DIR 0x40 /* relative seek direction (up) */
+
+/* command codes and description */
+
+/*
+ * Read an entire track.
+ * Qualifiers: MFM, SK (8272A only)
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_READ_TRACK 0x02
+
+/*
+ * Specify timers
+ * Qualifiers:
+ * Bytes total: 3 code,srt+hut,hlt+nd
+ * Result total:
+ */
+#define FD_CMD_SPECIFY 0x03
+
+/*
+ * Sense status of drive
+ * Qualifiers:
+ * Bytes total: 2 code,hds+ds +mot(82072 only)
+ * Result total: 1 st3
+ */
+#define FD_CMD_SENSE_DRIVE_STATUS 0x04
+# define FD_CMD_SDS_NO_MOT 0x80
+
+/*
+ * Write
+ * Qualifiers: MT, MFM
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_WRITE_DATA 0x05
+
+/*
+ * Read
+ * Qualifiers: MT, MFM, SK
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_READ_DATA 0x06
+
+/*
+ * Seek to track 0
+ * Qualifiers:
+ * Bytes total: 2 code,ds
+ * Result total:
+ */
+#define FD_CMD_RECALIBRATE 0x07
+
+/*
+ * Sense interrupt status
+ * Qualifiers:
+ * Bytes total: 1 code
+ * Result total: 2 st0,pcn
+ */
+#define FD_CMD_SENSE_INT_STATUS 0x08
+
+/*
+ * Write data and mark deleted
+ * Qualifiers: MT, MFM
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_WRITE_DELETED_DATA 0x09
+
+/*
+ * Read current head position
+ * Qualifiers: MFM
+ * Bytes total: 2 code,hds+ds
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_READ_ID 0x0a
+
+/*
+ * Set value of MOT pin, unconditionally
+ * Qualifiers: see
+ * Bytes total: 1 code+..
+ * Result total: none returns to command phase
+ */
+#define FD_CMD_MOTOR_ON_OFF 0x0b /* 82072 only */
+
+# define FD_CMD_MOT_ON 0x80
+# define FD_CMD_MOT_DS 0x60
+# define FD_CMD_MOT_DS_SHIFT 5
+
+/*
+ * Read data despite deleted address mark
+ * Qualifiers: MT, MFM, SK
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_READ_DELETED_DATA 0x0c
+
+/*
+ * Media initialization
+ * Qualifiers: MFM
+ * Bytes total: 6 code,hds+ds,n,sc,gpl,d
+ * Data: 4*sc/2 c,h,r,n
+ * Result total: 7 st0,st1,st2,?,?,?,?
+ */
+#define FD_CMD_FORMAT_TRACK 0x0d
+
+/*
+ * Dump internal register status
+ * Qualifiers:
+ * Bytes total: 1 code
+ * Result total: 10 pcn0,pcn1,pcn2,pcn3,srt+hut,hlt+nd,
+ * sc/eot,hsda+moff+mon,
+ * eis+dfifo+poll+fifothr, pretrk
+ * Notes: 82077AA does not provide for hsda+moff+mon
+ */
+#define FD_CMD_DUMPREG 0x0e /* not 8272a */
+
+/*
+ * Move head
+ * Qualifiers:
+ * Bytes total: 3 code,hds+ds,ncn
+ * Result total:
+ */
+#define FD_CMD_SEEK 0x0f
+
+/*
+ *
+ * Qualifiers:
+ * Bytes total: 1 code
+ * Result total: 1 version
+ */
+#define FD_CMD_VERSION 0x10 /* 82077AA only */
+# define FD_VERSION_82077AA 0x90
+
+/*
+ * Scan disk data
+ * Qualifiers: MT, MFM, SK
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_SCAN_EQUAL 0x11 /* 8272A only */
+
+/*
+ * Specify timers
+ * Qualifiers:
+ * Bytes total: 2 code,wgate+gap
+ * Result total:
+ */
+#define FD_CMD_PERPENDICULAR_MODE 0x12 /* 82077AA only */
+
+/*
+ * Set configuration parameters
+ * Qualifiers:
+ * Bytes total: 4 code,hsda+moff+mon,eis+dfifo+poll+fifothr,
+ * pretrk
+ * Result total:
+ * Notes: 82077AA does not provide for hsda+moff+mon
+ */
+#define FD_CMD_CONFIGURE 0x13 /* not 8272a */
+
+/*
+ * Verify CRC of disk data
+ * Qualifiers: MT, MFM, SK
+ * Bytes total: 9 code,ec+hds+ds,c,h,r,n,eot,gpl,dtl/sc
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_VERIFY 0x16 /* 82077AA only */
+
+/*
+ * Scan disk data (disk less-or-equal memory)
+ * Qualifiers: MT, MFM, SK
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_SCAN_LOW_OR_EQUAL 0x19 /* 8272A only */
+
+/*
+ * Scan disk data (disk greater-or-equal memory)
+ * Qualifiers: MT, MFM, SK
+ * Bytes total: 9 code,hds+ds,c,h,r,n,eot,gpl,dtl
+ * Result total: 7 st0,st1,st2,c,h,r,n
+ */
+#define FD_CMD_SCAN_HIGH_OR_EQUAL 0x1d /* 8272A only */
+
+/*
+ * Specify timers
+ * Qualifiers: DIR
+ * Bytes total: 3 code,hds+ds,rcn
+ * Result total:
+ */
+#define FD_CMD_RELATIVE_SEEK 0x8f /* not 8272a */
+
+/*
+ * Any invalid command code
+ * Qualifiers:
+ * Bytes total: 1 code
+ * Result total: 1 st0 (st0 == 0x80)
+ */
+#define FD_CMD_INVALID 0xff
+
+
+/*
+ * Results and statii
+ *
+ * The typical command returns three status bytes,
+ * followed by four drive status bytes.
+ */
+
+/*
+ * Status register 0
+ */
+#define FD_ST0_IC_MASK 0xc0 /* interrupt completion code */
+
+# define FD_ST0_IC_OK 0x00 /* terminated ok */
+# define FD_ST0_IC_AT 0x40 /* exec phase ended sour */
+# define FD_ST0_IC_BAD_CMD 0x80 /* didnt grok */
+# define FD_ST0_IC_AT_POLL 0xc0 /* polling got in the way */
+
+#define FD_ST0_SE 0x20 /* (implied) seek ended */
+#define FD_ST0_EC 0x10 /* equipment check */
+#define FD_ST0_NR 0x08 /* not ready (raz for 82077aa) */
+#define FD_ST0_H 0x04 /* currently selected head */
+#define FD_ST0_DS 0x03 /* currently selected drive */
+
+/*
+ * Status register 1
+ */
+
+#define FD_ST1_EN 0x80 /* end of cylinder (TC not set?) */
+#define FD_ST1_zero 0x48
+#define FD_ST1_DE 0x20 /* data error, bad CRC */
+#define FD_ST1_OR 0x10 /* overrun/underrun
+#define FD_ST1_ND 0x04 /* no data, sector not found */
+#define FD_ST1_NW 0x02 /* write protect signal */
+#define FD_ST1_MA 0x01 /* missing address mark */
+
+/*
+ * Status register 2
+ */
+
+#define FD_ST2_zero 0x80
+#define FD_ST2_CM 0x40 /* control mark, improper read */
+#define FD_ST2_DD 0x20 /* the CRC error was for data */
+#define FD_ST2_WC 0x10 /* wrong cylinder */
+#define FD_ST2_SH 0x08 /* scan hit (8272a only) */
+#define FD_ST2_SN 0x04 /* scan not met (8272a only) */
+#define FD_ST2_BC 0x02 /* bad cylinder, has 0xff mark */
+#define FD_ST2_MD 0x01 /* missing data mark */
+
+/*
+ * Status register 3
+ * (sense drive status)
+ */
+
+#define FD_ST3_FT 0x80 /* fault pin (0 if not 8272a) */
+#define FD_ST3_WP 0x40 /* write protect pin */
+#define FD_ST3_RDY 0x20 /* ready pin (1 on 82077aa) */
+#define FD_ST3_T0 0x10 /* track0 pin */
+#define FD_ST3_TS 0x08 /* two-sided pin (1 if not 8272a) */
+#define FD_ST3_HD 0x04 /* hdsel pin */
+#define FD_ST3_DS 0x03 /* drive select pins (1&0) */
+
+
+#endif /* _FDC_82077_H_ */
diff --git a/chips/fdc_82077_hdw.c b/chips/fdc_82077_hdw.c
new file mode 100644
index 00000000..f52da830
--- /dev/null
+++ b/chips/fdc_82077_hdw.c
@@ -0,0 +1,821 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: fdi_82077_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Driver for the Intel 82077 Floppy Disk Controller.
+ */
+
+#include <fd.h>
+#if NFD > 0
+
+#include <mach/std_types.h>
+#include <machine/machspl.h>
+#include <chips/busses.h>
+
+#include <chips/fdc_82077.h>
+#include <platforms.h>
+
+/* ---- */
+#include <device/param.h>
+#include <device/io_req.h>
+#include <device/device_types.h>
+#include <device/disk_status.h>
+#define UNITNO(d) ((d)>>5)
+#define SLAVENO(d) (((d)>>3)&0x3)
+#define PARAMNO(d) ((d)&0x7)
+/* ---- */
+
+#ifdef MAXINE
+
+/* we can only take one */
+#define MAX_DRIVES 1
+
+#define my_fdc_type fdc_82077aa
+#define the_fdc_type fd->fdc_type
+/* later: #define the_fdc_type my_fdc_type */
+
+/* Registers are read/written as words, byte 0 */
+/* padding is to x40 boundaries */
+typedef struct {
+ volatile unsigned int fd_sra; /* r: status register A */
+ int pad0[15];
+ volatile unsigned int fd_srb; /* r: status register B */
+ int pad1[15];
+ volatile unsigned int fd_dor; /* rw: digital output reg */
+ int pad2[15];
+ volatile unsigned int fd_tdr; /* rw: tape drive register */
+ int pad3[15];
+ volatile unsigned int fd_msr; /* r: main status register */
+/*#define fd_dsr fd_msr; /* w: data rate select reg */
+ int pad4[15];
+ volatile unsigned int fd_data; /* rw: fifo */
+ int pad5[15];
+ volatile unsigned int fd_xxx; /* --reserved-- */
+ int pad6[15];
+ volatile unsigned int fd_dir; /* r: digital input reg */
+/*#define fd_ccr fd_dir; /* w: config control reg */
+} fd_padded_regmap_t;
+
+#define machdep_reset_8272a(f,r)
+
+#else /* MAXINE */
+
+/* Pick your chip and padding */
+#define my_fdc_type fdc_8272a
+#define the_fdc_type my_fdc_type
+
+#define fd_padded_regmap_t fd_8272a_regmap_t
+
+#define machdep_reset_8272a(f,r) 1
+
+#endif /* MAXINE */
+
+
+#ifndef MAX_DRIVES
+#define MAX_DRIVES DRIVES_PER_FDC
+#endif
+
+/*
+ * Autoconf info
+ */
+
+static vm_offset_t fd_std[NFD] = { 0 };
+static struct bus_device *fd_info[NFD];
+static struct bus_ctlr *fd_minfo[NFD];
+static int fd_probe(), fd_slave(), fd_go();
+static void fd_attach();
+
+struct bus_driver fd_driver =
+ { fd_probe, fd_slave, fd_attach, fd_go, fd_std, "fd", fd_info,
+ "fdc", fd_minfo, /*BUS_INTR_B4_PROBE*/};
+
+/*
+ * Externally visible functions
+ */
+int fd_intr(); /* kernel */
+
+/*
+ * Media table
+ *
+ * Cyls,Sec,spc,part,Mtype,RWFpl,FGpl
+ */
+typedef struct {
+ unsigned char d_cylperunit;
+ unsigned char d_secpercyl;
+ unsigned short d_secperunit;
+ unsigned char d_secpertrk;
+ unsigned char d_gpl;
+ unsigned char d_fgpl;
+ unsigned char d_xfer_rate;
+} fd_params_t;
+
+fd_params_t fd_params[8] = {
+ {80, 18, 1440, 9, 0x2a, 0x50, FD_DSR_DD_250}, /* [0] 3.50" 720 Kb */
+ {80, 36, 2880, 18, 0x1b, 0x6c, FD_DSR_DD_500}, /* [1] 3.50" 1.44 Meg */
+ {40, 18, 720, 9, 0x2a, 0x50, FD_DSR_DD_250}, /* [2] 5.25" 360 Kb */
+ {80, 30, 2400, 15, 0x1b, 0x54, FD_DSR_DD_500}, /* [3] 5.25" 1.20 Meg */
+};
+
+/*
+ * Software status of chip
+ */
+struct fd_softc {
+ fd_padded_regmap_t *regs;
+ char fdc_type;
+ char fdc_mode;
+ char messed_up;
+ char slave_active;
+ struct slave_t {
+ io_req_t ior;
+ decl_simple_lock_data(,slave_lock)
+
+ /* status at end of last command */
+ unsigned char st0;
+ unsigned char st1;
+ unsigned char st2;
+ unsigned char c;
+ unsigned char h;
+ unsigned char r;
+ unsigned char n;
+ unsigned char st3;
+ /* ... */
+ unsigned char medium_status;
+# define ST_MEDIUM_PRESENT 1
+# define ST_MEDIUM_KNOWN 2
+ char last_command;
+ char bytes_expected;
+ fd_params_t *params;
+
+ } slave_status[DRIVES_PER_FDC];
+} fd_softc_data[NFD];
+
+typedef struct fd_softc *fd_softc_t;
+
+fd_softc_t fd_softc[NFD];
+
+static char *chip_names[4] = { "8272-A", "82072", "82077-AA", 0 };
+static char *mode_names[4] = { "PC AT", "PS/2", "Model 30", 0 };
+
+/*
+ * Probe chip to see if it is there
+ */
+static fd_probe (reg, ctlr)
+ vm_offset_t reg;
+ struct bus_ctlr *ctlr;
+{
+ int unit = ctlr->unit;
+ fd_softc_t fd;
+ fd_padded_regmap_t *regs;
+
+ /*
+ * See if we are here
+ */
+ if (check_memory(reg, 0)) {
+ /* no rides today */
+ return 0;
+ }
+
+ fd = &fd_softc_data[unit];
+ fd_softc[unit] = fd;
+
+ regs = (fd_padded_regmap_t *)reg;
+ fd->regs = regs;
+ fd->fdc_type = my_fdc_type;
+
+ fd_reset(fd);
+
+ if (the_fdc_type == fdc_82077aa) {
+ /* See if properly functioning */
+ unsigned char temp = FD_CMD_VERSION;
+ if (!fd_go(fd, 0, &temp, 1, 1))
+ return 0; /* total brxage */
+ if (!fd_get_result(fd, &temp, 1, FALSE))
+ return 0; /* partial brxage */
+ if (temp != FD_VERSION_82077AA)
+ printf( "{ %s x%x } ",
+ "Accepting non-82077aa version id",
+ temp);
+ }
+
+ printf("%s%d: %s chip controller",
+ ctlr->name, ctlr->unit, chip_names[fd->fdc_type]);
+ if (the_fdc_type == fdc_82077aa)
+ printf(" in %s mode", mode_names[fd->fdc_mode]);
+ printf(".\n");
+
+ return 1;
+}
+
+/* See if we like this slave */
+static fd_slave(ui, reg)
+ struct bus_device *ui;
+ vm_offset_t reg;
+{
+ int slave = ui->slave;
+ fd_softc_t fd;
+ unsigned char sns[2];
+
+ if (slave >= MAX_DRIVES) return 0;
+
+ fd = fd_softc[ui->ctlr];
+
+ sns[0] = FD_CMD_SENSE_DRIVE_STATUS;
+ sns[1] = slave & 0x3;
+ if (the_fdc_type == fdc_82072)
+ sns[1] |= FD_CMD_SDS_NO_MOT;
+ if (!fd_go(fd, slave, sns, 2, 1)) return 0;
+ if (!fd_get_result(fd, sns, 1, FALSE)) return 0;
+
+ fd->slave_status[slave].st3 = sns[0];
+
+ return 1;
+}
+
+static void
+fd_attach (ui)
+ struct bus_device *ui;
+{
+ /* Attach a slave */
+}
+
+static boolean_t
+fd_go(fd, slave, cmd, cmdlen, reply_count)
+ fd_softc_t fd;
+ unsigned char cmd[];
+{
+
+ /* XXX check who active, enque ifnot */
+
+ fd->slave_active = slave;
+ fd->slave_status[slave].bytes_expected = reply_count;
+ fd->slave_status[slave].last_command = *cmd;
+ return fd_command(fd, cmd, cmdlen);
+}
+
+fd_intr (unit, spllevel)
+{
+ fd_softc_t fd;
+ fd_padded_regmap_t *regs;
+ unsigned char msr;
+ register struct slave_t *slv;
+
+
+ splx(spllevel);
+
+ fd = fd_softc[unit];
+ regs = fd->regs;
+
+ /* did polling see a media change */
+ /* busy bit in msr sez ifasync or not */
+
+ msr = regs->fd_msr;
+ if ((msr & (FD_MSR_RQM|FD_MSR_DIO)) == (FD_MSR_RQM|FD_MSR_DIO)) {
+
+ /* result phase */
+*(unsigned int *)0xbc040100 &= ~0x00600000;
+
+ slv = &fd->slave_status[fd->slave_active];
+ fd_get_result(fd, &slv->st0, slv->bytes_expected, FALSE);
+ fd_start(fd, fd->slave_active, TRUE);
+ return;
+ }
+ /* async interrupt, either seek complete or media change */
+ while (1) {
+ unsigned char st[2];
+ register int slave, m;
+
+ *st = FD_CMD_SENSE_INT_STATUS;
+ fd_command(fd, st, 1);
+
+ fd_get_result(fd, st, 2, FALSE);
+
+ slave = *st & FD_ST0_DS;
+ slv = &fd->slave_status[slave];
+ slv->c = st[1];
+
+ switch (*st & FD_ST0_IC_MASK) {
+
+ case FD_ST0_IC_OK:
+/* we get an FD_ST0_SE for RECALIBRATE. Wait for it or discard ? */
+
+ case FD_ST0_IC_AT:
+
+ case FD_ST0_IC_BAD_CMD:
+ return;
+
+ case FD_ST0_IC_AT_POLL:
+ m = slv->medium_status;
+ if (m & ST_MEDIUM_PRESENT)
+ m &= ~ST_MEDIUM_PRESENT;
+ else
+ m |= ST_MEDIUM_PRESENT;
+ slv->medium_status = m;
+ }
+ }
+}
+
+/*
+ * Non-interface functions and utilities
+ */
+
+fd_reset(fd)
+ fd_softc_t fd;
+{
+ register fd_padded_regmap_t *regs;
+
+ regs = fd->regs;
+
+ /*
+ * Reset the chip
+ */
+ if (the_fdc_type == fdc_82072)
+ /* Fix if your box uses an external PLL */
+ regs->fd_dsr = FD_DSR_RESET | FD_DSR_EPLL;
+ else if (the_fdc_type == fdc_82077aa)
+ regs->fd_dor = 0;
+ else
+ machdep_reset_8272a(fd, regs);
+
+ delay(5); /* 4usecs in specs */
+
+ /*
+ * Be smart with the smart ones
+ */
+ if (the_fdc_type == fdc_82077aa) {
+
+ /*
+ * See in which mood we are (it cannot be changed)
+ */
+ int temp;
+
+ /* Take chip out of hw reset */
+ regs->fd_dor = FD_DOR_ENABLE | FD_DOR_DMA_GATE;
+ delay(10);
+
+ /* what do we readback from the DIR register as datarate ? */
+ regs->fd_ccr = FD_DSR_SD_125;
+ delay(10);
+
+ temp = regs->fd_dir;
+ if ((temp & 0x7) == FD_DSR_SD_125)
+ fd->fdc_mode = mod30_mode;
+ else if ((temp & (FD_DIR_ones | FD_DIR_DR_MASK_PS2)) ==
+ ((FD_DSR_SD_125 << FD_DIR_DR_SHIFT_PS2) | FD_DIR_ones))
+ fd->fdc_mode = ps2_mode;
+ else
+ /* this assumes tri-stated bits 1&2 read the same */
+ fd->fdc_mode = at_mode;
+
+ }
+
+ /*
+ * Send at least 4 sense interrupt cmds, one per slave
+ */
+ {
+
+ unsigned char sns, st[2];
+ int i, nloops;
+
+ sns = FD_CMD_SENSE_INT_STATUS;
+ i = nloops = 0;
+
+ do {
+ nloops++;
+
+ (void) fd_command(fd, &sns, 1);
+
+ st[0] = 0; /* in case bad status */
+ (void) fd_get_result(fd, st, 2, TRUE);
+
+ if ((st[0] & FD_ST0_IC_MASK) == FD_ST0_IC_AT_POLL) {
+ register int slave;
+
+ slave = st[0] & FD_ST0_DS;
+ fd->slave_status[slave].st0 = st[0];
+ fd->slave_status[slave].c = st[1];
+ i++;
+ }
+ } while ( (nloops < 30) &&
+ ((i < 4) || (st[0] != FD_ST0_IC_BAD_CMD)) );
+
+ /* sanity check */
+ if (nloops == 30) {
+ (void) fd_messed_up(fd);
+ return;
+ }
+ }
+
+ /*
+ * Install current parameters
+ */
+ if (the_fdc_type != fdc_8272a) {
+
+ unsigned char cnf[4];
+
+ /* send configure command to turn polling off */
+ cnf[0] = FD_CMD_CONFIGURE;
+ cnf[1] = 0x60; /* moff 110 */
+ cnf[2] = 0x48; /* eis, poll, thr=8 */
+ cnf[3] = 0;
+ if (!fd_command(fd, cnf, 4))
+ return;
+ /* no status */
+ }
+
+ /*
+ * Send specify to select defaults
+ */
+ {
+ unsigned char sfy[3];
+
+ sfy[0] = FD_CMD_SPECIFY;
+#if 0
+ sfy[1] = (12 << 4) | 7; /* step 4, hut 112us @500 */
+ sfy[2] = 2 << 1; /* hlt 29us @500 */
+#else
+ sfy[1] = (13 << 4) | 15;
+ sfy[2] = 1 << 1;
+#endif
+ (void) fd_command(fd, sfy, 3);
+ /* no status */
+ }
+}
+
+#define FD_MAX_WAIT 1000
+
+boolean_t
+fd_command(fd, cmd, cmd_len)
+ fd_softc_t fd;
+ char *cmd;
+{
+ register fd_padded_regmap_t *regs;
+
+ regs = fd->regs;
+
+ while (cmd_len > 0) {
+ register int i, s;
+
+ /* there might be long delays, so we pay this price */
+ s = splhigh();
+ for (i = 0; i < FD_MAX_WAIT; i++)
+ if ((regs->fd_msr & (FD_MSR_RQM|FD_MSR_DIO)) ==
+ FD_MSR_RQM)
+ break;
+ else
+ delay(10);
+ if (i == FD_MAX_WAIT) {
+ splx(s);
+ return fd_messed_up(fd);
+ }
+ regs->fd_data = *cmd++;
+ splx(s);
+ if (--cmd_len) delay(12);
+ }
+
+ return TRUE;
+}
+
+boolean_t
+fd_get_result(fd, st, st_len, ignore_errors)
+ fd_softc_t fd;
+ char *st;
+{
+ register fd_padded_regmap_t *regs;
+
+ regs = fd->regs;
+
+ while (st_len > 0) {
+ register int i, s;
+
+ /* there might be long delays, so we pay this price */
+ s = splhigh();
+ for (i = 0; i < FD_MAX_WAIT; i++)
+ if ((regs->fd_msr & (FD_MSR_RQM|FD_MSR_DIO)) ==
+ (FD_MSR_RQM|FD_MSR_DIO))
+ break;
+ else
+ delay(10);
+ if (i == FD_MAX_WAIT) {
+ splx(s);
+ return (ignore_errors) ? FALSE : fd_messed_up(fd);
+ }
+ *st++ = regs->fd_data;
+ splx(s);
+ st_len--;
+ }
+
+ return TRUE;
+}
+
+
+boolean_t
+fd_messed_up(fd)
+ fd_softc_t fd;
+{
+ fd->messed_up++;
+ printf("fd%d: messed up, disabling.\n", fd - fd_softc_data);
+ /* here code to
+ ior->error = ..;
+ restart
+ */
+ return FALSE;
+}
+
+/*
+ * Debugging aids
+ */
+
+fd_state(unit)
+{
+ fd_softc_t fd = fd_softc[unit];
+ fd_padded_regmap_t *regs;
+
+ if (!fd || !fd->regs) return 0;
+ regs = fd->regs;
+ if (the_fdc_type == fdc_8272a)
+ printf("msr %x\n", regs->fd_msr);
+ else
+ printf("sra %x srb %x dor %x tdr %x msr %x dir %x\n",
+ regs->fd_sra, regs->fd_srb, regs->fd_dor,
+ regs->fd_tdr, regs->fd_msr, regs->fd_dir);
+}
+
+#endif
+
+/* to be moved in separate file, or the above modified to live with scsi */
+
+fd_open(dev, mode, ior)
+ int dev;
+ dev_mode_t mode;
+ io_req_t ior;
+{
+ unsigned char cmd[2];
+ fd_softc_t fd;
+ int slave;
+
+ fd = fd_softc[UNITNO(dev)];
+ slave = SLAVENO(dev);
+
+ /* XXX find out what medium we have, automagically XXX */
+ /* fornow, set params depending on minor */
+ fd->slave_status[slave].params = &fd_params[PARAMNO(dev)];
+
+ /* XXXYYYXXXYYY SEND CONFIGURE if params changed */
+
+ /* Turn motor on */
+ if (the_fdc_type == fdc_82072) {
+
+ cmd[0] = FD_CMD_MOTOR_ON_OFF | FD_CMD_MOT_ON |
+ ((slave << FD_CMD_MOT_DS_SHIFT) & FD_CMD_MOT_DS);
+ (void) fd_go(fd, slave, cmd, 1, 0);
+ /* no status */
+
+ } else if (the_fdc_type == fdc_82077aa) {
+
+ fd->regs->fd_dor |= ((1<<slave)<<4);
+ }
+
+ /* recalibrate to track 0 */
+ cmd[0] = FD_CMD_RECALIBRATE;
+ cmd[1] = slave;
+ if (!fd_go(fd, slave, cmd, 2, 0))
+ return D_DEVICE_DOWN;
+ /* will generate a completion interrupt */
+
+ /* if not writeable return D_READ_ONLY ? */
+
+ return D_SUCCESS;
+}
+
+fd_close(dev)
+ int dev;
+{
+ fd_softc_t fd;
+ register int slave;
+ unsigned char cmd[2];
+
+ slave = SLAVENO(dev);
+ fd = fd_softc[UNITNO(dev)];
+
+ /* do not delete media info, do that iff interrupt sez changed */
+
+ /* Turn motor off */
+ if (the_fdc_type == fdc_82072) {
+
+ cmd[0] = FD_CMD_MOTOR_ON_OFF |
+ ((slave << FD_CMD_MOT_DS_SHIFT) & FD_CMD_MOT_DS);
+ (void) fd_go(fd, 0, cmd, 1, 0);
+ /* no status */
+
+ } else if (the_fdc_type == fdc_82077aa) {
+
+ fd->regs->fd_dor &= ~((1<<slave)<<4);
+ }
+ return D_SUCCESS;
+}
+
+fd_strategy(ior)
+ io_req_t ior;
+{
+#if 0
+ if (ior->io_op & IO_READ)
+ bzero(ior->io_data, ior->io_count);
+ iodone(ior);
+#else
+ struct slave_t *slv;
+ fd_softc_t fd;
+ unsigned int i, rec, max, dev;
+ fd_params_t *params;
+
+ /* readonly */
+
+ dev = ior->io_unit;
+
+ /* only one partition */
+ fd = fd_softc[UNITNO(dev)];
+ slv = &fd->slave_status[SLAVENO(dev)];
+ params = slv->params;
+ max = params->d_secperunit;
+ rec = ior->io_recnum;
+ i = btodb(ior->io_count + DEV_BSIZE - 1);
+ if (((rec + i) > max) || (ior->io_count < 0)) {
+ ior->io_error = D_INVALID_SIZE;
+ ior->io_op |= IO_ERROR;
+ ior->io_residual = ior->io_count;
+ iodone(ior);
+ return;
+ }
+
+ ior->io_residual = rec / params->d_secpercyl;
+
+ /*
+ * Enqueue operation
+ */
+ i = splbio();
+ simple_lock(&slv->slave_lock);
+ if (slv->ior) {
+ disksort(slv->ior, ior);
+ simple_unlock(&slv->slave_lock);
+ } else {
+ ior->io_next = 0;
+ slv->ior = ior;
+ simple_unlock(&slv->slave_lock);
+ fd_start(fd, SLAVENO(dev), FALSE);
+ }
+ splx(i);
+#endif
+}
+
+fd_start(fd, slave, done)
+ boolean_t done;
+ fd_softc_t fd;
+{
+ register io_req_t ior;
+ struct slave_t *slv;
+
+ slv = &fd->slave_status[slave];
+ if ((ior = slv->ior) == 0)
+ return;
+
+ if (done) {
+ /* .. errors .. */
+ /* .. partial xfers .. */
+
+ /* dequeue next one */
+ {
+ io_req_t next;
+
+ simple_lock(&slv->target_lock);
+ next = ior->io_next;
+ slv->ior = next;
+ simple_unlock(&slv->target_lock);
+
+ iodone(ior);
+ if (next == 0)
+ return;
+
+ ior = next;
+ }
+ }
+
+#ifdef no_eis
+ if (slv->c != ior->io_residual) SEEK_it;
+#endif
+
+/* setup dma */
+#if 1
+ if (ior->io_op & IO_READ) /* like SCSI */
+#else
+ if ((ior->io_op & IO_READ) == 0)
+#endif
+ {
+ *(unsigned int *)0xbc040100 |= 0x00200000 | 0x00400000;
+ } else {
+ *(unsigned int *)0xbc040100 &= ~0x00400000;
+ *(unsigned int *)0xbc040100 |= 0x00200000;
+ }
+ *(unsigned int *)0xbc040070 = (((unsigned int)kvtophys(ior->io_data))>>2)<<5;
+ *(unsigned int *)0xbc0401a0 = 13;
+
+#ifdef no_eis
+ if (slv->c == ior->io_residual) {
+#else
+ {
+#endif
+ unsigned char cmd[9];
+ unsigned char head, sec;
+ fd_params_t *params;
+
+ params = slv->params;
+
+ fd->regs->fd_dsr = params->d_xfer_rate;
+
+ sec = ior->io_recnum % params->d_secpercyl;
+ head = sec / params->d_secpertrk;
+ sec = (sec % params->d_secpertrk);
+
+ cmd[0] = (ior->io_op & IO_READ) ?
+ FD_CMD_MT | FD_CMD_MFM | FD_CMD_READ_DATA :
+ FD_CMD_MT | FD_CMD_MFM | FD_CMD_WRITE_DATA;
+ cmd[1] = (head << 2) | slave;
+ cmd[2] = ior->io_residual;
+ cmd[3] = head;
+ cmd[4] = sec + 1; /* 0 starts at 1 :-) */
+ cmd[5] = 0x2; /* 512 byte sectors */
+ cmd[6] = params->d_secpertrk;
+ cmd[7] = params->d_gpl;
+ cmd[8] = 0xff;
+
+ fd_go( fd, slave, cmd, 9, 7);
+
+ }
+}
+
+extern minphys();
+
+fd_read(dev, ior)
+ int dev;
+ io_req_t ior;
+{
+ return block_io(fd_strategy, minphys, ior);
+}
+
+int fdc_write_enable = 1;
+
+fd_write(dev, ior)
+ int dev;
+ io_req_t ior;
+{
+/* check if writeable */
+
+if (fdc_write_enable)
+ return block_io(fd_strategy, minphys, ior);
+else return D_SUCCESS;
+}
+
+fd_set_status(dev, flavor, status, status_count)
+ int dev;
+ int flavor;
+ dev_status_t status;
+ unsigned int *status_count;
+{
+ printf("fdc_set_status(%x, %x, %x, %x)", dev, flavor, status, status_count);
+ return D_SUCCESS;
+}
+
+fd_get_status(dev, flavor, status, status_count)
+ int dev;
+ int flavor;
+ dev_status_t status;
+ unsigned int status_count;
+{
+ printf("fdc_get_status(%x, %x, %x, %x)", dev, flavor, status, status_count);
+ return D_SUCCESS;
+}
+
diff --git a/chips/frc.c b/chips/frc.c
new file mode 100644
index 00000000..7f033c37
--- /dev/null
+++ b/chips/frc.c
@@ -0,0 +1,150 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: frc.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 3/92
+ *
+ * Generic, mappable free running counter driver.
+ */
+
+#include <frc.h>
+#if NFRC > 0
+
+#include <mach/std_types.h>
+#include <chips/busses.h>
+#include <device/device_types.h>
+
+/*
+ * Machine defines
+ * All you need to do to get this working on a
+ * random box is to define one macro and provide
+ * the correct virtual address.
+ */
+#include <platforms.h>
+#ifdef DECSTATION
+#define btop(x) mips_btop(x)
+#endif /* DECSTATION */
+
+/*
+ * Autoconf info
+ */
+
+static vm_offset_t frc_std[NFRC] = { 0 };
+static vm_size_t frc_offset[NFRC] = { 0 };
+static struct bus_device *frc_info[NFRC];
+static int frc_probe(vm_offset_t,struct bus_ctlr *);
+static void frc_attach(struct bus_device *);
+
+struct bus_driver frc_driver =
+ { frc_probe, 0, frc_attach, 0, frc_std, "frc", frc_info, };
+
+/*
+ * Externally visible functions
+ */
+io_return_t frc_openclose(int,int); /* user */
+vm_offset_t frc_mmap(int,vm_offset_t,vm_prot_t);
+void frc_set_address(int,vm_size_t);
+
+/*
+ * FRC's in kernel virtual memory. For in-kernel timestamps.
+ */
+vm_offset_t frc_address[NFRC];
+
+/* machine-specific setups */
+void
+frc_set_address(
+ int unit,
+ vm_size_t offset)
+{
+ if (unit < NFRC) {
+ frc_offset[unit] = offset;
+ }
+}
+
+
+/*
+ * Probe chip to see if it is there
+ */
+static frc_probe (
+ vm_offset_t reg,
+ struct bus_ctlr *ui)
+{
+ /* see if something present at the given address */
+ if (check_memory(reg, 0)) {
+ frc_address[ui->unit] = 0;
+ return 0;
+ }
+ frc_std[ui->unit] = (vm_offset_t) reg;
+ printf("[mappable] ");
+ return 1;
+}
+
+static void
+frc_attach (
+ struct bus_device *ui)
+{
+ if (ui->unit < NFRC) {
+ frc_address[ui->unit] =
+ (vm_offset_t) frc_std[ui->unit] + frc_offset[ui->unit];
+ printf(": free running counter %d at kernel vaddr 0x%x",
+ ui->unit, frc_address[ui->unit]);
+ }
+ else
+ panic("frc: unknown unit number"); /* shouldn't happen */
+}
+
+int frc_intr()
+{
+ /* we do not expect interrupts */
+ panic("frc_intr");
+}
+
+io_return_t
+frc_openclose(
+ int dev,
+ int flag)
+{
+ if (frc_std[dev])
+ return D_SUCCESS;
+ else
+ return D_NO_SUCH_DEVICE;
+}
+
+vm_offset_t
+frc_mmap(
+ int dev,
+ vm_offset_t off,
+ vm_prot_t prot)
+{
+ vm_offset_t addr;
+ if ((prot & VM_PROT_WRITE) || (off >= PAGE_SIZE) )
+ return (-1);
+ addr = (vm_offset_t) frc_std[dev] + frc_offset[dev];
+ return btop(pmap_extract(pmap_kernel(), addr));
+}
+
+#endif
diff --git a/chips/ims332.c b/chips/ims332.c
new file mode 100644
index 00000000..ebe6a6cb
--- /dev/null
+++ b/chips/ims332.c
@@ -0,0 +1,312 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: ims332.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Routines for the Inmos IMS-G332 Colour video controller
+ */
+
+#include <platforms.h>
+
+#include <chips/ims332.h>
+#include <chips/screen.h>
+
+#include <chips/xcfb_monitor.h>
+
+/*
+ * Generic register access
+ */
+typedef volatile unsigned char *ims332_padded_regmap_t;
+
+#ifdef MAXINE
+
+unsigned int
+ims332_read_register(regs, regno)
+ unsigned char *regs;
+{
+ unsigned char *rptr;
+ register unsigned int val, v1;
+
+ /* spec sez: */
+ rptr = regs + 0x80000 + (regno << 4);
+ val = * ((volatile unsigned short *) rptr );
+ v1 = * ((volatile unsigned short *) regs );
+
+ return (val & 0xffff) | ((v1 & 0xff00) << 8);
+}
+
+ims332_write_register(regs, regno, val)
+ unsigned char *regs;
+ register unsigned int val;
+{
+ unsigned char *wptr;
+
+ /* spec sez: */
+ wptr = regs + 0xa0000 + (regno << 4);
+ * ((volatile unsigned int *)(regs)) = (val >> 8) & 0xff00;
+ * ((volatile unsigned short *)(wptr)) = val;
+}
+
+#define assert_ims332_reset_bit(r) *r &= ~0x40
+#define deassert_ims332_reset_bit(r) *r |= 0x40
+
+#else /*MAXINE*/
+
+#define ims332_read_register(p,r) \
+ ((unsigned int *)(p)) [ (r) ]
+#define ims332_write_register(p,r,v) \
+ ((unsigned int *)(p)) [ (r) ] = (v)
+
+#endif /*MAXINE*/
+
+
+/*
+ * Color map
+ */
+ims332_load_colormap( regs, map)
+ ims332_padded_regmap_t *regs;
+ color_map_t *map;
+{
+ register int i;
+
+ for (i = 0; i < 256; i++, map++)
+ ims332_load_colormap_entry(regs, i, map);
+}
+
+ims332_load_colormap_entry( regs, entry, map)
+ ims332_padded_regmap_t *regs;
+ color_map_t *map;
+{
+ /* ?? stop VTG */
+ ims332_write_register(regs, IMS332_REG_LUT_BASE + (entry & 0xff),
+ (map->blue << 16) |
+ (map->green << 8) |
+ (map->red));
+}
+
+ims332_init_colormap( regs)
+ ims332_padded_regmap_t *regs;
+{
+ color_map_t m;
+
+ m.red = m.green = m.blue = 0;
+ ims332_load_colormap_entry( regs, 0, &m);
+
+ m.red = m.green = m.blue = 0xff;
+ ims332_load_colormap_entry( regs, 1, &m);
+ ims332_load_colormap_entry( regs, 255, &m);
+
+ /* since we are at it, also fix cursor LUT */
+ ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_0, &m);
+ ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_1, &m);
+ /* *we* do not use this, but the prom does */
+ ims332_load_colormap_entry( regs, IMS332_REG_CURSOR_LUT_2, &m);
+}
+
+#if 1/*debug*/
+ims332_print_colormap( regs)
+ ims332_padded_regmap_t *regs;
+{
+ register int i;
+
+ for (i = 0; i < 256; i++) {
+ register unsigned int color;
+
+ color = ims332_read_register( regs, IMS332_REG_LUT_BASE + i);
+ printf("%x->[x%x x%x x%x]\n", i,
+ (color >> 16) & 0xff,
+ (color >> 8) & 0xff,
+ color & 0xff);
+ }
+}
+#endif
+
+/*
+ * Video on/off
+ *
+ * It is unfortunate that X11 goes backward with white@0
+ * and black@1. So we must stash away the zero-th entry
+ * and fix it while screen is off. Also must remember
+ * it, sigh.
+ */
+struct vstate {
+ ims332_padded_regmap_t *regs;
+ unsigned short off;
+};
+
+ims332_video_off(vstate, up)
+ struct vstate *vstate;
+ user_info_t *up;
+{
+ register ims332_padded_regmap_t *regs = vstate->regs;
+ register unsigned *save, csr;
+
+ if (vstate->off)
+ return;
+
+ /* Yes, this is awful */
+ save = (unsigned *)up->dev_dep_2.gx.colormap;
+
+ *save = ims332_read_register(regs, IMS332_REG_LUT_BASE);
+
+ ims332_write_register(regs, IMS332_REG_LUT_BASE, 0);
+
+ ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0);
+
+ /* cursor now */
+ csr = ims332_read_register(regs, IMS332_REG_CSR_A);
+ csr |= IMS332_CSR_A_DISABLE_CURSOR;
+ ims332_write_register(regs, IMS332_REG_CSR_A, csr);
+
+ vstate->off = 1;
+}
+
+ims332_video_on(vstate, up)
+ struct vstate *vstate;
+ user_info_t *up;
+{
+ register ims332_padded_regmap_t *regs = vstate->regs;
+ register unsigned *save, csr;
+
+ if (!vstate->off)
+ return;
+
+ /* Like I said.. */
+ save = (unsigned *)up->dev_dep_2.gx.colormap;
+
+ ims332_write_register(regs, IMS332_REG_LUT_BASE, *save);
+
+ ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0xffffffff);
+
+ /* cursor now */
+ csr = ims332_read_register(regs, IMS332_REG_CSR_A);
+ csr &= ~IMS332_CSR_A_DISABLE_CURSOR;
+ ims332_write_register(regs, IMS332_REG_CSR_A, csr);
+
+ vstate->off = 0;
+}
+
+/*
+ * Cursor
+ */
+ims332_pos_cursor(regs,x,y)
+ ims332_padded_regmap_t *regs;
+ register int x,y;
+{
+ ims332_write_register( regs, IMS332_REG_CURSOR_LOC,
+ ((x & 0xfff) << 12) | (y & 0xfff) );
+}
+
+
+ims332_cursor_color( regs, color)
+ ims332_padded_regmap_t *regs;
+ color_map_t *color;
+{
+ /* Bg is color[0], Fg is color[1] */
+ ims332_write_register(regs, IMS332_REG_CURSOR_LUT_0,
+ (color->blue << 16) |
+ (color->green << 8) |
+ (color->red));
+ color++;
+ ims332_write_register(regs, IMS332_REG_CURSOR_LUT_1,
+ (color->blue << 16) |
+ (color->green << 8) |
+ (color->red));
+}
+
+ims332_cursor_sprite( regs, cursor)
+ ims332_padded_regmap_t *regs;
+ unsigned short *cursor;
+{
+ register int i;
+
+ /* We *could* cut this down a lot... */
+ for (i = 0; i < 512; i++, cursor++)
+ ims332_write_register( regs,
+ IMS332_REG_CURSOR_RAM+i, *cursor);
+}
+
+/*
+ * Initialization
+ */
+ims332_init(regs, reset, mon)
+ ims332_padded_regmap_t *regs;
+ unsigned int *reset;
+ xcfb_monitor_type_t mon;
+{
+ int shortdisplay, broadpulse, frontporch;
+
+ assert_ims332_reset_bit(reset);
+ delay(1); /* specs sez 50ns.. */
+ deassert_ims332_reset_bit(reset);
+
+ /* CLOCKIN appears to receive a 6.25 Mhz clock --> PLL 12 for 75Mhz monitor */
+ ims332_write_register(regs, IMS332_REG_BOOT, 12 | IMS332_BOOT_CLOCK_PLL);
+
+ /* initialize VTG */
+ ims332_write_register(regs, IMS332_REG_CSR_A,
+ IMS332_BPP_8 | IMS332_CSR_A_DISABLE_CURSOR);
+ delay(50); /* spec does not say */
+
+ /* datapath registers (values taken from prom's settings) */
+
+ frontporch = mon->line_time - (mon->half_sync * 2 +
+ mon->back_porch +
+ mon->frame_visible_width / 4);
+
+ shortdisplay = mon->line_time / 2 - (mon->half_sync * 2 +
+ mon->back_porch + frontporch);
+ broadpulse = mon->line_time / 2 - frontporch;
+
+ ims332_write_register( regs, IMS332_REG_HALF_SYNCH, mon->half_sync);
+ ims332_write_register( regs, IMS332_REG_BACK_PORCH, mon->back_porch);
+ ims332_write_register( regs, IMS332_REG_DISPLAY,
+ mon->frame_visible_width / 4);
+ ims332_write_register( regs, IMS332_REG_SHORT_DIS, shortdisplay);
+ ims332_write_register( regs, IMS332_REG_BROAD_PULSE, broadpulse);
+ ims332_write_register( regs, IMS332_REG_V_SYNC, mon->v_sync * 2);
+ ims332_write_register( regs, IMS332_REG_V_PRE_EQUALIZE,
+ mon->v_pre_equalize);
+ ims332_write_register( regs, IMS332_REG_V_POST_EQUALIZE,
+ mon->v_post_equalize);
+ ims332_write_register( regs, IMS332_REG_V_BLANK, mon->v_blank * 2);
+ ims332_write_register( regs, IMS332_REG_V_DISPLAY,
+ mon->frame_visible_height * 2);
+ ims332_write_register( regs, IMS332_REG_LINE_TIME, mon->line_time);
+ ims332_write_register( regs, IMS332_REG_LINE_START, mon->line_start);
+ ims332_write_register( regs, IMS332_REG_MEM_INIT, mon->mem_init);
+ ims332_write_register( regs, IMS332_REG_XFER_DELAY, mon->xfer_delay);
+
+ ims332_write_register( regs, IMS332_REG_COLOR_MASK, 0xffffff);
+
+ ims332_init_colormap( regs );
+
+ ims332_write_register(regs, IMS332_REG_CSR_A,
+ IMS332_BPP_8 | IMS332_CSR_A_DMA_DISABLE | IMS332_CSR_A_VTG_ENABLE);
+
+}
diff --git a/chips/ims332.h b/chips/ims332.h
new file mode 100644
index 00000000..edb2302e
--- /dev/null
+++ b/chips/ims332.h
@@ -0,0 +1,137 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: ims332.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Defines for the Inmos IMS-G332 Colour video controller
+ */
+
+
+#ifndef _CHIPS_IMS332_H_
+#define _CHIPS_IMS332_H_ 1
+
+/*
+ * Although the chip is built to be memory-mapped
+ * it can be programmed for 32 or 64 bit addressing.
+ * Moreover, the hardware bits have been twisted
+ * even more on the machine I am writing this for.
+ * So I'll just define the chip's offsets and leave
+ * it to the implementation to define the rest.
+ */
+
+#define IMS332_REG_BOOT 0x000 /* boot time config */
+
+#define IMS332_REG_HALF_SYNCH 0x021 /* datapath registers */
+#define IMS332_REG_BACK_PORCH 0x022
+#define IMS332_REG_DISPLAY 0x023
+#define IMS332_REG_SHORT_DIS 0x024
+#define IMS332_REG_BROAD_PULSE 0x025
+#define IMS332_REG_V_SYNC 0x026
+#define IMS332_REG_V_PRE_EQUALIZE 0x027
+#define IMS332_REG_V_POST_EQUALIZE 0x028
+#define IMS332_REG_V_BLANK 0x029
+#define IMS332_REG_V_DISPLAY 0x02a
+#define IMS332_REG_LINE_TIME 0x02b
+#define IMS332_REG_LINE_START 0x02c
+#define IMS332_REG_MEM_INIT 0x02d
+#define IMS332_REG_XFER_DELAY 0x02e
+
+#define IMS332_REG_COLOR_MASK 0x040 /* color mask register */
+
+#define IMS332_REG_CSR_A 0x060
+
+#define IMS332_REG_CSR_B 0x070
+
+#define IMS332_REG_TOP_SCREEN 0x080 /* top-of-screen offset */
+
+#define IMS332_REG_CURSOR_LUT_0 0x0a1 /* cursor palette */
+#define IMS332_REG_CURSOR_LUT_1 0x0a2
+#define IMS332_REG_CURSOR_LUT_2 0x0a3
+
+#define IMS332_REG_RGB_CKSUM_0 0x0c0 /* test registers */
+#define IMS332_REG_RGB_CKSUM_1 0x0c1
+#define IMS332_REG_RGB_CKSUM_2 0x0c2
+
+#define IMS332_REG_CURSOR_LOC 0x0c7 /* cursor location */
+
+#define IMS332_REG_LUT_BASE 0x100 /* color palette */
+#define IMS332_REG_LUT_END 0x1ff
+
+#define IMS332_REG_CURSOR_RAM 0x200 /* cursor bitmap */
+#define IMS332_REG_CURSOR_RAM_END 0x3ff
+
+/*
+ * Control register A
+ */
+
+#define IMS332_CSR_A_VTG_ENABLE 0x000001 /* vertical timing generator */
+#define IMS332_CSR_A_INTERLACED 0x000002 /* screen format */
+#define IMS332_CSR_A_CCIR 0x000004 /* default is EIA */
+#define IMS332_CSR_A_SLAVE_SYNC 0x000008 /* else from our pll */
+#define IMS332_CSR_A_PLAIN_SYNC 0x000010 /* else tesselated */
+#define IMS332_CSR_A_SEPARATE_SYNC 0x000020 /* else composite */
+#define IMS332_CSR_A_VIDEO_ONLY 0x000040 /* else video+sync */
+#define IMS332_CSR_A_BLANK_PEDESTAL 0x000080 /* blank level */
+#define IMS332_CSR_A_CBLANK_IS_OUT 0x000100
+#define IMS332_CSR_A_CBLANK_NO_DELAY 0x000200
+#define IMS332_CSR_A_FORCE_BLANK 0x000400
+#define IMS332_CSR_A_BLANK_DISABLE 0x000800
+#define IMS332_CSR_A_VRAM_INCREMENT 0x003000
+# define IMS332_VRAM_INC_1 0x000000
+# define IMS332_VRAM_INC_256 0x001000 /* except interlaced->2 */
+# define IMS332_VRAM_INC_512 0x002000
+# define IMS332_VRAM_INC_1024 0x003000
+#define IMS332_CSR_A_DMA_DISABLE 0x004000
+#define IMS332_CSR_A_SYNC_DELAY_MASK 0x038000 /* 0-7 VTG clk delays */
+#define IMS332_CSR_A_PIXEL_INTERLEAVE 0x040000
+#define IMS332_CSR_A_DELAYED_SAMPLING 0x080000
+#define IMS332_CSR_A_BITS_PER_PIXEL 0x700000
+# define IMS332_BPP_1 0x000000
+# define IMS332_BPP_2 0x100000
+# define IMS332_BPP_4 0x200000
+# define IMS332_BPP_8 0x300000
+# define IMS332_BPP_15 0x400000
+# define IMS332_BPP_16 0x500000
+#define IMS332_CSR_A_DISABLE_CURSOR 0x800000
+
+
+/*
+ * Control register B is mbz
+ */
+
+/*
+ * Boot register
+ */
+
+#define IMS332_BOOT_PLL 0x00001f /* xPLL, binary */
+#define IMS332_BOOT_CLOCK_PLL 0x000020 /* else xternal */
+#define IMS332_BOOT_64_BIT_MODE 0x000040 /* else 32 */
+#define IMS332_BOOT_xxx 0xffff80 /* reserved, mbz */
+
+
+#endif _CHIPS_IMS332_H_
diff --git a/chips/isdn_79c30.h b/chips/isdn_79c30.h
new file mode 100644
index 00000000..2e7b5d76
--- /dev/null
+++ b/chips/isdn_79c30.h
@@ -0,0 +1,165 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*-
+ * Copyright (c) 1991, 1992 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 Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. The name of the Laboratory may not 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.
+ */
+
+/*
+ * Bit encodings for chip commands from "Microprocessor Access Guide for
+ * Indirect Registers", p.19 Am79C30A/32A Advanced Micro Devices spec
+ * sheet (preliminary).
+ *
+ * Indirect register numbers (the value written into cr to select a given
+ * chip registers) have the form AMDR_*. Register fields look like AMD_*.
+ */
+
+typedef struct {
+ volatile unsigned char cr; /* command register (wo) */
+#define ir cr /* interrupt register (ro) */
+ volatile unsigned char dr; /* data register (rw) */
+ volatile unsigned char dsr1; /* D-channel status register 1 (ro) */
+ volatile unsigned char der; /* D-channel error register (ro) */
+ volatile unsigned char dctb; /* D-channel transmit register (wo) */
+#define dcrb dctb /* D-channel receive register (ro) */
+ volatile unsigned char bbtb; /* Bb-channel transmit register (wo) */
+#define bbrb bbtb /* Bb-channel receive register (ro) */
+ volatile unsigned char bctb; /* Bc-channel transmit register (wo)*/
+#define bcrb bctb /* Bc-channel receive register (ro) */
+ volatile unsigned char dsr2; /* D-channel status register 2 (ro) */
+} amd79c30_regmap_t;
+
+#define AMDR_INIT 0x21
+#define AMD_INIT_PMS_IDLE 0x00
+#define AMD_INIT_PMS_ACTIVE 0x01
+#define AMD_INIT_PMS_ACTIVE_DATA 0x02
+#define AMD_INIT_INT_DISABLE (0x01 << 2)
+#define AMD_INIT_CDS_DIV2 (0x00 << 3)
+#define AMD_INIT_CDS_DIV1 (0x01 << 3)
+#define AMD_INIT_CDS_DIV4 (0x02 << 3)
+#define AMD_INIT_AS_RX (0x01 << 6)
+#define AMD_INIT_AS_TX (0x01 << 7)
+
+#define AMDR_LIU_LSR 0xa1
+#define AMDR_LIU_LPR 0xa2
+#define AMDR_LIU_LMR1 0xa3
+#define AMDR_LIU_LMR2 0xa4
+#define AMDR_LIU_2_4 0xa5
+#define AMDR_LIU_MF 0xa6
+#define AMDR_LIU_MFSB 0xa7
+#define AMDR_LIU_MFQB 0xa8
+
+#define AMDR_MUX_MCR1 0x41
+#define AMDR_MUX_MCR2 0x42
+#define AMDR_MUX_MCR3 0x43
+#define AMD_MCRCHAN_NC 0x00
+#define AMD_MCRCHAN_B1 0x01
+#define AMD_MCRCHAN_B2 0x02
+#define AMD_MCRCHAN_BA 0x03
+#define AMD_MCRCHAN_BB 0x04
+#define AMD_MCRCHAN_BC 0x05
+#define AMD_MCRCHAN_BD 0x06
+#define AMD_MCRCHAN_BE 0x07
+#define AMD_MCRCHAN_BF 0x08
+#define AMDR_MUX_MCR4 0x44
+#define AMD_MCR4_INT_ENABLE (1 << 3)
+#define AMD_MCR4_SWAPBB (1 << 4)
+#define AMD_MCR4_SWAPBC (1 << 5)
+
+#define AMDR_MUX_1_4 0x45
+
+#define AMDR_MAP_X 0x61
+#define AMDR_MAP_R 0x62
+#define AMDR_MAP_GX 0x63
+#define AMDR_MAP_GR 0x64
+#define AMDR_MAP_GER 0x65
+#define AMDR_MAP_STG 0x66
+#define AMDR_MAP_FTGR 0x67
+#define AMDR_MAP_ATGR 0x68
+#define AMDR_MAP_MMR1 0x69
+#define AMD_MMR1_ALAW 0x01
+#define AMD_MMR1_GX 0x02
+#define AMD_MMR1_GR 0x04
+#define AMD_MMR1_GER 0x08
+#define AMD_MMR1_X 0x10
+#define AMD_MMR1_R 0x20
+#define AMD_MMR1_STG 0x40
+#define AMD_MMR1_LOOP 0x80
+#define AMDR_MAP_MMR2 0x6a
+#define AMD_MMR2_AINB 0x01
+#define AMD_MMR2_LS 0x02
+#define AMD_MMR2_DTMF 0x04
+#define AMD_MMR2_GEN 0x08
+#define AMD_MMR2_RNG 0x10
+#define AMD_MMR2_DIS_HPF 0x20
+#define AMD_MMR2_DIS_AZ 0x40
+#define AMDR_MAP_1_10 0x6b
+
+#define AMDR_DLC_FRAR123 0x81
+#define AMDR_DLC_SRAR123 0x82
+#define AMDR_DLC_TAR 0x83
+#define AMDR_DLC_DRLR 0x84
+#define AMDR_DLC_DTCR 0x85
+#define AMDR_DLC_DMR1 0x86
+#define AMDR_DLC_DMR2 0x87
+#define AMDR_DLC_1_7 0x88
+#define AMDR_DLC_DRCR 0x89
+#define AMDR_DLC_RNGR1 0x8a
+#define AMDR_DLC_RNGR2 0x8b
+#define AMDR_DLC_FRAR4 0x8c
+#define AMDR_DLC_SRAR4 0x8d
+#define AMDR_DLC_DMR3 0x8e
+#define AMDR_DLC_DMR4 0x8f
+#define AMDR_DLC_12_15 0x90
+#define AMDR_DLC_ASR 0x91
diff --git a/chips/isdn_79c30_hdw.c b/chips/isdn_79c30_hdw.c
new file mode 100644
index 00000000..769d1cb1
--- /dev/null
+++ b/chips/isdn_79c30_hdw.c
@@ -0,0 +1,602 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: isdn_79c30_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Driver for the AMD 79c30 ISDN (Integrated Speech and
+ * Data Network) controller chip.
+ */
+
+/*-
+ * Copyright (c) 1991, 1992 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 Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. The name of the Laboratory may not 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 <isdn.h>
+#if NISDN > 0
+
+#include <platforms.h>
+
+#include <mach/std_types.h>
+#include <machine/machspl.h>
+#include <sys/ioctl.h> /* for Sun compat */
+#include <chips/busses.h>
+
+#include <device/device_types.h>
+#include <device/io_req.h>
+#include <device/audio_status.h>
+#include <chips/audio_defs.h>
+
+#include <chips/isdn_79c30.h>
+
+#include <chips/audio_config.h> /* machdep config */
+
+#define private static
+
+/*
+ * Autoconf info
+ */
+private int isdn_probe (vm_offset_t reg, struct bus_ctlr *ui);
+private void isdn_attach ( struct bus_device *ui);
+
+private vm_offset_t isdn_std[NISDN] = { 0 };
+private struct bus_device *isdn_info[NISDN];
+
+struct bus_driver isdn_driver =
+ { isdn_probe, 0, isdn_attach, 0, isdn_std, "isdn", isdn_info, };
+
+
+/*
+ * Externally visible functions and data
+ */
+int isdn_intr();
+
+
+/*
+ * Status bookeeping and globals
+ */
+typedef struct {
+ amd79c30_padded_regs_t *regs;
+ void *audio_status; /* for upcalls */
+ struct mapreg sc_map; /* MAP status */
+ /*
+ * keep track of levels so we don't have to convert back from
+ * MAP gain constants
+ */
+ int sc_rlevel; /* record level */
+ int sc_plevel; /* play level */
+ int sc_mlevel; /* monitor level */
+} isdn_softc_t;
+
+isdn_softc_t isdn_softc_data[NISDN];
+isdn_softc_t *isdn_softc[NISDN];
+
+private int audio_default_level = 150;
+
+
+/*
+ * Forward decls
+ */
+audio_switch_t isdn_ops;
+
+private void isdn_init( isdn_softc_t *sc );
+
+private void isdn_set_mmr2(
+ register amd79c30_padded_regs_t *regs,
+ register int mmr2);
+
+private void isdn_setgains(
+ isdn_softc_t *sc,
+ int pgain,
+ int rgain,
+ int mgain);
+
+/*
+ * Probe chip to see if it is there
+ */
+private isdn_probe(
+ vm_offset_t reg,
+ struct bus_ctlr *ui)
+{
+ isdn_softc_t *sc = &isdn_softc_data[ui->unit];
+
+ isdn_softc[ui->unit] = sc;
+ sc->regs = (amd79c30_padded_regs_t *)reg;
+
+ return 1;
+}
+
+/*
+ * Attach device to chip-indep driver(s)
+ */
+private void
+isdn_attach(
+ struct bus_device *ui)
+{
+ register isdn_softc_t *sc = isdn_softc[ui->unit];
+ register amd79c30_padded_regs_t *regs = sc->regs;
+
+ /* disable interrupts */
+ write_reg(regs->cr, AMDR_INIT);
+ write_reg(regs->dr, AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE);
+
+ /*
+ * Initialize the mux unit. We use MCR3 to route audio (MAP)
+ * through channel Bb. MCR1 and MCR2 are unused.
+ * Setting the INT enable bit in MCR4 will generate an interrupt
+ * on each converted audio sample.
+ */
+ write_reg(regs->cr, AMDR_MUX_1_4);
+ write_reg(regs->dr, 0);
+ write_reg(regs->dr, 0);
+ write_reg(regs->dr, (AMD_MCRCHAN_BB << 4) | AMD_MCRCHAN_BA);
+ write_reg(regs->dr, AMD_MCR4_INT_ENABLE);
+
+ printf(" AMD 79C30A/79C32A");
+
+ audio_attach( sc, &isdn_ops, &sc->audio_status );
+}
+
+/*
+ * Chip re-initialization
+ */
+private void
+isdn_init(
+ isdn_softc_t *sc)
+{
+ register amd79c30_padded_regs_t *regs;
+
+ bzero((char *)&sc->sc_map, sizeof sc->sc_map);
+ /* default to speaker */
+ sc->sc_map.mr_mmr2 = AMD_MMR2_AINB | AMD_MMR2_LS;
+
+ /* enable interrupts and set parameters established above */
+ regs = sc->regs;
+ isdn_set_mmr2 (regs, sc->sc_map.mr_mmr2);
+ isdn_setgains (sc, audio_default_level, audio_default_level, 0);
+ write_reg(regs->cr, AMDR_INIT);
+ write_reg(regs->dr, AMD_INIT_PMS_ACTIVE);
+}
+
+/*
+ * Chip shutdown
+ */
+private void
+isdn_close(
+ isdn_softc_t *sc)
+{
+ register amd79c30_padded_regs_t *regs;
+
+ regs = sc->regs;
+ write_reg(regs->cr, AMDR_INIT);
+ write_reg(regs->dr, AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE);
+}
+
+/*
+ * Audio port selection
+ */
+private void
+isdn_setport(
+ isdn_softc_t *sc,
+ int port)
+{
+ if (port == AUDIO_SPEAKER) {
+ sc->sc_map.mr_mmr2 |= AMD_MMR2_LS;
+ isdn_set_mmr2(sc->regs, sc->sc_map.mr_mmr2);
+ } else if (port == AUDIO_HEADPHONE) {
+ sc->sc_map.mr_mmr2 &=~ AMD_MMR2_LS;
+ isdn_set_mmr2(sc->regs, sc->sc_map.mr_mmr2);
+ }
+}
+
+private int
+isdn_getport(
+ isdn_softc_t *sc)
+{
+ return (sc->sc_map.mr_mmr2 & AMD_MMR2_LS) ?
+ AUDIO_SPEAKER : AUDIO_HEADPHONE;
+}
+
+/*
+ * Volume control
+ */
+private void
+isdn_setgains(
+ isdn_softc_t *sc,
+ int pgain,
+ int rgain,
+ int mgain)
+{
+ private void isdn_set_pgain(), isdn_set_rgain(), isdn_set_mgain();
+
+ if (pgain != ~0)
+ isdn_set_pgain(sc, pgain);
+ if (rgain != ~0)
+ isdn_set_rgain(sc, rgain);
+ if (mgain != ~0)
+ isdn_set_mgain(sc, mgain);
+
+}
+
+private void
+isdn_getgains(
+ isdn_softc_t *sc,
+ int *pgain,
+ int *rgain,
+ int *mgain)
+{
+ *mgain = sc->sc_mlevel;
+ *rgain = sc->sc_rlevel;
+ *pgain = sc->sc_plevel;
+}
+
+
+/*
+ * User control over MAP processor
+ */
+private io_return_t
+isdn_setstate(
+ isdn_softc_t *sc,
+ dev_flavor_t flavor,
+ register struct mapreg *map,
+ natural_t n_ints)
+{
+ register amd79c30_padded_regs_t *regs = sc->regs;
+ register int i, v;
+ spl_t s;
+
+ /* Sun compat */
+ if (flavor == AUDIOSETREG) {
+ register struct audio_ioctl *a = (struct audio_ioctl *)map;
+ s = splaudio();
+ write_reg(regs->cr, (a->control >> 8) & 0xff);
+ for (i = 0; i < (a->control & 0xff); i++) {
+ write_reg(regs->dr, a->data[i]);
+ }
+ splx(s);
+ return D_SUCCESS;
+ }
+
+ if (flavor != AUDIO_SETMAP)
+ return D_INVALID_OPERATION;
+
+ if ((n_ints * sizeof(int)) < sizeof(*map))
+ return D_INVALID_SIZE;
+
+ bcopy(map, &sc->sc_map, sizeof(sc->sc_map));
+ sc->sc_map.mr_mmr2 &= 0x7f;
+
+ s = splaudio();
+ write_reg(regs->cr, AMDR_MAP_1_10);
+ for (i = 0; i < 8; i++) {
+ v = map->mr_x[i];
+ WAMD16(regs, v);
+ }
+ for (i = 0; i < 8; ++i) {
+ v = map->mr_r[i];
+ WAMD16(regs, v);
+ }
+ v = map->mr_gx; WAMD16(regs, v);
+ v = map->mr_gr; WAMD16(regs, v);
+ v = map->mr_ger; WAMD16(regs, v);
+ v = map->mr_stgr; WAMD16(regs, v);
+ v = map->mr_ftgr; WAMD16(regs, v);
+ v = map->mr_atgr; WAMD16(regs, v);
+ write_reg(regs->dr, map->mr_mmr1);
+ write_reg(regs->dr, map->mr_mmr2);
+ splx(s);
+ return D_SUCCESS;
+}
+
+private io_return_t
+isdn_getstate(
+ isdn_softc_t *sc,
+ dev_flavor_t flavor,
+ register struct mapreg *map,
+ natural_t *count)
+{
+ register amd79c30_padded_regs_t *regs = sc->regs;
+ spl_t s;
+ int i;
+
+ /* Sun compat */
+ if (flavor == AUDIOGETREG) {
+ register struct audio_ioctl *a = (struct audio_ioctl *)map;
+ s = splaudio();
+ write_reg(regs->cr, (a->control >> 8) & 0xff);
+ for (i = 0; i < (a->control & 0xff); i++) {
+ read_reg(regs->dr,a->data[i]);
+ }
+ splx(s);
+ *count = sizeof(*a) / sizeof(int);
+ return D_SUCCESS;
+ }
+
+ if ( (*count * sizeof(int)) < sizeof(*map))
+ return D_INVALID_SIZE;
+ bcopy(&sc->sc_map, map, sizeof(sc->sc_map));
+ *count = sizeof(*map) / sizeof(int);
+ return D_SUCCESS;
+}
+
+
+
+/*
+ * Set the mmr1 register and one other 16 bit register in the audio chip.
+ * The other register is indicated by op and val.
+ */
+private void
+isdn_set_mmr1(
+ register amd79c30_padded_regs_t *regs,
+ register int mmr1,
+ register int op,
+ register int val)
+{
+ register int s = splaudio();
+
+ write_reg(regs->cr, AMDR_MAP_MMR1);
+ write_reg(regs->dr, mmr1);
+ write_reg(regs->cr, op);
+ WAMD16(regs, val);
+ splx(s);
+}
+
+/*
+ * Set the mmr2 register.
+ */
+private void
+isdn_set_mmr2(
+ register amd79c30_padded_regs_t *regs,
+ register int mmr2)
+{
+ register int s = splaudio();
+
+ write_reg(regs->cr, AMDR_MAP_MMR2);
+ write_reg(regs->dr, mmr2);
+ splx(s);
+}
+
+/*
+ * gx, gr & stg gains. this table must contain 256 elements with
+ * the 0th being "infinity" (the magic value 9008). The remaining
+ * elements match sun's gain curve (but with higher resolution):
+ * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
+ */
+private const unsigned short gx_coeff[256] = {
+ 0x9008, 0x8b7c, 0x8b51, 0x8b45, 0x8b42, 0x8b3b, 0x8b36, 0x8b33,
+ 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22,
+ 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b,
+ 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb,
+ 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a,
+ 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213,
+ 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231,
+ 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4,
+ 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2,
+ 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa,
+ 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b,
+ 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b,
+ 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd,
+ 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808,
+ 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243,
+ 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224,
+ 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb,
+ 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33,
+ 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32,
+ 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323,
+ 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a,
+ 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23,
+ 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1,
+ 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333,
+ 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227,
+ 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6,
+ 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2,
+ 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba,
+ 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033,
+ 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021,
+ 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012,
+ 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e,
+};
+
+/*
+ * second stage play gain.
+ */
+private const unsigned short ger_coeff[] = {
+ 0x431f, /* 5. dB */
+ 0x331f, /* 5.5 dB */
+ 0x40dd, /* 6. dB */
+ 0x11dd, /* 6.5 dB */
+ 0x440f, /* 7. dB */
+ 0x411f, /* 7.5 dB */
+ 0x311f, /* 8. dB */
+ 0x5520, /* 8.5 dB */
+ 0x10dd, /* 9. dB */
+ 0x4211, /* 9.5 dB */
+ 0x410f, /* 10. dB */
+ 0x111f, /* 10.5 dB */
+ 0x600b, /* 11. dB */
+ 0x00dd, /* 11.5 dB */
+ 0x4210, /* 12. dB */
+ 0x110f, /* 13. dB */
+ 0x7200, /* 14. dB */
+ 0x2110, /* 15. dB */
+ 0x2200, /* 15.9 dB */
+ 0x000b, /* 16.9 dB */
+ 0x000f /* 18. dB */
+#define NGER (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
+};
+
+private void
+isdn_set_rgain(
+ register isdn_softc_t *sc,
+ register int level)
+{
+ level &= 0xff;
+ sc->sc_rlevel = level;
+ sc->sc_map.mr_mmr1 |= AMD_MMR1_GX;
+ sc->sc_map.mr_gx = gx_coeff[level];
+ isdn_set_mmr1(sc->regs, sc->sc_map.mr_mmr1,
+ AMDR_MAP_GX, sc->sc_map.mr_gx);
+}
+
+private void
+isdn_set_pgain(
+ register isdn_softc_t *sc,
+ register int level)
+{
+ register int gi, s;
+ register amd79c30_padded_regs_t *regs;
+
+ level &= 0xff;
+ sc->sc_plevel = level;
+ sc->sc_map.mr_mmr1 |= AMD_MMR1_GER|AMD_MMR1_GR;
+ level *= 256 + NGER;
+ level >>= 8;
+ if (level >= 256) {
+ gi = level - 256;
+ level = 255;
+ } else
+ gi = 0;
+ sc->sc_map.mr_ger = ger_coeff[gi];
+ sc->sc_map.mr_gr = gx_coeff[level];
+
+ regs = sc->regs;
+ s = splaudio();
+ write_reg(regs->cr, AMDR_MAP_MMR1);
+ write_reg(regs->dr, sc->sc_map.mr_mmr1);
+ write_reg(regs->cr, AMDR_MAP_GR);
+ gi = sc->sc_map.mr_gr;
+ WAMD16(regs, gi);
+ write_reg(regs->cr, AMDR_MAP_GER);
+ gi = sc->sc_map.mr_ger;
+ WAMD16(regs, gi);
+ splx(s);
+}
+
+private void
+isdn_set_mgain(
+ register isdn_softc_t *sc,
+ register int level)
+{
+ level &= 0xff;
+ sc->sc_mlevel = level;
+ sc->sc_map.mr_mmr1 |= AMD_MMR1_STG;
+ sc->sc_map.mr_stgr = gx_coeff[level];
+ isdn_set_mmr1(sc->regs, sc->sc_map.mr_mmr1,
+ AMDR_MAP_STG, sc->sc_map.mr_stgr);
+}
+
+/*
+ * Interrupt routine
+ */
+#if old
+isdn_intr (unit, spllevel)
+ spl_t spllevel;
+{
+#ifdef MAXINE
+ xine_enable_interrupt(7, 0, 0);
+#endif
+#ifdef FLAMINGO
+ kn15aa_enable_interrupt(12, 0, 0);
+#endif
+ printf("ISDN interrupt");
+}
+#else
+isdn_intr (unit, spllevel)
+ spl_t spllevel;
+{
+ isdn_softc_t *sc = isdn_softc[unit];
+ amd79c30_padded_regs_t *regs = sc->regs;
+ register int i;
+ unsigned int c;
+
+ read_reg(regs->ir, i); mb(); /* clear interrupt, now */
+#if mips
+ splx(spllevel); /* drop priority */
+#endif
+
+#if 0
+ if (..this is an audio interrupt..)
+#endif
+ {
+ read_reg(regs->bbrb, c);
+ if (audio_hwintr(sc->audio_status, c, &c))
+ write_reg(regs->bbtb, c);
+ }
+}
+#endif
+
+
+
+/*
+ * Standard operations vector
+ */
+audio_switch_t isdn_ops = {
+ isdn_init,
+ isdn_close,
+ isdn_setport,
+ isdn_getport,
+ isdn_setgains,
+ isdn_getgains,
+ isdn_setstate,
+ isdn_getstate
+};
+
+#if 1
+write_an_int(int *where, int what) { *where = what;}
+read_an_int(int *where) { return *where;}
+#endif
+
+#endif
diff --git a/chips/kernel_font.c b/chips/kernel_font.c
new file mode 100644
index 00000000..71c52c48
--- /dev/null
+++ b/chips/kernel_font.c
@@ -0,0 +1,3083 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * THIS FILE WAS GENERATED BY build_font FROM kernel_font.data
+ * IF YOU NEED TO, BE SURE YOU EDIT THE REAL THING!
+ */
+/*
+ * Object:
+ * kfont_7x14 EXPORTED array
+ *
+ * Kernel font for printable ASCII chars
+ *
+ * The smallest index in this array corresponds to a
+ * space. So, we start at 0x20 in the ascii table.
+ * Note that glyphs are mirrored (byteorder, I think)
+ * the commented bitmap shows how they really look like
+ */
+
+unsigned char kfont_7x14[] = {
+/* 0 ' ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 1 '!' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 2 '"' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 3 '#' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01001000 */ 0x12,
+ /* 01001000 */ 0x12,
+ /* 11111100 */ 0x3f,
+ /* 01001000 */ 0x12,
+ /* 01001000 */ 0x12,
+ /* 01001000 */ 0x12,
+ /* 01001000 */ 0x12,
+ /* 11111100 */ 0x3f,
+ /* 01001000 */ 0x12,
+ /* 01001000 */ 0x12,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 4 '$' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 01111110 */ 0x7e,
+ /* 10010000 */ 0x9,
+ /* 10010000 */ 0x9,
+ /* 01111100 */ 0x3e,
+ /* 00010010 */ 0x48,
+ /* 00010010 */ 0x48,
+ /* 11111100 */ 0x3f,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 5 '%' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000010 */ 0x42,
+ /* 10100100 */ 0x25,
+ /* 01000100 */ 0x22,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 01000100 */ 0x22,
+ /* 01001010 */ 0x52,
+ /* 10000100 */ 0x21,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 6 '&' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01110000 */ 0xe,
+ /* 10001000 */ 0x11,
+ /* 10001000 */ 0x11,
+ /* 10001000 */ 0x11,
+ /* 01110000 */ 0xe,
+ /* 10001000 */ 0x11,
+ /* 10001010 */ 0x51,
+ /* 10000100 */ 0x21,
+ /* 10001100 */ 0x31,
+ /* 01110010 */ 0x4e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 7 ''' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00011000 */ 0x18,
+ /* 00011000 */ 0x18,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 8 '(' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 00100000 */ 0x4,
+ /* 00100000 */ 0x4,
+ /* 00100000 */ 0x4,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00001000 */ 0x10,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 9 ')' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00001000 */ 0x10,
+ /* 00001000 */ 0x10,
+ /* 00001000 */ 0x10,
+ /* 00001000 */ 0x10,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a '*' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 10010010 */ 0x49,
+ /* 01010100 */ 0x2a,
+ /* 00111000 */ 0x1c,
+ /* 00111000 */ 0x1c,
+ /* 01010100 */ 0x2a,
+ /* 10010010 */ 0x49,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b '+' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 11111110 */ 0x7f,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* c ',' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00110000 */ 0xc,
+ /* 01000000 */ 0x2,
+ /* 00000000 */ 0,
+/* d '-' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* e '.' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00110000 */ 0xc,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* f '/' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000010 */ 0x40,
+ /* 00000100 */ 0x20,
+ /* 00000100 */ 0x20,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 01000000 */ 0x2,
+ /* 01000000 */ 0x2,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 10 '0' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01000100 */ 0x22,
+ /* 00111000 */ 0x1c,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 11 '1' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00110000 */ 0xc,
+ /* 01010000 */ 0xa,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 12 '2' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000100 */ 0x20,
+ /* 00011000 */ 0x18,
+ /* 00100000 */ 0x4,
+ /* 01000000 */ 0x2,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 13 '3' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00011100 */ 0x38,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 14 '4' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000100 */ 0x20,
+ /* 00001100 */ 0x30,
+ /* 00010100 */ 0x28,
+ /* 00100100 */ 0x24,
+ /* 01000100 */ 0x22,
+ /* 10000100 */ 0x21,
+ /* 11111110 */ 0x7f,
+ /* 00000100 */ 0x20,
+ /* 00000100 */ 0x20,
+ /* 00000100 */ 0x20,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 15 '5' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111100 */ 0x3f,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 16 '6' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111100 */ 0x3f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 17 '7' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 00000010 */ 0x40,
+ /* 00000100 */ 0x20,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 01000000 */ 0x2,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 18 '8' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 19 '9' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111110 */ 0x7e,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 1a ':' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00110000 */ 0xc,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00110000 */ 0xc,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 1b ';' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00110000 */ 0xc,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00110000 */ 0xc,
+ /* 01000000 */ 0x2,
+ /* 00000000 */ 0,
+/* 1c '<' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 01000000 */ 0x2,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00001000 */ 0x10,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 1d '=' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 1e '>' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00001000 */ 0x10,
+ /* 00000100 */ 0x20,
+ /* 00000010 */ 0x40,
+ /* 00000100 */ 0x20,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 1f '?' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000100 */ 0x20,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 20 '@' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111100 */ 0x3c,
+ /* 01000010 */ 0x42,
+ /* 10011010 */ 0x59,
+ /* 10101010 */ 0x55,
+ /* 10101010 */ 0x55,
+ /* 10011100 */ 0x39,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000010 */ 0x42,
+ /* 00111100 */ 0x3c,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 21 'A' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 22 'B' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111100 */ 0x3f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111100 */ 0x3f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111100 */ 0x3f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 23 'C' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 24 'D' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111000 */ 0x1f,
+ /* 10000100 */ 0x21,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000100 */ 0x21,
+ /* 11111000 */ 0x1f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 25 'E' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111000 */ 0x1f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 26 'F' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111000 */ 0x1f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 27 'G' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10011110 */ 0x79,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 28 'H' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 29 'I' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 2a 'J' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 2b 'K' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000100 */ 0x21,
+ /* 10001000 */ 0x11,
+ /* 10010000 */ 0x9,
+ /* 10100000 */ 0x5,
+ /* 11000000 */ 0x3,
+ /* 10100000 */ 0x5,
+ /* 10010000 */ 0x9,
+ /* 10001000 */ 0x11,
+ /* 10000100 */ 0x21,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 2c 'L' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 2d 'M' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11000110 */ 0x63,
+ /* 10101010 */ 0x55,
+ /* 10010010 */ 0x49,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 2e 'N' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11000010 */ 0x43,
+ /* 10100010 */ 0x45,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10001010 */ 0x51,
+ /* 10000110 */ 0x61,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 2f 'O' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 30 'P' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111100 */ 0x3f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111100 */ 0x3f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 31 'Q' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10001010 */ 0x51,
+ /* 01000100 */ 0x22,
+ /* 00111010 */ 0x5c,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 32 'R' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111100 */ 0x3f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111100 */ 0x3f,
+ /* 10100000 */ 0x5,
+ /* 10010000 */ 0x9,
+ /* 10001000 */ 0x11,
+ /* 10000100 */ 0x21,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 33 'S' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 34 'T' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 35 'U' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 36 'V' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01000100 */ 0x22,
+ /* 01000100 */ 0x22,
+ /* 01000100 */ 0x22,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 37 'W' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 01101100 */ 0x36,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 38 'X' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 01000100 */ 0x22,
+ /* 01000100 */ 0x22,
+ /* 00101000 */ 0x14,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 01000100 */ 0x22,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 39 'Y' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01000100 */ 0x22,
+ /* 00101000 */ 0x14,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 3a 'Z' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00000010 */ 0x40,
+ /* 00000100 */ 0x20,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 01000000 */ 0x2,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 3b '[' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00011110 */ 0x78,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00011110 */ 0x78,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 3c '\' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00001000 */ 0x10,
+ /* 00000100 */ 0x20,
+ /* 00000100 */ 0x20,
+ /* 00000010 */ 0x40,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 3d ']' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11110000 */ 0xf,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 11110000 */ 0xf,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 3e '^' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 3f '_' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 40 '`' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01100000 */ 0x6,
+ /* 01100000 */ 0x6,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 41 'a' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111000 */ 0x1e,
+ /* 00000100 */ 0x20,
+ /* 01111100 */ 0x3e,
+ /* 10000100 */ 0x21,
+ /* 10000100 */ 0x21,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 42 'b' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10111100 */ 0x3d,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10111100 */ 0x3d,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 43 'c' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 44 'd' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 01111010 */ 0x5e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 45 'e' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 46 'f' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010100 */ 0x28,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00111100 */ 0x3c,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 47 'g' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111010 */ 0x5e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 01111100 */ 0x3e,
+/* 48 'h' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10111100 */ 0x3d,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 49 'i' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 4a 'j' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01010000 */ 0xa,
+ /* 00100000 */ 0x4,
+/* 4b 'k' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000100 */ 0x21,
+ /* 10001000 */ 0x11,
+ /* 10010000 */ 0x9,
+ /* 10110000 */ 0xd,
+ /* 11001000 */ 0x13,
+ /* 10000100 */ 0x21,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 4c 'l' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 4d 'm' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10101100 */ 0x35,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 4e 'n' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10111100 */ 0x3d,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 4f 'o' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 50 'p' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10111100 */ 0x3d,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10111100 */ 0x3d,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+/* 51 'q' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111010 */ 0x5e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+/* 52 'r' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10111100 */ 0x3d,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 53 's' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111110 */ 0x7e,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 11111100 */ 0x3f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 54 't' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00111000 */ 0x1c,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010100 */ 0x28,
+ /* 00001000 */ 0x10,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 55 'u' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 56 'v' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01000100 */ 0x22,
+ /* 01000100 */ 0x22,
+ /* 00101000 */ 0x14,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 57 'w' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10010010 */ 0x49,
+ /* 10101010 */ 0x55,
+ /* 01000100 */ 0x22,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 58 'x' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000100 */ 0x21,
+ /* 01001000 */ 0x12,
+ /* 00110000 */ 0xc,
+ /* 00110000 */ 0xc,
+ /* 01001000 */ 0x12,
+ /* 10000100 */ 0x21,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 59 'y' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 01111100 */ 0x3e,
+/* 5a 'z' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00000100 */ 0x20,
+ /* 00001000 */ 0x10,
+ /* 00110000 */ 0xc,
+ /* 01000000 */ 0x2,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 5b '{' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00001000 */ 0x10,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 5c '|' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 5d '}' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 5e '~' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01100000 */ 0x6,
+ /* 10010010 */ 0x49,
+ /* 00001100 */ 0x30,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 5f '' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 60 '€' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+/* 61 '' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 62 '‚' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010100 */ 0x28,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00111100 */ 0x3c,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00110000 */ 0xc,
+ /* 01010010 */ 0x4a,
+ /* 00101100 */ 0x34,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 63 'ƒ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 64 '„' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01000100 */ 0x22,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 65 '…' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 66 '†' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000010 */ 0x40,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 67 '‡' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 68 'ˆ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10011010 */ 0x59,
+ /* 10100010 */ 0x45,
+ /* 10100010 */ 0x45,
+ /* 10100010 */ 0x45,
+ /* 10011010 */ 0x59,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 69 '‰' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 00000100 */ 0x20,
+ /* 00111100 */ 0x3c,
+ /* 01000100 */ 0x22,
+ /* 00111010 */ 0x5c,
+ /* 00000000 */ 0,
+ /* 01111110 */ 0x7e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 6a 'Š' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001010 */ 0x50,
+ /* 00010100 */ 0x28,
+ /* 00101000 */ 0x14,
+ /* 01010000 */ 0xa,
+ /* 10100000 */ 0x5,
+ /* 01010000 */ 0xa,
+ /* 00101000 */ 0x14,
+ /* 00010100 */ 0x28,
+ /* 00001010 */ 0x50,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 6b '‹' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 6c 'Œ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 6d '' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 6e 'Ž' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 6f '' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 01001000 */ 0x12,
+ /* 00110000 */ 0xc,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 70 '' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 11111110 */ 0x7f,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 71 '‘' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 01000100 */ 0x22,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 72 '’' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 00000100 */ 0x20,
+ /* 00011000 */ 0x18,
+ /* 00000100 */ 0x20,
+ /* 01000100 */ 0x22,
+ /* 00111000 */ 0x1c,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 73 '“' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 74 '”' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000010 */ 0x42,
+ /* 01000010 */ 0x42,
+ /* 01000010 */ 0x42,
+ /* 01000010 */ 0x42,
+ /* 01100110 */ 0x66,
+ /* 01011010 */ 0x5a,
+ /* 01000000 */ 0x2,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+/* 75 '•' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 01101000 */ 0x16,
+ /* 11101000 */ 0x17,
+ /* 11101000 */ 0x17,
+ /* 11101000 */ 0x17,
+ /* 01101000 */ 0x16,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 76 '–' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00011000 */ 0x18,
+ /* 00011000 */ 0x18,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 77 '—' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 78 '˜' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00110000 */ 0xc,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00111000 */ 0x1c,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 79 '™' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111100 */ 0x3c,
+ /* 01000010 */ 0x42,
+ /* 01000010 */ 0x42,
+ /* 01000010 */ 0x42,
+ /* 00111100 */ 0x3c,
+ /* 00000000 */ 0,
+ /* 01111110 */ 0x7e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 7a 'š' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 10100000 */ 0x5,
+ /* 01010000 */ 0xa,
+ /* 00101000 */ 0x14,
+ /* 00010100 */ 0x28,
+ /* 00001010 */ 0x50,
+ /* 00010100 */ 0x28,
+ /* 00101000 */ 0x14,
+ /* 01010000 */ 0xa,
+ /* 10100000 */ 0x5,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 7b '›' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 11000000 */ 0x3,
+ /* 01000010 */ 0x42,
+ /* 01000100 */ 0x22,
+ /* 11101000 */ 0x17,
+ /* 00010100 */ 0x28,
+ /* 00101100 */ 0x34,
+ /* 01010100 */ 0x2a,
+ /* 10011110 */ 0x79,
+ /* 00000100 */ 0x20,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 7c 'œ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 11000000 */ 0x3,
+ /* 01000010 */ 0x42,
+ /* 01000100 */ 0x22,
+ /* 11101000 */ 0x17,
+ /* 00011100 */ 0x38,
+ /* 00110010 */ 0x4c,
+ /* 01000100 */ 0x22,
+ /* 10001000 */ 0x11,
+ /* 00011110 */ 0x78,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 7d '' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 7e 'ž' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00100000 */ 0x4,
+ /* 01000000 */ 0x2,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 7f 'Ÿ' */
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 80 ' ' */
+ /* 00000000 */ 0,
+ /* 00000100 */ 0x20,
+ /* 00001000 */ 0x10,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 81 '¡' */
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 82 '¢' */
+ /* 00000000 */ 0,
+ /* 00110100 */ 0x2c,
+ /* 01001000 */ 0x12,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 83 '£' */
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 84 '¤' */
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00010000 */ 0x8,
+ /* 00111000 */ 0x1c,
+ /* 01000100 */ 0x22,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 85 '¥' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00111110 */ 0x7c,
+ /* 01010000 */ 0xa,
+ /* 01010000 */ 0xa,
+ /* 10010000 */ 0x9,
+ /* 10011100 */ 0x39,
+ /* 11110000 */ 0xf,
+ /* 10010000 */ 0x9,
+ /* 10011110 */ 0x79,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 86 '¦' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+/* 87 '§' */
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111000 */ 0x1f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 88 '¨' */
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111000 */ 0x1f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 89 '©' */
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111000 */ 0x1f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 8a 'ª' */
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111000 */ 0x1f,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 11111110 */ 0x7f,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 8b '«' */
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 8c '¬' */
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 8d '­' */
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 8e '®' */
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 8f '¯' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 90 '°' */
+ /* 00000000 */ 0,
+ /* 00110100 */ 0x2c,
+ /* 01001000 */ 0x12,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 11000010 */ 0x43,
+ /* 10100010 */ 0x45,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10001010 */ 0x51,
+ /* 10000110 */ 0x61,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 91 '±' */
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 92 '²' */
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 93 '³' */
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 94 '´' */
+ /* 00000000 */ 0,
+ /* 00110100 */ 0x2c,
+ /* 01001000 */ 0x12,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 95 'µ' */
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 96 '¶' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111110 */ 0x7e,
+ /* 10010000 */ 0x9,
+ /* 10010000 */ 0x9,
+ /* 10010000 */ 0x9,
+ /* 10011100 */ 0x39,
+ /* 10010000 */ 0x9,
+ /* 10010000 */ 0x9,
+ /* 01111110 */ 0x7e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 97 '·' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000010 */ 0x40,
+ /* 01111100 */ 0x3e,
+ /* 10000110 */ 0x61,
+ /* 10001010 */ 0x51,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10100010 */ 0x45,
+ /* 11000010 */ 0x43,
+ /* 01111100 */ 0x3e,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 98 '¸' */
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 99 '¹' */
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 9a 'º' */
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 9b '»' */
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 9c '¼' */
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01000100 */ 0x22,
+ /* 00101000 */ 0x14,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 9d '½' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* 9e '¾' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10111100 */ 0x3d,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10111100 */ 0x3d,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+/* 9f '¿' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 01111000 */ 0x1e,
+ /* 00000100 */ 0x20,
+ /* 01111100 */ 0x3e,
+ /* 10000100 */ 0x21,
+ /* 10000100 */ 0x21,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a0 'À' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 01111000 */ 0x1e,
+ /* 00000100 */ 0x20,
+ /* 01111100 */ 0x3e,
+ /* 10000100 */ 0x21,
+ /* 10000100 */ 0x21,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a1 'Á' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111000 */ 0x1e,
+ /* 00000100 */ 0x20,
+ /* 01111100 */ 0x3e,
+ /* 10000100 */ 0x21,
+ /* 10000100 */ 0x21,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a2 'Â' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110100 */ 0x2c,
+ /* 01001000 */ 0x12,
+ /* 00000000 */ 0,
+ /* 01111000 */ 0x1e,
+ /* 00000100 */ 0x20,
+ /* 01111100 */ 0x3e,
+ /* 10000100 */ 0x21,
+ /* 10000100 */ 0x21,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a3 'Ã' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111000 */ 0x1e,
+ /* 00000100 */ 0x20,
+ /* 01111100 */ 0x3e,
+ /* 10000100 */ 0x21,
+ /* 10000100 */ 0x21,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a4 'Ä' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00010000 */ 0x8,
+ /* 01111000 */ 0x1e,
+ /* 00000100 */ 0x20,
+ /* 01111100 */ 0x3e,
+ /* 10000100 */ 0x21,
+ /* 10000100 */ 0x21,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a5 'Å' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01101100 */ 0x36,
+ /* 00010010 */ 0x48,
+ /* 01111110 */ 0x7e,
+ /* 10010000 */ 0x9,
+ /* 10010010 */ 0x49,
+ /* 01101100 */ 0x36,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a6 'Æ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+/* a7 'Ç' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a8 'È' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* a9 'É' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* aa 'Ê' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 11111110 */ 0x7f,
+ /* 10000000 */ 0x1,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* ab 'Ë' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* ac 'Ì' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* ad 'Í' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* ae 'Î' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 00110000 */ 0xc,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* af 'Ï' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b0 'Ð' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110100 */ 0x2c,
+ /* 01001000 */ 0x12,
+ /* 00000000 */ 0,
+ /* 10111100 */ 0x3d,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b1 'Ñ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b2 'Ò' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b3 'Ó' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b4 'Ô' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00110100 */ 0x2c,
+ /* 01001000 */ 0x12,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b5 'Õ' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b6 'Ö' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01101100 */ 0x36,
+ /* 10010010 */ 0x49,
+ /* 10011110 */ 0x79,
+ /* 10010000 */ 0x9,
+ /* 10010010 */ 0x49,
+ /* 01101100 */ 0x36,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b7 '×' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000010 */ 0x40,
+ /* 01111100 */ 0x3e,
+ /* 10001010 */ 0x51,
+ /* 10010010 */ 0x49,
+ /* 10010010 */ 0x49,
+ /* 10100010 */ 0x45,
+ /* 01111100 */ 0x3e,
+ /* 10000000 */ 0x1,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b8 'Ø' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* b9 'Ù' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00001000 */ 0x10,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* ba 'Ú' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* bb 'Û' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111010 */ 0x5e,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+/* bc 'Ü' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00101000 */ 0x14,
+ /* 00101000 */ 0x14,
+ /* 00000000 */ 0,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 10000010 */ 0x41,
+ /* 01111100 */ 0x3e,
+ /* 00000010 */ 0x40,
+ /* 00000010 */ 0x40,
+ /* 01111100 */ 0x3e,
+/* bd 'Ý' */
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 01111100 */ 0x3e,
+ /* 10000010 */ 0x41,
+ /* 10000000 */ 0x1,
+ /* 10000000 */ 0x1,
+ /* 01000000 */ 0x2,
+ /* 00100000 */ 0x4,
+ /* 00010000 */ 0x8,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00010000 */ 0x8,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+ /* 00000000 */ 0,
+};
diff --git a/chips/kernel_font.data b/chips/kernel_font.data
new file mode 100644
index 00000000..200cf847
--- /dev/null
+++ b/chips/kernel_font.data
@@ -0,0 +1,3108 @@
+#
+# Mach Operating System
+# Copyright (c) 1991,1990,1989 Carnegie Mellon University
+# All Rights Reserved.
+#
+# Permission to use, copy, modify and distribute this software and its
+# documentation is hereby granted, provided that both the copyright
+# notice and this permission notice appear in all copies of the
+# software, derivative works or modified versions, and any portions
+# thereof, and that both notices appear in supporting documentation.
+#
+# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+# CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+#
+# Carnegie Mellon requests users of this software to return to
+#
+# Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+# School of Computer Science
+# Carnegie Mellon University
+# Pittsburgh PA 15213-3890
+#
+# any improvements or extensions that they make and grant Carnegie Mellon
+# the rights to redistribute these changes.
+#
+#
+# File : kernel_font.data
+# Content: Bitmaps for a 7x15 ASCII font
+# Authors: Alessandro and Giovanna Forin
+#
+# Copyright (c) 1990 Alessandro and Giovanna Forin
+#
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appears in all
+# copies and that both the copyright notice and this permission notice
+# appear in supporting documentation, and that the name of the authors
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+#
+# THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+# NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# NOTE: comment lines must start with a "#" character, and are
+# only permitted at the beginning of the file.
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+!
+00000000
+00000000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+"
+00000000
+00000000
+00101000
+00101000
+00101000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+#
+00000000
+00000000
+01001000
+01001000
+11111100
+01001000
+01001000
+01001000
+01001000
+11111100
+01001000
+01001000
+00000000
+00000000
+00000000
+$
+00000000
+00000000
+00000000
+00010000
+01111110
+10010000
+10010000
+01111100
+00010010
+00010010
+11111100
+00010000
+00000000
+00000000
+00000000
+%
+00000000
+00000000
+01000010
+10100100
+01000100
+00001000
+00010000
+00010000
+00100000
+01000100
+01001010
+10000100
+00000000
+00000000
+00000000
+&
+00000000
+00000000
+01110000
+10001000
+10001000
+10001000
+01110000
+10001000
+10001010
+10000100
+10001100
+01110010
+00000000
+00000000
+00000000
+'
+00000000
+00000000
+00011000
+00011000
+00100000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+(
+00000000
+00000000
+00001000
+00010000
+00010000
+00100000
+00100000
+00100000
+00100000
+00100000
+00010000
+00010000
+00001000
+00000000
+00000000
+)
+00000000
+00000000
+00100000
+00010000
+00010000
+00001000
+00001000
+00001000
+00001000
+00001000
+00010000
+00010000
+00100000
+00000000
+00000000
+*
+00000000
+00000000
+00000000
+00010000
+10010010
+01010100
+00111000
+00111000
+01010100
+10010010
+00010000
+00000000
+00000000
+00000000
+00000000
++
+00000000
+00000000
+00000000
+00000000
+00010000
+00010000
+00010000
+11111110
+00010000
+00010000
+00010000
+00000000
+00000000
+00000000
+00000000
+,
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00110000
+00110000
+01000000
+00000000
+-
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+11111110
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+.
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00110000
+00110000
+00000000
+00000000
+00000000
+/
+00000000
+00000000
+00000010
+00000100
+00000100
+00001000
+00010000
+00010000
+00100000
+01000000
+01000000
+10000000
+00000000
+00000000
+00000000
+0
+00000000
+00000000
+00111000
+01000100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01000100
+00111000
+00000000
+00000000
+00000000
+1
+00000000
+00000000
+00010000
+00110000
+01010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+2
+00000000
+00000000
+01111100
+10000010
+00000010
+00000010
+00000100
+00011000
+00100000
+01000000
+10000000
+11111110
+00000000
+00000000
+00000000
+3
+00000000
+00000000
+01111100
+10000010
+00000010
+00000010
+00011100
+00000010
+00000010
+00000010
+10000010
+01111100
+00000000
+00000000
+00000000
+4
+00000000
+00000000
+00000100
+00001100
+00010100
+00100100
+01000100
+10000100
+11111110
+00000100
+00000100
+00000100
+00000000
+00000000
+00000000
+5
+00000000
+00000000
+11111110
+10000000
+10000000
+10000000
+11111100
+00000010
+00000010
+00000010
+10000010
+01111100
+00000000
+00000000
+00000000
+6
+00000000
+00000000
+01111100
+10000000
+10000000
+10000000
+11111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+7
+00000000
+00000000
+11111110
+10000010
+00000010
+00000100
+00001000
+00010000
+00100000
+01000000
+10000000
+10000000
+00000000
+00000000
+00000000
+8
+00000000
+00000000
+01111100
+10000010
+10000010
+10000010
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+9
+00000000
+00000000
+01111100
+10000010
+10000010
+10000010
+01111110
+00000010
+00000010
+00000010
+00000010
+01111100
+00000000
+00000000
+00000000
+:
+00000000
+00000000
+00000000
+00000000
+00000000
+00110000
+00110000
+00000000
+00000000
+00000000
+00110000
+00110000
+00000000
+00000000
+00000000
+;
+00000000
+00000000
+00000000
+00000000
+00000000
+00110000
+00110000
+00000000
+00000000
+00000000
+00000000
+00110000
+00110000
+01000000
+00000000
+<
+00000000
+00000000
+00000000
+00001000
+00010000
+00100000
+01000000
+10000000
+01000000
+00100000
+00010000
+00001000
+00000000
+00000000
+00000000
+=
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+11111110
+00000000
+11111110
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+>
+00000000
+00000000
+00000000
+00100000
+00010000
+00001000
+00000100
+00000010
+00000100
+00001000
+00010000
+00100000
+00000000
+00000000
+00000000
+?
+00000000
+00000000
+01111100
+10000010
+00000010
+00000010
+00000100
+00001000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+@
+00000000
+00000000
+00111100
+01000010
+10011010
+10101010
+10101010
+10011100
+10000000
+10000000
+01000010
+00111100
+00000000
+00000000
+00000000
+A
+00000000
+00000000
+00111000
+01000100
+10000010
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+B
+00000000
+00000000
+11111100
+10000010
+10000010
+10000010
+11111100
+10000010
+10000010
+10000010
+10000010
+11111100
+00000000
+00000000
+00000000
+C
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+10000000
+10000000
+10000000
+10000000
+10000010
+01111100
+00000000
+00000000
+00000000
+D
+00000000
+00000000
+11111000
+10000100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000100
+11111000
+00000000
+00000000
+00000000
+E
+00000000
+00000000
+11111110
+10000000
+10000000
+10000000
+11111000
+10000000
+10000000
+10000000
+10000000
+11111110
+00000000
+00000000
+00000000
+F
+00000000
+00000000
+11111110
+10000000
+10000000
+10000000
+11111000
+10000000
+10000000
+10000000
+10000000
+10000000
+00000000
+00000000
+00000000
+G
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+10011110
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+H
+00000000
+00000000
+10000010
+10000010
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+I
+00000000
+00000000
+01111100
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+J
+00000000
+00000000
+00000010
+00000010
+00000010
+00000010
+00000010
+00000010
+00000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+K
+00000000
+00000000
+10000100
+10001000
+10010000
+10100000
+11000000
+10100000
+10010000
+10001000
+10000100
+10000010
+00000000
+00000000
+00000000
+L
+00000000
+00000000
+10000000
+10000000
+10000000
+10000000
+10000000
+10000000
+10000000
+10000000
+10000000
+11111110
+00000000
+00000000
+00000000
+M
+00000000
+00000000
+10000010
+10000010
+11000110
+10101010
+10010010
+10000010
+10000010
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+N
+00000000
+00000000
+10000010
+10000010
+11000010
+10100010
+10010010
+10010010
+10001010
+10000110
+10000010
+10000010
+00000000
+00000000
+00000000
+O
+00000000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+P
+00000000
+00000000
+11111100
+10000010
+10000010
+10000010
+11111100
+10000000
+10000000
+10000000
+10000000
+10000000
+00000000
+00000000
+00000000
+Q
+00000000
+00000000
+00111000
+01000100
+10000010
+10000010
+10000010
+10000010
+10000010
+10001010
+01000100
+00111010
+00000000
+00000000
+00000000
+R
+00000000
+00000000
+11111100
+10000010
+10000010
+10000010
+11111100
+10100000
+10010000
+10001000
+10000100
+10000010
+00000000
+00000000
+00000000
+S
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01111100
+00000010
+00000010
+00000010
+10000010
+01111100
+00000000
+00000000
+00000000
+T
+00000000
+00000000
+11111110
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00000000
+00000000
+00000000
+U
+00000000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+V
+00000000
+00000000
+10000010
+10000010
+10000010
+01000100
+01000100
+01000100
+00101000
+00101000
+00010000
+00010000
+00000000
+00000000
+00000000
+W
+00000000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10010010
+10010010
+10010010
+01101100
+00000000
+00000000
+00000000
+X
+00000000
+00000000
+10000010
+01000100
+01000100
+00101000
+00010000
+00010000
+00101000
+01000100
+01000100
+10000010
+00000000
+00000000
+00000000
+Y
+00000000
+00000000
+10000010
+10000010
+01000100
+00101000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00000000
+00000000
+00000000
+Z
+00000000
+00000000
+11111110
+00000010
+00000100
+00001000
+00010000
+00100000
+01000000
+10000000
+10000000
+11111110
+00000000
+00000000
+00000000
+[
+00000000
+00000000
+00011110
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00011110
+00000000
+00000000
+00000000
+\
+00000000
+00000000
+10000000
+01000000
+01000000
+00100000
+00010000
+00010000
+00001000
+00000100
+00000100
+00000010
+00000000
+00000000
+00000000
+]
+00000000
+00000000
+11110000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+11110000
+00000000
+00000000
+00000000
+^
+00000000
+00000000
+00010000
+00101000
+01000100
+10000010
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+_
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+11111110
+00000000
+00000000
+00000000
+`
+00000000
+00000000
+01100000
+01100000
+00010000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+a
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111000
+00000100
+01111100
+10000100
+10000100
+01111010
+00000000
+00000000
+00000000
+b
+00000000
+00000000
+10000000
+10000000
+10000000
+10000000
+10111100
+10000010
+10000010
+10000010
+10000010
+10111100
+00000000
+00000000
+00000000
+c
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+10000010
+01111100
+00000000
+00000000
+00000000
+d
+00000000
+00000000
+00000010
+00000010
+00000010
+00000010
+01111010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000000
+00000000
+00000000
+e
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111100
+10000010
+10000010
+11111110
+10000000
+01111100
+00000000
+00000000
+00000000
+f
+00000000
+00000000
+00001000
+00010100
+00010000
+00010000
+00111100
+00010000
+00010000
+00010000
+00010000
+00010000
+00000000
+00000000
+00000000
+g
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000010
+00000010
+01111100
+h
+00000000
+00000000
+10000000
+10000000
+10000000
+10000000
+10111100
+10000010
+10000010
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+i
+00000000
+00000000
+00000000
+00010000
+00000000
+00110000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+j
+00000000
+00000000
+00000000
+00010000
+00000000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01010000
+00100000
+k
+00000000
+00000000
+10000000
+10000000
+10000000
+10000100
+10001000
+10010000
+10110000
+11001000
+10000100
+10000010
+00000000
+00000000
+00000000
+l
+00000000
+00000000
+00110000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+m
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10101100
+10010010
+10010010
+10010010
+10010010
+10010010
+00000000
+00000000
+00000000
+n
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10111100
+10000010
+10000010
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+o
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+p
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10111100
+10000010
+10000010
+10000010
+10000010
+10111100
+10000000
+10000000
+10000000
+q
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000010
+00000010
+00000010
+r
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10111100
+10000010
+10000000
+10000000
+10000000
+10000000
+00000000
+00000000
+00000000
+s
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111110
+10000000
+01111100
+00000010
+00000010
+11111100
+00000000
+00000000
+00000000
+t
+00000000
+00000000
+00000000
+00010000
+00010000
+00111000
+00010000
+00010000
+00010000
+00010000
+00010100
+00001000
+00000000
+00000000
+00000000
+u
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000000
+00000000
+00000000
+v
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10000010
+10000010
+01000100
+01000100
+00101000
+00010000
+00000000
+00000000
+00000000
+w
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10000010
+10000010
+10000010
+10010010
+10101010
+01000100
+00000000
+00000000
+00000000
+x
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10000100
+01001000
+00110000
+00110000
+01001000
+10000100
+00000000
+00000000
+00000000
+y
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000010
+00000010
+01111100
+z
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+11111110
+00000100
+00001000
+00110000
+01000000
+11111110
+00000000
+00000000
+00000000
+{
+00000000
+00000000
+00001000
+00010000
+00010000
+00010000
+00010000
+00100000
+00010000
+00010000
+00010000
+00010000
+00001000
+00000000
+00000000
+|
+00000000
+00000000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00000000
+00000000
+00000000
+}
+00000000
+00000000
+00100000
+00010000
+00010000
+00010000
+00010000
+00001000
+00010000
+00010000
+00010000
+00010000
+00100000
+00000000
+00000000
+~
+00000000
+00000000
+00000000
+01100000
+10010010
+00001100
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00010000
+00000000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00010000
+01111100
+10000010
+10000000
+10000000
+10000010
+01111100
+00010000
+00000000
+00000000
+
+00000000
+00000000
+00001000
+00010100
+00010000
+00010000
+00111100
+00010000
+00010000
+00110000
+01010010
+00101100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+10000010
+10000010
+01000100
+01111100
+00010000
+01111100
+00010000
+00010000
+00010000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+01111100
+10000010
+10000010
+01111100
+00000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+10000010
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+10000010
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10011010
+10100010
+10100010
+10100010
+10011010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00111000
+00000100
+00111100
+01000100
+00111010
+00000000
+01111110
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00001010
+00010100
+00101000
+01010000
+10100000
+01010000
+00101000
+00010100
+00001010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00110000
+01001000
+00110000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00010000
+00010000
+11111110
+00010000
+00010000
+00000000
+11111110
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00111000
+01000100
+01000100
+00001000
+00010000
+00100000
+01111100
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00111000
+01000100
+00000100
+00011000
+00000100
+01000100
+00111000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01000010
+01000010
+01000010
+01000010
+01100110
+01011010
+01000000
+10000000
+00000000
+
+00000000
+00000000
+00101000
+01101000
+11101000
+11101000
+11101000
+01101000
+00101000
+00101000
+00101000
+00101000
+00101000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00011000
+00011000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00010000
+00110000
+00010000
+00010000
+00010000
+00010000
+00111000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00111100
+01000010
+01000010
+01000010
+00111100
+00000000
+01111110
+00000000
+00000000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+10100000
+01010000
+00101000
+00010100
+00001010
+00010100
+00101000
+01010000
+10100000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01000000
+11000000
+01000010
+01000100
+11101000
+00010100
+00101100
+01010100
+10011110
+00000100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01000000
+11000000
+01000010
+01000100
+11101000
+00011100
+00110010
+01000100
+10001000
+00011110
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00010000
+00000000
+00010000
+00010000
+00100000
+01000000
+10000000
+10000000
+10000010
+01111100
+00000000
+00000000
+
+00000000
+01000000
+00100000
+00000000
+00111000
+01000100
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+
+00000000
+00000100
+00001000
+00000000
+00111000
+01000100
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+
+00000000
+00010000
+00101000
+00000000
+00111000
+01000100
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+
+00000000
+00110100
+01001000
+00000000
+00111000
+01000100
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+
+00000000
+00101000
+00101000
+00000000
+00111000
+01000100
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+
+00000000
+00010000
+00101000
+00010000
+00111000
+01000100
+10000010
+10000010
+11111110
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00111110
+01010000
+01010000
+10010000
+10011100
+11110000
+10010000
+10011110
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+10000000
+10000000
+10000000
+10000000
+10000010
+01111100
+00001000
+00010000
+00000000
+
+00000000
+01000000
+00100000
+00000000
+11111110
+10000000
+10000000
+11111000
+10000000
+10000000
+10000000
+11111110
+00000000
+00000000
+00000000
+
+00000000
+00001000
+00010000
+00000000
+11111110
+10000000
+10000000
+11111000
+10000000
+10000000
+10000000
+11111110
+00000000
+00000000
+00000000
+
+00000000
+00010000
+00101000
+00000000
+11111110
+10000000
+10000000
+11111000
+10000000
+10000000
+10000000
+11111110
+00000000
+00000000
+00000000
+
+00000000
+00101000
+00101000
+00000000
+11111110
+10000000
+10000000
+11111000
+10000000
+10000000
+10000000
+11111110
+00000000
+00000000
+00000000
+
+00000000
+01000000
+00100000
+00000000
+01111100
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00001000
+00010000
+00000000
+01111100
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00010000
+00101000
+00000000
+01111100
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00101000
+00101000
+00000000
+01111100
+00010000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00110100
+01001000
+00000000
+10000010
+11000010
+10100010
+10010010
+10010010
+10001010
+10000110
+10000010
+00000000
+00000000
+00000000
+
+00000000
+01000000
+00100000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00001000
+00010000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00010000
+00101000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00110100
+01001000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00101000
+00101000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+01111110
+10010000
+10010000
+10010000
+10011100
+10010000
+10010000
+01111110
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000010
+01111100
+10000110
+10001010
+10010010
+10010010
+10100010
+11000010
+01111100
+10000000
+00000000
+00000000
+
+00000000
+01000000
+00100000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00001000
+00010000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00010000
+00101000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00101000
+00101000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00101000
+00101000
+00000000
+10000010
+10000010
+01000100
+00101000
+00010000
+00010000
+00010000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000010
+10000010
+10111100
+10000010
+10000010
+10000010
+10000010
+10111100
+10000000
+10000000
+00000000
+
+00000000
+00000000
+00000000
+01000000
+00100000
+00000000
+01111000
+00000100
+01111100
+10000100
+10000100
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00001000
+00010000
+00000000
+01111000
+00000100
+01111100
+10000100
+10000100
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00010000
+00101000
+00000000
+01111000
+00000100
+01111100
+10000100
+10000100
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00110100
+01001000
+00000000
+01111000
+00000100
+01111100
+10000100
+10000100
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00101000
+00101000
+00000000
+01111000
+00000100
+01111100
+10000100
+10000100
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00010000
+00101000
+00010000
+01111000
+00000100
+01111100
+10000100
+10000100
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01101100
+00010010
+01111110
+10010000
+10010010
+01101100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+10000010
+01111100
+00001000
+00010000
+00000000
+
+00000000
+00000000
+00000000
+01000000
+00100000
+00000000
+01111100
+10000010
+10000010
+11111110
+10000000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00001000
+00010000
+00000000
+01111100
+10000010
+10000010
+11111110
+10000000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00010000
+00101000
+00000000
+01111100
+10000010
+10000010
+11111110
+10000000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00101000
+00101000
+00000000
+01111100
+10000010
+10000010
+11111110
+10000000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00100000
+00010000
+00000000
+00110000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00001000
+00010000
+00000000
+00110000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00010000
+00101000
+00000000
+00110000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00101000
+00101000
+00000000
+00110000
+00010000
+00010000
+00010000
+00010000
+00010000
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00110100
+01001000
+00000000
+10111100
+10000010
+10000010
+10000010
+10000010
+10000010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+01000000
+00100000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00001000
+00010000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00010000
+00101000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00110100
+01001000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00101000
+00101000
+00000000
+01111100
+10000010
+10000010
+10000010
+10000010
+01111100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+01101100
+10010010
+10011110
+10010000
+10010010
+01101100
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00000000
+00000000
+00000010
+01111100
+10001010
+10010010
+10010010
+10100010
+01111100
+10000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+01000000
+00100000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00001000
+00010000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00010000
+00101000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00101000
+00101000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+01111010
+00000000
+00000000
+00000000
+
+00000000
+00000000
+00000000
+00101000
+00101000
+00000000
+10000010
+10000010
+10000010
+10000010
+10000010
+01111100
+00000010
+00000010
+01111100
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
+
+00000000
+00000000
+01111100
+10000010
+10000000
+10000000
+01000000
+00100000
+00010000
+00010000
+00000000
+00010000
+00000000
+00000000
+00000000
diff --git a/chips/lance.c b/chips/lance.c
new file mode 100644
index 00000000..750d4c57
--- /dev/null
+++ b/chips/lance.c
@@ -0,0 +1,1570 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: lance.c
+ * Author: Robert V. Baron & Alessandro Forin
+ * Date: 5/90
+ *
+ * Driver for the DEC LANCE Ethernet Controller.
+ */
+
+/*
+
+ Byte ordering issues.
+
+ The lance sees data naturally as half word (16 bit) quantitites.
+ Bit 2 (BSWP) in control register 3 (CSR3) controls byte swapping.
+ To quote the spec:
+
+ 02 BSWP BYTE SWAP allows the chip to
+ operate in systems that consdier bits (15:08) of data pointers
+ by an even addressa and bits (7:0) to be pointed by an
+ odd address.
+
+ When BSWP=1, the chip will swap the high and low bytes on DMA
+ data transfers between the silo and bus memory. Only data from
+ silo transfers is swapped; the Initialization Block data and
+ the Descriptor Ring entries are NOT swapped. (emphasis theirs)
+
+
+ So on systems with BYTE_MSF=1, the BSWP bit should be set. Note,
+ however, that all shorts in the descriptor ring and initialization
+ block need to be swapped. The BITFIELD macros in lance.h handle this
+ magic.
+
+*/
+
+#include <ln.h>
+#if NLN > 0
+#include <platforms.h>
+
+/*
+ * AMD Am7990 LANCE (Ethernet Interface)
+ */
+#include <sys/ioctl.h>
+#include <vm/vm_kern.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <kern/time_out.h>
+#include <sys/syslog.h>
+#include <ipc/ipc_port.h>
+#include <ipc/ipc_kmsg.h>
+
+#include <device/device_types.h>
+#include <device/errno.h>
+#include <device/io_req.h>
+#include <device/if_hdr.h>
+#include <device/if_ether.h>
+#include <device/net_status.h>
+#include <device/net_io.h>
+
+#ifdef FLAMINGO
+#define se_reg_type unsigned int
+#endif
+
+#include <chips/lance.h>
+#include <chips/busses.h>
+
+#define private static
+#define public
+
+typedef struct se_softc *se_softc_t; /* move above prototypes */
+
+void se_write_reg(); /* forwards */
+void se_read();
+void se_rint();
+void se_tint();
+
+private vm_offset_t se_Hmem_nogap(), se_Hmem_gap16();
+private vm_offset_t se_malloc();
+
+
+/* This config section should go into a separate file */
+
+#ifdef LUNA88K
+# include <luna88k/board.h>
+# define MAPPED 1
+ #undef bcopy
+ extern void bcopy(), bzero();
+
+#define wbflush()
+#define Hmem(lna) (vm_offset_t)((lna) + sc->lnbuf)
+#define Lmem(lna) (vm_offset_t)((lna) + sc->lnoffset)
+
+#define SPACE (TRI_PORT_RAM_SPACE>>1)
+private struct se_switch se_switch[] = {
+ { LANCE_ADDR - TRI_PORT_RAM, /* pointer */
+ SPACE /* host side */,
+ SPACE /* lance side */,
+ - TRI_PORT_RAM,
+ 0, /* romstride */
+ 0, /* ramstride */
+ SPACE,
+ /* desc_copyin */ bcopy,
+ /* desc_copyout */ bcopy,
+ /* data_copyin */ bcopy,
+ /* data_copyout */ bcopy,
+ /* bzero */ bzero,
+ /* mapaddr */ se_Hmem_nogap,
+ /* mapoffs */ se_Hmem_nogap
+ },
+};
+
+#endif
+
+#ifdef DECSTATION
+#include <mips/mips_cpu.h>
+#include <mips/PMAX/pmad_aa.h>
+
+#define MAPPED 1
+
+/*
+ * The LANCE buffer memory as seen from the Pmax cpu is funny.
+ * It is viewed as short words (16bits), spaced at word (32bits)
+ * intervals. The same applies to the registers. From the LANCE
+ * point of view memory is instead contiguous.
+ * The ROM that contains the station address is in the space belonging
+ * to the clock/battery backup memory. This space is again 16 bits
+ * in a 32bit envelope. And the ether address is stored in the "high"
+ * byte of 6 consecutive quantities.
+ *
+ * But Pmaxen and 3maxen (and..) map lance space differently.
+ * This requires dynamic adaptation of the driver, which
+ * is done via the following switches.
+ * For convenience, the switch holds information about
+ * the location of the lance control registers as well.
+ * This could be either absolute (pmax) or relative to
+ * some register base (3max, turbochannel)
+ */
+void copyin_gap16(), copyout_gap16(), bzero_gap16();
+extern void bcopy(), bzero();
+void copyin_gap32(), copyout_gap32();
+
+private struct se_switch se_switch[] = {
+/* pmax */
+ { 0x00000000, 0x01000000, 0x0, 0x05000000, 8, 16, 64*1024,
+ copyin_gap16, copyout_gap16, copyin_gap16, copyout_gap16,
+ bzero_gap16, se_Hmem_gap16, se_Hmem_gap16},
+/* 3max */
+ { PMAD_OFFSET_LANCE, PMAD_OFFSET_RAM, PMAD_OFFSET_RAM, PMAD_OFFSET_ROM,
+ 16, 0, PMAD_RAM_SIZE,
+ bcopy, bcopy, bcopy, bcopy, bzero, se_Hmem_nogap, se_Hmem_nogap},
+/* 3min */
+/* XXX re-use other 64k */
+ { 0/*later*/, 0/*later*/, 0x0, 0/*later*/, 0, 128, 64*1024,
+ copyin_gap16, copyout_gap16, copyin_gap32, copyout_gap32,
+ bzero_gap16, se_Hmem_gap16, se_Hmem_nogap},
+};
+
+/*
+ * "lna" is what se_malloc hands back. They are offsets using
+ * the sizing that the Lance would use. The Lance space is
+ * mapped somewhere in the I/O space, as indicated by the softc.
+ * Hence we have these two macros:
+ */
+/* H & L are not hi and lo but
+ H = HOST == addresses for host to reference board memory
+ L = LOCAL == addresses on board
+ */
+#define Hmem(lna) (vm_offset_t)((se_sw->mapaddr)(lna) + sc->lnbuf)
+#define Lmem(lna) (vm_offset_t)((vm_offset_t)lna + sc->lnoffset)
+#endif /*DECSTATION*/
+
+
+#ifdef VAXSTATION
+#include <vax/ka3100.h>
+
+#define wbflush()
+
+void xzero(x, l) vm_offset_t x; int l; { blkclr(x, l); }
+void xcopy(f, t, l) vm_offset_t f, t; int l; { bcopy(f, t, l); }
+
+private struct se_switch se_switch[] = {
+ /* pvax sees contiguous bits in lower 16Meg of memory */
+ { 0, 0, 0, 0, 0, 0, 64*1024,
+ xcopy, xcopy, xcopy, xcopy, xzero, se_Hmem_nogap, se_Hmem_nogap},
+};
+
+/*
+ * "lna" is what se_malloc hands back. They are offsets using
+ * the sizing that the Lance would use. The Lance space is
+ * mapped somewhere in the I/O space, as indicated by the softc.
+ * Hence we have these two macros:
+ */
+/* H & L are not hi and lo but
+ H = HOST == addresses for host to reference board memory
+ L = LOCAL == addresses on board
+ */
+ /*
+ * This does not deal with > 16 Meg physical memory, where
+ * Hmem != Lmem
+ */
+#define Hmem(lna) (vm_offset_t)((lna) + sc->lnbuf)
+#define Lmem(lna) (vm_offset_t)((lna) + sc->lnoffset)
+
+#endif /*VAXSTATION*/
+
+
+#ifdef FLAMINGO
+#include <alpha/alpha_cpu.h>
+
+/* XXX might be wrong, mostly stolen from kmin */
+extern void copyin_gap16(), copyout_gap16(), bzero_gap16();
+extern void copyin_gap32(), copyout_gap32();
+extern void bcopy(), bzero();
+
+private struct se_switch se_switch[] = {
+/* XXX re-use other 64k */
+ { 0/*later*/, 0/*later*/, 0x0, 0/*later*/, 0, 128, 64*1024,
+ copyin_gap16, copyout_gap16, copyin_gap32, copyout_gap32,
+ bzero_gap16, se_Hmem_gap16, se_Hmem_nogap},
+};
+
+/*
+ * "lna" is what se_malloc hands back. They are offsets using
+ * the sizing that the Lance would use. The Lance space is
+ * mapped somewhere in the I/O space, as indicated by the softc.
+ * Hence we have these two macros:
+ */
+/* H & L are not hi and lo but
+ H = HOST == addresses for host to reference board memory
+ L = LOCAL == addresses on board
+ */
+#define Hmem(lna) (vm_offset_t)((se_sw->mapaddr)(lna) + sc->lnbuf)
+#define Lmem(lna) (vm_offset_t)((vm_offset_t)lna + sc->lnoffset)
+#endif /*FLAMINGO*/
+
+
+/*
+ * Map a lance-space offset into an host-space one
+ */
+private vm_offset_t se_Hmem_nogap( vm_offset_t lna) { return lna;}
+private vm_offset_t se_Hmem_gap16( vm_offset_t lna) { return lna << 1;}
+
+/*
+ * Memory addresses for LANCE are 24 bits wide.
+ */
+#define Addr_lo(y) ((unsigned short)((vm_offset_t)(y) & 0xffff))
+#define Addr_hi(y) ((unsigned short)(((vm_offset_t)(y)>>16) & 0xff))
+
+#define LN_MEMORY_SIZE (se_sw->ramsize)
+
+/* XXX to accomodate heterogeneity this should be made per-drive */
+/* XXX and then some more */
+
+struct se_switch *se_sw = se_switch;
+
+void set_se_switch(n)
+int n;
+{
+ se_sw = &se_switch[n];
+}
+
+#ifndef LUNA88K
+void setse_switch(n, r, b, l, o)
+ vm_offset_t r, b, l, o;
+ int n;
+{
+ se_switch[n].regspace = r;
+ se_switch[n].bufspace = b;
+ se_switch[n].ln_bufspace = l;
+ se_switch[n].romspace = o;
+
+ /* make sure longword aligned */
+ if (se_switch[n].bufspace & 0x7) {
+ se_switch[n].bufspace = (se_switch[n].bufspace+0x7) & ~0x7;
+ }
+
+ set_se_switch(n);
+}
+#endif
+
+/*
+ * Autoconf info
+ */
+
+private vm_offset_t se_std[NLN] = { 0 };
+private struct bus_device *se_info[NLN];
+private int se_probe();
+private void se_attach();
+
+struct bus_driver se_driver =
+ { se_probe, 0, se_attach, 0, se_std, "se", se_info, };
+
+/*
+ * Externally visible functions
+ */
+char *se_unprobed_addr = 0;
+void se_intr(); /* kernel */
+
+int se_open(), se_output(), se_get_status(), /* user */
+ se_set_status(), se_setinput(), se_restart();
+
+/*
+ *
+ * Internal functions & definitions
+ *
+ */
+
+private int se_probe();
+private void se_init();
+private void init_lance_space();
+private void se_desc_set_status();
+private volatile long *se_desc_alloc(); /* must be aligned! */
+void se_start();
+private void copy_from_lance();
+private int copy_to_lance();
+
+int se_verbose = 0; /* debug flag */
+
+#define RLOG 4 /* 2**4 = 16 receive descriptors */
+#define TLOG 4 /* 2**4 = 16 transmit descriptors */
+#define NRCV (1<<RLOG) /* Receive descriptors */
+#define NXMT (1<<TLOG) /* Transmit descriptors */
+
+#define LN_BUFFER_SIZE (0x800-0x80)
+
+/*
+ * Ethernet software status per interface.
+ *
+ * Each interface is referenced by a network interface structure,
+ * is_if, which contains the output queue for the interface, its address, ...
+ */
+int se_loopback_hack = 1;
+
+struct se_softc {
+ struct ifnet is_if; /* generic interface header */
+ unsigned char is_addr[6]; /* ethernet hardware address */
+ unsigned short pad;
+ se_reg_t lnregs; /* Lance registers */
+ vm_offset_t lnbuf; /* Lance memory, Host offset */
+ vm_offset_t lnoffset; /* Lance memory, Lance offset */
+ vm_offset_t lnrom;
+ vm_offset_t lnsbrk; /* Lance memory allocator */
+ vm_offset_t lninit_block; /* Init block address */
+ se_desc_t lnrring[NRCV]; /* Receive ring desc. */
+ volatile long *lnrbuf[NRCV]; /* Receive buffers */
+ se_desc_t lntring[NXMT]; /* Transmit ring desc. */
+ volatile long *lntbuf[NXMT]; /* Transmit buffers */
+
+ int rcv_last; /* Rcv buffer last read */
+
+ io_req_t tpkt[NXMT+1]; /* Xmt pkt queue */
+ int xmt_count; /* Xmt queue size */
+ int xmt_last; /* Xmt queue head (insert) */
+ int xmt_complete; /* Xmt queue tail (remove) */
+
+ int se_flags; /* Flags for SIOCSIFFLAGS */
+ int counters[4]; /* error counters */
+#define bablcnt counters[0]
+#define misscnt counters[1]
+#define merrcnt counters[2]
+#define rstrtcnt counters[3]
+} se_softc_data[NLN];
+
+se_softc_t se_softc[NLN]; /* quick access */
+
+/*
+ * Probe the Lance to see if it's there
+ */
+private int se_open_state = 0;
+
+private int se_probe(
+ vm_offset_t reg,
+ register struct bus_device *ui)
+{
+ register se_softc_t sc;
+ se_reg_t rdp, rap;
+ int unit = ui->unit;
+
+ /*
+ * See if the interface is there by reading the lance CSR. On pmaxen
+ * and 3maxen this is superfluous, but..
+ */
+ rdp = (se_reg_t) (reg + se_sw->regspace);
+#ifdef DECSTATION
+ if (check_memory(rdp, 0))
+ return 0;
+#endif /*DECSTATION*/
+#ifdef MAPPED
+ SE_probe(reg,ui);
+#endif /*MAPPED*/
+ rap = rdp + 2; /* XXX might not be true in the future XXX */
+ /* rdp and rap are "shorts" on consecutive
+ "long" word boundaries */
+
+ /*
+ * Bind this interface to the softc.
+ */
+ sc = &se_softc_data[unit];
+ se_softc[unit] = sc;
+ sc->lnregs = (se_reg_t) (reg + se_sw->regspace);
+ sc->lnbuf = (vm_offset_t) (reg + se_sw->bufspace);
+ sc->lnoffset = (vm_offset_t) (se_sw->ln_bufspace);
+ sc->lnrom = (vm_offset_t) (reg + se_sw->romspace);
+
+ /*
+ * Reset the interface, and make sure we really do it! (the 3max
+ * seems quite stubborn about these registers)
+ */
+ se_write_reg(rap, CSR0_SELECT, CSR0_SELECT, "RAP");
+ se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
+
+ /*
+ * Allocate lance RAM buffer memory
+ */
+ init_lance_space(sc);
+
+ /*
+ * Initialize the chip
+ *
+ * NOTE: From now on we will only touch csr0
+ */
+ if (se_ship_init_block(sc, unit))
+ return 0;
+
+ /*
+ * Tell the world we are alive and well
+ */
+ se_open_state++;
+ return 1;
+}
+
+int se_ship_init_block(
+ register se_softc_t sc,
+ int unit)
+{
+ se_reg_t rdp = sc->lnregs;
+ se_reg_t rap;
+ register int i = 0;
+
+ rap = rdp + 2; /* XXX might not be true in the future XXX */
+
+ /*
+ * Load LANCE control block.
+ */
+
+#ifdef LUNA88K
+ /* turn on byte swap bit in csr3, set bcon bit - as in 2.5 */
+ se_write_reg(rap, CSR3_SELECT, CSR3_SELECT, "RAP");
+ se_write_reg(rdp, LN_CSR3_BSWP|LN_CSR3_BCON,
+ LN_CSR3_BSWP|LN_CSR3_BCON, "csr3");
+#endif
+
+ se_write_reg(rap, CSR1_SELECT, CSR1_SELECT, "RAP");
+ se_write_reg(rdp, Addr_lo(Lmem(sc->lninit_block)),
+ Addr_lo(Lmem(sc->lninit_block)), "csr1");
+
+ se_write_reg(rap, CSR2_SELECT, CSR2_SELECT, "RAP");
+ se_write_reg(rdp, Addr_hi(Lmem(sc->lninit_block)),
+ Addr_hi(Lmem(sc->lninit_block)), "csr2");
+
+ /*
+ * Start the INIT sequence now
+ */
+ se_write_reg(rap, CSR0_SELECT, CSR0_SELECT, "RAP");
+ *rdp = (LN_CSR0_IDON | LN_CSR0_INIT);
+ wbflush();
+
+ /* give it plenty of time to settle */
+ while (i++ < 10000) {
+ delay(100);
+ if ((*rdp & LN_CSR0_IDON) != 0)
+ break;
+ }
+ /* make sure got out okay */
+ if ((*rdp & LN_CSR0_IDON) == 0) {
+ printf("se%d: cannot initialize\n", unit);
+ if (*rdp & LN_CSR0_ERR)
+ printf("se%d: initialization error, csr = %04x\n",
+ unit, (*rdp & 0xffff));
+ return 1;
+ }
+ /*
+ * Do not enable interrupts just yet.
+ */
+ /* se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0"); */
+
+ return 0;
+}
+
+void
+se_write_reg(
+ register se_reg_t regptr,
+ register int val,
+ register int result,
+ char *regname)
+{
+ register int i = 0;
+
+ while ((unsigned short)(*regptr) != (unsigned short)result) {
+ *regptr = (se_reg_type)val;
+ wbflush();
+ if (++i > 10000) {
+ printf("se: %s did not settle (to x%x): x%x\n",
+ regname, result, (unsigned short)(*regptr));
+ return;
+ }
+ delay(100);
+ }
+}
+
+unsigned short
+se_read_reg(
+ register se_reg_t regptr)
+{
+ return (unsigned short) (*regptr);
+}
+
+private void
+init_lance_space(
+ register se_softc_t sc)
+{
+ register int lptr; /* Generic lance pointer */
+ se_desc_t ringaddr;
+ long *rom_eaddress = (long *) sc->lnrom;
+ int i;
+ struct se_init_block init_block;
+
+ /*
+ * Allocate local RAM buffer memory for the init block,
+ * fill in our local copy then copyout.
+ */
+
+ sc->lninit_block = se_malloc(sc, sizeof (struct se_init_block));
+
+ /*
+ * Set values on stack, then copyout en-masse
+ */
+ bzero(&init_block, sizeof(init_block));
+ init_block.mode = 0;
+
+ /* byte swapping between host and lance */
+
+ init_block.phys_addr_low = ((rom_eaddress[0]>>se_sw->romstride)&0xff) |
+ (((rom_eaddress[1]>>se_sw->romstride)&0xff) << 8);
+ init_block.phys_addr_med = ((rom_eaddress[2]>>se_sw->romstride)&0xff) |
+ (((rom_eaddress[3]>>se_sw->romstride)&0xff) << 8);
+ init_block.phys_addr_high = ((rom_eaddress[4]>>se_sw->romstride)&0xff) |
+ (((rom_eaddress[5]>>se_sw->romstride)&0xff) << 8);
+
+ /*
+ * Allocate both descriptor rings at once.
+ * Note that the quadword alignment requirement is
+ * inherent in the way we perform allocation,
+ * but it does depend on the size of the init block.
+ */
+ lptr = se_malloc(sc, sizeof (struct se_desc) * (NXMT + NRCV));
+
+ /*
+ * Initialize the buffer descriptors
+ */
+ init_block.recv_ring_pointer_lo = Addr_lo(Lmem(lptr));
+ init_block.recv_ring_pointer_hi = Addr_hi(Lmem(lptr));
+ init_block.recv_ring_len = RLOG;
+
+ for ( i = 0; i < NRCV ; i++, lptr += sizeof(struct se_desc)) {
+ ringaddr = (se_desc_t)Hmem(lptr);
+ sc->lnrring[i] = ringaddr;
+ sc->lnrbuf[i] = se_desc_alloc (sc, ringaddr);
+ }
+
+ init_block.xmit_ring_pointer_lo = Addr_lo(Lmem(lptr));
+ init_block.xmit_ring_pointer_hi = Addr_hi(Lmem(lptr));
+ init_block.xmit_ring_len = TLOG;
+
+ for ( i = 0 ; i < NXMT ; i++, lptr += sizeof(struct se_desc)) {
+ ringaddr = (se_desc_t)Hmem(lptr);
+ sc->lntring[i] = ringaddr;
+ sc->lntbuf[i] = se_desc_alloc (sc, ringaddr);
+ }
+
+ /*
+ * No logical address filtering
+ */
+ init_block.logical_addr_filter0 = 0;
+ init_block.logical_addr_filter1 = 0;
+ init_block.logical_addr_filter2 = 0;
+ init_block.logical_addr_filter3 = 0;
+
+ /*
+ * Move init block into lance space
+ */
+ (se_sw->desc_copyout)((vm_offset_t)&init_block, Hmem(sc->lninit_block), sizeof(init_block));
+ wbflush();
+}
+
+/*
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
+ */
+private void
+se_attach(
+ register struct bus_device *ui)
+{
+ unsigned char *enaddr;
+ struct ifnet *ifp;
+ long *rom_eaddress;
+ int unit = ui->unit;
+ se_softc_t sc = se_softc[unit];
+
+ rom_eaddress = (long *) sc->lnrom;
+
+ /*
+ * Read the address from the prom and save it.
+ */
+ enaddr = sc->is_addr;
+ enaddr[0] = (unsigned char) ((rom_eaddress[0] >> se_sw->romstride) & 0xff);
+ enaddr[1] = (unsigned char) ((rom_eaddress[1] >> se_sw->romstride) & 0xff);
+ enaddr[2] = (unsigned char) ((rom_eaddress[2] >> se_sw->romstride) & 0xff);
+ enaddr[3] = (unsigned char) ((rom_eaddress[3] >> se_sw->romstride) & 0xff);
+ enaddr[4] = (unsigned char) ((rom_eaddress[4] >> se_sw->romstride) & 0xff);
+ enaddr[5] = (unsigned char) ((rom_eaddress[5] >> se_sw->romstride) & 0xff);
+
+ printf(": %x-%x-%x-%x-%x-%x",
+ (rom_eaddress[0] >> se_sw->romstride) & 0xff,
+ (rom_eaddress[1] >> se_sw->romstride) & 0xff,
+ (rom_eaddress[2] >> se_sw->romstride) & 0xff,
+ (rom_eaddress[3] >> se_sw->romstride) & 0xff,
+ (rom_eaddress[4] >> se_sw->romstride) & 0xff,
+ (rom_eaddress[5] >> se_sw->romstride) & 0xff);
+
+ /*
+ * Initialize the standard interface descriptor
+ */
+ ifp = &sc->is_if;
+ ifp->if_unit = unit;
+ ifp->if_header_size = sizeof(struct ether_header);
+ ifp->if_header_format = HDR_ETHERNET;
+ ifp->if_address_size = 6;
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_flags |= IFF_BROADCAST;
+
+ ifp->if_address = (char *) enaddr;
+
+ if_init_queues(ifp);
+#ifdef MAPPED
+ SE_attach(ui);
+#endif /*MAPPED*/
+
+}
+
+/*
+ * Use a different hardware address for interface
+ */
+void
+se_setaddr(
+ unsigned char eaddr[6],
+ int unit)
+{
+ register se_softc_t sc = se_softc[unit];
+ struct se_init_block init_block;
+
+ /*
+ * Modify initialization block accordingly
+ */
+ (se_sw->desc_copyin) (Hmem(sc->lninit_block), (vm_offset_t)&init_block, sizeof(init_block));
+ bcopy(eaddr, &init_block.phys_addr_low, sizeof(*eaddr));
+ (se_sw->desc_copyout)((vm_offset_t)&init_block, Hmem(sc->lninit_block), sizeof(init_block));
+ /*
+ * Make a note of it
+ */
+ bcopy(eaddr, sc->is_addr, sizeof(*eaddr));
+
+ /*
+ * Restart the interface
+ */
+ se_restart(&sc->is_if);
+ se_init(unit);
+}
+
+/*
+ * Restart interface
+ *
+ * We use this internally on those errors that hang the chip,
+ * not sure yet what use the MI code will make of it.
+ *
+ * After stopping the chip and effectively turning off the interface
+ * we release all pending buffers and cause the chip to init
+ * itself. We do not enable interrupts here.
+ */
+int
+se_restart( register struct ifnet *ifp )
+{
+ register se_softc_t sc = se_softc[ifp->if_unit];
+ se_reg_t rdp;
+ register int i;
+
+ rdp = sc->lnregs;
+
+ /*
+ * stop the chip
+ */
+ se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
+
+ /*
+ * stop network activity
+ */
+ if (ifp->if_flags & IFF_RUNNING) {
+ ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
+ sc->se_flags &= ~(IFF_UP | IFF_RUNNING);
+ }
+ sc->rstrtcnt++;
+
+ if (se_verbose)
+ printf("se%d: %d restarts\n", ifp->if_unit, sc->rstrtcnt);
+
+ /*
+ * free up any buffers currently in use
+ */
+ for (i = 0; i < NXMT; i++)
+ if (sc->tpkt[i]) {
+ iodone(sc->tpkt[i]);
+ sc->tpkt[i] = (io_req_t) 0;
+ }
+ /*
+ * INIT the chip again, no need to reload init block address.
+ */
+ se_ship_init_block(sc, ifp->if_unit);
+
+ return (0);
+}
+
+/*
+ * Initialize the interface.
+ */
+private void
+se_init( int unit )
+{
+ register se_softc_t sc = se_softc[unit];
+ register se_desc_t *rp;
+ register struct ifnet *ifp = &sc->is_if;
+ se_reg_t rdp;
+ short mode;
+ spl_t s;
+ int i;
+
+ if (ifp->if_flags & IFF_RUNNING)
+ return;
+
+ rdp = sc->lnregs;
+
+ /*
+ * Init the buffer descriptors and indexes for each of the rings.
+ */
+ for (i = 0, rp = sc->lnrring; i < NRCV; i++, rp++)
+ se_desc_set_status(*rp, LN_RSTATE_OWN);
+
+ for (i = 0, rp = sc->lntring; i < NXMT; i++, rp++)
+ se_desc_set_status(*rp, 0);
+
+ sc->xmt_count = sc->xmt_complete = sc->xmt_last = sc->rcv_last = 0;
+
+ /*
+ * Deal with loopback mode operation
+ */
+ s = splimp();
+
+ (se_sw->desc_copyin) (Hmem(sc->lninit_block), (vm_offset_t)&mode, sizeof(mode));
+
+ if (ifp->if_flags & IFF_LOOPBACK
+ && ((mode & LN_MODE_LOOP) == 0)) {
+ /* if not already in loopback mode, do external loopback */
+ mode &= ~LN_MODE_INTL;
+ mode |= LN_MODE_LOOP;
+ (se_sw->desc_copyout) ((vm_offset_t)&mode, Hmem(sc->lninit_block), sizeof(mode));
+ se_restart(ifp);
+ se_init(ifp->if_unit);
+ splx(s);
+ return;
+ }
+
+ ifp->if_flags |= (IFF_UP | IFF_RUNNING);
+ sc->se_flags |= (IFF_UP | IFF_RUNNING);
+
+ /*
+ * Start the Lance and enable interrupts
+ */
+ *rdp = (LN_CSR0_STRT | LN_CSR0_INEA);
+ wbflush();
+
+ /*
+ * See if anything is already queued
+ */
+ se_start(unit);
+ splx(s);
+}
+
+
+/*
+ * Shut off the lance
+ */
+void
+se_stop(int unit)
+{
+ se_reg_t rdp = se_softc[unit]->lnregs;
+
+ se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
+}
+
+
+/*
+ * Open the device, declaring the interface up
+ * and enabling lance interrupts.
+ */
+/*ARGSUSED*/
+int
+se_open(
+ int unit,
+ int flag)
+{
+ register se_softc_t sc = se_softc[unit];
+
+ if (unit >= NLN)
+ return EINVAL;
+ if (!se_open_state)
+ return ENXIO;
+
+ sc->is_if.if_flags |= IFF_UP;
+ se_open_state++;
+ se_init(unit);
+ return (0);
+}
+
+#ifdef MAPPED
+int se_use_mapped_interface[NLN];
+#endif /*MAPPED*/
+
+void
+se_normal(int unit)
+{
+#ifdef MAPPED
+ se_use_mapped_interface[unit] = 0;
+#endif /*MAPPED*/
+ if (se_softc[unit]) {
+ se_restart((struct ifnet *)se_softc[unit]);
+ se_init(unit);
+ }
+}
+
+/*
+ * Ethernet interface interrupt routine
+ */
+void
+se_intr(
+ int unit,
+ spl_t spllevel)
+{
+ register se_softc_t sc = se_softc[unit];
+ se_reg_t rdp;
+ register struct ifnet *ifp = &sc->is_if;
+ register unsigned short csr;
+
+#ifdef MAPPED
+ if (se_use_mapped_interface[unit])
+ {
+ SE_intr(unit,spllevel);
+ return;
+ }
+#endif /*MAPPED*/
+
+ if (se_open_state < 2) { /* Stray, or not open for business */
+ rdp = (sc ? sc->lnregs : (se_reg_t)se_unprobed_addr);
+ *rdp |= LN_CSR0_STOP;
+ wbflush();
+ return;
+ }
+ rdp = sc->lnregs;
+
+ /*
+ * Read the CSR and process any error condition.
+ * Later on, restart the lance by writing back
+ * the CSR (for set-to-clear bits).
+ */
+ csr = *rdp; /* pick up the csr */
+
+ /* drop spurious interrupts */
+ if ((csr & LN_CSR0_INTR) == 0)
+ return;
+
+#ifdef DECSTATION
+ splx(spllevel); /* drop priority now */
+#endif /*DECSTATION*/
+again:
+ /*
+ * Check for errors first
+ */
+ if ( csr & LN_CSR0_ERR ) {
+ if (csr & LN_CSR0_MISS) {
+ /*
+ * Stop the chip to prevent a corrupt packet from
+ * being transmitted. There is a known problem with
+ * missed packet errors causing corrupted data to
+ * be transmitted to the same host as was just
+ * transmitted, with a valid crc appended to the
+ * packet. The only solution is to stop the chip,
+ * which will clear the Lance silo, thus preventing
+ * the corrupt data from being sent.
+ */
+ se_write_reg(rdp, LN_CSR0_STOP, LN_CSR0_STOP, "csr0");
+
+ sc->misscnt++;
+ if (se_verbose) {
+ int me = 0, lance = 0, index;
+ struct se_desc r;
+ for (index = 0; index < NRCV; index++) {
+ (se_sw->desc_copyin)(
+ (vm_offset_t)sc->lnrring[index],
+ (vm_offset_t)&r,
+ sizeof(r));
+ if (r.status & LN_RSTATE_OWN)
+ lance++;
+ else
+ me++;
+ }
+ printf("se%d: missed packet (%d) csr = %x, Lance %x, me %x\n",
+ unit, sc->misscnt, csr, lance, me);
+ }
+ se_restart(ifp);
+ se_init(unit);
+ return;
+ }
+ if (csr & LN_CSR0_BABL) {
+ sc->bablcnt++;
+ if (se_verbose)
+ printf("se%d: xmt timeout (%d)\n",
+ unit, sc->bablcnt);
+ }
+ if (csr & LN_CSR0_MERR) {
+ sc->merrcnt++;
+ printf("se%d: memory error (%d)\n",
+ unit, sc->merrcnt);
+
+ if (((csr & LN_CSR0_RXON) == 0)
+ || ((csr & LN_CSR0_TXON) == 0)) {
+ se_restart(ifp);
+ se_init(unit);
+ return;
+ }
+ }
+ }
+
+ *rdp = LN_CSR0_INEA | (csr & LN_CSR0_WTC);
+ wbflush();
+
+ if ( csr & LN_CSR0_RINT )
+ se_rint( unit );
+
+ if ( csr & LN_CSR0_TINT )
+ se_tint( unit );
+
+ if ((csr = *rdp) & (LN_CSR0_RINT | LN_CSR0_TINT))
+ goto again;
+}
+
+/*
+ * Handle a transmitter complete interrupt.
+ */
+void
+se_tint(int unit)
+{
+ register se_softc_t sc = se_softc[unit];
+ register index;
+ register status;
+ io_req_t request;
+ struct se_desc r;
+
+ /*
+ * Free up descriptors for all packets in queue for which
+ * transmission is complete. Start from queue tail, stop at first
+ * descriptor we do not OWN, or which is in an inconsistent state
+ * (lance still working).
+ */
+
+ while ((sc->xmt_complete != sc->xmt_last) && (sc->xmt_count > 0)) {
+
+ index = sc->xmt_complete;
+ (se_sw->desc_copyin) ((vm_offset_t)sc->lntring[index],
+ (vm_offset_t)&r, sizeof(r));
+ status = r.status;
+
+ /*
+ * Does lance still own it ?
+ */
+ if (status & LN_TSTATE_OWN)
+ break;
+
+ /*
+ * Packet sent allright, release queue slot.
+ */
+ request = sc->tpkt[index];
+ sc->tpkt[index] = (io_req_t) 0;
+ sc->xmt_complete = ++index & (NXMT - 1);
+ --sc->xmt_count;
+
+ sc->is_if.if_opackets++;
+ if (status & (LN_TSTATE_DEF|LN_TSTATE_ONE|LN_TSTATE_MORE))
+ sc->is_if.if_collisions++;
+
+ /*
+ * Check for transmission errors.
+ */
+ if (!se_loopback_hack && status & LN_TSTATE_ERR) {
+ sc->is_if.if_oerrors++;
+ if (se_verbose)
+ printf("se%d: xmt error (x%x)\n", unit, r.status2);
+
+ if (r.status2 & (LN_TSTATE2_RTRY|LN_TSTATE2_LCOL))
+ sc->is_if.if_collisions++;
+
+ /*
+ * Restart chip on errors that disable the
+ * transmitter.
+ */
+ iodone(request);
+ if (r.status2 & LN_TSTATE2_DISABLE) {
+ register struct ifnet *ifp = &sc->is_if;
+ se_restart(ifp);
+ se_init(ifp->if_unit);
+ return;
+ }
+ } else if (request) {
+ /*
+ * If this was a broadcast packet loop it back.
+ * Signal successful transmission of the packet.
+ */
+ register struct ether_header *eh;
+ register int i;
+
+ eh = (struct ether_header *) request->io_data;
+ /* ether broadcast address is in the spec */
+ for (i = 0; (i < 6) && (eh->ether_dhost[i] == 0xff); i++)
+ ; /* nop */
+ /* sending to ourselves makes sense sometimes */
+ if (i != 6 && se_loopback_hack)
+ for (i = 0;
+ (i < 6) && (eh->ether_dhost[i] == sc->is_addr[i]);
+ i++)
+ ; /* nop */
+ if (i == 6)
+ se_read(sc, 0, request->io_count, request);
+ iodone(request);
+ }
+ }
+ /*
+ * Dequeue next transmit request, if any.
+ */
+ if (sc->xmt_count <= 0)
+ se_start(unit);
+}
+
+/*
+ * Handle a receiver complete interrupt.
+ */
+void
+se_rint(int unit)
+{
+ register se_softc_t sc = se_softc[unit];
+ register index, first, len;
+ unsigned char status, status1;
+ int ring_cnt;
+ struct se_desc r;
+
+ /*
+ * Starting from where we left off, look around the receive ring and
+ * pass on all complete packets.
+ */
+
+ for (;; sc->rcv_last = ++index & (NRCV - 1)) {
+
+ /*
+ * Read in current descriptor
+ */
+read_descriptor:
+ (se_sw->desc_copyin) ((vm_offset_t)sc->lnrring[sc->rcv_last],
+ (vm_offset_t)&r, sizeof(r));
+ status = r.status;
+ if (status & LN_RSTATE_OWN)
+ break;
+ first = index = sc->rcv_last;
+
+ /*
+ * If not the start of a packet, error
+ */
+ if (!(status & LN_RSTATE_STP)) {
+ if (se_verbose)
+ printf("se%d: Rring #%d, status=%x !STP\n",
+ unit, index, status);
+ break;
+ }
+ /*
+ * See if packet is chained (should not) by looking at
+ * the last descriptor (OWN clear and ENP set).
+ * Remember the status info in this last descriptor.
+ */
+ ring_cnt = 1, status1 = status;
+ while (((status1 & (LN_RSTATE_ERR | LN_RSTATE_OWN | LN_RSTATE_ENP)) == 0) &&
+ (ring_cnt++ <= NRCV)) {
+ struct se_desc r1;
+ index = (index + 1) & (NRCV - 1);
+ (se_sw->desc_copyin) ((vm_offset_t)sc->lnrring[index],
+ (vm_offset_t)&r1, sizeof(r1));
+ status1 = r1.status;
+ }
+
+ /*
+ * Chained packet (--> illegally sized!); re-init the
+ * descriptors involved and ignore this bogus packet. I
+ * donno how, but it really happens that we get these
+ * monsters.
+ */
+ if (ring_cnt > 1) {
+ /*
+ * Return all descriptors to lance
+ */
+ se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN);
+ while (first != index) {
+ first = (first + 1) & (NRCV - 1);
+ se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN);
+ }
+ if ((status1 & LN_RSTATE_ERR) && se_verbose)
+ printf("se%d: rcv error %x (chained)\n", unit, status1);
+ continue;
+ }
+
+ /*
+ * Good packets must be owned by us and have the end of
+ * packet flag. And nothing else.
+ */
+ if ((status & ~LN_RSTATE_STP) == LN_RSTATE_ENP) {
+ sc->is_if.if_ipackets++;
+
+ if ((len = r.message_size) == 0)
+ /* race seen on pmaxen: the lance
+ * has not updated the size yet ??
+ */
+ goto read_descriptor;
+ /*
+ * Drop trailing CRC bytes from len and ship packet
+ * up
+ */
+ se_read(sc, (volatile char*)sc->lnrbuf[first], len-4,0);
+
+ /*
+ * Return descriptor to lance, and move on to next
+ * packet
+ */
+ r.status = LN_RSTATE_OWN;
+ (se_sw->desc_copyout)((vm_offset_t)&r,
+ (vm_offset_t)sc->lnrring[first],
+ sizeof(r));
+ continue;
+ }
+ /*
+ * Not a good packet, see what is wrong
+ */
+ if (status & LN_RSTATE_ERR) {
+ sc->is_if.if_ierrors++;
+
+ if (se_verbose)
+ printf("se%d: rcv error (x%x)\n", unit, status);
+
+ /*
+ * Return descriptor to lance
+ */
+ se_desc_set_status(sc->lnrring[first], LN_RSTATE_OWN);
+ } else {
+ /*
+ * Race condition viz lance, Wait for the next
+ * interrupt.
+ */
+ return;
+ }
+ }
+}
+
+/*
+ * Output routine.
+ * Call common function for wiring memory,
+ * come back later (to se_start) to get
+ * things going.
+ */
+io_return_t
+se_output(
+ int dev,
+ io_req_t ior)
+{
+ return net_write(&se_softc[dev]->is_if, (int(*)())se_start, ior);
+}
+
+/*
+ * Start output on interface.
+ *
+ */
+void
+se_start(int unit)
+{
+ register se_softc_t sc = se_softc[unit];
+ io_req_t request;
+ struct se_desc r;
+ int tlen;
+ spl_t s;
+ register int index;
+
+ s = splimp();
+
+ for (index = sc->xmt_last;
+ sc->xmt_count < (NXMT - 1);
+ sc->xmt_last = index = (index + 1) & (NXMT - 1)) {
+ /*
+ * Dequeue the next transmit request, if any.
+ */
+ IF_DEQUEUE(&sc->is_if.if_snd, request);
+ if (request == 0) {
+ /*
+ * Tell the lance to send the packet now
+ * instead of waiting until the next 1.6 ms
+ * poll interval expires.
+ */
+ *sc->lnregs = LN_CSR0_TDMD | LN_CSR0_INEA;
+ splx(s);
+ return; /* Nothing on the queue */
+ }
+
+ /*
+ * Keep request around until transmission complete
+ */
+ sc->tpkt[index] = request;
+ tlen = copy_to_lance(request, sc->lntbuf[index]);
+
+ /*
+ * Give away buffer. Must copyin/out, set len,
+ * and set the OWN flag. We do not do chaining.
+ */
+ (se_sw->desc_copyin)((vm_offset_t)sc->lntring[index],
+ (vm_offset_t)&r, sizeof(r));
+ r.buffer_size = -(tlen) | 0xf000;
+ r.status = (LN_TSTATE_OWN | LN_TSTATE_STP | LN_TSTATE_ENP);
+ (se_sw->desc_copyout)((vm_offset_t)&r,
+ (vm_offset_t)sc->lntring[index],
+ sizeof(r));
+ wbflush();
+
+ sc->xmt_count++;
+ }
+ /*
+ * Since we actually have queued new packets, tell
+ * the chip to rescan the descriptors _now_.
+ * It is quite unlikely that the ring be filled,
+ * but if it is .. the more reason to do it!
+ */
+ *sc->lnregs = LN_CSR0_TDMD | LN_CSR0_INEA;
+ splx(s);
+}
+
+
+/*
+ * Pull a packet off the interface and
+ * hand it up to the higher levels.
+ *
+ * Simulate broadcast packets in software.
+ */
+void
+se_read(
+ register se_softc_t sc,
+ volatile char *lnrbuf,
+ int len,
+ io_req_t loop_back)
+{
+ register struct ifnet *ifp = &sc->is_if;
+ register ipc_kmsg_t new_kmsg;
+ char *hdr, *pkt;
+
+ if (len <= sizeof(struct ether_header))
+ return; /* sanity */
+
+ /*
+ * Get a new kmsg to put data into.
+ */
+ new_kmsg = net_kmsg_get();
+ if (new_kmsg == IKM_NULL) {
+ /*
+ * No room, drop the packet
+ */
+ ifp->if_rcvdrops++;
+ return;
+ }
+
+ hdr = net_kmsg(new_kmsg)->header;
+ pkt = net_kmsg(new_kmsg)->packet;
+
+#define OFF0 (sizeof(struct ether_header) - sizeof(struct packet_header))
+#define OFF1 (OFF0 & ~3)
+ if (loop_back) {
+ bcopy(loop_back->io_data, hdr, sizeof(struct ether_header));
+ bcopy(loop_back->io_data + OFF0,
+ pkt, len - OFF0);
+ } else
+ copy_from_lance(lnrbuf, len, (struct ether_header*)hdr,
+ (struct packet_header*)pkt);
+
+ /*
+ * Set up the 'fake' header with length. Type has been left
+ * in the correct place.
+ */
+ len = len - OFF0;
+ ((struct packet_header *)pkt)->length = len;
+
+ /*
+ * Hand the packet to the network module.
+ */
+ net_packet(ifp, new_kmsg, len, ethernet_priority(new_kmsg));
+}
+
+
+/*
+ * Get a packet out of Lance memory and into main memory.
+ */
+private void
+copy_from_lance(
+ register volatile unsigned char *rbuf,
+ register unsigned int nbytes,
+ struct ether_header *hdr,
+ struct packet_header *pkt)
+{
+ /*
+ * Read in ethernet header
+ */
+ (se_sw->data_copyin) ((vm_offset_t)rbuf, (vm_offset_t)hdr, sizeof(struct ether_header));
+
+ nbytes -= sizeof(struct ether_header);
+ rbuf += (se_sw->mapoffs) (sizeof(struct ether_header));
+
+ pkt->type = (unsigned short) hdr->ether_type;
+
+ (se_sw->data_copyin) ((vm_offset_t)rbuf, (vm_offset_t)(pkt + 1), nbytes);
+}
+
+
+/*
+ * Move a packet into Lance space
+ */
+private int
+copy_to_lance(
+ register io_req_t request,
+ volatile char *sbuf)
+{
+ register unsigned short *dp;
+ register int len;
+
+ dp = (unsigned short *) request->io_data;
+ len = request->io_count;
+
+ if (len > (int)(ETHERMTU + sizeof(struct ether_header))) {
+ printf("se: truncating HUGE packet\n");
+ len = ETHERMTU + sizeof(struct ether_header);
+ }
+
+ (se_sw->data_copyout) ((vm_offset_t)dp, (vm_offset_t)sbuf, len);
+
+ if (len < LN_MINBUF_NOCH)
+ /*
+ * The lance needs at least this much data in a packet. Who
+ * cares if I send some garbage that was left in the lance
+ * buffer ? If one can spoof packets then one can spoof
+ * packets!
+ */
+ len = LN_MINBUF_NOCH;
+ return len;
+}
+
+/*
+ * Reset a descriptor's flags.
+ * Optionally give the descriptor to the lance
+ */
+private void
+se_desc_set_status (
+ register se_desc_t lndesc,
+ int val)
+{
+ struct se_desc desc;
+
+ (se_sw->desc_copyin) ((vm_offset_t)lndesc, (vm_offset_t)&desc, sizeof(desc));
+ desc.desc4.bits = 0;
+ desc.status = val;
+ (se_sw->desc_copyout) ((vm_offset_t)&desc, (vm_offset_t)lndesc, sizeof(desc));
+ wbflush();
+}
+
+/*
+ * Set/Get status functions
+ */
+int
+se_get_status(
+ int dev,
+ dev_flavor_t flavor,
+ dev_status_t status, /* pointer to OUT array */
+ natural_t *status_count) /* out */
+{
+ return (net_getstat(&se_softc[dev]->is_if,
+ flavor, status, status_count));
+}
+
+int
+se_set_status(
+ int unit,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ register se_softc_t sc;
+
+ sc = se_softc[unit];
+
+
+ switch (flavor) {
+
+ case NET_STATUS:
+ break;
+
+ case NET_ADDRESS: {
+
+ register union ether_cvt {
+ unsigned char addr[6];
+ int lwd[2];
+ } *ec = (union ether_cvt *) status;
+
+ if (status_count < sizeof(*ec) / sizeof(int))
+ return (D_INVALID_SIZE);
+
+ ec->lwd[0] = ntohl(ec->lwd[0]);
+ ec->lwd[1] = ntohl(ec->lwd[1]);
+
+ se_setaddr(ec->addr, unit);
+
+ break;
+ }
+
+ default:
+ return (D_INVALID_OPERATION);
+ }
+
+ return (D_SUCCESS);
+}
+
+
+/*
+ * Install new filter.
+ * Nothing special needs to be done here.
+ */
+io_return_t
+se_setinput(
+ int dev,
+ ipc_port_t receive_port,
+ int priority,
+ filter_t *filter,
+ natural_t filter_count)
+{
+ return (net_set_filter(&se_softc[dev]->is_if,
+ receive_port, priority,
+ filter, filter_count));
+}
+
+/*
+ * Allocate and initialize a ring descriptor.
+ * Allocates a buffer from the lance memory and writes a descriptor
+ * for that buffer to the host virtual address LNDESC.
+ */
+private volatile long
+*se_desc_alloc (
+ register se_softc_t sc,
+ register se_desc_t lndesc)
+{
+ register vm_offset_t dp; /* data pointer */
+ struct se_desc desc;
+
+ /*
+ * Allocate buffer in lance space
+ */
+ dp = se_malloc(sc, LN_BUFFER_SIZE);
+
+ /*
+ * Build a descriptor pointing to it
+ */
+ desc.addr_low = Addr_lo(Lmem(dp));
+ desc.addr_hi = Addr_hi(Lmem(dp));
+ desc.status = 0;
+ desc.buffer_size = -LN_BUFFER_SIZE;
+ desc.desc4.bits = 0;
+
+ /*
+ * Copy the descriptor to lance space
+ */
+ (se_sw->desc_copyout) ((vm_offset_t)&desc, (vm_offset_t)lndesc, sizeof(desc));
+ wbflush();
+
+ return (volatile long *) Hmem(dp);
+}
+
+/*
+ * Allocate a chunk of lance RAM buffer. Since we never
+ * give lance RAM buffer memory back, we'll just step up the
+ * byte-count on a per-unit basis.
+ *
+ * The return value is an index into the lance memory, which can be
+ * passed with Hmem() and Lmem() to get the host and chip virtual addresses.
+ */
+private vm_offset_t
+se_malloc(
+ se_softc_t sc,
+ int size)
+{
+ register vm_offset_t ret;
+
+ /*
+ * On first call, zero lance memory
+ */
+ if (sc->lnsbrk == 0)
+ (se_sw->bzero) (Hmem(0), LN_MEMORY_SIZE);
+
+ /*
+ * Start out on the first double longword boundary
+ * (this accomodates some machines, with minimal loss)
+ */
+ if (sc->lnsbrk & 0xf)
+ sc->lnsbrk = (sc->lnsbrk + 0x10) & ~0xf;
+
+ ret = sc->lnsbrk;
+ sc->lnsbrk += size;
+
+ if (sc->lnsbrk > LN_MEMORY_SIZE)
+ panic("se_malloc");
+
+ return ret;
+}
+
+#endif NLN > 0
diff --git a/chips/lance.h b/chips/lance.h
new file mode 100644
index 00000000..f799d7e6
--- /dev/null
+++ b/chips/lance.h
@@ -0,0 +1,284 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: if_se.h
+ * Authors: Robert V. Baron and Alessandro Forin
+ * Date: 1989
+ *
+ */
+/*
+ * AMD 7990 "Lance" Ethernet interface definitions.
+ * All structures are as seen from the Lance,
+ * both in the memory-alignment sense and in the
+ * byte-order sense. Mapping to host memory is
+ * model specific: on pmaxen there is a 16 bit gap
+ * every other 16 bits.
+ */
+
+#include <scsi/scsi_endian.h>
+
+/*
+ * Selection of one of the four Lance CSR is done in a
+ * two-step process: select which CSR first by writing
+ * into the RAP, then access the register via the RDP.
+ * Note that (a) the selection remains, and (b) all
+ * but CSR0 can only be accessed when the chip is stopped.
+ * These registers are mapped in the 'registers' I/O segment.
+ */
+#ifndef se_reg_type
+#define se_reg_type unsigned short
+#endif
+typedef volatile se_reg_type *se_reg_t;
+
+#define CSR0_SELECT 0x0 /* Valid RAP selections */
+#define CSR1_SELECT 0x1
+#define CSR2_SELECT 0x2
+#define CSR3_SELECT 0x3
+
+/*
+ * Bit definitions for the CSR0.
+ * Legend:
+ * R=Readable W=Writeable
+ * S=Set-on-write-1 C=Clear-on-write-1
+ */
+
+#define LN_CSR0_INIT 0x0001 /* (RS) Initialize */
+#define LN_CSR0_STRT 0x0002 /* (RS) Start */
+#define LN_CSR0_STOP 0x0004 /* (RS) Stop */
+#define LN_CSR0_TDMD 0x0008 /* (RS) Transmit demand */
+#define LN_CSR0_TXON 0x0010 /* (R) Transmitter enabled */
+#define LN_CSR0_RXON 0x0020 /* (R) Receiver enabled */
+#define LN_CSR0_INEA 0x0040 /* (RW) Interrupt enable */
+#define LN_CSR0_INTR 0x0080 /* (R) Interrupt pending */
+#define LN_CSR0_IDON 0x0100 /* (RC) Initialization done */
+#define LN_CSR0_TINT 0x0200 /* (RC) Transmitter interrupt */
+#define LN_CSR0_RINT 0x0400 /* (RC) Receiver interrupt */
+#define LN_CSR0_MERR 0x0800 /* (RC) Memory error during DMA */
+#define LN_CSR0_MISS 0x1000 /* (RC) No available receive buffers */
+#define LN_CSR0_CERR 0x2000 /* (RC) Signal quality (SQE) test */
+#define LN_CSR0_BABL 0x4000 /* (RC) Babble error: xmit too long */
+#define LN_CSR0_ERR 0x8000 /* (R) Error summary: any of the 4 above */
+
+#define LN_CSR0_WTC 0x7f00 /* Write-to-clear bits */
+
+/*
+ * Bit definitions for the CSR1.
+ */
+
+#define LN_CSR1_MBZ 0x0001 /* Must be zero */
+#define LN_CSR1_IADR 0xfffe /* (RW) Initialization block address (low) */
+
+/*
+ * Bit definitions for the CSR2.
+ */
+
+#define LN_CSR2_IADR 0x00ff /* (RW) Initialization block address (high) */
+#define LN_CSR2_XXXX 0xff00 /* (RW) Reserved */
+
+/*
+ * Bit definitions for the CSR3.
+ */
+
+#define LN_CSR3_BCON 0x0001 /* (RW) BM/HOLD Control */
+#define LN_CSR3_ACON 0x0002 /* (RW) ALE Control */
+#define LN_CSR3_BSWP 0x0004 /* (RW) Byte Swap */
+#define LN_CSR3_XXXX 0xfff8 /* (RW) Reserved */
+
+
+/*
+ * Initialization Block
+ *
+ * Read when the INIT command is sent to the lance.
+ */
+
+struct se_init_block {
+ unsigned short mode; /* Mode Register, see below */
+ unsigned short phys_addr_low; /* Ethernet address */
+ unsigned short phys_addr_med; /* Ethernet address */
+ unsigned short phys_addr_high; /* Ethernet address */
+ unsigned short logical_addr_filter0; /* Multicast filter */
+ unsigned short logical_addr_filter1; /* Multicast filter */
+ unsigned short logical_addr_filter2; /* Multicast filter */
+ unsigned short logical_addr_filter3; /* Multicast filter */
+ unsigned short recv_ring_pointer_lo; /* Receive Ring ptr, low */
+ BITFIELD_3(unsigned char,
+ recv_ring_pointer_hi, /* Receive Ring ptr, high */
+ reserved0 : 5,
+ recv_ring_len : 3); /* Length: log2(nbuffers) */
+ unsigned short xmit_ring_pointer_lo; /* Transmit Ring ptr, low */
+ BITFIELD_3(unsigned char,
+ xmit_ring_pointer_hi, /* Transmit Ring ptr, high */
+ reserved1 : 5,
+ xmit_ring_len : 3); /* Length: log2(nbuffers) */
+};
+
+typedef volatile struct se_init_block *se_init_block_t;
+
+/*
+ * Bit definitions for the MODE word
+ * (Normally set to 0)
+ */
+
+#define LN_MODE_DRX 0x0001 /* Disable Receiver */
+#define LN_MODE_DTX 0x0002 /* Disable Transmitter */
+#define LN_MODE_LOOP 0x0004 /* Loopback mode */
+#define LN_MODE_DTRC 0x0008 /* Disable CRC generation */
+#define LN_MODE_COLL 0x0010 /* Force collision */
+#define LN_MODE_DRTY 0x0020 /* Disable retry */
+#define LN_MODE_INTL 0x0040 /* Internal Loopback mode */
+#define LN_MODE_XXXX 0x7f80 /* Reserved */
+#define LN_MODE_PROM 0x8000 /* Promiscuous mode */
+
+/*
+ * Bit definitions for the ring pointers
+ */
+
+#define LN_RNGP_LOW 0xfffc /* longword aligned */
+
+
+/*
+ * Buffer Descriptors
+ * Legend:
+ * H-set-by-Host C-set-by-chip
+ */
+
+struct se_desc {
+ unsigned short addr_low; /* (H) Buffer pointer low */
+ BITFIELD_2(unsigned char,
+ addr_hi, /* (H) Buffer pointer high */
+ status); /* (HC) Buffer status */
+ unsigned short buffer_size; /* (H) Buffer length (bytes),*/
+ /* bits 15..12 must be ones */
+ union {
+ struct {
+ BITFIELD_2(unsigned short,
+ bcnt : 12, /* (C) Rcvd data size */
+ res : 4); /* Reads as zeroes */
+ } rcv;
+ struct {
+ BITFIELD_2(unsigned short,
+ TDR : 10, /* (C) Time Domain Reflectometry */
+ flg2 : 6); /* (C) Xmit status */
+ } xmt;
+ unsigned short bits;
+ } desc4;
+#define message_size desc4.rcv.bcnt
+#define tdr desc4.xmt.TDR
+#define status2 desc4.xmt.flg2
+};
+
+typedef volatile struct se_desc *se_desc_t;
+
+/*
+ * Bit definition for STATUS byte (receive case)
+ */
+
+#define LN_RSTATE_ENP 0x01 /* (C) End of Packet */
+#define LN_RSTATE_STP 0x02 /* (C) Start of packet */
+#define LN_RSTATE_BUFF 0x04 /* (C) Buffer error */
+#define LN_RSTATE_CRC 0x08 /* (C) CRC error */
+#define LN_RSTATE_OFLO 0x10 /* (C) SILO Overflow */
+#define LN_RSTATE_FRAM 0x20 /* (C) Framing error */
+#define LN_RSTATE_ERR 0x40 /* (C) Error summary */
+#define LN_RSTATE_OWN 0x80 /* (C) Owned by Lance Chip (if set) */
+
+
+/*
+ * Bit definition for STATUS byte (transmit case)
+ */
+
+#define LN_TSTATE_ENP 0x01 /* (H) End of Packet */
+#define LN_TSTATE_STP 0x02 /* (H) Start of packet */
+#define LN_TSTATE_DEF 0x04 /* (C) Deferred */
+#define LN_TSTATE_ONE 0x08 /* (C) Retried exactly once */
+#define LN_TSTATE_MORE 0x10 /* (C) Retried more than once */
+#define LN_TSTATE_XXXX 0x20 /* Reserved */
+#define LN_TSTATE_ERR 0x40 /* (C) Error summary (see status2) */
+#define LN_TSTATE_OWN 0x80 /* (H) Owned by Lance Chip (if set) */
+
+/*
+ * Bit definitions for STATUS2 byte (transmit case)
+ */
+
+#define LN_TSTATE2_RTRY 0x01 /* (C) Failed after 16 retransmissions */
+#define LN_TSTATE2_LCAR 0x02 /* (C) Loss of Carrier */
+#define LN_TSTATE2_LCOL 0x04 /* (C) Late collision */
+#define LN_TSTATE2_XXXX 0x08 /* Reserved */
+#define LN_TSTATE2_UFLO 0x10 /* (C) Underflow (late memory) */
+#define LN_TSTATE2_BUFF 0x20 /* (C) Buffering error (no ENP) */
+
+ /* Errors that disable the transmitter */
+#define LN_TSTATE2_DISABLE (LN_TSTATE2_UFLO|LN_TSTATE2_BUFF|LN_TSTATE2_RTRY)
+
+/*
+ * Other chip characteristics
+ */
+
+#define LN_MINBUF_CH 100 /* Minimum size of first lance buffer, if
+ chaining */
+
+#define LN_MINBUF_NOCH 60 /* Minimum size of a lance buffer, if
+ no chaining and DTCR==1 */
+
+#define LN_MINBUF_NOCH_RAW 64 /* Minimum size of a lance buffer, if
+ no chaining and DTCR==0 */
+
+/*
+ * Information for mapped ether
+ */
+typedef struct mapped_ether_info {
+ volatile unsigned int interrupt_count;
+ /* tot interrupts received */
+ volatile unsigned short saved_csr0;
+ /* copy of csr0 at last intr */
+ unsigned char rom_stride;
+ unsigned char ram_stride;
+ /* rom&ram strides */
+ unsigned buffer_size;
+ /* how much ram for lance */
+ natural_t buffer_physaddr;
+ /* where it is in phys memory */
+ unsigned wait_event;
+} *mapped_ether_info_t;
+
+#ifdef KERNEL
+extern struct se_switch {
+ vm_offset_t regspace;
+ vm_offset_t bufspace;
+ vm_offset_t ln_bufspace;
+ vm_offset_t romspace;
+ short romstride;
+ short ramstride;
+ int ramsize;
+ void (*desc_copyin)( vm_offset_t, vm_offset_t, int);
+ void (*desc_copyout)( vm_offset_t, vm_offset_t, int);
+ void (*data_copyin)( vm_offset_t, vm_offset_t, int);
+ void (*data_copyout)( vm_offset_t, vm_offset_t, int);
+ void (*bzero)( vm_offset_t, int );
+ vm_offset_t (*mapaddr)( vm_offset_t );
+ vm_size_t (*mapoffs)( vm_size_t );
+} *se_sw;
+#endif KERNEL
diff --git a/chips/lance_mapped.c b/chips/lance_mapped.c
new file mode 100644
index 00000000..26096bd9
--- /dev/null
+++ b/chips/lance_mapped.c
@@ -0,0 +1,417 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: if_se_mapped.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 8/90
+ *
+ * In-kernel side of the user-mapped ethernet driver.
+ */
+
+#include <ln.h>
+#if NLN > 0
+#include <platforms.h>
+
+#include <mach/machine/vm_types.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <chips/lance.h>
+#include <chips/busses.h>
+
+#include <device/device_types.h>
+#include <device/errno.h>
+#include <device/io_req.h>
+#include <device/net_status.h>
+#include <device/net_io.h>
+#include <device/if_hdr.h>
+#include <device/if_ether.h>
+
+#include <vm/vm_kern.h>
+#include <kern/eventcount.h>
+
+#include <machine/machspl.h>
+
+#ifdef DECSTATION
+
+#define machine_btop mips_btop
+
+#define kvctophys(v) K0SEG_TO_PHYS((v)) /* kernel virtual cached */
+#define phystokvc(p) PHYS_TO_K0SEG((p)) /* and back */
+#define kvutophys(v) K1SEG_TO_PHYS((v)) /* kernel virtual uncached */
+#define phystokvu(p) PHYS_TO_K1SEG((p)) /* and back */
+ /* remap from k2 to k0 */
+#define kvirt(v) ((phystokvc(pmap_extract(pmap_kernel(),v))))
+
+#include <mips/mips_cpu.h>
+/*
+ * Wired addresses and sizes
+ */
+#define SE0_REG_EMRG (se_reg_t)(0xb8000000)
+
+#define REGBASE(unit) (((u_int)SE_statii[unit].registers) - se_sw->regspace)
+
+#define SE_REG_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->regspace)
+#define SE_REG_SIZE PAGE_SIZE
+
+#define SE_BUF_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->bufspace)
+#define SE_BUF_SIZE (128*1024)
+
+#define SE_ADR_PHYS(unit) kvutophys(REGBASE(unit)+se_sw->romspace)
+#define SE_ADR_SIZE PAGE_SIZE
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#define machine_btop vax_btop
+#endif /*VAXSTATION*/
+
+#ifdef LUNA88K
+# define machine_btop m88k_btop
+# define kvirt(v) (v)
+# define kvctophys(v) pmap_extract(pmap_kernel(),(v))
+# define SE0_REG_EMRG ((se_reg_t)0xF1000000U)
+# define REGBASE(unit) (((u_int)SE_statii[unit].registers) - se_sw->regspace)
+# define SE_REG_PHYS(unit) (REGBASE(unit) + se_sw->regspace)
+# define SE_REG_SIZE PAGE_SIZE
+# define SE_BUF_PHYS(unit) (REGBASE(unit) + se_sw->bufspace)
+# define SE_BUF_SIZE (64*1024)
+# define SE_ADR_PHYS(unit) kvctophys(REGBASE(unit) + se_sw->romspace)
+# define SE_ADR_SIZE PAGE_SIZE
+# define wbflush() /*empty*/
+#endif /*LUNA88K*/
+
+/*
+ * Autoconf info
+ */
+
+static vm_offset_t SEstd[NLN] = { 0 };
+static struct bus_device *SEinfo[NLN];
+ void SE_attach();
+ int SE_probe();
+
+struct bus_driver SEdriver =
+ { SE_probe, 0, SE_attach, 0, SEstd, "SE", SEinfo, };
+
+/*
+ * Externally visible functions
+ */
+int SE_probe(); /* Kernel */
+void SE_intr(), SE_portdeath();
+ /* User */
+int SE_open(), SE_close();
+vm_offset_t SE_mmap();
+
+
+/* forward declarations */
+
+static void SE_stop(unsigned int unit);
+
+/*
+ * Status information for all interfaces
+ */
+/*static*/ struct SE_status {
+ se_reg_t registers;
+ mapped_ether_info_t info;
+ struct evc eventcounter;
+} SE_statii[NLN];
+
+
+/*
+ * Probe the Lance to see (if) that it's there
+ */
+int
+SE_probe(regbase, ui)
+ vm_offset_t regbase;
+ register struct bus_device *ui;
+{
+ int unit = ui->unit;
+ se_reg_t regs;
+ vm_offset_t addr;
+ mapped_ether_info_t info;
+ struct SE_status *self;
+
+
+ if (unit >= NLN)
+ return 0;
+
+ self = &SE_statii[unit];
+
+ printf("[mappable] ");
+
+ regs = (se_reg_t) (regbase + se_sw->regspace);
+ self->registers = regs;
+
+ /*
+ * Reset the interface
+ */
+ SE_stop(unit);
+
+ /*
+ * Grab a page to be mapped later to users
+ */
+ (void) kmem_alloc_wired(kernel_map, &addr, PAGE_SIZE);
+ /*
+ on the decstation, kmem_alloc_wired returns virtual addresses
+ in the k2 seg. Since this page is going to get mapped in
+ user space, we need to transform it to a better understood
+ virtual address. The kvirt function does this.
+ */
+ bzero(addr, PAGE_SIZE);
+ info = (mapped_ether_info_t) kvirt(addr);
+ self->info = info;
+
+ /*
+ * Set permanent info
+ */
+ info->rom_stride = se_sw->romstride;
+ info->ram_stride = se_sw->ramstride;
+ info->buffer_size = se_sw->ramsize;
+ info->buffer_physaddr = se_sw->ln_bufspace;
+
+ /*
+ * Synch setup
+ */
+ evc_init(&self->eventcounter);
+ info->wait_event = self->eventcounter.ev_id;
+
+ return 1;
+}
+
+void
+SE_attach(ui)
+ register struct bus_device *ui;
+{
+}
+
+
+/*
+ * Shut off the lance
+ */
+static void SE_stop(unsigned int unit)
+{
+ register se_reg_t regs = SE_statii[unit].registers;
+
+ if (regs == 0)
+ /* Stray interrupt */
+ regs = SE0_REG_EMRG;
+
+ regs[2] = CSR0_SELECT; /* XXXX rap XXXX */
+ wbflush();
+ regs[0] = LN_CSR0_STOP;
+ wbflush();
+}
+
+
+/*
+ * Ethernet interface interrupt routine
+ */
+void SE_intr(unit,spllevel)
+ int unit;
+ spl_t spllevel;
+{
+ register struct SE_status *self = &SE_statii[unit];
+ register se_reg_t regs = self->registers;
+ register csr;
+
+ if (regs == 0) { /* stray */
+ SE_stop(unit);
+ return;
+ }
+
+ /* Acknowledge interrupt request, drop spurious intr */
+ csr = regs[0];
+ if ((csr & LN_CSR0_INTR) == 0)
+ return;
+ regs[0] = csr & LN_CSR0_WTC; /* silence it */
+
+ splx(spllevel); /* drop priority now */
+
+ /* Pass csr state up to user thread */
+ if (self->info) {
+ self->info->interrupt_count++; /* total interrupts */
+ self->info->saved_csr0 = csr;
+ }
+
+ /* Awake user thread */
+ evc_signal(&self->eventcounter);
+}
+
+
+extern boolean_t se_use_mapped_interface[NLN];
+
+/*
+ * Device open procedure
+ */
+int SE_open(dev, flag, ior)
+ io_req_t ior;
+{
+ int unit = dev;
+ register struct SE_status *self = &SE_statii[unit];
+
+ if (unit >= NLN)
+ return EINVAL;
+
+ /*
+ * Silence interface, just in case
+ */
+ SE_stop(unit);
+
+ /*
+ * Reset eventcounter
+ */
+ evc_signal(&self->eventcounter);
+
+ se_use_mapped_interface[unit] = 1;
+
+ /*
+ * Do not turn Ether interrupts on. The user can do it when ready
+ * to take them.
+ */
+
+ return 0;
+}
+
+/*
+ * Device close procedure
+ */
+int SE_close(dev, flag)
+{
+ int unit = dev;
+ register struct SE_status *self = &SE_statii[unit];
+
+ if (unit >= NLN)
+ return EINVAL;
+
+ /*
+ * Silence interface, in case user forgot
+ */
+ SE_stop(unit);
+ evc_signal(&self->eventcounter);
+
+ se_normal(unit);
+
+ return 0;
+}
+
+
+/*
+ * Get status procedure.
+ * We need to tell that we are mappable.
+ */
+io_return_t
+SE_get_status(ifp, flavor, status, status_count)
+/* struct ifnet *ifp; not really..*/
+ int flavor;
+ dev_status_t status; /* pointer to OUT array */
+ unsigned int *status_count; /* OUT */
+{
+ switch (flavor) {
+ case NET_STATUS:
+ {
+ register struct net_status *ns = (struct net_status *)status;
+
+ ns->min_packet_size = sizeof(struct ether_header);
+ ns->max_packet_size = sizeof(struct ether_header) + ETHERMTU;
+ ns->header_format = HDR_ETHERNET;
+ ns->header_size = sizeof(struct ether_header);
+ ns->address_size = 6;
+ ns->flags = IFF_BROADCAST;
+ ns->mapped_size = SE_BUF_SIZE + (3 * PAGE_SIZE);
+
+ *status_count = NET_STATUS_COUNT;
+ break;
+ }
+/* case NET_ADDRESS: find it yourself */
+ default:
+ return (D_INVALID_OPERATION);
+ }
+ return (D_SUCCESS);
+}
+
+/*
+ * Should not refuse this either
+ */
+int SE_set_status(dev, flavor, status, status_count)
+ int dev;
+ int flavor;
+ dev_status_t status;
+ unsigned int status_count;
+{
+ return (D_SUCCESS);
+}
+
+/*
+ * Port death notification routine
+ */
+void SE_portdeath(dev, dead_port)
+{
+}
+
+
+/*
+ * Virtual->physical mapping routine.
+ */
+vm_offset_t
+SE_mmap(dev, off, prot)
+ int dev;
+ vm_offset_t off;
+ vm_prot_t prot;
+{
+ vm_offset_t page;
+ vm_offset_t addr;
+ int unit = dev;
+
+ /*
+ * The offset (into the VM object) defines the following layout
+ *
+ * off size what
+ * 0 1pg mapping information (csr & #interrupts)
+ * 1pg 1pg lance registers
+ * 2pg 1pg lance station address (ROM)
+ * 3pg 128k lance buffers
+ */
+#define S0 PAGE_SIZE
+#define S1 (S0+SE_REG_SIZE)
+#define S2 (S1+SE_ADR_SIZE)
+#define S3 (S2+SE_BUF_SIZE)
+
+ if (off < S0) {
+ addr = kvctophys (SE_statii[unit].info);
+ } else if (off < S1) {
+ addr = (vm_offset_t) SE_REG_PHYS(unit);
+ off -= S0;
+ } else if (off < S2) {
+ addr = (vm_offset_t) SE_ADR_PHYS(unit);
+ off -= S1;
+ } else if (off < S3) {
+ addr = (vm_offset_t) SE_BUF_PHYS(unit);
+ off -= S2;
+ } else
+ return (EINVAL);
+
+ page = machine_btop(addr + off);
+ return (page);
+}
+
+#endif NLN > 0
diff --git a/chips/lk201.c b/chips/lk201.c
new file mode 100644
index 00000000..d11b1e97
--- /dev/null
+++ b/chips/lk201.c
@@ -0,0 +1,695 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: lk201.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Routines for the LK201 Keyboard Driver
+ */
+
+#include <lk.h>
+#if NLK > 0
+#include <bm.h>
+
+#include <mach_kdb.h>
+
+#include <mach/std_types.h>
+#include <device/device_types.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <sys/ioctl.h>
+#include <machine/machspl.h>
+#include <chips/lk201.h>
+#include <chips/serial_defs.h>
+#include <chips/screen_defs.h>
+
+
+/*
+ * Structures describing the keyboard status
+ */
+typedef struct {
+ unsigned short kbd_flags;
+ unsigned short kbd_previous;
+ char kbd_gen_shift;
+ char kbd_ctrl;
+ char kbd_lock;
+ char kbd_meta;
+ char kbd_shift;
+} lk201_kbd_state_t;
+
+#define mapLOCKtoCNTRL 0x1 /* flags */
+
+typedef struct {
+ char led_active;
+ char led_pattern;
+ char led_increasing;
+ char led_lights;
+ int led_interval;
+ int led_light_count;
+} lk201_led_state_t;
+
+
+/*
+ * Keyboard state
+ */
+
+struct lk201_softc {
+ lk201_kbd_state_t kbd;
+ lk201_led_state_t led;
+ int sl_unit;
+} lk201_softc_data[NLK];
+
+typedef struct lk201_softc *lk201_softc_t;
+
+lk201_softc_t lk201_softc[NLK];
+
+/*
+ * Forward decls
+ */
+io_return_t
+lk201_translation(
+ int key,
+ char c,
+ int tabcode );
+
+int
+lk201_input(
+ int unit,
+ unsigned short data);
+
+
+/*
+ * Autoconf (sort-of)
+ */
+lk201_probe(
+ int unit)
+{
+ lk201_softc[unit] = &lk201_softc_data[unit];
+ return 1;
+}
+
+void lk201_attach(
+ int unit,
+ int sl_unit)
+{
+ lk201_softc[unit]->sl_unit = sl_unit;
+ lk201_selftest(unit);
+}
+
+/*
+ * Keyboard initialization
+ */
+
+static unsigned char lk201_reset_string[] = {
+ LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */
+ LK_CMD_SET_DEFAULTS,
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,1),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,2),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,3),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,4),
+ LK_CMD_MODE(LK_MODE_DOWN_UP,5),
+ LK_CMD_MODE(LK_MODE_DOWN_UP,6),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,7),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,8),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,9),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,10),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,11),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,12),
+ LK_CMD_MODE(LK_MODE_DOWN,13),
+ LK_CMD_MODE(LK_MODE_RPT_DOWN,14),
+ LK_CMD_ENB_RPT,
+/* LK_CMD_ENB_KEYCLK, LK_PARAM_VOLUME(4), */
+ LK_CMD_DIS_KEYCLK,
+ LK_CMD_RESUME,
+ LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4),
+ LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf)
+};
+
+void
+lk201_reset(
+ int unit)
+{
+ register int i, sl;
+ register spl_t s;
+ lk201_softc_t lk;
+
+ lk = lk201_softc[unit];
+ sl = lk->sl_unit;
+ s = spltty();
+ for (i = 0; i < sizeof(lk201_reset_string); i++) {
+ (*console_putc)(sl,
+ SCREEN_LINE_KEYBOARD,
+ lk201_reset_string[i]);
+ delay(100);
+ }
+ /* zero any state associated with previous keypresses */
+ bzero(lk, sizeof(*lk));
+ lk->sl_unit = sl;
+ splx(s);
+}
+
+lk201_selftest(
+ int unit)
+{
+ int messg[4], sl;
+ spl_t s;
+
+ sl = lk201_softc[unit]->sl_unit;
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_REQ_ID);
+ delay(10000);/* arbitrary */
+ messg[0] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[1] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ splx(s);
+
+ printf("( lk201 id %x.%x", messg[0], messg[1]);
+
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_POWER_UP);
+
+ /* cannot do this, waiting too long might cause receiver overruns */
+/* delay(80000);/* spec says 70 msecs or less */
+
+ messg[0] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[1] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[2] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ messg[3] = (*console_getc)(sl, SCREEN_LINE_KEYBOARD, TRUE, TRUE);
+ splx(s);
+
+ printf(", self-test ");
+ if (messg[0] != 0x01 || messg[1] || messg[2] || messg[3])
+ printf("bad [%x %x %x %x]",
+ messg[0], messg[1], messg[2], messg[3]);
+ else
+ printf("ok )");
+
+ lk201_reset(unit);
+}
+
+/*
+ * Tinkerbell
+ */
+void
+lk201_ring_bell(
+ int unit)
+{
+ spl_t s = spltty();
+ (*console_putc)(lk201_softc[unit]->sl_unit, SCREEN_LINE_KEYBOARD, LK_CMD_BELL);
+ splx(s);
+}
+
+/*
+ * Here is your LED toy, Bob
+ */
+void
+lk201_lights(
+ int unit,
+ boolean_t on)
+{
+ unsigned int sl;
+ spl_t s;
+
+ sl = lk201_softc[unit]->sl_unit;
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0xf));
+ if (on < 16 && on > 0) {
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(on));
+ }
+ splx(s);
+}
+
+
+lk201_led(
+ int unit)
+{
+ lk201_led_state_t *leds = &lk201_softc[unit]->led;
+ unsigned int sl;
+ spl_t s;
+
+ sl = lk201_softc[unit]->sl_unit;
+ if (leds->led_interval) { /* leds are on */
+ if (leds->led_light_count <= 0) { /* hit this lights */
+
+ if (leds->led_lights <= 0) leds->led_lights= 1; /* sanity */
+ if (leds->led_lights > 16) leds->led_lights = 16;/* sanity */
+ leds->led_light_count = leds->led_interval; /* reset */
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(leds->led_lights));
+ switch (leds->led_pattern) {
+ case LED_OFF:
+ leds->led_interval = 0; /* since you can now set */
+ break; /* the interval even if off */
+ case LED_COUNT:
+ leds->led_lights++;
+ if (leds->led_lights > 16) leds->led_lights = 1;
+ break;
+ case LED_ROTATE:
+ leds->led_lights <<= 1;
+ if (leds->led_lights > 8) leds->led_lights = 1;
+ break;
+ case LED_CYLON:
+ if (leds->led_increasing) {
+ leds->led_lights <<= 1;
+ if (leds->led_lights > 8) {
+ leds->led_lights >>= 2;
+ leds->led_increasing = 0;
+ }
+ } else {
+ leds->led_lights >>= 1;
+ if (leds->led_lights <= 0) {
+ leds->led_lights = 2;
+ leds->led_increasing = 1;
+ }
+ }
+ break;
+ }
+ (*console_putc)( sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON);
+ (*console_putc)( sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(leds->led_lights));
+ splx(s);
+ }
+ leds->led_light_count--;
+ } else {
+ if (leds->led_lights) {
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0xf));
+ leds->led_lights = 0;
+ splx(s);
+ }
+ leds->led_active = 0;
+#if NBM > 0
+ screen_enable_vretrace(unit, 0); /* interrupts off */
+#endif
+ }
+}
+
+
+/*
+ * Special user-visible ops
+ */
+io_return_t
+lk201_set_status(
+ int unit,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ lk201_led_state_t *leds = &lk201_softc[unit]->led;
+ lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd;
+
+ switch( flavor ) {
+ case LK201_SEND_CMD:{
+ register lk201_cmd_t *cmd = (lk201_cmd_t*)status;
+ unsigned int cnt, s, sl;
+
+ if ((status_count < (sizeof(*cmd)/sizeof(int))) ||
+ ((cnt = cmd->len) > 2))
+ return D_INVALID_SIZE;
+
+ if (cnt == 0)
+ cmd->command |= LK_PARAM;
+ else
+ cmd->params[cnt-1] |= LK_PARAM;
+ sl = lk201_softc[unit]->sl_unit;
+ s = spltty();
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->command);
+ if (cnt > 0)
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->params[0]);
+ if (cnt > 1)
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, cmd->params[1]);
+ splx(s);
+ return D_SUCCESS;
+ }
+ case LK201_LED_PATTERN:{
+ register int ptn = * (int *) status;
+ if (ptn != LED_OFF && ptn != LED_COUNT &&
+ ptn != LED_ROTATE && ptn != LED_CYLON ) {
+ return -1;
+ } else {
+ leds->led_pattern = ptn;
+ }
+ break;
+ }
+ case LK201_LED_INTERVAL:{
+ register int lcnt = * (int *) status;
+ if (lcnt < 0)
+ lcnt = 1;
+ leds->led_interval = lcnt;
+ break;
+ }
+ case LK201_mapLOCKtoCNTRL:{
+ boolean_t enable = * (boolean_t*) status;
+ if (enable)
+ kbd->kbd_flags |= mapLOCKtoCNTRL;
+ else
+ kbd->kbd_flags &= ~mapLOCKtoCNTRL;
+ return D_SUCCESS;
+ }
+ case LK201_REMAP_KEY:{
+ register KeyMap *k = (KeyMap *) status;
+ int mode;
+
+ if (status_count < (sizeof(KeyMap)/sizeof(int)))
+ return D_INVALID_SIZE;
+
+ mode = k->shifted ? 1 : 0;
+ if (k->meta) mode += 2;
+ return lk201_translation( k->in_keyval,
+ k->out_keyval,
+ mode );
+ }
+ default:
+ return D_INVALID_OPERATION;
+ }
+ leds->led_lights = 1;
+ leds->led_active = 1;
+#if NBM > 0
+ screen_enable_vretrace(unit, 1); /* interrupts on */
+#endif
+ return D_SUCCESS;
+}
+
+/*
+ * Keycode translation tables
+ *
+ * NOTE: these tables have been compressed a little bit
+ * because the lk201 cannot generate very small codes.
+ */
+
+unsigned char lk201_xlate_key[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f,'\r','\t','`'
+ /* 192 */ ,'1' ,'q' ,'a' ,'z' ,0 ,'2' ,'w' ,'s'
+ /* 200 */ ,'x' ,'<' ,0 ,'3' ,'e' ,'d' ,'c' ,0
+ /* 208 */ ,'4' ,'r' ,'f' ,'v' ,' ' ,0 ,'5' ,'t'
+ /* 216 */ ,'g' ,'b' ,0 ,'6' ,'y' ,'h' ,'n' ,0
+ /* 224 */ ,'7' ,'u' ,'j' ,'m' ,0 ,'8' ,'i' ,'k'
+ /* 232 */ ,',' ,0 ,'9' ,'o' ,'l' ,'.' ,0 ,'0'
+ /* 240 */ ,'p' ,0 ,';' ,'/' ,0 ,'=' ,']' ,'\\'
+ /* 248 */ ,0 ,'-' ,'[' ,'\'' ,0 ,0 ,0 ,0
+};
+
+unsigned char lk201_xlate_shifted[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~'
+ /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S'
+ /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0
+ /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T'
+ /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0
+ /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K'
+ /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')'
+ /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|'
+ /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0
+};
+
+unsigned char lk201_xlate_meta[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~'
+ /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S'
+ /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0
+ /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T'
+ /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0
+ /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K'
+ /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')'
+ /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|'
+ /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0
+};
+
+unsigned char lk201_xlate_shifted_meta[] = {
+ /* 86 */ 0 ,0
+ /* 88 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 96 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 104 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 112 */ ,0 ,0x1b ,0x08 ,'\n' ,0 ,0 ,0 ,0
+ /* 120 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 128 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 136 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 144 */ ,0 ,0 ,'0',0 ,'.','\r','1','2'
+ /* 152 */ ,'3','4','5','6',',','7','8','9'
+ /* 160 */ ,'-',0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 168 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 176 */ ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
+ /* 184 */ ,0 ,0 ,0 ,0 ,0x7f ,'\r' ,'\t' ,'~'
+ /* 192 */ ,'!' ,'Q' ,'A' ,'Z' ,0 ,'@' ,'W' ,'S'
+ /* 200 */ ,'X' ,'>' ,0 ,'#' ,'E' ,'D' ,'C' ,0
+ /* 208 */ ,'$' ,'R' ,'F' ,'V' ,' ' ,0 ,'%' ,'T'
+ /* 216 */ ,'G' ,'B' ,0 ,'^' ,'Y' ,'H' ,'N' ,0
+ /* 224 */ ,'&' ,'U' ,'J' ,'M' ,0 ,'*' ,'I' ,'K'
+ /* 232 */ ,'<' ,0 ,'(' ,'O' ,'L' ,'>' ,0 ,')'
+ /* 240 */ ,'P' ,0 ,':' ,'?' ,0 ,'+' ,'}' ,'|'
+ /* 248 */ ,0 ,'_' ,'{' ,'"' ,0 ,0 ,0 ,0
+};
+
+
+io_return_t
+lk201_translation(
+ int key,
+ char c,
+ int tabcode )
+{
+ unsigned char *table;
+
+ if ((key &= 0xff) < LK_MINCODE)
+ return D_INVALID_OPERATION;
+
+ switch (tabcode) {
+ case 3:
+ table = lk201_xlate_shifted_meta;
+ break;
+ case 2:
+ table = lk201_xlate_meta;
+ break;
+ case 1:
+ table = lk201_xlate_shifted;
+ break;
+ case 0:
+ default:
+ table = lk201_xlate_key;
+ break;
+ }
+ table[key - LK_MINCODE] = c;
+ return D_SUCCESS;
+}
+
+/*
+ * Input character processing
+ */
+
+lk201_rint(
+ int unit,
+ unsigned short data,
+ boolean_t handle_shift,
+ boolean_t from_kernel)
+{
+ int c;
+ lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd;
+
+ /*
+ * Keyboard touched, clean char to 8 bits.
+ */
+#if NBM > 0
+ ssaver_bump(unit);
+#endif
+
+ data &= 0xff;
+
+ /* Translate keycode into ASCII */
+ if ((c = lk201_input(unit, data)) == -1)
+ return -1;
+
+#if NBM > 0
+ /*
+ * Notify X, unless we are called from inside kernel
+ */
+ if (!from_kernel &&
+ screen_keypress_event(unit, DEV_KEYBD, data, EVT_BUTTON_RAW))
+ return -1;
+#endif
+
+ /* Handle shifting if need to */
+ if (kbd->kbd_gen_shift)
+ return (handle_shift) ? cngetc() : -1;
+
+ return c;
+}
+
+/*
+ * Routine to grock a character from LK201
+ */
+#if MACH_KDB
+int lk201_allow_kdb = 1;
+#endif
+
+int lk201_debug = 0;
+
+lk201_input(
+ int unit,
+ unsigned short data)
+{
+ int c, sl;
+ lk201_kbd_state_t *kbd = &lk201_softc[unit]->kbd;
+
+ kbd->kbd_gen_shift = 0;
+
+#if MACH_KDB
+ if (lk201_allow_kdb && (data == LK_DO)) {
+ kdb_kintr();
+ return -2;
+ }
+#endif
+
+ /*
+ * Sanity checks
+ */
+
+ if (data == LK_INPUT_ERR || data == LK_OUTPUT_ERR) {
+ printf(" Keyboard error, code = %x\n",data);
+ return -1;
+ }
+ if (data < LK_MINCODE)
+ return -1;
+
+ /*
+ * Check special keys: shifts, ups, ..
+ */
+
+ if (data == LK_LOCK && (kbd->kbd_flags&mapLOCKtoCNTRL))
+ data = LK_CNTRL;
+
+ switch (data) {
+ case LK_LOCK:
+ kbd->kbd_lock ^= 1;
+ kbd->kbd_gen_shift = 1;
+ sl = lk201_softc[unit]->sl_unit;
+ /* called from interrupt, no need for spl */
+ if (kbd->kbd_lock)
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_ON);
+ else
+ (*console_putc)(sl,SCREEN_LINE_KEYBOARD, LK_CMD_LEDS_OFF);
+ (*console_putc)(sl, SCREEN_LINE_KEYBOARD, LK_PARAM_LED_MASK(0x4));
+ return 0;
+
+ case LK_ALT:
+ case LK_L_ALT:
+ case LK_R_ALT:
+ case LK_R_COMPOSE:
+ kbd->kbd_meta ^= 1;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_SHIFT:
+ case LK_R_SHIFT:
+ kbd->kbd_shift ^= 1;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_CNTRL:
+ kbd->kbd_ctrl ^= 1;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_ALLUP:
+ kbd->kbd_ctrl = 0;
+ kbd->kbd_shift = 0;
+ kbd->kbd_meta = 0;
+ kbd->kbd_gen_shift = 1;
+ return 0;
+
+ case LK_REPEAT:
+ c = kbd->kbd_previous;
+ break;
+
+ default:
+
+ /*
+ * Do the key translation to ASCII
+ */
+ if (kbd->kbd_ctrl || kbd->kbd_lock || kbd->kbd_shift) {
+ c = ((kbd->kbd_meta) ?
+ lk201_xlate_shifted_meta : lk201_xlate_shifted)
+ [data - LK_MINCODE];
+ if (kbd->kbd_ctrl)
+ c &= 0x1f;
+ } else
+ c = ((kbd->kbd_meta) ?
+ lk201_xlate_meta : lk201_xlate_key)
+ [data-LK_MINCODE];
+ break;
+
+ }
+
+ kbd->kbd_previous = c;
+
+ /*
+ * DEBUG code DEBUG
+ */
+ if (lk201_debug && (c == 0)) {
+ printf("lk201: [%x]\n", data);
+ }
+
+ return c;
+}
+
+#endif /* NLK > 0 */
diff --git a/chips/lk201.h b/chips/lk201.h
new file mode 100644
index 00000000..5c7bbba0
--- /dev/null
+++ b/chips/lk201.h
@@ -0,0 +1,241 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: lk201.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Definitions for the LK201 Keyboard Driver
+ */
+
+/*
+ * KeyCodes generated by the LK201 board
+ * (labels as in the lk201-AA USA model)
+ */
+
+#define LK_MINCODE 0x56
+ /* Function keys */
+#define LK_F1 0x56 /* div 10 */
+#define LK_F2 0x57
+#define LK_F3 0x58
+#define LK_F4 0x59
+#define LK_F5 0x5a
+#define LK_F6 0x64 /* div 11 */
+#define LK_F7 0x65
+#define LK_F8 0x66
+#define LK_F9 0x67
+#define LK_F10 0x68
+#define LK_F11 0x71 /* div 12 */
+#define LK_ESC LK_F11
+#define LK_F12 0x72
+#define LK_BS LK_F12
+#define LK_F13 0x73
+#define LK_LF LK_F13
+#define LK_F14 0x74
+#define LK_HELP 0x7c /* div 13 */
+#define LK_DO 0x7d
+#define LK_F17 0x80 /* div 14 */
+#define LK_F18 0x81
+#define LK_F19 0x82
+#define LK_F20 0x83
+ /* Editing keys */
+#define LK_FIND 0x8a /* div 9 */
+#define LK_INSERT 0x8b
+#define LK_REMOVE 0x8c
+#define LK_SELECT 0x8d
+#define LK_PREV_SCREEN 0x8e
+#define LK_NEXT_SCREEN 0x8f
+ /* Numeric keypad */
+#define LK_KP_0 0x92 /* div 2 */
+#define LK_KP_DOT 0x94
+#define LK_KP_ENTER 0x95
+#define LK_KP_1 0x96
+#define LK_KP_2 0x97
+#define LK_KP_3 0x98
+#define LK_KP_4 0x99
+#define LK_KP_5 0x9a
+#define LK_KP_6 0x9b
+#define LK_KP_COMMA 0x9c
+#define LK_KP_7 0x9d
+#define LK_KP_8 0x9e
+#define LK_KP_9 0x9f
+#define LK_KP_MINUS 0xa0
+#define LK_KP_PF1 0xa1
+#define LK_KP_PF2 0xa2
+#define LK_KP_PF3 0xa3
+#define LK_KP_PF4 0xa4
+ /* Cursor keys */
+#define LK_LEFT 0xa7 /* div 7 */
+#define LK_RIGHT 0xa8
+#define LK_DOWN 0xa9 /* div 8 */
+#define LK_UP 0xaa
+ /* Shift & Co. */
+#define LK_R_SHIFT 0xab /* lk401 */
+#define LK_L_ALT 0xac /* lk401 */
+#define LK_R_COMPOSE 0xad /* lk401 */
+#define LK_SHIFT 0xae /* div 6 */
+#define LK_CNTRL 0xaf
+#define LK_LOCK 0xb0 /* div 5 */
+#define LK_ALT 0xb1
+#define LK_R_ALT 0xb2 /* lk401 */
+ /* Special codes */
+#define LK_ALLUP 0xb3
+#define LK_REPEAT 0xb4
+#define LK_OUTPUT_ERR 0xb5
+#define LK_INPUT_ERR 0xb6
+#define LK_KDBLOCK_ACK 0xb7
+#define LK_TESTMODE_ACK 0xb8
+#define LK_PFX_KEYDOWN 0xb9
+#define LK_MODECHG_ACK 0xba
+ /* Delete & Co. */
+#define LK_DEL 0xbc /* div 3 */
+#define LK_RETURN 0xbd /* div 4 */
+#define LK_TAB 0xbe
+ /* Graphic keys */
+
+#define LK_TILDE 0xbf /* div 2 */
+#define LK_1 0xc0
+#define LK_Q 0xc1
+#define LK_A 0xc2
+#define LK_Z 0xc3
+#define LK_2 0xc5
+#define LK_W 0xc6
+#define LK_S 0xc7
+#define LK_X 0xc8
+#define LK_LESSGRT 0xc9
+#define LK_3 0xcb
+#define LK_E 0xcc
+#define LK_D 0xcd
+#define LK_C 0xce
+#define LK_4 0xd0
+#define LK_R 0xd1
+#define LK_F 0xd2
+#define LK_V 0xd3
+#define LK_SP 0xd4
+#define LK_5 0xd6
+#define LK_T 0xd7
+#define LK_G 0xd8
+#define LK_B 0xd9
+#define LK_6 0xdb
+#define LK_Y 0xdc
+#define LK_H 0xdd
+#define LK_N 0xde
+#define LK_7 0xe0 /* div 1 */
+#define LK_U 0xe1
+#define LK_J 0xe2
+#define LK_M 0xe3
+#define LK_8 0xe5
+#define LK_I 0xe6
+#define LK_K 0xe7
+#define LK_DQUOTE 0xe8
+#define LK_9 0xea
+#define LK_O 0xeb
+#define LK_L 0xec
+#define LK_DOT 0xed
+#define LK_0 0xef
+#define LK_P 0xf0
+#define LK_COLON 0xf2
+#define LK_QMARK 0xf3
+#define LK_PLUS 0xf5
+#define LK_RBRACKET 0xf6
+#define LK_VBAR 0xf7
+#define LK_MINUS 0xf9
+#define LK_LBRACKET 0xfa
+#define LK_COMMA 0xfb
+
+
+/*
+ * Commands to the keyboard processor
+ */
+
+#define LK_PARAM 0x80 /* start/end parameter list */
+
+#define LK_CMD_RESUME 0x8b
+#define LK_CMD_INHIBIT 0xb9
+#define LK_CMD_LEDS_ON 0x13 /* 1 param: led bitmask */
+#define LK_CMD_LEDS_OFF 0x11 /* 1 param: led bitmask */
+#define LK_CMD_DIS_KEYCLK 0x99
+#define LK_CMD_ENB_KEYCLK 0x1b /* 1 param: volume */
+#define LK_CMD_DIS_CTLCLK 0xb9
+#define LK_CMD_ENB_CTLCLK 0xbb
+#define LK_CMD_SOUND_CLK 0x9f
+#define LK_CMD_DIS_BELL 0xa1
+#define LK_CMD_ENB_BELL 0x23 /* 1 param: volume */
+#define LK_CMD_BELL 0xa7
+#define LK_CMD_TMP_NORPT 0xc1
+#define LK_CMD_ENB_RPT 0xe3
+#define LK_CMD_DIS_RPT 0xe1
+#define LK_CMD_RPT_TO_DOWN 0xd9
+#define LK_CMD_REQ_ID 0xab
+#define LK_CMD_POWER_UP 0xfd
+#define LK_CMD_TEST_MODE 0xcb
+#define LK_CMD_SET_DEFAULTS 0xd3
+
+/* there are 4 leds, represent them in the low 4 bits of a byte */
+#define LK_PARAM_LED_MASK(ledbmap) (LK_PARAM|(ledbmap))
+
+/* max volume is 0, lowest is 0x7 */
+#define LK_PARAM_VOLUME(v) (LK_PARAM|((v)&0x7))
+
+/* mode set command(s) details */
+#define LK_MODE_DOWN 0x0
+#define LK_MODE_RPT_DOWN 0x2
+#define LK_MODE_DOWN_UP 0x6
+#define LK_CMD_MODE(m,div) (LK_PARAM|(div<<3)|m)
+
+
+/*
+ * Keyboard set_status codes and arguments
+ */
+
+/* Send a command packet to the lk201 */
+typedef struct {
+ unsigned char len; /* how many params */
+ unsigned char command; /* cmd to lk201 */
+ unsigned char params[2]; /* extra params */
+} lk201_cmd_t;
+#define LK201_SEND_CMD _IOW('q', 5, lk201_cmd_t)/* keybd. per. cmd */
+
+/* Control rotation of lk201 leds */
+#define LK201_LED_PATTERN _IOW('q', 119, int) /* cylon, ... */
+# define LED_COUNT 1 /* led counter */
+# define LED_ROTATE 2 /* led rotate */
+# define LED_CYLON 3 /* led cylon mode */
+
+#define LK201_LED_INTERVAL _IOW('q', 120, int) /* refresh interval */
+# define LED_OFF 0 /* no led movement */
+
+/* Map the caps-lock key to act as the control key (skinny-fingers) */
+#define LK201_mapLOCKtoCNTRL _IOW('q', 121, int) /* 1 or 0 */
+
+/* Remap a lk201 keycode to a different (ASCII) translation */
+typedef struct {
+ unsigned char in_keyval;
+ unsigned char shifted;
+ unsigned char out_keyval;
+ unsigned char meta;
+} KeyMap;
+#define LK201_REMAP_KEY _IOW('q', 122, KeyMap) /* 1 or 0 */
diff --git a/chips/mc_clock.c b/chips/mc_clock.c
new file mode 100644
index 00000000..15fa049d
--- /dev/null
+++ b/chips/mc_clock.c
@@ -0,0 +1,516 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: mc_clock.c
+ * Author: Alessandro Forin
+ * Date: 8/90
+ *
+ * Driver for the MC146818 Clock
+ */
+
+#include <mc.h>
+#if NMC > 0
+#include <platforms.h>
+
+#include <mach/std_types.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <chips/busses.h>
+
+#include <sys/time.h>
+#include <kern/time_out.h>
+#include <chips/mc_clock.h>
+
+#ifdef DECSTATION
+#include <mips/mips_cpu.h>
+#include <mips/clock.h>
+#endif /*DECSTATION*/
+
+#ifdef FLAMINGO
+#include <alpha/clock.h>
+#endif /*FLAMINGO*/
+
+#define private static
+#define public
+
+
+/* Architecture-specific defines */
+
+#ifdef DECSTATION
+
+#define MC_DEFAULT_ADDRESS (mc_clock_ram_t *)PHYS_TO_K1SEG(0x1d000000)
+#define MC_DOES_DELAYS 1
+
+/*
+ * Both the Pmax and the 3max implementations of the chip map
+ * bytes of the chip's RAM to 32 bit words (low byte).
+ * For convenience, we redefine here the chip's RAM layout
+ * making padding explicit.
+ */
+
+typedef struct {
+ volatile unsigned char mc_second;
+ char pad0[3];
+ volatile unsigned char mc_alarm_second;
+ char pad1[3];
+ volatile unsigned char mc_minute;
+ char pad2[3];
+ volatile unsigned char mc_alarm_minute;
+ char pad3[3];
+ volatile unsigned char mc_hour;
+ char pad4[3];
+ volatile unsigned char mc_alarm_hour;
+ char pad5[3];
+ volatile unsigned char mc_day_of_week;
+ char pad6[3];
+ volatile unsigned char mc_day_of_month;
+ char pad7[3];
+ volatile unsigned char mc_month;
+ char pad8[3];
+ volatile unsigned char mc_year;
+ char pad9[3];
+ volatile unsigned char mc_register_A;
+ char pad10[3];
+ volatile unsigned char mc_register_B;
+ char pad11[3];
+ volatile unsigned char mc_register_C;
+ char pad12[3];
+ volatile unsigned char mc_register_D;
+ char pad13[3];
+ unsigned char mc_non_volatile_ram[50 * 4]; /* unused */
+} mc_clock_ram_t;
+
+#define MC_CLOCK_PADDED 1
+
+#endif /*DECSTATION*/
+
+
+#ifdef FLAMINGO
+#define MC_DEFAULT_ADDRESS 0L
+
+/* padded, later */
+
+#endif /* FLAMINGO */
+
+
+
+#ifndef MC_CLOCK_PADDED
+typedef mc_clock_t mc_clock_ram_t; /* No padding needed */
+#endif
+
+/*
+ * Functions provided herein
+ */
+int mc_probe( vm_offset_t addr, struct bus_ctlr * );
+private void mc_attach();
+
+int mc_intr();
+
+void mc_open(), mc_close(), mc_write();
+private unsigned int mc_read();
+
+private void mc_wait_for_uip( mc_clock_ram_t *clock );
+
+
+/*
+ * Status
+ */
+boolean_t mc_running = FALSE;
+boolean_t mc_new_century = FALSE; /* "year" info overfloweth */
+
+private int days_per_month[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+private unsigned int mc_read(); /* forward */
+private void mc_wait_for_uip();
+
+/*
+ * Where is the chip's RAM mapped
+ */
+private mc_clock_ram_t *rt_clock = MC_DEFAULT_ADDRESS;
+
+/*
+ * (Auto?)Configuration
+ */
+private vm_offset_t mc_std[NMC] = { 0 };
+private struct bus_device *mc_info[NMC];
+
+struct bus_driver mc_driver =
+ { mc_probe, 0, mc_attach, 0, mc_std, "mc", mc_info, };
+
+
+mc_probe(vm_offset_t addr, struct bus_ctlr *ui)
+{
+ rt_clock = (mc_clock_ram_t *)addr;
+ return 1;
+}
+
+private void
+mc_attach()
+{
+ printf(": MC146818 or like Time-Of-Year chip");
+}
+
+/*
+ * Interrupt routine
+ */
+#if MC_DOES_DELAYS
+
+private int config_step = 3;
+private volatile int had_intr;
+
+mc_intr(spllevel)
+ spl_t spllevel;
+{
+ /*
+ * Interrupt flags are read-to-clear.
+ */
+ if (config_step > 2)
+ return (rt_clock->mc_register_C & MC_REG_C_IRQF);
+ had_intr = (rt_clock->mc_register_C & MC_REG_C_IRQF) ? 1 : 0;
+ if (config_step++ == 0)
+ accurate_config_delay(spllevel);
+ return had_intr;
+}
+#else /* MC_DOES_DELAYS */
+
+mc_intr()
+{
+ return (rt_clock->mc_register_C); /* clear intr */
+}
+
+#endif /* MC_DOES_DELAYS */
+
+/*
+ * Start real-time clock.
+ */
+void
+mc_open()
+{
+ /*
+ * All we should need to do is to enable interrupts, but
+ * since we do not know what OS last ran on this box
+ * we'll reset it all over again. Just kidding..
+ */
+ unsigned unix_seconds_now;
+
+ /*
+ * Check for battery backup power. If we do not have it,
+ * warn the user. Time will be bogus only after power up.
+ */
+ if ((rt_clock->mc_register_D & MC_REG_D_VRT) == 0)
+ printf("WARNING: clock batteries are low\n");
+
+ /*
+ * Read the current time settings, check if the year info
+ * has been screwed up.
+ */
+ unix_seconds_now = mc_read();
+
+ if (unix_seconds_now < (SECYR * (1990 - YRREF)))
+ printf("The prom has clobbered the clock\n");
+
+ time.tv_sec = (long)unix_seconds_now;
+ mc_write();
+
+ mc_running = TRUE;
+}
+
+void
+mc_close()
+{
+ /*
+ * Disable interrupts, but keep the chip running.
+ * Note we are called at splhigh and an interrupt
+ * might be pending already.
+ */
+
+ mc_intr(0);
+ rt_clock->mc_register_B &= ~(MC_REG_B_UIE|MC_REG_B_AIE|MC_REG_B_PIE);
+ mc_running = FALSE;
+#if MC_DOES_DELAYS
+ config_step = 0;
+#endif
+}
+
+
+/*
+ * Set time-of-day. Must be called at splhigh()
+ */
+void
+mc_write()
+{
+ register mc_clock_ram_t *clock = rt_clock;
+ register unsigned years, months, days, hours, minutes, seconds;
+ register unsigned unix_seconds = time.tv_sec;
+ int frequence_selector, temp;
+ int bogus_hz = 0;
+
+ /*
+ * Convert U*x time into absolute time
+ */
+
+ years = YRREF;
+ while (1) {
+ seconds = SECYR;
+ if (LEAPYEAR(years))
+ seconds += SECDAY;
+ if (unix_seconds < seconds)
+ break;
+ unix_seconds -= seconds;
+ years++;
+ }
+
+ months = 0;
+ while (1) {
+ seconds = days_per_month[months++] * SECDAY;
+ if (months == 2 /* February */ && LEAPYEAR(years))
+ seconds += SECDAY;
+ if (unix_seconds < seconds)
+ break;
+ unix_seconds -= seconds;
+ }
+
+ days = unix_seconds / SECDAY;
+ unix_seconds -= SECDAY * days++;
+
+ hours = unix_seconds / SECHOUR;
+ unix_seconds -= SECHOUR * hours;
+
+ minutes = unix_seconds / SECMIN;
+ unix_seconds -= SECMIN * minutes;
+
+ seconds = unix_seconds;
+
+ /*
+ * Trim years into 0-99 range.
+ */
+ if ((years -= 1900) > 99) {
+ years -= 100;
+ mc_new_century = TRUE;
+ }
+
+ /*
+ * Check for "hot dates"
+ */
+ if (days >= 28 && days <= 30 &&
+ hours == 23 && minutes == 59 &&
+ seconds >= 58)
+ seconds = 57;
+
+ /*
+ * Select the interrupt frequency based on system params
+ */
+ switch (hz) {
+ case 1024:
+ frequence_selector = MC_BASE_32_KHz | MC_RATE_1024_Hz;
+ break;
+ case 512:
+ frequence_selector = MC_BASE_32_KHz | MC_RATE_512_Hz;
+ break;
+ case 256:
+ frequence_selector = MC_BASE_32_KHz | MC_RATE_256_Hz;
+ break;
+ case 128:
+ frequence_selector = MC_BASE_32_KHz | MC_RATE_128_Hz;
+ break;
+ case 64:
+default_frequence:
+ frequence_selector = MC_BASE_32_KHz | MC_RATE_64_Hz;
+ break;
+ default:
+ bogus_hz = hz;
+ hz = 64;
+ tick = 1000000 / 64;
+ goto default_frequence;
+ }
+
+ /*
+ * Stop updates while we fix it
+ */
+ mc_wait_for_uip(clock);
+ clock->mc_register_B = MC_REG_B_STOP;
+ wbflush();
+
+ /*
+ * Ack any pending interrupts
+ */
+ temp = clock->mc_register_C;
+
+ /*
+ * Reset the frequency divider, in case we are changing it.
+ */
+ clock->mc_register_A = MC_BASE_RESET;
+
+ /*
+ * Now update the time
+ */
+ clock->mc_second = seconds;
+ clock->mc_minute = minutes;
+ clock->mc_hour = hours;
+ clock->mc_day_of_month = days;
+ clock->mc_month = months;
+ clock->mc_year = years;
+
+ /*
+ * Spec says the VRT bit can be validated, but does not say how. I
+ * assume it is via reading the register.
+ */
+ temp = clock->mc_register_D;
+
+ /*
+ * Reconfigure the chip and get it started again
+ */
+ clock->mc_register_A = frequence_selector;
+ clock->mc_register_B = MC_REG_B_24HM | MC_REG_B_DM | MC_REG_B_PIE;
+
+ /*
+ * Print warnings, if we have to
+ */
+ if (bogus_hz != 0)
+ printf("Unacceptable value (%d Hz) for hz, reset to %d Hz\n",
+ bogus_hz, hz);
+}
+
+
+/*
+ * Internal functions
+ */
+
+private void
+mc_wait_for_uip(clock)
+ mc_clock_ram_t *clock;
+{
+ while (clock->mc_register_A & MC_REG_A_UIP)
+ delay(MC_UPD_MINIMUM >> 2);
+}
+
+private unsigned int
+mc_read()
+{
+ /*
+ * Note we only do this at boot time
+ */
+ register unsigned years, months, days, hours, minutes, seconds;
+ register mc_clock_ram_t *clock = rt_clock;;
+
+ /*
+ * If the chip is updating, wait
+ */
+ mc_wait_for_uip(clock);
+
+ years = clock->mc_year;
+ months = clock->mc_month;
+ days = clock->mc_day_of_month;
+ hours = clock->mc_hour;
+ minutes = clock->mc_minute;
+ seconds = clock->mc_second;
+
+ /*
+ * Convert to Unix time
+ */
+ seconds += minutes * SECMIN;
+ seconds += hours * SECHOUR;
+ seconds += (days - 1) * SECDAY;
+ if (months > 2 /* February */ && LEAPYEAR(years))
+ seconds += SECDAY;
+ while (months > 1)
+ seconds += days_per_month[--months - 1];
+
+ /*
+ * Note that in ten years from today (Aug,1990) the new century will
+ * cause the trouble that mc_new_century attempts to avoid.
+ */
+ if (mc_new_century)
+ years += 100;
+ years += 1900; /* chip base year in YRREF's century */
+
+ for (--years; years >= YRREF; years--) {
+ seconds += SECYR;
+ if (LEAPYEAR(years))
+ seconds += SECDAY;
+ }
+
+ return seconds;
+}
+
+#ifdef MC_DOES_DELAYS
+
+/*
+ * Timed delays
+ */
+extern unsigned int cpu_speed;
+
+void
+config_delay(speed)
+{
+ /*
+ * This is just an initial estimate, later on with the clock
+ * running we'll tune it more accurately.
+ */
+ cpu_speed = speed;
+}
+
+accurate_config_delay(spllevel)
+ spl_t spllevel;
+{
+ register unsigned int i;
+ register spl_t s;
+ int inner_loop_count;
+
+#ifdef mips
+ /* find "spllevel - 1" */
+ s = spllevel | ((spllevel >> 1) & SR_INT_MASK);
+ splx(s);
+#else
+#endif
+
+ /* wait till we have an interrupt pending */
+ had_intr = 0;
+ while (!had_intr)
+ continue;
+
+ had_intr = 0;
+ i = delay_timing_function(1, &had_intr, &inner_loop_count);
+
+ splx(spllevel);
+
+ i *= hz;
+ cpu_speed = i / (inner_loop_count * 1000000);
+
+ /* roundup clock speed */
+ i /= 100000;
+ if ((i % 10) >= 5)
+ i += 5;
+ printf("Estimating CPU clock at %d Mhz\n", i / 10);
+ if (isa_pmax() && cpu_speed != MC_DELAY_PMAX) {
+ printf("%s\n", "This machine looks like a DEC 2100");
+ machine_slot[cpu_number()].cpu_subtype = CPU_SUBTYPE_MIPS_R2000;
+ }
+}
+#endif /* MC_DOES_DELAYS */
+
+#endif NMC > 0
diff --git a/chips/mc_clock.h b/chips/mc_clock.h
new file mode 100644
index 00000000..0cd59579
--- /dev/null
+++ b/chips/mc_clock.h
@@ -0,0 +1,147 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: mc_clock.h
+ * Author: Alessandro Forin
+ * Date: 8/90
+ *
+ * Definitions for the MC146818 Clock Driver
+ */
+
+/*
+ * Functions this module implements
+ */
+
+extern void resettodr(/* */); /* reset time-of-day register */
+extern void startrtclock(/* */); /* start real-time clock */
+extern void stopclocks(/* */); /* stop real-time clock */
+extern boolean_t ackrtclock(/* */); /* acknowledge interrupt, if any */
+extern boolean_t todr_running; /* status */
+
+extern boolean_t mc_new_century; /* patch this after year 2000 (honest!) */
+
+extern void delay(/* int usecs */); /* waste that many microseconds */
+extern void config_delay(/* int speed */); /* for delay() */
+#define MC_DELAY_PMAX 8
+#define MC_DELAY_3MAX 12
+
+extern void set_clock_addr(/* vm_offset_t addr */); /* RAM location */
+
+/*
+ * Real-Time Clock plus RAM device (MC146818)
+ */
+
+/*
+ * RAM Memory Map (as seen by the chip)
+ */
+typedef struct {
+ volatile unsigned char mc_second;
+ volatile unsigned char mc_alarm_second;
+ volatile unsigned char mc_minute;
+ volatile unsigned char mc_alarm_minute;
+ volatile unsigned char mc_hour;
+ volatile unsigned char mc_alarm_hour;
+ volatile unsigned char mc_day_of_week;
+ volatile unsigned char mc_day_of_month;
+ volatile unsigned char mc_month;
+ volatile unsigned char mc_year;
+ volatile unsigned char mc_register_A;
+ volatile unsigned char mc_register_B;
+ volatile unsigned char mc_register_C;
+ volatile unsigned char mc_register_D;
+ unsigned char mc_non_volatile_ram[50];
+} mc_clock_t;
+
+/*
+ * Register A defines (read/write)
+ */
+
+#define MC_REG_A_RS 0x0f /* Interrupt rate (and SQwave) select */
+#define MC_REG_A_DV 0x70 /* Divider select */
+#define MC_REG_A_UIP 0x80 /* Update In Progress (read-only bit) */
+
+/* Time base configuration */
+#define MC_BASE_4_MHz 0x00
+#define MC_BASE_1_MHz 0x10
+#define MC_BASE_32_KHz 0x20
+#define MC_BASE_NONE 0x60 /* actually, both of these reset */
+#define MC_BASE_RESET 0x70
+
+/* Interrupt rate table */
+#define MC_RATE_NONE 0x0 /* disabled */
+#define MC_RATE_1 0x1 /* 256Hz if MC_BASE_32_KHz, else 32768Hz */
+#define MC_RATE_2 0x2 /* 128Hz if MC_BASE_32_KHz, else 16384Hz */
+#define MC_RATE_8192_Hz 0x3 /* Tpi: 122.070 usecs */
+#define MC_RATE_4096_Hz 0x4 /* Tpi: 244.141 usecs */
+#define MC_RATE_2048_Hz 0x5 /* Tpi: 488.281 usecs */
+#define MC_RATE_1024_Hz 0x6 /* Tpi: 976.562 usecs */
+#define MC_RATE_512_Hz 0x7 /* Tpi: 1.953125 ms */
+#define MC_RATE_256_Hz 0x8 /* Tpi: 3.90625 ms */
+#define MC_RATE_128_Hz 0x9 /* Tpi: 7.8125 ms */
+#define MC_RATE_64_Hz 0xa /* Tpi: 15.625 ms */
+#define MC_RATE_32_Hz 0xb /* Tpi: 31.25 ms */
+#define MC_RATE_16_Hz 0xc /* Tpi: 62.5 ms */
+#define MC_RATE_8_Hz 0xd /* Tpi: 125 ms */
+#define MC_RATE_4_Hz 0xe /* Tpi: 250 ms */
+#define MC_RATE_2_Hz 0xf /* Tpi: 500 ms */
+
+/* Update cycle time */
+#define MC_UPD_4_MHz 248 /* usecs */
+#define MC_UPD_1_MHz 248 /* usecs */
+#define MC_UPD_32_KHz 1984 /* usecs */
+#define MC_UPD_MINIMUM 244 /* usecs, guaranteed if UIP=0 */
+
+/*
+ * Register B defines (read/write)
+ */
+
+#define MC_REG_B_DSE 0x01 /* Daylight Savings Enable */
+#define MC_REG_B_24HM 0x02 /* 24/12 Hour Mode */
+#define MC_REG_B_DM 0x04 /* Data Mode, 1=Binary 0=BCD */
+#define MC_REG_B_SQWE 0x08 /* Sqare Wave Enable */
+#define MC_REG_B_UIE 0x10 /* Update-ended Interrupt Enable */
+#define MC_REG_B_AIE 0x20 /* Alarm Interrupt Enable */
+#define MC_REG_B_PIE 0x40 /* Periodic Interrupt Enable */
+#define MC_REG_B_SET 0x80 /* Set NVram info, e.g. update time or ..*/
+#define MC_REG_B_STOP MC_REG_B_SET /* Stop updating the timing info */
+
+/*
+ * Register C defines (read-only)
+ */
+
+#define MC_REG_C_ZEROES 0x0f /* Reads as zero bits */
+#define MC_REG_C_UF 0x10 /* Update-ended interrupt flag */
+#define MC_REG_C_AF 0x20 /* Alarm interrupt flag */
+#define MC_REG_C_PF 0x40 /* Periodic interrupt flag */
+#define MC_REG_C_IRQF 0x80 /* Interrupt request flag */
+
+/*
+ * Register D defines (read-only)
+ */
+
+#define MC_REG_D_ZEROES 0x7f /* Reads as zero bits */
+#define MC_REG_D_VRT 0x80 /* Valid RAM and Time */
+
diff --git a/chips/mouse.c b/chips/mouse.c
new file mode 100644
index 00000000..85a27447
--- /dev/null
+++ b/chips/mouse.c
@@ -0,0 +1,321 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992-1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: mouse.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Driver code for Digital's mouse AND tablet
+ */
+
+/*
+ * XXX This should be rewritten to support other
+ * XXX sorts of mices and tablets. But for now
+ * XXX I have none to play with. Sorry about that.
+ */
+
+#include <lk.h> /* one mouse per lk201 */
+#if NLK > 0
+
+#include <mach/std_types.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <sys/time.h>
+#include <kern/time_out.h>
+
+#include <chips/serial_defs.h>
+#include <chips/screen_defs.h>
+
+#define MOUSE_INCREMENTAL 0x52 /* R */
+#define MOUSE_PROMPTED 0x44 /* D */
+#define MOUSE_REQ_POSITION 0x50 /* P */
+#define MOUSE_SELFTEST 0x54 /* T */
+#define MOUSE_RESERVED_FUNC 0x5a /* Z, param byte follows */
+
+#define TABLET_SAMPLE_55 0x4b /* K */ /* in reps/sec */
+#define TABLET_SAMPLE_72 0x4c /* L */
+#define TABLET_SAMPLE_120 0x4d /* M */
+#define TABLET_9600 0x42 /* B */
+
+#define TYPE_MOUSE 0x2
+#define TYPE_TABLET 0x4
+
+#define START_REPORT 0x80
+
+typedef union {
+ struct {
+ unsigned char r : 1, m : 1, l : 1, sy : 1, sx : 1;
+ unsigned char xpos;
+ unsigned char ypos;
+ } ms;
+ struct {
+ unsigned char pr : 1, buttons : 4;
+ unsigned char xlo, xhi;
+ unsigned char ylo, yhi;
+ } tb;
+ unsigned char raw[1];
+} mouse_report_t;
+
+
+/*
+ * Mouse state
+ */
+struct mouse_softc {
+ user_info_t *up;
+ mouse_report_t report;
+ unsigned char rep_bytes;
+ unsigned char rep_ptr;
+ unsigned char prev_buttons;
+ unsigned char flags;
+#define MS_TABLET 0x1
+#define MS_MOVING 0x2
+ char screen_unit;
+ char sl_unit;
+} mouse_softc_data[NLK];
+
+typedef struct mouse_softc *mouse_softc_t;
+
+mouse_softc_t mouse_softc[NLK];
+
+
+mouse_notify_mapped(
+ int unit,
+ int screen_unit,
+ user_info_t *up)
+{
+ mouse_softc_t ms = &mouse_softc_data[unit];
+
+ ms->up = up;
+ ms->screen_unit = screen_unit;
+}
+
+/*
+ * Autoconfiguration
+ */
+mouse_probe(
+ int unit)
+{
+ mouse_softc[unit] = &mouse_softc_data[unit];
+}
+
+mouse_attach(
+ int unit,
+ int sl_unit)
+{
+ int messg[4];
+ spl_t s;
+ mouse_softc_t ms;
+
+ ms = mouse_softc[unit];
+ ms->sl_unit = sl_unit;
+
+ s = spltty();
+ (*console_putc)(sl_unit, SCREEN_LINE_POINTER, MOUSE_SELFTEST);
+ delay(1);
+ messg[0] = (*console_getc)(sl_unit, SCREEN_LINE_POINTER, TRUE, TRUE);
+ messg[1] = (*console_getc)(sl_unit, SCREEN_LINE_POINTER, TRUE, TRUE);
+ messg[2] = (*console_getc)(sl_unit, SCREEN_LINE_POINTER, TRUE, TRUE);
+ messg[3] = (*console_getc)(sl_unit, SCREEN_LINE_POINTER, TRUE, TRUE);
+
+ delay(100000); /* spec says less than 500 msecs */
+ (*console_putc)(sl_unit, SCREEN_LINE_POINTER, MOUSE_INCREMENTAL);
+ splx(s);
+
+ ms->rep_bytes = 3;/* mouse */
+ if (messg[2] | messg[3]) {
+ printf(" bad pointer [%x %x %x %x] ",
+ messg[0], messg[1], messg[2], messg[3]);
+ if (messg[2] >= 0x20) printf("fatal ");
+ if (messg[2] == 0x3e) printf("RAM/ROM");
+ if (messg[2] == 0x3d) printf("button(s) %x", messg[3] & 0x1f);
+ } else {
+ int rev = messg[0] & 0xf;
+ int loc = (messg[1] & 0xf0) >> 4;
+ int tag = (messg[1] & 0xf);
+ printf("( %s rev. %x.%x )",
+ (tag == TYPE_MOUSE) ? "mouse" : "tablet",
+ rev, loc);
+ if (tag == TYPE_TABLET) {
+ ms->flags = MS_TABLET;
+ ms->rep_bytes = 5;
+ }
+ }
+}
+
+/*
+ * Process a character from the mouse
+ */
+mouse_input(
+ int unit,
+ register unsigned short data)
+{
+ mouse_softc_t ms = mouse_softc[unit];
+ register char flg, but;
+
+ data &= 0xff;
+
+ /* sanity: might miss a byte sometimes */
+ if (data & START_REPORT)
+ ms->rep_ptr = 0;
+
+ /* add byte to report */
+ ms->report.raw[ms->rep_ptr++] = data;
+
+ /* does this mean the mouse is moving */
+ if (data && ((data & START_REPORT) == 0))
+ ms->flags |= MS_MOVING;
+
+ /* Report complete ? */
+ if (ms->rep_ptr != ms->rep_bytes)
+ return;
+ ms->rep_ptr = 0;
+
+ ssaver_bump(ms->screen_unit);
+
+ /* check for mouse moved */
+ flg = ms->flags;
+ if (flg & MS_MOVING) {
+ ms->flags = flg & ~MS_MOVING;
+ mouse_motion_event(ms, flg);
+ }
+
+ /* check for button pressed */
+ if (but = ms->prev_buttons ^ ms->report.raw[0]) {
+ mouse_button_event(ms, flg, but);
+ ms->prev_buttons = ms->report.raw[0];
+ }
+}
+
+/*
+ * The mouse/puck moved.
+ * Find how much and post an event
+ */
+mouse_motion_event(
+ mouse_softc_t ms,
+ int flg)
+{
+ register int x, y;
+
+ if (flg & MS_TABLET) {
+
+ flg = DEV_TABLET;
+
+ x = (ms->report.tb.xhi << 8) | ms->report.tb.xlo;
+ y = (ms->report.tb.yhi << 8) | ms->report.tb.ylo;
+
+ } else {
+
+ flg = DEV_MOUSE;
+
+ x = ms->report.ms.xpos;
+ if (!ms->report.ms.sx) /* ??? */
+ x = -x;
+
+ y = ms->report.ms.ypos;
+ if (ms->report.ms.sy)
+ y = -y;
+
+ }
+
+ screen_motion_event(ms->screen_unit, flg, x, y);
+}
+
+/*
+ * A mouse/puck button was pressed/released.
+ * Find which one and post an event
+ */
+mouse_button_event(
+ mouse_softc_t ms,
+ int flg,
+ int bmask)
+{
+ register unsigned int buttons, i;
+ int key, type;
+
+ buttons = ms->report.raw[0];
+ if (flg & MS_TABLET) {
+ /* check each one of the four buttons */
+ for (i = 0; i < 4; i += 1) {
+ if ((bmask & (2<<i)) == 0)
+ continue;/* did not change */
+ type = (buttons & (2<<i)) ? EVT_BUTTON_DOWN : EVT_BUTTON_UP;
+ key = i;
+
+ screen_keypress_event( ms->screen_unit,
+ DEV_TABLET, key, type);
+ }
+ } else {
+ ms->up->mouse_buttons = buttons & 0x7;
+ /* check each one of the three buttons */
+ for (i = 0; i < 3; i += 1) {
+ if ((bmask & (1<<i)) == 0)
+ continue;/* did not change */
+ type = (buttons & (1<<i)) ? EVT_BUTTON_DOWN : EVT_BUTTON_UP;
+
+ if (i & 1)
+ key = KEY_MIDDLE_BUTTON;
+ else if ((i & 2) == 0)
+ key = KEY_RIGHT_BUTTON;
+ else
+ key = KEY_LEFT_BUTTON;
+
+ screen_keypress_event( ms->screen_unit,
+ DEV_MOUSE, key, type);
+ }
+ }
+}
+
+/*
+ * Generate escape sequences for position reporting
+ * These are the same as xterm's.
+ * Prefix:
+ * ESC [ M button down
+ * ESC [ N button up
+ * Body:
+ * BUTTON COL ROW
+ * Button:
+ * 0 <-> left, 1 <-> middle, 2 <-> right
+ * All body values are offset by the ascii SPACE character
+ */
+#define ESC '\033'
+#define SPACE ' '
+
+mouse_report_position(
+ int unit,
+ int col,
+ int row,
+ int key,
+ int type)
+{
+ cons_input(SCREEN_LINE_KEYBOARD, ESC, 0);
+ cons_input(SCREEN_LINE_KEYBOARD, '[', 0);
+ cons_input(SCREEN_LINE_KEYBOARD, (type==EVT_BUTTON_DOWN) ? 'M':'N', 0);
+
+ cons_input(SCREEN_LINE_KEYBOARD, (key - 1) + SPACE, 0);/* quick remapping */
+ cons_input(SCREEN_LINE_KEYBOARD, SPACE + col + 2, 0);
+ cons_input(SCREEN_LINE_KEYBOARD, SPACE + row + 1, 0);
+}
+
+#endif NLK > 0
diff --git a/chips/nc.c b/chips/nc.c
new file mode 100644
index 00000000..adce0ae0
--- /dev/null
+++ b/chips/nc.c
@@ -0,0 +1,851 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** NETWORK INTERFACE IMPLEMENTATION CORE ***/
+
+#ifndef STUB
+#include <chips/nc.h>
+#else
+#include "nc.h"
+#endif
+
+/*** Types and data structures ***/
+
+#if PRODUCTION
+#define MAX_HASH 701
+#define MAX_HOST 4000
+#else
+#define MAX_HASH 7
+#define MAX_HOST 4
+#endif
+
+nw_dev_entry_s nc_failure_entry_table = {nc_fail, nc_fail,
+ nc_null, nc_null,
+ nc_null_poll, nc_null_send, nc_null_rpc,
+ nc_null_signal, nc_open_fail, nc_accept_fail,
+ nc_close_fail, nc_open_fail, nc_open_fail};
+
+nw_dev_entry_s nc_local_entry_table = {nc_succeed, nc_succeed,
+ nc_null, nc_null,
+ nc_null_poll, nc_local_send, nc_local_rpc,
+ nc_null_signal, nc_open_fail, nc_accept_fail,
+ nc_close_fail, nc_open_fail, nc_open_fail};
+
+
+typedef struct {
+ nw_address_s address;
+ int name_next:16;
+ int ip_next:16;
+ int nw_next:16;
+ nw_ep line:16;
+} nw_alist_s, *nw_alist_t;
+
+
+boolean_t nc_initialized = FALSE;
+nw_tx_header_s nw_tx[MAX_EP/2];
+nw_tx_header_t nw_free_tx_header;
+nw_rx_header_s nw_rx[2*MAX_EP];
+nw_rx_header_t nw_free_rx_header;
+nw_plist_s nw_peer[MAX_EP];
+nw_plist_t nw_free_peer;
+
+nw_devcb devct[MAX_DEV];
+
+nw_ecb ect[MAX_EP];
+
+int nw_free_ep_first, nw_free_ep_last;
+int nw_free_line_first, nw_free_line_last;
+
+nw_alist_s nw_address[MAX_HOST];
+int nw_free_address;
+
+int nw_name[MAX_HASH];
+int nw_ip[MAX_HASH];
+int nw_nw[MAX_HASH];
+
+int nw_fast_req;
+
+/*** System-independent functions ***/
+
+void nc_initialize() {
+ int ep, last_ep;
+
+ if (!nc_initialized) {
+ last_ep = sizeof(nw_tx)/sizeof(nw_tx_header_s) - 1;
+ for (ep = 0; ep < last_ep; ep++)
+ nw_tx[ep].next = &nw_tx[ep+1];
+ nw_tx[last_ep].next = NULL;
+ nw_free_tx_header = &nw_tx[0];
+ last_ep = sizeof(nw_rx)/sizeof(nw_rx_header_s) - 1;
+ for (ep = 0; ep < last_ep; ep++)
+ nw_rx[ep].next = &nw_rx[ep+1];
+ nw_rx[last_ep].next = NULL;
+ nw_free_rx_header = &nw_rx[0];
+ last_ep = sizeof(nw_peer)/sizeof(nw_plist_s) - 1;
+ for (ep = 0; ep < last_ep; ep++)
+ nw_peer[ep].next = &nw_peer[ep+1];
+ nw_peer[last_ep].next = NULL;
+ nw_free_peer = &nw_peer[0];
+ for (ep = 0; ep < MAX_DEV; ep++) {
+ devct[ep].status = NW_FAILURE;
+ devct[ep].type = NW_CONNECTIONLESS;
+ devct[ep].addr = NULL;
+ devct[ep].local_addr_1 = 0;
+ devct[ep].local_addr_2 = 0;
+ devct[ep].entry = &nc_failure_entry_table;
+ devct[ep].fast_req = 0;
+ }
+ devct[NW_NULL].status = NW_SUCCESS;
+ devct[NW_NULL].entry = &nc_local_entry_table;
+ last_ep = sizeof(ect)/sizeof(nw_ecb);
+ for (ep = 0; ep < last_ep; ep++) {
+ ect[ep].state = NW_INEXISTENT;
+ ect[ep].id = ep;
+ ect[ep].seqno = 0;
+ ect[ep].previous = ep - 1;
+ ect[ep].next = ep + 1;
+ }
+ ect[0].next = ect[0].previous = 0;
+ ect[last_ep-1].next = 0;
+ nw_free_ep_first = 1;
+ nw_free_ep_last = last_ep - 1;
+ nw_free_line_first = nw_free_line_last = 0;
+ for (ep = 0; ep < MAX_HOST; ep++) {
+ nw_address[ep].nw_next = ep + 1;
+ }
+ nw_address[MAX_HOST - 1].nw_next = -1;
+ nw_free_address = 0;
+ for (ep = 0; ep < MAX_HASH; ep++) {
+ nw_name[ep] = -1;
+ nw_ip[ep] = -1;
+ nw_nw[ep] = -1;
+ }
+ nw_fast_req = 0;
+ h_initialize();
+ nc_initialized = TRUE;
+ }
+}
+
+nw_tx_header_t nc_tx_header_allocate() {
+ nw_tx_header_t header;
+
+ header = nw_free_tx_header;
+ if (header != NULL)
+ nw_free_tx_header = header->next;
+ return header;
+}
+
+void nc_tx_header_deallocate(nw_tx_header_t header) {
+ nw_tx_header_t first_header;
+
+ first_header = header;
+ while (header->next != NULL)
+ header = header->next;
+ header->next = nw_free_tx_header;
+ nw_free_tx_header = first_header;
+}
+
+nw_rx_header_t nc_rx_header_allocate() {
+ nw_rx_header_t header;
+
+ header = nw_free_rx_header;
+ if (header != NULL)
+ nw_free_rx_header = header->next;
+ return header;
+}
+
+void nc_rx_header_deallocate(nw_rx_header_t header) {
+
+ header->next = nw_free_rx_header;
+ nw_free_rx_header = header;
+}
+
+nw_plist_t nc_peer_allocate() {
+ nw_plist_t peer;
+
+ peer = nw_free_peer;
+ if (peer != NULL)
+ nw_free_peer = peer->next;
+ return peer;
+}
+
+void nc_peer_deallocate(nw_plist_t peer) {
+ nw_plist_t first_peer;
+
+ first_peer = peer;
+ while (peer->next != NULL)
+ peer = peer->next;
+ peer->next = nw_free_peer;
+ nw_free_peer = first_peer;
+}
+
+
+nw_result nc_device_register(u_int dev, nw_dev_type type, char *dev_addr,
+ nw_dev_entry_t dev_entry_table) {
+ nw_result rc;
+
+ if (dev >= MAX_DEV) {
+ rc = NW_FAILURE;
+ } else {
+ devct[dev].status = NW_SUCCESS;
+ devct[dev].type = type;
+ devct[dev].addr = dev_addr;
+ devct[dev].entry = dev_entry_table;
+ devct[dev].fast_req = 0;
+ rc = NW_SUCCESS;
+ }
+ return rc;
+}
+
+nw_result nc_device_unregister(u_int dev, nw_result status) {
+ nw_result rc;
+
+ if (dev >= MAX_DEV) {
+ rc = NW_FAILURE;
+ } else {
+ devct[dev].status = status;
+ devct[dev].addr = NULL;
+ devct[dev].entry = &nc_failure_entry_table;
+ devct[dev].fast_req = 0;
+ rc = NW_SUCCESS;
+ }
+ return rc;
+}
+
+void nc_slow_sweep() {
+ int dev;
+
+ for (dev = 0; dev < MAX_DEV; dev++) {
+ if (devct[dev].status == NW_SUCCESS) {
+ (*(devct[dev].entry->slow_sweep)) (dev);
+ }
+ }
+}
+
+void nc_fast_timer_set(int dev) {
+
+ devct[dev].fast_req++;
+ if (nw_fast_req++ == 0)
+ h_fast_timer_set();
+}
+
+void nc_fast_timer_reset(int dev) {
+
+ devct[dev].fast_req--;
+ if (nw_fast_req-- == 0)
+ h_fast_timer_reset();
+}
+
+
+void nc_fast_sweep() {
+ int dev;
+
+ for (dev = 0; dev < MAX_DEV; dev++) {
+ if (devct[dev].status == NW_SUCCESS &&
+ devct[dev].fast_req > 0) {
+ devct[dev].fast_req = 0;
+ (*(devct[dev].entry->fast_sweep)) (dev);
+ }
+ }
+}
+
+int nc_hash_name(char *cp) {
+ int h;
+ char ch;
+ char *cp_end;
+
+ cp_end = cp + 19;
+ *cp_end = '\0';
+ h = 0;
+ ch = *cp++;
+ while (ch != '\0') {
+ h = (h << 7) + ch;
+ ch = *cp++;
+ if (ch != '\0') {
+ h = (h << 7) + ch;
+ ch = *cp++;
+ if (ch != '\0') {
+ h = (h << 7) + ch;
+ ch = *cp++;
+ }
+ }
+ h %= MAX_HASH;
+ }
+ return h;
+}
+
+
+nw_result nc_update(nw_update_type up_type, int *up_info) {
+ nw_result rc;
+ nw_alist_t ad;
+ int h, slot, previous_slot, found_slot;
+ nw_address_1 n1;
+ nw_address_2 n2;
+
+ if (up_type == NW_HOST_ADDRESS_REGISTER) {
+ if (nw_free_address == -1) {
+ rc = NW_NO_RESOURCES;
+ } else {
+ slot = nw_free_address;
+ ad = &nw_address[slot];
+ nw_free_address = ad->nw_next;
+ ad->address = *((nw_address_t) up_info);
+ h = nc_hash_name(ad->address.name);
+ ad->name_next = nw_name[h];
+ nw_name[h] = slot;
+ h = ad->address.ip_addr % MAX_HASH;
+ ad->ip_next = nw_ip[h];
+ nw_ip[h] = slot;
+ h = (ad->address.nw_addr_1 % MAX_HASH + ad->address.nw_addr_2)
+ % MAX_HASH;
+ ad->nw_next = nw_nw[h];
+ nw_nw[h] = slot;
+ ad->line = 0;
+ rc = NW_SUCCESS;
+ }
+ } else if (up_type == NW_HOST_ADDRESS_UNREGISTER) {
+ n1 = ((nw_address_t) up_info)->nw_addr_1;
+ n2 = ((nw_address_t) up_info)->nw_addr_2;
+ h = (n1 % MAX_HASH + n2) % MAX_HASH;
+ slot = nw_nw[h];
+ previous_slot = -1;
+ ad = &nw_address[slot];
+ while (slot != -1 && (ad->address.nw_addr_1 != n1 ||
+ ad->address.nw_addr_2 != n2)) {
+ previous_slot = slot;
+ slot = ad->nw_next;
+ ad = &nw_address[slot];
+ }
+ if (slot == -1) {
+ rc = NW_BAD_ADDRESS;
+ } else {
+ if (previous_slot == -1)
+ nw_nw[h] = ad->nw_next;
+ else
+ nw_address[previous_slot].nw_next = ad->nw_next;
+ ad->nw_next = nw_free_address;
+ nw_free_address = slot;
+ found_slot = slot;
+ if (ad->address.ip_addr != 0) {
+ h = ad->address.ip_addr % MAX_HASH;
+ slot = nw_ip[h];
+ previous_slot = -1;
+ while (slot != -1 && slot != found_slot) {
+ previous_slot = slot;
+ slot = nw_address[slot].ip_next;
+ }
+ if (slot == found_slot) {
+ if (previous_slot == -1)
+ nw_ip[h] = ad->ip_next;
+ else
+ nw_address[previous_slot].ip_next = ad->ip_next;
+ }
+ }
+ if (ad->address.name[0] != '\0') {
+ h = nc_hash_name(ad->address.name);
+ slot = nw_name[h];
+ previous_slot = -1;
+ while (slot != -1 && slot != found_slot) {
+ previous_slot = slot;
+ slot = nw_address[slot].name_next;
+ }
+ if (slot == found_slot) {
+ if (previous_slot == -1)
+ nw_name[h] = ad->name_next;
+ else
+ nw_address[previous_slot].name_next = ad->name_next;
+ }
+ }
+ rc = NW_SUCCESS;
+ }
+ } else {
+ rc = NW_INVALID_ARGUMENT;
+ }
+ return rc;
+}
+
+nw_result nc_lookup(nw_lookup_type lt, int *look_info) {
+ nw_result rc;
+ nw_address_t addr;
+ nw_alist_t ad;
+ int h, slot;
+ ip_address ip;
+ nw_address_1 n1;
+ nw_address_2 n2;
+
+ if (lt == NW_HOST_ADDRESS_LOOKUP) {
+ addr = (nw_address_t) look_info;
+ if (addr->ip_addr != 0) {
+ ip = addr->ip_addr;
+ h = ip % MAX_HASH;
+ slot = nw_ip[h];
+ ad = &nw_address[slot];
+ while (slot != -1 && ad->address.ip_addr != ip) {
+ slot = ad->ip_next;
+ ad = &nw_address[slot];
+ }
+ if (slot != -1) {
+ strcpy(addr->name, ad->address.name);
+ addr->nw_addr_1 = ad->address.nw_addr_1;
+ addr->nw_addr_2 = ad->address.nw_addr_2;
+ return NW_SUCCESS;
+ }
+ }
+ if (addr->name[0] != '\0') {
+ h = nc_hash_name(addr->name);
+ slot = nw_name[h];
+ ad = &nw_address[slot];
+ while (slot != -1 && strcmp(ad->address.name, addr->name) != 0) {
+ slot = ad->name_next;
+ ad = &nw_address[slot];
+ }
+ if (slot != -1) {
+ addr->ip_addr = ad->address.ip_addr;
+ addr->nw_addr_1 = ad->address.nw_addr_1;
+ addr->nw_addr_2 = ad->address.nw_addr_2;
+ return NW_SUCCESS;
+ }
+ }
+ if (addr->nw_addr_1 != 0 || addr->nw_addr_2 != 0) {
+ n1 = addr->nw_addr_1;
+ n2 = addr->nw_addr_2;
+ h = (n1 % MAX_HASH + n2) % MAX_HASH;
+ slot = nw_nw[h];
+ ad = &nw_address[slot];
+ while (slot != -1 && (ad->address.nw_addr_1 != n1 ||
+ ad->address.nw_addr_2 != n2)) {
+ slot = ad->nw_next;
+ ad = &nw_address[slot];
+ }
+ if (slot != -1) {
+ strcpy(addr->name, ad->address.name);
+ addr->ip_addr = ad->address.ip_addr;
+ return NW_SUCCESS;
+ }
+ }
+ rc = NW_BAD_ADDRESS;
+ } else {
+ rc = NW_INVALID_ARGUMENT;
+ }
+ return rc;
+}
+
+nw_result nc_line_update(nw_peer_t peer, nw_ep line) {
+ nw_result rc;
+ nw_alist_t ad;
+ int h, slot;
+ nw_address_1 n1;
+ nw_address_2 n2;
+
+ n1 = peer->rem_addr_1;
+ n2 = peer->rem_addr_2;
+ h = (n1 % MAX_HASH + n2) % MAX_HASH;
+ slot = nw_nw[h];
+ ad = &nw_address[slot];
+ while (slot != -1 && (ad->address.nw_addr_1 != n1 ||
+ ad->address.nw_addr_2 != n2)) {
+ slot = ad->nw_next;
+ ad = &nw_address[slot];
+ }
+ if (slot == -1) {
+ rc = NW_FAILURE;
+ } else {
+ ad->line = line;
+ rc = NW_SUCCESS;
+ }
+ return rc;
+}
+
+nw_ep nc_line_lookup(nw_peer_t peer) {
+ nw_ep lep;
+ nw_alist_t ad;
+ int h, slot;
+ nw_address_1 n1;
+ nw_address_2 n2;
+
+ n1 = peer->rem_addr_1;
+ n2 = peer->rem_addr_2;
+ h = (n1 % MAX_HASH + n2) % MAX_HASH;
+ slot = nw_nw[h];
+ ad = &nw_address[slot];
+ while (slot != -1 && (ad->address.nw_addr_1 != n1 ||
+ ad->address.nw_addr_2 != n2)) {
+ slot = ad->nw_next;
+ ad = &nw_address[slot];
+ }
+ if (slot == -1) {
+ lep = -1;
+ } else {
+ lep = ad->line;
+ }
+ return lep;
+}
+
+nw_result nc_endpoint_allocate(nw_ep_t epp, nw_protocol protocol,
+ nw_acceptance accept,
+ char *buffer_address, u_int buffer_size) {
+ nw_result rc;
+ nw_ep ep;
+ nw_ecb_t ecb;
+
+ if (ect[(ep = *epp)].state != NW_INEXISTENT) {
+ rc = NW_BAD_EP;
+ } else if (nw_free_ep_first == 0) {
+ *epp = nw_free_line_first;
+ rc = NW_NO_EP;
+ } else {
+ if (ep == 0) {
+ ecb = &ect[nw_free_ep_first];
+ *epp = ep = ecb->id;
+ nw_free_ep_first = ecb->next;
+ if (nw_free_ep_first == 0)
+ nw_free_ep_last = 0;
+ } else {
+ ecb = &ect[ep];
+ if (ecb->previous == 0)
+ nw_free_ep_first = ecb->next;
+ else
+ ect[ecb->previous].next = ecb->next;
+ if (ecb->next == 0)
+ nw_free_ep_last = ecb->previous;
+ else
+ ect[ecb->next].previous = ecb->previous;
+ }
+ if (protocol == NW_LINE) {
+ if (nw_free_line_last == 0)
+ nw_free_line_first = ep;
+ else
+ ect[nw_free_line_last].next = ep;
+ ecb->previous = nw_free_line_last;
+ ecb->next = 0;
+ nw_free_line_last = ep;
+ }
+ ecb->protocol = protocol;
+ ecb->accept = accept;
+ ecb->state = NW_UNCONNECTED;
+ ecb->conn = NULL;
+ ecb->buf_start = buffer_address;
+ ecb->buf_end = buffer_address + buffer_size;
+ ecb->free_buffer = (nw_unused_buffer_t) buffer_address;
+ ecb->free_buffer->buf_used = 0;
+ ecb->free_buffer->buf_length = buffer_size;
+ ecb->free_buffer->previous = NULL;
+ ecb->free_buffer->next = NULL;
+ ecb->overrun = 0;
+ ecb->seqno = 0;
+ ecb->tx_first = NULL;
+ ecb->tx_last = NULL;
+ ecb->tx_initial = NULL;
+ ecb->tx_current = NULL;
+ ecb->rx_first = NULL;
+ ecb->rx_last = NULL;
+ rc = NW_SUCCESS;
+ }
+ return rc;
+}
+
+nw_result nc_endpoint_deallocate(nw_ep ep) {
+ nw_ecb_t ecb;
+ nw_rx_header_t rx_header;
+
+ ecb = &ect[ep];
+ if (ecb->conn != NULL)
+ nc_peer_deallocate(ecb->conn);
+ if (ecb->tx_first != NULL)
+ nc_tx_header_deallocate(ecb->tx_first);
+ if (ecb->tx_initial != NULL)
+ nc_tx_header_deallocate(ecb->tx_initial);
+ while (ecb->rx_first != NULL) {
+ rx_header = ecb->rx_first;
+ ecb->rx_first = rx_header->next;
+ nc_rx_header_deallocate(rx_header);
+ }
+ if (ecb->protocol == NW_LINE) {
+ if (ecb->previous == 0)
+ nw_free_line_first = ecb->next;
+ else
+ ect[ecb->previous].next = ecb->next;
+ if (ecb->next == 0)
+ nw_free_line_last = ecb->previous;
+ else
+ ect[ecb->next].previous = ecb->previous;
+ }
+ ecb->next = 0;
+ ecb->previous = nw_free_ep_last;
+ if (nw_free_ep_last == 0)
+ nw_free_ep_first = ep;
+ else
+ ect[nw_free_ep_last].next = ep;
+ nw_free_ep_last = ep;
+ ecb->id = ep;
+ ecb->state = NW_INEXISTENT;
+ return NW_SUCCESS;
+}
+
+void nc_buffer_coalesce(nw_ecb_t ecb) {
+ nw_unused_buffer_t p, q, buf_free, buf_start, buf_end;
+
+ buf_start = p = (nw_unused_buffer_t) ecb->buf_start;
+ buf_end = (nw_unused_buffer_t) ecb->buf_end;
+ buf_free = NULL;
+ while (p >= buf_start && p < buf_end) {
+ if (p->buf_length & 0x3)
+ goto trash_area;
+ if (p->buf_used) {
+ p = (nw_unused_buffer_t) ((char *) p + p->buf_length);
+ } else {
+ q = (nw_unused_buffer_t) ((char *) p + p->buf_length);
+ while (q >= buf_start && q < buf_end && !q->buf_used) {
+ if (q->buf_length & 0x3)
+ goto trash_area;
+ p->buf_length += q->buf_length;
+ q = (nw_unused_buffer_t) ((char *) q + q->buf_length);
+ }
+ p->next = buf_free;
+ p->previous = NULL;
+ if (buf_free != NULL)
+ buf_free->previous = p;
+ buf_free = p;
+ p = q;
+ }
+ }
+ ecb->free_buffer = buf_free;
+ return;
+
+ trash_area:
+ ecb->free_buffer = NULL;
+ return;
+}
+
+
+nw_buffer_t nc_buffer_allocate(nw_ep ep, u_int size) {
+ nw_ecb_t ecb;
+ nw_unused_buffer_t buf, buf_start, buf_end;
+
+ ecb = &ect[ep];
+ buf_start = (nw_unused_buffer_t) ecb->buf_start;
+ buf_end = (nw_unused_buffer_t) (ecb->buf_end - sizeof(nw_buffer_s));
+ if (size < sizeof(nw_buffer_s))
+ size = sizeof(nw_buffer_s);
+ else
+ size = ((size + 3) >> 2) << 2;
+ buf = ecb->free_buffer;
+ if (buf != NULL) {
+ while (buf->buf_length < size) {
+ buf = buf->next;
+ if (buf < buf_start || buf > buf_end || ((int) buf & 0x3)) {
+ buf = NULL;
+ break;
+ }
+ }
+ }
+ if (buf == NULL) {
+ nc_buffer_coalesce(ecb);
+ buf = ecb->free_buffer;
+ while (buf != NULL && buf->buf_length < size)
+ buf = buf->next;
+ }
+ if (buf == NULL) {
+ ecb->overrun = 1;
+ } else {
+ if (buf->buf_length < size + sizeof(nw_buffer_s)) {
+ if (buf->previous == NULL)
+ ecb->free_buffer = buf->next;
+ else
+ buf->previous->next = buf->next;
+ if (buf->next != NULL)
+ buf->next->previous = buf->previous;
+ } else {
+ buf->buf_length -= size;
+ buf = (nw_unused_buffer_t) ((char *) buf + buf->buf_length);
+ buf->buf_length = size;
+ }
+ buf->buf_used = 1;
+ }
+ return (nw_buffer_t) buf;
+}
+
+nw_result nc_buffer_deallocate(nw_ep ep, nw_buffer_t buffer) {
+ nw_ecb_t ecb;
+ nw_unused_buffer_t buf;
+
+ ecb = &ect[ep];
+ buf = (nw_unused_buffer_t) buffer;
+ buf->buf_used = 0;
+ buf->previous = NULL;
+ buf->next = ecb->free_buffer;
+ if (ecb->free_buffer != NULL)
+ ecb->free_buffer->previous = buf;
+ ecb->free_buffer = buf;
+ return NW_SUCCESS;
+}
+
+nw_result nc_endpoint_status(nw_ep ep, nw_state_t state, nw_peer_t peer) {
+ nw_result rc;
+ nw_ecb_t ecb;
+
+ ecb = &ect[ep];
+ *state = ecb->state;
+ if (ecb->conn)
+ *peer = ecb->conn->peer;
+ if (ecb->overrun) {
+ ecb->overrun = 0;
+ rc = NW_OVERRUN;
+ } else if (ecb->rx_first != NULL) {
+ rc = NW_QUEUED;
+ } else {
+ rc = NW_SUCCESS;
+ }
+ return rc;
+}
+
+
+nw_result nc_local_send(nw_ep ep, nw_tx_header_t header, nw_options options) {
+ nw_result rc;
+ nw_ep receiver;
+ int length;
+ nw_buffer_t buffer;
+ nw_tx_header_t first_header;
+ nw_rx_header_t rx_header;
+ char *bufp;
+ nw_ecb_t ecb;
+
+ receiver = header->peer.remote_ep;
+ length = header->msg_length;
+ buffer = nc_buffer_allocate(receiver, sizeof(nw_buffer_s) + length);
+ if (buffer == NULL) {
+ rc = NW_OVERRUN;
+ } else {
+ buffer->buf_next = NULL;
+ buffer->block_offset = sizeof(nw_buffer_s);
+ buffer->block_length = length;
+ buffer->peer.rem_addr_1 = NW_NULL << 28;
+ buffer->peer.rem_addr_2 = 0;
+ buffer->peer.remote_ep = ep;
+ buffer->peer.local_ep = receiver;
+ bufp = (char *) buffer + sizeof(nw_buffer_s);
+ first_header = header;
+ while (header != NULL) {
+ length = header->block_length;
+ bcopy(header->block, bufp, length);
+ bufp += length;
+ if (header->buffer != NULL)
+ nc_buffer_deallocate(ep, header->buffer);
+ header = header->next;
+ }
+ nc_tx_header_deallocate(first_header);
+ ecb = &ect[receiver];
+ if (options == NW_URGENT) {
+ buffer->msg_seqno = 0;
+ if (nc_deliver_result(receiver, NW_RECEIVE_URGENT, (int) buffer))
+ rc = NW_SUCCESS;
+ else
+ rc = NW_NO_RESOURCES;
+ } else {
+ if (ecb->seqno == 1023)
+ buffer->msg_seqno = ecb->seqno = 1;
+ else
+ buffer->msg_seqno = ++ecb->seqno;
+ if (nc_deliver_result(receiver, NW_RECEIVE, (int) buffer))
+ rc = NW_SUCCESS;
+ else
+ rc = NW_NO_RESOURCES;
+ }
+ }
+ return rc;
+}
+
+nw_buffer_t nc_local_rpc(nw_ep ep, nw_tx_header_t header, nw_options options) {
+ nw_buffer_t buf;
+ nw_ecb_t ecb;
+ nw_rx_header_t rx_header;
+
+ ecb = &ect[ep];
+ rx_header = ecb->rx_first;
+ if (nc_local_send(ep, header, options) != NW_SUCCESS) {
+ buf = NW_BUFFER_ERROR;
+ } else if (rx_header == NULL) {
+ buf = NULL;
+ } else {
+ buf = rx_header->buffer;
+ ecb->rx_first = rx_header->next;
+ if (ecb->rx_first == NULL)
+ ecb->rx_last = NULL;
+ nc_rx_header_deallocate(rx_header);
+ }
+ return buf;
+}
+
+
+nw_result nc_succeed(int dev) {
+
+ return NW_SUCCESS;
+}
+
+void nc_null(int dev) {
+
+}
+
+nw_result nc_fail(int dev) {
+
+ return NW_FAILURE;
+}
+
+int nc_null_poll(int dev) {
+
+ return 1000000;
+}
+
+nw_result nc_null_send(nw_ep ep, nw_tx_header_t header, nw_options options) {
+
+ return NW_FAILURE;
+}
+
+nw_buffer_t nc_null_rpc(nw_ep ep, nw_tx_header_t header, nw_options options) {
+
+ return NW_BUFFER_ERROR;
+}
+
+void nc_null_signal(nw_buffer_t msg) {
+
+}
+
+nw_result nc_open_fail(nw_ep lep, nw_address_1 a1,
+ nw_address_2 a2, nw_ep rep) {
+
+ return NW_FAILURE;
+}
+
+nw_result nc_close_fail(nw_ep ep) {
+
+ return NW_FAILURE;
+}
+
+nw_result nc_accept_fail(nw_ep ep, nw_buffer_t msg, nw_ep_t epp) {
+
+ return NW_FAILURE;
+}
+
diff --git a/chips/nc.h b/chips/nc.h
new file mode 100644
index 00000000..0e481e8c
--- /dev/null
+++ b/chips/nc.h
@@ -0,0 +1,232 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** NETWORK INTERFACE IMPLEMENTATION CORE ***/
+
+#ifndef _NC_H_
+#define _NC_H_
+
+#ifndef STUB
+#include <chips/nw.h>
+#else
+#include "nw.h"
+#endif
+
+/*** Types and data structures ***/
+
+#if PRODUCTION
+#define MAX_EP 1024
+#define MAX_DEV 16
+#else
+#define MAX_EP 32
+#define MAX_DEV 3
+#endif
+
+#define MASTER_LINE_EP 0
+#define SIGNAL_EP 1
+
+typedef struct nw_tx_headers {
+ nw_buffer_t buffer;
+ u_int msg_length;
+ char *block;
+ u_int block_length;
+ nw_peer_s peer;
+ nw_ep sender;
+ nw_options options;
+ struct nw_tx_headers *next;
+} nw_tx_header_s;
+
+typedef nw_tx_header_s *nw_tx_header_t;
+
+typedef struct nw_rx_headers {
+ nw_buffer_t buffer;
+ nw_ep receiver;
+ u_int reply;
+ int time_stamp;
+ struct nw_rx_headers *next;
+} nw_rx_header_s, *nw_rx_header_t;
+
+typedef enum {
+ NW_CONNECTIONLESS,
+ NW_CONNECTION_ORIENTED
+} nw_dev_type;
+
+
+typedef struct {
+ nw_result (*initialize)(int);
+ nw_result (*status)(int);
+ void (*slow_sweep)(int);
+ void (*fast_sweep)(int);
+ int (*poll)(int);
+ nw_result (*send)(nw_ep, nw_tx_header_t, nw_options);
+ nw_buffer_t (*rpc)(nw_ep, nw_tx_header_t, nw_options);
+ void (*signal)(nw_buffer_t);
+ nw_result (*open)(nw_ep, nw_address_1, nw_address_2, nw_ep);
+ nw_result (*accept)(nw_ep, nw_buffer_t, nw_ep_t);
+ nw_result (*close)(nw_ep);
+ nw_result (*add)(nw_ep, nw_address_1, nw_address_2, nw_ep);
+ nw_result (*drop)(nw_ep, nw_address_1, nw_address_2, nw_ep);
+} nw_dev_entry_s, *nw_dev_entry_t;
+
+typedef struct {
+ nw_result status;
+ nw_dev_type type;
+ char *addr;
+ nw_address_1 local_addr_1;
+ nw_address_2 local_addr_2;
+ nw_dev_entry_t entry;
+ int fast_req;
+} nw_devcb;
+
+extern nw_devcb devct[MAX_DEV];
+
+typedef struct plists {
+ nw_peer_s peer;
+ struct plists *next;
+} nw_plist_s, *nw_plist_t;
+
+typedef struct nw_unused_buffers {
+ u_int buf_used:1;
+ u_int buf_length:31;
+ struct nw_unused_buffers *next;
+ struct nw_unused_buffers *previous;
+} nw_unused_buffer_s, *nw_unused_buffer_t;
+
+typedef struct ecbs{
+ nw_protocol protocol;
+ nw_acceptance accept;
+ nw_state state;
+ nw_plist_t conn;
+ char *buf_start;
+ char *buf_end;
+ nw_unused_buffer_t free_buffer;
+ nw_ep id:16;
+ u_int overrun:1;
+ u_int seqno:14;
+ nw_tx_header_t tx_first;
+ nw_tx_header_t tx_last;
+ nw_tx_header_t tx_initial;
+ nw_tx_header_t tx_current;
+ nw_rx_header_t rx_first;
+ nw_rx_header_t rx_last;
+ nw_ep next:16;
+ nw_ep previous:16;
+} nw_ecb, *nw_ecb_t;
+
+extern nw_ecb ect[MAX_EP];
+
+extern int nw_free_ep_first, nw_free_ep_last;
+extern int nw_free_line_first, nw_free_line_last;
+
+typedef enum {
+ NW_RECEIVE,
+ NW_RECEIVE_URGENT,
+ NW_SEND,
+ NW_SIGNAL
+} nw_delivery;
+
+
+/*** System-independent functions implemented in core ***/
+
+extern void nc_initialize();
+
+extern nw_tx_header_t nc_tx_header_allocate();
+
+extern void nc_tx_header_deallocate(nw_tx_header_t header);
+
+extern nw_rx_header_t nc_rx_header_allocate();
+
+extern void nc_rx_header_deallocate(nw_rx_header_t header);
+
+extern nw_plist_t nc_peer_allocate();
+
+extern void nc_peer_deallocate(nw_plist_t peer);
+
+extern nw_result nc_device_register(u_int dev, nw_dev_type type,
+ char *dev_addr,
+ nw_dev_entry_t dev_entry_table);
+
+extern nw_result nc_device_unregister(u_int dev, nw_result status);
+
+extern void nc_fast_sweep();
+
+extern void nc_fast_timer_set();
+
+extern void nc_fast_timer_reset();
+
+extern void nc_slow_sweep();
+
+extern nw_result nc_update(nw_update_type up_type, int *up_info);
+
+extern nw_result nc_lookup(nw_lookup_type lt, int *look_info);
+
+extern nw_result nc_line_update(nw_peer_t peer, nw_ep line);
+
+extern nw_ep nc_line_lookup(nw_peer_t peer);
+
+extern nw_result nc_endpoint_allocate(nw_ep_t epp, nw_protocol protocol,
+ nw_acceptance accept,
+ char *buffer_address, u_int buffer_size);
+
+extern nw_result nc_endpoint_deallocate(nw_ep ep);
+
+extern nw_buffer_t nc_buffer_allocate(nw_ep ep, u_int size);
+
+extern nw_result nc_buffer_deallocate(nw_ep ep, nw_buffer_t buffer);
+
+extern nw_result nc_endpoint_status(nw_ep ep,
+ nw_state_t state, nw_peer_t peer);
+
+
+/* System-dependent function implemented in wrapper*/
+
+extern boolean_t nc_deliver_result(nw_ep ep, nw_delivery type, int result);
+
+/* Support required in wrapper */
+
+extern void h_initialize();
+
+extern void h_fast_timer_set();
+
+extern void h_fast_timer_reset();
+
+
+/* Stubs for device table */
+
+extern nw_result nc_succeed(int);
+extern nw_result nc_fail(int);
+extern void nc_null(int);
+extern int nc_null_poll(int);
+extern nw_result nc_null_send(nw_ep, nw_tx_header_t, nw_options);
+extern nw_buffer_t nc_null_rpc(nw_ep, nw_tx_header_t, nw_options);
+extern nw_result nc_local_send(nw_ep, nw_tx_header_t, nw_options);
+extern nw_buffer_t nc_local_rpc(nw_ep, nw_tx_header_t, nw_options);
+extern void nc_null_signal(nw_buffer_t);
+extern nw_result nc_open_fail(nw_ep, nw_address_1, nw_address_2, nw_ep);
+extern nw_result nc_accept_fail(nw_ep, nw_buffer_t, nw_ep_t);
+extern nw_result nc_close_fail(nw_ep);
+
+#endif /* _NC_H_ */
diff --git a/chips/nw.h b/chips/nw.h
new file mode 100644
index 00000000..63d497b6
--- /dev/null
+++ b/chips/nw.h
@@ -0,0 +1,494 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _NW_H_
+#define _NW_H_ 1
+
+#if defined(KMODE) || defined(KERNEL)
+#include <sys/types.h>
+#include <mach/port.h>
+#else
+#include "stub0.h"
+#endif
+
+/*** NETWORK APPLICATION PROGRAMMING INTERFACE ***/
+
+/*** TYPES ***/
+
+typedef enum {
+ NW_SUCCESS,
+ NW_FAILURE,
+ NW_BAD_ADDRESS,
+ NW_OVERRUN,
+ NW_NO_CARRIER,
+ NW_NOT_SERVER,
+ NW_NO_EP,
+ NW_BAD_EP,
+ NW_INVALID_ARGUMENT,
+ NW_NO_RESOURCES,
+ NW_PROT_VIOLATION,
+ NW_BAD_BUFFER,
+ NW_BAD_LENGTH,
+ NW_NO_REMOTE_EP,
+ NW_TIME_OUT,
+ NW_INCONSISTENCY,
+ NW_ABORTED,
+ NW_SYNCH,
+ NW_QUEUED
+} nw_result, *nw_result_t;
+
+typedef enum {
+ NW_INITIALIZE,
+ NW_HOST_ADDRESS_REGISTER,
+ NW_HOST_ADDRESS_UNREGISTER
+} nw_update_type;
+
+typedef enum {
+ NW_STATUS,
+ NW_HOST_ADDRESS_LOOKUP
+} nw_lookup_type;
+
+typedef u_int ip_address;
+
+typedef u_int nw_address_1;
+typedef u_int nw_address_2;
+
+typedef struct {
+ char name[20]; /*Host name -- first 19 characters, zero-terminated*/
+ ip_address ip_addr;
+ nw_address_1 nw_addr_1; /*4 most significant bits specify the device*/
+ nw_address_2 nw_addr_2;
+} nw_address_s, *nw_address_t;
+
+typedef enum {
+ NW_NULL,
+ NW_IP, /*Virtual network for IP addresses*/
+ NW_TCA100_1, /*Fore Systems ATM network, first unit*/
+ NW_TCA100_2 /*Fore Systems ATM network, second unit*/
+} nw_device, *nw_device_t;
+
+#define NW_DEVICE(addr) (addr >> 28)
+
+typedef u_int nw_ep, *nw_ep_t;
+
+typedef enum {
+ NW_RAW, /*Raw service provided by network*/
+ NW_DATAGRAM, /*Connectionless service*/
+ NW_SEQ_PACKET, /*Connection-oriented service*/
+ NW_LINE /*Multiplexing line (system use only)*/
+} nw_protocol;
+
+typedef enum {
+ NW_NO_ACCEPT, /*Connection requests not accepted (client)*/
+ NW_APPL_ACCEPT, /*Connection requests received as message by
+ application (msg_seqno 0), for examination
+ and approval (nw_connection_accept function)*/
+ NW_AUTO_ACCEPT, /*Connection requests automatically accepted
+ if endpoint is connection-oriented and
+ not already connected*/
+ NW_LINE_ACCEPT /*Connection requests automatically accepted
+ on a new endpoint (system use only)*/
+} nw_acceptance;
+
+typedef struct {
+ nw_address_1 rem_addr_1;
+ nw_address_2 rem_addr_2;
+ nw_ep remote_ep:16;
+ nw_ep local_ep:16;
+} nw_peer_s, *nw_peer_t;
+
+typedef struct nw_buffer {
+ u_int buf_used:1; /*Read-only for applications (always 1)*/
+ u_int buf_length:31; /*Read-only for applications*/
+ struct nw_buffer *buf_next; /*Used only to gather on sends*/
+ u_int msg_seqno:10; /*Sequential number of message,
+ automatically set by network interface*/
+ u_int block_offset:22; /*Offset to the beginning of data (in bytes),
+ from the start of the buffer*/
+ u_int block_deallocate:1; /*Used only to deallocate on sends*/
+ u_int block_length:31; /*Length of data (in bytes)
+ beginning at offset*/
+ nw_peer_s peer; /*Set on receives. Also required
+ in first block on datagram sends.
+ Ignored on sequenced packet sends.*/
+} nw_buffer_s, *nw_buffer_t;
+
+
+/* msg_seqno is normally between 1 and 1023, and increases modulo 1024
+ (skipping 0) between consecutive messages. In sequenced packets, msg_seqno
+ increases strictly by one. msg_seqno is assigned automatically.
+ The network interface writes in the buffer the msg_seqno used,
+ but only after the buffer has been transmitted and, in case of
+ sequenced packet, acknowledged. The application can use this update
+ to determine if a buffer can be reused, after a sending a message without
+ the deallocate option.
+ msg_seqno 0 is used when the corresponding send specifies the NW_URGENT
+ option. Such messages bypass any other messages possibly enqueued.
+ msg_seqno 0 is also used for open connection requests, in the case
+ of sequenced packet endpoints with the NW_APPL_ACCEPT option.
+ The type of msg_seqno 0 message is differentiated by the first word in the
+ message, which has type nw_options */
+
+#define NW_BUFFER_ERROR ((nw_buffer_t) -1) /*Used for error indication
+ other than buffer overrun
+ (for which NULL is used)*/
+
+typedef enum {
+ NW_INEXISTENT,
+ NW_UNCONNECTED,
+ NW_SIMPLEX_ORIGINATING,
+ NW_SIMPLEX_ORIGINATED,
+ NW_DUPLEX_ORIGINATING,
+ NW_DUPLEX_ORIGINATING_2,
+ NW_DUPLEX_ORIGINATED,
+ NW_ORIGINATOR_CLOSING,
+ NW_ORIGINATOR_RCLOSING,
+ NW_ACCEPTING,
+ NW_SIMPLEX_ACCEPTED,
+ NW_DUPLEX_ACCEPTING,
+ NW_DUPLEX_ACCEPTED,
+ NW_ACCEPTOR_CLOSING,
+ NW_ACCEPTOR_RCLOSING
+} nw_state, *nw_state_t;
+
+
+typedef enum nw_options {
+ NW_NORMAL,
+ NW_URGENT,
+ NW_SYNCHRONIZATION /*System use only*/
+} nw_options;
+
+
+/*** FUNCTIONS ***/
+
+extern nw_result nw_update(mach_port_t master_port, nw_update_type up_type,
+ int *up_info);
+
+/*****************************************************************************
+ Allows privileged applications to update network tables. The
+ application must present the device master port. up_type selects the
+ type of update, and up_info is cast accordingly to the correct type.
+
+ For NW_HOST_ADDRESS_REGISTER and NW_HOST_ADDRESS_UNREGISTER,
+ up_info has type nw_address_t. For NW_HOST_ADDRESS_UNREGISTER,
+ however, only the network address field is used.
+
+ up_info is not used for NW_INITIALIZE. This option is used to
+ initialize network interface tables, but does not initialize
+ devices. Initialization of hardware and network tables occurs
+ automatically at probe/boot time, so this option is normally
+ unnecessary.
+
+ Returns NW_SUCCESS if operation completed successfully.
+ NW_FAILURE if master port not presented.
+ NW_NO_RESOURCES if network tables full (NW_HOST_ADDRESS_REGISTER).
+ NW_BAD_ADDRESS if host not found (NW_HOST_ADDRESS_UNREGISTER).
+ NW_INVALID_ARGUMENT if up_type is invalid or up_info is
+ a bad pointer.
+ *****************************************************************************/
+
+
+extern nw_result nw_lookup(nw_lookup_type lt, int *look_info);
+
+/*****************************************************************************
+ Allows applications to lookup network tables. The type of
+ lookup is selected by lt, and look_info is cast to the correct type
+ accordingly.
+
+ For lt equal to NW_HOST_ADDRESS_LOOKUP, look_info has type
+ nw_address_t. In this option, the host is looked up first using the
+ IP address as a key (if non-zero), then by name (if non-empty),
+ and finally by network address (if non-zero). The function
+ returns NW_SUCCESS on the first match it finds, and sets the non-key
+ fields of look_info to the values found. No consistency check is
+ made if more than one key is supplied. The function returns
+ NW_BAD_ADDRESS if the host was not found, and NW_INVALID_ARGUMENT
+ if lt is invalid or look_info is a bad pointer.
+
+ For lt equal to NW_STATUS, look_info has type nw_device_t on input
+ and nw_result_t on output. The function returns NW_INVALID_ARGUMENT
+ if the device chosen is invalid or look_info is a bad pointer;
+ otherwise, the function returns NW_SUCCESS. look_info is
+ set to: NW_FAILURE if the device is not present, NW_NOT_SERVER
+ if the device is not serviced by this interface, or a
+ device-dependent value otherwise (NW_SUCCESS if there is no device error).
+
+ *****************************************************************************/
+
+
+extern nw_result nw_endpoint_allocate(nw_ep_t epp, nw_protocol protocol,
+ nw_acceptance accept, u_int buffer_size);
+
+/*****************************************************************************
+ Allocates a communication endpoint. On input, epp should point to the
+ the endpoint number desired, or to 0 if any number is adequate.
+ On output, epp points to the actual number allocated for the endpoint.
+ protocol specifies the transport discipline applied to data transmitted
+ or received through the endpoint. accept selects how open connection
+ requests received for the endpoint should be handled (connection-oriented
+ protocol), or whether the endpoint can receive messages (connectionless
+ protocol). buffer_size specifies the length in bytes of the buffer area
+ for data sent or received through the endpoint.
+
+ Returns NW_SUCCESS if endpoint successfully allocated.
+ NW_INVALID_ARGUMENT if epp is a bad pointer or the
+ protocol or accept arguments are invalid.
+ NW_NO_EP if the endpoint name space is exhausted.
+ NW_BAD_EP if there already is an endpoint with the
+ number selected, or the number selected is
+ out of bounds.
+ NW_NO_RESOURCES if not enough memory for buffer.
+ *****************************************************************************/
+
+
+extern nw_result nw_endpoint_deallocate(nw_ep ep);
+
+/*****************************************************************************
+ Deallocates the given endpoint.
+
+ Returns NW_SUCCESS if successfully deallocated endpoint.
+ NW_BAD_EP if endpoint does not exist.
+ NW_PROT_VIOLATION if access to endpoint not authorized.
+ *****************************************************************************/
+
+
+extern nw_buffer_t nw_buffer_allocate(nw_ep ep, u_int size);
+
+/*****************************************************************************
+ Allocates a buffer of the given size (in bytes) from the buffer area
+ of the given endpoint.
+
+ Returns NW_BUFFER_ERROR if endpoint does not exist or access to endpoint
+ is not authorized.
+ NULL if no buffer with given size could be allocated.
+ Pointer to allocated buffer, otherwise.
+ *****************************************************************************/
+
+
+extern nw_result nw_buffer_deallocate(nw_ep ep, nw_buffer_t buffer);
+
+/*****************************************************************************
+ Deallocates the given buffer.
+
+ Returns NW_SUCCESS if successfully deallocated buffer.
+ NW_BAD_EP if endpoint does not exist.
+ NW_PROT_VIOLATION if access to endpoint not authorized.
+ NW_BAD_BUFFER if buffer does not belong to endpoint's
+ buffer area or is malformed.
+ *****************************************************************************/
+
+
+extern nw_result nw_connection_open(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+/*****************************************************************************
+ Opens a connection.
+
+ Returns NW_SUCCESS if connection successfully opened.
+ NW_BAD_EP if local endpoint does not exist, uses connectionless
+ protocol or is already connected.
+ NW_PROT_VIOLATION if access to local or remote endpoint
+ not authorized.
+ NW_BAD_ADDRESS if address of remote host is invalid.
+ NW_NO_REMOTE_EP if connection name space exhausted at
+ remote host.
+ NW_TIME_OUT if attempt to open connection timed out repeatedly.
+ NW_FAILURE if remote endpoint does not exist, uses connectionless
+ protocol or is already connected, or if remote
+ application did not accept open request.
+ *****************************************************************************/
+
+
+extern nw_result nw_connection_accept(nw_ep ep, nw_buffer_t msg,
+ nw_ep_t new_epp);
+
+/*****************************************************************************
+ Accepts open request (at the remote host). On input, new_epp equal to
+ NULL indicates that the application does not accept the request.
+ new_epp pointing to the value 0 indicates that the application wants
+ to accept the connection on a new endpoint, created dynamically,
+ with the same attributes as the original endpoint; new_epp pointing
+ to the value ep indicates that the application wants to simply
+ accept the open request. On output, new_epp points to the endpoint
+ actually connected, if any. msg points to the open request, which is
+ automatically deallocated.
+
+ Returns NW_SUCCESS if connection correctly accepted or refused.
+ NW_BAD_EP if endpoint does not exist or has no outstanding
+ open request.
+ NW_PROT_VIOLATION if access to endpoint not authorized.
+ NW_BAD_BUFFER if msg does not belong to the endpoint's
+ buffer area, or is malformed.
+ NW_INVALID_ARGUMENT if new_epp is a bad pointer or points to
+ invalid value.
+ NW_NO_EP if endpoint name space exhausted.
+ NW_NO_RESOURCES if no buffer available for new endpoint.
+ NW_TIME_OUT if attempt to accept at different endpoint
+ repeatedly timed out.
+ *****************************************************************************/
+
+
+extern nw_result nw_connection_close(nw_ep ep);
+
+/*****************************************************************************
+ Closes the endpoint's connection.
+
+ Returns NW_SUCCESS if successfully closed connection.
+ NW_BAD_EP if endpoint does not exist or is not connected.
+ NW_PROT_VIOLATION if access to endpoint not authorized.
+ *****************************************************************************/
+
+
+extern nw_result nw_multicast_add(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+/*****************************************************************************
+ Open multicast group or add one more member to multicast group.
+
+ Returns NW_SUCCESS if successfully opened multicast group
+ or added member.
+ NW_BAD_EP if local endpoint does not exist, uses connectionless
+ protocol or is already connected point-to-point.
+ NW_PROT_VIOLATION if access to local or remote endpoint
+ not authorized.
+ NW_BAD_ADDRESS if address of remote host is invalid.
+ NW_NO_REMOTE_EP if connection name space exhausted at
+ remote host.
+ NW_TIME_OUT if attempt to open or add to multicast
+ timed out repeatedly.
+ NW_FAILURE if remote endpoint does not exist, uses connectionless
+ protocol or is already connected, or if remote
+ application did not accept open or add request.
+ *****************************************************************************/
+
+
+extern nw_result nw_multicast_drop(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+/*****************************************************************************
+ Drop member from multicast group, or close group if last member.
+
+ Returns NW_SUCCESS if successfully dropped member or closed group.
+ NW_BAD_EP if local endpoint does not exist or is not connected in
+ multicast to the given remote endpoint.
+ NW_PROT_VIOLATION if access to local endpoint not authorized.
+ *****************************************************************************/
+
+
+extern nw_result nw_endpoint_status(nw_ep ep, nw_state_t state,
+ nw_peer_t peer);
+
+/*****************************************************************************
+ Returns the state of the given endpoint and peer to which it is
+ connected, if any. In case of multicast group, the first peer is
+ returned.
+
+ Returns NW_SUCCESS if status correctly returned.
+ NW_BAD_EP if endpoint does not exist.
+ NW_PROT_VIOLATION if access to endpoint not authorized.
+ NW_INVALID_ARGUMENT if state or peer is a bad pointer.
+ *****************************************************************************/
+
+
+extern nw_result nw_send(nw_ep ep, nw_buffer_t msg, nw_options options);
+
+/*****************************************************************************
+ Sends message through endpoint with the given options.
+
+ Returns NW_SUCCESS if message successfully queued for sending
+ (connectionless protocol) or sent and acknowledged
+ (connection-oriented protocol).
+ NW_BAD_EP if endpoint does not exist or uses connection-oriented
+ protocol but is unconnected.
+ NW_PROT_VIOLATION if access to endpoint not authorized.
+ NW_BAD_BUFFER if msg (or one of the buffers linked by buf_next)
+ is not a buffer in the endpoint's buffer area, or
+ is malformed (e.g., block_length extends beyond
+ end of buffer).
+ NW_NO_RESOURCES if unable to queue message due to resource
+ exhaustion.
+ NW_BAD_LENGTH if the total message length is too long for the
+ network and protocol used.
+ NW_BAD_ADDRESS if address of remote host is invalid
+ (connectionless protocol).
+ NW_FAILURE if repeated errors in message transmission
+ (connection-oriented).
+ NW_TIME_OUT if repeated time-outs in message transmission
+ (connection-oriented).
+ NW_OVERRUN if no buffer available in receiver's buffer area.
+ (connection-oriented).
+ *****************************************************************************/
+
+
+extern nw_buffer_t nw_receive(nw_ep ep, int time_out);
+
+/*****************************************************************************
+ Receive message destined to endpoint. Return if request not
+ satisfied within time_out msec. time_out 0 means non-blocking receive,
+ while -1 means block indefinitely.
+
+ Returns NW_BUFFER_ERROR if endpoint does not exist or access
+ to endpoint is not authorized.
+ NULL if no message available for reception within the
+ specified time-out period.
+ Pointer to message, otherwise.
+ *****************************************************************************/
+
+
+extern nw_buffer_t nw_rpc(nw_ep ep, nw_buffer_t send_msg, nw_options options,
+ int time_out);
+
+/*****************************************************************************
+ Send message through given endpoint with given options and then
+ receive message through the same endpoint. Receive waiting time
+ is limited to time_out msec.
+
+ Returns NW_BUFFER_ERROR if endpoint does not exist, access to
+ endpoint is not authorized, or there was
+ some transmission error.
+ NULL if no message available for reception within the
+ specified time-out period.
+ Pointer to message received, otherwise.
+ *****************************************************************************/
+
+
+extern nw_buffer_t nw_select(u_int nep, nw_ep_t epp, int time_out);
+
+/*****************************************************************************
+ Receive message from one of the nep endpoints in the array epp.
+ Waiting time is limited to time_out msec.
+
+ Returns NW_BUFFER_ERROR if epp does not point to a valid array of nep
+ endpoint numbers, one of the endpoints does
+ not exist or has restricted access or the request
+ could not be correctly queued because of resource
+ exhaustion.
+ NULL if no message arrived within the specified time-out period.
+ Pointer to message received, otherwise.
+ *****************************************************************************/
+
+
+#endif /* _NW_H_ */
diff --git a/chips/nw_mk.c b/chips/nw_mk.c
new file mode 100644
index 00000000..067cf7d0
--- /dev/null
+++ b/chips/nw_mk.c
@@ -0,0 +1,1323 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Scienctxe
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** MACH KERNEL WRAPPER ***/
+
+#ifndef STUB
+#include <kern/task.h>
+#include <kern/thread.h>
+#include <kern/sched_prim.h>
+#include <kern/eventcount.h>
+#include <kern/time_out.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <vm/vm_kern.h>
+#include <chips/nc.h>
+#include <chips/nw_mk.h>
+
+decl_simple_lock_data(, nw_simple_lock);
+u_int previous_spl;
+
+#define nw_lock() \
+ previous_spl = splimp(); \
+ simple_lock(&nw_simple_lock)
+
+#define nw_unlock() \
+ simple_unlock(&nw_simple_lock); \
+ splx(previous_spl)
+
+typedef struct nw_pvs {
+ task_t owner;
+ char *buf_start;
+ char *buf_end;
+ struct nw_pvs *next;
+} nw_pv_s, *nw_pv_t;
+
+typedef struct nw_waiters {
+ thread_t waiter;
+ struct nw_waiters *next;
+} nw_waiter_s, *nw_waiter_t;
+
+typedef struct {
+ nw_pv_t pv;
+ thread_t sig_waiter;
+ nw_waiter_t rx_first;
+ nw_waiter_t rx_last;
+ nw_waiter_t tx_first;
+ nw_waiter_t tx_last;
+} nw_hecb, *nw_hecb_t;
+
+#else
+#include "nc.h"
+#include "nw_mk.h"
+#endif
+
+/*** Types and data structures ***/
+
+int h_initialized = FALSE;
+nw_pv_s nw_pv[2*MAX_EP];
+nw_pv_t nw_free_pv;
+nw_waiter_s nw_waiter[2*MAX_EP];
+nw_waiter_t nw_free_waiter;
+nw_ep_owned_s nw_waited[3*MAX_EP];
+nw_ep_owned_t nw_free_waited;
+nw_hecb hect[MAX_EP];
+timer_elt_data_t nw_fast_timer, nw_slow_timer;
+
+/*** Initialization ***/
+
+void h_initialize() {
+ int ep, last_ep;
+
+ if (!h_initialized) {
+ last_ep = sizeof(nw_pv)/sizeof(nw_pv_s) - 1;
+ for (ep = 0; ep < last_ep; ep++) {
+ nw_pv[ep].next = &nw_pv[ep+1];
+ }
+ nw_pv[last_ep].next = NULL;
+ nw_free_pv = &nw_pv[0];
+ last_ep = sizeof(nw_waiter)/sizeof(nw_waiter_s) - 1;
+ for (ep = 0; ep < last_ep; ep++) {
+ nw_waiter[ep].next = &nw_waiter[ep+1];
+ }
+ nw_waiter[last_ep].next = NULL;
+ nw_free_waiter = &nw_waiter[0];
+ last_ep = sizeof(nw_waited)/sizeof(nw_ep_owned_s) - 1;
+ for (ep = 0; ep < last_ep; ep++) {
+ nw_waited[ep].next = &nw_waited[ep+1];
+ }
+ nw_waited[last_ep].next = NULL;
+ nw_free_waited = &nw_waited[0];
+ last_ep = sizeof(hect)/sizeof(nw_hecb);
+ for (ep = 0; ep < last_ep; ep++) {
+ hect[ep].pv = NULL;
+ hect[ep].sig_waiter = NULL;
+ hect[ep].rx_first = NULL;
+ hect[ep].rx_last = NULL;
+ hect[ep].tx_first = NULL;
+ hect[ep].tx_last = NULL;
+ }
+ nw_fast_timer.fcn = mk_fast_sweep;
+ nw_fast_timer.param = NULL;
+ nw_fast_timer.set = TELT_UNSET;
+ nw_slow_timer.fcn = mk_slow_sweep;
+ nw_slow_timer.param = NULL;
+#if PRODUCTION
+ set_timeout(&nw_slow_timer, 2*hz);
+#endif
+ h_initialized = TRUE;
+ }
+}
+
+/*** User-trappable functions ***/
+
+nw_result mk_update(mach_port_t master_port, nw_update_type up_type,
+ int *up_info) {
+ nw_result rc;
+
+ if (master_port == 0) { /* XXX */
+ rc = NW_FAILURE;
+ } else {
+ nw_lock();
+ switch (up_type) {
+ case NW_HOST_ADDRESS_REGISTER:
+ case NW_HOST_ADDRESS_UNREGISTER:
+ if (invalid_user_access(current_task()->map, (vm_offset_t) up_info,
+ (vm_offset_t) up_info + sizeof(nw_address_s) - 1,
+ VM_PROT_READ | VM_PROT_WRITE)) {
+ rc = NW_INVALID_ARGUMENT;
+ } else {
+ rc = nc_update(up_type, up_info);
+ }
+ break;
+ case NW_INITIALIZE:
+ nc_initialize();
+ rc = NW_SUCCESS;
+ break;
+ default:
+ rc = NW_INVALID_ARGUMENT;
+ }
+ nw_unlock();
+ }
+ return rc;
+}
+
+
+
+nw_result mk_lookup(nw_lookup_type lt, int *look_info) {
+ nw_result rc;
+ int max_size, dev;
+
+ nw_lock();
+ switch (lt) {
+ case NW_HOST_ADDRESS_LOOKUP:
+ if (invalid_user_access(current_task()->map, (vm_offset_t) look_info,
+ (vm_offset_t) look_info + sizeof(nw_address_s) - 1,
+ VM_PROT_READ | VM_PROT_WRITE)) {
+ rc = NW_INVALID_ARGUMENT;
+ } else {
+ rc = nc_lookup(lt, look_info);
+ }
+ break;
+ case NW_STATUS:
+ max_size = sizeof(nw_device);
+ if (max_size < sizeof(nw_result))
+ max_size = sizeof(nw_result);
+ if (invalid_user_access(current_task()->map, (vm_offset_t) look_info,
+ (vm_offset_t) look_info + max_size - 1,
+ VM_PROT_READ | VM_PROT_WRITE) ||
+ (dev = look_info[0]) >= MAX_DEV || dev < 0) {
+ rc = NW_INVALID_ARGUMENT;
+ } else {
+ if (devct[dev].status != NW_SUCCESS) {
+ look_info[0] = (int) devct[dev].status;
+ rc = NW_SUCCESS;
+ } else {
+ rc = (*(devct[dev].entry->status)) (dev);
+ }
+ }
+ break;
+ default:
+ rc = NW_INVALID_ARGUMENT;
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_endpoint_allocate_internal(nw_ep_t epp, nw_protocol protocol,
+ nw_acceptance accept,
+ u_int buffer_size, boolean_t system) {
+ nw_result rc;
+ u_int ep;
+ vm_offset_t kernel_addr, user_addr;
+ nw_pv_t pv;
+ nw_ep_owned_t owned;
+
+ ep = *epp;
+ if (buffer_size == 0)
+ buffer_size = 0x1000;
+ else
+ buffer_size = (buffer_size + 0xfff) & ~0xfff;
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) != NULL) {
+ rc = NW_BAD_EP;
+ } else if (nw_free_pv == NULL || nw_free_waited == NULL) {
+ rc = NW_NO_EP;
+ } else if (projected_buffer_allocate(current_task()->map, buffer_size, 0,
+ &kernel_addr, &user_addr,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_INHERIT_NONE) != KERN_SUCCESS) {
+ rc = NW_NO_RESOURCES;
+ } else {
+ rc = nc_endpoint_allocate(epp, protocol, accept,
+ (char *) kernel_addr, buffer_size);
+ if (rc == NW_NO_EP && (ep = *epp) != 0) {
+ rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->
+ close)) (ep);
+ if (rc == NW_SYNCH) {
+ hect[ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ simple_unlock(&nw_simple_lock);
+ thread_block((void (*)()) 0);
+ }
+ rc = nc_endpoint_deallocate(ep);
+ if (rc == NW_SUCCESS) {
+ nc_line_update(&ect[ep].conn->peer, 0);
+ rc = nc_endpoint_allocate(epp, protocol, accept,
+ (char *) kernel_addr, buffer_size);
+ }
+ }
+ if (rc == NW_SUCCESS) {
+ ep = *epp;
+ if (system) {
+ hect[ep].pv = NULL;
+ } else {
+ hect[ep].pv = nw_free_pv;
+ nw_free_pv = nw_free_pv->next;
+ hect[ep].pv->owner = current_task();
+ hect[ep].pv->buf_start = (char *) user_addr;
+ hect[ep].pv->buf_end = (char *) user_addr + buffer_size;
+ hect[ep].pv->next = NULL;
+ }
+ hect[ep].sig_waiter = NULL;
+ hect[ep].rx_first = NULL;
+ hect[ep].rx_last = NULL;
+ hect[ep].tx_first = NULL;
+ hect[ep].tx_last = NULL;
+ owned = nw_free_waited;
+ nw_free_waited = nw_free_waited->next;
+ owned->ep = ep;
+ owned->next = current_task()->nw_ep_owned;
+ current_task()->nw_ep_owned = owned;
+ } else {
+ projected_buffer_deallocate(current_task()->map, user_addr,
+ user_addr + buffer_size);
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_endpoint_allocate(nw_ep_t epp, nw_protocol protocol,
+ nw_acceptance accept, u_int buffer_size) {
+ nw_result rc;
+
+ if (invalid_user_access(current_task()->map, (vm_offset_t) epp,
+ (vm_offset_t) epp + sizeof(nw_ep) - 1,
+ VM_PROT_READ | VM_PROT_WRITE) ||
+ (protocol != NW_RAW && protocol != NW_DATAGRAM &&
+ protocol != NW_SEQ_PACKET) || (accept != NW_NO_ACCEPT &&
+ accept != NW_APPL_ACCEPT && accept != NW_AUTO_ACCEPT)) {
+ rc = NW_INVALID_ARGUMENT;
+ } else {
+ rc = mk_endpoint_allocate_internal(epp, protocol, accept,
+ buffer_size, FALSE);
+ }
+ return rc;
+}
+
+nw_result mk_endpoint_deallocate_internal(nw_ep ep, task_t task,
+ boolean_t shutdown) {
+ nw_result rc;
+ nw_pv_t pv, pv_previous;
+ nw_ep_owned_t owned, owned_previous;
+ nw_waiter_t w, w_previous, w_next;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ pv_previous = NULL;
+ while (pv != NULL && pv->owner != task) {
+ pv_previous = pv;
+ pv = pv->next;
+ }
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ if (projected_buffer_deallocate(task->map, pv->buf_start,
+ pv->buf_end) != KERN_SUCCESS) {
+ rc = NW_INCONSISTENCY;
+ printf("Endpoint deallocate: inconsistency p. buffer\n");
+ } else {
+ if (pv_previous == NULL)
+ hect[ep].pv = pv->next;
+ else
+ pv_previous->next = pv->next;
+ pv->next = nw_free_pv;
+ nw_free_pv = pv;
+ owned = task->nw_ep_owned;
+ owned_previous = NULL;
+ while (owned != NULL && owned->ep != ep) {
+ owned_previous = owned;
+ owned = owned->next;
+ }
+ if (owned == NULL) {
+ rc = NW_INCONSISTENCY;
+ printf("Endpoint deallocate: inconsistency owned\n");
+ } else {
+ if (owned_previous == NULL)
+ task->nw_ep_owned = owned->next;
+ else
+ owned_previous->next = owned->next;
+ owned->next = nw_free_waited;
+ nw_free_waited = owned;
+ if (hect[ep].sig_waiter != NULL &&
+ hect[ep].sig_waiter->task == task) {
+/* if (!shutdown)*/
+ mk_deliver_result(hect[ep].sig_waiter, NW_ABORTED);
+ hect[ep].sig_waiter = NULL;
+ }
+ w = hect[ep].rx_first;
+ w_previous = NULL;
+ while (w != NULL) {
+ if (w->waiter->task == task) {
+/* if (!shutdown)*/
+ mk_deliver_result(w->waiter, NULL);
+ w_next = w->next;
+ if (w_previous == NULL)
+ hect[ep].rx_first = w_next;
+ else
+ w_previous->next = w_next;
+ w->next = nw_free_waiter;
+ nw_free_waiter = w;
+ w = w_next;
+ } else {
+ w_previous = w;
+ w = w->next;
+ }
+ }
+ if (hect[ep].rx_first == NULL)
+ hect[ep].rx_last = NULL;
+ w = hect[ep].tx_first;
+ w_previous = NULL;
+ while (w != NULL) {
+ if (w->waiter->task == task) {
+/* if (!shutdown)*/
+ mk_deliver_result(w->waiter, NW_ABORTED);
+ w_next = w->next;
+ if (w_previous == NULL)
+ hect[ep].tx_first = w_next;
+ else
+ w_previous->next = w_next;
+ w->next = nw_free_waiter;
+ nw_free_waiter = w;
+ w = w_next;
+ } else {
+ w_previous = w;
+ w = w->next;
+ }
+ }
+ if (hect[ep].tx_first == NULL)
+ hect[ep].tx_last = NULL;
+ if (hect[ep].pv == NULL) {
+ if (ect[ep].state != NW_UNCONNECTED) {
+ rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->
+ close)) (ep);
+ if (rc == NW_SYNCH) {
+ hect[ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ simple_unlock(&nw_simple_lock);
+ thread_block((void (*)()) 0);
+ }
+ }
+ rc = nc_endpoint_deallocate(ep);
+ }
+ }
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+nw_result mk_endpoint_deallocate(nw_ep ep) {
+
+ mk_endpoint_deallocate_internal(ep, current_task(), FALSE);
+}
+
+
+nw_buffer_t mk_buffer_allocate(nw_ep ep, u_int size) {
+ nw_buffer_t buf;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ buf = NW_BUFFER_ERROR;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ buf = NW_BUFFER_ERROR;
+ } else {
+ buf = nc_buffer_allocate(ep, size);
+ if (buf != NULL) {
+ buf = (nw_buffer_t) ((char *) buf - ect[ep].buf_start + pv->buf_start);
+ }
+ }
+ }
+ nw_unlock();
+ return buf;
+}
+
+
+
+nw_result mk_buffer_deallocate(nw_ep ep, nw_buffer_t buffer) {
+ nw_result rc;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ if ((char *) buffer < pv->buf_start ||
+ (char *) buffer + sizeof(nw_buffer_s) > pv->buf_end ||
+ !buffer->buf_used ||
+ (char *) buffer + buffer->buf_length > pv->buf_end) {
+ rc = NW_BAD_BUFFER;
+ } else {
+ buffer = (nw_buffer_t) ((char *) buffer - pv->buf_start +
+ ect[ep].buf_start);
+ rc = nc_buffer_deallocate(ep, buffer);
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_connection_open_internal(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep) {
+ nw_result rc;
+
+ rc = (*devct[NW_DEVICE(rem_addr_1)].entry->open) (local_ep,
+ rem_addr_1, rem_addr_2,
+ remote_ep);
+ if (rc == NW_SYNCH) {
+ hect[local_ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ simple_unlock(&nw_simple_lock);
+ thread_block((void (*)()) 0);
+ }
+ return rc;
+}
+
+nw_result mk_connection_open(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep) {
+ nw_result rc;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->open))
+ (local_ep, rem_addr_1, rem_addr_2, remote_ep);
+ if (rc == NW_SYNCH) {
+ hect[local_ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ current_thread()->nw_ep_waited = NULL;
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_connection_accept(nw_ep ep, nw_buffer_t msg,
+ nw_ep_t new_epp) {
+ nw_result rc;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else if ((char *) msg < pv->buf_start ||
+ (char *) msg + sizeof(nw_buffer_s) > pv->buf_end ||
+ !msg->buf_used ||
+ (char *) msg + msg->buf_length > pv->buf_end) {
+ rc = NW_BAD_BUFFER;
+ } else if (new_epp != NULL &&
+ (invalid_user_access(current_task()->map, (vm_offset_t) new_epp,
+ (vm_offset_t) new_epp + sizeof(nw_ep) - 1,
+ VM_PROT_READ | VM_PROT_WRITE) ||
+ (*new_epp != 0 && *new_epp != ep))) {
+ rc = NW_INVALID_ARGUMENT;
+ } else {
+ rc = (*(devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->accept))
+ (ep, msg, new_epp);
+ if (rc == NW_SYNCH) {
+ hect[ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ current_thread()->nw_ep_waited = NULL;
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+nw_result mk_connection_close(nw_ep ep) {
+ nw_result rc;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ rc = (*devct[NW_DEVICE(ect[ep].conn->peer.rem_addr_1)].entry->close)
+ (ep);
+ if (rc == NW_SYNCH) {
+ hect[ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ current_thread()->nw_ep_waited = NULL;
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_multicast_add(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep) {
+ nw_result rc;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->add))
+ (local_ep, rem_addr_1, rem_addr_2, remote_ep);
+ if (rc == NW_SYNCH) {
+ hect[local_ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ current_thread()->nw_ep_waited = NULL;
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_multicast_drop(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep) {
+ nw_result rc;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (local_ep >= MAX_EP || (pv = hect[local_ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ rc = (*(devct[NW_DEVICE(rem_addr_1)].entry->drop))
+ (local_ep, rem_addr_1, rem_addr_2, remote_ep);
+ if (rc == NW_SYNCH) {
+ hect[local_ep].sig_waiter = current_thread();
+ assert_wait(0, TRUE);
+ current_thread()->nw_ep_waited = NULL;
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_endpoint_status(nw_ep ep, nw_state_t state,
+ nw_peer_t peer) {
+ nw_result rc;
+ nw_pv_t pv;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ if (invalid_user_access(current_task()->map, (vm_offset_t) state,
+ (vm_offset_t) state + sizeof(nw_state) - 1,
+ VM_PROT_WRITE) ||
+ invalid_user_access(current_task()->map, (vm_offset_t) peer,
+ (vm_offset_t) peer + sizeof(nw_peer_s) - 1,
+ VM_PROT_WRITE)) {
+ rc = NW_INVALID_ARGUMENT;
+ } else {
+ rc = nc_endpoint_status(ep, state, peer);
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_result mk_send(nw_ep ep, nw_buffer_t msg, nw_options options) {
+ nw_result rc;
+ nw_pv_t pv;
+ nw_ep sender;
+ int dev;
+ nw_ecb_t ecb;
+ nw_tx_header_t header, first_header, previous_header;
+ nw_hecb_t hecb;
+ nw_waiter_t w;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BAD_EP;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_PROT_VIOLATION;
+ } else {
+ ecb = &ect[ep];
+ if (ecb->state == NW_INEXISTENT ||
+ (ecb->protocol == NW_SEQ_PACKET && ecb->conn == NULL)) {
+ rc = NW_BAD_EP;
+ } else {
+ first_header = header = nc_tx_header_allocate();
+ previous_header = NULL;
+ rc = NW_SUCCESS;
+ while (header != NULL) {
+ if ((char *) msg < pv->buf_start ||
+ (char *) msg + sizeof(nw_buffer_s) > pv->buf_end ||
+ ((int) msg & 0x3) || (msg->block_offset & 0x3) ||
+ (msg->block_length & 0x3) || !msg->buf_used ||
+ (char *) msg + msg->buf_length > pv->buf_end ||
+ msg->block_offset + msg->block_length > msg->buf_length) {
+ rc = NW_BAD_BUFFER;
+ break;
+ } else {
+ if (previous_header == NULL) {
+ if (ecb->protocol == NW_SEQ_PACKET)
+ header->peer = ecb->conn->peer;
+ else
+ header->peer = msg->peer;
+ } else {
+ previous_header->next = header;
+ }
+ header->buffer = (nw_buffer_t) ((char *) msg - pv->buf_start +
+ ecb->buf_start);
+ header->block = (char *) header->buffer + msg->block_offset;
+ if (!msg->block_deallocate)
+ header->buffer = NULL;
+ header->msg_length = 0;
+ header->block_length = msg->block_length;
+ first_header->msg_length += header->block_length;
+ header->next = NULL;
+ if (msg->buf_next == NULL)
+ break;
+ msg = msg->buf_next;
+ previous_header = header;
+ header = nc_tx_header_allocate();
+ }
+ }
+ if (header == NULL) {
+ nc_tx_header_deallocate(first_header);
+ rc = NW_NO_RESOURCES;
+ } else if (rc == NW_SUCCESS) {
+ dev = NW_DEVICE(first_header->peer.rem_addr_1);
+ if (ecb->protocol != NW_DATAGRAM ||
+ devct[dev].type != NW_CONNECTION_ORIENTED) {
+ sender = first_header->peer.local_ep;
+ rc = NW_SUCCESS;
+ } else {
+ sender = nc_line_lookup(&first_header->peer);
+ if (sender == -1) {
+ rc = NW_BAD_ADDRESS;
+ } else if (sender > 0) {
+ rc = NW_SUCCESS;
+ } else {
+ rc = mk_endpoint_allocate_internal(&sender, NW_LINE,
+ NW_AUTO_ACCEPT, 0, TRUE);
+ if (rc == NW_SUCCESS) {
+ rc = mk_connection_open_internal(sender,
+ first_header->peer.rem_addr_1,
+ first_header->peer.rem_addr_2,
+ MASTER_LINE_EP);
+ if (rc == NW_SUCCESS)
+ nc_line_update(&first_header->peer, sender);
+ }
+ }
+ }
+ if (rc == NW_SUCCESS) {
+ first_header->sender = sender;
+ first_header->options = options;
+ rc = (*(devct[dev].entry->send)) (sender, first_header, options);
+ if ((rc == NW_SYNCH || rc == NW_QUEUED) &&
+ nw_free_waiter != NULL) {
+ w = nw_free_waiter;
+ nw_free_waiter = w->next;
+ w->waiter = current_thread();
+ w->next = NULL;
+ hecb = &hect[sender];
+ if (hecb->tx_last == NULL) {
+ hecb->tx_first = hecb->tx_last = w;
+ } else {
+ hecb->tx_last = hecb->tx_last->next = w;
+ }
+ assert_wait(0, TRUE);
+ current_thread()->nw_ep_waited = NULL;
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_buffer_t mk_receive(nw_ep ep, int time_out) {
+ nw_buffer_t rc;
+ nw_pv_t pv;
+ nw_ecb_t ecb;
+ nw_rx_header_t header;
+ nw_hecb_t hecb;
+ nw_waiter_t w;
+ nw_ep_owned_t waited;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BUFFER_ERROR;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_BUFFER_ERROR;
+ } else {
+ ecb = &ect[ep];
+ header = ecb->rx_first;
+ if (header != NULL) {
+ rc = (nw_buffer_t) ((char *) header->buffer - ecb->buf_start +
+ pv->buf_start);
+ ecb->rx_first = header->next;
+ if (ecb->rx_first == NULL)
+ ecb->rx_last = NULL;
+ nc_rx_header_deallocate(header);
+ } else if (time_out != 0 && nw_free_waiter != NULL &&
+ (time_out == -1 || nw_free_waited != NULL)) {
+ w = nw_free_waiter;
+ nw_free_waiter = w->next;
+ w->waiter = current_thread();
+ w->next = NULL;
+ hecb = &hect[ep];
+ if (hecb->rx_last == NULL)
+ hecb->rx_first = hecb->rx_last = w;
+ else
+ hecb->rx_last = hecb->rx_last->next = w;
+ assert_wait(0, TRUE);
+ if (time_out != -1) {
+ waited = nw_free_waited;
+ nw_free_waited = waited->next;
+ waited->ep = ep;
+ waited->next = NULL;
+ current_thread()->nw_ep_waited = waited;
+ current_thread()->wait_result = NULL;
+ if (!current_thread()->timer.set)
+ thread_set_timeout(time_out);
+ } else {
+ current_thread()->nw_ep_waited = NULL;
+ }
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ } else {
+ rc = NULL;
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+
+nw_buffer_t mk_rpc(nw_ep ep, nw_buffer_t msg, nw_options options,
+ int time_out) {
+ nw_buffer_t rc;
+ nw_result nrc;
+ nw_ep sender;
+ int dev;
+ nw_pv_t pv;
+ nw_ecb_t ecb;
+ nw_tx_header_t header, first_header, previous_header;
+ nw_hecb_t hecb;
+ nw_waiter_t w;
+ nw_ep_owned_t waited;
+
+ nw_lock();
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BUFFER_ERROR;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_BUFFER_ERROR;
+ } else {
+ ecb = &ect[ep];
+ if (ecb->state == NW_INEXISTENT ||
+ (ecb->protocol == NW_SEQ_PACKET && ecb->conn == NULL)) {
+ rc = NW_BUFFER_ERROR;
+ } else {
+ first_header = header = nc_tx_header_allocate();
+ previous_header = NULL;
+ rc = NULL;
+ while (header != NULL) {
+ if ((char *) msg < pv->buf_start ||
+ (char *) msg + sizeof(nw_buffer_s) > pv->buf_end ||
+ ((int) msg & 0x3) || (msg->block_offset & 0x3) ||
+ (msg->block_length & 0x3) || !msg->buf_used ||
+ (char *) msg + msg->buf_length > pv->buf_end ||
+ msg->block_offset + msg->block_length > msg->buf_length) {
+ rc = NW_BUFFER_ERROR;
+ break;
+ } else {
+ if (previous_header == NULL) {
+ if (ecb->protocol == NW_SEQ_PACKET)
+ header->peer = ecb->conn->peer;
+ else
+ header->peer = msg->peer;
+ } else {
+ previous_header->next = header;
+ }
+ header->buffer = (nw_buffer_t) ((char *) msg - pv->buf_start +
+ ecb->buf_start);
+ header->block = (char *) header->buffer + msg->block_offset;
+ if (!msg->block_deallocate)
+ header->buffer = NULL;
+ header->msg_length = 0;
+ header->block_length = msg->block_length;
+ first_header->msg_length += header->block_length;
+ header->next = NULL;
+ if (msg->buf_next == NULL)
+ break;
+ msg = msg->buf_next;
+ previous_header = header;
+ header = nc_tx_header_allocate();
+ }
+ }
+ if (header == NULL) {
+ nc_tx_header_deallocate(first_header);
+ rc = NW_BUFFER_ERROR;
+ } else if (rc != NW_BUFFER_ERROR) {
+ dev = NW_DEVICE(first_header->peer.rem_addr_1);
+ if (ecb->protocol != NW_DATAGRAM ||
+ devct[dev].type != NW_CONNECTION_ORIENTED) {
+ sender = first_header->peer.local_ep;
+ nrc = NW_SUCCESS;
+ } else {
+ sender = nc_line_lookup(&first_header->peer);
+ if (sender == -1) {
+ nrc = NW_BAD_ADDRESS;
+ } else if (sender > 0) {
+ nrc = NW_SUCCESS;
+ } else {
+ nrc = mk_endpoint_allocate_internal(&sender, NW_LINE,
+ NW_AUTO_ACCEPT, 0, TRUE);
+ if (nrc == NW_SUCCESS) {
+ nrc = mk_connection_open_internal(sender,
+ first_header->peer.rem_addr_1,
+ first_header->peer.rem_addr_2,
+ MASTER_LINE_EP);
+ if (nrc == NW_SUCCESS)
+ nc_line_update(&first_header->peer, sender);
+ }
+ }
+ }
+ if (nrc == NW_SUCCESS) {
+ first_header->sender = sender;
+ first_header->options = options;
+ rc = (*(devct[dev].entry->rpc)) (sender, first_header, options);
+ if (rc != NULL && rc != NW_BUFFER_ERROR) {
+ rc = (nw_buffer_t) ((char *) rc - ecb->buf_start +
+ pv->buf_start);
+ } else if (rc == NULL && time_out != 0 && nw_free_waiter != NULL &&
+ (time_out == -1 || nw_free_waited != NULL)) {
+ w = nw_free_waiter;
+ nw_free_waiter = w->next;
+ w->waiter = current_thread();
+ w->next = NULL;
+ hecb = &hect[ep];
+ if (hecb->rx_last == NULL)
+ hecb->rx_first = hecb->rx_last = w;
+ else
+ hecb->rx_last = hecb->rx_last->next = w;
+ assert_wait(0, TRUE);
+ if (time_out != -1) {
+ waited = nw_free_waited;
+ nw_free_waited = waited->next;
+ waited->ep = ep;
+ waited->next = NULL;
+ current_thread()->nw_ep_waited = waited;
+ current_thread()->wait_result = NULL;
+ if (!current_thread()->timer.set)
+ thread_set_timeout(time_out);
+ } else {
+ current_thread()->nw_ep_waited = NULL;
+ }
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ }
+ }
+ }
+ nw_unlock();
+ return rc;
+}
+
+nw_buffer_t mk_select(u_int nep, nw_ep_t epp, int time_out) {
+ nw_buffer_t rc;
+ nw_pv_t pv;
+ int i;
+ nw_ep ep;
+ nw_ecb_t ecb;
+ nw_rx_header_t header;
+ nw_hecb_t hecb;
+ nw_waiter_t w, w_next;
+ nw_ep_owned_t waited;
+
+ if (invalid_user_access(current_task()->map, (vm_offset_t) epp,
+ (vm_offset_t) epp + nep*sizeof(nw_ep) - 1,
+ VM_PROT_READ)) {
+ rc = NW_BUFFER_ERROR;
+ } else {
+ nw_lock();
+ for (i = 0; i < nep; i++) {
+ ep = epp[i];
+ if (ep >= MAX_EP || (pv = hect[ep].pv) == NULL) {
+ rc = NW_BUFFER_ERROR;
+ break;
+ } else {
+ while (pv != NULL && pv->owner != current_task())
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = NW_BUFFER_ERROR;
+ break;
+ } else {
+ ecb = &ect[ep];
+ header = ecb->rx_first;
+ if (header != NULL) {
+ rc = (nw_buffer_t) ((char *) header->buffer - ecb->buf_start +
+ pv->buf_start);
+ ecb->rx_first = header->next;
+ if (ecb->rx_first == NULL)
+ ecb->rx_last = NULL;
+ nc_rx_header_deallocate(header);
+ break;
+ }
+ }
+ }
+ }
+ if (i == nep) {
+ if (time_out == 0) {
+ rc = NULL;
+ } else {
+ w = nw_free_waiter;
+ waited = nw_free_waited;
+ i = 0;
+ while (i < nep &&
+ nw_free_waiter != NULL && nw_free_waited != NULL) {
+ nw_free_waiter = nw_free_waiter->next;
+ nw_free_waited = nw_free_waited->next;
+ i++;
+ }
+ if (i < nep) {
+ nw_free_waiter = w;
+ nw_free_waited = waited;
+ rc = NW_BUFFER_ERROR;
+ } else {
+ current_thread()->nw_ep_waited = waited;
+ for (i = 0; i < nep; i++) {
+ ep = epp[i];
+ waited->ep = ep;
+ if (i < nep-1)
+ waited = waited->next;
+ else
+ waited->next = NULL;
+ w->waiter = current_thread();
+ w_next = w->next;
+ w->next = NULL;
+ hecb = &hect[ep];
+ if (hecb->rx_last == NULL)
+ hecb->rx_first = hecb->rx_last = w;
+ else
+ hecb->rx_last = hecb->rx_last->next = w;
+ w = w_next;
+ }
+ assert_wait(0, TRUE);
+ if (time_out != -1) {
+ current_thread()->wait_result = NULL;
+ if (!current_thread()->timer.set)
+ thread_set_timeout(time_out);
+ }
+ simple_unlock(&nw_simple_lock);
+ thread_block(mk_return);
+ }
+ }
+ }
+ nw_unlock();
+ }
+ return rc;
+}
+
+
+/*** System-dependent support ***/
+
+void mk_endpoint_collect(task_t task) {
+
+ while (task->nw_ep_owned != NULL) {
+ mk_endpoint_deallocate_internal(task->nw_ep_owned->ep, task, TRUE);
+ }
+}
+
+void mk_waited_collect(thread_t thread) {
+ nw_hecb_t hecb;
+ nw_waiter_t w, w_previous;
+ nw_ep_owned_t waited, waited_previous;
+
+ waited = thread->nw_ep_waited;
+ if (waited != NULL) {
+ while (waited != NULL) {
+ hecb = &hect[waited->ep];
+ w = hecb->rx_first;
+ w_previous = NULL;
+ while (w != NULL && w->waiter != thread) {
+ w_previous = w;
+ w = w->next;
+ }
+ if (w != NULL) {
+ if (w_previous == NULL)
+ hecb->rx_first = w->next;
+ else
+ w_previous->next = w->next;
+ if (w->next == NULL)
+ hecb->rx_last = w_previous;
+ w->next = nw_free_waiter;
+ nw_free_waiter = w;
+ }
+ waited_previous = waited;
+ waited = waited->next;
+ }
+ waited_previous->next = nw_free_waited;
+ nw_free_waited = thread->nw_ep_waited;
+ thread->nw_ep_waited = NULL;
+ }
+}
+
+void mk_return() {
+
+ thread_syscall_return(current_thread()->wait_result);
+}
+
+
+boolean_t mk_deliver_result(thread_t thread, int result) {
+ boolean_t rc;
+ int state, s;
+
+ s = splsched();
+ thread_lock(thread);
+ state = thread->state;
+
+ reset_timeout_check(&thread->timer);
+
+ switch (state & TH_SCHED_STATE) {
+ case TH_WAIT | TH_SUSP | TH_UNINT:
+ case TH_WAIT | TH_UNINT:
+ case TH_WAIT:
+ /*
+ * Sleeping and not suspendable - put on run queue.
+ */
+ thread->state = (state &~ TH_WAIT) | TH_RUN;
+ thread->wait_result = (kern_return_t) result;
+ simpler_thread_setrun(thread, TRUE);
+ rc = TRUE;
+ break;
+
+ case TH_WAIT | TH_SUSP:
+ case TH_RUN | TH_WAIT:
+ case TH_RUN | TH_WAIT | TH_SUSP:
+ case TH_RUN | TH_WAIT | TH_UNINT:
+ case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
+ /*
+ * Either already running, or suspended.
+ */
+ thread->state = state &~ TH_WAIT;
+ thread->wait_result = (kern_return_t) result;
+ rc = FALSE;
+ break;
+
+ default:
+ /*
+ * Not waiting.
+ */
+ rc = FALSE;
+ break;
+ }
+ thread_unlock(thread);
+ splx(s);
+ return rc;
+}
+
+
+boolean_t nc_deliver_result(nw_ep ep, nw_delivery type, int result) {
+ boolean_t rc;
+ nw_hecb_t hecb;
+ nw_ecb_t ecb;
+ nw_waiter_t w;
+ thread_t thread;
+ task_t task;
+ nw_pv_t pv;
+ nw_buffer_t buf;
+ nw_rx_header_t rx_header;
+ nw_tx_header_t tx_header;
+ nw_ep lep;
+
+ hecb = &hect[ep];
+ ecb = &ect[ep];
+
+ thread = NULL;
+ if (type == NW_RECEIVE || type == NW_RECEIVE_URGENT) {
+ w = hecb->rx_first;
+ if (w != NULL) {
+ thread = w->waiter;
+ hecb->rx_first = w->next;
+ if (hecb->rx_first == NULL)
+ hecb->rx_last = NULL;
+ w->next = nw_free_waiter;
+ nw_free_waiter = w;
+ task = thread->task;
+ pv = hecb->pv;
+ while (pv != NULL && pv->owner != task)
+ pv = pv->next;
+ if (pv == NULL) {
+ rc = FALSE;
+ } else {
+ buf = (nw_buffer_t) ((char *) result - ecb->buf_start + pv->buf_start);
+ rc = mk_deliver_result(thread, (int) buf);
+ }
+ } else {
+ rx_header = nc_rx_header_allocate();
+ if (rx_header == NULL) {
+ rc = FALSE;
+ } else {
+ rx_header->buffer = (nw_buffer_t) result;
+ if (type == NW_RECEIVE) {
+ rx_header->next = NULL;
+ if (ecb->rx_last == NULL)
+ ecb->rx_first = rx_header;
+ else
+ ecb->rx_last->next = rx_header;
+ ecb->rx_last = rx_header;
+ } else {
+ rx_header->next = ecb->rx_first;
+ if (ecb->rx_first == NULL)
+ ecb->rx_last = rx_header;
+ ecb->rx_first = rx_header;
+ }
+ rc = TRUE;
+ }
+ }
+ } else if (type == NW_SEND) {
+ w = hecb->tx_first;
+ if (w == NULL) {
+ rc = FALSE;
+ } else {
+ thread = w->waiter;
+ hecb->tx_first = w->next;
+ if (hecb->tx_first == NULL)
+ hecb->tx_last = NULL;
+ w->next = nw_free_waiter;
+ nw_free_waiter = w;
+ rc = mk_deliver_result(thread, result);
+ }
+ tx_header = ect[ep].tx_initial;
+ if (result == NW_SUCCESS) {
+ lep = tx_header->peer.local_ep;
+ while (tx_header != NULL) {
+ if (tx_header->buffer != NULL)
+ nc_buffer_deallocate(lep, tx_header->buffer);
+ tx_header = tx_header->next;
+ }
+ }
+ nc_tx_header_deallocate(ect[ep].tx_initial);
+ ect[ep].tx_initial = ect[ep].tx_current = NULL;
+ } else if (type == NW_SIGNAL) {
+ thread = hecb->sig_waiter;
+ hecb->sig_waiter = NULL;
+ if (thread == NULL) {
+ rc = FALSE;
+ } else {
+ rc = mk_deliver_result(thread, result);
+ }
+ }
+ return rc;
+}
+
+int mk_fast_sweep() {
+
+ nw_lock();
+ nc_fast_sweep();
+ nw_unlock();
+ return 0;
+}
+
+void h_fast_timer_set() {
+
+#ifdef PRODUCTION
+ if (!nw_fast_timer.set)
+ set_timeout(&nw_fast_timer, 1);
+#endif
+}
+
+void h_fast_timer_reset() {
+
+ if (nw_fast_timer.set)
+ reset_timeout(&nw_fast_timer);
+}
+
+int mk_slow_sweep() {
+
+#ifdef PRODUCTION
+ nw_lock();
+ nc_slow_sweep();
+ nw_unlock();
+ set_timeout(&nw_slow_timer, 2*hz);
+ return 0;
+#endif
+}
+
diff --git a/chips/nw_mk.h b/chips/nw_mk.h
new file mode 100644
index 00000000..d7ba503d
--- /dev/null
+++ b/chips/nw_mk.h
@@ -0,0 +1,97 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _NW_MK_H_
+#define _NW_MK_H_ 1
+
+#ifndef STUB
+#include <chips/nw.h>
+#include <kern/thread.h>
+#else
+#include "nw.h"
+#include "stub.h"
+#endif
+
+/*** NETWORK INTERFACE -- WRAPPER FOR MACH KERNEL ***/
+
+/*** User-trappable functions ***/
+
+extern nw_result mk_update(mach_port_t master_port, nw_update_type up_type,
+ int *up_info);
+
+extern nw_result mk_lookup(nw_lookup_type lt, int *look_info);
+
+extern nw_result mk_endpoint_allocate(nw_ep_t epp, nw_protocol protocol,
+ nw_acceptance accept, u_int buffer_size);
+
+extern nw_result mk_endpoint_deallocate(nw_ep ep);
+
+extern nw_buffer_t mk_buffer_allocate(nw_ep ep, u_int size);
+
+extern nw_result mk_buffer_deallocate(nw_ep ep, nw_buffer_t buffer);
+
+extern nw_result mk_connection_open(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+extern nw_result mk_connection_accept(nw_ep ep, nw_buffer_t msg,
+ nw_ep_t new_epp);
+
+extern nw_result mk_connection_close(nw_ep ep);
+
+extern nw_result mk_multicast_add(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+extern nw_result mk_multicast_drop(nw_ep local_ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+extern nw_result mk_endpoint_status(nw_ep ep, nw_state_t state,
+ nw_peer_t peer);
+
+extern nw_result mk_send(nw_ep ep, nw_buffer_t msg, nw_options options);
+
+extern nw_buffer_t mk_receive(nw_ep ep, int time_out);
+
+extern nw_buffer_t mk_rpc(nw_ep ep, nw_buffer_t send_msg,
+ nw_options options, int time_out);
+
+extern nw_buffer_t mk_select(u_int nep, nw_ep_t epp, int time_out);
+
+
+/*** System-dependent support ***/
+
+extern void mk_endpoint_collect(task_t task);
+
+extern void mk_waited_collect(thread_t thread);
+
+extern void mk_return();
+
+extern boolean_t mk_deliver_result(thread_t thread, int result);
+
+extern int mk_fast_sweep();
+
+extern int mk_slow_sweep();
+
+#endif /* _NW_MK_H_ */
diff --git a/chips/pm_defs.h b/chips/pm_defs.h
new file mode 100644
index 00000000..623f65ec
--- /dev/null
+++ b/chips/pm_defs.h
@@ -0,0 +1,57 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: pm_defs.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Definitions specific to the "pm" simple framebuffer driver,
+ * exported across sub-modules. Some other framebuffer drivers
+ * that share code with pm use these defs also.
+ */
+
+/* Hardware state (to be held in the screen descriptor) */
+
+typedef struct {
+ char *cursor_registers; /* opaque, for sharing */
+ unsigned short cursor_state; /* some regs are W-only */
+ short unused; /* padding, free */
+ char *vdac_registers; /* opaque, for sharing */
+ unsigned char *framebuffer;
+ unsigned char *plane_mask;
+} pm_softc_t;
+
+extern pm_softc_t *pm_alloc(/* unit, curs, framebuf, planem */);
+
+/* user mapping sizes */
+#define USER_INFO_SIZE PAGE_SIZE
+#define PMASK_SIZE PAGE_SIZE
+#define BITMAP_SIZE(sc) \
+ ((sc)->frame_height * (((sc)->flags & COLOR_SCREEN) ? \
+ sc->frame_scanline_width : \
+ sc->frame_scanline_width>>3))
+
+#define PM_SIZE(sc) (USER_INFO_SIZE+PMASK_SIZE+BITMAP_SIZE(sc))
diff --git a/chips/pm_hdw.c b/chips/pm_hdw.c
new file mode 100644
index 00000000..8ac94925
--- /dev/null
+++ b/chips/pm_hdw.c
@@ -0,0 +1,201 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: pm_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Driver for the VFB01/02 Mono/Color framebuffer (pmax)
+ * Hardware-level operations.
+ */
+
+#include <bm.h>
+#if NBM>0
+#include <platforms.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+#include <chips/busses.h>
+#include <machine/machspl.h>
+
+#ifdef DECSTATION
+#include <mips/mips_cpu.h>
+#include <mips/PMAX/kn01.h>
+
+#define KN01_CSR_ADDR PHYS_TO_K1SEG(KN01_SYS_CSR)
+#define KN01_FBUF_ADDR PHYS_TO_K1SEG(KN01_PHYS_FBUF_START)
+#define KN01_PLM_ADDR PHYS_TO_K1SEG(KN01_PHYS_COLMASK_START)
+#define KN01_BT478_ADDR PHYS_TO_K1SEG(KN01_SYS_VDAC)
+#define KN01_DC503_ADDR PHYS_TO_K1SEG(KN01_SYS_PCC)
+
+#define VRETRACE dc503_vretrace
+#define MONO_FRAME_WIDTH 2048
+#define ISA_MONO ((*(volatile short*)KN01_CSR_ADDR)&KN01_CSR_MONO)
+
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#include <vax/ka3100.h>
+#define VRETRACE ka42_vretrace
+#define ISA_MONO 1
+#define MONO_FRAME_WIDTH 1024
+#endif /*VAXSTATION*/
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int pm_probe(), pm_intr();
+static void pm_attach();
+
+vm_offset_t pm_std[] = { 0 };
+struct bus_device *pm_info[1];
+struct bus_driver pm_driver =
+ { pm_probe, 0, pm_attach, 0, pm_std, "pm", pm_info, };
+
+/*
+ * Probe/Attach functions
+ */
+
+pm_probe( /* reg, ui */)
+{
+ static probed_once = 0;
+#ifdef DECSTATION
+ if (!isa_pmax())
+ return 0;
+ if (check_memory(KN01_FBUF_ADDR, 0))
+ return 0;
+#endif /*DECSTATION*/
+ if (probed_once++ > 1)
+ printf("[mappable] ");
+ return 1;
+}
+
+static void
+pm_attach(ui)
+ struct bus_device *ui;
+{
+ int isa_mono = ISA_MONO;
+
+ printf(": %s%s",
+ isa_mono ? "monochrome" : "color",
+ " display");
+}
+
+
+/*
+ * Interrupt routine
+ */
+#ifdef DECSTATION
+pm_intr(unit,spllevel)
+ spl_t spllevel;
+{
+ /* this is the vertical retrace one */
+ splx(spllevel);
+ lk201_led(unit);
+}
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+pm_intr(unit)
+{
+ lk201_led(unit);
+}
+#endif /*VAXSTATION*/
+
+/*
+ * Boot time initialization: must make device
+ * usable as console asap.
+ */
+extern int
+ pm_cons_init(), pm_soft_reset(),
+ dc503_video_on(), dc503_video_off(),
+ pm_char_paint(), dc503_pos_cursor(),
+ pm_insert_line(), pm_remove_line(), pm_clear_bitmap(),
+ pm_set_status(), pm_get_status(),
+ VRETRACE(), pm_map_page();
+
+static struct screen_switch pm_sw = {
+ screen_noop, /* graphic_open */
+ pm_soft_reset, /* graphic_close */
+ pm_set_status, /* set_status */
+ pm_get_status, /* set_status */
+ pm_char_paint, /* char_paint */
+ dc503_pos_cursor, /* pos_cursor */
+ pm_insert_line, /* insert_line */
+ pm_remove_line, /* remove_line */
+ pm_clear_bitmap, /* clear_bitmap */
+ dc503_video_on, /* video_on */
+ dc503_video_off, /* video_off */
+ VRETRACE, /* enable vert retrace intr */
+ pm_map_page /* map_page */
+};
+
+pm_cold_init(unit, up)
+ user_info_t *up;
+{
+ pm_softc_t *pm;
+ screen_softc_t sc = screen(unit);
+ int isa_mono = ISA_MONO;
+
+ bcopy(&pm_sw, &sc->sw, sizeof(sc->sw));
+ if (isa_mono) {
+ sc->flags |= MONO_SCREEN;
+ sc->frame_scanline_width = MONO_FRAME_WIDTH;
+ } else {
+ sc->flags |= COLOR_SCREEN;
+ sc->frame_scanline_width = 1024;
+ }
+ sc->frame_height = 864;
+ sc->frame_visible_width = 1024;
+ sc->frame_visible_height = 864;
+
+ pm_init_screen_params(sc, up);
+ (void) screen_up(unit, up);
+
+#ifdef DECSTATION
+ pm = pm_alloc(unit, KN01_DC503_ADDR, KN01_FBUF_ADDR, KN01_PLM_ADDR);
+ pm->vdac_registers = (char*)KN01_BT478_ADDR;
+#endif /*DECSTATION*/
+#ifdef VAXSTATION
+ pm = pm_alloc(unit, cur_xxx, bm_mem, 0);
+#endif /*VAXSTATION*/
+
+ screen_default_colors(up);
+
+ dc503_init(pm);
+
+ pm_soft_reset(sc);
+
+ /*
+ * Clearing the screen at boot saves from scrolling
+ * much, and speeds up booting quite a bit.
+ */
+ screen_blitc( unit, 'C'-'@');/* clear screen */
+}
+
+#endif NBM>0
diff --git a/chips/pm_misc.c b/chips/pm_misc.c
new file mode 100644
index 00000000..d423645b
--- /dev/null
+++ b/chips/pm_misc.c
@@ -0,0 +1,594 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: pm_misc.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Driver for the VFB01/02 Mono/Color framebuffer (pmax)
+ * Hardware-independent operations, mostly shared with
+ * the CFB driver (see each individual function header),
+ * and possibly others.
+ */
+
+
+#include <platforms.h>
+
+#include <fb.h>
+
+#if defined(DECSTATION) || defined(FLAMINGO)
+#include <cfb.h>
+#include <mfb.h>
+#include <xcfb.h>
+#include <sfb.h>
+#define NPM (NFB+NCFB+NMFB+NXCFB+NSFB)
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#define NPM (NFB)
+#endif /*VAXSTATION*/
+
+
+#if (NPM > 0)
+
+#include <mach/vm_param.h> /* PAGE_SIZE */
+#include <device/device_types.h>
+#include <vm/vm_map.h> /* kernel_pmap */
+
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+
+
+#ifdef DECSTATION
+#define machine_btop mips_btop
+#define MONO_BM (256*1024)
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#define machine_btop vax_btop
+/*
+ For now we use the last page of the frame for
+ the user_info structure.
+*/
+#define MONO_BM (256*1024-PAGE_SIZE)
+#endif /*VAXSTATION*/
+
+#ifdef FLAMINGO
+#define machine_btop alpha_btop
+#define MONO_BM (256*1024)
+#define LOG2_SIZEOF_LONG 3 /* 64bit archies */
+#endif /* FLAMINGO */
+
+#ifndef LOG2_SIZEOF_LONG
+#define LOG2_SIZEOF_LONG 2 /* 32bit archies */
+#endif
+
+
+/* Hardware state */
+pm_softc_t pm_softc_data[NPM];
+
+pm_softc_t*
+pm_alloc(
+ int unit,
+ char *cur,
+ unsigned char *fb,
+ unsigned char *pl)
+{
+ pm_softc_t *pm = &pm_softc_data[unit];
+
+ pm->cursor_registers = cur;
+ pm->framebuffer = fb;
+ pm->plane_mask = pl;
+ pm->vdac_registers = 0; /* later, if ever */
+
+ screen_attach(unit, (char *) pm);
+
+ return pm;
+}
+
+
+/*
+ * Routine to paint a char on a simple framebuffer.
+ * This is common to the pm, fb and cfb drivers.
+ */
+pm_char_paint(
+ screen_softc_t sc,
+ int c,
+ int row,
+ int col)
+{
+ register int incr;
+ int line_size;
+ register unsigned char *font, *bmap;
+ pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
+
+ /*
+ * Here are the magic numbers that drive the loops below:
+ * incr bytes between scanlines of the glyph
+ * line_size bytes in a row, using the system font
+ *
+ * This code has been optimized to avoid multiplications,
+ * and is therefore much less obvious than it could be.
+ */
+ if (sc->flags & MONO_SCREEN) {
+ /*
+ * B&W screen: 1 bit/pixel
+ * incr --> 1 * BytesPerLine, with possible stride
+ */
+ incr = sc->frame_scanline_width >> 3;
+ } else {
+ /*
+ * Color screen: 8 bits/pixel
+ * incr --> 8 * BytesPerLine, with possible stride
+ */
+ incr = sc->frame_scanline_width;
+ col <<= 3;
+ }
+
+ /* not all compilers are smart about multiply by 15 */
+#if (KfontHeight==15)
+# define TIMES_KfontHeight(w) (((w)<<4)-(w))
+#else
+# define TIMES_KfontHeight(w) ((w)*KfontHeight)
+#endif
+ line_size = TIMES_KfontHeight(incr);
+
+ bmap = pm->framebuffer + col + (row * line_size);
+ font = &kfont_7x14[ (int)(c - ' ') * 15];
+ if (sc->flags & MONO_SCREEN) {
+ /*
+ * Unroll simple loops, take note of common cases
+ */
+ if (sc->standout) {
+# define mv() *bmap = ~*font++; bmap += incr;
+ mv();mv();mv();mv();mv();mv();mv();mv();
+ mv();mv();mv();mv();mv();mv();mv();
+# undef mv
+ } else if (c == ' ') {
+# define mv() *bmap = 0; bmap += incr;
+ mv();mv();mv();mv();mv();mv();mv();mv();
+ mv();mv();mv();mv();mv();mv();mv();
+# undef mv
+ } else {
+# define mv() *bmap = *font++; bmap += incr;
+ mv();mv();mv();mv();mv();mv();mv();mv();
+ mv();mv();mv();mv();mv();mv();mv();
+# undef mv
+ }
+ } else {
+ /*
+ * 8 bits per pixel --> paint one byte per each font bit.
+ * In order to spread out the 8 bits of a glyph line over
+ * the 64 bits per scanline use a simple vector multiply,
+ * taking 4 bits at a time to get the two resulting words
+ */
+ static unsigned int spread[16] = {
+ 0x00000000, 0x00000001, 0x00000100, 0x00000101,
+ 0x00010000, 0x00010001, 0x00010100, 0x00010101,
+ 0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ 0x01010000, 0x01010001, 0x01010100, 0x01010101,
+ };
+ register int rev_video = sc->standout;
+ register int j;
+ for (j = 0; j < KfontHeight; j++) {
+ register unsigned char c = *font++;
+ if (rev_video) c = ~c;
+#if (LOG2_SIZEOF_LONG==3)
+ *((long*)bmap) = (long)spread[ c & 0xf ] |
+ ((long)(spread[ (c>>4) & 0xf ]) << 32);
+#else
+ ((int*)bmap)[0] = spread[ c & 0xf ];
+ ((int*)bmap)[1] = spread[ (c>>4) & 0xf ];
+#endif
+ bmap += incr;
+ }
+ }
+}
+
+/*
+ * Delete the line at the given row.
+ * This is common to the pm, fb and cfb drivers.
+ */
+pm_remove_line(
+ screen_softc_t sc,
+ short row)
+{
+ register long *dest, *src;
+ register long *end;
+ register long temp0,temp1,temp2,temp3;
+ register long i, scaninc, blockcnt;
+ long line_size, incr;
+ unsigned char *framebuffer;
+ pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
+ long CharRows, CharCols;
+
+ CharRows = sc->up->max_row;
+ CharCols = sc->up->max_col;
+ framebuffer = pm->framebuffer;
+
+ /* Inner loop works 4 long words at a time (writebuffer deep) */
+# define BlockSizeShift (2+LOG2_SIZEOF_LONG)
+
+ /* To copy one (MONO) line, we need to iterate this many times */
+# define Blocks (CharCols>>BlockSizeShift)
+
+ /* Skip this many bytes to get to the next line */
+# define Slop(w) ((w) - (blockcnt<<BlockSizeShift))
+
+ if (sc->flags & MONO_SCREEN) {
+ blockcnt = Blocks;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width >> 3;
+ } else {
+ blockcnt = Blocks << 3;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width;
+ }
+ line_size = TIMES_KfontHeight(incr);
+
+ scaninc = (Slop(incr)) >> LOG2_SIZEOF_LONG; /* pointers are long* */
+
+ dest = (long *)(framebuffer + row * line_size);
+ src = (long *)((char*)dest + line_size);
+ end = (long *)(framebuffer + CharRows * line_size);
+ while (src < end) {
+ i = 0;
+ do {
+ temp0 = src[0];
+ temp1 = src[1];
+ temp2 = src[2];
+ temp3 = src[3];
+ dest[0] = temp0;
+ dest[1] = temp1;
+ dest[2] = temp2;
+ dest[3] = temp3;
+ dest += 4;
+ src += 4;
+ i++;
+ } while (i < blockcnt);
+ src += scaninc;
+ dest += scaninc;
+ }
+
+ /* Now zero out the last line */
+ bzero(framebuffer + (CharRows - 1) * line_size, line_size);
+
+ ascii_screen_rem_update(sc, row);
+}
+
+
+/*
+ * Open a new blank line at the given row.
+ * This is common to the pm, fb and cfb drivers.
+ */
+pm_insert_line(
+ screen_softc_t sc,
+ short row)
+{
+ register long *dest, *src;
+ register long *end;
+ register long temp0,temp1,temp2,temp3;
+ register long i, scaninc, blockcnt;
+ long line_size, incr;
+ unsigned char *framebuffer;
+ pm_softc_t *pm = (pm_softc_t*)sc->hw_state;
+ long CharRows, CharCols;
+
+ CharRows = sc->up->max_row;
+ CharCols = sc->up->max_col;
+
+ framebuffer = pm->framebuffer;
+
+ /* See above for comments */
+ if (sc->flags & MONO_SCREEN) {
+ blockcnt = Blocks;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width >> 3;
+ } else {
+ blockcnt = Blocks << 3;
+ /* See comments in pm_char_paint() */
+ incr = sc->frame_scanline_width;
+ }
+ line_size = TIMES_KfontHeight(incr);
+
+ scaninc = Slop(incr) + ((2 * blockcnt) << BlockSizeShift);
+ scaninc >>= LOG2_SIZEOF_LONG; /* pointers are long* */
+ dest = (long *)(framebuffer + (CharRows - 1) * line_size);
+ src = (long *)((char*)dest - line_size);
+ end = (long *)(framebuffer + row * line_size);
+ while (src >= end) {
+ i = 0;
+ do {
+ temp0 = src[0];
+ temp1 = src[1];
+ temp2 = src[2];
+ temp3 = src[3];
+ dest[0] = temp0;
+ dest[1] = temp1;
+ dest[2] = temp2;
+ dest[3] = temp3;
+ dest += 4;
+ src += 4;
+ i++;
+ } while (i < blockcnt);
+ src -= scaninc;
+ dest -= scaninc;
+ }
+
+ /* Now zero out the line being opened */
+ bzero(framebuffer + row * line_size, line_size);
+
+ ascii_screen_ins_update(sc, row);
+}
+
+#undef Slop
+
+
+/*
+ * Initialize screen parameters in the
+ * user-mapped descriptor.
+ * This is common to various drivers.
+ */
+pm_init_screen_params(
+ screen_softc_t sc,
+ user_info_t *up)
+{
+ register int vis_x, vis_y;
+
+ up->frame_scanline_width = sc->frame_scanline_width;
+ up->frame_height = sc->frame_height;
+
+ vis_x = sc->frame_visible_width;
+ vis_y = sc->frame_visible_height;
+
+ up->max_x = vis_x;
+ up->max_y = vis_y;
+ up->max_cur_x = vis_x - 1;
+ up->max_cur_y = vis_y - 1;
+ up->min_cur_x = -15;
+ up->min_cur_y = -15;
+ up->max_row = vis_y / KfontHeight;
+ up->max_col = vis_x / KfontWidth;
+
+ up->version = 11;
+
+ up->mouse_threshold = 4;
+ up->mouse_scale = 2;
+
+ up->dev_dep_2.pm.tablet_scale_x = ((vis_x - 1) * 1000) / 2200;
+ up->dev_dep_2.pm.tablet_scale_y = ((vis_y - 1) * 1000) / 2200;
+}
+
+/*
+ * Clear the screen
+ * Used by pm, fb and cfb
+ */
+pm_clear_bitmap(
+ screen_softc_t sc)
+{
+ pm_softc_t *pm = (pm_softc_t *) sc->hw_state;
+ unsigned int screen_size;
+
+ /* Do not touch the non visible part */
+ screen_size = sc->frame_scanline_width * sc->frame_visible_height;
+ blkclr((char *)pm->framebuffer,
+ (sc->flags & MONO_SCREEN) ? (screen_size>>3) : screen_size);
+
+ /* clear ascii screenmap */
+ ascii_screen_fill(sc, ' ');
+}
+
+
+/*
+ * Size of the user-mapped structure
+ * Used by both pm and cfb
+ */
+pm_mem_need()
+{
+ return USER_INFO_SIZE;
+}
+
+/*
+ * Device-specific get status.
+ * Used by fb and cfb also.
+ */
+pm_get_status(
+ screen_softc_t sc,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t *status_count)
+{
+ if (flavor == SCREEN_GET_OFFSETS) {
+ unsigned *offs = (unsigned *) status;
+
+ offs[0] = PM_SIZE(sc); /* virtual size */
+ offs[1] = 0; /* offset of user_info_t */
+ *status_count = 2;
+ return D_SUCCESS;
+ } else
+ return D_INVALID_OPERATION;
+}
+
+/*
+ * Driver-specific set status
+ * Only partially used by fb and cfb.
+ */
+pm_set_status(
+ screen_softc_t sc,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ switch (flavor) {
+ case SCREEN_ADJ_MAPPED_INFO: {
+ unsigned user_addr = *(unsigned *) status;
+ user_info_t *up = sc->up;
+
+ /* Make it point to the event_queue, in user virtual */
+ up->evque.events = (screen_event_t *)(user_addr +
+ ((char*)up->event_queue - (char*)up));
+
+ /* Make it point to the point_track, in user virtual */
+ up->evque.track = (screen_timed_point_t *)(user_addr +
+ ((char*)up->point_track - (char*)up));
+
+ up->dev_dep_1.pm.planemask = (unsigned char *)(user_addr + USER_INFO_SIZE);
+
+ up->dev_dep_1.pm.bitmap = up->dev_dep_1.pm.planemask + PMASK_SIZE;
+
+ break;
+ }
+
+ case SCREEN_LOAD_CURSOR: {
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ dc503_load_cursor(sc->hw_state, (unsigned short*)status);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+#ifdef DECSTATION
+ case SCREEN_SET_CURSOR_COLOR: {
+ pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt478_cursor_color (pm->vdac_registers, (cursor_color_t*) status);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+ case SCREEN_SET_CMAP_ENTRY: {
+ pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
+ color_map_entry_t *e = (color_map_entry_t*) status;
+
+ if (e->index < 256) {
+ sc->flags |= SCREEN_BEING_UPDATED;
+ bt478_load_colormap_entry( pm->vdac_registers, e->index, &e->value);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+ }
+
+ break;
+ }
+#endif /*DECSTATION*/
+ default:
+ return D_INVALID_OPERATION;
+ }
+ return D_SUCCESS;
+}
+
+/*
+ * Map pages to user space
+ */
+vm_offset_t pm_map_page_empty = (vm_offset_t) 0;
+
+integer_t
+pm_map_page(
+ screen_softc_t sc,
+ vm_offset_t off,
+ int prot)
+{
+ int bitmapsize;
+ integer_t addr;
+ pm_softc_t *pm = (pm_softc_t *)sc->hw_state;
+ extern vm_offset_t pmap_extract( pmap_t map, vm_offset_t addr);
+
+ bitmapsize = BITMAP_SIZE(sc);
+
+#define OFF0 USER_INFO_SIZE /* user mapped info */
+#define OFF1 OFF0+PMASK_SIZE /* plane mask register */
+#define OFF2 OFF1+bitmapsize /* frame buffer mem */
+
+ if (off < OFF0)
+#ifdef DECSTATION
+ addr = kvtophys(sc->up);
+#else
+ addr = (integer_t) pmap_extract(kernel_pmap,
+ (vm_offset_t)sc->up);
+#endif
+ else
+ if (off < OFF1) {
+#ifdef VAXSTATION
+ if (pm_map_page_empty == 0) {
+ pm_map_page_empty = vm_page_grab_phys_addr();
+ }
+ addr = (integer_t)pmap_extract(kernel_pmap, pm_map_page_empty);
+#else
+ addr = (integer_t) pm->plane_mask;
+#endif
+ off -= OFF0;
+ } else
+ if (off < OFF2) {
+#ifdef DECSTATION
+ addr = (integer_t)pm->framebuffer;
+#else
+ addr = (integer_t)pmap_extract(kernel_pmap,
+ (vm_offset_t)pm->framebuffer);
+#endif
+ off -= OFF1;
+ } else
+ return D_INVALID_SIZE; /* ??? */
+
+ addr = machine_btop(addr + off);
+ return (addr);
+}
+
+
+/*
+ *-----------------------------------------------------------
+ * The rest of this file is stricly pmax/pvax-specific
+ *-----------------------------------------------------------
+ */
+#if (NFB > 0)
+
+/*
+ * Do what's needed when the X server exits
+ */
+pm_soft_reset(
+ screen_softc_t sc)
+{
+ pm_softc_t *pm = (pm_softc_t*) sc->hw_state;
+ user_info_t *up = sc->up;
+
+ /*
+ * Restore params in mapped structure
+ */
+ pm_init_screen_params(sc, up);
+ up->row = up->max_row - 2;
+ dc503_init(pm);
+
+#ifdef DECSTATION
+ if (sc->flags & MONO_SCREEN)
+ bt478_init_bw_map(pm->vdac_registers, pm->plane_mask);
+ else
+ bt478_init_color_map(pm->vdac_registers, pm->plane_mask);
+#endif /*DECSTATION*/
+}
+#endif /* NFB > 0 */
+
+
+#endif /* NPM > 0 */
diff --git a/chips/scc_8530.h b/chips/scc_8530.h
new file mode 100644
index 00000000..96a7964e
--- /dev/null
+++ b/chips/scc_8530.h
@@ -0,0 +1,355 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: scc_8530.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 6/91
+ *
+ * Definitions for the Zilog Z8530 SCC serial line chip
+ */
+
+#ifndef _SCC_8530_H_
+#define _SCC_8530_H_
+
+/*
+ * Register map, needs definition of the alignment
+ * used on the specific machine.
+ * #define the 'scc_register_t' data type before
+ * including this header file. For restrictions on
+ * access modes define the set/get_datum macros.
+ * We provide defaults ifnot.
+ */
+
+#ifndef scc_register_t
+
+typedef struct scc_register {
+ volatile unsigned char datum;
+} scc_register_t;
+
+#endif
+
+
+#define SCC_CHANNEL_A 1
+#define SCC_CHANNEL_B 0
+
+typedef struct {
+ /* Channel B is first, then A */
+ struct {
+ scc_register_t scc_command; /* reg select */
+ scc_register_t scc_data; /* Rx/Tx buffer */
+ } scc_channel[2];
+} scc_regmap_t;
+
+
+#ifndef scc_set_datum
+#define scc_set_datum(d,v) (d) = (v)
+#define scc_get_datum(d,v) (v) = (d)
+#endif
+
+#define scc_init_reg(scc,chan) { \
+ char tmp; \
+ scc_get_datum((scc)->scc_channel[(chan)].scc_command.datum,tmp); \
+ scc_get_datum((scc)->scc_channel[(chan)].scc_command.datum,tmp); \
+ }
+
+#define scc_read_reg(scc,chan,reg,val) { \
+ scc_set_datum((scc)->scc_channel[(chan)].scc_command.datum,reg); \
+ scc_get_datum((scc)->scc_channel[(chan)].scc_command.datum,val); \
+ }
+
+#define scc_read_reg_zero(scc,chan,val) { \
+ scc_get_datum((scc)->scc_channel[(chan)].scc_command.datum,val); \
+ }
+
+#define scc_write_reg(scc,chan,reg,val) { \
+ scc_set_datum((scc)->scc_channel[(chan)].scc_command.datum,reg); \
+ scc_set_datum((scc)->scc_channel[(chan)].scc_command.datum,val); \
+ }
+
+#define scc_write_reg_zero(scc,chan,val) { \
+ scc_set_datum((scc)->scc_channel[(chan)].scc_command.datum,val); \
+ }
+
+#define scc_read_data(scc,chan,val) { \
+ scc_get_datum((scc)->scc_channel[(chan)].scc_data.datum,val); \
+ }
+
+#define scc_write_data(scc,chan,val) { \
+ scc_set_datum((scc)->scc_channel[(chan)].scc_data.datum,val); \
+ }
+
+/*
+ * Addressable registers
+ */
+
+#define SCC_RR0 0 /* status register */
+#define SCC_RR1 1 /* special receive conditions */
+#define SCC_RR2 2 /* (modified) interrupt vector */
+#define SCC_RR3 3 /* interrupts pending (cha A only) */
+#define SCC_RR8 8 /* recv buffer (alias for data) */
+#define SCC_RR10 10 /* sdlc status */
+#define SCC_RR12 12 /* BRG constant, low part */
+#define SCC_RR13 13 /* BRG constant, high part */
+#define SCC_RR15 15 /* interrupts currently enabled */
+
+#define SCC_WR0 0 /* reg select, and commands */
+#define SCC_WR1 1 /* interrupt and DMA enables */
+#define SCC_WR2 2 /* interrupt vector */
+#define SCC_WR3 3 /* receiver params and enables */
+#define SCC_WR4 4 /* clock/char/parity params */
+#define SCC_WR5 5 /* xmit params and enables */
+#define SCC_WR6 6 /* synchr SYNCH/address */
+#define SCC_WR7 7 /* synchr SYNCH/flag */
+#define SCC_WR8 8 /* xmit buffer (alias for data) */
+#define SCC_WR9 9 /* vectoring and resets */
+#define SCC_WR10 10 /* synchr params */
+#define SCC_WR11 11 /* clocking definitions */
+#define SCC_WR12 12 /* BRG constant, low part */
+#define SCC_WR13 13 /* BRG constant, high part */
+#define SCC_WR14 14 /* BRG enables and commands */
+#define SCC_WR15 15 /* interrupt enables */
+
+/*
+ * Read registers defines
+ */
+
+#define SCC_RR0_BREAK 0x80 /* break detected (rings twice), or */
+#define SCC_RR0_ABORT 0x80 /* abort (synchr) */
+#define SCC_RR0_TX_UNDERRUN 0x40 /* xmit buffer empty/end of message */
+#define SCC_RR0_CTS 0x20 /* clear-to-send pin active (sampled
+ only on intr and after RESI cmd */
+#define SCC_RR0_SYNCH 0x10 /* SYNCH found/still hunting */
+#define SCC_RR0_DCD 0x08 /* carrier-detect (same as CTS) */
+#define SCC_RR0_TX_EMPTY 0x04 /* xmit buffer empty */
+#define SCC_RR0_ZERO_COUNT 0x02 /* ? */
+#define SCC_RR0_RX_AVAIL 0x01 /* recv fifo not empty */
+
+#define SCC_RR1_EOF 0x80 /* end-of-frame, SDLC mode */
+#define SCC_RR1_CRC_ERR 0x40 /* incorrect CRC or.. */
+#define SCC_RR1_FRAME_ERR 0x40 /* ..bad frame */
+#define SCC_RR1_RX_OVERRUN 0x20 /* rcv fifo overflow */
+#define SCC_RR1_PARITY_ERR 0x10 /* incorrect parity in data */
+#define SCC_RR1_RESIDUE0 0x08
+#define SCC_RR1_RESIDUE1 0x04
+#define SCC_RR1_RESIDUE2 0x02
+#define SCC_RR1_ALL_SENT 0x01
+
+/* RR2 contains the interrupt vector unmodified (channel A) or
+ modified as follows (channel B, if vector-include-status) */
+
+#define SCC_RR2_STATUS(val) ((val)&0xf)
+
+#define SCC_RR2_B_XMIT_DONE 0x0
+#define SCC_RR2_B_EXT_STATUS 0x2
+#define SCC_RR2_B_RECV_DONE 0x4
+#define SCC_RR2_B_RECV_SPECIAL 0x6
+#define SCC_RR2_A_XMIT_DONE 0x8
+#define SCC_RR2_A_EXT_STATUS 0xa
+#define SCC_RR2_A_RECV_DONE 0xc
+#define SCC_RR2_A_RECV_SPECIAL 0xe
+
+/* Interrupts pending, to be read from channel A only (B raz) */
+#define SCC_RR3_zero 0xc0
+#define SCC_RR3_RX_IP_A 0x20
+#define SCC_RR3_TX_IP_A 0x10
+#define SCC_RR3_EXT_IP_A 0x08
+#define SCC_RR3_RX_IP_B 0x04
+#define SCC_RR3_TX_IP_B 0x02
+#define SCC_RR3_EXT_IP_B 0x01
+
+/* RR8 is the receive data buffer, a 3 deep FIFO */
+#define SCC_RECV_BUFFER SCC_RR8
+#define SCC_RECV_FIFO_DEEP 3
+
+#define SCC_RR10_1CLKS 0x80
+#define SCC_RR10_2CLKS 0x40
+#define SCC_RR10_zero 0x2d
+#define SCC_RR10_LOOP_SND 0x10
+#define SCC_RR10_ON_LOOP 0x02
+
+/* RR12/RR13 hold the timing base, upper byte in RR13 */
+
+#define scc_get_timing_base(scc,chan,val) { \
+ register char tmp; \
+ scc_read_reg(scc,chan,SCC_RR12,val);\
+ scc_read_reg(scc,chan,SCC_RR13,tmp);\
+ (val) = ((val)<<8)|(tmp&0xff);\
+ }
+
+#define SCC_RR15_BREAK_IE 0x80
+#define SCC_RR15_TX_UNDERRUN_IE 0x40
+#define SCC_RR15_CTS_IE 0x20
+#define SCC_RR15_SYNCH_IE 0x10
+#define SCC_RR15_DCD_IE 0x08
+#define SCC_RR15_zero 0x05
+#define SCC_RR15_ZERO_COUNT_IE 0x02
+
+
+/*
+ * Write registers defines
+ */
+
+/* WR0 is used for commands too */
+#define SCC_RESET_TXURUN_LATCH 0xc0
+#define SCC_RESET_TX_CRC 0x80
+#define SCC_RESET_RX_CRC 0x40
+#define SCC_RESET_HIGHEST_IUS 0x38 /* channel A only */
+#define SCC_RESET_ERROR 0x30
+#define SCC_RESET_TX_IP 0x28
+#define SCC_IE_NEXT_CHAR 0x20
+#define SCC_SEND_SDLC_ABORT 0x18
+#define SCC_RESET_EXT_IP 0x10
+
+#define SCC_WR1_DMA_ENABLE 0x80 /* dma control */
+#define SCC_WR1_DMA_MODE 0x40 /* drive ~req for DMA controller */
+#define SCC_WR1_DMA_RECV_DATA 0x20 /* from wire to host memory */
+ /* interrupt enable/conditions */
+#define SCC_WR1_RXI_SPECIAL_O 0x18 /* on special only */
+#define SCC_WR1_RXI_ALL_CHAR 0x10 /* on each char, or special */
+#define SCC_WR1_RXI_FIRST_CHAR 0x08 /* on first char, or special */
+#define SCC_WR1_RXI_DISABLE 0x00 /* never on recv */
+#define SCC_WR1_PARITY_IE 0x04 /* on parity errors */
+#define SCC_WR1_TX_IE 0x02
+#define SCC_WR1_EXT_IE 0x01
+
+/* WR2 is common and contains the interrupt vector (high nibble) */
+
+#define SCC_WR3_RX_8_BITS 0xc0
+#define SCC_WR3_RX_6_BITS 0x80
+#define SCC_WR3_RX_7_BITS 0x40
+#define SCC_WR3_RX_5_BITS 0x00
+#define SCC_WR3_AUTO_ENABLE 0x20
+#define SCC_WR3_HUNT_MODE 0x10
+#define SCC_WR3_RX_CRC_ENABLE 0x08
+#define SCC_WR3_SDLC_SRCH 0x04
+#define SCC_WR3_INHIBIT_SYNCH 0x02
+#define SCC_WR3_RX_ENABLE 0x01
+
+/* Should be re-written after reset */
+#define SCC_WR4_CLK_x64 0xc0 /* clock divide factor */
+#define SCC_WR4_CLK_x32 0x80
+#define SCC_WR4_CLK_x16 0x40
+#define SCC_WR4_CLK_x1 0x00
+#define SCC_WR4_EXT_SYNCH_MODE 0x30 /* synch modes */
+#define SCC_WR4_SDLC_MODE 0x20
+#define SCC_WR4_16BIT_SYNCH 0x10
+#define SCC_WR4_8BIT_SYNCH 0x00
+#define SCC_WR4_2_STOP 0x0c /* asynch modes */
+#define SCC_WR4_1_5_STOP 0x08
+#define SCC_WR4_1_STOP 0x04
+#define SCC_WR4_SYNCH_MODE 0x00
+#define SCC_WR4_EVEN_PARITY 0x02
+#define SCC_WR4_PARITY_ENABLE 0x01
+
+#define SCC_WR5_DTR 0x80 /* drive DTR pin */
+#define SCC_WR5_TX_8_BITS 0x60
+#define SCC_WR5_TX_6_BITS 0x40
+#define SCC_WR5_TX_7_BITS 0x20
+#define SCC_WR5_TX_5_BITS 0x00
+#define SCC_WR5_SEND_BREAK 0x10
+#define SCC_WR5_TX_ENABLE 0x08
+#define SCC_WR5_CRC_16 0x04 /* CRC if non zero, .. */
+#define SCC_WR5_SDLC 0x00 /* ..SDLC otherwise */
+#define SCC_WR5_RTS 0x02 /* drive RTS pin */
+#define SCC_WR5_TX_CRC_ENABLE 0x01
+
+/* Registers WR6 and WR7 are for synch modes data, with among other things: */
+
+#define SCC_WR6_BISYNCH_12 0x0f
+#define SCC_WR6_SDLC_RANGE_MASK 0x0f
+#define SCC_WR7_SDLC_FLAG 0x7e
+
+/* WR8 is the transmit data buffer (no FIFO) */
+#define SCC_XMT_BUFFER SCC_WR8
+
+#define SCC_WR9_HW_RESET 0xc0 /* force hardware reset */
+#define SCC_WR9_RESET_CHA_A 0x80
+#define SCC_WR9_RESET_CHA_B 0x40
+#define SCC_WR9_NON_VECTORED 0x20 /* mbz for Zilog chip */
+#define SCC_WR9_STATUS_HIGH 0x10
+#define SCC_WR9_MASTER_IE 0x08
+#define SCC_WR9_DLC 0x04 /* disable-lower-chain */
+#define SCC_WR9_NV 0x02 /* no vector */
+#define SCC_WR9_VIS 0x01 /* vector-includes-status */
+
+#define SCC_WR10_CRC_PRESET 0x80
+#define SCC_WR10_FM0 0x60
+#define SCC_WR10_FM1 0x40
+#define SCC_WR10_NRZI 0x20
+#define SCC_WR10_NRZ 0x00
+#define SCC_WR10_ACTIVE_ON_POLL 0x10
+#define SCC_WR10_MARK_IDLE 0x08 /* flag if zero */
+#define SCC_WR10_ABORT_ON_URUN 0x04 /* flag if zero */
+#define SCC_WR10_LOOP_MODE 0x02
+#define SCC_WR10_6BIT_SYNCH 0x01
+#define SCC_WR10_8BIT_SYNCH 0x00
+
+#define SCC_WR11_RTxC_XTAL 0x80 /* RTxC pin is input (ext oscill) */
+#define SCC_WR11_RCLK_DPLL 0x60 /* clock received data on dpll */
+#define SCC_WR11_RCLK_BAUDR 0x40 /* .. on BRG */
+#define SCC_WR11_RCLK_TRc_PIN 0x20 /* .. on TRxC pin */
+#define SCC_WR11_RCLK_RTc_PIN 0x00 /* .. on RTxC pin */
+#define SCC_WR11_XTLK_DPLL 0x18
+#define SCC_WR11_XTLK_BAUDR 0x10
+#define SCC_WR11_XTLK_TRc_PIN 0x08
+#define SCC_WR11_XTLK_RTc_PIN 0x00
+#define SCC_WR11_TRc_OUT 0x04 /* drive TRxC pin as output from..*/
+#define SCC_WR11_TRcOUT_DPLL 0x03 /* .. the dpll */
+#define SCC_WR11_TRcOUT_BAUDR 0x02 /* .. the BRG */
+#define SCC_WR11_TRcOUT_XMTCLK 0x01 /* .. the xmit clock */
+#define SCC_WR11_TRcOUT_XTAL 0x00 /* .. the external oscillator */
+
+/* WR12/WR13 are for timing base preset */
+#define scc_set_timing_base(scc,chan,val) { \
+ scc_write_reg(scc,chan,SCC_RR12,val);\
+ scc_write_reg(scc,chan,SCC_RR13,(val)>>8);\
+ }
+
+/* More commands in this register */
+#define SCC_WR14_NRZI_MODE 0xe0 /* synch modulations */
+#define SCC_WR14_FM_MODE 0xc0
+#define SCC_WR14_RTc_SOURCE 0xa0 /* clock is from pin .. */
+#define SCC_WR14_BAUDR_SOURCE 0x80 /* .. or internal BRG */
+#define SCC_WR14_DISABLE_DPLL 0x60
+#define SCC_WR14_RESET_CLKMISS 0x40
+#define SCC_WR14_SEARCH_MODE 0x20
+/* ..and more bitsy */
+#define SCC_WR14_LOCAL_LOOPB 0x10
+#define SCC_WR14_AUTO_ECHO 0x08
+#define SCC_WR14_DTR_REQUEST 0x04
+#define SCC_WR14_BAUDR_SRC 0x02
+#define SCC_WR14_BAUDR_ENABLE 0x01
+
+#define SCC_WR15_BREAK_IE 0x80
+#define SCC_WR15_TX_UNDERRUN_IE 0x40
+#define SCC_WR15_CTS_IE 0x20
+#define SCC_WR15_SYNCHUNT_IE 0x10
+#define SCC_WR15_DCD_IE 0x08
+#define SCC_WR15_zero 0x05
+#define SCC_WR15_ZERO_COUNT_IE 0x02
+
+
+#endif /*_SCC_8530_H_*/
diff --git a/chips/scc_8530_hdw.c b/chips/scc_8530_hdw.c
new file mode 100644
index 00000000..68c6e9d2
--- /dev/null
+++ b/chips/scc_8530_hdw.c
@@ -0,0 +1,1145 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993-1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: scc_8530_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 6/91
+ *
+ * Hardware-level operations for the SCC Serial Line Driver
+ */
+
+#include <scc.h>
+#if NSCC > 0
+#include <bm.h>
+#include <platforms.h>
+
+#include <mach_kdb.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <mach/std_types.h>
+#include <device/io_req.h>
+#include <device/tty.h>
+
+#include <chips/busses.h>
+#include <chips/serial_defs.h>
+#include <chips/screen_defs.h>
+
+/* Alignment and padding */
+#if defined(DECSTATION)
+/*
+ * 3min's padding
+ */
+typedef struct {
+ char pad0;
+ volatile unsigned char datum;
+ char pad1[2];
+} scc_padded1_register_t;
+
+#define scc_register_t scc_padded1_register_t
+#endif
+
+#if defined(FLAMINGO)
+typedef struct {
+ volatile unsigned int datum;
+ unsigned int pad1;
+} scc_padded1_register_t;
+
+#define scc_register_t scc_padded1_register_t
+
+#define scc_set_datum(d,v) (d) = (volatile unsigned int) (v) << 8, wbflush()
+#define scc_get_datum(d,v) (v) = ((d) >> 8) & 0xff
+
+#endif
+
+#include <chips/scc_8530.h> /* needs the above defs */
+
+#define private static
+#define public
+
+/*
+ * Forward decls
+ */
+private check_car( struct tty *, boolean_t );
+
+/*
+ * On the 3min keyboard and mouse come in on channels A
+ * of the two units. The MI code expects them at 'lines'
+ * 0 and 1, respectively. So we map here back and forth.
+ * Note also the MI code believes unit 0 has four lines.
+ */
+
+#define SCC_KBDUNIT 1
+#define SCC_PTRUNIT 0
+
+mi_to_scc(unitp, linep)
+ int *unitp, *linep;
+{
+ /* only play games on MI 'unit' 0 */
+ if (*unitp) {
+ /* e.g. by mapping the first four lines specially */
+ *unitp++;
+ return;
+ }
+
+ /* always get unit=0 (console) and line = 0|1 */
+ if (*linep == SCREEN_LINE_KEYBOARD) {
+ *unitp = SCC_KBDUNIT;
+ *linep = SCC_CHANNEL_A;
+ } else if (*linep == SCREEN_LINE_POINTER) {
+ *unitp = SCC_PTRUNIT;
+ *linep = SCC_CHANNEL_A;
+ } else {
+ *unitp = (*linep & 1);
+ *linep = SCC_CHANNEL_B;
+ }
+/* line 0 is channel B, line 1 is channel A */
+}
+
+#define NSCC_LINE 2 /* 2 ttys per chip */
+
+/* only care for mapping to ttyno */
+scc_to_mi(sccunit, sccline)
+{
+ if (sccunit > 1)
+ return (sccunit * NSCC_LINE + sccline);
+ /* only for console (first pair of SCCs): */
+ if (sccline == SCC_CHANNEL_A)
+ return ((!sccunit) & 1);
+ return 2+sccunit;
+}
+
+
+/*
+ * Driver status
+ */
+struct scc_softc {
+ scc_regmap_t *regs;
+
+ /* software copy of some write regs, for reg |= */
+ struct softreg {
+ unsigned char wr1;
+ unsigned char wr4;
+ unsigned char wr5;
+ unsigned char wr14;
+ } softr[2]; /* per channel */
+
+ unsigned char last_rr0[2]; /* for modem signals */
+ unsigned short fake; /* missing rs232 bits, channel A */
+ char polling_mode;
+ char softCAR, osoftCAR;
+ char probed_once;
+
+ boolean_t full_modem;
+ boolean_t isa_console;
+
+} scc_softc_data[NSCC];
+
+typedef struct scc_softc *scc_softc_t;
+
+scc_softc_t scc_softc[NSCC];
+
+scc_softCAR(unit, line, on)
+{
+ mi_to_scc(&unit, &line);
+ if (on)
+ scc_softc[unit]->softCAR |= 1<<line;
+ else
+ scc_softc[unit]->softCAR &= ~(1 << line);
+}
+
+
+/*
+ * BRG formula is:
+ * ClockFrequency
+ * BRGconstant = --------------------------- - 2
+ * 2 * BaudRate * ClockDivider
+ */
+/* Speed selections with Pclk=7.3728Mhz, clock x16 */
+static
+short scc_speeds[] =
+ /* 0 50 75 110 134.5 150 200 300 600 1200 1800 2400 */
+ { 0, 4606, 3070, 2093, 1711, 1534, 1150, 766, 382, 190, 126, 94,
+
+ /* 4800 9600 19.2k 38.4k */
+ 46, 22, 10, 4};
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int scc_probe(), scc_intr();
+static void scc_attach();
+
+vm_offset_t scc_std[NSCC] = { 0 };
+struct bus_device *scc_info[NSCC];
+struct bus_driver scc_driver =
+ { scc_probe, 0, scc_attach, 0, scc_std, "scc", scc_info,};
+
+/*
+ * Adapt/Probe/Attach functions
+ */
+boolean_t scc_uses_modem_control = FALSE;/* patch this with adb */
+
+set_scc_address(
+ int sccunit,
+ vm_offset_t regs,
+ boolean_t has_modem,
+ boolean_t isa_console)
+{
+ extern int scc_probe(), scc_param(), scc_start(),
+ scc_putc(), scc_getc(),
+ scc_pollc(), scc_mctl(), scc_softCAR();
+
+ scc_std[sccunit] = regs;
+ scc_softc_data[sccunit].full_modem = has_modem & scc_uses_modem_control;
+ scc_softc_data[sccunit].isa_console = isa_console;
+
+ /* Do this here */
+ console_probe = scc_probe;
+ console_param = scc_param;
+ console_start = scc_start;
+ console_putc = scc_putc;
+ console_getc = scc_getc;
+ console_pollc = scc_pollc;
+ console_mctl = scc_mctl;
+ console_softCAR = scc_softCAR;
+
+}
+
+scc_probe(
+ int xxx,
+ struct bus_device *ui)
+{
+ int sccunit = ui->unit;
+ scc_softc_t scc;
+ register int val;
+ register scc_regmap_t *regs;
+
+ regs = (scc_regmap_t *)scc_std[sccunit];
+ if (regs == 0)
+ return 0;
+
+ /*
+ * See if we are here
+ */
+ if (check_memory(regs, 0)) {
+ /* no rides today */
+ return 0;
+ }
+
+ scc = &scc_softc_data[sccunit];
+
+ if (scc->probed_once++){
+ return 1;
+ }
+ /*
+ * Chip once-only initialization
+ *
+ * NOTE: The wiring we assume is the one on the 3min:
+ *
+ * out A-TxD --> TxD keybd or mouse
+ * in A-RxD --> RxD keybd or mouse
+ * out A-DTR~ --> DTR comm
+ * out A-RTS~ --> RTS comm
+ * in A-CTS~ --> SI comm
+ * in A-DCD~ --> RI comm
+ * in A-SYNCH~--> DSR comm
+ * out B-TxD --> TxD comm
+ * in B-RxD --> RxD comm
+ * in B-RxC --> TRxCB comm
+ * in B-TxC --> RTxCB comm
+ * out B-RTS~ --> SS comm
+ * in B-CTS~ --> CTS comm
+ * in B-DCD~ --> CD comm
+ */
+
+ scc_softc[sccunit] = scc;
+ scc->regs = regs;
+
+ scc->fake = 1<<SCC_CHANNEL_A;
+
+ {
+ register int i;
+ /* We need this in scc_start only, hence the funny
+ value: we need it non-zero and we want to avoid
+ too much overhead in getting to (scc,regs,line) */
+ for (i = 0; i < NSCC_LINE; i++) {
+ register struct tty *tp;
+
+ tp = console_tty[scc_to_mi(sccunit,i)];
+ tp->t_addr = (char*)(0x80000000L + (sccunit<<1) + (i&1));
+ /* do min buffering */
+ tp->t_state |= TS_MIN;
+ }
+ }
+
+ /* make sure reg pointer is in known state */
+ scc_init_reg(regs, SCC_CHANNEL_A);
+ scc_init_reg(regs, SCC_CHANNEL_B);
+
+ /* reset chip, fully */
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET);
+ delay(50000);/*enough ? */
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, 0);
+
+ /* program the interrupt vector */
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0);
+ scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0);
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS);
+
+ /* most of the init is in scc_param() */
+
+ /* timing base defaults */
+ scc->softr[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16;
+ scc->softr[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16;
+
+ /* enable DTR, RTS and dont SS */
+#if 0
+ /* According to one book I have this signal (pin 23, "SS")
+ is "specified by the provider", meaning the EIA-232-D
+ standard does not define what it is. Better leave
+ it alone */
+ scc->softr[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS;
+#else
+ scc->softr[SCC_CHANNEL_B].wr5 = 0;
+#endif
+ scc->softr[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR;
+
+ /* baud rates */
+ val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC;
+ scc->softr[SCC_CHANNEL_B].wr14 = val;
+ scc->softr[SCC_CHANNEL_A].wr14 = val;
+
+ /* interrupt conditions */
+ val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE |
+ SCC_WR1_EXT_IE | SCC_WR1_TX_IE;
+ scc->softr[SCC_CHANNEL_A].wr1 = val;
+ scc->softr[SCC_CHANNEL_B].wr1 = val;
+
+ scc_read_reg_zero(regs, SCC_CHANNEL_A, scc->last_rr0[SCC_CHANNEL_A]);
+ scc_read_reg_zero(regs, SCC_CHANNEL_B, scc->last_rr0[SCC_CHANNEL_B]);
+
+ /*
+ * After probing, any line that should be active
+ * (keybd,mouse,rcline) is activated via scc_param().
+ */
+
+ scc_set_modem_control(scc, scc->full_modem);
+
+#if defined(KMIN) || defined (FLAMINGO) || defined(KN03)
+ /*
+ * Crock: MI code knows of unit 0 as console, we need
+ * unit 1 as well since the keyboard is there
+ * This is acceptable on maxine, which has to call its
+ * only one chip unit 1 so that rconsole is happy.
+ */
+ if (sccunit == 0) {
+ struct bus_device d;
+ d = *ui;
+ d.unit = 1;
+ scc_probe( xxx, &d);
+ }
+#endif
+ return 1;
+}
+
+boolean_t scc_timer_started = FALSE;
+
+static void
+scc_attach(
+ register struct bus_device *ui)
+{
+ int sccunit = ui->unit;
+ extern scc_scan();
+ extern int tty_inq_size;
+ int i;
+
+ /* We only have 4 ttys, but always at 9600
+ * Give em a lot of room (plus dma..)
+ */
+ tty_inq_size = 4096;
+ if (!scc_timer_started) {
+ /* do all of them, before we call scc_scan() */
+ /* harmless if done already */
+ for (i = 0; i < NSCC*NSCC_LINE; i++)
+ ttychars(console_tty[i]);
+
+ scc_timer_started = TRUE;
+ scc_scan();
+ }
+
+#if NBM > 0
+ if (SCREEN_ISA_CONSOLE() && scc_softc[sccunit]->isa_console) {
+ printf("\n sl0: ");
+ if (sccunit && rcline == 3) printf("( rconsole )");
+
+ if (sccunit == SCC_KBDUNIT) {
+ printf("\n sl1: "); lk201_attach(0, sccunit >> 1);
+ } else if (sccunit == SCC_PTRUNIT) {
+ printf("\n sl1: "); mouse_attach(0, sccunit >> 1);
+ }
+ } else
+#endif /*NBM > 0*/
+ {
+ printf("%s", (sccunit == 1) ?
+ "\n sl0: ( alternate console )\n sl1:" :
+ "\n sl0:\n sl1:");
+ }
+}
+
+/*
+ * Would you like to make a phone call ?
+ */
+scc_set_modem_control(
+ scc_softc_t scc,
+ boolean_t on)
+{
+ if (on)
+ /* your problem if the hardware then is broke */
+ scc->fake = 0;
+ else
+ scc->fake = 3;
+ scc->full_modem = on;
+ /* user should do an scc_param() ifchanged */
+}
+
+/*
+ * Polled I/O (debugger)
+ */
+scc_pollc(
+ int unit,
+ boolean_t on)
+{
+ scc_softc_t scc;
+ int line = SCREEN_LINE_KEYBOARD,
+ sccunit = unit;
+
+ mi_to_scc(&sccunit, &line);
+
+ scc = scc_softc[sccunit];
+ if (on) {
+ scc->polling_mode++;
+#if NBM > 0
+ screen_on_off(unit, TRUE);
+#endif NBM > 0
+ } else
+ scc->polling_mode--;
+}
+
+/*
+ * Interrupt routine
+ */
+int scc_intr_count;
+
+scc_intr(
+ int unit,
+ spl_t spllevel)
+{
+ scc_softc_t scc = scc_softc[unit];
+ register scc_regmap_t *regs = scc->regs;
+ register int rr1, rr2;
+ register int c;
+
+scc_intr_count++;
+
+#if mips
+ splx(spllevel); /* lower priority */
+#endif
+
+ while (1) {
+
+ scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR2, rr2);
+
+ rr2 = SCC_RR2_STATUS(rr2);
+
+ /* are we done yet ? */
+ if (rr2 == 6) { /* strange, distinguished value */
+ register int rr3;
+ scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR3, rr3);
+ if (rr3 == 0)
+ return;
+ }
+
+ if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
+
+ register chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
+ SCC_CHANNEL_A : SCC_CHANNEL_B;
+
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
+ c = cons_simple_tint(scc_to_mi(unit,chan), FALSE);
+
+ if (c == -1) {
+ /* no more data for this line */
+
+ scc_read_reg(regs, chan, SCC_RR15, c);
+ c &= ~SCC_WR15_TX_UNDERRUN_IE;
+ scc_write_reg(regs, chan, SCC_WR15, c);
+
+ c = scc->softr[chan].wr1 & ~SCC_WR1_TX_IE;
+ scc_write_reg(regs, chan, SCC_WR1, c);
+ scc->softr[chan].wr1 = c;
+
+ c = cons_simple_tint(scc_to_mi(unit,chan), TRUE);
+ if (c != -1)
+ /* funny race, scc_start has been called already */
+ scc_write_data(regs, chan, c);
+ } else {
+ scc_write_data(regs, chan, c);
+ /* and leave it enabled */
+ }
+ }
+
+ else if (rr2 == SCC_RR2_A_RECV_DONE) {
+ int err = 0;
+
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
+ if (scc->polling_mode)
+ continue;
+
+ scc_read_data(regs, SCC_CHANNEL_A, c);
+ rr1 = scc_to_mi(unit,SCC_CHANNEL_A);
+ cons_simple_rint (rr1, rr1, c, 0);
+ }
+
+ else if (rr2 == SCC_RR2_B_RECV_DONE) {
+ int err = 0;
+
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
+ if (scc->polling_mode)
+ continue;
+
+ scc_read_data(regs, SCC_CHANNEL_B, c);
+ rr1 = scc_to_mi(unit,SCC_CHANNEL_B);
+ cons_simple_rint (rr1, rr1, c, 0);
+ }
+
+ else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
+ int chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
+ SCC_CHANNEL_A : SCC_CHANNEL_B;
+ scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_EXT_IP);
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
+ scc_modem_intr(scc, chan, unit);
+ }
+
+ else if ((rr2 == SCC_RR2_A_RECV_SPECIAL) || (rr2 == SCC_RR2_B_RECV_SPECIAL)) {
+ register int chan = (rr2 == SCC_RR2_A_RECV_SPECIAL) ?
+ SCC_CHANNEL_A : SCC_CHANNEL_B;
+
+ scc_read_reg(regs, chan, SCC_RR1, rr1);
+ if (rr1 & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
+ int err;
+ /* map to CONS_ERR_xxx MI error codes */
+ err = ((rr1 & SCC_RR1_PARITY_ERR)<<8) |
+ ((rr1 & SCC_RR1_RX_OVERRUN)<<9) |
+ ((rr1 & SCC_RR1_FRAME_ERR)<<7);
+ scc_write_reg(regs, chan, SCC_RR0, SCC_RESET_ERROR);
+ rr1 = scc_to_mi(unit,chan);
+ cons_simple_rint(rr1, rr1, 0, err);
+ }
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
+ }
+
+ }
+
+}
+
+boolean_t
+scc_start(
+ struct tty *tp)
+{
+ register scc_regmap_t *regs;
+ register int chan, temp;
+ register struct softreg *sr;
+
+ temp = (natural_t)tp->t_addr;
+ chan = (temp & 1); /* channel */
+ temp = (temp >> 1)&0xff;/* sccunit */
+ regs = scc_softc[temp]->regs;
+ sr = &scc_softc[temp]->softr[chan];
+
+ scc_read_reg(regs, chan, SCC_RR15, temp);
+ temp |= SCC_WR15_TX_UNDERRUN_IE;
+ scc_write_reg(regs, chan, SCC_WR15, temp);
+
+ temp = sr->wr1 | SCC_WR1_TX_IE;
+ scc_write_reg(regs, chan, SCC_WR1, temp);
+ sr->wr1 = temp;
+
+ /* but we need a first char out or no cookie */
+ scc_read_reg(regs, chan, SCC_RR0, temp);
+ if (temp & SCC_RR0_TX_EMPTY)
+ {
+ register char c;
+
+ c = getc(&tp->t_outq);
+ scc_write_data(regs, chan, c);
+ }
+}
+
+/*
+ * Get a char from a specific SCC line
+ * [this is only used for console&screen purposes]
+ */
+scc_getc(
+ int unit,
+ int line,
+ boolean_t wait,
+ boolean_t raw)
+{
+ scc_softc_t scc;
+ register scc_regmap_t *regs;
+ unsigned char c;
+ int value, mi_line, rcvalue, from_line;
+
+ mi_line = line;
+ mi_to_scc(&unit, &line);
+
+ scc = scc_softc[unit];
+ regs = scc->regs;
+
+ /*
+ * wait till something available
+ *
+ * NOTE: we know! that rcline==3
+ */
+ if (rcline) rcline = 3;
+again:
+ rcvalue = 0;
+ while (1) {
+ scc_read_reg_zero(regs, line, value);
+ if (rcline && (mi_line == SCREEN_LINE_KEYBOARD)) {
+ scc_read_reg_zero(regs, SCC_CHANNEL_B, rcvalue);
+ value |= rcvalue;
+ }
+ if (((value & SCC_RR0_RX_AVAIL) == 0) && wait)
+ delay(10);
+ else
+ break;
+ }
+
+ /*
+ * if nothing found return -1
+ */
+ from_line = (rcvalue & SCC_RR0_RX_AVAIL) ? SCC_CHANNEL_B : line;
+
+ if (value & SCC_RR0_RX_AVAIL) {
+ scc_read_reg(regs, from_line, SCC_RR1, value);
+ scc_read_data(regs, from_line, c);
+ } else {
+/* splx(s);*/
+ return -1;
+ }
+
+ /*
+ * bad chars not ok
+ */
+ if (value&(SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | SCC_RR1_FRAME_ERR)) {
+/* scc_state(unit,from_line); */
+ scc_write_reg(regs, from_line, SCC_RR0, SCC_RESET_ERROR);
+ if (wait) {
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
+ goto again;
+ }
+ }
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
+/* splx(s);*/
+
+
+#if NBM > 0
+ if ((mi_line == SCREEN_LINE_KEYBOARD) && (from_line == SCC_CHANNEL_A) &&
+ !raw && SCREEN_ISA_CONSOLE() && scc->isa_console)
+ return lk201_rint(SCREEN_CONS_UNIT(), c, wait, scc->polling_mode);
+ else
+#endif NBM > 0
+ return c;
+}
+
+/*
+ * Put a char on a specific SCC line
+ */
+scc_putc(
+ int unit,
+ int line,
+ int c)
+{
+ scc_softc_t scc;
+ register scc_regmap_t *regs;
+ spl_t s = spltty();
+ register int value;
+
+ mi_to_scc(&unit, &line);
+
+ scc = scc_softc[unit];
+ regs = scc->regs;
+
+ do {
+ scc_read_reg(regs, line, SCC_RR0, value);
+ if (value & SCC_RR0_TX_EMPTY)
+ break;
+ delay(100);
+ } while (1);
+
+ scc_write_data(regs, line, c);
+/* wait for it to swallow the char ? */
+
+ splx(s);
+}
+
+scc_param(
+ struct tty *tp,
+ int line)
+{
+ scc_regmap_t *regs;
+ int value, sccline, unit;
+ struct softreg *sr;
+ scc_softc_t scc;
+
+ line = tp->t_dev;
+ /* MI code wants us to handle 4 lines on unit 0 */
+ unit = (line < 4) ? 0 : (line / NSCC_LINE);
+ sccline = line;
+ mi_to_scc(&unit, &sccline);
+
+ if ((scc = scc_softc[unit]) == 0) return; /* sanity */
+ regs = scc->regs;
+
+ sr = &scc->softr[sccline];
+
+ /*
+ * Do not let user fool around with kbd&mouse
+ */
+#if NBM > 0
+ if (screen_captures(line)) {
+ tp->t_ispeed = tp->t_ospeed = B4800;
+ tp->t_flags |= TF_LITOUT;
+ }
+#endif NBM > 0
+
+ if (tp->t_ispeed == 0) {
+ (void) scc_mctl(tp->t_dev, TM_HUP, DMSET); /* hang up line */
+ return;
+ }
+
+ /* reset line */
+ value = (sccline == SCC_CHANNEL_A) ? SCC_WR9_RESET_CHA_A : SCC_WR9_RESET_CHA_B;
+ scc_write_reg(regs, sccline, SCC_WR9, value);
+ delay(25);
+
+ /* stop bits, normally 1 */
+ value = sr->wr4 & 0xf0;
+ value |= (tp->t_ispeed == B110) ? SCC_WR4_2_STOP : SCC_WR4_1_STOP;
+
+ /* .. and parity */
+ if ((tp->t_flags & (TF_ODDP | TF_EVENP)) == TF_ODDP)
+ value |= SCC_WR4_PARITY_ENABLE;
+
+ /* set it now, remember it must be first after reset */
+ sr->wr4 = value;
+ scc_write_reg(regs, sccline, SCC_WR4, value);
+
+ /* vector again */
+ scc_write_reg(regs, sccline, SCC_WR2, 0xf0);
+
+ /* we only do 8 bits per char */
+ value = SCC_WR3_RX_8_BITS;
+ scc_write_reg(regs, sccline, SCC_WR3, value);
+
+ /* clear break, keep rts dtr */
+ value = sr->wr5 & (SCC_WR5_DTR|SCC_WR5_RTS);
+ value |= SCC_WR5_TX_8_BITS;
+ sr->wr5 = value;
+ scc_write_reg(regs, sccline, SCC_WR5, value);
+ /* some are on the other channel, which might
+ never be used (e.g. maxine has only one line) */
+ {
+ register int otherline = (sccline+1)&1;
+
+ scc_write_reg(regs, otherline, SCC_WR5, scc->softr[otherline].wr5);
+ }
+
+ scc_write_reg(regs, sccline, SCC_WR6, 0);
+ scc_write_reg(regs, sccline, SCC_WR7, 0);
+
+ scc_write_reg(regs, sccline, SCC_WR9, SCC_WR9_VIS);
+
+ scc_write_reg(regs, sccline, SCC_WR10, 0);
+
+ /* clock config */
+ value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR |
+ SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR;
+ scc_write_reg(regs, sccline, SCC_WR11, value);
+
+ value = scc_speeds[tp->t_ispeed];
+ scc_set_timing_base(regs,sccline,value);
+
+ value = sr->wr14;
+ scc_write_reg(regs, sccline, SCC_WR14, value);
+
+#if FLAMINGO
+ if (unit != 1)
+#else
+ if (1)
+#endif
+ {
+ /* Chan-A: CTS==SI DCD==RI DSR=SYNCH */
+ value = SCC_WR15_CTS_IE | SCC_WR15_DCD_IE | SCC_WR15_SYNCHUNT_IE;
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR15, value);
+
+ /* Chan-B: CTS==CTS DCD==DCD */
+ value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE;
+ scc_write_reg(regs, SCC_CHANNEL_B, SCC_WR15, value);
+ } else {
+ /* Here if modem bits are floating noise, keep quiet */
+ value = SCC_WR15_BREAK_IE;
+ scc_write_reg(regs, sccline, SCC_WR15, value);
+ }
+
+ /* and now the enables */
+ value = SCC_WR3_RX_8_BITS | SCC_WR3_RX_ENABLE;
+ scc_write_reg(regs, sccline, SCC_WR3, value);
+
+ value = sr->wr5 | SCC_WR5_TX_ENABLE;
+ sr->wr5 = value;
+ scc_write_reg(regs, sccline, SCC_WR5, value);
+
+ /* master inter enable */
+ scc_write_reg(regs,sccline,SCC_WR9,SCC_WR9_MASTER_IE|SCC_WR9_VIS);
+
+ scc_write_reg(regs, sccline, SCC_WR1, sr->wr1);
+
+}
+
+/*
+ * Modem control functions
+ */
+scc_mctl(
+ int dev,
+ int bits,
+ int how)
+{
+ register scc_regmap_t *regs;
+ struct softreg *sra, *srb, *sr;
+ int unit, sccline;
+ int b = 0;
+ spl_t s;
+ scc_softc_t scc;
+
+ /* MI code wants us to handle 4 lines on unit 0 */
+ unit = (dev < 4) ? 0 : (dev / NSCC_LINE);
+ sccline = dev;
+ mi_to_scc(&unit, &sccline);
+
+ if ((scc = scc_softc[unit]) == 0) return 0; /* sanity */
+ regs = scc->regs;
+
+ sr = &scc->softr[sccline];
+ sra = &scc->softr[SCC_CHANNEL_A];
+ srb = &scc->softr[SCC_CHANNEL_B];
+
+ if (bits == TM_HUP) { /* close line (internal) */
+ bits = TM_DTR | TM_RTS;
+ how = DMBIC;
+ /* xxx interrupts too ?? */
+ }
+
+ if (bits & TM_BRK) {
+ switch (how) {
+ case DMSET:
+ case DMBIS:
+ sr->wr5 |= SCC_WR5_SEND_BREAK;
+ break;
+ case DMBIC:
+ sr->wr5 &= ~SCC_WR5_SEND_BREAK;
+ break;
+ default:
+ goto dontbrk;
+ }
+ s = spltty();
+ scc_write_reg(regs, sccline, SCC_WR5, sr->wr5);
+ splx(s);
+dontbrk:
+ b |= (sr->wr5 & SCC_WR5_SEND_BREAK) ? TM_BRK : 0;
+ }
+
+ /* no modem support on channel A */
+ if (sccline == SCC_CHANNEL_A)
+ return (b | TM_LE | TM_DTR | TM_CTS | TM_CAR | TM_DSR);
+
+ sra = &scc->softr[SCC_CHANNEL_A];
+ srb = &scc->softr[SCC_CHANNEL_B];
+
+#if 0
+ /* do I need to do something on this ? */
+ if (bits & TM_LE) { /* line enable */
+ }
+#endif
+
+ if (bits & (TM_DTR|TM_RTS)) { /* data terminal ready, request to send */
+ register int w = 0;
+
+ if (bits & TM_DTR) w |= SCC_WR5_DTR;
+ if (bits & TM_RTS) w |= SCC_WR5_RTS;
+
+ switch (how) {
+ case DMSET:
+ case DMBIS:
+ sra->wr5 |= w;
+ break;
+ case DMBIC:
+ sra->wr5 &= ~w;
+ break;
+ default:
+ goto dontdtr;
+ }
+ s = spltty();
+ scc_write_reg(regs, SCC_CHANNEL_A, SCC_WR5, sra->wr5);
+ splx(s);
+dontdtr:
+ b |= (sra->wr5 & w) ? (bits & (TM_DTR|TM_RTS)) : 0;
+ }
+
+ s = spltty();
+
+#if 0
+ /* Unsupported */
+ if (bits & TM_ST) { /* secondary transmit */
+ }
+ if (bits & TM_SR) { /* secondary receive */
+ }
+#endif
+
+ if (bits & TM_CTS) { /* clear to send */
+ register int value;
+ scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value);
+ b |= (value & SCC_RR0_CTS) ? TM_CTS : 0;
+ }
+
+ if (bits & TM_CAR) { /* carrier detect */
+ register int value;
+ scc_read_reg(regs, SCC_CHANNEL_B, SCC_RR0, value);
+ b |= (value & SCC_RR0_DCD) ? TM_CAR : 0;
+ }
+
+ if (bits & TM_RNG) { /* ring */
+ register int value;
+ scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value);
+ b |= (value & SCC_RR0_DCD) ? TM_RNG : 0;
+ }
+
+ if (bits & TM_DSR) { /* data set ready */
+ register int value;
+ scc_read_reg(regs, SCC_CHANNEL_A, SCC_RR0, value);
+ b |= (value & SCC_RR0_SYNCH) ? TM_DSR : 0;
+ }
+
+ splx(s);
+
+ return b;
+}
+
+#define debug 0
+
+scc_modem_intr(
+ scc_softc_t scc,
+ int chan,
+ int unit)
+{
+ register int value, changed;
+
+ scc_read_reg_zero(scc->regs, chan, value);
+
+ /* See what changed */
+ changed = value ^ scc->last_rr0[chan];
+ scc->last_rr0[chan] = value;
+
+#if debug
+printf("sccmodem: chan %c now %x, changed %x : ",
+ (chan == SCC_CHANNEL_B) ? 'B' : 'A',
+ value, changed);
+#endif
+
+ if (chan == SCC_CHANNEL_A) {
+ if (changed & SCC_RR0_CTS) {
+ /* Speed indicator, ignore XXX */
+#if debug
+printf("%s-speed ", (value & SCC_RR0_CTS) ? "Full" : "Half");
+#endif
+ }
+ if (changed & SCC_RR0_DCD) {
+ /* Ring indicator */
+#if debug
+printf("Ring ");
+#endif
+ }
+ if (changed & SCC_RR0_SYNCH) {
+ /* Data Set Ready */
+#if debug
+printf("DSR ");
+#endif
+ /* If modem went down then CD will also go down,
+ or it did already.
+ If modem came up then we have to wait for CD
+ anyways before enabling the line.
+ Either way, nothing to do here */
+ }
+ } else {
+ if (changed & SCC_RR0_CTS) {
+ /* Clear To Send */
+#if debug
+printf("CTS ");
+#endif
+ tty_cts(console_tty[scc_to_mi(unit,chan)],
+ value & SCC_RR0_CTS);
+ }
+ if (changed & SCC_RR0_DCD) {
+#if debug
+printf("CD ");
+#endif
+ check_car(console_tty[scc_to_mi(unit,chan)],
+ value & SCC_RR0_DCD);
+ }
+ }
+#if debug
+printf(".\n");
+#endif
+}
+
+private check_car(
+ register struct tty *tp,
+ boolean_t car)
+
+{
+ if (car) {
+#if notyet
+ /* cancel modem timeout if need to */
+ if (car & (SCC_MSR_CD2 | SCC_MSR_CD3))
+ untimeout(scc_hup, (vm_offset_t)tp);
+#endif
+
+ /* I think this belongs in the MI code */
+ if (tp->t_state & TS_WOPEN)
+ tp->t_state |= TS_ISOPEN;
+ /* carrier present */
+ if ((tp->t_state & TS_CARR_ON) == 0)
+ (void)ttymodem(tp, 1);
+ } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0)
+ scc_mctl( tp->t_dev, TM_DTR, DMBIC);
+}
+
+/*
+ * Periodically look at the CD signals:
+ * they do generate interrupts but we
+ * must fake them on channel A. We might
+ * also fake them on channel B.
+ */
+scc_scan()
+{
+ register i;
+ spl_t s = spltty();
+
+ for (i = 0; i < NSCC; i++) {
+ register scc_softc_t scc;
+ register int car;
+ register struct tty **tpp;
+
+ scc = scc_softc[i];
+ if (scc == 0)
+ continue;
+ car = scc->softCAR | scc->fake;
+
+ tpp = &console_tty[i * NSCC_LINE];
+
+ while (car) {
+ if (car & 1)
+ check_car(*tpp, 1);
+ tpp++;
+ car = car>>1;
+ }
+
+ }
+ splx(s);
+ timeout(scc_scan, (vm_offset_t)0, 5*hz);
+}
+
+
+#if debug
+scc_rr0(unit,chan)
+{
+ int val;
+ scc_read_reg_zero(scc_softc[unit]->regs, chan, val);
+ return val;
+}
+
+scc_rreg(unit,chan,n)
+{
+ int val;
+ scc_read_reg(scc_softc[unit]->regs, chan, n, val);
+ return val;
+}
+
+scc_wreg(unit,chan,n,val)
+{
+ scc_write_reg(scc_softc[unit]->regs, chan, n, val);
+}
+
+scc_state(unit,soft)
+{
+ int rr0, rr1, rr3, rr12, rr13, rr15;
+
+ rr0 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR0);
+ rr1 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR1);
+ rr3 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR3);
+ rr12 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR12);
+ rr13 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR13);
+ rr15 = scc_rreg(unit, SCC_CHANNEL_A, SCC_RR15);
+ printf("{%d intr, A: R0 %x R1 %x R3 %x baudr %x R15 %x}\n",
+ scc_intr_count, rr0, rr1, rr3,
+ (rr13 << 8) | rr12, rr15);
+
+ rr0 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR0);
+ rr1 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR1);
+ rr3 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR2);
+ rr12 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR12);
+ rr13 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR13);
+ rr15 = scc_rreg(unit, SCC_CHANNEL_B, SCC_RR15);
+ printf("{B: R0 %x R1 %x R2 %x baudr %x R15 %x}\n",
+ rr0, rr1, rr3,
+ (rr13 << 8) | rr12, rr15);
+
+ if (soft) {
+ struct softreg *sr;
+ sr = scc_softc[unit]->softr;
+ printf("{B: W1 %x W4 %x W5 %x W14 %x}",
+ sr->wr1, sr->wr4, sr->wr5, sr->wr14);
+ sr++;
+ printf("{A: W1 %x W4 %x W5 %x W14 %x}\n",
+ sr->wr1, sr->wr4, sr->wr5, sr->wr14);
+ }
+}
+
+#endif
+
+#endif NSCC > 0
diff --git a/chips/screen.c b/chips/screen.c
new file mode 100644
index 00000000..22512815
--- /dev/null
+++ b/chips/screen.c
@@ -0,0 +1,1103 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: screen.c
+ * Author: Alessandro Forin, Robert V. Baron, Joseph S. Barrera,
+ * at Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Generic Screen Driver routines.
+ */
+
+#include <bm.h>
+#if NBM > 0
+#include <dtop.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <chips/screen_defs.h>
+
+#include <chips/lk201.h>
+
+#include <mach/std_types.h>
+#include <sys/time.h>
+#include <kern/time_out.h>
+#include <device/io_req.h>
+
+#include <vm/vm_map.h>
+#include <device/ds_routines.h>
+#include <machine/machspl.h>
+
+#define Ctrl(x) ((x)-'@')
+
+#define SCREEN_BLITC_NORMAL 0
+#define SCREEN_BLITC_ROW 1
+#define SCREEN_BLITC_COL 2
+
+#define SCREEN_ASCII_INVALID '\0' /* ascii_screen not valid here */
+
+struct screen_softc screen_softc_data[NBM];
+struct screen_softc *screen_softc[NBM];
+
+short screen_console = 0;
+
+/* Forward decls */
+
+void screen_blitc(
+ int unit,
+ register unsigned char c);
+
+void screen_blitc_at(
+ register screen_softc_t sc,
+ unsigned char c,
+ short row,
+ short col);
+
+
+/*
+ 8-D A "Screen" has a bitmapped display, a keyboard and a mouse
+ *
+ */
+
+#if NDTOP > 0
+extern int dtop_kbd_probe(), dtop_set_status(), dtop_kbd_reset(),
+ dtop_ring_bell();
+#endif /* NDTOP */
+extern int lk201_probe(), lk201_set_status(), lk201_reset(),
+ lk201_ring_bell();
+
+struct kbd_probe_vector {
+ int (*probe)();
+ int (*set_status)();
+ int (*reset)();
+ int (*beep)();
+} kbd_vector[] = {
+#if NDTOP > 0
+ {dtop_kbd_probe, dtop_set_status, dtop_kbd_reset, dtop_ring_bell},
+#endif
+ {lk201_probe, lk201_set_status, lk201_reset, lk201_ring_bell},
+ {0,}
+};
+
+screen_find_kbd(int unit)
+{
+ struct kbd_probe_vector *p = kbd_vector;
+
+ for (; p->probe; p++) {
+ if ((*p->probe) (unit)) {
+ screen_softc[unit]->kbd_set_status = p->set_status;
+ screen_softc[unit]->kbd_reset = p->reset;
+ screen_softc[unit]->kbd_beep = p->beep;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * The screen probe routine looks for the associated
+ * keyboard and mouse, at the same unit number.
+ */
+screen_probe(int unit)
+{
+ if (unit >= NBM)
+ return 0;
+ screen_softc[unit] = &screen_softc_data[unit];
+ if (!screen_find())
+ return 0;
+ if (!screen_find_kbd(unit))
+ return 0;
+ mouse_probe(unit);
+ return 1;
+}
+
+screen_softc_t
+screen(int unit)
+{
+ return screen_softc[unit];
+}
+
+/*
+ * This is an upcall from the specific display
+ * hardware, to register its descriptor
+ */
+screen_attach(
+ int unit,
+ char **hwp)
+{
+ register screen_softc_t sc = screen_softc[unit];
+
+ sc->hw_state = hwp;
+ sc->blitc_state = SCREEN_BLITC_NORMAL;
+}
+
+/*
+ * This is another upcall (for now) to register
+ * the user-mapped information
+ */
+void
+screen_up(
+ int unit,
+ user_info_t *screen_data)
+{
+ register screen_softc_t sc = screen_softc[unit];
+
+ sc->up = screen_data;
+ mouse_notify_mapped(unit, unit, screen_data);
+ screen_event_init(screen_data);
+ ascii_screen_initialize(sc);
+}
+
+/*
+ * Screen saver
+ */
+#define SSAVER_MIN_TIME (2*60) /* Minimum fade interval */
+long ssaver_last = 0; /* Last tv_sec that the keyboard was touched */
+long ssaver_time = 0; /* Number of seconds before screen is blanked */
+
+void
+ssaver_bump(int unit)
+{
+ register long tnow = time.tv_sec;
+
+ if ((tnow - ssaver_last) > ssaver_time)
+ screen_on_off(unit, TRUE);
+ ssaver_last = tnow;
+}
+
+void
+screen_saver(int unit)
+{
+ register screen_softc_t sc = screen_softc[unit];
+
+ /* wakeup each minute */
+ timeout(screen_saver, unit, hz * 60);
+ if ((time.tv_sec - ssaver_last) >= ssaver_time)
+ /* this does nothing if already off */
+ screen_on_off(unit, FALSE);
+}
+
+/*
+ * Screen open routine. We are also notified
+ * of console operations if our screen is acting
+ * as a console display.
+ */
+screen_open(
+ int unit,
+ boolean_t console_only)
+{
+ register screen_softc_t sc = screen_softc[unit];
+
+ /*
+ * Start screen saver on first (console) open
+ */
+ if (!ssaver_time) {
+ ssaver_time = 10*60; /* 10 minutes to fade */
+ ssaver_bump(unit); /* .. from now */
+ screen_saver(unit); /* Start timer */
+ }
+ /*
+ * Really opening the screen or just notifying ?
+ */
+ if (!console_only) {
+#if 0
+ (*sc->sw.init_colormap)(sc);
+#endif
+ screen_event_init(sc->up);
+ ascii_screen_initialize(sc);
+ (*sc->sw.graphic_open)(sc->hw_state);
+ sc->mapped = TRUE;
+ }
+}
+
+/*
+ * Screen close
+ */
+screen_close(
+ int unit,
+ boolean_t console_only)
+{
+ register screen_softc_t sc = screen_softc[unit];
+
+ /*
+ * Closing of the plain console has no effect
+ */
+ if (!console_only) {
+ user_info_t *up = sc->up;
+
+ screen_default_colors(up);
+ /* mapped info, cursor and colormap resetting */
+ (*sc->sw.graphic_close)(sc);
+
+ /* turn screen on, and blank it */
+ screen_on_off(unit, TRUE);
+ ascii_screen_initialize(sc);
+ (*sc->sw.clear_bitmap)(sc);
+
+ /* position cursor circa page end */
+ up->row = up->max_row - 1;
+ up->col = 0;
+
+ /* set keyboard back our way */
+ (*sc->kbd_reset)(unit);
+ lk201_lights(unit, LED_OFF);
+
+ sc->mapped = FALSE;
+ }
+}
+
+screen_default_colors(
+ user_info_t *up)
+{
+ register int i;
+
+ /* restore bg and fg colors */
+ for (i = 0; i < 3; i++) {
+ up->dev_dep_2.pm.Bg_color[i] = 0x00;
+ up->dev_dep_2.pm.Fg_color[i] = 0xff;
+ }
+}
+
+/*
+ * Write characters to the screen
+ */
+screen_write(
+ int unit,
+ register io_req_t ior)
+{
+ register int count;
+ register unsigned char *data;
+ vm_offset_t addr;
+
+ if (unit == 1) /* no writes to the mouse */
+ return D_INVALID_OPERATION;
+
+ data = (unsigned char*) ior->io_data;
+ count = ior->io_count;
+ if (count == 0)
+ return (D_SUCCESS);
+
+ if (!(ior->io_op & IO_INBAND)) {
+ vm_map_copy_t copy = (vm_map_copy_t) data;
+ kern_return_t kr;
+
+ kr = vm_map_copyout(device_io_map, &addr, copy);
+ if (kr != KERN_SUCCESS)
+ return (kr);
+ data = (unsigned char *) addr;
+ }
+
+ /* Spill chars out, might fault data in */
+ while (count--)
+ screen_blitc(unit, *data++);
+
+ if (!(ior->io_op & IO_INBAND))
+ (void) vm_deallocate(device_io_map, addr, ior->io_count);
+
+ return (D_SUCCESS);
+}
+
+/*
+ * Read from the screen. This really means waiting
+ * for an event, which can be either a keypress on
+ * the keyboard (or pointer) or a mouse movement.
+ * If there are no available events we queue the
+ * request for later.
+ */
+queue_head_t screen_read_queue = { &screen_read_queue, &screen_read_queue };
+boolean_t screen_read_done();
+
+screen_read(
+ int unit,
+ register io_req_t ior)
+{
+ register user_info_t *up = screen_softc[unit]->up;
+ register spl_t s = spltty();
+
+ if (up->evque.q_head != up->evque.q_tail) {
+ splx(s);
+ return (D_SUCCESS);
+ }
+ ior->io_dev_ptr = (char *) up;
+ ior->io_done = screen_read_done;
+ enqueue_tail(&screen_read_queue, (queue_entry_t) ior);
+ splx(s);
+ return (D_IO_QUEUED);
+}
+
+boolean_t
+screen_read_done(
+ register io_req_t ior)
+{
+ register user_info_t *up = (user_info_t *) ior->io_dev_ptr;
+ register spl_t s = spltty();
+
+ if (up->evque.q_head != up->evque.q_tail) {
+ splx(s);
+ (void) ds_read_done(ior);
+ return (TRUE);
+ }
+ enqueue_tail(&screen_read_queue, (queue_entry_t) ior);
+ splx(s);
+ return (FALSE);
+}
+
+static
+screen_event_posted(
+ register user_info_t *up)
+{
+ if (up->evque.q_head != up->evque.q_tail) {
+ register io_req_t ior;
+ while ((ior = (io_req_t)dequeue_head(&screen_read_queue)))
+ iodone(ior);
+ }
+}
+
+boolean_t compress_mouse_events = TRUE;
+
+/*
+ * Upcall from input pointer devices
+ */
+screen_motion_event(
+ int unit,
+ int device,
+ int x,
+ int y)
+{
+ register screen_softc_t sc = screen_softc[unit];
+ register user_info_t *up = sc->up;
+ register unsigned next;
+ unsigned int ev_time;
+
+ /*
+ * Take care of scale/threshold issues
+ */
+ if (device == DEV_MOUSE) {
+ register int scale;
+
+ scale = up->mouse_scale;
+
+ if (scale >= 0) {
+ register int threshold;
+ register boolean_t neg;
+
+ threshold = up->mouse_threshold;
+
+ neg = (x < 0);
+ if (neg) x = -x;
+ if (x >= threshold)
+ x += (x - threshold) * scale;
+ if (neg) x = -x;
+
+ neg = (y < 0);
+ if (neg) y = -y;
+ if (y >= threshold)
+ y += (y - threshold) * scale;
+ if (neg) y = -y;
+
+ }
+
+ /* we expect mices in incremental mode */
+ x += up->mouse_loc.x;
+ y += up->mouse_loc.y;
+
+ } else if (device == DEV_TABLET) {
+
+ /* we expect tablets in absolute mode */
+ x = (x * up->dev_dep_2.pm.tablet_scale_x) / 1000;
+ y = ((2200 - y) * up->dev_dep_2.pm.tablet_scale_y) / 1000;
+
+ } /* else who are you */
+
+ /*
+ * Clip if necessary
+ */
+ {
+ register int max;
+
+ if (x > (max = up->max_cur_x))
+ x = max;
+ if (y > (max = up->max_cur_y))
+ y = max;
+ }
+
+ /*
+ * Did it actually move
+ */
+ if ((up->mouse_loc.x == x) &&
+ (up->mouse_loc.y == y))
+ return;
+
+ /*
+ * Update mouse location, and cursor
+ */
+ up->mouse_loc.x = x;
+ up->mouse_loc.y = y;
+
+ screen_set_cursor(sc, x, y);
+
+ /*
+ * Add point to track.
+ */
+ {
+ register screen_timed_point_t *tr;
+
+ /* simply add and overflow if necessary */
+ next = up->evque.t_next;
+ if (next >= MAX_TRACK)
+ next = MAX_TRACK-1;
+ tr = &up->point_track[next++];
+ up->evque.t_next = (next == MAX_TRACK) ? 0 : next;
+
+ ev_time = (unsigned) approx_time_in_msec();
+ tr->time = ev_time;
+ tr->x = x;
+ tr->y = y;
+ }
+
+ /*
+ * Don't post event if mouse is within bounding box,
+ * Note our y-s are upside down
+ */
+ if (y < up->mouse_box.bottom &&
+ y >= up->mouse_box.top &&
+ x < up->mouse_box.right &&
+ x >= up->mouse_box.left)
+ return;
+ up->mouse_box.bottom = 0; /* X11 wants it ? */
+
+ /*
+ * Post motion event now
+ */
+#define round(x) ((x) & (MAX_EVENTS - 1))
+ {
+ register unsigned int head = up->evque.q_head;
+ register unsigned int tail = up->evque.q_tail;
+ register screen_event_t *ev;
+
+ if (round(tail + 1) == head) /* queue full, drop it */
+ return;
+
+ /* see if we can spare too many motion events */
+ next = round(tail - 1);
+ if (compress_mouse_events &&
+ (tail != head) && (next != head)) {
+ ev = & up->event_queue[next];
+ if (ev->type == EVT_PTR_MOTION) {
+ ev->x = x;
+ ev->y = y;
+ ev->time = ev_time;
+ ev->device = device;
+ screen_event_posted(up);
+ return;
+ }
+ }
+ ev = & up->event_queue[tail];
+ ev->type = EVT_PTR_MOTION;
+ ev->time = ev_time;
+ ev->x = x;
+ ev->y = y;
+ ev->device = device;
+
+ /* added to queue */
+ up->evque.q_tail = round(tail + 1);
+ }
+
+ /*
+ * Wakeup any sleepers
+ */
+ screen_event_posted(up);
+}
+
+/*
+ * Upcall from keypress input devices
+ * Returns wether the event was consumed or not.
+ */
+boolean_t
+screen_keypress_event(
+ int unit,
+ int device,
+ int key,
+ int type)
+{
+ register screen_softc_t sc = screen_softc[unit];
+ register user_info_t *up = sc->up;
+ register unsigned int head, tail;
+ register screen_event_t *ev;
+
+ if (!sc->mapped) {
+ int col, row;
+
+ if (device != DEV_MOUSE)
+ return FALSE;
+ /* generate escapes for mouse position */
+ col = up->mouse_loc.x / 8;
+ row = up->mouse_loc.y / 15;
+ mouse_report_position(unit, col, row, key, type);
+ return TRUE;
+ }
+
+ head = up->evque.q_head;
+ tail = up->evque.q_tail;
+
+ if (round(tail + 1) == head) /* queue full */
+ return TRUE;
+
+ ev = & up->event_queue[tail];
+ ev->key = key;
+ ev->type = type;
+ ev->device = device;
+ ev->time = approx_time_in_msec();
+ ev->x = up->mouse_loc.x;
+ ev->y = up->mouse_loc.y;
+
+ up->evque.q_tail = round(tail + 1);
+
+ screen_event_posted(up);
+
+ return TRUE;
+}
+#undef round
+
+/*
+ * Event queue initialization
+ */
+screen_event_init(
+ user_info_t *up)
+{
+ up->evque.q_size = MAX_EVENTS;
+ up->evque.q_head = 0;
+ up->evque.q_tail = 0;
+; up->evque.t_size = MAX_TRACK;
+ up->evque.t_next = 0;
+ up->evque.timestamp = approx_time_in_msec();
+
+}
+
+/*
+ * Set/Get status functions.
+ * ...
+ */
+io_return_t
+screen_set_status(
+ int unit,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t status_count)
+{
+ register screen_softc_t sc = screen_softc[unit];
+ register user_info_t *up = sc->up;
+ io_return_t ret = D_SUCCESS;
+
+/* XXX checks before getting here */
+
+ switch (flavor) {
+
+ case SCREEN_INIT:
+ ascii_screen_initialize(sc);
+ break;
+
+ case SCREEN_ON:
+ screen_on_off(unit, TRUE);
+ break;
+
+ case SCREEN_OFF:
+ screen_on_off(unit, FALSE);
+ break;
+
+ case SCREEN_FADE: {
+ register int tm = * (int *) status;
+
+ untimeout(screen_saver, unit); /* stop everything and */
+ if (tm == -1) /* don't reschedule a fade */
+ break;
+ if (tm < SSAVER_MIN_TIME)
+ tm = SSAVER_MIN_TIME;
+ ssaver_time = tm;
+ ssaver_bump(unit);
+ screen_saver(unit);
+ break;
+ }
+
+ case SCREEN_SET_CURSOR: {
+ screen_point_t *loc = (screen_point_t*) status;
+
+ if (status_count < sizeof(screen_point_t)/sizeof(int))
+ return D_INVALID_SIZE;
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ up->mouse_loc = *loc;
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ screen_set_cursor(sc, loc->x, loc->y);
+
+ break;
+ }
+
+ /* COMPAT: these codes do nothing, but we understand */
+ case _IO('q', 8): /* KERNLOOP */
+ case _IO('q', 9): /* KERNUNLOOP */
+ case _IO('g', 21): /* KERN_UNLOOP */
+ break;
+
+ /*
+ * Anything else is either device-specific,
+ * or for the keyboard
+ */
+ default:
+ ret = (*sc->sw.set_status)(sc, flavor, status, status_count);
+ if (ret == D_INVALID_OPERATION)
+ ret = (*sc->kbd_set_status)(unit, flavor,
+ status, status_count);
+ break;
+ }
+ return ret;
+}
+
+io_return_t
+screen_get_status(
+ int unit,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ natural_t *count)
+{
+ register screen_softc_t sc = screen_softc[unit];
+
+ if (flavor == SCREEN_STATUS_FLAGS) {
+ *(int *)status = sc->flags;
+ *count = 1;
+ return D_SUCCESS;
+ } else if (flavor == SCREEN_HARDWARE_INFO) {
+ screen_hw_info_t *hinfo;
+
+ hinfo = (screen_hw_info_t*)status;
+ hinfo->frame_width = sc->frame_scanline_width;
+ hinfo->frame_height = sc->frame_height;
+ hinfo->frame_visible_width = sc->frame_visible_width;
+ hinfo->frame_visible_height = sc->frame_visible_height;
+ *count = sizeof(screen_hw_info_t)/sizeof(int);
+ return D_SUCCESS;
+ } else
+
+ return (*sc->sw.get_status)(sc, flavor, status, count);
+}
+
+/*
+ * Routine to handle display and control characters sent to screen
+ */
+void
+screen_blitc(
+ int unit,
+ register unsigned char c)
+{
+ register screen_softc_t sc = screen_softc[unit];
+ register user_info_t *up = sc->up;
+ register unsigned char *ap;
+ register int i;
+
+ /*
+ * Handle cursor positioning sequence
+ */
+ switch (sc->blitc_state) {
+ case SCREEN_BLITC_NORMAL:
+ break;
+
+ case SCREEN_BLITC_ROW:
+ c -= ' ';
+ if (c >= up->max_row) {
+ up->row = up->max_row - 1;
+ } else {
+ up->row = c;
+ }
+ sc->blitc_state = SCREEN_BLITC_COL;
+ return;
+
+ case SCREEN_BLITC_COL:
+ c -= ' ';
+ if (c >= up->max_col) {
+ up->col = up->max_col - 1;
+ } else {
+ up->col = c;
+ }
+ sc->blitc_state = SCREEN_BLITC_NORMAL;
+ goto move_cursor;
+ }
+
+ c &= 0xff;
+
+ /* echo on rconsole line */
+ rcputc(c);
+
+ /* we got something to say, turn on the TV */
+ ssaver_bump(unit);
+
+ switch (c) {
+ /* Locate cursor*/
+ case Ctrl('A'): /* ^A -> cm */
+ sc->blitc_state = SCREEN_BLITC_ROW;
+ return;
+
+ /* Home cursor */
+ case Ctrl('B'): /* ^B -> ho */
+ up->row = 0;
+ up->col = 0;
+ break;
+
+ /* Clear screen */
+ case Ctrl('C'): /* ^C -> cl */
+ up->row = 0;
+ up->col = 0;
+ (*sc->sw.clear_bitmap)(sc);
+ break;
+
+ /* Move forward */
+ case Ctrl('D'): /* ^D -> nd */
+ screen_advance_position(sc);
+ break;
+
+ /* Clear to eol */
+ case Ctrl('E'): /* ^E -> ce */
+ ap = &sc->ascii_screen[up->max_col*up->row + up->col];
+ for (i = up->col; i < up->max_col; i++, ap++) {
+ if (sc->standout || *ap != ' ') {
+ if (sc->standout) {
+ *ap = SCREEN_ASCII_INVALID;
+ } else {
+ *ap = ' ';
+ }
+ screen_blitc_at(sc, ' ', up->row, i);
+ }
+ }
+ return;
+
+ /* Cursor up */
+ case Ctrl('F'): /* ^F -> up */
+ if (up->row != 0) up->row--;
+ break;
+
+ case Ctrl('G'): /* ^G -> bell */
+ (*sc->kbd_beep)(unit);
+ return;
+
+ /* Backspace */
+ case Ctrl('H'): /* ^H -> bs */
+ if (--up->col < 0)
+ up->col = 0;
+ break;
+
+ case Ctrl('I'): /* ^I -> tab */
+ up->col += (8 - (up->col & 0x7));
+ break;
+
+ case Ctrl('J'): /* ^J -> lf */
+ if (up->row+1 >= up->max_row)
+ (*sc->sw.remove_line)(sc, 0);
+ else
+ up->row++;
+ break;
+
+ /* Start rev-video */
+ case Ctrl('K'): /* ^K -> so */
+ sc->standout = 1;
+ return;
+
+ /* End rev-video */
+ case Ctrl('L'): /* ^L -> se */
+ sc->standout = 0;
+ return;
+
+ case Ctrl('M'): /* ^M -> return */
+ up->col = 0;
+ break;
+
+ /* Save cursor position */
+ case Ctrl('N'): /* ^N -> sc */
+ sc->save_col = up->col;
+ sc->save_row = up->row;
+ return;
+
+ /* Restore cursor position */
+ case Ctrl('O'): /* ^O -> rc */
+ up->row = sc->save_row;
+ up->col = sc->save_col;
+ break;
+
+ /* Add blank line */
+ case Ctrl('P'): /* ^P -> al */
+ (*sc->sw.insert_line)(sc, up->row);
+ return;
+
+ /* Delete line */
+ case Ctrl('Q'): /* ^Q -> dl */
+ (*sc->sw.remove_line)(sc, up->row);
+ return;
+
+ default:
+ /*
+ * If the desired character is already there, then don't
+ * bother redrawing it. Always redraw standout-ed chars,
+ * so that we can assume that all cached characters are
+ * un-standout-ed. (This could be fixed.)
+ */
+ ap = &sc->ascii_screen[up->max_col*up->row + up->col];
+ if (sc->standout || c != *ap) {
+ if (sc->standout) {
+ *ap = SCREEN_ASCII_INVALID;
+ } else {
+ *ap = c;
+ }
+ screen_blitc_at(sc, c, up->row, up->col);
+ }
+ screen_advance_position(sc);
+ break;
+ }
+
+move_cursor:
+ screen_set_cursor(sc, up->col*8, up->row*15);
+
+}
+
+
+/*
+ * Advance current position, wrapping and scrolling when necessary
+ */
+screen_advance_position(
+ register screen_softc_t sc)
+{
+ register user_info_t *up = sc->up;
+
+ if (++up->col >= up->max_col) {
+ up->col = 0 ;
+ if (up->row+1 >= up->max_row) {
+ (*sc->sw.remove_line)(sc, 0);
+ } else {
+ up->row++;
+ }
+ }
+}
+
+
+/*
+ * Routine to display a character at a given position
+ */
+void
+screen_blitc_at(
+ register screen_softc_t sc,
+ unsigned char c,
+ short row,
+ short col)
+{
+ /*
+ * Silently ignore non-printable chars
+ */
+ if (c < ' ' || c > 0xfd)
+ return;
+ (*sc->sw.char_paint)(sc, c, row, col);
+}
+
+/*
+ * Update sc->ascii_screen array after deleting ROW
+ */
+ascii_screen_rem_update(
+ register screen_softc_t sc,
+ int row)
+{
+ register user_info_t *up = sc->up;
+ register unsigned int col_w, row_w;
+ register unsigned char *c, *end;
+
+ /* cache and sanity */
+ col_w = up->max_col;
+ if (col_w > MaxCharCols)
+ col_w = MaxCharCols;
+ row_w = up->max_row;
+ if (row_w > MaxCharRows)
+ row_w = MaxCharRows;
+
+ /* scroll up */
+ c = &sc->ascii_screen[row * col_w];
+ end = &sc->ascii_screen[(row_w-1) * col_w];
+ for (; c < end; c++) /* bcopy ? XXX */
+ *c = *(c + col_w);
+
+ /* zero out line that entered at end */
+ c = end;
+ end = &sc->ascii_screen[row_w * col_w];
+ for (; c < end; c++)
+ *c = ' ';
+
+}
+
+/*
+ * Update sc->ascii_screen array after opening new ROW
+ */
+ascii_screen_ins_update(
+ register screen_softc_t sc,
+ int row)
+{
+ register user_info_t *up = sc->up;
+ register unsigned int col_w, row_w;
+ register unsigned char *c, *end;
+
+ /* cache and sanity */
+ col_w = up->max_col;
+ if (col_w > MaxCharCols)
+ col_w = MaxCharCols;
+ row_w = up->max_row;
+ if (row_w > MaxCharRows)
+ row_w = MaxCharRows;
+
+ /* scroll down */
+ c = &sc->ascii_screen[row_w * col_w - 1];
+ end = &sc->ascii_screen[(row + 1) * col_w];
+ for (; c >= end; c--)
+ *c = *(c - col_w);
+
+ /* zero out line that entered at row */
+ c = end - 1;
+ end = &sc->ascii_screen[row * col_w];
+ for (; c >= end; c--)
+ *c = ' ';
+}
+
+/*
+ * Init charmap
+ */
+ascii_screen_fill(
+ register screen_softc_t sc,
+ char c)
+{
+ register user_info_t *up = sc->up;
+ register int i, to;
+
+ to = up->max_row * up->max_col;
+ for (i = 0; i < to; i++) {
+ sc->ascii_screen[i] = c;
+ }
+}
+
+ascii_screen_initialize(
+ register screen_softc_t sc)
+{
+ ascii_screen_fill(sc, SCREEN_ASCII_INVALID);
+}
+
+/*
+ * Cursor positioning
+ */
+screen_set_cursor(
+ register screen_softc_t sc,
+ register int x,
+ register int y)
+{
+ register user_info_t *up = sc->up;
+
+ /* If we are called from interrupt level.. */
+ if (sc->flags & SCREEN_BEING_UPDATED)
+ return;
+ sc->flags |= SCREEN_BEING_UPDATED;
+ /*
+ * Note that that was not atomic, but this is
+ * a two-party game on the same processor and
+ * not a real parallel program.
+ */
+
+ /* Sanity checks (ignore noise) */
+ if (y < up->min_cur_y || y > up->max_cur_y)
+ y = up->cursor.y;
+ if (x < up->min_cur_x || x > up->max_cur_x)
+ x = up->cursor.x;
+
+ /*
+ * Track cursor position
+ */
+ up->cursor.x = x;
+ up->cursor.y = y;
+
+ (*sc->sw.pos_cursor)(*(sc->hw_state), x, y);
+
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+}
+
+screen_on_off(
+ int unit,
+ boolean_t on)
+{
+ register screen_softc_t sc = screen_softc[unit];
+
+ if (sc->sw.video_on == 0) /* sanity */
+ return;
+
+ if (on)
+ (*sc->sw.video_on)(sc->hw_state, sc->up);
+ else
+ (*sc->sw.video_off)(sc->hw_state, sc->up);
+}
+
+screen_enable_vretrace(
+ int unit,
+ boolean_t on)
+{
+ register screen_softc_t sc = screen_softc[unit];
+ (*sc->sw.intr_enable)(sc->hw_state, on);
+}
+
+/*
+ * For our purposes, time does not need to be
+ * precise but just monotonic and approximate
+ * to about the millisecond. Instead of div/
+ * mul by 1000 we div/mul by 1024 (shifting).
+ *
+ * Well, it almost worked. The only problem
+ * is that X somehow checks the time against
+ * gettimeofday() and .. turns screen off at
+ * startup if we use approx time. SO we are
+ * back to precise time, sigh.
+ */
+approx_time_in_msec()
+{
+#if 0
+ return ((time.seconds << 10) + (time.microseconds >> 10));
+#else
+ return ((time.seconds * 1000) + (time.microseconds / 1000));
+#endif
+}
+
+/*
+ * Screen mapping to user space
+ * This is called on a per-page basis
+ */
+screen_mmap(
+ int dev,
+ vm_offset_t off,
+ int prot)
+{
+ /* dev is safe, but it is the mouse's one */
+ register screen_softc_t sc = screen_softc[dev-1];
+
+ (*sc->sw.map_page)(sc, off, prot);
+}
+
+#endif NBM > 0
diff --git a/chips/screen.h b/chips/screen.h
new file mode 100644
index 00000000..69154d49
--- /dev/null
+++ b/chips/screen.h
@@ -0,0 +1,289 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: screen.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Definitions for the Generic Screen Driver.
+ */
+
+/*
+ * Most of these structures are defined so that the
+ * resulting structure mapped to user space appears
+ * to be compatible with the one used by the DEC X
+ * servers (pm_info..). Keep it that way and the
+ * X servers will keep on running.
+ */
+
+/*
+ * Generic structures and defines
+ */
+
+/* colors */
+typedef struct {
+ unsigned short red;
+ unsigned short green;
+ unsigned short blue;
+} color_map_t;
+
+typedef struct {
+ short unused;
+ unsigned short index;
+ color_map_t value;
+} color_map_entry_t;
+
+typedef struct {
+ unsigned int Bg_rgb[3];
+ unsigned int Fg_rgb[3];
+} cursor_color_t;
+
+/* generic input event */
+typedef struct {
+ short x; /* x position */
+ short y; /* y position */
+ unsigned int time; /* 1 millisecond units */
+
+ unsigned char type; /* button up/down/raw or motion */
+# define EVT_BUTTON_UP 0
+# define EVT_BUTTON_DOWN 1
+# define EVT_BUTTON_RAW 2
+# define EVT_PTR_MOTION 3
+
+ unsigned char key; /* the key (button only) */
+# define KEY_LEFT_BUTTON 1
+# define KEY_MIDDLE_BUTTON 2
+# define KEY_RIGHT_BUTTON 3
+# define KEY_TBL_LEFT_BUTTON 0
+# define KEY_TBL_FRONT_BUTTON 1
+# define KEY_TBL_RIGHT_BUTTON 2
+# define KEY_TBL_BACK_BUTTON 3
+
+ unsigned char index; /* which instance of device */
+
+ unsigned char device; /* which device */
+# define DEV_NULL 0
+# define DEV_MOUSE 1
+# define DEV_KEYBD 2
+# define DEV_TABLET 3
+# define DEV_AUX 4
+# define DEV_CONSOLE 5
+# define DEV_KNOB 8
+# define DEV_JOYSTICK 9
+
+} screen_event_t;
+
+/* timed coordinate info */
+typedef struct {
+ unsigned int time;
+ short x, y;
+} screen_timed_point_t;
+
+/* queue of input events, and ring of mouse motions track */
+typedef struct {
+ screen_event_t *events;
+ unsigned int q_size;
+ unsigned int q_head;
+ unsigned int q_tail;
+ unsigned long timestamp;
+ screen_timed_point_t *track;
+ unsigned int t_size;
+ unsigned int t_next;
+} screen_evque_t;
+
+/* mouse/cursor position */
+typedef struct {
+ short x;
+ short y;
+} screen_point_t;
+
+/* mouse motion bounding boxes */
+typedef struct {
+ short bottom;
+ short right;
+ short left;
+ short top;
+} screen_rect_t;
+
+/*
+ * Here it is, each field is marked as
+ *
+ * Kset : kernel sets it unconditionally
+ * Kuse : kernel uses it, safely
+ * Kdep : kernel might depend on it
+ */
+typedef struct {
+ screen_evque_t evque; /* Kset, Kuse */
+ short mouse_buttons; /* Kset */
+ screen_point_t xx3 /*tablet*/;
+ short xx4 /*tswitches*/;
+ screen_point_t cursor; /* Kset */
+ short row; /* Kdep */
+ short col; /* Kdep */
+ short max_row; /* Kdep */
+ short max_col; /* Kdep */
+ short max_x; /* Kset */
+ short max_y; /* Kset */
+ short max_cur_x; /* Kdep */
+ short max_cur_y; /* Kdep */
+ int version; /* Kset */
+ union {
+ struct {
+ unsigned char * bitmap; /* Kset */
+ short * x16 /*scanmap*/;
+ short * x17 /*cursorbits*/;
+ short * x18 /*pmaddr*/;
+ unsigned char * planemask; /* Kset */
+ } pm;
+ struct {
+ int x15 /* flags */;
+ int * gram /* Kset */;
+ int * rb_addr /* Kset */;
+ int rb_phys /* Kset */;
+ int rb_size /* Kset */;
+ } gx;
+ } dev_dep_1;
+ screen_point_t mouse_loc; /* Kdep */
+ screen_rect_t mouse_box; /* Kdep */
+ short mouse_threshold;/* Kuse */
+ short mouse_scale; /* Kuse */
+ short min_cur_x; /* Kdep */
+ short min_cur_y; /* Kdep */
+ union {
+ struct {
+ int x26 /*dev_type*/;
+ char * x27 /*framebuffer*/;
+ char * x28 /*volatile struct bt459 *bt459*/;
+ int x29 /*slot*/;
+ char cursor_sprite[1024];/* Kset */
+ unsigned char Bg_color[3]; /* Kset */
+ unsigned char Fg_color[3]; /* Kset */
+ int tablet_scale_x; /* Kuse */
+ int tablet_scale_y; /* Kuse */
+ } pm;
+ struct {
+ char * gxo /* Kset */;
+ char stamp_width /* Kset */;
+ char stamp_height /* Kset */;
+ char nplanes /* Kset */;
+ char x27_4 /* n10_present */;
+ char x28_1 /* dplanes */;
+ char zplanes /* Kset */;
+ char zzplanes /* Kset */;
+ unsigned char cursor_sprite[1024] /* Kuse */;
+ char x285_0 /* padding for next, which was int */;
+ unsigned char Fg_color[4] /* Kuse */;
+ unsigned char Bg_color[4] /* Kuse */;
+ unsigned short cmap_index /* Kuse */;
+ unsigned short cmap_count /* Kuse */;
+ unsigned int colormap[256] /* Kuse */;
+ int * stic_dma_rb /* Kset */;
+ int * stic_reg /* Kset */;
+ int ptpt_phys /* Kdep */;
+ int ptpt_size /* Kdep */;
+ int * ptpt_pgin /* Kset */;
+ } gx;
+ } dev_dep_2;
+ short frame_scanline_width; /* in pixels, Kset */
+ short frame_height; /* in scanlines, Kset */
+ /*
+ * Event queues are allocated right after that
+ */
+#define MAX_EVENTS 64
+#define MAX_TRACK 100
+ screen_event_t event_queue[MAX_EVENTS]; /* Kset */
+ screen_timed_point_t point_track[MAX_TRACK]; /* Kset */
+ /*
+ * Some like it hot
+ */
+ unsigned int event_id;
+ int interrupt_info;
+} user_info_t;
+
+
+/*
+ * Screen get_status codes and arguments
+ */
+#include <sys/ioctl.h>
+
+ /* Get size (and offset) of mapped info */
+#define SCREEN_GET_OFFSETS _IOR('q', 6, unsigned **)
+
+ /* Get screen status flags */
+#define SCREEN_STATUS_FLAGS _IOR('q', 22, int *)
+# define MONO_SCREEN 0x01
+# define COLOR_SCREEN 0x02
+# define SCREEN_BEING_UPDATED 0x04
+
+/*
+ * Screen set_status codes and arguments
+ */
+
+ /* start/stop screen saver, control fading interval */
+#define SCREEN_FADE _IOW('q', 114, int) /* fade screen */
+# define NO_FADE -1
+
+ /* Turn video on/off manually */
+#define SCREEN_ON _IO('q', 10)
+#define SCREEN_OFF _IO('q', 11)
+
+ /* Fixup pointers inside mapped info structure */
+#define SCREEN_ADJ_MAPPED_INFO _IOR('q', 1, user_info_t *)
+
+ /* Initialize anything that needs to, hw-wise */
+#define SCREEN_INIT _IO('q', 4)
+
+ /* Position cursor to a specific spot */
+#define SCREEN_SET_CURSOR _IOW('q', 2, screen_point_t)
+
+ /* Load Bg/Fg colors for cursor */
+#define SCREEN_SET_CURSOR_COLOR _IOW('q', 3, cursor_color_t)
+
+ /* Load cursor sprite, small cursor form */
+typedef unsigned short cursor_sprite_t[32];
+
+#define SCREEN_LOAD_CURSOR _IOW('q', 7, cursor_sprite_t)
+
+ /* Load cursor sprite, large 64x64 cursor form */
+typedef char cursor_sprite_long_t[1024];
+
+#define SCREEN_LOAD_CURSOR_LONG _IOW('q', 13, cursor_sprite_long_t)
+
+ /* Modify a given entry in the color map (VDAC) */
+#define SCREEN_SET_CMAP_ENTRY _IOW('q', 12, color_map_entry_t)
+
+ /* Return some other information about hardware (optional) */
+typedef struct {
+ int frame_width;
+ int frame_height;
+ int frame_visible_width;
+ int frame_visible_height;
+} screen_hw_info_t;
+#define SCREEN_HARDWARE_INFO _IOR('q', 23, screen_hw_info_t)
+
+ /* Screen-dependent, unspecified (and despised) */
+#define SCREEN_HARDWARE_DEP _IO('q', 24)
+
diff --git a/chips/screen_defs.h b/chips/screen_defs.h
new file mode 100644
index 00000000..083e11e5
--- /dev/null
+++ b/chips/screen_defs.h
@@ -0,0 +1,97 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: screen_defs.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 11/90
+ *
+ * Definitions for the Generic Screen Driver.
+ */
+
+#include <chips/screen.h>
+#include <chips/screen_switch.h>
+#include <device/device_types.h>
+
+/*
+ * Driver state
+ */
+typedef struct screen_softc {
+ user_info_t *up;
+ char **hw_state; /* semi-opaque */
+
+ struct screen_switch sw;
+
+ /* should also be a switch */
+ io_return_t (*kbd_set_status)();
+ int (*kbd_reset)();
+ int (*kbd_beep)();
+
+ char flags;
+ char mapped;
+ char blitc_state;
+ char standout;
+ short save_row;
+ short save_col;
+ /*
+ * Eventually move here all that is Kdep in the user structure,
+ * to avoid crashing because of a bogus graphic server
+ */
+ short frame_scanline_width; /* in pixels */
+ short frame_height; /* in scanlines */
+ short frame_visible_width; /* in pixels */
+ short frame_visible_height; /* in pixels */
+
+/* This is used by all screens, therefore it is sized maximally */
+# define MaxCharRows 68 /* 2DA screen & PMAG-AA */
+# define MaxCharCols 160 /* PMAG-AA */
+# define MinCharRows 57 /* pmax */
+ unsigned char ascii_screen[MaxCharRows*MaxCharCols];
+
+} *screen_softc_t;
+
+extern screen_softc_t screen(/* int unit */);
+
+/*
+ * This global says if we have a graphic console
+ * and where it is and if it is enabled
+ */
+extern short screen_console;
+#define SCREEN_CONS_ENBL (0x0100)
+#define SCREEN_ISA_CONSOLE() (screen_console & SCREEN_CONS_ENBL)
+#define SCREEN_CONS_UNIT() (screen_console & 0x00ff)
+
+/*
+ * A graphic screen needs a keyboard and a mouse/tablet
+ */
+#define SCREEN_LINE_KEYBOARD 0
+#define SCREEN_LINE_POINTER 1
+#define SCREEN_LINE_OTHER (-1)
+
+/* kernel font */
+#define KfontWidth 8
+#define KfontHeight 15
+extern unsigned char kfont_7x14[];
+
diff --git a/chips/screen_switch.c b/chips/screen_switch.c
new file mode 100644
index 00000000..e216a534
--- /dev/null
+++ b/chips/screen_switch.c
@@ -0,0 +1,154 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: screen_switch.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Autoconfiguration code for the Generic Screen Driver.
+ */
+
+#include <platforms.h>
+
+#if defined(DECSTATION) || defined(FLAMINGO)
+#include <fb.h>
+#include <gx.h>
+#include <cfb.h>
+#include <mfb.h>
+#include <xcfb.h>
+#include <sfb.h>
+#endif
+
+#ifdef VAXSTATION
+#define NGX 0
+#define NCFB 0
+#define NXCFB 0
+#endif
+
+#include <chips/screen_switch.h>
+
+/* When nothing needed */
+int screen_noop()
+{}
+
+/*
+ * Vector of graphic interface drivers to probe.
+ * Zero terminate this list.
+ */
+
+
+#if NGX > 0
+extern int gq_probe(), gq_cold_init();
+extern unsigned int gq_mem_need();
+
+extern int ga_probe(), ga_cold_init();
+extern unsigned int ga_mem_need();
+#endif /* NGX > 0 */
+
+#if NCFB > 0
+extern int cfb_probe(), cfb_cold_init();
+extern unsigned int pm_mem_need();
+#endif /* NCFB > 0 */
+
+#if NMFB > 0
+extern int fb_probe(), fb_cold_init();
+extern unsigned int pm_mem_need();
+#endif /* NMFB > 0 */
+
+#if NXCFB > 0
+extern int xcfb_probe(), xcfb_cold_init();
+extern unsigned int pm_mem_need();
+#endif /* NXCFB > 0 */
+
+#if NSFB > 0
+extern int sfb_probe(), sfb_cold_init();
+extern unsigned int pm_mem_need();
+#endif /* NSFB > 0 */
+
+#if NFB > 0
+extern int pm_probe(), pm_cold_init();
+extern unsigned int pm_mem_need();
+#endif /* NFB > 0 */
+
+struct screen_probe_vector screen_probe_vector[] = {
+
+#if NGX > 0
+ gq_probe, gq_mem_need, gq_cold_init, /* 3max 3D color option */
+ ga_probe, ga_mem_need, ga_cold_init, /* 3max 2D color option */
+#endif /* NGX > 0 */
+
+#if NSFB > 0
+ sfb_probe, pm_mem_need, sfb_cold_init, /* Smart frame buffer */
+#endif /* NSFB > 0 */
+
+#if NMFB > 0
+ fb_probe, pm_mem_need, fb_cold_init, /* 3max/3min 1D(?) mono option */
+#endif /* NMFB > 0 */
+
+#if NCFB > 0
+ cfb_probe, pm_mem_need, cfb_cold_init, /* 3max 1D(?) color option */
+#endif /* NCFB > 0 */
+
+#if NXCFB > 0
+ xcfb_probe, pm_mem_need, xcfb_cold_init,/* MAXine frame buffer */
+#endif /* NXCFB > 0 */
+
+#if NFB > 0
+ pm_probe, pm_mem_need, pm_cold_init, /* "pm" mono/color (pmax) */
+#endif
+ 0,
+};
+
+char *screen_data; /* opaque */
+
+int screen_find()
+{
+ struct screen_probe_vector *p = screen_probe_vector;
+ for (;p->probe; p++)
+ if ((*p->probe)()) {
+ (*p->setup)(0/*XXX*/, screen_data);
+ return 1;
+ }
+ return 0;
+}
+
+unsigned int
+screen_memory_alloc(avail)
+ char *avail;
+{
+ struct screen_probe_vector *p = screen_probe_vector;
+ int size;
+ for (; p->probe; p++)
+ if ((*p->probe) ()) {
+ screen_data = avail;
+ size = (*p->alloc) ();
+ bzero(screen_data, size);
+ return size;
+ }
+ return 0;
+
+}
+
diff --git a/chips/screen_switch.h b/chips/screen_switch.h
new file mode 100644
index 00000000..a84b4e7f
--- /dev/null
+++ b/chips/screen_switch.h
@@ -0,0 +1,85 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: screen_switch.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 10/90
+ *
+ * Definitions of things that must be tailored to
+ * specific hardware boards for the Generic Screen Driver.
+ */
+
+#ifndef SCREEN_SWITCH_H
+#define SCREEN_SWITCH_H 1
+
+/*
+ * List of probe routines, scanned at cold-boot time
+ * to see which, if any, graphic display is available.
+ * This is done before autoconf, so that printing on
+ * the console works early on. The alloc routine is
+ * called only on the first device that answers.
+ * Ditto for the setup routine, called later on.
+ */
+struct screen_probe_vector {
+ int (*probe)();
+ unsigned int (*alloc)();
+ int (*setup)();
+};
+
+/*
+ * Low-level operations on the graphic device, used
+ * by the otherwise device-independent interface code
+ */
+struct screen_switch {
+ int (*graphic_open)(); /* when X11 opens */
+ int (*graphic_close)(); /* .. or closes */
+ int (*set_status)(); /* dev-specific ops */
+ int (*get_status)(); /* dev-specific ops */
+ int (*char_paint)(); /* blitc */
+ int (*pos_cursor)(); /* cursor positioning */
+ int (*insert_line)(); /* ..and scroll down */
+ int (*remove_line)(); /* ..and scroll up */
+ int (*clear_bitmap)(); /* blank screen */
+ int (*video_on)(); /* screen saver */
+ int (*video_off)();
+ int (*intr_enable)();
+ int (*map_page)(); /* user-space mapping */
+};
+
+/*
+ * Each graphic device needs page-aligned memory
+ * to be mapped in user space later (for events
+ * and such). Size and content of this memory
+ * is unfortunately device-dependent, even if
+ * it did not need to (puns).
+ */
+extern char *screen_data;
+
+extern struct screen_probe_vector screen_probe_vector[];
+
+extern int screen_noop(), screen_find();
+
+#endif SCREEN_SWITCH_H
diff --git a/chips/serial_console.c b/chips/serial_console.c
new file mode 100644
index 00000000..7b15dd4c
--- /dev/null
+++ b/chips/serial_console.c
@@ -0,0 +1,694 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: serial_console.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 7/91
+ *
+ * Console driver for serial-line based consoles.
+ */
+
+#include <constty.h>
+#if NCONSTTY > 0
+#include <bm.h>
+#include <platforms.h>
+
+#include <mach_kdb.h>
+
+#include <machine/machspl.h> /* spl definitions */
+#include <device/io_req.h>
+#include <device/tty.h>
+#include <sys/syslog.h>
+
+#include <chips/busses.h>
+#include <chips/screen_defs.h>
+#include <chips/serial_defs.h>
+
+#ifdef DECSTATION
+#include <mips/prom_interface.h>
+#define find_rconsole(p) dec_check_rcline(p)
+#define CONSOLE_SERIAL_LINE_NO 3
+#endif /*DECSTATION*/
+
+#ifdef VAXSTATION
+#define find_rconsole(p)
+#define cnputc ser_putc
+#define cngetc ser_getc
+#define cnpollc ser_pollc
+#define cnmaygetc ser_maygetc
+#define CONSOLE_SERIAL_LINE_NO 3
+#endif /*VAXSTATION*/
+
+#ifdef FLAMINGO
+#define CONSOLE_SERIAL_LINE_NO 3
+#endif
+
+#ifndef CONSOLE_SERIAL_LINE_NO
+#define CONSOLE_SERIAL_LINE_NO 0
+#endif
+
+/* Size this as max possible number of lines in any serial chip we might use */
+static struct tty console_tty_data[NCONSTTY];
+struct tty *console_tty[NCONSTTY]; /* exported */
+
+#define DEFAULT_SPEED B9600
+#define DEFAULT_FLAGS (TF_EVENP|TF_ODDP|TF_ECHO)
+
+
+/*
+ * A machine MUST have a console. In our case
+ * things are a little complicated by the graphic
+ * display: people expect it to be their "console",
+ * but we'd like to be able to live without it.
+ * This is not to be confused with the "rconsole" thing:
+ * that just duplicates the console I/O to
+ * another place (for debugging/logging purposes).
+ *
+ * There is then another historical kludge: if
+ * there is a graphic display it is assumed that
+ * the minor "1" is the mouse, with some more
+ * magic attached to it. And again, one might like to
+ * use the serial line 1 as a regular one.
+ *
+ */
+#define user_console 0
+
+int console = 0;
+
+int (*console_probe)() = 0,
+ (*console_param)() = 0,
+ (*console_start)() = 0,
+ (*console_putc)() = 0,
+ (*console_getc)() = 0,
+ (*console_pollc)() = 0,
+ (*console_mctl)() = 0,
+ (*console_softCAR)() = 0;
+
+/*
+ * Lower-level (internal) interfaces, for printf and gets
+ */
+int cnunit = 0; /* which unit owns the 'console' */
+int cnline = 0; /* which line of that unit */
+int rcline = 3; /* alternate, "remote console" line */
+
+rcoff()
+{
+ spl_t s = splhigh();
+ cnpollc(FALSE);
+ rcline = 0;
+ cnpollc(TRUE);
+ splx(s);
+}
+
+rcputc(c)
+{
+ if (rcline)
+ (*console_putc)( cnunit, rcline, c);
+}
+
+cnputc(c)
+{
+#if NBM > 0
+ if (SCREEN_ISA_CONSOLE()) {
+ /* this does its own rcputc */
+ screen_blitc(SCREEN_CONS_UNIT(), c);
+ } else
+#endif NBM > 0
+ {
+ rcputc(c);
+ (*console_putc)( cnunit, cnline, c);/* insist on a console still */
+ }
+ if (c == '\n')
+ cnputc('\r');
+}
+
+cngetc()
+{
+ return (*console_getc)( cnunit, cnline, TRUE, FALSE);
+}
+
+cnpollc(bool)
+{
+ (*console_pollc)(cnunit, bool);
+}
+
+
+/* Debugger support */
+cnmaygetc()
+{
+ return (*console_getc)( cnunit, cnline, FALSE, FALSE);
+}
+
+
+#if NBM > 0
+boolean_t
+screen_captures(line)
+ register int line;
+{
+ return (SCREEN_ISA_CONSOLE() &&
+ ((line == SCREEN_LINE_KEYBOARD) ||
+ (line == SCREEN_LINE_POINTER)));
+}
+#endif
+
+/*
+ * Higher level (external) interface, for GP use
+ */
+
+
+/*
+ * This is basically a special form of autoconf,
+ * to get printf() going before true autoconf.
+ */
+cons_find(tube)
+ boolean_t tube;
+{
+ static struct bus_device d;
+ register int i;
+ struct tty *tp;
+
+ for (i = 0; i < NCONSTTY; i++)
+ console_tty[i] = &console_tty_data[i];
+ /* the hardware device will set tp->t_addr for valid ttys */
+
+ d.unit = 0;
+
+ if ((console_probe == 0) ||
+ ((*console_probe)(0, &d) == 0)) {
+ /* we have no console, but maybe that's ok */
+#if defined(DECSTATION) || defined(FLAMINGO)
+ /* no, it is not */
+ dprintf("%s", "no console!\n");
+ halt();
+#endif
+ return 0;
+ }
+
+ /*
+ * Remote console line
+ */
+ find_rconsole(&rcline);
+
+ /*
+ * Console always on unit 0. Fix if you need to
+ */
+ cnunit = 0;
+
+#if NBM > 0
+ if (tube && screen_probe(0)) {
+
+ /* associate screen to console iff */
+ if (console == user_console)
+ screen_console = cnunit | SCREEN_CONS_ENBL;
+ cnline = SCREEN_LINE_KEYBOARD;
+
+ /* mouse and keybd */
+ tp = console_tty[SCREEN_LINE_KEYBOARD];
+ tp->t_ispeed = B4800;
+ tp->t_ospeed = B4800;
+ tp->t_flags = TF_LITOUT|TF_EVENP|TF_ECHO|TF_XTABS|TF_CRMOD;
+ tp->t_dev = SCREEN_LINE_KEYBOARD;
+ (*console_param)(tp, SCREEN_LINE_KEYBOARD);
+
+ tp = console_tty[SCREEN_LINE_POINTER];
+ tp->t_ispeed = B4800;
+ tp->t_ospeed = B4800;
+ tp->t_flags = TF_LITOUT|TF_ODDP;
+ tp->t_dev = SCREEN_LINE_POINTER;
+ (*console_param)(tp, SCREEN_LINE_POINTER);
+ /* console_scan will turn on carrier */
+
+ } else {
+#endif NBM > 0
+ /* use non-graphic console as console */
+ cnline = CONSOLE_SERIAL_LINE_NO;
+
+ tp = console_tty[cnline];
+ tp->t_ispeed = B9600;
+ tp->t_ospeed = B9600;
+ tp->t_flags = TF_LITOUT|TF_EVENP|TF_ECHO|TF_XTABS|TF_CRMOD;
+ (*console_softCAR)(cnunit, cnline, TRUE);
+ console = cnline;
+ tp->t_dev = console;
+ (*console_param)(tp, SCREEN_LINE_OTHER);
+#if NBM > 0
+ }
+
+ /*
+ * Enable rconsole interrupts for KDB
+ */
+ if (tube && rcline != cnline) {
+ tp = console_tty[rcline];
+ tp->t_ispeed = B9600;
+ tp->t_ospeed = B9600;
+ tp->t_flags = TF_LITOUT|TF_EVENP|TF_ECHO|TF_XTABS|TF_CRMOD;
+ tp->t_dev = rcline;
+ (*console_softCAR)(cnunit, rcline, TRUE);
+ (*console_param)(tp, SCREEN_LINE_OTHER);
+ } else
+ rcline = 0;
+#endif NBM > 0
+}
+
+/*
+ * Open routine
+ */
+extern int
+ cons_start(struct tty *),
+ cons_stop(struct tty *, int),
+ cons_mctl(struct tty *, int, int);
+
+cons_open(dev, flag, ior)
+ int dev;
+ int flag;
+ io_req_t ior;
+{
+ register struct tty *tp;
+ register int ttyno;
+
+ if (dev == user_console)
+ dev = console;
+
+ ttyno = dev;
+ if (ttyno >= NCONSTTY)
+ return D_NO_SUCH_DEVICE;
+ tp = console_tty[ttyno];
+
+ /* But was it there at probe time */
+ if (tp->t_addr == 0)
+ return D_NO_SUCH_DEVICE;
+
+ tp->t_start = cons_start;
+ tp->t_stop = cons_stop;
+ tp->t_mctl = cons_mctl;
+
+#if NBM > 0
+ if (screen_captures(ttyno))
+ screen_open(SCREEN_CONS_UNIT(), ttyno==SCREEN_LINE_KEYBOARD);
+#endif NBM > 0
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ if (tp->t_ispeed == 0) {
+ tp->t_ispeed = DEFAULT_SPEED;
+ tp->t_ospeed = DEFAULT_SPEED;
+ tp->t_flags = DEFAULT_FLAGS;
+ }
+ tp->t_dev = dev;
+ (*console_param)(tp, ttyno);
+ }
+
+ return (char_open(dev, tp, flag, ior));
+}
+
+
+/*
+ * Close routine
+ */
+cons_close(dev, flag)
+ int dev;
+{
+ register struct tty *tp;
+ register int ttyno;
+ spl_t s;
+
+ if (dev == user_console)
+ dev = console;
+
+ ttyno = dev;
+
+#if NBM > 0
+ if (screen_captures(ttyno))
+ screen_close(SCREEN_CONS_UNIT(), ttyno==SCREEN_LINE_KEYBOARD);
+#endif NBM > 0
+
+ tp = console_tty[ttyno];
+
+ s = spltty();
+ simple_lock(&tp->t_lock);
+
+ ttyclose(tp);
+
+ simple_unlock(&tp->t_lock);
+ splx(s);
+}
+
+cons_read(dev, ior)
+ int dev;
+ register io_req_t ior;
+{
+ register struct tty *tp;
+ register ttyno;
+
+ if (dev == user_console)
+ dev = console;
+
+ ttyno = dev;
+#if NBM > 0
+ if (SCREEN_ISA_CONSOLE() && (ttyno == SCREEN_LINE_POINTER))
+ return screen_read(SCREEN_CONS_UNIT(), ior);
+#endif NBM > 0
+
+ tp = console_tty[ttyno];
+ return char_read(tp, ior);
+}
+
+
+cons_write(dev, ior)
+ int dev;
+ register io_req_t ior;
+{
+ register struct tty *tp;
+ register ttyno;
+
+ if (dev == user_console)
+ dev = console;
+
+ ttyno = dev;
+#if NBM > 0
+ if (screen_captures(ttyno))
+ return screen_write(SCREEN_CONS_UNIT(), ior);
+#endif NBM > 0
+
+ tp = console_tty[ttyno];
+ return char_write(tp, ior);
+}
+
+/*
+ * Start output on a line
+ */
+cons_start(tp)
+ register struct tty *tp;
+{
+ spl_t s;
+
+ s = spltty();
+ if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
+ goto out;
+
+ if (tp->t_outq.c_cc == 0)
+ goto out;
+
+ tp->t_state |= TS_BUSY;
+
+ (*console_start)(tp);
+
+out:
+ splx(s);
+}
+
+/*
+ * Stop output on a line.
+ */
+cons_stop(tp, flag)
+ register struct tty *tp;
+{
+ register spl_t s;
+
+ s = spltty();
+ if (tp->t_state & TS_BUSY) {
+ if ((tp->t_state&TS_TTSTOP)==0)
+ tp->t_state |= TS_FLUSH;
+ }
+ splx(s);
+}
+
+
+/*
+ * Modem control
+ */
+cons_mctl(
+ struct tty *tp,
+ int bits,
+ int how)
+{
+ return (*console_mctl)(tp->t_dev, bits, how);
+}
+
+/*
+ * Abnormal close
+ */
+cons_portdeath(dev, port)
+ int dev;
+ mach_port_t port;
+{
+ if (dev == user_console)
+ dev = console;
+ return (tty_portdeath(console_tty[dev], port));
+}
+
+/*
+ * Get/Set status rotuines
+ */
+io_return_t
+cons_get_status(dev, flavor, data, status_count)
+ int dev;
+ dev_flavor_t flavor;
+ int * data; /* pointer to OUT array */
+ unsigned int *status_count; /* out */
+{
+ register struct tty *tp;
+ register int ttyno;
+
+ if (dev == user_console)
+ dev = console;
+
+ ttyno = dev;
+
+#if NBM > 0
+ if (screen_captures(ttyno) &&
+ (screen_get_status(SCREEN_CONS_UNIT(),
+ flavor, data, status_count) == D_SUCCESS))
+ return D_SUCCESS;
+#endif NBM > 0
+
+ tp = console_tty[ttyno];
+
+ switch (flavor) {
+ case TTY_MODEM:
+ /* Take all bits */
+ *data = (*console_mctl)(dev, -1, DMGET);
+ *status_count = 1;
+ break;
+ default:
+ return (tty_get_status(tp, flavor, data, status_count));
+ }
+ return (D_SUCCESS);
+}
+
+io_return_t
+cons_set_status(dev, flavor, data, status_count)
+ int dev;
+ dev_flavor_t flavor;
+ int * data;
+ unsigned int status_count;
+{
+ register struct tty *tp;
+ register int ttyno;
+
+ if (dev == user_console)
+ dev = console;
+
+ ttyno = dev;
+
+#if NBM > 0
+ if (screen_captures(ttyno) &&
+ (screen_set_status(SCREEN_CONS_UNIT(),
+ flavor, data, status_count) == D_SUCCESS))
+ return D_SUCCESS;
+#endif NBM > 0
+
+ tp = console_tty[ttyno];
+
+ switch (flavor) {
+ case TTY_MODEM:
+ if (status_count < TTY_MODEM_COUNT)
+ return (D_INVALID_OPERATION);
+ (void) (*console_mctl)(dev, *data, DMSET);
+ break;
+
+ case TTY_SET_BREAK:
+ (void) (*console_mctl)(dev, TM_BRK, DMBIS);
+ break;
+
+ case TTY_CLEAR_BREAK:
+ (void) (*console_mctl)(dev, TM_BRK, DMBIC);
+ break;
+
+ case TTY_STATUS:
+ {
+ register int error = D_SUCCESS;
+ struct tty_status *tsp;
+
+ /*
+ * Defend from noise. The cshell...
+ */
+ tsp = (struct tty_status *)data;
+ if ((tsp->tt_ispeed != tp->t_ispeed) ||
+ (tsp->tt_ospeed != tp->t_ospeed) ||
+ (tsp->tt_breakc != tp->t_breakc) ||
+ ((tsp->tt_flags & ~TF_HUPCLS) != tp->t_flags)) {
+
+ error = tty_set_status(tp, flavor, data, status_count);
+ if (error == 0) {
+ spl_t s = spltty();
+ tp->t_state &= ~(TS_BUSY|TS_FLUSH);
+ (*console_param)(tp, ttyno);
+ splx(s);
+ }
+ } else
+ if (tsp->tt_flags & TF_HUPCLS)
+ tp->t_state |= TS_HUPCLS;
+ return (error);
+ }
+ default:
+ return (tty_set_status(tp, flavor, data, status_count));
+ }
+ return (D_SUCCESS);
+}
+
+
+/*
+ * A simple scheme to dispatch interrupts.
+ *
+ * This deals with the fairly common case where we get an
+ * interrupt on each rx/tx character. A more elaborate
+ * scheme [someday here too..] would handle instead many
+ * characters per interrupt, perhaps using a DMA controller
+ * or a large SILO. Note that it is also possible to simulate
+ * a DMA chip with 'pseudo-dma' code that runs directly down
+ * in the interrupt routine.
+ */
+
+/*
+ * We just received a character, ship it up for further processing.
+ * Arguments are the tty number for which it is meant, a flag that
+ * indicates a keyboard or mouse is potentially attached to that
+ * tty (-1 if not), the character proper stripped down to 8 bits,
+ * and an indication of any error conditions associated with the
+ * receipt of the character.
+ * We deal here with rconsole input handling and dispatching to
+ * mouse or keyboard translation routines. cons_input() does
+ * the rest.
+ */
+#if MACH_KDB
+int l3break = 0x10; /* dear old ^P, we miss you so bad. */
+#endif MACH_KDB
+
+cons_simple_rint(ttyno, line, c, err)
+ int line;
+ int c;
+{
+ /*
+ * Rconsole. Drop in the debugger on break or ^P.
+ * Otherwise pretend input came from keyboard.
+ */
+ if (rcline && ttyno == rcline) {
+#if MACH_KDB
+ if ((err & CONS_ERR_BREAK) ||
+ ((c & 0x7f) == l3break))
+ return gimmeabreak();
+#endif /* MACH_KDB */
+ ttyno = console;
+ goto process_it;
+ }
+
+#if NBM > 0
+ if (screen_captures(line)) {
+ if (line == SCREEN_LINE_POINTER)
+ return mouse_input(SCREEN_CONS_UNIT(), c);
+ if (line == SCREEN_LINE_KEYBOARD) {
+ c = lk201_rint(SCREEN_CONS_UNIT(), c, FALSE, FALSE);
+ if (c == -1)
+ return; /* shift or bad char */
+ }
+ }
+#endif NBM > 0
+process_it:
+ cons_input(ttyno, c, err);
+}
+
+/*
+ * Send along a character on a tty. If we were waiting for
+ * this char to complete the open procedure do so; check
+ * for errors; if all is well proceed to ttyinput().
+ */
+cons_input(ttyno, c, err)
+{
+ register struct tty *tp;
+
+ tp = console_tty[ttyno];
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ tt_open_wakeup(tp);
+ return;
+ }
+ if (err) {
+ if (err & CONS_ERR_OVERRUN)
+ log(LOG_WARNING, "sl%d: silo overflow\n", ttyno);
+
+ if (err & CONS_ERR_PARITY)
+ if (((tp->t_flags & (TF_EVENP|TF_ODDP)) == TF_EVENP)
+ || ((tp->t_flags & (TF_EVENP|TF_ODDP)) == TF_ODDP))
+ return;
+ if (err & CONS_ERR_BREAK) /* XXX autobaud XXX */
+ c = tp->t_breakc;
+ }
+ ttyinput(c, tp);
+}
+
+/*
+ * Transmission of a character is complete.
+ * Return the next character or -1 if none.
+ */
+cons_simple_tint(ttyno, all_sent)
+ boolean_t all_sent;
+{
+ register struct tty *tp;
+
+ tp = console_tty[ttyno];
+ if ((tp->t_addr == 0) || /* not probed --> stray */
+ (tp->t_state & TS_TTSTOP))
+ return -1;
+
+ if (all_sent) {
+ tp->t_state &= ~TS_BUSY;
+ if (tp->t_state & TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
+
+ cons_start(tp);
+ }
+
+ if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
+ return -1;
+
+ return getc(&tp->t_outq);
+}
+
+
+
+
+
+#endif /*NCONSTTY > 0*/
diff --git a/chips/serial_defs.h b/chips/serial_defs.h
new file mode 100644
index 00000000..97027b0b
--- /dev/null
+++ b/chips/serial_defs.h
@@ -0,0 +1,53 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: serial_defs.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 7/91
+ *
+ * Generic console driver for serial-line based consoles.
+ */
+
+
+/*
+ * Common defs
+ */
+
+extern int (*console_probe)(), (*console_param)(), (*console_start)(),
+ (*console_putc)(), (*console_getc)(),
+ (*console_pollc)(), (*console_mctl)(), (*console_softCAR)();
+extern cngetc(), cnmaygetc(), cnputc(), rcputc();
+
+extern struct tty *console_tty[];
+extern int rcline, cnline;
+extern int console;
+
+/* Simple one-char-at-a-time scheme */
+extern cons_simple_tint(), cons_simple_rint();
+
+#define CONS_ERR_PARITY 0x1000
+#define CONS_ERR_BREAK 0x2000
+#define CONS_ERR_OVERRUN 0x4000
diff --git a/chips/sfb_hdw.c b/chips/sfb_hdw.c
new file mode 100644
index 00000000..ff2b1f6d
--- /dev/null
+++ b/chips/sfb_hdw.c
@@ -0,0 +1,253 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: sfb_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 11/92
+ *
+ * Driver for the Smart Color Frame Buffer Display,
+ * hardware-level operations.
+ */
+
+#include <sfb.h>
+#if (NSFB > 0)
+#include <platforms.h>
+
+#include <machine/machspl.h>
+#include <mach/std_types.h>
+#include <chips/busses.h>
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+#include <machine/machspl.h>
+
+typedef pm_softc_t sfb_softc_t;
+
+#ifdef DECSTATION
+#include <mips/PMAX/pmagb_ba.h>
+#include <mips/PMAX/tc.h>
+#endif
+
+#ifdef FLAMINGO
+#include <mips/PMAX/pmagb_ba.h> /* XXXX fixme */
+#include <alpha/DEC/tc.h>
+#define sparsify(x) ((1L << 28) | (((x) & 0x7ffffff) << 1) | \
+ ((x) & ~0x7ffffffL))
+#endif
+
+#ifndef sparsify
+#define sparsify(x) x
+#endif
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int sfb_probe(), sfb_intr();
+void sfb_attach();
+
+vm_offset_t sfb_std[NSFB] = { 0 };
+struct bus_device *sfb_info[NSFB];
+struct bus_driver sfb_driver =
+ { sfb_probe, 0, sfb_attach, 0, sfb_std, "sfb", sfb_info,
+ 0, 0, BUS_INTR_DISABLED};
+
+/*
+ * Probe/Attach functions
+ */
+
+sfb_probe(
+ vm_offset_t addr,
+ struct bus_device *device)
+{
+ static probed_once = 0;
+
+ /*
+ * Probing was really done sweeping the TC long ago
+ */
+ if (tc_probe("sfb") == 0)
+ return 0;
+ if (probed_once++ > 1) {
+ printf("[mappable] ");
+ device->address = addr;
+ }
+ return 1;
+}
+
+void sfb_attach(
+ struct bus_device *ui)
+{
+ /* ... */
+ printf(": smart frame buffer");
+}
+
+
+/*
+ * Interrupt routine
+ */
+
+sfb_intr(
+ int unit,
+ spl_t spllevel)
+{
+ register volatile char *ack;
+
+ /* acknowledge interrupt */
+ ack = (volatile char *) sfb_info[unit]->address + SFB_OFFSET_ICLR;
+ *ack = 0;
+
+#if mips
+ splx(spllevel);
+#endif
+ lk201_led(unit);
+}
+
+sfb_vretrace(
+ sfb_softc_t *sfb,
+ boolean_t on)
+{
+ sfb_regs *regs;
+
+ regs = (sfb_regs *) ((char *)sfb->framebuffer - SFB_OFFSET_VRAM + SFB_OFFSET_REGS);
+
+ regs->intr_enable = (on) ? 1 : 0;
+}
+
+/*
+ * Boot time initialization: must make device
+ * usable as console asap.
+ */
+#define sfb_set_status cfb_set_status
+
+extern int
+ sfb_soft_reset(), sfb_set_status(),
+ sfb_pos_cursor(), bt459_video_on(),
+ bt459_video_off(), sfb_vretrace(),
+ pm_get_status(), pm_char_paint(),
+ pm_insert_line(), pm_remove_line(),
+ pm_clear_bitmap(), pm_map_page();
+
+static struct screen_switch sfb_sw = {
+ screen_noop, /* graphic_open */
+ sfb_soft_reset, /* graphic_close */
+ sfb_set_status, /* set_status */
+ pm_get_status, /* get_status */
+ pm_char_paint, /* char_paint */
+ sfb_pos_cursor, /* pos_cursor */
+ pm_insert_line, /* insert_line */
+ pm_remove_line, /* remove_line */
+ pm_clear_bitmap, /* clear_bitmap */
+ bt459_video_on, /* video_on */
+ bt459_video_off, /* video_off */
+ sfb_vretrace, /* intr_enable */
+ pm_map_page /* map_page */
+};
+
+sfb_cold_init(
+ int unit,
+ user_info_t *up)
+{
+ sfb_softc_t *sfb;
+ screen_softc_t sc = screen(unit);
+ vm_offset_t base = tc_probe("sfb");
+ int hor_p, ver_p;
+ boolean_t makes_sense;
+
+ bcopy(&sfb_sw, &sc->sw, sizeof(sc->sw));
+ sc->flags |= COLOR_SCREEN;
+
+ /*
+ * I am confused here by the documentation. One document
+ * sez there are three boards:
+ * "PMAGB-BA" can do 1280x1024 @66Hz or @72Hz
+ * "PMAGB-BC" can do 1024x864 @60Hz or 1280x1024 @72Hz
+ * "PMAGB-BE" can do 1024x768 @72Hz or 1280x1024 @72Hz
+ * Another document sez things differently:
+ * "PMAGB-BB" can do 1024x768 @72Hz
+ * "PMAGB-BD" can do 1024x864 @60Hz or 1280x1024 @72Hz
+ *
+ * I would be inclined to believe the first one, which came
+ * with an actual piece of hardware attached (a PMAGB-BA).
+ * But I could swear I got a first board (which blew up
+ * instantly) and it was calling itself PMAGB-BB...
+ *
+ * Since I have not seen any other hardware I will make
+ * this code as hypothetical as I can. Should work :-))
+ */
+
+ makes_sense = FALSE;
+
+ {
+ sfb_regs *regs;
+
+ regs = (sfb_regs *) ((char *)base + SFB_OFFSET_REGS);
+ hor_p = (regs->vhor_setup & 0x1ff) * 4;
+ ver_p = regs->vvert_setup & 0x7ff;
+
+ if (((hor_p == 1280) && (ver_p == 1024)) ||
+ ((hor_p == 1024) && (ver_p == 864)) ||
+ ((hor_p == 1024) && (ver_p == 768)))
+ makes_sense = TRUE;
+ }
+
+ if (makes_sense) {
+ sc->frame_scanline_width = hor_p;
+ sc->frame_height = ver_p;
+ sc->frame_visible_width = hor_p;
+ sc->frame_visible_height = ver_p;
+ } else {
+ sc->frame_scanline_width = 1280;
+ sc->frame_height = 1024;
+ sc->frame_visible_width = 1280;
+ sc->frame_visible_height = 1024;
+ }
+
+ pm_init_screen_params(sc,up);
+ (void) screen_up(unit, up);
+
+ sfb = pm_alloc( unit, sparsify(base + SFB_OFFSET_BT459),
+ base + SFB_OFFSET_VRAM, -1);
+
+ screen_default_colors(up);
+
+ sfb_soft_reset(sc);
+
+ /*
+ * Clearing the screen at boot saves from scrolling
+ * much, and speeds up booting quite a bit.
+ */
+ screen_blitc( unit, 'C'-'@');/* clear screen */
+}
+
+#if 0 /* this is how you find out about a new screen */
+fill(addr,n,c)
+ char *addr;
+{
+ while (n-- > 0) *addr++ = c;
+}
+#endif
+
+
+#endif (NSFB > 0)
diff --git a/chips/sfb_misc.c b/chips/sfb_misc.c
new file mode 100644
index 00000000..a51e9a43
--- /dev/null
+++ b/chips/sfb_misc.c
@@ -0,0 +1,133 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: sfb_misc.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 11/92
+ *
+ * Driver for the PMAGB-BA smart color framebuffer
+ *
+ */
+
+#include <sfb.h>
+#if (NSFB > 0)
+#include <platforms.h>
+
+/*
+ * NOTE: This driver relies heavily on the pm one, as well as the cfb.
+ */
+
+#include <device/device_types.h>
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+typedef pm_softc_t sfb_softc_t;
+
+#include <chips/bt459.h>
+#define bt459 cursor_registers
+
+#ifdef DECSTATION
+#include <mips/PMAX/pmagb_ba.h>
+#endif
+
+#ifdef FLAMINGO
+#include <mips/PMAX/pmagb_ba.h> /* XXXX */
+#endif
+
+/*
+ * Initialize color map, for kernel use
+ */
+#define sfb_init_colormap cfb_init_colormap
+
+/*
+ * Position cursor
+ */
+sfb_pos_cursor(
+ bt459_regmap_t *regs,
+ int x,
+ int y)
+{
+ bt459_pos_cursor( regs, x + 368 - 219, y + 37 - 34);
+}
+
+/*
+ * Large viz small cursor
+ */
+#define sfb_small_cursor_to_large cfb_small_cursor_to_large
+
+/*
+ * Device-specific set status
+ */
+#define sfb_set_status cfb_set_status
+
+/*
+ * Hardware initialization
+ */
+sfb_init_screen(
+ sfb_softc_t *sfb)
+{
+ bt459_init( sfb->bt459,
+ sfb->bt459 + (SFB_OFFSET_RESET - SFB_OFFSET_BT459),
+ 4 /* 4:1 MUX */);
+}
+
+/*
+ * Do what's needed when X exits
+ */
+sfb_soft_reset(
+ screen_softc_t sc)
+{
+ sfb_softc_t *sfb = (sfb_softc_t*) sc->hw_state;
+ user_info_t *up = sc->up;
+ extern cursor_sprite_t dc503_default_cursor;
+
+ /*
+ * Restore params in mapped structure
+ */
+ pm_init_screen_params(sc,up);
+ up->row = up->max_row - 1;
+
+ up->dev_dep_2.pm.x26 = 2; /* you do not want to know */
+ up->dev_dep_1.pm.x18 = (short*)2;
+
+ /*
+ * Restore RAMDAC chip to default state
+ */
+ sfb_init_screen(sfb);
+
+ /*
+ * Load kernel's cursor sprite: just use the same pmax one
+ */
+ sfb_small_cursor_to_large(up, dc503_default_cursor);
+ bt459_cursor_sprite(sfb->bt459, up->dev_dep_2.pm.cursor_sprite);
+
+ /*
+ * Color map and cursor color
+ */
+ sfb_init_colormap(sc);
+}
+
+
+#endif (NSFB > 0)
diff --git a/chips/spans.c b/chips/spans.c
new file mode 100644
index 00000000..4529f8b6
--- /dev/null
+++ b/chips/spans.c
@@ -0,0 +1,114 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** SPANS SIGNALING ***/
+
+#ifndef STUB
+#include <chips/spans.h>
+#include <chips/tca100_if.h>
+#else
+#include "spans.h"
+#include "tca100_if.h"
+#endif
+
+nw_result spans_initialize(int dev) {
+
+#if !PERMANENT_VIRTUAL_CONNECTIONS
+#endif
+
+}
+
+
+void spans_input(nw_buffer_t msg) {
+
+#if !PERMANENT_VIRTUAL_CONNECTIONS
+#endif
+
+}
+
+nw_result spans_open(nw_ep ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep) {
+ nw_result rc;
+
+#if PERMANENT_VIRTUAL_CONNECTIONS
+ rc = NW_FAILURE;
+#else
+#endif
+
+ return rc;
+}
+
+nw_result spans_accept(nw_ep ep, nw_buffer_t msg, nw_ep_t new_epp) {
+ nw_result rc;
+
+#if PERMANENT_VIRTUAL_CONNECTIONS
+ rc = NW_FAILURE;
+#else
+#endif
+
+ return rc;
+}
+
+nw_result spans_close(nw_ep ep) {
+ nw_result rc;
+
+ tct[ep].rx_sar_header = 0;
+ rc = NW_SUCCESS;
+ return rc;
+}
+
+nw_result spans_add(nw_ep ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep) {
+ nw_result rc;
+
+#if PERMANENT_VIRTUAL_CONNECTIONS
+ rc = NW_FAILURE;
+#else
+#endif
+
+ return rc;
+}
+
+nw_result spans_drop(nw_ep ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep) {
+ nw_result rc;
+
+#if PERMANENT_VIRTUAL_CONNECTIONS
+ rc = NW_FAILURE;
+#else
+#endif
+
+ return rc;
+}
+
+void spans_timer_sweep() {
+
+#if !PERMANENT_VIRTUAL_CONNECTIONS
+#endif
+
+}
+
+
diff --git a/chips/spans.h b/chips/spans.h
new file mode 100644
index 00000000..7cb35002
--- /dev/null
+++ b/chips/spans.h
@@ -0,0 +1,58 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** SPANS SIGNALING ***/
+
+#ifndef _SPANS_H_
+#define _SPANS_H_ 1
+
+#ifndef STUB
+#include <chips/nc.h>
+#else
+#include "nc.h"
+#endif
+
+extern nw_result spans_initialize(int dev);
+
+extern void spans_input(nw_buffer_t msg);
+
+extern nw_result spans_open(nw_ep ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+extern nw_result spans_accept(nw_ep ep, nw_buffer_t msg, nw_ep_t new_epp);
+
+extern nw_result spans_close(nw_ep ep);
+
+extern nw_result spans_add(nw_ep ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+extern nw_result spans_drop(nw_ep ep, nw_address_1 rem_addr_1,
+ nw_address_2 rem_addr_2, nw_ep remote_ep);
+
+extern void spans_timer_sweep();
+
+
+#endif /* _SPANS_H_ */
diff --git a/chips/tca100.c b/chips/tca100.c
new file mode 100644
index 00000000..7ad4feca
--- /dev/null
+++ b/chips/tca100.c
@@ -0,0 +1,360 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef STUB
+#include <atm.h>
+#else
+#include "atm.h"
+#endif
+
+#if NATM > 0
+
+#ifndef STUB
+#include <sys/types.h>
+#include <kern/thread.h>
+#include <kern/lock.h>
+#include <kern/eventcount.h>
+#include <machine/machspl.h> /* spl definitions */
+#include <mips/mips_cpu.h>
+#include <vm/vm_kern.h>
+#include <device/io_req.h>
+#include <device/device_types.h>
+#include <device/net_status.h>
+#include <chips/busses.h>
+#include <chips/nc.h>
+#include <chips/tca100.h>
+#include <chips/tca100_if.h>
+
+decl_simple_lock_data(, atm_simple_lock);
+
+#else
+#include "stub.h"
+#include "nc.h"
+#include "tca100_if.h"
+#include "tca100.h"
+
+int atm_simple_lock;
+
+#endif
+
+struct bus_device *atm_info[NATM];
+
+int atm_probe();
+void atm_attach();
+struct bus_driver atm_driver =
+ { atm_probe, 0, atm_attach, 0, /* csr */ 0, "atm", atm_info,
+ "", 0, /* flags */ 0 };
+
+atm_device_t atmp[NATM] = {NULL};
+u_int atm_open_count[NATM];
+u_int atm_mapped[NATM];
+u_int atm_control_mask[NATM];
+struct evc atm_event_counter[NATM];
+
+#define DEVICE(unit) ((unit == 0) ? NW_TCA100_1 : NW_TCA100_2)
+
+void atm_initialize(int unit) {
+
+ atmp[unit]->creg = (CR_RX_RESET | CR_TX_RESET);
+ atmp[unit]->creg = 0;
+ atmp[unit]->rxtimerv = 0;
+ atmp[unit]->rxthresh = 1;
+ atmp[unit]->txthresh = 0;
+ atmp[unit]->sreg = 0;
+ atmp[unit]->creg = atm_control_mask[unit] = (CR_RX_ENABLE | CR_TX_ENABLE);
+ atm_open_count[unit] = 0;
+ atm_mapped[unit] = 0;
+}
+
+/*** Device entry points ***/
+
+int atm_probe(vm_offset_t reg, struct bus_device *ui) {
+ int un;
+
+ un = ui->unit;
+ if (un >= NATM || check_memory(reg, 0)) {
+ return 0;
+ }
+
+ atm_info[un] = ui;
+ atmp[un] = (atm_device_t) reg;
+ nc_initialize();
+ if (nc_device_register(DEVICE(un), NW_CONNECTION_ORIENTED, (char *) reg,
+ &tca100_entry_table) == NW_SUCCESS &&
+ tca100_initialize(DEVICE(un)) == NW_SUCCESS) {
+ atm_initialize(un);
+ evc_init(&atm_event_counter[un]);
+ return 1;
+ } else {
+ atmp[un] = NULL;
+ (void) nc_device_unregister(DEVICE(un), NW_FAILURE);
+ return 0;
+ }
+}
+
+void atm_attach(struct bus_device *ui) {
+ int un;
+
+ un = ui->unit;
+ if (un >= NATM) {
+ printf("atm: stray attach\n");
+ } else {
+ atmp[un]->creg =
+ atm_control_mask[un] = CR_TX_ENABLE | CR_RX_ENABLE | RX_COUNT_INTR;
+ /*Enable ATM interrupts*/
+ }
+}
+
+void atm_intr(int unit, int spl_level) {
+
+ if (unit >= NATM || atmp[unit] == NULL) {
+ printf("atm: stray interrupt\n");
+ } else {
+ atmp[unit]->creg = CR_TX_ENABLE | CR_RX_ENABLE; /*Disable ATM interrupts*/
+ wbflush();
+ if (atm_mapped[unit]) {
+ splx(spl_level);
+ evc_signal(&atm_event_counter[unit]);
+ } else {
+ simple_lock(&atm_simple_lock);
+ tca100_poll(DEVICE(unit));
+ atmp[unit]->creg = atm_control_mask[unit];
+ simple_unlock(&atm_simple_lock);
+ splx(spl_level);
+ }
+ }
+}
+
+io_return_t atm_open(dev_t dev, int mode, io_req_t ior) {
+ int un;
+
+ un = minor(dev);
+ if (un >= NATM || atmp[un] == NULL) {
+ return D_NO_SUCH_DEVICE;
+/*
+ } else if (atm_open_count[un] > 0 && (atm_mapped[un] || (mode & D_WRITE))) {
+ return D_ALREADY_OPEN;
+*/
+ } else {
+ atm_open_count[un]++;
+ atm_mapped[un] = ((mode & D_WRITE) != 0);
+ if (atm_mapped[un])
+ (void) nc_device_unregister(DEVICE(un), NW_NOT_SERVER);
+ return D_SUCCESS;
+ }
+}
+
+io_return_t atm_close(dev_t dev) {
+ int un;
+
+ un = minor(dev);
+ if (un >= NATM || atmp[un] == NULL) {
+ return D_NO_SUCH_DEVICE;
+ } else if (atm_open_count[un] == 0) {
+ return D_INVALID_OPERATION;
+ } else {
+ if (atm_mapped[un]) {
+ (void) nc_device_register(DEVICE(un), NW_CONNECTION_ORIENTED,
+ (char *) atmp[un],
+ &tca100_entry_table);
+ atm_mapped[un] = 0;
+ }
+ atm_open_count[un]--;
+ return D_SUCCESS;
+ }
+}
+
+unsigned int *frc = 0xbe801000;
+char data[66000];
+
+io_return_t atm_read(dev_t dev, io_req_t ior) {
+ unsigned int ck1, ck2;
+ int i, j;
+ char c[16];
+
+ ck1 = *frc;
+ device_read_alloc(ior, ior->io_count);
+ for (i = 0, j = 0; i < ior->io_count; i += 4096, j++)
+ c[j] = (ior->io_data)[i];
+ ck2 = *frc;
+ ((int *) ior->io_data)[0] = ck1;
+ ((int *) ior->io_data)[1] = ck2;
+ return D_SUCCESS;
+}
+
+io_return_t atm_write(dev_t dev, io_req_t ior) {
+ int i, j;
+ char c[16];
+ boolean_t wait;
+
+ device_write_get(ior, &wait);
+ for (i = 0, j = 0; i < ior->io_total; i += 4096, j++)
+ c[j] = (ior->io_data)[i];
+ ior->io_residual = ior->io_total - *frc;
+ return D_SUCCESS;
+}
+
+io_return_t atm_get_status(dev_t dev, int flavor, dev_status_t status,
+ u_int *status_count) {
+ int un;
+
+ un = minor(dev);
+ if (un >= NATM || atmp[un] == NULL) {
+ return D_NO_SUCH_DEVICE;
+ } else {
+ switch ((atm_status) flavor) {
+ case ATM_MAP_SIZE:
+ status[0] = sizeof(atm_device_s);
+ *status_count = sizeof(int);
+ return D_SUCCESS;
+ case ATM_MTU_SIZE:
+ status[0] = 65535; /*MTU size*/
+ *status_count = sizeof(int);
+ return D_SUCCESS;
+ case ATM_EVC_ID:
+ status[0] = atm_event_counter[un].ev_id;
+ *status_count = sizeof(int);
+ return D_SUCCESS;
+ case ATM_ASSIGNMENT:
+ status[0] = atm_mapped[un];
+ status[1] = atm_open_count[un];
+ *status_count = 2 * sizeof(int);
+ return D_SUCCESS;
+ default:
+ return D_INVALID_OPERATION;
+ }
+ }
+}
+
+io_return_t atm_set_status(dev_t dev, int flavor, dev_status_t status,
+ u_int status_count) {
+ io_return_t rc;
+ int un, s;
+ nw_pvc_t pvcp;
+ nw_plist_t pel;
+ nw_ep lep;
+
+ un = minor(dev);
+ if (un >= NATM || atmp[un] == NULL) {
+ return D_NO_SUCH_DEVICE;
+ } else switch ((atm_status) flavor) {
+ case ATM_INITIALIZE:
+ if (status_count != 0) {
+ return D_INVALID_OPERATION;
+ } else {
+ s = splsched();
+ if (nc_device_register(DEVICE(un), NW_CONNECTION_ORIENTED,
+ (char *) atmp[un],
+ &tca100_entry_table) == NW_SUCCESS &&
+ tca100_initialize(DEVICE(un)) == NW_SUCCESS) {
+ atm_initialize(un);
+ rc = D_SUCCESS;
+ } else {
+ atmp[un] = NULL;
+ (void) nc_device_unregister(DEVICE(un), NW_FAILURE);
+ rc = D_INVALID_OPERATION;
+ }
+ splx(s);
+ return rc;
+ }
+ break;
+
+#if PERMANENT_VIRTUAL_CONNECTIONS
+ case ATM_PVC_SET:
+ pvcp = (nw_pvc_t) status;
+ if (status_count != sizeof(nw_pvc_s) || pvcp->pvc.local_ep >= MAX_EP) {
+ rc = D_INVALID_OPERATION;
+ } else if ((pel = nc_peer_allocate()) == NULL) {
+ rc = D_INVALID_OPERATION;
+ } else {
+ lep = pvcp->pvc.local_ep;
+ tct[lep].rx_sar_header = SSM | 1;
+ tct[lep].tx_atm_header = pvcp->tx_vp << ATM_VPVC_SHIFT;
+ tct[lep].tx_sar_header = 1;
+ ect[lep].state = NW_DUPLEX_ACCEPTED;
+ pel->peer = pvcp->pvc;
+ pel->next = NULL;
+ ect[lep].conn = pel;
+ if (pvcp->protocol == NW_LINE) {
+ if (nc_line_update(&pel->peer, lep) == NW_SUCCESS) {
+ ect[lep].protocol = pvcp->protocol;
+ if (nw_free_line_last == 0)
+ nw_free_line_first = lep;
+ else
+ ect[nw_free_line_last].next = lep;
+ ect[lep].previous = nw_free_line_last;
+ ect[lep].next = 0;
+ nw_free_line_last = lep;
+ rc = D_SUCCESS;
+ } else {
+ rc = D_INVALID_OPERATION;
+ }
+ } else {
+ rc = D_SUCCESS;
+ }
+ }
+ return rc;
+#endif
+
+ default:
+ return D_INVALID_OPERATION;
+ }
+}
+
+int atm_mmap(dev_t dev, vm_offset_t off, int prot) {
+ int un;
+ vm_offset_t addr;
+
+ un = minor(dev);
+ if (un >= NATM || atmp[un] == NULL || !atm_mapped[un] ||
+ off >= sizeof(atm_device_s)) {
+ return -1;
+ } else {
+ return mips_btop(K1SEG_TO_PHYS( (vm_offset_t) atmp[un] ) + off );
+ }
+}
+
+io_return_t atm_restart(int u) {
+
+ return D_INVALID_OPERATION;
+}
+
+io_return_t atm_setinput(dev_t dev, ipc_port_t receive_port, int priority,
+ filter_array_t *filter, u_int filter_count) {
+
+ return D_INVALID_OPERATION;
+}
+
+int atm_portdeath(dev_t dev, mach_port_t port) {
+
+ return D_INVALID_OPERATION;
+}
+
+
+#endif NATM > 0
+
+
+
diff --git a/chips/tca100.h b/chips/tca100.h
new file mode 100644
index 00000000..29312259
--- /dev/null
+++ b/chips/tca100.h
@@ -0,0 +1,200 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _TCA100_H_
+#define _TCA100_H_ 1
+
+#ifndef STUB
+#include <chips/nw.h>
+#else
+#include "nw.h"
+#endif
+
+/*** FORE TCA-100 Turbochannel ATM computer interface ***/
+
+/*** HARDWARE REGISTERS ***/
+
+typedef volatile unsigned int vol_u_int;
+
+typedef struct atm_device {
+ unsigned int prom[64 * 1024 / 4];
+ vol_u_int sreg;
+ vol_u_int creg_set;
+ vol_u_int creg_clr;
+ vol_u_int creg;
+ vol_u_int rxtimer;
+ unsigned int pad1;
+ vol_u_int rxtimerv;
+ unsigned int pad2;
+ vol_u_int rxcount;
+ unsigned int pad3;
+ vol_u_int rxthresh;
+ unsigned int pad4;
+ vol_u_int txcount;
+ unsigned int pad5;
+ vol_u_int txthresh;
+ unsigned int pad6[64*1024/4 - 15];
+ vol_u_int rxfifo[14];
+ unsigned int pad7[64*1024/4 - 14];
+ vol_u_int txfifo[14];
+ unsigned int pad8[64*1024/4 - 14];
+} atm_device_s, *atm_device_t;
+
+
+/*** DEFINITION OF BITS IN THE STATUS AND CONTROL REGISTERS ***/
+
+#define RX_COUNT_INTR 0x0001
+#define RX_EOM_INTR 0x0002
+#define RX_TIME_INTR 0x0004
+#define TX_COUNT_INTR 0x0008
+#define RX_CELL_LOST 0x0010
+#define RX_NO_CARRIER 0x0020
+#define CR_RX_ENABLE 0x0040
+#define CR_TX_ENABLE 0x0080
+#define CR_RX_RESET 0x0100
+#define CR_TX_RESET 0x0200
+
+#define RX_COUNTER_MASK 0x03ff
+
+/*** DEFINITION OF FIELDS FOR AAL3/4 WITH THE TCA-100 PADDING ***/
+
+/*Header -- ATM header*/
+
+#define VPI 0x0ff00000
+#define VCI 0x000ffff0
+
+#define ATM_HEADER_RSV_BITS 0x00000004
+
+#define PERMANENT_VIRTUAL_CONNECTIONS 1
+
+#if PERMANENT_VIRTUAL_CONNECTIONS
+#define ATM_VPVC_MASK 0x3ff00000
+#define ATM_VPVC_SHIFT 20
+#else
+#define ATM_VPVC_MASK 0x00003ff0
+#define ATM_VPVC_SHIFT 4
+#endif
+
+
+/*First payload word -- SAR header*/
+
+#define ATM_HEADER_CRC 0xff000000
+#define ATM_HEADER_CRC_SYNDROME 0x00ff0000
+
+#define SEG_TYPE 0x0000c000
+#define BOM 0x00008000
+#define COM 0x00000000
+#define EOM 0x00004000
+#define SSM 0x0000c000
+
+#define BOM_DATA_SIZE 40
+#define COM_DATA_SIZE 44
+#define EOM_DATA_SIZE 40
+#define SSM_DATA_SIZE 36
+
+#define SEQ_NO 0x00003c00
+#define SEQ_INC 0x00000400
+
+#define MID 0x000003ff
+#define MID_INC 0x00000001
+
+#define SAR_HEADER_MASK (ATM_HEADER_CRC_SYNDROME | SEG_TYPE | SEQ_NO | MID)
+
+/*Trailer -- SAR trailer and error flags*/
+
+#define PAYLOAD_LENGTH 0xfc000000
+#define FULL_SEGMENT_TRAILER (44 << 26)
+#define EMPTY_SEGMENT_TRAILER (4 << 26)
+#define SYNCH_SEGMENT_TRAILER (16 << 26)
+
+#define FRAMING_ERROR 0x0001
+#define HEADER_CRC_ERROR 0x0002
+#define PAYLOAD_CRC_ERROR 0x0004
+#define PAD2_ERROR 0x0007
+
+#define SAR_TRAILER_MASK (PAYLOAD_LENGTH | PAD2_ERROR)
+ /*This field should be FULL_SEGMENT_TRAILER IN BOM OR COM*/
+
+
+/*CS header and trailer fields*/
+
+#define CS_PDU_TYPE 0xff000000
+#define BE_TAG 0x00ff0000
+#define BA_SIZE 0x0000ffff
+
+#define CS_PROTOCOL_CONTROL_FIELD 0xff000000
+#define CS_LENGTH 0x0000ffff
+
+/*** DEVICE STATUS ***/
+
+typedef enum { /*"Flavors" for device_get_status and device_set_status*/
+ ATM_MAP_SIZE, /* device_get_status options */
+ ATM_MTU_SIZE,
+ ATM_EVC_ID, /* ID of event counter assigned to device */
+ ATM_ASSIGNMENT, /* Returns two words indicating whether device is mapped
+ and number of tasks with the device open */
+ /* device_set_status options */
+ ATM_INITIALIZE, /* Restarts hardware and low-level driver */
+ ATM_PVC_SET /* Sets up a permanent virtual connection --
+ the status argument array is cast to a nw_pvc_s
+ structure */
+
+} atm_status;
+
+typedef struct {
+ nw_peer_s pvc; /* Permanent virtual connection */
+ u_int tx_vp; /* VPI used for transmissions to permanent virtual
+ connection. The VPI used for reception is the
+ local endpoint number. VCIs are 0 */
+ nw_protocol protocol; /* Protocol of connection (possibly NW_LINE) */
+} nw_pvc_s, *nw_pvc_t;
+
+/*** BYTE ORDER ***/
+
+/*The ATM header and SAR header and trailer are converted to and from
+ host byte order by hardware. CS headers and trailers and
+ signaling messages need byte order conversion in software.
+ Conversion in software is also necessary for application messages
+ if the communicating hosts have different byte orders (e.g. DECstation
+ and SPARCstation). */
+
+#define HTONL(x) \
+ ((x << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | ((u_int) x >> 24))
+
+#define NTOHL(x) HTONL(x)
+
+#if 0
+unsigned int htonl(unsigned int x) {
+
+ return ((x << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | (x >> 24));
+}
+
+#define ntohl(x) htonl(x)
+
+#endif
+
+#endif /* _TCA100_H_ */
+
diff --git a/chips/tca100_if.c b/chips/tca100_if.c
new file mode 100644
index 00000000..5eeec101
--- /dev/null
+++ b/chips/tca100_if.c
@@ -0,0 +1,1377 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** TCA 100 ATM NETWORK INTERFACE ***/
+
+#ifndef STUB
+#include <chips/tca100_if.h>
+# else
+#include "tca100_if.h"
+#endif
+
+#define SMALL_WINDOW_SIZE (BOM_DATA_SIZE + EOM_DATA_SIZE)
+#define INITIAL_WINDOW_SIZE BOM_DATA_SIZE
+#define CONTINUATION_WINDOW_SIZE (71 * COM_DATA_SIZE)
+#define FINAL_WINDOW_SIZE (70 * COM_DATA_SIZE + EOM_DATA_SIZE)
+#define MAX_LONG_RX 2
+#define MAX_LONG_TX 5
+#define BASE_TIME_OUT 5
+#define DELAYED_TIME_OUT 15
+#define MAX_RETRY 3
+#define POLL_LIMIT 100000
+#define POLL_IDLE_TIME 1
+#define POLL_CELL_TIME 8
+
+#define TCA_SYNCH 0xfc00
+#define TCA_ACK (NW_SUCCESS << 10)
+#define TCA_NAK (NW_FAILURE << 10)
+#define TCA_OVR (NW_OVERRUN << 10)
+#define TCA_SEQ (NW_INCONSISTENCY << 10)
+
+int tca100_verbose = 0;
+
+int tick[MAX_DEV];
+
+nw_control_s nw_tx_control[MAX_DEV][MAX_LONG_TX];
+nw_control_s nw_rx_control[MAX_DEV][MAX_LONG_RX];
+
+int long_tx_count[MAX_DEV], long_rx_count[MAX_DEV];
+
+nw_tx_header_t delayed_tx_first[MAX_DEV], delayed_tx_last[MAX_DEV];
+nw_rx_header_t delayed_rx_first[MAX_DEV], delayed_rx_last[MAX_DEV];
+
+nw_tcb tct[MAX_EP];
+
+u_int MTU[] = {9244, 65528, 65532, 65528};
+u_int MTU_URGENT[] = {32, 28, 32, 28};
+
+nw_dev_entry_s tca100_entry_table = {
+ tca100_initialize, tca100_status, spans_timer_sweep, tca100_timer_sweep,
+ tca100_poll, tca100_send, tca100_rpc, spans_input, spans_open, spans_accept,
+ spans_close, spans_add, spans_drop};
+
+typedef enum {
+ ATM_HEADER,
+ SAR_HEADER,
+ SAR_TRAILER,
+ CS_HEADER,
+ CS_TRAILER,
+ FRAME_ERROR,
+ DELIVERY_ERROR,
+ SYNCH_ERROR,
+ SEQ_ERROR,
+ OVERRUN_ERROR,
+ RX_RETRANSMISSION,
+ TX_RETRANSMISSION
+} tca_error;
+
+int tca_ec[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+nw_result tca100_initialize(int dev) {
+ nw_result rc;
+ int i;
+
+ rc = spans_initialize(dev);
+ if (rc = NW_SUCCESS) {
+ tick[dev] = 0;
+ for (i = 0; i < MAX_LONG_TX; i++)
+ nw_tx_control[dev][i].ep = 0;
+ long_tx_count[dev] = 0;
+ delayed_tx_first[dev] = delayed_tx_last[dev] = NULL;
+ for (i = 0; i < MAX_LONG_RX; i++)
+ nw_rx_control[dev][i].ep = 0;
+ long_rx_count[dev] = 0;
+ delayed_rx_first[dev] = delayed_rx_last[dev] = NULL;
+ for (i = 0; i < MAX_EP; i++) {
+ tct[i].rx_sar_header = 0;
+ tct[i].rx_control = NULL;
+ tct[i].tx_queued_count = 0;
+ tct[i].tx_control = NULL;
+ }
+ rc = NW_SUCCESS;
+ }
+ return rc;
+}
+
+nw_result tca100_status(int dev) {
+ nw_result rc;
+ atm_device_t atmp;
+ u_int status;
+
+ atmp = (atm_device_t) devct[dev].addr;
+ status = atmp->sreg;
+ if (status & RX_NO_CARRIER) {
+ atmp->creg_set = CR_RX_RESET;
+ atmp->creg_clr = ~CR_RX_RESET;
+ atmp->creg_set = CR_RX_ENABLE;
+ atmp->sreg = 0;
+ rc = NW_NO_CARRIER;
+ } else if (status & RX_CELL_LOST) {
+ atmp->sreg = RX_COUNT_INTR;
+ rc = NW_OVERRUN;
+ } else {
+ rc = NW_SUCCESS;
+ }
+ return rc;
+}
+
+
+void tca100_synch_send(int dev, nw_tcb_t tcb, u_int reply) {
+ vol_u_int *tx_fifo = &((atm_device_t) devct[dev].addr)->txfifo[0];
+
+#ifdef TRACING
+ printf("Synch sent %x\n", reply);
+#endif
+
+ tx_fifo[0] = tcb->tx_atm_header;
+ tx_fifo[1] = SSM;
+ tx_fifo[2] = HTONL(8);
+ tx_fifo[3] = HTONL(NW_SYNCHRONIZATION);
+ tx_fifo[4] = htonl(reply);
+ tx_fifo[5] = HTONL(8);
+ tx_fifo[6] = 0;
+ tx_fifo[7] = 0;
+ tx_fifo[8] = 0;
+ tx_fifo[9] = 0;
+ tx_fifo[10] = 0;
+ tx_fifo[11] = 0;
+ tx_fifo[12] = 0;
+ tx_fifo[13] = SYNCH_SEGMENT_TRAILER;
+}
+
+#define broken_cell_mend(length) { \
+ missing = length; \
+ while (missing != 0) { \
+ if (missing > block_count) { \
+ limit = 0; \
+ missing -= block_count; \
+ } else { \
+ limit = block_count - missing; \
+ missing = 0; \
+ } \
+ while (block_count > limit) { \
+ t1 = block[0]; \
+ block++; \
+ tx_fifo[1] = t1; \
+ block_count -= 4; \
+ } \
+ if (block_count == 0) { \
+ ecb->tx_current = tx_header = ecb->tx_current->next; \
+ if (tx_header != NULL) { \
+ block_count = tx_header->block_length; \
+ block = (vol_u_int *) tx_header->block; \
+ } \
+ } \
+ } \
+}
+
+
+nw_result tca100_window_send(int dev, nw_ecb_t ecb, nw_tcb_t tcb,
+ boolean_t initial) {
+ nw_result rc;
+ register vol_u_int *tx_fifo = &((atm_device_t) devct[dev].addr)->txfifo[0];
+ register vol_u_int *block;
+ register u_int block_count, msg_count;
+ register int com_count;
+ int eom_count;
+ register u_int atm_header, sar_header, sar_trailer;
+ u_int cs_header, end_count;
+ int limit, missing;
+ register u_int t1, t2;
+ nw_tx_header_t tx_header;
+ nw_options options;
+
+ atm_header = tcb->tx_atm_header;
+ if (initial) {
+ sar_header = tcb->tx_sar_header & MID;
+ tx_header = ecb->tx_initial;
+ block = (vol_u_int *) tx_header->block;
+ block_count = tx_header->block_length;
+ options = tx_header->options;
+ msg_count = tx_header->msg_length;
+ if (ecb->protocol == NW_LINE)
+ msg_count += 4;
+ if (options == NW_URGENT)
+ msg_count += 4;
+ cs_header = ecb->protocol | (sar_header & 0xff) << 8 |
+ (msg_count & 0xff00) << 8 | msg_count << 24;
+ tcb->tx_cs_header = cs_header;
+
+ if (msg_count <= SSM_DATA_SIZE) { /*Single segment message*/
+ tx_fifo[0] = atm_header;
+ sar_trailer = (msg_count + 8) << 26;
+ tx_fifo[1] = SSM | sar_header; /*Sequence number 0 is implicit*/
+ end_count = msg_count + 4;
+ tx_fifo[1] = cs_header;
+ if (options == NW_URGENT) {
+ tx_fifo[1] = HTONL(NW_URGENT);
+ msg_count -= 4;
+ }
+ if (ecb->protocol == NW_LINE) {
+ tx_fifo[1] = tx_header->peer.local_ep >> 8 |
+ (tx_header->peer.local_ep & 0x00ff) << 8 |
+ (tx_header->peer.remote_ep & 0xff00) << 8 |
+ tx_header->peer.remote_ep << 24;
+ msg_count -= 4;
+ }
+ if (ecb->protocol == NW_SEQ_PACKET) {
+ tcb->tx_synch = 0;
+ } else {
+ tcb->tx_synch = -1;
+ }
+ goto EOM_payload;
+
+ } else { /*Beginning of message*/
+ tx_fifo[0] = atm_header;
+ sar_trailer = FULL_SEGMENT_TRAILER;
+ tx_fifo[1] = BOM | sar_header; /*Sequence number 0 is implicit*/
+ tx_fifo[2] = cs_header;
+ if (block_count < BOM_DATA_SIZE) {
+ if (ecb->protocol == NW_LINE) {
+ t1 = tx_header->peer.local_ep >> 8 |
+ (tx_header->peer.local_ep & 0x00ff) << 8 |
+ (tx_header->peer.remote_ep & 0xff00) << 8 |
+ tx_header->peer.remote_ep << 24;
+ missing = BOM_DATA_SIZE - 4;
+ tx_fifo[3] = t1;
+ } else {
+ missing = BOM_DATA_SIZE;
+ }
+ broken_cell_mend(missing);
+ } else {
+ if (ecb->protocol == NW_LINE) {
+ t1 = tx_header->peer.local_ep >> 8 |
+ (tx_header->peer.local_ep & 0x00ff) << 8 |
+ (tx_header->peer.remote_ep & 0xff00) << 8 |
+ tx_header->peer.remote_ep << 24;
+ } else {
+ t1 = block[0];
+ block_count -= 4;
+ block++;
+ }
+ t2 = block[0];
+ tx_fifo[3] = t1;
+ tx_fifo[4] = t2;
+ t1 = block[1];
+ t2 = block[2];
+ tx_fifo[5] = t1;
+ tx_fifo[6] = t2;
+ t1 = block[3];
+ t2 = block[4];
+ tx_fifo[7] = t1;
+ tx_fifo[8] = t2;
+ t1 = block[5];
+ t2 = block[6];
+ tx_fifo[9] = t1;
+ tx_fifo[10] = t2;
+ t1 = block[7];
+ t2 = block[8];
+ tx_fifo[11] = t1;
+ tx_fifo[12] = t2;
+ block_count -= (BOM_DATA_SIZE - 4);
+ block += 9;
+ }
+ if (ecb->protocol == NW_RAW) {
+ msg_count -= BOM_DATA_SIZE;
+ com_count = msg_count / COM_DATA_SIZE;
+ msg_count = msg_count % COM_DATA_SIZE;
+ eom_count = 1;
+ tcb->tx_synch = -1;
+ } else if (msg_count > SMALL_WINDOW_SIZE) {
+ com_count = eom_count = 0;
+ tcb->tx_synch = msg_count;
+ msg_count -= BOM_DATA_SIZE;
+ } else {
+ com_count = 0;
+ eom_count = 1;
+ if (ecb->protocol == NW_SEQ_PACKET) {
+ tcb->tx_synch = 0;
+ } else {
+ tcb->tx_synch = -1;
+ }
+ msg_count -= BOM_DATA_SIZE;
+ }
+ tx_fifo[13] = sar_trailer;
+ sar_header += SEQ_INC;
+ }
+
+ } else {
+ sar_header = tcb->tx_sar_header;
+ sar_trailer = FULL_SEGMENT_TRAILER;
+ block = (vol_u_int *) tcb->tx_p;
+ block_count = tcb->tx_block_count;
+ msg_count = tcb->tx_msg_count;
+ if (msg_count > FINAL_WINDOW_SIZE) {
+ com_count = (CONTINUATION_WINDOW_SIZE / COM_DATA_SIZE);
+ eom_count = 0;
+ tcb->tx_synch = msg_count;
+ msg_count -= CONTINUATION_WINDOW_SIZE;
+ } else {
+ com_count = msg_count / COM_DATA_SIZE;
+ msg_count = msg_count % COM_DATA_SIZE;
+ eom_count = 1;
+ if (ecb->protocol == NW_SEQ_PACKET) {
+ tcb->tx_synch = 0;
+ } else {
+ tcb->tx_synch = -1;
+ }
+ }
+ }
+
+ while (com_count-- > 0) { /*Continuation of message*/
+ tx_fifo[0] = atm_header;
+ tx_fifo[1] = sar_header; /*COM is 0 and is implicit*/
+ if (block_count >= COM_DATA_SIZE) {
+ t1 = block[0];
+ t2 = block[1];
+ tx_fifo[2] = t1;
+ tx_fifo[3] = t2;
+ t1 = block[2];
+ t2 = block[3];
+ tx_fifo[4] = t1;
+ tx_fifo[5] = t2;
+ t1 = block[4];
+ t2 = block[5];
+ tx_fifo[6] = t1;
+ tx_fifo[7] = t2;
+ t1 = block[6];
+ t2 = block[7];
+ tx_fifo[8] = t1;
+ tx_fifo[9] = t2;
+ t1 = block[8];
+ t2 = block[9];
+ tx_fifo[10] = t1;
+ tx_fifo[11] = t2;
+ t1 = block[10];
+ block_count -= COM_DATA_SIZE;
+ tx_fifo[12] = t1;
+ tx_fifo[13] = sar_trailer;
+ block += 11;
+ sar_header = (sar_header + SEQ_INC) & (SEQ_NO | MID);
+ } else {
+ broken_cell_mend(COM_DATA_SIZE);
+ tx_fifo[13] = sar_trailer;
+ sar_header = (sar_header + SEQ_INC) & (SEQ_NO | MID);
+ }
+ }
+
+ if (eom_count != 0) { /*End of message*/
+ tx_fifo[0] = atm_header;
+ tx_fifo[1] = EOM | sar_header;
+ end_count = msg_count;
+ sar_trailer = (msg_count + 4) << 26;
+
+ EOM_payload:
+ if (block_count >= msg_count) {
+ if (msg_count & 0x4) {
+ t1 = block[0];
+ tx_fifo[1] = t1;
+ }
+ block = (vol_u_int *) ((char *) block + msg_count);
+ switch (msg_count >> 3) {
+ case 5:
+ t1 = block[-10];
+ t2 = block[-9];
+ tx_fifo[1] = t1;
+ tx_fifo[1] = t2;
+ case 4:
+ t1 = block[-8];
+ t2 = block[-7];
+ tx_fifo[1] = t1;
+ tx_fifo[1] = t2;
+ case 3:
+ t1 = block[-6];
+ t2 = block[-5];
+ tx_fifo[1] = t1;
+ tx_fifo[1] = t2;
+ case 2:
+ t1 = block[-4];
+ t2 = block[-3];
+ tx_fifo[1] = t1;
+ tx_fifo[1] = t2;
+ case 1:
+ t1 = block[-2];
+ t2 = block[-1];
+ tx_fifo[1] = t1;
+ tx_fifo[1] = t2;
+ }
+ msg_count = 0;
+ } else {
+ broken_cell_mend(msg_count);
+ msg_count = 0;
+ }
+
+ EOM_cs_trailer:
+ tx_fifo[1] = tcb->tx_cs_header;
+ switch (end_count) {
+ case 0: tx_fifo[1] = 0;
+ case 4: tx_fifo[1] = 0;
+ case 8: tx_fifo[1] = 0;
+ case 12: tx_fifo[1] = 0;
+ case 16: tx_fifo[1] = 0;
+ case 20: tx_fifo[1] = 0;
+ case 24: tx_fifo[1] = 0;
+ case 28: tx_fifo[1] = 0;
+ case 32: tx_fifo[1] = 0;
+ case 36: tx_fifo[1] = 0;
+ }
+ tx_fifo[13] = sar_trailer;
+ }
+
+ if (tcb->tx_synch == -1) {
+
+#ifdef TRACING
+ printf("Final window sent\n");
+#endif
+
+ sar_header = (sar_header + MID_INC) & MID;
+ if (sar_header == 0)
+ sar_header = 1;
+ tcb->tx_sar_header = sar_header;
+ rc = NW_SUCCESS;
+ } else {
+
+#ifdef TRACING
+ printf("Window synch at %x\n", msg_count);
+#endif
+
+ tcb->tx_sar_header = sar_header;
+ tcb->tx_p = (u_int *) block;
+ tcb->tx_block_count = block_count;
+ tcb->tx_msg_count = msg_count;
+ rc = NW_SYNCH;
+ }
+ return rc;
+}
+
+nw_result tca100_send(nw_ep ep, nw_tx_header_t header, nw_options options) {
+ nw_result rc;
+ int i, dev;
+ nw_ecb_t ecb;
+ nw_tcb_t tcb;
+ nw_control_t control;
+ nw_tx_header_t tx_header, tx_previous;
+
+ dev = NW_DEVICE(header->peer.rem_addr_1);
+ ecb = &ect[ep];
+ tcb = &tct[ep];
+ if ((options == NW_URGENT && header->msg_length >
+ MTU_URGENT[ecb->protocol]) || header->msg_length > MTU[ecb->protocol]) {
+ rc = NW_BAD_LENGTH;
+ } else if (tcb->tx_queued_count != 0 ||
+ (ecb->protocol != NW_RAW &&
+ long_tx_count[dev] >= MAX_LONG_TX &&
+ (header->msg_length > SMALL_WINDOW_SIZE ||
+ ecb->protocol == NW_SEQ_PACKET))) {
+ if (options == NW_URGENT && tcb->tx_queued_count != 0) {
+ tx_header = delayed_tx_first[dev];
+ tx_previous = NULL;
+ while (tx_header != NULL && tx_header->sender != ep) {
+ tx_previous = tx_header;
+ tx_header = tx_header->next;
+ }
+ if (tx_previous == NULL)
+ delayed_tx_first[dev] = header;
+ else
+ tx_previous->next = header;
+ while (header->next != NULL)
+ header = header->next;
+ header->next = tx_header;
+ } else {
+ if (delayed_tx_first[dev] == NULL)
+ delayed_tx_first[dev] = header;
+ else
+ delayed_tx_last[dev]->next = header;
+ delayed_tx_last[dev] = header;
+ }
+ tcb->tx_queued_count++;
+ rc = NW_QUEUED;
+
+#ifdef TRACING
+ printf("Send enqueued ep %d\n", ep);
+#endif
+
+ } else {
+
+
+#ifdef TRACING
+ printf("Send ep %d\n", ep);
+#endif
+
+ ecb->tx_initial = ecb->tx_current = header;
+ rc = tca100_window_send(dev, ecb, tcb, TRUE);
+ if (rc == NW_SUCCESS) {
+ while (header != NULL) {
+ if (header->buffer != NULL)
+ nc_buffer_deallocate(ep, header->buffer);
+ header = header->next;
+ }
+ nc_tx_header_deallocate(ecb->tx_initial);
+ ecb->tx_initial = ecb->tx_current = NULL;
+ } else {
+ control = &nw_tx_control[dev][0];
+ while (control->ep != 0)
+ control++;
+ control->ep = ep;
+ control->time_out = tick[dev] + BASE_TIME_OUT;
+ control->retry = 0;
+ tcb->reply = TCA_SYNCH;
+ tcb->tx_control = control;
+ tcb->tx_queued_count++;
+ if (long_tx_count[dev] + long_rx_count[dev] == 0)
+ nc_fast_timer_set(dev);
+ long_tx_count[dev]++;
+ }
+ }
+ return rc;
+}
+
+
+nw_result tx_slot_free(int dev, nw_control_t control) {
+ nw_result rc;
+ nw_tcb_t tcb;
+ nw_ecb_t ecb;
+ nw_tx_header_t tx_header;
+ nw_ep ep;
+
+ tcb = &tct[control->ep];
+ tcb->tx_control = NULL;
+ tcb->tx_queued_count--;
+ do {
+ tx_header = delayed_tx_first[dev];
+ if (tx_header == NULL) {
+ control->ep = 0;
+ long_tx_count[dev]--;
+ rc = NW_FAILURE;
+ } else {
+ ep = tx_header->sender;
+
+#ifdef TRACING
+ printf("Send dequeued ep %d\n", ep);
+#endif
+
+ ecb = &ect[ep];
+ tcb = &tct[ep];
+ ecb->tx_initial = ecb->tx_current = tx_header;
+ while (tx_header->next != NULL &&
+ tx_header->next->msg_length == 0) {
+ tx_header = tx_header->next;
+ }
+ delayed_tx_first[dev] = tx_header->next;
+ if (tx_header->next == NULL)
+ delayed_tx_last[dev] = NULL;
+ tx_header->next = NULL;
+ rc = tca100_window_send(dev, ecb, tcb, TRUE);
+ if (rc == NW_SYNCH) {
+ control->ep = ep;
+ tcb->tx_control = control;
+ tcb->reply = TCA_SYNCH;
+ control->time_out = tick[dev] + BASE_TIME_OUT;
+ control->retry = 0;
+ }
+ }
+ } while (rc == NW_SUCCESS);
+ return rc;
+}
+
+nw_result rx_slot_free(int dev, nw_control_t control) {
+ nw_result rc;
+ nw_rx_header_t rx_header;
+ nw_ep ep;
+ nw_tcb_t tcb;
+
+ if (control == NULL) {
+ rc = NW_SUCCESS;
+ } else {
+ tct[control->ep].rx_control = NULL;
+ while ((rx_header = delayed_rx_first[dev]) != NULL &&
+ tick[dev] >= rx_header->time_stamp) {
+ delayed_rx_first[dev] = rx_header->next;
+ nc_buffer_deallocate(rx_header->buffer->peer.local_ep,
+ rx_header->buffer);
+ ep = rx_header->receiver;
+ tcb = &tct[ep];
+ tcb->rx_sar_header = SSM | (tcb->rx_sar_header & MID);
+ nc_rx_header_deallocate(rx_header);
+ }
+ if (rx_header == NULL) {
+ delayed_rx_last[dev] = NULL;
+ control->ep = 0;
+ long_rx_count[dev]--;
+ rc = NW_FAILURE;
+ } else {
+ delayed_rx_first[dev] = rx_header->next;
+ if (rx_header->next == NULL)
+ delayed_rx_last[dev] = NULL;
+ ep = rx_header->receiver;
+ tcb = &tct[ep];
+ tca100_synch_send(dev, tcb, rx_header->reply);
+ control->ep = ep;
+ control->time_out = tick[dev] + BASE_TIME_OUT;
+ tcb->rx_control = control;
+ nc_rx_header_deallocate(rx_header);
+ }
+ }
+}
+
+
+int tca100_poll(int dev) {
+ vol_u_int *status = &((atm_device_t) devct[dev].addr)->sreg;
+ vol_u_int *ctl_set = &((atm_device_t) devct[dev].addr)->creg_set;
+ vol_u_int *rx_counter = &((atm_device_t) devct[dev].addr)->rxcount;
+ register vol_u_int *rx_fifo = &((atm_device_t) devct[dev].addr)->rxfifo[0];
+ register u_int rx_cell_count;
+ register u_int predicted_atm_header = 0;
+ register u_int predicted_sar_header;
+ u_int atm_header, sar_header, predicted_sar_trailer,
+ cs_header, end_count, cs_pad, rx_cell_total, reply,
+ block_length, initial_offset;
+ register vol_u_int *msg;
+ register int msg_count;
+ register int next_synch;
+ register u_int t1, t2;
+ nw_ecb_t ecb, tx_ecb;
+ nw_tcb_t new_tcb, tx_tcb;
+ nw_tcb dummy_tcb_s;
+ nw_tcb_t tcb = &dummy_tcb_s;
+ nw_control_t control;
+ nw_buffer_t buffer;
+ nw_protocol protocol;
+ nw_ep lep, rep;
+ nw_delivery delivery_type = NW_RECEIVE;
+ nw_rx_header_t rx_header;
+ nw_tx_header_t tx_header;
+ int i;
+ u_int tx_seqno, rx_seqno, tx_count, rx_count;
+
+ rx_cell_total = 0;
+ while ((rx_cell_count = *rx_counter & RX_COUNTER_MASK) != 0) {
+ rx_cell_total += rx_cell_count;
+ while (rx_cell_count-- > 0) {
+ atm_header = rx_fifo[0]; /*Check ATM header and SAR header*/
+ sar_header = (rx_fifo[1] & SAR_HEADER_MASK);
+ if (atm_header != predicted_atm_header) {
+ /*Must be cell from a different connection*/
+ if (atm_header & ~(ATM_VPVC_MASK | ATM_HEADER_RSV_BITS)) {
+ atm_header_error:
+ tca_ec[ATM_HEADER]++;
+ if (tca100_verbose)
+ printf("ATM header error %x\n", atm_header);
+ discard_cell:
+ *((char *) rx_fifo) = 0;
+ delivery_type = NW_RECEIVE;
+ continue;
+ } else {
+ t1 = (atm_header & ATM_VPVC_MASK) >> ATM_VPVC_SHIFT;
+ new_tcb = &tct[t1];
+ ecb = &ect[t1];
+
+ /*Switch cached connection*/
+ if (new_tcb->rx_sar_header == 0)
+ goto atm_header_error;
+ tcb->rx_sar_header = predicted_sar_header;
+ tcb->rx_p = (u_int *) msg;
+ tcb->rx_count = msg_count;
+ tcb->rx_next_synch = next_synch;
+ predicted_atm_header = atm_header;
+ tcb = new_tcb;
+ predicted_sar_header = tcb->rx_sar_header;
+ msg = tcb->rx_p;
+ msg_count = tcb->rx_count;
+ next_synch = tcb->rx_next_synch;
+ }
+ }
+
+ if (sar_header != predicted_sar_header) {
+ if ((sar_header ^ predicted_sar_header) == EOM &&
+ ((predicted_sar_header & BOM) || msg_count <= EOM_DATA_SIZE)) {
+ /*Difference on end of message bit only*/
+ predicted_sar_header = sar_header;
+ } else if (sar_header == SSM) { /*MID 0*/
+ cs_header = rx_fifo[2];
+ t1 = rx_fifo[3];
+ if (cs_header == HTONL(8) && t1 == HTONL(NW_SYNCHRONIZATION)) {
+ reply = rx_fifo[4]; /*Synch cell*/
+ if (rx_fifo[5] != cs_header)
+ goto cs_header_error;
+ cs_pad = rx_fifo[6];
+ t1 = rx_fifo[7];
+ t2 = rx_fifo[8];
+ cs_pad |= t1;
+ cs_pad |= t2;
+ t1 = rx_fifo[9];
+ t2 = rx_fifo[10];
+ cs_pad |= t1;
+ cs_pad |= t2;
+ t1 = rx_fifo[11];
+ t2 = rx_fifo[12];
+ cs_pad |= t1;
+ cs_pad |= t2;
+ t1 = rx_fifo[13];
+ if (cs_pad)
+ goto cs_trailer_error;
+ if ((t1 & SAR_TRAILER_MASK) != SYNCH_SEGMENT_TRAILER)
+ goto sar_trailer_error;
+ if (tcb->tx_control == NULL) {
+ tca_ec[SYNCH_ERROR]++;
+ if (tca100_verbose)
+ printf("Synch error %x\n", ntohl(reply));
+ } else {
+ tcb->reply = ntohl(reply);
+
+#ifdef TRACING
+ printf("Received synch ep %d %x\n", ecb->id, tcb->reply);
+#endif
+
+ }
+ continue;
+ } else if (t1 == HTONL(NW_URGENT)) { /*Urgent cell*/
+ delivery_type = NW_RECEIVE_URGENT;
+ goto cs_header_check;
+ } else { /*Bad segment*/
+ goto sar_header_error;
+ }
+ } else if (!(sar_header & ATM_HEADER_CRC_SYNDROME) &&
+ (sar_header & BOM) && (sar_header & SEQ_NO) == 0) {
+ if ((sar_header & MID) == (predicted_sar_header & MID)) {
+ /*Retransmission*/
+ if (tcb->rx_control != NULL) {
+ tcb->rx_control->ep = 0;
+ long_rx_count[dev]--;
+ }
+ nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
+ tcb->rx_buffer);
+ predicted_sar_header = sar_header;
+ tca_ec[RX_RETRANSMISSION]++;
+ if (tca100_verbose)
+ printf("Receiving retransmission ep %d sar %x\n",
+ ecb->id, sar_header);
+ } else if (predicted_sar_header & BOM) {
+ /*Sequence number error*/
+ if (tca100_verbose)
+ printf("Sequence error ep %d pred %x real %x\n", ecb->id,
+ predicted_sar_header, sar_header);
+ if (ecb->protocol == NW_SEQ_PACKET) {
+ reply = 0xffff0000 | TCA_SEQ | (predicted_sar_header & MID);
+ tca100_synch_send(dev, tcb, reply);
+ tca_ec[SEQ_ERROR]++;
+ goto discard_cell;
+ } else {
+ predicted_sar_header = sar_header;
+ }
+ } else {
+ goto sar_header_error; /*Badly out of synch*/
+ }
+ } else { /*Cell loss*/
+
+ sar_header_error:
+ if (!(predicted_sar_header & BOM)) {
+ rx_slot_free(dev, tcb->rx_control);
+ nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
+ tcb->rx_buffer);
+ predicted_sar_header = SSM | (predicted_sar_header & MID);
+ }
+ tca_ec[SAR_HEADER]++;
+ if (tca100_verbose)
+ printf("SAR header error ep %d pred %x real %x\n", ecb->id,
+ predicted_sar_header, sar_header);
+ goto discard_cell;
+ }
+ }
+
+ if ((predicted_sar_header & SEG_TYPE) == COM) {
+ /*Continuation of message*/
+ if (msg_count <= next_synch) {
+ if (msg_count == next_synch &&
+ msg_count >= CONTINUATION_WINDOW_SIZE) {
+ reply = (msg_count << 16) | TCA_ACK | (predicted_sar_header & MID);
+ tca100_synch_send(dev, tcb, reply);
+ if (msg_count > (CONTINUATION_WINDOW_SIZE + FINAL_WINDOW_SIZE)) {
+ next_synch = msg_count - CONTINUATION_WINDOW_SIZE;
+ } else if (ecb->protocol == NW_SEQ_PACKET) {
+ next_synch = 0;
+ } else {
+ next_synch = -1;
+ }
+ tcb->rx_control->time_out = tick[dev] + BASE_TIME_OUT;
+ } else {
+ rx_slot_free(dev, tcb->rx_control);
+ nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
+ tcb->rx_buffer);
+ predicted_sar_header = SSM | (predicted_sar_header & MID);
+ tca_ec[FRAME_ERROR]++;
+ if (tca100_verbose)
+ printf("Frame error ep %d\n", ecb->id);
+ goto discard_cell;
+ }
+ }
+ t1 = rx_fifo[2];
+ t2 = rx_fifo[3];
+ msg[0] = t1;
+ msg[1] = t2;
+ t1 = rx_fifo[4];
+ t2 = rx_fifo[5];
+ msg[2] = t1;
+ msg[3] = t2;
+ t1 = rx_fifo[6];
+ t2 = rx_fifo[7];
+ msg[4] = t1;
+ msg[5] = t2;
+ t1 = rx_fifo[8];
+ t2 = rx_fifo[9];
+ msg[6] = t1;
+ msg[7] = t2;
+ t1 = rx_fifo[10];
+ t2 = rx_fifo[11];
+ msg[8] = t1;
+ msg[9] = t2;
+ t1 = rx_fifo[12];
+ t2 = rx_fifo[13];
+ msg[10] = t1;
+ if ((t2 & SAR_TRAILER_MASK) != FULL_SEGMENT_TRAILER) {
+ t1 = t2;
+ goto sar_trailer_error;
+ }
+ predicted_sar_header = (predicted_sar_header + SEQ_INC) &
+ (SEQ_NO | MID);
+ msg_count -= COM_DATA_SIZE;
+ msg += 11;
+
+ } else if ((predicted_sar_header & BOM) != 0) {
+ cs_header = rx_fifo[2];
+
+ cs_header_check:
+ block_length = msg_count = (((cs_header >> 8) & 0xff00) |
+ (cs_header >> 24));
+ protocol = cs_header & 0x00ff;
+ if (protocol == NW_RAW || protocol == NW_SEQ_PACKET) {
+ lep = ecb->conn->peer.local_ep;
+ rep = ecb->conn->peer.remote_ep;
+ if (delivery_type == NW_RECEIVE)
+ initial_offset = 0;
+ else
+ initial_offset = 4;
+ } else {
+ t1 = rx_fifo[3];
+ block_length -= 4;
+ lep = (t1 >> 8) & 0xff00 | t1 >> 24;
+ rep = (t1 & 0xff00) >> 8 | (t1 & 0x00ff) << 8;
+ if (delivery_type == NW_RECEIVE)
+ initial_offset = 4;
+ else
+ initial_offset = 8;
+ }
+ if (protocol != ecb->protocol || (protocol == NW_DATAGRAM) ||
+ (protocol == NW_LINE && ect[lep].protocol != NW_DATAGRAM) ||
+ ((predicted_sar_header & 0x00ff) << 8) != (cs_header & 0xff00) ||
+ ((delivery_type != NW_RECEIVE) &&
+ msg_count - initial_offset > MTU_URGENT[protocol]) ||
+ msg_count > MTU[protocol] || (msg_count & 0x3)) {
+
+ cs_header_error:
+ if ((protocol != NW_RAW && msg_count > SMALL_WINDOW_SIZE) ||
+ protocol == NW_SEQ_PACKET) {
+ reply = 0xffff0000 | TCA_NAK | (predicted_sar_header & MID);
+ tca100_synch_send(dev, tcb, reply);
+ }
+ tca_ec[CS_HEADER]++;
+ if (tca100_verbose)
+ printf("CS header error ep %d sar %x cs %x\n", ecb->id,
+ predicted_sar_header, cs_header);
+ goto discard_cell;
+ }
+ buffer = nc_buffer_allocate(lep, sizeof(nw_buffer_s) + block_length);
+ if (buffer == NULL) {
+ if ((protocol != NW_RAW && msg_count > SMALL_WINDOW_SIZE) ||
+ protocol == NW_SEQ_PACKET) {
+ reply = 0xffff0000 | TCA_OVR | (predicted_sar_header & MID);
+ tca100_synch_send(dev, tcb, reply);
+ }
+ tca_ec[OVERRUN_ERROR]++;
+ if (tca100_verbose)
+ printf("Overrun error ep %d\n", ecb->id);
+ goto discard_cell;
+ }
+ if (protocol == NW_RAW) {
+ next_synch = -1;
+ } else if (msg_count > SMALL_WINDOW_SIZE) {
+ reply = (msg_count << 16) | TCA_ACK | (predicted_sar_header & MID);
+ if (long_rx_count[dev] >= MAX_LONG_RX) {
+ rx_header = nc_rx_header_allocate();
+ if (rx_header == NULL) {
+ nc_buffer_deallocate(lep, buffer);
+ tca_ec[OVERRUN_ERROR]++;
+ goto discard_cell;
+ }
+ rx_header->buffer = buffer;
+ rx_header->receiver = ecb->id;
+ rx_header->reply = reply;
+ rx_header->time_stamp = tick[dev] + DELAYED_TIME_OUT;
+ rx_header->next = NULL;
+ if (delayed_rx_last[dev] == NULL)
+ delayed_rx_first[dev] = rx_header;
+ else
+ delayed_rx_last[dev]->next = rx_header;
+ delayed_rx_last[dev] = rx_header;
+ } else {
+ tca100_synch_send(dev, tcb, reply);
+ control = &nw_rx_control[dev][0];
+ while (control->ep != 0)
+ control++;
+ control->ep = ecb->id;
+ control->time_out = tick[dev] + BASE_TIME_OUT;
+ tcb->rx_control = control;
+ if (long_rx_count[dev] + long_tx_count[dev] == 0)
+ nc_fast_timer_set(dev);
+ long_rx_count[dev]++;
+ }
+ if (msg_count > INITIAL_WINDOW_SIZE + FINAL_WINDOW_SIZE)
+ next_synch = msg_count - INITIAL_WINDOW_SIZE;
+ else if (protocol == NW_SEQ_PACKET)
+ next_synch = 0;
+ else
+ next_synch = -1;
+ } else if (protocol == NW_SEQ_PACKET) {
+ next_synch = 0;
+ } else {
+ next_synch = -1;
+ }
+ msg = (vol_u_int *) ((char *) buffer + sizeof(nw_buffer_s));
+ tcb->rx_cs_header = cs_header;
+ tcb->rx_buffer = buffer;
+ buffer->buf_next = NULL;
+ buffer->msg_seqno = sar_header & MID;
+ buffer->block_offset = sizeof(nw_buffer_s);
+ buffer->block_length = block_length;
+ buffer->peer.rem_addr_1 = ecb->conn->peer.rem_addr_1;
+ buffer->peer.rem_addr_2 = ecb->conn->peer.rem_addr_2;
+ buffer->peer.local_ep = lep;
+ buffer->peer.remote_ep = rep;
+
+ if ((predicted_sar_header & EOM) == 0) { /*BOM*/
+ if (initial_offset == 0) {
+ t1 = rx_fifo[3];
+ t2 = rx_fifo[4];
+ msg[0] = t1;
+ msg[1] = t2;
+ msg += 2;
+ } else {
+ msg[0] = rx_fifo[4];
+ msg++;
+ }
+ t1 = rx_fifo[5];
+ t2 = rx_fifo[6];
+ msg[0] = t1;
+ msg[1] = t2;
+ t1 = rx_fifo[7];
+ t2 = rx_fifo[8];
+ msg[2] = t1;
+ msg[3] = t2;
+ t1 = rx_fifo[9];
+ t2 = rx_fifo[10];
+ msg[4] = t1;
+ msg[5] = t2;
+ t1 = rx_fifo[11];
+ t2 = rx_fifo[12];
+ msg[6] = t1;
+ t1 = rx_fifo[13];
+ msg[7] = t2;
+ if ((t1 & SAR_TRAILER_MASK) != FULL_SEGMENT_TRAILER)
+ goto sar_trailer_error;
+ msg_count -= BOM_DATA_SIZE;
+ msg += 8;
+ predicted_sar_header = (predicted_sar_header + SEQ_INC) &
+ (SEQ_NO | MID);
+
+ } else { /*SSM*/
+ end_count = msg_count + 4;
+ predicted_sar_trailer = (msg_count + 8) << 26;
+ if (delivery_type != NW_RECEIVE) {
+ msg[0] = NW_URGENT;
+ msg++;
+ }
+ msg_count -= initial_offset;
+ goto EOM_payload;
+ }
+ } else { /*EOM*/
+ end_count = msg_count;
+ predicted_sar_trailer = (msg_count + 4) << 26;
+
+ EOM_payload:
+ if (msg_count & 0x4) {
+ msg[0] = rx_fifo[2];
+ }
+ msg = (vol_u_int *) ((char *) msg + msg_count);
+ /*Fall-through the cases is intentional*/
+ switch (msg_count >> 3) {
+ case 5:
+ t1 = rx_fifo[2];
+ t2 = rx_fifo[2];
+ msg[-10] = t1;
+ msg[-9] = t2;
+ case 4:
+ t1 = rx_fifo[2];
+ t2 = rx_fifo[2];
+ msg[-8] = t1;
+ msg[-7] = t2;
+ case 3:
+ t1 = rx_fifo[2];
+ t2 = rx_fifo[2];
+ msg[-6] = t1;
+ msg[-5] = t2;
+ case 2:
+ t1 = rx_fifo[2];
+ t2 = rx_fifo[2];
+ msg[-4] = t1;
+ msg[-3] = t2;
+ case 1:
+ t1 = rx_fifo[2];
+ t2 = rx_fifo[2];
+ msg[-2] = t1;
+ msg[-1] = t2;
+ }
+
+ /*CS trailer should be equal to the CS header, followed by
+ padding zeros*/
+ cs_pad = (rx_fifo[2] != tcb->rx_cs_header);
+ /*Fall-through the cases is intentional*/
+ t1 = t2 = 0;
+ switch (end_count) {
+ case 0:
+ t1 = rx_fifo[2];
+ case 4:
+ t2 = rx_fifo[2];
+ cs_pad |= t1;
+ case 8:
+ t1 = rx_fifo[2];
+ cs_pad |= t2;
+ case 12:
+ t2 = rx_fifo[2];
+ cs_pad |= t1;
+ case 16:
+ t1 = rx_fifo[2];
+ cs_pad |= t2;
+ case 20:
+ t2 = rx_fifo[2];
+ cs_pad |= t1;
+ case 24:
+ t1 = rx_fifo[2];
+ cs_pad |= t2;
+ case 28:
+ t2 = rx_fifo[2];
+ cs_pad |= t1;
+ case 32:
+ t1 = rx_fifo[2];
+ cs_pad |= t2;
+ case 36:
+ t2 = rx_fifo[2];
+ cs_pad |= t1;
+ cs_pad |= t2;
+ }
+ t1 = rx_fifo[13];
+ if (cs_pad != 0) {
+ /*Errors in CS trailer or pad*/
+ cs_trailer_error:
+ tca_ec[CS_TRAILER]++;
+ if (tca100_verbose)
+ printf("CS trailer error ep %d hd %x pad %x\n", ecb->id,
+ tcb->rx_cs_header, cs_pad);
+ goto trailer_error;
+
+ } else if ((t1 & SAR_TRAILER_MASK) != predicted_sar_trailer) {
+ /*Error in SAR trailer or framing*/
+ sar_trailer_error:
+ tca_ec[SAR_TRAILER]++;
+ if (tca100_verbose)
+ printf("SAR trailer error ep %d pred %x real %x\n", ecb->id,
+ predicted_sar_trailer, t1);
+ goto trailer_error;
+
+ } else if (!nc_deliver_result(tcb->rx_buffer->peer.local_ep,
+ delivery_type, (int) tcb->rx_buffer)) {
+ tca_ec[DELIVERY_ERROR]++;
+ if (tca100_verbose)
+ printf("Delivery error ep %d\n", ecb->id);
+
+ trailer_error:
+ if (next_synch >= 0 && !(t1 & HEADER_CRC_ERROR)) {
+ reply = (msg_count << 16) | TCA_NAK | (predicted_sar_header & MID);
+ tca100_synch_send(dev, tcb, reply);
+ }
+ rx_slot_free(dev, tcb->rx_control);
+ nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep,
+ tcb->rx_buffer);
+ predicted_sar_header = SSM | (predicted_sar_header & MID);
+ delivery_type = NW_RECEIVE;
+ } else {
+
+#ifdef TRACING
+ printf("Received correctly ep %d\n", ecb->id);
+#endif
+
+ if (next_synch == 0) {
+ reply = TCA_ACK | (predicted_sar_header & MID);
+ tca100_synch_send(dev, tcb, reply);
+ }
+ rx_slot_free(dev, tcb->rx_control);
+ if (delivery_type != NW_RECEIVE) {
+ delivery_type = NW_RECEIVE;
+ predicted_sar_header = SSM | (predicted_sar_header & MID);
+ } else {
+ predicted_sar_header = (predicted_sar_header + MID_INC) & MID;
+ if (predicted_sar_header == 0)
+ predicted_sar_header = 1;
+ predicted_sar_header |= SSM;
+ }
+ }
+ }
+ }
+
+ control = &nw_tx_control[dev][0];
+ for (i = 0; i < MAX_LONG_TX; i++) {
+ if (control->ep != 0 && tct[control->ep].reply != TCA_SYNCH) {
+ tx_ecb = &ect[control->ep];
+ tx_tcb = &tct[control->ep];
+ rx_seqno = tx_tcb->reply & MID;
+ tx_seqno = tx_tcb->tx_sar_header & MID;
+ rx_count = tx_tcb->reply >> 16;
+ tx_count = tx_tcb->tx_synch;
+ reply = tx_tcb->reply & TCA_SYNCH;
+ if (reply == TCA_ACK) {
+ if (rx_seqno == tx_seqno && rx_count == tx_count) {
+ if (rx_count == 0) {
+#ifdef TRACING
+ printf("Received final ack ep %d\n", tx_ecb->id);
+#endif
+
+ tx_seqno = (tx_seqno + MID_INC) & MID;
+ if (tx_seqno == 0)
+ tx_seqno = 1;
+ tx_tcb->tx_sar_header = tx_seqno;
+ tx_slot_free(dev, control);
+ tx_tcb->reply = NW_SUCCESS;
+ nc_deliver_result(tx_ecb->id, NW_SEND, NW_SUCCESS);
+ } else {
+ if (tca100_window_send(dev, tx_ecb, tx_tcb,
+ FALSE) == NW_SUCCESS) {
+ nc_deliver_result(control->ep, NW_SEND, NW_SUCCESS);
+ tx_tcb->reply = NW_SUCCESS;
+ tx_slot_free(dev, control);
+ } else {
+ control->time_out = tick[dev] + BASE_TIME_OUT;
+ tx_tcb->reply = TCA_SYNCH;
+ }
+ }
+ } else {
+ goto synch_error;
+ }
+ } else if (reply == TCA_OVR) {
+ if (rx_seqno == tx_seqno && rx_count == 0xffff &&
+ ((int) tx_ecb->tx_initial->msg_length -
+ (int) tx_tcb->tx_synch) <= (int) SMALL_WINDOW_SIZE) {
+ nc_deliver_result(control->ep, NW_SEND, NW_OVERRUN);
+ tx_tcb->reply = NW_OVERRUN;
+ tx_slot_free(dev, control);
+ } else {
+ goto synch_error;
+ }
+ } else if (reply == TCA_NAK) {
+ if (rx_seqno == tx_seqno &&
+ (rx_count == tx_count || (rx_count == 0xffff &&
+ ((int) tx_ecb->tx_initial->msg_length -
+ (int) tx_tcb->tx_synch) <= (int) SMALL_WINDOW_SIZE))) {
+ if (++control->retry < MAX_RETRY) {
+ if (tca100_verbose)
+ printf("Sending retransmission ep %d\n", tx_ecb->id);
+ if (tca100_window_send(dev, tx_ecb, tx_tcb,
+ TRUE) == NW_SUCCESS) {
+ nc_deliver_result(control->ep, NW_SEND, NW_SUCCESS);
+ tx_tcb->reply = NW_SUCCESS;
+ tx_slot_free(dev, control);
+ } else {
+ control->time_out = tick[dev] + BASE_TIME_OUT;
+ tx_tcb->reply = TCA_SYNCH;
+ }
+ tca_ec[TX_RETRANSMISSION]++;
+ } else {
+ nc_deliver_result(control->ep, NW_SEND, NW_FAILURE);
+ tx_tcb->reply = NW_FAILURE;
+ tx_slot_free(dev, control);
+ }
+ } else {
+ goto synch_error;
+ }
+ } else if (reply == TCA_SEQ) {
+ if (rx_count == 0xffff && tx_ecb->protocol == NW_SEQ_PACKET &&
+ ((int) tx_ecb->tx_initial->msg_length -
+ (int) tx_tcb->tx_synch) <= (int) SMALL_WINDOW_SIZE &&
+ rx_seqno == ((((tx_seqno + MID_INC) & MID) == 0) ?
+ 1 : tx_seqno + MID_INC)) {
+ tx_tcb->tx_sar_header = rx_seqno;
+ if (tca100_window_send(dev, tx_ecb, tx_tcb,
+ TRUE) == NW_SUCCESS) {
+ nc_deliver_result(control->ep, NW_SEND, NW_SUCCESS);
+ tx_tcb->reply = NW_SUCCESS;
+ tx_slot_free(dev, control);
+ } else {
+ control->time_out = tick[dev] + BASE_TIME_OUT;
+ tx_tcb->reply = TCA_SYNCH;
+ }
+ tca_ec[TX_RETRANSMISSION]++;
+ if (tca100_verbose)
+ printf("Sending seq retransmission ep %d\n", tx_ecb->id);
+ } else {
+ goto synch_error;
+ }
+ } else {
+ synch_error:
+ tca_ec[SYNCH_ERROR]++;
+ tx_tcb->reply = NW_FAILURE;
+ if (tca100_verbose)
+ printf("Synch error\n");
+ }
+ }
+ control++;
+ }
+ }
+ *status = ~(RX_COUNT_INTR | RX_EOM_INTR | RX_TIME_INTR);
+ tcb->rx_sar_header = predicted_sar_header;
+ tcb->rx_p = (u_int *) msg;
+ tcb->rx_count = msg_count;
+ tcb->rx_next_synch = next_synch;
+ *ctl_set = RX_COUNT_INTR;
+ return rx_cell_total;
+}
+
+
+
+void tca100_timer_sweep(int dev) {
+ int i, rt;
+ u_int reply;
+ nw_control_t control;
+ nw_ecb_t ecb;
+ nw_tcb_t tcb;
+ nw_tx_header_t tx_header;
+ nw_rx_header_t rx_header;
+
+ tick[dev]++;
+ control = &nw_rx_control[dev][0];
+ for (i = 0; i < MAX_LONG_RX; i++) {
+ if (control->ep != 0 && control->time_out < tick[dev]) {
+ rx_slot_free(dev, control);
+ tcb = &tct[control->ep];
+ nc_buffer_deallocate(tcb->rx_buffer->peer.local_ep, tcb->rx_buffer);
+ tcb->rx_sar_header = SSM | (tcb->rx_sar_header & MID);
+ }
+ control++;
+ }
+ control = &nw_tx_control[dev][0];
+ for (i = 0; i < MAX_LONG_TX; i++) {
+ if (control->ep != 0 && control->time_out < tick[dev]) {
+ ecb = &ect[control->ep];
+ tcb = &tct[control->ep];
+ if (++control->retry < MAX_RETRY) {
+ if (control->retry == 1)
+ rt = ( /* random() */ + devct[dev].local_addr_2) & 0x000f;
+ else
+ rt = ( /* random() */ + devct[dev].local_addr_1
+ + devct[dev].local_addr_2) & 0x00ff;
+ control->time_out = tick[dev] + BASE_TIME_OUT + rt;
+ tca100_window_send(dev, ecb, tcb, TRUE);
+ tca_ec[TX_RETRANSMISSION]++;
+ } else {
+ nc_deliver_result(control->ep, NW_SEND, NW_TIME_OUT);
+ tx_slot_free(dev, control);
+ }
+ }
+ control++;
+ }
+ if (long_tx_count[dev] + long_rx_count[dev] > 0)
+ nc_fast_timer_set(dev);
+ else
+ tick[dev] = 0;
+}
+
+nw_buffer_t tca100_rpc(nw_ep ep, nw_tx_header_t header, nw_options options) {
+ nw_result rc;
+ nw_buffer_t buf;
+ nw_ecb_t ecb;
+ nw_tcb_t tcb;
+ nw_rx_header_t rx_header;
+ int dev, poll_time, ncells;
+
+ tcb = &tct[ep];
+ ecb = &ect[header->peer.local_ep];
+ dev = NW_DEVICE(header->peer.rem_addr_1);
+ if ((rc = tca100_send(ep, header, options)) == NW_BAD_LENGTH) {
+ buf = NW_BUFFER_ERROR;
+ } else if (rc == NW_QUEUED) {
+ buf = NULL;
+ } else {
+ poll_time = 0;
+ if (rc == NW_SYNCH) {
+ while (tcb->reply == TCA_SYNCH && poll_time < POLL_LIMIT) {
+ ncells = tca100_poll(dev);
+ if (ncells == 0)
+ poll_time += POLL_IDLE_TIME;
+ else
+ poll_time += ncells * POLL_CELL_TIME;
+ }
+ }
+ if (tcb->reply != NW_SUCCESS) {
+ buf = NW_BUFFER_ERROR;
+ } else {
+ while (ecb->rx_first == NULL && poll_time < POLL_LIMIT) {
+ ncells = tca100_poll(dev);
+ if (ncells == 0)
+ poll_time += POLL_IDLE_TIME;
+ else
+ poll_time += ncells * POLL_CELL_TIME;
+ }
+ if (ecb->rx_first == NULL) {
+ buf = NULL;
+ } else {
+ rx_header = ecb->rx_first;
+ buf = rx_header->buffer;
+ ecb->rx_first = rx_header->next;
+ if (ecb->rx_first == NULL)
+ ecb->rx_last = NULL;
+ nc_rx_header_deallocate(rx_header);
+ }
+ }
+ }
+
+ return buf;
+}
+
+
+
+
+
+
+
+
+
diff --git a/chips/tca100_if.h b/chips/tca100_if.h
new file mode 100644
index 00000000..41183ea0
--- /dev/null
+++ b/chips/tca100_if.h
@@ -0,0 +1,89 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*** TCA 100 ATM NETWORK INTERFACE ***/
+
+#ifndef STUB
+#include <chips/nc.h>
+#include <chips/spans.h>
+#include <chips/tca100.h>
+#else
+#include "nc.h"
+#include "spans.h"
+#include "tca100.h"
+#endif
+
+typedef struct {
+ nw_ep ep;
+ int time_out;
+ int retry;
+} nw_control_s, *nw_control_t;
+
+
+typedef struct {
+ u_int rx_sar_header;
+ u_int rx_cs_header;
+ u_int *rx_p;
+ u_int rx_count;
+ u_int rx_next_synch;
+ nw_buffer_t rx_buffer;
+ nw_control_t rx_control;
+ u_int tx_atm_header;
+ u_int tx_sar_header;
+ u_int tx_cs_header;
+ u_int *tx_p;
+ u_int tx_msg_count;
+ u_int tx_block_count;
+ u_int tx_synch;
+ u_int tx_queued_count;
+ nw_control_t tx_control;
+ u_int reply;
+} nw_tcb, *nw_tcb_t;
+
+extern nw_tcb tct[MAX_EP];
+
+extern nw_dev_entry_s tca100_entry_table;
+
+extern nw_result tca100_initialize(int dev);
+
+extern nw_result tca100_status(int dev);
+
+extern void tca100_timer_sweep(int dev);
+
+extern int tca100_poll(int dev);
+
+extern nw_result tca100_send(nw_ep ep, nw_tx_header_t header,
+ nw_options options);
+
+extern nw_buffer_t tca100_rpc(nw_ep ep, nw_tx_header_t header,
+ nw_options options);
+
+
+
+
+
+
+
diff --git a/chips/vs42x_rb.h b/chips/vs42x_rb.h
new file mode 100644
index 00000000..82b89b06
--- /dev/null
+++ b/chips/vs42x_rb.h
@@ -0,0 +1,267 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: vs42x_rb.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 5/91
+ *
+ * This file contains definitions for the VS42X-RB Storage
+ * controller, which includes a Disk controller and a
+ * SCSI controller.
+ */
+
+#ifndef _VS42X_RB_H_
+#define _VS42X_RB_H_
+
+/*
+ * Phys addresses for the Vax3100
+ */
+#define VAX3100_STC_BASE 0x200c0000
+#define VAX3100_STC_RAM_COMPAT 0x200d0000
+#define VAX3100_STC_RAM 0x202d0000
+
+#define VAX3100_STC_HDC9224 0x00000000 /* offsets from BASE */
+#define VAX3100_STC_5380_A 0x00000080
+#define VAX3100_STC_5380_B 0x00000180
+#define VAX3100_STC_DMAREG_A 0x000000a0
+#define VAX3100_STC_DMAREG_B 0x000001a0
+#define VAX3100_STC_RAM_MODE 0x000000e0
+
+#define VAX3100_STC_DMAREG_OFF (0xa0-0x80) /* offset from 5380 */
+
+#define SCI_REG_SIZE 512
+
+/*
+ * RAM Buffer for this storage system
+ */
+#define SCI_RAM_SIZE 128*1024
+#define SCI_RAM_COMPATSIZE 32*1024
+#define SCI_RAM_EXPMODE 0x01 /* char-size mode register */
+
+/*
+ * DMA controller for the SCSI subsystem
+ * (Defines for the NCR 5380 are elsewhere)
+ */
+
+typedef struct {
+ unsigned int sci_dma_adr; /* +000000a0 */
+ char pad0[0xc0-0xa0-4];
+ unsigned int sci_dma_count; /* +000000c0 */
+ unsigned int sci_dma_dir; /* +000000c4 */
+ char pad1[0xe0-0xc4-4];
+ unsigned char sci_dma_rammode;/* +000000e0 */
+} *sci_dmaregs_t;
+
+#define SCI_DMADR_PUT(ptr,adr) (ptr)->sci_dma_adr = (unsigned)(adr) & SCI_DMA_COUNT_MASK;
+#define SCI_DMADR_GET(ptr,adr) (adr) = (ptr)->sci_dma_adr;
+
+#define SCI_DMA_COUNT_MASK 0x0001ffff
+#define SCI_TC_GET(ptr,cnt) {\
+ (cnt) = (ptr)->sci_dma_count;\
+ if ((cnt) & 0x00010000) (cnt) |= ~SCI_DMA_COUNT_MASK;\
+ (cnt) = -(cnt);\
+ }
+#define SCI_TC_PUT(ptr,cnt) (ptr)->sci_dma_count = -(cnt);
+
+#define SCI_DMA_DIR_READ 0x00000001
+#define SCI_DMA_DIR_WRITE 0x00000000
+
+/*
+ * Disk controller subsytem (ST506/412), uses a
+ * HDC 9224 Universal Disk Controller chip and
+ * addresses up to 4 disks.
+ */
+typedef struct {
+ unsigned char hdc_rap; /* rw: reg addres ptr */
+ char pad0[3];
+ unsigned char hdc_cmd; /* w: controller command */
+#define hdc_status hdc_cmd /* r: interrupt status */
+ char pad1[3];
+} *sci_hdcregs_t;
+
+/*
+ * Register Address Pointer
+ */
+#define UDC_DMA7 0 /* rw: DMA address bits 7:0 */
+#define UDC_DMA15 1 /* rw: DMA address bits 15:8 */
+#define UDC_DMA23 2 /* rw: DMA address bits 23:16 */
+#define UDC_DSECT 3 /* rw: desired sector */
+#define UDC_DHEAD 4 /* wo: desired head */
+#define UDC_CHEAD 4 /* ro: current head */
+#define UDC_DCYL 5 /* wo: desired cylinder */
+#define UDC_CCYL 5 /* ro: current cylinder */
+#define UDC_SCNT 6 /* wo: sector count */
+#define UDC_RTCNT 7 /* wo: retry count */
+#define UDC_MODE 8 /* wo: operating mode */
+#define UDC_CSTAT 8 /* ro: chip status */
+#define UDC_TERM 9 /* wo: termination conditions */
+#define UDC_DSTAT 9 /* ro: drive status */
+#define UDC_DATA 10 /* rw: data */
+
+/*
+ * Controller Commands
+ */
+#define HDCC_RESET 0x00
+
+#define HDCC_SET_REGP 0x40 /* low 4 bits is regnum */
+
+#define HDCC_DESELECT 0x01
+
+#define HDCC_SELECT 0x20
+# define HDCC_SELECT_IDMASK 0x03
+# define HDCC_SELECT_DR_HD 0x04
+# define HDCC_SELECT_DR_SD 0x08
+# define HDCC_SELECT_DR_DD 0x0c
+
+#define HDCC_RESTORE_HD 0x03
+
+#define HDCC_RESTORE_RX 0x02
+
+#define HDCC_STEP 0x04
+# define HDCC_STEP_OUT 0x02
+# define HDCC_STEP_SKWAIT 0x01
+
+#define HDCC_POLL 0x10 /* low 4 bits is drive mask */
+
+#define HDCC_SEEK 0x50
+# define HDCC_SEEK_STEP 0x04
+# define HDCC_SEEK_SKWAIT 0x02
+# define HDCC_SEEK_VFY 0x01
+
+#define HDCC_FORMAT 0x60
+# define HDCC_FORMAT_DDMARK 0x10
+
+#define HDCC_READ_T 0x5a
+# define HDCC_READ_XDATA 0x01
+
+#define HDCC_READ_P 0x58
+
+#define HDCC_READ_L 0x5c
+# define HDCC_READ_L_BYPASS 0x02
+
+#define HDCC_WRITE_P 0x80
+# define HDCC_WRITE_BYPASS 0x40
+# define HDCC_WRITE_DDMARK 0x10
+
+#define HDCC_WRITE_L 0xa0
+
+/*
+ * Interrupt Status Register
+ */
+#define HDCI_BADSECT 0x01
+#define HDCI_OVRUN 0x02
+#define HDCI_RDYCHNG 0x04
+#define HDCI_TERMCOD 0x18
+# define HDC_T_SUCCESS 0x00
+# define HDC_T_EREAD_ID 0x08
+# define HDC_T_EVFY 0x10
+# define HDC_T_EXFER 0x18
+#define HDCI_DONE 0x20
+#define HDCI_DMAREQ 0x40
+#define HDCI_INT 0x80 /* interrupt pending */
+
+/*
+ * Desired/Current Head
+ */
+#define UDC_HEAD_HMASK 0x0f /* desired head no */
+#define UDC_HEAD_CMASK 0x70 /* desired cyl 10:8 */
+#define UDC_HEAD_BADSEC 0x80
+
+/*
+ * Sector Count
+ */
+#define HDC_MAXDATA 256*512
+
+/*
+ * Retry Count
+ */
+#define UDC_RTCNT_MASK 0xf0
+#define UDC_RTCNT_RXDIS 0x08 /* mbz */
+#define UDC_RTCNT_INVRDY 0x04
+#define UDC_RTCNT_MOTOR 0x02
+#define UDC_RTCNT_LOSPEED 0x01
+
+/*
+ * Mode
+ */
+#define UDC_MODE_HD 0x80 /* hard disk mode mb1 */
+#define UDC_MODE_CHKCOD 0x60 /* error checkin code */
+# define UDC_MODE_CRC 0x00
+# define UDC_MODE_EECC 0x20 /* NA */
+# define UDC_MODE_IECC 0x40 /* hard disks internal 32 ecc */
+# define UDC_MODE_AECC 0x60 /* NA */
+#define UDC_MODE_DENS 0x10 /* mbz */
+#define UDC_MODE_SRATE 0x07
+# define UDC_MODE_RATE_HD 0x00 /* hard disk */
+# define UDC_MODE_RATE_DD 0x01 /* double den rx23 */
+# define UDC_MODE_RATE_SD 0x02 /* single den rz23 */
+# define UDC_MODE_RATE_RD 0x06 /* restore drive */
+
+#define UDC_MODE_RX23_DD 0x81
+#define UDC_MODE_RX23_SD 0x82
+#define UDC_MODE_RDxx 0xc0
+#define UDC_MODE_RD_RESTORE 0xc6
+
+/*
+ * Status
+ */
+#define UDC_CSTAT_RETRIED 0x80
+#define UDC_CSTAT_ECC 0x40
+#define UDC_CSTAT_ECC_ERR 0x20
+#define UDC_CSTAT_DELDATA 0x10
+#define UDC_CSTAT_SYN_ERR 0x08
+#define UDC_CSTAT_COMP_ERR 0x04
+#define UDC_CSTAT_SELMASK 0x03
+# define UDC_CSTAT_SELHD0 0x00
+# define UDC_CSTAT_SELHD1 0x01
+# define UDC_CSTAT_SELRX 0x02
+# define UDC_CSTAT_SELHD2 0x03
+
+/*
+ * Termination
+ */
+#define UDC_TERM_CRCPRE 0x80 /* mb1 */
+#define UDC_TERM_IDONE 0x20
+#define UDC_TERM_DELDAT 0x10
+#define UDC_TERM_STAT3 0x08 /* mbz */
+#define UDC_TERM_WPROT 0x04
+#define UDC_TERM_IRDCHNG 0x02
+#define UDC_TERM_WFLT 0x01
+
+/*
+ * Drive status
+ */
+#define UDC_DSTAT_SELACK 0x80
+#define UDC_DSTAT_INDEX 0x40
+#define UDC_DSTAT_SKCOM 0x20
+#define UDC_DSTAT_TRK0 0x10
+#define UDC_DSTAT_STAT3 0x08 /* mbz */
+#define UDC_DSTAT_WPROT 0x04
+#define UDC_DSTAT_READY 0x02
+#define UDC_DSTAT_WFLT 0x01
+
+
+#endif _VS42X_RB_H_
diff --git a/chips/xcfb_hdw.c b/chips/xcfb_hdw.c
new file mode 100644
index 00000000..b2c67d67
--- /dev/null
+++ b/chips/xcfb_hdw.c
@@ -0,0 +1,230 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: xcfb_hdw.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Driver for the MAXine Color Frame Buffer Display,
+ * hardware-level operations.
+ */
+
+#include <xcfb.h>
+#if (NXCFB > 0)
+
+#include <platforms.h>
+
+#include <machine/machspl.h>
+#include <mach/std_types.h>
+#include <chips/busses.h>
+
+#include <chips/screen_defs.h>
+#include <chips/pm_defs.h>
+#include <machine/machspl.h>
+
+#ifdef MAXINE
+
+#include <chips/xcfb_monitor.h>
+
+#include <mips/PMAX/pmag_xine.h>
+#include <mips/PMAX/tc.h>
+#define enable_interrupt(s,o,x) (*tc_enable_interrupt)(s,o,x)
+
+#else /* MAXINE */
+You must say the magic words to get the coockies:
+#define enable_interrupt(slot,on,xx)
+#define IMS332_ADDRESS
+#define VRAM_OFFSET
+#define IMS332_RESET_ADDRESS
+#endif /* MAXINE */
+
+typedef pm_softc_t xcfb_softc_t;
+
+
+/*
+ * Definition of the driver for the auto-configuration program.
+ */
+
+int xcfb_probe(), xcfb_intr();
+static void xcfb_attach();
+
+vm_offset_t xcfb_std[NXCFB] = { 0 };
+struct bus_device *xcfb_info[NXCFB];
+struct bus_driver xcfb_driver =
+ { xcfb_probe, 0, xcfb_attach, 0, xcfb_std, "xcfb", xcfb_info,
+ 0, 0, BUS_INTR_DISABLED};
+
+/*
+ * Probe/Attach functions
+ */
+
+xcfb_probe( /* reg, ui */)
+{
+ static probed_once = 0;
+
+ /*
+ * Probing was really done sweeping the TC long ago
+ */
+ if (tc_probe("xcfb") == 0)
+ return 0;
+ if (probed_once++ > 1)
+ printf("[mappable] ");
+ return 1;
+}
+
+static void
+xcfb_attach(ui)
+ struct bus_device *ui;
+{
+ /* ... */
+ printf(": color display");
+}
+
+
+/*
+ * Interrupt routine
+ */
+
+xcfb_intr(unit,spllevel)
+ spl_t spllevel;
+{
+ /* interrupt has been acknowledge already */
+#if 0
+ splx(spllevel);
+ /* XXX make it load the unsafe things */
+#endif
+}
+
+xcfb_vretrace(xcfb, on)
+ xcfb_softc_t *xcfb;
+{
+ int i;
+
+ for (i = 0; i < NXCFB; i++)
+ if (xcfb_info[i]->address == (vm_offset_t)xcfb->framebuffer)
+ break;
+ if (i == NXCFB) return;
+
+ enable_interrupt(xcfb_info[i]->adaptor, on, 0);
+}
+
+/*
+ * Boot time initialization: must make device
+ * usable as console asap.
+ */
+
+/* some of these values are made up using ad hocery */
+static struct xcfb_monitor_type monitors[] = {
+ { "VRM17", 1024, 768, 1024, 1024, 16, 33,
+ 6, 2, 2, 21, 326, 16, 10, 10 },
+ /* XXX Add VRC16 */
+ { "VR262", 1024, 864, 1024, 1024, 16, 35,
+ 5, 3, 3, 37, 330, 16, 10, 10 },
+ { "VR299", 1024, 864, 1024, 1024, 16, 35,
+ 5, 3, 3, 37, 330, 16, 10, 10 },
+ { 0 }};
+
+/* set from prom command line */
+extern unsigned char *monitor_types[4];
+
+xcfb_monitor_type_t xcfb_get_monitor_type()
+{
+ xcfb_monitor_type_t m;
+
+ m = monitors;
+ if (monitor_types[3])
+ while (m->name) {
+ /* xcfb is always on the motherboard (slot 3),
+ fix if you need */
+ if (!strcmp(monitor_types[3], m->name))
+ break;
+ m++;
+ }
+ if (!m->name) /* the first is the default */
+ m = monitors;
+ return m;
+}
+
+
+extern int
+ xcfb_soft_reset(), xcfb_set_status(),
+ ims332_pos_cursor(), ims332_video_on(),
+ ims332_video_off(), xcfb_vretrace(),
+ pm_get_status(), pm_char_paint(),
+ pm_insert_line(), pm_remove_line(),
+ pm_clear_bitmap(), pm_map_page();
+
+static struct screen_switch xcfb_sw = {
+ screen_noop, /* graphic_open */
+ xcfb_soft_reset, /* graphic_close */
+ xcfb_set_status, /* set_status */
+ pm_get_status, /* get_status */
+ pm_char_paint, /* char_paint */
+ ims332_pos_cursor, /* pos_cursor */
+ pm_insert_line, /* insert_line */
+ pm_remove_line, /* remove_line */
+ pm_clear_bitmap, /* clear_bitmap */
+ ims332_video_on, /* video_on */
+ ims332_video_off, /* video_off */
+ xcfb_vretrace, /* intr_enable */
+ pm_map_page /* map_page */
+};
+
+xcfb_cold_init(unit, up)
+ user_info_t *up;
+{
+ xcfb_softc_t *xcfb;
+ screen_softc_t sc = screen(unit);
+ int base = tc_probe("xcfb");
+ xcfb_monitor_type_t m = xcfb_get_monitor_type();
+
+ bcopy(&xcfb_sw, &sc->sw, sizeof(sc->sw));
+
+ sc->flags |= COLOR_SCREEN; /* XXX should come from m->flags? */
+ sc->frame_scanline_width = m->frame_scanline_width;
+ sc->frame_height = m->frame_height;
+ sc->frame_visible_width = m->frame_visible_width;
+ sc->frame_visible_height = m->frame_visible_height;
+
+ pm_init_screen_params(sc, up);
+ (void) screen_up(unit, up);
+
+ xcfb = pm_alloc(unit, IMS332_ADDRESS, base + VRAM_OFFSET, 0);
+ xcfb->vdac_registers = (char *)IMS332_RESET_ADDRESS;
+
+ screen_default_colors(up);
+
+ xcfb_soft_reset(sc);
+
+ /*
+ * Clearing the screen at boot saves from scrolling
+ * much, and speeds up booting quite a bit.
+ */
+ screen_blitc( unit, 'C'-'@');/* clear screen */
+}
+
+
+#endif (NXCFB > 0)
diff --git a/chips/xcfb_misc.c b/chips/xcfb_misc.c
new file mode 100644
index 00000000..e7a08c33
--- /dev/null
+++ b/chips/xcfb_misc.c
@@ -0,0 +1,246 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: xcfb_misc.c
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 1/92
+ *
+ * Driver for the MAXine color framebuffer
+ *
+ */
+
+#include <xcfb.h>
+#if (NXCFB > 0)
+
+/*
+ * NOTE: This driver relies heavily on the pm one.
+ */
+
+#include <device/device_types.h>
+
+#include <chips/screen_defs.h>
+
+#include <chips/xcfb_monitor.h>
+#include <chips/pm_defs.h>
+typedef pm_softc_t xcfb_softc_t;
+
+#include <chips/ims332.h>
+#define ims332 cursor_registers
+
+
+/*
+ * Initialize color map, for kernel use
+ */
+xcfb_init_colormap(sc)
+ screen_softc_t sc;
+{
+ xcfb_softc_t *xcfb = (xcfb_softc_t*)sc->hw_state;
+ user_info_t *up = sc->up;
+ color_map_t Bg_Fg[2];
+ register int i;
+
+ ims332_init_colormap( xcfb->ims332 );
+
+ /* init bg/fg colors */
+ for (i = 0; i < 3; i++) {
+ up->dev_dep_2.pm.Bg_color[i] = 0x00;
+ up->dev_dep_2.pm.Fg_color[i] = 0xff;
+ }
+
+ Bg_Fg[0].red = Bg_Fg[0].green = Bg_Fg[0].blue = 0x00;
+ Bg_Fg[1].red = Bg_Fg[1].green = Bg_Fg[1].blue = 0xff;
+ ims332_cursor_color( xcfb->ims332, Bg_Fg);
+}
+
+/*
+ * Large viz small cursor
+ */
+xcfb_small_cursor_to_large(up, cursor)
+ user_info_t *up;
+ cursor_sprite_t cursor;
+{
+ unsigned short new_cursor[32];
+ unsigned char *cursor_bytes;
+ char *sprite;
+ register int i;
+
+ /* Clear out old cursor */
+ bzero( up->dev_dep_2.pm.cursor_sprite,
+ sizeof(up->dev_dep_2.pm.cursor_sprite));
+
+ /* small cursor is 32x2 bytes, fg first */
+ cursor_bytes = (unsigned char *) cursor;
+
+ /* use the upper left corner of the large cursor
+ * as a 64x1 cursor, fg&bg alternated */
+ for (i = 0; i < 32; i++) {
+ register short nc = 0;
+ register unsigned char fg, bg;
+ register int j, k;
+
+ fg = cursor_bytes[i];
+ bg = cursor_bytes[i + 32];
+ bg &= ~fg;
+ for (j = 1, k = 0; j < 256; j <<= 1) {
+ nc |= (bg & j) << (k++);
+ nc |= (fg & j) << (k);
+ }
+ new_cursor[i] = nc;
+ }
+
+ /* Now stick it in the proper place */
+
+ cursor_bytes = (unsigned char *) new_cursor;
+ sprite = up->dev_dep_2.pm.cursor_sprite;
+ for (i = 0; i < 64; i += 4) {
+ *sprite++ = cursor_bytes[i + 0];
+ *sprite++ = cursor_bytes[i + 1];
+ *sprite++ = cursor_bytes[i + 2];
+ *sprite++ = cursor_bytes[i + 3];
+ sprite += 12; /* skip rest of the line */
+ }
+}
+
+
+/*
+ * Device-specific set status
+ */
+xcfb_set_status(sc, flavor, status, status_count)
+ screen_softc_t sc;
+ int flavor;
+ dev_status_t status;
+ unsigned int status_count;
+{
+ xcfb_softc_t *xcfb = (xcfb_softc_t*) sc->hw_state;
+
+ switch (flavor) {
+
+ case SCREEN_ADJ_MAPPED_INFO:
+ return pm_set_status(sc, flavor, status, status_count);
+
+ case SCREEN_LOAD_CURSOR:
+
+ if (status_count < sizeof(cursor_sprite_t)/sizeof(int))
+ return D_INVALID_SIZE;
+
+ xcfb_small_cursor_to_large(sc->up, (cursor_sprite_t*) status);
+
+ /* Fall through */
+
+ case SCREEN_LOAD_CURSOR_LONG: /* 3max only */
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ ims332_cursor_sprite(xcfb->ims332, sc->up->dev_dep_2.pm.cursor_sprite);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+
+ case SCREEN_SET_CURSOR_COLOR: {
+ color_map_t c[2];
+ register cursor_color_t *cc = (cursor_color_t*) status;
+
+ c[0].red = cc->Bg_rgb[0];
+ c[0].green = cc->Bg_rgb[1];
+ c[0].blue = cc->Bg_rgb[2];
+ c[1].red = cc->Fg_rgb[0];
+ c[1].green = cc->Fg_rgb[1];
+ c[1].blue = cc->Fg_rgb[2];
+
+ sc->flags |= SCREEN_BEING_UPDATED;
+ ims332_cursor_color (xcfb->ims332, c );
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+
+ break;
+ }
+
+ case SCREEN_SET_CMAP_ENTRY: {
+ color_map_entry_t *e = (color_map_entry_t*) status;
+
+ if (e->index < 256) {
+ sc->flags |= SCREEN_BEING_UPDATED;
+ ims332_load_colormap_entry( xcfb->ims332, e->index, &e->value);
+ sc->flags &= ~SCREEN_BEING_UPDATED;
+ }
+ break;
+ }
+
+ default:
+ return D_INVALID_OPERATION;
+ }
+ return D_SUCCESS;
+}
+
+/*
+ * Hardware initialization
+ */
+xcfb_init_screen(xcfb)
+ xcfb_softc_t *xcfb;
+{
+ extern xcfb_monitor_type_t xcfb_get_monitor_type();
+
+ ims332_init( xcfb->ims332, xcfb->vdac_registers, xcfb_get_monitor_type());
+}
+
+/*
+ * Do what's needed when X exits
+ */
+xcfb_soft_reset(sc)
+ screen_softc_t sc;
+{
+ xcfb_softc_t *xcfb = (xcfb_softc_t*) sc->hw_state;
+ user_info_t *up = sc->up;
+ extern cursor_sprite_t dc503_default_cursor;
+
+ /*
+ * Restore params in mapped structure
+ */
+ pm_init_screen_params(sc,up);
+ up->row = up->max_row - 1;
+
+ up->dev_dep_2.pm.x26 = 2; /* you do not want to know */
+ up->dev_dep_1.pm.x18 = (short*)2;
+
+ /*
+ * Restore RAMDAC chip to default state
+ */
+ xcfb_init_screen(xcfb);
+
+ /*
+ * Load kernel's cursor sprite: just use the same pmax one
+ */
+ xcfb_small_cursor_to_large(up, dc503_default_cursor);
+ ims332_cursor_sprite(xcfb->ims332, up->dev_dep_2.pm.cursor_sprite);
+
+ /*
+ * Color map and cursor color
+ */
+ xcfb_init_colormap(sc);
+}
+
+
+
+
+#endif (NXCFB > 0)
diff --git a/chips/xcfb_monitor.h b/chips/xcfb_monitor.h
new file mode 100644
index 00000000..50dc9c90
--- /dev/null
+++ b/chips/xcfb_monitor.h
@@ -0,0 +1,56 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992 Carnegie Mellon University
+ * Copyright (c) 1992 Helsinki University of Technology
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON AND HELSINKI UNIVERSITY OF TECHNOLOGY ALLOW FREE USE
+ * OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
+ * HELSINKI UNIVERSITY OF TECHNOLOGY DISCLAIM ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * File: xcfb_monitor.h
+ * Author: Jukka Partanen, Helsinki University of Technology 1992.
+ *
+ * A type describing the physical properties of a monitor
+ */
+
+#ifndef _XCFB_MONITOR_H_
+#define _XCFB_MONITOR_H_
+
+typedef struct xcfb_monitor_type {
+ char *name;
+ short frame_visible_width; /* pixels */
+ short frame_visible_height;
+ short frame_scanline_width;
+ short frame_height;
+ short half_sync; /* screen units (= 4 pixels) */
+ short back_porch;
+ short v_sync; /* lines */
+ short v_pre_equalize;
+ short v_post_equalize;
+ short v_blank;
+ short line_time; /* screen units */
+ short line_start;
+ short mem_init; /* some units */
+ short xfer_delay;
+} *xcfb_monitor_type_t;
+
+#endif /* _XCFB_MONITOR_H_ */