summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorKenji Aoyama <aoyama@cvs.openbsd.org>2014-04-16 12:01:34 +0000
committerKenji Aoyama <aoyama@cvs.openbsd.org>2014-04-16 12:01:34 +0000
commit4996567438ccba9f4d7be798894b816ce339ed1b (patch)
tree7b3794819e44d77bd26824bb1284e5d6ea6444d3 /sys/arch
parentf835eee727683f1f21e319510529b3bf48777c3f (diff)
Add generic driver for "NEC PC-9801(*) extension board slot" on
LUNA-88K. LUNA-88K{,2} has one or two slot(s) that can attach the extension board designed for PC-9801. This driver provides dedicated mmap(2) and capability for waiting specified interrupt on that slot so that we can use the extension board from userland program. (*)PC-9801 is a Japanese popular personal computer, mainly used in 1980-90's. (see http://en.wikipedia.org/wiki/NEC_PC-9801) ok miod@, and man pages jmc@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/luna88k/conf/GENERIC5
-rw-r--r--sys/arch/luna88k/conf/files.luna88k6
-rw-r--r--sys/arch/luna88k/dev/pcex.c287
-rw-r--r--sys/arch/luna88k/include/conf.h11
-rw-r--r--sys/arch/luna88k/include/pcex.h32
-rw-r--r--sys/arch/luna88k/luna88k/conf.c5
-rw-r--r--sys/arch/luna88k/luna88k/mainbus.c6
-rw-r--r--sys/arch/luna88k/luna88k/pmap_table.c4
8 files changed, 348 insertions, 8 deletions
diff --git a/sys/arch/luna88k/conf/GENERIC b/sys/arch/luna88k/conf/GENERIC
index 9d6da0619e8..9f9382661e4 100644
--- a/sys/arch/luna88k/conf/GENERIC
+++ b/sys/arch/luna88k/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.16 2013/04/28 23:33:12 aoyama Exp $
+# $OpenBSD: GENERIC,v 1.17 2014/04/16 12:01:33 aoyama Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -42,6 +42,9 @@ fb0 at mainbus0
spc0 at mainbus0
spc1 at mainbus0
+# PC-9801 extension board slot
+pcex0 at mainbus0
+
# Workstation Console attachments
wsdisplay* at fb?
wskbd* at ws? mux 1
diff --git a/sys/arch/luna88k/conf/files.luna88k b/sys/arch/luna88k/conf/files.luna88k
index 27d0dc84ed1..1a8818b53d8 100644
--- a/sys/arch/luna88k/conf/files.luna88k
+++ b/sys/arch/luna88k/conf/files.luna88k
@@ -1,4 +1,4 @@
-# $OpenBSD: files.luna88k,v 1.19 2013/11/16 22:45:37 aoyama Exp $
+# $OpenBSD: files.luna88k,v 1.20 2014/04/16 12:01:33 aoyama Exp $
#
maxpartitions 16
@@ -70,6 +70,10 @@ file arch/luna88k/dev/mb89352.c spc
#file arch/luna88k/dev/nec86hw.c pcm needs-flag
#file arch/luna88k/dev/nec86_luna88k.c pcm needs-flag
+device pcex
+attach pcex at mainbus
+file arch/luna88k/dev/pcex.c pcex needs-flag
+
# list of standard files
file arch/luna88k/luna88k/clock.c
diff --git a/sys/arch/luna88k/dev/pcex.c b/sys/arch/luna88k/dev/pcex.c
new file mode 100644
index 00000000000..c6552b3fe4c
--- /dev/null
+++ b/sys/arch/luna88k/dev/pcex.c
@@ -0,0 +1,287 @@
+/* $OpenBSD: pcex.c,v 1.1 2014/04/16 12:01:33 aoyama Exp $ */
+
+/*
+ * Copyright (c) 2014 Kenji Aoyama.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * PC-9801 extension board slot direct access driver for LUNA-88K{,2}
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h> /* tsleep()/wakeup() */
+#include <sys/device.h>
+#include <sys/ioctl.h>
+
+#include <machine/asm_macro.h> /* ff1() */
+#include <machine/autoconf.h>
+#include <machine/board.h> /* PC_BASE */
+#include <machine/conf.h>
+#include <machine/intr.h>
+#include <machine/pcex.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <luna88k/luna88k/isr.h>
+
+extern int hz;
+
+#if 0
+#define PCEX_DEBUG
+#endif
+
+#define PCEXMEM_BASE PC_BASE
+#define PCEXIO_BASE (PC_BASE + 0x1000000)
+#define CBUS_ISR (PC_BASE + 0x1100000)
+
+/*
+ * C-bus Interrupt Status Register
+ */
+volatile u_int8_t *cisr = (u_int8_t *)CBUS_ISR;
+
+const u_int8_t cisr_int_bits[] = {
+ 0x40, /* INT 0 */
+ 0x20, /* INT 1 */
+ 0x10, /* INT 2 */
+ 0x08, /* INT 3 */
+ 0x04, /* INT 4 */
+ 0x02, /* INT 5 */
+ 0x01 /* INT 6 */
+/* 0x80 NMI(?), not supported in this driver now */
+};
+
+/* autoconf stuff */
+int pcex_match(struct device *, void *, void *);
+void pcex_attach(struct device *, struct device *, void *);
+
+struct pcex_softc {
+ struct device sc_dev;
+ u_int8_t int_bits;
+};
+
+const struct cfattach pcex_ca = {
+ sizeof(struct pcex_softc), pcex_match, pcex_attach
+};
+
+struct cfdriver pcex_cd = {
+ NULL, "pcex", DV_DULL
+};
+
+/* prototypes */
+int pcex_intr(void *);
+int pcex_set_int(struct pcex_softc *, u_int);
+int pcex_reset_int(struct pcex_softc *, u_int);
+int pcex_wait_int(struct pcex_softc *, u_int);
+
+int
+pcex_match(struct device *parent, void *cf, void *aux)
+{
+ struct mainbus_attach_args *ma = aux;
+
+ if (strcmp(ma->ma_name, pcex_cd.cd_name))
+ return 0;
+#if 0
+ if (badaddr((vaddr_t)ma->ma_addr, 4))
+ return 0;
+#endif
+ return 1;
+}
+
+void
+pcex_attach(struct device *parent, struct device *self, void *args)
+{
+ struct pcex_softc *sc = (struct pcex_softc *)self;
+ struct mainbus_attach_args *ma = args;
+ u_int8_t i;
+
+ sc->int_bits = 0x00;
+
+ /* make sure of clearing interrupt flags for INT0-INT6 */
+ for (i = 0; i < 7; i++)
+ *cisr = i;
+
+ isrlink_autovec(pcex_intr, (void *)self, ma->ma_ilvl,
+ ISRPRI_TTY, self->dv_xname);
+
+ printf("\n");
+}
+
+int
+pcexopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+ switch (minor(dev)) {
+ case 0: /* memory area */
+ case 1: /* I/O port area */
+ return 0;
+ default:
+ return ENXIO;
+ }
+}
+
+int
+pcexclose(dev_t dev, int flag, int mode, struct proc *p)
+{
+ return (0);
+}
+
+paddr_t
+pcexmmap(dev_t dev, off_t offset, int prot)
+{
+ paddr_t cookie = -1;
+
+ switch (minor(dev)) {
+ case 0: /* memory area */
+ if (offset >= 0 && offset < 0x1000000)
+ cookie = (paddr_t)(PCEXMEM_BASE + offset);
+ break;
+ case 1: /* I/O port area */
+ if (offset >= 0 && offset < 0x10000)
+ cookie = (paddr_t)(PCEXIO_BASE + offset);
+ break;
+ default:
+ break;
+ }
+
+ return cookie;
+}
+
+int
+pcexioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
+{
+ struct pcex_softc *sc = NULL;
+ u_int level;
+
+ if (pcex_cd.cd_ndevs != 0)
+ sc = pcex_cd.cd_devs[0];
+ if (sc == NULL)
+ return ENXIO;
+
+ level = *(u_int *)data;
+
+ switch(cmd) {
+ case PCEXSETLEVEL:
+ return pcex_set_int(sc, level);
+
+ case PCEXRESETLEVEL:
+ return pcex_reset_int(sc, level);
+
+ case PCEXWAITINT:
+ return pcex_wait_int(sc, level);
+
+ default:
+ return ENOTTY;
+ }
+}
+
+int
+pcex_set_int(struct pcex_softc *sc, u_int level)
+{
+ if (level > 6)
+ return EINVAL;
+
+ sc->int_bits |= cisr_int_bits[level];
+
+ return 0;
+}
+
+int
+pcex_reset_int(struct pcex_softc *sc, u_int level)
+{
+ if (level > 6)
+ return EINVAL;
+
+ sc->int_bits &= ~cisr_int_bits[level];
+
+ return 0;
+}
+
+int
+pcex_wait_int(struct pcex_softc *sc, u_int level)
+{
+ int ret;
+
+ if (level > 6)
+ return EINVAL;
+
+ ret = tsleep((void *)sc, PWAIT | PCATCH, "pcex", hz /* XXX: 1 sec. */);
+#ifdef PCEX_DEBUG
+ if (ret == EWOULDBLOCK)
+ printf("%s: timeout in tsleep\n", __func__);
+#endif
+ return ret;
+}
+
+/*
+ * Note about interrupt on PC-9801 extension board slot
+ *
+ * PC-9801 extension board slot bus (so-called 'C-bus' in Japan) use 8 own
+ * interrupt levels, INT0-INT6, and NMI. On LUNA-88K{,2}, they all trigger
+ * level 4 interrupt, so we need to check the dedicated interrupt status
+ * register to know which C-bus interrupt is occurred.
+ *
+ * The interrupt status register for C-bus is located at (u_int8_t *)CBUS_ISR.
+ * Each bit of the register becomes 0 when corresponding C-bus interrupt has
+ * occurred, otherwise 1.
+ *
+ * bit 7 = NMI(?)
+ * bit 6 = INT0
+ * bit 5 = INT1
+ * :
+ * bit 0 = INT6
+ *
+ * To clear the C-bus interrupt flag, write the corresponding 'bit' number
+ * (as u_int_8) to the register. For example, if you want to clear INT1,
+ * you should write '5' like:
+ * *(u_int8_t *)CBUS_ISR = 5;
+ */
+
+/*
+ * Interrupt handler
+ */
+int
+pcex_intr(void *arg)
+{
+ struct pcex_softc *sc = (struct pcex_softc *)arg;
+ u_int8_t int_status;
+ int n;
+
+ /*
+ * LUNA-88K{,2}'s interrupt level 4 is shared with other devices,
+ * such as le(4), for example. So we check:
+ * - the value of our C-bus interrupt status register, and
+ * - if the INT level is what we are looking for.
+ */
+ int_status = *cisr & sc->int_bits;
+ if (int_status == sc->int_bits) return -1; /* Not for me */
+
+#ifdef PCEX_DEBUG
+ printf("%s: called, *cisr=0x%02x, int_bits = 0x%02x\n",
+ __func__, *cisr, sc->int_bits);
+#endif
+
+ /* Just wakeup(9) for now */
+ wakeup((void *)sc);
+
+ /* Make the bit pattern that we should clear interrupt flag */
+ int_status = int_status ^ sc->int_bits;
+
+ /* Clear each interrupt flag */
+ while ((n = ff1(int_status)) != 32) {
+ *cisr = (u_int8_t)n;
+ int_status &= ~(1 << n);
+ }
+
+ return 1;
+}
diff --git a/sys/arch/luna88k/include/conf.h b/sys/arch/luna88k/include/conf.h
index 27dd8083330..b7799146f87 100644
--- a/sys/arch/luna88k/include/conf.h
+++ b/sys/arch/luna88k/include/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.2 2007/01/29 14:18:00 aoyama Exp $ */
+/* $OpenBSD: conf.h,v 1.3 2014/04/16 12:01:33 aoyama Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
* All rights reserved.
@@ -37,9 +37,18 @@ cdev_decl(sio);
cdev_decl(lcd);
+cdev_decl(pcex);
+
/* open, close, write, ioctl */
#define cdev_lcd_init(c,n) { \
dev_init(c,n,open), dev_init(c,n,close), \
(dev_type_read((*))) enodev, dev_init(c,n,write), \
dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
0, seltrue, (dev_type_mmap((*))) enodev }
+
+/* open, close, ioctl, mmap */
+#define cdev_pcex_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, selfalse, \
+ dev_init(c,n,mmap) }
diff --git a/sys/arch/luna88k/include/pcex.h b/sys/arch/luna88k/include/pcex.h
new file mode 100644
index 00000000000..33ac1ca71aa
--- /dev/null
+++ b/sys/arch/luna88k/include/pcex.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: pcex.h,v 1.1 2014/04/16 12:01:33 aoyama Exp $ */
+
+/*
+ * Copyright (c) 2014 Kenji Aoyama.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_PCEX_H_
+#define _MACHINE_PCEX_H_
+
+/*
+ * PC-9801 extension board slot support for LUNA-88K{,2}
+ */
+
+/* The ioctl defines */
+
+#define PCEXSETLEVEL _IOW('P', 1, int) /* Set INT level */
+#define PCEXRESETLEVEL _IOW('P', 2, int) /* Reset INT level */
+#define PCEXWAITINT _IOW('P', 3, int) /* Wait for INT */
+
+#endif /* _MACHINE_PCEX_H_ */
diff --git a/sys/arch/luna88k/luna88k/conf.c b/sys/arch/luna88k/luna88k/conf.c
index cec1e05409e..0d1e1780ddc 100644
--- a/sys/arch/luna88k/luna88k/conf.c
+++ b/sys/arch/luna88k/luna88k/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.20 2013/06/13 13:42:12 aoyama Exp $ */
+/* $OpenBSD: conf.c,v 1.21 2014/04/16 12:01:33 aoyama Exp $ */
/*-
* Copyright (c) 1991 The Regents of the University of California.
@@ -55,6 +55,7 @@
#include "ksyms.h"
#include "lcd.h"
+#include "pcex.h"
#include "siotty.h"
#include "wsdisplay.h"
@@ -121,7 +122,7 @@ struct cdevsw cdevsw[] =
cdev_bpf_init(NBPFILTER,bpf), /* 22: berkeley packet filter */
cdev_tun_init(NTUN,tun), /* 23: network tunnel */
cdev_lkm_init(NLKM,lkm), /* 24: loadable module driver */
- cdev_notdef(), /* 25 */
+ cdev_pcex_init(NPCEX, pcex), /* 25: PC-9801 extension board slot */
cdev_notdef(), /* 26 */
cdev_notdef(), /* 27 */
cdev_notdef(), /* 28 */
diff --git a/sys/arch/luna88k/luna88k/mainbus.c b/sys/arch/luna88k/luna88k/mainbus.c
index e0957d4a62b..eb3009acb9a 100644
--- a/sys/arch/luna88k/luna88k/mainbus.c
+++ b/sys/arch/luna88k/luna88k/mainbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.9 2012/02/28 13:40:53 aoyama Exp $ */
+/* $OpenBSD: mainbus.c,v 1.10 2014/04/16 12:01:33 aoyama Exp $ */
/* $NetBSD: mainbus.c,v 1.2 2000/01/07 05:13:08 nisimura Exp $ */
/*-
@@ -42,6 +42,7 @@
#include <machine/cpu.h>
#include "lcd.h"
+#include "pcex.h"
static const struct mainbus_attach_args devs[] = {
{ "clock", 0x45000000, 6, LUNA_88K|LUNA_88K2 }, /* Mostek/Dallas TimeKeeper */
@@ -56,6 +57,9 @@ static const struct mainbus_attach_args devs[] = {
#if NPCM > 0
{ "pcm", 0x91000000, 4, LUNA_88K|LUNA_88K2 }, /* NEC-9801-86 Sound board (under testing) */
#endif
+#if NPCEX > 0
+ { "pcex", 0x91000000, 4, LUNA_88K|LUNA_88K2 }, /* PC-9801 extension slot */
+#endif
};
void mainbus_attach(struct device *, struct device *, void *);
diff --git a/sys/arch/luna88k/luna88k/pmap_table.c b/sys/arch/luna88k/luna88k/pmap_table.c
index 33aa7d0fcc1..715421a4c7e 100644
--- a/sys/arch/luna88k/luna88k/pmap_table.c
+++ b/sys/arch/luna88k/luna88k/pmap_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap_table.c,v 1.10 2014/01/02 15:30:34 aoyama Exp $ */
+/* $OpenBSD: pmap_table.c,v 1.11 2014/04/16 12:01:33 aoyama Exp $ */
/*
* Mach Operating System
@@ -60,8 +60,8 @@ luna88k_board_table[] = {
#if 0
{ EXT_A_ADDR, EXT_A_SPACE, RW, CI },
{ EXT_B_ADDR, EXT_B_SPACE, RW, CI },
- { PC_BASE, PC_SPACE, RW, CI },
#endif
+ { PC_BASE, PC_SPACE, RW, CI },
{ MROM_ADDR, MROM_SPACE, R, CI },
{ BMAP_RFCNT, PAGE_SIZE, RW, CI },
{ BMAP_BMSEL, PAGE_SIZE, RW, CI },