summaryrefslogtreecommitdiff
path: root/sys/arch/atari/dev
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/atari/dev
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/atari/dev')
-rw-r--r--sys/arch/atari/dev/atari5380.c840
-rw-r--r--sys/arch/atari/dev/clock.c466
-rw-r--r--sys/arch/atari/dev/clockioctl.h47
-rw-r--r--sys/arch/atari/dev/clockreg.h79
-rw-r--r--sys/arch/atari/dev/dma.c277
-rw-r--r--sys/arch/atari/dev/event.c173
-rw-r--r--sys/arch/atari/dev/event_var.h89
-rw-r--r--sys/arch/atari/dev/fd.c1202
-rw-r--r--sys/arch/atari/dev/fdreg.h93
-rw-r--r--sys/arch/atari/dev/font.h48
-rw-r--r--sys/arch/atari/dev/font_8x16.c565
-rw-r--r--sys/arch/atari/dev/font_8x8.c307
-rw-r--r--sys/arch/atari/dev/grf.c567
-rw-r--r--sys/arch/atari/dev/grfabs.c229
-rw-r--r--sys/arch/atari/dev/grfabs_fal.c424
-rw-r--r--sys/arch/atari/dev/grfabs_reg.h219
-rw-r--r--sys/arch/atari/dev/grfabs_tt.c402
-rw-r--r--sys/arch/atari/dev/grfioctl.h212
-rw-r--r--sys/arch/atari/dev/grfvar.h97
-rw-r--r--sys/arch/atari/dev/ite.c2348
-rw-r--r--sys/arch/atari/dev/ite_cc.c671
-rw-r--r--sys/arch/atari/dev/iteioctl.h83
-rw-r--r--sys/arch/atari/dev/itevar.h200
-rw-r--r--sys/arch/atari/dev/kbd.c563
-rw-r--r--sys/arch/atari/dev/kbdmap.c207
-rw-r--r--sys/arch/atari/dev/kbdmap.h144
-rw-r--r--sys/arch/atari/dev/kbdreg.h54
-rw-r--r--sys/arch/atari/dev/ms.c397
-rw-r--r--sys/arch/atari/dev/ncr5380.c1906
-rw-r--r--sys/arch/atari/dev/ncr5380reg.h258
-rw-r--r--sys/arch/atari/dev/ramd.c481
-rw-r--r--sys/arch/atari/dev/view.c420
-rw-r--r--sys/arch/atari/dev/viewioctl.h57
-rw-r--r--sys/arch/atari/dev/viewvar.h63
-rw-r--r--sys/arch/atari/dev/vuid_event.h87
-rw-r--r--sys/arch/atari/dev/zs.c1214
-rw-r--r--sys/arch/atari/dev/zsvar.h147
37 files changed, 15636 insertions, 0 deletions
diff --git a/sys/arch/atari/dev/atari5380.c b/sys/arch/atari/dev/atari5380.c
new file mode 100644
index 00000000000..b58b7ab7a4d
--- /dev/null
+++ b/sys/arch/atari/dev/atari5380.c
@@ -0,0 +1,840 @@
+/* $NetBSD: atari5380.c,v 1.4 1995/10/05 08:52:53 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_message.h>
+#include <scsi/scsiconf.h>
+
+/*
+ * Include the driver definitions
+ */
+#include <atari/dev/ncr5380reg.h>
+
+#include <machine/stdarg.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+
+#if defined(FALCON_SCSI)
+#include <machine/dma.h>
+#endif
+
+/*
+ * This is crap, but because the interrupts now run at MFP spl-level (6),
+ * splbio() is not enough at some places. The code should be checked to
+ * find out where splhigh() is needed and where splbio() should be used.
+ * Now that I use this interrupt sceme, the spl values are fake!
+ */
+#undef splbio()
+#define splbio() splhigh()
+
+/*
+ * Set the various driver options
+ */
+#define NREQ 18 /* Size of issue queue */
+#define AUTO_SENSE 1 /* Automatically issue a request-sense */
+
+#define DRNAME ncrscsi /* used in various prints */
+#undef DBG_SEL /* Show the selection process */
+#undef DBG_REQ /* Show enqueued/ready requests */
+#undef DBG_ERR_RET /* Show requests with != 0 return code */
+#undef DBG_NOWRITE /* Do not allow writes to the targets */
+#undef DBG_PIO /* Show the polled-I/O process */
+#undef DBG_INF /* Show information transfer process */
+#define DBG_NOSTATIC /* No static functions, all in DDB trace*/
+#define DBG_PID /* Keep track of driver */
+#define REAL_DMA /* Use DMA if sensible */
+#if defined(FALCON_SCSI)
+#define REAL_DMA_POLL 1 /* 1: Poll for end of DMA-transfer */
+#else
+#define REAL_DMA_POLL 0 /* 1: Poll for end of DMA-transfer */
+#endif
+#undef USE_PDMA /* Use special pdma-transfer function */
+#define MIN_PHYS 65536 /*BARF!!!!*/
+
+/*
+ * The atari specific driver options
+ */
+#undef NO_TTRAM_DMA /* Do not use DMA to TT-ram. This */
+ /* fails on older atari's */
+#define ENABLE_NCR5380(sc) cur_softc = sc;
+
+/*
+ * Functions that do nothing on the atari
+ */
+#define pdma_ready() 0
+
+#if defined(TT_SCSI)
+/*
+ * Define all the things we need of the DMA-controller
+ */
+#define SCSI_DMA ((struct scsi_dma *)AD_SCSI_DMA)
+#define SCSI_5380 ((struct scsi_5380 *)AD_NCR5380)
+
+struct scsi_dma {
+ volatile u_char s_dma_ptr[8]; /* use only the odd bytes */
+ volatile u_char s_dma_cnt[8]; /* use only the odd bytes */
+ volatile u_char s_dma_res[4]; /* data residue register */
+ volatile u_char s_dma_gap; /* not used */
+ volatile u_char s_dma_ctrl; /* control register */
+};
+
+#define set_scsi_dma(addr, val) (void)( \
+ { \
+ u_char *address = (u_char*)addr+1; \
+ u_long nval = (u_long)val; \
+ __asm("movepl %0, %1@(0)": :"d" (nval), "a" (address)); \
+ })
+
+#define get_scsi_dma(addr, res) ( \
+ { \
+ u_char *address = (u_char*)addr+1; \
+ u_long nval; \
+ __asm("movepl %1@(0), %0": "=d" (nval) : "a" (address)); \
+ res = (u_long)nval; \
+ })
+
+/*
+ * Defines for TT-DMA control register
+ */
+#define SD_BUSERR 0x80 /* 1 = transfer caused bus error*/
+#define SD_ZERO 0x40 /* 1 = byte counter is zero */
+#define SD_ENABLE 0x02 /* 1 = Enable DMA */
+#define SD_OUT 0x01 /* Direction: memory to SCSI */
+#define SD_IN 0x00 /* Direction: SCSI to memory */
+
+/*
+ * Define the 5380 register set
+ */
+struct scsi_5380 {
+ volatile u_char scsi_5380[16]; /* use only the odd bytes */
+};
+#endif /* TT_SCSI */
+
+/**********************************************
+ * Variables present for both TT and Falcon. *
+ **********************************************/
+
+/*
+ * Softc of currently active controller (a bit of fake; we only have one)
+ */
+static struct ncr_softc *cur_softc;
+
+#if defined(TT_SCSI) && !defined(FALCON_SCSI)
+/*
+ * We can be more efficient for some functions when only TT_SCSI is selected
+ */
+#define GET_5380_REG(rnum) SCSI_5380->scsi_5380[(rnum << 1) | 1]
+#define SET_5380_REG(rnum,val) (SCSI_5380->scsi_5380[(rnum << 1) | 1] = val)
+
+#define scsi_mach_init(sc) scsi_tt_init(sc)
+#define scsi_ienable() scsi_tt_ienable()
+#define scsi_idisable() scsi_tt_idisable()
+#define scsi_clr_ipend() scsi_tt_clr_ipend()
+#define scsi_dma_setup(r,p,m) scsi_tt_dmasetup(r, p, m)
+#define wrong_dma_range(r,d) tt_wrong_dma_range(r, d)
+#define poll_edma(reqp) tt_poll_edma(reqp)
+#define get_dma_result(r, b) tt_get_dma_result(r, b)
+
+#define fair_to_keep_dma() 1
+#define claimed_dma() 1
+#define reconsider_dma()
+
+#endif /* defined(TT_SCSI) && !defined(FALCON_SCSI) */
+
+#if defined(TT_SCSI)
+
+/*
+ * Define these too, so we can use them locally...
+ */
+#define GET_TT_REG(rnum) SCSI_5380->scsi_5380[(rnum << 1) | 1]
+#define SET_TT_REG(rnum,val) (SCSI_5380->scsi_5380[(rnum << 1) | 1] = val)
+
+#ifdef NO_TTRAM_DMA
+static int tt_wrong_dma_range(reqp, dm)
+SC_REQ *reqp;
+struct dma_chain *dm;
+{
+ if (dm->dm_addr & 0xff000000) {
+ reqp->dr_flag |= DRIVER_BOUNCING;
+ return(1);
+ }
+ return(0);
+}
+#else
+#define tt_wrong_dma_range(reqp, dm) 0
+#endif
+
+static void scsi_tt_init(sc)
+struct ncr_softc *sc;
+{
+ /*
+ * Enable SCSI-related interrupts
+ */
+ MFP2->mf_aer |= 0x80; /* SCSI IRQ goes HIGH!!!!! */
+
+ MFP2->mf_ierb |= IB_SCDM; /* SCSI-dma interrupts */
+ MFP2->mf_iprb &= ~IB_SCDM;
+ MFP2->mf_imrb |= IB_SCDM;
+
+ MFP2->mf_iera |= IA_SCSI; /* SCSI-5380 interrupts */
+ MFP2->mf_ipra &= ~IA_SCSI;
+ MFP2->mf_imra |= IA_SCSI;
+
+ /*
+ * LWP: DMA transfers to TT-ram causes data to be garbeled
+ * without notice on some revisons of the TT-mainboard.
+ * When program's generate misterious Segmentations faults,
+ * try turning on NO_TTRAM_DMA.
+ */
+#ifdef NO_TTRAM_DMA
+ printf(": DMA to TT-RAM is disabled!");
+#endif
+}
+
+static u_char get_tt_5380_reg(rnum)
+u_short rnum;
+{
+ return(SCSI_5380->scsi_5380[(rnum << 1) | 1]);
+}
+
+static void set_tt_5380_reg(rnum, val)
+u_short rnum, val;
+{
+ SCSI_5380->scsi_5380[(rnum << 1) | 1] = val;
+}
+
+extern __inline__ void scsi_tt_ienable()
+{
+ int sps = splbio();
+ MFP2->mf_ierb |= IB_SCDM;
+ MFP2->mf_iera |= IA_SCSI;
+ splx(sps);
+}
+
+extern __inline__ scsi_tt_idisable()
+{
+ int sps = splbio();
+ MFP2->mf_ierb &= ~IB_SCDM;
+ MFP2->mf_iera &= ~IA_SCSI;
+ splx(sps);
+}
+
+extern __inline__ scsi_tt_clr_ipend()
+{
+ int tmp;
+
+ SCSI_DMA->s_dma_ctrl = 0;
+ tmp = GET_TT_REG(NCR5380_IRCV);
+}
+
+static void scsi_tt_dmasetup(reqp, phase, mode)
+SC_REQ *reqp;
+u_int phase;
+u_char mode;
+{
+ if (PH_IN(phase)) {
+ SCSI_DMA->s_dma_ctrl = SD_IN;
+ set_scsi_dma(&(SCSI_DMA->s_dma_ptr), reqp->dm_cur->dm_addr);
+ set_scsi_dma(&(SCSI_DMA->s_dma_cnt), reqp->dm_cur->dm_count);
+ SET_TT_REG(NCR5380_ICOM, 0);
+ SET_TT_REG(NCR5380_MODE, mode);
+ SCSI_DMA->s_dma_ctrl = SD_ENABLE;
+ SET_TT_REG(NCR5380_IRCV, 0);
+ }
+ else {
+ SCSI_DMA->s_dma_ctrl = SD_OUT;
+ set_scsi_dma(&(SCSI_DMA->s_dma_ptr), reqp->dm_cur->dm_addr);
+ set_scsi_dma(&(SCSI_DMA->s_dma_cnt), reqp->dm_cur->dm_count);
+ SET_TT_REG(NCR5380_MODE, mode);
+ SET_TT_REG(NCR5380_ICOM, SC_ADTB);
+ SET_TT_REG(NCR5380_DMSTAT, 0);
+ SCSI_DMA->s_dma_ctrl = SD_ENABLE|SD_OUT;
+ }
+}
+
+static int
+tt_poll_edma(reqp)
+SC_REQ *reqp;
+{
+ u_char dmstat, dmastat;
+ int timeout = 9000; /* XXX */
+
+ /*
+ * We wait here until the DMA has finished. This can be
+ * achieved by checking the following conditions:
+ * - 5380:
+ * - End of DMA flag is set
+ * - We lost BSY (error!!)
+ * - A phase mismatch has occured (partial transfer)
+ * - DMA-controller:
+ * - A bus error occurred (Kernel error!!)
+ * - All bytes are transferred
+ * If one of the terminating conditions was met, we call
+ * 'dma_ready' to check errors and perform the bookkeeping.
+ */
+
+ for (;;) {
+ delay(20);
+ if (--timeout <= 0) {
+ ncr_tprint(reqp, "timeout on polled transfer\n");
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ return(0);
+ }
+ dmstat = GET_TT_REG(NCR5380_DMSTAT);
+ dmastat = SCSI_DMA->s_dma_ctrl;
+ if (dmstat & (SC_END_DMA|SC_BSY_ERR|SC_IRQ_SET))
+ break;
+ if (!(dmstat & SC_PHS_MTCH))
+ break;
+ if (dmastat & (SD_BUSERR|SD_ZERO))
+ break;
+ }
+ return(1);
+}
+
+/*
+ * Convert physical DMA address to a virtual address.
+ */
+static u_char *
+ptov(reqp, phaddr)
+SC_REQ *reqp;
+u_long *phaddr;
+{
+ struct dma_chain *dm;
+ u_char *vaddr;
+
+ dm = reqp->dm_chain;
+ vaddr = reqp->xdata_ptr;
+ for(; dm < reqp->dm_cur; dm++)
+ vaddr += dm->dm_count;
+ vaddr += (u_long)phaddr - dm->dm_addr;
+ return(vaddr);
+}
+
+static int
+tt_get_dma_result(reqp, bytes_left)
+SC_REQ *reqp;
+u_long *bytes_left;
+{
+ int dmastat, dmstat;
+ u_char *byte_p;
+ u_long leftover;
+
+ dmastat = SCSI_DMA->s_dma_ctrl;
+ dmstat = GET_TT_REG(NCR5380_DMSTAT);
+ get_scsi_dma(SCSI_DMA->s_dma_cnt, leftover);
+ get_scsi_dma(SCSI_DMA->s_dma_ptr, (u_long)byte_p);
+
+ if (dmastat & SD_BUSERR) {
+ /*
+ * The DMA-controller seems to access 8 bytes beyond
+ * it's limits on output. Therefore check also the byte
+ * count. If it's zero, ignore the bus error.
+ */
+ if (leftover != 0) {
+ ncr_tprint(reqp,
+ "SCSI-DMA buserror - accessing 0x%x\n", byte_p);
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ }
+ }
+
+ /*
+ * We handle the following special condition below:
+ * -- The device disconnects in the middle of a write operation --
+ * In this case, the 5380 has already pre-fetched the next byte from
+ * the DMA-controller before the phase mismatch occurs. Therefore,
+ * leftover is 1 too low.
+ * This does not always happen! Therefore, we only do this when
+ * leftover is odd. This assumes that DMA transfers are _even_! This
+ * is normally the case on disks and types but might not always be.
+ * XXX: Check if ACK is consistently high on these occasions LWP
+ */
+ if ((leftover & 1) && !(dmstat & SC_PHS_MTCH) && PH_OUT(reqp->phase))
+ leftover++;
+
+ /*
+ * Check if there are some 'restbytes' left in the DMA-controller.
+ */
+ if (((u_long)byte_p & 3) && PH_IN(reqp->phase)) {
+ u_char *p, *q;
+
+ p = ptov(reqp, (u_long)byte_p & ~3);
+ q = (u_char*)&(SCSI_DMA->s_dma_res);
+ switch ((u_long)byte_p & 3) {
+ case 3: *p++ = *q++;
+ case 2: *p++ = *q++;
+ case 1: *p++ = *q++;
+ }
+ }
+ *bytes_left = leftover;
+ return ((dmastat & (SD_BUSERR|SD_ZERO)) ? 1 : 0);
+}
+
+#endif /* defined(TT_SCSI) */
+
+#if defined(FALCON_SCSI) && !defined(TT_SCSI)
+
+#define GET_5380_REG(rnum) get_falcon_5380_reg(rnum)
+#define SET_5380_REG(rnum,val) set_falcon_5380_reg(rnum, val)
+#define scsi_mach_init(sc) scsi_falcon_init(sc)
+#define scsi_ienable() scsi_falcon_ienable()
+#define scsi_idisable() scsi_falcon_idisable()
+#define scsi_clr_ipend() scsi_falcon_clr_ipend()
+#define scsi_dma_setup(r,p,m) scsi_falcon_dmasetup(r, p, m)
+#define wrong_dma_range(r,d) falcon_wrong_dma_range(r, d)
+#define poll_edma(reqp) falcon_poll_edma(reqp)
+#define get_dma_result(r, b) falcon_get_dma_result(r, b)
+
+#define fair_to_keep_dma() (!st_dmawanted())
+#define claimed_dma() falcon_claimed_dma()
+#define reconsider_dma() falcon_reconsider_dma()
+
+#endif /* defined(FALCON_SCSI) && !defined(TT_SCSI) */
+
+#if defined(FALCON_SCSI)
+
+static void fscsi_int __P((void));
+
+static void scsi_falcon_init(sc)
+struct ncr_softc *sc;
+{
+ /*
+ * Enable disk related interrupts
+ */
+ MFP->mf_ierb |= IB_DINT;
+ MFP->mf_iprb &= ~IB_DINT;
+ MFP->mf_imrb |= IB_DINT;
+}
+
+static u_char get_falcon_5380_reg(rnum)
+u_short rnum;
+{
+ DMA->dma_mode = DMA_SCSI + rnum;
+ return(DMA->dma_data);
+}
+
+static void set_falcon_5380_reg(rnum, val)
+u_short rnum, val;
+{
+ DMA->dma_mode = DMA_SCSI + rnum;
+ DMA->dma_data = val;
+}
+
+extern __inline__ void scsi_falcon_ienable()
+{
+ MFP->mf_ierb |= IB_DINT;
+}
+
+extern __inline__ scsi_falcon_idisable()
+{
+ MFP->mf_ierb &= ~IB_DINT;
+}
+
+extern __inline__ scsi_falcon_clr_ipend()
+{
+ int tmp;
+
+ tmp = get_falcon_5380_reg(NCR5380_IRCV);
+}
+
+static int falcon_wrong_dma_range(reqp, dm)
+SC_REQ *reqp;
+struct dma_chain *dm;
+{
+ /*
+ * Do not allow chains yet! See also comment with
+ * falcon_poll_edma() !!!
+ */
+ if (((dm - reqp->dm_chain) > 0) || (dm->dm_addr & 0xff000000)) {
+ reqp->dr_flag |= DRIVER_BOUNCING;
+ return(1);
+ }
+ /*
+ * Never allow DMA to happen on a Falcon when the transfer
+ * size is no multiple of 512. This is the transfer unit of the
+ * ST DMA-controller.
+ */
+ if(dm->dm_count & 511)
+ return(1);
+ return(0);
+}
+
+static int falcon_lock = 0;
+
+extern __inline__ falcon_claimed_dma()
+{
+ if (!(falcon_lock & DMA_LOCK_GRANT)) {
+ if (falcon_lock) {
+ /*
+ * DMA access is being claimed.
+ */
+ return(0);
+ }
+ if (!st_dmagrab(fscsi_int, run_main, &connected,&falcon_lock,1))
+ return(0);
+ }
+ return(1);
+}
+
+extern __inline__ void falcon_reconsider_dma()
+{
+ if (falcon_lock && (connected == NULL) && (discon_q == NULL)) {
+ /*
+ * No need to keep DMA locked by us as we are not currently
+ * connected and no disconnected jobs are pending.
+ */
+ st_dmafree(&connected, &falcon_lock);
+ }
+
+ if (!falcon_lock && (issue_q != NULL)) {
+ /*
+ * We must (re)claim DMA access as there are jobs
+ * waiting in the issue queue.
+ */
+ st_dmagrab(fscsi_int, run_main, &connected, &falcon_lock, 0);
+ }
+}
+
+static void fal1_dma(dir, nsects, reqp)
+u_int dir, nsects;
+SC_REQ *reqp;
+{
+ dir <<= 8;
+ st_dmaaddr_set((caddr_t)reqp->dm_cur->dm_addr);
+ DMA->dma_mode = 0x90 | dir;
+ DMA->dma_mode = 0x90 | (dir ^ DMA_WRBIT);
+ DMA->dma_mode = 0x90 | dir;
+ delay(40); /* XXX: LWP - is this really needed ? */
+ DMA->dma_data = nsects;
+ delay(40); /* XXX: LWP - is this really needed ? */
+ DMA->dma_mode = 0x10 | dir;
+ delay(40); /* XXX: LWP - is this really needed ? */
+}
+
+static void scsi_falcon_dmasetup(reqp, phase, mode)
+SC_REQ *reqp;
+u_int phase;
+u_char mode;
+{
+ int nsects = reqp->dm_cur->dm_count / 512; /* XXX */
+
+ /*
+ * XXX: We should probably clear the fifo before putting the
+ * 5380 into DMA-mode.
+ */
+ if (PH_IN(phase)) {
+ set_falcon_5380_reg(NCR5380_ICOM, 0);
+ set_falcon_5380_reg(NCR5380_MODE, mode);
+ set_falcon_5380_reg(NCR5380_IRCV, 0);
+ fal1_dma(0, nsects, reqp);
+ }
+ else {
+ set_falcon_5380_reg(NCR5380_MODE, mode);
+ set_falcon_5380_reg(NCR5380_ICOM, SC_ADTB);
+ set_falcon_5380_reg(NCR5380_DMSTAT, 0);
+ fal1_dma(1, nsects, reqp);
+ }
+}
+
+/*
+ * Falcon SCSI interrupt. _Always_ called at spl1!
+ */
+static void fscsi_int()
+{
+ int itype;
+ int dma_done;
+
+ if (get_falcon_5380_reg(NCR5380_DMSTAT) & SC_IRQ_SET) {
+ scsi_falcon_idisable();
+ ncr_ctrl_intr(cur_softc);
+ }
+}
+
+static int
+falcon_poll_edma(reqp)
+SC_REQ *reqp;
+{
+ int timeout = 9000; /* XXX */
+
+ /*
+ * Because of the Falcon hardware, it is impossible to reach
+ * the 5380 while doing DMA-transfers. So we have to rely on
+ * the interrupt line to determine if DMA-has finished. the
+ * DMA-controller itself will never fire an interrupt. This means
+ * that 'broken-up' DMA transfers are not (yet) possible on the
+ * Falcon.
+ */
+ for (;;) {
+ delay(20);
+ if (--timeout <= 0) {
+ ncr_tprint(reqp, "Timeout on polled transfer\n");
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ return(0);
+ }
+ if (!(MFP->mf_gpip & IO_DINT))
+ break;
+ }
+ return(1);
+}
+
+static int
+falcon_get_dma_result(reqp, bytes_left)
+SC_REQ *reqp;
+u_long *bytes_left;
+{
+ int rv = 0;
+ int st_dmastat;
+ u_long bytes_done;
+
+ /*
+ * Select sector counter register first (See Atari docu.)
+ */
+ DMA->dma_mode = 0x90;
+ if (!(st_dmastat = DMA->dma_stat) & 0x01) {
+ /*
+ * Misc. DMA-error according to Atari...
+ */
+ ncr_tprint(reqp, "Unknow ST-SCSI error near 0x%x\n",
+ st_dmaaddr_get());
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ rv = 1;
+ }
+ if (st_dmastat & 0x02) {
+ /*
+ * Bytecount not zero.... As the fifo loads in 16 byte
+ * chunks, check if bytes are stuck in fifo.
+ * As we don't use DMA on chunks less than 512 bytes
+ * on the Falcon, report any residual not a multiple of
+ * 512 as an error...
+ */
+ bytes_done = st_dmaaddr_get() - reqp->dm_cur->dm_addr;
+ if (bytes_done & 511) {
+ ncr_tprint(reqp, "Some bytes stuck in fifo\n");
+ bytes_done &= ~511;
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ }
+ *bytes_left = reqp->dm_cur->dm_count - bytes_done;
+ }
+ else {
+ *bytes_left = 0;
+ rv = 1;
+ }
+ return(rv);
+}
+
+#endif /* defined(FALCON_SCSI) */
+
+#if defined(TT_SCSI) && defined(FALCON_SCSI)
+/*
+ * Define some functions to support _both_ TT and Falcon SCSI
+ */
+
+/*
+ * Register access will be done through the following 2 function pointers.
+ */
+static u_char (*get_5380_reg)();
+static void (*set_5380_reg)();
+
+#define GET_5380_REG (*get_5380_reg)
+#define SET_5380_REG (*set_5380_reg)
+
+static void scsi_mach_init(sc)
+struct ncr_softc *sc;
+{
+ if (machineid & ATARI_FALCON) {
+ get_5380_reg = get_falcon_5380_reg;
+ set_5380_reg = set_falcon_5380_reg;
+ scsi_falcon_init(sc);
+ }
+ else {
+ get_5380_reg = get_tt_5380_reg;
+ set_5380_reg = set_tt_5380_reg;
+ scsi_tt_init(sc);
+ }
+}
+
+extern __inline__ void scsi_ienable()
+{
+ if (machineid & ATARI_FALCON)
+ scsi_falcon_ienable();
+ else scsi_tt_ienable();
+}
+
+extern __inline__ void scsi_idisable()
+{
+ if (machineid & ATARI_FALCON)
+ scsi_falcon_idisable();
+ else scsi_tt_idisable();
+}
+
+extern __inline__ scsi_clr_ipend()
+{
+ if (machineid & ATARI_FALCON)
+ scsi_falcon_clr_ipend();
+ else scsi_tt_clr_ipend();
+}
+
+extern __inline__ scsi_dma_setup(reqp, phase, mbase)
+SC_REQ *reqp;
+u_int phase;
+u_char mbase;
+{
+ if (machineid & ATARI_FALCON)
+ scsi_falcon_dmasetup(reqp, phase, mbase);
+ else scsi_tt_dmasetup(reqp, phase, mbase);
+}
+
+extern __inline__ int wrong_dma_range(reqp, dm)
+SC_REQ *reqp;
+struct dma_chain *dm;
+{
+ if (machineid & ATARI_FALCON)
+ return(falcon_wrong_dma_range(reqp, dm));
+ else return(tt_wrong_dma_range(reqp, dm));
+}
+
+extern __inline__ int poll_edma(reqp)
+SC_REQ *reqp;
+{
+ if (machineid & ATARI_FALCON)
+ return(falcon_poll_edma(reqp));
+ else return(tt_poll_edma(reqp));
+}
+
+extern __inline__ int get_dma_result(reqp, bytes_left)
+SC_REQ *reqp;
+u_long *bytes_left;
+{
+ if (machineid & ATARI_FALCON)
+ return(falcon_get_dma_result(reqp, bytes_left));
+ else return(tt_get_dma_result(reqp, bytes_left));
+}
+
+/*
+ * Locking stuff. All turns into NOP's on the TT.
+ */
+#define fair_to_keep_dma() ((machineid & ATARI_FALCON) ? \
+ !st_dmawanted() : 1)
+#define claimed_dma() ((machineid & ATARI_FALCON) ? \
+ falcon_claimed_dma() : 1)
+#define reconsider_dma() { \
+ if(machineid & ATARI_FALCON) \
+ falcon_reconsider_dma();\
+ }
+#endif /* defined(TT_SCSI) && defined(FALCON_SCSI) */
+
+/**********************************************
+ * Functions present for both TT and Falcon. *
+ **********************************************/
+/*
+ * Our autoconfig matching function
+ */
+static int
+machine_match(pdp, cdp, auxp, cd)
+struct device *pdp;
+struct cfdata *cdp;
+void *auxp;
+struct cfdriver *cd;
+{
+ if (strcmp(auxp, cd->cd_name))
+ return(0);
+ if (cdp->cf_unit != 0) /* Only one unit */
+ return(0);
+ return(1);
+}
+
+/*
+ * Bounce buffer (de)allocation. Those buffers are gotten from the ST-mem
+ * pool. Allocation here is both contiguous and in the lower 16Mb of
+ * the address space. Thus being DMA-able for all controllers.
+ */
+static u_char *
+alloc_bounceb(len)
+u_long len;
+{
+ u_long tmp;
+
+ return((u_char *)alloc_stmem(len, &tmp));
+}
+
+static void
+free_bounceb(bounceb)
+u_char *bounceb;
+{
+ free_stmem(bounceb);
+}
+
+/*
+ * 5380 interrupt.
+ */
+scsi_ctrl(sr)
+int sr; /* sr at time of interrupt */
+{
+ if (GET_5380_REG(NCR5380_DMSTAT) & SC_IRQ_SET) {
+ scsi_idisable();
+ if (!BASEPRI(sr))
+ add_sicallback(ncr_ctrl_intr, cur_softc, 0);
+ else {
+ spl1();
+ ncr_ctrl_intr(cur_softc);
+ }
+ }
+}
+
+/*
+ * DMA controller interrupt
+ */
+scsi_dma(sr)
+int sr; /* sr at time of interrupt */
+{
+ SC_REQ *reqp;
+
+ if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)) {
+ scsi_idisable();
+ if (!BASEPRI(sr))
+ add_sicallback(ncr_dma_intr, cur_softc, 0);
+ else {
+ spl1();
+ ncr_dma_intr(cur_softc);
+ }
+ }
+}
+
+/*
+ * Last but not least... Include the general driver code
+ */
+#include "atari/dev/ncr5380.c"
diff --git a/sys/arch/atari/dev/clock.c b/sys/arch/atari/dev/clock.c
new file mode 100644
index 00000000000..c1471e4dc8d
--- /dev/null
+++ b/sys/arch/atari/dev/clock.c
@@ -0,0 +1,466 @@
+/* $NetBSD: clock.c,v 1.4 1995/09/23 20:23:28 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: clock.c 1.18 91/01/21$
+ *
+ * @(#)clock.c 7.6 (Berkeley) 5/7/91
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <machine/psl.h>
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <atari/dev/clockreg.h>
+
+#if defined(GPROF) && defined(PROFTIMER)
+#include <machine/profile.h>
+#endif
+
+/*
+ * Machine-dependent clock routines.
+ *
+ * Startrtclock restarts the real-time clock, which provides
+ * hardclock interrupts to kern_clock.c.
+ *
+ * Inittodr initializes the time of day hardware which provides
+ * date functions.
+ *
+ * Resettodr restores the time of day hardware after a time change.
+ *
+ * A note on the real-time clock:
+ * We actually load the clock with CLK_INTERVAL-1 instead of CLK_INTERVAL.
+ * This is because the counter decrements to zero after N+1 enabled clock
+ * periods where N is the value loaded into the counter.
+ */
+
+int clockmatch __P((struct device *, struct cfdata *, void *));
+void clockattach __P((struct device *, struct device *, void *));
+
+struct cfdriver clockcd = {
+ NULL, "clock", (cfmatch_t)clockmatch, clockattach,
+ DV_DULL, sizeof(struct device), NULL, 0
+};
+
+static u_long gettod __P((void));
+static int settod __P((u_long));
+
+static int divisor;
+
+int
+clockmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(!strcmp("clock", auxp))
+ return(1);
+ return(0);
+}
+
+/*
+ * Start the real-time clock.
+ */
+void clockattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ /*
+ * Initialize Timer-A in the ST-MFP. We use a divisor of 200.
+ * The MFP clock runs at 2457600Hz. Therefore the timer runs
+ * at an effective rate of: 2457600/200 = 12288Hz. The
+ * following expression works for 48, 64 or 96 hz.
+ */
+ divisor = 12288/hz;
+ MFP->mf_tacr = 0; /* Stop timer */
+ MFP->mf_iera &= ~IA_TIMA; /* Disable timer interrupts */
+ MFP->mf_tadr = divisor; /* Set divisor */
+
+ printf(": system hz %d timer-A divisor 200/%d\n", hz, divisor);
+
+ /*
+ * Initialize Timer-B in the ST-MFP. This timer is used by the 'delay'
+ * function below. This time is setup to be continueously counting from
+ * 255 back to zero at a frequency of 614400Hz.
+ */
+ MFP->mf_tbcr = 0; /* Stop timer */
+ MFP->mf_iera &= ~IA_TIMB; /* Disable timer interrupts */
+ MFP->mf_tbdr = 0;
+ MFP->mf_tbcr = T_Q004; /* Start timer */
+
+}
+
+void cpu_initclocks()
+{
+ MFP->mf_tacr = T_Q200; /* Start timer */
+ MFP->mf_ipra &= ~IA_TIMA; /* Clear pending interrupts */
+ MFP->mf_iera |= IA_TIMA; /* Enable timer interrupts */
+ MFP->mf_imra |= IA_TIMA; /* ..... */
+}
+
+setstatclockrate(hz)
+ int hz;
+{
+}
+
+/*
+ * Returns number of usec since last recorded clock "tick"
+ * (i.e. clock interrupt).
+ */
+clkread()
+{
+ u_int delta;
+
+ delta = ((divisor - MFP->mf_tadr) * tick) / divisor;
+ /*
+ * Account for pending clock interrupts
+ */
+ if(MFP->mf_iera & IA_TIMA)
+ return(delta + tick);
+ return(delta);
+}
+
+#define TIMB_FREQ 614400
+#define TIMB_LIMIT 256
+
+/*
+ * Wait "n" microseconds.
+ * Relies on MFP-Timer B counting down from TIMB_LIMIT at TIMB_FREQ Hz.
+ * Note: timer had better have been programmed before this is first used!
+ */
+void delay(n)
+int n;
+{
+ int tick, otick;
+
+ /*
+ * Read the counter first, so that the rest of the setup overhead is
+ * counted.
+ */
+ otick = MFP->mf_tbdr;
+
+ /*
+ * Calculate ((n * TIMER_FREQ) / 1e6) using explicit assembler code so
+ * we can take advantage of the intermediate 64-bit quantity to prevent
+ * loss of significance.
+ */
+ n -= 5;
+ if(n < 0)
+ return;
+ {
+ u_int temp;
+
+ __asm __volatile ("mulul %2,%1:%0" : "=d" (n), "=d" (temp)
+ : "d" (TIMB_FREQ));
+ __asm __volatile ("divul %1,%2:%0" : "=d" (n)
+ : "d"(1000000),"d"(temp),"0"(n));
+ }
+
+ while(n > 0) {
+ tick = MFP->mf_tbdr;
+ if(tick > otick)
+ n -= TIMB_LIMIT - (tick - otick);
+ else n -= otick - tick;
+ otick = tick;
+ }
+}
+
+#ifdef PROFTIMER
+/*
+ * This code allows the amiga kernel to use one of the extra timers on
+ * the clock chip for profiling, instead of the regular system timer.
+ * The advantage of this is that the profiling timer can be turned up to
+ * a higher interrupt rate, giving finer resolution timing. The profclock
+ * routine is called from the lev6intr in locore, and is a specialized
+ * routine that calls addupc. The overhead then is far less than if
+ * hardclock/softclock was called. Further, the context switch code in
+ * locore has been changed to turn the profile clock on/off when switching
+ * into/out of a process that is profiling (startprofclock/stopprofclock).
+ * This reduces the impact of the profiling clock on other users, and might
+ * possibly increase the accuracy of the profiling.
+ */
+int profint = PRF_INTERVAL; /* Clock ticks between interrupts */
+int profscale = 0; /* Scale factor from sys clock to prof clock */
+char profon = 0; /* Is profiling clock on? */
+
+/* profon values - do not change, locore.s assumes these values */
+#define PRF_NONE 0x00
+#define PRF_USER 0x01
+#define PRF_KERNEL 0x80
+
+initprofclock()
+{
+#if NCLOCK > 0
+ struct proc *p = curproc; /* XXX */
+
+ /*
+ * If the high-res timer is running, force profiling off.
+ * Unfortunately, this gets reflected back to the user not as
+ * an error but as a lack of results.
+ */
+ if (clockon) {
+ p->p_stats->p_prof.pr_scale = 0;
+ return;
+ }
+ /*
+ * Keep track of the number of user processes that are profiling
+ * by checking the scale value.
+ *
+ * XXX: this all assumes that the profiling code is well behaved;
+ * i.e. profil() is called once per process with pcscale non-zero
+ * to turn it on, and once with pcscale zero to turn it off.
+ * Also assumes you don't do any forks or execs. Oh well, there
+ * is always adb...
+ */
+ if (p->p_stats->p_prof.pr_scale)
+ profprocs++;
+ else
+ profprocs--;
+#endif
+ /*
+ * The profile interrupt interval must be an even divisor
+ * of the CLK_INTERVAL so that scaling from a system clock
+ * tick to a profile clock tick is possible using integer math.
+ */
+ if (profint > CLK_INTERVAL || (CLK_INTERVAL % profint) != 0)
+ profint = CLK_INTERVAL;
+ profscale = CLK_INTERVAL / profint;
+}
+
+startprofclock()
+{
+ unsigned short interval;
+
+ /* stop timer B */
+ ciab.crb = ciab.crb & 0xc0;
+
+ /* load interval into registers.
+ the clocks run at NTSC: 715.909kHz or PAL: 709.379kHz */
+
+ interval = profint - 1;
+
+ /* order of setting is important ! */
+ ciab.tblo = interval & 0xff;
+ ciab.tbhi = interval >> 8;
+
+ /* enable interrupts for timer B */
+ ciab.icr = (1<<7) | (1<<1);
+
+ /* start timer B in continuous shot mode */
+ ciab.crb = (ciab.crb & 0xc0) | 1;
+}
+
+stopprofclock()
+{
+ /* stop timer B */
+ ciab.crb = ciab.crb & 0xc0;
+}
+
+#ifdef GPROF
+/*
+ * profclock() is expanded in line in lev6intr() unless profiling kernel.
+ * Assumes it is called with clock interrupts blocked.
+ */
+profclock(pc, ps)
+ caddr_t pc;
+ int ps;
+{
+ /*
+ * Came from user mode.
+ * If this process is being profiled record the tick.
+ */
+ if (USERMODE(ps)) {
+ if (p->p_stats.p_prof.pr_scale)
+ addupc(pc, &curproc->p_stats.p_prof, 1);
+ }
+ /*
+ * Came from kernel (supervisor) mode.
+ * If we are profiling the kernel, record the tick.
+ */
+ else if (profiling < 2) {
+ register int s = pc - s_lowpc;
+
+ if (s < s_textsize)
+ kcount[s / (HISTFRACTION * sizeof (*kcount))]++;
+ }
+ /*
+ * Kernel profiling was on but has been disabled.
+ * Mark as no longer profiling kernel and if all profiling done,
+ * disable the clock.
+ */
+ if (profiling && (profon & PRF_KERNEL)) {
+ profon &= ~PRF_KERNEL;
+ if (profon == PRF_NONE)
+ stopprofclock();
+ }
+}
+#endif
+#endif
+
+/*
+ * Initialize the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+inittodr(base)
+time_t base;
+{
+ u_long timbuf = base; /* assume no battery clock exists */
+
+ timbuf = gettod();
+
+ if(timbuf < base) {
+ printf("WARNING: bad date in battery clock\n");
+ timbuf = base;
+ }
+
+ /* Battery clock does not store usec's, so forget about it. */
+ time.tv_sec = timbuf;
+}
+
+resettodr()
+{
+ if(settod(time.tv_sec) == 1)
+ return;
+ printf("Cannot set battery backed clock\n");
+}
+
+static char dmsize[12] =
+{
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static char ldmsize[12] =
+{
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static u_long
+gettod()
+{
+ int i, sps;
+ u_long new_time = 0;
+ char *msize;
+ mc_todregs clkregs;
+
+ sps = splhigh();
+ MC146818_GETTOD(RTC, &clkregs);
+ splx(sps);
+
+ if(range_test(clkregs[MC_HOUR], 0, 23))
+ return(0);
+ if(range_test(clkregs[MC_DOM], 1, 31))
+ return(0);
+ if (range_test(clkregs[MC_MONTH], 1, 12))
+ return(0);
+ if(range_test(clkregs[MC_YEAR], 0, 2000 - GEMSTARTOFTIME))
+ return(0);
+ clkregs[MC_YEAR] += GEMSTARTOFTIME;
+
+ for(i = BSDSTARTOFTIME; i < clkregs[MC_YEAR]; i++) {
+ if(is_leap(i))
+ new_time += 366;
+ else new_time += 365;
+ }
+
+ msize = is_leap(clkregs[MC_YEAR]) ? ldmsize : dmsize;
+ for(i = 0; i < (clkregs[MC_MONTH] - 1); i++)
+ new_time += msize[i];
+ new_time += clkregs[MC_DOM] - 1;
+ new_time *= SECS_DAY;
+ new_time += (clkregs[MC_HOUR] * 3600) + (clkregs[MC_MIN] * 60);
+ return(new_time + clkregs[MC_SEC]);
+}
+
+static int
+settod(newtime)
+u_long newtime;
+{
+ register long days, rem, year;
+ register char *ml;
+ int sps, sec, min, hour, month;
+ mc_todregs clkregs;
+
+ /* Number of days since Jan. 1 'BSDSTARTOFTIME' */
+ days = newtime / SECS_DAY;
+ rem = newtime % SECS_DAY;
+
+ /*
+ * Calculate sec, min, hour
+ */
+ hour = rem / SECS_HOUR;
+ rem %= SECS_HOUR;
+ min = rem / 60;
+ sec = rem % 60;
+
+ /*
+ * Figure out the year. Day in year is left in 'days'.
+ */
+ year = BSDSTARTOFTIME;
+ while(days >= (rem = is_leap(year) ? 366 : 365)) {
+ ++year;
+ days -= rem;
+ }
+
+ /*
+ * Determine the month
+ */
+ ml = is_leap(year) ? ldmsize : dmsize;
+ for(month = 0; days >= ml[month]; ++month)
+ days -= ml[month];
+
+ /*
+ * Now that everything is calculated, program the RTC
+ */
+ mc146818_write(RTC, MC_REGA, MC_BASE_32_KHz);
+ mc146818_write(RTC, MC_REGB, MC_REGB_24HR | MC_REGB_BINARY);
+ sps = splhigh();
+ MC146818_GETTOD(RTC, &clkregs);
+ clkregs[MC_SEC] = sec;
+ clkregs[MC_MIN] = min;
+ clkregs[MC_HOUR] = hour;
+ clkregs[MC_DOM] = days+1;
+ clkregs[MC_MONTH] = month+1;
+ clkregs[MC_YEAR] = year - GEMSTARTOFTIME;
+ MC146818_PUTTOD(RTC, &clkregs);
+ splx(sps);
+
+ return(1);
+}
diff --git a/sys/arch/atari/dev/clockioctl.h b/sys/arch/atari/dev/clockioctl.h
new file mode 100644
index 00000000000..03f16574b05
--- /dev/null
+++ b/sys/arch/atari/dev/clockioctl.h
@@ -0,0 +1,47 @@
+/* $NetBSD: clockioctl.h,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1989 University of Utah.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: clockioctl.h 1.1 90/07/09$
+ *
+ * @(#)clockioctl.h 7.2 (Berkeley) 11/2/90
+ */
+
+#define CLOCKMAP _IOWR('C', 1, int)
+#define CLOCKUNMAP _IOW('C', 2, int)
+#define CLOCKGETRES _IOR('C', 3, int)
diff --git a/sys/arch/atari/dev/clockreg.h b/sys/arch/atari/dev/clockreg.h
new file mode 100644
index 00000000000..9ced9f98abb
--- /dev/null
+++ b/sys/arch/atari/dev/clockreg.h
@@ -0,0 +1,79 @@
+/* $NetBSD: clockreg.h,v 1.3 1995/06/28 04:30:40 cgd Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CLOCKREG_H
+#define _CLOCKREG_H
+/*
+ * Atari TT hardware:
+ * Motorola MC146818A RealTimeClock
+ */
+
+#define RTC ((struct rtc *)AD_RTC)
+
+struct rtc {
+ volatile u_char rtc_dat[4];
+};
+
+#define rtc_regno rtc_dat[1] /* register nr. select */
+#define rtc_data rtc_dat[3] /* data register */
+
+/*
+ * Pull in general mc146818 definitions
+ */
+#include <dev/ic/mc146818reg.h>
+
+__inline__ u_int mc146818_read(rtc, regno)
+void *rtc;
+u_int regno;
+{
+ ((struct rtc *)rtc)->rtc_regno = regno;
+ return(((struct rtc *)rtc)->rtc_data & 0377);
+}
+
+__inline__ void mc146818_write(rtc, regno, value)
+void *rtc;
+u_int regno, value;
+{
+ ((struct rtc *)rtc)->rtc_regno = regno;
+ ((struct rtc *)rtc)->rtc_data = value;
+}
+
+/*
+ * Some useful constants/macros
+ */
+#define is_leap(x) (!(x % 4) && ((x % 100) || !(x % 1000)))
+#define range_test(n, l, h) ((n) < (l) || (n) > (h))
+#define SECS_DAY 86400L
+#define SECS_HOUR 3600L
+#define GEMSTARTOFTIME ((machineid & ATARI_CLKBROKEN) ? 1970 : 1968)
+#define BSDSTARTOFTIME 1970
+#endif /* _CLOCKREG_H */
diff --git a/sys/arch/atari/dev/dma.c b/sys/arch/atari/dev/dma.c
new file mode 100644
index 00000000000..4be5f26b62a
--- /dev/null
+++ b/sys/arch/atari/dev/dma.c
@@ -0,0 +1,277 @@
+/* $NetBSD: dma.c,v 1.4 1995/05/14 15:46:17 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file contains special code dealing with the DMA interface
+ * on the Atari ST.
+ *
+ * The DMA circuitry requires some special treatment for the peripheral
+ * devices which make use of the ST's DMA feature (the hard disk and the
+ * floppy drive).
+ * All devices using DMA need mutually exclusive access and can follow some
+ * standard pattern which will be provided in this file.
+ *
+ * The file contains the following entry points:
+ *
+ * st_dmagrab: ensure exclusive access to the DMA circuitry
+ * st_dmafree: free exclusive access to the DMA circuitry
+ * st_dmawanted: somebody is queued waiting for DMA-access
+ * dmaint: DMA interrupt routine, switches to the current driver
+ * st_dmaaddr_set: specify 24 bit RAM address
+ * st_dmaaddr_get: get address of last DMA-op
+ * st_dmacomm: program DMA, flush FIFO first
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/dma.h>
+
+#define NDMA_DEV 10 /* Max 2 floppy's, 8 hard-disks */
+typedef struct dma_entry {
+ TAILQ_ENTRY(dma_entry) entries; /* List pointers */
+ void (*call_func)(); /* Call when lock granted */
+ void (*int_func)(); /* Call on DMA interrupt */
+ void *softc; /* Arg. to int_func */
+ int *lock_stat; /* status of DMA lock */
+} DMA_ENTRY;
+
+/*
+ * Preallocated entries. An allocator seem an overkill here.
+ */
+static DMA_ENTRY dmatable[NDMA_DEV]; /* preallocated entries */
+static int sched_soft = 0; /* callback scheduled */
+
+/*
+ * Heads of free and active lists:
+ */
+static TAILQ_HEAD(freehead, dma_entry) dma_free;
+static TAILQ_HEAD(acthead, dma_entry) dma_active;
+
+static int must_init = 1; /* Must initialize */
+
+static void cdmasoft __P((void));
+static void init_queues __P((void));
+
+static void init_queues()
+{
+ int i;
+
+ TAILQ_INIT(&dma_free);
+ TAILQ_INIT(&dma_active);
+
+ for(i = 0; i < NDMA_DEV; i++)
+ TAILQ_INSERT_HEAD(&dma_free, &dmatable[i], entries);
+}
+
+int st_dmagrab(int_func, call_func, softc, lock_stat, rcaller)
+void (*int_func)();
+void (*call_func)();
+void *softc;
+int *lock_stat;
+int rcaller;
+{
+ int sps;
+ DMA_ENTRY *req;
+
+ if(must_init) {
+ init_queues();
+ must_init = 0;
+ }
+ *lock_stat = DMA_LOCK_REQ;
+
+ sps = splhigh();
+
+ /*
+ * Create a request...
+ */
+ if(dma_free.tqh_first == NULL)
+ panic("st_dmagrab: Too many outstanding requests\n");
+ req = dma_free.tqh_first;
+ TAILQ_REMOVE(&dma_free, dma_free.tqh_first, entries);
+ req->call_func = call_func;
+ req->int_func = int_func;
+ req->softc = softc;
+ req->lock_stat = lock_stat;
+ TAILQ_INSERT_TAIL(&dma_active, req, entries);
+
+ if(dma_active.tqh_first != req) {
+ splx(sps);
+ return(0);
+ }
+ splx(sps);
+
+ /*
+ * We're at the head of the queue, ergo: we got the lock.
+ */
+ *lock_stat = DMA_LOCK_GRANT;
+
+ if(rcaller) {
+ /*
+ * Just return to caller immediately without going
+ * through 'call_func' first.
+ */
+ return(1);
+ }
+
+ (*call_func)(softc); /* Call followup function */
+ return(0);
+}
+
+void
+st_dmafree(softc, lock_stat)
+void *softc;
+int *lock_stat;
+{
+ int sps;
+ DMA_ENTRY *req;
+
+ sps = splhigh();
+
+ /*
+ * Some validity checks first.
+ */
+ if((req = dma_active.tqh_first) == NULL)
+ panic("st_dmafree: empty active queue\n");
+ if(req->softc != softc)
+ printf("Caller of st_dmafree is not lock-owner!\n");
+
+ /*
+ * Clear lock status, move request from active to free queue.
+ */
+ *lock_stat = 0;
+ TAILQ_REMOVE(&dma_active, req, entries);
+ TAILQ_INSERT_HEAD(&dma_free, req, entries);
+
+ if((req = dma_active.tqh_first) != NULL) {
+ /*
+ * Call next request through softint handler. This avoids
+ * spl-conflicts.
+ */
+ *req->lock_stat = DMA_LOCK_GRANT;
+ add_sicallback(req->call_func, req->softc, 0);
+ }
+ splx(sps);
+ return;
+}
+
+int
+st_dmawanted()
+{
+ return(dma_active.tqh_first->entries.tqe_next != NULL);
+}
+
+cdmaint(sr)
+long sr; /* sr at time of interrupt */
+{
+ if(dma_active.tqh_first != NULL) {
+ if(!BASEPRI(sr)) {
+ if(!sched_soft++)
+ add_sicallback(cdmasoft, 0, 0);
+ }
+ else {
+ spl1();
+ cdmasoft();
+ }
+ }
+ else printf("DMA interrupt discarded\n");
+}
+
+static void cdmasoft()
+{
+ int s;
+ void (*int_func)();
+ void *softc;
+
+ /*
+ * Prevent a race condition here. DMA might be freed while
+ * the callback was pending!
+ */
+ s = splhigh();
+ sched_soft = 0;
+ if(dma_active.tqh_first != NULL) {
+ int_func = dma_active.tqh_first->int_func;
+ softc = dma_active.tqh_first->softc;
+ }
+ else int_func = NULL;
+ splx(s);
+
+ if(int_func != NULL)
+ (*int_func)(softc);
+}
+
+/*
+ * Setup address for DMA-transfer.
+ * Note: The order _is_ important!
+ */
+void
+st_dmaaddr_set(address)
+caddr_t address;
+{
+ register u_long ad = (u_long)address;
+
+ DMA->dma_addr[AD_LOW ] = (ad ) & 0xff;
+ DMA->dma_addr[AD_MID ] = (ad >> 8) & 0xff;
+ DMA->dma_addr[AD_HIGH] = (ad >>16) & 0xff;
+}
+
+/*
+ * Get address from DMA unit.
+ */
+u_long
+st_dmaaddr_get()
+{
+ register u_long ad = 0;
+
+ ad = (DMA->dma_addr[AD_LOW ] & 0xff);
+ ad |= (DMA->dma_addr[AD_MID ] & 0xff) << 8;
+ ad |= (DMA->dma_addr[AD_HIGH] & 0xff) <<16;
+ return(ad);
+}
+
+/*
+ * Program the DMA-controller to transfer 'nblk' blocks of 512 bytes.
+ * The DMA_WRBIT trick flushes the FIFO before doing DMA.
+ */
+void
+st_dmacomm(mode, nblk)
+int mode, nblk;
+{
+ DMA->dma_mode = mode;
+ DMA->dma_mode = mode ^ DMA_WRBIT;
+ DMA->dma_mode = mode;
+ DMA->dma_data = nblk;
+ DMA->dma_mode = DMA_SCREG | (mode & DMA_WRBIT);
+}
diff --git a/sys/arch/atari/dev/event.c b/sys/arch/atari/dev/event.c
new file mode 100644
index 00000000000..c4ae6c8b89f
--- /dev/null
+++ b/sys/arch/atari/dev/event.c
@@ -0,0 +1,173 @@
+/* $NetBSD: event.c,v 1.2 1995/06/25 19:05:23 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)event.c 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: event.c,v 1.5 92/11/26 01:10:44 torek Exp (LBL)
+ */
+
+/*
+ * Internal `Firm_event' interface for the keyboard and mouse drivers.
+ */
+
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+
+#include <atari/dev/vuid_event.h>
+#include <atari/dev/event_var.h>
+
+/*
+ * Initialize a firm_event queue.
+ */
+void
+ev_init(ev)
+ register struct evvar *ev;
+{
+
+ ev->ev_get = ev->ev_put = 0;
+ ev->ev_q = malloc((u_long)EV_QSIZE * sizeof(struct firm_event),
+ M_DEVBUF, M_WAITOK);
+ bzero((caddr_t)ev->ev_q, EV_QSIZE * sizeof(struct firm_event));
+}
+
+/*
+ * Tear down a firm_event queue.
+ */
+void
+ev_fini(ev)
+ register struct evvar *ev;
+{
+
+ free(ev->ev_q, M_DEVBUF);
+}
+
+/*
+ * User-level interface: read, select.
+ * (User cannot write an event queue.)
+ */
+int
+ev_read(ev, uio, flags)
+ register struct evvar *ev;
+ struct uio *uio;
+ int flags;
+{
+ int s, n, cnt, error;
+
+ /*
+ * Make sure we can return at least 1.
+ */
+ if (uio->uio_resid < sizeof(struct firm_event))
+ return (EMSGSIZE); /* ??? */
+ s = splev();
+ while (ev->ev_get == ev->ev_put) {
+ if (flags & IO_NDELAY) {
+ splx(s);
+ return (EWOULDBLOCK);
+ }
+ ev->ev_wanted = 1;
+ error = tsleep((caddr_t)ev, PEVENT | PCATCH, "firm_event", 0);
+ if (error) {
+ splx(s);
+ return (error);
+ }
+ }
+ /*
+ * Move firm_events from tail end of queue (there is at least one
+ * there).
+ */
+ if (ev->ev_put < ev->ev_get)
+ cnt = EV_QSIZE - ev->ev_get; /* events in [get..QSIZE) */
+ else
+ cnt = ev->ev_put - ev->ev_get; /* events in [get..put) */
+ splx(s);
+ n = howmany(uio->uio_resid, sizeof(struct firm_event));
+ if (cnt > n)
+ cnt = n;
+ error = uiomove((caddr_t)&ev->ev_q[ev->ev_get],
+ cnt * sizeof(struct firm_event), uio);
+ n -= cnt;
+ /*
+ * If we do not wrap to 0, used up all our space, or had an error,
+ * stop. Otherwise move from front of queue to put index, if there
+ * is anything there to move.
+ */
+ if ((ev->ev_get = (ev->ev_get + cnt) % EV_QSIZE) != 0 ||
+ n == 0 || error || (cnt = ev->ev_put) == 0)
+ return (error);
+ if (cnt > n)
+ cnt = n;
+ error = uiomove((caddr_t)&ev->ev_q[0],
+ cnt * sizeof(struct firm_event), uio);
+ ev->ev_get = cnt;
+ return (error);
+}
+
+int
+ev_select(ev, rw, p)
+ register struct evvar *ev;
+ int rw;
+ struct proc *p;
+{
+ int s = splev();
+
+ switch (rw) {
+
+ case FREAD:
+ /* succeed if there is something to read */
+ if (ev->ev_get != ev->ev_put) {
+ splx(s);
+ return (1);
+ }
+ selrecord(p, &ev->ev_sel);
+ break;
+
+ case FWRITE:
+ return (1); /* always fails => never blocks */
+ }
+ splx(s);
+ return (0);
+}
diff --git a/sys/arch/atari/dev/event_var.h b/sys/arch/atari/dev/event_var.h
new file mode 100644
index 00000000000..766bc2632fa
--- /dev/null
+++ b/sys/arch/atari/dev/event_var.h
@@ -0,0 +1,89 @@
+/* $NetBSD: event_var.h,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)event_var.h 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: event_var.h,v 1.5 92/11/26 01:11:51 torek Exp (LBL)
+ */
+
+/*
+ * Internal `Firm_event' interface for the keyboard and mouse drivers.
+ * The drivers are expected not to place events in the queue above spltty(),
+ * i.e., are expected to run off serial ports.
+ */
+
+/* EV_QSIZE should be a power of two so that `%' is fast */
+#define EV_QSIZE 256 /* may need tuning; this uses 2k */
+
+struct evvar {
+ u_int ev_get; /* get (read) index (modified synchronously) */
+ volatile u_int ev_put; /* put (write) index (modified by interrupt) */
+ struct selinfo ev_sel; /* process selecting */
+ struct proc *ev_io; /* process that opened queue (can get SIGIO) */
+ char ev_wanted; /* wake up on input ready */
+ char ev_async; /* send SIGIO on input ready */
+ struct firm_event *ev_q;/* circular buffer (queue) of events */
+};
+
+#define splev() spltty()
+
+#define EV_WAKEUP(ev) { \
+ selwakeup(&(ev)->ev_sel); \
+ if ((ev)->ev_wanted) { \
+ (ev)->ev_wanted = 0; \
+ wakeup((caddr_t)(ev)); \
+ } \
+ if ((ev)->ev_async) \
+ psignal((ev)->ev_io, SIGIO); \
+}
+
+void ev_init __P((struct evvar *));
+void ev_fini __P((struct evvar *));
+int ev_read __P((struct evvar *, struct uio *, int));
+int ev_select __P((struct evvar *, int, struct proc *));
+
+/*
+ * PEVENT is set just above PSOCK, which is just above TTIPRI, on the
+ * theory that mouse and keyboard `user' input should be quick.
+ */
+#define PEVENT 23
diff --git a/sys/arch/atari/dev/fd.c b/sys/arch/atari/dev/fd.c
new file mode 100644
index 00000000000..586e0b2f53a
--- /dev/null
+++ b/sys/arch/atari/dev/fd.c
@@ -0,0 +1,1202 @@
+/* $NetBSD: fd.c,v 1.10.2.1 1995/10/14 20:19:41 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file contains a driver for the Floppy Disk Controller (FDC)
+ * on the Atari TT. It uses the WD 1772 chip, modified for steprates.
+ *
+ * The ST floppy disk controller shares the access to the DMA circuitry
+ * with other devices. For this reason the floppy disk controller makes
+ * use of some special DMA accessing code.
+ *
+ * Interrupts from the FDC are in fact DMA interrupts which get their
+ * first level handling in 'dma.c' . If the floppy driver is currently
+ * using DMA the interrupt is signalled to 'fdcint'.
+ *
+ * TODO:
+ * - Test it with 2 drives (I don't have them)
+ * - Test it with an HD-drive (Don't have that either)
+ * - Finish ioctl's
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/conf.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/dkbad.h>
+#include <atari/atari/device.h>
+#include <machine/disklabel.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <machine/dma.h>
+#include <machine/video.h>
+#include <atari/dev/fdreg.h>
+
+/*
+ * Be verbose for debugging
+ */
+/*#define FLP_DEBUG 1 */
+
+#define FDC_MAX_DMA_AD 0x1000000 /* No DMA possible beyond */
+
+/* Parameters for the disk drive. */
+#define SECTOR_SIZE 512 /* physical sector size in bytes */
+#define NR_DRIVES 2 /* maximum number of drives */
+#define NR_TYPES 3 /* number of diskette/drive combinations*/
+#define MAX_ERRORS 10 /* how often to try rd/wt before quitting*/
+#define STEP_DELAY 6000 /* 6ms (6000us) delay after stepping */
+
+
+#define INV_TRK 32000 /* Should fit in unsigned short */
+#define INV_PART NR_TYPES
+
+/*
+ * Driver states
+ */
+#define FLP_IDLE 0x00 /* floppy is idle */
+#define FLP_MON 0x01 /* idle with motor on */
+#define FLP_STAT 0x02 /* determine floppy status */
+#define FLP_XFER 0x04 /* read/write data from floppy */
+
+/*
+ * Timer delay's
+ */
+#define FLP_MONDELAY (3 * hz) /* motor-on delay */
+#define FLP_XFERDELAY (2 * hz) /* timeout on transfer */
+
+/*
+ * The density codes
+ */
+#define FLP_DD 0 /* Double density */
+#define FLP_HD 1 /* High density */
+
+
+#define b_block b_resid /* FIXME: this is not the place */
+
+/*
+ * Global data for all physical floppy devices
+ */
+static short selected = 0; /* drive/head currently selected*/
+static short motoron = 0; /* motor is spinning */
+static short nopens = 0; /* Number of opens executed */
+
+static short fd_state = FLP_IDLE; /* Current driver state */
+static int lock_stat= 0; /* dma locking status */
+static short fd_cmd = 0; /* command being executed */
+static char *fd_error= NULL; /* error from fd_xfer_ok() */
+
+/*
+ * Private per device data
+ */
+struct fd_softc {
+ struct dkdevice dkdev;
+ struct buf bufq; /* queue of buf's */
+ int unit; /* unit for atari controlling hw*/
+ int nheads; /* number of heads in use */
+ int nsectors; /* number of sectors/track */
+ int density; /* density code */
+ int nblocks; /* number of blocks on disk */
+ int curtrk; /* track head positioned on */
+ short flags; /* misc flags */
+ short part; /* Current open partition */
+ int sector; /* logical sector for I/O */
+ caddr_t io_data; /* KVA for data transfer */
+ int io_bytes; /* bytes left for I/O */
+ int io_dir; /* B_READ/B_WRITE */
+ int errcnt; /* current error count */
+ u_char *bounceb; /* Bounce buffer */
+
+};
+
+/*
+ * Flags in fd_softc:
+ */
+#define FLPF_NOTRESP 0x001 /* Unit not responding */
+#define FLPF_ISOPEN 0x002 /* Unit is open */
+#define FLPF_SPARE 0x004 /* Not used */
+#define FLPF_HAVELAB 0x008 /* We have a valid label */
+#define FLPF_BOUNCE 0x010 /* Now using the bounce buffer */
+#define FLPF_WRTPROT 0x020 /* Unit is write-protected */
+#define FLPF_EMPTY 0x040 /* Unit is empty */
+#define FLPF_INOPEN 0x080 /* Currently being opened */
+#define FLPF_GETSTAT 0x100 /* Getting unit status */
+
+struct fd_types {
+ int nheads; /* Heads in use */
+ int nsectors; /* sectors per track */
+ int nblocks; /* number of blocks */
+ int density; /* density code */
+} fdtypes[NR_TYPES] = {
+ { 1, 9, 720 , FLP_DD }, /* 360 Kb */
+ { 2, 9, 1440 , FLP_DD }, /* 720 Kb */
+ { 2, 18, 2880 , FLP_HD }, /* 1.44 Mb */
+};
+
+typedef void (*FPV)();
+
+/*
+ * Private drive functions....
+ */
+static void fdstart __P((struct fd_softc *));
+static void fddone __P((struct fd_softc *));
+static void fdstatus __P((struct fd_softc *));
+static void fd_xfer __P((struct fd_softc *));
+static void fdcint __P((struct fd_softc *));
+static int fd_xfer_ok __P((struct fd_softc *));
+static void fdmotoroff __P((struct fd_softc *));
+static void fdminphys __P((struct buf *));
+static void fdtestdrv __P((struct fd_softc *));
+static int fdgetdisklabel __P((struct fd_softc *, dev_t));
+static int fdselect __P((int, int, int));
+static void fddeselect __P((void));
+
+extern __inline__ u_char read_fdreg(u_short regno)
+{
+ DMA->dma_mode = regno;
+ return(DMA->dma_data);
+}
+
+extern __inline__ void write_fdreg(u_short regno, u_short val)
+{
+ DMA->dma_mode = regno;
+ DMA->dma_data = val;
+}
+
+extern __inline__ u_char read_dmastat(void)
+{
+ DMA->dma_mode = FDC_CS | DMA_SCREG;
+ return(DMA->dma_stat);
+}
+
+/*
+ * Autoconfig stuff....
+ */
+static int fdcmatch __P((struct device *, struct cfdata *, void *));
+static int fdcprint __P((void *, char *));
+static void fdcattach __P((struct device *, struct device *, void *));
+
+struct cfdriver fdccd = {
+ NULL, "fdc", (cfmatch_t)fdcmatch, fdcattach, DV_DULL,
+ sizeof(struct device), NULL, 0 };
+
+static int
+fdcmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp("fdc", auxp) || cfp->cf_unit != 0)
+ return(0);
+ return(1);
+}
+
+static void
+fdcattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ struct fd_softc fdsoftc;
+ int i, nfound = 0;
+
+ printf("\n");
+ fddeselect();
+ for(i = 0; i < NR_DRIVES; i++) {
+
+ /*
+ * Test if unit is present
+ */
+ fdsoftc.unit = i;
+ fdsoftc.flags = 0;
+ st_dmagrab(fdcint, fdtestdrv, &fdsoftc, &lock_stat, 0);
+ st_dmafree(&fdsoftc, &lock_stat);
+
+ if(!(fdsoftc.flags & FLPF_NOTRESP)) {
+ nfound++;
+ config_found(dp, (void*)i, fdcprint);
+ }
+ }
+
+ if(nfound) {
+ /*
+ * enable disk related interrupts
+ */
+ MFP->mf_ierb |= IB_DINT;
+ MFP->mf_iprb &= ~IB_DINT;
+ MFP->mf_imrb |= IB_DINT;
+ }
+}
+
+static int
+fdcprint(auxp, pnp)
+void *auxp;
+char *pnp;
+{
+ return(UNCONF);
+}
+
+static int fdmatch __P((struct device *, struct cfdata *, void *));
+static void fdattach __P((struct device *, struct device *, void *));
+ void fdstrategy __P((struct buf *));
+struct dkdriver fddkdriver = { fdstrategy };
+
+struct cfdriver fdcd = {
+ NULL, "fd", (cfmatch_t)fdmatch, fdattach, DV_DISK,
+ sizeof(struct fd_softc), NULL, 0 };
+
+static int
+fdmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ int unit = (int)auxp;
+ return(1);
+}
+
+static void
+fdattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ struct fd_softc *sc;
+
+ sc = (struct fd_softc *)dp;
+
+ printf("\n");
+
+ sc->dkdev.dk_driver = &fddkdriver;
+}
+
+fdioctl(dev, cmd, addr, flag, p)
+dev_t dev;
+u_long cmd;
+int flag;
+caddr_t addr;
+struct proc *p;
+{
+ struct fd_softc *sc;
+ void *data;
+
+ sc = getsoftc(fdcd, DISKUNIT(dev));
+
+ if((sc->flags & FLPF_HAVELAB) == 0)
+ return(EBADF);
+
+ switch(cmd) {
+ case DIOCSBAD:
+ return(EINVAL);
+ case DIOCGDINFO:
+ *(struct disklabel *)addr = sc->dkdev.dk_label;
+ return(0);
+ case DIOCGPART:
+ ((struct partinfo *)addr)->disklab =
+ &sc->dkdev.dk_label;
+ ((struct partinfo *)addr)->part =
+ &sc->dkdev.dk_label.d_partitions[DISKPART(dev)];
+ return(0);
+#ifdef notyet /* XXX LWP */
+ case DIOCSRETRIES:
+ case DIOCSSTEP:
+ case DIOCSDINFO:
+ case DIOCWDINFO:
+ case DIOCWLABEL:
+#endif /* notyet */
+ default:
+ return(ENOTTY);
+ }
+}
+
+/*
+ * Open the device. If this is the first open on both the floppy devices,
+ * intialize the controller.
+ * Note that partition info on the floppy device is used to distinguise
+ * between 780Kb and 360Kb floppy's.
+ * partition 0: 360Kb
+ * partition 1: 780Kb
+ */
+Fdopen(dev, flags, devtype, proc)
+dev_t dev;
+int flags, devtype;
+struct proc *proc;
+{
+ struct fd_softc *sc;
+ int sps;
+
+#ifdef FLP_DEBUG
+ printf("Fdopen dev=0x%x\n", dev);
+#endif
+
+ if(DISKPART(dev) >= NR_TYPES)
+ return(ENXIO);
+
+ if((sc = getsoftc(fdcd, DISKUNIT(dev))) == NULL)
+ return(ENXIO);
+
+ /*
+ * If no floppy currently open, reset the controller and select
+ * floppy type.
+ */
+ if(!nopens) {
+
+#ifdef FLP_DEBUG
+ printf("Fdopen device not yet open\n");
+#endif
+ nopens++;
+ write_fdreg(FDC_CS, IRUPT);
+ delay(40);
+ }
+
+ /*
+ * Sleep while other process is opening the device
+ */
+ sps = splbio();
+ while(sc->flags & FLPF_INOPEN)
+ tsleep((caddr_t)sc, PRIBIO, "Fdopen", 0);
+ splx(sps);
+
+ if(!(sc->flags & FLPF_ISOPEN)) {
+ /*
+ * Initialise some driver values.
+ */
+ int part = DISKPART(dev);
+ void *addr;
+
+ sc->bufq.b_actf = NULL;
+ sc->unit = DISKUNIT(dev);
+ sc->part = part;
+ sc->nheads = fdtypes[part].nheads;
+ sc->nsectors = fdtypes[part].nsectors;
+ sc->nblocks = fdtypes[part].nblocks;
+ sc->density = fdtypes[part].density;
+ sc->curtrk = INV_TRK;
+ sc->sector = 0;
+ sc->errcnt = 0;
+ sc->bounceb = (u_char*)alloc_stmem(SECTOR_SIZE, &addr);
+ if(sc->bounceb == NULL)
+ return(ENOMEM); /* XXX */
+
+ /*
+ * Go get write protect + loaded status
+ */
+ sc->flags |= FLPF_INOPEN|FLPF_GETSTAT;
+ sps = splbio();
+ st_dmagrab(fdcint, fdstatus, sc, &lock_stat, 0);
+ while(sc->flags & FLPF_GETSTAT)
+ tsleep((caddr_t)sc, PRIBIO, "Fdopen", 0);
+ splx(sps);
+ wakeup((caddr_t)sc);
+
+ if((sc->flags & FLPF_WRTPROT) && (flags & FWRITE)) {
+ sc->flags = 0;
+ return(EPERM);
+ }
+ if(sc->flags & FLPF_EMPTY) {
+ sc->flags = 0;
+ return(ENXIO);
+ }
+ sc->flags &= ~(FLPF_INOPEN|FLPF_GETSTAT);
+ sc->flags |= FLPF_ISOPEN;
+ }
+ else {
+ /*
+ * Multiply opens are granted when accessing the same type of
+ * floppy (eq. the same partition).
+ */
+ if(sc->part != DISKPART(dev))
+ return(ENXIO); /* XXX temporarely out of business */
+ }
+ fdgetdisklabel(sc, dev);
+#ifdef FLP_DEBUG
+ printf("Fdopen open succeeded on type %d\n", sc->part);
+#endif
+}
+
+fdclose(dev, flags, devtype, proc)
+dev_t dev;
+int flags, devtype;
+struct proc *proc;
+{
+ struct fd_softc *sc;
+
+ sc = getsoftc(fdcd, DISKUNIT(dev));
+ free_stmem(sc->bounceb);
+ sc->flags = 0;
+ nopens--;
+
+#ifdef FLP_DEBUG
+ printf("Closed floppy device -- nopens: %d\n", nopens);
+#endif
+ return(0);
+}
+
+void
+fdstrategy(bp)
+struct buf *bp;
+{
+ struct fd_softc *sc;
+ struct disklabel *lp;
+ int sps, nblocks;
+
+ sc = getsoftc(fdcd, DISKUNIT(bp->b_dev));
+
+#ifdef FLP_DEBUG
+ printf("fdstrategy: 0x%x\n", bp);
+#endif
+
+ /*
+ * check for valid partition and bounds
+ */
+ lp = &sc->dkdev.dk_label;
+ if ((sc->flags & FLPF_HAVELAB) == 0) {
+ bp->b_error = EIO;
+ goto bad;
+ }
+ if (bounds_check_with_label(bp, lp, 0) <= 0)
+ goto done;
+
+ if (bp->b_bcount == 0)
+ goto done;
+
+ /*
+ * queue the buf and kick the low level code
+ */
+ sps = splbio();
+ disksort(&sc->bufq, bp);
+ if (!lock_stat) {
+ if (fd_state & FLP_MON)
+ untimeout((FPV)fdmotoroff, (void*)sc);
+ fd_state = FLP_IDLE;
+ st_dmagrab(fdcint, fdstart, sc, &lock_stat, 0);
+ }
+ splx(sps);
+
+ return;
+bad:
+ bp->b_flags |= B_ERROR;
+done:
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+}
+
+/*
+ * no dumps to floppy disks thank you.
+ */
+int
+fddump(dev_t dev)
+{
+ return(ENXIO);
+}
+
+/*
+ * no dumps to floppy disks thank you.
+ */
+int
+fdsize(dev)
+dev_t dev;
+{
+ return(-1);
+}
+
+int
+fdread(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return(physio(fdstrategy, NULL, dev, B_READ, fdminphys, uio));
+}
+
+int
+fdwrite(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return(physio(fdstrategy, NULL, dev, B_WRITE, fdminphys, uio));
+}
+
+/*
+ * Called through DMA-dispatcher, get status.
+ */
+static void
+fdstatus(sc)
+struct fd_softc *sc;
+{
+#ifdef FLP_DEBUG
+ printf("fdstatus\n");
+#endif
+ sc->errcnt = 0;
+ fd_state = FLP_STAT;
+ fd_xfer(sc);
+}
+
+/*
+ * Called through the dma-dispatcher. So we know we are the only ones
+ * messing with the floppy-controler.
+ * Initialize some fields in the fdsoftc for the state-machine and get
+ * it going.
+ */
+static void
+fdstart(sc)
+struct fd_softc *sc;
+{
+ struct buf *bp;
+
+ bp = sc->bufq.b_actf;
+ sc->sector = bp->b_blkno; /* Start sector for I/O */
+ sc->io_data = bp->b_data; /* KVA base for I/O */
+ sc->io_bytes = bp->b_bcount; /* Transfer size in bytes */
+ sc->io_dir = bp->b_flags & B_READ;/* Direction of transfer */
+ sc->errcnt = 0; /* No errors yet */
+ fd_state = FLP_XFER; /* Yes, we're going to transfer */
+
+ fd_xfer(sc);
+}
+
+/*
+ * The current transaction is finished (for good or bad). Let go of
+ * the the dma-resources. Call biodone() to finish the transaction.
+ * Find a new transaction to work on.
+ */
+static void
+fddone(sc)
+register struct fd_softc *sc;
+{
+ struct buf *bp, *dp;
+ struct fd_softc *sc1;
+ int i, sps;
+
+ /*
+ * Give others a chance to use the dma.
+ */
+ st_dmafree(sc, &lock_stat);
+
+
+ if(fd_state != FLP_STAT) {
+ /*
+ * Finish current transaction.
+ */
+ sps = splbio();
+ dp = &sc->bufq;
+ bp = dp->b_actf;
+ if(bp == NULL)
+ panic("fddone");
+ dp->b_actf = bp->b_actf;
+ splx(sps);
+
+#ifdef FLP_DEBUG
+ printf("fddone: unit: %d, buf: %x, resid: %d\n",sc->unit,bp,
+ sc->io_bytes);
+#endif
+ bp->b_resid = sc->io_bytes;
+ biodone(bp);
+ }
+ fd_state = FLP_MON;
+
+ if(lock_stat)
+ return; /* XXX Is this possible? */
+
+ /*
+ * Find a new transaction on round-robin basis.
+ */
+ for(i = sc->unit + 1; ;i++) {
+ if(i >= fdcd.cd_ndevs)
+ i = 0;
+ if((sc1 = fdcd.cd_devs[i]) == NULL)
+ continue;
+ if(sc1->bufq.b_actf)
+ break;
+ if(i == sc->unit) {
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_MONDELAY);
+#ifdef FLP_DEBUG
+ printf("fddone: Nothing to do\n");
+#endif
+ return; /* No work */
+ }
+ }
+ fd_state = FLP_IDLE;
+#ifdef FLP_DEBUG
+ printf("fddone: Staring job on unit %d\n", sc1->unit);
+#endif
+ st_dmagrab(fdcint, fdstart, sc1, &lock_stat, 0);
+}
+
+static int
+fdselect(drive, head, dense)
+int drive, head, dense;
+{
+ int i, sps, spinning;
+#ifdef FLP_DEBUG
+ printf("fdselect: drive=%d, head=%d, dense=%d\n", drive, head, dense);
+#endif
+ i = ((drive == 1) ? PA_FLOP1 : PA_FLOP0) | head;
+ spinning = motoron;
+ motoron = 1;
+
+ switch(dense) {
+ case FLP_DD:
+ DMA->dma_drvmode = 0;
+ break;
+ case FLP_HD:
+ DMA->dma_drvmode = (FDC_HDSET|FDC_HDSIG);
+ break;
+ default:
+ panic("fdselect: unknown density code\n");
+ }
+ if(i != selected) {
+ sps = splhigh();
+
+ selected = i;
+ SOUND->sd_selr = YM_IOA;
+ SOUND->sd_wdat = (SOUND->sd_rdat & 0x78) | (i ^ 0x07);
+ splx(sps);
+ }
+ return(spinning);
+}
+
+static void
+fddeselect()
+{
+ int sps;
+
+ sps = splhigh();
+ SOUND->sd_selr = YM_IOA;
+ SOUND->sd_wdat = SOUND->sd_rdat | 0x07;
+ splx(sps);
+
+ motoron = selected = 0;
+ DMA->dma_drvmode = 0;
+}
+
+/****************************************************************************
+ * The following functions assume to be running as a result of a *
+ * disk-interrupt (e.q. spl = splbio). *
+ * They form the finit-state machine, the actual driver. *
+ * *
+ * fdstart()/ --> fd_xfer() -> activate hardware *
+ * fdopen() ^ *
+ * | *
+ * +-- not ready -<------------+ *
+ * | *
+ * fdmotoroff()/ --> fdcint() -> fd_xfer_ok() ---+ *
+ * h/w interrupt | *
+ * \|/ *
+ * finished ---> fdone() *
+ * *
+ ****************************************************************************/
+static void
+fd_xfer(sc)
+struct fd_softc *sc;
+{
+ register int head = 0;
+ register int track, sector, hbit;
+ int i;
+ u_long phys_addr;
+
+ switch(fd_state) {
+ case FLP_XFER:
+ /*
+ * Calculate head/track values
+ */
+ track = sc->sector / sc->nsectors;
+ head = track % sc->nheads;
+ track = track / sc->nheads;
+#ifdef FLP_DEBUG
+ printf("fd_xfer: sector:%d,head:%d,track:%d\n", sc->sector,head,
+ track);
+#endif
+ break;
+
+ case FLP_STAT:
+ /*
+ * FLP_STAT only wants to recalibrate
+ */
+ sc->curtrk = INV_TRK;
+ break;
+ default:
+ panic("fd_xfer: wrong state (0x%x)", fd_state);
+ }
+
+ /*
+ * Select the drive.
+ */
+ hbit = fdselect(sc->unit, head, sc->density) ? HBIT : 0;
+
+ if(sc->curtrk == INV_TRK) {
+ /*
+ * Recalibrate, since we lost track of head positioning.
+ * The floppy disk controller has no way of determining its
+ * absolute arm position (track). Instead, it steps the
+ * arm a track at a time and keeps track of where it
+ * thinks it is (in software). However, after a SEEK, the
+ * hardware reads information from the diskette telling
+ * where the arm actually is. If the arm is in the wrong place,
+ * a recalibration is done, which forces the arm to track 0.
+ * This way the controller can get back into sync with reality.
+ */
+ fd_cmd = RESTORE;
+ write_fdreg(FDC_CS, RESTORE|VBIT|hbit);
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_XFERDELAY);
+
+#ifdef FLP_DEBUG
+ printf("fd_xfer:Recalibrating drive %d\n", sc->unit);
+#endif
+ return;
+ }
+
+ write_fdreg(FDC_TR, sc->curtrk);
+
+ /*
+ * Issue a SEEK command on the indicated drive unless the arm is
+ * already positioned on the correct track.
+ */
+ if(track != sc->curtrk) {
+ sc->curtrk = track; /* be optimistic */
+ write_fdreg(FDC_DR, track);
+ write_fdreg(FDC_CS, SEEK|RATE6|VBIT|hbit);
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_XFERDELAY);
+ fd_cmd = SEEK;
+#ifdef FLP_DEBUG
+ printf("fd_xfer:Seek to track %d on drive %d\n",track,sc->unit);
+#endif
+ return;
+ }
+
+ /*
+ * The drive is now on the proper track. Read or write 1 block.
+ */
+ sector = sc->sector % sc->nsectors;
+ sector++; /* start numbering at 1 */
+
+ write_fdreg(FDC_SR, sector);
+
+ phys_addr = (u_long)kvtop(sc->io_data);
+ if(phys_addr >= FDC_MAX_DMA_AD) {
+ /*
+ * We _must_ bounce this address
+ */
+ phys_addr = (u_long)kvtop(sc->bounceb);
+ if(sc->io_dir == B_WRITE)
+ bcopy(sc->io_data, sc->bounceb, SECTOR_SIZE);
+ sc->flags |= FLPF_BOUNCE;
+ }
+ st_dmaaddr_set((caddr_t)phys_addr); /* DMA address setup */
+
+#ifdef FLP_DEBUG
+ printf("fd_xfer:Start io (io_addr:%x)\n", kvtop(sc->io_data));
+#endif
+
+ if(sc->io_dir == B_READ) {
+ /* Issue the command */
+ st_dmacomm(DMA_FDC | DMA_SCREG, 1);
+ write_fdreg(FDC_CS, F_READ|hbit);
+ fd_cmd = F_READ;
+ }
+ else {
+ /* Issue the command */
+ st_dmacomm(DMA_WRBIT | DMA_FDC | DMA_SCREG, 1);
+ write_fdreg(DMA_WRBIT | FDC_CS, F_WRITE|hbit|EBIT|PBIT);
+ fd_cmd = F_WRITE;
+ }
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_XFERDELAY);
+}
+
+/* return values of fd_xfer_ok(): */
+#define X_OK 0
+#define X_AGAIN 1
+#define X_ERROR 2
+#define X_FAIL 3
+
+/*
+ * Hardware interrupt function.
+ */
+static void
+fdcint(sc)
+struct fd_softc *sc;
+{
+ struct buf *bp;
+
+#ifdef FLP_DEBUG
+ printf("fdcint: unit = %d\n", sc->unit);
+#endif
+
+ /*
+ * Cancel timeout (we made it, didn't we)
+ */
+ untimeout((FPV)fdmotoroff, (void*)sc);
+
+ switch(fd_xfer_ok(sc)) {
+ case X_ERROR :
+ if(++(sc->errcnt) < MAX_ERRORS) {
+ /*
+ * Command failed but still retries left.
+ */
+ break;
+ }
+ /* FALL THROUGH */
+ case X_FAIL :
+ /*
+ * Non recoverable error. Fall back to motor-on
+ * idle-state.
+ */
+ if(fd_error != NULL) {
+ printf("Floppy error: %s\n", fd_error);
+ fd_error = NULL;
+ }
+
+ if(fd_state == FLP_STAT) {
+ sc->flags |= FLPF_EMPTY;
+ sc->flags &= ~FLPF_GETSTAT;
+ wakeup((caddr_t)sc);
+ fddone(sc);
+ return;
+ }
+
+ bp = sc->bufq.b_actf;
+
+ bp->b_error = EIO;
+ bp->b_flags |= B_ERROR;
+ fd_state = FLP_MON;
+
+ break;
+ case X_AGAIN:
+ /*
+ * Start next part of state machine.
+ */
+ break;
+ case X_OK:
+ /*
+ * Command ok and finished. Reset error-counter.
+ * If there are no more bytes to transfer fall back
+ * to motor-on idle state.
+ */
+ sc->errcnt = 0;
+
+ if(fd_state == FLP_STAT) {
+ sc->flags &= ~FLPF_GETSTAT;
+ wakeup((caddr_t)sc);
+ fddone(sc);
+ return;
+ }
+
+ if((sc->flags & FLPF_BOUNCE) && (sc->io_dir == B_READ))
+ bcopy(sc->bounceb, sc->io_data, SECTOR_SIZE);
+ sc->flags &= ~FLPF_BOUNCE;
+
+ sc->sector++;
+ sc->io_data += SECTOR_SIZE;
+ sc->io_bytes -= SECTOR_SIZE;
+ if(sc->io_bytes <= 0)
+ fd_state = FLP_MON;
+ }
+ if(fd_state == FLP_MON)
+ fddone(sc);
+ else fd_xfer(sc);
+}
+
+/*
+ * Determine status of last command. Should only be called through
+ * 'fdcint()'.
+ * Returns:
+ * X_ERROR : Error on command; might succeed next time.
+ * X_FAIL : Error on command; will never succeed.
+ * X_AGAIN : Part of a command succeeded, call 'fd_xfer()' to complete.
+ * X_OK : Command succeeded and is complete.
+ *
+ * This function only affects sc->curtrk.
+ */
+static int
+fd_xfer_ok(sc)
+register struct fd_softc *sc;
+{
+ register int status;
+
+#ifdef FLP_DEBUG
+ printf("fd_xfer_ok: cmd: 0x%x, state: 0x%x\n", fd_cmd, fd_state);
+#endif
+ switch(fd_cmd) {
+ case IRUPT:
+ /*
+ * Timeout. Force a recalibrate before we try again.
+ */
+ status = read_fdreg(FDC_CS);
+
+ fd_error = "Timeout";
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ case F_READ:
+ /*
+ * Test for DMA error
+ */
+ status = read_dmastat();
+ if(!(status & DMAOK)) {
+ fd_error = "Dma error";
+ return(X_ERROR);
+ }
+ /*
+ * Get controller status and check for errors.
+ */
+ status = read_fdreg(FDC_CS);
+ if(status & (RNF | CRCERR | LD_T00)) {
+ fd_error = "Read error";
+ if(status & RNF)
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ break;
+ case F_WRITE:
+ /*
+ * Test for DMA error
+ */
+ status = read_dmastat();
+ if(!(status & DMAOK)) {
+ fd_error = "Dma error";
+ return(X_ERROR);
+ }
+ /*
+ * Get controller status and check for errors.
+ */
+ status = read_fdreg(FDC_CS);
+ if(status & WRI_PRO) {
+ fd_error = "Write protected";
+ return(X_FAIL);
+ }
+ if(status & (RNF | CRCERR | LD_T00)) {
+ fd_error = "Write error";
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ break;
+ case SEEK:
+ status = read_fdreg(FDC_CS);
+ if(status & (RNF | CRCERR)) {
+ fd_error = "Seek error";
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ return(X_AGAIN);
+ case RESTORE:
+ /*
+ * Determine if the recalibration succeeded.
+ */
+ status = read_fdreg(FDC_CS);
+ if(status & RNF) {
+ fd_error = "Recalibrate error";
+ /* reset controller */
+ write_fdreg(FDC_CS, IRUPT);
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ sc->curtrk = 0;
+ if(fd_state == FLP_STAT) {
+ if(status & WRI_PRO)
+ sc->flags |= FLPF_WRTPROT;
+ break;
+ }
+ return(X_AGAIN);
+ default:
+ fd_error = "Driver error: fd_xfer_ok : Unknown state";
+ return(X_FAIL);
+ }
+ return(X_OK);
+}
+
+/*
+ * All timeouts will call this function.
+ */
+static void
+fdmotoroff(sc)
+struct fd_softc *sc;
+{
+ int sps;
+
+ /*
+ * Get at harware interrupt level
+ */
+ sps = splbio();
+
+#if FLP_DEBUG
+ printf("fdmotoroff, state = 0x%x\n", fd_state);
+#endif
+
+ switch(fd_state) {
+ case FLP_STAT :
+ case FLP_XFER :
+ /*
+ * Timeout during a transfer; cancel transaction
+ * set command to 'IRUPT'.
+ * A drive-interrupt is simulated to trigger the state
+ * machine.
+ */
+ /*
+ * Cancel current transaction
+ */
+ fd_cmd = IRUPT;
+ write_fdreg(FDC_CS, IRUPT);
+ delay(20);
+ (void)read_fdreg(FDC_CS);
+ write_fdreg(FDC_CS, RESTORE);
+ break;
+
+ case FLP_MON :
+ /*
+ * Turn motor off.
+ */
+ if(selected)
+ fddeselect();
+ fd_state = FLP_IDLE;
+ break;
+ }
+ splx(sps);
+}
+
+/*
+ * min byte count to whats left of the track in question
+ */
+static void
+fdminphys(bp)
+struct buf *bp;
+{
+ struct fd_softc *sc;
+ int sec, toff, tsz;
+
+ if((sc = getsoftc(fdcd, DISKUNIT(bp->b_dev))) == NULL)
+ panic("fdminphys: couldn't get softc");
+
+ sec = bp->b_blkno % (sc->nsectors * sc->nheads);
+ toff = sec * SECTOR_SIZE;
+ tsz = sc->nsectors * sc->nheads * SECTOR_SIZE;
+
+#ifdef FLP_DEBUG
+ printf("fdminphys: before %d", bp->b_bcount);
+#endif
+
+ bp->b_bcount = min(bp->b_bcount, tsz - toff);
+
+#ifdef FLP_DEBUG
+ printf(" after %d\n", bp->b_bcount);
+#endif
+
+ minphys(bp);
+}
+
+/*
+ * Used to find out wich drives are actually connected. We do this by issueing
+ * is 'RESTORE' command and check if the 'track-0' bit is set. This also works
+ * if the drive is present but no floppy is inserted.
+ */
+static void
+fdtestdrv(fdsoftc)
+struct fd_softc *fdsoftc;
+{
+ int i, status;
+
+ /*
+ * Select the right unit and head.
+ */
+ fdselect(fdsoftc->unit, 0, FLP_DD);
+
+ write_fdreg(FDC_CS, RESTORE|HBIT);
+
+ /*
+ * Wait for about 2 seconds.
+ */
+ delay(2000000);
+
+ status = read_fdreg(FDC_CS);
+ if(status & (RNF|BUSY)) {
+ write_fdreg(FDC_CS, IRUPT); /* reset controller */
+ delay(40);
+ }
+
+ if(!(status & LD_T00))
+ fdsoftc->flags |= FLPF_NOTRESP;
+
+ fddeselect();
+}
+
+/*
+ * Build disk label. For now we only create a label from what we know
+ * from 'sc'.
+ */
+static int
+fdgetdisklabel(sc, dev)
+struct fd_softc *sc;
+dev_t dev;
+{
+ struct disklabel *lp, *dlp;
+ int part;
+
+ /*
+ * If we already got one, get out.
+ */
+ if(sc->flags & FLPF_HAVELAB)
+ return(0);
+
+#ifdef FLP_DEBUG
+ printf("fdgetdisklabel()\n");
+#endif
+
+ part = DISKPART(dev);
+ lp = &sc->dkdev.dk_label;
+ bzero(lp, sizeof(struct disklabel));
+
+ lp->d_secsize = SECTOR_SIZE;
+ lp->d_ntracks = sc->nheads;
+ lp->d_nsectors = sc->nsectors;
+ lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+ lp->d_ncylinders = sc->nblocks / lp->d_secpercyl;
+ lp->d_secperunit = sc->nblocks;
+
+ lp->d_type = DTYPE_FLOPPY;
+ lp->d_rpm = 300; /* good guess I suppose. */
+ lp->d_interleave = 1; /* FIXME: is this OK? */
+ lp->d_bbsize = 0;
+ lp->d_sbsize = 0;
+ lp->d_npartitions = part + 1;
+ lp->d_trkseek = STEP_DELAY;
+ lp->d_magic = DISKMAGIC;
+ lp->d_magic2 = DISKMAGIC;
+ lp->d_checksum = dkcksum(lp);
+ lp->d_partitions[part].p_size = lp->d_secperunit;
+ lp->d_partitions[part].p_fstype = FS_UNUSED;
+ lp->d_partitions[part].p_fsize = 1024;
+ lp->d_partitions[part].p_frag = 8;
+ sc->flags |= FLPF_HAVELAB;
+
+ return(0);
+}
diff --git a/sys/arch/atari/dev/fdreg.h b/sys/arch/atari/dev/fdreg.h
new file mode 100644
index 00000000000..255fea0126d
--- /dev/null
+++ b/sys/arch/atari/dev/fdreg.h
@@ -0,0 +1,93 @@
+/* $NetBSD: fdreg.h,v 1.2 1995/04/22 22:18:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FDREG_H
+#define _FDREG_H
+/*
+ * Atari TT hardware:
+ * Western Digital 1772 Floppy Disk Controller.
+ */
+
+/*
+ * Accessing the FDC registers is indirect through ST-specific
+ * DMA circuitry. See also dma.h.
+ */
+#define FDC_CS (DMA_FDC ) /* command/status */
+#define FDC_TR (DMA_FDC| DMA_A0) /* track register */
+#define FDC_SR (DMA_FDC|DMA_A1 ) /* sector register */
+#define FDC_DR (DMA_FDC|DMA_A1|DMA_A0) /* data register */
+
+/*
+ * commands (relevant bits/fields indicated)
+ */
+#define RESTORE 0x00 /* ( HVRR) seek to track 0 */
+#define SEEK 0x10 /* ( HVRR) seek to track */
+#define STEP 0x20 /* (UHVRR) step in same direction */
+#define STEPI 0x40 /* (UHVRR) step in */
+#define STEPO 0x60 /* (UHVRR) step out */
+#define F_READ 0x80 /* (MHE00) read sector */
+#define F_WRITE 0xA0 /* (MHEPA) write sector */
+#define READID 0xC0 /* ( HE00) read sector ID */
+#define READTR 0xE0 /* ( HE00) read track */
+#define WRITETR 0xF0 /* ( HEP0) write track */
+#define IRUPT 0xD0 /* ( IIII) force interrupt */
+
+/*
+ * other bits/fields in command register
+ */
+#define RATE6 0x00 /* not 2, but 6 msec steprate */
+#define RATE12 0x01 /* not 3, but 12 msec steprate */
+#define RATE2 0x02 /* not 5, but 2 msec steprate */
+#define RATE3 0x03 /* not 6, but 3 msec steprate */
+#define VBIT 0x04 /* verify sector ID */
+#define HBIT 0x08 /* suppress motor on sequence */
+#define UBIT 0x10 /* update track register */
+#define EBIT 0x04 /* wait 30 msec to settle */
+#define MBIT 0x10 /* multi-sector */
+#define PBIT 0x02 /* write precompensate */
+#define A0BIT 0x01 /* suppress (?) data address mark */
+#define IINDEX 0x04 /* interrupt on each index pulse */
+#define IFORCE 0x08 /* force interrupt */
+
+/*
+ * status register
+ */
+#define BUSY 0x01 /* set if command under execution */
+#define DRQ 0x02 /* Data Register status (pin c1) */
+#define LD_T00 0x04 /* lost data; track 00 */
+#define CRCERR 0x08 /* CRC error */
+#define RNF 0x10 /* Record Not Found */
+#define RT_SU 0x20 /* Record Type; Spin Up completed */
+#define WRI_PRO 0x40 /* Write Protected */
+#define MOTORON 0x80 /* Motor On */
+
+#endif /* _FDREG_H */
diff --git a/sys/arch/atari/dev/font.h b/sys/arch/atari/dev/font.h
new file mode 100644
index 00000000000..c96b55a429e
--- /dev/null
+++ b/sys/arch/atari/dev/font.h
@@ -0,0 +1,48 @@
+/* $NetBSD: font.h,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FONT_H
+#define _FONT_H
+/*
+ * What we like to know about fonts...
+ */
+typedef struct {
+ short boldsmear;
+ unsigned char width;
+ unsigned char height;
+ unsigned char baseline;
+ unsigned char font_lo;
+ unsigned char font_hi;
+ unsigned char *font_p;
+} font_info;
+
+#endif /* _FONT_H */
diff --git a/sys/arch/atari/dev/font_8x16.c b/sys/arch/atari/dev/font_8x16.c
new file mode 100644
index 00000000000..fa852f2f2a3
--- /dev/null
+++ b/sys/arch/atari/dev/font_8x16.c
@@ -0,0 +1,565 @@
+/* $NetBSD: font_8x16.c,v 1.2 1995/09/23 20:25:34 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993, 1994 Hellmuth Michaelis and Joerg Wunsch
+ *
+ * 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
+ * Hellmuth Michaelis and Joerg Wunsch
+ * 4. The name authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
+ */
+
+/*
+ * Translated into compiler and human readable for for the Atari-TT port of
+ * NetBSD by Leo Weppelman.
+ *
+ * Reorganized and edited some chars to fit the iso-8859-1 fontset by
+ * Thomas Gerner
+ */
+#include <atari/dev/font.h>
+
+char fontname_8x16[64] = "vt220iso.816";
+
+extern unsigned char fontdata_8x16[];
+font_info font_info_8x16 = { 1, 8, 16, 14, 0, 255, &fontdata_8x16[0] };
+
+int fontheight_8x16 = 16;
+int fontwidth_8x16 = 8;
+
+unsigned char fontdata_8x16[] = {
+/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x01 */ 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0xff,
+ 0xff, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, 0x00,
+/* 0x02 */ 0x42, 0x99, 0x99, 0x42, 0x42, 0x99, 0x99, 0x42,
+ 0x42, 0x99, 0x99, 0x42, 0x42, 0x99, 0x99, 0x42,
+/* 0x03 */ 0x00, 0x00, 0x90, 0x90, 0xf0, 0x90, 0x90, 0x00,
+ 0x3e, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+/* 0x04 */ 0x00, 0x00, 0xf0, 0x80, 0xe0, 0x80, 0x80, 0x00,
+ 0x1e, 0x10, 0x1c, 0x10, 0x10, 0x00, 0x00, 0x00,
+/* 0x05 */ 0x00, 0x00, 0x60, 0x90, 0x80, 0x90, 0x60, 0x00,
+ 0x1c, 0x12, 0x1c, 0x12, 0x12, 0x00, 0x00, 0x00,
+/* 0x06 */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x00,
+ 0x1e, 0x10, 0x1c, 0x10, 0x10, 0x00, 0x00, 0x00,
+/* 0x07 */ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+ 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+/* 0x09 */ 0x00, 0x00, 0x88, 0x98, 0xa8, 0xc8, 0x88, 0x00,
+ 0x10, 0x10, 0x10, 0x10, 0x1e, 0x00, 0x00, 0x00,
+/* 0x0a */ 0x00, 0x00, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00,
+ 0x3e, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+/* 0x0b */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x0c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x0d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x0e */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x0f */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x10 */ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x11 */ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+/* 0x14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+/* 0x15 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x16 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x17 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x19 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x1a */ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18,
+ 0x0c, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00,
+/* 0x1b */ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18,
+ 0x30, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00,
+/* 0x1c */ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c,
+ 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* 0x1d */ 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18,
+ 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x1e */ 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60,
+ 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* 0x1f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '!' */ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18,
+ 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '"' */ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '#' */ 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c,
+ 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* '$' */ 0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c,
+ 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
+/* '%' */ 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
+ 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
+/* '&' */ 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* ''' */ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '(' */ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
+/* ')' */ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+/* '*' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff,
+ 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '+' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+ 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* ',' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+/* '-' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '.' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '/' */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18,
+ 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+/* '0' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6,
+ 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '1' */ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* '2' */ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30,
+ 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* '3' */ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06,
+ 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '4' */ 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
+ 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
+/* '5' */ 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06,
+ 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '6' */ 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '7' */ 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
+ 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+/* '8' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '9' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06,
+ 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
+/* ':' */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* ';' */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+/* '<' */ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60,
+ 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
+/* '=' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '>' */ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06,
+ 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+/* '?' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18,
+ 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '@' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
+ 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'A' */ 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'B' */ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66,
+ 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* 'C' */ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+ 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'D' */ 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+/* 'E' */ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+ 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 'F' */ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 'G' */ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde,
+ 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+/* 'H' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'I' */ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'J' */ 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+/* 'K' */ 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78,
+ 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'L' */ 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 'M' */ 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'N' */ 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'O' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'P' */ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 'Q' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
+/* 'R' */ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
+ 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'S' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c,
+ 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'T' */ 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'U' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'V' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+/* 'W' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6,
+ 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* 'X' */ 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38,
+ 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'Y' */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'Z' */ 0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30,
+ 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* '[' */ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* '\' */ 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38,
+ 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+/* ']' */ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* '^' */ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '_' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+/* '`' */ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 'a' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 'b' */ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66,
+ 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'c' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'd' */ 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 'e' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'f' */ 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 'g' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
+/* 'h' */ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66,
+ 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'i' */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'j' */ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
+/* 'k' */ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78,
+ 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'l' */ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'm' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6,
+ 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'n' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+/* 'o' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'p' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+/* 'q' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+/* 'r' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 's' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
+ 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 't' */ 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30,
+ 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+/* 'u' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 'v' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+/* 'w' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6,
+ 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* 'x' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38,
+ 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'y' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
+/* 'z' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18,
+ 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* '{' */ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18,
+ 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
+/* '|' */ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '}' */ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18,
+ 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+/* '~' */ 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x7f */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
+ 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8b */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8e */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9b */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9e */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa1 */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18,
+ 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0xa2 */ 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60,
+ 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0xa3 */ 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60,
+ 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* 0xa4 */ 0xc3, 0x3c, 0x66, 0x42, 0x66, 0x3c, 0xc3, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa5 */ 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
+ 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0xa6 */ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+/* 0xa7 */ 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6,
+ 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
+/* 0xa8 */ 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa9 */ 0x00, 0x7c, 0xc6, 0x82, 0x9a, 0xa6, 0xa2, 0xa6,
+ 0x9a, 0x82, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xaa */ 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xab */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8,
+ 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xac */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06,
+ 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xad */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xae */ 0x00, 0x7c, 0xc6, 0x82, 0xba, 0xa6, 0xba, 0xaa,
+ 0xa6, 0x82, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xaf */ 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb0 */ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb1 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+ 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+/* 0xb2 */ 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb3 */ 0x00, 0x70, 0xd8, 0x30, 0x30, 0xd8, 0x70, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb4 */ 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb5 */ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+/* 0xb6 */ 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b,
+ 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+/* 0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x00,
+/* 0xb9 */ 0x00, 0x30, 0x70, 0xf0, 0x30, 0x30, 0x78, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xba */ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xbb */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
+ 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xbc */ 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+ 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00,
+/* 0xbd */ 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+ 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00,
+/* 0xbe */ 0x00, 0xc0, 0x60, 0xc2, 0x66, 0xcc, 0x18, 0x30,
+ 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00,
+/* 0xbf */ 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60,
+ 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xc0 */ 0x18, 0x0c, 0x06, 0x00, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xc1 */ 0x18, 0x30, 0x60, 0x00, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xc2 */ 0x10, 0x38, 0x6c, 0x00, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xc3 */ 0x76, 0xdc, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xc4 */ 0xc6, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xc5 */ 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xc6 */ 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+/* 0xc7 */ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+ 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+/* 0xc8 */ 0x18, 0x0c, 0x06, 0x00, 0xfe, 0x66, 0x60, 0x7c,
+ 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 0xc9 */ 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c,
+ 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 0xca */ 0x10, 0x38, 0x6c, 0x00, 0xfe, 0x66, 0x60, 0x7c,
+ 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 0xcb */ 0x00, 0xc6, 0x00, 0xfe, 0x66, 0x60, 0x60, 0x7c,
+ 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 0xcc */ 0x18, 0x0c, 0x06, 0x00, 0x3c, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xcd */ 0x18, 0x30, 0x60, 0x00, 0x3c, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xce */ 0x10, 0x38, 0x6c, 0x00, 0x3c, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xcf */ 0x00, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xd0 */ 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66,
+ 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+/* 0xd1 */ 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde,
+ 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xd2 */ 0x18, 0x0c, 0x06, 0x00, 0x7c, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xd3 */ 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xd4 */ 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xd5 */ 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xd6 */ 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xd7 */ 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38,
+ 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xd8 */ 0x00, 0x06, 0x7e, 0xce, 0xce, 0xce, 0xd6, 0xd6,
+ 0xe6, 0xe6, 0xe6, 0xfc, 0xc0, 0x00, 0x00, 0x00,
+/* 0xd9 */ 0x18, 0x0c, 0x06, 0x00, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xda */ 0x18, 0x30, 0x60, 0x00, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xdb */ 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xdc */ 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xdd */ 0x18, 0x30, 0x60, 0x00, 0x66, 0x66, 0x66, 0x3c,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xde */ 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x7c,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 0xdf */ 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc,
+ 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
+/* 0xe0 */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xe1 */ 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xe2 */ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xe3 */ 0x00, 0x00, 0x76, 0xdc, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xe4 */ 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xe5 */ 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xe6 */ 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xb2, 0x32,
+ 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00,
+/* 0xe7 */ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60,
+ 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
+/* 0xe8 */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xe9 */ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xea */ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xeb */ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xec */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xed */ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xee */ 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xef */ 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xf0 */ 0x00, 0x00, 0x3e, 0x30, 0x18, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xf1 */ 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+/* 0xf2 */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xf3 */ 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xf4 */ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xf5 */ 0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xf6 */ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xf7 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xf8 */ 0x00, 0x00, 0x00, 0x00, 0x06, 0x7e, 0xce, 0xce,
+ 0xd6, 0xe6, 0xe6, 0xfc, 0xc0, 0x00, 0x00, 0x00,
+/* 0xf9 */ 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xfa */ 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xfb */ 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xfc */ 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xfd */ 0x00, 0x18, 0x30, 0x60, 0x00, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+/* 0xfe */ 0x00, 0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+/* 0xff */ 0x00, 0xc6, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00
+};
diff --git a/sys/arch/atari/dev/font_8x8.c b/sys/arch/atari/dev/font_8x8.c
new file mode 100644
index 00000000000..0817d2b8845
--- /dev/null
+++ b/sys/arch/atari/dev/font_8x8.c
@@ -0,0 +1,307 @@
+/* $NetBSD: font_8x8.c,v 1.2 1995/09/23 20:25:36 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993, 1994 Hellmuth Michaelis and Joerg Wunsch
+ *
+ * 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
+ * Hellmuth Michaelis and Joerg Wunsch
+ * 4. The name authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
+ */
+
+/*
+ * Translated into compiler and human readable for for the Atari-TT port of
+ * NetBSD by Leo Weppelman.
+ *
+ * Reorganized and edited some chars to fit the iso-8859-1 fontset
+ * by Thomas Gerner
+ */
+#include <atari/dev/font.h>
+
+char fontname_8x8[64] = "vt220iso.808";
+
+extern unsigned char fontdata_8x8[];
+
+font_info font_info_8x8 = { 1, 8, 8, 6, 0, 255, &fontdata_8x8[0] };
+
+unsigned char fontdata_8x8[] = {
+/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x01 */ 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18,
+/* 0x02 */ 0x5a, 0x99, 0x42, 0x99, 0x5a, 0x81, 0x5a, 0x99,
+/* 0x03 */ 0x44, 0x44, 0x7c, 0x44, 0x3e, 0x08, 0x08, 0x08,
+/* 0x04 */ 0x7c, 0x40, 0x78, 0x40, 0x3e, 0x20, 0x3c, 0x20,
+/* 0x05 */ 0x3c, 0x40, 0x40, 0x3c, 0x3c, 0x22, 0x3c, 0x26,
+/* 0x06 */ 0x40, 0x40, 0x40, 0x7c, 0x3e, 0x20, 0x3c, 0x20,
+/* 0x07 */ 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+/* 0x08 */ 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
+/* 0x09 */ 0x64, 0x54, 0x4c, 0x44, 0x20, 0x20, 0x20, 0x3e,
+/* 0x0a */ 0x44, 0x44, 0x28, 0x10, 0x3e, 0x08, 0x08, 0x08,
+/* 0x0b */ 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00,
+/* 0x0c */ 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18,
+/* 0x0d */ 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18,
+/* 0x0e */ 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
+/* 0x0f */ 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
+/* 0x10 */ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x11 */ 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x12 */ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+/* 0x13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+/* 0x14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+/* 0x15 */ 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+/* 0x16 */ 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
+/* 0x17 */ 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00,
+/* 0x18 */ 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18,
+/* 0x19 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0x1a */ 0x30, 0x18, 0x0c, 0x18, 0x30, 0xfe, 0x00, 0xfe,
+/* 0x1b */ 0x18, 0x30, 0x60, 0x30, 0x18, 0xfe, 0x00, 0xfe,
+/* 0x1c */ 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
+/* 0x1d */ 0x02, 0x04, 0x7e, 0x08, 0x10, 0x7e, 0x20, 0x40,
+/* 0x1e */ 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00,
+/* 0x1f */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+/* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '!' */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00,
+/* '"' */ 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '#' */ 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
+/* '$' */ 0x30, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x30, 0x00,
+/* '%' */ 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
+/* '&' */ 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xce, 0x7b, 0x00,
+/* ''' */ 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '(' */ 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+/* ')' */ 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00,
+/* '*' */ 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00,
+/* '+' */ 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
+/* ',' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
+/* '-' */ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* '.' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+/* '/' */ 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
+/* '0' */ 0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0x7c, 0x00,
+/* '1' */ 0x30, 0x70, 0xb0, 0x30, 0x30, 0x30, 0xfc, 0x00,
+/* '2' */ 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xc0, 0xfc, 0x00,
+/* '3' */ 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
+/* '4' */ 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
+/* '5' */ 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
+/* '6' */ 0x78, 0xcc, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
+/* '7' */ 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
+/* '8' */ 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* '9' */ 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
+/* ':' */ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
+/* ';' */ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
+/* '<' */ 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
+/* '=' */ 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
+/* '>' */ 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00,
+/* '?' */ 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00,
+/* '@' */ 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x7e, 0x00,
+/* 'A' */ 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
+/* 'B' */ 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00,
+/* 'C' */ 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00,
+/* 'D' */ 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00,
+/* 'E' */ 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
+/* 'F' */ 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
+/* 'G' */ 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
+/* 'H' */ 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
+/* 'I' */ 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'J' */ 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
+/* 'K' */ 0xe6, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0xe6, 0x00,
+/* 'L' */ 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
+/* 'M' */ 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00,
+/* 'N' */ 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
+/* 'O' */ 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
+/* 'P' */ 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+/* 'Q' */ 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
+/* 'R' */ 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
+/* 'S' */ 0x78, 0xcc, 0xc0, 0x78, 0x0c, 0xcc, 0x78, 0x00,
+/* 'T' */ 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'U' */ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 'V' */ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+/* 'W' */ 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xfe, 0xc6, 0x00,
+/* 'X' */ 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
+/* 'Y' */ 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
+/* 'Z' */ 0xfc, 0xcc, 0x98, 0x30, 0x64, 0xcc, 0xfc, 0x00,
+/* '[' */ 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+/* '\' */ 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
+/* ']' */ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+/* '^' */ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* '_' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+/* '`' */ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 'a' */ 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
+/* 'b' */ 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00,
+/* 'c' */ 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
+/* 'd' */ 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x7e, 0x00,
+/* 'e' */ 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 'f' */ 0x38, 0x6c, 0x60, 0xf8, 0x60, 0x60, 0xf0, 0x00,
+/* 'g' */ 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+/* 'h' */ 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
+/* 'i' */ 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'j' */ 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
+/* 'k' */ 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
+/* 'l' */ 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'm' */ 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
+/* 'n' */ 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+/* 'o' */ 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 'p' */ 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
+/* 'q' */ 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
+/* 'r' */ 0x00, 0x00, 0xdc, 0x76, 0x60, 0x60, 0xf0, 0x00,
+/* 's' */ 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00,
+/* 't' */ 0x10, 0x30, 0x7c, 0x30, 0x30, 0x36, 0x1c, 0x00,
+/* 'u' */ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
+/* 'v' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7c, 0x38, 0x00,
+/* 'w' */ 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
+/* 'x' */ 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
+/* 'y' */ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+/* 'z' */ 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
+/* '{' */ 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
+/* '|' */ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+/* '}' */ 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
+/* '~' */ 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x7f */ 0x10, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
+/* 0x80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8b */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8e */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x8f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9b */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9e */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x9f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa1 */ 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
+/* 0xa2 */ 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18,
+/* 0xa3 */ 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00,
+/* 0xa4 */ 0x00, 0xc3, 0xdb, 0x3c, 0x66, 0x3c, 0xdb, 0xc3,
+/* 0xa5 */ 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30,
+/* 0xa6 */ 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18,
+/* 0xa7 */ 0x7e, 0xc3, 0xfc, 0x66, 0x66, 0x3f, 0xc3, 0x7e,
+/* 0xa8 */ 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa9 */ 0x7c, 0x82, 0x9a, 0xa2, 0xa2, 0x9a, 0x82, 0x7c,
+/* 0xaa */ 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
+/* 0xab */ 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
+/* 0xac */ 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
+/* 0xad */ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* 0xae */ 0x7c, 0x82, 0xba, 0xaa, 0xb2, 0xaa, 0x82, 0x7c,
+/* 0xaf */ 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb0 */ 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+/* 0xb1 */ 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
+/* 0xb2 */ 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
+/* 0xb3 */ 0x70, 0x18, 0x30, 0x18, 0x70, 0x00, 0x00, 0x00,
+/* 0xb4 */ 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb5 */ 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
+/* 0xb6 */ 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
+/* 0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+/* 0xb8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x78,
+/* 0xb9 */ 0x38, 0x78, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+/* 0xba */ 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
+/* 0xbb */ 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
+/* 0xbc */ 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
+/* 0xbd */ 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
+/* 0xbe */ 0xc3, 0x66, 0xcc, 0x5b, 0xb7, 0x6f, 0xcf, 0x03,
+/* 0xbf */ 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
+/* 0xc0 */ 0xe0, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
+/* 0xc1 */ 0x0e, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
+/* 0xc2 */ 0x7c, 0x82, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x00,
+/* 0xc3 */ 0xfe, 0x00, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x00,
+/* 0xc4 */ 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
+/* 0xc5 */ 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00,
+/* 0xc6 */ 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00,
+/* 0xc7 */ 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78,
+/* 0xc8 */ 0xe0, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
+/* 0xc9 */ 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
+/* 0xca */ 0x78, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
+/* 0xcb */ 0xcc, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
+/* 0xcc */ 0x70, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00,
+/* 0xcd */ 0x0e, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00,
+/* 0xce */ 0x7e, 0x81, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00,
+/* 0xcf */ 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00,
+/* 0xd0 */ 0xfc, 0x66, 0x66, 0xf6, 0x66, 0x66, 0xfc, 0x00,
+/* 0xd1 */ 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
+/* 0xd2 */ 0x70, 0x00, 0x18, 0x3c, 0x66, 0x3c, 0x18, 0x00,
+/* 0xd3 */ 0x0e, 0x00, 0x18, 0x3c, 0x66, 0x3c, 0x18, 0x00,
+/* 0xd4 */ 0x3c, 0x42, 0x18, 0x3c, 0x66, 0x3c, 0x18, 0x00,
+/* 0xd5 */ 0x7e, 0x00, 0x18, 0x3c, 0x66, 0x3c, 0x18, 0x00,
+/* 0xd6 */ 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00,
+/* 0xd7 */ 0x00, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82,
+/* 0xd8 */ 0x00, 0x02, 0x7c, 0xce, 0xd6, 0xe6, 0x7c, 0x80,
+/* 0xd9 */ 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xda */ 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xdb */ 0x78, 0x84, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xdc */ 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xdd */ 0x1c, 0x00, 0xcc, 0xcc, 0x78, 0x30, 0x78, 0x00,
+/* 0xde */ 0xf0, 0x60, 0x78, 0x6c, 0x78, 0x60, 0xf0, 0x00,
+/* 0xdf */ 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
+/* 0xe0 */ 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0xe1 */ 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0xe2 */ 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00,
+/* 0xe3 */ 0xfe, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0xe4 */ 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0xe5 */ 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0xe6 */ 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00,
+/* 0xe7 */ 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38,
+/* 0xe8 */ 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 0xe9 */ 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 0xea */ 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
+/* 0xeb */ 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 0xec */ 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 0xed */ 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 0xee */ 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
+/* 0xef */ 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 0xf0 */ 0x00, 0x7c, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xf1 */ 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
+/* 0xf2 */ 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xf3 */ 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xf4 */ 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xf5 */ 0x00, 0xfc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xf6 */ 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xf7 */ 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
+/* 0xf8 */ 0x02, 0x3a, 0x6c, 0xd6, 0xd6, 0x6c, 0xb8, 0x80,
+/* 0xf9 */ 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0xfa */ 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0xfb */ 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0xfc */ 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0xfd */ 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+/* 0xfe */ 0x00, 0xc0, 0xc0, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
+/* 0xff */ 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8
+};
diff --git a/sys/arch/atari/dev/grf.c b/sys/arch/atari/dev/grf.c
new file mode 100644
index 00000000000..81f78e5577b
--- /dev/null
+++ b/sys/arch/atari/dev/grf.c
@@ -0,0 +1,567 @@
+/* $NetBSD: grf.c,v 1.6 1995/06/26 19:55:45 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: grf.c 1.31 91/01/21$
+ *
+ * @(#)grf.c 7.8 (Berkeley) 5/7/91
+ */
+
+/*
+ * Graphics display driver for the Atari
+ * This is the hardware-independent portion of the driver.
+ * Hardware access is through the grf_softc->g_mode routine.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/file.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <sys/mman.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
+#include <machine/cpu.h>
+#include <atari/atari/device.h>
+#include <atari/dev/grfioctl.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/grfvar.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+
+#include "grf.h"
+#if NGRF > 0
+
+#include "ite.h"
+#if NITE == 0
+#define ite_on(u,f)
+#define ite_off(u,f)
+#define ite_reinit(d)
+#endif
+
+int grfopen __P((dev_t, int, int, struct proc *));
+int grfclose __P((dev_t, int));
+int grfioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+int grfselect __P((dev_t, int));
+int grfmmap __P((dev_t, int, int));
+
+int grfon __P((dev_t));
+int grfoff __P((dev_t));
+int grfsinfo __P((dev_t, struct grfdyninfo *));
+#ifdef BANKEDDEVPAGER
+int grfbanked_get __P((dev_t, off_t, int));
+int grfbanked_cur __P((dev_t));
+int grfbanked_set __P((dev_t, int));
+#endif
+static void grf_viewsync __P((struct grf_softc *));
+static int grf_mode __P((struct grf_softc *, int, void *, int, int));
+
+int grfbusprint __P((void *auxp, char *));
+int grfbusmatch __P((struct device *, struct cfdata *, void *));
+void grfbusattach __P((struct device *, struct device *, void *));
+
+void grfattach __P((struct device *, struct device *, void *));
+int grfmatch __P((struct device *, struct cfdata *, void *));
+int grfprint __P((void *, char *));
+/*
+ * pointers to grf drivers device structs
+ */
+struct grf_softc *grfsp[NGRF];
+
+
+struct cfdriver grfbuscd = {
+ NULL, "grfbus", (cfmatch_t)grfbusmatch, grfbusattach, DV_DULL,
+ sizeof(struct device)
+};
+
+struct cfdriver grfcd = {
+ NULL, "grf", (cfmatch_t)grfmatch, grfattach, DV_DULL,
+ sizeof(struct grf_softc), NULL, 0
+};
+
+/*
+ * only used in console init.
+ */
+static struct cfdata *cfdata_gbus = NULL;
+static struct cfdata *cfdata_grf = NULL;
+
+int
+grfbusmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp(auxp, grfbuscd.cd_name))
+ return(0);
+
+ if((atari_realconfig == 0) || (cfdata_gbus == NULL)) {
+ /*
+ * Probe layers we depend on
+ */
+ if(grfabs_probe() == 0)
+ return(0);
+ viewprobe();
+
+ if(atari_realconfig == 0) {
+ /*
+ * XXX: console init opens view 0
+ */
+ if(viewopen(0, 0))
+ return(0);
+ cfdata_gbus = cfp;
+ }
+ }
+ return(1); /* Always there */
+}
+
+void
+grfbusattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ static int did_cons = 0;
+ int i;
+
+ if(dp == NULL) { /* Console init */
+ did_cons = 1;
+ i = 0;
+ atari_config_found(cfdata_gbus, NULL, (void*)&i, grfbusprint);
+ }
+ else {
+ printf("\n");
+ for(i = 0; i < NGRF; i++) {
+ /*
+ * Skip opening view[0] when we this is the console.
+ */
+ if(!did_cons || (i > 0))
+ if(viewopen(i, 0))
+ break;
+ config_found(dp, (void*)&i, grfbusprint);
+ }
+ }
+}
+
+int
+grfbusprint(auxp, name)
+void *auxp;
+char *name;
+{
+ if(name == NULL)
+ return(UNCONF);
+ return(QUIET);
+}
+
+
+int
+grfmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ int unit = *(int*)auxp;
+
+ /*
+ * Match only on unit indicated by grfbus attach.
+ */
+ if(cfp->cf_unit != unit)
+ return(0);
+
+ cfdata_grf = cfp;
+ return(1);
+}
+
+/*
+ * attach: initialize the grf-structure and try to attach an ite to us.
+ * note : dp is NULL during early console init.
+ */
+void
+grfattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ static struct grf_softc congrf;
+ struct grf_softc *gp;
+ int maj;
+
+ /*
+ * find our major device number
+ */
+ for(maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == grfopen)
+ break;
+
+ /*
+ * Handle exeption case: early console init
+ */
+ if(dp == NULL) {
+ congrf.g_unit = 0;
+ congrf.g_grfdev = makedev(maj, 0);
+ congrf.g_flags = GF_ALIVE;
+ congrf.g_mode = grf_mode;
+ congrf.g_conpri = grfcc_cnprobe();
+ congrf.g_viewdev = congrf.g_unit;
+ grfcc_iteinit(&congrf);
+ grf_viewsync(&congrf);
+
+ /* Attach console ite */
+ atari_config_found(cfdata_grf, NULL, &congrf, grfprint);
+ return;
+ }
+
+ gp = (struct grf_softc *)dp;
+ gp->g_unit = gp->g_device.dv_unit;
+ grfsp[gp->g_unit] = gp;
+
+ if((cfdata_grf != NULL) && (gp->g_unit == 0)) {
+ /*
+ * We inited earlier just copy the info, take care
+ * not to copy the device struct though.
+ */
+ bcopy(&congrf.g_display, &gp->g_display,
+ (char *)&gp[1] - (char *)&gp->g_display);
+ }
+ else {
+ gp->g_grfdev = makedev(maj, gp->g_unit);
+ gp->g_flags = GF_ALIVE;
+ gp->g_mode = grf_mode;
+ gp->g_conpri = 0;
+ gp->g_viewdev = gp->g_unit;
+ grfcc_iteinit(gp);
+ grf_viewsync(gp);
+ }
+
+ printf(": width %d height %d", gp->g_display.gd_dwidth,
+ gp->g_display.gd_dheight);
+ if(gp->g_display.gd_colors == 2)
+ printf(" monochrome\n");
+ else printf(" colors %d\n", gp->g_display.gd_colors);
+
+ /*
+ * try and attach an ite
+ */
+ config_found(dp, gp, grfprint);
+}
+
+int
+grfprint(auxp, pnp)
+void *auxp;
+char *pnp;
+{
+ if(pnp)
+ printf("ite at %s", pnp);
+ return(UNCONF);
+}
+
+/*ARGSUSED*/
+int
+grfopen(dev, flags, devtype, p)
+ dev_t dev;
+ int flags, devtype;
+ struct proc *p;
+{
+ struct grf_softc *gp;
+
+ if (GRFUNIT(dev) >= NGRF)
+ return(ENXIO);
+
+ gp = grfsp[GRFUNIT(dev)];
+
+ if ((gp->g_flags & GF_ALIVE) == 0)
+ return(ENXIO);
+
+ if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
+ return(EBUSY);
+ grf_viewsync(gp);
+
+ return(0);
+}
+
+/*ARGSUSED*/
+int
+grfclose(dev, flags)
+ dev_t dev;
+ int flags;
+{
+ struct grf_softc *gp;
+
+ gp = grfsp[GRFUNIT(dev)];
+ (void)grfoff(dev);
+ gp->g_flags &= GF_ALIVE;
+ return(0);
+}
+
+/*ARGSUSED*/
+int
+grfioctl(dev, cmd, data, flag, p)
+dev_t dev;
+u_long cmd;
+int flag;
+caddr_t data;
+struct proc *p;
+{
+ struct grf_softc *gp;
+ int error;
+
+ gp = grfsp[GRFUNIT(dev)];
+ error = 0;
+
+ switch (cmd) {
+ case OGRFIOCGINFO:
+ /* argl.. no bank-member.. */
+ bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4);
+ break;
+ case GRFIOCGINFO:
+ bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
+ break;
+ case GRFIOCON:
+ error = grfon(dev);
+ break;
+ case GRFIOCOFF:
+ error = grfoff(dev);
+ break;
+ case GRFIOCSINFO:
+ error = grfsinfo(dev, (struct grfdyninfo *) data);
+ break;
+ case GRFGETVMODE:
+ return(gp->g_mode(gp, GM_GRFGETVMODE, data));
+ case GRFSETVMODE:
+ error = gp->g_mode(gp, GM_GRFSETVMODE, data);
+ if (error == 0 && gp->g_itedev)
+ ite_reinit(gp->g_itedev);
+ break;
+ case GRFGETNUMVM:
+ return(gp->g_mode(gp, GM_GRFGETNUMVM, data));
+ /*
+ * these are all hardware dependant, and have to be resolved
+ * in the respective driver.
+ */
+ case GRFIOCPUTCMAP:
+ case GRFIOCGETCMAP:
+ case GRFIOCSSPRITEPOS:
+ case GRFIOCGSPRITEPOS:
+ case GRFIOCSSPRITEINF:
+ case GRFIOCGSPRITEINF:
+ case GRFIOCGSPRITEMAX:
+ default:
+ /*
+ * check to see whether it's a command recognized by the
+ * view code.
+ */
+ return(viewioctl(gp->g_viewdev, cmd, data, flag, p));
+ error = EINVAL;
+ break;
+
+ }
+ return(error);
+}
+
+/*ARGSUSED*/
+int
+grfselect(dev, rw)
+ dev_t dev;
+ int rw;
+{
+ if (rw == FREAD)
+ return(0);
+ return(1);
+}
+
+/*
+ * map the contents of a graphics display card into process'
+ * memory space.
+ */
+int
+grfmmap(dev, off, prot)
+dev_t dev;
+int off, prot;
+{
+ struct grf_softc *gp;
+ struct grfinfo *gi;
+
+ gp = grfsp[GRFUNIT(dev)];
+ gi = &gp->g_display;
+
+ /*
+ * frame buffer
+ */
+ if ((off >= 0) && (off < gi->gd_fbsize))
+ return (((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
+ return(-1);
+}
+
+int
+grfon(dev)
+ dev_t dev;
+{
+ struct grf_softc *gp;
+
+ gp = grfsp[GRFUNIT(dev)];
+
+ if (gp->g_flags & GF_GRFON)
+ return(0);
+
+ gp->g_flags |= GF_GRFON;
+ if (gp->g_itedev != NODEV)
+ ite_off(gp->g_itedev, 3);
+
+ return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON));
+}
+
+int
+grfoff(dev)
+ dev_t dev;
+{
+ struct grf_softc *gp;
+ int error;
+
+ gp = grfsp[GRFUNIT(dev)];
+
+ if ((gp->g_flags & GF_GRFON) == 0)
+ return(0);
+
+ gp->g_flags &= ~GF_GRFON;
+ error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF);
+
+ /*
+ * Closely tied together no X's
+ */
+ if (gp->g_itedev != NODEV)
+ ite_on(gp->g_itedev, 2);
+
+ return(error);
+}
+
+int
+grfsinfo(dev, dyninfo)
+ dev_t dev;
+ struct grfdyninfo *dyninfo;
+{
+ struct grf_softc *gp;
+ int error;
+
+ gp = grfsp[GRFUNIT(dev)];
+ error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo);
+
+ /*
+ * Closely tied together no X's
+ */
+ if (gp->g_itedev != NODEV)
+ ite_reinit(gp->g_itedev);
+ return(error);
+}
+
+/*
+ * Get the grf-info in sync with underlying view.
+ */
+static void
+grf_viewsync(gp)
+struct grf_softc *gp;
+{
+ struct view_size vs;
+ bmap_t bm;
+ struct grfinfo *gi;
+
+ gi = &gp->g_display;
+
+ viewioctl(gp->g_viewdev, VIOCGBMAP, &bm, 0, -1);
+
+ gp->g_data = (caddr_t) 0xDeadBeaf; /* not particularly clean.. */
+
+ gi->gd_fbaddr = bm.hw_address;
+ gi->gd_fbsize = bm.depth*bm.bytes_per_row*bm.rows;
+
+ if(viewioctl(gp->g_viewdev, VIOCGSIZE, &vs, 0, -1)) {
+ /*
+ * fill in some default values...
+ * XXX: Should _never_ happen
+ */
+ vs.width = 640;
+ vs.height = 400;
+ vs.depth = 1;
+ }
+ gi->gd_colors = 1 << vs.depth;
+ gi->gd_planes = vs.depth;
+
+ gi->gd_fbwidth = vs.width;
+ gi->gd_fbheight = vs.height;
+ gi->gd_dyn.gdi_fbx = 0;
+ gi->gd_dyn.gdi_fby = 0;
+ gi->gd_dyn.gdi_dwidth = vs.width;
+ gi->gd_dyn.gdi_dheight = vs.height;
+ gi->gd_dyn.gdi_dx = 0;
+ gi->gd_dyn.gdi_dy = 0;
+}
+
+/*
+ * Change the mode of the display.
+ * Right now all we can do is grfon/grfoff.
+ * Return a UNIX error number or 0 for success.
+ */
+/*ARGSUSED*/
+static int
+grf_mode(gp, cmd, arg, a2, a3)
+struct grf_softc *gp;
+int cmd, a2, a3;
+void *arg;
+{
+ switch (cmd) {
+ case GM_GRFON:
+ /*
+ * Get in sync with view, ite might have changed it.
+ */
+ grf_viewsync(gp);
+ viewioctl(gp->g_viewdev, VIOCDISPLAY, NULL, 0, -1);
+ return(0);
+ case GM_GRFOFF:
+ viewioctl(gp->g_viewdev, VIOCREMOVE, NULL, 0, -1);
+ return(0);
+ case GM_GRFCONFIG:
+ default:
+ break;
+ }
+ return(EINVAL);
+}
+#endif /* NGRF > 0 */
diff --git a/sys/arch/atari/dev/grfabs.c b/sys/arch/atari/dev/grfabs.c
new file mode 100644
index 00000000000..65f3eb3933c
--- /dev/null
+++ b/sys/arch/atari/dev/grfabs.c
@@ -0,0 +1,229 @@
+/* $NetBSD: grfabs.c,v 1.7 1995/09/23 20:29:16 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * atari abstract graphics driver.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/video.h>
+#include <machine/mfp.h>
+#include <atari/dev/grfabs_reg.h>
+
+/*
+ * Function decls
+ */
+static dmode_t *get_best_display_mode __P((dimen_t *, int, dmode_t *));
+
+/*
+ * List of available graphic modes
+ */
+static MODES modes;
+
+/*
+ * Ugh.. Stuff needed to allocate console structures before the VM-system
+ * is running. There is no malloc() available at that time.
+ * Decision to use these: atari_realconfig == 0
+ */
+view_t gra_con_view;
+colormap_t gra_con_cmap;
+long gra_con_colors[MAX_CENTRIES];
+
+/*
+ * Default colors.....
+ * Currently the TT-low (256 colors) just uses 16 times the 16-color default.
+ * If you have a sensible 256 scale, feel free to add.....
+ * The first 2 colors in all maps are {black,white}, so ite (text) displays
+ * are initially readable. Also, this enables me to supply only 1 map. The
+ * 4 color mode uses the first four entries of the 16 color mode thus giving
+ * a gray scale display. (Maybe we can add an intensity bit to the ite...)
+ */
+u_long gra_def_color16[16] = {
+ 0x00000000, /* black */
+ 0x00ffffff, /* white */
+ 0x000c0c0c, /* light gray */
+ 0x00808008, /* gray */
+ 0x0000000c, /* blue */
+ 0x00000c00, /* green */
+ 0x00000c0c, /* cyan */
+ 0x00c00000, /* red */
+ 0x00c0000c, /* magenta */
+ 0x00c00c00, /* brown */
+ 0x000000ff, /* light blue */
+ 0x0000ff00, /* light green */
+ 0x0000ffff, /* light cyan */
+ 0x00ff0000, /* light red */
+ 0x00ff00ff, /* light magenta */
+ 0x00ffff00 /* light brown */
+};
+
+/*
+ * XXX: called from ite console init routine.
+ * Initialize list of posible video modes.
+ */
+int
+grfabs_probe()
+{
+ static int inited = 0;
+
+ if (inited)
+ return (1); /* Has to be done only once */
+ inited++;
+
+ LIST_INIT(&modes);
+
+#ifdef FALCON_VIDEO
+ if (machineid & ATARI_FALCON)
+ falcon_probe_video(&modes);
+#endif /* FALCON_VIDEO */
+#ifdef TT_VIDEO
+ if (machineid & ATARI_TT)
+ tt_probe_video(&modes);
+#endif /* TT_VIDEO */
+ return ((modes.lh_first == NULL) ? 0 : 1);
+}
+
+view_t *
+grf_alloc_view(d, dim, depth)
+dmode_t *d;
+dimen_t *dim;
+u_char depth;
+{
+ if (!d)
+ d = get_best_display_mode(dim, depth, NULL);
+ if (d)
+ return ((d->grfabs_funcs->alloc_view)(d, dim, depth));
+ return(NULL);
+}
+
+dmode_t *
+grf_get_best_mode(dim, depth)
+dimen_t *dim;
+u_char depth;
+{
+ return (get_best_display_mode(dim, depth, NULL));
+}
+
+void grf_display_view(v)
+view_t *v;
+{
+ (v->mode->grfabs_funcs->display_view)(v);
+}
+
+void grf_remove_view(v)
+view_t *v;
+{
+ (v->mode->grfabs_funcs->remove_view)(v);
+}
+
+void grf_free_view(v)
+view_t *v;
+{
+ (v->mode->grfabs_funcs->free_view)(v);
+}
+
+int
+grf_get_colormap(v, cm)
+view_t *v;
+colormap_t *cm;
+{
+ colormap_t *gcm;
+ int i, n;
+ u_long *sv_entry;
+
+ gcm = v->colormap;
+ n = cm->size < gcm->size ? cm->size : gcm->size;
+
+ /*
+ * Copy struct from view but be carefull to keep 'entry'
+ */
+ sv_entry = cm->entry;
+ *cm = *gcm;
+ cm->entry = sv_entry;
+
+ /*
+ * Copy the colors
+ */
+ bzero(cm->entry, cm->size * sizeof(long));
+ for (i = 0; i < n; i++)
+ cm->entry[i] = gcm->entry[i];
+ return (0);
+}
+
+int
+grf_use_colormap(v, cm)
+view_t *v;
+colormap_t *cm;
+{
+ return (v->mode->grfabs_funcs->use_colormap)(v, cm);
+}
+
+static dmode_t *
+get_best_display_mode(dim, depth, curr_mode)
+int depth;
+dimen_t *dim;
+dmode_t *curr_mode;
+{
+ dmode_t *save;
+ dmode_t *dm;
+ long dt, dx, dy, ct;
+
+ save = NULL;
+ dm = modes.lh_first;
+ while (dm != NULL) {
+ dx = abs(dm->size.width - dim->width);
+ dy = abs(dm->size.height - dim->height);
+ ct = dx + dy;
+
+ if (ct < dt || save == NULL) {
+ save = dm;
+ dt = ct;
+ }
+ dm = dm->link.le_next;
+ }
+ /*
+ * Did we do better than the current mode?
+ */
+ if ((save != NULL) && (curr_mode != NULL)) {
+ dx = abs(curr_mode->size.width - dim->width);
+ dy = abs(curr_mode->size.height - dim->height);
+ ct = dx + dy;
+ if (ct <= dt)
+ return (NULL);
+ }
+ return (save);
+}
diff --git a/sys/arch/atari/dev/grfabs_fal.c b/sys/arch/atari/dev/grfabs_fal.c
new file mode 100644
index 00000000000..72b9f9da5a6
--- /dev/null
+++ b/sys/arch/atari/dev/grfabs_fal.c
@@ -0,0 +1,424 @@
+/* $NetBSD: grfabs_fal.c,v 1.1 1995/08/20 18:17:32 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef FALCON_VIDEO
+/*
+ * atari abstract graphics driver: Falcon-interface
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <machine/iomap.h>
+#include <machine/video.h>
+#include <machine/mfp.h>
+#include <atari/atari/device.h>
+#include <atari/dev/grfabs_reg.h>
+
+/*
+ * Function decls
+ */
+static void init_view __P((view_t *, bmap_t *, dmode_t *, box_t *));
+static bmap_t *alloc_bitmap __P((u_long, u_long, u_char));
+static colormap_t *alloc_colormap __P((dmode_t *));
+static void free_bitmap __P((bmap_t *));
+static void falcon_display_view __P((view_t *));
+static view_t *falcon_alloc_view __P((dmode_t *, dimen_t *, u_char));
+static void falcon_free_view __P((view_t *));
+static void falcon_remove_view __P((view_t *));
+static int falcon_use_colormap __P((view_t *, colormap_t *));
+static void falcon_dedect __P((dmode_t *));
+
+/*
+ * Our function switch table
+ */
+struct grfabs_sw fal_vid_sw = {
+ falcon_display_view,
+ falcon_alloc_view,
+ falcon_free_view,
+ falcon_remove_view,
+ falcon_use_colormap
+};
+
+static dmode_t vid_modes[] = {
+ { { NULL, NULL }, "falauto",{ 0, 0 }, 0, RES_FALAUTO ,&fal_vid_sw},
+ { { NULL, NULL }, "sthigh", { 640, 400 }, 1, RES_FAL_STHIGH ,&fal_vid_sw},
+ { { NULL, NULL }, "stmid", { 640, 200 }, 2, RES_FAL_STMID ,&fal_vid_sw},
+ { { NULL, NULL }, "stlow", { 320, 200 }, 4, RES_FAL_STLOW ,&fal_vid_sw},
+ { { NULL, NULL }, "ttlow", { 320, 480 }, 8, RES_FAL_TTLOW ,&fal_vid_sw},
+ { { NULL, NULL }, "vga2", { 640, 480 }, 1, RES_VGA2 ,&fal_vid_sw},
+ { { NULL, NULL }, "vga4", { 640, 480 }, 2, RES_VGA4 ,&fal_vid_sw},
+ { { NULL, NULL }, "vga16", { 640, 480 }, 4, RES_VGA16 ,&fal_vid_sw},
+ { { NULL, NULL }, "vga256", { 640, 480 }, 8, RES_VGA256 ,&fal_vid_sw},
+ { { NULL, NULL }, "highcol",{ 320, 200 }, 16, RES_DIRECT ,&fal_vid_sw},
+ { { NULL, NULL }, NULL, }
+};
+
+/*
+ * XXX: called from ite console init routine.
+ * Initialize list of posible video modes.
+ */
+void
+falcon_probe_video(modelp)
+MODES *modelp;
+{
+ dmode_t *dm;
+ int i;
+
+ /* Currently we support only one mode of the falcon video system.
+ * This is the mode that is initialized before NetBSD starts. This
+ * is possible since the bios has already done that work.
+ */
+
+ for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
+ if (dm->vm_reg == RES_FALAUTO) {
+ falcon_dedect(dm);
+ LIST_INSERT_HEAD(modelp, dm, link);
+ }
+ }
+
+ /*
+ * This seems to prevent bordered screens.
+ */
+ for (i=0; i < 16; i++)
+ VIDEO->vd_fal_rgb[i] = CM_L2FAL(gra_def_color16[i]);
+}
+
+static void
+falcon_dedect(dm)
+dmode_t *dm;
+{
+ u_short falshift, stshift;
+ short interlace, doublescan;
+
+ interlace = (VIDEO->vd_fal_ctrl & 0x2) >>1;
+ doublescan = VIDEO->vd_fal_ctrl & 0x1;
+
+ /*
+ * Calculate the depth of the screen
+ */
+
+ falshift = VIDEO->vd_fal_res;
+ stshift = VIDEO->vd_st_res;
+
+ if (falshift & 0x400) /* 2 color */
+ dm->depth = 1;
+ else if (falshift & 0x100) /* high color, direct */
+ dm->depth = 16;
+ else if (falshift & 0x10) /* 256 color */
+ dm->depth = 8;
+ else if (stshift == 0) /* 16 color */
+ dm->depth = 4;
+ else if (stshift == 1) /* 4 color */
+ dm->depth = 2;
+ else dm->depth = 1; /* 2 color */
+
+ /*
+ * Now calculate the screen hight
+ */
+
+ dm->size.height = VIDEO->vd_v_dis_end - VIDEO->vd_v_dis_beg;
+ if (!interlace) dm->size.height >>=1;
+ if (doublescan) dm->size.height >>=1;
+
+ /*
+ * And the width
+ */
+
+ dm->size.width = VIDEO->vd_vert_wrap * 16 / dm->depth;
+}
+
+static void
+falcon_display_view(v)
+view_t *v;
+{
+ dmode_t *dm = v->mode;
+ bmap_t *bm = v->bitmap;
+
+ if (dm->current_view) {
+ /*
+ * Mark current view for this mode as no longer displayed
+ */
+ dm->current_view->flags &= ~VF_DISPLAY;
+ }
+ dm->current_view = v;
+ v->flags |= VF_DISPLAY;
+
+ falcon_use_colormap(v, v->colormap);
+
+ /* XXX: should use vbl for this */
+ /*
+ * Falcon: here should set the videl to switch the video mode.
+ * This will be added later.
+ * At the moment we set only the video base.
+ */
+ VIDEO->vd_raml = (u_long)bm->hw_address & 0xff;
+ VIDEO->vd_ramm = ((u_long)bm->hw_address >> 8) & 0xff;
+ VIDEO->vd_ramh = ((u_long)bm->hw_address >> 16) & 0xff;
+}
+
+static void
+falcon_remove_view(v)
+view_t *v;
+{
+ dmode_t *mode = v->mode;
+
+ if (mode->current_view == v) {
+#if 0
+ if (v->flags & VF_DISPLAY)
+ panic("Cannot shutdown display\n"); /* XXX */
+#endif
+ mode->current_view = NULL;
+ }
+ v->flags &= ~VF_DISPLAY;
+}
+
+static void
+falcon_free_view(v)
+view_t *v;
+{
+ if (v) {
+ dmode_t *md = v->mode;
+
+ falcon_remove_view(v);
+ if (v->colormap != &gra_con_cmap)
+ free(v->colormap, M_DEVBUF);
+ free_bitmap(v->bitmap);
+ if (v != &gra_con_view)
+ free(v, M_DEVBUF);
+ }
+}
+
+static int
+falcon_use_colormap(v, cm)
+view_t *v;
+colormap_t *cm;
+{
+ dmode_t *dm;
+ volatile u_short *creg;
+ volatile u_long *fcreg;
+ u_long *src;
+ colormap_t *vcm;
+ u_long *vcreg;
+ u_short ncreg;
+ int i;
+
+ dm = v->mode;
+ vcm = v->colormap;
+
+ /*
+ * I guess it seems reasonable to require the maps to be
+ * of the same type...
+ */
+ if (cm->type != vcm->type)
+ return (EINVAL);
+
+ /*
+ * First get the colormap addresses an calculate
+ * howmany colors are in it.
+ */
+ if (dm->depth == 16) /* direct color, no colormap;
+ but also not (yet) supported */
+ return(0);
+ fcreg = &VIDEO->vd_fal_rgb[0];
+ creg = &VIDEO->vd_st_rgb[0];
+ ncreg = 1 << dm->depth;
+
+ /* If first entry specified beyond capabilities -> error */
+ if (cm->first >= ncreg)
+ return (EINVAL);
+
+ /*
+ * A little tricky, the actual colormap pointer will be NULL
+ * when view is not displaying, valid otherwise.
+ */
+ if (v->flags & VF_DISPLAY)
+ creg = &creg[cm->first];
+ else creg = NULL;
+
+ vcreg = &vcm->entry[cm->first];
+ ncreg -= cm->first;
+ if (cm->size > ncreg)
+ return (EINVAL);
+ ncreg = cm->size;
+
+ for (i = 0, src = cm->entry; i < ncreg; i++, vcreg++) {
+ *vcreg = *src++;
+
+ /*
+ * If displaying, also update actual color register.
+ */
+ if (creg != NULL) {
+ *fcreg++ = CM_L2FAL(*vcreg);
+ if (i < 16 )
+ *creg++ = CM_L2ST(*vcreg);
+ }
+ }
+ return (0);
+}
+
+static view_t *
+falcon_alloc_view(mode, dim, depth)
+dmode_t *mode;
+dimen_t *dim;
+u_char depth;
+{
+ view_t *v;
+ bmap_t *bm;
+
+ if (!atari_realconfig)
+ v = &gra_con_view;
+ else v = malloc(sizeof(*v), M_DEVBUF, M_NOWAIT);
+ if (v == NULL)
+ return(NULL);
+
+ bm = alloc_bitmap(mode->size.width, mode->size.height, mode->depth);
+ if (bm) {
+ box_t box;
+
+ v->colormap = alloc_colormap(mode);
+ if (v->colormap) {
+ INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
+ init_view(v, bm, mode, &box);
+ return(v);
+ }
+ free_bitmap(bm);
+ }
+ if (v != &gra_con_view)
+ free(v, M_DEVBUF);
+ return (NULL);
+}
+
+static void
+init_view(v, bm, mode, dbox)
+view_t *v;
+bmap_t *bm;
+dmode_t *mode;
+box_t *dbox;
+{
+ v->bitmap = bm;
+ v->mode = mode;
+ v->flags = 0;
+ bcopy(dbox, &v->display, sizeof(box_t));
+}
+
+/* bitmap functions */
+
+static bmap_t *
+alloc_bitmap(width, height, depth)
+u_long width, height;
+u_char depth;
+{
+ int i;
+ u_long total_size, bm_size;
+ void *hw_address;
+ bmap_t *bm;
+
+ /*
+ * Sigh, it seems for mapping to work we need the bitplane data to
+ * 1: be aligned on a page boundry.
+ * 2: be n pages large.
+ *
+ * why? because the user gets a page aligned address, if this is before
+ * your allocation, too bad. Also it seems that the mapping routines
+ * do not watch to closely to the allowable length. so if you go over
+ * n pages by less than another page, the user gets to write all over
+ * the entire page. Since you did not allocate up to a page boundry
+ * (or more) the user writes into someone elses memory. -ch
+ */
+ bm_size = atari_round_page((width * height * depth) / NBBY);
+ total_size = bm_size + sizeof(bmap_t) + NBPG;
+
+ if ((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL)
+ return(NULL);
+
+ bm->plane = (u_char*)bm + sizeof(bmap_t);
+ bm->plane = (u_char*)atari_round_page(bm->plane);
+ bm->hw_address = (u_char*)hw_address + sizeof(bmap_t);
+ bm->hw_address = (u_char*)atari_round_page(bm->hw_address);
+ bm->bytes_per_row = (width * depth) / NBBY;
+ bm->rows = height;
+ bm->depth = depth;
+
+ bzero(bm->plane, bm_size);
+ return (bm);
+}
+
+static void
+free_bitmap(bm)
+bmap_t *bm;
+{
+ if (bm)
+ free_stmem(bm);
+}
+
+static colormap_t *
+alloc_colormap(dm)
+dmode_t *dm;
+{
+ int nentries, i;
+ colormap_t *cm;
+ u_char type = CM_COLOR;
+
+ if (dm->depth == 16) /* direct color, no colormap;
+ not (yet) supported */
+ nentries = 0;
+ else
+ nentries = 1 << dm->depth;
+
+ if (!atari_realconfig) {
+ cm = &gra_con_cmap;
+ cm->entry = gra_con_colors;
+ }
+ else {
+ int size;
+
+ size = sizeof(*cm) + (nentries * sizeof(cm->entry[0]));
+ cm = malloc(size, M_DEVBUF, M_NOWAIT);
+ if (cm == NULL)
+ return(NULL);
+ cm->entry = (long *)&cm[1];
+
+ }
+
+ if ((cm->type = type) == CM_COLOR)
+ cm->red_mask = cm->green_mask = cm->blue_mask = 0x3f;
+
+ cm->first = 0;
+ cm->size = nentries;
+
+ for (i = 0; i < nentries; i++)
+ cm->entry[i] = gra_def_color16[i % 16];
+ return (cm);
+}
+#endif /* FALCON_VIDEO */
diff --git a/sys/arch/atari/dev/grfabs_reg.h b/sys/arch/atari/dev/grfabs_reg.h
new file mode 100644
index 00000000000..1377d2aee84
--- /dev/null
+++ b/sys/arch/atari/dev/grfabs_reg.h
@@ -0,0 +1,219 @@
+/* $NetBSD: grfabs_reg.h,v 1.5 1995/09/04 19:41:41 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GRFABS_REG_H
+#define _GRFABS_REG_H
+
+struct point {
+ long x;
+ long y;
+};
+typedef struct point point_t;
+
+struct dimension {
+ u_long width;
+ u_long height;
+};
+typedef struct dimension dimen_t;
+
+struct box {
+ long x;
+ long y;
+ u_long width;
+ u_long height;
+};
+typedef struct box box_t;
+
+struct rectangle {
+ long left;
+ long top;
+ long right;
+ long bottom;
+};
+typedef struct rectangle rect_t;
+
+typedef struct bitmap bmap_t;
+typedef struct colormap colormap_t;
+typedef struct display_mode dmode_t;
+
+/*
+ * View stuff.
+ */
+
+struct view {
+ bmap_t *bitmap; /* bitmap. */
+ box_t display; /* viewable area. */
+ dmode_t *mode; /* the mode for this view */
+ colormap_t *colormap; /* the colormap for this view */
+ int flags;
+};
+typedef struct view view_t;
+
+/* View-flags: */
+#define VF_DISPLAY 1 /* view is on the air now */
+
+/*
+ * Bitmap stuff.
+ */
+struct bitmap {
+ u_short bytes_per_row; /* number of bytes per display row. */
+ u_short rows; /* number of display rows. */
+ u_short depth; /* depth of bitmap. */
+ u_char *plane; /* plane data for bitmap. */
+ u_char *hw_address; /* mappable bitplane pointer. */
+};
+
+/*
+ * Colormap stuff.
+ */
+struct colormap {
+ u_char type; /* what type of entries these are. */
+ union {
+ u_char grey; /* CM_GREYSCALE */
+ struct { /* CM_COLOR */
+ u_char red;
+ u_char green;
+ u_char blue;
+ } rgb_mask;
+ } valid_mask;
+ u_short first; /* color register entry[0] refers to */
+ u_short size; /* number of entries */
+ u_long *entry; /* the table of actual color values */
+};
+
+/*
+ * Mask short-hands
+ */
+#define grey_mask valid_mask.grey
+#define red_mask valid_mask.rgb_mask.red
+#define green_mask valid_mask.rgb_mask.green
+#define blue_mask valid_mask.rgb_mask.blue
+
+enum colormap_type {
+ CM_MONO, /* only on or off allowed */
+ CM_GREYSCALE, /* grey values */
+ CM_COLOR /* RGB values */
+};
+
+#define MAX_CENTRIES 256 /* that all there is */
+/*
+ * Create a colormap entry
+ */
+#define MAKE_COLOR_ENTRY(r,g,b) (((r & 0xff)<<16)|((g & 0xff)<<8)|(b & 0xff))
+#define MAKE_MONO_ENTRY(x) ((x) ? 1 : 0)
+#define MAKE_GREY_ENTRY(l) (l & 0xff)
+
+#define CM_L2TT(v) \
+ (((0x000f0000 & (v)) >> 8) | ((0x00000f00 & (v)) >> 4) |\
+ (0x0000000f & (v)))
+#define CM_TT2L(v) \
+ ((((0x00000f00 & (v)) * 0xff / 0xf) << 8) |\
+ (((0x000000f0 & (v)) * 0xff / 0xf) << 4) |\
+ (0x0000000f & (v)) * 0xff / 0xf)
+#define CM_L2FAL(v) \
+ (((0x003f0000 & (v)) << 10) | ((0x00003f00 & (v)) << 10) |\
+ (0x0000003f & (v)) << 2)
+#define CM_FAL2L(v) \
+ (((((0xfc000000 & (v)) >> 10) * 0xff / 0x3f) & 0x00ff0000) |\
+ ((((0x00fc0000 & (v)) >> 10) * 0xff / 0x3f) & 0x0000ff00) |\
+ ((0x000000fc & (v)) >> 2) * 0xff / 0x3f)
+#define CM_L2ST(v) \
+ (((0x000e0000 & (v)) >> 9) | ((0x00000e00 & (v)) >> 5) |\
+ (0x0000000e & (v)) >> 1)
+#define CM_ST2L(v) \
+ (((((0x00000700 & (v)) * 0xff / 0x7) << 8) & 0x00ff0000) |\
+ ((((0x00000070 & (v)) * 0xff / 0x7) << 4) & 0x0000ff00) |\
+ (0x00000007 & (v)) * 0xff / 0x7)
+
+struct grfabs_sw {
+ void (*display_view) __P((view_t*));
+ view_t * (*alloc_view) __P((dmode_t *, dimen_t *, u_char));
+ void (*free_view) __P((view_t *));
+ void (*remove_view) __P((view_t *));
+ int (*use_colormap) __P((view_t *, colormap_t *));
+};
+
+/* display mode */
+struct display_mode {
+ LIST_ENTRY(display_mode) link;
+ u_char *name; /* logical name for mode. */
+ dimen_t size; /* screen size */
+ u_char depth; /* screen depth */
+ u_short vm_reg; /* video mode register */
+ struct grfabs_sw *grfabs_funcs; /* hardware switch table */
+ view_t *current_view; /* view displaying me */
+};
+
+/*
+ * Definition of available graphic mode list.
+ */
+typedef LIST_HEAD(modelist, display_mode) MODES;
+
+/*
+ * Misc draw related macros.
+ */
+#define INIT_BOX(b,xx,yy,ww,hh) \
+ do { \
+ (b)->x = xx; \
+ (b)->y = yy; \
+ (b)->width = ww; \
+ (b)->height = hh; \
+ } while(0)
+
+
+/*
+ * Common variables
+ */
+extern view_t gra_con_view;
+extern colormap_t gra_con_cmap;
+extern long gra_con_colors[MAX_CENTRIES];
+extern u_long gra_def_color16[16];
+
+/*
+ * Prototypes:
+ */
+#ifdef FALCON_VIDEO
+void falcon_probe_video __P((MODES *));
+#endif /* FALCON_VIDEO */
+#ifdef TT_VIDEO
+void tt_probe_video __P((MODES *));
+#endif /* TT_VIDEO */
+
+view_t *grf_alloc_view __P((dmode_t *d, dimen_t *dim, u_char depth));
+dmode_t *grf_get_best_mode __P((dimen_t *dim, u_char depth));
+void grf_display_view __P((view_t *v));
+void grf_remove_view __P((view_t *v));
+void grf_free_view __P((view_t *v));
+int grf_get_colormap __P((view_t *, colormap_t *));
+int grf_use_colormap __P((view_t *, colormap_t *));
+
+#endif /* _GRFABS_REG_H */
diff --git a/sys/arch/atari/dev/grfabs_tt.c b/sys/arch/atari/dev/grfabs_tt.c
new file mode 100644
index 00000000000..65d2a871585
--- /dev/null
+++ b/sys/arch/atari/dev/grfabs_tt.c
@@ -0,0 +1,402 @@
+/* $NetBSD: grfabs_tt.c,v 1.1 1995/08/20 18:17:34 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef TT_VIDEO
+/*
+ * atari abstract graphics driver: TT-interface
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <machine/iomap.h>
+#include <machine/video.h>
+#include <machine/mfp.h>
+#include <atari/atari/device.h>
+#include <atari/dev/grfabs_reg.h>
+
+/*
+ * Function decls
+ */
+static void init_view __P((view_t *, bmap_t *, dmode_t *, box_t *));
+static bmap_t *alloc_bitmap __P((u_long, u_long, u_char));
+static colormap_t *alloc_colormap __P((dmode_t *));
+static void free_bitmap __P((bmap_t *));
+static void tt_display_view __P((view_t *));
+static view_t *tt_alloc_view __P((dmode_t *, dimen_t *, u_char));
+static void tt_free_view __P((view_t *));
+static void tt_remove_view __P((view_t *));
+static int tt_use_colormap __P((view_t *, colormap_t *));
+
+/*
+ * Our function switch table
+ */
+struct grfabs_sw tt_vid_sw = {
+ tt_display_view,
+ tt_alloc_view,
+ tt_free_view,
+ tt_remove_view,
+ tt_use_colormap
+};
+
+static dmode_t vid_modes[] = {
+ { { NULL, NULL }, "sthigh", { 640, 400 }, 1, RES_STHIGH, &tt_vid_sw },
+ { { NULL, NULL }, "tthigh", { 1280, 960 }, 1, RES_TTHIGH, &tt_vid_sw },
+ { { NULL, NULL }, "stmid", { 640, 200 }, 2, RES_STMID , &tt_vid_sw },
+ { { NULL, NULL }, "stlow", { 320, 200 }, 4, RES_STLOW , &tt_vid_sw },
+ { { NULL, NULL }, "ttmid", { 640, 480 }, 4, RES_TTMID , &tt_vid_sw },
+ { { NULL, NULL }, "ttlow", { 320, 480 }, 8, RES_TTLOW , &tt_vid_sw },
+ { { NULL, NULL }, NULL, }
+};
+
+/*
+ * XXX: called from ite console init routine.
+ * Initialize list of posible video modes.
+ */
+void
+tt_probe_video(modelp)
+MODES *modelp;
+{
+ dmode_t *dm;
+ int i;
+ int has_mono;
+
+ /*
+ * First find out what kind of monitor is attached. Dma-sound
+ * should be off because the 'sound-done' and 'monochrome-detect'
+ * are xor-ed together. I think that shutting it down here is the
+ * wrong place.
+ */
+ has_mono = (MFP->mf_gpip & IA_MONO) == 0;
+
+ for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
+ if (has_mono && (dm->vm_reg != RES_TTHIGH))
+ continue;
+ if (!has_mono && (dm->vm_reg == RES_TTHIGH))
+ continue;
+ LIST_INSERT_HEAD(modelp, dm, link);
+ }
+
+ for (i=0; i < 16; i++)
+ VIDEO->vd_tt_rgb[i] = CM_L2TT(gra_def_color16[i]);
+}
+
+static void
+tt_display_view(v)
+view_t *v;
+{
+ dmode_t *dm = v->mode;
+ bmap_t *bm = v->bitmap;
+
+ if (dm->current_view) {
+ /*
+ * Mark current view for this mode as no longer displayed
+ */
+ dm->current_view->flags &= ~VF_DISPLAY;
+ }
+ dm->current_view = v;
+ v->flags |= VF_DISPLAY;
+
+ tt_use_colormap(v, v->colormap);
+
+ /* XXX: should use vbl for this */
+ VIDEO->vd_tt_res = dm->vm_reg;
+ VIDEO->vd_raml = (u_long)bm->hw_address & 0xff;
+ VIDEO->vd_ramm = ((u_long)bm->hw_address >> 8) & 0xff;
+ VIDEO->vd_ramh = ((u_long)bm->hw_address >> 16) & 0xff;
+}
+
+void
+tt_remove_view(v)
+view_t *v;
+{
+ dmode_t *mode = v->mode;
+
+ if (mode->current_view == v) {
+#if 0
+ if (v->flags & VF_DISPLAY)
+ panic("Cannot shutdown display\n"); /* XXX */
+#endif
+ mode->current_view = NULL;
+ }
+ v->flags &= ~VF_DISPLAY;
+}
+
+void
+tt_free_view(v)
+view_t *v;
+{
+ if(v) {
+ dmode_t *md = v->mode;
+
+ tt_remove_view(v);
+ if (v->colormap != &gra_con_cmap)
+ free(v->colormap, M_DEVBUF);
+ free_bitmap(v->bitmap);
+ if (v != &gra_con_view)
+ free(v, M_DEVBUF);
+ }
+}
+
+static int
+tt_use_colormap(v, cm)
+view_t *v;
+colormap_t *cm;
+{
+ dmode_t *dm;
+ volatile u_short *creg;
+ u_long *src;
+ colormap_t *vcm;
+ u_long *vcreg;
+ u_short ncreg;
+ int i;
+
+ dm = v->mode;
+ vcm = v->colormap;
+
+ /*
+ * I guess it seems reasonable to require the maps to be
+ * of the same type...
+ */
+ if (cm->type != vcm->type)
+ return(EINVAL);
+
+ /*
+ * First figure out where the actual colormap resides and
+ * howmany colors are in it.
+ */
+ switch (dm->vm_reg) {
+ case RES_STLOW:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 16;
+ break;
+ case RES_STMID:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 4;
+ break;
+ case RES_STHIGH:
+ creg = &VIDEO->vd_tt_rgb[254];
+ ncreg = 2;
+ break;
+ case RES_TTLOW:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 256;
+ break;
+ case RES_TTMID:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 16;
+ break;
+ case RES_TTHIGH:
+ return(0); /* No colors */
+ default:
+ panic("grf_tt:use_colormap: wrong mode!?");
+ }
+
+ /* If first entry specified beyond capabilities -> error */
+ if (cm->first >= ncreg)
+ return(EINVAL);
+
+ /*
+ * A little tricky, the actual colormap pointer will be NULL
+ * when view is not displaying, valid otherwise.
+ */
+ if (v->flags & VF_DISPLAY)
+ creg = &creg[cm->first];
+ else creg = NULL;
+
+ vcreg = &vcm->entry[cm->first];
+ ncreg -= cm->first;
+ if (cm->size > ncreg)
+ return(EINVAL);
+ ncreg = cm->size;
+
+ for (i = 0, src = cm->entry; i < ncreg; i++, vcreg++) {
+ *vcreg = *src++;
+
+ /*
+ * If displaying, also update actual color registers.
+ */
+ if (creg != NULL)
+ *creg++ = CM_L2TT(*vcreg);
+ }
+ return (0);
+}
+
+static view_t *
+tt_alloc_view(mode, dim, depth)
+dmode_t *mode;
+dimen_t *dim;
+u_char depth;
+{
+ view_t *v;
+ bmap_t *bm;
+
+ if (!atari_realconfig)
+ v = &gra_con_view;
+ else v = malloc(sizeof(*v), M_DEVBUF, M_NOWAIT);
+ if(v == NULL)
+ return (NULL);
+
+ bm = alloc_bitmap(mode->size.width, mode->size.height, mode->depth);
+ if (bm) {
+ box_t box;
+
+ v->colormap = alloc_colormap(mode);
+ if (v->colormap) {
+ INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
+ init_view(v, bm, mode, &box);
+ return (v);
+ }
+ free_bitmap(bm);
+ }
+ if (v != &gra_con_view)
+ free(v, M_DEVBUF);
+ return (NULL);
+}
+
+static void
+init_view(v, bm, mode, dbox)
+view_t *v;
+bmap_t *bm;
+dmode_t *mode;
+box_t *dbox;
+{
+ v->bitmap = bm;
+ v->mode = mode;
+ v->flags = 0;
+ bcopy(dbox, &v->display, sizeof(box_t));
+}
+
+/* bitmap functions */
+
+static bmap_t *
+alloc_bitmap(width, height, depth)
+u_long width, height;
+u_char depth;
+{
+ int i;
+ u_long total_size, bm_size;
+ void *hw_address;
+ bmap_t *bm;
+
+ /*
+ * Sigh, it seems for mapping to work we need the bitplane data to
+ * 1: be aligned on a page boundry.
+ * 2: be n pages large.
+ *
+ * why? because the user gets a page aligned address, if this is before
+ * your allocation, too bad. Also it seems that the mapping routines
+ * do not watch to closely to the allowable length. so if you go over
+ * n pages by less than another page, the user gets to write all over
+ * the entire page. Since you did not allocate up to a page boundry
+ * (or more) the user writes into someone elses memory. -ch
+ */
+ bm_size = atari_round_page((width * height * depth) / NBBY);
+ total_size = bm_size + sizeof(bmap_t) + NBPG;
+
+ if ((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL)
+ return(NULL);
+
+ bm->plane = (u_char*)bm + sizeof(bmap_t);
+ bm->plane = (u_char*)atari_round_page(bm->plane);
+ bm->hw_address = (u_char*)hw_address + sizeof(bmap_t);
+ bm->hw_address = (u_char*)atari_round_page(bm->hw_address);
+ bm->bytes_per_row = (width * depth) / NBBY;
+ bm->rows = height;
+ bm->depth = depth;
+
+ bzero(bm->plane, bm_size);
+ return (bm);
+}
+
+static void
+free_bitmap(bm)
+bmap_t *bm;
+{
+ if (bm)
+ free_stmem(bm);
+}
+
+static colormap_t *
+alloc_colormap(dm)
+dmode_t *dm;
+{
+ int nentries, i;
+ colormap_t *cm;
+ u_char type = CM_COLOR;
+
+ switch (dm->vm_reg) {
+ case RES_STLOW:
+ case RES_TTMID:
+ nentries = 16;
+ break;
+ case RES_STMID:
+ nentries = 4;
+ break;
+ case RES_STHIGH:
+ nentries = 2;
+ break;
+ case RES_TTLOW:
+ nentries = 256;
+ break;
+ case RES_TTHIGH:
+ type = CM_MONO;
+ nentries = 0;
+ break;
+ default:
+ panic("grf_tt:alloc_colormap: wrong mode!?");
+ }
+ if (!atari_realconfig) {
+ cm = &gra_con_cmap;
+ cm->entry = gra_con_colors;
+ }
+ else {
+ int size;
+
+ size = sizeof(*cm) + (nentries * sizeof(cm->entry[0]));
+ cm = malloc(size, M_DEVBUF, M_NOWAIT);
+ if (cm == NULL)
+ return (NULL);
+ cm->entry = (long *)&cm[1];
+
+ }
+ if ((cm->type = type) == CM_COLOR)
+ cm->red_mask = cm->green_mask = cm->blue_mask = 0xf;
+ cm->first = 0;
+ cm->size = nentries;
+
+ for (i = 0; i < nentries; i++)
+ cm->entry[i] = gra_def_color16[i % 16];
+ return (cm);
+}
+#endif /* TT_VIDEO */
diff --git a/sys/arch/atari/dev/grfioctl.h b/sys/arch/atari/dev/grfioctl.h
new file mode 100644
index 00000000000..fb5b32571c3
--- /dev/null
+++ b/sys/arch/atari/dev/grfioctl.h
@@ -0,0 +1,212 @@
+/* $NetBSD: grfioctl.h,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: grfioctl.h 1.1 90/07/09$
+ *
+ * @(#)grfioctl.h 7.2 (Berkeley) 11/4/90
+ */
+
+
+/* these are changeable values, encapsulated in their own structure, so
+ no the whole thing has to be copied when setting parameters. */
+struct grfdyninfo {
+ int gdi_fbx; /* frame buffer x offset */
+ int gdi_fby; /* frame buffer y offset */
+ int gdi_dwidth; /* displayed part width */
+ int gdi_dheight; /* displayed part height */
+ int gdi_dx; /* displayed part x offset */
+ int gdi_dy; /* displayed part y offset */
+};
+
+struct grfinfo {
+ caddr_t gd_fbaddr; /* frame buffer physaddr */
+ int gd_fbsize; /* frame buffer size */
+ short gd_colors; /* number of colors */
+ short gd_planes; /* number of planes */
+
+ int gd_fbwidth; /* frame buffer width */
+ int gd_fbheight; /* frame buffer height */
+
+ struct grfdyninfo gd_dyn; /* everything changable by GRFIOCSINFO */
+/* compatibility... */
+#define gd_fbx gd_dyn.gdi_fbx
+#define gd_fby gd_dyn.gdi_fby
+#define gd_dwidth gd_dyn.gdi_dwidth
+#define gd_dheight gd_dyn.gdi_dheight
+#define gd_dx gd_dyn.gdi_dx
+#define gd_dy gd_dyn.gdi_dy
+
+ /* new for banked pager support */
+ int gd_bank_size; /* size of a bank (or 0) */
+};
+
+
+/* video mode, should be display-independant, but it might need
+ modifications in the future to really become hardware-independant. */
+
+struct grfvideo_mode {
+ u_char mode_num; /* index in mode table */
+ char mode_descr[80]; /* description of mode */
+ u_long pixel_clock; /* in Hz. */
+ u_short disp_width; /* width of displayed video (incl overscan) */
+ u_short disp_height; /* height "" */
+ u_short depth; /* number of bitplanes resp. bits per pixel */
+ u_short hblank_start;
+ u_short hblank_stop;
+ u_short hsync_start; /* video-parameters, take care not to */
+ u_short hsync_stop; /* use parameters that violete specs of */
+ u_short htotal; /* your monitor ! */
+ u_short vblank_start;
+ u_short vblank_stop;
+ u_short vsync_start;
+ u_short vsync_stop;
+ u_short vtotal;
+};
+
+
+/*
+ * BSD ioctls
+ */
+#define OGRFIOCGINFO 0x40344700 /* to keep compat for a while... */
+#define GRFIOCGINFO _IOR('G', 0, struct grfinfo) /* get info on device */
+#define GRFIOCON _IO('G', 1) /* turn graphics on */
+#define GRFIOCOFF _IO('G', 2) /* turn graphics off */
+#define GRFIOCMAP _IOWR('G', 5, int) /* map in regs+framebuffer */
+#define GRFIOCUNMAP _IOW('G', 6, int) /* unmap regs+framebuffer */
+
+/* amiga addons */
+ /* set info on device */
+#define GRFIOCSINFO _IOW('G', 40, struct grfdyninfo)
+ /* get video_mode. mode_num==0 gets current mode. */
+#define GRFGETVMODE _IOWR('G', 41, struct grfvideo_mode)
+ /* set video_mode. */
+#define GRFSETVMODE _IOW('G', 42, int)
+ /* get number of configured video modes */
+#define GRFGETNUMVM _IOR('G', 43, int)
+
+
+/*
+ * generic framebuffer-related ioctls. These are somewhat
+ * similar to SunOS fb-ioctls since I liked them reading
+ * thru the X11-server code.
+ */
+
+/*
+ * colormap related information. Every grf has an associated
+ * colormap. Depending on the capabilities of the hardware, more
+ * or less of the information provided may be used.
+ * Maxium value of "index" can be deduced from grfinfo->gd_colors.
+ */
+struct grf_colormap {
+ int index; /* start at red[index],green[index],blue[index] */
+ int count; /* till < red[index+count],... */
+ u_char *red;
+ u_char *green;
+ u_char *blue;
+};
+
+/* write the selected slots into the active colormap */
+#define GRFIOCPUTCMAP _IOW('G', 50, struct grf_colormap)
+
+/* retrieve the selected slots from the active colormap */
+#define GRFIOCGETCMAP _IOWR('G', 51, struct grf_colormap)
+
+
+/*
+ * support a possibly available hardware sprite. calls just fail
+ * if a given grf doesn't implement hardware sprites.
+ */
+struct grf_position {
+ u_short x, y; /* 0,0 is upper left corner */
+};
+#define GRFIOCSSPRITEPOS _IOW('G', 52, struct grf_position)
+#define GRFIOCGSPRITEPOS _IOR('G', 53, struct grf_position)
+
+struct grf_spriteinfo {
+ u_short set;
+#define GRFSPRSET_ENABLE (1<<0)
+#define GRFSPRSET_POS (1<<1)
+#define GRFSPRSET_HOT (1<<2)
+#define GRFSPRSET_CMAP (1<<3)
+#define GRFSPRSET_SHAPE (1<<4)
+#define GRFSPRSET_ALL 0x1f
+ u_short enable; /* sprite is displayed if == 1 */
+ struct grf_position pos; /* sprite location */
+ struct grf_position hot; /* sprite hot spot */
+ struct grf_colormap cmap; /* colormap for the sprite. */
+ struct grf_position size; /* x == width, y == height */
+ u_char *image, *mask; /* sprite bitmap and mask */
+};
+
+#define GRFIOCSSPRITEINF _IOW('G', 54, struct grf_spriteinfo)
+#define GRFIOCGSPRITEINF _IOR('G', 55, struct grf_spriteinfo)
+
+/* get maximum sprite size hardware can display */
+#define GRFIOCGSPRITEMAX _IOR('G', 56, struct grf_position)
+
+
+/* support for a BitBlt operation. The op-codes are identical
+ to X11 GCs */
+#define GRFBBOPclear 0x0 /* 0 */
+#define GRFBBOPand 0x1 /* src AND dst */
+#define GRFBBOPandReverse 0x2 /* src AND NOT dst */
+#define GRFBBOPcopy 0x3 /* src */
+#define GRFBBOPandInverted 0x4 /* NOT src AND dst */
+#define GRFBBOPnoop 0x5 /* dst */
+#define GRFBBOPxor 0x6 /* src XOR dst */
+#define GRFBBOPor 0x7 /* src OR dst */
+#define GRFBBOPnor 0x8 /* NOT src AND NOT dst */
+#define GRFBBOPequiv 0x9 /* NOT src XOR dst */
+#define GRFBBOPinvert 0xa /* NOT dst */
+#define GRFBBOPorReverse 0xb /* src OR NOT dst */
+#define GRFBBOPcopyInverted 0xc /* NOT src */
+#define GRFBBOPorInverted 0xd /* NOT src OR dst */
+#define GRFBBOPnand 0xe /* NOT src OR NOT dst */
+#define GRFBBOPset 0xf /* 1 */
+
+struct grf_bitblt {
+ u_short op; /* see above */
+ u_short src_x, src_y; /* upper left corner of source-region */
+ u_short dst_x, dst_y; /* upper left corner of dest-region */
+ u_short w, h; /* width, height of region */
+ u_short mask; /* bitmask to apply */
+};
+
+#define GRFIOCBITBLT _IOR('G', 57, struct grf_bitblt)
+
diff --git a/sys/arch/atari/dev/grfvar.h b/sys/arch/atari/dev/grfvar.h
new file mode 100644
index 00000000000..121fd265bca
--- /dev/null
+++ b/sys/arch/atari/dev/grfvar.h
@@ -0,0 +1,97 @@
+/* $NetBSD: grfvar.h,v 1.2 1995/05/28 19:45:38 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: grfvar.h 1.9 91/01/21$
+ *
+ * @(#)grfvar.h 7.3 (Berkeley) 5/7/91
+ */
+
+struct ite_softc;
+
+/*
+ * this struct is owned by the driver (grfcc)
+ * and is passed to grf when grf is configed. The ite also
+ * uses it...
+ */
+struct grf_softc {
+ struct device g_device; /* config sets this up. */
+ struct grfinfo g_display; /* hardware descr. (for ioctl) */
+ int g_flags; /* software flags */
+ int g_unit; /* grf unit we want/have */
+ dev_t g_itedev; /* ite device number */
+ dev_t g_grfdev; /* grf device number */
+ dev_t g_viewdev; /* view device number */
+ caddr_t g_data; /* device dependent data */
+ int (*g_mode)();
+ int g_conpri; /* priority of ite as console */
+ void (*g_iteinit)();
+ void (*g_itedeinit)();
+ void (*g_iteclear)();
+ void (*g_iteputc)();
+ void (*g_itecursor)();
+ void (*g_itescroll)();
+};
+
+/* flags */
+#define GF_ALIVE 0x01
+#define GF_OPEN 0x02
+#define GF_EXCLUDE 0x04
+#define GF_WANTED 0x08
+#define GF_GRFON 0x10
+
+/* software ids defined in grfioctl.h */
+
+/* requests to mode routine (g_mode())*/
+#define GM_GRFON 1
+#define GM_GRFOFF 2
+#define GM_GRFOVON 3
+#define GM_GRFOVOFF 4
+#define GM_GRFCONFIG 5
+#define GM_GRFGETVMODE 6
+#define GM_GRFSETVMODE 7
+#define GM_GRFGETNUMVM 8
+#define GM_GRFGETBANK 9
+#define GM_GRFSETBANK 10
+#define GM_GRFGETCURBANK 11
+#define GM_GRFIOCTL 12
+
+/* minor device interpretation */
+#define GRFOVDEV 0x10 /* XXX no driver uses yet, overlay planes */
+#define GRFIMDEV 0x20 /* XXX no driver uses yet, images planes */
+#define GRFUNIT(d) ((d) & 0x7)
diff --git a/sys/arch/atari/dev/ite.c b/sys/arch/atari/dev/ite.c
new file mode 100644
index 00000000000..3d29cc47bbe
--- /dev/null
+++ b/sys/arch/atari/dev/ite.c
@@ -0,0 +1,2348 @@
+/* $NetBSD: ite.c,v 1.7 1995/09/04 19:39:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: ite.c 1.1 90/07/09
+ * from: @(#)ite.c 7.6 (Berkeley) 5/16/91
+ */
+
+/*
+ * ite - bitmapped terminal.
+ * Supports VT200, a few terminal features will be unavailable until
+ * the system actually probes the device (i.e. not after consinit())
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/termios.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <dev/cons.h>
+
+#include <atari/atari/kdassert.h>
+#include <atari/dev/kbdmap.h>
+#include <atari/dev/iteioctl.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/grfioctl.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/grfvar.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+
+#define ITEUNIT(dev) (minor(dev))
+
+#define SUBR_INIT(ip) (ip)->grf->g_iteinit(ip)
+#define SUBR_DEINIT(ip) (ip)->grf->g_itedeinit(ip)
+#define SUBR_PUTC(ip,c,dy,dx,m) (ip)->grf->g_iteputc(ip,c,dy,dx,m)
+#define SUBR_CURSOR(ip,flg) (ip)->grf->g_itecursor(ip,flg)
+#define SUBR_CLEAR(ip,sy,sx,h,w) (ip)->grf->g_iteclear(ip,sy,sx,h,w)
+#define SUBR_SCROLL(ip,sy,sx,cnt,dir) (ip)->grf->g_itescroll(ip,sy,sx,cnt,dir)
+
+u_int ite_confunits; /* configured units */
+
+int start_repeat_timeo = 30; /* first repeat after x s/100 */
+int next_repeat_timeo = 10; /* next repeat after x s/100 */
+
+int ite_default_wrap = 1; /* you want vtxxx-nam, binpatch */
+
+struct ite_softc con_itesoftc;
+u_char cons_tabs[MAX_TABS];
+
+struct ite_softc *kbd_ite;
+int kbd_init;
+
+static char *index __P((const char *, int));
+static int inline atoi __P((const char *));
+static void ite_switch __P((int));
+void iteputchar __P((int c, struct ite_softc *ip));
+void ite_putstr __P((const u_char * s, int len, dev_t dev));
+void iteattach __P((struct device *, struct device *, void *));
+int itematch __P((struct device *, struct cfdata *, void *));
+
+struct cfdriver itecd = {
+ NULL, "ite", (cfmatch_t)itematch, iteattach, DV_DULL,
+ sizeof(struct ite_softc), NULL, 0 };
+
+int
+itematch(pdp, cdp, auxp)
+ struct device *pdp;
+ struct cfdata *cdp;
+ void *auxp;
+{
+ struct grf_softc *gp;
+ int maj;
+
+ gp = auxp;
+
+ /* ite0 should be at grf0 */
+ if(cdp->cf_unit != gp->g_unit)
+ return(0);
+
+ /*
+ * all that our mask allows (more than enough no one
+ * has > 32 monitors for text consoles on one machine)
+ */
+ if (cdp->cf_unit >= sizeof(ite_confunits) * NBBY)
+ return(0);
+ /*
+ * XXX
+ * normally this would be done in attach, however
+ * during early init we do not have a device pointer
+ * and thus no unit number.
+ */
+ for(maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == iteopen)
+ break;
+ gp->g_itedev = makedev(maj, cdp->cf_unit);
+ return(1);
+}
+
+void
+iteattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ extern int hz;
+ struct grf_softc *gp;
+ struct ite_softc *ip;
+ int s;
+
+ gp = (struct grf_softc *)auxp;
+
+ /*
+ * mark unit as attached (XXX see itematch)
+ */
+ ite_confunits |= 1 << ITEUNIT(gp->g_itedev);
+
+ if(dp) {
+ ip = (struct ite_softc *)dp;
+
+ s = spltty();
+ if(con_itesoftc.grf != NULL
+ && con_itesoftc.grf->g_unit == gp->g_unit) {
+ /*
+ * console reinit copy params over.
+ * and console always gets keyboard
+ */
+ bcopy(&con_itesoftc.grf, &ip->grf,
+ (char *)&ip[1] - (char *)&ip->grf);
+ con_itesoftc.grf = NULL;
+ kbd_ite = ip;
+ }
+ ip->grf = gp;
+ splx(s);
+
+ iteinit(gp->g_itedev);
+ printf(": rows %d cols %d", ip->rows, ip->cols);
+ printf(" repeat at (%d/100)s next at (%d/100)s",
+ start_repeat_timeo, next_repeat_timeo);
+
+ if (kbd_ite == NULL)
+ kbd_ite = ip;
+ if (kbd_ite == ip)
+ printf(" has keyboard");
+ printf("\n");
+ } else {
+ if (con_itesoftc.grf != NULL &&
+ con_itesoftc.grf->g_conpri > gp->g_conpri)
+ return;
+ con_itesoftc.grf = gp;
+ con_itesoftc.tabs = cons_tabs;
+ }
+}
+
+struct ite_softc *
+getitesp(dev)
+ dev_t dev;
+{
+ extern int atari_realconfig;
+
+ if(atari_realconfig && (con_itesoftc.grf == NULL))
+ return(itecd.cd_devs[ITEUNIT(dev)]);
+
+ if(con_itesoftc.grf == NULL)
+ panic("no ite_softc for console");
+ return(&con_itesoftc);
+}
+
+/*
+ * cons.c entry points into ite device.
+ */
+
+/*
+ * Return a priority in consdev->cn_pri field highest wins. This function
+ * is called before any devices have been probed.
+ */
+void
+itecnprobe(cd)
+ struct consdev *cd;
+{
+ /*
+ * bring graphics layer up.
+ */
+ config_console();
+
+ /*
+ * return priority of the best ite (already picked from attach)
+ * or CN_DEAD.
+ */
+ if (con_itesoftc.grf == NULL)
+ cd->cn_pri = CN_DEAD;
+ else {
+ cd->cn_pri = con_itesoftc.grf->g_conpri;
+ cd->cn_dev = con_itesoftc.grf->g_itedev;
+ }
+}
+
+void
+itecninit(cd)
+ struct consdev *cd;
+{
+ struct ite_softc *ip;
+
+ ip = getitesp(cd->cn_dev);
+ ip->flags |= ITE_ISCONS;
+ iteinit(cd->cn_dev);
+ ip->flags |= ITE_ACTIVE | ITE_ISCONS;
+}
+
+/*
+ * ite_cnfinish() is called in ite_init() when the device is
+ * being probed in the normal fasion, thus we can finish setting
+ * up this ite now that the system is more functional.
+ */
+void
+ite_cnfinish(ip)
+ struct ite_softc *ip;
+{
+ static int done;
+
+ if (done)
+ return;
+ done = 1;
+}
+
+int
+itecngetc(dev)
+ dev_t dev;
+{
+ int c;
+
+ /* XXX this should be moved */
+ if (!kbd_init) {
+ kbd_init = 1;
+ kbdenable();
+ }
+ do {
+ c = kbdgetcn();
+ c = ite_cnfilter(c, ITEFILT_CONSOLE);
+ } while (c == -1);
+ return (c);
+}
+
+void
+itecnputc(dev, c)
+ dev_t dev;
+ int c;
+{
+ static int paniced;
+ struct ite_softc *ip;
+ char ch;
+
+ ip = getitesp(dev);
+ ch = c;
+
+ if (panicstr && !paniced &&
+ (ip->flags & (ITE_ACTIVE | ITE_INGRF)) != ITE_ACTIVE) {
+ (void)ite_on(dev, 3);
+ paniced = 1;
+ }
+ iteputchar(ch, ip);
+}
+
+/*
+ * standard entry points to the device.
+ */
+
+/*
+ * iteinit() is the standard entry point for initialization of
+ * an ite device, it is also called from itecninit().
+ *
+ */
+void
+iteinit(dev)
+ dev_t dev;
+{
+ extern int atari_realconfig;
+ struct ite_softc *ip;
+
+ ip = getitesp(dev);
+ if (ip->flags & ITE_INITED)
+ return;
+ if (atari_realconfig) {
+ if (ip->kbdmap && ip->kbdmap != &ascii_kbdmap)
+ free(ip->kbdmap, M_DEVBUF);
+ ip->kbdmap = malloc(sizeof(struct kbdmap), M_DEVBUF, M_WAITOK);
+ bcopy(&ascii_kbdmap, ip->kbdmap, sizeof(struct kbdmap));
+ }
+ else ip->kbdmap = &ascii_kbdmap;
+
+ ip->cursorx = 0;
+ ip->cursory = 0;
+ SUBR_INIT(ip);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ if (ip->tabs == NULL)
+ ip->tabs = malloc(MAX_TABS * sizeof(u_char),M_DEVBUF,M_WAITOK);
+ ite_reset(ip);
+ ip->flags |= ITE_INITED;
+}
+
+int
+iteopen(dev, mode, devtype, p)
+ dev_t dev;
+ int mode, devtype;
+ struct proc *p;
+{
+ struct ite_softc *ip;
+ struct tty *tp;
+ int error, first, unit;
+
+ unit = ITEUNIT(dev);
+ first = 0;
+
+ if (((1 << unit) & ite_confunits) == 0)
+ return (ENXIO);
+
+ ip = getitesp(dev);
+
+ if (ip->tp == NULL)
+ tp = ip->tp = ttymalloc();
+ else
+ tp = ip->tp;
+ if ((tp->t_state & (TS_ISOPEN | TS_XCLUDE)) == (TS_ISOPEN | TS_XCLUDE)
+ && p->p_ucred->cr_uid != 0)
+ return (EBUSY);
+ if ((ip->flags & ITE_ACTIVE) == 0) {
+ error = ite_on(dev, 0);
+ if (error)
+ return (error);
+ first = 1;
+ }
+ tp->t_oproc = itestart;
+ tp->t_param = ite_param;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ tp->t_state = TS_WOPEN | TS_CARR_ON;
+ ttsetwater(tp);
+ }
+ error = (*linesw[tp->t_line].l_open) (dev, tp);
+ if (error == 0) {
+ tp->t_winsize.ws_row = ip->rows;
+ tp->t_winsize.ws_col = ip->cols;
+ if (!kbd_init) {
+ kbd_init = 1;
+ kbdenable();
+ }
+ } else if (first)
+ ite_off(dev, 0);
+ return (error);
+}
+
+int
+iteclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct tty *tp;
+
+ tp = getitesp(dev)->tp;
+
+ KDASSERT(tp);
+ (*linesw[tp->t_line].l_close) (tp, flag);
+ ttyclose(tp);
+ ite_off(dev, 0);
+ return (0);
+}
+
+int
+iteread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct tty *tp;
+
+ tp = getitesp(dev)->tp;
+
+ KDASSERT(tp);
+ return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
+}
+
+int
+itewrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct tty *tp;
+
+ tp = getitesp(dev)->tp;
+
+ KDASSERT(tp);
+ return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
+}
+
+int
+itestop(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+
+}
+
+struct tty *
+itetty(dev)
+ dev_t dev;
+{
+ return(getitesp(dev)->tp);
+}
+
+int
+iteioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ u_long cmd;
+ int flag;
+ caddr_t addr;
+ struct proc *p;
+{
+ struct iterepeat *irp;
+ struct ite_softc *ip;
+ struct tty *tp;
+ int error;
+
+ ip = getitesp(dev);
+ tp = ip->tp;
+
+ KDASSERT(tp);
+
+ error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, addr, flag, p);
+ if(error >= 0)
+ return (error);
+ error = ttioctl(tp, cmd, addr, flag, p);
+ if (error >= 0)
+ return (error);
+
+ switch (cmd) {
+ case ITEIOCSKMAP:
+ if (addr == 0)
+ return(EFAULT);
+ bcopy(addr, ip->kbdmap, sizeof(struct kbdmap));
+ return(0);
+ case ITEIOCSSKMAP:
+ if (addr == 0)
+ return(EFAULT);
+ bcopy(addr, &ascii_kbdmap, sizeof(struct kbdmap));
+ return(0);
+ case ITEIOCGKMAP:
+ if (addr == NULL)
+ return(EFAULT);
+ bcopy(ip->kbdmap, addr, sizeof(struct kbdmap));
+ return(0);
+ case ITEIOCGREPT:
+ irp = (struct iterepeat *)addr;
+ irp->start = start_repeat_timeo;
+ irp->next = next_repeat_timeo;
+ return(0);
+ case ITEIOCSREPT:
+ irp = (struct iterepeat *)addr;
+ if (irp->start < ITEMINREPEAT || irp->next < ITEMINREPEAT)
+ return(EINVAL);
+ start_repeat_timeo = irp->start;
+ next_repeat_timeo = irp->next;
+ return(0);
+ }
+ error = ite_grf_ioctl(ip, cmd, addr, flag, p);
+ if(error >= 0)
+ return(error);
+ return (ENOTTY);
+}
+
+void
+itestart(tp)
+ struct tty *tp;
+{
+ struct clist *rbp;
+ struct ite_softc *ip;
+ u_char buf[ITEBURST];
+ int s, len, n;
+
+ ip = getitesp(tp->t_dev);
+
+ KDASSERT(tp);
+
+ s = spltty(); {
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto out;
+
+ tp->t_state |= TS_BUSY;
+ rbp = &tp->t_outq;
+
+ len = q_to_b(rbp, buf, ITEBURST);
+ } splx(s);
+
+ /* Here is a really good place to implement pre/jumpscroll() */
+ ite_putstr((char *)buf, len, tp->t_dev);
+
+ s = spltty(); {
+ tp->t_state &= ~TS_BUSY;
+ /* we have characters remaining. */
+ if (rbp->c_cc) {
+ tp->t_state |= TS_TIMEOUT;
+ timeout(ttrstrt, tp, 1);
+ }
+ /* wakeup we are below */
+ if (rbp->c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t) rbp);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ out: ;
+ } splx(s);
+}
+
+int
+ite_on(dev, flag)
+ dev_t dev;
+ int flag;
+{
+ struct ite_softc *ip;
+ int unit;
+
+ unit = ITEUNIT(dev);
+ if (((1 << unit) & ite_confunits) == 0)
+ return (ENXIO);
+
+ ip = getitesp(dev);
+
+ /* force ite active, overriding graphics mode */
+ if (flag & 1) {
+ ip->flags |= ITE_ACTIVE;
+ ip->flags &= ~(ITE_INGRF | ITE_INITED);
+ }
+ /* leave graphics mode */
+ if (flag & 2) {
+ ip->flags &= ~ITE_INGRF;
+ if ((ip->flags & ITE_ACTIVE) == 0)
+ return (0);
+ }
+ ip->flags |= ITE_ACTIVE;
+ if (ip->flags & ITE_INGRF)
+ return (0);
+ iteinit(dev);
+ return (0);
+}
+
+int
+ite_off(dev, flag)
+dev_t dev;
+int flag;
+{
+ struct ite_softc *ip;
+
+ ip = getitesp(dev);
+ if (flag & 2)
+ ip->flags |= ITE_INGRF;
+ if ((ip->flags & ITE_ACTIVE) == 0)
+ return;
+ if ((flag & 1) ||
+ (ip->flags & (ITE_INGRF | ITE_ISCONS | ITE_INITED)) == ITE_INITED)
+ SUBR_DEINIT(ip);
+ if ((flag & 2) == 0) /* XXX hmm grfon() I think wants this to go inactive. */
+ ip->flags &= ~ITE_ACTIVE;
+}
+
+static void
+ite_switch(unit)
+int unit;
+{
+ struct ite_softc *ip;
+
+ if(!(ite_confunits & (1 << unit)))
+ return; /* Don't try unconfigured units */
+ ip = getitesp(unit);
+ if(!(ip->flags & ITE_INITED))
+ return;
+
+ /*
+ * If switching to an active ite, also switch the keyboard.
+ */
+ if(ip->flags & ITE_ACTIVE)
+ kbd_ite = ip;
+
+ /*
+ * Now make it visible
+ */
+ viewioctl(ip->grf->g_viewdev, VIOCDISPLAY, NULL, 0, -1);
+}
+
+/* XXX called after changes made in underlying grf layer. */
+/* I want to nuke this */
+void
+ite_reinit(dev)
+ dev_t dev;
+{
+ struct ite_softc *ip;
+
+ ip = getitesp(dev);
+ ip->flags &= ~ITE_INITED;
+ iteinit(dev);
+}
+
+int
+ite_param(tp, t)
+ struct tty *tp;
+ struct termios *t;
+{
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+ return (0);
+}
+
+void
+ite_reset(ip)
+ struct ite_softc *ip;
+{
+ int i;
+
+ ip->curx = 0;
+ ip->cury = 0;
+ ip->attribute = ATTR_NOR;
+ ip->save_curx = 0;
+ ip->save_cury = 0;
+ ip->save_attribute = ATTR_NOR;
+ ip->ap = ip->argbuf;
+ ip->emul_level = 0;
+ ip->eightbit_C1 = 0;
+ ip->top_margin = 0;
+ ip->bottom_margin = ip->rows - 1;
+ ip->inside_margins = 0;
+ ip->linefeed_newline = 0;
+ ip->auto_wrap = ite_default_wrap;
+ ip->cursor_appmode = 0;
+ ip->keypad_appmode = 0;
+ ip->imode = 0;
+ ip->key_repeat = 1;
+ bzero(ip->tabs, ip->cols);
+ for (i = 0; i < ip->cols; i++)
+ ip->tabs[i] = ((i & 7) == 0);
+}
+
+/*
+ * has to be global becuase of the shared filters.
+ */
+static u_char key_mod;
+static u_char last_dead;
+
+/* Used in console at startup only */
+int
+ite_cnfilter(c, caller)
+u_int c;
+enum caller caller;
+{
+ struct key key;
+ struct kbdmap *kbdmap;
+ u_char code, up, mask;
+ int s;
+
+ up = KBD_RELEASED(c);
+ c = KBD_SCANCODE(c);
+ code = 0;
+ mask = 0;
+ kbdmap = (kbd_ite == NULL) ? &ascii_kbdmap : kbd_ite->kbdmap;
+
+ s = spltty();
+
+ /*
+ * Handle special keys
+ */
+ switch(c) {
+ case KBD_LEFT_SHIFT:
+ mask = KBD_MOD_LSHIFT;
+ break;
+ case KBD_RIGHT_SHIFT:
+ mask = KBD_MOD_RSHIFT;
+ break;
+ case KBD_CTRL:
+ mask = KBD_MOD_CTRL;
+ break;
+ case KBD_ALT:
+ mask = KBD_MOD_ALT;
+ break;
+ case KBD_CAPS_LOCK:
+ /* CAPSLOCK is a toggle */
+ if(!up)
+ key_mod ^= KBD_MOD_CAPS;
+ splx(s);
+ return;
+ break;
+ }
+ if(mask) {
+ if(up)
+ key_mod &= ~mask;
+ else
+ key_mod |= mask;
+ splx(s);
+ return -1;
+ }
+
+ /*
+ * No special action if key released
+ */
+ if(up) {
+ splx(s);
+ return -1;
+ }
+
+ /* translate modifiers */
+ if(key_mod & KBD_MOD_SHIFT) {
+ if(key_mod & KBD_MOD_ALT)
+ key = kbdmap->alt_shift_keys[c];
+ else key = kbdmap->shift_keys[c];
+ }
+ else if(key_mod & KBD_MOD_ALT)
+ key = kbdmap->alt_keys[c];
+ else {
+ key = kbdmap->keys[c];
+ /*
+ * If CAPS and key is CAPable (no pun intended)
+ */
+ if((key_mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
+ key = kbdmap->shift_keys[c];
+ }
+ code = key.code;
+
+#ifdef notyet /* LWP: Didn't have time to look at this yet */
+ /*
+ * If string return simple console filter
+ */
+ if(key->mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) {
+ splx(s);
+ return -1;
+ }
+ /* handle dead keys */
+ if(key->mode & KBD_MODE_DEAD) {
+ /* if entered twice, send accent itself */
+ if (last_dead == key->mode & KBD_MODE_ACCMASK)
+ last_dead = 0;
+ else {
+ last_dead = key->mode & KBD_MODE_ACCMASK;
+ splx(s);
+ return -1;
+ }
+ }
+ if(last_dead) {
+ /* can't apply dead flag to string-keys */
+ if (code >= '@' && code < 0x7f)
+ code =
+ acctable[KBD_MODE_ACCENT(last_dead)][code - '@'];
+ last_dead = 0;
+ }
+#endif
+ if(key_mod & KBD_MOD_CTRL)
+ code &= 0x1f;
+
+ /*
+ * Do console mapping.
+ */
+ code = code == '\r' ? '\n' : code;
+
+ splx(s);
+ return (code);
+}
+
+/* And now the old stuff. */
+
+/* these are used to implement repeating keys.. */
+static u_char last_char;
+static u_char tout_pending;
+
+/*ARGSUSED*/
+static void
+
+repeat_handler(arg)
+void *arg;
+{
+ tout_pending = 0;
+ if(last_char)
+ add_sicallback(ite_filter, last_char, ITEFILT_REPEATER);
+}
+
+void
+ite_filter(c, caller)
+u_int c;
+enum caller caller;
+{
+ struct tty *kbd_tty;
+ struct kbdmap *kbdmap;
+ u_char code, *str, up, mask;
+ struct key key;
+ int s, i;
+
+ if(kbd_ite == NULL)
+ return;
+
+ kbd_tty = kbd_ite->tp;
+ kbdmap = kbd_ite->kbdmap;
+
+ up = KBD_RELEASED(c);
+ c = KBD_SCANCODE(c);
+ code = 0;
+ mask = 0;
+
+ /* have to make sure we're at spltty in here */
+ s = spltty();
+
+ /*
+ * keyboard interrupts come at priority 2, while softint
+ * generated keyboard-repeat interrupts come at level 1. So,
+ * to not allow a key-up event to get thru before a repeat for
+ * the key-down, we remove any outstanding callout requests..
+ */
+ rem_sicallback(ite_filter);
+
+
+ /*
+ * Handle special keys
+ */
+ switch(c) {
+ case KBD_LEFT_SHIFT:
+ mask = KBD_MOD_LSHIFT;
+ break;
+ case KBD_RIGHT_SHIFT:
+ mask = KBD_MOD_RSHIFT;
+ break;
+ case KBD_CTRL:
+ mask = KBD_MOD_CTRL;
+ break;
+ case KBD_ALT:
+ mask = KBD_MOD_ALT;
+ break;
+ case KBD_CAPS_LOCK:
+ /* CAPSLOCK is a toggle */
+ if(!up)
+ key_mod ^= KBD_MOD_CAPS;
+ splx(s);
+ return;
+ break;
+ }
+ if(mask) {
+ if(up)
+ key_mod &= ~mask;
+ else
+ key_mod |= mask;
+ splx(s);
+ return;
+ }
+
+ /*
+ * Stop repeating on up event
+ */
+ if (up) {
+ if(tout_pending) {
+ untimeout(repeat_handler, 0);
+ tout_pending = 0;
+ last_char = 0;
+ }
+ splx(s);
+ return;
+ }
+ else if(tout_pending && last_char != c) {
+ /*
+ * Different character, stop also
+ */
+ untimeout(repeat_handler, 0);
+ tout_pending = 0;
+ last_char = 0;
+ }
+
+ /*
+ * Handle ite-switching ALT + Fx
+ */
+ if((key_mod == KBD_MOD_ALT) && (c >= 0x3b) && (c <= 0x44)) {
+ ite_switch(c - 0x3b);
+ splx(s);
+ return;
+ }
+ /*
+ * Safety button, switch back to ascii keymap.
+ */
+ if(key_mod == (KBD_MOD_ALT | KBD_MOD_LSHIFT) && c == 0x3b) {
+ /* ALT + LSHIFT + F1 */
+ bcopy(&ascii_kbdmap, kbdmap, sizeof(struct kbdmap));
+ splx(s);
+ return;
+#ifdef DDB
+ }
+ else if(key_mod == (KBD_MOD_ALT | KBD_MOD_LSHIFT) && c == 0x43) {
+ /* ALT + LSHIFT + F9 */
+ extern int Debugger();
+ Debugger();
+ splx(s);
+ return;
+#endif
+ }
+
+ /*
+ * The rest of the code is senseless when the device is not open.
+ */
+ if(kbd_tty == NULL) {
+ splx(s);
+ return;
+ }
+
+ /*
+ * Translate modifiers
+ */
+ if(key_mod & KBD_MOD_SHIFT) {
+ if(key_mod & KBD_MOD_ALT)
+ key = kbdmap->alt_shift_keys[c];
+ else key = kbdmap->shift_keys[c];
+ }
+ else if(key_mod & KBD_MOD_ALT)
+ key = kbdmap->alt_keys[c];
+ else {
+ key = kbdmap->keys[c];
+ /*
+ * If CAPS and key is CAPable (no pun intended)
+ */
+ if((key_mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
+ key = kbdmap->shift_keys[c];
+ }
+ code = key.code;
+
+ /*
+ * Arrange to repeat the keystroke. By doing this at the level
+ * of scan-codes, we can have function keys, and keys that
+ * send strings, repeat too. This also entitles an additional
+ * overhead, since we have to do the conversion each time, but
+ * I guess that's ok.
+ */
+ if(!tout_pending && caller == ITEFILT_TTY && kbd_ite->key_repeat) {
+ tout_pending = 1;
+ last_char = c;
+ timeout(repeat_handler, 0, start_repeat_timeo * hz / 100);
+ }
+ else if(!tout_pending && caller==ITEFILT_REPEATER
+ && kbd_ite->key_repeat) {
+ tout_pending = 1;
+ last_char = c;
+ timeout(repeat_handler, 0, next_repeat_timeo * hz / 100);
+ }
+ /* handle dead keys */
+ if (key.mode & KBD_MODE_DEAD) {
+ /* if entered twice, send accent itself */
+ if (last_dead == key.mode & KBD_MODE_ACCMASK)
+ last_dead = 0;
+ else {
+ last_dead = key.mode & KBD_MODE_ACCMASK;
+ splx(s);
+ return;
+ }
+ }
+ if (last_dead) {
+ /* can't apply dead flag to string-keys */
+ if (!(key.mode & KBD_MODE_STRING) && code >= '@' &&
+ code < 0x7f)
+ code = acctable[KBD_MODE_ACCENT(last_dead)][code - '@'];
+ last_dead = 0;
+ }
+
+ /*
+ * If not string, apply CTRL modifiers
+ */
+ if(!(key.mode & KBD_MODE_STRING)
+ && (!(key.mode & KBD_MODE_KPAD)
+ || (kbd_ite && !kbd_ite->keypad_appmode))) {
+ if(key_mod & KBD_MOD_CTRL)
+ code &= 0x1f;
+ }
+ else if((key.mode & KBD_MODE_KPAD)
+ && (kbd_ite && kbd_ite->keypad_appmode)) {
+ static char *in = "0123456789-+.\r()/*";
+ static char *out = "pqrstuvwxymlnMPQRS";
+ char *cp = index(in, code);
+
+ /*
+ * keypad-appmode sends SS3 followed by the above
+ * translated character
+ */
+ (*linesw[kbd_tty->t_line].l_rint) (27, kbd_tty);
+ (*linesw[kbd_tty->t_line].l_rint) ('O', kbd_tty);
+ (*linesw[kbd_tty->t_line].l_rint) (out[cp - in], kbd_tty);
+ splx(s);
+ return;
+ } else {
+ /* *NO* I don't like this.... */
+ static u_char app_cursor[] =
+ {
+ 3, 27, 'O', 'A',
+ 3, 27, 'O', 'B',
+ 3, 27, 'O', 'C',
+ 3, 27, 'O', 'D'};
+
+ str = kbdmap->strings + code;
+ /*
+ * if this is a cursor key, AND it has the default
+ * keymap setting, AND we're in app-cursor mode, switch
+ * to the above table. This is *nasty* !
+ */
+ if(((c == 0x48) || (c == 0x4b) || (c == 0x4d) || (c == 0x50))
+ && kbd_ite->cursor_appmode
+ && !bcmp(str, "\x03\x1b[", 3) &&
+ index("ABCD", str[3]))
+ str = app_cursor + 4 * (str[3] - 'A');
+
+ /*
+ * using a length-byte instead of 0-termination allows
+ * to embed \0 into strings, although this is not used
+ * in the default keymap
+ */
+ for (i = *str++; i; i--)
+ (*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
+ splx(s);
+ return;
+ }
+ (*linesw[kbd_tty->t_line].l_rint) (code, kbd_tty);
+
+ splx(s);
+ return;
+}
+
+/* helper functions, makes the code below more readable */
+static void inline
+ite_sendstr(str)
+ char *str;
+{
+ struct tty *kbd_tty;
+
+ kbd_tty = kbd_ite->tp;
+ KDASSERT(kbd_tty);
+ while (*str)
+ (*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
+}
+
+static void
+alignment_display(ip)
+ struct ite_softc *ip;
+{
+ int i, j;
+
+ for (j = 0; j < ip->rows; j++)
+ for (i = 0; i < ip->cols; i++)
+ SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
+ attrclr(ip, 0, 0, ip->rows, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+snap_cury(ip)
+ struct ite_softc *ip;
+{
+ if (ip->inside_margins)
+ {
+ if (ip->cury < ip->top_margin)
+ ip->cury = ip->top_margin;
+ if (ip->cury > ip->bottom_margin)
+ ip->cury = ip->bottom_margin;
+ }
+}
+
+static void inline
+ite_dnchar(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ n = min(n, ip->cols - ip->curx);
+ if (n < ip->cols - ip->curx)
+ {
+ SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
+ attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
+ 1, ip->cols - ip->curx - n);
+ attrclr(ip, ip->cury, ip->cols - n, 1, n);
+ }
+ while (n-- > 0)
+ SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_inchar(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ n = min(n, ip->cols - ip->curx);
+ if (n < ip->cols - ip->curx)
+ {
+ SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
+ attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
+ 1, ip->cols - ip->curx - n);
+ attrclr(ip, ip->cury, ip->curx, 1, n);
+ }
+ while (n--)
+ SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_clrtoeol(ip)
+ struct ite_softc *ip;
+{
+ int y = ip->cury, x = ip->curx;
+ if (ip->cols - x > 0)
+ {
+ SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
+ attrclr(ip, y, x, 1, ip->cols - x);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ }
+}
+
+static void inline
+ite_clrtobol(ip)
+ struct ite_softc *ip;
+{
+ int y = ip->cury, x = min(ip->curx + 1, ip->cols);
+ SUBR_CLEAR(ip, y, 0, 1, x);
+ attrclr(ip, y, 0, 1, x);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_clrline(ip)
+ struct ite_softc *ip;
+{
+ int y = ip->cury;
+ SUBR_CLEAR(ip, y, 0, 1, ip->cols);
+ attrclr(ip, y, 0, 1, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+
+
+static void inline
+ite_clrtoeos(ip)
+ struct ite_softc *ip;
+{
+ ite_clrtoeol(ip);
+ if (ip->cury < ip->rows - 1)
+ {
+ SUBR_CLEAR(ip, ip->cury + 1, 0, ip->rows - 1 - ip->cury, ip->cols);
+ attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ }
+}
+
+static void inline
+ite_clrtobos(ip)
+ struct ite_softc *ip;
+{
+ ite_clrtobol(ip);
+ if (ip->cury > 0)
+ {
+ SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
+ attrclr(ip, 0, 0, ip->cury, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ }
+}
+
+static void inline
+ite_clrscreen(ip)
+ struct ite_softc *ip;
+{
+ SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
+ attrclr(ip, 0, 0, ip->rows, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+
+
+static void inline
+ite_dnline(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ /* interesting.. if the cursor is outside the scrolling
+ region, this command is simply ignored.. */
+ if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
+ return;
+
+ n = min(n, ip->bottom_margin + 1 - ip->cury);
+ if (n <= ip->bottom_margin - ip->cury)
+ {
+ SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
+ attrmov(ip, ip->cury + n, 0, ip->cury, 0,
+ ip->bottom_margin + 1 - ip->cury - n, ip->cols);
+ }
+ SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
+ attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_inline(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ /* interesting.. if the cursor is outside the scrolling
+ region, this command is simply ignored.. */
+ if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
+ return;
+
+ n = min(n, ip->bottom_margin + 1 - ip->cury);
+ if (n <= ip->bottom_margin - ip->cury)
+ {
+ SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
+ attrmov(ip, ip->cury, 0, ip->cury + n, 0,
+ ip->bottom_margin + 1 - ip->cury - n, ip->cols);
+ }
+ SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
+ attrclr(ip, ip->cury, 0, n, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_lf (ip)
+ struct ite_softc *ip;
+{
+ ++ip->cury;
+ if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows))
+ {
+ ip->cury--;
+ SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
+ ite_clrline(ip);
+ }
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr(ip, ATTR_INV);
+}
+
+static void inline
+ite_crlf (ip)
+ struct ite_softc *ip;
+{
+ ip->curx = 0;
+ ite_lf (ip);
+}
+
+static void inline
+ite_cr (ip)
+ struct ite_softc *ip;
+{
+ if (ip->curx)
+ {
+ ip->curx = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+}
+
+static void inline
+ite_rlf (ip)
+ struct ite_softc *ip;
+{
+ ip->cury--;
+ if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1))
+ {
+ ip->cury++;
+ SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
+ ite_clrline(ip);
+ }
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr(ip, ATTR_INV);
+}
+
+static int inline
+atoi (cp)
+ const char *cp;
+{
+ int n;
+
+ for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
+ n = n * 10 + *cp - '0';
+
+ return n;
+}
+
+static char *
+index (cp, ch)
+ const char *cp;
+ int ch;
+{
+ while (*cp && *cp != ch) cp++;
+ return *cp ? (char *) cp : 0;
+}
+
+
+
+static int inline
+ite_argnum (ip)
+ struct ite_softc *ip;
+{
+ char ch;
+ int n;
+
+ /* convert argument string into number */
+ if (ip->ap == ip->argbuf)
+ return 1;
+ ch = *ip->ap;
+ *ip->ap = 0;
+ n = atoi (ip->argbuf);
+ *ip->ap = ch;
+
+ return n;
+}
+
+static int inline
+ite_zargnum (ip)
+ struct ite_softc *ip;
+{
+ char ch, *cp;
+ int n;
+
+ /* convert argument string into number */
+ if (ip->ap == ip->argbuf)
+ return 0;
+ ch = *ip->ap;
+ *ip->ap = 0;
+ n = atoi (ip->argbuf);
+ *ip->ap = ch;
+
+ return n; /* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
+}
+
+static int inline
+strncmp (a, b, l)
+ const char *a, *b;
+ int l;
+{
+ for (;l--; a++, b++)
+ if (*a != *b)
+ return *a - *b;
+ return 0;
+}
+
+void
+ite_putstr(s, len, dev)
+ const u_char *s;
+ int len;
+ dev_t dev;
+{
+ struct ite_softc *ip;
+ int i;
+
+ ip = getitesp(dev);
+
+ /* XXX avoid problems */
+ if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
+ return;
+
+ SUBR_CURSOR(ip, START_CURSOROPT);
+ for (i = 0; i < len; i++)
+ if (s[i])
+ iteputchar(s[i], ip);
+ SUBR_CURSOR(ip, END_CURSOROPT);
+}
+
+
+void
+iteputchar(c, ip)
+ register int c;
+ struct ite_softc *ip;
+{
+ struct tty *kbd_tty;
+ int n, x, y;
+ char *cp;
+
+ if (kbd_ite == NULL)
+ kbd_tty = NULL;
+ else
+ kbd_tty = kbd_ite->tp;
+
+ if (ip->escape)
+ {
+doesc:
+ switch (ip->escape)
+ {
+ case ESC:
+ switch (c)
+ {
+ /* first 7bit equivalents for the 8bit control characters */
+
+ case 'D':
+ c = IND;
+ ip->escape = 0;
+ break; /* and fall into the next switch below (same for all `break') */
+
+ case 'E':
+ c = NEL;
+ ip->escape = 0;
+ break;
+
+ case 'H':
+ c = HTS;
+ ip->escape = 0;
+ break;
+
+ case 'M':
+ c = RI;
+ ip->escape = 0;
+ break;
+
+ case 'N':
+ c = SS2;
+ ip->escape = 0;
+ break;
+
+ case 'O':
+ c = SS3;
+ ip->escape = 0;
+ break;
+
+ case 'P':
+ c = DCS;
+ ip->escape = 0;
+ break;
+
+ case '[':
+ c = CSI;
+ ip->escape = 0;
+ break;
+
+ case '\\':
+ c = ST;
+ ip->escape = 0;
+ break;
+
+ case ']':
+ c = OSC;
+ ip->escape = 0;
+ break;
+
+ case '^':
+ c = PM;
+ ip->escape = 0;
+ break;
+
+ case '_':
+ c = APC;
+ ip->escape = 0;
+ break;
+
+
+ /* introduces 7/8bit control */
+ case ' ':
+ /* can be followed by either F or G */
+ ip->escape = ' ';
+ break;
+
+
+ /* a lot of character set selections, not yet used...
+ 94-character sets: */
+ case '(': /* G0 */
+ case ')': /* G1 */
+ ip->escape = c;
+ return;
+
+ case '*': /* G2 */
+ case '+': /* G3 */
+ case 'B': /* ASCII */
+ case 'A': /* ISO latin 1 */
+ case '<': /* user preferred suplemental */
+ case '0': /* dec special graphics */
+
+ /* 96-character sets: */
+ case '-': /* G1 */
+ case '.': /* G2 */
+ case '/': /* G3 */
+
+ /* national character sets: */
+ case '4': /* dutch */
+ case '5':
+ case 'C': /* finnish */
+ case 'R': /* french */
+ case 'Q': /* french canadian */
+ case 'K': /* german */
+ case 'Y': /* italian */
+ case '6': /* norwegian/danish */
+ /* note: %5 and %6 are not supported (two chars..) */
+
+ ip->escape = 0;
+ /* just ignore for now */
+ return;
+
+
+ /* locking shift modes (as you might guess, not yet supported..) */
+ case '`':
+ ip->GR = ip->G1;
+ ip->escape = 0;
+ return;
+
+ case 'n':
+ ip->GL = ip->G2;
+ ip->escape = 0;
+ return;
+
+ case '}':
+ ip->GR = ip->G2;
+ ip->escape = 0;
+ return;
+
+ case 'o':
+ ip->GL = ip->G3;
+ ip->escape = 0;
+ return;
+
+ case '|':
+ ip->GR = ip->G3;
+ ip->escape = 0;
+ return;
+
+
+ /* font width/height control */
+ case '#':
+ ip->escape = '#';
+ return;
+
+
+ /* hard terminal reset .. */
+ case 'c':
+ ite_reset (ip);
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ ip->escape = 0;
+ return;
+
+
+ case '7':
+ ip->save_curx = ip->curx;
+ ip->save_cury = ip->cury;
+ ip->save_attribute = ip->attribute;
+ ip->escape = 0;
+ return;
+
+ case '8':
+ ip->curx = ip->save_curx;
+ ip->cury = ip->save_cury;
+ ip->attribute = ip->save_attribute;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ ip->escape = 0;
+ return;
+
+ case '=':
+ ip->keypad_appmode = 1;
+ ip->escape = 0;
+ return;
+
+ case '>':
+ ip->keypad_appmode = 0;
+ ip->escape = 0;
+ return;
+
+ case 'Z': /* request ID */
+ if (ip->emul_level == EMUL_VT100)
+ ite_sendstr ("\033[?61;0c"); /* XXX not clean */
+ else
+ ite_sendstr ("\033[?63;0c"); /* XXX not clean */
+ ip->escape = 0;
+ return;
+
+ /* default catch all for not recognized ESC sequences */
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+ case '(':
+ case ')':
+ ip->escape = 0;
+ return;
+
+
+ case ' ':
+ switch (c)
+ {
+ case 'F':
+ ip->eightbit_C1 = 0;
+ ip->escape = 0;
+ return;
+
+ case 'G':
+ ip->eightbit_C1 = 1;
+ ip->escape = 0;
+ return;
+
+ default:
+ /* not supported */
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+ case '#':
+ switch (c)
+ {
+ case '5':
+ /* single height, single width */
+ ip->escape = 0;
+ return;
+
+ case '6':
+ /* double width, single height */
+ ip->escape = 0;
+ return;
+
+ case '3':
+ /* top half */
+ ip->escape = 0;
+ return;
+
+ case '4':
+ /* bottom half */
+ ip->escape = 0;
+ return;
+
+ case '8':
+ /* screen alignment pattern... */
+ alignment_display (ip);
+ ip->escape = 0;
+ return;
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+
+ case CSI:
+ /* the biggie... */
+ switch (c)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case ';': case '\"': case '$': case '>':
+ if (ip->ap < ip->argbuf + MAX_ARGSIZE)
+ *ip->ap++ = c;
+ return;
+
+ case BS:
+ /* you wouldn't believe such perversion is possible?
+ it is.. BS is allowed in between cursor sequences
+ (at least), according to vttest.. */
+ if (--ip->curx < 0)
+ ip->curx = 0;
+ else
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+
+ case 'p':
+ *ip->ap = 0;
+ if (! strncmp (ip->argbuf, "61\"", 3))
+ ip->emul_level = EMUL_VT100;
+ else if (! strncmp (ip->argbuf, "63;1\"", 5)
+ || ! strncmp (ip->argbuf, "62;1\"", 5))
+ ip->emul_level = EMUL_VT300_7;
+ else
+ ip->emul_level = EMUL_VT300_8;
+ ip->escape = 0;
+ return;
+
+
+ case '?':
+ *ip->ap = 0;
+ ip->escape = '?';
+ ip->ap = ip->argbuf;
+ return;
+
+
+ case 'c':
+ *ip->ap = 0;
+ if (ip->argbuf[0] == '>')
+ {
+ ite_sendstr ("\033[>24;0;0;0c");
+ }
+ else switch (ite_zargnum(ip))
+ {
+ case 0:
+ /* primary DA request, send primary DA response */
+ if (ip->emul_level == EMUL_VT100)
+ ite_sendstr ("\033[?1;1c");
+ else
+ ite_sendstr ("\033[?63;1c");
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+ case 'n':
+ switch (ite_zargnum(ip))
+ {
+ case 5:
+ ite_sendstr ("\033[0n"); /* no malfunction */
+ break;
+ case 6:
+ /* cursor position report */
+ sprintf (ip->argbuf, "\033[%d;%dR",
+ ip->cury + 1, ip->curx + 1);
+ ite_sendstr (ip->argbuf);
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'x':
+ switch (ite_zargnum(ip))
+ {
+ case 0:
+ /* Fake some terminal parameters. */
+ ite_sendstr ("\033[2;1;1;112;112;1;0x");
+ break;
+ case 1:
+ ite_sendstr ("\033[3;1;1;112;112;1;0x");
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'g':
+ switch (ite_zargnum(ip))
+ {
+ case 0:
+ if (ip->curx < ip->cols)
+ ip->tabs[ip->curx] = 0;
+ break;
+ case 3:
+ for (n = 0; n < ip->cols; n++)
+ ip->tabs[n] = 0;
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'h': case 'l':
+ n = ite_zargnum (ip);
+ switch (n)
+ {
+ case 4:
+ ip->imode = (c == 'h'); /* insert/replace mode */
+ break;
+ case 20:
+ ip->linefeed_newline = (c == 'h');
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'M':
+ ite_dnline (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case 'L':
+ ite_inline (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case 'P':
+ ite_dnchar (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case '@':
+ ite_inchar (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case 'G':
+ /* this one was *not* in my vt320 manual but in
+ a vt320 termcap entry.. who is right?
+ It's supposed to set the horizontal cursor position. */
+ *ip->ap = 0;
+ x = atoi (ip->argbuf);
+ if (x) x--;
+ ip->curx = min(x, ip->cols - 1);
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+
+ case 'd':
+ /* same thing here, this one's for setting the absolute
+ vertical cursor position. Not documented... */
+ *ip->ap = 0;
+ y = atoi (ip->argbuf);
+ if (y) y--;
+ if (ip->inside_margins)
+ y += ip->top_margin;
+ ip->cury = min(y, ip->rows - 1);
+ ip->escape = 0;
+ snap_cury(ip);
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+
+ case 'H':
+ case 'f':
+ *ip->ap = 0;
+ y = atoi (ip->argbuf);
+ x = 0;
+ cp = index (ip->argbuf, ';');
+ if (cp)
+ x = atoi (cp + 1);
+ if (x) x--;
+ if (y) y--;
+ if (ip->inside_margins)
+ y += ip->top_margin;
+ ip->cury = min(y, ip->rows - 1);
+ ip->curx = min(x, ip->cols - 1);
+ ip->escape = 0;
+ snap_cury(ip);
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'A':
+ n = ite_argnum (ip);
+ n = ip->cury - (n ? n : 1);
+ if (n < 0) n = 0;
+ if (ip->inside_margins)
+ n = max(ip->top_margin, n);
+ else if (n == ip->top_margin - 1)
+ /* allow scrolling outside region, but don't scroll out
+ of active region without explicit CUP */
+ n = ip->top_margin;
+ ip->cury = n;
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'B':
+ n = ite_argnum (ip);
+ n = ip->cury + (n ? n : 1);
+ n = min(ip->rows - 1, n);
+ if (ip->inside_margins)
+ n = min(ip->bottom_margin, n);
+ else if (n == ip->bottom_margin + 1)
+ /* allow scrolling outside region, but don't scroll out
+ of active region without explicit CUP */
+ n = ip->bottom_margin;
+ ip->cury = n;
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'C':
+ n = ite_argnum (ip);
+ n = n ? n : 1;
+ ip->curx = min(ip->curx + n, ip->cols - 1);
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'D':
+ n = ite_argnum (ip);
+ n = n ? n : 1;
+ n = ip->curx - n;
+ ip->curx = n >= 0 ? n : 0;
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+
+
+
+ case 'J':
+ *ip->ap = 0;
+ n = ite_zargnum (ip);
+ if (n == 0)
+ ite_clrtoeos(ip);
+ else if (n == 1)
+ ite_clrtobos(ip);
+ else if (n == 2)
+ ite_clrscreen(ip);
+ ip->escape = 0;
+ return;
+
+
+ case 'K':
+ n = ite_zargnum (ip);
+ if (n == 0)
+ ite_clrtoeol(ip);
+ else if (n == 1)
+ ite_clrtobol(ip);
+ else if (n == 2)
+ ite_clrline(ip);
+ ip->escape = 0;
+ return;
+
+
+ case 'X':
+ n = ite_argnum(ip) - 1;
+ n = min(n, ip->cols - 1 - ip->curx);
+ for (; n >= 0; n--)
+ {
+ attrclr(ip, ip->cury, ip->curx + n, 1, 1);
+ SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
+ }
+ ip->escape = 0;
+ return;
+
+
+ case '}': case '`':
+ /* status line control */
+ ip->escape = 0;
+ return;
+
+
+ case 'r':
+ *ip->ap = 0;
+ x = atoi (ip->argbuf);
+ x = x ? x : 1;
+ y = ip->rows;
+ cp = index (ip->argbuf, ';');
+ if (cp)
+ {
+ y = atoi (cp + 1);
+ y = y ? y : ip->rows;
+ }
+ if (y - x < 2)
+ {
+ /* if illegal scrolling region, reset to defaults */
+ x = 1;
+ y = ip->rows;
+ }
+ x--;
+ y--;
+ ip->top_margin = min(x, ip->rows - 1);
+ ip->bottom_margin = min(y, ip->rows - 1);
+ if (ip->inside_margins)
+ {
+ ip->cury = ip->top_margin;
+ ip->curx = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'm':
+ /* big attribute setter/resetter */
+ {
+ char *cp;
+ *ip->ap = 0;
+ /* kludge to make CSIm work (== CSI0m) */
+ if (ip->ap == ip->argbuf)
+ ip->ap++;
+ for (cp = ip->argbuf; cp < ip->ap; )
+ {
+ switch (*cp)
+ {
+ case 0:
+ case '0':
+ clr_attr (ip, ATTR_ALL);
+ cp++;
+ break;
+
+ case '1':
+ set_attr (ip, ATTR_BOLD);
+ cp++;
+ break;
+
+ case '2':
+ switch (cp[1])
+ {
+ case '2':
+ clr_attr (ip, ATTR_BOLD);
+ cp += 2;
+ break;
+
+ case '4':
+ clr_attr (ip, ATTR_UL);
+ cp += 2;
+ break;
+
+ case '5':
+ clr_attr (ip, ATTR_BLINK);
+ cp += 2;
+ break;
+
+ case '7':
+ clr_attr (ip, ATTR_INV);
+ cp += 2;
+ break;
+
+ default:
+ cp++;
+ break;
+ }
+ break;
+
+ case '4':
+ set_attr (ip, ATTR_UL);
+ cp++;
+ break;
+
+ case '5':
+ set_attr (ip, ATTR_BLINK);
+ cp++;
+ break;
+
+ case '7':
+ set_attr (ip, ATTR_INV);
+ cp++;
+ break;
+
+ default:
+ cp++;
+ break;
+ }
+ }
+
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'u':
+ /* DECRQTSR */
+ ite_sendstr ("\033P\033\\");
+ ip->escape = 0;
+ return;
+
+
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+
+ case '?': /* CSI ? */
+ switch (c)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case ';': case '\"': case '$':
+ /* Don't fill the last character; it's needed. */
+ /* XXX yeah, where ?? */
+ if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
+ *ip->ap++ = c;
+ return;
+
+
+ case 'n':
+ *ip->ap = 0;
+ if (ip->ap == &ip->argbuf[2])
+ {
+ if (! strncmp (ip->argbuf, "15", 2))
+ /* printer status: no printer */
+ ite_sendstr ("\033[13n");
+
+ else if (! strncmp (ip->argbuf, "25", 2))
+ /* udk status */
+ ite_sendstr ("\033[20n");
+
+ else if (! strncmp (ip->argbuf, "26", 2))
+ /* keyboard dialect: US */
+ ite_sendstr ("\033[27;1n");
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'h': case 'l':
+ n = ite_zargnum (ip);
+ switch (n)
+ {
+ case 1:
+ ip->cursor_appmode = (c == 'h');
+ break;
+
+ case 3:
+ /* 132/80 columns (132 == 'h') */
+ break;
+
+ case 4: /* smooth scroll */
+ break;
+
+ case 5:
+ /* light background (=='h') /dark background(=='l') */
+ break;
+
+ case 6: /* origin mode */
+ ip->inside_margins = (c == 'h');
+ ip->curx = 0;
+ ip->cury = ip->inside_margins ? ip->top_margin : 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+
+ case 7: /* auto wraparound */
+ ip->auto_wrap = (c == 'h');
+ break;
+
+ case 8: /* keyboard repeat */
+ ip->key_repeat = (c == 'h');
+ break;
+
+ case 20: /* newline mode */
+ ip->linefeed_newline = (c == 'h');
+ break;
+
+ case 25: /* cursor on/off */
+ SUBR_CURSOR(ip, (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ }
+
+ switch (c) {
+
+ case VT: /* VT is treated like LF */
+ case FF: /* so is FF */
+ case LF:
+ /* cr->crlf distinction is done here, on output,
+ not on input! */
+ if (ip->linefeed_newline)
+ ite_crlf (ip);
+ else
+ ite_lf (ip);
+ break;
+
+ case CR:
+ ite_cr (ip);
+ break;
+
+ case BS:
+ if (--ip->curx < 0)
+ ip->curx = 0;
+ else
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+
+ case HT:
+ for (n = ip->curx + 1; n < ip->cols; n++) {
+ if (ip->tabs[n]) {
+ ip->curx = n;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+ }
+ }
+ break;
+
+ case BEL:
+ if(kbd_tty && kbd_ite && kbd_ite->tp == kbd_tty)
+ kbdbell();
+ break;
+
+ case SO:
+ ip->GL = ip->G1;
+ break;
+
+ case SI:
+ ip->GL = ip->G0;
+ break;
+
+ case ENQ:
+ /* send answer-back message !! */
+ break;
+
+ case CAN:
+ ip->escape = 0; /* cancel any escape sequence in progress */
+ break;
+
+ case SUB:
+ ip->escape = 0; /* dito, but see below */
+ /* should also display a reverse question mark!! */
+ break;
+
+ case ESC:
+ ip->escape = ESC;
+ break;
+
+
+ /* now it gets weird.. 8bit control sequences.. */
+ case IND: /* index: move cursor down, scroll */
+ ite_lf (ip);
+ break;
+
+ case NEL: /* next line. next line, first pos. */
+ ite_crlf (ip);
+ break;
+
+ case HTS: /* set horizontal tab */
+ if (ip->curx < ip->cols)
+ ip->tabs[ip->curx] = 1;
+ break;
+
+ case RI: /* reverse index */
+ ite_rlf (ip);
+ break;
+
+ case SS2: /* go into G2 for one character */
+ /* not yet supported */
+ break;
+
+ case SS3: /* go into G3 for one character */
+ break;
+
+ case DCS: /* device control string introducer */
+ ip->escape = DCS;
+ ip->ap = ip->argbuf;
+ break;
+
+ case CSI: /* control sequence introducer */
+ ip->escape = CSI;
+ ip->ap = ip->argbuf;
+ break;
+
+ case ST: /* string terminator */
+ /* ignore, if not used as terminator */
+ break;
+
+ case OSC: /* introduces OS command. Ignore everything upto ST */
+ ip->escape = OSC;
+ break;
+
+ case PM: /* privacy message, ignore everything upto ST */
+ ip->escape = PM;
+ break;
+
+ case APC: /* application program command, ignore everything upto ST */
+ ip->escape = APC;
+ break;
+
+ default:
+ if (c < ' ' || c == DEL)
+ break;
+ if (ip->imode)
+ ite_inchar(ip, 1);
+ iteprecheckwrap(ip);
+#ifdef DO_WEIRD_ATTRIBUTES
+ if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
+ attrset(ip, ATTR_INV);
+ SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
+ }
+ else
+ SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
+#else
+ SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
+#endif
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ itecheckwrap(ip);
+ break;
+ }
+}
+
+iteprecheckwrap(ip)
+ struct ite_softc *ip;
+{
+ if (ip->auto_wrap && ip->curx == ip->cols) {
+ ip->curx = 0;
+ clr_attr(ip, ATTR_INV);
+ if (++ip->cury >= ip->bottom_margin + 1) {
+ ip->cury = ip->bottom_margin;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
+ ite_clrtoeol(ip);
+ } else
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+}
+
+itecheckwrap(ip)
+ struct ite_softc *ip;
+{
+ if (ip->curx < ip->cols) {
+ ip->curx++;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+}
diff --git a/sys/arch/atari/dev/ite_cc.c b/sys/arch/atari/dev/ite_cc.c
new file mode 100644
index 00000000000..676c499e061
--- /dev/null
+++ b/sys/arch/atari/dev/ite_cc.c
@@ -0,0 +1,671 @@
+/* $NetBSD: ite_cc.c,v 1.4 1995/05/28 19:45:39 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "grf.h"
+#if NGRF > 0
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/termios.h>
+#include <sys/malloc.h>
+#include <dev/cons.h>
+#include <machine/cpu.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/iteioctl.h>
+#include <atari/dev/grfioctl.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/grfvar.h>
+#include <atari/dev/font.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+
+/*
+ * This is what ip->priv points to;
+ * it contains local variables for custom-chip ites.
+ */
+struct ite_priv {
+ u_char **row_ptr; /* array of pointers into the bitmap */
+ u_long row_bytes;
+ u_long cursor_opt;
+ u_short *column_offset; /* array of offsets for columns */
+ u_int row_offset; /* the row offset */
+ u_short width; /* the bitmap width */
+ u_short underline; /* where the underline goes */
+ u_short ft_x; /* the font width */
+ u_short ft_y; /* the font height */
+ u_char *font_cell[256];/* the font pointer */
+};
+typedef struct ite_priv ipriv_t;
+
+/*
+ * We need the following space to get an ite-console setup before
+ * the VM-system is brought up. We setup for a 1280x960 monitor with
+ * an 8x8 font.
+ */
+extern int atari_realconfig;
+
+#define CONS_MAXROW 120 /* Max. number of rows on console */
+#define CONS_MAXCOL 160 /* Max. number of columns on console */
+static u_short con_columns[CONS_MAXCOL];
+static u_char *con_rows[CONS_MAXROW];
+static ipriv_t con_ipriv;
+
+extern font_info font_info_8x8;
+extern font_info font_info_8x16;
+
+static void view_init __P((struct ite_softc *));
+static void view_deinit __P((struct ite_softc *));
+static int ite_newsize __P((struct ite_softc *, struct itewinsize *));
+static void cursor32 __P((struct ite_softc *, int));
+static void putc8 __P((struct ite_softc *, int, int, int, int));
+static void clear8 __P((struct ite_softc *, int, int, int, int));
+static void scroll8 __P((struct ite_softc *, int, int, int, int));
+static void scrollbmap __P((bmap_t *, u_short, u_short, u_short, u_short,
+ short, short));
+
+/*
+ * Patchable
+ */
+int ite_default_x = 0; /* def leftedge offset */
+int ite_default_y = 0; /* def topedge offset */
+int ite_default_width = 640; /* def width */
+int ite_default_depth = 1; /* def depth */
+int ite_default_height = 400; /* def height */
+
+/*
+ * called from grf_cc to return console priority
+ */
+int
+grfcc_cnprobe()
+{
+ return(CN_INTERNAL);
+}
+/*
+ * called from grf_cc to init ite portion of
+ * grf_softc struct
+ */
+void
+grfcc_iteinit(gp)
+struct grf_softc *gp;
+{
+
+ gp->g_itecursor = cursor32;
+ gp->g_iteputc = putc8;
+ gp->g_iteclear = clear8;
+ gp->g_itescroll = scroll8;
+ gp->g_iteinit = view_init;
+ gp->g_itedeinit = view_deinit;
+}
+
+static void
+view_deinit(ip)
+struct ite_softc *ip;
+{
+ ip->flags &= ~ITE_INITED;
+}
+
+static void
+view_init(ip)
+register struct ite_softc *ip;
+{
+ struct itewinsize wsz;
+ ipriv_t *cci;
+
+ if(cci = ip->priv)
+ return;
+
+#if defined(KFONT_8X8)
+ ip->font = font_info_8x8;
+#else
+ ip->font = font_info_8x16;
+#endif
+
+ /* Find the correct set of rendering routines for this font. */
+ if(ip->font.width != 8)
+ panic("kernel font size not supported");
+
+ if(!atari_realconfig)
+ ip->priv = cci = &con_ipriv;
+ else ip->priv = cci = (ipriv_t*)malloc(sizeof(*cci), M_DEVBUF,M_WAITOK);
+ if(cci == NULL)
+ panic("No memory for ite-view");
+ bzero(cci, sizeof(*cci));
+
+ cci->cursor_opt = 0;
+ cci->row_ptr = NULL;
+ cci->column_offset = NULL;
+
+ wsz.x = ite_default_x;
+ wsz.y = ite_default_y;
+ wsz.width = ite_default_width;
+ wsz.height = ite_default_height;
+ wsz.depth = ite_default_depth;
+
+ ite_newsize (ip, &wsz);
+
+ /*
+ * Only console will be turned on by default..
+ */
+ if(ip->flags & ITE_ISCONS)
+ ip->grf->g_mode(ip->grf, GM_GRFON, NULL, 0, 0);
+}
+
+static int
+ite_newsize(ip, winsz)
+struct ite_softc *ip;
+struct itewinsize *winsz;
+{
+ struct view_size vs;
+ ipriv_t *cci = ip->priv;
+ u_long fbp, i, j;
+ int error = 0;
+ view_t *view;
+
+ vs.x = winsz->x;
+ vs.y = winsz->y;
+ vs.width = winsz->width;
+ vs.height = winsz->height;
+ vs.depth = winsz->depth;
+
+ error = viewioctl(ip->grf->g_viewdev, VIOCSSIZE, &vs, 0, -1);
+ view = viewview(ip->grf->g_viewdev);
+
+ /*
+ * Reinitialize our structs
+ */
+ ip->cols = view->display.width / ip->font.width;
+ ip->rows = view->display.height / ip->font.height;
+
+ /*
+ * save new values so that future opens use them
+ * this may not be correct when we implement Virtual Consoles
+ */
+ ite_default_height = view->display.height;
+ ite_default_width = view->display.width;
+ ite_default_x = view->display.x;
+ ite_default_y = view->display.y;
+ ite_default_depth = view->bitmap->depth;
+
+ if(cci->row_ptr && (cci->row_ptr != con_rows)) {
+ free(cci->row_ptr, M_DEVBUF);
+ cci->row_ptr = NULL;
+ }
+ if(cci->column_offset && (cci->column_offset != con_columns)) {
+ free(cci->column_offset, M_DEVBUF);
+ cci->column_offset = NULL;
+ }
+
+ if(!atari_realconfig) {
+ cci->row_ptr = con_rows;
+ cci->column_offset = con_columns;
+ }
+ else {
+ cci->row_ptr = malloc(sizeof(u_char *) * ip->rows,M_DEVBUF,M_NOWAIT);
+ cci->column_offset = malloc(sizeof(u_int)*ip->cols,M_DEVBUF,M_NOWAIT);
+ }
+
+ if(!cci->row_ptr || !cci->column_offset)
+ panic("No memory for ite-view");
+
+ cci->width = view->bitmap->bytes_per_row << 3;
+ cci->underline = ip->font.baseline + 1;
+ cci->row_offset = view->bitmap->bytes_per_row;
+ cci->ft_x = ip->font.width;
+ cci->ft_y = ip->font.height;
+ cci->row_bytes = cci->row_offset * cci->ft_y;
+ cci->row_ptr[0] = view->bitmap->plane;
+ for(i = 1; i < ip->rows; i++)
+ cci->row_ptr[i] = cci->row_ptr[i-1] + cci->row_bytes;
+
+ /*
+ * Initialize the column offsets to point at the correct location
+ * in the first plane. This definitely assumes a font width of 8!
+ */
+ j = view->bitmap->depth * 2;
+ cci->column_offset[0] = 0;
+ for(i = 1; i < ip->cols; i++)
+ cci->column_offset[i] = ((i >> 1) * j) + (i & 1);
+
+ /* initialize the font cell pointers */
+ cci->font_cell[ip->font.font_lo] = ip->font.font_p;
+ for(i = ip->font.font_lo+1; i <= ip->font.font_hi; i++)
+ cci->font_cell[i] = cci->font_cell[i-1] + ip->font.height;
+
+ return(error);
+}
+
+int
+ite_grf_ioctl(ip, cmd, addr, flag, p)
+struct ite_softc *ip;
+u_long cmd;
+caddr_t addr;
+int flag;
+struct proc *p;
+{
+ struct winsize ws;
+ struct itewinsize *is;
+ struct itebell *ib;
+ int error = 0;
+ ipriv_t *cci = ip->priv;
+ view_t *view = viewview(ip->grf->g_viewdev);
+
+ switch (cmd) {
+ case ITEIOCGWINSZ:
+ is = (struct itewinsize *)addr;
+ is->x = view->display.x;
+ is->y = view->display.y;
+ is->width = view->display.width;
+ is->height = view->display.height;
+ is->depth = view->bitmap->depth;
+ break;
+ case ITEIOCSWINSZ:
+ is = (struct itewinsize *)addr;
+
+ if(ite_newsize(ip, is))
+ error = ENOMEM;
+ else {
+ view = viewview(ip->grf->g_viewdev);
+ ws.ws_row = ip->rows;
+ ws.ws_col = ip->cols;
+ ws.ws_xpixel = view->display.width;
+ ws.ws_ypixel = view->display.height;
+ ite_reset(ip);
+ /*
+ * XXX tell tty about the change
+ * XXX this is messy, but works
+ */
+ iteioctl(ip->grf->g_itedev,TIOCSWINSZ,(caddr_t)&ws,0,p);
+ }
+ break;
+ case ITEIOCDSPWIN:
+ ip->grf->g_mode(ip->grf, GM_GRFON, NULL, 0, 0);
+ break;
+ case ITEIOCREMWIN:
+ ip->grf->g_mode(ip->grf, GM_GRFOFF, NULL, 0, 0);
+ break;
+ case ITEIOCGBELL:
+#if 0 /* LWP */
+ /* XXX This won't work now */
+ /* XXX Should the bell be device dependent? */
+ ib = (struct itebell *)addr;
+ ib->volume = bvolume;
+ ib->pitch = bpitch;
+ ib->msec = bmsec;
+#endif
+ break;
+ case ITEIOCSBELL:
+#if 0 /* LWP */
+ /* XXX See above */
+ ib = (struct itebell *)addr;
+ /* bounds check */
+ if(ib->pitch > MAXBPITCH || ib->pitch < MINBPITCH ||
+ ib->volume > MAXBVOLUME || ib->msec > MAXBTIME)
+ error = EINVAL;
+ else {
+ bvolume = ib->volume;
+ bpitch = ib->pitch;
+ bmsec = ib->msec;
+ }
+#endif
+ break;
+ case VIOCSCMAP:
+ case VIOCGCMAP:
+ /*
+ * XXX watchout for that -1 its not really the kernel talking
+ * XXX these two commands don't use the proc pointer though
+ */
+ error = viewioctl(ip->grf->g_viewdev, cmd, addr, flag, -1);
+ break;
+ default:
+ error = -1;
+ break;
+ }
+ return (error);
+}
+
+static void
+cursor32(struct ite_softc *ip, int flag)
+{
+ int cend;
+ u_char *pl;
+ ipriv_t *cci;
+
+ cci = ip->priv;
+
+ if(flag == END_CURSOROPT)
+ cci->cursor_opt--;
+ else if(flag == START_CURSOROPT) {
+ if(!cci->cursor_opt)
+ cursor32(ip, ERASE_CURSOR);
+ cci->cursor_opt++;
+ return; /* if we are already opted. */
+ }
+
+ if(cci->cursor_opt)
+ return; /* if we are still nested. */
+ /* else we draw the cursor. */
+
+ if(flag != DRAW_CURSOR && flag != END_CURSOROPT) {
+ /*
+ * erase the cursor
+ */
+ cend = ip->font.height-1;
+ pl = cci->column_offset[ip->cursorx]
+ + cci->row_ptr[ip->cursory];
+ __asm__ __volatile__
+ ("1: notb %0@ ; addaw %4,%0\n\t"
+ "dbra %1,1b"
+ : "=a" (pl), "=d" (cend)
+ : "0" (pl), "1" (cend),
+ "d" (cci->row_offset)
+ );
+ }
+
+ if(flag != DRAW_CURSOR && flag != MOVE_CURSOR && flag != END_CURSOROPT)
+ return;
+
+ /*
+ * draw the cursor
+ */
+ ip->cursorx = min(ip->curx, ip->cols-1);
+ ip->cursory = ip->cury;
+ cend = ip->font.height-1;
+ pl = cci->column_offset[ip->cursorx]
+ + cci->row_ptr[ip->cursory];
+
+ __asm__ __volatile__
+ ("1: notb %0@ ; addaw %4,%0\n\t"
+ "dbra %1,1b"
+ : "=a" (pl), "=d" (cend)
+ : "0" (pl), "1" (cend),
+ "d" (cci->row_offset)
+ );
+}
+
+static void
+putc8(struct ite_softc *ip, int c, int dy, int dx, int mode)
+{
+ register ipriv_t *cci = (ipriv_t *)ip->priv;
+ register u_char *pl = cci->column_offset[dx] + cci->row_ptr[dy];
+ register u_int fh = cci->ft_y;
+ register u_int ro = cci->row_offset;
+ register u_char eor_mask;
+ register u_char bl, tmp, ul;
+ register u_char *ft;
+
+ if(c < ip->font.font_lo || c > ip->font.font_hi)
+ return;
+
+ ft = cci->font_cell[c];
+
+ if(!mode) {
+ while(fh--) {
+ *pl = *ft++; pl += ro;
+ }
+ return;
+ }
+
+ eor_mask = (mode & ATTR_INV) ? 0xff : 0x00;
+ bl = (mode & ATTR_BOLD) ? 1 : 0;
+ ul = (mode & ATTR_UL) ? fh - cci->underline : fh;
+ for(; fh--; pl += ro) {
+ if(fh != ul) {
+ tmp = *ft++;
+ if(bl)
+ tmp |= (tmp >> 1);
+ *pl = tmp ^ eor_mask;
+ }
+ else {
+ *pl = 0xff ^ eor_mask;
+ ft++;
+ }
+ }
+}
+
+static void
+clear8(struct ite_softc *ip, int sy, int sx, int h, int w)
+{
+ ipriv_t *cci = (ipriv_t *) ip->priv;
+ view_t *v = viewview(ip->grf->g_viewdev);
+ bmap_t *bm = v->bitmap;
+
+ if((sx == 0) && (w == ip->cols)) {
+ /* common case: clearing whole lines */
+ while (h--) {
+ int i;
+ u_char *ptr = cci->row_ptr[sy];
+ for(i = 0; i < ip->font.height; i++) {
+ bzero(ptr, bm->bytes_per_row);
+ ptr += bm->bytes_per_row;
+ }
+ sy++;
+ }
+ }
+ else {
+ /*
+ * clearing only part of a line
+ * XXX could be optimized MUCH better, but is it worth the
+ * trouble?
+ */
+
+ int i;
+ u_char *pls, *ple;
+
+ pls = cci->row_ptr[sy];
+ ple = pls + cci->column_offset[sx + w-1];
+ pls = pls + cci->column_offset[sx];
+
+ for(i = ((ip->font.height) * h)-1; i >= 0; i--) {
+ u_char *p = pls;
+ while(p <= ple)
+ *p++ = 0;
+ pls += bm->bytes_per_row;
+ ple += bm->bytes_per_row;
+ }
+ }
+}
+
+/* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT. */
+static void
+scroll8(ip, sy, sx, count, dir)
+register struct ite_softc *ip;
+register int sy;
+int dir, sx, count;
+{
+ bmap_t *bm = viewview(ip->grf->g_viewdev)->bitmap;
+ u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy];
+
+ if(dir == SCROLL_UP) {
+ int dy = sy - count;
+ int height = ip->bottom_margin - sy + 1;
+ int i;
+
+ cursor32(ip, ERASE_CURSOR);
+ scrollbmap(bm, 0, dy*ip->font.height, bm->bytes_per_row >> 3,
+ (ip->bottom_margin-dy+1)*ip->font.height,
+ 0, -(count*ip->font.height));
+ }
+ else if(dir == SCROLL_DOWN) {
+ int dy = sy + count;
+ int height = ip->bottom_margin - dy + 1;
+ int i;
+
+ cursor32(ip, ERASE_CURSOR);
+ scrollbmap(bm, 0, sy*ip->font.height, bm->bytes_per_row >> 3,
+ (ip->bottom_margin-sy+1)*ip->font.height,
+ 0, count*ip->font.height);
+ }
+ else if(dir == SCROLL_RIGHT) {
+ int sofs = (ip->cols - count) * ip->font.width;
+ int dofs = (ip->cols) * ip->font.width;
+ int i, j;
+
+ cursor32(ip, ERASE_CURSOR);
+ for(j = ip->font.height-1; j >= 0; j--) {
+ int sofs2 = sofs, dofs2 = dofs;
+ for (i = (ip->cols - (sx + count))-1; i >= 0; i--) {
+ int t;
+ sofs2 -= ip->font.width;
+ dofs2 -= ip->font.width;
+ asm("bfextu %1@{%2:%3},%0" : "=d" (t)
+ : "a" (pl), "d" (sofs2), "d" (ip->font.width));
+ asm("bfins %3,%0@{%1:%2}" :
+ : "a" (pl), "d" (dofs2), "d" (ip->font.width),
+ "d" (t));
+ }
+ pl += bm->bytes_per_row;
+ }
+ }
+ else { /* SCROLL_LEFT */
+ int sofs = (sx) * ip->font.width;
+ int dofs = (sx - count) * ip->font.width;
+ int i, j;
+
+ cursor32(ip, ERASE_CURSOR);
+ for(j = ip->font.height-1; j >= 0; j--) {
+ int sofs2 = sofs, dofs2 = dofs;
+ for(i = (ip->cols - sx)-1; i >= 0; i--) {
+ int t;
+
+ asm("bfextu %1@{%2:%3},%0" : "=d" (t)
+ : "a" (pl), "d" (sofs2), "d" (ip->font.width));
+ asm("bfins %3,%0@{%1:%2}"
+ : : "a" (pl), "d" (dofs2),"d" (ip->font.width),
+ "d" (t));
+ sofs2 += ip->font.width;
+ dofs2 += ip->font.width;
+ }
+ pl += bm->bytes_per_row;
+ }
+ }
+}
+
+static void
+scrollbmap (bmap_t *bm, u_short x, u_short y, u_short width, u_short height, short dx, short dy)
+{
+ u_short depth = bm->depth;
+ u_short lwpr = bm->bytes_per_row >> 2;
+
+ if(dx) {
+ /* FIX: */ panic ("delta x not supported in scroll bitmap yet.");
+ }
+
+ if(dy == 0) {
+ return;
+ }
+ if(dy > 0) {
+ u_long *pl = (u_long *)bm->plane;
+ u_long *src_y = pl + (lwpr*y);
+ u_long *dest_y = pl + (lwpr*(y+dy));
+ u_long count = lwpr*(height-dy);
+ u_long *clr_y = src_y;
+ u_long clr_count = dest_y - src_y;
+ u_long bc, cbc;
+
+ src_y += count - 1;
+ dest_y += count - 1;
+
+ bc = count >> 4;
+ count &= 0xf;
+
+ while (bc--) {
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ }
+ while (count--)
+ *dest_y-- = *src_y--;
+
+ cbc = clr_count >> 4;
+ clr_count &= 0xf;
+
+ while (cbc--) {
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ }
+ while(clr_count--)
+ *clr_y++ = 0;
+ }
+ else {
+ u_long *pl = (u_long *)bm->plane;
+ u_long *src_y = pl + (lwpr*(y-dy));
+ u_long *dest_y = pl + (lwpr*y);
+ long count = lwpr*(height + dy);
+ u_long *clr_y = dest_y + count;
+ u_long clr_count = src_y - dest_y;
+ u_long bc, cbc;
+
+ bc = count >> 4;
+ count &= 0xf;
+
+ while(bc--) {
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ }
+ while(count--)
+ *dest_y++ = *src_y++;
+
+ cbc = clr_count >> 4;
+ clr_count &= 0xf;
+
+ while (cbc--) {
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ }
+ while (clr_count--)
+ *clr_y++ = 0;
+ }
+}
+#else
+#error Must be defined
+#endif /* NGRF */
diff --git a/sys/arch/atari/dev/iteioctl.h b/sys/arch/atari/dev/iteioctl.h
new file mode 100644
index 00000000000..b1555bfd772
--- /dev/null
+++ b/sys/arch/atari/dev/iteioctl.h
@@ -0,0 +1,83 @@
+/* $NetBSD: iteioctl.h,v 1.2 1995/07/24 05:56:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: iteioctl.h 1.1 90/07/09$
+ *
+ * @(#)iteioctl.h 7.2 (Berkeley) 11/4/90
+ */
+
+struct itewinsize {
+ int x; /* leftedge offset to the right */
+ int y; /* topedge offset down */
+ u_int width; /* width of ite display */
+ u_int height; /* height of ite display */
+ u_int depth; /* depth of ite display */
+};
+
+struct itebell {
+ u_int volume; /* volume of bell (0-64) */
+ u_int pitch; /* pitch of bell (10-2000) */
+ u_int msec; /* duration of bell */
+};
+#define MAXBVOLUME (63)
+#define MAXBPITCH (2000)
+#define MINBPITCH (10)
+#define MAXBTIME (5000) /* 5 seconds */
+
+struct iterepeat {
+ int start; /* number of 100/s before repeat start */
+ int next; /* number of 100/s before next repeat */
+};
+#define ITEMINREPEAT 5 /* mininum number of 100/s for key repeat */
+
+#define ITEIOCSKMAP _IOW('Z',0x70, struct kbdmap)
+#define ITEIOCSSKMAP _IOW('Z',0x68, struct kbdmap)
+#define ITEIOCGKMAP _IOR('Z',0x71, struct kbdmap)
+#define ITEIOCGWINSZ _IOR('Z',0x72, struct itewinsize)
+#define ITEIOCSWINSZ _IOW('Z',0x73, struct itewinsize)
+#define ITEIOCDSPWIN _IO('Z', 0x74)
+#define ITEIOCREMWIN _IO('Z', 0x75)
+#define ITEIOCGBELL _IOR('Z', 0x76, struct itebell)
+#define ITEIOCSBELL _IOW('Z', 0x77, struct itebell)
+#define ITEIOCGREPT _IOR('Z', 0x78, struct iterepeat)
+#define ITEIOCSREPT _IOW('Z', 0x79, struct iterepeat)
+
+
+#define ITESWITCH _IOW('Z',0x69, int) /* XXX */
+
diff --git a/sys/arch/atari/dev/itevar.h b/sys/arch/atari/dev/itevar.h
new file mode 100644
index 00000000000..1607302db84
--- /dev/null
+++ b/sys/arch/atari/dev/itevar.h
@@ -0,0 +1,200 @@
+/* $NetBSD: itevar.h,v 1.2 1995/07/25 13:49:26 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ITEVAR_H
+#define _ITEVAR_H
+
+#include <atari/dev/font.h>
+
+enum ite_arraymaxs {
+ MAX_ARGSIZE = 256,
+ MAX_TABS = 256,
+};
+
+enum ite_attr {
+ ATTR_NOR = 0,
+ ATTR_INV = 1,
+ ATTR_UL = 2,
+ ATTR_BOLD = 4,
+ ATTR_BLINK = 8,
+ ATTR_ALL = 16-1,
+
+ ATTR_KEYPAD = 0x80 /* XXX */
+};
+
+struct ite_softc {
+ struct device device; /* _Must_ be first */
+ char argbuf[MAX_ARGSIZE];
+ struct grf_softc *grf; /* XXX */
+ char *ap;
+ struct tty *tp;
+ void *priv;
+ font_info font;
+ u_char *tabs;
+ struct kbdmap *kbdmap;
+ int flags;
+ short cursorx;
+ short cursory;
+ short rows;
+ short cols;
+ u_char *cursor;
+ char imode;
+ u_char escape;
+ u_char cursor_opt;
+ u_char key_repeat;
+ char GL;
+ char GR;
+ char G0;
+ char G1;
+ char G2;
+ char G3;
+ char linefeed_newline;
+ char auto_wrap;
+ char cursor_appmode;
+ char keypad_appmode;
+ short top_margin;
+ short bottom_margin;
+ short inside_margins;
+ short eightbit_C1;
+ short emul_level;
+ enum ite_attr attribute;
+ enum ite_attr save_attribute;
+ int curx;
+ int save_curx;
+ int cury;
+ int save_cury;
+};
+
+enum ite_flags {
+ ITE_ALIVE = 0x1, /* grf layer is configed */
+ ITE_ISCONS = 0x2, /* ite is acting console. */
+ ITE_INITED = 0x4, /* ite has been inited. */
+ ITE_ISOPEN = 0x8, /* ite has been opened */
+ ITE_INGRF = 0x10, /* ite is in graphics mode */
+ ITE_ACTIVE = 0x20, /* ite is an active terminal */
+};
+
+enum ite_replrules {
+ RR_CLEAR = 0,
+ RR_COPY = 0x3,
+ RR_XOR = 0x6,
+ RR_COYINVERTED = 0xC
+};
+
+enum ite_scrolldir {
+ SCROLL_UP = 1,
+ SCROLL_DOWN,
+ SCROLL_LEFT,
+ SCROLL_RIGHT,
+};
+
+enum ite_cursact {
+ DRAW_CURSOR = 5,
+ ERASE_CURSOR,
+ MOVE_CURSOR,
+ START_CURSOROPT,
+ END_CURSOROPT
+};
+
+enum ite_special_keycodes {
+ KBD_LEFT_SHIFT = 0x2a,
+ KBD_RIGHT_SHIFT = 0x36,
+ KBD_CAPS_LOCK = 0x3a,
+ KBD_CTRL = 0x1d,
+ KBD_ALT = 0x38
+};
+
+enum ite_modifiers {
+ KBD_MOD_LSHIFT = 0x01,
+ KBD_MOD_RSHIFT = 0x02,
+ KBD_MOD_CTRL = 0x04,
+ KBD_MOD_ALT = 0x08,
+ KBD_MOD_CAPS = 0x10,
+ KBD_MOD_SHIFT = (KBD_MOD_LSHIFT | KBD_MOD_RSHIFT)
+};
+
+enum caller {
+ ITEFILT_TTY,
+ ITEFILT_CONSOLE,
+ ITEFILT_REPEATER
+};
+
+enum emul_level {
+ EMUL_VT100 = 1,
+ EMUL_VT300_8,
+ EMUL_VT300_7
+};
+
+enum ite_max_getsize { ITEBURST = 64 };
+
+enum tab_size { TABSIZE = 8 };
+#define TABEND(u) (ite_tty[u]->t_windsize.ws_col - TABSIZE) /* XXX */
+
+#define set_attr(ip, attr) ((ip)->attribute |= (attr))
+#define clr_attr(ip, attr) ((ip)->attribute &= ~(attr))
+#define attrloc(ip, y, x) 0
+#define attrclr(ip, sy, sx, h, w)
+#define attrmov(ip, sy, sx, dy, dx, h, w)
+#define attrtest(ip, attr) 0
+#define attrset(ip, attr)
+
+struct proc;
+struct consdev;
+struct termios;
+
+/* console related function */
+void ite_cnprobe __P((struct consdev *));
+void ite_cninit __P((struct consdev *));
+int ite_cngetc __P((dev_t));
+void ite_cnputc __P((dev_t, int));
+void ite_cnfinish __P((struct ite_softc *));
+
+/* standard ite device entry points. */
+void iteinit __P((dev_t));
+int iteopen __P((dev_t, int, int, struct proc *));
+int iteclose __P((dev_t, int, int, struct proc *));
+int iteread __P((dev_t, struct uio *, int));
+int itewrite __P((dev_t, struct uio *, int));
+int iteioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+void itestart __P((struct tty *));
+
+/* ite functions */
+int ite_on __P((dev_t, int));
+int ite_off __P((dev_t, int));
+void ite_reinit __P((dev_t));
+int ite_param __P((struct tty *, struct termios *));
+void ite_reset __P((struct ite_softc *));
+int ite_cnfilter __P((u_int, enum caller));
+void ite_filter __P((u_int ,enum caller));
+
+#endif /* _ITEVAR_H */
diff --git a/sys/arch/atari/dev/kbd.c b/sys/arch/atari/dev/kbd.c
new file mode 100644
index 00000000000..32a80018a25
--- /dev/null
+++ b/sys/arch/atari/dev/kbd.c
@@ -0,0 +1,563 @@
+/* $NetBSD: kbd.c,v 1.5 1995/06/26 14:31:27 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <dev/cons.h>
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <machine/acia.h>
+#include <machine/video.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/kbdreg.h>
+#include <atari/dev/event_var.h>
+#include <atari/dev/vuid_event.h>
+
+#include "mouse.h"
+
+/*
+ * The ringbuffer is the interface between the hard and soft interrupt handler.
+ * The hard interrupt runs straight from the MFP interrupt.
+ */
+#define KBD_RING_SIZE 256 /* Sz of input ring buffer, must be power of 2 */
+#define KBD_RING_MASK 255 /* Modulo mask for above */
+
+static u_char kbd_ring[KBD_RING_SIZE];
+static volatile u_int kbd_rbput = 0; /* 'put' index */
+static u_int kbd_rbget = 0; /* 'get' index */
+static u_char kbd_soft = 0; /* 1: Softint has been scheduled*/
+
+struct kbd_softc {
+ int k_event_mode; /* if 1, collect events, */
+ /* else pass to ite */
+ struct evvar k_events; /* event queue state */
+ u_char k_soft_cs; /* control-reg. copy */
+ u_char k_package[20]; /* XXX package being build */
+ u_char k_pkg_size; /* Size of the package */
+ u_char k_pkg_idx;
+ u_char *k_sendp; /* Output pointer */
+ int k_send_cnt; /* Chars left for output */
+};
+
+static struct kbd_softc kbd_softc;
+
+void kbd_write __P((u_char *, int));
+
+static void kbdsoft __P((void));
+static void kbdattach __P((struct device *, struct device *, void *));
+static int kbdmatch __P((struct device *, struct cfdata *, void *));
+static int kbd_write_poll __P((u_char *, int));
+static void kbd_pkg_start __P((struct kbd_softc *, u_char));
+
+struct cfdriver kbdcd = {
+ NULL, "kbd", (cfmatch_t)kbdmatch, kbdattach,
+ DV_DULL, sizeof(struct device), NULL, 0 };
+
+
+/*ARGSUSED*/
+static int
+kbdmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if (!strcmp((char *)auxp, "kbd"))
+ return (1);
+ return (0);
+}
+
+/*ARGSUSED*/
+static void
+kbdattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ int timeout;
+ u_char kbd_rst[] = { 0x80, 0x01 };
+ u_char kbd_icmd[] = { 0x12, 0x15 };
+
+ /*
+ * Disable keyboard interrupts from MFP
+ */
+ MFP->mf_ierb &= ~IB_AINT;
+
+ /*
+ * Reset ACIA and intialize to:
+ * divide by 16, 8 data, 1 stop, no parity, enable RX interrupts
+ */
+ KBD->ac_cs = A_RESET;
+ delay(100); /* XXX: enough? */
+ KBD->ac_cs = kbd_softc.k_soft_cs = KBD_INIT | A_RXINT;
+
+ /*
+ * Clear error conditions
+ */
+ while (KBD->ac_cs & (A_IRQ|A_RXRDY))
+ timeout = KBD->ac_da;
+
+ /*
+ * Now send the reset string, and read+ignore it's response
+ */
+ if (!kbd_write_poll(kbd_rst, 2))
+ printf("kbd: error cannot reset keyboard\n");
+ for (timeout = 1000; timeout > 0; timeout--) {
+ if (KBD->ac_cs & (A_IRQ|A_RXRDY)) {
+ timeout = KBD->ac_da;
+ timeout = 100;
+ }
+ delay(100);
+ }
+ /*
+ * Send init command: disable mice & joysticks
+ */
+ kbd_write_poll(kbd_icmd, sizeof(kbd_icmd));
+
+ printf("\n");
+}
+
+/* definitions for atari keyboard encoding. */
+#define KEY_CODE(c) ((u_char)(c) & 0x7f)
+#define KEY_UP(c) ((u_char)(c) & 0x80)
+#define IS_KEY(c) ((u_char)(c) < 0xf6)
+
+void
+kbdenable()
+{
+ int s, code;
+
+ s = spltty();
+
+ /*
+ * Clear error conditions...
+ */
+ while (KBD->ac_cs & (A_IRQ|A_RXRDY))
+ code = KBD->ac_da;
+ /*
+ * Enable interrupts from MFP
+ */
+ MFP->mf_iprb &= ~IB_AINT;
+ MFP->mf_ierb |= IB_AINT;
+ MFP->mf_imrb |= IB_AINT;
+
+ kbd_softc.k_event_mode = 0;
+ kbd_softc.k_events.ev_io = 0;
+ kbd_softc.k_pkg_size = 0;
+ splx(s);
+}
+
+int kbdopen(dev_t dev, int flags, int mode, struct proc *p)
+{
+ int s, error;
+
+ if (kbd_softc.k_events.ev_io)
+ return EBUSY;
+
+ kbd_softc.k_events.ev_io = p;
+ ev_init(&kbd_softc.k_events);
+ return (0);
+}
+
+int
+kbdclose(dev_t dev, int flags, int mode, struct proc *p)
+{
+ /* Turn off event mode, dump the queue */
+ kbd_softc.k_event_mode = 0;
+ ev_fini(&kbd_softc.k_events);
+ kbd_softc.k_events.ev_io = NULL;
+ return (0);
+}
+
+int
+kbdread(dev_t dev, struct uio *uio, int flags)
+{
+ return ev_read(&kbd_softc.k_events, uio, flags);
+}
+
+int
+kbdioctl(dev_t dev,u_long cmd,register caddr_t data,int flag,struct proc *p)
+{
+ register struct kbd_softc *k = &kbd_softc;
+
+ switch (cmd) {
+ case KIOCTRANS:
+ if (*(int *)data == TR_UNTRANS_EVENT)
+ return 0;
+ break;
+
+ case KIOCGTRANS:
+ /*
+ * Get translation mode
+ */
+ *(int *)data = TR_UNTRANS_EVENT;
+ return 0;
+
+ case KIOCSDIRECT:
+ k->k_event_mode = *(int *)data;
+ return 0;
+
+ case FIONBIO: /* we will remove this someday (soon???) */
+ return 0;
+
+ case FIOASYNC:
+ k->k_events.ev_async = *(int *)data != 0;
+ return 0;
+
+ case TIOCSPGRP:
+ if (*(int *)data != k->k_events.ev_io->p_pgid)
+ return EPERM;
+ return 0;
+
+ default:
+ return ENOTTY;
+ }
+
+ /*
+ * We identified the ioctl, but we do not handle it.
+ */
+ return EOPNOTSUPP; /* misuse, but what the heck */
+}
+
+int
+kbdselect (dev_t dev, int rw, struct proc *p)
+{
+ return ev_select (&kbd_softc.k_events, rw, p);
+}
+
+/*
+ * Keyboard interrupt handler called straight from MFP at spl6.
+ */
+int
+kbdintr(sr)
+int sr; /* sr at time of interrupt */
+{
+ int code;
+ int got_char = 0;
+
+ /*
+ * There may be multiple keys available. Read them all.
+ */
+ while (KBD->ac_cs & (A_RXRDY|A_OE|A_PE)) {
+ got_char = 1;
+ if (KBD->ac_cs & (A_OE|A_PE)) {
+ code = KBD->ac_da; /* Silently ignore errors */
+ continue;
+ }
+ kbd_ring[kbd_rbput++ & KBD_RING_MASK] = KBD->ac_da;
+ }
+
+ /*
+ * If characters are waiting for transmit, send them.
+ */
+ if ((kbd_softc.k_soft_cs & A_TXINT) && (KBD->ac_cs & A_TXRDY)) {
+ if (kbd_softc.k_sendp != NULL)
+ KBD->ac_da = *kbd_softc.k_sendp++;
+ if (--kbd_softc.k_send_cnt <= 0) {
+ /*
+ * The total package has been transmitted,
+ * wakeup anyone waiting for it.
+ */
+ KBD->ac_cs = (kbd_softc.k_soft_cs &= ~A_TXINT);
+ kbd_softc.k_sendp = NULL;
+ kbd_softc.k_send_cnt = 0;
+ wakeup((caddr_t)&kbd_softc.k_send_cnt);
+ }
+ }
+
+ /*
+ * Activate software-level to handle possible input.
+ */
+ if (got_char) {
+ if (!BASEPRI(sr)) {
+ if (!kbd_soft++)
+ add_sicallback(kbdsoft, 0, 0);
+ } else {
+ spl1();
+ kbdsoft();
+ }
+ }
+}
+
+/*
+ * Keyboard soft interrupt handler
+ */
+void
+kbdsoft()
+{
+ int s;
+ u_char code;
+ struct kbd_softc *k = &kbd_softc;
+ struct firm_event *fe;
+ int put;
+ int n, get;
+
+ kbd_soft = 0;
+ get = kbd_rbget;
+
+ for (;;) {
+ n = kbd_rbput;
+ if (get == n) /* We're done */
+ break;
+ n -= get;
+ if (n > KBD_RING_SIZE) { /* Ring buffer overflow */
+ get += n - KBD_RING_SIZE;
+ n = KBD_RING_SIZE;
+ }
+ while (--n >= 0) {
+ code = kbd_ring[get++ & KBD_RING_MASK];
+
+ /*
+ * If collecting a package, stuff it in and
+ * continue.
+ */
+ if (k->k_pkg_size && (k->k_pkg_idx < k->k_pkg_size)) {
+ k->k_package[k->k_pkg_idx++] = code;
+ if (k->k_pkg_idx == k->k_pkg_size) {
+ k->k_pkg_size = 0;
+#if NMOUSE > 0
+ /*
+ * Package is complete, we can now
+ * send it to the mouse driver...
+ */
+ mouse_soft(k->k_package, k->k_pkg_size);
+#endif /* NMOUSE */
+ }
+ continue;
+ }
+ /*
+ * If this is a package header, init pkg. handling.
+ */
+ if (!IS_KEY(code)) {
+ kbd_pkg_start(k, code);
+ continue;
+ }
+ /*
+ * if not in event mode, deliver straight to ite to
+ * process key stroke
+ */
+ if (!k->k_event_mode) {
+ /* Gets to spltty() by itself */
+ ite_filter(code, ITEFILT_TTY);
+ continue;
+ }
+
+ /*
+ * Keyboard is generating events. Turn this keystroke
+ * into an event and put it in the queue. If the queue
+ * is full, the keystroke is lost (sorry!).
+ */
+ s = spltty();
+ put = k->k_events.ev_put;
+ fe = &k->k_events.ev_q[put];
+ put = (put + 1) % EV_QSIZE;
+ if (put == k->k_events.ev_get) {
+ log(LOG_WARNING,
+ "keyboard event queue overflow\n");
+ splx(s);
+ continue;
+ }
+ fe->id = KEY_CODE(code);
+ fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN;
+ fe->time = time;
+ k->k_events.ev_put = put;
+ EV_WAKEUP(&k->k_events);
+ splx(s);
+ }
+ kbd_rbget = get;
+ }
+}
+
+static char sound[] = {
+ 0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
+ 0xF8,0x10,0x10,0x10,0x00,0x20,0x03
+};
+
+int
+kbdbell()
+{
+ register int i, sps;
+
+ sps = spltty();
+ for (i = 0; i < sizeof(sound); i++) {
+ SOUND->sd_selr = i;
+ SOUND->sd_wdat = sound[i];
+ }
+ splx(sps);
+}
+
+int
+kbdgetcn()
+{
+ u_char code;
+ int s = spltty();
+ int ints_active;
+
+ ints_active = 0;
+ if (MFP->mf_imrb & IB_AINT) {
+ ints_active = 1;
+ MFP->mf_imrb &= ~IB_AINT;
+ }
+ for (;;) {
+ while (!((KBD->ac_cs & (A_IRQ|A_RXRDY)) == (A_IRQ|A_RXRDY)))
+ ; /* Wait for key */
+ if (KBD->ac_cs & (A_OE|A_PE)) {
+ code = KBD->ac_da; /* Silently ignore errors */
+ continue;
+ }
+ break;
+ }
+
+ code = KBD->ac_da;
+ if (ints_active) {
+ MFP->mf_iprb &= ~IB_AINT;
+ MFP->mf_imrb |= IB_AINT;
+ }
+
+ splx (s);
+ return code;
+}
+
+/*
+ * Write a command to the keyboard in 'polled' mode.
+ */
+static int
+kbd_write_poll(cmd, len)
+u_char *cmd;
+int len;
+{
+ int timeout;
+
+ while (len-- > 0) {
+ KBD->ac_da = *cmd++;
+ for (timeout = 100; !(KBD->ac_cs & A_TXRDY); timeout--)
+ delay(10);
+ if (!(KBD->ac_cs & A_TXRDY))
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Write a command to the keyboard. Return when command is send.
+ */
+void
+kbd_write(cmd, len)
+u_char *cmd;
+int len;
+{
+ struct kbd_softc *k = &kbd_softc;
+ int sps;
+
+ /*
+ * Get to splhigh, 'real' interrupts arrive at spl6!
+ */
+ sps = splhigh();
+
+ /*
+ * Make sure any privious write has ended...
+ */
+ while (k->k_sendp != NULL)
+ tsleep((caddr_t)&k->k_sendp, TTOPRI, "kbd_write1", 0);
+
+ /*
+ * If the KBD-acia is not currently busy, send the first
+ * character now.
+ */
+ KBD->ac_cs = (k->k_soft_cs |= A_TXINT);
+ if (KBD->ac_cs & A_TXRDY) {
+ KBD->ac_da = *cmd++;
+ len--;
+ }
+
+ /*
+ * If we're not yet done, wait until all characters are send.
+ */
+ if (len > 0) {
+ k->k_sendp = cmd;
+ k->k_send_cnt = len;
+ tsleep((caddr_t)&k->k_send_cnt, TTOPRI, "kbd_write2", 0);
+ }
+ splx(sps);
+
+ /*
+ * Wakeup all procs waiting for us.
+ */
+ wakeup((caddr_t)&k->k_sendp);
+}
+
+/*
+ * Setup softc-fields to assemble a keyboard package.
+ */
+static void
+kbd_pkg_start(kp, msg_start)
+struct kbd_softc *kp;
+u_char msg_start;
+{
+ kp->k_pkg_idx = 1;
+ kp->k_package[0] = msg_start;
+ switch (msg_start) {
+ case 0xf6:
+ kp->k_pkg_size = 8;
+ break;
+ case 0xf7:
+ kp->k_pkg_size = 6;
+ break;
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ kp->k_pkg_size = 3;
+ break;
+ case 0xfc:
+ kp->k_pkg_size = 7;
+ break;
+ case 0xfe:
+ case 0xff:
+ kp->k_pkg_size = 2;
+ break;
+ default:
+ printf("kbd: Unknown packet 0x%x\n", msg_start);
+ break;
+ }
+}
diff --git a/sys/arch/atari/dev/kbdmap.c b/sys/arch/atari/dev/kbdmap.c
new file mode 100644
index 00000000000..26d1f936728
--- /dev/null
+++ b/sys/arch/atari/dev/kbdmap.c
@@ -0,0 +1,207 @@
+/* $NetBSD: kbdmap.c,v 1.2 1995/07/24 05:56:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <atari/dev/kbdmap.h>
+
+/* define a default keymap. This can be changed by keyboard ioctl's
+ (later at least..) */
+
+/* mode shortcuts: */
+#define S KBD_MODE_STRING
+#define C KBD_MODE_CAPS
+#define K KBD_MODE_KPAD
+
+struct kbdmap ascii_kbdmap = {
+ /* normal map */
+ {
+/* 0x00 */ 0, 0, 0, ESC, 0, '1', 0, '2',
+/* 0x04 */ 0, '3', 0, '4', 0, '5', 0, '6',
+/* 0x08 */ 0, '7', 0, '8', 0, '9', 0, '0',
+/* 0x0c */ 0, '-', 0, '=', 0, '\b', 0, '\t',
+/* 0x10 */ C, 'q', C, 'w', C, 'e', C, 'r',
+/* 0x14 */ C, 't', C, 'y', C, 'u', C, 'i',
+/* 0x18 */ C, 'o', C, 'p', 0, '[', 0, ']',
+/* 0x1c */ 0, '\r', 0, 0, C, 'a', C, 's',
+/* 0x20 */ C, 'd', C, 'f', C, 'g', C, 'h',
+/* 0x24 */ C, 'j', C, 'k', C, 'l', 0, ';',
+#ifdef US_KBD
+/* 0x28 */ 0, '\'', 0, '`', 0, 0, 0, '\\',
+#else
+/* 0x28 */ 0, '\'', 0, '`', 0, 0, 0, '#',
+#endif
+/* 0x2c */ C, 'z', C, 'x', C, 'c', C, 'v',
+/* 0x30 */ C, 'b', C, 'n', C, 'm', 0, ',',
+/* 0x34 */ 0, '.', 0, '/', 0, 0, 0, 0,
+/* 0x38 */ 0, 0, 0, ' ', 0, 0, S, 0x10,
+/* 0x3c */ S, 0x15, S, 0x1A, S, 0x1F, S, 0x24,
+/* 0x40 */ S, 0x29, S, 0x2E, S, 0x33, S, 0x38,
+/* 0x44 */ S, 0x3D, 0, 0, 0, 0, 0, 0,
+/* 0x48 */ S, 0x00, 0, 0, 0, '-', S, 0x0C,
+/* 0x4c */ 0, 0, S, 0x08, 0, '+', 0, 0,
+/* 0x50 */ S, 0x04, 0, 0, 0, 0, 0, DEL,
+/* 0x54 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x5c */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x60 */
+#ifdef US_KBD
+/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, '(',
+#else
+/* 0x60 */ 0, '\\', 0, 0, 0, 0, 0, '(',
+#endif
+/* 0x64 */ 0, ')', 0, '/', 0, '*', K, '7',
+/* 0x68 */ K, '8', K, '9', K, '4', K, '5',
+/* 0x6c */ K, '6', K, '1', K, '2', K, '3',
+/* 0x70 */ K, '0', K, '.', K, '\r', 0, 0,
+/* 0x74 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x7c */ 0, 0, 0, 0, 0, 0, 0, 0
+},
+ /* shifted map */
+ {
+#ifdef US_KBD
+/* 0x00 */ 0, 0, 0, ESC, 0, '!', 0, '@',
+#else
+/* 0x00 */ 0, 0, 0, ESC, 0, '!', 0, '"',
+#endif
+/* 0x04 */ 0, '#', 0, '$', 0, '%', 0, '^',
+/* 0x08 */ 0, '&', 0, '*', 0, '(', 0, ')',
+/* 0x0c */ 0, '_', 0, '+', 0, '\b', 0, '\t',
+/* 0x10 */ C, 'Q', C, 'W', C, 'E', C, 'R',
+/* 0x14 */ C, 'T', C, 'Y', C, 'U', C, 'I',
+/* 0x18 */ C, 'O', C, 'P', 0, '{', 0, '}',
+/* 0x1c */ 0, '\r', 0, 0, C, 'A', C, 'S',
+/* 0x20 */ C, 'D', C, 'F', C, 'G', C, 'H',
+/* 0x24 */ C, 'J', C, 'K', C, 'L', 0, ':',
+#ifdef US_KBD
+/* 0x28 */ 0, '"', 0, '~', 0, 0, 0, '|',
+#else
+/* 0x28 */ 0, '@', 0, '_', 0, 0, 0, '~',
+#endif
+/* 0x2c */ C, 'Z', C, 'X', C, 'C', C, 'V',
+/* 0x30 */ C, 'B', C, 'N', C, 'M', 0, '<',
+/* 0x34 */ 0, '>', 0, '?', 0, 0, 0, 0,
+/* 0x38 */ 0, 0, 0, ' ', 0, 0, S, 0x5d,
+/* 0x3c */ S, 0x63, S, 0x69, S, 0x6F, S, 0x75,
+/* 0x40 */ S, 0x7b, S, 0x81, S, 0x87, S, 0x8d,
+/* 0x44 */ S, 0x93, 0, 0, 0, 0, 0, 0,
+/* 0x48 */ S, 0x47, 0, 0, 0, '-', S, 0x57,
+/* 0x4c */ 0, 0, S, 0x51, 0, '+', 0, 0,
+/* 0x50 */ S, 0x4c, 0, 0, 0, 0, 0, DEL,
+/* 0x54 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x5c */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x60 */
+#ifdef US_KBD
+/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, '(',
+#else
+/* 0x60 */ 0, '|', 0, 0, 0, 0, 0, '(',
+#endif
+/* 0x64 */ 0, ')', 0, '/', 0, '*', K, '7',
+/* 0x68 */ K, '8', K, '9', K, '4', K, '5',
+/* 0x6c */ K, '6', K, '1', K, '2', K, '3',
+/* 0x70 */ K, '0', K, '.', K, '\r', 0, 0,
+/* 0x74 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x7c */ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+
+ /* alt map FIXME: No altmap yet.. */
+ {
+ 0, 0
+ },
+
+ /* shift alt map FIXME: No shift altmap yet... */
+ {
+ 0, 0
+ },
+
+ {
+ /* string table. If there's a better way to get the offsets into the
+ above table, please tell me..
+
+ NOTE: save yourself and others a lot of grief by *not* using
+ CSI == 0x9b, using the two-character sequence gives
+ much less trouble, especially in GNU-Emacs.. */
+
+ 3, ESC, '[', 'A', /* 0x00: CRSR UP */
+ 3, ESC, '[', 'B', /* 0x04: CRSR DOWN */
+ 3, ESC, '[', 'C', /* 0x08: CRSR RIGHT */
+ 3, ESC, '[', 'D', /* 0x0C: CRSR LEFT */
+ 4, ESC, '[', '0', '~', /* 0x10: F1 */
+ 4, ESC, '[', '1', '~', /* 0x15: F2 */
+ 4, ESC, '[', '2', '~', /* 0x1A: F3 */
+ 4, ESC, '[', '3', '~', /* 0x1F: F4 */
+ 4, ESC, '[', '4', '~', /* 0x24: F5 */
+ 4, ESC, '[', '5', '~', /* 0x29: F6 */
+ 4, ESC, '[', '6', '~', /* 0x2E: F7 */
+ 4, ESC, '[', '7', '~', /* 0x33: F8 */
+ 4, ESC, '[', '8', '~', /* 0x38: F9 */
+ 4, ESC, '[', '9', '~', /* 0x3D: F10 */
+ 4, ESC, '[', '?', '~', /* 0x42: HELP */
+
+ 4, ESC, '[', 'T', '~', /* 0x47: shift CRSR UP */
+ 4, ESC, '[', 'S', '~', /* 0x4C: shift CRSR DOWN */
+ 5, ESC, '[', ' ', '@', '~', /* 0x51: shift CRSR RIGHT */
+ 5, ESC, '[', ' ', 'A', '~', /* 0x57: shift CRSR LEFT */
+ 5, ESC, '[', '1', '0', '~', /* 0x5D: shift F1 */
+ 5, ESC, '[', '1', '1', '~', /* 0x63: shift F2 */
+ 5, ESC, '[', '1', '2', '~', /* 0x69: shift F3 */
+ 5, ESC, '[', '1', '3', '~', /* 0x6F: shift F4 */
+ 5, ESC, '[', '1', '4', '~', /* 0x75: shift F5 */
+ 5, ESC, '[', '1', '5', '~', /* 0x7B: shift F6 */
+ 5, ESC, '[', '1', '6', '~', /* 0x81: shift F7 */
+ 5, ESC, '[', '1', '7', '~', /* 0x87: shift F8 */
+ 5, ESC, '[', '1', '8', '~', /* 0x8D: shift F9 */
+ 5, ESC, '[', '1', '9', '~', /* 0x93: shift F10 */
+ 3, ESC, '[', 'Z', /* 0x99: shift TAB */
+ 2, ESC, '[', /* 0x9d: alt ESC == CSI */
+ },
+};
+
+unsigned char acctable[KBD_NUM_ACC][64] = {
+ { "@ÀBCDÈFGHÌJKLMNÒPQRSTÙVWXYZ[\\]^_"
+ "`àbcdèfghìjklmnòpqrstùvwxyz{|}~\177"}, /* KBD_ACC_GRAVE */
+
+ { "@ÁBCDÉFGHÍJKLMNÓPQRSTÚVWXYZ[\\]^_"
+ "`ábcdéfghíjklmnópqrstúvwxyz{|}~\177"}, /* KBD_ACC_ACUTE */
+
+ { "@ÂBCDÊFGHÎJKLMNÔPQRSTÛVWXYZ[\\]^_"
+ "`âbcdêfghîjklmnôpqrstûvwxyz{|}~\177"}, /* KBD_ACC_CIRC */
+
+ { "@ÃBCDEFGHIJKLMÑÕPQRSTUVWXYZ[\\]^_"
+ "`ãbcdefghijklmñÕpqrstuvwxyz{|}~\177"}, /* KBD_ACC_TILDE */
+
+ { "@ÄBCDËFGHÏJKLMNÖPQRSTÜVWXYZ[\\]^_"
+ "`äbcdëfghïjklmnöpqrstüvwxyz{|}~\177"}, /* KBD_ACC_DIER */
+};
+
+
diff --git a/sys/arch/atari/dev/kbdmap.h b/sys/arch/atari/dev/kbdmap.h
new file mode 100644
index 00000000000..b75795cbfb1
--- /dev/null
+++ b/sys/arch/atari/dev/kbdmap.h
@@ -0,0 +1,144 @@
+/* $NetBSD: kbdmap.h,v 1.3 1995/07/24 05:56:17 leo Exp $ */
+
+/*
+ * Copyright (c) 1993 Markus Wild
+ * 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 Markus Wild.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define NUL 0
+#define SOH 1
+#define STX 2
+#define ETX 3
+#define EOT 4
+#define ENQ 5
+#define ACK 6
+#define BEL 7
+#define BS 8
+#define HT 9
+#define LF 10
+#define VT 11
+#define FF 12
+#define CR 13
+#define SO 14
+#define SI 15
+#define DLE 16
+#define DC1 17
+#define DC2 18
+#define DC3 19
+#define DC4 20
+#define NAK 21
+#define SYN 22
+#define ETB 23
+#define CAN 24
+#define EM 25
+#define SUB 26
+#define ESC 27
+#define FS 28
+#define GS 29
+#define RS 30
+#define US 31
+#define DEL 127
+#define IND 132
+#define NEL 133
+#define SSA 134
+#define ESA 135
+#define HTS 136
+#define HTJ 137
+#define VTS 138
+#define PLD 139
+#define PLU 140
+#define RI 141
+#define SS2 142
+#define SS3 143
+#define DCS 144
+#define PU1 145
+#define PU2 146
+#define STS 147
+#define CCH 148
+#define MW 149
+#define SPA 150
+#define EPA 151
+#define CSI 155
+#define ST 156
+#define OSC 157
+#define PM 158
+#define APC 159
+
+
+/*
+ * A total of 0x80 scancode are defined for the atari keyboard.
+ */
+#define KBD_NUM_KEYS 0x80
+
+/* size of string table */
+#define KBD_STRTAB_SIZE 255
+
+/* for dead keys, index into acctable */
+/* FIXME: What the hell are dead keys?? */
+#define KBD_ACC_GRAVE 0
+#define KBD_ACC_ACUTE 1
+#define KBD_ACC_CIRC 2
+#define KBD_ACC_TILDE 3
+#define KBD_ACC_DIER 4
+#define KBD_NUM_ACC 5
+
+
+struct key {
+ unsigned char mode; /* see possible values below */
+ unsigned char code;
+};
+
+#define KBD_MODE_STRING (0x01) /* code is index into strings[] */
+#define KBD_MODE_DEAD (0x02) /* acc-index in upper nibble, code = plain acc */
+#define KBD_MODE_CAPS (0x04) /* key is capsable. Only in non-shifted maps */
+#define KBD_MODE_KPAD (0x08) /* key is on keypad */
+#define KBD_MODE_GRAVE (KBD_ACC_GRAVE << 4)
+#define KBD_MODE_ACUTE (KBD_ACC_ACUTE << 4)
+#define KBD_MODE_CIRC (KBD_ACC_CIRC << 4)
+#define KBD_MODE_TILDE (KBD_ACC_TILDE << 4)
+#define KBD_MODE_DIER (KBD_ACC_DIER << 4)
+#define KBD_MODE_ACCENT(m) ((m) >> 4) /* get accent from mode */
+#define KBD_MODE_ACCMASK (0xf0)
+
+#define KBD_SCANCODE(code) (code & 0x7f)
+#define KBD_RELEASED(code) (code & 0x80 ? 1 : 0)
+
+struct kbdmap {
+ struct key keys[KBD_NUM_KEYS],
+ shift_keys[KBD_NUM_KEYS],
+ alt_keys[KBD_NUM_KEYS],
+ alt_shift_keys[KBD_NUM_KEYS];
+ unsigned char strings[KBD_STRTAB_SIZE];
+};
+
+
+#ifdef _KERNEL
+/* XXX: ITE interface */
+extern struct kbdmap ascii_kbdmap;
+extern unsigned char acctable[KBD_NUM_ACC][64];
+#endif
diff --git a/sys/arch/atari/dev/kbdreg.h b/sys/arch/atari/dev/kbdreg.h
new file mode 100644
index 00000000000..84301c4fda2
--- /dev/null
+++ b/sys/arch/atari/dev/kbdreg.h
@@ -0,0 +1,54 @@
+/* $NetBSD: kbdreg.h,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kbio.h 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: kbio.h,v 1.4 92/11/26 01:16:32 torek Exp (LBL)
+ */
+
+#define KIOCTRANS _IOW('k', 0, int) /* set translation mode */
+ /* (we only accept TR_UNTRANS_EVENT) */
+#define KIOCGTRANS _IOR('k', 5, int) /* get translation mode */
+#define KIOCSDIRECT _IOW('k', 10, int) /* keys to console? */
+
+#define TR_UNTRANS_EVENT 3
diff --git a/sys/arch/atari/dev/ms.c b/sys/arch/atari/dev/ms.c
new file mode 100644
index 00000000000..5d5c647c0ee
--- /dev/null
+++ b/sys/arch/atari/dev/ms.c
@@ -0,0 +1,397 @@
+/* $NetBSD: ms.c,v 1.3 1995/07/27 06:35:46 leo Exp $
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * All rights reserved.
+ *
+ * based on:
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ms.c 8.1 (Berkeley) 6/11/93
+ *
+ * Header: ms.c,v 1.5 92/11/26 01:28:47 torek Exp (LBL)
+ */
+
+/*
+ * Mouse driver.
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+
+#include <atari/dev/event_var.h>
+#include <atari/dev/vuid_event.h>
+
+#include "mouse.h"
+#if NMOUSE > 0
+
+/* there's really no more physical ports on an atari. */
+#if NMOUSE > 1
+#undef NMOUSE
+#define NMOUSE 1
+#endif
+
+typedef void (*FPV)();
+
+/*
+ * Mouse specific packages produced by the keyboard. Currently, we only
+ * define the REL_MOUSE package, as this is the only one used.
+ */
+typedef struct {
+ u_char id;
+ char dx;
+ char dy;
+} REL_MOUSE;
+
+#define IS_REL_MOUSE(id) (((u_int)(id) & 0xF8) == 0xF8)
+#define TIMEOUT_ID (0xFC)
+
+static struct ms_softc {
+ u_char ms_buttons; /* button states */
+ struct evvar ms_events; /* event queue state */
+ int ms_dx; /* accumulated dx */
+ int ms_dy; /* accumulated dy */
+ struct firm_event ms_bq[2]; /* Button queue */
+ int ms_bq_idx; /* Button queue index */
+} ms_softc[NMOUSE];
+
+static void ms_3b_delay __P((struct ms_softc *));
+ void mouse_soft __P((REL_MOUSE *, int));
+
+int
+mouseattach(cnt)
+ int cnt;
+{
+ printf("1 mouse configured\n");
+ return(NMOUSE);
+}
+
+static void
+ms_3b_delay(ms)
+struct ms_softc *ms;
+{
+ REL_MOUSE rel_ms;
+
+ rel_ms.id = TIMEOUT_ID;
+ rel_ms.dx = rel_ms.dy = 0;
+ mouse_soft(&rel_ms, sizeof(rel_ms));
+}
+/*
+ * Note that we are called from the keyboard software interrupt!
+ */
+void
+mouse_soft(rel_ms, size)
+REL_MOUSE *rel_ms;
+int size;
+{
+ struct ms_softc *ms = &ms_softc[0];
+ struct firm_event *fe, *fe2;
+ int get, put;
+ int sps;
+ u_char mbut, bmask;
+ int is_timeout;
+ int flush_buttons;
+ int id;
+
+ if (!IS_REL_MOUSE(rel_ms->id))
+ return; /* Probably some other message */
+ if (ms->ms_events.ev_io == NULL)
+ return;
+
+ sps = splev();
+ get = ms->ms_events.ev_get;
+ put = ms->ms_events.ev_put;
+ fe = &ms->ms_events.ev_q[put];
+
+ if (rel_ms->id == TIMEOUT_ID) {
+ is_timeout = 1;
+ id = ms->ms_buttons;
+ }
+ else {
+ is_timeout = 0;
+ id = (rel_ms->id & 3) | (ms->ms_buttons & 4);
+ }
+
+ if (!is_timeout && ms->ms_bq_idx)
+ untimeout((FPV)ms_3b_delay, (void *)ms);
+
+ /*
+ * Button states are encoded in the lower 2 bits of 'id'
+ */
+ if (!(mbut = (id ^ ms->ms_buttons)) && (put != get)) {
+ /*
+ * Compact dx/dy messages. Always generate an event when
+ * a button is pressed or the event queue is empty.
+ */
+ ms->ms_dx += rel_ms->dx;
+ ms->ms_dy += rel_ms->dy;
+ goto out;
+ }
+ rel_ms->dx += ms->ms_dx;
+ rel_ms->dy += ms->ms_dy;
+ ms->ms_dx = ms->ms_dy = 0;
+
+ /*
+ * Output location events _before_ button events ie. make sure
+ * the button is pressed at the correct location.
+ */
+ if (rel_ms->dx) {
+ if ((++put) % EV_QSIZE == get) {
+ put--;
+ goto out;
+ }
+ fe->id = LOC_X_DELTA;
+ fe->value = rel_ms->dx;
+ fe->time = time;
+ if (put >= EV_QSIZE) {
+ put = 0;
+ fe = &ms->ms_events.ev_q[0];
+ }
+ else fe++;
+ }
+ if (rel_ms->dy) {
+ if ((++put) % EV_QSIZE == get) {
+ put--;
+ goto out;
+ }
+ fe->id = LOC_Y_DELTA;
+ fe->value = rel_ms->dy;
+ fe->time = time;
+ if (put >= EV_QSIZE) {
+ put = 0;
+ fe = &ms->ms_events.ev_q[0];
+ }
+ else fe++;
+ }
+ if (mbut && !is_timeout) {
+ for (bmask = 1; bmask < 0x04; bmask <<= 1) {
+ if (!(mbut & bmask))
+ continue;
+ fe2 = &ms->ms_bq[ms->ms_bq_idx++];
+ fe2->id = bmask & 1 ? MS_RIGHT : MS_LEFT;
+ fe2->value = id & bmask ? VKEY_DOWN : VKEY_UP;
+ fe2->time = time;
+ }
+ }
+ if (ms->ms_bq_idx) {
+ /*
+ * We have at least one button, handle it.
+ */
+ flush_buttons = (is_timeout) ? 1 : 0;
+ if (ms->ms_bq_idx == 2) {
+ if (ms->ms_bq[0].value == ms->ms_bq[1].value) {
+ /* Must be 2 button presses! */
+ if (ms->ms_bq[0].id != ms->ms_bq[1].id) {
+ ms->ms_bq[0].id = MS_MIDDLE;
+ ms->ms_bq_idx = 1;
+ id = 7;
+ }
+ }
+ flush_buttons = 1;
+ }
+ else {
+ if (ms->ms_bq[0].value == VKEY_UP) {
+ /*
+ * Release of a button is always flushed
+ * immediately. If the middle button is
+ * active, the release event is his. Mark
+ * all buttons released, this also surpresses
+ * a spurious release event of the not-yet-
+ * released button.
+ */
+ if( id & 4) {
+ ms->ms_bq[0].id = MS_MIDDLE;
+ id = 0;
+ }
+ flush_buttons = 1;
+ }
+ else if (!is_timeout) {
+ timeout((FPV)ms_3b_delay, (void *)ms, 10);
+ goto out;
+ }
+ }
+ if (flush_buttons) {
+ int i;
+
+ for (i = 0; i < ms->ms_bq_idx; i++) {
+ if ((++put) % EV_QSIZE == get) {
+ ms->ms_bq_idx = 0;
+ put--;
+ goto out;
+ }
+ *fe = ms->ms_bq[i];
+ if (put >= EV_QSIZE) {
+ put = 0;
+ fe = &ms->ms_events.ev_q[0];
+ }
+ else fe++;
+ }
+ ms->ms_bq_idx = 0;
+ }
+ }
+
+out:
+ ms->ms_events.ev_put = put;
+ ms->ms_buttons = id;
+ splx(sps);
+ EV_WAKEUP(&ms->ms_events);
+}
+
+int
+msopen(dev, flags, mode, p)
+dev_t dev;
+int flags, mode;
+struct proc *p;
+{
+ u_char report_ms[] = { 0x08 };
+ struct ms_softc *ms;
+ int unit;
+
+ unit = minor(dev);
+ ms = &ms_softc[unit];
+
+ if (unit >= NMOUSE)
+ return(EXDEV);
+
+ if (ms->ms_events.ev_io)
+ return(EBUSY);
+
+ ms->ms_events.ev_io = p;
+ ms->ms_dx = ms->ms_dy = 0;
+ ms->ms_buttons = 0;
+ ms->ms_bq[0].id = ms->ms_bq[1].id = 0;
+ ms->ms_bq_idx = 0;
+ ev_init(&ms->ms_events); /* may cause sleep */
+
+ /*
+ * Enable mouse reporting.
+ */
+ kbd_write(report_ms, sizeof(report_ms));
+ return(0);
+}
+
+int
+msclose(dev, flags, mode, p)
+dev_t dev;
+int flags, mode;
+struct proc *p;
+{
+ u_char disable_ms[] = { 0x12 };
+ int unit;
+ struct ms_softc *ms;
+
+ unit = minor (dev);
+ ms = &ms_softc[unit];
+
+ /*
+ * Turn off mouse interrogation.
+ */
+ kbd_write(disable_ms, sizeof(disable_ms));
+ ev_fini(&ms->ms_events);
+ ms->ms_events.ev_io = NULL;
+ return(0);
+}
+
+int
+msread(dev, uio, flags)
+dev_t dev;
+struct uio *uio;
+int flags;
+{
+ struct ms_softc *ms;
+
+ ms = &ms_softc[minor(dev)];
+ return(ev_read(&ms->ms_events, uio, flags));
+}
+
+int
+msioctl(dev, cmd, data, flag, p)
+dev_t dev;
+u_long cmd;
+register caddr_t data;
+int flag;
+struct proc *p;
+{
+ struct ms_softc *ms;
+ int unit;
+
+ unit = minor(dev);
+ ms = &ms_softc[unit];
+
+ switch (cmd) {
+ case FIONBIO: /* we will remove this someday (soon???) */
+ return(0);
+ case FIOASYNC:
+ ms->ms_events.ev_async = *(int *)data != 0;
+ return(0);
+ case TIOCSPGRP:
+ if (*(int *)data != ms->ms_events.ev_io->p_pgid)
+ return(EPERM);
+ return(0);
+ case VUIDGFORMAT: /* we only do firm_events */
+ *(int *)data = VUID_FIRM_EVENT;
+ return(0);
+ case VUIDSFORMAT:
+ if (*(int *)data != VUID_FIRM_EVENT)
+ return(EINVAL);
+ return(0);
+ }
+ return(ENOTTY);
+}
+
+int
+msselect(dev, rw, p)
+dev_t dev;
+int rw;
+struct proc *p;
+{
+ struct ms_softc *ms;
+
+ ms = &ms_softc[minor(dev)];
+ return(ev_select(&ms->ms_events, rw, p));
+}
+#endif /* NMOUSE > 0 */
diff --git a/sys/arch/atari/dev/ncr5380.c b/sys/arch/atari/dev/ncr5380.c
new file mode 100644
index 00000000000..5d88a1f8c68
--- /dev/null
+++ b/sys/arch/atari/dev/ncr5380.c
@@ -0,0 +1,1906 @@
+/* $NetBSD: ncr5380.c,v 1.11 1995/10/08 13:34:23 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifdef DBG_NOSTATIC
+# define static
+#endif
+#ifdef DBG_SEL
+# define DBG_SELPRINT(a,b) printf(a,b)
+#else
+# define DBG_SELPRINT(a,b)
+#endif
+#ifdef DBG_PIO
+# define DBG_PIOPRINT(a,b,c) printf(a,b,c)
+#else
+# define DBG_PIOPRINT(a,b,c)
+#endif
+#ifdef DBG_INF
+# define DBG_INFPRINT(a,b,c) a(b,c)
+#else
+# define DBG_INFPRINT(a,b,c)
+#endif
+#ifdef DBG_PID
+ static char *last_hit = NULL, *olast_hit = NULL;
+# define PID(a) olast_hit = last_hit; last_hit = a;
+#else
+# define PID(a)
+#endif
+
+/*
+ * Bit mask of targets you want debugging to be shown
+ */
+u_char dbg_target_mask = 0x7f;
+
+/*
+ * Set bit for target when parity checking must be disabled.
+ * My (LWP) Maxtor 7245S seems to generate parity errors on about 50%
+ * of all transfers while the data is correct!?
+ */
+u_char ncr5380_no_parchk = 0xff;
+
+/*
+ * This is the default sense-command we send.
+ */
+static u_char sense_cmd[] = {
+ REQUEST_SENSE, 0, 0, 0, sizeof(struct scsi_sense_data), 0
+};
+
+/*
+ * True if the main co-routine is running
+ */
+static volatile int main_running = 0;
+
+/*
+ * Mask of targets selected
+ */
+static u_char busy;
+
+static void ncr5380_minphys(struct buf *bp);
+static int ncr5380_scsi_cmd(struct scsi_xfer *xs);
+static int ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
+
+struct scsi_adapter ncr5380_switch = {
+ ncr5380_scsi_cmd, /* scsi_cmd() */
+ ncr5380_minphys, /* scsi_minphys() */
+ 0, /* open_target_lu() */
+ 0 /* close_target_lu() */
+};
+
+struct scsi_device ncr5380_dev = {
+ NULL, /* use default error handler */
+ NULL, /* do not have a start functio */
+ NULL, /* have no async handler */
+ NULL /* Use default done routine */
+};
+
+
+static SC_REQ req_queue[NREQ];
+static SC_REQ *free_head = NULL; /* Free request structures */
+
+
+/*
+ * Inline functions:
+ */
+
+/*
+ * Determine the size of a SCSI command.
+ */
+extern __inline__ int command_size(opcode)
+u_char opcode;
+{
+ switch ((opcode >> 4) & 0xf) {
+ case 0:
+ case 1:
+ return (6);
+ case 2:
+ case 3:
+ return (10);
+ }
+ return (12);
+}
+
+
+/*
+ * Wait for request-line to become active. When it doesn't return 0.
+ * Otherwise return != 0.
+ * The timeouts in the 'wait_req_*' functions are arbitrary and rather
+ * large. In 99% of the invocations nearly no timeout is needed but in
+ * some cases (especially when using my tapedrive, a Tandberg 3600) the
+ * device is busy internally and the first SCSI-phase will be delayed.
+ */
+extern __inline__ int wait_req_true(void)
+{
+ int timeout = 25000;
+
+ while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
+ delay(1);
+ return (GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ);
+}
+
+/*
+ * Wait for request-line to become inactive. When it doesn't return 0.
+ * Otherwise return != 0.
+ */
+extern __inline__ int wait_req_false(void)
+{
+ int timeout = 25000;
+
+ while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
+ delay(1);
+ return (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ));
+}
+
+extern __inline__ void ack_message()
+{
+ SET_5380_REG(NCR5380_ICOM, 0);
+}
+
+extern __inline__ void nack_message(SC_REQ *reqp, u_char msg)
+{
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ reqp->msgout = msg;
+}
+
+extern __inline__ void finish_req(SC_REQ *reqp)
+{
+ int sps;
+ struct scsi_xfer *xs = reqp->xs;
+
+#ifdef REAL_DMA
+ /*
+ * If we bounced, free the bounce buffer
+ */
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ free_bounceb(reqp->bounceb);
+#endif /* REAL_DMA */
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, "DONE");
+#endif
+#ifdef DBG_ERR_RET
+ if (reqp->xs->error != 0)
+ show_request(reqp, "ERR_RET");
+#endif
+
+ /*
+ * Return request to free-q
+ */
+ sps = splbio();
+ reqp->next = free_head;
+ free_head = reqp;
+ splx(sps);
+
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+}
+
+/*
+ * Auto config stuff....
+ */
+int ncr_cprint __P((void *auxp, char *));
+void ncr_attach __P((struct device *, struct device *, void *));
+int ncr_match __P((struct device *, struct cfdata *, void *));
+
+/*
+ * Tricks to make driver-name configurable
+ */
+#define CFNAME(n) __CONCAT(n,cd)
+#define CFSTRING(n) __STRING(n)
+
+struct cfdriver CFNAME(DRNAME) = {
+ NULL, CFSTRING(DRNAME), (cfmatch_t)ncr_match, ncr_attach,
+ DV_DULL, sizeof(struct ncr_softc), NULL, 0 };
+
+int
+ncr_match(pdp, cdp, auxp)
+struct device *pdp;
+struct cfdata *cdp;
+void *auxp;
+{
+ return (machine_match(pdp, cdp, auxp, &CFNAME(DRNAME)));
+}
+
+void
+ncr_attach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ struct ncr_softc *sc;
+ int i;
+
+ sc = (struct ncr_softc *)dp;
+
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = 7;
+ sc->sc_link.adapter = &ncr5380_switch;
+ sc->sc_link.device = &ncr5380_dev;
+ sc->sc_link.openings = NREQ - 1;
+
+ /*
+ * bitmasks
+ */
+ sc->sc_noselatn = 0;
+ sc->sc_selected = 0;
+
+ /*
+ * Initialize machine-type specific things...
+ */
+ scsi_mach_init(sc);
+ printf("\n");
+
+ /*
+ * Initialize request queue freelist.
+ */
+ for (i = 0; i < NREQ; i++) {
+ req_queue[i].next = free_head;
+ free_head = &req_queue[i];
+ }
+
+ /*
+ * Initialize the host adapter
+ */
+ scsi_idisable();
+ ENABLE_NCR5380(sc);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_TCOM, 0);
+ SET_5380_REG(NCR5380_IDSTAT, 0);
+ scsi_ienable();
+
+ /*
+ * attach all scsi units on us
+ */
+ config_found(dp, &sc->sc_link, ncr_cprint);
+}
+
+/*
+ * print diag if name is NULL else just extra
+ */
+int
+ncr_cprint(auxp, name)
+void *auxp;
+char *name;
+{
+ if (name == NULL)
+ return (UNCONF);
+ return (QUIET);
+}
+/*
+ * End of auto config stuff....
+ */
+
+/*
+ * Carry out a request from the high level driver.
+ */
+static int
+ncr5380_scsi_cmd(struct scsi_xfer *xs)
+{
+ int sps;
+ SC_REQ *reqp;
+ int flags = xs->flags;
+
+ /*
+ * We do not queue RESET commands
+ */
+ if (flags & SCSI_RESET) {
+ scsi_reset(xs->sc_link->adapter_softc);
+ return (COMPLETE);
+ }
+
+ /*
+ * Get a request block
+ */
+ sps = splbio();
+ if ((reqp = free_head) == 0) {
+ splx(sps);
+ return (TRY_AGAIN_LATER);
+ }
+ free_head = reqp->next;
+ reqp->next = NULL;
+ splx(sps);
+
+ /*
+ * Initialize our private fields
+ */
+ reqp->dr_flag = (flags & SCSI_POLL) ? DRIVER_NOINT : 0;
+ reqp->phase = NR_PHASE;
+ reqp->msgout = MSG_NOOP;
+ reqp->status = SCSGOOD;
+ reqp->link = NULL;
+ reqp->xs = xs;
+ reqp->targ_id = xs->sc_link->target;
+ reqp->targ_lun = xs->sc_link->lun;
+ reqp->xdata_ptr = (u_char*)xs->data;
+ reqp->xdata_len = xs->datalen;
+ memcpy(&reqp->xcmd, xs->cmd, sizeof(struct scsi_generic));
+ reqp->xcmd.bytes[0] |= reqp->targ_lun << 5;
+
+ /*
+ * Sanity check on flags...
+ */
+ if (flags & ITSDONE) {
+ ncr_tprint(reqp, "scsi_cmd: command already done.....\n");
+ xs->flags &= ~ITSDONE;
+ }
+ if (!(flags & INUSE)) {
+ ncr_tprint(reqp, "scsi_cmd: command not in use.....\n");
+ xs->flags |= ~INUSE;
+ }
+
+#ifdef REAL_DMA
+ /*
+ * Check if DMA can be used on this request
+ */
+ if (scsi_dmaok(reqp))
+ reqp->dr_flag |= DRIVER_DMAOK;
+#endif /* REAL_DMA */
+
+ /*
+ * Insert the command into the issue queue. Note that 'REQUEST SENSE'
+ * commands are inserted at the head of the queue since any command
+ * will clear the existing contingent allegience condition and the sense
+ * data is only valid while the condition exists.
+ * When possible, link the command to a previous command to the same
+ * target. This is not very sensible when AUTO_SENSE is not defined!
+ * Interrupts are disabled while we are fiddling with the issue-queue.
+ */
+ sps = splbio();
+ if ((issue_q == NULL) || (reqp->xcmd.opcode == REQUEST_SENSE)) {
+ reqp->next = issue_q;
+ issue_q = reqp;
+ }
+ else {
+ SC_REQ *tmp, *link;
+
+ tmp = issue_q;
+ link = NULL;
+ do {
+ if (!link && (tmp->targ_id == reqp->targ_id) && !tmp->link)
+ link = tmp;
+ } while (tmp->next && (tmp = tmp->next));
+ tmp->next = reqp;
+#ifdef AUTO_SENSE
+ if (link) {
+ link->link = reqp;
+ link->xcmd.bytes[link->xs->cmdlen-1] |= 1;
+ }
+#endif
+ }
+ splx(sps);
+
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, (reqp->xcmd.opcode == REQUEST_SENSE) ?
+ "HEAD":"TAIL");
+#endif
+
+ run_main(xs->sc_link->adapter_softc);
+
+ if (xs->flags & SCSI_POLL)
+ return (COMPLETE); /* We're booting */
+ return (SUCCESSFULLY_QUEUED);
+}
+
+static void
+ncr5380_minphys(struct buf *bp)
+{
+ if (bp->b_bcount > MIN_PHYS)
+ bp->b_bcount = MIN_PHYS;
+ minphys(bp);
+}
+#undef MIN_PHYS
+
+static int
+ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
+{
+ u_char *b = (u_char *) xs->cmd;
+ int i = 0;
+
+ if (!(xs->flags & SCSI_RESET)) {
+ printf("(%d:%d:%d,0x%x)-", xs->sc_link->scsibus,
+ xs->sc_link->target, xs->sc_link->lun, xs->sc_link->flags);
+ while (i < xs->cmdlen) {
+ if (i)
+ printf(",");
+ printf("%x",b[i++]);
+ }
+ printf("-\n");
+ }
+ else {
+ printf("(%d:%d:%d)-RESET-\n",
+ xs->sc_link->scsibus,xs->sc_link->target, xs->sc_link->lun);
+ }
+}
+
+/*
+ * The body of the driver.
+ */
+static void
+scsi_main(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *req, *prev;
+ int itype;
+ int sps;
+
+ /*
+ * While running in the driver SCSI-interrupts are disabled.
+ */
+ scsi_idisable();
+ ENABLE_NCR5380(sc);
+
+ PID("scsi_main1");
+ for (;;) {
+ sps = splbio();
+ if (!connected) {
+ /*
+ * Check if it is fair keep any exclusive access to DMA
+ * claimed. If not, stop queueing new jobs so the discon_q
+ * will be eventually drained and DMA can be given up.
+ */
+ if (!fair_to_keep_dma())
+ goto main_exit;
+
+ /*
+ * Search through the issue-queue for a command
+ * destined for a target that isn't busy.
+ */
+ prev = NULL;
+ for (req=issue_q; req != NULL; prev = req, req = req->next) {
+ if (!(busy & (1 << req->targ_id))) {
+ /*
+ * Found one, remove it from the issue queue
+ */
+ if (prev == NULL)
+ issue_q = req->next;
+ else prev->next = req->next;
+ req->next = NULL;
+ break;
+ }
+ }
+
+ /*
+ * When a request has just ended, we get here before an other
+ * device detects that the bus is free and that it can
+ * reconnect. The problem is that when this happens, we always
+ * baffle the device because our (initiator) id is higher. This
+ * can cause a sort of starvation on slow devices. So we check
+ * for a pending reselection here.
+ * Note that 'connected' will be non-null if the reselection
+ * succeeds.
+ */
+ if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
+ == (SC_S_SEL|SC_S_IO)){
+ if (req != NULL) {
+ req->next = issue_q;
+ issue_q = req;
+ }
+ splx(sps);
+
+ reselect(sc);
+ scsi_clr_ipend();
+ goto connected;
+ }
+
+ /*
+ * The host is not connected and there is no request
+ * pending, exit.
+ */
+ if (req == NULL) {
+ PID("scsi_main2");
+ goto main_exit;
+ }
+
+ /*
+ * Re-enable interrupts before handling the request.
+ */
+ splx(sps);
+
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << req->targ_id))
+ show_request(req, "TARGET");
+#endif
+ /*
+ * We found a request. Try to connect to the target. If the
+ * initiator fails arbitration, the command is put back in the
+ * issue queue.
+ */
+ if (scsi_select(req, 0)) {
+ sps = splbio();
+ req->next = issue_q;
+ issue_q = req;
+ splx(sps);
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << req->targ_id))
+ ncr_tprint(req, "Select failed\n");
+#endif
+ }
+ }
+ else splx(sps);
+connected:
+ if (connected) {
+ /*
+ * If the host is currently connected but a 'real-dma' transfer
+ * is in progress, the 'end-of-dma' interrupt restarts main.
+ * So quit.
+ */
+ sps = splbio();
+ if (connected && (connected->dr_flag & DRIVER_IN_DMA)) {
+ PID("scsi_main3");
+ goto main_exit;
+ }
+ splx(sps);
+
+ /*
+ * Let the target guide us through the bus-phases
+ */
+ while (information_transfer() == -1)
+ ;
+ }
+ }
+ /* NEVER TO REACH HERE */
+ panic("ncr5380-SCSI: not designed to come here");
+
+main_exit:
+ /*
+ * We enter here with interrupts disabled. We are about to exit main
+ * so interrupts should be re-enabled. Because interrupts are edge
+ * triggered, we could already have missed the interrupt. Therefore
+ * we check the IRQ-line here and re-enter when we really missed a
+ * valid interrupt.
+ */
+ PID("scsi_main4");
+ scsi_ienable();
+ SET_5380_REG(NCR5380_IDSTAT, SC_HOST_ID);
+ if (GET_5380_REG(NCR5380_DMSTAT) & SC_IRQ_SET) {
+ if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
+ scsi_idisable();
+ splx(sps);
+
+ if (itype == INTR_RESEL)
+ reselect(sc);
+#ifdef REAL_DMA
+ else dma_ready();
+#else
+ else {
+ if (pdma_ready())
+ goto connected;
+ panic("Got DMA interrupt without DMA");
+ }
+#endif
+ scsi_clr_ipend();
+ goto connected;
+ }
+ }
+ reconsider_dma();
+
+ main_running = 0;
+ splx(sps);
+ PID("scsi_main5");
+}
+
+#ifdef REAL_DMA
+/*
+ * The SCSI-DMA interrupt.
+ * This interrupt can only be triggered when running in non-polled DMA
+ * mode. When DMA is not active, it will be silently ignored, it is usually
+ * to late because the EOP interrupt of the controller happens just a tiny
+ * bit earlier. It might become usefull when scatter/gather is implemented,
+ * because in that case only part of the DATAIN/DATAOUT transfer is taken
+ * out of a single buffer.
+ */
+static void
+ncr_dma_intr(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *reqp;
+ int dma_done;
+
+ PID("ncr_dma_intr");
+ if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)) {
+ scsi_idisable();
+ if (!(dma_done = dma_ready())) {
+ transfer_dma(reqp, reqp->phase, 0);
+ return;
+ }
+ run_main(sc);
+ }
+}
+#endif /* REAL_DMA */
+
+/*
+ * The SCSI-controller interrupt. This interrupt occurs on reselections and
+ * at the end of non-polled DMA-interrupts. It is assumed to be called from
+ * the machine-dependent hardware interrupt.
+ */
+static void
+ncr_ctrl_intr(sc)
+struct ncr_softc *sc;
+{
+ int itype;
+ int dma_done;
+
+ while (GET_5380_REG(NCR5380_DMSTAT) & SC_IRQ_SET) {
+ scsi_idisable();
+ if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
+ if (itype == INTR_RESEL)
+ reselect(sc);
+ else {
+#ifdef REAL_DMA
+ if (!(dma_done = dma_ready())) {
+ transfer_dma(connected, connected->phase, 0);
+ return;
+ }
+#else
+ if (pdma_ready())
+ return;
+ panic("Got DMA interrupt without DMA\n");
+#endif
+ }
+ scsi_clr_ipend();
+ }
+ run_main(sc);
+ return;
+ }
+ PID("ncr_ctrl_intr1");
+}
+
+/*
+ * Initiate a connection path between the host and the target. The function
+ * first goes into arbitration for the SCSI-bus. When this succeeds, the target
+ * is selected and an 'IDENTIFY' message is send.
+ * Returns -1 when the arbitration failed. Otherwise 0 is returned. When
+ * the target does not respond (to either selection or 'MESSAGE OUT') the
+ * 'done' function is executed.
+ * The result code given by the driver can be influenced by setting 'code'
+ * to a non-zero value. This is the case when 'select' is called by abort.
+ */
+static int
+scsi_select(reqp, code)
+SC_REQ *reqp;
+{
+ u_long timeout;
+ u_char tmp[1];
+ u_char phase;
+ u_long cnt;
+ int sps;
+ u_int8_t atn_flag;
+ u_int8_t targ_bit;
+ struct ncr_softc *sc;
+
+ sc = reqp->xs->sc_link->adapter_softc;
+ DBG_SELPRINT ("Starting arbitration\n", 0);
+ PID("scsi_select1");
+
+ sps = splbio();
+
+ /*
+ * Prevent a race condition here. If a reslection interrupt occurred
+ * between the decision to pick a new request and the call to select,
+ * we abort the selection.
+ * Interrupts are lowered when the 5380 is setup to arbitrate for the
+ * bus.
+ */
+ if (connected) {
+ splx(sps);
+ PID("scsi_select2");
+ return (-1);
+ }
+
+ /*
+ * Set phase bits to 0, otherwise the 5380 won't drive the bus during
+ * selection.
+ */
+ SET_5380_REG(NCR5380_TCOM, 0);
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ /*
+ * Arbitrate for the bus.
+ */
+ SET_5380_REG(NCR5380_DATA, SC_HOST_ID);
+ SET_5380_REG(NCR5380_MODE, SC_ARBIT);
+
+ splx(sps);
+
+ cnt = 10;
+ while (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP) && --cnt)
+ delay(1);
+
+ if (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP)) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ DBG_SELPRINT ("Arbitration lost, bus not free\n",0);
+ PID("scsi_select3");
+ return (-1);
+ }
+
+ /* The arbitration delay is 2.2 usecs */
+ delay(3);
+
+ /*
+ * Check the result of the arbitration. If we failed, return -1.
+ */
+ if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ PID("scsi_select4");
+ return (-1);
+ }
+
+ /*
+ * The spec requires that we should read the data register to
+ * check for higher id's and check the SC_LA again.
+ */
+ tmp[0] = GET_5380_REG(NCR5380_DATA);
+ if (tmp[0] & ~((SC_HOST_ID << 1) - 1)) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ DBG_SELPRINT ("Arbitration lost, higher id present\n",0);
+ PID("scsi_select5");
+ return (-1);
+ }
+ if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0);
+ PID("scsi_select6");
+ return (-1);
+ }
+ SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_BSY);
+ if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+ DBG_SELPRINT ("Arbitration lost, deassert SC_A_SEL\n", 0);
+ PID("scsi_select7");
+ return (-1);
+ }
+ /* Bus settle delay + Bus clear delay = 1.2 usecs */
+ delay(2);
+ DBG_SELPRINT ("Arbitration complete\n", 0);
+
+ /*
+ * Now that we won the arbitration, start the selection.
+ */
+ targ_bit = 1 << reqp->targ_id;
+ SET_5380_REG(NCR5380_DATA, SC_HOST_ID | targ_bit);
+
+ if (sc->sc_noselatn & targ_bit)
+ atn_flag = 0;
+ else
+ atn_flag = SC_A_ATN;
+
+ /*
+ * Raise ATN while SEL is true before BSY goes false from arbitration,
+ * since this is the only way to guarantee that we'll get a MESSAGE OUT
+ * phase immediately after the selection.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_BSY | SC_A_SEL | atn_flag | SC_ADTB);
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+
+ /*
+ * Turn off reselection interrupts
+ */
+ SET_5380_REG(NCR5380_IDSTAT, 0);
+
+ /*
+ * Reset BSY. The delay following it, surpresses a glitch in the
+ * 5380 which causes us to see our own BSY signal instead of that of
+ * the target.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag | SC_ADTB);
+ delay(1);
+
+ /*
+ * Wait for the target to react, the specs call for a timeout of
+ * 250 ms.
+ */
+ cnt = 25000;
+ while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) && --cnt)
+ delay(10);
+
+ if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
+ /*
+ * There is no reaction from the target, start the selection
+ * timeout procedure. We release the databus but keep SEL
+ * asserted. After that we wait a 'selection abort time' (200
+ * usecs) and 2 deskew delays (90 ns) and check BSY again.
+ * When BSY is asserted, we assume the selection succeeded,
+ * otherwise we release the bus.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag);
+ delay(201);
+ if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
+ SET_5380_REG(NCR5380_ICOM, 0);
+ reqp->xs->error = code ? code : XS_SELTIMEOUT;
+ DBG_SELPRINT ("Target %d not responding to sel\n",
+ reqp->targ_id);
+ finish_req(reqp);
+ PID("scsi_select8");
+ return (0);
+ }
+ }
+ SET_5380_REG(NCR5380_ICOM, atn_flag);
+
+ DBG_SELPRINT ("Target %d responding to select.\n", reqp->targ_id);
+
+ /*
+ * The SCSI-interrupts are disabled while a request is being handled.
+ */
+ scsi_idisable();
+
+ /*
+ * If we did not request ATN, then don't try to send IDENTIFY.
+ */
+ if (atn_flag == 0) {
+ reqp->phase = PH_CMD;
+ goto identify_failed;
+ }
+
+ /*
+ * Here we prepare to send an 'IDENTIFY' message.
+ * Allow disconnect only when interrups are allowed.
+ */
+ tmp[0] = MSG_IDENTIFY(reqp->targ_lun,
+ (reqp->dr_flag & DRIVER_NOINT) ? 0 : 1);
+ cnt = 1;
+ phase = PH_MSGOUT;
+
+ /*
+ * Since we followed the SCSI-spec and raised ATN while SEL was true
+ * but before BSY was false during the selection, a 'MESSAGE OUT'
+ * phase should follow. Unfortunately, this does not happen on
+ * all targets (Asante ethernet devices, for example), so we must
+ * check the actual mode if the message transfer fails--if the
+ * new phase is PH_CMD and has never been successfully selected
+ * w/ATN in the past, then we assume that it is an old device
+ * that doesn't support select w/ATN.
+ */
+ if (transfer_pio(&phase, tmp, &cnt, 0) || cnt) {
+
+ if ((phase == PH_CMD) && !(sc->sc_selected & targ_bit)) {
+ DBG_SELPRINT ("Target %d: not responding to ATN.\n",
+ reqp->targ_id);
+ sc->sc_noselatn |= targ_bit;
+ reqp->phase = PH_CMD;
+ goto identify_failed;
+ }
+
+ DBG_SELPRINT ("Target %d: failed to send identify\n",
+ reqp->targ_id);
+ /*
+ * Try to disconnect from the target. We cannot leave
+ * it just hanging here.
+ */
+ if (!reach_msg_out(sc, sizeof(struct scsi_generic))) {
+ u_long len = 1;
+ u_char phase = PH_MSGOUT;
+ u_char msg = MSG_ABORT;
+
+ transfer_pio(&phase, &msg, &len, 0);
+ }
+ else scsi_reset(sc);
+
+ SET_5380_REG(NCR5380_ICOM, 0);
+ reqp->xs->error = code ? code : XS_DRIVER_STUFFUP;
+ finish_req(reqp);
+ PID("scsi_select9");
+ return (0);
+ }
+ reqp->phase = PH_MSGOUT;
+
+identify_failed:
+ sc->sc_selected |= targ_bit;
+
+#ifdef notyet /* LWP: Do we need timeouts in the driver? */
+ /*
+ * Command is connected, start timer ticking.
+ */
+ ccb_p->xtimeout = ccb_p->timeout + Lbolt;
+#endif
+
+ connected = reqp;
+ busy |= targ_bit;
+ PID("scsi_select10");
+ return (0);
+}
+
+/*
+ * Return codes:
+ * -1: quit main, trigger on interrupt
+ * 0: keep on running main.
+ */
+static int
+information_transfer()
+{
+ SC_REQ *reqp = connected;
+ u_char tmp, phase;
+ u_long len;
+
+ PID("info_transf1");
+ /*
+ * Clear pending interrupts from 5380-chip.
+ */
+ scsi_clr_ipend();
+
+ /*
+ * We only have a valid SCSI-phase when REQ is asserted. Something
+ * is deadly wrong when BSY has dropped.
+ */
+ tmp = GET_5380_REG(NCR5380_IDSTAT);
+
+ if (!(tmp & SC_S_BSY)) {
+ busy &= ~(1 << reqp->targ_id);
+ connected = NULL;
+ reqp->xs->error = XS_BUSY;
+ finish_req(reqp);
+ PID("info_transf2");
+ return (0);
+ }
+
+ if (tmp & SC_S_REQ) {
+ phase = (tmp >> 2) & 7;
+ if (phase != reqp->phase) {
+ reqp->phase = phase;
+ DBG_INFPRINT(show_phase, reqp, phase);
+ }
+ }
+ else return (-1);
+
+ switch (phase) {
+ case PH_DATAOUT:
+#ifdef DBG_NOWRITE
+ ncr_tprint(reqp, "NOWRITE set -- write attempt aborted.");
+ reqp->msgout = MSG_ABORT;
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ return (-1);
+#endif /* DBG_NOWRITE */
+ /*
+ * If this is the first write using DMA, fill
+ * the bounce buffer.
+ */
+ if (reqp->xdata_ptr == reqp->xs->data) { /* XXX */
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ bcopy(reqp->xdata_ptr, reqp->bounceb, reqp->xdata_len);
+ }
+
+ case PH_DATAIN:
+#ifdef REAL_DMA
+ if (reqp->dr_flag & DRIVER_DMAOK) {
+ int poll = REAL_DMA_POLL|(reqp->dr_flag & DRIVER_NOINT);
+ transfer_dma(reqp, phase, poll);
+ if (!poll)
+ return (0);
+ }
+ else
+#endif
+ {
+ PID("info_transf3");
+ len = reqp->xdata_len;
+#ifdef USE_PDMA
+ if (transfer_pdma(&phase, reqp->xdata_ptr, &len) == 0)
+ return (0);
+#else
+ transfer_pio(&phase, reqp->xdata_ptr, &len, 0);
+#endif
+ reqp->xdata_ptr += reqp->xdata_len - len;
+ reqp->xdata_len = len;
+ }
+ return (-1);
+ case PH_MSGIN:
+ /*
+ * We only expect single byte messages here.
+ */
+ len = 1;
+ transfer_pio(&phase, &tmp, &len, 1);
+ reqp->message = tmp;
+ return (handle_message(reqp, tmp));
+ case PH_MSGOUT:
+ len = 1;
+ transfer_pio(&phase, &reqp->msgout, &len, 0);
+ if (reqp->msgout == MSG_ABORT) {
+ busy &= ~(1 << reqp->targ_id);
+ connected = NULL;
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ finish_req(reqp);
+ PID("info_transf4");
+ return (0);
+ }
+ reqp->msgout = MSG_NOOP;
+ return (-1);
+ case PH_CMD :
+ len = command_size(reqp->xcmd.opcode);
+ transfer_pio(&phase, (u_char *)&reqp->xcmd, &len, 0);
+ PID("info_transf5");
+ return (-1);
+ case PH_STATUS:
+ len = 1;
+ transfer_pio(&phase, &tmp, &len, 0);
+ reqp->status = tmp;
+ PID("info_transf6");
+ return (-1);
+ default :
+ ncr_tprint(reqp, "Unknown phase\n");
+ }
+ PID("info_transf7");
+ return (-1);
+}
+
+/*
+ * Handle the message 'msg' send to us by the target.
+ * Return values:
+ * 0 : The current command has completed.
+ * -1 : Get on to the next phase.
+ */
+static int
+handle_message(reqp, msg)
+SC_REQ *reqp;
+u_int msg;
+{
+ int sps;
+
+ PID("hmessage1");
+ switch (msg) {
+ /*
+ * Linking lets us reduce the time required to get
+ * the next command to the device, skipping the arbitration
+ * and selection time. In the current implementation,
+ * we merely have to start the next command pointed
+ * to by 'next_link'.
+ */
+ case MSG_LINK_CMD_COMPLETE:
+ case MSG_LINK_CMD_COMPLETEF:
+ if (reqp->link == NULL) {
+ ncr_tprint(reqp, "No link for linked command");
+ nack_message(reqp, MSG_ABORT);
+ PID("hmessage2");
+ return (-1);
+ }
+ ack_message();
+ reqp->xs->error = 0;
+
+#ifdef AUTO_SENSE
+ if (check_autosense(reqp, 0) == -1)
+ return (-1);
+#endif /* AUTO_SENSE */
+
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp->link, "LINK");
+#endif
+ connected = reqp->link;
+ finish_req(reqp);
+ PID("hmessage3");
+ return (-1);
+ case MSG_ABORT:
+ case MSG_CMDCOMPLETE:
+ ack_message();
+ connected = NULL;
+ busy &= ~(1 << reqp->targ_id);
+ if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
+ reqp->xs->resid = reqp->xdata_len;
+ reqp->xs->error = 0;
+ }
+
+#ifdef AUTO_SENSE
+ if (check_autosense(reqp, 0) == -1) {
+ PID("hmessage4");
+ return (0);
+ }
+#endif /* AUTO_SENSE */
+
+ finish_req(reqp);
+ PID("hmessage5");
+ return (0);
+ case MSG_MESSAGE_REJECT:
+ ack_message();
+ PID("hmessage6");
+ return (-1);
+ case MSG_DISCONNECT:
+ ack_message();
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, "DISCON");
+#endif
+ sps = splbio();
+ connected = NULL;
+ reqp->next = discon_q;
+ discon_q = reqp;
+ splx(sps);
+ PID("hmessage7");
+ return (0);
+ case MSG_SAVEDATAPOINTER:
+ case MSG_RESTOREPOINTERS:
+ /*
+ * We save pointers implicitely at disconnect.
+ * So we can ignore these messages.
+ */
+ ack_message();
+ PID("hmessage8");
+ return (-1);
+ case MSG_EXTENDED:
+ nack_message(reqp, MSG_MESSAGE_REJECT);
+ PID("hmessage9");
+ return (-1);
+ default:
+ ncr_tprint(reqp, "Unknown message %x\n", msg);
+ return (-1);
+ }
+ PID("hmessage10");
+ return (-1);
+}
+
+/*
+ * Handle reselection. If a valid reconnection occurs, connected
+ * points at the reconnected command. The command is removed from the
+ * disconnected queue.
+ */
+static void
+reselect(sc)
+struct ncr_softc *sc;
+{
+ u_char phase;
+ u_long len;
+ u_char msg;
+ u_char target_mask;
+ int abort = 0;
+ SC_REQ *tmp, *prev;
+
+ PID("reselect1");
+ target_mask = GET_5380_REG(NCR5380_DATA) & ~SC_HOST_ID;
+
+ /*
+ * At this point, we have detected that our SCSI-id is on the bus,
+ * SEL is true and BSY was false for at least one bus settle
+ * delay (400 ns.).
+ * We must assert BSY ourselves, until the target drops the SEL signal.
+ * The SCSI-spec specifies no maximum time for this, so we have to
+ * choose something long enough to suit all targets.
+ */
+ SET_5380_REG(NCR5380_ICOM, SC_A_BSY);
+ len = 1000;
+ while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) && (len > 0)) {
+ if(!GET_5380_REG(NCR5380_DATA)) {
+ /*
+ * We stepped into the reselection timeout....
+ */
+ SET_5380_REG(NCR5380_ICOM, 0);
+ return;
+ }
+ delay(1);
+ len--;
+ }
+ if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) {
+ /* Damn SEL isn't dropping */
+ scsi_reset(sc);
+ return;
+ }
+
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ /*
+ * Get the expected identify message.
+ */
+ phase = PH_MSGIN;
+ len = 1;
+ transfer_pio(&phase, &msg, &len, 0);
+ if (len || !MSG_ISIDENTIFY(msg)) {
+ ncr_aprint(sc, "Expecting IDENTIFY, got 0x%x\n", msg);
+ abort = 1;
+ }
+ else {
+ /*
+ * Find the command reconnecting
+ */
+ for (tmp = discon_q, prev = NULL; tmp; prev = tmp, tmp = tmp->next){
+ if (target_mask == (1 << tmp->targ_id)) {
+ if (prev)
+ prev->next = tmp->next;
+ else discon_q = tmp->next;
+ tmp->next = NULL;
+ break;
+ }
+ }
+ if (tmp == NULL) {
+ ncr_aprint(sc, "No disconnected job for targetmask %x\n",
+ target_mask);
+ abort = 1;
+ }
+ }
+ if (abort) {
+ msg = MSG_ABORT;
+ len = 1;
+ phase = PH_MSGOUT;
+
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ transfer_pio(&phase, &msg, &len, 0);
+ }
+ else {
+ connected = tmp;
+#ifdef DBG_REQ
+ if (dbg_target_mask & (1 << tmp->targ_id))
+ show_request(tmp, "RECON");
+#endif
+ }
+ PID("reselect2");
+}
+
+/*
+ * Transfer data in a given phase using programmed I/O.
+ * Returns -1 when a different phase is entered without transferring the
+ * maximum number of bytes, 0 if all bytes transferred or exit is in the same
+ * phase.
+ */
+static int
+transfer_pio(phase, data, len, dont_drop_ack)
+u_char *phase;
+u_char *data;
+u_long *len;
+int dont_drop_ack;
+{
+ u_int cnt = *len;
+ u_char ph = *phase;
+ u_char tmp, new_icom;
+
+ DBG_PIOPRINT ("SCSI: transfer_pio start: phase: %d, len: %d\n", ph,cnt);
+ PID("tpio1");
+ SET_5380_REG(NCR5380_TCOM, ph);
+ do {
+ if (!wait_req_true()) {
+ DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
+ break;
+ }
+ if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != ph) {
+ DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
+ break;
+ }
+ if (PH_IN(ph)) {
+ *data++ = GET_5380_REG(NCR5380_DATA);
+ SET_5380_REG(NCR5380_ICOM, SC_A_ACK);
+ if ((cnt == 1) && dont_drop_ack)
+ new_icom = SC_A_ACK;
+ else new_icom = 0;
+ }
+ else {
+ SET_5380_REG(NCR5380_DATA, *data++);
+
+ /*
+ * The SCSI-standard suggests that in the 'MESSAGE OUT' phase,
+ * the initiator should drop ATN on the last byte of the
+ * message phase after REQ has been asserted for the handshake
+ * but before the initiator raises ACK.
+ */
+ if (!( (ph == PH_MSGOUT) && (cnt > 1) )) {
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB);
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ACK);
+ new_icom = 0;
+ }
+ else {
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ATN);
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ATN|SC_A_ACK);
+ new_icom = SC_A_ATN;
+ }
+ }
+ if (!wait_req_false()) {
+ DBG_PIOPRINT ("SCSI: transfer_pio - REQ not dropping\n", 0, 0);
+ break;
+ }
+ SET_5380_REG(NCR5380_ICOM, new_icom);
+
+ } while (--cnt);
+
+ if ((tmp = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
+ *phase = (tmp >> 2) & 7;
+ else *phase = NR_PHASE;
+ *len = cnt;
+ DBG_PIOPRINT ("SCSI: transfer_pio done: phase: %d, len: %d\n",
+ *phase, cnt);
+ PID("tpio2");
+ if (!cnt || (*phase == ph))
+ return (0);
+ return (-1);
+}
+
+#ifdef REAL_DMA
+/*
+ * Start a DMA-transfer on the device using the current pointers.
+ * If 'poll' is true, the function busy-waits until DMA has completed.
+ */
+static void
+transfer_dma(reqp, phase, poll)
+SC_REQ *reqp;
+u_int phase;
+int poll;
+{
+ int dma_done;
+ u_char mbase = 0;
+ int sps;
+
+again:
+ PID("tdma1");
+
+ /*
+ * We should be in phase, otherwise we are not allowed to
+ * drive the bus.
+ */
+ SET_5380_REG(NCR5380_TCOM, phase);
+
+ /*
+ * Defer interrupts until DMA is fully running.
+ */
+ sps = splbio();
+
+ /*
+ * Clear pending interrupts and parity errors.
+ */
+ scsi_clr_ipend();
+
+ if (!poll) {
+ /*
+ * Enable SCSI interrupts and set IN_DMA flag, set 'mbase'
+ * to the interrupts we want enabled.
+ */
+ scsi_ienable();
+ reqp->dr_flag |= DRIVER_IN_DMA;
+ mbase = SC_E_EOPI | SC_MON_BSY;
+ }
+ else scsi_idisable();
+ mbase |= IMODE_BASE | SC_M_DMA;
+ scsi_dma_setup(reqp, phase, mbase);
+
+ splx(sps);
+
+ if (poll) {
+ /*
+ * On polled-dma transfers, we wait here until the
+ * 'end-of-dma' condition occurs.
+ */
+ poll_edma(reqp);
+ if (!(dma_done = dma_ready()))
+ goto again;
+ }
+ PID("tdma2");
+}
+
+/*
+ * Check results of a DMA data-transfer.
+ */
+static int
+dma_ready()
+{
+ SC_REQ *reqp = connected;
+ int dmstat, is_edma;
+ long bytes_left, bytes_done;
+
+ is_edma = get_dma_result(reqp, &bytes_left);
+ dmstat = GET_5380_REG(NCR5380_DMSTAT);
+
+ /*
+ * Check if the call is sensible and not caused by any spurious
+ * interrupt.
+ */
+ if (!is_edma && !(dmstat & (SC_END_DMA|SC_BSY_ERR))
+ && (dmstat & SC_PHS_MTCH) ) {
+ ncr_tprint(reqp, "dma_ready: spurious call"
+ "(dm:%x,last_hit: %s)\n",
+#ifdef DBG_PID
+ dmstat, last_hit);
+#else
+ dmstat, "unknown");
+#endif
+ return (0);
+ }
+
+ /*
+ * Clear all (pending) interrupts.
+ */
+ scsi_clr_ipend();
+
+ /*
+ * Update various transfer-pointers/lengths
+ */
+ bytes_done = reqp->dm_cur->dm_count - bytes_left;
+
+ if ((reqp->dr_flag & DRIVER_BOUNCING) && (PH_IN(reqp->phase))) {
+ /*
+ * Copy the bytes read until now from the bounce buffer
+ * to the 'real' destination. Flush the data-cache
+ * before copying.
+ */
+ PCIA();
+ bcopy(reqp->bouncerp, reqp->xdata_ptr, bytes_done);
+ reqp->bouncerp += bytes_done;
+ }
+
+ reqp->xdata_ptr = &reqp->xdata_ptr[bytes_done]; /* XXX */
+ reqp->xdata_len -= bytes_done; /* XXX */
+ if ((reqp->dm_cur->dm_count -= bytes_done) == 0)
+ reqp->dm_cur++;
+ else reqp->dm_cur->dm_addr += bytes_done;
+
+ if (PH_IN(reqp->phase) && (dmstat & SC_PAR_ERR)) {
+ if (!(ncr5380_no_parchk & (1 << reqp->targ_id)))
+ /* XXX: Should be parity error ???? */
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ }
+
+ /*
+ * DMA mode should always be reset even when we will continue with the
+ * next chain. It is also essential to clear the MON_BUSY because
+ * when LOST_BUSY is unexpectedly set, we will not be able to drive
+ * the bus....
+ */
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+
+
+ if ((dmstat & SC_BSY_ERR) || !(dmstat & SC_PHS_MTCH)
+ || (reqp->dm_cur > reqp->dm_last) || (reqp->xs->error)) {
+
+ /*
+ * Tell interrupt functions DMA mode has ended.
+ */
+ reqp->dr_flag &= ~DRIVER_IN_DMA;
+
+ /*
+ * Clear mode and icom
+ */
+ SET_5380_REG(NCR5380_MODE, IMODE_BASE);
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ if (dmstat & SC_BSY_ERR) {
+ if (!reqp->xs->error)
+ reqp->xs->error = XS_BUSY;
+ finish_req(reqp);
+ PID("dma_ready1");
+ return (1);
+ }
+
+ if (reqp->xs->error != 0) {
+ncr_tprint(reqp, "dma-ready: code = %d\n", reqp->xs->error); /* LWP */
+ reqp->msgout = MSG_ABORT;
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ }
+ PID("dma_ready2");
+ return (1);
+ }
+ return (0);
+}
+#endif /* REAL_DMA */
+
+static int
+check_autosense(reqp, linked)
+SC_REQ *reqp;
+int linked;
+{
+ int sps;
+
+ /*
+ * If we not executing an auto-sense and the status code
+ * is request-sense, we automatically issue a request
+ * sense command.
+ */
+ PID("cautos1");
+ if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
+ if (reqp->status == SCSCHKC) {
+ memcpy(&reqp->xcmd, sense_cmd, sizeof(sense_cmd));
+ reqp->xdata_ptr = (u_char *)&reqp->xs->sense;
+ reqp->xdata_len = sizeof(reqp->xs->sense);
+ reqp->dr_flag |= DRIVER_AUTOSEN;
+ reqp->dr_flag &= ~DRIVER_DMAOK;
+ if (!linked) {
+ sps = splbio();
+ reqp->next = issue_q;
+ issue_q = reqp;
+ splx(sps);
+ }
+ else reqp->xcmd.bytes[4] |= 1;
+
+#ifdef DBG_REQ
+ bzero(reqp->xdata_ptr, reqp->xdata_len);
+ if (dbg_target_mask & (1 << reqp->targ_id))
+ show_request(reqp, "AUTO-SENSE");
+#endif
+ PID("cautos2");
+ return (-1);
+ }
+ }
+ else {
+ /*
+ * An auto-sense has finished
+ */
+ if ((reqp->status & SCSMASK) != SCSGOOD)
+ reqp->xs->error = XS_DRIVER_STUFFUP; /* SC_E_AUTOSEN; */
+ else reqp->xs->error = XS_SENSE;
+ reqp->status = SCSCHKC;
+ }
+ PID("cautos3");
+ return (0);
+}
+
+static int
+reach_msg_out(sc, len)
+struct ncr_softc *sc;
+u_long len;
+{
+ u_char phase;
+ u_char data;
+
+ ncr_aprint(sc, "Trying to reach Message-out phase\n");
+ if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
+ phase = (phase >> 2) & 7;
+ else return (-1);
+ ncr_aprint(sc, "Trying to reach Message-out phase, now: %d\n", phase);
+ if (phase == PH_MSGOUT)
+ return (0);
+
+ SET_5380_REG(NCR5380_TCOM, phase);
+
+ do {
+ if (!wait_req_true())
+ break;
+ if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != phase)
+ break;
+ if (PH_IN(phase)) {
+ data = GET_5380_REG(NCR5380_DATA);
+ SET_5380_REG(NCR5380_ICOM, SC_A_ACK | SC_A_ATN);
+ }
+ else {
+ SET_5380_REG(NCR5380_DATA, 0);
+ SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ACK|SC_A_ATN);
+ }
+ if (!wait_req_false())
+ break;
+ SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
+ } while (--len);
+
+ if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ) {
+ phase = (phase >> 2) & 7;
+ if (phase == PH_MSGOUT) {
+ ncr_aprint(sc, "Message-out phase reached.\n");
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+static void
+scsi_reset(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *tmp, *next;
+ int sps;
+
+ ncr_aprint(sc, "Resetting SCSI-bus\n");
+
+ PID("scsi_reset1");
+ sps = splbio();
+ SET_5380_REG(NCR5380_ICOM, SC_A_RST);
+ delay(1);
+ SET_5380_REG(NCR5380_ICOM, 0);
+
+ /*
+ * None of the jobs in the discon_q will ever be reconnected,
+ * notify this to the higher level code.
+ */
+ for (tmp = discon_q; tmp ;) {
+ next = tmp->next;
+ tmp->next = NULL;
+ tmp->xs->error = XS_TIMEOUT;
+ busy &= ~(1 << tmp->targ_id);
+ finish_req(tmp);
+ tmp = next;
+ }
+ discon_q = NULL;
+
+ /*
+ * The current job will never finish either.
+ * The problem is that we can't finish the job because an instance
+ * of main is running on it. Our best guess is that the job is currently
+ * doing REAL-DMA. In that case 'dma_ready()' should correctly finish
+ * the job because it detects BSY-loss.
+ */
+ if (tmp = connected) {
+ if (tmp->dr_flag & DRIVER_IN_DMA) {
+ tmp->xs->error = XS_DRIVER_STUFFUP;
+#ifdef REAL_DMA
+ dma_ready();
+#endif
+ }
+ }
+ splx(sps);
+ PID("scsi_reset2");
+}
+
+/*
+ * Check validity of the IRQ set by the 5380. If the interrupt is valid,
+ * the appropriate action is carried out (reselection or DMA ready) and
+ * INTR_RESEL or INTR_DMA is returned. Otherwise a console notice is written
+ * and INTR_SPURIOUS is returned.
+ */
+static int
+check_intr(sc)
+struct ncr_softc *sc;
+{
+ SC_REQ *reqp;
+
+ if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
+ ==(SC_S_SEL|SC_S_IO))
+ return (INTR_RESEL);
+ else {
+ if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)){
+ reqp->dr_flag &= ~DRIVER_IN_DMA;
+ return (INTR_DMA);
+ }
+ }
+ scsi_clr_ipend();
+ printf("-->");
+ scsi_show();
+ ncr_aprint(sc, "Spurious interrupt.\n");
+ return (INTR_SPURIOUS);
+}
+
+#ifdef REAL_DMA
+/*
+ * Check if DMA can be used for this request. This function also builds
+ * the dma-chain.
+ */
+static int
+scsi_dmaok(reqp)
+SC_REQ *reqp;
+{
+ u_long phy_buf;
+ u_long phy_len;
+ void *req_addr;
+ u_long req_len;
+ struct dma_chain *dm;
+
+ /*
+ * Initialize locals and requests' DMA-chain.
+ */
+ req_len = reqp->xdata_len;
+ req_addr = (void*)reqp->xdata_ptr;
+ dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
+ dm->dm_count = dm->dm_addr = 0;
+ reqp->dr_flag &= ~DRIVER_BOUNCING;
+
+ /*
+ * Do not accept zero length DMA.
+ */
+ if (req_len == 0)
+ return (0);
+
+ /*
+ * LWP: I think that this restriction is not strictly nessecary.
+ */
+ if ((req_len & 0x1) || ((u_int)req_addr & 0x3))
+ return (0);
+
+ /*
+ * Build the DMA-chain.
+ */
+ dm->dm_addr = phy_buf = kvtop(req_addr);
+ while (req_len) {
+ if (req_len < (phy_len = NBPG - ((u_long)req_addr & PGOFSET)))
+ phy_len = req_len;
+
+ req_addr += phy_len;
+ req_len -= phy_len;
+ dm->dm_count += phy_len;
+
+ if (req_len) {
+ u_long tmp = kvtop(req_addr);
+
+ if ((phy_buf + phy_len) != tmp) {
+ if (wrong_dma_range(reqp, dm)) {
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ goto bounceit;
+ return (0);
+ }
+
+ if (++dm >= &reqp->dm_chain[MAXDMAIO]) {
+ ncr_tprint(reqp,"dmaok: DMA chain too long!\n");
+ return (0);
+ }
+ dm->dm_count = 0;
+ dm->dm_addr = tmp;
+ }
+ phy_buf = tmp;
+ }
+ }
+ if (wrong_dma_range(reqp, dm)) {
+ if (reqp->dr_flag & DRIVER_BOUNCING)
+ goto bounceit;
+ return (0);
+ }
+ reqp->dm_last = dm;
+ return (1);
+
+bounceit:
+ if ((reqp->bounceb = alloc_bounceb(reqp->xdata_len)) == NULL) {
+ /*
+ * If we can't get a bounce buffer, forget DMA
+ */
+ reqp->dr_flag &= ~DRIVER_BOUNCING;
+ return(0);
+ }
+ /*
+ * Initialize a single DMA-range containing the bounced request
+ */
+ dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
+ dm->dm_addr = kvtop(reqp->bounceb);
+ dm->dm_count = reqp->xdata_len;
+ reqp->bouncerp = reqp->bounceb;
+
+ return (1);
+}
+#endif /* REAL_DMA */
+
+static void
+run_main(sc)
+struct ncr_softc *sc;
+{
+ int sps = splbio();
+
+ if (!main_running) {
+ /*
+ * If shared resources are required, claim them
+ * before entering 'scsi_main'. If we can't get them
+ * now, assume 'run_main' will be called when the resource
+ * becomes available.
+ */
+ if (!claimed_dma()) {
+ splx(sps);
+ return;
+ }
+ main_running = 1;
+ splx(sps);
+ scsi_main(sc);
+ }
+ else splx(sps);
+}
+
+/*
+ * Prefix message with full target info.
+ */
+static void
+ncr_tprint(SC_REQ *reqp, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sc_print_addr(reqp->xs->sc_link);
+ printf("%r", fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Prefix message with adapter info.
+ */
+static void
+ncr_aprint(struct ncr_softc *sc, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ printf("%s : %r", sc->sc_dev.dv_xname, fmt, ap);
+ va_end(ap);
+}
+/****************************************************************************
+ * Start Debugging Functions *
+ ****************************************************************************/
+static void
+show_data_sense(xs)
+struct scsi_xfer *xs;
+{
+ u_char *p1, *p2;
+ int i;
+ int sz;
+
+ p1 = (u_char *) xs->cmd;
+ p2 = (u_char *)&xs->sense;
+ if(*p2 == 0)
+ return; /* No(n)sense */
+ printf("cmd[%d,%d]: ", xs->cmdlen, sz = command_size(*p1));
+ for (i = 0; i < sz; i++)
+ printf("%x ", p1[i]);
+ printf("\nsense: ");
+ for (i = 0; i < sizeof(xs->sense); i++)
+ printf("%x ", p2[i]);
+ printf("\n");
+}
+
+static void
+show_request(reqp, qtxt)
+SC_REQ *reqp;
+char *qtxt;
+{
+ printf("REQ-%s: %d %x[%d] cmd[0]=%x S=%x M=%x R=%x resid=%d %s\n",
+ qtxt, reqp->targ_id, reqp->xdata_ptr, reqp->xdata_len,
+ reqp->xcmd.opcode, reqp->status, reqp->message,
+ reqp->xs->error, reqp->xs->resid, reqp->link ? "L":"");
+ if (reqp->status == SCSCHKC)
+ show_data_sense(reqp->xs);
+}
+
+static char *sig_names[] = {
+ "PAR", "SEL", "I/O", "C/D", "MSG", "REQ", "BSY", "RST",
+ "ACK", "ATN", "LBSY", "PMATCH", "IRQ", "EPAR", "DREQ", "EDMA"
+};
+
+static void
+show_signals(dmstat, idstat)
+u_char dmstat, idstat;
+{
+ u_short tmp, mask;
+ int i, j, need_pipe;
+
+ tmp = idstat | ((dmstat & 3) << 8);
+ printf("Bus signals (%02x/%02x): ", idstat, dmstat & 3);
+ for (mask = 1, j = need_pipe = 0; mask <= tmp; mask <<= 1, j++) {
+ if (tmp & mask)
+ printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
+ }
+ printf("\nDma status (%02x): ", dmstat);
+ for (mask = 4, j = 10, need_pipe = 0; mask <= dmstat; mask <<= 1, j++) {
+ if (dmstat & mask)
+ printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
+ }
+ printf("\n");
+}
+
+scsi_show()
+{
+ SC_REQ *tmp;
+ int sps = splhigh();
+ u_char idstat, dmstat;
+
+#ifndef DBG_PID
+ #define last_hit ""
+ #define olast_hit ""
+#endif
+
+ for (tmp = issue_q; tmp; tmp = tmp->next)
+ show_request(tmp, "ISSUED");
+ for (tmp = discon_q; tmp; tmp = tmp->next)
+ show_request(tmp, "DISCONNECTED");
+ if (connected)
+ show_request(connected, "CONNECTED");
+ idstat = GET_5380_REG(NCR5380_IDSTAT);
+ dmstat = GET_5380_REG(NCR5380_DMSTAT);
+ show_signals(dmstat, idstat);
+ if (connected)
+ printf("phase = %d, ", connected->phase);
+ printf("busy:%x, last_hit:%s, olast_hit:%s spl:%04x\n", busy,
+ last_hit, olast_hit, sps);
+
+ splx(sps);
+}
diff --git a/sys/arch/atari/dev/ncr5380reg.h b/sys/arch/atari/dev/ncr5380reg.h
new file mode 100644
index 00000000000..717434ff81d
--- /dev/null
+++ b/sys/arch/atari/dev/ncr5380reg.h
@@ -0,0 +1,258 @@
+/* $NetBSD: ncr5380reg.h,v 1.5 1995/10/05 08:53:00 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NCR5380REG_H
+#define _NCR5380REG_H
+/*
+ * NCR5380 common interface definitions.
+ */
+
+/*
+ * Register numbers: (first argument to GET/SET_5380_REG )
+ */
+#define NCR5380_DATA 0 /* Data register */
+#define NCR5380_ICOM 1 /* Initiator command register */
+#define NCR5380_MODE 2 /* Mode register */
+#define NCR5380_TCOM 3 /* Target command register */
+#define NCR5380_IDSTAT 4 /* Bus status register */
+#define NCR5380_DMSTAT 5 /* DMA status register */
+#define NCR5380_TRCV 6 /* Target receive register */
+#define NCR5380_IRCV 7 /* Initiator receive register */
+
+/*
+ * Definitions for Initiator command register.
+ */
+#define SC_A_RST 0x80 /* RW - Assert RST */
+#define SC_TEST 0x40 /* W - Test mode */
+#define SC_AIP 0x40 /* R - Arbitration in progress */
+#define SC_LA 0x20 /* R - Lost arbitration */
+#define SC_A_ACK 0x10 /* RW - Assert ACK */
+#define SC_A_BSY 0x08 /* RW - Assert BSY */
+#define SC_A_SEL 0x04 /* RW - Assert SEL */
+#define SC_A_ATN 0x02 /* RW - Assert ATN */
+#define SC_ADTB 0x01 /* RW - Assert Data To Bus */
+
+/*
+ * Definitions for mode register
+ */
+#define SC_B_DMA 0x80 /* RW - Block mode DMA (not on TT!) */
+#define SC_T_MODE 0x40 /* RW - Target mode */
+#define SC_E_PAR 0x20 /* RW - Enable parity check */
+#define SC_E_PARI 0x10 /* RW - Enable parity interrupt */
+#define SC_E_EOPI 0x08 /* RW - Enable End Of Process Interrupt */
+#define SC_MON_BSY 0x04 /* RW - Monitor BSY */
+#define SC_M_DMA 0x02 /* RW - Set DMA mode */
+#define SC_ARBIT 0x01 /* RW - Arbitrate */
+
+/*
+ * Definitions for tcom register
+ */
+#define SC_LBS 0x80 /* RW - Last Byte Send (not on TT!) */
+#define SC_A_REQ 0x08 /* RW - Assert REQ */
+#define SC_A_MSG 0x04 /* RW - Assert MSG */
+#define SC_A_CD 0x02 /* RW - Assert C/D */
+#define SC_A_IO 0x01 /* RW - Assert I/O */
+
+/*
+ * Definitions for idstat register
+ */
+#define SC_S_RST 0x80 /* R - RST is set */
+#define SC_S_BSY 0x40 /* R - BSY is set */
+#define SC_S_REQ 0x20 /* R - REQ is set */
+#define SC_S_MSG 0x10 /* R - MSG is set */
+#define SC_S_CD 0x08 /* R - C/D is set */
+#define SC_S_IO 0x04 /* R - I/O is set */
+#define SC_S_SEL 0x02 /* R - SEL is set */
+#define SC_S_PAR 0x01 /* R - Parity bit */
+
+/*
+ * Definitions for dmastat register
+ */
+#define SC_END_DMA 0x80 /* R - End of DMA */
+#define SC_DMA_REQ 0x40 /* R - DMA request */
+#define SC_PAR_ERR 0x20 /* R - Parity error */
+#define SC_IRQ_SET 0x10 /* R - IRQ is active */
+#define SC_PHS_MTCH 0x08 /* R - Phase Match */
+#define SC_BSY_ERR 0x04 /* R - Busy error */
+#define SC_ATN_STAT 0x02 /* R - State of ATN line */
+#define SC_ACK_STAT 0x01 /* R - State of ACK line */
+#define SC_S_SEND 0x00 /* W - Start DMA output */
+
+#define SC_CLINT { /* Clear interrupts */ \
+ int i = GET_5380_REG(NCR5380_IRCV); \
+ }
+
+
+/*
+ * Definition of SCSI-bus phases. The values are determined by signals
+ * on the SCSI-bus. DO NOT CHANGE!
+ * The values must be used to index the pointers in SCSI-PARMS.
+ */
+#define NR_PHASE 8
+#define PH_DATAOUT 0
+#define PH_DATAIN 1
+#define PH_CMD 2
+#define PH_STATUS 3
+#define PH_RES1 4
+#define PH_RES2 5
+#define PH_MSGOUT 6
+#define PH_MSGIN 7
+
+#define PH_OUT(phase) (!(phase & 1)) /* TRUE if output phase */
+#define PH_IN(phase) (phase & 1) /* TRUE if input phase */
+
+/*
+ * Id of Host-adapter
+ */
+#define SC_HOST_ID 0x80
+
+/*
+ * Base setting for 5380 mode register
+ */
+#define IMODE_BASE SC_E_PAR
+
+/*
+ * SCSI completion status codes, should move to sys/scsi/????
+ */
+#define SCSMASK 0x1e /* status code mask */
+#define SCSGOOD 0x00 /* good status */
+#define SCSCHKC 0x02 /* check condition */
+#define SCSBUSY 0x08 /* busy status */
+#define SCSCMET 0x04 /* condition met / good */
+
+/*
+ * Return values of check_intr()
+ */
+#define INTR_SPURIOUS 0
+#define INTR_RESEL 2
+#define INTR_DMA 3
+
+struct ncr_softc {
+ struct device sc_dev;
+ struct scsi_link sc_link;
+
+ /*
+ * Some (pre-SCSI2) devices don't support select with ATN.
+ * If the device responds to select with ATN by going into
+ * command phase (ignoring ATN), then we flag it in the
+ * following bitmask.
+ * We also keep track of which devices have been selected
+ * before. This allows us to not even try raising ATN if
+ * the target doesn't respond to it the first time.
+ */
+ u_int8_t sc_noselatn;
+ u_int8_t sc_selected;
+};
+
+/*
+ * Max. number of dma-chains per request
+ */
+#define MAXDMAIO (MAXPHYS/NBPG + 1)
+
+/*
+ * Some requests are not contiguous in physical memory. We need to break them
+ * up into contiguous parts for DMA.
+ */
+struct dma_chain {
+ u_int dm_count;
+ u_long dm_addr;
+};
+
+/*
+ * Define our issue, free and disconnect queue's.
+ */
+typedef struct req_q {
+ struct req_q *next; /* next in free, issue or discon queue */
+ struct req_q *link; /* next linked command to execute */
+ struct scsi_xfer *xs; /* request from high-level driver */
+ u_short dr_flag; /* driver state */
+ u_char phase; /* current SCSI phase */
+ u_char msgout; /* message to send when requested */
+ u_char targ_id; /* target for command */
+ u_char targ_lun; /* lun for command */
+ u_char status; /* returned status byte */
+ u_char message; /* returned message byte */
+ u_char *bounceb; /* allocated bounce buffer */
+ u_char *bouncerp; /* bounce read-pointer */
+ struct dma_chain dm_chain[MAXDMAIO];
+ struct dma_chain *dm_cur; /* current dma-request */
+ struct dma_chain *dm_last; /* last dma-request */
+ long xdata_len; /* length of transfer */
+ u_char *xdata_ptr; /* virtual address of transfer */
+ struct scsi_generic xcmd; /* command to execute */
+} SC_REQ;
+
+/*
+ * Values for dr_flag:
+ */
+#define DRIVER_IN_DMA 0x01 /* Non-polled DMA activated */
+#define DRIVER_AUTOSEN 0x02 /* Doing automatic sense */
+#define DRIVER_NOINT 0x04 /* We are booting: no interrupts */
+#define DRIVER_DMAOK 0x08 /* DMA can be used on this request */
+#define DRIVER_BOUNCING 0x10 /* Using the bounce buffer */
+
+/* XXX: Should go to ncr5380var.h */
+static SC_REQ *issue_q = NULL; /* Commands waiting to be issued*/
+static SC_REQ *discon_q = NULL; /* Commands disconnected */
+static SC_REQ *connected = NULL; /* Command currently connected */
+
+/*
+ * Function decls:
+ */
+static int transfer_pio __P((u_char *, u_char *, u_long *, int));
+static int wait_req_true __P((void));
+static int wait_req_false __P((void));
+static int scsi_select __P((SC_REQ *, int));
+static int handle_message __P((SC_REQ *, u_int));
+static void ack_message __P((void));
+static void nack_message __P((SC_REQ *, u_char));
+static int information_transfer __P((void));
+static void reselect __P((struct ncr_softc *));
+static int dma_ready __P((void));
+static void transfer_dma __P((SC_REQ *, u_int, int));
+static int check_autosense __P((SC_REQ *, int));
+static int reach_msg_out __P((struct ncr_softc *, u_long));
+static int check_intr __P((struct ncr_softc *));
+static void scsi_reset __P((struct ncr_softc *));
+static int scsi_dmaok __P((SC_REQ *));
+static void run_main __P((struct ncr_softc *));
+static void scsi_main __P((struct ncr_softc *));
+static void ncr_ctrl_intr __P((struct ncr_softc *));
+static void ncr_dma_intr __P((struct ncr_softc *));
+static void ncr_tprint __P((SC_REQ *, char *, ...));
+static void ncr_aprint __P((struct ncr_softc *, char *, ...));
+
+static void show_request __P((SC_REQ *, char *));
+static void show_phase __P((SC_REQ *, int));
+static void show_signals __P((u_char, u_char));
+
+#endif /* _NCR5380REG_H */
diff --git a/sys/arch/atari/dev/ramd.c b/sys/arch/atari/dev/ramd.c
new file mode 100644
index 00000000000..46f7fab41bf
--- /dev/null
+++ b/sys/arch/atari/dev/ramd.c
@@ -0,0 +1,481 @@
+/* $NetBSD: ramd.c,v 1.5 1995/08/12 20:31:02 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/conf.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/dkbad.h>
+
+/*
+ * Misc. defines:
+ */
+#define RAMD_CHUNK (9 * 512) /* Chunk-size for auto-load */
+#define RAMD_NDEV 2 /* Number of devices configured */
+
+struct ramd_info {
+ u_long ramd_size; /* Size of disk in bytes */
+ u_long ramd_flag; /* see defs below */
+ dev_t ramd_dev; /* device to load from */
+ u_long ramd_state; /* runtime state see defs below */
+ caddr_t ramd_addr; /* Kernel virtual addr */
+};
+
+/*
+ * ramd_flag:
+ */
+#define RAMD_LOAD 0x01 /* Auto load when first opened */
+#define RAMD_LCOMP 0x02 /* Input is compressed */
+
+/*
+ * ramd_state:
+ */
+#define RAMD_ALLOC 0x01 /* Memory is allocated */
+#define RAMD_OPEN 0x02 /* Ramdisk is open */
+#define RAMD_INOPEN 0x04 /* Ramdisk is being opened */
+#define RAMD_WANTED 0x08 /* Someone is waiting on struct */
+#define RAMD_LOADED 0x10 /* Ramdisk is properly loaded */
+
+struct ramd_info rd_info[RAMD_NDEV] = {
+ {
+ 1105920, /* 1Mb in 2160 sectors */
+ RAMD_LOAD, /* auto-load this device */
+ MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
+ 0, /* Will be set at runtime */
+ NULL /* Will be set at runtime */
+ },
+ {
+ 1474560, /* 1.44Mb in 2880 sectors */
+ RAMD_LOAD, /* auto-load this device */
+ MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
+ 0, /* Will be set at runtime */
+ NULL /* Will be set at runtime */
+ }
+};
+
+struct read_info {
+ struct buf *bp; /* buffer for strategy function */
+ long nbytes; /* total number of bytes to read */
+ long offset; /* offset in input medium */
+ caddr_t bufp; /* current output buffer */
+ caddr_t ebufp; /* absolute maximum for bufp */
+ int chunk; /* chunk size on input medium */
+ int media_sz; /* size of input medium */
+ void (*strat)(); /* strategy function for read */
+};
+
+/*
+ * Autoconfig stuff....
+ */
+static int ramdmatch __P((struct device *, struct cfdata *, void *));
+static int ramdprint __P((void *, char *));
+static void ramdattach __P((struct device *, struct device *, void *));
+
+struct cfdriver ramdcd = {
+ NULL, "rd", (cfmatch_t)ramdmatch, ramdattach, DV_DULL,
+ sizeof(struct device), NULL, 0 };
+
+static int
+ramdmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp("rd", auxp) || (cfp->cf_unit >= RAMD_NDEV))
+ return(0);
+ return(1);
+}
+
+static void
+ramdattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ int i;
+
+ for(i = 0; i < RAMD_NDEV; i++)
+ config_found(dp, (void*)i, ramdprint);
+}
+
+static int
+ramdprint(auxp, pnp)
+void *auxp;
+char *pnp;
+{
+ return(UNCONF);
+}
+
+static int loaddisk __P((struct ramd_info *, struct proc *));
+static int ramd_norm_read __P((struct read_info *));
+static int cpy_uncompressed __P((caddr_t, int, struct read_info *));
+static int rd_compressed __P((caddr_t, int, struct read_info *));
+
+int
+rdopen(dev, flags, devtype, p)
+dev_t dev;
+int flags, devtype;
+struct proc *p;
+{
+ struct ramd_info *ri;
+ int s;
+ int error = 0;
+
+ if(DISKUNIT(dev) >= RAMD_NDEV)
+ return(ENXIO);
+
+ ri = &rd_info[DISKUNIT(dev)];
+ if(ri->ramd_state & RAMD_OPEN)
+ return(0);
+
+ /*
+ * If someone is busy opening, wait for it to complete.
+ */
+ s = splbio();
+ while(ri->ramd_state & RAMD_INOPEN) {
+ ri->ramd_state |= RAMD_WANTED;
+ tsleep((caddr_t)ri, PRIBIO, "rdopen", 0);
+ }
+ ri->ramd_state |= RAMD_INOPEN;
+ splx(s);
+
+ if(!(ri->ramd_state & RAMD_ALLOC)) {
+ ri->ramd_addr = malloc(ri->ramd_size, M_DEVBUF, M_WAITOK);
+ if(ri->ramd_addr == NULL) {
+ error = ENXIO;
+ goto done;
+ }
+ ri->ramd_state |= RAMD_ALLOC;
+ }
+ if((ri->ramd_flag & RAMD_LOAD) && !(ri->ramd_state & RAMD_LOADED)) {
+ error = loaddisk(ri, p);
+ if(!error)
+ ri->ramd_state |= RAMD_LOADED;
+ }
+done:
+ ri->ramd_state &= ~RAMD_INOPEN;
+ if(ri->ramd_state & RAMD_WANTED) {
+ ri->ramd_state &= ~RAMD_WANTED;
+ wakeup((caddr_t)ri);
+ }
+ return(error);
+}
+
+int
+rdclose(dev, flags, devtype, p)
+dev_t dev;
+int flags, devtype;
+struct proc *p;
+{
+ return(0);
+}
+
+int
+rdioctl(dev, cmd, addr, flag, p)
+dev_t dev;
+u_long cmd;
+int flag;
+caddr_t addr;
+struct proc *p;
+{
+ return(ENOTTY);
+}
+
+/*
+ * no dumps to ram disks thank you.
+ */
+int
+rdsize(dev)
+dev_t dev;
+{
+ return(-1);
+}
+
+void
+rdstrategy(bp)
+struct buf *bp;
+{
+ struct ramd_info *ri;
+ long maxsz, sz;
+ char *datap;
+
+ ri = &rd_info[DISKUNIT(bp->b_dev)];
+
+ maxsz = ri->ramd_size / DEV_BSIZE;
+ sz = (bp->b_bcount + DEV_BSIZE - 1) / DEV_BSIZE;
+ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+ if((bp->b_blkno == maxsz) && (bp->b_flags & B_READ)) {
+ /* Hitting EOF */
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ sz = maxsz - bp->b_blkno;
+ if((sz <= 0) || (bp->b_blkno < 0)) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ goto done;
+ }
+ bp->b_bcount = sz * DEV_BSIZE;
+ }
+ datap = (char*)((u_long)ri->ramd_addr + bp->b_blkno * DEV_BSIZE);
+ if(bp->b_flags & B_READ)
+ bcopy(datap, bp->b_data, bp->b_bcount);
+ else bcopy(bp->b_data, datap, bp->b_bcount);
+ bp->b_resid = 0;
+ biodone(bp);
+ return;
+
+done:
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+}
+
+int
+rdread(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+rdwrite(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+static int
+loaddisk(ri, proc)
+struct ramd_info *ri;
+struct proc *proc;
+{
+ struct buf buf;
+ int error;
+ struct bdevsw *bdp = &bdevsw[major(ri->ramd_dev)];
+ struct disklabel dl;
+ struct read_info rs;
+
+ /*
+ * Initialize out buffer header:
+ */
+ buf.b_actf = NULL;
+ buf.b_rcred = buf.b_wcred = proc->p_ucred;
+ buf.b_vnbufs.le_next = NOLIST;
+ buf.b_flags = B_BUSY;
+ buf.b_dev = ri->ramd_dev;
+ buf.b_error = 0;
+ buf.b_proc = proc;
+
+ /*
+ * Setup read_info:
+ */
+ rs.bp = &buf;
+ rs.nbytes = ri->ramd_size;
+ rs.offset = 0;
+ rs.bufp = ri->ramd_addr;
+ rs.ebufp = ri->ramd_addr + ri->ramd_size;
+ rs.chunk = RAMD_CHUNK;
+ rs.media_sz = ri->ramd_size;
+ rs.strat = bdp->d_strategy;
+
+ /*
+ * Open device and try to get some statistics.
+ */
+ if(error = bdp->d_open(ri->ramd_dev,FREAD | FNONBLOCK, 0, proc))
+ return(error);
+ if(bdp->d_ioctl(ri->ramd_dev,DIOCGDINFO,(caddr_t)&dl,FREAD,proc) == 0) {
+ /* Read on a cylinder basis */
+ rs.chunk = dl.d_secsize * dl.d_secpercyl;
+ rs.media_sz = dl.d_secperunit * dl.d_secsize;
+ }
+
+#ifdef notyet
+ if(ri->ramd_flag & RAMD_LCOMP)
+ error = decompress(cpy_uncompressed, rd_compressed, &rs);
+ else
+#endif /* notyet */
+ error = ramd_norm_read(&rs);
+
+ bdp->d_close(ri->ramd_dev,FREAD | FNONBLOCK, 0, proc);
+ return(error);
+}
+
+static int
+ramd_norm_read(rsp)
+struct read_info *rsp;
+{
+ long bytes_left;
+ int done, error;
+ struct buf *bp;
+ int s;
+ int dotc = 0;
+
+ bytes_left = rsp->nbytes;
+ bp = rsp->bp;
+ error = 0;
+
+ while(bytes_left > 0) {
+ s = splbio();
+ bp->b_flags = B_BUSY | B_PHYS | B_READ;
+ splx(s);
+ bp->b_blkno = btodb(rsp->offset);
+ bp->b_bcount = rsp->chunk;
+ bp->b_data = rsp->bufp;
+
+ /* Initiate read */
+ (*rsp->strat)(bp);
+
+ /* Wait for results */
+ s = splbio();
+ while ((bp->b_flags & B_DONE) == 0)
+ tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
+ if (bp->b_flags & B_ERROR)
+ error = (bp->b_error ? bp->b_error : EIO);
+ splx(s);
+
+ /* Dot counter */
+ printf(".");
+ if(!(++dotc % 40))
+ printf("\n");
+
+ done = bp->b_bcount - bp->b_resid;
+ bytes_left -= done;
+ rsp->offset += done;
+ rsp->bufp += done;
+
+ if(error || !done)
+ break;
+
+ if((rsp->offset == rsp->media_sz) && (bytes_left != 0)) {
+ printf("\nInsert next media and hit any key...");
+ cngetc();
+ printf("\n");
+ rsp->offset = 0;
+ }
+ }
+ printf("\n");
+ s = splbio();
+ splx(s);
+ return(error);
+}
+
+/*
+ * Functions supporting uncompression:
+ */
+/*
+ * Copy from the uncompression buffer to the ramdisk
+ */
+static int
+cpy_uncompressed(buf, nbyte, rsp)
+caddr_t buf;
+struct read_info *rsp;
+int nbyte;
+{
+ if((rsp->bufp + nbyte) >= rsp->ebufp)
+ return(0);
+ bcopy(buf, rsp->bufp, nbyte);
+ rsp->bufp += nbyte;
+ return(0);
+}
+
+/*
+ * Read a maximum of 'nbyte' bytes into 'buf'.
+ */
+static int
+rd_compressed(buf, nbyte, rsp)
+caddr_t buf;
+struct read_info *rsp;
+int nbyte;
+{
+ static int dotc = 0;
+ struct buf *bp;
+ int nread = 0;
+ int s;
+ int done, error;
+
+
+ error = 0;
+ bp = rsp->bp;
+ nbyte &= ~(DEV_BSIZE - 1);
+
+ while(nbyte > 0) {
+ s = splbio();
+ bp->b_flags = B_BUSY | B_PHYS | B_READ;
+ splx(s);
+ bp->b_blkno = btodb(rsp->offset);
+ bp->b_bcount = min(rsp->chunk, nbyte);
+ bp->b_data = buf;
+
+ /* Initiate read */
+ (*rsp->strat)(bp);
+
+ /* Wait for results */
+ s = splbio();
+ while ((bp->b_flags & B_DONE) == 0)
+ tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
+ if (bp->b_flags & B_ERROR)
+ error = (bp->b_error ? bp->b_error : EIO);
+ splx(s);
+
+ /* Dot counter */
+ printf(".");
+ if(!(++dotc % 40))
+ printf("\n");
+
+ done = bp->b_bcount - bp->b_resid;
+ nbyte -= done;
+ nread += done;
+ rsp->offset += done;
+
+ if(error || !done)
+ break;
+
+ if(rsp->offset == rsp->media_sz) {
+ printf("\nInsert next media and hit any key...");
+ if(cngetc() != '\n')
+ printf("\n");
+ rsp->offset = 0;
+ }
+ }
+ s = splbio();
+ splx(s);
+ return(nread);
+}
diff --git a/sys/arch/atari/dev/view.c b/sys/arch/atari/dev/view.c
new file mode 100644
index 00000000000..09dbaf75244
--- /dev/null
+++ b/sys/arch/atari/dev/view.c
@@ -0,0 +1,420 @@
+/* $NetBSD: view.c,v 1.6 1995/08/17 20:32:50 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* The view major device is a placeholder device. It serves
+ * simply to map the semantics of a graphics dipslay to
+ * the semantics of a character block device. In other
+ * words the graphics system as currently built does not like to be
+ * refered to by open/close/ioctl. This device serves as
+ * a interface to graphics. */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <machine/cpu.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+#include "view.h"
+
+static void view_display __P((struct view_softc *));
+static void view_remove __P((struct view_softc *));
+static int view_setsize __P((struct view_softc *, struct view_size *));
+static int view_get_colormap __P((struct view_softc *, colormap_t *));
+static int view_set_colormap __P((struct view_softc *, colormap_t *));
+
+void viewclose __P((dev_t, int));
+int viewioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+int viewopen __P((dev_t, int));
+int viewmmap __P((dev_t, int, int));
+
+int viewprobe ();
+
+struct view_softc views[NVIEW];
+static int view_inited;
+
+int view_default_x;
+int view_default_y;
+int view_default_width = 640;
+int view_default_height = 400;
+int view_default_depth = 1;
+
+/*
+ * functions for probeing.
+ */
+viewattach(cnt)
+ int cnt;
+{
+ viewprobe();
+ printf("%d view%s configured\n", NVIEW, NVIEW > 1 ? "s" : "");
+}
+
+/* this function is called early to set up a display. */
+viewprobe()
+{
+ int i;
+
+ if(view_inited)
+ return(1);
+
+ view_inited = 1;
+
+ for(i=0; i<NVIEW; i++) {
+ views[i].view = NULL;
+ views[i].flags = 0;
+ }
+ return(1);
+}
+
+
+/*
+ * Internal functions.
+ */
+
+static void
+view_display (vu)
+ struct view_softc *vu;
+{
+ int s, i;
+
+ if (vu == NULL)
+ return;
+
+ s = spltty ();
+
+ /*
+ * mark views that share this monitor as not displaying
+ */
+ for (i=0; i<NVIEW; i++) {
+ if(views[i].flags & VUF_DISPLAY)
+ views[i].flags &= ~VUF_DISPLAY;
+ }
+
+ vu->flags |= VUF_ADDED;
+ if (vu->view) {
+ vu->view->display.x = vu->size.x;
+ vu->view->display.y = vu->size.y;
+
+ grf_display_view(vu->view);
+
+ vu->size.x = vu->view->display.x;
+ vu->size.y = vu->view->display.y;
+ vu->flags |= VUF_DISPLAY;
+ }
+ splx(s);
+}
+
+/*
+ * remove a view from our added list if it is marked as displaying
+ * switch to a new display.
+ */
+static void
+view_remove(vu)
+ struct view_softc *vu;
+{
+ int i;
+
+ if ((vu->flags & VUF_ADDED) == 0)
+ return;
+
+ vu->flags &= ~VUF_ADDED;
+ if (vu->flags & VUF_DISPLAY) {
+ for (i = 0; i < NVIEW; i++) {
+ if((views[i].flags & VUF_ADDED) && &views[i] != vu) {
+ view_display(&views[i]);
+ break;
+ }
+ }
+ }
+ vu->flags &= ~VUF_DISPLAY;
+ grf_remove_view(vu->view);
+}
+
+static int
+view_setsize(vu, vs)
+ struct view_softc *vu;
+ struct view_size *vs;
+{
+ view_t *new, *old;
+ dmode_t *dmode;
+ dimen_t ns;
+ int co, cs;
+
+ co = 0;
+ cs = 0;
+ if (vs->x != vu->size.x || vs->y != vu->size.y)
+ co = 1;
+
+ if (vs->width != vu->size.width || vs->height != vu->size.height ||
+ vs->depth != vu->size.depth)
+ cs = 1;
+
+ if (cs == 0 && co == 0)
+ return(0);
+
+ ns.width = vs->width;
+ ns.height = vs->height;
+
+ if((dmode = grf_get_best_mode(&ns, vs->depth)) != NULL) {
+ /*
+ * If we can't do better, leave it
+ */
+ if(dmode == vu->view->mode)
+ return(0);
+ }
+ new = grf_alloc_view(dmode, &ns, vs->depth);
+ if (new == NULL)
+ return(ENOMEM);
+
+ old = vu->view;
+ vu->view = new;
+ vu->size.x = new->display.x;
+ vu->size.y = new->display.y;
+ vu->size.width = new->display.width;
+ vu->size.height = new->display.height;
+ vu->size.depth = new->bitmap->depth;
+
+ /*
+ * we need a custom remove here to avoid letting
+ * another view display mark as not added or displayed
+ */
+ if (vu->flags & VUF_DISPLAY) {
+ vu->flags &= ~(VUF_ADDED|VUF_DISPLAY);
+ view_display(vu);
+ }
+ grf_free_view(old);
+ return(0);
+}
+
+static int
+view_get_colormap (vu, ucm)
+struct view_softc *vu;
+colormap_t *ucm;
+{
+ int error;
+ long *cme;
+ long *uep;
+
+ if(ucm->size > MAX_CENTRIES)
+ return(EINVAL);
+
+ /* add one incase of zero, ick. */
+ cme = malloc(sizeof(ucm->entry[0])*(ucm->size+1), M_IOCTLOPS,M_WAITOK);
+ if (cme == NULL)
+ return(ENOMEM);
+
+ error = 0;
+ uep = ucm->entry;
+ ucm->entry = cme; /* set entry to out alloc. */
+ if(vu->view == NULL || grf_get_colormap(vu->view, ucm))
+ error = EINVAL;
+ else error = copyout(cme, uep, sizeof(ucm->entry[0]) * ucm->size);
+ ucm->entry = uep; /* set entry back to users. */
+ free(cme, M_IOCTLOPS);
+ return(error);
+}
+
+static int
+view_set_colormap(vu, ucm)
+struct view_softc *vu;
+colormap_t *ucm;
+{
+ colormap_t *cm;
+ int error = 0;
+
+ if(ucm->size > MAX_CENTRIES)
+ return(EINVAL);
+
+ cm = malloc(sizeof(ucm->entry[0])*ucm->size + sizeof(*cm), M_IOCTLOPS,
+ M_WAITOK);
+ if(cm == NULL)
+ return(ENOMEM);
+
+ bcopy(ucm, cm, sizeof(colormap_t));
+ cm->entry = (long *)&cm[1]; /* table directly after. */
+ if (((error =
+ copyin(ucm->entry,cm->entry,sizeof(ucm->entry[0])*ucm->size)) == 0)
+ && (vu->view == NULL || grf_use_colormap(vu->view, cm)))
+ error = EINVAL;
+ free(cm, M_IOCTLOPS);
+ return(error);
+}
+
+/*
+ * functions made available by conf.c
+ */
+
+/*ARGSUSED*/
+int viewopen(dev, flags)
+dev_t dev;
+int flags;
+{
+ dimen_t size;
+ struct view_softc *vu;
+
+ vu = &views[minor(dev)];
+
+ if(minor(dev) >= NVIEW)
+ return(EXDEV);
+ if(vu->flags & VUF_OPEN)
+ return(EBUSY);
+
+ vu->size.x = view_default_x;
+ vu->size.y = view_default_y;
+ size.width = vu->size.width = view_default_width;
+ size.height = vu->size.height = view_default_height;
+ vu->size.depth = view_default_depth;
+ vu->view = grf_alloc_view(NULL, &size, vu->size.depth);
+ if (vu->view == NULL)
+ return(ENOMEM);
+
+ vu->size.x = vu->view->display.x;
+ vu->size.y = vu->view->display.y;
+ vu->size.width = vu->view->display.width;
+ vu->size.height = vu->view->display.height;
+ vu->size.depth = vu->view->bitmap->depth;
+ vu->flags |= VUF_OPEN;
+ return(0);
+}
+
+/*ARGSUSED*/
+void
+viewclose (dev, flags)
+ dev_t dev;
+ int flags;
+{
+ struct view_softc *vu;
+
+ vu = &views[minor(dev)];
+
+ if ((vu->flags & VUF_OPEN) == 0)
+ return;
+ view_remove (vu);
+ grf_free_view (vu->view);
+ vu->flags = 0;
+ vu->view = NULL;
+}
+
+
+/*ARGSUSED*/
+int
+viewioctl (dev, cmd, data, flag, p)
+dev_t dev;
+u_long cmd;
+caddr_t data;
+int flag;
+struct proc *p;
+{
+ struct view_softc *vu;
+ bmap_t *bm;
+ int error;
+
+ vu = &views[minor(dev)];
+ error = 0;
+
+ switch (cmd) {
+ case VIOCDISPLAY:
+ view_display(vu);
+ break;
+ case VIOCREMOVE:
+ view_remove(vu);
+ break;
+ case VIOCGSIZE:
+ bcopy(&vu->size, data, sizeof (struct view_size));
+ break;
+ case VIOCSSIZE:
+ error = view_setsize(vu, (struct view_size *)data);
+ break;
+ case VIOCGBMAP:
+ bm = (bmap_t *)data;
+ bcopy(vu->view->bitmap, bm, sizeof(bmap_t));
+ if ((int)p != -1) {
+ bm->plane = NULL;
+ bm->hw_address = NULL;
+ }
+ break;
+ case VIOCGCMAP:
+ error = view_get_colormap(vu, (colormap_t *)data);
+ break;
+ case VIOCSCMAP:
+ error = view_set_colormap(vu, (colormap_t *)data);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
+
+/*ARGSUSED*/
+int
+viewmmap(dev, off, prot)
+dev_t dev;
+int off, prot;
+{
+ struct view_softc *vu;
+ bmap_t *bm;
+ u_char *bmd_start;
+ u_long bmd_size;
+
+ vu = &views[minor(dev)];
+ bm = vu->view->bitmap;
+ bmd_start = bm->hw_address;
+ bmd_size = bm->bytes_per_row*bm->rows*bm->depth;
+
+ if (off >= 0 && off < bmd_size)
+ return(((u_int)bmd_start + off) >> PGSHIFT);
+
+ return(-1);
+}
+
+/*ARGSUSED*/
+int
+viewselect(dev, rw)
+dev_t dev;
+int rw;
+{
+ if(rw == FREAD)
+ return(0);
+ return(1);
+}
+
+view_t *
+viewview(dev)
+dev_t dev;
+{
+ return(views[minor(dev)].view);
+}
diff --git a/sys/arch/atari/dev/viewioctl.h b/sys/arch/atari/dev/viewioctl.h
new file mode 100644
index 00000000000..86b3970459e
--- /dev/null
+++ b/sys/arch/atari/dev/viewioctl.h
@@ -0,0 +1,57 @@
+/* $NetBSD: viewioctl.h,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The view major device is a placeholder device. It serves
+ * simply to map the semantics of a graphics display to
+ * the semantics of a character block device. In other
+ * words the graphics system as currently built does not like to be
+ * refered to by open/close/ioctl. This device serves as
+ * a interface to graphics.
+ */
+
+struct view_size {
+ int x;
+ int y;
+ u_int width;
+ u_int height;
+ u_int depth;
+};
+
+#define VIOCREMOVE _IO('V', 0x0) /* if displaying remove. */
+#define VIOCDISPLAY _IO('V', 0x1) /* if not displaying, display */
+#define VIOCSSIZE _IOW('V', 0x2, struct view_size)
+#define VIOCGSIZE _IOR('V', 0x3, struct view_size)
+#define VIOCGBMAP _IOR('V', 0x4, bmap_t)
+#define VIOCSCMAP _IOW('V', 0x5, colormap_t)
+#define VIOCGCMAP _IOWR('V', 0x6, colormap_t)
+
diff --git a/sys/arch/atari/dev/viewvar.h b/sys/arch/atari/dev/viewvar.h
new file mode 100644
index 00000000000..3c4b7c59de4
--- /dev/null
+++ b/sys/arch/atari/dev/viewvar.h
@@ -0,0 +1,63 @@
+/* $NetBSD: viewvar.h,v 1.2 1995/05/28 19:45:43 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* The view major device is a placeholder device. It serves
+ * simply to map the semantics of a graphics dipslay to
+ * the semantics of a character block device. In other
+ * words the graphics system as currently built does not like to be
+ * refered to by open/close/ioctl. This device serves as
+ * a interface to graphics. */
+
+struct view_softc {
+ struct view_size size;
+ view_t *view;
+ pid_t lock_process;
+ int flags;
+};
+
+enum view_unit_flag_bits {
+ VUB_OPEN,
+ VUB_ADDED,
+ VUB_DISPLAY,
+ VUB_LAST_BIT
+};
+
+enum view_unit_flags {
+ VUF_OPEN = 1<<VUB_OPEN,
+ VUF_ADDED = 1<<VUB_ADDED,
+ VUF_DISPLAY = 1<<VUB_DISPLAY,
+ VUF_MASK = ((1<<VUB_LAST_BIT)-1)
+};
+
+#ifdef _KERNEL
+view_t *viewview __P((dev_t));
+#endif /* _KERNEL */
diff --git a/sys/arch/atari/dev/vuid_event.h b/sys/arch/atari/dev/vuid_event.h
new file mode 100644
index 00000000000..8342f31f19b
--- /dev/null
+++ b/sys/arch/atari/dev/vuid_event.h
@@ -0,0 +1,87 @@
+/* $NetBSD: vuid_event.h,v 1.1.1.1 1995/03/26 07:12:11 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)vuid_event.h 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: vuid_event.h,v 1.4 92/11/26 01:20:27 torek Exp (LBL)
+ */
+
+/*
+ * The following is a minimal emulation of Sun's `Firm_event' structures
+ * and related operations necessary to make X11 happy (i.e., make it
+ * compile, and make old X11 binaries run).
+ */
+typedef struct firm_event {
+ u_short id; /* key or MS_* or LOC_[XY]_DELTA */
+ u_short pad; /* unused, at least by X11 */
+ int value; /* VKEY_{UP,DOWN} or locator delta */
+ struct timeval time;
+} Firm_event;
+
+/*
+ * Special `id' fields. These weird numbers simply match the old binaries.
+ * Others are in 0..0x7f and are keyboard key numbers (keyboard dependent!).
+ */
+#define MS_LEFT 0x7f20 /* left mouse button */
+#define MS_MIDDLE 0x7f21 /* middle mouse button */
+#define MS_RIGHT 0x7f22 /* right mouse button */
+#define LOC_X_DELTA 0x7f80 /* mouse delta-X */
+#define LOC_Y_DELTA 0x7f81 /* mouse delta-Y */
+
+/*
+ * Special `value' fields. These apply to keys and mouse buttons. The
+ * value of a mouse delta is the delta. Note that positive deltas are
+ * left and up (not left and down as you might expect).
+ */
+#define VKEY_UP 0 /* key or button went up */
+#define VKEY_DOWN 1 /* key or button went down */
+
+/*
+ * The following ioctls are clearly intended to take things in and out
+ * of `firm event' mode. Since we always run in this mode (as far as
+ * /dev/kbd and /dev/mouse are concerned, anyway), we always claim to
+ * be in this mode and reject anything else.
+ */
+#define VUIDSFORMAT _IOW('v', 1, int)
+#define VUIDGFORMAT _IOR('v', 2, int)
+#define VUID_FIRM_EVENT 1 /* the only format we support */
diff --git a/sys/arch/atari/dev/zs.c b/sys/arch/atari/dev/zs.c
new file mode 100644
index 00000000000..d4bd7d4014a
--- /dev/null
+++ b/sys/arch/atari/dev/zs.c
@@ -0,0 +1,1214 @@
+/* $NetBSD: zs.c,v 1.9 1995/09/23 20:29:17 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman (Atari modifications)
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)zs.c 8.1 (Berkeley) 7/19/93
+ */
+
+/*
+ * Zilog Z8530 (ZSCC) driver.
+ *
+ * Runs two tty ports (modem2 and serial2) on zs0.
+ *
+ * This driver knows far too much about chip to usage mappings.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/scu.h>
+#include <machine/mfp.h>
+
+#include <dev/ic/z8530reg.h>
+#include <atari/dev/zsvar.h>
+#include "zs.h"
+#if NZS > 1
+#error "This driver supports only 1 85C30!"
+#endif
+
+#if NZS > 0
+
+#define PCLK (8000000) /* PCLK pin input clock rate */
+
+#define splzs spl5
+
+/*
+ * Software state per found chip.
+ */
+struct zs_softc {
+ struct device zi_dev; /* base device */
+ volatile struct zsdevice *zi_zs; /* chip registers */
+ struct zs_chanstate zi_cs[2]; /* chan A and B software state */
+};
+
+static u_char cb_scheduled = 0; /* Already asked for callback? */
+/*
+ * Define the registers for a closed port
+ */
+static u_char zs_init_regs[16] = {
+/* 0 */ 0,
+/* 1 */ 0,
+/* 2 */ 0x60,
+/* 3 */ 0,
+/* 4 */ 0,
+/* 5 */ 0,
+/* 6 */ 0,
+/* 7 */ 0,
+/* 8 */ 0,
+/* 9 */ ZSWR9_VECTOR_INCL_STAT,
+/* 10 */ ZSWR10_NRZ,
+/* 11 */ ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
+/* 12 */ 0,
+/* 13 */ 0,
+/* 14 */ ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
+/* 15 */ 0
+};
+
+/*
+ * Define the machine dependant clock frequencies
+ * If BRgen feeds sender/receiver we always use a
+ * divisor 16, therefor the division by 16 can as
+ * well be done here.
+ */
+static u_long zs_freqs_tt[] = {
+ /*
+ * Atari TT, RTxCB is generated by TT-MFP timer C,
+ * which is set to 307.2KHz during initialisation
+ * and never changed afterwards.
+ */
+ PCLK/16, /* BRgen, PCLK, divisor 16 */
+ 229500, /* BRgen, RTxCA, divisor 16 */
+ 3672000, /* RTxCA, from PCLK4 */
+ 0, /* TRxCA, external */
+
+ PCLK/16, /* BRgen, PCLK, divisor 16 */
+ 19200, /* BRgen, RTxCB, divisor 16 */
+ 307200, /* RTxCB, from TT-MFP TCO */
+ 2457600 /* TRxCB, from BCLK */
+};
+static u_long zs_freqs_falcon[] = {
+ /*
+ * Atari Falcon, XXX no specs available, this might be wrong
+ */
+ PCLK/16, /* BRgen, PCLK, divisor 16 */
+ 229500, /* BRgen, RTxCA, divisor 16 */
+ 3672000, /* RTxCA, ??? */
+ 0, /* TRxCA, external */
+
+ PCLK/16, /* BRgen, PCLK, divisor 16 */
+ 229500, /* BRgen, RTxCB, divisor 16 */
+ 3672000, /* RTxCB, ??? */
+ 2457600 /* TRxCB, ??? */
+};
+static u_long zs_freqs_generic[] = {
+ /*
+ * other machines, assume only PCLK is available
+ */
+ PCLK/16, /* BRgen, PCLK, divisor 16 */
+ 0, /* BRgen, RTxCA, divisor 16 */
+ 0, /* RTxCA, unknown */
+ 0, /* TRxCA, unknown */
+
+ PCLK/16, /* BRgen, PCLK, divisor 16 */
+ 0, /* BRgen, RTxCB, divisor 16 */
+ 0, /* RTxCB, unknown */
+ 0 /* TRxCB, unknown */
+};
+static u_long *zs_frequencies;
+
+/* Definition of the driver for autoconfig. */
+static int zsmatch __P((struct device *, struct cfdata *, void *));
+static void zsattach __P((struct device *, struct device *, void *));
+struct cfdriver zscd = {
+ NULL, "zs", (cfmatch_t)zsmatch, zsattach, DV_TTY,
+ sizeof(struct zs_softc), NULL, 0 };
+
+/* Interrupt handlers. */
+int zshard __P((long));
+static int zssoft __P((long));
+static int zsrint __P((struct zs_chanstate *, volatile struct zschan *));
+static int zsxint __P((struct zs_chanstate *, volatile struct zschan *));
+static int zssint __P((struct zs_chanstate *, volatile struct zschan *));
+
+static struct zs_chanstate *zslist;
+
+/* Routines called from other code. */
+static void zsstart __P((struct tty *));
+void zsstop __P((struct tty *, int));
+static int zsparam __P((struct tty *, struct termios *));
+static int zsbaudrate __P((int, int, int *, int *, int *, int *));
+
+/* Routines purely local to this driver. */
+static void zs_reset __P((volatile struct zschan *, int, int));
+static int zs_modem __P((struct zs_chanstate *, int, int));
+static void zs_loadchannelregs __P((volatile struct zschan *, u_char *));
+
+static int zsshortcuts; /* number of "shortcut" software interrupts */
+
+static int
+zsmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp("zs", auxp) || cfp->cf_unit != 0)
+ return(0);
+ return(1);
+}
+
+/*
+ * Attach a found zs.
+ */
+static void
+zsattach(parent, dev, aux)
+struct device *parent;
+struct device *dev;
+void *aux;
+{
+ register struct zs_softc *zi;
+ register struct zs_chanstate *cs;
+ register volatile struct zsdevice *addr;
+ register struct tty *tp;
+ char tmp;
+
+ addr = (struct zsdevice *)AD_SCC;
+ zi = (struct zs_softc *)dev;
+ zi->zi_zs = addr;
+ cs = zi->zi_cs;
+
+ /*
+ * Get the command register into a known state.
+ */
+ tmp = addr->zs_chan[ZS_CHAN_A].zc_csr;
+ tmp = addr->zs_chan[ZS_CHAN_A].zc_csr;
+ tmp = addr->zs_chan[ZS_CHAN_B].zc_csr;
+ tmp = addr->zs_chan[ZS_CHAN_B].zc_csr;
+
+ /*
+ * Do a hardware reset.
+ */
+ ZS_WRITE(&addr->zs_chan[ZS_CHAN_A], 9, ZSWR9_HARD_RESET);
+ delay(50000); /*enough ? */
+ ZS_WRITE(&addr->zs_chan[ZS_CHAN_A], 9, 0);
+
+ /*
+ * Initialize both channels
+ */
+ zs_loadchannelregs(&addr->zs_chan[ZS_CHAN_A], zs_init_regs);
+ zs_loadchannelregs(&addr->zs_chan[ZS_CHAN_B], zs_init_regs);
+
+ if(machineid & ATARI_TT) {
+ /*
+ * ininitialise TT-MFP timer C: 307200Hz
+ * timer C and D share one control register:
+ * bits 0-2 control timer D
+ * bits 4-6 control timer C
+ */
+ int cr = MFP2->mf_tcdcr & 7;
+ MFP2->mf_tcdcr = cr; /* stop timer C */
+ MFP2->mf_tcdr = 1; /* counter 1 */
+ cr |= T_Q004 << 4; /* divisor 4 */
+ MFP2->mf_tcdcr = cr; /* start timer C */
+ /*
+ * enable scc related interrupts
+ */
+ SCU->sys_mask |= SCU_SCC;
+
+ zs_frequencies = zs_freqs_tt;
+ } else if (machineid & ATARI_FALCON) {
+ zs_frequencies = zs_freqs_falcon;
+ } else {
+ zs_frequencies = zs_freqs_generic;
+ }
+
+ /* link into interrupt list with order (A,B) (B=A+1) */
+ cs[0].cs_next = &cs[1];
+ cs[1].cs_next = zslist;
+ zslist = cs;
+
+ cs->cs_unit = 0;
+ cs->cs_zc = &addr->zs_chan[ZS_CHAN_A];
+ cs++;
+ cs->cs_unit = 1;
+ cs->cs_zc = &addr->zs_chan[ZS_CHAN_B];
+
+ printf(": serial2 on channel a and modem2 on channel b\n");
+}
+
+/*
+ * Open a zs serial port.
+ */
+int
+zsopen(dev, flags, mode, p)
+dev_t dev;
+int flags;
+int mode;
+struct proc *p;
+{
+ register struct tty *tp;
+ register struct zs_chanstate *cs;
+ struct zs_softc *zi;
+ int unit = ZS_UNIT(dev);
+ int zs = unit >> 1;
+ int error, s;
+
+ if(zs >= zscd.cd_ndevs || (zi = zscd.cd_devs[zs]) == NULL)
+ return (ENXIO);
+ cs = &zi->zi_cs[unit & 1];
+ tp = cs->cs_ttyp;
+ if(tp == NULL) {
+ cs->cs_ttyp = tp = ttymalloc();
+ tp->t_dev = dev;
+ tp->t_oproc = zsstart;
+ tp->t_param = zsparam;
+ }
+
+ s = spltty();
+ if((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ if(tp->t_ispeed == 0) {
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ }
+ (void)zsparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ }
+ else if(tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
+ splx(s);
+ return (EBUSY);
+ }
+ error = 0;
+ for(;;) {
+ /* loop, turning on the device, until carrier present */
+ zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, DMSET);
+
+ /* May never get a status intr. if DCD already on. -gwr */
+ if(cs->cs_zc->zc_csr & ZSRR0_DCD)
+ tp->t_state |= TS_CARR_ON;
+ if(cs->cs_softcar)
+ tp->t_state |= TS_CARR_ON;
+ if(flags & O_NONBLOCK || tp->t_cflag & CLOCAL ||
+ tp->t_state & TS_CARR_ON)
+ break;
+ tp->t_state |= TS_WOPEN;
+ if(error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
+ ttopen, 0)) {
+ if(!(tp->t_state & TS_ISOPEN)) {
+ zs_modem(cs, 0, DMSET);
+ tp->t_state &= ~TS_WOPEN;
+ ttwakeup(tp);
+ }
+ splx(s);
+ return error;
+ }
+ }
+ splx(s);
+ if(error == 0)
+ error = linesw[tp->t_line].l_open(dev, tp);
+ if(error)
+ zs_modem(cs, 0, DMSET);
+ return(error);
+}
+
+/*
+ * Close a zs serial port.
+ */
+int
+zsclose(dev, flags, mode, p)
+dev_t dev;
+int flags;
+int mode;
+struct proc *p;
+{
+ register struct zs_chanstate *cs;
+ register struct tty *tp;
+ struct zs_softc *zi;
+ int unit = ZS_UNIT(dev);
+ int s;
+
+ zi = zscd.cd_devs[unit >> 1];
+ cs = &zi->zi_cs[unit & 1];
+ tp = cs->cs_ttyp;
+ linesw[tp->t_line].l_close(tp, flags);
+ if(tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
+ (tp->t_state & TS_ISOPEN) == 0) {
+ zs_modem(cs, 0, DMSET);
+ /* hold low for 1 second */
+ (void)tsleep((caddr_t)cs, TTIPRI, ttclos, hz);
+ }
+ if(cs->cs_creg[5] & ZSWR5_BREAK) {
+ s = splzs();
+ cs->cs_preg[5] &= ~ZSWR5_BREAK;
+ cs->cs_creg[5] &= ~ZSWR5_BREAK;
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ splx(s);
+ }
+ ttyclose(tp);
+
+ /*
+ * Drop all lines and cancel interrupts
+ */
+ zs_loadchannelregs(&zi->zi_zs->zs_chan[unit & 1], zs_init_regs);
+ return (0);
+}
+
+/*
+ * Read/write zs serial port.
+ */
+int
+zsread(dev, uio, flags)
+dev_t dev;
+struct uio *uio;
+int flags;
+{
+ register struct zs_chanstate *cs;
+ register struct zs_softc *zi;
+ register struct tty *tp;
+ int unit;
+
+ unit = ZS_UNIT(dev);
+ zi = zscd.cd_devs[unit >> 1];
+ cs = &zi->zi_cs[unit & 1];
+ tp = cs->cs_ttyp;
+
+ return(linesw[tp->t_line].l_read(tp, uio, flags));
+}
+
+int
+zswrite(dev, uio, flags)
+dev_t dev;
+struct uio *uio;
+int flags;
+{
+ register struct zs_chanstate *cs;
+ register struct zs_softc *zi;
+ register struct tty *tp;
+ int unit;
+
+ unit = ZS_UNIT(dev);
+ zi = zscd.cd_devs[unit >> 1];
+ cs = &zi->zi_cs[unit & 1];
+ tp = cs->cs_ttyp;
+
+ return(linesw[tp->t_line].l_write(tp, uio, flags));
+}
+
+struct tty *
+zstty(dev)
+dev_t dev;
+{
+ register struct zs_chanstate *cs;
+ register struct zs_softc *zi;
+ int unit;
+
+ unit = ZS_UNIT(dev);
+ zi = zscd.cd_devs[unit >> 1];
+ cs = &zi->zi_cs[unit & 1];
+ return(cs->cs_ttyp);
+}
+
+/*
+ * ZS hardware interrupt. Scan all ZS channels. NB: we know here that
+ * channels are kept in (A,B) pairs.
+ *
+ * Do just a little, then get out; set a software interrupt if more
+ * work is needed.
+ *
+ * We deliberately ignore the vectoring Zilog gives us, and match up
+ * only the number of `reset interrupt under service' operations, not
+ * the order.
+ */
+
+int
+zshard(sr)
+long sr;
+{
+ register struct zs_chanstate *a;
+#define b (a + 1)
+ register volatile struct zschan *zc;
+ register int rr3, intflags = 0, v, i;
+
+ do {
+ intflags &= ~4;
+ for(a = zslist; a != NULL; a = b->cs_next) {
+ rr3 = ZS_READ(a->cs_zc, 3);
+ if(rr3 & (ZSRR3_IP_A_RX|ZSRR3_IP_A_TX|ZSRR3_IP_A_STAT)) {
+ intflags |= 4|2;
+ zc = a->cs_zc;
+ i = a->cs_rbput;
+ if(rr3 & ZSRR3_IP_A_RX && (v = zsrint(a, zc)) != 0) {
+ a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_A_TX && (v = zsxint(a, zc)) != 0) {
+ a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_A_STAT && (v = zssint(a, zc)) != 0) {
+ a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ a->cs_rbput = i;
+ }
+ if(rr3 & (ZSRR3_IP_B_RX|ZSRR3_IP_B_TX|ZSRR3_IP_B_STAT)) {
+ intflags |= 4|2;
+ zc = b->cs_zc;
+ i = b->cs_rbput;
+ if(rr3 & ZSRR3_IP_B_RX && (v = zsrint(b, zc)) != 0) {
+ b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_B_TX && (v = zsxint(b, zc)) != 0) {
+ b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_B_STAT && (v = zssint(b, zc)) != 0) {
+ b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ b->cs_rbput = i;
+ }
+ }
+ } while(intflags & 4);
+#undef b
+
+ if(intflags & 1) {
+ if(BASEPRI(sr)) {
+ spl1();
+ zsshortcuts++;
+ return(zssoft(sr));
+ }
+ else if(!cb_scheduled) {
+ cb_scheduled++;
+ add_sicallback(zssoft, 0, 0);
+ }
+ }
+ return(intflags & 2);
+}
+
+static int
+zsrint(cs, zc)
+register struct zs_chanstate *cs;
+register volatile struct zschan *zc;
+{
+ register int c;
+
+ /*
+ * First read the status, because read of the received char
+ * destroy the status of this char.
+ */
+ c = ZS_READ(zc, 1);
+ c |= (zc->zc_data << 8);
+
+ /* clear receive error & interrupt condition */
+ zc->zc_csr = ZSWR0_RESET_ERRORS;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+
+ return(ZRING_MAKE(ZRING_RINT, c));
+}
+
+static int
+zsxint(cs, zc)
+register struct zs_chanstate *cs;
+register volatile struct zschan *zc;
+{
+ register int i = cs->cs_tbc;
+
+ if(i == 0) {
+ zc->zc_csr = ZSWR0_RESET_TXINT;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+ return(ZRING_MAKE(ZRING_XINT, 0));
+ }
+ cs->cs_tbc = i - 1;
+ zc->zc_data = *cs->cs_tba++;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+ return (0);
+}
+
+static int
+zssint(cs, zc)
+register struct zs_chanstate *cs;
+register volatile struct zschan *zc;
+{
+ register int rr0;
+
+ rr0 = zc->zc_csr;
+ zc->zc_csr = ZSWR0_RESET_STATUS;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+ /*
+ * The chip's hardware flow control is, as noted in zsreg.h,
+ * busted---if the DCD line goes low the chip shuts off the
+ * receiver (!). If we want hardware CTS flow control but do
+ * not have it, and carrier is now on, turn HFC on; if we have
+ * HFC now but carrier has gone low, turn it off.
+ */
+ if(rr0 & ZSRR0_DCD) {
+ if(cs->cs_ttyp->t_cflag & CCTS_OFLOW &&
+ (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
+ cs->cs_creg[3] |= ZSWR3_HFC;
+ ZS_WRITE(zc, 3, cs->cs_creg[3]);
+ }
+ }
+ else {
+ if (cs->cs_creg[3] & ZSWR3_HFC) {
+ cs->cs_creg[3] &= ~ZSWR3_HFC;
+ ZS_WRITE(zc, 3, cs->cs_creg[3]);
+ }
+ }
+ return(ZRING_MAKE(ZRING_SINT, rr0));
+}
+
+/*
+ * Print out a ring or fifo overrun error message.
+ */
+static void
+zsoverrun(unit, ptime, what)
+int unit;
+long *ptime;
+char *what;
+{
+
+ if(*ptime != time.tv_sec) {
+ *ptime = time.tv_sec;
+ log(LOG_WARNING, "zs%d%c: %s overrun\n", unit >> 1,
+ (unit & 1) + 'a', what);
+ }
+}
+
+/*
+ * ZS software interrupt. Scan all channels for deferred interrupts.
+ */
+int
+zssoft(sr)
+long sr;
+{
+ register struct zs_chanstate *cs;
+ register volatile struct zschan *zc;
+ register struct linesw *line;
+ register struct tty *tp;
+ register int get, n, c, cc, unit, s;
+ int retval = 0;
+
+ cb_scheduled = 0;
+ s = spltty();
+ for(cs = zslist; cs != NULL; cs = cs->cs_next) {
+ get = cs->cs_rbget;
+again:
+ n = cs->cs_rbput; /* atomic */
+ if(get == n) /* nothing more on this line */
+ continue;
+ retval = 1;
+ unit = cs->cs_unit; /* set up to handle interrupts */
+ zc = cs->cs_zc;
+ tp = cs->cs_ttyp;
+ line = &linesw[tp->t_line];
+ /*
+ * Compute the number of interrupts in the receive ring.
+ * If the count is overlarge, we lost some events, and
+ * must advance to the first valid one. It may get
+ * overwritten if more data are arriving, but this is
+ * too expensive to check and gains nothing (we already
+ * lost out; all we can do at this point is trade one
+ * kind of loss for another).
+ */
+ n -= get;
+ if(n > ZLRB_RING_SIZE) {
+ zsoverrun(unit, &cs->cs_rotime, "ring");
+ get += n - ZLRB_RING_SIZE;
+ n = ZLRB_RING_SIZE;
+ }
+ while(--n >= 0) {
+ /* race to keep ahead of incoming interrupts */
+ c = cs->cs_rbuf[get++ & ZLRB_RING_MASK];
+ switch (ZRING_TYPE(c)) {
+
+ case ZRING_RINT:
+ c = ZRING_VALUE(c);
+ if(c & ZSRR1_DO)
+ zsoverrun(unit, &cs->cs_fotime, "fifo");
+ cc = c >> 8;
+ if(c & ZSRR1_FE)
+ cc |= TTY_FE;
+ if(c & ZSRR1_PE)
+ cc |= TTY_PE;
+ line->l_rint(cc, tp);
+ break;
+
+ case ZRING_XINT:
+ /*
+ * Transmit done: change registers and resume,
+ * or clear BUSY.
+ */
+ if(cs->cs_heldchange) {
+ int sps;
+
+ sps = splzs();
+ c = zc->zc_csr;
+ if((c & ZSRR0_DCD) == 0)
+ cs->cs_preg[3] &= ~ZSWR3_HFC;
+ bcopy((caddr_t)cs->cs_preg,
+ (caddr_t)cs->cs_creg, 16);
+ zs_loadchannelregs(zc, cs->cs_creg);
+ splx(sps);
+ cs->cs_heldchange = 0;
+ if(cs->cs_heldtbc
+ && (tp->t_state & TS_TTSTOP) == 0) {
+ cs->cs_tbc = cs->cs_heldtbc - 1;
+ zc->zc_data = *cs->cs_tba++;
+ goto again;
+ }
+ }
+ tp->t_state &= ~TS_BUSY;
+ if(tp->t_state & TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
+ else ndflush(&tp->t_outq,cs->cs_tba
+ - (caddr_t)tp->t_outq.c_cf);
+ line->l_start(tp);
+ break;
+
+ case ZRING_SINT:
+ /*
+ * Status line change. HFC bit is run in
+ * hardware interrupt, to avoid locking
+ * at splzs here.
+ */
+ c = ZRING_VALUE(c);
+ if((c ^ cs->cs_rr0) & ZSRR0_DCD) {
+ cc = (c & ZSRR0_DCD) != 0;
+ if(line->l_modem(tp, cc) == 0)
+ zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR,
+ cc ? DMBIS : DMBIC);
+ }
+ cs->cs_rr0 = c;
+ break;
+
+ default:
+ log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (%x)\n",
+ unit >> 1, (unit & 1) + 'a', c);
+ break;
+ }
+ }
+ cs->cs_rbget = get;
+ goto again;
+ }
+ splx(s);
+ return (retval);
+}
+
+int
+zsioctl(dev, cmd, data, flag, p)
+dev_t dev;
+u_long cmd;
+caddr_t data;
+int flag;
+struct proc *p;
+{
+ int unit = ZS_UNIT(dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+ register struct tty *tp = zi->zi_cs[unit & 1].cs_ttyp;
+ register int error, s;
+ register struct zs_chanstate *cs = &zi->zi_cs[unit & 1];
+
+ error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, p);
+ if(error >= 0)
+ return(error);
+ error = ttioctl(tp, cmd, data, flag, p);
+ if(error >= 0)
+ return (error);
+
+ switch (cmd) {
+ case TIOCSBRK:
+ s = splzs();
+ cs->cs_preg[5] |= ZSWR5_BREAK;
+ cs->cs_creg[5] |= ZSWR5_BREAK;
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ splx(s);
+ break;
+ case TIOCCBRK:
+ s = splzs();
+ cs->cs_preg[5] &= ~ZSWR5_BREAK;
+ cs->cs_creg[5] &= ~ZSWR5_BREAK;
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ splx(s);
+ break;
+ case TIOCGFLAGS: {
+ int bits = 0;
+
+ if(cs->cs_softcar)
+ bits |= TIOCFLAG_SOFTCAR;
+ if(cs->cs_creg[15] & ZSWR15_DCD_IE)
+ bits |= TIOCFLAG_CLOCAL;
+ if(cs->cs_creg[3] & ZSWR3_HFC)
+ bits |= TIOCFLAG_CRTSCTS;
+ *(int *)data = bits;
+ break;
+ }
+ case TIOCSFLAGS: {
+ int userbits, driverbits = 0;
+
+ error = suser(p->p_ucred, &p->p_acflag);
+ if(error != 0)
+ return (EPERM);
+
+ userbits = *(int *)data;
+
+ /*
+ * can have `local' or `softcar', and `rtscts' or `mdmbuf'
+ # defaulting to software flow control.
+ */
+ if(userbits & TIOCFLAG_SOFTCAR && userbits & TIOCFLAG_CLOCAL)
+ return(EINVAL);
+ if(userbits & TIOCFLAG_MDMBUF) /* don't support this (yet?) */
+ return(ENXIO);
+
+ s = splzs();
+ if((userbits & TIOCFLAG_SOFTCAR)) {
+ cs->cs_softcar = 1; /* turn on softcar */
+ cs->cs_preg[15] &= ~ZSWR15_DCD_IE; /* turn off dcd */
+ cs->cs_creg[15] &= ~ZSWR15_DCD_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ }
+ else if(userbits & TIOCFLAG_CLOCAL) {
+ cs->cs_softcar = 0; /* turn off softcar */
+ cs->cs_preg[15] |= ZSWR15_DCD_IE; /* turn on dcd */
+ cs->cs_creg[15] |= ZSWR15_DCD_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ tp->t_termios.c_cflag |= CLOCAL;
+ }
+ if(userbits & TIOCFLAG_CRTSCTS) {
+ cs->cs_preg[15] |= ZSWR15_CTS_IE;
+ cs->cs_creg[15] |= ZSWR15_CTS_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ cs->cs_preg[3] |= ZSWR3_HFC;
+ cs->cs_creg[3] |= ZSWR3_HFC;
+ ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]);
+ tp->t_termios.c_cflag |= CRTSCTS;
+ }
+ else {
+ /* no mdmbuf, so we must want software flow control */
+ cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
+ cs->cs_creg[15] &= ~ZSWR15_CTS_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ cs->cs_preg[3] &= ~ZSWR3_HFC;
+ cs->cs_creg[3] &= ~ZSWR3_HFC;
+ ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]);
+ tp->t_termios.c_cflag &= ~CRTSCTS;
+ }
+ splx(s);
+ break;
+ }
+ case TIOCSDTR:
+ zs_modem(cs, ZSWR5_DTR, DMBIS);
+ break;
+ case TIOCCDTR:
+ zs_modem(cs, ZSWR5_DTR, DMBIC);
+ break;
+ case TIOCMGET:
+ zs_modem(cs, 0, DMGET);
+ break;
+ case TIOCMSET:
+ case TIOCMBIS:
+ case TIOCMBIC:
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+/*
+ * Start or restart transmission.
+ */
+static void
+zsstart(tp)
+register struct tty *tp;
+{
+ register struct zs_chanstate *cs;
+ register int s, nch;
+ int unit = ZS_UNIT(tp->t_dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+
+ cs = &zi->zi_cs[unit & 1];
+ s = spltty();
+
+ /*
+ * If currently active or delaying, no need to do anything.
+ */
+ if(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto out;
+
+ /*
+ * If there are sleepers, and output has drained below low
+ * water mark, awaken.
+ */
+ if(tp->t_outq.c_cc <= tp->t_lowat) {
+ if(tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)&tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+
+ nch = ndqb(&tp->t_outq, 0); /* XXX */
+ if(nch) {
+ register char *p = tp->t_outq.c_cf;
+
+ /* mark busy, enable tx done interrupts, & send first byte */
+ tp->t_state |= TS_BUSY;
+ (void) splzs();
+ cs->cs_preg[1] |= ZSWR1_TIE;
+ cs->cs_creg[1] |= ZSWR1_TIE;
+ ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
+ cs->cs_zc->zc_data = *p;
+ cs->cs_tba = p + 1;
+ cs->cs_tbc = nch - 1;
+ } else {
+ /*
+ * Nothing to send, turn off transmit done interrupts.
+ * This is useful if something is doing polled output.
+ */
+ (void) splzs();
+ cs->cs_preg[1] &= ~ZSWR1_TIE;
+ cs->cs_creg[1] &= ~ZSWR1_TIE;
+ ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
+ }
+out:
+ splx(s);
+}
+
+/*
+ * Stop output, e.g., for ^S or output flush.
+ */
+void
+zsstop(tp, flag)
+register struct tty *tp;
+ int flag;
+{
+ register struct zs_chanstate *cs;
+ register int s, unit = ZS_UNIT(tp->t_dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+
+ cs = &zi->zi_cs[unit & 1];
+ s = splzs();
+ if(tp->t_state & TS_BUSY) {
+ /*
+ * Device is transmitting; must stop it.
+ */
+ cs->cs_tbc = 0;
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ }
+ splx(s);
+}
+
+/*
+ * Set ZS tty parameters from termios.
+ *
+ * This routine makes use of the fact that only registers
+ * 1, 3, 4, 5, 9, 10, 11, 12, 13, 14, and 15 are written.
+ */
+static int
+zsparam(tp, t)
+register struct tty *tp;
+register struct termios *t;
+{
+ int unit = ZS_UNIT(tp->t_dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+ register struct zs_chanstate *cs = &zi->zi_cs[unit & 1];
+ int cdiv, clkm, brgm, tcon;
+ register int tmp, tmp5, cflag, s;
+
+ tmp = t->c_ospeed;
+ tmp5 = t->c_ispeed;
+ if(tmp < 0 || (tmp5 && tmp5 != tmp))
+ return(EINVAL);
+ if(tmp == 0) {
+ /* stty 0 => drop DTR and RTS */
+ zs_modem(cs, 0, DMSET);
+ return(0);
+ }
+ tmp = zsbaudrate(unit, tmp, &cdiv, &clkm, &brgm, &tcon);
+ if (tmp < 0)
+ return(EINVAL);
+ tp->t_ispeed = tp->t_ospeed = tmp;
+
+ cflag = tp->t_cflag = t->c_cflag;
+ if (cflag & CSTOPB)
+ cdiv |= ZSWR4_TWOSB;
+ else
+ cdiv |= ZSWR4_ONESB;
+ if (!(cflag & PARODD))
+ cdiv |= ZSWR4_EVENP;
+ if (cflag & PARENB)
+ cdiv |= ZSWR4_PARENB;
+
+ switch(cflag & CSIZE) {
+ case CS5:
+ tmp = ZSWR3_RX_5;
+ tmp5 = ZSWR5_TX_5;
+ break;
+ case CS6:
+ tmp = ZSWR3_RX_6;
+ tmp5 = ZSWR5_TX_6;
+ break;
+ case CS7:
+ tmp = ZSWR3_RX_7;
+ tmp5 = ZSWR5_TX_7;
+ break;
+ case CS8:
+ default:
+ tmp = ZSWR3_RX_8;
+ tmp5 = ZSWR5_TX_8;
+ break;
+ }
+ tmp |= ZSWR3_RX_ENABLE;
+ tmp5 |= ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
+
+ /*
+ * Block interrupts so that state will not
+ * be altered until we are done setting it up.
+ */
+ s = splzs();
+ cs->cs_preg[4] = cdiv;
+ cs->cs_preg[11] = clkm;
+ cs->cs_preg[12] = tcon;
+ cs->cs_preg[13] = tcon >> 8;
+ cs->cs_preg[14] = brgm;
+ cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE;
+ cs->cs_preg[9] = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT;
+ cs->cs_preg[10] = ZSWR10_NRZ;
+ cs->cs_preg[15] = ZSWR15_BREAK_IE | ZSWR15_DCD_IE;
+
+ /*
+ * Output hardware flow control on the chip is horrendous: if
+ * carrier detect drops, the receiver is disabled. Hence we
+ * can only do this when the carrier is on.
+ */
+ if(cflag & CCTS_OFLOW && cs->cs_zc->zc_csr & ZSRR0_DCD)
+ tmp |= ZSWR3_HFC;
+ cs->cs_preg[3] = tmp;
+ cs->cs_preg[5] = tmp5;
+
+ /*
+ * If nothing is being transmitted, set up new current values,
+ * else mark them as pending.
+ */
+ if(cs->cs_heldchange == 0) {
+ if (cs->cs_ttyp->t_state & TS_BUSY) {
+ cs->cs_heldtbc = cs->cs_tbc;
+ cs->cs_tbc = 0;
+ cs->cs_heldchange = 1;
+ } else {
+ bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16);
+ zs_loadchannelregs(cs->cs_zc, cs->cs_creg);
+ }
+ }
+ splx(s);
+ return (0);
+}
+
+/*
+ * search for the best matching baudrate
+ */
+static int
+zsbaudrate(unit, wanted, divisor, clockmode, brgenmode, timeconst)
+int unit, wanted, *divisor, *clockmode, *brgenmode, *timeconst;
+{
+ int bestdiff, bestbps, source;
+
+ unit = (unit & 1) << 2;
+ for (source = 0; source < 4; ++source) {
+ long freq = zs_frequencies[unit + source];
+ int diff, bps, div, clkm, brgm, tcon;
+ switch (source) {
+ case 0: /* BRgen, PCLK */
+ brgm = ZSWR14_BAUD_ENA|ZSWR14_BAUD_FROM_PCLK;
+ break;
+ case 1: /* BRgen, RTxC */
+ brgm = ZSWR14_BAUD_ENA;
+ break;
+ case 2: /* RTxC */
+ clkm = ZSWR11_RXCLK_RTXC|ZSWR11_TXCLK_RTXC;
+ break;
+ case 3: /* TRxC */
+ clkm = ZSWR11_RXCLK_TRXC|ZSWR11_TXCLK_TRXC;
+ break;
+ }
+ switch (source) {
+ case 0:
+ case 1:
+ div = ZSWR4_CLK_X16;
+ clkm = ZSWR11_RXCLK_BAUD|ZSWR11_TXCLK_BAUD;
+ tcon = BPS_TO_TCONST(freq, wanted);
+ if (tcon < 0)
+ tcon = 0;
+ bps = TCONST_TO_BPS(freq, tcon);
+ break;
+ case 2:
+ case 3:
+ { int b1 = freq / 16, d1 = abs(b1 - wanted);
+ int b2 = freq / 32, d2 = abs(b2 - wanted);
+ int b3 = freq / 64, d3 = abs(b3 - wanted);
+
+ if (d1 < d2 && d1 < d3) {
+ div = ZSWR4_CLK_X16;
+ bps = b1;
+ } else if (d2 < d3 && d2 < d1) {
+ div = ZSWR4_CLK_X32;
+ bps = b2;
+ } else {
+ div = ZSWR4_CLK_X64;
+ bps = b3;
+ }
+ brgm = tcon = 0;
+ break;
+ }
+ }
+ diff = abs(bps - wanted);
+ if (!source || diff < bestdiff) {
+ *divisor = div;
+ *clockmode = clkm;
+ *brgenmode = brgm;
+ *timeconst = tcon;
+ bestbps = bps;
+ bestdiff = diff;
+ if (diff == 0)
+ break;
+ }
+ }
+ /* Allow deviations upto 5% */
+ if (20 * bestdiff > wanted)
+ return -1;
+ return bestbps;
+}
+
+/*
+ * Raise or lower modem control (DTR/RTS) signals. If a character is
+ * in transmission, the change is deferred.
+ */
+static int
+zs_modem(cs, bits, how)
+struct zs_chanstate *cs;
+int bits, how;
+{
+ int s, mbits;
+
+ bits &= ZSWR5_DTR | ZSWR5_RTS;
+
+ s = splzs();
+ mbits = cs->cs_preg[5] & (ZSWR5_DTR | ZSWR5_RTS);
+
+ switch(how) {
+ case DMSET:
+ mbits = bits;
+ break;
+ case DMBIS:
+ mbits |= bits;
+ break;
+ case DMBIC:
+ mbits &= ~bits;
+ break;
+ case DMGET:
+ splx(s);
+ return(mbits);
+ }
+
+ cs->cs_preg[5] = (cs->cs_preg[5] & ~(ZSWR5_DTR | ZSWR5_RTS)) | mbits;
+ if(cs->cs_heldchange == 0) {
+ if(cs->cs_ttyp->t_state & TS_BUSY) {
+ cs->cs_heldtbc = cs->cs_tbc;
+ cs->cs_tbc = 0;
+ cs->cs_heldchange = 1;
+ }
+ else {
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ }
+ }
+ splx(s);
+ return(0);
+}
+
+/*
+ * Write the given register set to the given zs channel in the proper order.
+ * The channel must not be transmitting at the time. The receiver will
+ * be disabled for the time it takes to write all the registers.
+ */
+static void
+zs_loadchannelregs(zc, reg)
+volatile struct zschan *zc;
+u_char *reg;
+{
+ int i;
+
+ zc->zc_csr = ZSM_RESET_ERR; /* reset error condition */
+ i = zc->zc_data; /* drain fifo */
+ i = zc->zc_data;
+ i = zc->zc_data;
+ ZS_WRITE(zc, 4, reg[4]);
+ ZS_WRITE(zc, 10, reg[10]);
+ ZS_WRITE(zc, 3, reg[3] & ~ZSWR3_RX_ENABLE);
+ ZS_WRITE(zc, 5, reg[5] & ~ZSWR5_TX_ENABLE);
+ ZS_WRITE(zc, 1, reg[1]);
+ ZS_WRITE(zc, 9, reg[9]);
+ ZS_WRITE(zc, 11, reg[11]);
+ ZS_WRITE(zc, 12, reg[12]);
+ ZS_WRITE(zc, 13, reg[13]);
+ ZS_WRITE(zc, 14, reg[14]);
+ ZS_WRITE(zc, 15, reg[15]);
+ ZS_WRITE(zc, 3, reg[3]);
+ ZS_WRITE(zc, 5, reg[5]);
+}
+#endif /* NZS > 1 */
diff --git a/sys/arch/atari/dev/zsvar.h b/sys/arch/atari/dev/zsvar.h
new file mode 100644
index 00000000000..7f2b5019339
--- /dev/null
+++ b/sys/arch/atari/dev/zsvar.h
@@ -0,0 +1,147 @@
+/* $NetBSD: zsvar.h,v 1.2 1995/04/11 02:37:18 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)zsvar.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Software state, per zs channel.
+ *
+ * The zs chip has insufficient buffering, so we provide a software
+ * buffer using a two-level interrupt scheme. The hardware (high priority)
+ * interrupt simply grabs the `cause' of the interrupt and stuffs it into
+ * a ring buffer. It then schedules a software interrupt; the latter
+ * empties the ring as fast as it can, hoping to avoid overflow.
+ *
+ * Interrupts can happen because of:
+ * - received data;
+ * - transmit pseudo-DMA done; and
+ * - status change.
+ * These are all stored together in the (single) ring. The size of the
+ * ring is a power of two, to make % operations fast. Since we need two
+ * bits to distinguish the interrupt type, and up to 16 for the received
+ * data plus RR1 status, we use 32 bits per ring entry.
+ *
+ * When the value is a character + RR1 status, the character is in the
+ * upper 8 bits of the RR1 status.
+ */
+#define ZLRB_RING_SIZE 256 /* ZS line ring buffer size */
+#define ZLRB_RING_MASK 255 /* mask for same */
+
+/* 0 is reserved (means "no interrupt") */
+#define ZRING_RINT 1 /* receive data interrupt */
+#define ZRING_XINT 2 /* transmit done interrupt */
+#define ZRING_SINT 3 /* status change interrupt */
+
+#define ZRING_TYPE(x) ((x) & 3)
+#define ZRING_VALUE(x) ((x) >> 8)
+#define ZRING_MAKE(t, v) ((t) | (v) << 8)
+
+struct zs_chanstate {
+ struct zs_chanstate *cs_next; /* linked list for zshard() */
+ volatile struct zschan *cs_zc; /* points to hardware regs */
+ int cs_unit; /* unit number */
+ struct tty *cs_ttyp; /* ### */
+
+ /*
+ * We must keep a copy of the write registers as they are
+ * mostly write-only and we sometimes need to set and clear
+ * individual bits (e.g., in WR3). Not all of these are
+ * needed but 16 bytes is cheap and this makes the addressing
+ * simpler. Unfortunately, we can only write to some registers
+ * when the chip is not actually transmitting, so whenever
+ * we are expecting a `transmit done' interrupt the preg array
+ * is allowed to `get ahead' of the current values. In a
+ * few places we must change the current value of a register,
+ * rather than (or in addition to) the pending value; for these
+ * cs_creg[] contains the current value.
+ */
+ u_char cs_creg[16]; /* current values */
+ u_char cs_preg[16]; /* pending values */
+ u_char cs_heldchange; /* change pending (creg != preg) */
+ u_char cs_rr0; /* last rr0 processed */
+
+ /* pure software data, per channel */
+ char cs_softcar; /* software carrier */
+ char cs_xxx; /* (spare) */
+
+ /*
+ * The transmit byte count and address are used for pseudo-DMA
+ * output in the hardware interrupt code. PDMA can be suspended
+ * to get pending changes done; heldtbc is used for this. It can
+ * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
+ */
+ int cs_tbc; /* transmit byte count */
+ caddr_t cs_tba; /* transmit buffer address */
+ int cs_heldtbc; /* held tbc while xmission stopped */
+
+ /*
+ * Printing an overrun error message often takes long enough to
+ * cause another overrun, so we only print one per second.
+ */
+ long cs_rotime; /* time of last ring overrun */
+ long cs_fotime; /* time of last fifo overrun */
+
+ /*
+ * The ring buffer.
+ */
+ u_int cs_rbget; /* ring buffer `get' index */
+ volatile u_int cs_rbput; /* ring buffer `put' index */
+ int cs_rbuf[ZLRB_RING_SIZE];/* type, value pairs */
+};
+
+#define ZS_CHAN_A 0
+#define ZS_CHAN_B 1
+
+/*
+ * Macros to read and write individual registers (except 0) in a channel.
+ */
+#define ZS_READ(c, r) ((c)->zc_csr = (r), (c)->zc_csr)
+#define ZS_WRITE(c, r, v) ((c)->zc_csr = (r), (c)->zc_csr = (v))
+
+/*
+ * Split minor into unit & flag nibble.
+ */
+#define ZS_UNIT(dev) ((minor(dev) >> 4) & 0xf)
+#define ZS_FLAGS(dev) (minor(dev) & 0xf)