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@
-# $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
--- /dev/null
+.\" $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 .
-# $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.
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
-# $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
#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
--- /dev/null
+/* $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;
+}
-/* $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.
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) }
--- /dev/null
+/* $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_ */
-/* $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.
#include "ksyms.h"
#include "lcd.h"
+#include "pcex.h"
#include "siotty.h"
#include "wsdisplay.h"
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 */
-/* $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 $ */
/*-
#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 */
#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 *);
-/* $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
#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 },