diff options
author | Kenji Aoyama <aoyama@cvs.openbsd.org> | 2014-04-16 12:01:34 +0000 |
---|---|---|
committer | Kenji Aoyama <aoyama@cvs.openbsd.org> | 2014-04-16 12:01:34 +0000 |
commit | 4996567438ccba9f4d7be798894b816ce339ed1b (patch) | |
tree | 7b3794819e44d77bd26824bb1284e5d6ea6444d3 /sys/arch | |
parent | f835eee727683f1f21e319510529b3bf48777c3f (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/GENERIC | 5 | ||||
-rw-r--r-- | sys/arch/luna88k/conf/files.luna88k | 6 | ||||
-rw-r--r-- | sys/arch/luna88k/dev/pcex.c | 287 | ||||
-rw-r--r-- | sys/arch/luna88k/include/conf.h | 11 | ||||
-rw-r--r-- | sys/arch/luna88k/include/pcex.h | 32 | ||||
-rw-r--r-- | sys/arch/luna88k/luna88k/conf.c | 5 | ||||
-rw-r--r-- | sys/arch/luna88k/luna88k/mainbus.c | 6 | ||||
-rw-r--r-- | sys/arch/luna88k/luna88k/pmap_table.c | 4 |
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 }, |