From a5a68e2f7b2e5092a0233ced0bcb9a61b8effb58 Mon Sep 17 00:00:00 2001 From: aoyama Date: Wed, 16 Apr 2014 12:01:33 +0000 Subject: [PATCH] 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@ --- share/man/man4/man4.luna88k/Makefile | 4 +- share/man/man4/man4.luna88k/pcexmem.4 | 76 +++++++ sys/arch/luna88k/conf/GENERIC | 5 +- sys/arch/luna88k/conf/files.luna88k | 6 +- sys/arch/luna88k/dev/pcex.c | 287 ++++++++++++++++++++++++++ sys/arch/luna88k/include/conf.h | 11 +- sys/arch/luna88k/include/pcex.h | 32 +++ sys/arch/luna88k/luna88k/conf.c | 5 +- sys/arch/luna88k/luna88k/mainbus.c | 6 +- sys/arch/luna88k/luna88k/pmap_table.c | 4 +- 10 files changed, 426 insertions(+), 10 deletions(-) create mode 100644 share/man/man4/man4.luna88k/pcexmem.4 create mode 100644 sys/arch/luna88k/dev/pcex.c create mode 100644 sys/arch/luna88k/include/pcex.h diff --git a/share/man/man4/man4.luna88k/Makefile b/share/man/man4/man4.luna88k/Makefile index aa57c7c6884..6dea1ffcb67 100644 --- a/share/man/man4/man4.luna88k/Makefile +++ b/share/man/man4/man4.luna88k/Makefile @@ -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 index 00000000000..d00b90f1642 --- /dev/null +++ b/share/man/man4/man4.luna88k/pcexmem.4 @@ -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 . 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 +#include /* tsleep()/wakeup() */ +#include +#include + +#include /* ff1() */ +#include +#include /* PC_BASE */ +#include +#include +#include + +#include + +#include + +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 #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 }, -- 2.20.1