Add generic driver for "NEC PC-9801(*) extension board slot" on
authoraoyama <aoyama@openbsd.org>
Wed, 16 Apr 2014 12:01:33 +0000 (12:01 +0000)
committeraoyama <aoyama@openbsd.org>
Wed, 16 Apr 2014 12:01:33 +0000 (12:01 +0000)
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@

share/man/man4/man4.luna88k/Makefile
share/man/man4/man4.luna88k/pcexmem.4 [new file with mode: 0644]
sys/arch/luna88k/conf/GENERIC
sys/arch/luna88k/conf/files.luna88k
sys/arch/luna88k/dev/pcex.c [new file with mode: 0644]
sys/arch/luna88k/include/conf.h
sys/arch/luna88k/include/pcex.h [new file with mode: 0644]
sys/arch/luna88k/luna88k/conf.c
sys/arch/luna88k/luna88k/mainbus.c
sys/arch/luna88k/luna88k/pmap_table.c

index aa57c7c..6dea1ff 100644 (file)
@@ -1,7 +1,7 @@
-#      $OpenBSD: Makefile,v 1.2 2007/02/15 14:19:59 aoyama Exp $
+#      $OpenBSD: Makefile,v 1.3 2014/04/16 12:01:33 aoyama Exp $
 
 # TODO: clock fb sio/siotty ws
-MAN=   autoconf.4 intro.4 lcd.4 le.4 mem.4 spc.4
+MAN=   autoconf.4 intro.4 lcd.4 le.4 mem.4 pcexmem.4 spc.4
 MANSUBDIR=luna88k
 
 MLINKS+= mem.4 kmem.4
diff --git a/share/man/man4/man4.luna88k/pcexmem.4 b/share/man/man4/man4.luna88k/pcexmem.4
new file mode 100644 (file)
index 0000000..d00b90f
--- /dev/null
@@ -0,0 +1,76 @@
+.\"    $OpenBSD: pcexmem.4,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.
+.Dd $Mdocdate: April 16 2014 $
+.Dt PCEXMEM 4 luna88k
+.Os
+.Sh NAME
+.Nm pcexmem ,
+.Nm pcexio
+.Nd NEC PC-9801 extension board slot
+.Sh SYNOPSIS
+.Cd "pcex0 at mainbus0"
+.Sh DESCRIPTION
+The file
+.Pa /dev/pcexmem
+is an
+.Xr mmap 2
+capable interface to the memory area of the installed board at "NEC PC-9801
+extension board slot" on LUNA88K.
+Byte offsets in this file are interpreted as relative memory addresses
+of the installed board.
+The range should be between 0x0 and 0xffffff.
+.Pp
+The I/O port area of the installed board is accessed via the file
+.Pa /dev/pcexio
+in the same manner as
+.Pa /dev/pcexmem .
+The range should be between 0x0 and 0xffff.
+.Pp
+The following
+.Xr ioctl 2
+calls apply to
+.Pa /dev/pcexmem
+and
+.Pa /dev/pcexio
+in order to handle interrupts of this extension slot.
+Currently 7 levels of interrupt (0 to 6) are supported.
+.Bl -tag -width PCEX
+.It Dv PCEXSETLEVEL Fa "u_int *"
+Register the specified interrupt level with this driver to handle.
+.It Dv PCEXRESETLEVEL Fa "u_int *"
+Unregister the specified interrupt level with this driver.
+.It Dv PCEXWAITINT Fa "u_int *"
+Wait for the interrupt with the specified level.
+.El
+.Sh FILES
+.Bl -tag -width /dev/pcexmem -compact
+.It Pa /dev/pcexmem
+.It Pa /dev/pcexio
+.El
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EWOULDBLOCK
+PCEXWAITINT timeouts (currently 1 second).
+.El
+.Sh SEE ALSO
+.Xr ioctl 2
+.Sh HISTORY
+The
+.Pa /dev/pcexmem
+and
+.Pa /dev/pcexio
+files first appeared in
+.Ox 5.6 .
index 9d6da06..9f93826 100644 (file)
@@ -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
index 27d0dc8..1a8818b 100644 (file)
@@ -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 (file)
index 0000000..c6552b3
--- /dev/null
@@ -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;
+}
index 27dd808..b779914 100644 (file)
@@ -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 (file)
index 0000000..33ac1ca
--- /dev/null
@@ -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_ */
index cec1e05..0d1e178 100644 (file)
@@ -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 */
index e0957d4..eb3009a 100644 (file)
@@ -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 *);
index 33aa7d0..715421a 100644 (file)
@@ -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 },