diff options
author | nyan <nyan@FreeBSD.org> | 2005-05-10 12:02:18 +0000 |
---|---|---|
committer | nyan <nyan@FreeBSD.org> | 2005-05-10 12:02:18 +0000 |
commit | 7d03ad1458ef99a90237ab0926026b117edd0d91 (patch) | |
tree | 0d3cf7498692dd1d1a5e911b14b159833365b122 | |
parent | e571f8f77c821803b7c8084feb8283f6dd32db1e (diff) | |
download | FreeBSD-src-7d03ad1458ef99a90237ab0926026b117edd0d91.zip FreeBSD-src-7d03ad1458ef99a90237ab0926026b117edd0d91.tar.gz |
Change a directory layout for pc98.
- Move MD files into <arch>/<arch>.
- Move bus dependent files into <arch>/<bus>.
Rename some files to more suitable names.
Repo-copied by: peter
Discussed with: imp
52 files changed, 53 insertions, 22354 deletions
diff --git a/sys/boot/pc98/boot2/io.c b/sys/boot/pc98/boot2/io.c index d4657a2..4d03246 100644 --- a/sys/boot/pc98/boot2/io.c +++ b/sys/boot/pc98/boot2/io.c @@ -32,7 +32,7 @@ __FBSDID("$FreeBSD$"); #include "boot.h" #include <machine/cpufunc.h> #include <sys/reboot.h> -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> static int getchar(int in_buf); diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index fc4de01..5435444 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -347,29 +347,29 @@ libkern/ucmpdi2.c standard libkern/udivdi3.c standard libkern/umoddi3.c standard pc98/apm/apm_bioscall.S optional apm -pc98/i386/busio.s standard -pc98/i386/busiosubr.c standard -pc98/i386/machdep.c standard +pc98/cbus/cbus_dma.c optional isa +pc98/cbus/clock.c standard +pc98/cbus/fdc.c optional fdc +pc98/cbus/fdc_cbus.c optional fdc isa +pc98/cbus/gdc.c optional gdc +pc98/cbus/nmi.c standard +pc98/cbus/olpt.c optional olpt +pc98/cbus/pckbd.c optional pckbd +pc98/cbus/pmc.c optional pmc +pc98/cbus/ppc.c optional ppc +pc98/cbus/scgdcrndr.c optional sc gdc +pc98/cbus/scterm-sck.c optional sc +pc98/cbus/scvtb.c optional sc +pc98/cbus/sio.c optional sio +pc98/cbus/sio_cbus.c optional sio isa +pc98/cbus/syscons_cbus.c optional sc +pc98/pc98/busio.s standard +pc98/pc98/busiosubr.c standard pc98/pc98/canbepm.c optional canbepm pc98/pc98/canbus.c optional canbus pc98/pc98/canbus_if.m optional canbus -pc98/pc98/clock.c standard -pc98/pc98/fd.c optional fdc -pc98/pc98/fdc_cbus.c optional fdc isa -pc98/pc98/isa_dma.c optional isa -pc98/pc98/nmi.c standard -pc98/pc98/olpt.c optional olpt +pc98/pc98/machdep.c standard pc98/pc98/pc98_machdep.c standard -pc98/pc98/pc98gdc.c optional gdc -pc98/pc98/pc98kbd.c optional pckbd -pc98/pc98/pmc.c optional pmc -pc98/pc98/ppc.c optional ppc -pc98/pc98/scgdcrndr.c optional sc gdc -pc98/pc98/scterm-sck.c optional sc -pc98/pc98/scvtbpc98.c optional sc -pc98/pc98/sio.c optional sio -pc98/pc98/sio_cbus.c optional sio isa -pc98/pc98/syscons_pc98.c optional sc pccard/pccard.c optional card pccard/pccard_beep.c optional card pccard/pccard_nbk.c optional card diff --git a/sys/dev/ct/ct_isa.c b/sys/dev/ct/ct_isa.c index b16b1d8..7d6dad6 100644 --- a/sys/dev/ct/ct_isa.c +++ b/sys/dev/ct/ct_isa.c @@ -78,7 +78,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <machine/md_var.h> -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #include <isa/isavar.h> #include <compat/netbsd/dvcfg.h> diff --git a/sys/dev/speaker/spkr.c b/sys/dev/speaker/spkr.c index 7b41f25..321b2cb 100644 --- a/sys/dev/speaker/spkr.c +++ b/sys/dev/speaker/spkr.c @@ -20,7 +20,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <isa/isavar.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index 99bf8a4..b5fb872 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -34,7 +34,7 @@ /* machine-dependent part of the header */ #ifdef PC98 -#include <pc98/pc98/sc_machdep.h> +#include <pc98/cbus/sc_machdep.h> #elif defined(__i386__) /* nothing for the moment */ #elif defined(__alpha__) diff --git a/sys/i386/i386/nexus.c b/sys/i386/i386/nexus.c index e8d1406..15751bd 100644 --- a/sys/i386/i386/nexus.c +++ b/sys/i386/i386/nexus.c @@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$"); #ifdef DEV_ISA #include <isa/isavar.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index ab9eb81..df01592 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -91,7 +91,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif diff --git a/sys/i386/isa/atpic.c b/sys/i386/isa/atpic.c index d326c68..8d17ec1 100644 --- a/sys/i386/isa/atpic.c +++ b/sys/i386/isa/atpic.c @@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ic/i8259.h> #include <i386/isa/icu.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 9e65106..9a7ba17 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$"); #include <machine/ucontext.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif diff --git a/sys/i386/isa/prof_machdep.c b/sys/i386/isa/prof_machdep.c index 616be3e..981727c 100644 --- a/sys/i386/isa/prof_machdep.c +++ b/sys/i386/isa/prof_machdep.c @@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$"); #include <machine/asmacros.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif diff --git a/sys/i386/isa/spkr.c b/sys/i386/isa/spkr.c index 7b41f25..321b2cb 100644 --- a/sys/i386/isa/spkr.c +++ b/sys/i386/isa/spkr.c @@ -20,7 +20,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <isa/isavar.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif diff --git a/sys/modules/fdc/Makefile b/sys/modules/fdc/Makefile index de92183..b632dcd 100644 --- a/sys/modules/fdc/Makefile +++ b/sys/modules/fdc/Makefile @@ -4,8 +4,8 @@ KMOD= fdc WARNS?= 2 .if ${MACHINE} == "pc98" -.PATH: ${.CURDIR}/../../pc98/pc98 -SRCS= fd.c fdc_cbus.c +.PATH: ${.CURDIR}/../../pc98/cbus +SRCS= fdc.c fdc_cbus.c .else .PATH: ${.CURDIR}/../../dev/fdc SRCS= fdc.c fdc_isa.c fdc_pccard.c diff --git a/sys/modules/pmc/Makefile b/sys/modules/pmc/Makefile index 30c1581..60dd350 100644 --- a/sys/modules/pmc/Makefile +++ b/sys/modules/pmc/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../pc98/pc98 +.PATH: ${.CURDIR}/../../pc98/cbus KMOD= pmc SRCS= pmc.c diff --git a/sys/modules/sio/Makefile b/sys/modules/sio/Makefile index a0c02bb..8ec6b4e 100644 --- a/sys/modules/sio/Makefile +++ b/sys/modules/sio/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ .if ${MACHINE} == "pc98" -.PATH: ${.CURDIR}/../../pc98/pc98 +.PATH: ${.CURDIR}/../../pc98/cbus .endif .PATH: ${.CURDIR}/../../dev/sio diff --git a/sys/pc98/cbus/cbus_dma.c b/sys/pc98/cbus/cbus_dma.c index 5bf2c88..f85e3c7 100644 --- a/sys/pc98/cbus/cbus_dma.c +++ b/sys/pc98/cbus/cbus_dma.c @@ -60,9 +60,9 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> -#include <pc98/pc98/pc98.h> #include <dev/ic/i8237.h> #include <isa/isavar.h> +#include <pc98/cbus/cbus.h> /* ** Register definitions for DMA controller 1 (channels 0..3): diff --git a/sys/pc98/cbus/clock.c b/sys/pc98/cbus/clock.c index 484e8df..f3d956b 100644 --- a/sys/pc98/cbus/clock.c +++ b/sys/pc98/cbus/clock.c @@ -81,7 +81,7 @@ #include <machine/specialreg.h> #include <i386/isa/icu.h> -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #include <pc98/pc98/pc98_machdep.h> #ifdef DEV_ISA #include <isa/isavar.h> diff --git a/sys/pc98/cbus/fdc.c b/sys/pc98/cbus/fdc.c index d2ead23..3b366a1 100644 --- a/sys/pc98/cbus/fdc.c +++ b/sys/pc98/cbus/fdc.c @@ -78,11 +78,11 @@ #ifdef PC98 #include <isa/isavar.h> -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> +#include <pc98/cbus/cbus.h> +#include <pc98/cbus/fdcreg.h> +#include <pc98/cbus/fdcvar.h> #include <pc98/pc98/epsonio.h> -#include <pc98/pc98/fdreg.h> -#include <pc98/pc98/fdcvar.h> +#include <pc98/pc98/pc98_machdep.h> #else #include <isa/isavar.h> #include <isa/isareg.h> diff --git a/sys/pc98/cbus/fdc_cbus.c b/sys/pc98/cbus/fdc_cbus.c index 0980e00..de60a43 100644 --- a/sys/pc98/cbus/fdc_cbus.c +++ b/sys/pc98/cbus/fdc_cbus.c @@ -39,11 +39,11 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> -#include <pc98/pc98/fdcvar.h> -#include <pc98/pc98/fdreg.h> +#include <pc98/cbus/cbus.h> +#include <pc98/cbus/fdcreg.h> +#include <pc98/cbus/fdcvar.h> #include <isa/isavar.h> -#include <pc98/pc98/pc98.h> static bus_addr_t fdc_iat[] = {0, 2, 4}; diff --git a/sys/pc98/cbus/gdc.c b/sys/pc98/cbus/gdc.c index 9df28d5..f9c2f58 100644 --- a/sys/pc98/cbus/gdc.c +++ b/sys/pc98/cbus/gdc.c @@ -55,7 +55,7 @@ #include <dev/fb/fbreg.h> #ifdef LINE30 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #endif #include <pc98/pc98/pc98_machdep.h> #include <isa/isavar.h> @@ -423,7 +423,7 @@ DRIVER_MODULE(gdc, isa, gdcdriver, gdc_devclass, 0, 0); /* LOW-LEVEL */ -#include <pc98/pc98/30line.h> +#include <pc98/cbus/30line.h> #define TEXT_BUF_BASE 0x000a0000 #define TEXT_BUF_SIZE 0x00008000 diff --git a/sys/pc98/cbus/pckbd.c b/sys/pc98/cbus/pckbd.c index f33b8c2..3d3587f 100644 --- a/sys/pc98/cbus/pckbd.c +++ b/sys/pc98/cbus/pckbd.c @@ -43,8 +43,7 @@ #include <dev/kbd/kbdreg.h> -#include <pc98/pc98/pc98.h> - +#include <pc98/cbus/cbus.h> #include <isa/isavar.h> #define DRIVER_NAME "pckbd" diff --git a/sys/pc98/cbus/pcrtc.c b/sys/pc98/cbus/pcrtc.c index 484e8df..f3d956b 100644 --- a/sys/pc98/cbus/pcrtc.c +++ b/sys/pc98/cbus/pcrtc.c @@ -81,7 +81,7 @@ #include <machine/specialreg.h> #include <i386/isa/icu.h> -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #include <pc98/pc98/pc98_machdep.h> #ifdef DEV_ISA #include <isa/isavar.h> diff --git a/sys/pc98/cbus/ppc.c b/sys/pc98/cbus/ppc.c index 67adef3..e04e3fb 100644 --- a/sys/pc98/cbus/ppc.c +++ b/sys/pc98/cbus/ppc.c @@ -44,7 +44,7 @@ #include <sys/rman.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <isa/isareg.h> #endif @@ -55,7 +55,7 @@ #include <dev/ppc/ppcvar.h> #ifdef PC98 -#include <pc98/pc98/ppcreg.h> +#include <pc98/cbus/ppcreg.h> #else #include <dev/ppc/ppcreg.h> #endif diff --git a/sys/pc98/cbus/sio.c b/sys/pc98/cbus/sio.c index 297f61d..007e1b2 100644 --- a/sys/pc98/cbus/sio.c +++ b/sys/pc98/cbus/sio.c @@ -111,7 +111,7 @@ #include <dev/sio/siovar.h> #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #include <pc98/pc98/pc98_machdep.h> #endif diff --git a/sys/pc98/cbus/syscons_cbus.c b/sys/pc98/cbus/syscons_cbus.c index df8934e..fc430e9 100644 --- a/sys/pc98/cbus/syscons_cbus.c +++ b/sys/pc98/cbus/syscons_cbus.c @@ -39,7 +39,7 @@ #include <machine/clock.h> -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #include <pc98/pc98/pc98_machdep.h> #include <dev/syscons/syscons.h> diff --git a/sys/pc98/i386/busio.s b/sys/pc98/i386/busio.s deleted file mode 100644 index 915dcae..0000000 --- a/sys/pc98/i386/busio.s +++ /dev/null @@ -1,1774 +0,0 @@ -/* $FreeBSD$ */ -/* $NecBSD: busio.s,v 1.16.4.1 1999/08/16 09:06:08 kmatsuda Exp $ */ -/* $NetBSD$ */ - -/*- - * [NetBSD for NEC PC-98 series] - * Copyright (c) 1996, 1997, 1998 - * NetBSD/pc98 porting staff. All rights reserved. - * - * [Ported for FreeBSD] - * Copyright (c) 2001 - * TAKAHASHI Yoshihiro. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1997, 1998 - * Naofumi HONDA. All rights reserved. - */ - -#include <machine/asmacros.h> - -#include "assym.s" - -/*********************************************************** - * Bus IO access methods (Direct Access) - ***********************************************************/ -#define BUS_ACCESS_ADDR(BSHREG,ADDRREG) \ - addl BUS_SPACE_HANDLE_BASE/**/(%/**/BSHREG/**/),%/**/ADDRREG - -/* - * read_N - * IN: edx port - * OUT: eax data - */ -ENTRY(SBUS_DA_io_space_read_1) - BUS_ACCESS_ADDR(ebx,edx) - inb %dx,%al - ret - -ENTRY(SBUS_DA_io_space_read_2) - BUS_ACCESS_ADDR(ebx,edx) - inw %dx,%ax - ret - -ENTRY(SBUS_DA_io_space_read_4) - BUS_ACCESS_ADDR(ebx,edx) - inl %dx,%eax - ret - -/* - * write_N - * IN:eax DATA - * edx PORT - */ -ENTRY(SBUS_DA_io_space_write_1) - BUS_ACCESS_ADDR(ebx,edx) - outb %al,%dx - ret - -ENTRY(SBUS_DA_io_space_write_2) - BUS_ACCESS_ADDR(ebx,edx) - outw %ax,%dx - ret - -ENTRY(SBUS_DA_io_space_write_4) - BUS_ACCESS_ADDR(ebx,edx) - outl %eax,%dx - ret - -/* - * read_multi_N - * IN: ecx COUNT - * edx PORT - * edi BUFP - */ -ENTRY(SBUS_DA_io_space_read_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - insb - ret - -ENTRY(SBUS_DA_io_space_read_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - insw - ret - -ENTRY(SBUS_DA_io_space_read_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - insl - ret - -/* - * write_multi_N - * IN: ecx COUNT - * edx PORT - * esi BUFP - */ -ENTRY(SBUS_DA_io_space_write_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - outsb - ret - -ENTRY(SBUS_DA_io_space_write_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - outsw - ret - -ENTRY(SBUS_DA_io_space_write_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - outsl - ret - -/* - * read_region_N - * IN: ecx COUNT - * edx PORT - * edi BUFP - */ -ENTRY(SBUS_DA_io_space_read_region_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - inb %dx,%al - stosb - incl %edx - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_io_space_read_region_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - inw %dx,%ax - stosw - addl $2,%edx - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_io_space_read_region_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - inl %dx,%eax - stosl - addl $4,%edx - decl %ecx - jnz 1b -2: - popl %eax - ret - -/* - * write_region_N - * IN: ecx COUNT - * edx PORT - * esi BUFP - */ -ENTRY(SBUS_DA_io_space_write_region_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsb - outb %al,%dx - incl %edx - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_io_space_write_region_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsw - outw %ax,%dx - addl $2,%edx - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_io_space_write_region_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsl - outl %eax,%dx - addl $4,%edx - decl %ecx - jnz 1b -2: - popl %eax - ret - -/* - * set_multi_N - * IN: eax DATA - * ecx COUNT - * edx PORT - */ -ENTRY(SBUS_DA_io_space_set_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outb %al,%dx - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_DA_io_space_set_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outw %ax,%dx - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_DA_io_space_set_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outl %eax,%dx - decl %ecx - jnz 1b -2: - ret - -/* - * set_region_N - * IN: eax DATA - * ecx COUNT - * edx PORT - */ -ENTRY(SBUS_DA_io_space_set_region_1) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outb %al,%dx - incl %edx - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_DA_io_space_set_region_2) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outw %ax,%dx - addl $2,%edx - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_DA_io_space_set_region_4) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outl %eax,%dx - addl $4,%edx - decl %ecx - jnz 1b -2: - ret - -/* - * copy_region_N - * IN: ecx COUNT - * esi SPORT - * edi DPORT - */ -ENTRY(SBUS_DA_io_space_copy_region_1) - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - pushl %eax - pushl %edx - orl %ecx,%ecx - jz 2f -1: - movl %esi,%edx - inb %dx,%al - incl %esi - - movl %edi,%edx - outb %al,%dx - incl %edi - - decl %ecx - jnz 1b -2: - popl %edx - popl %eax - ret - -ENTRY(SBUS_DA_io_space_copy_region_2) - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - pushl %eax - pushl %edx - orl %ecx,%ecx - jz 2f -1: - movl %esi,%edx - inw %dx,%ax - addl $2,%esi - - movl %edi,%edx - outw %ax,%dx - addl $2,%edi - - decl %ecx - jnz 1b -2: - popl %edx - popl %eax - ret - -ENTRY(SBUS_DA_io_space_copy_region_4) - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - pushl %eax - pushl %edx - orl %ecx,%ecx - jz 2f -1: - movl %esi,%edx - inl %dx,%eax - addl $4,%esi - - movl %edi,%edx - outl %eax,%dx - addl $4,%edi - - decl %ecx - jnz 1b -2: - popl %edx - popl %eax - ret - -/*********************************************************** - * Bus Memory access methods (Direct Access) - ***********************************************************/ -/* - * read_N - */ -ENTRY(SBUS_DA_mem_space_read_1) - BUS_ACCESS_ADDR(ebx,edx) - movb (%edx),%al - ret - -ENTRY(SBUS_DA_mem_space_read_2) - BUS_ACCESS_ADDR(ebx,edx) - movw (%edx),%ax - ret - -ENTRY(SBUS_DA_mem_space_read_4) - BUS_ACCESS_ADDR(ebx,edx) - movl (%edx),%eax - ret - -/* - * write_N - */ -ENTRY(SBUS_DA_mem_space_write_1) - BUS_ACCESS_ADDR(ebx,edx) - movb %al,(%edx) - ret - -ENTRY(SBUS_DA_mem_space_write_2) - BUS_ACCESS_ADDR(ebx,edx) - movw %ax,(%edx) - ret - -ENTRY(SBUS_DA_mem_space_write_4) - BUS_ACCESS_ADDR(ebx,edx) - movl %eax,(%edx) - ret - -/* - * read_multi_N - */ -ENTRY(SBUS_DA_mem_space_read_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - movb (%edx),%al - stosb - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_mem_space_read_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - movw (%edx),%ax - stosw - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_mem_space_read_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - movl (%edx),%eax - stosl - decl %ecx - jnz 1b -2: - popl %eax - ret - -/* - * write_multi_N - */ -ENTRY(SBUS_DA_mem_space_write_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsb - movb %al,(%edx) - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_mem_space_write_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsw - movw %ax,(%edx) - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_DA_mem_space_write_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsl - movl %eax,(%edx) - decl %ecx - jnz 1b -2: - popl %eax - ret - -/* - * read_region_N - */ -ENTRY(SBUS_DA_mem_space_read_region_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %esi - movl %edx,%esi - rep - movsb - popl %esi - ret - -ENTRY(SBUS_DA_mem_space_read_region_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %esi - movl %edx,%esi - rep - movsw - popl %esi - ret - -ENTRY(SBUS_DA_mem_space_read_region_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %esi - movl %edx,%esi - rep - movsl - popl %esi - ret - -/* - * write_region_N - */ -ENTRY(SBUS_DA_mem_space_write_region_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %edi - movl %edx,%edi - rep - movsb - popl %edi - ret - -ENTRY(SBUS_DA_mem_space_write_region_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %edi - movl %edx,%edi - rep - movsw - popl %edi - ret - -ENTRY(SBUS_DA_mem_space_write_region_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %edi - movl %edx,%edi - rep - movsl - popl %edi - ret - -/* - * set_multi_N - */ -ENTRY(SBUS_DA_mem_space_set_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - movb %al,(%edx) - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_DA_mem_space_set_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - movw %ax,(%edx) - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_DA_mem_space_set_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - movl %eax,(%edx) - decl %ecx - jnz 1b -2: - ret - -/* - * set_region_N - */ -ENTRY(SBUS_DA_mem_space_set_region_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %edi - movl %edx,%edi - rep - stosb - popl %edi - ret - -ENTRY(SBUS_DA_mem_space_set_region_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %edi - movl %edx,%edi - rep - stosw - popl %edi - ret - -ENTRY(SBUS_DA_mem_space_set_region_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %edi - movl %edx,%edi - rep - stosl - popl %edi - ret - -/* - * copy_region_N - */ -ENTRY(SBUS_DA_mem_space_copy_region_1) - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - cld - rep - movsb - ret - -ENTRY(SBUS_DA_mem_space_copy_region_2) - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - cld - rep - movsw - ret - -ENTRY(SBUS_DA_mem_space_copy_region_4) - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - cld - rep - movsl - ret - -#undef BUS_ACCESS_ADDR - -/*********************************************************** - * Bus IO access methods (Relocate Access) - ***********************************************************/ -#define BUS_ACCESS_ADDR(BSHREG,ADDRREG) \ - movl BUS_SPACE_HANDLE_IAT/**/(%/**/BSHREG/**/, %/**/ADDRREG/**/, 4), \ - %/**/ADDRREG -#define BUS_ACCESS_ADDR2(BSHREG,ADDRREG,DSTREG) \ - movl BUS_SPACE_HANDLE_IAT/**/(%/**/BSHREG/**/, %/**/ADDRREG/**/, 4), \ - %/**/DSTREG -/* - * read_N - * IN: edx port - * OUT: eax data - */ -ENTRY(SBUS_RA_io_space_read_1) - BUS_ACCESS_ADDR(ebx,edx) - inb %dx,%al - ret - -ENTRY(SBUS_RA_io_space_read_2) - BUS_ACCESS_ADDR(ebx,edx) - inw %dx,%ax - ret - -ENTRY(SBUS_RA_io_space_read_4) - BUS_ACCESS_ADDR(ebx,edx) - inl %dx,%eax - ret - -/* - * write_N - * IN:eax DATA - * edx PORT - */ -ENTRY(SBUS_RA_io_space_write_1) - BUS_ACCESS_ADDR(ebx,edx) - outb %al,%dx - ret - -ENTRY(SBUS_RA_io_space_write_2) - BUS_ACCESS_ADDR(ebx,edx) - outw %ax,%dx - ret - -ENTRY(SBUS_RA_io_space_write_4) - BUS_ACCESS_ADDR(ebx,edx) - outl %eax,%dx - ret - -/* - * read_multi_N - * IN: ecx COUNT - * edx PORT - * edi BUFP - */ -ENTRY(SBUS_RA_io_space_read_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - insb - ret - -ENTRY(SBUS_RA_io_space_read_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - insw - ret - -ENTRY(SBUS_RA_io_space_read_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - insl - ret - -/* - * write_multi_N - * IN: ecx COUNT - * edx PORT - * esi BUFP - */ -ENTRY(SBUS_RA_io_space_write_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - outsb - ret - -ENTRY(SBUS_RA_io_space_write_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - outsw - ret - -ENTRY(SBUS_RA_io_space_write_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - rep - outsl - ret - -/* - * read_region_N - * IN: ecx COUNT - * edx PORT - * edi BUFP - */ -ENTRY(SBUS_RA_io_space_read_region_1) - cld - pushl %eax - pushl %esi - orl %ecx,%ecx - jz 2f - movl %edx,%esi -1: - BUS_ACCESS_ADDR2(ebx,esi,edx) - inb %dx,%al - stosb - incl %esi - decl %ecx - jnz 1b -2: - popl %esi - popl %eax - ret - -ENTRY(SBUS_RA_io_space_read_region_2) - cld - pushl %eax - pushl %esi - orl %ecx,%ecx - jz 2f - movl %edx,%esi -1: - BUS_ACCESS_ADDR2(ebx,esi,edx) - inw %dx,%ax - stosw - addl $2,%esi - decl %ecx - jnz 1b -2: - popl %esi - popl %eax - ret - -ENTRY(SBUS_RA_io_space_read_region_4) - cld - pushl %eax - pushl %esi - orl %ecx,%ecx - jz 2f - movl %edx,%esi -1: - BUS_ACCESS_ADDR2(ebx,esi,edx) - inl %dx,%eax - stosl - addl $4,%esi - decl %ecx - jnz 1b -2: - popl %esi - popl %eax - ret - -/* - * write_region_N - * IN: ecx COUNT - * edx PORT - * esi BUFP - */ -ENTRY(SBUS_RA_io_space_write_region_1) - cld - pushl %eax - pushl %edi - orl %ecx,%ecx - jz 2f - movl %edx,%edi -1: - BUS_ACCESS_ADDR2(ebx,edi,edx) - lodsb - outb %al,%dx - incl %edi - decl %ecx - jnz 1b -2: - popl %edi - popl %eax - ret - -ENTRY(SBUS_RA_io_space_write_region_2) - cld - pushl %eax - pushl %edi - orl %ecx,%ecx - jz 2f - movl %edx,%edi -1: - BUS_ACCESS_ADDR2(ebx,edi,edx) - lodsw - outw %ax,%dx - addl $2,%edi - decl %ecx - jnz 1b -2: - popl %edi - popl %eax - ret - -ENTRY(SBUS_RA_io_space_write_region_4) - cld - pushl %eax - pushl %edi - orl %ecx,%ecx - jz 2f - movl %edx,%edi -1: - BUS_ACCESS_ADDR2(ebx,edi,edx) - lodsl - outl %eax,%dx - addl $4,%edi - decl %ecx - jnz 1b -2: - popl %edi - popl %eax - ret - -/* - * set_multi_N - * IN: eax DATA - * ecx COUNT - * edx PORT - */ -ENTRY(SBUS_RA_io_space_set_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outb %al,%dx - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_RA_io_space_set_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outw %ax,%dx - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_RA_io_space_set_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - outl %eax,%dx - decl %ecx - jnz 1b -2: - ret - -/* - * set_region_N - * IN: eax DATA - * ecx COUNT - * edx PORT - */ -ENTRY(SBUS_RA_io_space_set_region_1) - pushl %edi - orl %ecx,%ecx - jz 2f - movl %edx,%edi -1: - BUS_ACCESS_ADDR2(ebx,edi,edx) - outb %al,%dx - incl %edi - decl %ecx - jnz 1b -2: - popl %edi - ret - -ENTRY(SBUS_RA_io_space_set_region_2) - pushl %edi - orl %ecx,%ecx - jz 2f - movl %edx,%edi -1: - BUS_ACCESS_ADDR2(ebx,edi,edx) - outw %ax,%dx - addl $2,%edi - decl %ecx - jnz 1b -2: - popl %edi - ret - -ENTRY(SBUS_RA_io_space_set_region_4) - pushl %edi - orl %ecx,%ecx - jz 2f - movl %edx,%edi -1: - BUS_ACCESS_ADDR2(ebx,edi,edx) - outl %eax,%dx - addl $4,%edi - decl %ecx - jnz 1b -2: - popl %edi - ret - -/* - * copy_region_N - * IN: ecx COUNT - * esi SPORT - * edi DPORT - */ -ENTRY(SBUS_RA_io_space_copy_region_1) - pushl %eax - pushl %edx - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,esi,edx) - inb %dx,%al - incl %esi - - BUS_ACCESS_ADDR2(ebx,edi,edx) - outb %al,%dx - incl %edi - - decl %ecx - jnz 1b -2: - popl %edx - popl %eax - ret - -ENTRY(SBUS_RA_io_space_copy_region_2) - pushl %eax - pushl %edx - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,esi,edx) - inw %dx,%ax - addl $2,%esi - - BUS_ACCESS_ADDR2(ebx,edi,edx) - outw %ax,%dx - addl $2,%edi - - decl %ecx - jnz 1b -2: - popl %edx - popl %eax - ret - -ENTRY(SBUS_RA_io_space_copy_region_4) - pushl %eax - pushl %edx - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,esi,edx) - inl %dx,%eax - addl $4,%esi - - BUS_ACCESS_ADDR2(ebx,edi,edx) - outl %eax,%dx - addl $4,%edi - - decl %ecx - jnz 1b -2: - popl %edx - popl %eax - ret - -/*********************************************************** - * Bus Memory access methods - ***********************************************************/ -/* - * read_N - */ -ENTRY(SBUS_RA_mem_space_read_1) - BUS_ACCESS_ADDR(ebx,edx) - movb (%edx),%al - ret - -ENTRY(SBUS_RA_mem_space_read_2) - BUS_ACCESS_ADDR(ebx,edx) - movw (%edx),%ax - ret - -ENTRY(SBUS_RA_mem_space_read_4) - BUS_ACCESS_ADDR(ebx,edx) - movl (%edx),%eax - ret - -/* - * write_N - */ -ENTRY(SBUS_RA_mem_space_write_1) - BUS_ACCESS_ADDR(ebx,edx) - movb %al,(%edx) - ret - -ENTRY(SBUS_RA_mem_space_write_2) - BUS_ACCESS_ADDR(ebx,edx) - movw %ax,(%edx) - ret - -ENTRY(SBUS_RA_mem_space_write_4) - BUS_ACCESS_ADDR(ebx,edx) - movl %eax,(%edx) - ret - -/* - * read_multi_N - */ -ENTRY(SBUS_RA_mem_space_read_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - movb (%edx),%al - stosb - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_RA_mem_space_read_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - movw (%edx),%ax - stosw - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_RA_mem_space_read_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - movl (%edx),%eax - stosl - decl %ecx - jnz 1b -2: - popl %eax - ret - -/* - * write_multi_N - */ -ENTRY(SBUS_RA_mem_space_write_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsb - movb %al,(%edx) - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_RA_mem_space_write_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsw - movw %ax,(%edx) - decl %ecx - jnz 1b -2: - popl %eax - ret - -ENTRY(SBUS_RA_mem_space_write_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - cld - pushl %eax - orl %ecx,%ecx - jz 2f -1: - lodsl - movl %eax,(%edx) - decl %ecx - jnz 1b -2: - popl %eax - ret - -/* - * read_region_N - */ -ENTRY(SBUS_RA_mem_space_read_region_1) - cld - pushl %esi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,esi) - movsb - incl %edx - decl %ecx - jnz 1b -2: - popl %esi - ret - -ENTRY(SBUS_RA_mem_space_read_region_2) - cld - pushl %esi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,esi) - movsw - addl $2,%edx - decl %ecx - jnz 1b -2: - popl %esi - ret - -ENTRY(SBUS_RA_mem_space_read_region_4) - cld - pushl %esi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,esi) - movsl - addl $4,%edx - decl %ecx - jnz 1b -2: - popl %esi - ret - -/* - * write_region_N - */ -ENTRY(SBUS_RA_mem_space_write_region_1) - cld - pushl %edi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,edi) - movsb - incl %edx - decl %ecx - jnz 1b -2: - popl %edi - ret - -ENTRY(SBUS_RA_mem_space_write_region_2) - cld - pushl %edi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,edi) - movsw - addl $2,%edx - decl %ecx - jnz 1b -2: - popl %edi - ret - -ENTRY(SBUS_RA_mem_space_write_region_4) - cld - pushl %edi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,edi) - movsl - addl $4,%edx - decl %ecx - jnz 1b -2: - popl %edi - ret - -/* - * set_multi_N - */ -ENTRY(SBUS_RA_mem_space_set_multi_1) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - movb %al,(%edx) - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_RA_mem_space_set_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - movw %ax,(%edx) - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_RA_mem_space_set_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - orl %ecx,%ecx - jz 2f -1: - movl %eax,(%edx) - decl %ecx - jnz 1b -2: - ret - -/* - * set_region_N - */ -ENTRY(SBUS_RA_mem_space_set_region_1) - cld - pushl %edi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,edi) - stosb - incl %edx - decl %ecx - jnz 1b -2: - popl %edi - ret - -ENTRY(SBUS_RA_mem_space_set_region_2) - cld - pushl %edi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,edi) - stosw - addl $2,%edx - decl %ecx - jnz 1b -2: - popl %edi - ret - -ENTRY(SBUS_RA_mem_space_set_region_4) - cld - pushl %edi - orl %ecx,%ecx - jz 2f -1: - BUS_ACCESS_ADDR2(ebx,edx,edi) - stosl - addl $4,%edx - decl %ecx - jnz 1b -2: - popl %edi - ret - -/* - * copy_region_N - */ -ENTRY(SBUS_RA_mem_space_copy_region_1) - cld - orl %ecx,%ecx - jz 2f -1: - pushl %esi - pushl %edi - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - movsb - popl %edi - popl %esi - incl %esi - incl %edi - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_RA_mem_space_copy_region_2) - cld - orl %ecx,%ecx - jz 2f -1: - pushl %esi - pushl %edi - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - movsw - popl %edi - popl %esi - addl $2,%esi - addl $2,%edi - decl %ecx - jnz 1b -2: - ret - -ENTRY(SBUS_RA_mem_space_copy_region_4) - cld - orl %ecx,%ecx - jz 2f -1: - pushl %esi - pushl %edi - BUS_ACCESS_ADDR(eax,esi) - BUS_ACCESS_ADDR(ebx,edi) - movsl - popl %edi - popl %esi - addl $4,%esi - addl $4,%edi - decl %ecx - jnz 1b -2: - ret - -#undef BUS_ACCESS_ADDR -#undef BUS_ACCESS_ADDR2 - - -#include "opt_mecia.h" -#ifdef DEV_MECIA - -/*********************************************************** - * NEPC pcmcia 16 bits bus access - ***********************************************************/ -#define NEPC_SWITCH_BUS16 \ - pushl %ebp ;\ - pushl %eax ;\ - pushl %edx ;\ - movl $0x2a8e,%edx ;\ - inb %dx,%al ;\ - movl %eax,%ebp ;\ - andl $~0x20,%eax ;\ - outb %al,%dx ;\ - popl %edx ;\ - popl %eax - -#define NEPC_BUS_RESTORE \ - pushl %eax ;\ - movl %ebp,%eax ;\ - xchgl %edx,%ebp ;\ - movl $0x2a8e,%edx ;\ - outb %al,%dx ;\ - xchgl %ebp,%edx ;\ - popl %eax ;\ - popl %ebp - -/*********************************************************** - * NEPC pcmcia 16 bits bus acces (Direct Access) - ***********************************************************/ -#define BUS_ACCESS_ADDR(BSHREG,ADDRREG) \ - addl BUS_SPACE_HANDLE_BASE/**/(%/**/BSHREG/**/),%/**/ADDRREG - -ENTRY(NEPC_DA_io_space_read_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - inw %dx,%ax - NEPC_BUS_RESTORE - ret - - -ENTRY(NEPC_DA_io_space_write_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - outw %ax,%dx - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_read_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - insw - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_write_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - outsw - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_read_region_2) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_read_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_write_region_2) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_write_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_set_multi_2) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_set_multi_2 - NEPC_BUS_RESTORE - ret - - -ENTRY(NEPC_DA_io_space_set_region_2) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_set_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_copy_region_2) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_copy_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_read_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - inl %dx,%eax - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_write_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - outl %eax,%dx - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_read_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - insl - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_write_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - outsl - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_read_region_4) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_read_region_4 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_write_region_4) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_write_region_4 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_set_multi_4) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_set_multi_4 - NEPC_BUS_RESTORE - ret - - -ENTRY(NEPC_DA_io_space_set_region_4) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_set_region_4 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_DA_io_space_copy_region_4) - NEPC_SWITCH_BUS16 - call SBUS_DA_io_space_copy_region_4 - NEPC_BUS_RESTORE - ret - -#undef BUS_ACCESS_ADDR - -/*********************************************************** - * NEPC pcmcia 16 bits bus acces (Relocate Access) - ***********************************************************/ -#define BUS_ACCESS_ADDR(BSHREG,ADDRREG) \ - movl BUS_SPACE_HANDLE_IAT/**/(%/**/BSHREG/**/, %/**/ADDRREG/**/, 4), \ - %/**/ADDRREG - -ENTRY(NEPC_RA_io_space_read_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - inw %dx,%ax - NEPC_BUS_RESTORE - ret - - -ENTRY(NEPC_RA_io_space_write_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - outw %ax,%dx - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_read_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - insw - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_write_multi_2) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - outsw - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_read_region_2) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_read_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_write_region_2) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_write_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_set_multi_2) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_set_multi_2 - NEPC_BUS_RESTORE - ret - - -ENTRY(NEPC_RA_io_space_set_region_2) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_set_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_copy_region_2) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_copy_region_2 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_read_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - inl %dx,%eax - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_write_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - outl %eax,%dx - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_read_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - insl - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_write_multi_4) - BUS_ACCESS_ADDR(ebx,edx) - NEPC_SWITCH_BUS16 - cld - rep - outsl - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_read_region_4) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_read_region_4 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_write_region_4) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_write_region_4 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_set_multi_4) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_set_multi_4 - NEPC_BUS_RESTORE - ret - - -ENTRY(NEPC_RA_io_space_set_region_4) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_set_region_4 - NEPC_BUS_RESTORE - ret - -ENTRY(NEPC_RA_io_space_copy_region_4) - NEPC_SWITCH_BUS16 - call SBUS_RA_io_space_copy_region_4 - NEPC_BUS_RESTORE - ret - -#endif /* DEV_MECIA */ diff --git a/sys/pc98/i386/busiosubr.c b/sys/pc98/i386/busiosubr.c deleted file mode 100644 index 8776d3f..0000000 --- a/sys/pc98/i386/busiosubr.c +++ /dev/null @@ -1,281 +0,0 @@ -/* $FreeBSD$ */ -/* $NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $ */ -/* $NetBSD$ */ - -/*- - * [NetBSD for NEC PC-98 series] - * Copyright (c) 1996, 1997, 1998 - * NetBSD/pc98 porting staff. All rights reserved. - * - * [Ported for FreeBSD] - * Copyright (c) 2001 - * TAKAHASHI Yoshihiro. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1997, 1998 - * Naofumi HONDA. All rights reserved. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <machine/bus.h> - -static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle"); - -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int8_t,1) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int16_t,2) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int32_t,4) - -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int8_t,1) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int16_t,2) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int32_t,4) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int8_t,1) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2) -_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4) - -struct bus_space_tag SBUS_io_space_tag = { - BUS_SPACE_IO, - - /* direct bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int32_t,4), - }, - - /* relocate bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int32_t,4), - } -}; - -struct bus_space_tag SBUS_mem_space_tag = { - BUS_SPACE_MEM, - - /* direct bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4), - }, - - /* relocate bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4), - } -}; - - -#include "opt_mecia.h" -#ifdef DEV_MECIA - -_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int16_t,2) -_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int32_t,4) - -_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2) -_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4) - -struct bus_space_tag NEPC_io_space_tag = { - BUS_SPACE_IO, - - /* direct bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int32_t,4), - }, - - /* relocate bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int32_t,4), - } -}; - -struct bus_space_tag NEPC_mem_space_tag = { - BUS_SPACE_MEM, - - /* direct bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4), - }, - - /* relocate bus access methods */ - { - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2), - _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4), - } -}; - -#endif /* DEV_MECIA */ - -/************************************************************************* - * map init - *************************************************************************/ -static __inline void -bus_space_iat_init(bus_space_handle_t bsh) -{ - int i; - - for (i = 0; i < bsh->bsh_maxiatsz; i++) - bsh->bsh_iat[i] = bsh->bsh_base + i; -} - -/************************************************************************* - * handle allocation - *************************************************************************/ -int -i386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, - bus_space_handle_t *bshp) -{ - bus_space_handle_t bsh; - - bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE, - M_NOWAIT | M_ZERO); - if (bsh == NULL) - return ENOMEM; - - bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE; - bsh->bsh_iatsz = 0; - bsh->bsh_base = bpa; - bsh->bsh_sz = size; - bsh->bsh_res = NULL; - bsh->bsh_ressz = 0; - bus_space_iat_init(bsh); - - bsh->bsh_bam = t->bs_da; /* default: direct access */ - - *bshp = bsh; - return 0; -} - -void -i386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh, - size_t size) -{ - - free(bsh, M_BUSSPACEHANDLE); -} - -/************************************************************************* - * map - *************************************************************************/ -int -i386_memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, - bus_space_handle_t *bshp) -{ - - return i386_bus_space_handle_alloc(t, bpa, size, bshp); -} - -void -i386_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) -{ - - i386_bus_space_handle_free(t, bsh, bsh->bsh_sz); -} - -void -i386_memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) -{ - - /* i386_memio_unmap() does all that we need to do. */ - i386_memio_unmap(t, bsh, bsh->bsh_sz); -} - -int -i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, - bus_size_t offset, bus_size_t size, - bus_space_handle_t *tbshp) -{ - int i, error = 0; - bus_space_handle_t bsh; - bus_addr_t pbase; - - pbase = pbsh->bsh_base + offset; - switch (t->bs_tag) { - case BUS_SPACE_IO: - if (pbsh->bsh_iatsz > 0) { - if (offset >= pbsh->bsh_iatsz || - offset + size > pbsh->bsh_iatsz) - return EINVAL; - pbase = pbsh->bsh_base; - } - break; - - case BUS_SPACE_MEM: - if (pbsh->bsh_iatsz > 0) - return EINVAL; - if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz) - return EINVAL; - break; - - default: - panic("i386_memio_subregion: bad bus space tag"); - break; - } - - error = i386_bus_space_handle_alloc(t, pbase, size, &bsh); - if (error != 0) - return error; - - switch (t->bs_tag) { - case BUS_SPACE_IO: - if (pbsh->bsh_iatsz > 0) { - for (i = 0; i < size; i ++) - bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset]; - bsh->bsh_iatsz = size; - } else if (pbsh->bsh_base > bsh->bsh_base || - pbsh->bsh_base + pbsh->bsh_sz < - bsh->bsh_base + bsh->bsh_sz) { - i386_bus_space_handle_free(t, bsh, size); - return EINVAL; - } - break; - - case BUS_SPACE_MEM: - break; - } - - if (pbsh->bsh_iatsz > 0) - bsh->bsh_bam = t->bs_ra; /* relocate access */ - *tbshp = bsh; - return error; -} diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c deleted file mode 100644 index ab6c5c9..0000000 --- a/sys/pc98/i386/machdep.c +++ /dev/null @@ -1,2779 +0,0 @@ -/*- - * Copyright (c) 1992 Terrence R. Lambert. - * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_atalk.h" -#include "opt_compat.h" -#include "opt_cpu.h" -#include "opt_ddb.h" -#include "opt_inet.h" -#include "opt_ipx.h" -#include "opt_isa.h" -#include "opt_kstack_pages.h" -#include "opt_maxmem.h" -#include "opt_msgbuf.h" -#include "opt_npx.h" -#include "opt_perfmon.h" - -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/systm.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/bus.h> -#include <sys/callout.h> -#include <sys/cons.h> -#include <sys/cpu.h> -#include <sys/eventhandler.h> -#include <sys/exec.h> -#include <sys/imgact.h> -#include <sys/kdb.h> -#include <sys/kernel.h> -#include <sys/ktr.h> -#include <sys/linker.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/memrange.h> -#include <sys/msgbuf.h> -#include <sys/mutex.h> -#include <sys/pcpu.h> -#include <sys/ptrace.h> -#include <sys/reboot.h> -#include <sys/sched.h> -#include <sys/signalvar.h> -#include <sys/sysctl.h> -#include <sys/sysent.h> -#include <sys/sysproto.h> -#include <sys/ucontext.h> -#include <sys/vmmeter.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> -#include <vm/vm_kern.h> -#include <vm/vm_page.h> -#include <vm/vm_map.h> -#include <vm/vm_object.h> -#include <vm/vm_pager.h> -#include <vm/vm_param.h> - -#ifdef DDB -#ifndef KDB -#error KDB must be enabled in order for DDB to work! -#endif -#include <ddb/ddb.h> -#include <ddb/db_sym.h> -#endif - -#include <pc98/pc98/pc98_machdep.h> -#include <pc98/pc98/pc98.h> - -#include <net/netisr.h> - -#include <machine/bootinfo.h> -#include <machine/clock.h> -#include <machine/cpu.h> -#include <machine/cputypes.h> -#include <machine/intr_machdep.h> -#include <machine/md_var.h> -#include <machine/pc/bios.h> -#include <machine/pcb.h> -#include <machine/pcb_ext.h> -#include <machine/proc.h> -#include <machine/reg.h> -#include <machine/sigframe.h> -#include <machine/specialreg.h> -#include <machine/vm86.h> -#ifdef PERFMON -#include <machine/perfmon.h> -#endif -#ifdef SMP -#include <machine/privatespace.h> -#include <machine/smp.h> -#endif - -#ifdef DEV_ISA -#include <i386/isa/icu.h> -#endif - -/* Sanity check for __curthread() */ -CTASSERT(offsetof(struct pcpu, pc_curthread) == 0); - -extern void init386(int first); -extern void dblfault_handler(void); - -extern void printcpuinfo(void); /* XXX header file */ -extern void finishidentcpu(void); -extern void panicifcpuunsupported(void); -extern void initializecpu(void); - -#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) -#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) - -#if !defined(CPU_ENABLE_SSE) && defined(I686_CPU) -#define CPU_ENABLE_SSE -#endif -#if defined(CPU_DISABLE_SSE) -#undef CPU_ENABLE_SSE -#endif - -static void cpu_startup(void *); -static void fpstate_drop(struct thread *td); -static void get_fpcontext(struct thread *td, mcontext_t *mcp); -static int set_fpcontext(struct thread *td, const mcontext_t *mcp); -#ifdef CPU_ENABLE_SSE -static void set_fpregs_xmm(struct save87 *, struct savexmm *); -static void fill_fpregs_xmm(struct savexmm *, struct save87 *); -#endif /* CPU_ENABLE_SSE */ -SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) - -int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */ -int need_post_dma_flush; /* If 1, use invd after DMA transfer. */ - -#ifdef DDB -extern vm_offset_t ksym_start, ksym_end; -#endif - -int _udatasel, _ucodesel; -u_int basemem; - -static int ispc98 = 1; -SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, ""); - -int cold = 1; - -#ifdef COMPAT_43 -static void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); -#endif -#ifdef COMPAT_FREEBSD4 -static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, - u_long code); -#endif - -long Maxmem = 0; -long realmem = 0; - -vm_paddr_t phys_avail[10]; - -/* must be 2 less so 0 0 can signal end of chunks */ -#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) - -struct kva_md_info kmi; - -static struct trapframe proc0_tf; -#ifndef SMP -static struct pcpu __pcpu; -#endif - -struct mtx icu_lock; - -struct mem_range_softc mem_range_softc; - -static void -cpu_startup(dummy) - void *dummy; -{ - /* - * Good {morning,afternoon,evening,night}. - */ - startrtclock(); - printcpuinfo(); - panicifcpuunsupported(); -#ifdef PERFMON - perfmon_init(); -#endif - printf("real memory = %ju (%ju MB)\n", ptoa((uintmax_t)Maxmem), - ptoa((uintmax_t)Maxmem) / 1048576); - realmem = Maxmem; - /* - * Display any holes after the first chunk of extended memory. - */ - if (bootverbose) { - int indx; - - printf("Physical memory chunk(s):\n"); - for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { - vm_paddr_t size; - - size = phys_avail[indx + 1] - phys_avail[indx]; - printf( - "0x%016jx - 0x%016jx, %ju bytes (%ju pages)\n", - (uintmax_t)phys_avail[indx], - (uintmax_t)phys_avail[indx + 1] - 1, - (uintmax_t)size, (uintmax_t)size / PAGE_SIZE); - } - } - - vm_ksubmap_init(&kmi); - - printf("avail memory = %ju (%ju MB)\n", - ptoa((uintmax_t)cnt.v_free_count), - ptoa((uintmax_t)cnt.v_free_count) / 1048576); - - /* - * Set up buffers, so they can be used to read disk labels. - */ - bufinit(); - vm_pager_bufferinit(); - - cpu_setregs(); -} - -/* - * Send an interrupt to process. - * - * Stack is set up to allow sigcode stored - * at top to call routine, followed by kcall - * to sigreturn routine below. After sigreturn - * resets the signal mask, the stack, and the - * frame pointer, it returns to the user - * specified pc, psl. - */ -#ifdef COMPAT_43 -static void -osendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; -{ - struct osigframe sf, *fp; - struct proc *p; - struct thread *td; - struct sigacts *psp; - struct trapframe *regs; - int oonstack; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - psp = p->p_sigacts; - mtx_assert(&psp->ps_mtx, MA_OWNED); - regs = td->td_frame; - oonstack = sigonstack(regs->tf_esp); - - /* Allocate space for the signal handler context. */ - if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && - SIGISMEMBER(psp->ps_sigonstack, sig)) { - fp = (struct osigframe *)(td->td_sigstk.ss_sp + - td->td_sigstk.ss_size - sizeof(struct osigframe)); -#if defined(COMPAT_43) - td->td_sigstk.ss_flags |= SS_ONSTACK; -#endif - } else - fp = (struct osigframe *)regs->tf_esp - 1; - - /* Translate the signal if appropriate. */ - if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) - sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; - - /* Build the argument list for the signal handler. */ - sf.sf_signum = sig; - sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; - if (SIGISMEMBER(psp->ps_siginfo, sig)) { - /* Signal handler installed with SA_SIGINFO. */ - sf.sf_arg2 = (register_t)&fp->sf_siginfo; - sf.sf_siginfo.si_signo = sig; - sf.sf_siginfo.si_code = code; - sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher; - } else { - /* Old FreeBSD-style arguments. */ - sf.sf_arg2 = code; - sf.sf_addr = regs->tf_err; - sf.sf_ahu.sf_handler = catcher; - } - mtx_unlock(&psp->ps_mtx); - PROC_UNLOCK(p); - - /* Save most if not all of trap frame. */ - sf.sf_siginfo.si_sc.sc_eax = regs->tf_eax; - sf.sf_siginfo.si_sc.sc_ebx = regs->tf_ebx; - sf.sf_siginfo.si_sc.sc_ecx = regs->tf_ecx; - sf.sf_siginfo.si_sc.sc_edx = regs->tf_edx; - sf.sf_siginfo.si_sc.sc_esi = regs->tf_esi; - sf.sf_siginfo.si_sc.sc_edi = regs->tf_edi; - sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs; - sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds; - sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss; - sf.sf_siginfo.si_sc.sc_es = regs->tf_es; - sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs; - sf.sf_siginfo.si_sc.sc_gs = rgs(); - sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp; - - /* Build the signal context to be used by osigreturn(). */ - sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0; - SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask); - sf.sf_siginfo.si_sc.sc_sp = regs->tf_esp; - sf.sf_siginfo.si_sc.sc_fp = regs->tf_ebp; - sf.sf_siginfo.si_sc.sc_pc = regs->tf_eip; - sf.sf_siginfo.si_sc.sc_ps = regs->tf_eflags; - sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno; - sf.sf_siginfo.si_sc.sc_err = regs->tf_err; - - /* - * If we're a vm86 process, we want to save the segment registers. - * We also change eflags to be our emulated eflags, not the actual - * eflags. - */ - if (regs->tf_eflags & PSL_VM) { - /* XXX confusing names: `tf' isn't a trapframe; `regs' is. */ - struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; - struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; - - sf.sf_siginfo.si_sc.sc_gs = tf->tf_vm86_gs; - sf.sf_siginfo.si_sc.sc_fs = tf->tf_vm86_fs; - sf.sf_siginfo.si_sc.sc_es = tf->tf_vm86_es; - sf.sf_siginfo.si_sc.sc_ds = tf->tf_vm86_ds; - - if (vm86->vm86_has_vme == 0) - sf.sf_siginfo.si_sc.sc_ps = - (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | - (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); - - /* See sendsig() for comments. */ - tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); - } - - /* - * Copy the sigframe out to the user's stack. - */ - if (copyout(&sf, fp, sizeof(*fp)) != 0) { -#ifdef DEBUG - printf("process %ld has trashed its stack\n", (long)p->p_pid); -#endif - PROC_LOCK(p); - sigexit(td, SIGILL); - } - - regs->tf_esp = (int)fp; - regs->tf_eip = PS_STRINGS - szosigcode; - regs->tf_eflags &= ~PSL_T; - regs->tf_cs = _ucodesel; - regs->tf_ds = _udatasel; - regs->tf_es = _udatasel; - regs->tf_fs = _udatasel; - load_gs(_udatasel); - regs->tf_ss = _udatasel; - PROC_LOCK(p); - mtx_lock(&psp->ps_mtx); -} -#endif /* COMPAT_43 */ - -#ifdef COMPAT_FREEBSD4 -static void -freebsd4_sendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; -{ - struct sigframe4 sf, *sfp; - struct proc *p; - struct thread *td; - struct sigacts *psp; - struct trapframe *regs; - int oonstack; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - psp = p->p_sigacts; - mtx_assert(&psp->ps_mtx, MA_OWNED); - regs = td->td_frame; - oonstack = sigonstack(regs->tf_esp); - - /* Save user context. */ - bzero(&sf, sizeof(sf)); - sf.sf_uc.uc_sigmask = *mask; - sf.sf_uc.uc_stack = td->td_sigstk; - sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) - ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; - sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; - sf.sf_uc.uc_mcontext.mc_gs = rgs(); - bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs)); - - /* Allocate space for the signal handler context. */ - if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && - SIGISMEMBER(psp->ps_sigonstack, sig)) { - sfp = (struct sigframe4 *)(td->td_sigstk.ss_sp + - td->td_sigstk.ss_size - sizeof(struct sigframe4)); -#if defined(COMPAT_43) - td->td_sigstk.ss_flags |= SS_ONSTACK; -#endif - } else - sfp = (struct sigframe4 *)regs->tf_esp - 1; - - /* Translate the signal if appropriate. */ - if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) - sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; - - /* Build the argument list for the signal handler. */ - sf.sf_signum = sig; - sf.sf_ucontext = (register_t)&sfp->sf_uc; - if (SIGISMEMBER(psp->ps_siginfo, sig)) { - /* Signal handler installed with SA_SIGINFO. */ - sf.sf_siginfo = (register_t)&sfp->sf_si; - sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; - - /* Fill in POSIX parts */ - sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void *)regs->tf_err; - } else { - /* Old FreeBSD-style arguments. */ - sf.sf_siginfo = code; - sf.sf_addr = regs->tf_err; - sf.sf_ahu.sf_handler = catcher; - } - mtx_unlock(&psp->ps_mtx); - PROC_UNLOCK(p); - - /* - * If we're a vm86 process, we want to save the segment registers. - * We also change eflags to be our emulated eflags, not the actual - * eflags. - */ - if (regs->tf_eflags & PSL_VM) { - struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; - struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; - - sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; - sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; - sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; - sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; - - if (vm86->vm86_has_vme == 0) - sf.sf_uc.uc_mcontext.mc_eflags = - (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | - (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); - - /* - * Clear PSL_NT to inhibit T_TSSFLT faults on return from - * syscalls made by the signal handler. This just avoids - * wasting time for our lazy fixup of such faults. PSL_NT - * does nothing in vm86 mode, but vm86 programs can set it - * almost legitimately in probes for old cpu types. - */ - tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); - } - - /* - * Copy the sigframe out to the user's stack. - */ - if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { -#ifdef DEBUG - printf("process %ld has trashed its stack\n", (long)p->p_pid); -#endif - PROC_LOCK(p); - sigexit(td, SIGILL); - } - - regs->tf_esp = (int)sfp; - regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode; - regs->tf_eflags &= ~PSL_T; - regs->tf_cs = _ucodesel; - regs->tf_ds = _udatasel; - regs->tf_es = _udatasel; - regs->tf_fs = _udatasel; - regs->tf_ss = _udatasel; - PROC_LOCK(p); - mtx_lock(&psp->ps_mtx); -} -#endif /* COMPAT_FREEBSD4 */ - -void -sendsig(catcher, sig, mask, code) - sig_t catcher; - int sig; - sigset_t *mask; - u_long code; -{ - struct sigframe sf, *sfp; - struct proc *p; - struct thread *td; - struct sigacts *psp; - char *sp; - struct trapframe *regs; - int oonstack; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - psp = p->p_sigacts; - mtx_assert(&psp->ps_mtx, MA_OWNED); -#ifdef COMPAT_FREEBSD4 - if (SIGISMEMBER(psp->ps_freebsd4, sig)) { - freebsd4_sendsig(catcher, sig, mask, code); - return; - } -#endif -#ifdef COMPAT_43 - if (SIGISMEMBER(psp->ps_osigset, sig)) { - osendsig(catcher, sig, mask, code); - return; - } -#endif - regs = td->td_frame; - oonstack = sigonstack(regs->tf_esp); - - /* Save user context. */ - bzero(&sf, sizeof(sf)); - sf.sf_uc.uc_sigmask = *mask; - sf.sf_uc.uc_stack = td->td_sigstk; - sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) - ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; - sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; - sf.sf_uc.uc_mcontext.mc_gs = rgs(); - bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs)); - sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ - get_fpcontext(td, &sf.sf_uc.uc_mcontext); - fpstate_drop(td); - - /* Allocate space for the signal handler context. */ - if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && - SIGISMEMBER(psp->ps_sigonstack, sig)) { - sp = td->td_sigstk.ss_sp + - td->td_sigstk.ss_size - sizeof(struct sigframe); -#if defined(COMPAT_43) - td->td_sigstk.ss_flags |= SS_ONSTACK; -#endif - } else - sp = (char *)regs->tf_esp - sizeof(struct sigframe); - /* Align to 16 bytes. */ - sfp = (struct sigframe *)((unsigned int)sp & ~0xF); - - /* Translate the signal if appropriate. */ - if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) - sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; - - /* Build the argument list for the signal handler. */ - sf.sf_signum = sig; - sf.sf_ucontext = (register_t)&sfp->sf_uc; - if (SIGISMEMBER(psp->ps_siginfo, sig)) { - /* Signal handler installed with SA_SIGINFO. */ - sf.sf_siginfo = (register_t)&sfp->sf_si; - sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; - - /* Fill in POSIX parts */ - sf.sf_si.si_signo = sig; - sf.sf_si.si_code = code; - sf.sf_si.si_addr = (void *)regs->tf_err; - } else { - /* Old FreeBSD-style arguments. */ - sf.sf_siginfo = code; - sf.sf_addr = regs->tf_err; - sf.sf_ahu.sf_handler = catcher; - } - mtx_unlock(&psp->ps_mtx); - PROC_UNLOCK(p); - - /* - * If we're a vm86 process, we want to save the segment registers. - * We also change eflags to be our emulated eflags, not the actual - * eflags. - */ - if (regs->tf_eflags & PSL_VM) { - struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; - struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; - - sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; - sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; - sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; - sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; - - if (vm86->vm86_has_vme == 0) - sf.sf_uc.uc_mcontext.mc_eflags = - (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | - (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); - - /* - * Clear PSL_NT to inhibit T_TSSFLT faults on return from - * syscalls made by the signal handler. This just avoids - * wasting time for our lazy fixup of such faults. PSL_NT - * does nothing in vm86 mode, but vm86 programs can set it - * almost legitimately in probes for old cpu types. - */ - tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); - } - - /* - * Copy the sigframe out to the user's stack. - */ - if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { -#ifdef DEBUG - printf("process %ld has trashed its stack\n", (long)p->p_pid); -#endif - PROC_LOCK(p); - sigexit(td, SIGILL); - } - - regs->tf_esp = (int)sfp; - regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); - regs->tf_eflags &= ~PSL_T; - regs->tf_cs = _ucodesel; - regs->tf_ds = _udatasel; - regs->tf_es = _udatasel; - regs->tf_fs = _udatasel; - regs->tf_ss = _udatasel; - PROC_LOCK(p); - mtx_lock(&psp->ps_mtx); -} - -/* - * Build siginfo_t for SA thread - */ -void -cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) -{ - struct proc *p; - struct thread *td; - - td = curthread; - p = td->td_proc; - PROC_LOCK_ASSERT(p, MA_OWNED); - - bzero(si, sizeof(*si)); - si->si_signo = sig; - si->si_code = code; - si->si_addr = (void *)td->td_frame->tf_err; - /* XXXKSE fill other fields */ -} - -/* - * System call to cleanup state after a signal - * has been taken. Reset signal mask and - * stack state from context left by sendsig (above). - * Return to previous pc and psl as specified by - * context left by sendsig. Check carefully to - * make sure that the user has not modified the - * state to gain improper privileges. - * - * MPSAFE - */ -#ifdef COMPAT_43 -int -osigreturn(td, uap) - struct thread *td; - struct osigreturn_args /* { - struct osigcontext *sigcntxp; - } */ *uap; -{ - struct osigcontext sc; - struct trapframe *regs; - struct osigcontext *scp; - struct proc *p = td->td_proc; - int eflags, error; - - regs = td->td_frame; - error = copyin(uap->sigcntxp, &sc, sizeof(sc)); - if (error != 0) - return (error); - scp = ≻ - eflags = scp->sc_ps; - if (eflags & PSL_VM) { - struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; - struct vm86_kernel *vm86; - - /* - * if pcb_ext == 0 or vm86_inited == 0, the user hasn't - * set up the vm86 area, and we can't enter vm86 mode. - */ - if (td->td_pcb->pcb_ext == 0) - return (EINVAL); - vm86 = &td->td_pcb->pcb_ext->ext_vm86; - if (vm86->vm86_inited == 0) - return (EINVAL); - - /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); - - if (vm86->vm86_has_vme) { - eflags = (tf->tf_eflags & ~VME_USERCHANGE) | - (eflags & VME_USERCHANGE) | PSL_VM; - } else { - vm86->vm86_eflags = eflags; /* save VIF, VIP */ - eflags = (tf->tf_eflags & ~VM_USERCHANGE) | - (eflags & VM_USERCHANGE) | PSL_VM; - } - tf->tf_vm86_ds = scp->sc_ds; - tf->tf_vm86_es = scp->sc_es; - tf->tf_vm86_fs = scp->sc_fs; - tf->tf_vm86_gs = scp->sc_gs; - tf->tf_ds = _udatasel; - tf->tf_es = _udatasel; - tf->tf_fs = _udatasel; - } else { - /* - * Don't allow users to change privileged or reserved flags. - */ - /* - * XXX do allow users to change the privileged flag PSL_RF. - * The cpu sets PSL_RF in tf_eflags for faults. Debuggers - * should sometimes set it there too. tf_eflags is kept in - * the signal context during signal handling and there is no - * other place to remember it, so the PSL_RF bit may be - * corrupted by the signal handler without us knowing. - * Corruption of the PSL_RF bit at worst causes one more or - * one less debugger trap, so allowing it is fairly harmless. - */ - if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { - return (EINVAL); - } - - /* - * Don't allow users to load a valid privileged %cs. Let the - * hardware check for invalid selectors, excess privilege in - * other selectors, invalid %eip's and invalid %esp's. - */ - if (!CS_SECURE(scp->sc_cs)) { - trapsignal(td, SIGBUS, T_PROTFLT); - return (EINVAL); - } - regs->tf_ds = scp->sc_ds; - regs->tf_es = scp->sc_es; - regs->tf_fs = scp->sc_fs; - } - - /* Restore remaining registers. */ - regs->tf_eax = scp->sc_eax; - regs->tf_ebx = scp->sc_ebx; - regs->tf_ecx = scp->sc_ecx; - regs->tf_edx = scp->sc_edx; - regs->tf_esi = scp->sc_esi; - regs->tf_edi = scp->sc_edi; - regs->tf_cs = scp->sc_cs; - regs->tf_ss = scp->sc_ss; - regs->tf_isp = scp->sc_isp; - regs->tf_ebp = scp->sc_fp; - regs->tf_esp = scp->sc_sp; - regs->tf_eip = scp->sc_pc; - regs->tf_eflags = eflags; - - PROC_LOCK(p); -#if defined(COMPAT_43) - if (scp->sc_onstack & 1) - td->td_sigstk.ss_flags |= SS_ONSTACK; - else - td->td_sigstk.ss_flags &= ~SS_ONSTACK; -#endif - SIGSETOLD(td->td_sigmask, scp->sc_mask); - SIG_CANTMASK(td->td_sigmask); - signotify(td); - PROC_UNLOCK(p); - return (EJUSTRETURN); -} -#endif /* COMPAT_43 */ - -#ifdef COMPAT_FREEBSD4 -/* - * MPSAFE - */ -int -freebsd4_sigreturn(td, uap) - struct thread *td; - struct freebsd4_sigreturn_args /* { - const ucontext4 *sigcntxp; - } */ *uap; -{ - struct ucontext4 uc; - struct proc *p = td->td_proc; - struct trapframe *regs; - const struct ucontext4 *ucp; - int cs, eflags, error; - - error = copyin(uap->sigcntxp, &uc, sizeof(uc)); - if (error != 0) - return (error); - ucp = &uc; - regs = td->td_frame; - eflags = ucp->uc_mcontext.mc_eflags; - if (eflags & PSL_VM) { - struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; - struct vm86_kernel *vm86; - - /* - * if pcb_ext == 0 or vm86_inited == 0, the user hasn't - * set up the vm86 area, and we can't enter vm86 mode. - */ - if (td->td_pcb->pcb_ext == 0) - return (EINVAL); - vm86 = &td->td_pcb->pcb_ext->ext_vm86; - if (vm86->vm86_inited == 0) - return (EINVAL); - - /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); - - if (vm86->vm86_has_vme) { - eflags = (tf->tf_eflags & ~VME_USERCHANGE) | - (eflags & VME_USERCHANGE) | PSL_VM; - } else { - vm86->vm86_eflags = eflags; /* save VIF, VIP */ - eflags = (tf->tf_eflags & ~VM_USERCHANGE) | - (eflags & VM_USERCHANGE) | PSL_VM; - } - bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe)); - tf->tf_eflags = eflags; - tf->tf_vm86_ds = tf->tf_ds; - tf->tf_vm86_es = tf->tf_es; - tf->tf_vm86_fs = tf->tf_fs; - tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs; - tf->tf_ds = _udatasel; - tf->tf_es = _udatasel; - tf->tf_fs = _udatasel; - } else { - /* - * Don't allow users to change privileged or reserved flags. - */ - /* - * XXX do allow users to change the privileged flag PSL_RF. - * The cpu sets PSL_RF in tf_eflags for faults. Debuggers - * should sometimes set it there too. tf_eflags is kept in - * the signal context during signal handling and there is no - * other place to remember it, so the PSL_RF bit may be - * corrupted by the signal handler without us knowing. - * Corruption of the PSL_RF bit at worst causes one more or - * one less debugger trap, so allowing it is fairly harmless. - */ - if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { - printf("freebsd4_sigreturn: eflags = 0x%x\n", eflags); - return (EINVAL); - } - - /* - * Don't allow users to load a valid privileged %cs. Let the - * hardware check for invalid selectors, excess privilege in - * other selectors, invalid %eip's and invalid %esp's. - */ - cs = ucp->uc_mcontext.mc_cs; - if (!CS_SECURE(cs)) { - printf("freebsd4_sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); - return (EINVAL); - } - - bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs)); - } - - PROC_LOCK(p); -#if defined(COMPAT_43) - if (ucp->uc_mcontext.mc_onstack & 1) - td->td_sigstk.ss_flags |= SS_ONSTACK; - else - td->td_sigstk.ss_flags &= ~SS_ONSTACK; -#endif - - td->td_sigmask = ucp->uc_sigmask; - SIG_CANTMASK(td->td_sigmask); - signotify(td); - PROC_UNLOCK(p); - return (EJUSTRETURN); -} -#endif /* COMPAT_FREEBSD4 */ - -/* - * MPSAFE - */ -int -sigreturn(td, uap) - struct thread *td; - struct sigreturn_args /* { - const __ucontext *sigcntxp; - } */ *uap; -{ - ucontext_t uc; - struct proc *p = td->td_proc; - struct trapframe *regs; - const ucontext_t *ucp; - int cs, eflags, error, ret; - - error = copyin(uap->sigcntxp, &uc, sizeof(uc)); - if (error != 0) - return (error); - ucp = &uc; - regs = td->td_frame; - eflags = ucp->uc_mcontext.mc_eflags; - if (eflags & PSL_VM) { - struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; - struct vm86_kernel *vm86; - - /* - * if pcb_ext == 0 or vm86_inited == 0, the user hasn't - * set up the vm86 area, and we can't enter vm86 mode. - */ - if (td->td_pcb->pcb_ext == 0) - return (EINVAL); - vm86 = &td->td_pcb->pcb_ext->ext_vm86; - if (vm86->vm86_inited == 0) - return (EINVAL); - - /* Go back to user mode if both flags are set. */ - if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) - trapsignal(td, SIGBUS, 0); - - if (vm86->vm86_has_vme) { - eflags = (tf->tf_eflags & ~VME_USERCHANGE) | - (eflags & VME_USERCHANGE) | PSL_VM; - } else { - vm86->vm86_eflags = eflags; /* save VIF, VIP */ - eflags = (tf->tf_eflags & ~VM_USERCHANGE) | - (eflags & VM_USERCHANGE) | PSL_VM; - } - bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe)); - tf->tf_eflags = eflags; - tf->tf_vm86_ds = tf->tf_ds; - tf->tf_vm86_es = tf->tf_es; - tf->tf_vm86_fs = tf->tf_fs; - tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs; - tf->tf_ds = _udatasel; - tf->tf_es = _udatasel; - tf->tf_fs = _udatasel; - } else { - /* - * Don't allow users to change privileged or reserved flags. - */ - /* - * XXX do allow users to change the privileged flag PSL_RF. - * The cpu sets PSL_RF in tf_eflags for faults. Debuggers - * should sometimes set it there too. tf_eflags is kept in - * the signal context during signal handling and there is no - * other place to remember it, so the PSL_RF bit may be - * corrupted by the signal handler without us knowing. - * Corruption of the PSL_RF bit at worst causes one more or - * one less debugger trap, so allowing it is fairly harmless. - */ - if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { - printf("sigreturn: eflags = 0x%x\n", eflags); - return (EINVAL); - } - - /* - * Don't allow users to load a valid privileged %cs. Let the - * hardware check for invalid selectors, excess privilege in - * other selectors, invalid %eip's and invalid %esp's. - */ - cs = ucp->uc_mcontext.mc_cs; - if (!CS_SECURE(cs)) { - printf("sigreturn: cs = 0x%x\n", cs); - trapsignal(td, SIGBUS, T_PROTFLT); - return (EINVAL); - } - - ret = set_fpcontext(td, &ucp->uc_mcontext); - if (ret != 0) - return (ret); - bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs)); - } - - PROC_LOCK(p); -#if defined(COMPAT_43) - if (ucp->uc_mcontext.mc_onstack & 1) - td->td_sigstk.ss_flags |= SS_ONSTACK; - else - td->td_sigstk.ss_flags &= ~SS_ONSTACK; -#endif - - td->td_sigmask = ucp->uc_sigmask; - SIG_CANTMASK(td->td_sigmask); - signotify(td); - PROC_UNLOCK(p); - return (EJUSTRETURN); -} - -/* - * Machine dependent boot() routine - * - * I haven't seen anything to put here yet - * Possibly some stuff might be grafted back here from boot() - */ -void -cpu_boot(int howto) -{ -} - -/* Get current clock frequency for the given cpu id. */ -int -cpu_est_clockrate(int cpu_id, uint64_t *rate) -{ - register_t reg; - uint64_t tsc1, tsc2; - - if (pcpu_find(cpu_id) == NULL || rate == NULL) - return (EINVAL); - if (!tsc_present) - return (EOPNOTSUPP); - - /* If we're booting, trust the rate calibrated moments ago. */ - if (cold) { - *rate = tsc_freq; - return (0); - } - -#ifdef SMP - /* Schedule ourselves on the indicated cpu. */ - mtx_lock_spin(&sched_lock); - sched_bind(curthread, cpu_id); - mtx_unlock_spin(&sched_lock); -#endif - - /* Calibrate by measuring a short delay. */ - reg = intr_disable(); - tsc1 = rdtsc(); - DELAY(1000); - tsc2 = rdtsc(); - intr_restore(reg); - -#ifdef SMP - mtx_lock_spin(&sched_lock); - sched_unbind(curthread); - mtx_unlock_spin(&sched_lock); -#endif - - /* - * Calculate the difference in readings, convert to Mhz, and - * subtract 0.5% of the total. Empirical testing has shown that - * overhead in DELAY() works out to approximately this value. - */ - tsc2 -= tsc1; - *rate = tsc2 * 1000 - tsc2 * 5; - return (0); -} - -/* - * Shutdown the CPU as much as possible - */ -void -cpu_halt(void) -{ - for (;;) - __asm__ ("hlt"); -} - -/* - * Hook to idle the CPU when possible. In the SMP case we default to - * off because a halted cpu will not currently pick up a new thread in the - * run queue until the next timer tick. If turned on this will result in - * approximately a 4.2% loss in real time performance in buildworld tests - * (but improves user and sys times oddly enough), and saves approximately - * 5% in power consumption on an idle machine (tests w/2xCPU 1.1GHz P3). - * - * XXX we need to have a cpu mask of idle cpus and generate an IPI or - * otherwise generate some sort of interrupt to wake up cpus sitting in HLT. - * Then we can have our cake and eat it too. - * - * XXX I'm turning it on for SMP as well by default for now. It seems to - * help lock contention somewhat, and this is critical for HTT. -Peter - */ -static int cpu_idle_hlt = 1; -SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_hlt, CTLFLAG_RW, - &cpu_idle_hlt, 0, "Idle loop HLT enable"); - -static void -cpu_idle_default(void) -{ - /* - * we must absolutely guarentee that hlt is the - * absolute next instruction after sti or we - * introduce a timing window. - */ - __asm __volatile("sti; hlt"); -} - -/* - * Note that we have to be careful here to avoid a race between checking - * sched_runnable() and actually halting. If we don't do this, we may waste - * the time between calling hlt and the next interrupt even though there - * is a runnable process. - */ -void -cpu_idle(void) -{ - -#ifdef SMP - if (mp_grab_cpu_hlt()) - return; -#endif - - if (cpu_idle_hlt) { - disable_intr(); - if (sched_runnable()) - enable_intr(); - else - (*cpu_idle_hook)(); - } -} - -/* Other subsystems (e.g., ACPI) can hook this later. */ -void (*cpu_idle_hook)(void) = cpu_idle_default; - -/* - * Clear registers on exec - */ -void -exec_setregs(td, entry, stack, ps_strings) - struct thread *td; - u_long entry; - u_long stack; - u_long ps_strings; -{ - struct trapframe *regs = td->td_frame; - struct pcb *pcb = td->td_pcb; - - /* Reset pc->pcb_gs and %gs before possibly invalidating it. */ - pcb->pcb_gs = _udatasel; - load_gs(_udatasel); - - if (td->td_proc->p_md.md_ldt) - user_ldt_free(td); - - bzero((char *)regs, sizeof(struct trapframe)); - regs->tf_eip = entry; - regs->tf_esp = stack; - regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T); - regs->tf_ss = _udatasel; - regs->tf_ds = _udatasel; - regs->tf_es = _udatasel; - regs->tf_fs = _udatasel; - regs->tf_cs = _ucodesel; - - /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ - regs->tf_ebx = ps_strings; - - /* - * Reset the hardware debug registers if they were in use. - * They won't have any meaning for the newly exec'd process. - */ - if (pcb->pcb_flags & PCB_DBREGS) { - pcb->pcb_dr0 = 0; - pcb->pcb_dr1 = 0; - pcb->pcb_dr2 = 0; - pcb->pcb_dr3 = 0; - pcb->pcb_dr6 = 0; - pcb->pcb_dr7 = 0; - if (pcb == PCPU_GET(curpcb)) { - /* - * Clear the debug registers on the running - * CPU, otherwise they will end up affecting - * the next process we switch to. - */ - reset_dbregs(); - } - pcb->pcb_flags &= ~PCB_DBREGS; - } - - /* - * Initialize the math emulator (if any) for the current process. - * Actually, just clear the bit that says that the emulator has - * been initialized. Initialization is delayed until the process - * traps to the emulator (if it is done at all) mainly because - * emulators don't provide an entry point for initialization. - */ - td->td_pcb->pcb_flags &= ~FP_SOFTFP; - - /* - * Drop the FP state if we hold it, so that the process gets a - * clean FP state if it uses the FPU again. - */ - fpstate_drop(td); - - /* - * XXX - Linux emulator - * Make sure sure edx is 0x0 on entry. Linux binaries depend - * on it. - */ - td->td_retval[1] = 0; -} - -void -cpu_setregs(void) -{ - unsigned int cr0; - - cr0 = rcr0(); - /* - * CR0_MP, CR0_NE and CR0_TS are also set by npx_probe() for the - * BSP. See the comments there about why we set them. - */ - cr0 |= CR0_MP | CR0_NE | CR0_TS | CR0_WP | CR0_AM; - load_cr0(cr0); - load_gs(_udatasel); -} - -static int -sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS) -{ - int error; - error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, - req); - if (!error && req->newptr) - resettodr(); - return (error); -} - -SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW, - &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", ""); - -SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, - CTLFLAG_RW, &disable_rtc_set, 0, ""); - -SYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, - CTLFLAG_RD, &bootinfo, bootinfo, ""); - -SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock, - CTLFLAG_RW, &wall_cmos_clock, 0, ""); - -u_long bootdev; /* not a struct cdev *- encoding is different */ -SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev, - CTLFLAG_RD, &bootdev, 0, "Maybe the Boot device (not in struct cdev *format)"); - -/* - * Initialize 386 and configure to run kernel - */ - -/* - * Initialize segments & interrupt table - */ - -int _default_ldt; -union descriptor gdt[NGDT * MAXCPU]; /* global descriptor table */ -static struct gate_descriptor idt0[NIDT]; -struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */ -union descriptor ldt[NLDT]; /* local descriptor table */ -struct region_descriptor r_gdt, r_idt; /* table descriptors */ - -int private_tss; /* flag indicating private tss */ - -#if defined(I586_CPU) && !defined(NO_F00F_HACK) -extern int has_f00f_bug; -#endif - -static struct i386tss dblfault_tss; -static char dblfault_stack[PAGE_SIZE]; - -extern vm_offset_t proc0kstack; - - -/* - * software prototypes -- in more palatable form. - * - * GCODE_SEL through GUDATA_SEL must be in this order for syscall/sysret - * GUFS_SEL and GUGS_SEL must be in this order (swtch.s knows it) - */ -struct soft_segment_descriptor gdt_segs[] = { -/* GNULL_SEL 0 Null Descriptor */ -{ 0x0, /* segment base address */ - 0x0, /* length */ - 0, /* segment type */ - 0, /* segment descriptor priority level */ - 0, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, -/* GPRIV_SEL 1 SMP Per-Processor Private Data Descriptor */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMRWA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GUFS_SEL 2 %fs Descriptor for user */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMRWA, /* segment type */ - SEL_UPL, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GUGS_SEL 3 %gs Descriptor for user */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMRWA, /* segment type */ - SEL_UPL, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GCODE_SEL 4 Code Descriptor for kernel */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMERA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GDATA_SEL 5 Data Descriptor for kernel */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMRWA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GUCODE_SEL 6 Code Descriptor for user */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMERA, /* segment type */ - SEL_UPL, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GUDATA_SEL 7 Data Descriptor for user */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMRWA, /* segment type */ - SEL_UPL, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */ -{ 0x400, /* segment base address */ - 0xfffff, /* length */ - SDT_MEMRWA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GPROC0_SEL 9 Proc 0 Tss Descriptor */ -{ - 0x0, /* segment base address */ - sizeof(struct i386tss)-1,/* length */ - SDT_SYS386TSS, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* unused - default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, -/* GLDT_SEL 10 LDT Descriptor */ -{ (int) ldt, /* segment base address */ - sizeof(ldt)-1, /* length - all address space */ - SDT_SYSLDT, /* segment type */ - SEL_UPL, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* unused - default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, -/* GUSERLDT_SEL 11 User LDT Descriptor per process */ -{ (int) ldt, /* segment base address */ - (512 * sizeof(union descriptor)-1), /* length */ - SDT_SYSLDT, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* unused - default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, -/* GPANIC_SEL 12 Panic Tss Descriptor */ -{ (int) &dblfault_tss, /* segment base address */ - sizeof(struct i386tss)-1,/* length - all address space */ - SDT_SYS386TSS, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* unused - default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, -/* GBIOSCODE32_SEL 13 BIOS 32-bit interface (32bit Code) */ -{ 0, /* segment base address (overwritten) */ - 0xfffff, /* length */ - SDT_MEMERA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GBIOSCODE16_SEL 14 BIOS 32-bit interface (16bit Code) */ -{ 0, /* segment base address (overwritten) */ - 0xfffff, /* length */ - SDT_MEMERA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GBIOSDATA_SEL 15 BIOS 32-bit interface (Data) */ -{ 0, /* segment base address (overwritten) */ - 0xfffff, /* length */ - SDT_MEMRWA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GBIOSUTIL_SEL 16 BIOS 16-bit interface (Utility) */ -{ 0, /* segment base address (overwritten) */ - 0xfffff, /* length */ - SDT_MEMRWA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GBIOSARGS_SEL 17 BIOS 16-bit interface (Arguments) */ -{ 0, /* segment base address (overwritten) */ - 0xfffff, /* length */ - SDT_MEMRWA, /* segment type */ - 0, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -/* GNDIS_SEL 18 NDIS Descriptor */ -{ 0x0, /* segment base address */ - 0x0, /* length */ - 0, /* segment type */ - 0, /* segment descriptor priority level */ - 0, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, -}; - -static struct soft_segment_descriptor ldt_segs[] = { - /* Null Descriptor - overwritten by call gate */ -{ 0x0, /* segment base address */ - 0x0, /* length - all address space */ - 0, /* segment type */ - 0, /* segment descriptor priority level */ - 0, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, - /* Null Descriptor - overwritten by call gate */ -{ 0x0, /* segment base address */ - 0x0, /* length - all address space */ - 0, /* segment type */ - 0, /* segment descriptor priority level */ - 0, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, - /* Null Descriptor - overwritten by call gate */ -{ 0x0, /* segment base address */ - 0x0, /* length - all address space */ - 0, /* segment type */ - 0, /* segment descriptor priority level */ - 0, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, - /* Code Descriptor for user */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMERA, /* segment type */ - SEL_UPL, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, - /* Null Descriptor - overwritten by call gate */ -{ 0x0, /* segment base address */ - 0x0, /* length - all address space */ - 0, /* segment type */ - 0, /* segment descriptor priority level */ - 0, /* segment descriptor present */ - 0, 0, - 0, /* default 32 vs 16 bit size */ - 0 /* limit granularity (byte/page units)*/ }, - /* Data Descriptor for user */ -{ 0x0, /* segment base address */ - 0xfffff, /* length - all address space */ - SDT_MEMRWA, /* segment type */ - SEL_UPL, /* segment descriptor priority level */ - 1, /* segment descriptor present */ - 0, 0, - 1, /* default 32 vs 16 bit size */ - 1 /* limit granularity (byte/page units)*/ }, -}; - -void -setidt(idx, func, typ, dpl, selec) - int idx; - inthand_t *func; - int typ; - int dpl; - int selec; -{ - struct gate_descriptor *ip; - - ip = idt + idx; - ip->gd_looffset = (int)func; - ip->gd_selector = selec; - ip->gd_stkcpy = 0; - ip->gd_xx = 0; - ip->gd_type = typ; - ip->gd_dpl = dpl; - ip->gd_p = 1; - ip->gd_hioffset = ((int)func)>>16 ; -} - -#define IDTVEC(name) __CONCAT(X,name) - -extern inthand_t - IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), - IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), - IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), - IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), - IDTVEC(xmm), IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall); - -#ifdef DDB -/* - * Display the index and function name of any IDT entries that don't use - * the default 'rsvd' entry point. - */ -DB_SHOW_COMMAND(idt, db_show_idt) -{ - struct gate_descriptor *ip; - int idx, quit; - uintptr_t func; - - ip = idt; - db_setup_paging(db_simple_pager, &quit, db_lines_per_page); - for (idx = 0, quit = 0; idx < NIDT; idx++) { - func = (ip->gd_hioffset << 16 | ip->gd_looffset); - if (func != (uintptr_t)&IDTVEC(rsvd)) { - db_printf("%3d\t", idx); - db_printsym(func, DB_STGY_PROC); - db_printf("\n"); - } - ip++; - } -} -#endif - -void -sdtossd(sd, ssd) - struct segment_descriptor *sd; - struct soft_segment_descriptor *ssd; -{ - ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase; - ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit; - ssd->ssd_type = sd->sd_type; - ssd->ssd_dpl = sd->sd_dpl; - ssd->ssd_p = sd->sd_p; - ssd->ssd_def32 = sd->sd_def32; - ssd->ssd_gran = sd->sd_gran; -} - -#define PHYSMAP_SIZE (2 * 8) - -/* - * Populate the (physmap) array with base/bound pairs describing the - * available physical memory in the system, then test this memory and - * build the phys_avail array describing the actually-available memory. - * - * If we cannot accurately determine the physical memory map, then use - * value from the 0xE801 call, and failing that, the RTC. - * - * Total memory size may be set by the kernel environment variable - * hw.physmem or the compile-time define MAXMEM. - * - * XXX first should be vm_paddr_t. - */ -static void -getmemsize(int first) -{ - int i, physmap_idx, pa_indx, pg_n; - u_long physmem_tunable; - u_int extmem, under16; - vm_offset_t pa, physmap[PHYSMAP_SIZE]; - pt_entry_t *pte; - quad_t dcons_addr, dcons_size; - - /* XXX - some of EPSON machines can't use PG_N */ - pg_n = PG_N; - if (pc98_machine_type & M_EPSON_PC98) { - switch (epson_machine_id) { -#ifdef WB_CACHE - default: -#endif - case 0x34: /* PC-486HX */ - case 0x35: /* PC-486HG */ - case 0x3B: /* PC-486HA */ - pg_n = 0; - break; - } - } - bzero(physmap, sizeof(physmap)); - - /* - * Perform "base memory" related probes & setup - */ - under16 = pc98_getmemsize(&basemem, &extmem); - if (basemem > 640) { - printf("Preposterous BIOS basemem of %uK, truncating to 640K\n", - basemem); - basemem = 640; - } - - /* - * XXX if biosbasemem is now < 640, there is a `hole' - * between the end of base memory and the start of - * ISA memory. The hole may be empty or it may - * contain BIOS code or data. Map it read/write so - * that the BIOS can write to it. (Memory from 0 to - * the physical end of the kernel is mapped read-only - * to begin with and then parts of it are remapped. - * The parts that aren't remapped form holes that - * remain read-only and are unused by the kernel. - * The base memory area is below the physical end of - * the kernel and right now forms a read-only hole. - * The part of it from PAGE_SIZE to - * (trunc_page(biosbasemem * 1024) - 1) will be - * remapped and used by the kernel later.) - * - * This code is similar to the code used in - * pmap_mapdev, but since no memory needs to be - * allocated we simply change the mapping. - */ - for (pa = trunc_page(basemem * 1024); - pa < ISA_HOLE_START; pa += PAGE_SIZE) - pmap_kenter(KERNBASE + pa, pa); - - /* - * if basemem != 640, map pages r/w into vm86 page table so - * that the bios can scribble on it. - */ - pte = (pt_entry_t *)vm86paddr; - for (i = basemem / 4; i < 160; i++) - pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U; - - physmap[0] = 0; - physmap[1] = basemem * 1024; - physmap_idx = 2; - physmap[physmap_idx] = 0x100000; - physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024; - - /* - * Now, physmap contains a map of physical memory. - */ - -#ifdef SMP - /* make hole for AP bootstrap code */ - physmap[1] = mp_bootaddress(physmap[1]); -#endif - - /* - * Maxmem isn't the "maximum memory", it's one larger than the - * highest page of the physical address space. It should be - * called something like "Maxphyspage". We may adjust this - * based on ``hw.physmem'' and the results of the memory test. - */ - Maxmem = atop(physmap[physmap_idx + 1]); - -#ifdef MAXMEM - Maxmem = MAXMEM / 4; -#endif - - if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable)) - Maxmem = atop(physmem_tunable); - - if (atop(physmap[physmap_idx + 1]) != Maxmem && - (boothowto & RB_VERBOSE)) - printf("Physical memory use set to %ldK\n", Maxmem * 4); - - /* - * If Maxmem has been increased beyond what the system has detected, - * extend the last memory segment to the new limit. - */ - if (atop(physmap[physmap_idx + 1]) < Maxmem) - physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem); - - /* - * We need to divide chunk if Maxmem is larger than 16MB and - * under 16MB area is not full of memory. - * (1) system area (15-16MB region) is cut off - * (2) extended memory is only over 16MB area (ex. Melco "HYPERMEMORY") - */ - if ((under16 != 16 * 1024) && (extmem > 15 * 1024)) { - /* 15M - 16M region is cut off, so need to divide chunk */ - physmap[physmap_idx + 1] = under16 * 1024; - physmap_idx += 2; - physmap[physmap_idx] = 0x1000000; - physmap[physmap_idx + 1] = physmap[2] + extmem * 1024; - } - - /* call pmap initialization to make new kernel address space */ - pmap_bootstrap(first, 0); - - /* - * Size up each available chunk of physical memory. - */ - physmap[0] = PAGE_SIZE; /* mask off page 0 */ - pa_indx = 0; - phys_avail[pa_indx++] = physmap[0]; - phys_avail[pa_indx] = physmap[0]; - pte = CMAP1; - - /* - * Get dcons buffer address - */ - if (getenv_quad("dcons.addr", &dcons_addr) == 0 || - getenv_quad("dcons.size", &dcons_size) == 0) - dcons_addr = 0; - - /* - * physmap is in bytes, so when converting to page boundaries, - * round up the start address and round down the end address. - */ - for (i = 0; i <= physmap_idx; i += 2) { - vm_paddr_t end; - - end = ptoa((vm_paddr_t)Maxmem); - if (physmap[i + 1] < end) - end = trunc_page(physmap[i + 1]); - for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) { - int tmp, page_bad; - int *ptr = (int *)CADDR1; - - /* - * block out kernel memory as not available. - */ - if (pa >= KERNLOAD && pa < first) - continue; - - /* - * block out dcons buffer - */ - if (dcons_addr > 0 - && pa >= trunc_page(dcons_addr) - && pa < dcons_addr + dcons_size) - continue; - - page_bad = FALSE; - - /* - * map page into kernel: valid, read/write,non-cacheable - */ - *pte = pa | PG_V | PG_RW | pg_n; - invltlb(); - - tmp = *(int *)ptr; - /* - * Test for alternating 1's and 0's - */ - *(volatile int *)ptr = 0xaaaaaaaa; - if (*(volatile int *)ptr != 0xaaaaaaaa) { - page_bad = TRUE; - } - /* - * Test for alternating 0's and 1's - */ - *(volatile int *)ptr = 0x55555555; - if (*(volatile int *)ptr != 0x55555555) { - page_bad = TRUE; - } - /* - * Test for all 1's - */ - *(volatile int *)ptr = 0xffffffff; - if (*(volatile int *)ptr != 0xffffffff) { - page_bad = TRUE; - } - /* - * Test for all 0's - */ - *(volatile int *)ptr = 0x0; - if (*(volatile int *)ptr != 0x0) { - page_bad = TRUE; - } - /* - * Restore original value. - */ - *(int *)ptr = tmp; - - /* - * Adjust array of valid/good pages. - */ - if (page_bad == TRUE) { - continue; - } - /* - * If this good page is a continuation of the - * previous set of good pages, then just increase - * the end pointer. Otherwise start a new chunk. - * Note that "end" points one higher than end, - * making the range >= start and < end. - * If we're also doing a speculative memory - * test and we at or past the end, bump up Maxmem - * so that we keep going. The first bad page - * will terminate the loop. - */ - if (phys_avail[pa_indx] == pa) { - phys_avail[pa_indx] += PAGE_SIZE; - } else { - pa_indx++; - if (pa_indx == PHYS_AVAIL_ARRAY_END) { - printf( - "Too many holes in the physical address space, giving up\n"); - pa_indx--; - break; - } - phys_avail[pa_indx++] = pa; /* start */ - phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */ - } - physmem++; - } - } - *pte = 0; - invltlb(); - - /* - * XXX - * The last chunk must contain at least one page plus the message - * buffer to avoid complicating other code (message buffer address - * calculation, etc.). - */ - while (phys_avail[pa_indx - 1] + PAGE_SIZE + - round_page(MSGBUF_SIZE) >= phys_avail[pa_indx]) { - physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]); - phys_avail[pa_indx--] = 0; - phys_avail[pa_indx--] = 0; - } - - Maxmem = atop(phys_avail[pa_indx]); - - /* Trim off space for the message buffer. */ - phys_avail[pa_indx] -= round_page(MSGBUF_SIZE); - - avail_end = phys_avail[pa_indx]; -} - -void -init386(first) - int first; -{ - struct gate_descriptor *gdp; - int gsel_tss, metadata_missing, off, x; - struct pcpu *pc; - - thread0.td_kstack = proc0kstack; - thread0.td_pcb = (struct pcb *) - (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; - - /* - * This may be done better later if it gets more high level - * components in it. If so just link td->td_proc here. - */ - proc_linkup(&proc0, &ksegrp0, &thread0); - - /* - * Initialize DMAC - */ - pc98_init_dmac(); - - metadata_missing = 0; - if (bootinfo.bi_modulep) { - preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE; - preload_bootstrap_relocate(KERNBASE); - } else { - metadata_missing = 1; - } - if (envmode == 1) - kern_envp = static_env; - else if (bootinfo.bi_envp) - kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE; - - /* Init basic tunables, hz etc */ - init_param1(); - - /* - * Make gdt memory segments. All segments cover the full 4GB - * of address space and permissions are enforced at page level. - */ - gdt_segs[GCODE_SEL].ssd_limit = atop(0 - 1); - gdt_segs[GDATA_SEL].ssd_limit = atop(0 - 1); - gdt_segs[GUCODE_SEL].ssd_limit = atop(0 - 1); - gdt_segs[GUDATA_SEL].ssd_limit = atop(0 - 1); - gdt_segs[GUFS_SEL].ssd_limit = atop(0 - 1); - gdt_segs[GUGS_SEL].ssd_limit = atop(0 - 1); - -#ifdef SMP - pc = &SMP_prvspace[0].pcpu; -#else - pc = &__pcpu; -#endif - gdt_segs[GPRIV_SEL].ssd_limit = atop(0 - 1); - gdt_segs[GPRIV_SEL].ssd_base = (int) pc; - gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss; - - for (x = 0; x < NGDT; x++) - ssdtosd(&gdt_segs[x], &gdt[x].sd); - - r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; - r_gdt.rd_base = (int) gdt; - lgdt(&r_gdt); - - pcpu_init(pc, 0, sizeof(struct pcpu)); - PCPU_SET(prvspace, pc); - PCPU_SET(curthread, &thread0); - PCPU_SET(curpcb, thread0.td_pcb); - - /* - * Initialize mutexes. - * - * icu_lock: in order to allow an interrupt to occur in a critical - * section, to set pcpu->ipending (etc...) properly, we - * must be able to get the icu lock, so it can't be - * under witness. - */ - mutex_init(); - mtx_init(&clock_lock, "clk", NULL, MTX_SPIN); - mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS); - - /* make ldt memory segments */ - ldt_segs[LUCODE_SEL].ssd_limit = atop(0 - 1); - ldt_segs[LUDATA_SEL].ssd_limit = atop(0 - 1); - for (x = 0; x < sizeof ldt_segs / sizeof ldt_segs[0]; x++) - ssdtosd(&ldt_segs[x], &ldt[x].sd); - - _default_ldt = GSEL(GLDT_SEL, SEL_KPL); - lldt(_default_ldt); - PCPU_SET(currentldt, _default_ldt); - - /* exceptions */ - for (x = 0; x < NIDT; x++) - setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_DE, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_DB, &IDTVEC(dbg), SDT_SYS386IGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_NMI, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_BP, &IDTVEC(bpt), SDT_SYS386IGT, SEL_UPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_OF, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_BR, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_NM, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL - , GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_DF, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL)); - setidt(IDT_FPUGP, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_TS, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_NP, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_SS, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_PF, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_MF, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_AC, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_MC, &IDTVEC(mchk), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_XF, &IDTVEC(xmm), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall), SDT_SYS386TGT, SEL_UPL, - GSEL(GCODE_SEL, SEL_KPL)); - - r_idt.rd_limit = sizeof(idt0) - 1; - r_idt.rd_base = (int) idt; - lidt(&r_idt); - - /* - * Initialize the console before we print anything out. - */ - cninit(); - - if (metadata_missing) - printf("WARNING: loader(8) metadata is missing!\n"); - -#ifdef DEV_ISA - atpic_startup(); -#endif - -#ifdef DDB - ksym_start = bootinfo.bi_symtab; - ksym_end = bootinfo.bi_esymtab; -#endif - - kdb_init(); - -#ifdef KDB - if (boothowto & RB_KDB) - kdb_enter("Boot flags requested debugger"); -#endif - - finishidentcpu(); /* Final stage of CPU initialization */ - setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); - initializecpu(); /* Initialize CPU registers */ - - /* make an initial tss so cpu can get interrupt stack on syscall! */ - /* Note: -16 is so we can grow the trapframe if we came from vm86 */ - PCPU_SET(common_tss.tss_esp0, thread0.td_kstack + - KSTACK_PAGES * PAGE_SIZE - sizeof(struct pcb) - 16); - PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL)); - gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); - private_tss = 0; - PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd); - PCPU_SET(common_tssd, *PCPU_GET(tss_gdt)); - PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16); - ltr(gsel_tss); - - /* pointer to selector slot for %fs/%gs */ - PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd); - - dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 = - dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)]; - dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 = - dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL); - dblfault_tss.tss_cr3 = (int)IdlePTD; - dblfault_tss.tss_eip = (int)dblfault_handler; - dblfault_tss.tss_eflags = PSL_KERNEL; - dblfault_tss.tss_ds = dblfault_tss.tss_es = - dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL); - dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL); - dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL); - dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL); - - vm86_initialize(); - getmemsize(first); - init_param2(physmem); - - /* now running on new page tables, configured,and u/iom is accessible */ - - /* Map the message buffer. */ - for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) - pmap_kenter((vm_offset_t)msgbufp + off, avail_end + off); - - msgbufinit(msgbufp, MSGBUF_SIZE); - - /* make a call gate to reenter kernel with */ - gdp = &ldt[LSYS5CALLS_SEL].gd; - - x = (int) &IDTVEC(lcall_syscall); - gdp->gd_looffset = x; - gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); - gdp->gd_stkcpy = 1; - gdp->gd_type = SDT_SYS386CGT; - gdp->gd_dpl = SEL_UPL; - gdp->gd_p = 1; - gdp->gd_hioffset = x >> 16; - - /* XXX does this work? */ - /* XXX yes! */ - ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL]; - ldt[LSOL26CALLS_SEL] = ldt[LSYS5CALLS_SEL]; - - /* transfer to user mode */ - - _ucodesel = GSEL(GUCODE_SEL, SEL_UPL); - _udatasel = GSEL(GUDATA_SEL, SEL_UPL); - - /* setup proc 0's pcb */ - thread0.td_pcb->pcb_flags = 0; /* XXXKSE */ - thread0.td_pcb->pcb_cr3 = (int)IdlePTD; - thread0.td_pcb->pcb_ext = 0; - thread0.td_frame = &proc0_tf; -} - -void -cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) -{ - -} - -void -spinlock_enter(void) -{ - struct thread *td; - - td = curthread; - if (td->td_md.md_spinlock_count == 0) - td->td_md.md_saved_flags = intr_disable(); - td->td_md.md_spinlock_count++; - critical_enter(); -} - -void -spinlock_exit(void) -{ - struct thread *td; - - td = curthread; - critical_exit(); - td->td_md.md_spinlock_count--; - if (td->td_md.md_spinlock_count == 0) - intr_restore(td->td_md.md_saved_flags); -} - -#if defined(I586_CPU) && !defined(NO_F00F_HACK) -static void f00f_hack(void *unused); -SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL) - -static void -f00f_hack(void *unused) -{ - struct gate_descriptor *new_idt; - vm_offset_t tmp; - - if (!has_f00f_bug) - return; - - GIANT_REQUIRED; - - printf("Intel Pentium detected, installing workaround for F00F bug\n"); - - tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2); - if (tmp == 0) - panic("kmem_alloc returned 0"); - - /* Put the problematic entry (#6) at the end of the lower page. */ - new_idt = (struct gate_descriptor*) - (tmp + PAGE_SIZE - 7 * sizeof(struct gate_descriptor)); - bcopy(idt, new_idt, sizeof(idt0)); - r_idt.rd_base = (u_int)new_idt; - lidt(&r_idt); - idt = new_idt; - if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE, - VM_PROT_READ, FALSE) != KERN_SUCCESS) - panic("vm_map_protect failed"); -} -#endif /* defined(I586_CPU) && !NO_F00F_HACK */ - -/* - * Construct a PCB from a trapframe. This is called from kdb_trap() where - * we want to start a backtrace from the function that caused us to enter - * the debugger. We have the context in the trapframe, but base the trace - * on the PCB. The PCB doesn't have to be perfect, as long as it contains - * enough for a backtrace. - */ -void -makectx(struct trapframe *tf, struct pcb *pcb) -{ - - pcb->pcb_edi = tf->tf_edi; - pcb->pcb_esi = tf->tf_esi; - pcb->pcb_ebp = tf->tf_ebp; - pcb->pcb_ebx = tf->tf_ebx; - pcb->pcb_eip = tf->tf_eip; - pcb->pcb_esp = (ISPL(tf->tf_cs)) ? tf->tf_esp : (int)(tf + 1) - 8; -} - -int -ptrace_set_pc(struct thread *td, u_long addr) -{ - - td->td_frame->tf_eip = addr; - return (0); -} - -int -ptrace_single_step(struct thread *td) -{ - td->td_frame->tf_eflags |= PSL_T; - return (0); -} - -int -ptrace_clear_single_step(struct thread *td) -{ - td->td_frame->tf_eflags &= ~PSL_T; - return (0); -} - -int -fill_regs(struct thread *td, struct reg *regs) -{ - struct pcb *pcb; - struct trapframe *tp; - - tp = td->td_frame; - regs->r_fs = tp->tf_fs; - regs->r_es = tp->tf_es; - regs->r_ds = tp->tf_ds; - regs->r_edi = tp->tf_edi; - regs->r_esi = tp->tf_esi; - regs->r_ebp = tp->tf_ebp; - regs->r_ebx = tp->tf_ebx; - regs->r_edx = tp->tf_edx; - regs->r_ecx = tp->tf_ecx; - regs->r_eax = tp->tf_eax; - regs->r_eip = tp->tf_eip; - regs->r_cs = tp->tf_cs; - regs->r_eflags = tp->tf_eflags; - regs->r_esp = tp->tf_esp; - regs->r_ss = tp->tf_ss; - pcb = td->td_pcb; - regs->r_gs = pcb->pcb_gs; - return (0); -} - -int -set_regs(struct thread *td, struct reg *regs) -{ - struct pcb *pcb; - struct trapframe *tp; - - tp = td->td_frame; - if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) || - !CS_SECURE(regs->r_cs)) - return (EINVAL); - tp->tf_fs = regs->r_fs; - tp->tf_es = regs->r_es; - tp->tf_ds = regs->r_ds; - tp->tf_edi = regs->r_edi; - tp->tf_esi = regs->r_esi; - tp->tf_ebp = regs->r_ebp; - tp->tf_ebx = regs->r_ebx; - tp->tf_edx = regs->r_edx; - tp->tf_ecx = regs->r_ecx; - tp->tf_eax = regs->r_eax; - tp->tf_eip = regs->r_eip; - tp->tf_cs = regs->r_cs; - tp->tf_eflags = regs->r_eflags; - tp->tf_esp = regs->r_esp; - tp->tf_ss = regs->r_ss; - pcb = td->td_pcb; - pcb->pcb_gs = regs->r_gs; - return (0); -} - -#ifdef CPU_ENABLE_SSE -static void -fill_fpregs_xmm(sv_xmm, sv_87) - struct savexmm *sv_xmm; - struct save87 *sv_87; -{ - register struct env87 *penv_87 = &sv_87->sv_env; - register struct envxmm *penv_xmm = &sv_xmm->sv_env; - int i; - - bzero(sv_87, sizeof(*sv_87)); - - /* FPU control/status */ - penv_87->en_cw = penv_xmm->en_cw; - penv_87->en_sw = penv_xmm->en_sw; - penv_87->en_tw = penv_xmm->en_tw; - penv_87->en_fip = penv_xmm->en_fip; - penv_87->en_fcs = penv_xmm->en_fcs; - penv_87->en_opcode = penv_xmm->en_opcode; - penv_87->en_foo = penv_xmm->en_foo; - penv_87->en_fos = penv_xmm->en_fos; - - /* FPU registers */ - for (i = 0; i < 8; ++i) - sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc; -} - -static void -set_fpregs_xmm(sv_87, sv_xmm) - struct save87 *sv_87; - struct savexmm *sv_xmm; -{ - register struct env87 *penv_87 = &sv_87->sv_env; - register struct envxmm *penv_xmm = &sv_xmm->sv_env; - int i; - - /* FPU control/status */ - penv_xmm->en_cw = penv_87->en_cw; - penv_xmm->en_sw = penv_87->en_sw; - penv_xmm->en_tw = penv_87->en_tw; - penv_xmm->en_fip = penv_87->en_fip; - penv_xmm->en_fcs = penv_87->en_fcs; - penv_xmm->en_opcode = penv_87->en_opcode; - penv_xmm->en_foo = penv_87->en_foo; - penv_xmm->en_fos = penv_87->en_fos; - - /* FPU registers */ - for (i = 0; i < 8; ++i) - sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i]; -} -#endif /* CPU_ENABLE_SSE */ - -int -fill_fpregs(struct thread *td, struct fpreg *fpregs) -{ -#ifdef CPU_ENABLE_SSE - if (cpu_fxsr) { - fill_fpregs_xmm(&td->td_pcb->pcb_save.sv_xmm, - (struct save87 *)fpregs); - return (0); - } -#endif /* CPU_ENABLE_SSE */ - bcopy(&td->td_pcb->pcb_save.sv_87, fpregs, sizeof *fpregs); - return (0); -} - -int -set_fpregs(struct thread *td, struct fpreg *fpregs) -{ -#ifdef CPU_ENABLE_SSE - if (cpu_fxsr) { - set_fpregs_xmm((struct save87 *)fpregs, - &td->td_pcb->pcb_save.sv_xmm); - return (0); - } -#endif /* CPU_ENABLE_SSE */ - bcopy(fpregs, &td->td_pcb->pcb_save.sv_87, sizeof *fpregs); - return (0); -} - -/* - * Get machine context. - */ -int -get_mcontext(struct thread *td, mcontext_t *mcp, int flags) -{ - struct trapframe *tp; - - tp = td->td_frame; - - PROC_LOCK(curthread->td_proc); - mcp->mc_onstack = sigonstack(tp->tf_esp); - PROC_UNLOCK(curthread->td_proc); - mcp->mc_gs = td->td_pcb->pcb_gs; - mcp->mc_fs = tp->tf_fs; - mcp->mc_es = tp->tf_es; - mcp->mc_ds = tp->tf_ds; - mcp->mc_edi = tp->tf_edi; - mcp->mc_esi = tp->tf_esi; - mcp->mc_ebp = tp->tf_ebp; - mcp->mc_isp = tp->tf_isp; - if (flags & GET_MC_CLEAR_RET) { - mcp->mc_eax = 0; - mcp->mc_edx = 0; - } else { - mcp->mc_eax = tp->tf_eax; - mcp->mc_edx = tp->tf_edx; - } - mcp->mc_ebx = tp->tf_ebx; - mcp->mc_ecx = tp->tf_ecx; - mcp->mc_eip = tp->tf_eip; - mcp->mc_cs = tp->tf_cs; - mcp->mc_eflags = tp->tf_eflags; - mcp->mc_esp = tp->tf_esp; - mcp->mc_ss = tp->tf_ss; - mcp->mc_len = sizeof(*mcp); - get_fpcontext(td, mcp); - return (0); -} - -/* - * Set machine context. - * - * However, we don't set any but the user modifiable flags, and we won't - * touch the cs selector. - */ -int -set_mcontext(struct thread *td, const mcontext_t *mcp) -{ - struct trapframe *tp; - int eflags, ret; - - tp = td->td_frame; - if (mcp->mc_len != sizeof(*mcp)) - return (EINVAL); - eflags = (mcp->mc_eflags & PSL_USERCHANGE) | - (tp->tf_eflags & ~PSL_USERCHANGE); - if ((ret = set_fpcontext(td, mcp)) == 0) { - tp->tf_fs = mcp->mc_fs; - tp->tf_es = mcp->mc_es; - tp->tf_ds = mcp->mc_ds; - tp->tf_edi = mcp->mc_edi; - tp->tf_esi = mcp->mc_esi; - tp->tf_ebp = mcp->mc_ebp; - tp->tf_ebx = mcp->mc_ebx; - tp->tf_edx = mcp->mc_edx; - tp->tf_ecx = mcp->mc_ecx; - tp->tf_eax = mcp->mc_eax; - tp->tf_eip = mcp->mc_eip; - tp->tf_eflags = eflags; - tp->tf_esp = mcp->mc_esp; - tp->tf_ss = mcp->mc_ss; - td->td_pcb->pcb_gs = mcp->mc_gs; - ret = 0; - } - return (ret); -} - -static void -get_fpcontext(struct thread *td, mcontext_t *mcp) -{ -#ifndef DEV_NPX - mcp->mc_fpformat = _MC_FPFMT_NODEV; - mcp->mc_ownedfp = _MC_FPOWNED_NONE; -#else - union savefpu *addr; - - /* - * XXX mc_fpstate might be misaligned, since its declaration is not - * unportabilized using __attribute__((aligned(16))) like the - * declaration of struct savemm, and anyway, alignment doesn't work - * for auto variables since we don't use gcc's pessimal stack - * alignment. Work around this by abusing the spare fields after - * mcp->mc_fpstate. - * - * XXX unpessimize most cases by only aligning when fxsave might be - * called, although this requires knowing too much about - * npxgetregs()'s internals. - */ - addr = (union savefpu *)&mcp->mc_fpstate; - if (td == PCPU_GET(fpcurthread) && -#ifdef CPU_ENABLE_SSE - cpu_fxsr && -#endif - ((uintptr_t)(void *)addr & 0xF)) { - do - addr = (void *)((char *)addr + 4); - while ((uintptr_t)(void *)addr & 0xF); - } - mcp->mc_ownedfp = npxgetregs(td, addr); - if (addr != (union savefpu *)&mcp->mc_fpstate) { - bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); - bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); - } - mcp->mc_fpformat = npxformat(); -#endif -} - -static int -set_fpcontext(struct thread *td, const mcontext_t *mcp) -{ - union savefpu *addr; - - if (mcp->mc_fpformat == _MC_FPFMT_NODEV) - return (0); - else if (mcp->mc_fpformat != _MC_FPFMT_387 && - mcp->mc_fpformat != _MC_FPFMT_XMM) - return (EINVAL); - else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) - /* We don't care what state is left in the FPU or PCB. */ - fpstate_drop(td); - else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || - mcp->mc_ownedfp == _MC_FPOWNED_PCB) { - /* XXX align as above. */ - addr = (union savefpu *)&mcp->mc_fpstate; - if (td == PCPU_GET(fpcurthread) && -#ifdef CPU_ENABLE_SSE - cpu_fxsr && -#endif - ((uintptr_t)(void *)addr & 0xF)) { - do - addr = (void *)((char *)addr + 4); - while ((uintptr_t)(void *)addr & 0xF); - bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate)); - } -#ifdef DEV_NPX - /* - * XXX we violate the dubious requirement that npxsetregs() - * be called with interrupts disabled. - */ - npxsetregs(td, addr); -#endif - /* - * Don't bother putting things back where they were in the - * misaligned case, since we know that the caller won't use - * them again. - */ - } else - return (EINVAL); - return (0); -} - -static void -fpstate_drop(struct thread *td) -{ - register_t s; - - s = intr_disable(); -#ifdef DEV_NPX - if (PCPU_GET(fpcurthread) == td) - npxdrop(); -#endif - /* - * XXX force a full drop of the npx. The above only drops it if we - * owned it. npxgetregs() has the same bug in the !cpu_fxsr case. - * - * XXX I don't much like npxgetregs()'s semantics of doing a full - * drop. Dropping only to the pcb matches fnsave's behaviour. - * We only need to drop to !PCB_INITDONE in sendsig(). But - * sendsig() is the only caller of npxgetregs()... perhaps we just - * have too many layers. - */ - curthread->td_pcb->pcb_flags &= ~PCB_NPXINITDONE; - intr_restore(s); -} - -int -fill_dbregs(struct thread *td, struct dbreg *dbregs) -{ - struct pcb *pcb; - - if (td == NULL) { - dbregs->dr[0] = rdr0(); - dbregs->dr[1] = rdr1(); - dbregs->dr[2] = rdr2(); - dbregs->dr[3] = rdr3(); - dbregs->dr[4] = rdr4(); - dbregs->dr[5] = rdr5(); - dbregs->dr[6] = rdr6(); - dbregs->dr[7] = rdr7(); - } else { - pcb = td->td_pcb; - dbregs->dr[0] = pcb->pcb_dr0; - dbregs->dr[1] = pcb->pcb_dr1; - dbregs->dr[2] = pcb->pcb_dr2; - dbregs->dr[3] = pcb->pcb_dr3; - dbregs->dr[4] = 0; - dbregs->dr[5] = 0; - dbregs->dr[6] = pcb->pcb_dr6; - dbregs->dr[7] = pcb->pcb_dr7; - } - return (0); -} - -int -set_dbregs(struct thread *td, struct dbreg *dbregs) -{ - struct pcb *pcb; - int i; - u_int32_t mask1, mask2; - - if (td == NULL) { - load_dr0(dbregs->dr[0]); - load_dr1(dbregs->dr[1]); - load_dr2(dbregs->dr[2]); - load_dr3(dbregs->dr[3]); - load_dr4(dbregs->dr[4]); - load_dr5(dbregs->dr[5]); - load_dr6(dbregs->dr[6]); - load_dr7(dbregs->dr[7]); - } else { - /* - * Don't let an illegal value for dr7 get set. Specifically, - * check for undefined settings. Setting these bit patterns - * result in undefined behaviour and can lead to an unexpected - * TRCTRAP. - */ - for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8; - i++, mask1 <<= 2, mask2 <<= 2) - if ((dbregs->dr[7] & mask1) == mask2) - return (EINVAL); - - pcb = td->td_pcb; - - /* - * Don't let a process set a breakpoint that is not within the - * process's address space. If a process could do this, it - * could halt the system by setting a breakpoint in the kernel - * (if ddb was enabled). Thus, we need to check to make sure - * that no breakpoints are being enabled for addresses outside - * process's address space, unless, perhaps, we were called by - * uid 0. - * - * XXX - what about when the watched area of the user's - * address space is written into from within the kernel - * ... wouldn't that still cause a breakpoint to be generated - * from within kernel mode? - */ - - if (suser(td) != 0) { - if (dbregs->dr[7] & 0x3) { - /* dr0 is enabled */ - if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS) - return (EINVAL); - } - - if (dbregs->dr[7] & (0x3<<2)) { - /* dr1 is enabled */ - if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS) - return (EINVAL); - } - - if (dbregs->dr[7] & (0x3<<4)) { - /* dr2 is enabled */ - if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS) - return (EINVAL); - } - - if (dbregs->dr[7] & (0x3<<6)) { - /* dr3 is enabled */ - if (dbregs->dr[3] >= VM_MAXUSER_ADDRESS) - return (EINVAL); - } - } - - pcb->pcb_dr0 = dbregs->dr[0]; - pcb->pcb_dr1 = dbregs->dr[1]; - pcb->pcb_dr2 = dbregs->dr[2]; - pcb->pcb_dr3 = dbregs->dr[3]; - pcb->pcb_dr6 = dbregs->dr[6]; - pcb->pcb_dr7 = dbregs->dr[7]; - - pcb->pcb_flags |= PCB_DBREGS; - } - - return (0); -} - -/* - * Return > 0 if a hardware breakpoint has been hit, and the - * breakpoint was in user space. Return 0, otherwise. - */ -int -user_dbreg_trap(void) -{ - u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */ - u_int32_t bp; /* breakpoint bits extracted from dr6 */ - int nbp; /* number of breakpoints that triggered */ - caddr_t addr[4]; /* breakpoint addresses */ - int i; - - dr7 = rdr7(); - if ((dr7 & 0x000000ff) == 0) { - /* - * all GE and LE bits in the dr7 register are zero, - * thus the trap couldn't have been caused by the - * hardware debug registers - */ - return 0; - } - - nbp = 0; - dr6 = rdr6(); - bp = dr6 & 0x0000000f; - - if (!bp) { - /* - * None of the breakpoint bits are set meaning this - * trap was not caused by any of the debug registers - */ - return 0; - } - - /* - * at least one of the breakpoints were hit, check to see - * which ones and if any of them are user space addresses - */ - - if (bp & 0x01) { - addr[nbp++] = (caddr_t)rdr0(); - } - if (bp & 0x02) { - addr[nbp++] = (caddr_t)rdr1(); - } - if (bp & 0x04) { - addr[nbp++] = (caddr_t)rdr2(); - } - if (bp & 0x08) { - addr[nbp++] = (caddr_t)rdr3(); - } - - for (i=0; i<nbp; i++) { - if (addr[i] < - (caddr_t)VM_MAXUSER_ADDRESS) { - /* - * addr[i] is in user space - */ - return nbp; - } - } - - /* - * None of the breakpoints are in user space. - */ - return 0; -} - -#ifdef KDB - -/* - * Provide inb() and outb() as functions. They are normally only - * available as macros calling inlined functions, thus cannot be - * called from the debugger. - * - * The actual code is stolen from <machine/cpufunc.h>, and de-inlined. - */ - -#undef inb -#undef outb - -/* silence compiler warnings */ -u_char inb(u_int); -void outb(u_int, u_char); - -u_char -inb(u_int port) -{ - u_char data; - /* - * We use %%dx and not %1 here because i/o is done at %dx and not at - * %edx, while gcc generates inferior code (movw instead of movl) - * if we tell it to load (u_short) port. - */ - __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); - return (data); -} - -void -outb(u_int port, u_char data) -{ - u_char al; - /* - * Use an unnecessary assignment to help gcc's register allocator. - * This make a large difference for gcc-1.40 and a tiny difference - * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for - * best results. gcc-2.6.0 can't handle this. - */ - al = data; - __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); -} - -#endif /* KDB */ diff --git a/sys/pc98/pc98/30line.h b/sys/pc98/pc98/30line.h deleted file mode 100644 index c2e0f10..0000000 --- a/sys/pc98/pc98/30line.h +++ /dev/null @@ -1,130 +0,0 @@ -/*- - * Copyright (c) 1994, 1995, 1996. FreeBSD(98) porting team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef __PC98_PC98_30LINE_H__ -#define __PC98_PC98_30LINE_H__ - -#define LINE30_ROW 30 -#define _HS 1 + 1 -#define _VS 2 -#define _HFP 3 + 1 -#define _HBP 14 + 1 -#define _VFP 11 -#define _VBP 44 - -#define _CR 80 -#define _LF LINE30_ROW*16 - -#define _GDC_RESET 0x00 -#define _GDC_SYNC 0x0e -#define _GDC_MASTER 0x6f -#define _GDC_SLAVE 0x6e -#define _GDC_START 0x0d -#define _GDC_STOP 0x0c -#define _GDC_SCROLL 0x70 -#define _GDC_PITCH 0x47 - -#define GDC_CR 0 -#define GDC_VS 1 -#define GDC_HS 2 -#define GDC_HFP 3 -#define GDC_HBP 4 -#define GDC_VFP 5 -#define GDC_VBP 6 -#define GDC_LF 7 - - -#define _24KHZ 0 -#define _31KHZ 1 - -#define _2_5MHZ 0 -#define _5MHZ 1 - -#define _25L 0 -#define _30L 1 - -#define T25_G400 0 -#define T30_G400 1 -#define T30_G480 2 - -static void master_gdc_cmd(unsigned int); -static void master_gdc_prm(unsigned int); -static void master_gdc_word_prm(unsigned int); -#ifdef LINE30 -static void master_gdc_fifo_empty(void); -#endif -static void master_gdc_wait_vsync(void); - -static void gdc_cmd(unsigned int); -#ifdef LINE30 -static void gdc_prm(unsigned int); -static void gdc_word_prm(unsigned int); -static void gdc_fifo_empty(void); -#endif -static void gdc_wait_vsync(void); - -#ifdef LINE30 -static int check_gdc_clock(void); - -static int gdc_INFO = _25L; -#endif -static int gdc_FH = _24KHZ; -static void initialize_gdc(unsigned int, int); - -#ifdef LINE30 -static unsigned int master_param[2][2][8] = { -{{78, 8, 7, 9, 7, 7, 25, 400}, /* 400/24k */ - {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}}, /* 480/24k */ -{{78, 2, 7, 3, 7, 13, 34, 400}, /* 400/31k */ - {78, 2, 11, 3, 3, 6, 37, 480}}}; /* 480/31k */ - -static unsigned int slave_param[2][6][8] = { -{{38, 8, 3, 4, 3, 7, 25, 400}, /* normal */ - {78, 8, 7, 9, 7, 7, 25, 400}, - {_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1, - _VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400}, /* 30 & 400 */ - {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, - _VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400}, - {_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1, - _VFP, _VBP, _LF}, /* 30 & 480 */ - {_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}}, -{{38, 2, 3, 1, 3, 13, 34, 400}, /* normal */ - {78, 2, 7, 3, 7, 13, 34, 400}, - {38, 2, 5, 1, 1, 6+48, 37+32, 400}, /* 30 & 400 */ - {78, 2, 11, 3, 3, 6+48, 37+32, 400}, - {38, 2, 5, 1, 1, 6, 37, 480}, /* 30 & 480 */ - {78, 2, 11, 3, 3, 6, 37, 480}}}; - -static int SlavePCH[2] = {40,80}; -static int MasterPCH = 80; -static int SlaveScrlLF[3] = {400,400,_LF}; -#endif - -#endif /* __PC98_PC98_30LINE_H__ */ diff --git a/sys/pc98/pc98/clock.c b/sys/pc98/pc98/clock.c deleted file mode 100644 index 484e8df..0000000 --- a/sys/pc98/pc98/clock.c +++ /dev/null @@ -1,885 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz and Don Ahn. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $FreeBSD$ - */ - -/* - * Routines to handle clock hardware. - */ - -/* - * inittodr, settodr and support routines written - * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> - * - * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 - */ - -/* - * modified for PC98 by Kakefuda - */ - -#include "opt_apic.h" -#include "opt_clock.h" -#include "opt_isa.h" -#include "opt_mca.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/lock.h> -#include <sys/kdb.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/time.h> -#include <sys/timetc.h> -#include <sys/kernel.h> -#include <sys/limits.h> -#include <sys/module.h> -#include <sys/sysctl.h> -#include <sys/cons.h> -#include <sys/power.h> - -#include <machine/clock.h> -#include <machine/cputypes.h> -#include <machine/frame.h> -#include <machine/intr_machdep.h> -#include <machine/md_var.h> -#include <machine/psl.h> -#ifdef DEV_APIC -#include <machine/apicvar.h> -#endif -#include <machine/specialreg.h> - -#include <i386/isa/icu.h> -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> -#ifdef DEV_ISA -#include <isa/isavar.h> -#endif -#include <i386/isa/timerreg.h> - -/* - * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we - * can use a simple formula for leap years. - */ -#define LEAPYEAR(y) (((u_int)(y) % 4 == 0) ? 1 : 0) -#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) - -#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x)) - -int adjkerntz; /* local offset from GMT in seconds */ -int clkintr_pending; -int disable_rtc_set; /* disable resettodr() if != 0 */ -int pscnt = 1; -int psdiv = 1; -int statclock_disable; -#ifndef TIMER_FREQ -#define TIMER_FREQ 2457600 -#endif -u_int timer_freq = TIMER_FREQ; -int timer0_max_count; -int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ -struct mtx clock_lock; - -static int beeping = 0; -static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; -static u_int hardclock_max_count; -static struct intsrc *i8254_intsrc; -static u_int32_t i8254_lastcount; -static u_int32_t i8254_offset; -static int (*i8254_pending)(struct intsrc *); -static int i8254_ticked; -static int using_lapic_timer; - -/* Values for timerX_state: */ -#define RELEASED 0 -#define RELEASE_PENDING 1 -#define ACQUIRED 2 -#define ACQUIRE_PENDING 3 - -static u_char timer1_state; -static u_char timer2_state; -static void rtc_serialcombit(int); -static void rtc_serialcom(int); -static int rtc_inb(void); -static void rtc_outb(int); - -static unsigned i8254_get_timecount(struct timecounter *tc); -static void set_timer_freq(u_int freq, int intr_freq); - -static struct timecounter i8254_timecounter = { - i8254_get_timecount, /* get_timecount */ - 0, /* no poll_pps */ - ~0u, /* counter_mask */ - 0, /* frequency */ - "i8254", /* name */ - 0 /* quality */ -}; - -static void -clkintr(struct clockframe *frame) -{ - - if (timecounter->tc_get_timecount == i8254_get_timecount) { - mtx_lock_spin(&clock_lock); - if (i8254_ticked) - i8254_ticked = 0; - else { - i8254_offset += timer0_max_count; - i8254_lastcount = 0; - } - clkintr_pending = 0; - mtx_unlock_spin(&clock_lock); - } - if (!using_lapic_timer) - hardclock(frame); -} - -int -acquire_timer1(int mode) -{ - - if (timer1_state != RELEASED) - return (-1); - timer1_state = ACQUIRED; - - /* - * This access to the timer registers is as atomic as possible - * because it is a single instruction. We could do better if we - * knew the rate. Use of splclock() limits glitches to 10-100us, - * and this is probably good enough for timer2, so we aren't as - * careful with it as with timer0. - */ - outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f)); - - return (0); -} - -int -acquire_timer2(int mode) -{ - - if (timer2_state != RELEASED) - return (-1); - timer2_state = ACQUIRED; - - /* - * This access to the timer registers is as atomic as possible - * because it is a single instruction. We could do better if we - * knew the rate. Use of splclock() limits glitches to 10-100us, - * and this is probably good enough for timer2, so we aren't as - * careful with it as with timer0. - */ - outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f)); - - return (0); -} - -int -release_timer1() -{ - - if (timer1_state != ACQUIRED) - return (-1); - timer1_state = RELEASED; - outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT); - return (0); -} - -int -release_timer2() -{ - - if (timer2_state != ACQUIRED) - return (-1); - timer2_state = RELEASED; - outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT); - return (0); -} - - -static int -getit(void) -{ - int high, low; - - mtx_lock_spin(&clock_lock); - - /* Select timer0 and latch counter value. */ - outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); - - low = inb(TIMER_CNTR0); - high = inb(TIMER_CNTR0); - - mtx_unlock_spin(&clock_lock); - return ((high << 8) | low); -} - -/* - * Wait "n" microseconds. - * Relies on timer 1 counting down from (timer_freq / hz) - * Note: timer had better have been programmed before this is first used! - */ -void -DELAY(int n) -{ - int delta, prev_tick, tick, ticks_left; - -#ifdef DELAYDEBUG - int getit_calls = 1; - int n1; - static int state = 0; - - if (state == 0) { - state = 1; - for (n1 = 1; n1 <= 10000000; n1 *= 10) - DELAY(n1); - state = 2; - } - if (state == 1) - printf("DELAY(%d)...", n); -#endif - /* - * Guard against the timer being uninitialized if we are called - * early for console i/o. - */ - if (timer0_max_count == 0) - set_timer_freq(timer_freq, hz); - - /* - * Read the counter first, so that the rest of the setup overhead is - * counted. Guess the initial overhead is 20 usec (on most systems it - * takes about 1.5 usec for each of the i/o's in getit(). The loop - * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The - * multiplications and divisions to scale the count take a while). - * - * However, if ddb is active then use a fake counter since reading - * the i8254 counter involves acquiring a lock. ddb must not do - * locking for many reasons, but it calls here for at least atkbd - * input. - */ -#ifdef KDB - if (kdb_active) - prev_tick = 1; - else -#endif - prev_tick = getit(); - n -= 0; /* XXX actually guess no initial overhead */ - /* - * Calculate (n * (timer_freq / 1e6)) without using floating point - * and without any avoidable overflows. - */ - if (n <= 0) - ticks_left = 0; - else if (n < 256) - /* - * Use fixed point to avoid a slow division by 1000000. - * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest. - * 2^15 is the first power of 2 that gives exact results - * for n between 0 and 256. - */ - ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15; - else - /* - * Don't bother using fixed point, although gcc-2.7.2 - * generates particularly poor code for the long long - * division, since even the slow way will complete long - * before the delay is up (unless we're interrupted). - */ - ticks_left = ((u_int)n * (long long)timer_freq + 999999) - / 1000000; - - while (ticks_left > 0) { -#ifdef KDB - if (kdb_active) { - outb(0x5f, 0); - tick = prev_tick - 1; - if (tick <= 0) - tick = timer0_max_count; - } else -#endif - tick = getit(); -#ifdef DELAYDEBUG - ++getit_calls; -#endif - delta = prev_tick - tick; - prev_tick = tick; - if (delta < 0) { - delta += timer0_max_count; - /* - * Guard against timer0_max_count being wrong. - * This shouldn't happen in normal operation, - * but it may happen if set_timer_freq() is - * traced. - */ - if (delta < 0) - delta = 0; - } - ticks_left -= delta; - } -#ifdef DELAYDEBUG - if (state == 1) - printf(" %d calls to getit() at %d usec each\n", - getit_calls, (n + 5) / getit_calls); -#endif -} - -static void -sysbeepstop(void *chan) -{ - outb(IO_PPI, inb(IO_PPI)|0x08); /* disable counter1 output to speaker */ - release_timer1(); - beeping = 0; -} - -int -sysbeep(int pitch, int period) -{ - int x = splclock(); - - if (acquire_timer1(TIMER_SQWAVE|TIMER_16BIT)) - if (!beeping) { - /* Something else owns it. */ - splx(x); - return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ - } - disable_intr(); - outb(0x3fdb, pitch); - outb(0x3fdb, (pitch>>8)); - enable_intr(); - if (!beeping) { - /* enable counter1 output to speaker */ - outb(IO_PPI, (inb(IO_PPI) & 0xf7)); - beeping = period; - timeout(sysbeepstop, (void *)NULL, period); - } - splx(x); - return (0); -} - - -unsigned int delaycount; -#define FIRST_GUESS 0x2000 -static void findcpuspeed(void) -{ - int i; - int remainder; - - /* Put counter in count down mode */ - outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); - outb(TIMER_CNTR0, 0xff); - outb(TIMER_CNTR0, 0xff); - for (i = FIRST_GUESS; i; i--) - ; - remainder = getit(); - delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff - remainder); -} - -static u_int -calibrate_clocks(void) -{ - int timeout; - u_int count, prev_count, tot_count; - u_short sec, start_sec; - - if (bootverbose) - printf("Calibrating clock(s) ... "); - /* Check ARTIC. */ - if (!(PC98_SYSTEM_PARAMETER(0x458) & 0x80) && - !(PC98_SYSTEM_PARAMETER(0x45b) & 0x04)) - goto fail; - timeout = 100000000; - - /* Read the ARTIC. */ - sec = inw(0x5e); - - /* Wait for the ARTIC to changes. */ - start_sec = sec; - for (;;) { - sec = inw(0x5e); - if (sec != start_sec) - break; - if (--timeout == 0) - goto fail; - } - prev_count = getit(); - if (prev_count == 0 || prev_count > timer0_max_count) - goto fail; - tot_count = 0; - - start_sec = sec; - for (;;) { - sec = inw(0x5e); - count = getit(); - if (count == 0 || count > timer0_max_count) - goto fail; - if (count > prev_count) - tot_count += prev_count - (count - timer0_max_count); - else - tot_count += prev_count - count; - prev_count = count; - if ((sec == start_sec + 1200) || /* 1200 = 307.2KHz >> 8 */ - (sec < start_sec && - (u_int)sec + 0x10000 == (u_int)start_sec + 1200)) - break; - if (--timeout == 0) - goto fail; - } - - if (bootverbose) { - printf("i8254 clock: %u Hz\n", tot_count); - } - return (tot_count); - -fail: - if (bootverbose) - printf("failed, using default i8254 clock of %u Hz\n", - timer_freq); - return (timer_freq); -} - -static void -set_timer_freq(u_int freq, int intr_freq) -{ - int new_timer0_max_count; - - mtx_lock_spin(&clock_lock); - timer_freq = freq; - new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); - if (new_timer0_max_count != timer0_max_count) { - timer0_max_count = new_timer0_max_count; - outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); - outb(TIMER_CNTR0, timer0_max_count & 0xff); - outb(TIMER_CNTR0, timer0_max_count >> 8); - } - mtx_unlock_spin(&clock_lock); -} - -static void -i8254_restore(void) -{ - - mtx_lock_spin(&clock_lock); - outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); - outb(TIMER_CNTR0, timer0_max_count & 0xff); - outb(TIMER_CNTR0, timer0_max_count >> 8); - mtx_unlock_spin(&clock_lock); -} - - -/* - * Restore all the timers non-atomically (XXX: should be atomically). - * - * This function is called from pmtimer_resume() to restore all the timers. - * This should not be necessary, but there are broken laptops that do not - * restore all the timers on resume. - */ -void -timer_restore(void) -{ - - i8254_restore(); /* restore timer_freq and hz */ -} - -/* - * Initialize 8254 timer 0 early so that it can be used in DELAY(). - * XXX initialization of other timers is unintentionally left blank. - */ -void -startrtclock() -{ - u_int delta, freq; - - findcpuspeed(); - if (pc98_machine_type & M_8M) - timer_freq = 1996800L; /* 1.9968 MHz */ - else - timer_freq = 2457600L; /* 2.4576 MHz */ - - set_timer_freq(timer_freq, hz); - freq = calibrate_clocks(); -#ifdef CLK_CALIBRATION_LOOP - if (bootverbose) { - printf( - "Press a key on the console to abort clock calibration\n"); - while (cncheckc() == -1) - calibrate_clocks(); - } -#endif - - /* - * Use the calibrated i8254 frequency if it seems reasonable. - * Otherwise use the default, and don't use the calibrated i586 - * frequency. - */ - delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; - if (delta < timer_freq / 100) { -#ifndef CLK_USE_I8254_CALIBRATION - if (bootverbose) - printf( -"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); - freq = timer_freq; -#endif - timer_freq = freq; - } else { - if (bootverbose) - printf( - "%d Hz differs from default of %d Hz by more than 1%%\n", - freq, timer_freq); - } - - set_timer_freq(timer_freq, hz); - i8254_timecounter.tc_frequency = timer_freq; - tc_init(&i8254_timecounter); - - init_TSC(); -} - -static void -rtc_serialcombit(int i) -{ - outb(IO_RTC, ((i&0x01)<<5)|0x07); - DELAY(1); - outb(IO_RTC, ((i&0x01)<<5)|0x17); - DELAY(1); - outb(IO_RTC, ((i&0x01)<<5)|0x07); - DELAY(1); -} - -static void -rtc_serialcom(int i) -{ - rtc_serialcombit(i&0x01); - rtc_serialcombit((i&0x02)>>1); - rtc_serialcombit((i&0x04)>>2); - rtc_serialcombit((i&0x08)>>3); - outb(IO_RTC, 0x07); - DELAY(1); - outb(IO_RTC, 0x0f); - DELAY(1); - outb(IO_RTC, 0x07); - DELAY(1); -} - -static void -rtc_outb(int val) -{ - int s; - int sa = 0; - - for (s=0;s<8;s++) { - sa = ((val >> s) & 0x01) ? 0x27 : 0x07; - outb(IO_RTC, sa); /* set DI & CLK 0 */ - DELAY(1); - outb(IO_RTC, sa | 0x10); /* CLK 1 */ - DELAY(1); - } - outb(IO_RTC, sa & 0xef); /* CLK 0 */ -} - -static int -rtc_inb(void) -{ - int s; - int sa = 0; - - for (s=0;s<8;s++) { - sa |= ((inb(0x33) & 0x01) << s); - outb(IO_RTC, 0x17); /* CLK 1 */ - DELAY(1); - outb(IO_RTC, 0x07); /* CLK 0 */ - DELAY(2); - } - return sa; -} - -/* - * Initialize the time of day register, based on the time base which is, e.g. - * from a filesystem. - */ -void -inittodr(time_t base) -{ - unsigned long sec, days; - int year, month; - int y, m, s; - struct timespec ts; - int second, min, hour; - - if (base) { - s = splclock(); - ts.tv_sec = base; - ts.tv_nsec = 0; - tc_setclock(&ts); - splx(s); - } - - rtc_serialcom(0x03); /* Time Read */ - rtc_serialcom(0x01); /* Register shift command. */ - DELAY(20); - - second = bcd2bin(rtc_inb() & 0xff); /* sec */ - min = bcd2bin(rtc_inb() & 0xff); /* min */ - hour = bcd2bin(rtc_inb() & 0xff); /* hour */ - days = bcd2bin(rtc_inb() & 0xff) - 1; /* date */ - - month = (rtc_inb() >> 4) & 0x0f; /* month */ - for (m = 1; m < month; m++) - days += daysinmonth[m-1]; - year = bcd2bin(rtc_inb() & 0xff) + 1900; /* year */ - /* 2000 year problem */ - if (year < 1995) - year += 100; - if (year < 1970) - goto wrong_time; - for (y = 1970; y < year; y++) - days += DAYSPERYEAR + LEAPYEAR(y); - if ((month > 2) && LEAPYEAR(year)) - days ++; - sec = ((( days * 24 + - hour) * 60 + - min) * 60 + - second); - /* sec now contains the number of seconds, since Jan 1 1970, - in the local time zone */ - - s = splhigh(); - - sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); - - y = time_second - sec; - if (y <= -2 || y >= 2) { - /* badly off, adjust it */ - ts.tv_sec = sec; - ts.tv_nsec = 0; - tc_setclock(&ts); - } - splx(s); - return; - -wrong_time: - printf("Invalid time in real time clock.\n"); - printf("Check and reset the date immediately!\n"); -} - -/* - * Write system time back to RTC - */ -void -resettodr() -{ - unsigned long tm; - int y, m, s; - int wd; - - if (disable_rtc_set) - return; - - s = splclock(); - tm = time_second; - splx(s); - - rtc_serialcom(0x01); /* Register shift command. */ - - /* Calculate local time to put in RTC */ - - tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); - - rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ - rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ - rtc_outb(bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ - - /* We have now the days since 01-01-1970 in tm */ - wd = (tm + 4) % 7 + 1; /* Write back Weekday */ - for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); - tm >= m; - y++, m = DAYSPERYEAR + LEAPYEAR(y)) - tm -= m; - - /* Now we have the years in y and the day-of-the-year in tm */ - for (m = 0; ; m++) { - int ml; - - ml = daysinmonth[m]; - if (m == 1 && LEAPYEAR(y)) - ml++; - if (tm < ml) - break; - tm -= ml; - } - - m++; - rtc_outb(bin2bcd(tm+1)); /* Write back Day */ - rtc_outb((m << 4) | wd); /* Write back Month & Weekday */ - rtc_outb(bin2bcd(y%100)); /* Write back Year */ - - rtc_serialcom(0x02); /* Time set & Counter hold command. */ - rtc_serialcom(0x00); /* Register hold command. */ -} - - -/* - * Start both clocks running. - */ -void -cpu_initclocks() -{ - -#ifdef DEV_APIC - using_lapic_timer = lapic_setup_clock(); -#endif - /* - * If we aren't using the local APIC timer to drive the kernel - * clocks, setup the interrupt handler for the 8254 timer 0 so - * that it can drive hardclock(). - */ - if (!using_lapic_timer) { - intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL, - INTR_TYPE_CLK | INTR_FAST, NULL); - i8254_intsrc = intr_lookup_source(0); - if (i8254_intsrc != NULL) - i8254_pending = - i8254_intsrc->is_pic->pic_source_pending; - } - - init_TSC_tc(); -} - -void -cpu_startprofclock(void) -{ -} - -void -cpu_stopprofclock(void) -{ -} - -static int -sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS) -{ - int error; - u_int freq; - - /* - * Use `i8254' instead of `timer' in external names because `timer' - * is is too generic. Should use it everywhere. - */ - freq = timer_freq; - error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); - if (error == 0 && req->newptr != NULL) { - set_timer_freq(freq, hz); - i8254_timecounter.tc_frequency = freq; - } - return (error); -} - -SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", ""); - -static unsigned -i8254_get_timecount(struct timecounter *tc) -{ - u_int count; - u_int high, low; - u_int eflags; - - eflags = read_eflags(); - mtx_lock_spin(&clock_lock); - - /* Select timer0 and latch counter value. */ - outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); - - low = inb(TIMER_CNTR0); - high = inb(TIMER_CNTR0); - count = timer0_max_count - ((high << 8) | low); - if (count < i8254_lastcount || - (!i8254_ticked && (clkintr_pending || - ((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) && - i8254_pending != NULL && i8254_pending(i8254_intsrc))))) { - i8254_ticked = 1; - i8254_offset += timer0_max_count; - } - i8254_lastcount = count; - count += i8254_offset; - mtx_unlock_spin(&clock_lock); - return (count); -} - -#ifdef DEV_ISA -/* - * Attach to the ISA PnP descriptors for the timer and realtime clock. - */ -static struct isa_pnp_id attimer_ids[] = { - { 0x0001d041 /* PNP0100 */, "AT timer" }, - { 0x000bd041 /* PNP0B00 */, "AT realtime clock" }, - { 0 } -}; - -static int -attimer_probe(device_t dev) -{ - int result; - - if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0) - device_quiet(dev); - return(result); -} - -static int -attimer_attach(device_t dev) -{ - return(0); -} - -static device_method_t attimer_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, attimer_probe), - DEVMETHOD(device_attach, attimer_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX stop statclock? */ - DEVMETHOD(device_resume, bus_generic_resume), /* XXX restart statclock? */ - { 0, 0 } -}; - -static driver_t attimer_driver = { - "attimer", - attimer_methods, - 1, /* no softc */ -}; - -static devclass_t attimer_devclass; - -DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0); -#endif /* DEV_ISA */ diff --git a/sys/pc98/pc98/fd.c b/sys/pc98/pc98/fd.c deleted file mode 100644 index d2ead23..0000000 --- a/sys/pc98/pc98/fd.c +++ /dev/null @@ -1,2794 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Don Ahn. - * - * Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu) - * aided by the Linux floppy driver modifications from David Bateman - * (dbateman@eng.uts.edu.au). - * - * Copyright (c) 1993, 1994 by - * jc@irbs.UUCP (John Capo) - * vak@zebub.msk.su (Serge Vakulenko) - * ache@astral.msk.su (Andrew A. Chernov) - * - * Copyright (c) 1993, 1994, 1995 by - * joerg_wunsch@uriah.sax.de (Joerg Wunsch) - * dufault@hda.com (Peter Dufault) - * - * Copyright (c) 2001 Joerg Wunsch, - * joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $FreeBSD$ - */ - -#include "opt_fdc.h" - -#include <sys/param.h> -#include <sys/bio.h> -#include <sys/bus.h> -#include <sys/devicestat.h> -#include <sys/disk.h> -#include <sys/fcntl.h> -#include <sys/fdcio.h> -#include <sys/filio.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/rman.h> -#include <sys/systm.h> - -#include <machine/bus.h> -#include <machine/clock.h> -#include <machine/stdarg.h> - -#ifdef PC98 -#include <isa/isavar.h> -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> -#include <pc98/pc98/epsonio.h> -#include <pc98/pc98/fdreg.h> -#include <pc98/pc98/fdcvar.h> -#else -#include <isa/isavar.h> -#include <isa/isareg.h> -#include <dev/fdc/fdcreg.h> -#include <dev/fdc/fdcvar.h> -#include <isa/rtc.h> -#endif - -#define FDBIO_FORMAT BIO_CMD2 - -/* configuration flags for fdc */ -#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */ - -/* - * Stop retrying after this many DMA overruns. Since each retry takes - * one revolution, with 300 rpm., 25 retries take approximately 5 - * seconds which the read attempt will block in case the DMA overrun - * is persistent. - */ -#define FDC_DMAOV_MAX 25 - -/* - * Timeout value for the PIO loops to wait until the FDC main status - * register matches our expectations (request for master, direction - * bit). This is supposed to be a number of microseconds, although - * timing might actually not be very accurate. - * - * Timeouts of 100 msec are believed to be required for some broken - * (old) hardware. - */ -#define FDSTS_TIMEOUT 100000 - -/* - * Number of subdevices that can be used for different density types. - */ -#ifdef PC98 -#define NUMDENS 12 -#else -#define NUMDENS 16 -#endif - -#define FDBIO_RDSECTID BIO_CMD1 - -/* - * List of native drive densities. Order must match enum fd_drivetype - * in <sys/fdcio.h>. Upon attaching the drive, each of the - * programmable subdevices is initialized with the native density - * definition. - */ -#ifdef PC98 -static struct fd_type fd_native_types[] = -{ -{ 0 }, /* FDT_NONE */ -{ 0 }, /* FDT_360K */ -{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* FDT_12M */ -{ 0 }, /* FDT_720K */ -{ 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* FDT_144M */ -{ 0 }, /* FDT_288M */ -}; - -static struct fd_type fd_searchlist_12m[] = { -{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */ -#if 0 -{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */ -{ 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */ -#endif -{ 9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */ -{ 9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */ -{ 8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */ -{ 8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */ -#if 0 -{ 8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */ -#endif -}; -static struct fd_type fd_searchlist_144m[] = { -#if 0 -{ 21,2,0xFF,0x04,82,3444,2,2,0x0C,2,0,FL_MFM }, /* 1.72M in 3mode */ -{ 18,2,0xFF,0x1B,82,2952,2,2,0x54,1,0,FL_MFM }, /* 1.48M in 3mode */ -#endif -{ 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* 1.44M in 3mode */ -{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */ -#if 0 -{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */ -{ 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */ -#endif -{ 9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */ -{ 9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */ -{ 8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */ -{ 8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */ -#if 0 -{ 8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */ -{ 9,3,0xFF,0x35,82,1476,0,2,0x47,1,0,FL_MFM }, /* 1.48M 1024/sec 9sec */ -{ 10,3,0xFF,0x1B,82,1640,2,2,0x54,1,0,FL_MFM }, /* 1.64M in 3mode - Reserve */ -#endif -}; -#else /* PC98 */ -static struct fd_type fd_native_types[] = -{ -{ 0 }, /* FDT_NONE */ -{ 9,2,0xFF,0x2A,40, 720,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* FDT_360K */ -{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* FDT_12M */ -{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* FDT_720K */ -{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* FDT_144M */ -#if 0 /* we currently don't handle 2.88 MB */ -{ 36,2,0xFF,0x1B,80,5760,FDC_1MBPS, 2,0x4C,1,1,FL_MFM|FL_PERPND } /*FDT_288M*/ -#else -{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* FDT_144M */ -#endif -}; - -/* - * 360 KB 5.25" and 720 KB 3.5" drives don't have automatic density - * selection, they just start out with their native density (or lose). - * So 1.2 MB 5.25", 1.44 MB 3.5", and 2.88 MB 3.5" drives have their - * respective lists of densities to search for. - */ -static struct fd_type fd_searchlist_12m[] = { -{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* 1.2M */ -{ 9,2,0xFF,0x23,40, 720,FDC_300KBPS,2,0x50,1,0,FL_MFM|FL_2STEP }, /* 360K */ -{ 9,2,0xFF,0x20,80,1440,FDC_300KBPS,2,0x50,1,0,FL_MFM }, /* 720K */ -}; - -static struct fd_type fd_searchlist_144m[] = { -{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */ -{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */ -}; - -/* We search for 1.44M first since this is the most common case. */ -static struct fd_type fd_searchlist_288m[] = { -{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */ -#if 0 -{ 36,2,0xFF,0x1B,80,5760,FDC_1MBPS, 2,0x4C,1,1,FL_MFM|FL_PERPND } /* 2.88M */ -#endif -{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */ -}; -#endif /* PC98 */ - -#define MAX_SEC_SIZE (128 << 3) -#define MAX_CYLINDER 85 /* some people really stress their drives - * up to cyl 82 */ -#define MAX_HEAD 1 - -devclass_t fdc_devclass; - -/* - * Per drive structure (softc). - */ -struct fd_data { - struct fdc_data *fdc; /* pointer to controller structure */ - int fdsu; /* this units number on this controller */ - enum fd_drivetype type; /* drive type */ - struct fd_type *ft; /* pointer to current type descriptor */ - struct fd_type fts[NUMDENS]; /* type descriptors */ - int flags; -#define FD_OPEN 0x01 /* it's open */ -#define FD_NONBLOCK 0x02 /* O_NONBLOCK set */ -#define FD_ACTIVE 0x04 /* it's active */ -#define FD_MOTOR 0x08 /* motor should be on */ -#define FD_MOTOR_WAIT 0x10 /* motor coming up */ -#define FD_UA 0x20 /* force unit attention */ - int skip; - int hddrv; -#define FD_NO_TRACK -2 - int track; /* where we think the head is */ - int options; /* user configurable options, see fdcio.h */ - struct callout_handle toffhandle; - struct callout_handle tohandle; - struct devstat *device_stats; - struct cdev *masterdev; - device_t dev; - fdu_t fdu; -#ifdef PC98 - int pc98_trans; -#endif -}; - -struct fdc_ivars { - int fdunit; - int fdtype; -}; - -static devclass_t fd_devclass; - -/* configuration flags for fd */ -#define FD_TYPEMASK 0x0f /* drive type, matches enum - * fd_drivetype; on i386 machines, if - * given as 0, use RTC type for fd0 - * and fd1 */ -#define FD_DTYPE(flags) ((flags) & FD_TYPEMASK) -#define FD_NO_CHLINE 0x10 /* drive does not support changeline - * aka. unit attention */ -#define FD_NO_PROBE 0x20 /* don't probe drive (seek test), just - * assume it is there */ - -#ifdef EPSON_NRDISK -typedef unsigned int nrd_t; - -#define P_NRD_ADDRH 0xc24 -#define P_NRD_ADDRM 0xc22 -#define P_NRD_ADDRL 0xc20 -#define P_NRD_CHECK 0xc20 -#define P_NRD_DATA 0xc26 -#define P_NRD_LED 0xc36 -#define B_NRD_CHK 0x80 -#define B_NRD_LED 0x40 -#define A_NRD_INFO 0x2 -#define A_NRD_BASE 0x400 -#define NRD_STATUS 0x0 -#define NRD_ST0_HD 0x04 - -static fdu_t nrdu=-1; -static int nrdsec=0; -static nrd_t nrdblkn=0; -static nrd_t nrdaddr=0x0; - -#define nrd_check_ready() ({ \ - (epson_inb(P_NRD_CHECK) & B_NRD_CHK) ? 0 : 1; \ - }) -#define nrd_LED_on() epson_outb(P_NRD_LED, B_NRD_LED) -#define nrd_LED_off() epson_outb(P_NRD_LED, ~B_NRD_LED) -#define nrd_trac() ((int)(nrd_info(nrdaddr) & 0xff)) -#define nrd_head() ((int)((nrd_info(nrdaddr) >> 8) & 0xff)) -#define nrd_sec() ((int)(nrd_info(nrdaddr + 2) & 0xff)) -#define nrd_secsize() ((int)((nrd_info(A_NRD_INFO) >> 8) & 0xff)) -#define nrd_addrset(p) nrd_addr((nrd_t)((nrd_t)p+A_NRD_BASE)) - -static inline void -nrd_addr(addr) - nrd_t addr; -{ - epson_outb(P_NRD_ADDRH, (u_char)((addr >> 16) & 0x1f)); - epson_outb(P_NRD_ADDRM, (u_char)((addr >> 8) & 0xff)); - epson_outb(P_NRD_ADDRL, (u_char)(addr & 0xff)); -} - -static inline u_short -nrd_info(addr) - nrd_t addr; -{ - nrd_addr(addr); - return (epson_inw(P_NRD_DATA)); -} -#endif /* EPSON_NRDISK */ - -/* - * Throughout this file the following conventions will be used: - * - * fd is a pointer to the fd_data struct for the drive in question - * fdc is a pointer to the fdc_data struct for the controller - * fdu is the floppy drive unit number - * fdcu is the floppy controller unit number - * fdsu is the floppy drive unit number on that controller. (sub-unit) - */ - -/* - * Function declarations, same (chaotic) order as they appear in the - * file. Re-ordering is too late now, it would only obfuscate the - * diffs against old and offspring versions (like the PC98 one). - * - * Anyone adding functions here, please keep this sequence the same - * as below -- makes locating a particular function in the body much - * easier. - */ -static u_int8_t fdsts_rd(fdc_p); -static void fddata_wr(fdc_p, u_int8_t); -static u_int8_t fddata_rd(fdc_p); -static int fdc_err(struct fdc_data *, const char *); -static int enable_fifo(fdc_p fdc); -static int fd_sense_drive_status(fdc_p, int *); -static int fd_sense_int(fdc_p, int *, int *); -static int fd_read_status(fdc_p); -static int fd_probe(device_t); -static int fd_attach(device_t); -static int fd_detach(device_t); -static void set_motor(struct fdc_data *, int, int); -# define TURNON 1 -# define TURNOFF 0 -static timeout_t fd_turnoff; -static timeout_t fd_motor_on; -static void fd_turnon(struct fd_data *); -static void fdc_reset(fdc_p); -static int fd_in(struct fdc_data *, int *); -static int out_fdc(struct fdc_data *, int); -static d_open_t fdopen; -static d_close_t fdclose; -static d_strategy_t fdstrategy; -static void fdstart(struct fdc_data *); -static timeout_t fd_iotimeout; -static timeout_t fd_pseudointr; -static driver_intr_t fdc_intr; -static int fdcpio(fdc_p, long, caddr_t, u_int); -static int fdautoselect(struct cdev *); -static int fdstate(struct fdc_data *); -static int retrier(struct fdc_data *); -static void fdbiodone(struct bio *); -static int fdmisccmd(struct cdev *, u_int, void *); -static d_ioctl_t fdioctl; - -static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */ - -#ifdef FDC_DEBUG -/* CAUTION: fd_debug causes huge amounts of logging output */ -static int volatile fd_debug = 0; -#define TRACE0(arg) do { if (fd_debug) printf(arg); } while (0) -#define TRACE1(arg1, arg2) do { if (fd_debug) printf(arg1, arg2); } while (0) -#else /* FDC_DEBUG */ -#define TRACE0(arg) do { } while (0) -#define TRACE1(arg1, arg2) do { } while (0) -#endif /* FDC_DEBUG */ - -/* - * Bus space handling (access to low-level IO). - */ -#ifndef PC98 -void -fdout_wr(fdc_p fdc, u_int8_t v) -{ - bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v); -} -#endif - -static u_int8_t -fdsts_rd(fdc_p fdc) -{ - return bus_space_read_1(fdc->portt, fdc->porth, FDSTS+fdc->port_off); -} - -static void -fddata_wr(fdc_p fdc, u_int8_t v) -{ - bus_space_write_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off, v); -} - -static u_int8_t -fddata_rd(fdc_p fdc) -{ - return bus_space_read_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off); -} - -#ifdef PC98 -static void -fdctl_wr(fdc_p fdc, u_int8_t v) -{ - bus_space_write_1(fdc->portt, fdc->porth, FDCTL, v); -} -#endif - -#ifndef PC98 -static u_int8_t -fdin_rd(fdc_p fdc) -{ - return bus_space_read_1(fdc->portt, fdc->porth, FDIN); -} -#endif /* PC98 */ - -static struct cdevsw fd_cdevsw = { - .d_version = D_VERSION, - .d_open = fdopen, - .d_close = fdclose, - .d_read = physread, - .d_write = physwrite, - .d_ioctl = fdioctl, - .d_strategy = fdstrategy, - .d_name = "fd", - .d_flags = D_DISK | D_NEEDGIANT, -}; - -/* - * Auxiliary functions. Well, some only. Others are scattered - * throughout the entire file. - */ -static int -fdc_err(struct fdc_data *fdc, const char *s) -{ - fdc->fdc_errs++; - if (s) { - if (fdc->fdc_errs < FDC_ERRMAX) - device_printf(fdc->fdc_dev, "%s", s); - else if (fdc->fdc_errs == FDC_ERRMAX) - device_printf(fdc->fdc_dev, "too many errors, not " - "logging any more\n"); - } - - return FD_FAILED; -} - -/* - * fd_cmd: Send a command to the chip. Takes a varargs with this structure: - * Unit number, - * # of output bytes, output bytes as ints ..., - * # of input bytes, input bytes as ints ... - */ -int -fd_cmd(struct fdc_data *fdc, int n_out, ...) -{ - u_char cmd; - int n_in; - int n; - va_list ap; - - va_start(ap, n_out); - cmd = (u_char)(va_arg(ap, int)); - va_end(ap); - va_start(ap, n_out); - for (n = 0; n < n_out; n++) - { - if (out_fdc(fdc, va_arg(ap, int)) < 0) - { - char msg[50]; - snprintf(msg, sizeof(msg), - "cmd %x failed at out byte %d of %d\n", - cmd, n + 1, n_out); - return fdc_err(fdc, msg); - } - } - n_in = va_arg(ap, int); - for (n = 0; n < n_in; n++) - { - int *ptr = va_arg(ap, int *); - if (fd_in(fdc, ptr) < 0) - { - char msg[50]; - snprintf(msg, sizeof(msg), - "cmd %02x failed at in byte %d of %d\n", - cmd, n + 1, n_in); - return fdc_err(fdc, msg); - } - } - - return 0; -} - -static int -enable_fifo(fdc_p fdc) -{ - int i, j; - - if ((fdc->flags & FDC_HAS_FIFO) == 0) { - - /* - * Cannot use fd_cmd the normal way here, since - * this might be an invalid command. Thus we send the - * first byte, and check for an early turn of data directon. - */ - - if (out_fdc(fdc, I8207X_CONFIGURE) < 0) - return fdc_err(fdc, "Enable FIFO failed\n"); - - /* If command is invalid, return */ - j = FDSTS_TIMEOUT; - while ((i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM)) - != NE7_RQM && j-- > 0) { - if (i == (NE7_DIO | NE7_RQM)) { - fdc_reset(fdc); - return FD_FAILED; - } - DELAY(1); - } - if (j<0 || - fd_cmd(fdc, 3, - 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) { - fdc_reset(fdc); - return fdc_err(fdc, "Enable FIFO failed\n"); - } - fdc->flags |= FDC_HAS_FIFO; - return 0; - } - if (fd_cmd(fdc, 4, - I8207X_CONFIGURE, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) - return fdc_err(fdc, "Re-enable FIFO failed\n"); - return 0; -} - -static int -fd_sense_drive_status(fdc_p fdc, int *st3p) -{ - int st3; - - if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) - { - return fdc_err(fdc, "Sense Drive Status failed\n"); - } - if (st3p) - *st3p = st3; - - return 0; -} - -static int -fd_sense_int(fdc_p fdc, int *st0p, int *cylp) -{ - int cyl, st0, ret; - -#ifdef EPSON_NRDISK - if (fdc->fdu == nrdu) { - if (fdc->fd->track >= 0) nrdaddr = (fdc->fd->track + 1) * 8; - else nrdaddr = 0x0; - *st0p = nrd_head() ? NRD_ST0_HD : NRD_STATUS; - *cylp = nrd_trac(); - } - else { -#endif /* EPSON_NRDISK */ - ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0); - if (ret) { - (void)fdc_err(fdc, - "sense intr err reading stat reg 0\n"); - return ret; - } - - if (st0p) - *st0p = st0; - - if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) { - /* - * There doesn't seem to have been an interrupt. - */ - return FD_NOT_VALID; - } - - if (fd_in(fdc, &cyl) < 0) { - return fdc_err(fdc, "can't get cyl num\n"); - } - - if (cylp) - *cylp = cyl; - -#ifdef EPSON_NRDISK - } -#endif /* EPSON_NRDISK */ - return 0; -} - - -static int -fd_read_status(fdc_p fdc) -{ - int i, ret; - - for (i = ret = 0; i < 7; i++) { - /* - * XXX types are poorly chosen. Only bytes can be read - * from the hardware, but fdc->status[] wants u_ints and - * fd_in() gives ints. - */ - int status; - -#ifdef EPSON_NRDISK - if (fdc->fdu == nrdu) { - switch (i) { - case 0: fdc->status[i] = nrd_head() - ? NRD_ST0_HD : NRD_STATUS; break; - case 1: fdc->status[i] = NRD_STATUS; break; - case 2: fdc->status[i] = NRD_STATUS; break; - case 3: fdc->status[i] = nrd_trac(); break; - case 4: fdc->status[i] = nrd_head(); break; - case 5: fdc->status[i] = nrdsec; break; - case 6: fdc->status[i] = nrd_secsize(); break; - } - ret = 0; - } - else { -#endif /* EPSON_NRDISK */ - ret = fd_in(fdc, &status); - fdc->status[i] = status; - if (ret != 0) - break; -#ifdef EPSON_NRDISK - } -#endif /* EPSON_NRDISK */ - } - - if (ret == 0) - fdc->flags |= FDC_STAT_VALID; - else - fdc->flags &= ~FDC_STAT_VALID; - - return ret; -} - -#ifdef PC98 -static int pc98_trans = 0; /* 0 : HD , 1 : DD , 2 : 1.44 */ -static int pc98_trans_prev = -1; - -static void set_density(fdc_p fdc) -{ - /* always motor on */ - bus_space_write_1(fdc->sc_fdsiot, fdc->sc_fdsioh, 0, - (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC); - DELAY(100); - fdctl_wr(fdc, FDC_RST | FDC_DMAE); - /* in the case of note W, always inhibit 100ms timer */ -} - -static int pc98_fd_check_ready(fdu_t fdu) -{ - fd_p fd = devclass_get_softc(fd_devclass, fdu); - struct fdc_data *fdc = fd->fdc; - int retry = 0, status; - -#ifdef EPSON_NRDISK - if (fdu == nrdu) { - if (nrd_check_ready()) return 0; - else return -1; - } -#endif - while (retry++ < 30000) { - set_motor(fdc, fd->fdsu, TURNON); - out_fdc(fdc, NE7CMD_SENSED); /* Sense Drive Status */ - DELAY(100); - out_fdc(fdc, fdu); /* Drive number */ - DELAY(100); - if ((fd_in(fdc, &status) == 0) && (status & NE7_ST3_RD)) { - fdctl_wr(fdc, FDC_DMAE | FDC_MTON); - DELAY(10); - return 0; - } - } - return -1; -} - -static void pc98_fd_check_type(struct fd_data *fd) -{ - struct fdc_data *fdc; - - if (fd->type != FDT_NONE || fd->fdu < 0 || fd->fdu > 3) - return; - - fdc = fd->fdc; - - /* Look up what the BIOS thinks we have. */ - if (!((PC98_SYSTEM_PARAMETER(0x55c) >> fd->fdu) & 0x01)) { - fd->type = FDT_NONE; - return; - } - if ((PC98_SYSTEM_PARAMETER(0x5ae) >> fd->fdu) & 0x01) { - /* Check 3mode I/F */ - fd->pc98_trans = 0; - bus_space_write_1(fdc->sc_fdemsiot, fdc->sc_fdemsioh, 0, - (fd->fdu << 5) | 0x10); - if (!(bus_space_read_1(fdc->sc_fdemsiot, fdc->sc_fdemsioh, 0) & - 0x01)) { - fd->type = FDT_144M; - return; - } - device_printf(fd->dev, - "Warning: can't control 3mode I/F, fallback to 2mode.\n"); - } - - fd->type = FDT_12M; - - switch (epson_machine_id) { - case 0x20: - case 0x27: - if ((PC98_SYSTEM_PARAMETER(0x488) >> fd->fdu) & 0x01) { -#ifdef EPSON_NRDISK - if (nrd_check_ready()) { - nrd_LED_on(); - nrdu = fd->fdu; - } else -#endif - fd->type = FDT_NONE; - } - break; - } -} -#endif /* PC98 */ - -void -fdc_release_resources(struct fdc_data *fdc) -{ - device_t dev; - - dev = fdc->fdc_dev; - if (fdc->fdc_intr) { - BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq, - fdc->fdc_intr); - fdc->fdc_intr = NULL; - } - if (fdc->res_irq != 0) { - bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq, - fdc->res_irq); - bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq, - fdc->res_irq); - fdc->res_irq = NULL; - } -#ifndef PC98 - if (fdc->res_ctl != 0) { - bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl, - fdc->res_ctl); - bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl, - fdc->res_ctl); - fdc->res_ctl = NULL; - } -#endif -#ifdef PC98 - if (fdc->res_fdsio != 0) { - bus_deactivate_resource(dev, SYS_RES_IOPORT, 3, - fdc->res_fdsio); - bus_release_resource(dev, SYS_RES_IOPORT, 3, fdc->res_fdsio); - fdc->res_fdsio = NULL; - } - if (fdc->res_fdemsio != 0) { - bus_deactivate_resource(dev, SYS_RES_IOPORT, 4, - fdc->res_fdemsio); - bus_release_resource(dev, SYS_RES_IOPORT, 4, fdc->res_fdemsio); - fdc->res_fdemsio = NULL; - } -#endif - if (fdc->res_ioport != 0) { - bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, - fdc->res_ioport); - bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, - fdc->res_ioport); - fdc->res_ioport = NULL; - } - if (fdc->res_drq != 0) { - bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq, - fdc->res_drq); - bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq, - fdc->res_drq); - fdc->res_drq = NULL; - } -} - -/* - * Configuration/initialization stuff, per controller. - */ - -int -fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct fdc_ivars *ivars = device_get_ivars(child); - - switch (which) { - case FDC_IVAR_FDUNIT: - *result = ivars->fdunit; - break; - case FDC_IVAR_FDTYPE: - *result = ivars->fdtype; - break; - default: - return (ENOENT); - } - return (0); -} - -int -fdc_write_ivar(device_t dev, device_t child, int which, uintptr_t value) -{ - struct fdc_ivars *ivars = device_get_ivars(child); - - switch (which) { - case FDC_IVAR_FDUNIT: - ivars->fdunit = value; - break; - case FDC_IVAR_FDTYPE: - ivars->fdtype = value; - break; - default: - return (ENOENT); - } - return (0); -} - -int -fdc_initial_reset(struct fdc_data *fdc) -{ -#ifdef PC98 - /* see if it can handle a command */ - if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240), - NE7_SPEC_2(2, 0), 0)) - return (ENXIO); -#else - /* First, reset the floppy controller. */ - fdout_wr(fdc, 0); - DELAY(100); - fdout_wr(fdc, FDO_FRST); - - /* Then, see if it can handle a command. */ - if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), - NE7_SPEC_2(2, 0), 0)) - return (ENXIO); -#endif - return (0); -} - -int -fdc_detach(device_t dev) -{ - struct fdc_data *fdc; - int error; - - fdc = device_get_softc(dev); - - /* have our children detached first */ - if ((error = bus_generic_detach(dev))) - return (error); - -#ifdef PC98 - /* reset controller, turn motor off */ - fdc_reset(fdc); -#else - /* reset controller, turn motor off */ - fdout_wr(fdc, 0); -#endif - - fdc_release_resources(fdc); - return (0); -} - -/* - * Add a child device to the fdc controller. It will then be probed etc. - */ -device_t -fdc_add_child(device_t dev, const char *name, int unit) -{ - struct fdc_ivars *ivar; - device_t child; - - ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO); - if (ivar == NULL) - return (NULL); - child = device_add_child(dev, name, unit); - if (child == NULL) { - free(ivar, M_DEVBUF); - return (NULL); - } - device_set_ivars(child, ivar); - ivar->fdunit = unit; - ivar->fdtype = FDT_NONE; - if (resource_disabled(name, unit)) - device_disable(child); - return (child); -} - -int -fdc_attach(device_t dev) -{ - struct fdc_data *fdc; - int error; - - fdc = device_get_softc(dev); - fdc->fdc_dev = dev; - error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq, - INTR_TYPE_BIO | INTR_ENTROPY, fdc_intr, fdc, - &fdc->fdc_intr); - if (error) { - device_printf(dev, "cannot setup interrupt\n"); - return error; - } - fdc->fdcu = device_get_unit(dev); - fdc->flags |= FDC_NEEDS_RESET; - - fdc->state = DEVIDLE; - -#ifdef PC98 - /* reset controller, turn motor off, clear fdout mirror reg */ - fdc_reset(fdc); -#else - /* reset controller, turn motor off, clear fdout mirror reg */ - fdout_wr(fdc, fdc->fdout = 0); -#endif - bioq_init(&fdc->head); - - return (0); -} - -int -fdc_hints_probe(device_t dev) -{ - const char *name, *dname; - int i, error, dunit; - - /* - * Probe and attach any children. We should probably detect - * devices from the BIOS unless overridden. - */ - name = device_get_nameunit(dev); - i = 0; - while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) { - resource_int_value(dname, dunit, "drive", &dunit); - fdc_add_child(dev, dname, dunit); - } - - if ((error = bus_generic_attach(dev)) != 0) - return (error); - return (0); -} - -int -fdc_print_child(device_t me, device_t child) -{ - int retval = 0, flags; - - retval += bus_print_child_header(me, child); - retval += printf(" on %s drive %d", device_get_nameunit(me), - fdc_get_fdunit(child)); - if ((flags = device_get_flags(me)) != 0) - retval += printf(" flags %#x", flags); - retval += printf("\n"); - - return (retval); -} - -/* - * Configuration/initialization, per drive. - */ -static int -fd_probe(device_t dev) -{ - int i; -#ifndef PC98 - u_int st0, st3; -#endif - struct fd_data *fd; - struct fdc_data *fdc; - fdsu_t fdsu; - int flags, type; - - fdsu = fdc_get_fdunit(dev); - fd = device_get_softc(dev); - fdc = device_get_softc(device_get_parent(dev)); - flags = device_get_flags(dev); - - fd->dev = dev; - fd->fdc = fdc; - fd->fdsu = fdsu; - fd->fdu = device_get_unit(dev); - - /* Auto-probe if fdinfo is present, but always allow override. */ - type = FD_DTYPE(flags); - if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) { - fd->type = type; - goto done; - } else { - /* make sure fdautoselect() will be called */ - fd->flags = FD_UA; - fd->type = type; - } - -#ifdef PC98 - pc98_fd_check_type(fd); -#else -/* - * XXX I think using __i386__ is wrong here since we actually want to probe - * for the machine type, not the CPU type (so non-PC arch's like the PC98 will - * fail the probe). However, for whatever reason, testing for _MACHINE_ARCH - * == i386 breaks the test on FreeBSD/Alpha. - */ -#ifdef __i386__ - if (fd->type == FDT_NONE && (fd->fdu == 0 || fd->fdu == 1)) { - /* Look up what the BIOS thinks we have. */ - if (fd->fdu == 0) { - if ((fdc->flags & FDC_ISPCMCIA)) - /* - * Somewhat special. No need to force the - * user to set device flags, since the Y-E - * Data PCMCIA floppy is always a 1.44 MB - * device. - */ - fd->type = FDT_144M; - else - fd->type = (rtcin(RTC_FDISKETTE) & 0xf0) >> 4; - } else { - fd->type = rtcin(RTC_FDISKETTE) & 0x0f; - } - if (fd->type == FDT_288M_1) - fd->type = FDT_288M; - } -#endif /* __i386__ */ -#endif /* PC98 */ - - /* is there a unit? */ - if (fd->type == FDT_NONE) - return (ENXIO); - -#ifndef PC98 - /* select it */ - set_motor(fdc, fdsu, TURNON); - fdc_reset(fdc); /* XXX reset, then unreset, etc. */ - DELAY(1000000); /* 1 sec */ - - if ((flags & FD_NO_PROBE) == 0) { - /* If we're at track 0 first seek inwards. */ - if ((fd_sense_drive_status(fdc, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* Seek some steps... */ - if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { - /* ...wait a moment... */ - DELAY(300000); - /* make ctrlr happy: */ - fd_sense_int(fdc, 0, 0); - } - } - - for (i = 0; i < 2; i++) { - /* - * we must recalibrate twice, just in case the - * heads have been beyond cylinder 76, since - * most FDCs still barf when attempting to - * recalibrate more than 77 steps - */ - /* go back to 0: */ - if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) { - /* a second being enough for full stroke seek*/ - DELAY(i == 0 ? 1000000 : 300000); - - /* anything responding? */ - if (fd_sense_int(fdc, &st0, 0) == 0 && - (st0 & NE7_ST0_EC) == 0) - break; /* already probed succesfully */ - } - } - } - - set_motor(fdc, fdsu, TURNOFF); - - if ((flags & FD_NO_PROBE) == 0 && - (st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */ - return (ENXIO); -#endif /* PC98 */ - -done: -#ifndef PC98 - /* This doesn't work before the first reset. */ - if ((fdc->flags & FDC_HAS_FIFO) == 0 && - fdc->fdct == FDC_ENHANCED && - (device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0 && - enable_fifo(fdc) == 0) { - device_printf(device_get_parent(dev), - "FIFO enabled, %d bytes threshold\n", fifo_threshold); - } -#endif /* PC98 */ - -#ifdef PC98 - switch (fd->type) { - case FDT_144M: - device_set_desc(dev, "1.44M FDD"); - break; - case FDT_12M: -#ifdef EPSON_NRDISK - if (fd->fdu == nrdu) { - device_set_desc(dev, "EPSON RAM DRIVE"); - nrd_LED_off(); - } else - device_set_desc(dev, "1M/640K FDD"); -#else - device_set_desc(dev, "1M/640K FDD"); -#endif - break; - default: - return (ENXIO); - } -#else - switch (fd->type) { - case FDT_12M: - device_set_desc(dev, "1200-KB 5.25\" drive"); - break; - case FDT_144M: - device_set_desc(dev, "1440-KB 3.5\" drive"); - break; - case FDT_288M: - device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)"); - break; - case FDT_360K: - device_set_desc(dev, "360-KB 5.25\" drive"); - break; - case FDT_720K: - device_set_desc(dev, "720-KB 3.5\" drive"); - break; - default: - return (ENXIO); - } -#endif - fd->track = FD_NO_TRACK; - fd->fdc = fdc; - fd->fdsu = fdsu; - fd->options = 0; -#ifdef PC98 - fd->pc98_trans = 0; -#endif - callout_handle_init(&fd->toffhandle); - callout_handle_init(&fd->tohandle); - - /* initialize densities for subdevices */ -#ifdef PC98 - for (i = 0; i < NUMDENS; i++) - memcpy(fd->fts + i, fd_searchlist_144m + i, - sizeof(struct fd_type)); -#else - for (i = 0; i < NUMDENS; i++) - memcpy(fd->fts + i, fd_native_types + fd->type, - sizeof(struct fd_type)); -#endif - return (0); -} - -static int -fd_attach(device_t dev) -{ - struct fd_data *fd; - - fd = device_get_softc(dev); - fd->masterdev = make_dev(&fd_cdevsw, fd->fdu, - UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu); - fd->masterdev->si_drv1 = fd; - fd->device_stats = devstat_new_entry(device_get_name(dev), - device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, - DEVSTAT_PRIORITY_FD); - return (0); -} - -static int -fd_detach(device_t dev) -{ - struct fd_data *fd; - - fd = device_get_softc(dev); - untimeout(fd_turnoff, fd, fd->toffhandle); - devstat_remove_entry(fd->device_stats); - destroy_dev(fd->masterdev); - - return (0); -} - -static device_method_t fd_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, fd_probe), - DEVMETHOD(device_attach, fd_attach), - DEVMETHOD(device_detach, fd_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX */ - DEVMETHOD(device_resume, bus_generic_resume), /* XXX */ - - { 0, 0 } -}; - -static driver_t fd_driver = { - "fd", - fd_methods, - sizeof(struct fd_data) -}; - -DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, 0, 0); - -/* - * More auxiliary functions. - */ -/* - * Motor control stuff. - * Remember to not deselect the drive we're working on. - */ -static void -set_motor(struct fdc_data *fdc, int fdsu, int turnon) -{ -#ifdef PC98 - bus_space_write_1(fdc->sc_fdsiot, fdc->sc_fdsioh, 0, - (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC); - DELAY(10); - fdctl_wr(fdc, FDC_DMAE | FDC_MTON); -#else - int fdout; - - fdout = fdc->fdout; - if (turnon) { - fdout &= ~FDO_FDSEL; - fdout |= (FDO_MOEN0 << fdsu) | FDO_FDMAEN | FDO_FRST | fdsu; - } else - fdout &= ~(FDO_MOEN0 << fdsu); - fdc->fdout = fdout; - fdout_wr(fdc, fdout); - TRACE1("[0x%x->FDOUT]", fdout); -#endif -} - -static void -fd_turnoff(void *xfd) -{ - int s; - fd_p fd = xfd; - - TRACE1("[fd%d: turnoff]", fd->fdu); - - s = splbio(); - /* - * Don't turn off the motor yet if the drive is active. - * - * If we got here, this could only mean we missed an interrupt. - * This can e. g. happen on the Y-E Date PCMCIA floppy controller - * after a controller reset. Just schedule a pseudo-interrupt - * so the state machine gets re-entered. - */ - if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) { - fdc_intr(fd->fdc); - splx(s); - return; - } - - fd->flags &= ~FD_MOTOR; - set_motor(fd->fdc, fd->fdsu, TURNOFF); - splx(s); -} - -static void -fd_motor_on(void *xfd) -{ - int s; - fd_p fd = xfd; - - s = splbio(); - fd->flags &= ~FD_MOTOR_WAIT; - if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) - { - fdc_intr(fd->fdc); - } - splx(s); -} - -static void -fd_turnon(fd_p fd) -{ - if(!(fd->flags & FD_MOTOR)) - { - fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT); - set_motor(fd->fdc, fd->fdsu, TURNON); - timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */ - } -} - -static void -fdc_reset(fdc_p fdc) -{ - /* Try a reset, keep motor on */ -#ifdef PC98 - set_density(fdc); - if (pc98_machine_type & M_EPSON_PC98) - fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DD | FDC_MTON); - else - fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DMAE | FDC_MTON); - DELAY(200); - fdctl_wr(fdc, FDC_DMAE | FDC_MTON); - DELAY(10); -#else - fdout_wr(fdc, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); - TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); - DELAY(100); - /* enable FDC, but defer interrupts a moment */ - fdout_wr(fdc, fdc->fdout & ~FDO_FDMAEN); - TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN); - DELAY(100); - fdout_wr(fdc, fdc->fdout); - TRACE1("[0x%x->FDOUT]", fdc->fdout); -#endif - - /* XXX after a reset, silently believe the FDC will accept commands */ -#ifdef PC98 - (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, - NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0), - 0); -#else - (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, - NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), - 0); -#endif - if (fdc->flags & FDC_HAS_FIFO) - (void) enable_fifo(fdc); -} - -/* - * FDC IO functions, take care of the main status register, timeout - * in case the desired status bits are never set. - * - * These PIO loops initially start out with short delays between - * each iteration in the expectation that the required condition - * is usually met quickly, so it can be handled immediately. After - * about 1 ms, stepping is increased to achieve a better timing - * accuracy in the calls to DELAY(). - */ -static int -fd_in(struct fdc_data *fdc, int *ptr) -{ - int i, j, step; - - for (j = 0, step = 1; - (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && - j < FDSTS_TIMEOUT; - j += step) { - if (i == NE7_RQM) - return (fdc_err(fdc, "ready for output in input\n")); - if (j == 1000) - step = 1000; - DELAY(step); - } - if (j >= FDSTS_TIMEOUT) - return (fdc_err(fdc, bootverbose? "input ready timeout\n": 0)); -#ifdef FDC_DEBUG - i = fddata_rd(fdc); - TRACE1("[FDDATA->0x%x]", (unsigned char)i); - *ptr = i; - return (0); -#else /* !FDC_DEBUG */ - i = fddata_rd(fdc); - if (ptr) - *ptr = i; - return (0); -#endif /* FDC_DEBUG */ -} - -static int -out_fdc(struct fdc_data *fdc, int x) -{ - int i, j, step; - - for (j = 0, step = 1; - (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != NE7_RQM && - j < FDSTS_TIMEOUT; - j += step) { - if (i == (NE7_DIO|NE7_RQM)) - return (fdc_err(fdc, "ready for input in output\n")); - if (j == 1000) - step = 1000; - DELAY(step); - } - if (j >= FDSTS_TIMEOUT) - return (fdc_err(fdc, bootverbose? "output ready timeout\n": 0)); - - /* Send the command and return */ - fddata_wr(fdc, x); - TRACE1("[0x%x->FDDATA]", x); - return (0); -} - -/* - * Block device driver interface functions (interspersed with even more - * auxiliary functions). - */ -static int -fdopen(struct cdev *dev, int flags, int mode, struct thread *td) -{ - fd_p fd; - fdc_p fdc; -#ifdef PC98 - fdu_t fdu; -#endif - int rv, unitattn, dflags; - - fd = dev->si_drv1; - if (fd == NULL) - return (ENXIO); - fdc = fd->fdc; - if ((fdc == NULL) || (fd->type == FDT_NONE)) - return (ENXIO); -#ifdef PC98 - fdu = fd->fdu; -#endif - dflags = device_get_flags(fd->dev); - /* - * This is a bit bogus. It's still possible that e. g. a - * descriptor gets inherited to a child, but then it's at - * least for the same subdevice. By checking FD_OPEN here, we - * can ensure that a device isn't attempted to be opened with - * different densities at the same time where the second open - * could clobber the settings from the first one. - */ - if (fd->flags & FD_OPEN) - return (EBUSY); - -#ifdef PC98 - if (pc98_fd_check_ready(fdu) == -1) - return(EIO); -#endif - - if (flags & FNONBLOCK) { - /* - * Unfortunately, physio(9) discards its ioflag - * argument, thus preventing us from seeing the - * O_NONBLOCK bit. So we need to keep track - * ourselves. - */ - fd->flags |= FD_NONBLOCK; - fd->ft = 0; - } else { - /* - * Figure out a unit attention condition. - * - * If UA has been forced, proceed. - * - * If the drive has no changeline support, - * or if the drive parameters have been lost - * due to previous non-blocking access, - * assume a forced UA condition. - * - * If motor is off, turn it on for a moment - * and select our drive, in order to read the - * UA hardware signal. - * - * If motor is on, and our drive is currently - * selected, just read the hardware bit. - * - * If motor is on, but active for another - * drive on that controller, we are lost. We - * cannot risk to deselect the other drive, so - * we just assume a forced UA condition to be - * on the safe side. - */ - unitattn = 0; - if ((dflags & FD_NO_CHLINE) != 0 || - (fd->flags & FD_UA) != 0 || - fd->ft == 0) { - unitattn = 1; - fd->flags &= ~FD_UA; -#ifndef PC98 - } else if (fdc->fdout & (FDO_MOEN0 | FDO_MOEN1 | - FDO_MOEN2 | FDO_MOEN3)) { - if ((fdc->fdout & FDO_FDSEL) == fd->fdsu) - unitattn = fdin_rd(fdc) & FDI_DCHG; - else - unitattn = 1; - } else { - set_motor(fdc, fd->fdsu, TURNON); - unitattn = fdin_rd(fdc) & FDI_DCHG; - set_motor(fdc, fd->fdsu, TURNOFF); -#endif /* PC98 */ - } - if (unitattn && (rv = fdautoselect(dev)) != 0) - return (rv); - } - fd->flags |= FD_OPEN; - - if ((fdc->flags & FDC_NODMA) == 0) { - if (fdc->dmacnt++ == 0) { - isa_dma_acquire(fdc->dmachan); - isa_dmainit(fdc->dmachan, MAX_SEC_SIZE); - } - } - - /* - * Clearing the DMA overrun counter at open time is a bit messy. - * Since we're only managing one counter per controller, opening - * the second drive could mess it up. Anyway, if the DMA overrun - * condition is really persistent, it will eventually time out - * still. OTOH, clearing it here will ensure we'll at least start - * trying again after a previous (maybe even long ago) failure. - * Also, this is merely a stop-gap measure only that should not - * happen during normal operation, so we can tolerate it to be a - * bit sloppy about this. - */ - fdc->dma_overruns = 0; - - return 0; -} - -static int -fdclose(struct cdev *dev, int flags, int mode, struct thread *td) -{ - struct fd_data *fd; - fdc_p fdc; - - fd = dev->si_drv1; - fdc = fd->fdc; - fd->flags &= ~(FD_OPEN | FD_NONBLOCK); - fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR); - - if ((fdc->flags & FDC_NODMA) == 0) - if (--fdc->dmacnt == 0) - isa_dma_release(fdc->dmachan); - - return (0); -} - -static void -fdstrategy(struct bio *bp) -{ - long blknum, nblocks; - int s; - fdu_t fdu; - fdc_p fdc; - fd_p fd; - size_t fdblk; - - fd = bp->bio_dev->si_drv1; - fdu = fd->fdu; - fdc = fd->fdc; - bp->bio_resid = bp->bio_bcount; - if (fd->type == FDT_NONE || fd->ft == 0) { - if (fd->type != FDT_NONE && (fd->flags & FD_NONBLOCK)) - bp->bio_error = EAGAIN; - else - bp->bio_error = ENXIO; - bp->bio_flags |= BIO_ERROR; - goto bad; - } - fdblk = 128 << (fd->ft->secsize); - if (bp->bio_cmd != FDBIO_FORMAT && bp->bio_cmd != FDBIO_RDSECTID) { - if (fd->flags & FD_NONBLOCK) { - bp->bio_error = EAGAIN; - bp->bio_flags |= BIO_ERROR; - goto bad; - } - if (bp->bio_offset < 0) { - printf( - "fd%d: fdstrat: bad request offset = %ju, bcount = %ld\n", - fdu, (intmax_t)bp->bio_offset, bp->bio_bcount); - bp->bio_error = EINVAL; - bp->bio_flags |= BIO_ERROR; - goto bad; - } - if ((bp->bio_bcount % fdblk) != 0) { - bp->bio_error = EINVAL; - bp->bio_flags |= BIO_ERROR; - goto bad; - } - } - - /* - * Set up block calculations. - */ -#ifndef PC98 - if (bp->bio_offset >= ((off_t)128 << fd->ft->secsize) * fd->ft->size) { - bp->bio_error = EINVAL; - bp->bio_flags |= BIO_ERROR; - goto bad; - } -#endif - blknum = bp->bio_offset / fdblk; - nblocks = fd->ft->size; - if (blknum + bp->bio_bcount / fdblk > nblocks) { - if (blknum >= nblocks) { - if (bp->bio_cmd != BIO_READ) { - bp->bio_error = ENOSPC; - bp->bio_flags |= BIO_ERROR; - } - goto bad; /* not always bad, but EOF */ - } - bp->bio_bcount = (nblocks - blknum) * fdblk; - } - bp->bio_pblkno = blknum; - s = splbio(); - bioq_disksort(&fdc->head, bp); - untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */ - devstat_start_transaction_bio(fd->device_stats, bp); - device_busy(fd->dev); - fdstart(fdc); - splx(s); - return; - -bad: - biodone(bp); -} - -/* - * fdstart - * - * We have just queued something. If the controller is not busy - * then simulate the case where it has just finished a command - * So that it (the interrupt routine) looks on the queue for more - * work to do and picks up what we just added. - * - * If the controller is already busy, we need do nothing, as it - * will pick up our work when the present work completes. - */ -static void -fdstart(struct fdc_data *fdc) -{ - int s; - - s = splbio(); - if(fdc->state == DEVIDLE) - { - fdc_intr(fdc); - } - splx(s); -} - -static void -fd_iotimeout(void *xfdc) -{ - fdc_p fdc; - int s; - - fdc = xfdc; - TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); - - /* - * Due to IBM's brain-dead design, the FDC has a faked ready - * signal, hardwired to ready == true. Thus, any command - * issued if there's no diskette in the drive will _never_ - * complete, and must be aborted by resetting the FDC. - * Many thanks, Big Blue! - * The FDC must not be reset directly, since that would - * interfere with the state machine. Instead, pretend that - * the command completed but was invalid. The state machine - * will reset the FDC and retry once. - */ - s = splbio(); - fdc->status[0] = NE7_ST0_IC_IV; - fdc->flags &= ~FDC_STAT_VALID; - fdc->state = IOTIMEDOUT; - fdc_intr(fdc); - splx(s); -} - -/* Just ensure it has the right spl. */ -static void -fd_pseudointr(void *xfdc) -{ - int s; - - s = splbio(); - fdc_intr(xfdc); - splx(s); -} - -/* - * fdc_intr - * - * Keep calling the state machine until it returns a 0. - * Always called at splbio. - */ -static void -fdc_intr(void *xfdc) -{ - fdc_p fdc = xfdc; - while(fdstate(fdc)) - ; -} - -/* - * Magic pseudo-DMA initialization for YE FDC. Sets count and - * direction. - */ -#define SET_BCDR(fdc,wr,cnt,port) \ - bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port, \ - ((cnt)-1) & 0xff); \ - bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port + 1, \ - ((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f))); - -/* - * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy. - */ -static int -fdcpio(fdc_p fdc, long flags, caddr_t addr, u_int count) -{ - u_char *cptr = (u_char *)addr; - - if (flags == BIO_READ) { - if (fdc->state != PIOREAD) { - fdc->state = PIOREAD; - return(0); - } - SET_BCDR(fdc, 0, count, 0); - bus_space_read_multi_1(fdc->portt, fdc->porth, fdc->port_off + - FDC_YE_DATAPORT, cptr, count); - } else { - bus_space_write_multi_1(fdc->portt, fdc->porth, fdc->port_off + - FDC_YE_DATAPORT, cptr, count); - SET_BCDR(fdc, 0, count, 0); - } - return(1); -} - -/* - * Try figuring out the density of the media present in our device. - */ -static int -fdautoselect(struct cdev *dev) -{ - fd_p fd; - struct fd_type *fdtp; - struct fdc_readid id; - int i, n, oopts, rv; - - fd = dev->si_drv1; - - switch (fd->type) { - default: - return (ENXIO); - -#ifndef PC98 - case FDT_360K: - case FDT_720K: - /* no autoselection on those drives */ - fd->ft = fd_native_types + fd->type; - return (0); -#endif - - case FDT_12M: - fdtp = fd_searchlist_12m; - n = sizeof fd_searchlist_12m / sizeof(struct fd_type); - break; - - case FDT_144M: - fdtp = fd_searchlist_144m; - n = sizeof fd_searchlist_144m / sizeof(struct fd_type); - break; - -#ifndef PC98 - case FDT_288M: - fdtp = fd_searchlist_288m; - n = sizeof fd_searchlist_288m / sizeof(struct fd_type); - break; -#endif - } - - /* - * Try reading sector ID fields, first at cylinder 0, head 0, - * then at cylinder 2, head N. We don't probe cylinder 1, - * since for 5.25in DD media in a HD drive, there are no data - * to read (2 step pulses per media cylinder required). For - * two-sided media, the second probe always goes to head 1, so - * we can tell them apart from single-sided media. As a - * side-effect this means that single-sided media should be - * mentioned in the search list after two-sided media of an - * otherwise identical density. Media with a different number - * of sectors per track but otherwise identical parameters - * cannot be distinguished at all. - * - * If we successfully read an ID field on both cylinders where - * the recorded values match our expectation, we are done. - * Otherwise, we try the next density entry from the table. - * - * Stepping to cylinder 2 has the side-effect of clearing the - * unit attention bit. - */ - oopts = fd->options; - fd->options |= FDOPT_NOERRLOG | FDOPT_NORETRY; - for (i = 0; i < n; i++, fdtp++) { - fd->ft = fdtp; - - id.cyl = id.head = 0; - rv = fdmisccmd(dev, FDBIO_RDSECTID, &id); - if (rv != 0) - continue; - if (id.cyl != 0 || id.head != 0 || - id.secshift != fdtp->secsize) - continue; - id.cyl = 2; - id.head = fd->ft->heads - 1; - rv = fdmisccmd(dev, FDBIO_RDSECTID, &id); - if (id.cyl != 2 || id.head != fdtp->heads - 1 || - id.secshift != fdtp->secsize) - continue; - if (rv == 0) - break; - } - - fd->options = oopts; - if (i == n) { - if (bootverbose) - device_printf(fd->dev, "autoselection failed\n"); - fd->ft = 0; - return (EIO); - } else { - if (bootverbose) - device_printf(fd->dev, "autoselected %d KB medium\n", -#ifdef PC98 - (128 << (fd->ft->secsize)) * - fd->ft->size / 1024); -#else - fd->ft->size / 2); -#endif - return (0); - } -} - - -/* - * The controller state machine. - * - * If it returns a non zero value, it should be called again immediately. - */ -static int -fdstate(fdc_p fdc) -{ - struct fdc_readid *idp; - int read, format, rdsectid, cylinder, head, i, sec = 0, sectrac; - int st0, cyl, st3, idf, ne7cmd, mfm, steptrac; - unsigned long blknum; - fdu_t fdu = fdc->fdu; - fd_p fd; - register struct bio *bp; - struct fd_formb *finfo = NULL; - size_t fdblk; - - bp = fdc->bp; - if (bp == NULL) { - bp = bioq_takefirst(&fdc->head); - if (bp != NULL) - fdc->bp = bp; - } - if (bp == NULL) { - /* - * Nothing left for this controller to do, - * force into the IDLE state. - */ - fdc->state = DEVIDLE; - if (fdc->fd) { - device_printf(fdc->fdc_dev, - "unexpected valid fd pointer\n"); - fdc->fd = (fd_p) 0; - fdc->fdu = -1; - } - TRACE1("[fdc%d IDLE]", fdc->fdcu); - return (0); - } - fd = bp->bio_dev->si_drv1; - fdu = fd->fdu; - fdblk = 128 << fd->ft->secsize; - if (fdc->fd && (fd != fdc->fd)) - device_printf(fd->dev, "confused fd pointers\n"); - read = bp->bio_cmd == BIO_READ; - mfm = (fd->ft->flags & FL_MFM)? NE7CMD_MFM: 0; - steptrac = (fd->ft->flags & FL_2STEP)? 2: 1; - if (read) - idf = ISADMA_READ; - else - idf = ISADMA_WRITE; - format = bp->bio_cmd == FDBIO_FORMAT; - rdsectid = bp->bio_cmd == FDBIO_RDSECTID; - if (format) - finfo = (struct fd_formb *)bp->bio_data; - TRACE1("fd%d", fdu); - TRACE1("[%s]", fdstates[fdc->state]); - TRACE1("(0x%x)", fd->flags); - untimeout(fd_turnoff, fd, fd->toffhandle); - fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); - switch (fdc->state) - { - case DEVIDLE: - case FINDWORK: /* we have found new work */ - fdc->retry = 0; - fd->skip = 0; - fdc->fd = fd; - fdc->fdu = fdu; -#ifdef PC98 - pc98_trans = fd->ft->trans; - if (pc98_trans_prev != pc98_trans) { - int i; - set_density(fdc); - for (i = 0; i < 10; i++) { - outb(0x5f, 0); - outb(0x5f, 0); - } - pc98_trans_prev = pc98_trans; - } - if (pc98_trans != fd->pc98_trans) { - if (fd->type == FDT_144M) { - bus_space_write_1(fdc->sc_fdemsiot, - fdc->sc_fdemsioh, - 0, - (fdu << 5) | 0x10 | - (pc98_trans >> 1)); - outb(0x5f, 0); - outb(0x5f, 0); - } - fd->pc98_trans = pc98_trans; - } -#else - fdc->fdctl_wr(fdc, fd->ft->trans); -#endif - TRACE1("[0x%x->FDCTL]", fd->ft->trans); - /* - * If the next drive has a motor startup pending, then - * it will start up in its own good time. - */ - if(fd->flags & FD_MOTOR_WAIT) { - fdc->state = MOTORWAIT; - return (0); /* will return later */ - } - /* - * Maybe if it's not starting, it SHOULD be starting. - */ -#ifdef EPSON_NRDISK - if (fdu != nrdu) { - if (!(fd->flags & FD_MOTOR)) - { - fdc->state = MOTORWAIT; - fd_turnon(fdu); - return(0); - } - else /* at least make sure we are selected */ - { - set_motor(fdcu, fd->fdsu, TURNON); - } - } -#else /* !EPSON_NRDISK */ - if (!(fd->flags & FD_MOTOR)) - { - fdc->state = MOTORWAIT; - fd_turnon(fd); - return (0); /* will return later */ - } - else /* at least make sure we are selected */ - { - set_motor(fdc, fd->fdsu, TURNON); - } -#endif - if (fdc->flags & FDC_NEEDS_RESET) { - fdc->state = RESETCTLR; - fdc->flags &= ~FDC_NEEDS_RESET; - } else - fdc->state = DOSEEK; - return (1); /* will return immediately */ - - case DOSEEK: - blknum = bp->bio_pblkno + fd->skip / fdblk; - cylinder = blknum / (fd->ft->sectrac * fd->ft->heads); - if (cylinder == fd->track) - { - fdc->state = SEEKCOMPLETE; - return (1); /* will return immediately */ - } -#ifdef PC98 - pc98_fd_check_ready(fdu); -#endif - if (fd_cmd(fdc, 3, NE7CMD_SEEK, - fd->fdsu, cylinder * steptrac, 0)) - { - /* - * Seek command not accepted, looks like - * the FDC went off to the Saints... - */ - fdc->retry = 6; /* try a reset */ - return(retrier(fdc)); - } - fd->track = FD_NO_TRACK; - fdc->state = SEEKWAIT; - return(0); /* will return later */ - - case SEEKWAIT: - /* allow heads to settle */ - timeout(fd_pseudointr, fdc, hz / 16); - fdc->state = SEEKCOMPLETE; - return(0); /* will return later */ - - case SEEKCOMPLETE : /* seek done, start DMA */ - blknum = bp->bio_pblkno + fd->skip / fdblk; - cylinder = blknum / (fd->ft->sectrac * fd->ft->heads); - - /* Make sure seek really happened. */ - if(fd->track == FD_NO_TRACK) { - int descyl = cylinder * steptrac; - do { - /* - * This might be a "ready changed" interrupt, - * which cannot really happen since the - * RDY pin is hardwired to + 5 volts. This - * generally indicates a "bouncing" intr - * line, so do one of the following: - * - * When running on an enhanced FDC that is - * known to not go stuck after responding - * with INVALID, fetch all interrupt states - * until seeing either an INVALID or a - * real interrupt condition. - * - * When running on a dumb old NE765, give - * up immediately. The controller will - * provide up to four dummy RC interrupt - * conditions right after reset (for the - * corresponding four drives), so this is - * our only chance to get notice that it - * was not the FDC that caused the interrupt. - */ - if (fd_sense_int(fdc, &st0, &cyl) - == FD_NOT_VALID) - return (0); /* will return later */ - if(fdc->fdct == FDC_NE765 - && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) - return (0); /* hope for a real intr */ - } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); - - if (0 == descyl) { - int failed = 0; - /* - * seek to cyl 0 requested; make sure we are - * really there - */ - if (fd_sense_drive_status(fdc, &st3)) - failed = 1; -#ifdef EPSON_NRDISK - if (fdu == nrdu) st3 = NE7_ST3_T0; -#endif /* EPSON_NRDISK */ - if ((st3 & NE7_ST3_T0) == 0) { - printf( - "fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n", - fdu, st3, NE7_ST3BITS); - failed = 1; - } - - if (failed) { - if(fdc->retry < 3) - fdc->retry = 3; - return (retrier(fdc)); - } - } -#ifdef EPSON_NRDISK - if (fdu == nrdu) cyl = descyl; -#endif - - if (cyl != descyl) { - printf( - "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", - fdu, descyl, cyl, st0); - if (fdc->retry < 3) - fdc->retry = 3; - return (retrier(fdc)); - } - } - - fd->track = cylinder; - if (format) - fd->skip = (char *)&(finfo->fd_formb_cylno(0)) - - (char *)finfo; -#ifdef EPSON_NRDISK - if (fdu != nrdu) { -#endif /* EPSON_NRDISK */ - if (!rdsectid && !(fdc->flags & FDC_NODMA)) - isa_dmastart(idf, bp->bio_data+fd->skip, - format ? bp->bio_bcount : fdblk, fdc->dmachan); - blknum = bp->bio_pblkno + fd->skip / fdblk; - sectrac = fd->ft->sectrac; - sec = blknum % (sectrac * fd->ft->heads); - head = sec / sectrac; - sec = sec % sectrac + 1; - if (head != 0 && fd->ft->offset_side2 != 0) - sec += fd->ft->offset_side2; - fd->hddrv = ((head&1)<<2)+fdu; - - if(format || !(read || rdsectid)) - { - /* make sure the drive is writable */ - if(fd_sense_drive_status(fdc, &st3) != 0) - { - /* stuck controller? */ - if (!(fdc->flags & FDC_NODMA)) - isa_dmadone(idf, - bp->bio_data + fd->skip, - format ? bp->bio_bcount : fdblk, - fdc->dmachan); - fdc->retry = 6; /* reset the beast */ - return (retrier(fdc)); - } - if(st3 & NE7_ST3_WP) - { - /* - * XXX YES! this is ugly. - * in order to force the current operation - * to fail, we will have to fake an FDC - * error - all error handling is done - * by the retrier() - */ - fdc->status[0] = NE7_ST0_IC_AT; - fdc->status[1] = NE7_ST1_NW; - fdc->status[2] = 0; - fdc->status[3] = fd->track; - fdc->status[4] = head; - fdc->status[5] = sec; - fdc->retry = 8; /* break out immediately */ - fdc->state = IOTIMEDOUT; /* not really... */ - return (1); /* will return immediately */ - } - } - - if (format) { - ne7cmd = NE7CMD_FORMAT | mfm; - if (fdc->flags & FDC_NODMA) { - /* - * This seems to be necessary for - * whatever obscure reason; if we omit - * it, we end up filling the sector ID - * fields of the newly formatted track - * entirely with garbage, causing - * `wrong cylinder' errors all over - * the place when trying to read them - * back. - * - * Umpf. - */ - SET_BCDR(fdc, 1, bp->bio_bcount, 0); - - (void)fdcpio(fdc,bp->bio_cmd, - bp->bio_data+fd->skip, - bp->bio_bcount); - - } - /* formatting */ - if(fd_cmd(fdc, 6, ne7cmd, head << 2 | fdu, - finfo->fd_formb_secshift, - finfo->fd_formb_nsecs, - finfo->fd_formb_gaplen, - finfo->fd_formb_fillbyte, 0)) { - /* controller fell over */ - if (!(fdc->flags & FDC_NODMA)) - isa_dmadone(idf, - bp->bio_data + fd->skip, - format ? bp->bio_bcount : fdblk, - fdc->dmachan); - fdc->retry = 6; - return (retrier(fdc)); - } - } else if (rdsectid) { - ne7cmd = NE7CMD_READID | mfm; - if (fd_cmd(fdc, 2, ne7cmd, head << 2 | fdu, 0)) { - /* controller jamming */ - fdc->retry = 6; - return (retrier(fdc)); - } - } else { - /* read or write operation */ - ne7cmd = (read ? NE7CMD_READ | NE7CMD_SK : NE7CMD_WRITE) | mfm; - if (fdc->flags & FDC_NODMA) { - /* - * This seems to be necessary even when - * reading data. - */ - SET_BCDR(fdc, 1, fdblk, 0); - - /* - * Perform the write pseudo-DMA before - * the WRITE command is sent. - */ - if (!read) - (void)fdcpio(fdc,bp->bio_cmd, - bp->bio_data+fd->skip, - fdblk); - } - if (fd_cmd(fdc, 9, - ne7cmd, - head << 2 | fdu, /* head & unit */ - fd->track, /* track */ - head, - sec, /* sector + 1 */ - fd->ft->secsize, /* sector size */ - sectrac, /* sectors/track */ - fd->ft->gap, /* gap size */ - fd->ft->datalen, /* data length */ - 0)) { - /* the beast is sleeping again */ - if (!(fdc->flags & FDC_NODMA)) - isa_dmadone(idf, - bp->bio_data + fd->skip, - format ? bp->bio_bcount : fdblk, - fdc->dmachan); - fdc->retry = 6; - return (retrier(fdc)); - } - } - if (!rdsectid && (fdc->flags & FDC_NODMA)) - /* - * If this is a read, then simply await interrupt - * before performing PIO. - */ - if (read && !fdcpio(fdc,bp->bio_cmd, - bp->bio_data+fd->skip,fdblk)) { - fd->tohandle = timeout(fd_iotimeout, fdc, hz); - return(0); /* will return later */ - } - - /* - * Write (or format) operation will fall through and - * await completion interrupt. - */ - fdc->state = IOCOMPLETE; - fd->tohandle = timeout(fd_iotimeout, fdc, hz); - return (0); /* will return later */ -#ifdef EPSON_NRDISK - } - else { - nrdblkn = (nrd_t)((unsigned long)bp->b_blkno*DEV_BSIZE/fdblk - + fd->skip/fdblk); - nrd_LED_on(); - nrd_addrset(fdblk * nrdblkn); - while (!nrd_check_ready()) DELAY(1); - if (read) epson_insw(P_NRD_DATA, - bp->bio_data + fd->skip, - fdblk / sizeof(short)); - else epson_outsw(P_NRD_DATA, - bp->bio_data + fd->skip, - (format ? bp->bio_bcount : fdblk) - / sizeof(short)); - - blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/fdblk - + fd->skip/fdblk; - sectrac = fd->ft->sectrac; - sec = blknum % (sectrac * fd->ft->heads); - head = sec / sectrac; - sec = sec % sectrac + 1; - fd->hddrv = ((head&1)<<2)+fdu; - - if (nrdsec++ >= nrd_sec()) - nrdaddr = (nrd_t)(fd->track * 8 + head * 4); - nrdsec = sec; - fdc->state = IOCOMPLETE; - } -#endif - - case PIOREAD: - /* - * Actually perform the PIO read. The IOCOMPLETE case - * removes the timeout for us. - */ - (void)fdcpio(fdc,bp->bio_cmd,bp->bio_data+fd->skip,fdblk); - fdc->state = IOCOMPLETE; - /* FALLTHROUGH */ - case IOCOMPLETE: /* IO done, post-analyze */ -#ifdef EPSON_NRDISK - if (fdu != nrdu) - untimeout(fd_iotimeout, fdc, fd->tohandle); -#else - untimeout(fd_iotimeout, fdc, fd->tohandle); -#endif - - if (fd_read_status(fdc)) { - if (!rdsectid && !(fdc->flags & FDC_NODMA)) - isa_dmadone(idf, bp->bio_data + fd->skip, - format ? bp->bio_bcount : fdblk, - fdc->dmachan); - if (fdc->retry < 6) - fdc->retry = 6; /* force a reset */ - return (retrier(fdc)); - } - - fdc->state = IOTIMEDOUT; - - /* FALLTHROUGH */ - case IOTIMEDOUT: -#ifdef EPSON_NRDISK - if (fdu != nrdu) { -#endif /* EPSON_NRDISK */ - if (!rdsectid && !(fdc->flags & FDC_NODMA)) - isa_dmadone(idf, bp->bio_data + fd->skip, - format ? bp->bio_bcount : fdblk, fdc->dmachan); -#ifdef EPSON_NRDISK - } - else nrd_LED_off(); -#endif /* EPSON_NRDISK */ - if (fdc->status[0] & NE7_ST0_IC) { - if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT - && fdc->status[1] & NE7_ST1_OR) { - /* - * DMA overrun. Someone hogged the bus and - * didn't release it in time for the next - * FDC transfer. - * - * We normally restart this without bumping - * the retry counter. However, in case - * something is seriously messed up (like - * broken hardware), we rather limit the - * number of retries so the IO operation - * doesn't block indefinately. - */ - if (fdc->dma_overruns++ < FDC_DMAOV_MAX) { - fdc->state = SEEKCOMPLETE; - return (1);/* will return immediately */ - } /* else fall through */ - } - if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV - && fdc->retry < 6) - fdc->retry = 6; /* force a reset */ - else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT - && fdc->status[2] & NE7_ST2_WC - && fdc->retry < 3) - fdc->retry = 3; /* force recalibrate */ - return (retrier(fdc)); - } - /* All OK */ - if (rdsectid) { - /* copy out ID field contents */ - idp = (struct fdc_readid *)bp->bio_data; - idp->cyl = fdc->status[3]; - idp->head = fdc->status[4]; - idp->sec = fdc->status[5]; - idp->secshift = fdc->status[6]; - } - /* Operation successful, retry DMA overruns again next time. */ - fdc->dma_overruns = 0; - fd->skip += fdblk; - if (!rdsectid && !format && fd->skip < bp->bio_bcount) { - /* set up next transfer */ - fdc->state = DOSEEK; - } else { - /* ALL DONE */ - fd->skip = 0; - bp->bio_resid = 0; - fdc->bp = NULL; - device_unbusy(fd->dev); - biofinish(bp, fd->device_stats, 0); - fdc->fd = (fd_p) 0; - fdc->fdu = -1; - fdc->state = FINDWORK; - } - return (1); /* will return immediately */ - - case RESETCTLR: - fdc_reset(fdc); - fdc->retry++; - fdc->state = RESETCOMPLETE; - return (0); /* will return later */ - - case RESETCOMPLETE: - /* - * Discard all the results from the reset so that they - * can't cause an unexpected interrupt later. - */ - for (i = 0; i < 4; i++) - (void)fd_sense_int(fdc, &st0, &cyl); - fdc->state = STARTRECAL; - /* FALLTHROUGH */ - case STARTRECAL: -#ifdef PC98 - pc98_fd_check_ready(fdu); -#endif - if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) { - /* arrgl */ - fdc->retry = 6; - return (retrier(fdc)); - } - fdc->state = RECALWAIT; - return (0); /* will return later */ - - case RECALWAIT: - /* allow heads to settle */ - timeout(fd_pseudointr, fdc, hz / 8); - fdc->state = RECALCOMPLETE; - return (0); /* will return later */ - - case RECALCOMPLETE: - do { - /* - * See SEEKCOMPLETE for a comment on this: - */ - if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) - return (0); /* will return later */ - if(fdc->fdct == FDC_NE765 - && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC) - return (0); /* hope for a real intr */ - } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); -#ifdef EPSON_NRDISK - if (fdu == nrdu) { - st0 = NE7_ST0_IC_NT; - cyl = 0; - } -#endif - if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0) - { - if(fdc->retry > 3) - /* - * A recalibrate from beyond cylinder 77 - * will "fail" due to the FDC limitations; - * since people used to complain much about - * the failure message, try not logging - * this one if it seems to be the first - * time in a line. - */ - printf("fd%d: recal failed ST0 %b cyl %d\n", - fdu, st0, NE7_ST0BITS, cyl); - if(fdc->retry < 3) fdc->retry = 3; - return (retrier(fdc)); - } - fd->track = 0; - /* Seek (probably) necessary */ - fdc->state = DOSEEK; - return (1); /* will return immediately */ - - case MOTORWAIT: - if(fd->flags & FD_MOTOR_WAIT) - { - return (0); /* time's not up yet */ - } - if (fdc->flags & FDC_NEEDS_RESET) { - fdc->state = RESETCTLR; - fdc->flags &= ~FDC_NEEDS_RESET; - } else - fdc->state = DOSEEK; - return (1); /* will return immediately */ - - default: - device_printf(fdc->fdc_dev, "unexpected FD int->"); - if (fd_read_status(fdc) == 0) - printf("FDC status :%x %x %x %x %x %x %x ", - fdc->status[0], - fdc->status[1], - fdc->status[2], - fdc->status[3], - fdc->status[4], - fdc->status[5], - fdc->status[6] ); - else - printf("No status available "); - if (fd_sense_int(fdc, &st0, &cyl) != 0) - { - printf("[controller is dead now]\n"); - return (0); /* will return later */ - } - printf("ST0 = %x, PCN = %x\n", st0, cyl); - return (0); /* will return later */ - } - /* noone should ever get here */ -} - -static int -retrier(struct fdc_data *fdc) -{ - struct bio *bp; - struct fd_data *fd; - int fdu; - - bp = fdc->bp; - - /* XXX shouldn't this be cached somewhere? */ - fd = bp->bio_dev->si_drv1; - fdu = fd->fdu; - if (fd->options & FDOPT_NORETRY) - goto fail; - - switch (fdc->retry) { - case 0: case 1: case 2: - fdc->state = SEEKCOMPLETE; - break; - case 3: case 4: case 5: - fdc->state = STARTRECAL; - break; - case 6: - fdc->state = RESETCTLR; - break; - case 7: - break; - default: - fail: - if ((fd->options & FDOPT_NOERRLOG) == 0) { - disk_err(bp, "hard error", - fdc->fd->skip / DEV_BSIZE, 0); - if (fdc->flags & FDC_STAT_VALID) { - printf( - " (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n", - fdc->status[0], NE7_ST0BITS, - fdc->status[1], NE7_ST1BITS, - fdc->status[2], NE7_ST2BITS, - fdc->status[3], fdc->status[4], - fdc->status[5]); - } - else - printf(" (No status)\n"); - } - if ((fd->options & FDOPT_NOERROR) == 0) { - bp->bio_flags |= BIO_ERROR; - bp->bio_error = EIO; - bp->bio_resid = bp->bio_bcount - fdc->fd->skip; - } else - bp->bio_resid = 0; - fdc->bp = NULL; - fdc->fd->skip = 0; - device_unbusy(fd->dev); - biofinish(bp, fdc->fd->device_stats, 0); - fdc->state = FINDWORK; - fdc->flags |= FDC_NEEDS_RESET; - fdc->fd = (fd_p) 0; - fdc->fdu = -1; - return (1); - } - fdc->retry++; - return (1); -} - -static void -fdbiodone(struct bio *bp) -{ - wakeup(bp); -} - -static int -fdmisccmd(struct cdev *dev, u_int cmd, void *data) -{ - fdu_t fdu; - fd_p fd; - struct bio *bp; - struct fd_formb *finfo; - struct fdc_readid *idfield; - size_t fdblk; - int error; - - fd = dev->si_drv1; - fdu = fd->fdu; - fdblk = 128 << fd->ft->secsize; - finfo = (struct fd_formb *)data; - idfield = (struct fdc_readid *)data; - - bp = malloc(sizeof(struct bio), M_TEMP, M_WAITOK | M_ZERO); - - /* - * Set up a bio request for fdstrategy(). bio_offset is faked - * so that fdstrategy() will seek to the the requested - * cylinder, and use the desired head. - */ - bp->bio_cmd = cmd; - if (cmd == FDBIO_FORMAT) { - bp->bio_offset = - (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) + - finfo->head * fd->ft->sectrac) * fdblk; - bp->bio_bcount = sizeof(struct fd_idfield_data) * - finfo->fd_formb_nsecs; - } else if (cmd == FDBIO_RDSECTID) { - bp->bio_offset = - (idfield->cyl * (fd->ft->sectrac * fd->ft->heads) + - idfield->head * fd->ft->sectrac) * fdblk; - bp->bio_bcount = sizeof(struct fdc_readid); - } else - panic("wrong cmd in fdmisccmd()"); - bp->bio_data = data; - bp->bio_dev = dev; - bp->bio_done = fdbiodone; - bp->bio_flags = 0; - - /* Now run the command. */ - fdstrategy(bp); - error = biowait(bp, "fdcmd"); - - free(bp, M_TEMP); - return (error); -} - -static int -fdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) -{ - fdu_t fdu; - fd_p fd; - struct fdc_status *fsp; - struct fdc_readid *rid; - int error; - - fd = dev->si_drv1; - fdu = fd->fdu; - -#ifdef PC98 - pc98_fd_check_ready(fdu); -#endif - - /* - * First, handle everything that could be done with - * FD_NONBLOCK still being set. - */ - switch (cmd) { - - case DIOCGMEDIASIZE: - if (fd->ft == 0) - return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO); - *(off_t *)addr = (128 << (fd->ft->secsize)) * fd->ft->size; - return (0); - - case DIOCGSECTORSIZE: - if (fd->ft == 0) - return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO); - *(u_int *)addr = 128 << (fd->ft->secsize); - return (0); - - case FIONBIO: - if (*(int *)addr != 0) - fd->flags |= FD_NONBLOCK; - else { - if (fd->ft == 0) { - /* - * No drive type has been selected yet, - * cannot turn FNONBLOCK off. - */ - return (EINVAL); - } - fd->flags &= ~FD_NONBLOCK; - } - return (0); - - case FIOASYNC: - /* keep the generic fcntl() code happy */ - return (0); - - case FD_GTYPE: /* get drive type */ - if (fd->ft == 0) - /* no type known yet, return the native type */ - *(struct fd_type *)addr = fd_native_types[fd->type]; - else - *(struct fd_type *)addr = *fd->ft; - return (0); - - case FD_STYPE: /* set drive type */ - /* - * Allow setting drive type temporarily iff - * currently unset. Used for fdformat so any - * user can set it, and then start formatting. - */ - if (fd->ft) - return (EINVAL); /* already set */ - fd->fts[0] = *(struct fd_type *)addr; - fd->ft = &fd->fts[0]; - fd->flags |= FD_UA; - return (0); - - case FD_GOPTS: /* get drive options */ - *(int *)addr = fd->options + FDOPT_AUTOSEL; - return (0); - - case FD_SOPTS: /* set drive options */ - fd->options = *(int *)addr & ~FDOPT_AUTOSEL; - return (0); - -#ifdef FDC_DEBUG - case FD_DEBUG: - if ((fd_debug != 0) != (*(int *)addr != 0)) { - fd_debug = (*(int *)addr != 0); - printf("fd%d: debugging turned %s\n", - fd->fdu, fd_debug ? "on" : "off"); - } - return (0); -#endif - - case FD_CLRERR: - if (suser(td) != 0) - return (EPERM); - fd->fdc->fdc_errs = 0; - return (0); - - case FD_GSTAT: - fsp = (struct fdc_status *)addr; - if ((fd->fdc->flags & FDC_STAT_VALID) == 0) - return (EINVAL); - memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int)); - return (0); - - case FD_GDTYPE: - *(enum fd_drivetype *)addr = fd->type; - return (0); - } - - /* - * Now handle everything else. Make sure we have a valid - * drive type. - */ - if (fd->flags & FD_NONBLOCK) - return (EAGAIN); - if (fd->ft == 0) - return (ENXIO); - error = 0; - - switch (cmd) { - - case FD_FORM: - if ((flag & FWRITE) == 0) - return (EBADF); /* must be opened for writing */ - if (((struct fd_formb *)addr)->format_version != - FD_FORMAT_VERSION) - return (EINVAL); /* wrong version of formatting prog */ - error = fdmisccmd(dev, FDBIO_FORMAT, addr); - break; - - case FD_GTYPE: /* get drive type */ - *(struct fd_type *)addr = *fd->ft; - break; - - case FD_STYPE: /* set drive type */ - /* this is considered harmful; only allow for superuser */ - if (suser(td) != 0) - return (EPERM); - *fd->ft = *(struct fd_type *)addr; - break; - - case FD_GOPTS: /* get drive options */ - *(int *)addr = fd->options; - break; - - case FD_SOPTS: /* set drive options */ - fd->options = *(int *)addr; - break; - -#ifdef FDC_DEBUG - case FD_DEBUG: - if ((fd_debug != 0) != (*(int *)addr != 0)) { - fd_debug = (*(int *)addr != 0); - printf("fd%d: debugging turned %s\n", - fd->fdu, fd_debug ? "on" : "off"); - } - break; -#endif - - case FD_CLRERR: - if (suser(td) != 0) - return (EPERM); - fd->fdc->fdc_errs = 0; - break; - - case FD_GSTAT: - fsp = (struct fdc_status *)addr; - if ((fd->fdc->flags & FDC_STAT_VALID) == 0) - return (EINVAL); - memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int)); - break; - - case FD_READID: - rid = (struct fdc_readid *)addr; - if (rid->cyl > MAX_CYLINDER || rid->head > MAX_HEAD) - return (EINVAL); - error = fdmisccmd(dev, FDBIO_RDSECTID, addr); - break; - - default: - error = ENOTTY; - break; - } - return (error); -} diff --git a/sys/pc98/pc98/fdc_cbus.c b/sys/pc98/pc98/fdc_cbus.c deleted file mode 100644 index 0980e00..0000000 --- a/sys/pc98/pc98/fdc_cbus.c +++ /dev/null @@ -1,174 +0,0 @@ -/*- - * Copyright (c) 2004 Yoshihiro TAKAHASHI - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/bio.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/rman.h> -#include <sys/systm.h> - -#include <machine/bus.h> - -#include <pc98/pc98/fdcvar.h> -#include <pc98/pc98/fdreg.h> - -#include <isa/isavar.h> -#include <pc98/pc98/pc98.h> - -static bus_addr_t fdc_iat[] = {0, 2, 4}; - -static int -fdc_cbus_alloc_resources(device_t dev, struct fdc_data *fdc) -{ - int rid; - - fdc->fdc_dev = dev; - fdc->rid_ioport = 0; - fdc->rid_irq = 0; - fdc->rid_drq = 0; - fdc->res_irq = 0; - fdc->res_drq = 0; - - fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT, - &fdc->rid_ioport, fdc_iat, - 3, RF_ACTIVE); - if (fdc->res_ioport == 0) { - device_printf(dev, "cannot reserve I/O port range\n"); - return ENXIO; - } - isa_load_resourcev(fdc->res_ioport, fdc_iat, 3); - fdc->portt = rman_get_bustag(fdc->res_ioport); - fdc->porth = rman_get_bushandle(fdc->res_ioport); - - rid = 3; - bus_set_resource(dev, SYS_RES_IOPORT, rid, IO_FDPORT, 1); - fdc->res_fdsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, - RF_ACTIVE); - if (fdc->res_fdsio == 0) - return ENXIO; - fdc->sc_fdsiot = rman_get_bustag(fdc->res_fdsio); - fdc->sc_fdsioh = rman_get_bushandle(fdc->res_fdsio); - - rid = 4; - bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4be, 1); - fdc->res_fdemsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, - RF_ACTIVE); - if (fdc->res_fdemsio == 0) - return ENXIO; - fdc->sc_fdemsiot = rman_get_bustag(fdc->res_fdemsio); - fdc->sc_fdemsioh = rman_get_bushandle(fdc->res_fdemsio); - - fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq, - RF_ACTIVE); - if (fdc->res_irq == 0) { - device_printf(dev, "cannot reserve interrupt line\n"); - return ENXIO; - } - - if ((fdc->flags & FDC_NODMA) == 0) { - fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &fdc->rid_drq, RF_ACTIVE); - if (fdc->res_drq == 0) { - device_printf(dev, "cannot reserve DMA request line\n"); - return ENXIO; - } - fdc->dmachan = rman_get_start(fdc->res_drq); - } - - return 0; -} - -static int -fdc_cbus_probe(device_t dev) -{ - int error; - struct fdc_data *fdc; - - fdc = device_get_softc(dev); - - /* Check pnp ids */ - if (isa_get_vendorid(dev)) - return (ENXIO); - - /* Attempt to allocate our resources for the duration of the probe */ - error = fdc_cbus_alloc_resources(dev, fdc); - if (!error) - error = fdc_initial_reset(fdc); - - fdc_release_resources(fdc); - return (error); -} - -static int -fdc_cbus_attach(device_t dev) -{ - struct fdc_data *fdc; - int error; - - fdc = device_get_softc(dev); - - if ((error = fdc_cbus_alloc_resources(dev, fdc)) != 0 || - (error = fdc_attach(dev)) != 0 || - (error = fdc_hints_probe(dev)) != 0) { - fdc_release_resources(fdc); - return (error); - } - - return (0); -} - -static device_method_t fdc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, fdc_cbus_probe), - DEVMETHOD(device_attach, fdc_cbus_attach), - DEVMETHOD(device_detach, fdc_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, fdc_print_child), - DEVMETHOD(bus_read_ivar, fdc_read_ivar), - DEVMETHOD(bus_write_ivar, fdc_write_ivar), - /* Our children never use any other bus interface methods. */ - - { 0, 0 } -}; - -static driver_t fdc_driver = { - "fdc", - fdc_methods, - sizeof(struct fdc_data) -}; - -DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0); diff --git a/sys/pc98/pc98/fdcvar.h b/sys/pc98/pc98/fdcvar.h deleted file mode 100644 index 4ae53d9..0000000 --- a/sys/pc98/pc98/fdcvar.h +++ /dev/null @@ -1,167 +0,0 @@ -/*- - * Copyright (c) 2004 M. Warner Losh. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/* XXX should audit this file to see if additional copyrights needed */ - -enum fdc_type -{ - FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1 -}; - -enum fdc_states { - DEVIDLE, - FINDWORK, - DOSEEK, - SEEKCOMPLETE , - IOCOMPLETE, - RECALCOMPLETE, - STARTRECAL, - RESETCTLR, - SEEKWAIT, - RECALWAIT, - MOTORWAIT, - IOTIMEDOUT, - RESETCOMPLETE, - PIOREAD -}; - -#ifdef FDC_DEBUG -static char const * const fdstates[] = { - "DEVIDLE", - "FINDWORK", - "DOSEEK", - "SEEKCOMPLETE", - "IOCOMPLETE", - "RECALCOMPLETE", - "STARTRECAL", - "RESETCTLR", - "SEEKWAIT", - "RECALWAIT", - "MOTORWAIT", - "IOTIMEDOUT", - "RESETCOMPLETE", - "PIOREAD" -}; -#endif - -/* - * Per controller structure (softc). - */ -struct fdc_data -{ - int fdcu; /* our unit number */ - int dmacnt; - int dmachan; - int flags; -#define FDC_STAT_VALID 0x08 -#define FDC_HAS_FIFO 0x10 -#define FDC_NEEDS_RESET 0x20 -#define FDC_NODMA 0x40 -#define FDC_ISPNP 0x80 -#define FDC_ISPCMCIA 0x100 - struct fd_data *fd; - int fdu; /* the active drive */ - enum fdc_states state; - int retry; -#ifndef PC98 - int fdout; /* mirror of the w/o digital output reg */ -#endif - u_int status[7]; /* copy of the registers */ - enum fdc_type fdct; /* chip version of FDC */ - int fdc_errs; /* number of logged errors */ - int dma_overruns; /* number of DMA overruns */ - struct bio_queue_head head; - struct bio *bp; /* active buffer */ -#ifdef PC98 - struct resource *res_ioport, *res_fdsio, *res_fdemsio; - struct resource *res_irq, *res_drq; - int rid_ioport, rid_irq, rid_drq; -#else - struct resource *res_ioport, *res_ctl, *res_irq, *res_drq; - int rid_ioport, rid_ctl, rid_irq, rid_drq; -#endif - int port_off; - bus_space_tag_t portt; - bus_space_handle_t porth; -#ifdef PC98 - bus_space_tag_t sc_fdsiot; - bus_space_handle_t sc_fdsioh; - bus_space_tag_t sc_fdemsiot; - bus_space_handle_t sc_fdemsioh; -#else - bus_space_tag_t ctlt; - bus_space_handle_t ctlh; -#endif - void *fdc_intr; - struct device *fdc_dev; -#ifndef PC98 - void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v); -#endif -}; - -typedef int fdu_t; -typedef int fdcu_t; -typedef int fdsu_t; -typedef struct fd_data *fd_p; -typedef struct fdc_data *fdc_p; -typedef enum fdc_type fdc_t; - -/* error returns for fd_cmd() */ -#define FD_FAILED -1 -#define FD_NOT_VALID -2 -#define FDC_ERRMAX 100 /* do not log more */ - -extern devclass_t fdc_devclass; - -enum fdc_device_ivars { - FDC_IVAR_FDUNIT, - FDC_IVAR_FDTYPE, -}; - -__BUS_ACCESSOR(fdc, fdunit, FDC, FDUNIT, int); -__BUS_ACCESSOR(fdc, fdtype, FDC, FDTYPE, int); - -int fdc_alloc_resources(struct fdc_data *); -#ifndef PC98 -void fdout_wr(fdc_p, u_int8_t); -#endif -int fd_cmd(struct fdc_data *, int, ...); -void fdc_release_resources(struct fdc_data *); -int fdc_attach(device_t); -int fdc_hints_probe(device_t); -int fdc_detach(device_t dev); -device_t fdc_add_child(device_t, const char *, int); -int fdc_initial_reset(struct fdc_data *); -int fdc_print_child(device_t, device_t); -int fdc_read_ivar(device_t, device_t, int, uintptr_t *); -int fdc_write_ivar(device_t, device_t, int, uintptr_t); -#ifndef PC98 -int fdc_isa_alloc_resources(device_t, struct fdc_data *); -#endif diff --git a/sys/pc98/pc98/fdreg.h b/sys/pc98/pc98/fdreg.h deleted file mode 100644 index 6d8e7e1..0000000 --- a/sys/pc98/pc98/fdreg.h +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)fdreg.h 7.1 (Berkeley) 5/9/91 - * $FreeBSD$ - */ - -/* - * AT floppy controller registers and bitfields - */ - -/* uses NEC765 controller */ -#include <dev/ic/nec765.h> - -#ifdef PC98 -/* registers */ -#define FDSTS 0 /* NEC 765 Main Status Register (R) */ -#define FDDATA 1 /* NEC 765 Data Register (R/W) */ -#define FDCTL 2 /* FD Control Register */ -#define FDC_RST 0x80 /* FDC RESET */ -#define FDC_RDY 0x40 /* force READY */ -#define FDC_DD 0x20 /* FDD Mode Exchange 0:1M 1:640K */ -#define FDC_DMAE 0x10 /* enable floppy DMA */ -#define FDC_MTON 0x08 /* MOTOR ON (when EMTON=1)*/ -#define FDC_TMSK 0x04 /* TIMER MASK */ -#define FDC_TTRG 0x01 /* TIMER TRIGER */ - -#define FDP_EMTON 0x04 /* enable MTON */ -#define FDP_FDDEXC 0x02 /* FDD Mode Exchange 1:1M 0:640K */ -#define FDP_PORTEXC 0x01 /* PORT Exchane 1:1M 0:640K */ - -#else -/* registers */ -#define FDOUT 2 /* Digital Output Register (W) */ -#define FDO_FDSEL 0x03 /* floppy device select */ -#define FDO_FRST 0x04 /* floppy controller reset */ -#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */ -#define FDO_MOEN0 0x10 /* motor enable drive 0 */ -#define FDO_MOEN1 0x20 /* motor enable drive 1 */ -#define FDO_MOEN2 0x40 /* motor enable drive 2 */ -#define FDO_MOEN3 0x80 /* motor enable drive 3 */ - -#define FDSTS 4 /* NEC 765 Main Status Register (R) */ -#define FDDATA 5 /* NEC 765 Data Register (R/W) */ -#define FDCTL 7 /* Control Register (W) */ -#endif /* PC98 */ - -/* - * The definitions for FDC_500KBPS etc. have been moved out to <sys/fdcio.h> - * since they need to be visible in userland. They cover the lower two bits - * of FDCTL when used for output. - */ -/* - * this is the secret PIO data port (offset from base) - */ -#define FDC_YE_DATAPORT 6 - -#ifndef PC98 -#define FDIN 7 /* Digital Input Register (R) */ -#define FDI_DCHG 0x80 /* diskette has been changed */ - /* requires drive and motor being selected */ - /* is cleared by any step pulse to drive */ -#endif diff --git a/sys/pc98/pc98/isa_dma.c b/sys/pc98/pc98/isa_dma.c deleted file mode 100644 index 5bf2c88..0000000 --- a/sys/pc98/pc98/isa_dma.c +++ /dev/null @@ -1,497 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * code to manage AT bus - * - * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): - * Fixed uninitialized variable problem and added code to deal - * with DMA page boundaries in isa_dmarangecheck(). Fixed word - * mode DMA count compution and reorganized DMA setup code in - * isa_dmastart() - */ - -#include "opt_pc98.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/lock.h> -#include <sys/proc.h> -#include <sys/mutex.h> -#include <sys/module.h> -#include <machine/md_var.h> -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/pmap.h> -#include <pc98/pc98/pc98.h> -#include <dev/ic/i8237.h> -#include <isa/isavar.h> - -/* -** Register definitions for DMA controller 1 (channels 0..3): -*/ -#define DMA1_CHN(c) (IO_DMA + (4*(c))) /* addr reg for channel c */ -#define DMA1_STATUS (IO_DMA + 0x10) /* status register */ -#define DMA1_SMSK (IO_DMA + 0x14) /* single mask register */ -#define DMA1_MODE (IO_DMA + 0x16) /* mode register */ -#define DMA1_FFC (IO_DMA + 0x18) /* clear first/last FF */ - -static int isa_dmarangecheck(caddr_t va, u_int length, int chan); - -static caddr_t dma_bouncebuf[4]; -static u_int dma_bouncebufsize[4]; -static u_int8_t dma_bounced = 0; -static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ -static u_int8_t dma_inuse = 0; /* User for acquire/release */ -static u_int8_t dma_auto_mode = 0; - -#define VALID_DMA_MASK (3) - -/* high byte of address is stored in this port for i-th dma channel */ -static int dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 }; - -/* - * Setup a DMA channel's bounce buffer. - */ -int -isa_dma_init(int chan, u_int bouncebufsize, int flag) -{ - void *buf; - -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_init: channel out of range"); - if (dma_bouncebuf[chan] != NULL) - panic("isa_dma_init: impossible request"); -#endif - - dma_bouncebufsize[chan] = bouncebufsize; - - /* Try malloc() first. It works better if it works. */ - buf = malloc(bouncebufsize, M_DEVBUF, flag); - if (buf != NULL) { - if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) { - dma_bouncebuf[chan] = buf; - return (0); - } - free(buf, M_DEVBUF); - } - buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful, - 1ul, chan & 4 ? 0x20000ul : 0x10000ul); - if (buf == NULL) - return (ENOMEM); - dma_bouncebuf[chan] = buf; - return (0); -} - -/* - * Register a DMA channel's usage. Usually called from a device driver - * in open() or during its initialization. - */ -int -isa_dma_acquire(chan) - int chan; -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_acquire: channel out of range"); -#endif - - if (dma_inuse & (1 << chan)) { - printf("isa_dma_acquire: channel %d already in use\n", chan); - return (EBUSY); - } - dma_inuse |= (1 << chan); - dma_auto_mode &= ~(1 << chan); - - return (0); -} - -/* - * Unregister a DMA channel's usage. Usually called from a device driver - * during close() or during its shutdown. - */ -void -isa_dma_release(chan) - int chan; -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_release: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dma_release: channel %d not in use\n", chan); -#endif - - if (dma_busy & (1 << chan)) { - dma_busy &= ~(1 << chan); - /* - * XXX We should also do "dma_bounced &= (1 << chan);" - * because we are acting on behalf of isa_dmadone() which - * was not called to end the last DMA operation. This does - * not matter now, but it may in the future. - */ - } - - dma_inuse &= ~(1 << chan); - dma_auto_mode &= ~(1 << chan); -} - -/* - * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment - * problems by using a bounce buffer. - */ -void -isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) -{ - vm_paddr_t phys; - int waport; - caddr_t newaddr; - - GIANT_REQUIRED; - -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmastart: channel out of range"); - - if ((chan < 4 && nbytes > (1<<16)) - || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1))) - panic("isa_dmastart: impossible request"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastart: channel %d not acquired\n", chan); -#endif - -#if 0 - /* - * XXX This should be checked, but drivers like ad1848 only call - * isa_dmastart() once because they use Auto DMA mode. If we - * leave this in, drivers that do this will print this continuously. - */ - if (dma_busy & (1 << chan)) - printf("isa_dmastart: channel %d busy\n", chan); -#endif - - dma_busy |= (1 << chan); - - if (isa_dmarangecheck(addr, nbytes, chan)) { - if (dma_bouncebuf[chan] == NULL - || dma_bouncebufsize[chan] < nbytes) - panic("isa_dmastart: bad bounce buffer"); - dma_bounced |= (1 << chan); - newaddr = dma_bouncebuf[chan]; - - /* copy bounce buffer on write */ - if (!(flags & ISADMA_READ)) - bcopy(addr, newaddr, nbytes); - addr = newaddr; - } - - /* translate to physical */ - phys = pmap_extract(kernel_pmap, (vm_offset_t)addr); - - if (flags & ISADMA_RAW) { - dma_auto_mode |= (1 << chan); - } else { - dma_auto_mode &= ~(1 << chan); - } - - if (need_pre_dma_flush) - wbinvd(); /* wbinvd (WB cache flush) */ - - /* set dma channel mode, and reset address ff */ - - /* If ISADMA_RAW flag is set, then use autoinitialise mode */ - if (flags & ISADMA_RAW) { - if (flags & ISADMA_READ) - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); - else - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); - } else { - if (flags & ISADMA_READ) - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); - else - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); - } - outb(DMA1_FFC, 0); - - /* send start address */ - waport = DMA1_CHN(chan); - outb(waport, phys); - outb(waport, phys>>8); - outb(dmapageport[chan], phys>>16); - - /* send count */ - outb(waport + 2, --nbytes); - outb(waport + 2, nbytes>>8); - - /* unmask channel */ - outb(DMA1_SMSK, chan); -} - -void -isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) -{ - - if (flags & ISADMA_READ) { - /* cache flush only after reading 92/12/9 by A.Kojima */ - if (need_post_dma_flush) - invd(); - } - -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmadone: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmadone: channel %d not acquired\n", chan); -#endif - - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) - printf("isa_dmadone: channel %d not busy\n", chan); - - if ((dma_auto_mode & (1 << chan)) == 0) - outb(DMA1_SMSK, (chan & 3) | 4); - - if (dma_bounced & (1 << chan)) { - /* copy bounce buffer on read */ - if (flags & ISADMA_READ) - bcopy(dma_bouncebuf[chan], addr, nbytes); - - dma_bounced &= ~(1 << chan); - } - dma_busy &= ~(1 << chan); -} - -/* - * Check for problems with the address range of a DMA transfer - * (non-contiguous physical pages, outside of bus address space, - * crossing DMA page boundaries). - * Return true if special handling needed. - */ - -static int -isa_dmarangecheck(caddr_t va, u_int length, int chan) -{ - vm_paddr_t phys, priorpage = 0; - vm_offset_t endva; - u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); - - GIANT_REQUIRED; - - endva = (vm_offset_t)round_page((vm_offset_t)va + length); - for (; va < (caddr_t) endva ; va += PAGE_SIZE) { - phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va)); -#ifdef EPSON_BOUNCEDMA -#define ISARAM_END 0xf00000 -#else -#define ISARAM_END RAM_END -#endif - if (phys == 0) - panic("isa_dmacheck: no physical page present"); - if (phys >= ISARAM_END) - return (1); - if (priorpage) { - if (priorpage + PAGE_SIZE != phys) - return (1); - /* check if crossing a DMA page boundary */ - if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) - return (1); - } - priorpage = phys; - } - return (0); -} - -/* - * Query the progress of a transfer on a DMA channel. - * - * To avoid having to interrupt a transfer in progress, we sample - * each of the high and low databytes twice, and apply the following - * logic to determine the correct count. - * - * Reads are performed with interrupts disabled, thus it is to be - * expected that the time between reads is very small. At most - * one rollover in the low count byte can be expected within the - * four reads that are performed. - * - * There are three gaps in which a rollover can occur : - * - * - read low1 - * gap1 - * - read high1 - * gap2 - * - read low2 - * gap3 - * - read high2 - * - * If a rollover occurs in gap1 or gap2, the low2 value will be - * greater than the low1 value. In this case, low2 and high2 are a - * corresponding pair. - * - * In any other case, low1 and high1 can be considered to be correct. - * - * The function returns the number of bytes remaining in the transfer, - * or -1 if the channel requested is not active. - * - */ -int -isa_dmastatus(int chan) -{ - u_long cnt = 0; - int ffport, waport; - u_long low1, high1, low2, high2; - - /* channel active? */ - if ((dma_inuse & (1 << chan)) == 0) { - printf("isa_dmastatus: channel %d not active\n", chan); - return(-1); - } - /* channel busy? */ - - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) { - printf("chan %d not busy\n", chan); - return -2 ; - } - ffport = DMA1_FFC; - waport = DMA1_CHN(chan) + 2; - - disable_intr(); /* no interrupts Mr Jones! */ - outb(ffport, 0); /* clear register LSB flipflop */ - low1 = inb(waport); - high1 = inb(waport); - outb(ffport, 0); /* clear again */ - low2 = inb(waport); - high2 = inb(waport); - enable_intr(); /* enable interrupts again */ - - /* - * Now decide if a wrap has tried to skew our results. - * Note that after TC, the count will read 0xffff, while we want - * to return zero, so we add and then mask to compensate. - */ - if (low1 >= low2) { - cnt = (low1 + (high1 << 8) + 1) & 0xffff; - } else { - cnt = (low2 + (high2 << 8) + 1) & 0xffff; - } - - if (chan >= 4) /* high channels move words */ - cnt *= 2; - return(cnt); -} - -/* - * Reached terminal count yet ? - */ -int -isa_dmatc(int chan) -{ - - return(inb(DMA1_STATUS) & (1 << chan)); -} - -/* - * Stop a DMA transfer currently in progress. - */ -int -isa_dmastop(int chan) -{ - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastop: channel %d not acquired\n", chan); - - if (((dma_busy & (1 << chan)) == 0) && - ((dma_auto_mode & (1 << chan)) == 0)) { - printf("chan %d not busy\n", chan); - return -2 ; - } - - if ((chan & 4) == 0) - outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); - - return(isa_dmastatus(chan)); -} - -/* - * Attach to the ISA PnP descriptor for the AT DMA controller - */ -static struct isa_pnp_id atdma_ids[] = { - { 0x0002d041 /* PNP0200 */, "AT DMA controller" }, - { 0 } -}; - -static int -atdma_probe(device_t dev) -{ - int result; - - if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, atdma_ids)) <= 0) - device_quiet(dev); - return(result); -} - -static int -atdma_attach(device_t dev) -{ - return(0); -} - -static device_method_t atdma_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, atdma_probe), - DEVMETHOD(device_attach, atdma_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - { 0, 0 } -}; - -static driver_t atdma_driver = { - "atdma", - atdma_methods, - 1, /* no softc */ -}; - -static devclass_t atdma_devclass; - -DRIVER_MODULE(atdma, isa, atdma_driver, atdma_devclass, 0, 0); diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index ab6c5c9..e7ff04e 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -103,7 +103,7 @@ __FBSDID("$FreeBSD$"); #endif #include <pc98/pc98/pc98_machdep.h> -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #include <net/netisr.h> diff --git a/sys/pc98/pc98/nmi.c b/sys/pc98/pc98/nmi.c deleted file mode 100644 index 431dd06..0000000 --- a/sys/pc98/pc98/nmi.c +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/syslog.h> -#include <sys/systm.h> - -#include <machine/md_var.h> - -#include <pc98/pc98/epsonio.h> -#include <pc98/pc98/pc98_machdep.h> - -#define NMI_PARITY 0x04 -#define NMI_EPARITY 0x02 - -/* - * Handle a NMI, possibly a machine check. - * return true to panic system, false to ignore. - */ -int -isa_nmi(int cd) -{ - int retval = 0; - int port = inb(0x33); - - log(LOG_CRIT, "NMI PC98 port = %x\n", port); - if (epson_machine_id == 0x20) - epson_outb(0xc16, epson_inb(0xc16) | 0x1); - if (port & NMI_PARITY) { - log(LOG_CRIT, "BASE RAM parity error, likely hardware failure."); - retval = 1; - } else if (port & NMI_EPARITY) { - log(LOG_CRIT, "EXTENDED RAM parity error, likely hardware failure."); - retval = 1; - } else { - log(LOG_CRIT, "\nNMI Resume ??\n"); - } - - return(retval); -} diff --git a/sys/pc98/pc98/olpt.c b/sys/pc98/pc98/olpt.c deleted file mode 100644 index 494eb04..0000000 --- a/sys/pc98/pc98/olpt.c +++ /dev/null @@ -1,653 +0,0 @@ -/*- - * Copyright (c) 1990 William F. Jolitz, TeleMuse - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This software is a component of "386BSD" developed by - * William F. Jolitz, TeleMuse. - * 4. Neither the name of the developer nor the name "386BSD" - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ - * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS - * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. - * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT - * NOT MAKE USE OF THIS WORK. - * - * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED - * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN - * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES - * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING - * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND - * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE - * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS - * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: unknown origin, 386BSD 0.1 - * $FreeBSD$ - */ - -/* - * Device Driver for AT parallel printer port - * Written by William Jolitz 12/18/90 - */ - -/* - * Parallel port TCP/IP interfaces added. I looked at the driver from - * MACH but this is a complete rewrite, and btw. incompatible, and it - * should perform better too. I have never run the MACH driver though. - * - * This driver sends two bytes (0x08, 0x00) in front of each packet, - * to allow us to distinguish another format later. - * - * Now added a Linux/Crynwr compatibility mode which is enabled using - * IF_LINK0 - Tim Wilkinson. - * - * TODO: - * Make HDLC/PPP mode, use IF_LLC1 to enable. - * - * Connect the two computers using a Laplink parallel cable to use this - * feature: - * - * +----------------------------------------+ - * |A-name A-End B-End Descr. Port/Bit | - * +----------------------------------------+ - * |DATA0 2 15 Data 0/0x01 | - * |-ERROR 15 2 1/0x08 | - * +----------------------------------------+ - * |DATA1 3 13 Data 0/0x02 | - * |+SLCT 13 3 1/0x10 | - * +----------------------------------------+ - * |DATA2 4 12 Data 0/0x04 | - * |+PE 12 4 1/0x20 | - * +----------------------------------------+ - * |DATA3 5 10 Strobe 0/0x08 | - * |-ACK 10 5 1/0x40 | - * +----------------------------------------+ - * |DATA4 6 11 Data 0/0x10 | - * |BUSY 11 6 1/~0x80 | - * +----------------------------------------+ - * |GND 18-25 18-25 GND - | - * +----------------------------------------+ - * - * Expect transfer-rates up to 75 kbyte/sec. - * - * If GCC could correctly grok - * register int port asm("edx") - * the code would be cleaner - * - * Poul-Henning Kamp <phk@freebsd.org> - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/uio.h> -#include <sys/syslog.h> -#include <sys/malloc.h> - -#include <machine/clock.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <isa/isavar.h> - -#include <i386/isa/lptreg.h> -#include <dev/ppbus/lptio.h> - -#define LPINITRDY 4 /* wait up to 4 seconds for a ready */ -#define LPTOUTINITIAL 10 /* initial timeout to wait for ready 1/10 s */ -#define LPTOUTMAX 1 /* maximal timeout 1 s */ -#define LPPRI (PZERO+8) -#define BUFSIZE 1024 - -#ifndef DEBUG -#define lprintf(args) -#else -#define lprintf(args) do { \ - if (lptflag) \ - printf args; \ - } while (0) -static int volatile lptflag = 1; -#endif - -#define LPTUNIT(s) ((s)&0x03) -#define LPTFLAGS(s) ((s)&0xfc) - -struct lpt_softc { - struct resource *res_port; - struct resource *res_irq; - void *sc_ih; - - int sc_port; - short sc_state; - /* default case: negative prime, negative ack, handshake strobe, - prime once */ - u_char sc_control; - char sc_flags; -#define LP_POS_INIT 0x04 /* if we are a postive init signal */ -#define LP_POS_ACK 0x08 /* if we are a positive going ack */ -#define LP_NO_PRIME 0x10 /* don't prime the printer at all */ -#define LP_PRIMEOPEN 0x20 /* prime on every open */ -#define LP_AUTOLF 0x40 /* tell printer to do an automatic lf */ -#define LP_BYPASS 0x80 /* bypass printer ready checks */ - void *sc_inbuf; - short sc_xfercnt ; - char sc_primed; - char *sc_cp ; - u_char sc_irq ; /* IRQ status of port */ -#define LP_HAS_IRQ 0x01 /* we have an irq available */ -#define LP_USE_IRQ 0x02 /* we are using our irq */ -#define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */ - u_char sc_backoff ; /* time to call lptout() again */ -}; - -/* bits for state */ -#define OPEN (1<<0) /* device is open */ -#define ASLP (1<<1) /* awaiting draining of printer */ -#define ERROR (1<<2) /* error was received from printer */ -#define OBUSY (1<<3) /* printer is busy doing output */ -#define LPTOUT (1<<4) /* timeout while not selected */ -#define TOUT (1<<5) /* timeout while not selected */ -#define INIT (1<<6) /* waiting to initialize for open */ -#define INTERRUPTED (1<<7) /* write call was interrupted */ - - -/* status masks to interrogate printer status */ -#define RDY_MASK (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR) /* ready ? */ -#define LP_READY (LPS_SEL|LPS_NBSY|LPS_NERR) - -/* Printer Ready condition - from lpa.c */ -/* Only used in polling code */ -#define NOT_READY(x) ((inb(x) & LPS_NBSY) != LPS_NBSY) - -#define MAX_SLEEP (hz*5) /* Timeout while waiting for device ready */ -#define MAX_SPIN 20 /* Max delay for device ready in usecs */ - -static timeout_t lptout; -static int lpt_probe(device_t); -static int lpt_attach(device_t); -static void lpt_intr(void *); - -static devclass_t olpt_devclass; - -static device_method_t olpt_methods[] = { - DEVMETHOD(device_probe, lpt_probe), - DEVMETHOD(device_attach, lpt_attach), - { 0, 0 } -}; - -static driver_t olpt_driver = { - "olpt", - olpt_methods, - sizeof (struct lpt_softc), -}; - -DRIVER_MODULE(olpt, isa, olpt_driver, olpt_devclass, 0, 0); - -static d_open_t lptopen; -static d_close_t lptclose; -static d_write_t lptwrite; -static d_ioctl_t lptioctl; - -static struct cdevsw lpt_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = lptopen, - .d_close = lptclose, - .d_write = lptwrite, - .d_ioctl = lptioctl, - .d_name = "lpt", -}; - -static bus_addr_t lpt_iat[] = {0, 2, 4, 6}; - -/* - * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94 - * Based partially on Rod Grimes' printer probe - * - * Logic: - * 1) If no port address was given, use the bios detected ports - * and autodetect what ports the printers are on. - * 2) Otherwise, probe the data port at the address given, - * using the method in Rod Grimes' port probe. - * (Much code ripped off directly from Rod's probe.) - * - * Comments from Rod's probe: - * Logic: - * 1) You should be able to write to and read back the same value - * to the data port. Do an alternating zeros, alternating ones, - * walking zero, and walking one test to check for stuck bits. - * - * 2) You should be able to write to and read back the same value - * to the control port lower 5 bits, the upper 3 bits are reserved - * per the IBM PC technical reference manauls and different boards - * do different things with them. Do an alternating zeros, alternating - * ones, walking zero, and walking one test to check for stuck bits. - * - * Some printers drag the strobe line down when the are powered off - * so this bit has been masked out of the control port test. - * - * XXX Some printers may not like a fast pulse on init or strobe, I - * don't know at this point, if that becomes a problem these bits - * should be turned off in the mask byte for the control port test. - * - * We are finally left with a mask of 0x14, due to some printers - * being adamant about holding other bits high ........ - * - * Before probing the control port, we write a 0 to the data port - - * If not, some printers chuck out garbage when the strobe line - * gets toggled. - * - * 3) Set the data and control ports to a value of 0 - * - * This probe routine has been tested on Epson Lx-800, HP LJ3P, - * Epson FX-1170 and C.Itoh 8510RM - * printers. - * Quick exit on fail added. - */ - -int -lpt_probe(device_t dev) -{ -#define PC98_OLD_LPT 0x40 -#define PC98_IEEE_1284_FUNCTION 0x149 - int rid; - struct resource *res; - - /* Check isapnp ids */ - if (isa_get_vendorid(dev)) - return ENXIO; - - rid = 0; - res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, lpt_iat, 4, - RF_ACTIVE); - if (res == NULL) - return ENXIO; - isa_load_resourcev(res, lpt_iat, 4); - - if (isa_get_port(dev) == PC98_OLD_LPT) { - unsigned int pc98_ieee_mode, tmp; - - tmp = inb(PC98_IEEE_1284_FUNCTION); - pc98_ieee_mode = tmp; - if ((tmp & 0x10) == 0x10) { - outb(PC98_IEEE_1284_FUNCTION, tmp & ~0x10); - tmp = inb(PC98_IEEE_1284_FUNCTION); - if ((tmp & 0x10) != 0x10) { - outb(PC98_IEEE_1284_FUNCTION, pc98_ieee_mode); - bus_release_resource(dev, SYS_RES_IOPORT, rid, - res); - return ENXIO; - } - } - } - - bus_release_resource(dev, SYS_RES_IOPORT, rid, res); - return 0; -} - -/* XXX Todo - try and detect if interrupt is working */ -int -lpt_attach(device_t dev) -{ - int rid, unit; - struct lpt_softc *sc; - - unit = device_get_unit(dev); - sc = device_get_softc(dev); - - rid = 0; - sc->res_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - lpt_iat, 4, RF_ACTIVE); - if (sc->res_port == NULL) - return ENXIO; - isa_load_resourcev(sc->res_port, lpt_iat, 4); - - sc->sc_port = rman_get_start(sc->res_port); - sc->sc_primed = 0; /* not primed yet */ - - outb(sc->sc_port+lpt_pstb_ctrl, LPC_DIS_PSTB); /* PSTB disable */ - outb(sc->sc_port+lpt_control, LPC_MODE8255); /* 8255 mode set */ - outb(sc->sc_port+lpt_control, LPC_NIRQ8); /* IRQ8 inactive */ - outb(sc->sc_port+lpt_control, LPC_NPSTB); /* PSTB inactive */ - outb(sc->sc_port+lpt_pstb_ctrl, LPC_EN_PSTB); /* PSTB enable */ - - sc->sc_irq = 0; - if (isa_get_irq(dev) != -1) { - rid = 0; - sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_ACTIVE); - if (sc->res_irq == NULL) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, - sc->res_port); - return ENXIO; - } - if (bus_setup_intr(dev, sc->res_irq, INTR_TYPE_TTY, lpt_intr, - sc, &sc->sc_ih)) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, - sc->res_port); - bus_release_resource(dev, SYS_RES_IRQ, 0, - sc->res_irq); - return ENXIO; - } - sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ; - device_printf(dev, "Interrupt-driven port"); - } - - /* XXX what to do about the flags in the minor number? */ - make_dev(&lpt_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600, "lpt%d", unit); - make_dev(&lpt_cdevsw, unit | LP_BYPASS, - UID_ROOT, GID_WHEEL, 0600, "lpctl%d", unit); - - return 0; -} - -/* - * lptopen -- reset the printer, then wait until it's selected and not busy. - * If LP_BYPASS flag is selected, then we do not try to select the - * printer -- this is just used for passing ioctls. - */ - -static int -lptopen (struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct lpt_softc *sc; - int s; - int port; - - sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev))); - if (sc->sc_port == 0) - return (ENXIO); - - if (sc->sc_state) { - lprintf(("lp: still open %x\n", sc->sc_state)); - return(EBUSY); - } else - sc->sc_state |= INIT; - - sc->sc_flags = LPTFLAGS(minor(dev)); - - /* Check for open with BYPASS flag set. */ - if (sc->sc_flags & LP_BYPASS) { - sc->sc_state = OPEN; - return(0); - } - - s = spltty(); - lprintf(("lp flags 0x%x\n", sc->sc_flags)); - port = sc->sc_port; - - /* set IRQ status according to ENABLE_IRQ flag */ - if (sc->sc_irq & LP_ENABLE_IRQ) - sc->sc_irq |= LP_USE_IRQ; - else - sc->sc_irq &= ~LP_USE_IRQ; - - /* init printer */ - sc->sc_state = OPEN; - sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); - sc->sc_xfercnt = 0; - splx(s); - - /* only use timeout if using interrupt */ - lprintf(("irq %x\n", sc->sc_irq)); - if (sc->sc_irq & LP_USE_IRQ) { - sc->sc_state |= TOUT; - timeout (lptout, (caddr_t)sc, - (sc->sc_backoff = hz/LPTOUTINITIAL)); - } - - lprintf(("opened.\n")); - return(0); -} - -static void -lptout (void *arg) -{ - struct lpt_softc *sc = arg; - int pl; - - lprintf(("T %x ", inb(sc->sc_port+lpt_status))); - if (sc->sc_state & OPEN) { - sc->sc_backoff++; - if (sc->sc_backoff > hz/LPTOUTMAX) - sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX; - timeout (lptout, (caddr_t)sc, sc->sc_backoff); - } else - sc->sc_state &= ~TOUT; - - if (sc->sc_state & ERROR) - sc->sc_state &= ~ERROR; - - /* - * Avoid possible hangs do to missed interrupts - */ - if (sc->sc_xfercnt) { - pl = spltty(); - lpt_intr(sc); - splx(pl); - } else { - sc->sc_state &= ~OBUSY; - wakeup(sc); - } -} - -/* - * lptclose -- close the device, free the local line buffer. - * - * Check for interrupted write call added. - */ - -static int -lptclose(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct lpt_softc *sc; - - sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev))); - if(sc->sc_flags & LP_BYPASS) - goto end_close; - - sc->sc_state &= ~OPEN; - free(sc->sc_inbuf, M_DEVBUF); - -end_close: - sc->sc_state = 0; - sc->sc_xfercnt = 0; - lprintf(("closed.\n")); - return(0); -} - -/* - * pushbytes() - * Workhorse for actually spinning and writing bytes to printer - * Derived from lpa.c - * Originally by ? - * - * This code is only used when we are polling the port - */ -static int -pushbytes(struct lpt_softc * sc) -{ - int spin, err, tic; - char ch; - int port = sc->sc_port; - - lprintf(("p")); - /* loop for every character .. */ - while (sc->sc_xfercnt > 0) { - /* printer data */ - ch = *(sc->sc_cp); - sc->sc_cp++; - sc->sc_xfercnt--; - - /* - * Wait for printer ready. - * Loop 20 usecs testing BUSY bit, then sleep - * for exponentially increasing timeout. (vak) - */ - for (spin=0; NOT_READY(port+lpt_status) && spin<MAX_SPIN; ++spin) - DELAY(1); /* XXX delay is NOT this accurate! */ - if (spin >= MAX_SPIN) { - tic = 0; - while (NOT_READY(port+lpt_status)) { - /* - * Now sleep, every cycle a - * little longer .. - */ - tic = tic + tic + 1; - /* - * But no more than 10 seconds. (vak) - */ - if (tic > MAX_SLEEP) - tic = MAX_SLEEP; - err = tsleep(sc, LPPRI, - "lptpoll", tic); - if (err != EWOULDBLOCK) { - return (err); - } - } - } - - /* output data */ - outb(port+lpt_data, ch); - DELAY(1); - outb(port+lpt_control, LPC_PSTB); - DELAY(1); - outb(port+lpt_control, LPC_NPSTB); - } - return(0); -} - -/* - * lptwrite --copy a line from user space to a local buffer, then call - * putc to get the chars moved to the output queue. - * - * Flagging of interrupted write added. - */ - -static int -lptwrite(struct cdev *dev, struct uio * uio, int ioflag) -{ - register unsigned n; - int pl, err; - struct lpt_softc *sc; - - sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev))); - if(sc->sc_flags & LP_BYPASS) { - /* we can't do writes in bypass mode */ - return(EPERM); - } - - sc->sc_state &= ~INTERRUPTED; - while ((n = min(BUFSIZE, uio->uio_resid)) != 0) { - sc->sc_cp = sc->sc_inbuf; - uiomove(sc->sc_cp, n, uio); - sc->sc_xfercnt = n ; - while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) { - lprintf(("i")); - /* if the printer is ready for a char, */ - /* give it one */ - if ((sc->sc_state & OBUSY) == 0){ - lprintf(("\nC %d. ", sc->sc_xfercnt)); - pl = spltty(); - lpt_intr(sc); - (void) splx(pl); - } - lprintf(("W ")); - if (sc->sc_state & OBUSY) - if ((err = tsleep (sc, - LPPRI|PCATCH, "lpwrite", 0))) { - sc->sc_state |= INTERRUPTED; - return(err); - } - } - /* check to see if we must do a polled write */ - if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) { - lprintf(("p")); - if((err = pushbytes(sc))) - return(err); - } - } - return(0); -} - -/* - * lptintr -- handle printer interrupts which occur when the printer is - * ready to accept another char. - * - * do checking for interrupted write call. - */ - -static void -lpt_intr(void *arg) -{ -} - -static int -lptioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) -{ - int error = 0; - struct lpt_softc *sc; - u_int unit = LPTUNIT(minor(dev)); - u_char old_sc_irq; /* old printer IRQ status */ - - sc = devclass_get_softc(olpt_devclass, unit); - - switch (cmd) { - case LPT_IRQ : - if(sc->sc_irq & LP_HAS_IRQ) { - /* - * NOTE: - * If the IRQ status is changed, - * this will only be visible on the - * next open. - * - * If interrupt status changes, - * this gets syslog'd. - */ - old_sc_irq = sc->sc_irq; - if(*(int*)data == 0) - sc->sc_irq &= (~LP_ENABLE_IRQ); - else - sc->sc_irq |= LP_ENABLE_IRQ; - if (old_sc_irq != sc->sc_irq ) - log(LOG_NOTICE, "lpt%c switched to %s mode\n", - (char)unit+'0', - (sc->sc_irq & LP_ENABLE_IRQ)? - "interrupt-driven":"polled"); - } else /* polled port */ - error = EOPNOTSUPP; - break; - default: - error = ENODEV; - } - - return(error); -} diff --git a/sys/pc98/pc98/pc98.h b/sys/pc98/pc98/pc98.h deleted file mode 100644 index 627c0e9..0000000 --- a/sys/pc98/pc98/pc98.h +++ /dev/null @@ -1,128 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)isa.h 5.7 (Berkeley) 5/9/91 - * $FreeBSD$ - */ - -#ifndef _PC98_PC98_PC98_H_ -#define _PC98_PC98_PC98_H_ - -/* BEWARE: Included in both assembler and C code */ - -/* - * PC98 Bus conventions - * modified for PC9801 by A.Kojima F.Ukai M.Ishii - * Kyoto University Microcomputer Club (KMC) - */ - -/* - * Input / Output Port Assignments - */ -#ifndef IO_ISABEGIN -#define IO_ISABEGIN 0x000 /* 0x000 - Beginning of I/O Registers */ - -/* PC98 IO address ... very dirty (^_^; */ - -#define IO_ICU1 0x000 /* 8259A Interrupt Controller #1 */ -#define IO_DMA 0x001 /* 8237A DMA Controller */ -#define IO_ICU2 0x008 /* 8259A Interrupt Controller #2 */ -#define IO_RTC 0x020 /* 4990A RTC */ -#define IO_SYSPORT 0x031 /* 8255A System Port */ -#define IO_PPI 0x035 /* Programmable Peripheral Interface */ -#define IO_KBD 0x041 /* 8251A Keyboard */ -#define IO_TIMER1 0x071 /* 8253C Timer */ -#define IO_COM2 0x0B1 /* 8251A RS232C serial I/O (ext) */ -#define IO_COM3 0x0B9 /* 8251A RS232C serial I/O (ext) */ -#define IO_FDPORT 0x0BE /* FD I/F port (1M<->640K,EMTON) */ -#define IO_NPX 0x0F8 /* Numeric Coprocessor */ -#define IO_WD1_EPSON 0x80 /* 386note Hard disk controller */ -#define IO_ISAEND 0xFFFF /* - 0x3FF End of I/O Registers */ -#endif /* !IO_ISABEGIN */ - -/* - * Input / Output Port Sizes - these are from several sources, and tend - * to be the larger of what was found, ie COM ports can be 4, but some - * boards do not fully decode the address, thus 8 ports are used. - */ -#ifndef IO_ISASIZES -#define IO_ISASIZES - -#define IO_KBDSIZE 16 /* 8042 Keyboard controllers */ -#define IO_LPTSIZE 8 /* LPT controllers, some use only 4 */ -#define IO_LPTSIZE_EXTENDED 8 /* "Extended" LPT controllers */ -#define IO_LPTSIZE_NORMAL 4 /* "Normal" LPT controllers */ -#define IO_NPXSIZE 8 /* 80387/80487 NPX registers */ - -#endif /* !IO_ISASIZES */ - -/* - * Input / Output Memory Physical Addresses - */ -#ifndef IOM_BEGIN -#define IOM_BEGIN 0x0A0000 /* Start of I/O Memory "hole" */ -#define IOM_END 0x100000 /* End of I/O Memory "hole" */ -#define IOM_SIZE (IOM_END - IOM_BEGIN) -#endif /* !IOM_BEGIN */ - -/* - * RAM Physical Address Space (ignoring the above mentioned "hole") - */ -#ifndef RAM_BEGIN -#define RAM_BEGIN 0x0000000 /* Start of RAM Memory */ -#ifdef EPSON_BOUNCEDMA -#define RAM_END 0x0f00000 /* End of EPSON GR?? RAM Memory */ -#else -#define RAM_END 0x1000000 /* End of RAM Memory */ -#endif -#define RAM_SIZE (RAM_END - RAM_BEGIN) -#endif /* !RAM_BEGIN */ - -/* - * IRQs - */ -#define IRQ_NPX 8 - -/* - * Npx MD defines - */ -/* full reset of npx: not needed on pc98 */ -#define npx_full_reset() - -#define M_NEC_PC98 0x0001 -#define M_EPSON_PC98 0x0002 -#define M_NOT_H98 0x0010 -#define M_H98 0x0020 -#define M_NOTE 0x0040 -#define M_NORMAL 0x1000 -#define M_8M 0x8000 - -#endif /* !_PC98_PC98_PC98_H_ */ diff --git a/sys/pc98/pc98/pc98_machdep.c b/sys/pc98/pc98/pc98_machdep.c index fbb348e..c82647f 100644 --- a/sys/pc98/pc98/pc98_machdep.c +++ b/sys/pc98/pc98/pc98_machdep.c @@ -39,7 +39,7 @@ #include <cam/cam.h> #include <cam/cam_ccb.h> #ifdef EPSON_MEMWIN -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #endif #include <pc98/pc98/pc98_machdep.h> diff --git a/sys/pc98/pc98/pc98gdc.c b/sys/pc98/pc98/pc98gdc.c deleted file mode 100644 index 9df28d5..0000000 --- a/sys/pc98/pc98/pc98gdc.c +++ /dev/null @@ -1,1500 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD(98) port team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "opt_gdc.h" -#include "opt_fb.h" -#include "opt_syscons.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/conf.h> -#include <sys/bus.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <machine/resource.h> - -#include <sys/fbio.h> -#include <sys/fcntl.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_param.h> - -#include <machine/md_var.h> -#include <machine/pc/bios.h> - -#include <dev/fb/fbreg.h> - -#ifdef LINE30 -#include <pc98/pc98/pc98.h> -#endif -#include <pc98/pc98/pc98_machdep.h> -#include <isa/isavar.h> - -#define TEXT_GDC 0x60 -#define GRAPHIC_GDC 0xa0 -#define ROW 25 -#define COL 80 - -#define DRIVER_NAME "gdc" - -/* cdev driver declaration */ - -#define GDC_UNIT(dev) minor(dev) -#define GDC_MKMINOR(unit) (unit) - -typedef struct gdc_softc { - video_adapter_t *adp; - struct resource *res_tgdc, *res_ggdc; - struct resource *res_egc, *res_pegc, *res_grcg, *res_kcg; - struct resource *res_tmem, *res_gmem1, *res_gmem2; -#ifdef FB_INSTALL_CDEV - genfb_softc_t gensc; -#endif -} gdc_softc_t; - -#define GDC_SOFTC(unit) \ - ((gdc_softc_t *)devclass_get_softc(gdc_devclass, unit)) - -static bus_addr_t gdc_iat[] = {0, 2, 4, 6, 8, 10, 12, 14}; - -static devclass_t gdc_devclass; - -static int gdc_probe_unit(int unit, gdc_softc_t *sc, int flags); -static int gdc_attach_unit(int unit, gdc_softc_t *sc, int flags); -static int gdc_alloc_resource(device_t dev); -static int gdc_release_resource(device_t dev); - -#if FB_INSTALL_CDEV - -static d_open_t gdcopen; -static d_close_t gdcclose; -static d_read_t gdcread; -static d_write_t gdcwrite; -static d_ioctl_t gdcioctl; -static d_mmap_t gdcmmap; - -static struct cdevsw gdc_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = gdcopen, - .d_close = gdcclose, - .d_read = gdcread, - .d_write = gdcwrite, - .d_ioctl = gdcioctl, - .d_mmap = gdcmmap, - .d_name = DRIVER_NAME, -}; - -#endif /* FB_INSTALL_CDEV */ - -static void -gdc_identify(driver_t *driver, device_t parent) -{ - BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, DRIVER_NAME, 0); -} - -static int -gdcprobe(device_t dev) -{ - int error; - - /* Check isapnp ids */ - if (isa_get_vendorid(dev)) - return (ENXIO); - - device_set_desc(dev, "Generic GDC"); - - error = gdc_alloc_resource(dev); - if (error) - return (error); - - error = gdc_probe_unit(device_get_unit(dev), - device_get_softc(dev), - device_get_flags(dev)); - - gdc_release_resource(dev); - - return (error); -} - -static int -gdc_attach(device_t dev) -{ - gdc_softc_t *sc; - int error; - - error = gdc_alloc_resource(dev); - if (error) - return (error); - - sc = device_get_softc(dev); - error = gdc_attach_unit(device_get_unit(dev), - sc, - device_get_flags(dev)); - if (error) { - gdc_release_resource(dev); - return error; - } - -#ifdef FB_INSTALL_CDEV - /* attach a virtual frame buffer device */ - error = fb_attach(GDC_MKMINOR(device_get_unit(dev)), - sc->adp, &gdc_cdevsw); - if (error) { - gdc_release_resource(dev); - return error; - } -#endif /* FB_INSTALL_CDEV */ - - if (bootverbose) - (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose); - - return 0; -} - -static int -gdc_probe_unit(int unit, gdc_softc_t *sc, int flags) -{ - video_switch_t *sw; - - sw = vid_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - return (*sw->probe)(unit, &sc->adp, NULL, flags); -} - -static int -gdc_attach_unit(int unit, gdc_softc_t *sc, int flags) -{ - video_switch_t *sw; - - sw = vid_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - return (*sw->init)(unit, sc->adp, flags); -} - - -static int -gdc_alloc_resource(device_t dev) -{ - int rid; - gdc_softc_t *sc; - - sc = device_get_softc(dev); - - /* TEXT GDC */ - rid = 0; - bus_set_resource(dev, SYS_RES_IOPORT, rid, TEXT_GDC, 1); - sc->res_tgdc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - gdc_iat, 8, RF_ACTIVE); - if (sc->res_tgdc == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - isa_load_resourcev(sc->res_tgdc, gdc_iat, 8); - - /* GRAPHIC GDC */ - rid = 8; - bus_set_resource(dev, SYS_RES_IOPORT, rid, GRAPHIC_GDC, 1); - sc->res_ggdc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - gdc_iat, 8, RF_ACTIVE); - if (sc->res_ggdc == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - isa_load_resourcev(sc->res_ggdc, gdc_iat, 8); - - /* EGC */ - rid = 16; - bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4a0, 1); - sc->res_egc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - gdc_iat, 8, RF_ACTIVE); - if (sc->res_egc == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - isa_load_resourcev(sc->res_egc, gdc_iat, 8); - - /* PEGC */ - rid = 24; - bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x9a0, 1); - sc->res_pegc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - gdc_iat, 8, RF_ACTIVE); - if (sc->res_pegc == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - isa_load_resourcev(sc->res_pegc, gdc_iat, 8); - - /* CRTC/GRCG */ - rid = 32; - bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x70, 1); - sc->res_grcg = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - gdc_iat, 8, RF_ACTIVE); - if (sc->res_grcg == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - isa_load_resourcev(sc->res_grcg, gdc_iat, 8); - - /* KCG */ - rid = 40; - bus_set_resource(dev, SYS_RES_IOPORT, rid, 0xa1, 1); - sc->res_kcg = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - gdc_iat, 8, RF_ACTIVE); - if (sc->res_kcg == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - isa_load_resourcev(sc->res_kcg, gdc_iat, 8); - - - /* TEXT Memory */ - rid = 0; - sc->res_tmem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0xa0000, 0xa4fff, 0x5000, RF_ACTIVE); - if (sc->res_tmem == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - - /* GRAPHIC Memory */ - rid = 1; - sc->res_gmem1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0xa8000, 0xbffff, 0x18000, - RF_ACTIVE); - if (sc->res_gmem1 == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - rid = 2; - sc->res_gmem2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0xe0000, 0xe7fff, 0x8000, - RF_ACTIVE); - if (sc->res_gmem2 == NULL) { - gdc_release_resource(dev); - return (ENXIO); - } - - return (0); -} - -static int -gdc_release_resource(device_t dev) -{ - gdc_softc_t *sc; - - sc = device_get_softc(dev); - - if (sc->res_tgdc) - bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->res_tgdc); - if (sc->res_ggdc) - bus_release_resource(dev, SYS_RES_IOPORT, 8, sc->res_ggdc); - if (sc->res_egc) - bus_release_resource(dev, SYS_RES_IOPORT, 16, sc->res_egc); - if (sc->res_pegc) - bus_release_resource(dev, SYS_RES_IOPORT, 24, sc->res_pegc); - if (sc->res_grcg) - bus_release_resource(dev, SYS_RES_IOPORT, 32, sc->res_grcg); - if (sc->res_kcg) - bus_release_resource(dev, SYS_RES_IOPORT, 40, sc->res_kcg); - - if (sc->res_tmem) - bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res_tmem); - if (sc->res_gmem1) - bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->res_gmem1); - if (sc->res_gmem2) - bus_release_resource(dev, SYS_RES_MEMORY, 2, sc->res_gmem2); - - return (0); -} - -/* cdev driver functions */ - -#ifdef FB_INSTALL_CDEV - -static int -gdcopen(struct cdev *dev, int flag, int mode, struct thread *td) -{ - gdc_softc_t *sc; - - sc = GDC_SOFTC(GDC_UNIT(dev)); - if (sc == NULL) - return ENXIO; - if (mode & (O_CREAT | O_APPEND | O_TRUNC)) - return ENODEV; - - return genfbopen(&sc->gensc, sc->adp, flag, mode, td); -} - -static int -gdcclose(struct cdev *dev, int flag, int mode, struct thread *td) -{ - gdc_softc_t *sc; - - sc = GDC_SOFTC(GDC_UNIT(dev)); - return genfbclose(&sc->gensc, sc->adp, flag, mode, td); -} - -static int -gdcread(struct cdev *dev, struct uio *uio, int flag) -{ - gdc_softc_t *sc; - - sc = GDC_SOFTC(GDC_UNIT(dev)); - return genfbread(&sc->gensc, sc->adp, uio, flag); -} - -static int -gdcwrite(struct cdev *dev, struct uio *uio, int flag) -{ - gdc_softc_t *sc; - - sc = GDC_SOFTC(GDC_UNIT(dev)); - return genfbread(&sc->gensc, sc->adp, uio, flag); -} - -static int -gdcioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) -{ - gdc_softc_t *sc; - - sc = GDC_SOFTC(GDC_UNIT(dev)); - return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, td); -} - -static int -gdcmmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int prot) -{ - gdc_softc_t *sc; - - sc = GDC_SOFTC(GDC_UNIT(dev)); - return genfbmmap(&sc->gensc, sc->adp, offset, paddr, prot); -} - -#endif /* FB_INSTALL_CDEV */ - -static device_method_t gdc_methods[] = { - DEVMETHOD(device_identify, gdc_identify), - DEVMETHOD(device_probe, gdcprobe), - DEVMETHOD(device_attach, gdc_attach), - { 0, 0 } -}; - -static driver_t gdcdriver = { - DRIVER_NAME, - gdc_methods, - sizeof(gdc_softc_t), -}; - -DRIVER_MODULE(gdc, isa, gdcdriver, gdc_devclass, 0, 0); - -/* LOW-LEVEL */ - - -#include <pc98/pc98/30line.h> - -#define TEXT_BUF_BASE 0x000a0000 -#define TEXT_BUF_SIZE 0x00008000 -#define GRAPHICS_BUF_BASE 0x000a8000 -#define GRAPHICS_BUF_SIZE 0x00040000 -#define VIDEO_BUF_BASE 0x000a0000 -#define VIDEO_BUF_SIZE 0x00048000 - -#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED) -#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED) -#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED) - -/* - * NOTE: `va_window' should have a virtual address, but is initialized - * with a physical address in the following table, they will be - * converted at run-time. - */ -static video_adapter_t adapter_init_value[] = { - { 0, - KD_PC98, "gdc", /* va_type, va_name */ - 0, 0, /* va_unit, va_minor */ - V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_BORDER, - TEXT_GDC, 16, TEXT_GDC, /* va_io*, XXX */ - VIDEO_BUF_BASE, VIDEO_BUF_SIZE, /* va_mem* */ - TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, /* va_window* */ - 0, 0, /* va_buffer, va_buffer_size */ - 0, M_PC98_80x25, 0, /* va_*mode* */ - }, -}; - -static video_adapter_t biosadapter[1]; - -/* video driver declarations */ -static int gdc_configure(int flags); -static int gdc_err(video_adapter_t *adp, ...); -static vi_probe_t gdc_probe; -static vi_init_t gdc_init; -static vi_get_info_t gdc_get_info; -static vi_query_mode_t gdc_query_mode; -static vi_set_mode_t gdc_set_mode; -static vi_set_border_t gdc_set_border; -static vi_save_state_t gdc_save_state; -static vi_load_state_t gdc_load_state; -static vi_read_hw_cursor_t gdc_read_hw_cursor; -static vi_set_hw_cursor_t gdc_set_hw_cursor; -static vi_set_hw_cursor_shape_t gdc_set_hw_cursor_shape; -static vi_blank_display_t gdc_blank_display; -static vi_mmap_t gdc_mmap_buf; -static vi_ioctl_t gdc_dev_ioctl; -static vi_clear_t gdc_clear; -static vi_fill_rect_t gdc_fill_rect; -static vi_bitblt_t gdc_bitblt; -static vi_diag_t gdc_diag; -static vi_save_palette_t gdc_save_palette; -static vi_load_palette_t gdc_load_palette; -static vi_set_win_org_t gdc_set_origin; - -static video_switch_t gdcvidsw = { - gdc_probe, - gdc_init, - gdc_get_info, - gdc_query_mode, - gdc_set_mode, - (vi_save_font_t *)gdc_err, - (vi_load_font_t *)gdc_err, - (vi_show_font_t *)gdc_err, - gdc_save_palette, - gdc_load_palette, - gdc_set_border, - gdc_save_state, - gdc_load_state, - gdc_set_origin, - gdc_read_hw_cursor, - gdc_set_hw_cursor, - gdc_set_hw_cursor_shape, - gdc_blank_display, - gdc_mmap_buf, - gdc_dev_ioctl, - gdc_clear, - gdc_fill_rect, - gdc_bitblt, - (int (*)(void))gdc_err, - (int (*)(void))gdc_err, - gdc_diag, -}; - -VIDEO_DRIVER(gdc, gdcvidsw, gdc_configure); - -/* GDC BIOS standard video modes */ -#define EOT (-1) -#define NA (-2) - -static video_info_t bios_vmode[] = { - { M_PC98_80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, - TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, -#ifdef LINE30 - { M_PC98_80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, - TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, -#endif -#ifndef GDC_NOGRAPHICS - { M_PC98_EGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS, - 640, 400, 8, 16, 4, 4, - GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0, - V_INFO_MM_PLANAR }, - { M_PC98_PEGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA, - 640, 400, 8, 16, 8, 1, - GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0, - V_INFO_MM_PACKED, 1 }, -#ifdef LINE30 - { M_PC98_PEGC640x480, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA, - 640, 480, 8, 16, 8, 1, - GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0, - V_INFO_MM_PACKED, 1 }, -#endif -#endif - { EOT }, -}; - -static int gdc_init_done = FALSE; - -/* local functions */ -static int map_gen_mode_num(int type, int color, int mode); -static int probe_adapters(void); - -#define prologue(adp, flag, err) \ - if (!gdc_init_done || !((adp)->va_flags & (flag))) \ - return (err) - -/* a backdoor for the console driver */ -static int -gdc_configure(int flags) -{ - probe_adapters(); - biosadapter[0].va_flags |= V_ADP_INITIALIZED; - if (!config_done(&biosadapter[0])) { - if (vid_register(&biosadapter[0]) < 0) - return 1; - biosadapter[0].va_flags |= V_ADP_REGISTERED; - } - - return 1; -} - -/* local subroutines */ - -/* map a generic video mode to a known mode number */ -static int -map_gen_mode_num(int type, int color, int mode) -{ - static struct { - int from; - int to; - } mode_map[] = { - { M_TEXT_80x25, M_PC98_80x25, }, -#ifdef LINE30 - { M_TEXT_80x30, M_PC98_80x30, }, -#endif - }; - int i; - - for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { - if (mode_map[i].from == mode) - return mode_map[i].to; - } - return mode; -} - -static int -verify_adapter(video_adapter_t *adp) -{ -#ifndef GDC_NOGRAPHICS - int i; - - if (PC98_SYSTEM_PARAMETER(0x45c) & 0x40) { /* PEGC exists */ - adp->va_flags |= V_ADP_VESA; /* XXX */ - } else { - for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { - if (bios_vmode[i].vi_flags & V_INFO_VESA) - bios_vmode[i].vi_mode = NA; - } - } -#endif - return 0; -} - -/* probe video adapters and return the number of detected adapters */ -static int -probe_adapters(void) -{ - video_info_t info; - - /* do this test only once */ - if (gdc_init_done) - return 1; - gdc_init_done = TRUE; - - biosadapter[0] = adapter_init_value[0]; - biosadapter[0].va_flags |= V_ADP_PROBED; - biosadapter[0].va_mode = - biosadapter[0].va_initial_mode = biosadapter[0].va_initial_bios_mode; - - if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) || - (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) { - gdc_FH = (inb(0x9a8) & 1) ? _31KHZ : _24KHZ; - } else { - gdc_FH = _24KHZ; - } - - gdc_get_info(&biosadapter[0], biosadapter[0].va_initial_mode, &info); - initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS); - - biosadapter[0].va_window = BIOS_PADDRTOVADDR(info.vi_window); - biosadapter[0].va_window_size = info.vi_window_size; - biosadapter[0].va_window_gran = info.vi_window_gran; - biosadapter[0].va_buffer = 0; - biosadapter[0].va_buffer_size = 0; - if (info.vi_flags & V_INFO_GRAPHICS) { - switch (info.vi_depth/info.vi_planes) { - case 1: - biosadapter[0].va_line_width = info.vi_width/8; - break; - case 2: - biosadapter[0].va_line_width = info.vi_width/4; - break; - case 4: - biosadapter[0].va_line_width = info.vi_width/2; - break; - case 8: - default: /* shouldn't happen */ - biosadapter[0].va_line_width = info.vi_width; - break; - } - } else { - biosadapter[0].va_line_width = info.vi_width; - } - bcopy(&info, &biosadapter[0].va_info, sizeof(info)); - - verify_adapter(&biosadapter[0]); - - return 1; -} - -static void master_gdc_cmd(unsigned int cmd) -{ - while ( (inb(TEXT_GDC) & 2) != 0); - outb(TEXT_GDC+2, cmd); -} - -static void master_gdc_prm(unsigned int pmtr) -{ - while ( (inb(TEXT_GDC) & 2) != 0); - outb(TEXT_GDC, pmtr); -} - -static void master_gdc_word_prm(unsigned int wpmtr) -{ - master_gdc_prm(wpmtr & 0x00ff); - master_gdc_prm((wpmtr >> 8) & 0x00ff); -} - -#ifdef LINE30 -static void master_gdc_fifo_empty(void) -{ - while ( (inb(TEXT_GDC) & 4) == 0); -} -#endif - -static void master_gdc_wait_vsync(void) -{ - while ( (inb(TEXT_GDC) & 0x20) != 0); - while ( (inb(TEXT_GDC) & 0x20) == 0); -} - -static void gdc_cmd(unsigned int cmd) -{ - while ( (inb(GRAPHIC_GDC) & 2) != 0); - outb( GRAPHIC_GDC+2, cmd); -} - -#ifdef LINE30 -static void gdc_prm(unsigned int pmtr) -{ - while ( (inb(GRAPHIC_GDC) & 2) != 0); - outb( GRAPHIC_GDC, pmtr); -} - -static void gdc_word_prm(unsigned int wpmtr) -{ - gdc_prm(wpmtr & 0x00ff); - gdc_prm((wpmtr >> 8) & 0x00ff); -} - -static void gdc_fifo_empty(void) -{ - while ( (inb(GRAPHIC_GDC) & 0x04) == 0); -} -#endif - -static void gdc_wait_vsync(void) -{ - while ( (inb(GRAPHIC_GDC) & 0x20) != 0); - while ( (inb(GRAPHIC_GDC) & 0x20) == 0); -} - -#ifdef LINE30 -static int check_gdc_clock(void) -{ - if ((inb(IO_SYSPORT) & 0x80) == 0){ - return _5MHZ; - } else { - return _2_5MHZ; - } -} -#endif - -static void initialize_gdc(unsigned int mode, int isGraph) -{ -#ifdef LINE30 - /* start 30line initialize */ - int m_mode, s_mode, gdc_clock, hsync_clock; - - gdc_clock = check_gdc_clock(); - m_mode = (mode == T25_G400) ? _25L : _30L; - s_mode = 2*mode+gdc_clock; - gdc_INFO = m_mode; - - master_gdc_wait_vsync(); - - if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) || - (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) { - if (PC98_SYSTEM_PARAMETER(0x481) & 0x08) { - hsync_clock = (m_mode == _25L) ? gdc_FH : _31KHZ; - outb(0x9a8, (hsync_clock == _31KHZ) ? 1 : 0); - } else { - hsync_clock = gdc_FH; - } - } else { - hsync_clock = _24KHZ; - } - - if ((gdc_clock == _2_5MHZ) && - (slave_param[hsync_clock][s_mode][GDC_LF] > 400)) { - outb(0x6a, 0x83); - outb(0x6a, 0x85); - gdc_clock = _5MHZ; - s_mode = 2*mode+gdc_clock; - } - - master_gdc_cmd(_GDC_RESET); - master_gdc_cmd(_GDC_MASTER); - gdc_cmd(_GDC_RESET); - gdc_cmd(_GDC_SLAVE); - - /* GDC Master */ - master_gdc_cmd(_GDC_SYNC); - master_gdc_prm(0x00); /* flush less */ /* text & graph */ - master_gdc_prm(master_param[hsync_clock][m_mode][GDC_CR]); - master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_HFP] << 10) - + (master_param[hsync_clock][m_mode][GDC_VS] << 5) - + master_param[hsync_clock][m_mode][GDC_HS])); - master_gdc_prm(master_param[hsync_clock][m_mode][GDC_HBP]); - master_gdc_prm(master_param[hsync_clock][m_mode][GDC_VFP]); - master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_VBP] << 10) - + (master_param[hsync_clock][m_mode][GDC_LF]))); - master_gdc_fifo_empty(); - master_gdc_cmd(_GDC_PITCH); - master_gdc_prm(MasterPCH); - master_gdc_fifo_empty(); - - /* GDC slave */ - gdc_cmd(_GDC_SYNC); - gdc_prm(0x06); - gdc_prm(slave_param[hsync_clock][s_mode][GDC_CR]); - gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_HFP] << 10) - + (slave_param[hsync_clock][s_mode][GDC_VS] << 5) - + (slave_param[hsync_clock][s_mode][GDC_HS])); - gdc_prm(slave_param[hsync_clock][s_mode][GDC_HBP]); - gdc_prm(slave_param[hsync_clock][s_mode][GDC_VFP]); - gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_VBP] << 10) - + (slave_param[hsync_clock][s_mode][GDC_LF])); - gdc_fifo_empty(); - gdc_cmd(_GDC_PITCH); - gdc_prm(SlavePCH[gdc_clock]); - gdc_fifo_empty(); - - /* set Master GDC scroll param */ - master_gdc_wait_vsync(); - master_gdc_wait_vsync(); - master_gdc_wait_vsync(); - master_gdc_cmd(_GDC_SCROLL); - master_gdc_word_prm(0); - master_gdc_word_prm((master_param[hsync_clock][m_mode][GDC_LF] << 4) - | 0x0000); - master_gdc_fifo_empty(); - - /* set Slave GDC scroll param */ - gdc_wait_vsync(); - gdc_cmd(_GDC_SCROLL); - gdc_word_prm(0); - if (gdc_clock == _5MHZ) { - gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000); - } else { - gdc_word_prm(SlaveScrlLF[mode] << 4); - } - gdc_fifo_empty(); - - gdc_word_prm(0); - if (gdc_clock == _5MHZ) { - gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000); - } else { - gdc_word_prm(SlaveScrlLF[mode] << 4); - } - gdc_fifo_empty(); - - /* sync start */ - gdc_cmd(isGraph ? _GDC_START : _GDC_STOP); - - gdc_wait_vsync(); - gdc_wait_vsync(); - gdc_wait_vsync(); - - master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START); -#else - master_gdc_wait_vsync(); - master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START); /* text */ - gdc_wait_vsync(); - gdc_cmd(isGraph ? _GDC_START : _GDC_STOP); /* graphics */ -#endif -} - -#ifndef GDC_NOGRAPHICS -static u_char b_palette[] = { - /* R G B */ - 0x00, 0x00, 0x00, /* 0 */ - 0x00, 0x00, 0x7f, /* 1 */ - 0x7f, 0x00, 0x00, /* 2 */ - 0x7f, 0x00, 0x7f, /* 3 */ - 0x00, 0x7f, 0x00, /* 4 */ - 0x00, 0x7f, 0x7f, /* 5 */ - 0x7f, 0x7f, 0x00, /* 6 */ - 0x7f, 0x7f, 0x7f, /* 7 */ - 0x40, 0x40, 0x40, /* 8 */ - 0x00, 0x00, 0xff, /* 9 */ - 0xff, 0x00, 0x00, /* 10 */ - 0xff, 0x00, 0xff, /* 11 */ - 0x00, 0xff, 0x00, /* 12 */ - 0x00, 0xff, 0xff, /* 13 */ - 0xff, 0xff, 0x00, /* 14 */ - 0xff, 0xff, 0xff, /* 15 */ -}; -#endif - -static int -gdc_load_palette(video_adapter_t *adp, u_char *palette) -{ -#ifndef GDC_NOGRAPHICS - int i; - - if (adp->va_info.vi_flags & V_INFO_VESA) { - gdc_wait_vsync(); - for (i = 0; i < 256; ++i) { - outb(0xa8, i); - outb(0xac, *palette++); /* R */ - outb(0xaa, *palette++); /* G */ - outb(0xae, *palette++); /* B */ - } - } else { - /* - * XXX - Even though PC-98 text color is independent of palette, - * we should set palette in text mode. - * Because the background color of text mode is palette 0's one. - */ - outb(0x6a, 1); /* 16 colors mode */ - bcopy(palette, b_palette, sizeof(b_palette)); - - gdc_wait_vsync(); - for (i = 0; i < 16; ++i) { - outb(0xa8, i); - outb(0xac, *palette++ >> 4); /* R */ - outb(0xaa, *palette++ >> 4); /* G */ - outb(0xae, *palette++ >> 4); /* B */ - } - } -#endif - return 0; -} - -static int -gdc_save_palette(video_adapter_t *adp, u_char *palette) -{ -#ifndef GDC_NOGRAPHICS - int i; - - if (adp->va_info.vi_flags & V_INFO_VESA) { - for (i = 0; i < 256; ++i) { - outb(0xa8, i); - *palette++ = inb(0xac); /* R */ - *palette++ = inb(0xaa); /* G */ - *palette++ = inb(0xae); /* B */ - } - } else { - bcopy(b_palette, palette, sizeof(b_palette)); - } -#endif - return 0; -} - -static int -gdc_set_origin(video_adapter_t *adp, off_t offset) -{ -#ifndef GDC_NOGRAPHICS - if (adp->va_info.vi_flags & V_INFO_VESA) { - writew(BIOS_PADDRTOVADDR(0x000e0004), offset >> 15); - } -#endif - return 0; -} - -/* entry points */ - -static int -gdc_err(video_adapter_t *adp, ...) -{ - return ENODEV; -} - -static int -gdc_probe(int unit, video_adapter_t **adpp, void *arg, int flags) -{ - probe_adapters(); - if (unit >= 1) - return ENXIO; - - *adpp = &biosadapter[unit]; - - return 0; -} - -static int -gdc_init(int unit, video_adapter_t *adp, int flags) -{ - if ((unit >= 1) || (adp == NULL) || !probe_done(adp)) - return ENXIO; - - if (!init_done(adp)) { - /* nothing to do really... */ - adp->va_flags |= V_ADP_INITIALIZED; - } - - if (!config_done(adp)) { - if (vid_register(adp) < 0) - return ENXIO; - adp->va_flags |= V_ADP_REGISTERED; - } - - return 0; -} - -/* - * get_info(): - * Return the video_info structure of the requested video mode. - */ -static int -gdc_get_info(video_adapter_t *adp, int mode, video_info_t *info) -{ - int i; - - if (!gdc_init_done) - return ENXIO; - - mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); - for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { - if (bios_vmode[i].vi_mode == NA) - continue; - if (mode == bios_vmode[i].vi_mode) { - *info = bios_vmode[i]; - info->vi_buffer_size = info->vi_window_size*info->vi_planes; - return 0; - } - } - return EINVAL; -} - -/* - * query_mode(): - * Find a video mode matching the requested parameters. - * Fields filled with 0 are considered "don't care" fields and - * match any modes. - */ -static int -gdc_query_mode(video_adapter_t *adp, video_info_t *info) -{ - int i; - - if (!gdc_init_done) - return ENXIO; - - for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { - if (bios_vmode[i].vi_mode == NA) - continue; - - if ((info->vi_width != 0) - && (info->vi_width != bios_vmode[i].vi_width)) - continue; - if ((info->vi_height != 0) - && (info->vi_height != bios_vmode[i].vi_height)) - continue; - if ((info->vi_cwidth != 0) - && (info->vi_cwidth != bios_vmode[i].vi_cwidth)) - continue; - if ((info->vi_cheight != 0) - && (info->vi_cheight != bios_vmode[i].vi_cheight)) - continue; - if ((info->vi_depth != 0) - && (info->vi_depth != bios_vmode[i].vi_depth)) - continue; - if ((info->vi_planes != 0) - && (info->vi_planes != bios_vmode[i].vi_planes)) - continue; - /* XXX: should check pixel format, memory model */ - if ((info->vi_flags != 0) - && (info->vi_flags != bios_vmode[i].vi_flags)) - continue; - - /* verify if this mode is supported on this adapter */ - if (gdc_get_info(adp, bios_vmode[i].vi_mode, info)) - continue; - return 0; - } - return ENODEV; -} - -/* - * set_mode(): - * Change the video mode. - */ -static int -gdc_set_mode(video_adapter_t *adp, int mode) -{ - video_info_t info; - - prologue(adp, V_ADP_MODECHANGE, ENODEV); - - mode = map_gen_mode_num(adp->va_type, - adp->va_flags & V_ADP_COLOR, mode); - if (gdc_get_info(adp, mode, &info)) - return EINVAL; - - switch (info.vi_mode) { -#ifndef GDC_NOGRAPHICS - case M_PC98_PEGC640x480: /* PEGC 640x480 */ - initialize_gdc(T30_G480, info.vi_flags & V_INFO_GRAPHICS); - break; - case M_PC98_PEGC640x400: /* PEGC 640x400 */ - case M_PC98_EGC640x400: /* EGC GRAPHICS */ -#endif - case M_PC98_80x25: /* VGA TEXT */ - initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS); - break; - case M_PC98_80x30: /* VGA TEXT */ - initialize_gdc(T30_G400, info.vi_flags & V_INFO_GRAPHICS); - break; - default: - break; - } - -#ifndef GDC_NOGRAPHICS - if (info.vi_flags & V_INFO_VESA) { - outb(0x6a, 0x07); /* enable mode F/F change */ - outb(0x6a, 0x21); /* enhanced graphics */ - if (info.vi_height > 400) - outb(0x6a, 0x69); /* 800 lines */ - writeb(BIOS_PADDRTOVADDR(0x000e0100), 0); /* packed pixel */ - } else { - if (adp->va_flags & V_ADP_VESA) { - outb(0x6a, 0x07); /* enable mode F/F change */ - outb(0x6a, 0x20); /* normal graphics */ - outb(0x6a, 0x68); /* 400 lines */ - } - outb(0x6a, 1); /* 16 colors */ - } -#endif - - adp->va_mode = mode; - adp->va_flags &= ~V_ADP_COLOR; - adp->va_flags |= - (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; -#if 0 - adp->va_crtc_addr = - (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; -#endif - adp->va_window = BIOS_PADDRTOVADDR(info.vi_window); - adp->va_window_size = info.vi_window_size; - adp->va_window_gran = info.vi_window_gran; - if (info.vi_buffer_size == 0) { - adp->va_buffer = 0; - adp->va_buffer_size = 0; - } else { - adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); - adp->va_buffer_size = info.vi_buffer_size; - } - if (info.vi_flags & V_INFO_GRAPHICS) { - switch (info.vi_depth/info.vi_planes) { - case 1: - adp->va_line_width = info.vi_width/8; - break; - case 2: - adp->va_line_width = info.vi_width/4; - break; - case 4: - adp->va_line_width = info.vi_width/2; - break; - case 8: - default: /* shouldn't happen */ - adp->va_line_width = info.vi_width; - break; - } - } else { - adp->va_line_width = info.vi_width; - } - bcopy(&info, &adp->va_info, sizeof(info)); - - /* move hardware cursor out of the way */ - (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1); - - return 0; -} - -/* - * set_border(): - * Change the border color. - */ -static int -gdc_set_border(video_adapter_t *adp, int color) -{ - outb(0x6c, color << 4); - return 0; -} - -/* - * save_state(): - * Read video card register values. - */ -static int -gdc_save_state(video_adapter_t *adp, void *p, size_t size) -{ - return ENODEV; -} - -/* - * load_state(): - * Set video card registers at once. - */ -static int -gdc_load_state(video_adapter_t *adp, void *p) -{ - return ENODEV; -} - -/* - * read_hw_cursor(): - * Read the position of the hardware text cursor. - */ -static int -gdc_read_hw_cursor(video_adapter_t *adp, int *col, int *row) -{ - u_int16_t off; - int s; - - if (!gdc_init_done) - return ENXIO; - - if (adp->va_info.vi_flags & V_INFO_GRAPHICS) - return ENODEV; - - s = spltty(); - master_gdc_cmd(0xe0); /* _GDC_CSRR */ - while((inb(TEXT_GDC + 0) & 0x1) == 0) {} /* GDC wait */ - off = inb(TEXT_GDC + 2); /* EADl */ - off |= (inb(TEXT_GDC + 2) << 8); /* EADh */ - inb(TEXT_GDC + 2); /* dummy */ - inb(TEXT_GDC + 2); /* dummy */ - inb(TEXT_GDC + 2); /* dummy */ - splx(s); - - if (off >= ROW*COL) - off = 0; - *row = off / adp->va_info.vi_width; - *col = off % adp->va_info.vi_width; - - return 0; -} - -/* - * set_hw_cursor(): - * Move the hardware text cursor. If col and row are both -1, - * the cursor won't be shown. - */ -static int -gdc_set_hw_cursor(video_adapter_t *adp, int col, int row) -{ - u_int16_t off; - int s; - - if (!gdc_init_done) - return ENXIO; - - if ((col == -1) && (row == -1)) { - off = -1; - } else { - if (adp->va_info.vi_flags & V_INFO_GRAPHICS) - return ENODEV; - off = row*adp->va_info.vi_width + col; - } - - s = spltty(); - master_gdc_cmd(0x49); /* _GDC_CSRW */ - master_gdc_word_prm(off); - splx(s); - - return 0; -} - -/* - * set_hw_cursor_shape(): - * Change the shape of the hardware text cursor. If the height is zero - * or negative, the cursor won't be shown. - */ -static int -gdc_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, - int celsize, int blink) -{ - int start; - int end; - int s; - - if (!gdc_init_done) - return ENXIO; - - start = celsize - (base + height); - end = celsize - base - 1; - -#if 0 - /* - * muPD7220 GDC has anomaly that if end == celsize - 1 then start - * must be 0, otherwise the cursor won't be correctly shown - * in the first row in the screen. We shall set end to celsize - 2; - * if end == celsize -1 && start > 0. XXX - */ - if ((end == celsize - 1) && (start > 0) && (start < end)) - --end; -#endif - - s = spltty(); - master_gdc_cmd(0x4b); /* _GDC_CSRFORM */ - master_gdc_prm(((height > 0) ? 0x80 : 0) /* cursor on/off */ - | ((celsize - 1) & 0x1f)); /* cel size */ - master_gdc_word_prm(((end & 0x1f) << 11) /* end line */ - | (12 << 6) /* blink rate */ - | (blink ? 0 : 0x20) /* blink on/off */ - | (start & 0x1f)); /* start line */ - splx(s); - - return 0; -} - -/* - * blank_display() - * Put the display in power save/power off mode. - */ -static int -gdc_blank_display(video_adapter_t *adp, int mode) -{ - int s; - static int standby = 0; - - if (!gdc_init_done) - return ENXIO; - - s = splhigh(); - switch (mode) { - case V_DISPLAY_SUSPEND: - case V_DISPLAY_STAND_BY: - outb(0x09a2, 0x80 | 0x40); /* V/H-SYNC mask */ - if (inb(0x09a2) == (0x80 | 0x40)) - standby = 1; - /* FALLTHROUGH */ - - case V_DISPLAY_BLANK: - if (epson_machine_id == 0x20) { - outb(0x43f, 0x42); - outb(0xc17, inb(0xc17) & ~0x08); /* turn off side light */ - outb(0xc16, inb(0xc16) & ~0x02); /* turn off back light */ - outb(0x43f, 0x40); - } else { - while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */ - ; - outb(TEXT_GDC + 8, 0x0e); /* DISP off */ - } - break; - - case V_DISPLAY_ON: - if (epson_machine_id == 0x20) { - outb(0x43f, 0x42); - outb(0xc17, inb(0xc17) | 0x08); - outb(0xc16, inb(0xc16) | 0x02); - outb(0x43f, 0x40); - } else { - while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */ - ; - outb(TEXT_GDC + 8, 0x0f); /* DISP on */ - } - if (standby) { - outb(0x09a2, 0x00); /* V/H-SYNC unmask */ - standby = 0; - } - break; - } - splx(s); - return 0; -} - -/* - * mmap(): - * Mmap frame buffer. - */ -static int -gdc_mmap_buf(video_adapter_t *adp, vm_offset_t offset, vm_offset_t *paddr, - int prot) -{ - /* FIXME: is this correct? XXX */ - if (offset > VIDEO_BUF_SIZE - PAGE_SIZE) - return -1; - *paddr = adp->va_info.vi_window + offset; - return 0; -} - -#ifndef GDC_NOGRAPHICS -static void -planar_fill(video_adapter_t *adp, int val) -{ - - outb(0x7c, 0x80); /* GRCG on & TDW mode */ - outb(0x7e, 0); /* tile B */ - outb(0x7e, 0); /* tile R */ - outb(0x7e, 0); /* tile G */ - outb(0x7e, 0); /* tile I */ - - fillw_io(0, adp->va_window, 0x8000 / 2); /* XXX */ - - outb(0x7c, 0); /* GRCG off */ -} - -static void -packed_fill(video_adapter_t *adp, int val) -{ - int length; - int at; /* position in the frame buffer */ - int l; - - at = 0; - length = adp->va_line_width*adp->va_info.vi_height; - while (length > 0) { - l = imin(length, adp->va_window_size); - (*vidsw[adp->va_index]->set_win_org)(adp, at); - bzero_io(adp->va_window, l); - length -= l; - at += l; - } -} - -static int -gdc_clear(video_adapter_t *adp) -{ - - switch (adp->va_info.vi_mem_model) { - case V_INFO_MM_TEXT: - /* do nothing? XXX */ - break; - case V_INFO_MM_PLANAR: - planar_fill(adp, 0); - break; - case V_INFO_MM_PACKED: - packed_fill(adp, 0); - break; - } - - return 0; -} -#else /* GDC_NOGRAPHICS */ -static int -gdc_clear(video_adapter_t *adp) -{ - - return 0; -} -#endif /* GDC_NOGRAPHICS */ - -static int -gdc_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) -{ - return ENODEV; -} - -static int -gdc_bitblt(video_adapter_t *adp,...) -{ - /* FIXME */ - return ENODEV; -} - -static int -gdc_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) -{ - switch (cmd) { - case FBIO_GETWINORG: /* get frame buffer window origin */ - *(u_int *)arg = 0; - return 0; - - case FBIO_SETWINORG: /* set frame buffer window origin */ - case FBIO_SETDISPSTART: /* set display start address */ - case FBIO_SETLINEWIDTH: /* set scan line length in pixel */ - case FBIO_GETPALETTE: /* get color palette */ - case FBIO_SETPALETTE: /* set color palette */ - case FBIOGETCMAP: /* get color palette */ - case FBIOPUTCMAP: /* set color palette */ - return ENODEV; - - case FBIOGTYPE: /* get frame buffer type info. */ - ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type); - ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height; - ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width; - ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth; - if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8)) - ((struct fbtype *)arg)->fb_cmsize = 0; - else - ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth; - ((struct fbtype *)arg)->fb_size = adp->va_buffer_size; - return 0; - - default: - return fb_commonioctl(adp, cmd, arg); - } -} - -/* - * diag(): - * Print some information about the video adapter and video modes, - * with requested level of details. - */ -static int -gdc_diag(video_adapter_t *adp, int level) -{ -#if FB_DEBUG > 1 - int i; -#endif - - if (!gdc_init_done) - return ENXIO; - - fb_dump_adp_info(DRIVER_NAME, adp, level); - -#if FB_DEBUG > 1 - for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { - if (bios_vmode[i].vi_mode == NA) - continue; - if (get_mode_param(bios_vmode[i].vi_mode) == NULL) - continue; - fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level); - } -#endif - - return 0; -} diff --git a/sys/pc98/pc98/pc98kbd.c b/sys/pc98/pc98/pc98kbd.c deleted file mode 100644 index f33b8c2..0000000 --- a/sys/pc98/pc98/pc98kbd.c +++ /dev/null @@ -1,964 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD(98) port team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "opt_kbd.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <sys/kbio.h> - -#include <machine/resource.h> - -#include <dev/kbd/kbdreg.h> - -#include <pc98/pc98/pc98.h> - -#include <isa/isavar.h> - -#define DRIVER_NAME "pckbd" - -/* device configuration flags */ -#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */ - -static devclass_t pckbd_devclass; - -static int pckbdprobe(device_t dev); -static int pckbdattach(device_t dev); -static int pckbdresume(device_t dev); -static void pckbd_isa_intr(void *arg); - -static device_method_t pckbd_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pckbdprobe), - DEVMETHOD(device_attach, pckbdattach), - DEVMETHOD(device_resume, pckbdresume), - { 0, 0 } -}; - -static driver_t pckbd_driver = { - DRIVER_NAME, - pckbd_methods, - 1, -}; - -DRIVER_MODULE(pckbd, isa, pckbd_driver, pckbd_devclass, 0, 0); - -static bus_addr_t pckbd_iat[] = {0, 2}; - -static int pckbd_probe_unit(int unit, int port, int irq, - int flags); -static int pckbd_attach_unit(int unit, keyboard_t **kbd, - int port, int irq, int flags); -static timeout_t pckbd_timeout; - - -static int -pckbdprobe(device_t dev) -{ - struct resource *res; - int error, rid; - - /* Check isapnp ids */ - if (isa_get_vendorid(dev)) - return (ENXIO); - - device_set_desc(dev, "PC-98 Keyboard"); - - rid = 0; - res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2, - RF_ACTIVE); - if (res == NULL) - return ENXIO; - isa_load_resourcev(res, pckbd_iat, 2); - - error = pckbd_probe_unit(device_get_unit(dev), - isa_get_port(dev), - (1 << isa_get_irq(dev)), - device_get_flags(dev)); - - bus_release_resource(dev, SYS_RES_IOPORT, rid, res); - - return (error); -} - -static int -pckbdattach(device_t dev) -{ - keyboard_t *kbd; - void *ih; - struct resource *res; - int error, rid; - - rid = 0; - res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2, - RF_ACTIVE); - if (res == NULL) - return ENXIO; - isa_load_resourcev(res, pckbd_iat, 2); - - error = pckbd_attach_unit(device_get_unit(dev), &kbd, - isa_get_port(dev), - (1 << isa_get_irq(dev)), - device_get_flags(dev)); - - rid = 0; - res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); - if (res == NULL) - return ENXIO; - BUS_SETUP_INTR(device_get_parent(dev), dev, res, INTR_TYPE_TTY, - pckbd_isa_intr, kbd, &ih); - - return 0; -} - -static int -pckbdresume(device_t dev) -{ - keyboard_t *kbd; - - kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME, - device_get_unit(dev))); - if (kbd) - (*kbdsw[kbd->kb_index]->clear_state)(kbd); - - return (0); -} - -static void -pckbd_isa_intr(void *arg) -{ - keyboard_t *kbd = arg; - - (*kbdsw[kbd->kb_index]->intr)(kbd, NULL); -} - -static int -pckbd_probe_unit(int unit, int port, int irq, int flags) -{ - keyboard_switch_t *sw; - int args[2]; - int error; - - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - - args[0] = port; - args[1] = irq; - error = (*sw->probe)(unit, args, flags); - if (error) - return error; - return 0; -} - -static int -pckbd_attach_unit(int unit, keyboard_t **kbd, int port, int irq, int flags) -{ - keyboard_switch_t *sw; - int args[2]; - int error; - - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - - /* reset, initialize and enable the device */ - args[0] = port; - args[1] = irq; - *kbd = NULL; - error = (*sw->probe)(unit, args, flags); - if (error) - return error; - error = (*sw->init)(unit, kbd, args, flags); - if (error) - return error; - (*sw->enable)(*kbd); - -#ifdef KBD_INSTALL_CDEV - /* attach a virtual keyboard cdev */ - error = kbd_attach(*kbd); - if (error) - return error; -#endif /* KBD_INSTALL_CDEV */ - - /* - * This is a kludge to compensate for lost keyboard interrupts. - * A similar code used to be in syscons. See below. XXX - */ - pckbd_timeout(*kbd); - - if (bootverbose) - (*sw->diag)(*kbd, bootverbose); - - return 0; -} - -static void -pckbd_timeout(void *arg) -{ - keyboard_t *kbd; - int s; - - /* The following comments are extracted from syscons.c (1.287) */ - /* - * With release 2.1 of the Xaccel server, the keyboard is left - * hanging pretty often. Apparently an interrupt from the - * keyboard is lost, and I don't know why (yet). - * This ugly hack calls scintr if input is ready for the keyboard - * and conveniently hides the problem. XXX - */ - /* - * Try removing anything stuck in the keyboard controller; whether - * it's a keyboard scan code or mouse data. `scintr()' doesn't - * read the mouse data directly, but `kbdio' routines will, as a - * side effect. - */ - s = spltty(); - kbd = (keyboard_t *)arg; - if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) { - /* - * We have seen the lock flag is not set. Let's reset - * the flag early, otherwise the LED update routine fails - * which may want the lock during the interrupt routine. - */ - (*kbdsw[kbd->kb_index]->lock)(kbd, FALSE); - if ((*kbdsw[kbd->kb_index]->check_char)(kbd)) - (*kbdsw[kbd->kb_index]->intr)(kbd, NULL); - } - splx(s); - timeout(pckbd_timeout, arg, hz/10); -} - -/* LOW-LEVEL */ - -#include <sys/limits.h> - -#define PC98KBD_DEFAULT 0 - -typedef caddr_t KBDC; - -typedef struct pckbd_state { - KBDC kbdc; /* keyboard controller */ - int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ - int ks_flags; /* flags */ -#define COMPOSE (1 << 0) - int ks_state; /* shift/lock key state */ - int ks_accents; /* accent key index (> 0) */ - u_int ks_composed_char; /* composed char code (> 0) */ -} pckbd_state_t; - -/* keyboard driver declaration */ -static int pckbd_configure(int flags); -static kbd_probe_t pckbd_probe; -static kbd_init_t pckbd_init; -static kbd_term_t pckbd_term; -static kbd_intr_t pckbd_intr; -static kbd_test_if_t pckbd_test_if; -static kbd_enable_t pckbd_enable; -static kbd_disable_t pckbd_disable; -static kbd_read_t pckbd_read; -static kbd_check_t pckbd_check; -static kbd_read_char_t pckbd_read_char; -static kbd_check_char_t pckbd_check_char; -static kbd_ioctl_t pckbd_ioctl; -static kbd_lock_t pckbd_lock; -static kbd_clear_state_t pckbd_clear_state; -static kbd_get_state_t pckbd_get_state; -static kbd_set_state_t pckbd_set_state; -static kbd_poll_mode_t pckbd_poll; - -keyboard_switch_t pckbdsw = { - pckbd_probe, - pckbd_init, - pckbd_term, - pckbd_intr, - pckbd_test_if, - pckbd_enable, - pckbd_disable, - pckbd_read, - pckbd_check, - pckbd_read_char, - pckbd_check_char, - pckbd_ioctl, - pckbd_lock, - pckbd_clear_state, - pckbd_get_state, - pckbd_set_state, - genkbd_get_fkeystr, - pckbd_poll, - genkbd_diag, -}; - -KEYBOARD_DRIVER(pckbd, pckbdsw, pckbd_configure); - -struct kbdc_softc { - int port; /* base port address */ - int lock; /* FIXME: XXX not quite a semaphore... */ -}; - -/* local functions */ -static int probe_keyboard(KBDC kbdc, int flags); -static int init_keyboard(KBDC kbdc, int *type, int flags); -static KBDC kbdc_open(int port); -static int kbdc_lock(KBDC kbdc, int lock); -static int kbdc_data_ready(KBDC kbdc); -static int read_kbd_data(KBDC kbdc); -static int read_kbd_data_no_wait(KBDC kbdc); -static int wait_for_kbd_data(struct kbdc_softc *kbdc); - -/* local variables */ - -/* the initial key map, accent map and fkey strings */ -#include <dev/kbd/kbdtables.h> - -/* structures for the default keyboard */ -static keyboard_t default_kbd; -static pckbd_state_t default_kbd_state; -static keymap_t default_keymap; -static accentmap_t default_accentmap; -static fkeytab_t default_fkeytab[NUM_FKEYS]; - -/* - * The back door to the keyboard driver! - * This function is called by the console driver, via the kbdio module, - * to tickle keyboard drivers when the low-level console is being initialized. - * Almost nothing in the kernel has been initialied yet. Try to probe - * keyboards if possible. - * NOTE: because of the way the low-level conole is initialized, this routine - * may be called more than once!! - */ -static int -pckbd_configure(int flags) -{ - keyboard_t *kbd; - int arg[2]; - int i; - - /* XXX: a kludge to obtain the device configuration flags */ - if (resource_int_value(DRIVER_NAME, 0, "flags", &i) == 0) { - flags |= i; - /* if the driver is disabled, unregister the keyboard if any */ - if (resource_disabled(DRIVER_NAME, 0)) { - i = kbd_find_keyboard(DRIVER_NAME, PC98KBD_DEFAULT); - if (i >= 0) { - kbd = kbd_get_keyboard(i); - kbd_unregister(kbd); - kbd->kb_flags &= ~KB_REGISTERED; - return 0; - } - } - } - - /* probe the default keyboard */ - arg[0] = -1; - arg[1] = -1; - kbd = NULL; - if (pckbd_probe(PC98KBD_DEFAULT, arg, flags)) - return 0; - if (pckbd_init(PC98KBD_DEFAULT, &kbd, arg, flags)) - return 0; - - /* return the number of found keyboards */ - return 1; -} - -/* low-level functions */ - -/* detect a keyboard */ -static int -pckbd_probe(int unit, void *arg, int flags) -{ - KBDC kbdc; - int *data = (int *)arg; - - if (unit != PC98KBD_DEFAULT) - return ENXIO; - if (KBD_IS_PROBED(&default_kbd)) - return 0; - - kbdc = kbdc_open(data[0]); - if (kbdc == NULL) - return ENXIO; - if (probe_keyboard(kbdc, flags)) { - if (flags & KB_CONF_FAIL_IF_NO_KBD) - return ENXIO; - } - return 0; -} - -/* reset and initialize the device */ -static int -pckbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) -{ - keyboard_t *kbd; - pckbd_state_t *state; - keymap_t *keymap; - accentmap_t *accmap; - fkeytab_t *fkeymap; - int fkeymap_size; - int *data = (int *)arg; - - if (unit != PC98KBD_DEFAULT) /* shouldn't happen */ - return ENXIO; - - *kbdp = kbd = &default_kbd; - state = &default_kbd_state; - if (!KBD_IS_PROBED(kbd)) { - keymap = &default_keymap; - accmap = &default_accentmap; - fkeymap = default_fkeytab; - fkeymap_size = - sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); - - state->kbdc = kbdc_open(data[0]); - if (state->kbdc == NULL) - return ENXIO; - kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, - data[0], IO_KBDSIZE); - bcopy(&key_map, keymap, sizeof(key_map)); - bcopy(&accent_map, accmap, sizeof(accent_map)); - bcopy(fkey_tab, fkeymap, - imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); - kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); - kbd->kb_data = (void *)state; - - if (probe_keyboard(state->kbdc, flags)) {/* shouldn't happen */ - if (flags & KB_CONF_FAIL_IF_NO_KBD) - return ENXIO; - } else { - KBD_FOUND_DEVICE(kbd); - } - pckbd_clear_state(kbd); - state->ks_mode = K_XLATE; - KBD_PROBE_DONE(kbd); - } - if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { - if (KBD_HAS_DEVICE(kbd) - && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) - && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) - return ENXIO; - pckbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); - KBD_INIT_DONE(kbd); - } - if (!KBD_IS_CONFIGURED(kbd)) { - if (kbd_register(kbd) < 0) - return ENXIO; - KBD_CONFIG_DONE(kbd); - } - - return 0; -} - -/* finish using this keyboard */ -static int -pckbd_term(keyboard_t *kbd) -{ - kbd_unregister(kbd); - return 0; -} - -/* keyboard interrupt routine */ -static int -pckbd_intr(keyboard_t *kbd, void *arg) -{ - int c; - - if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { - /* let the callback function to process the input */ - (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, - kbd->kb_callback.kc_arg); - } else { - /* read and discard the input; no one is waiting for input */ - do { - c = pckbd_read_char(kbd, FALSE); - } while (c != NOKEY); - } - return 0; -} - -/* test the interface to the device */ -static int -pckbd_test_if(keyboard_t *kbd) -{ - return 0; -} - -/* - * Enable the access to the device; until this function is called, - * the client cannot read from the keyboard. - */ -static int -pckbd_enable(keyboard_t *kbd) -{ - int s; - - s = spltty(); - KBD_ACTIVATE(kbd); - splx(s); - return 0; -} - -/* disallow the access to the device */ -static int -pckbd_disable(keyboard_t *kbd) -{ - int s; - - s = spltty(); - KBD_DEACTIVATE(kbd); - splx(s); - return 0; -} - -/* read one byte from the keyboard if it's allowed */ -static int -pckbd_read(keyboard_t *kbd, int wait) -{ - int c; - - if (wait) - c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc); - else - c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc); - if (c != -1) - ++kbd->kb_count; - return (KBD_IS_ACTIVE(kbd) ? c : -1); -} - -/* check if data is waiting */ -static int -pckbd_check(keyboard_t *kbd) -{ - if (!KBD_IS_ACTIVE(kbd)) - return FALSE; - return kbdc_data_ready(((pckbd_state_t *)kbd->kb_data)->kbdc); -} - -/* read char from the keyboard */ -static u_int -pckbd_read_char(keyboard_t *kbd, int wait) -{ - pckbd_state_t *state; - u_int action; - int scancode; - int keycode; - - state = (pckbd_state_t *)kbd->kb_data; -next_code: - /* do we have a composed char to return? */ - if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { - action = state->ks_composed_char; - state->ks_composed_char = 0; - if (action > UCHAR_MAX) - return ERRKEY; - return action; - } - - /* see if there is something in the keyboard port */ - if (wait) { - do { - scancode = read_kbd_data(state->kbdc); - } while (scancode == -1); - } else { - scancode = read_kbd_data_no_wait(state->kbdc); - if (scancode == -1) - return NOKEY; - } - ++kbd->kb_count; - -#if 0 - printf("pckbd_read_char(): scancode:0x%x\n", scancode); -#endif - - /* return the byte as is for the K_RAW mode */ - if (state->ks_mode == K_RAW) - return scancode; - - /* translate the scan code into a keycode */ - keycode = scancode & 0x7F; - switch(scancode) { - case 0xF3: /* GRPH (compose key) released */ - if (state->ks_flags & COMPOSE) { - state->ks_flags &= ~COMPOSE; - if (state->ks_composed_char > UCHAR_MAX) - state->ks_composed_char = 0; - } - break; - case 0x73: /* GRPH (compose key) pressed */ - if (!(state->ks_flags & COMPOSE)) { - state->ks_flags |= COMPOSE; - state->ks_composed_char = 0; - } - break; - } - - /* return the key code in the K_CODE mode */ - if (state->ks_mode == K_CODE) - return (keycode | (scancode & 0x80)); - - /* compose a character code */ - if (state->ks_flags & COMPOSE) { - switch (scancode) { - /* key pressed, process it */ - case 0x42: case 0x43: case 0x44: /* keypad 7,8,9 */ - state->ks_composed_char *= 10; - state->ks_composed_char += scancode - 0x3B; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - case 0x46: case 0x47: case 0x48: /* keypad 4,5,6 */ - state->ks_composed_char *= 10; - state->ks_composed_char += scancode - 0x42; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - case 0x4A: case 0x4B: case 0x4C: /* keypad 1,2,3 */ - state->ks_composed_char *= 10; - state->ks_composed_char += scancode - 0x49; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - case 0x4E: /* keypad 0 */ - state->ks_composed_char *= 10; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - - /* key released, no interest here */ - case 0xC2: case 0xC3: case 0xC4: /* keypad 7,8,9 */ - case 0xC6: case 0xC7: case 0xC8: /* keypad 4,5,6 */ - case 0xCA: case 0xCB: case 0xCC: /* keypad 1,2,3 */ - case 0xCE: /* keypad 0 */ - goto next_code; - - case 0x73: /* GRPH key */ - break; - - default: - if (state->ks_composed_char > 0) { - state->ks_flags &= ~COMPOSE; - state->ks_composed_char = 0; - return ERRKEY; - } - break; - } - } - - /* keycode to key action */ - action = genkbd_keyaction(kbd, keycode, scancode & 0x80, - &state->ks_state, &state->ks_accents); - if (action == NOKEY) - goto next_code; - else - return action; -} - -/* check if char is waiting */ -static int -pckbd_check_char(keyboard_t *kbd) -{ - pckbd_state_t *state; - - if (!KBD_IS_ACTIVE(kbd)) - return FALSE; - state = (pckbd_state_t *)kbd->kb_data; - if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) - return TRUE; - return kbdc_data_ready(state->kbdc); -} - -/* some useful control functions */ -static int -pckbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) -{ - pckbd_state_t *state = kbd->kb_data; - int s; - int i; - - s = spltty(); - switch (cmd) { - - case KDGKBMODE: /* get keyboard mode */ - *(int *)arg = state->ks_mode; - break; - case KDSKBMODE: /* set keyboard mode */ - switch (*(int *)arg) { - case K_XLATE: - if (state->ks_mode != K_XLATE) { - /* make lock key state and LED state match */ - state->ks_state &= ~LOCK_MASK; - state->ks_state |= KBD_LED_VAL(kbd); - } - /* FALLTHROUGH */ - case K_RAW: - case K_CODE: - if (state->ks_mode != *(int *)arg) { - pckbd_clear_state(kbd); - state->ks_mode = *(int *)arg; - } - break; - default: - splx(s); - return EINVAL; - } - break; - - case KDGETLED: /* get keyboard LED */ - *(int *)arg = KBD_LED_VAL(kbd); - break; - case KDSETLED: /* set keyboard LED */ - /* NOTE: lock key state in ks_state won't be changed */ - if (*(int *)arg & ~LOCK_MASK) { - splx(s); - return EINVAL; - } - i = *(int *)arg; - /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ - if (kbd->kb_keymap->n_keys > ALTGR_OFFSET) { - if (i & ALKED) - i |= CLKED; - else - i &= ~CLKED; - } - KBD_LED_VAL(kbd) = *(int *)arg; - break; - - case KDGKBSTATE: /* get lock key state */ - *(int *)arg = state->ks_state & LOCK_MASK; - break; - case KDSKBSTATE: /* set lock key state */ - if (*(int *)arg & ~LOCK_MASK) { - splx(s); - return EINVAL; - } - state->ks_state &= ~LOCK_MASK; - state->ks_state |= *(int *)arg; - splx(s); - /* set LEDs and quit */ - return pckbd_ioctl(kbd, KDSETLED, arg); - - case KDSETRAD: /* set keyboard repeat rate (old interface)*/ - break; - case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ - break; - - case PIO_KEYMAP: /* set keyboard translation table */ - case PIO_KEYMAPENT: /* set keyboard translation table entry */ - case PIO_DEADKEYMAP: /* set accent key translation table */ - state->ks_accents = 0; - /* FALLTHROUGH */ - default: - splx(s); - return genkbd_commonioctl(kbd, cmd, arg); - } - - splx(s); - return 0; -} - -/* lock the access to the keyboard */ -static int -pckbd_lock(keyboard_t *kbd, int lock) -{ - return kbdc_lock(((pckbd_state_t *)kbd->kb_data)->kbdc, lock); -} - -/* clear the internal state of the keyboard */ -static void -pckbd_clear_state(keyboard_t *kbd) -{ - pckbd_state_t *state; - - state = (pckbd_state_t *)kbd->kb_data; - state->ks_flags = 0; - state->ks_state &= LOCK_MASK; /* preserve locking key state */ - state->ks_accents = 0; - state->ks_composed_char = 0; -} - -/* save the internal state */ -static int -pckbd_get_state(keyboard_t *kbd, void *buf, size_t len) -{ - if (len == 0) - return sizeof(pckbd_state_t); - if (len < sizeof(pckbd_state_t)) - return -1; - bcopy(kbd->kb_data, buf, sizeof(pckbd_state_t)); - return 0; -} - -/* set the internal state */ -static int -pckbd_set_state(keyboard_t *kbd, void *buf, size_t len) -{ - if (len < sizeof(pckbd_state_t)) - return ENOMEM; - if (((pckbd_state_t *)kbd->kb_data)->kbdc - != ((pckbd_state_t *)buf)->kbdc) - return ENOMEM; - bcopy(buf, kbd->kb_data, sizeof(pckbd_state_t)); - return 0; -} - -/* set polling mode */ -static int -pckbd_poll(keyboard_t *kbd, int on) -{ - return 0; -} - -/* local functions */ - -static int -probe_keyboard(KBDC kbdc, int flags) -{ - return 0; -} - -static int -init_keyboard(KBDC kbdc, int *type, int flags) -{ - *type = KB_OTHER; - return 0; -} - -/* keyboard I/O routines */ - -/* retry count */ -#ifndef KBD_MAXRETRY -#define KBD_MAXRETRY 3 -#endif - -/* timing parameters */ -#ifndef KBD_RESETDELAY -#define KBD_RESETDELAY 200 /* wait 200msec after kbd/mouse reset */ -#endif -#ifndef KBD_MAXWAIT -#define KBD_MAXWAIT 5 /* wait 5 times at most after reset */ -#endif - -/* I/O recovery time */ -#define KBDC_DELAYTIME 37 -#define KBDD_DELAYTIME 37 - -/* I/O ports */ -#define KBD_STATUS_PORT 2 /* status port, read */ -#define KBD_DATA_PORT 0 /* data port, read */ - -/* status bits (KBD_STATUS_PORT) */ -#define KBDS_BUFFER_FULL 0x0002 - -/* macros */ - -#define kbdcp(p) ((struct kbdc_softc *)(p)) - -/* local variables */ - -static struct kbdc_softc kbdc_softc[1] = { { 0 }, }; - -/* associate a port number with a KBDC */ - -static KBDC -kbdc_open(int port) -{ - if (port <= 0) - port = IO_KBD; - - /* PC-98 has only one keyboard I/F */ - kbdc_softc[0].port = port; - kbdc_softc[0].lock = FALSE; - return (KBDC)&kbdc_softc[0]; -} - -/* set/reset polling lock */ -static int -kbdc_lock(KBDC p, int lock) -{ - int prevlock; - - prevlock = kbdcp(p)->lock; - kbdcp(p)->lock = lock; - - return (prevlock != lock); -} - -/* check if any data is waiting to be processed */ -static int -kbdc_data_ready(KBDC p) -{ - return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL); -} - -/* wait for data from the keyboard */ -static int -wait_for_kbd_data(struct kbdc_softc *kbdc) -{ - /* CPU will stay inside the loop for 200msec at most */ - int retry = 10000; - int port = kbdc->port; - - while (!(inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)) { - DELAY(KBDD_DELAYTIME); - DELAY(KBDC_DELAYTIME); - if (--retry < 0) - return 0; - } - DELAY(KBDD_DELAYTIME); - return 1; -} - -/* read one byte from the keyboard */ -static int -read_kbd_data(KBDC p) -{ - if (!wait_for_kbd_data(kbdcp(p))) - return -1; /* timeout */ - DELAY(KBDC_DELAYTIME); - return inb(kbdcp(p)->port + KBD_DATA_PORT); -} - -/* read one byte from the keyboard, but return immediately if - * no data is waiting - */ -static int -read_kbd_data_no_wait(KBDC p) -{ - if (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) { - DELAY(KBDD_DELAYTIME); - return inb(kbdcp(p)->port + KBD_DATA_PORT); - } - return -1; /* no data */ -} diff --git a/sys/pc98/pc98/pmc.c b/sys/pc98/pc98/pmc.c deleted file mode 100644 index 13eade0..0000000 --- a/sys/pc98/pc98/pmc.c +++ /dev/null @@ -1,245 +0,0 @@ -/*- - * PMC (Power Management Controller of NEC PC-98Note) Driver - * - * Copyright (c) 2001 Chiharu Shibata. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/eventhandler.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/types.h> -#include <sys/conf.h> -#include <sys/reboot.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <isa/isavar.h> - -struct pmc_isa_softc { - struct resource *port_res; - eventhandler_tag evt; - int flags; -}; - -static int pmc_isa_alloc_resources(device_t); -static void pmc_isa_release_resources(device_t); -static int pmc_isa_probe(device_t); -static int pmc_isa_attach(device_t); -static int pmc_isa_detach(device_t); - -#define PMC_ISA_PORT 0x8f0 -#define PMC_ISA_PORTSIZE 4 - -#define sc_inw(sc, port) \ - bus_space_read_2(rman_get_bustag((sc)->port_res), \ - rman_get_bushandle((sc)->port_res), (port)) - -#define sc_outw(sc, port, value) \ - bus_space_write_2(rman_get_bustag((sc)->port_res), \ - rman_get_bushandle((sc)->port_res), (port), (value)) - -static void -pmc_poweroff(void *arg, int howto) -{ - struct pmc_isa_softc *sc = (struct pmc_isa_softc *)arg; - - if (!sc->flags) { - outb(0x5e8e, inb(0x5e8e) & ~0x11); /* FDD LED off */ - } - - if (!(howto & RB_POWEROFF)) { - return; - } - - sc_outw(sc, 0, 0x0044); - sc_outw(sc, 2, 1 << 10); -#if 1 - /* for 9801NS/T */ - sc_outw(sc, 0, 0xf00a); - sc_outw(sc, 2, 1 << 9); -#endif -} - -static int -pmc_isa_alloc_resources(device_t dev) -{ - struct pmc_isa_softc *sc = device_get_softc(dev); - int rid; - - bzero(sc, sizeof(*sc)); - - rid = 0; - sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0ul, ~0ul, PMC_ISA_PORTSIZE, - RF_ACTIVE); - if (sc->port_res == NULL) { - return (ENOMEM); - } - - return 0; -} - -static void -pmc_isa_release_resources(device_t dev) -{ - struct pmc_isa_softc *sc = device_get_softc(dev); - - if (sc->port_res != NULL) { - bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port_res); - } - sc->port_res = NULL; -} - -static int -pmc_isa_probe(device_t dev) -{ - struct pmc_isa_softc *sc = device_get_softc(dev); - u_int port; - u_int16_t save, tmp; - -#if 0 - if (isa_get_vendorid(dev)) { - return ENXIO; - } - if (device_get_unit(dev) > 0) { - printf("pmc: Only one PMC driver supported.\n"); - return ENXIO; - } -#endif - port = isa_get_port(dev); - if (port == -1) { - port = PMC_ISA_PORT; - } - if (bootverbose) { - device_printf(dev, "port = 0x%x\n", port); - } - - if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port, PMC_ISA_PORTSIZE)) { - if (bootverbose) { - device_printf(dev, "bus_set_resource failed\n"); - } - return ENXIO; - } - if (pmc_isa_alloc_resources(dev)) { - if (bootverbose) { - device_printf(dev, "pmc_isa_alloc_resources failed\n"); - } - return ENXIO; - } - - /* Check the existence of PMC */ - sc_outw(sc, 0, 0x0052); - save = sc_inw(sc, 2); - tmp = save & ~0x3f; - sc_outw(sc, 2, tmp); - if (sc_inw(sc, 2) != tmp) { - if (bootverbose) { - device_printf(dev, "failed to clear index(0x0052)\n"); - } - - pmc_isa_release_resources(dev); - return ENXIO; - } - - tmp |= 0x3e; - sc_outw(sc, 2, tmp); - if (sc_inw(sc, 2) != tmp) { - if (bootverbose) { - device_printf(dev, "failed to set index(0x0052)\n"); - } - - pmc_isa_release_resources(dev); - return ENXIO; - } - sc_outw(sc, 2, save); - - pmc_isa_release_resources(dev); - - device_set_desc(dev, "Power Management Controller"); - return 0; -} - -static int -pmc_isa_attach(device_t dev) -{ - struct pmc_isa_softc *sc = device_get_softc(dev); - int error; - - error = pmc_isa_alloc_resources(dev); - if (error) { - device_printf(dev, "resource allocation failed\n"); - return error; - } - - /* Power the system off using PMC */ - sc->evt = EVENTHANDLER_REGISTER(shutdown_final, pmc_poweroff, sc, - SHUTDOWN_PRI_LAST); - sc->flags = device_get_flags(dev); - return 0; -} - -static int -pmc_isa_detach(device_t dev) -{ - struct pmc_isa_softc *sc = device_get_softc(dev); - - if (bootverbose) { - device_printf(dev, "pmc_isa_detach called\n"); - } - - if (sc->evt != NULL) { - EVENTHANDLER_DEREGISTER(shutdown_final, sc->evt); - } - sc->evt = NULL; - - pmc_isa_release_resources(dev); - return 0; -} - -static device_method_t pmc_isa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pmc_isa_probe), - DEVMETHOD(device_attach, pmc_isa_attach), - DEVMETHOD(device_detach, pmc_isa_detach), - {0, 0} -}; - -static driver_t pmc_isa_driver = { - "pmc", - pmc_isa_methods, sizeof(struct pmc_isa_softc), -}; - -devclass_t pmc_devclass; - -DRIVER_MODULE(pmc, isa, pmc_isa_driver, pmc_devclass, 0, 0); diff --git a/sys/pc98/pc98/ppc.c b/sys/pc98/pc98/ppc.c deleted file mode 100644 index 67adef3..0000000 --- a/sys/pc98/pc98/ppc.c +++ /dev/null @@ -1,2212 +0,0 @@ -/*- - * Copyright (c) 2001 Alcove - Nicolas Souchu - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - * - */ - -#include "opt_ppc.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <machine/vmparam.h> -#include <sys/rman.h> - -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#else -#include <isa/isareg.h> -#endif -#include <isa/isavar.h> - -#include <dev/ppbus/ppbconf.h> -#include <dev/ppbus/ppb_msq.h> - -#include <dev/ppc/ppcvar.h> -#ifdef PC98 -#include <pc98/pc98/ppcreg.h> -#else -#include <dev/ppc/ppcreg.h> -#endif - -#include "ppbus_if.h" - -static int ppc_cbus_probe(device_t dev); - -static void ppcintr(void *arg); - -#define LOG_PPC(function, ppc, string) \ - if (bootverbose) printf("%s: %s\n", function, string) - - -#define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev)) - -devclass_t ppc_devclass; - -static device_method_t ppc_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, ppc_cbus_probe), - DEVMETHOD(device_attach, ppc_attach), - - /* bus interface */ - DEVMETHOD(bus_read_ivar, ppc_read_ivar), - DEVMETHOD(bus_setup_intr, ppc_setup_intr), - DEVMETHOD(bus_teardown_intr, ppc_teardown_intr), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), - - /* ppbus interface */ - DEVMETHOD(ppbus_io, ppc_io), - DEVMETHOD(ppbus_exec_microseq, ppc_exec_microseq), - DEVMETHOD(ppbus_reset_epp, ppc_reset_epp), - DEVMETHOD(ppbus_setmode, ppc_setmode), - DEVMETHOD(ppbus_ecp_sync, ppc_ecp_sync), - DEVMETHOD(ppbus_read, ppc_read), - DEVMETHOD(ppbus_write, ppc_write), - - { 0, 0 } - }; - -static driver_t ppc_driver = { - "ppc", - ppc_methods, - sizeof(struct ppc_data), -}; - -static char *ppc_models[] = { - "SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306", - "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", - "SMC FDC37C935", "PC87303", 0 -}; - -/* list of available modes */ -static char *ppc_avms[] = { - "COMPATIBLE", "NIBBLE-only", "PS2-only", "PS2/NIBBLE", "EPP-only", - "EPP/NIBBLE", "EPP/PS2", "EPP/PS2/NIBBLE", "ECP-only", - "ECP/NIBBLE", "ECP/PS2", "ECP/PS2/NIBBLE", "ECP/EPP", - "ECP/EPP/NIBBLE", "ECP/EPP/PS2", "ECP/EPP/PS2/NIBBLE", 0 -}; - -/* list of current executing modes - * Note that few modes do not actually exist. - */ -static char *ppc_modes[] = { - "COMPATIBLE", "NIBBLE", "PS/2", "PS/2", "EPP", - "EPP", "EPP", "EPP", "ECP", - "ECP", "ECP+PS2", "ECP+PS2", "ECP+EPP", - "ECP+EPP", "ECP+EPP", "ECP+EPP", 0 -}; - -static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 }; - -#ifdef __i386__ -/* - * BIOS printer list - used by BIOS probe. - */ -#define BIOS_PPC_PORTS 0x408 -#define BIOS_PORTS (short *)(KERNBASE+BIOS_PPC_PORTS) -#define BIOS_MAX_PPC 4 -#endif - -/* - * ppc_ecp_sync() XXX - */ -void -ppc_ecp_sync(device_t dev) { - - int i, r; - struct ppc_data *ppc = DEVTOSOFTC(dev); - - if (!(ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_dtm & PPB_ECP)) - return; - - r = r_ecr(ppc); - if ((r & 0xe0) != PPC_ECR_EPP) - return; - - for (i = 0; i < 100; i++) { - r = r_ecr(ppc); - if (r & 0x1) - return; - DELAY(100); - } - - printf("ppc%d: ECP sync failed as data still " \ - "present in FIFO.\n", ppc->ppc_unit); - - return; -} - -/* - * ppc_detect_fifo() - * - * Detect parallel port FIFO - */ -static int -ppc_detect_fifo(struct ppc_data *ppc) -{ - char ecr_sav; - char ctr_sav, ctr, cc; - short i; - - /* save registers */ - ecr_sav = r_ecr(ppc); - ctr_sav = r_ctr(ppc); - - /* enter ECP configuration mode, no interrupt, no DMA */ - w_ecr(ppc, 0xf4); - - /* read PWord size - transfers in FIFO mode must be PWord aligned */ - ppc->ppc_pword = (r_cnfgA(ppc) & PPC_PWORD_MASK); - - /* XXX 16 and 32 bits implementations not supported */ - if (ppc->ppc_pword != PPC_PWORD_8) { - LOG_PPC(__func__, ppc, "PWord not supported"); - goto error; - } - - w_ecr(ppc, 0x34); /* byte mode, no interrupt, no DMA */ - ctr = r_ctr(ppc); - w_ctr(ppc, ctr | PCD); /* set direction to 1 */ - - /* enter ECP test mode, no interrupt, no DMA */ - w_ecr(ppc, 0xd4); - - /* flush the FIFO */ - for (i=0; i<1024; i++) { - if (r_ecr(ppc) & PPC_FIFO_EMPTY) - break; - cc = r_fifo(ppc); - } - - if (i >= 1024) { - LOG_PPC(__func__, ppc, "can't flush FIFO"); - goto error; - } - - /* enable interrupts, no DMA */ - w_ecr(ppc, 0xd0); - - /* determine readIntrThreshold - * fill the FIFO until serviceIntr is set - */ - for (i=0; i<1024; i++) { - w_fifo(ppc, (char)i); - if (!ppc->ppc_rthr && (r_ecr(ppc) & PPC_SERVICE_INTR)) { - /* readThreshold reached */ - ppc->ppc_rthr = i+1; - } - if (r_ecr(ppc) & PPC_FIFO_FULL) { - ppc->ppc_fifo = i+1; - break; - } - } - - if (i >= 1024) { - LOG_PPC(__func__, ppc, "can't fill FIFO"); - goto error; - } - - w_ecr(ppc, 0xd4); /* test mode, no interrupt, no DMA */ - w_ctr(ppc, ctr & ~PCD); /* set direction to 0 */ - w_ecr(ppc, 0xd0); /* enable interrupts */ - - /* determine writeIntrThreshold - * empty the FIFO until serviceIntr is set - */ - for (i=ppc->ppc_fifo; i>0; i--) { - if (r_fifo(ppc) != (char)(ppc->ppc_fifo-i)) { - LOG_PPC(__func__, ppc, "invalid data in FIFO"); - goto error; - } - if (r_ecr(ppc) & PPC_SERVICE_INTR) { - /* writeIntrThreshold reached */ - ppc->ppc_wthr = ppc->ppc_fifo - i+1; - } - /* if FIFO empty before the last byte, error */ - if (i>1 && (r_ecr(ppc) & PPC_FIFO_EMPTY)) { - LOG_PPC(__func__, ppc, "data lost in FIFO"); - goto error; - } - } - - /* FIFO must be empty after the last byte */ - if (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) { - LOG_PPC(__func__, ppc, "can't empty the FIFO"); - goto error; - } - - w_ctr(ppc, ctr_sav); - w_ecr(ppc, ecr_sav); - - return (0); - -error: - w_ctr(ppc, ctr_sav); - w_ecr(ppc, ecr_sav); - - return (EINVAL); -} - -static int -ppc_detect_port(struct ppc_data *ppc) -{ - - w_ctr(ppc, 0x0c); /* To avoid missing PS2 ports */ - w_dtr(ppc, 0xaa); - if (r_dtr(ppc) != 0xaa) - return (0); - - return (1); -} - -/* - * EPP timeout, according to the PC87332 manual - * Semantics of clearing EPP timeout bit. - * PC87332 - reading SPP_STR does it... - * SMC - write 1 to EPP timeout bit XXX - * Others - (?) write 0 to EPP timeout bit - */ -static void -ppc_reset_epp_timeout(struct ppc_data *ppc) -{ - register char r; - - r = r_str(ppc); - w_str(ppc, r | 0x1); - w_str(ppc, r & 0xfe); - - return; -} - -static int -ppc_check_epp_timeout(struct ppc_data *ppc) -{ - ppc_reset_epp_timeout(ppc); - - return (!(r_str(ppc) & TIMEOUT)); -} - -/* - * Configure current operating mode - */ -static int -ppc_generic_setmode(struct ppc_data *ppc, int mode) -{ - u_char ecr = 0; - - /* check if mode is available */ - if (mode && !(ppc->ppc_avm & mode)) - return (EINVAL); - - /* if ECP mode, configure ecr register */ - if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) { - /* return to byte mode (keeping direction bit), - * no interrupt, no DMA to be able to change to - * ECP - */ - w_ecr(ppc, PPC_ECR_RESET); - ecr = PPC_DISABLE_INTR; - - if (mode & PPB_EPP) - return (EINVAL); - else if (mode & PPB_ECP) - /* select ECP mode */ - ecr |= PPC_ECR_ECP; - else if (mode & PPB_PS2) - /* select PS2 mode with ECP */ - ecr |= PPC_ECR_PS2; - else - /* select COMPATIBLE/NIBBLE mode */ - ecr |= PPC_ECR_STD; - - w_ecr(ppc, ecr); - } - - ppc->ppc_mode = mode; - - return (0); -} - -/* - * The ppc driver is free to choose options like FIFO or DMA - * if ECP mode is available. - * - * The 'RAW' option allows the upper drivers to force the ppc mode - * even with FIFO, DMA available. - */ -static int -ppc_smclike_setmode(struct ppc_data *ppc, int mode) -{ - u_char ecr = 0; - - /* check if mode is available */ - if (mode && !(ppc->ppc_avm & mode)) - return (EINVAL); - - /* if ECP mode, configure ecr register */ - if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) { - /* return to byte mode (keeping direction bit), - * no interrupt, no DMA to be able to change to - * ECP or EPP mode - */ - w_ecr(ppc, PPC_ECR_RESET); - ecr = PPC_DISABLE_INTR; - - if (mode & PPB_EPP) - /* select EPP mode */ - ecr |= PPC_ECR_EPP; - else if (mode & PPB_ECP) - /* select ECP mode */ - ecr |= PPC_ECR_ECP; - else if (mode & PPB_PS2) - /* select PS2 mode with ECP */ - ecr |= PPC_ECR_PS2; - else - /* select COMPATIBLE/NIBBLE mode */ - ecr |= PPC_ECR_STD; - - w_ecr(ppc, ecr); - } - - ppc->ppc_mode = mode; - - return (0); -} - -#ifdef PPC_PROBE_CHIPSET -/* - * ppc_pc873xx_detect - * - * Probe for a Natsemi PC873xx-family part. - * - * References in this function are to the National Semiconductor - * PC87332 datasheet TL/C/11930, May 1995 revision. - */ -static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0}; -static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0}; -static int pc873xx_irqtab[] = {5, 7, 5, 0}; - -static int pc873xx_regstab[] = { - PC873_FER, PC873_FAR, PC873_PTR, - PC873_FCR, PC873_PCR, PC873_PMC, - PC873_TUP, PC873_SID, PC873_PNP0, - PC873_PNP1, PC873_LPTBA, -1 -}; - -static char *pc873xx_rnametab[] = { - "FER", "FAR", "PTR", "FCR", "PCR", - "PMC", "TUP", "SID", "PNP0", "PNP1", - "LPTBA", NULL -}; - -static int -ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never forced */ -{ - static int index = 0; - int idport, irq; - int ptr, pcr, val, i; - - while ((idport = pc873xx_basetab[index++])) { - - /* XXX should check first to see if this location is already claimed */ - - /* - * Pull the 873xx through the power-on ID cycle (2.2,1.). - * We can't use this to locate the chip as it may already have - * been used by the BIOS. - */ - (void)inb(idport); (void)inb(idport); - (void)inb(idport); (void)inb(idport); - - /* - * Read the SID byte. Possible values are : - * - * 01010xxx PC87334 - * 0001xxxx PC87332 - * 01110xxx PC87306 - * 00110xxx PC87303 - */ - outb(idport, PC873_SID); - val = inb(idport + 1); - if ((val & 0xf0) == 0x10) { - ppc->ppc_model = NS_PC87332; - } else if ((val & 0xf8) == 0x70) { - ppc->ppc_model = NS_PC87306; - } else if ((val & 0xf8) == 0x50) { - ppc->ppc_model = NS_PC87334; - } else if ((val & 0xf8) == 0x40) { /* Should be 0x30 by the - documentation, but probing - yielded 0x40... */ - ppc->ppc_model = NS_PC87303; - } else { - if (bootverbose && (val != 0xff)) - printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val); - continue ; /* not recognised */ - } - - /* print registers */ - if (bootverbose) { - printf("PC873xx"); - for (i=0; pc873xx_regstab[i] != -1; i++) { - outb(idport, pc873xx_regstab[i]); - printf(" %s=0x%x", pc873xx_rnametab[i], - inb(idport + 1) & 0xff); - } - printf("\n"); - } - - /* - * We think we have one. Is it enabled and where we want it to be? - */ - outb(idport, PC873_FER); - val = inb(idport + 1); - if (!(val & PC873_PPENABLE)) { - if (bootverbose) - printf("PC873xx parallel port disabled\n"); - continue; - } - outb(idport, PC873_FAR); - val = inb(idport + 1); - /* XXX we should create a driver instance for every port found */ - if (pc873xx_porttab[val & 0x3] != ppc->ppc_base) { - - /* First try to change the port address to that requested... */ - - switch(ppc->ppc_base) { - case 0x378: - val &= 0xfc; - break; - - case 0x3bc: - val &= 0xfd; - break; - - case 0x278: - val &= 0xfe; - break; - - default: - val &= 0xfd; - break; - } - - outb(idport, PC873_FAR); - outb(idport + 1, val); - outb(idport + 1, val); - - /* Check for success by reading back the value we supposedly - wrote and comparing...*/ - - outb(idport, PC873_FAR); - val = inb(idport + 1) & 0x3; - - /* If we fail, report the failure... */ - - if (pc873xx_porttab[val] != ppc->ppc_base) { - if (bootverbose) - printf("PC873xx at 0x%x not for driver at port 0x%x\n", - pc873xx_porttab[val], ppc->ppc_base); - } - continue; - } - - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - - /* get irq settings */ - if (ppc->ppc_base == 0x378) - irq = (ptr & PC873_LPTBIRQ7) ? 7 : 5; - else - irq = pc873xx_irqtab[val]; - - if (bootverbose) - printf("PC873xx irq %d at 0x%x\n", irq, ppc->ppc_base); - - /* - * Check if irq settings are correct - */ - if (irq != ppc->ppc_irq) { - /* - * If the chipset is not locked and base address is 0x378, - * we have another chance - */ - if (ppc->ppc_base == 0x378 && !(ptr & PC873_CFGLOCK)) { - if (ppc->ppc_irq == 7) { - outb(idport + 1, (ptr | PC873_LPTBIRQ7)); - outb(idport + 1, (ptr | PC873_LPTBIRQ7)); - } else { - outb(idport + 1, (ptr & ~PC873_LPTBIRQ7)); - outb(idport + 1, (ptr & ~PC873_LPTBIRQ7)); - } - if (bootverbose) - printf("PC873xx irq set to %d\n", ppc->ppc_irq); - } else { - if (bootverbose) - printf("PC873xx sorry, can't change irq setting\n"); - } - } else { - if (bootverbose) - printf("PC873xx irq settings are correct\n"); - } - - outb(idport, PC873_PCR); - pcr = inb(idport + 1); - - if ((ptr & PC873_CFGLOCK) || !chipset_mode) { - if (bootverbose) - printf("PC873xx %s", (ptr & PC873_CFGLOCK)?"locked":"unlocked"); - - ppc->ppc_avm |= PPB_NIBBLE; - if (bootverbose) - printf(", NIBBLE"); - - if (pcr & PC873_EPPEN) { - ppc->ppc_avm |= PPB_EPP; - - if (bootverbose) - printf(", EPP"); - - if (pcr & PC873_EPP19) - ppc->ppc_epp = EPP_1_9; - else - ppc->ppc_epp = EPP_1_7; - - if ((ppc->ppc_model == NS_PC87332) && bootverbose) { - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - if (ptr & PC873_EPPRDIR) - printf(", Regular mode"); - else - printf(", Automatic mode"); - } - } else if (pcr & PC873_ECPEN) { - ppc->ppc_avm |= PPB_ECP; - if (bootverbose) - printf(", ECP"); - - if (pcr & PC873_ECPCLK) { /* XXX */ - ppc->ppc_avm |= PPB_PS2; - if (bootverbose) - printf(", PS/2"); - } - } else { - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - if (ptr & PC873_EXTENDED) { - ppc->ppc_avm |= PPB_SPP; - if (bootverbose) - printf(", SPP"); - } - } - } else { - if (bootverbose) - printf("PC873xx unlocked"); - - if (chipset_mode & PPB_ECP) { - if ((chipset_mode & PPB_EPP) && bootverbose) - printf(", ECP+EPP not supported"); - - pcr &= ~PC873_EPPEN; - pcr |= (PC873_ECPEN | PC873_ECPCLK); /* XXX */ - outb(idport + 1, pcr); - outb(idport + 1, pcr); - - if (bootverbose) - printf(", ECP"); - - } else if (chipset_mode & PPB_EPP) { - pcr &= ~(PC873_ECPEN | PC873_ECPCLK); - pcr |= (PC873_EPPEN | PC873_EPP19); - outb(idport + 1, pcr); - outb(idport + 1, pcr); - - ppc->ppc_epp = EPP_1_9; /* XXX */ - - if (bootverbose) - printf(", EPP1.9"); - - /* enable automatic direction turnover */ - if (ppc->ppc_model == NS_PC87332) { - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - ptr &= ~PC873_EPPRDIR; - outb(idport + 1, ptr); - outb(idport + 1, ptr); - - if (bootverbose) - printf(", Automatic mode"); - } - } else { - pcr &= ~(PC873_ECPEN | PC873_ECPCLK | PC873_EPPEN); - outb(idport + 1, pcr); - outb(idport + 1, pcr); - - /* configure extended bit in PTR */ - outb(idport, PC873_PTR); - ptr = inb(idport + 1); - - if (chipset_mode & PPB_PS2) { - ptr |= PC873_EXTENDED; - - if (bootverbose) - printf(", PS/2"); - - } else { - /* default to NIBBLE mode */ - ptr &= ~PC873_EXTENDED; - - if (bootverbose) - printf(", NIBBLE"); - } - outb(idport + 1, ptr); - outb(idport + 1, ptr); - } - - ppc->ppc_avm = chipset_mode; - } - - if (bootverbose) - printf("\n"); - - ppc->ppc_type = PPC_TYPE_GENERIC; - ppc_generic_setmode(ppc, chipset_mode); - - return(chipset_mode); - } - return(-1); -} - -/* - * ppc_smc37c66xgt_detect - * - * SMC FDC37C66xGT configuration. - */ -static int -ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode) -{ - int s, i; - u_char r; - int type = -1; - int csr = SMC66x_CSR; /* initial value is 0x3F0 */ - - int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 }; - - -#define cio csr+1 /* config IO port is either 0x3F1 or 0x371 */ - - /* - * Detection: enter configuration mode and read CRD register. - */ - - s = splhigh(); - outb(csr, SMC665_iCODE); - outb(csr, SMC665_iCODE); - splx(s); - - outb(csr, 0xd); - if (inb(cio) == 0x65) { - type = SMC_37C665GT; - goto config; - } - - for (i = 0; i < 2; i++) { - s = splhigh(); - outb(csr, SMC666_iCODE); - outb(csr, SMC666_iCODE); - splx(s); - - outb(csr, 0xd); - if (inb(cio) == 0x66) { - type = SMC_37C666GT; - break; - } - - /* Another chance, CSR may be hard-configured to be at 0x370 */ - csr = SMC666_CSR; - } - -config: - /* - * If chipset not found, do not continue. - */ - if (type == -1) - return (-1); - - /* select CR1 */ - outb(csr, 0x1); - - /* read the port's address: bits 0 and 1 of CR1 */ - r = inb(cio) & SMC_CR1_ADDR; - if (port_address[(int)r] != ppc->ppc_base) - return (-1); - - ppc->ppc_model = type; - - /* - * CR1 and CR4 registers bits 3 and 0/1 for mode configuration - * If SPP mode is detected, try to set ECP+EPP mode - */ - - if (bootverbose) { - outb(csr, 0x1); - printf("ppc%d: SMC registers CR1=0x%x", ppc->ppc_unit, - inb(cio) & 0xff); - - outb(csr, 0x4); - printf(" CR4=0x%x", inb(cio) & 0xff); - } - - /* select CR1 */ - outb(csr, 0x1); - - if (!chipset_mode) { - /* autodetect mode */ - - /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */ - if (type == SMC_37C666GT) { - ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP; - if (bootverbose) - printf(" configuration hardwired, supposing " \ - "ECP+EPP SPP"); - - } else - if ((inb(cio) & SMC_CR1_MODE) == 0) { - /* already in extended parallel port mode, read CR4 */ - outb(csr, 0x4); - r = (inb(cio) & SMC_CR4_EMODE); - - switch (r) { - case SMC_SPP: - ppc->ppc_avm |= PPB_SPP; - if (bootverbose) - printf(" SPP"); - break; - - case SMC_EPPSPP: - ppc->ppc_avm |= PPB_EPP | PPB_SPP; - if (bootverbose) - printf(" EPP SPP"); - break; - - case SMC_ECP: - ppc->ppc_avm |= PPB_ECP | PPB_SPP; - if (bootverbose) - printf(" ECP SPP"); - break; - - case SMC_ECPEPP: - ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP; - if (bootverbose) - printf(" ECP+EPP SPP"); - break; - } - } else { - /* not an extended port mode */ - ppc->ppc_avm |= PPB_SPP; - if (bootverbose) - printf(" SPP"); - } - - } else { - /* mode forced */ - ppc->ppc_avm = chipset_mode; - - /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */ - if (type == SMC_37C666GT) - goto end_detect; - - r = inb(cio); - if ((chipset_mode & (PPB_ECP | PPB_EPP)) == 0) { - /* do not use ECP when the mode is not forced to */ - outb(cio, r | SMC_CR1_MODE); - if (bootverbose) - printf(" SPP"); - } else { - /* an extended mode is selected */ - outb(cio, r & ~SMC_CR1_MODE); - - /* read CR4 register and reset mode field */ - outb(csr, 0x4); - r = inb(cio) & ~SMC_CR4_EMODE; - - if (chipset_mode & PPB_ECP) { - if (chipset_mode & PPB_EPP) { - outb(cio, r | SMC_ECPEPP); - if (bootverbose) - printf(" ECP+EPP"); - } else { - outb(cio, r | SMC_ECP); - if (bootverbose) - printf(" ECP"); - } - } else { - /* PPB_EPP is set */ - outb(cio, r | SMC_EPPSPP); - if (bootverbose) - printf(" EPP SPP"); - } - } - ppc->ppc_avm = chipset_mode; - } - - /* set FIFO threshold to 16 */ - if (ppc->ppc_avm & PPB_ECP) { - /* select CRA */ - outb(csr, 0xa); - outb(cio, 16); - } - -end_detect: - - if (bootverbose) - printf ("\n"); - - if (ppc->ppc_avm & PPB_EPP) { - /* select CR4 */ - outb(csr, 0x4); - r = inb(cio); - - /* - * Set the EPP protocol... - * Low=EPP 1.9 (1284 standard) and High=EPP 1.7 - */ - if (ppc->ppc_epp == EPP_1_9) - outb(cio, (r & ~SMC_CR4_EPPTYPE)); - else - outb(cio, (r | SMC_CR4_EPPTYPE)); - } - - /* end config mode */ - outb(csr, 0xaa); - - ppc->ppc_type = PPC_TYPE_SMCLIKE; - ppc_smclike_setmode(ppc, chipset_mode); - - return (chipset_mode); -} - -/* - * SMC FDC37C935 configuration - * Found on many Alpha machines - */ -static int -ppc_smc37c935_detect(struct ppc_data *ppc, int chipset_mode) -{ - int s; - int type = -1; - - s = splhigh(); - outb(SMC935_CFG, 0x55); /* enter config mode */ - outb(SMC935_CFG, 0x55); - splx(s); - - outb(SMC935_IND, SMC935_ID); /* check device id */ - if (inb(SMC935_DAT) == 0x2) - type = SMC_37C935; - - if (type == -1) { - outb(SMC935_CFG, 0xaa); /* exit config mode */ - return (-1); - } - - ppc->ppc_model = type; - - outb(SMC935_IND, SMC935_LOGDEV); /* select parallel port, */ - outb(SMC935_DAT, 3); /* which is logical device 3 */ - - /* set io port base */ - outb(SMC935_IND, SMC935_PORTHI); - outb(SMC935_DAT, (u_char)((ppc->ppc_base & 0xff00) >> 8)); - outb(SMC935_IND, SMC935_PORTLO); - outb(SMC935_DAT, (u_char)(ppc->ppc_base & 0xff)); - - if (!chipset_mode) - ppc->ppc_avm = PPB_COMPATIBLE; /* default mode */ - else { - ppc->ppc_avm = chipset_mode; - outb(SMC935_IND, SMC935_PPMODE); - outb(SMC935_DAT, SMC935_CENT); /* start in compatible mode */ - - /* SPP + EPP or just plain SPP */ - if (chipset_mode & (PPB_SPP)) { - if (chipset_mode & PPB_EPP) { - if (ppc->ppc_epp == EPP_1_9) { - outb(SMC935_IND, SMC935_PPMODE); - outb(SMC935_DAT, SMC935_EPP19SPP); - } - if (ppc->ppc_epp == EPP_1_7) { - outb(SMC935_IND, SMC935_PPMODE); - outb(SMC935_DAT, SMC935_EPP17SPP); - } - } else { - outb(SMC935_IND, SMC935_PPMODE); - outb(SMC935_DAT, SMC935_SPP); - } - } - - /* ECP + EPP or just plain ECP */ - if (chipset_mode & PPB_ECP) { - if (chipset_mode & PPB_EPP) { - if (ppc->ppc_epp == EPP_1_9) { - outb(SMC935_IND, SMC935_PPMODE); - outb(SMC935_DAT, SMC935_ECPEPP19); - } - if (ppc->ppc_epp == EPP_1_7) { - outb(SMC935_IND, SMC935_PPMODE); - outb(SMC935_DAT, SMC935_ECPEPP17); - } - } else { - outb(SMC935_IND, SMC935_PPMODE); - outb(SMC935_DAT, SMC935_ECP); - } - } - } - - outb(SMC935_CFG, 0xaa); /* exit config mode */ - - ppc->ppc_type = PPC_TYPE_SMCLIKE; - ppc_smclike_setmode(ppc, chipset_mode); - - return (chipset_mode); -} - -/* - * Winbond W83877F stuff - * - * EFER: extended function enable register - * EFIR: extended function index register - * EFDR: extended function data register - */ -#define efir ((efer == 0x250) ? 0x251 : 0x3f0) -#define efdr ((efer == 0x250) ? 0x252 : 0x3f1) - -static int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 }; -static int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 }; -static int w83877f_keyiter[] = { 1, 2, 2, 1 }; -static int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 }; - -static int -ppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode) -{ - int i, j, efer; - unsigned char r, hefere, hefras; - - for (i = 0; i < 4; i ++) { - /* first try to enable configuration registers */ - efer = w83877f_efers[i]; - - /* write the key to the EFER */ - for (j = 0; j < w83877f_keyiter[i]; j ++) - outb (efer, w83877f_keys[i]); - - /* then check HEFERE and HEFRAS bits */ - outb (efir, 0x0c); - hefere = inb(efdr) & WINB_HEFERE; - - outb (efir, 0x16); - hefras = inb(efdr) & WINB_HEFRAS; - - /* - * HEFRAS HEFERE - * 0 1 write 89h to 250h (power-on default) - * 1 0 write 86h twice to 3f0h - * 1 1 write 87h twice to 3f0h - * 0 0 write 88h to 250h - */ - if ((hefere | hefras) == w83877f_hefs[i]) - goto found; - } - - return (-1); /* failed */ - -found: - /* check base port address - read from CR23 */ - outb(efir, 0x23); - if (ppc->ppc_base != inb(efdr) * 4) /* 4 bytes boundaries */ - return (-1); - - /* read CHIP ID from CR9/bits0-3 */ - outb(efir, 0x9); - - switch (inb(efdr) & WINB_CHIPID) { - case WINB_W83877F_ID: - ppc->ppc_model = WINB_W83877F; - break; - - case WINB_W83877AF_ID: - ppc->ppc_model = WINB_W83877AF; - break; - - default: - ppc->ppc_model = WINB_UNKNOWN; - } - - if (bootverbose) { - /* dump of registers */ - printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]); - for (i = 0; i <= 0xd; i ++) { - outb(efir, i); - printf("0x%x ", inb(efdr)); - } - for (i = 0x10; i <= 0x17; i ++) { - outb(efir, i); - printf("0x%x ", inb(efdr)); - } - outb(efir, 0x1e); - printf("0x%x ", inb(efdr)); - for (i = 0x20; i <= 0x29; i ++) { - outb(efir, i); - printf("0x%x ", inb(efdr)); - } - printf("\n"); - printf("ppc%d:", ppc->ppc_unit); - } - - ppc->ppc_type = PPC_TYPE_GENERIC; - - if (!chipset_mode) { - /* autodetect mode */ - - /* select CR0 */ - outb(efir, 0x0); - r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1); - - /* select CR9 */ - outb(efir, 0x9); - r |= (inb(efdr) & WINB_PRTMODS2); - - switch (r) { - case WINB_W83757: - if (bootverbose) - printf("ppc%d: W83757 compatible mode\n", - ppc->ppc_unit); - return (-1); /* generic or SMC-like */ - - case WINB_EXTFDC: - case WINB_EXTADP: - case WINB_EXT2FDD: - case WINB_JOYSTICK: - if (bootverbose) - printf(" not in parallel port mode\n"); - return (-1); - - case (WINB_PARALLEL | WINB_EPP_SPP): - ppc->ppc_avm |= PPB_EPP | PPB_SPP; - if (bootverbose) - printf(" EPP SPP"); - break; - - case (WINB_PARALLEL | WINB_ECP): - ppc->ppc_avm |= PPB_ECP | PPB_SPP; - if (bootverbose) - printf(" ECP SPP"); - break; - - case (WINB_PARALLEL | WINB_ECP_EPP): - ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP; - ppc->ppc_type = PPC_TYPE_SMCLIKE; - - if (bootverbose) - printf(" ECP+EPP SPP"); - break; - default: - printf("%s: unknown case (0x%x)!\n", __func__, r); - } - - } else { - /* mode forced */ - - /* select CR9 and set PRTMODS2 bit */ - outb(efir, 0x9); - outb(efdr, inb(efdr) & ~WINB_PRTMODS2); - - /* select CR0 and reset PRTMODSx bits */ - outb(efir, 0x0); - outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1)); - - if (chipset_mode & PPB_ECP) { - if (chipset_mode & PPB_EPP) { - outb(efdr, inb(efdr) | WINB_ECP_EPP); - if (bootverbose) - printf(" ECP+EPP"); - - ppc->ppc_type = PPC_TYPE_SMCLIKE; - - } else { - outb(efdr, inb(efdr) | WINB_ECP); - if (bootverbose) - printf(" ECP"); - } - } else { - /* select EPP_SPP otherwise */ - outb(efdr, inb(efdr) | WINB_EPP_SPP); - if (bootverbose) - printf(" EPP SPP"); - } - ppc->ppc_avm = chipset_mode; - } - - if (bootverbose) - printf("\n"); - - /* exit configuration mode */ - outb(efer, 0xaa); - - switch (ppc->ppc_type) { - case PPC_TYPE_SMCLIKE: - ppc_smclike_setmode(ppc, chipset_mode); - break; - default: - ppc_generic_setmode(ppc, chipset_mode); - break; - } - - return (chipset_mode); -} -#endif - -/* - * ppc_generic_detect - */ -static int -ppc_generic_detect(struct ppc_data *ppc, int chipset_mode) -{ - /* default to generic */ - ppc->ppc_type = PPC_TYPE_GENERIC; - - if (bootverbose) - printf("ppc%d:", ppc->ppc_unit); - - /* first, check for ECP */ - w_ecr(ppc, PPC_ECR_PS2); - if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) { - ppc->ppc_dtm |= PPB_ECP | PPB_SPP; - if (bootverbose) - printf(" ECP SPP"); - - /* search for SMC style ECP+EPP mode */ - w_ecr(ppc, PPC_ECR_EPP); - } - - /* try to reset EPP timeout bit */ - if (ppc_check_epp_timeout(ppc)) { - ppc->ppc_dtm |= PPB_EPP; - - if (ppc->ppc_dtm & PPB_ECP) { - /* SMC like chipset found */ - ppc->ppc_model = SMC_LIKE; - ppc->ppc_type = PPC_TYPE_SMCLIKE; - - if (bootverbose) - printf(" ECP+EPP"); - } else { - if (bootverbose) - printf(" EPP"); - } - } else { - /* restore to standard mode */ - w_ecr(ppc, PPC_ECR_STD); - } - - /* XXX try to detect NIBBLE and PS2 modes */ - ppc->ppc_dtm |= PPB_NIBBLE; - - if (bootverbose) - printf(" SPP"); - - if (chipset_mode) - ppc->ppc_avm = chipset_mode; - else - ppc->ppc_avm = ppc->ppc_dtm; - - if (bootverbose) - printf("\n"); - - switch (ppc->ppc_type) { - case PPC_TYPE_SMCLIKE: - ppc_smclike_setmode(ppc, chipset_mode); - break; - default: - ppc_generic_setmode(ppc, chipset_mode); - break; - } - - return (chipset_mode); -} - -/* - * ppc_detect() - * - * mode is the mode suggested at boot - */ -static int -ppc_detect(struct ppc_data *ppc, int chipset_mode) { - -#ifdef PPC_PROBE_CHIPSET - int i, mode; - - /* list of supported chipsets */ - int (*chipset_detect[])(struct ppc_data *, int) = { - ppc_pc873xx_detect, - ppc_smc37c66xgt_detect, - ppc_w83877f_detect, - ppc_smc37c935_detect, - ppc_generic_detect, - NULL - }; -#endif - - /* if can't find the port and mode not forced return error */ - if (!ppc_detect_port(ppc) && chipset_mode == 0) - return (EIO); /* failed, port not present */ - - /* assume centronics compatible mode is supported */ - ppc->ppc_avm = PPB_COMPATIBLE; - -#ifdef PPC_PROBE_CHIPSET - /* we have to differenciate available chipset modes, - * chipset running modes and IEEE-1284 operating modes - * - * after detection, the port must support running in compatible mode - */ - if (ppc->ppc_flags & 0x40) { - if (bootverbose) - printf("ppc: chipset forced to generic\n"); -#endif - - ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode); - -#ifdef PPC_PROBE_CHIPSET - } else { - for (i=0; chipset_detect[i] != NULL; i++) { - if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) { - ppc->ppc_mode = mode; - break; - } - } - } -#endif - - /* configure/detect ECP FIFO */ - if ((ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_flags & 0x80)) - ppc_detect_fifo(ppc); - - return (0); -} - -/* - * ppc_exec_microseq() - * - * Execute a microsequence. - * Microsequence mechanism is supposed to handle fast I/O operations. - */ -int -ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq) -{ - struct ppc_data *ppc = DEVTOSOFTC(dev); - struct ppb_microseq *mi; - char cc, *p; - int i, iter, len; - int error; - - register int reg; - register char mask; - register int accum = 0; - register char *ptr = 0; - - struct ppb_microseq *stack = 0; - -/* microsequence registers are equivalent to PC-like port registers */ - -#define r_reg(register,ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, register)) -#define w_reg(register, ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, register, byte)) - -#define INCR_PC (mi ++) /* increment program counter */ - - mi = *p_msq; - for (;;) { - switch (mi->opcode) { - case MS_OP_RSET: - cc = r_reg(mi->arg[0].i, ppc); - cc &= (char)mi->arg[2].i; /* clear mask */ - cc |= (char)mi->arg[1].i; /* assert mask */ - w_reg(mi->arg[0].i, ppc, cc); - INCR_PC; - break; - - case MS_OP_RASSERT_P: - reg = mi->arg[1].i; - ptr = ppc->ppc_ptr; - - if ((len = mi->arg[0].i) == MS_ACCUM) { - accum = ppc->ppc_accum; - for (; accum; accum--) - w_reg(reg, ppc, *ptr++); - ppc->ppc_accum = accum; - } else - for (i=0; i<len; i++) - w_reg(reg, ppc, *ptr++); - ppc->ppc_ptr = ptr; - - INCR_PC; - break; - - case MS_OP_RFETCH_P: - reg = mi->arg[1].i; - mask = (char)mi->arg[2].i; - ptr = ppc->ppc_ptr; - - if ((len = mi->arg[0].i) == MS_ACCUM) { - accum = ppc->ppc_accum; - for (; accum; accum--) - *ptr++ = r_reg(reg, ppc) & mask; - ppc->ppc_accum = accum; - } else - for (i=0; i<len; i++) - *ptr++ = r_reg(reg, ppc) & mask; - ppc->ppc_ptr = ptr; - - INCR_PC; - break; - - case MS_OP_RFETCH: - *((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) & - (char)mi->arg[1].i; - INCR_PC; - break; - - case MS_OP_RASSERT: - case MS_OP_DELAY: - - /* let's suppose the next instr. is the same */ - prefetch: - for (;mi->opcode == MS_OP_RASSERT; INCR_PC) - w_reg(mi->arg[0].i, ppc, (char)mi->arg[1].i); - - if (mi->opcode == MS_OP_DELAY) { - DELAY(mi->arg[0].i); - INCR_PC; - goto prefetch; - } - break; - - case MS_OP_ADELAY: - if (mi->arg[0].i) - tsleep(NULL, PPBPRI, "ppbdelay", - mi->arg[0].i * (hz/1000)); - INCR_PC; - break; - - case MS_OP_TRIG: - reg = mi->arg[0].i; - iter = mi->arg[1].i; - p = (char *)mi->arg[2].p; - - /* XXX delay limited to 255 us */ - for (i=0; i<iter; i++) { - w_reg(reg, ppc, *p++); - DELAY((unsigned char)*p++); - } - INCR_PC; - break; - - case MS_OP_SET: - ppc->ppc_accum = mi->arg[0].i; - INCR_PC; - break; - - case MS_OP_DBRA: - if (--ppc->ppc_accum > 0) - mi += mi->arg[0].i; - INCR_PC; - break; - - case MS_OP_BRSET: - cc = r_str(ppc); - if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i) - mi += mi->arg[1].i; - INCR_PC; - break; - - case MS_OP_BRCLEAR: - cc = r_str(ppc); - if ((cc & (char)mi->arg[0].i) == 0) - mi += mi->arg[1].i; - INCR_PC; - break; - - case MS_OP_BRSTAT: - cc = r_str(ppc); - if ((cc & ((char)mi->arg[0].i | (char)mi->arg[1].i)) == - (char)mi->arg[0].i) - mi += mi->arg[2].i; - INCR_PC; - break; - - case MS_OP_C_CALL: - /* - * If the C call returns !0 then end the microseq. - * The current state of ptr is passed to the C function - */ - if ((error = mi->arg[0].f(mi->arg[1].p, ppc->ppc_ptr))) - return (error); - - INCR_PC; - break; - - case MS_OP_PTR: - ppc->ppc_ptr = (char *)mi->arg[0].p; - INCR_PC; - break; - - case MS_OP_CALL: - if (stack) - panic("%s: too much calls", __func__); - - if (mi->arg[0].p) { - /* store the state of the actual - * microsequence - */ - stack = mi; - - /* jump to the new microsequence */ - mi = (struct ppb_microseq *)mi->arg[0].p; - } else - INCR_PC; - - break; - - case MS_OP_SUBRET: - /* retrieve microseq and pc state before the call */ - mi = stack; - - /* reset the stack */ - stack = 0; - - /* XXX return code */ - - INCR_PC; - break; - - case MS_OP_PUT: - case MS_OP_GET: - case MS_OP_RET: - /* can't return to ppb level during the execution - * of a submicrosequence */ - if (stack) - panic("%s: can't return to ppb level", - __func__); - - /* update pc for ppb level of execution */ - *p_msq = mi; - - /* return to ppb level of execution */ - return (0); - - default: - panic("%s: unknown microsequence opcode 0x%x", - __func__, mi->opcode); - } - } - - /* unreached */ -} - -static void -ppcintr(void *arg) -{ - device_t dev = (device_t)arg; - struct ppc_data *ppc = (struct ppc_data *)device_get_softc(dev); - u_char ctr, ecr, str; - - str = r_str(ppc); - ctr = r_ctr(ppc); - ecr = r_ecr(ppc); - -#if PPC_DEBUG > 1 - printf("![%x/%x/%x]", ctr, ecr, str); -#endif - - /* don't use ecp mode with IRQENABLE set */ - if (ctr & IRQENABLE) { - return; - } - - /* interrupts are generated by nFault signal - * only in ECP mode */ - if ((str & nFAULT) && (ppc->ppc_mode & PPB_ECP)) { - /* check if ppc driver has programmed the - * nFault interrupt */ - if (ppc->ppc_irqstat & PPC_IRQ_nFAULT) { - - w_ecr(ppc, ecr | PPC_nFAULT_INTR); - ppc->ppc_irqstat &= ~PPC_IRQ_nFAULT; - } else { - /* shall be handled by underlying layers XXX */ - return; - } - } - - if (ppc->ppc_irqstat & PPC_IRQ_DMA) { - /* disable interrupts (should be done by hardware though) */ - w_ecr(ppc, ecr | PPC_SERVICE_INTR); - ppc->ppc_irqstat &= ~PPC_IRQ_DMA; - ecr = r_ecr(ppc); - - /* check if DMA completed */ - if ((ppc->ppc_avm & PPB_ECP) && (ecr & PPC_ENABLE_DMA)) { -#ifdef PPC_DEBUG - printf("a"); -#endif - /* stop DMA */ - w_ecr(ppc, ecr & ~PPC_ENABLE_DMA); - ecr = r_ecr(ppc); - - if (ppc->ppc_dmastat == PPC_DMA_STARTED) { -#ifdef PPC_DEBUG - printf("d"); -#endif - isa_dmadone( - ppc->ppc_dmaflags, - ppc->ppc_dmaddr, - ppc->ppc_dmacnt, - ppc->ppc_dmachan); - - ppc->ppc_dmastat = PPC_DMA_COMPLETE; - - /* wakeup the waiting process */ - wakeup(ppc); - } - } - } else if (ppc->ppc_irqstat & PPC_IRQ_FIFO) { - - /* classic interrupt I/O */ - ppc->ppc_irqstat &= ~PPC_IRQ_FIFO; - } - - return; -} - -int -ppc_read(device_t dev, char *buf, int len, int mode) -{ - return (EINVAL); -} - -/* - * Call this function if you want to send data in any advanced mode - * of your parallel port: FIFO, DMA - * - * If what you want is not possible (no ECP, no DMA...), - * EINVAL is returned - */ -int -ppc_write(device_t dev, char *buf, int len, int how) -{ - struct ppc_data *ppc = DEVTOSOFTC(dev); - char ecr, ecr_sav, ctr, ctr_sav; - int s, error = 0; - int spin; - -#ifdef PPC_DEBUG - printf("w"); -#endif - - ecr_sav = r_ecr(ppc); - ctr_sav = r_ctr(ppc); - - /* - * Send buffer with DMA, FIFO and interrupts - */ - if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) { - - if (ppc->ppc_dmachan > 0) { - - /* byte mode, no intr, no DMA, dir=0, flush fifo - */ - ecr = PPC_ECR_STD | PPC_DISABLE_INTR; - w_ecr(ppc, ecr); - - /* disable nAck interrupts */ - ctr = r_ctr(ppc); - ctr &= ~IRQENABLE; - w_ctr(ppc, ctr); - - ppc->ppc_dmaflags = 0; - ppc->ppc_dmaddr = (caddr_t)buf; - ppc->ppc_dmacnt = (u_int)len; - - switch (ppc->ppc_mode) { - case PPB_COMPATIBLE: - /* compatible mode with FIFO, no intr, DMA, dir=0 */ - ecr = PPC_ECR_FIFO | PPC_DISABLE_INTR | PPC_ENABLE_DMA; - break; - case PPB_ECP: - ecr = PPC_ECR_ECP | PPC_DISABLE_INTR | PPC_ENABLE_DMA; - break; - default: - error = EINVAL; - goto error; - } - - w_ecr(ppc, ecr); - ecr = r_ecr(ppc); - - /* enter splhigh() not to be preempted - * by the dma interrupt, we may miss - * the wakeup otherwise - */ - s = splhigh(); - - ppc->ppc_dmastat = PPC_DMA_INIT; - - /* enable interrupts */ - ecr &= ~PPC_SERVICE_INTR; - ppc->ppc_irqstat = PPC_IRQ_DMA; - w_ecr(ppc, ecr); - - isa_dmastart( - ppc->ppc_dmaflags, - ppc->ppc_dmaddr, - ppc->ppc_dmacnt, - ppc->ppc_dmachan); -#ifdef PPC_DEBUG - printf("s%d", ppc->ppc_dmacnt); -#endif - ppc->ppc_dmastat = PPC_DMA_STARTED; - - /* Wait for the DMA completed interrupt. We hope we won't - * miss it, otherwise a signal will be necessary to unlock the - * process. - */ - do { - /* release CPU */ - error = tsleep(ppc, - PPBPRI | PCATCH, "ppcdma", 0); - - } while (error == EWOULDBLOCK); - - splx(s); - - if (error) { -#ifdef PPC_DEBUG - printf("i"); -#endif - /* stop DMA */ - isa_dmadone( - ppc->ppc_dmaflags, ppc->ppc_dmaddr, - ppc->ppc_dmacnt, ppc->ppc_dmachan); - - /* no dma, no interrupt, flush the fifo */ - w_ecr(ppc, PPC_ECR_RESET); - - ppc->ppc_dmastat = PPC_DMA_INTERRUPTED; - goto error; - } - - /* wait for an empty fifo */ - while (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) { - - for (spin=100; spin; spin--) - if (r_ecr(ppc) & PPC_FIFO_EMPTY) - goto fifo_empty; -#ifdef PPC_DEBUG - printf("Z"); -#endif - error = tsleep(ppc, PPBPRI | PCATCH, "ppcfifo", hz/100); - if (error != EWOULDBLOCK) { -#ifdef PPC_DEBUG - printf("I"); -#endif - /* no dma, no interrupt, flush the fifo */ - w_ecr(ppc, PPC_ECR_RESET); - - ppc->ppc_dmastat = PPC_DMA_INTERRUPTED; - error = EINTR; - goto error; - } - } - -fifo_empty: - /* no dma, no interrupt, flush the fifo */ - w_ecr(ppc, PPC_ECR_RESET); - - } else - error = EINVAL; /* XXX we should FIFO and - * interrupts */ - } else - error = EINVAL; - -error: - - /* PDRQ must be kept unasserted until nPDACK is - * deasserted for a minimum of 350ns (SMC datasheet) - * - * Consequence may be a FIFO that never empty - */ - DELAY(1); - - w_ecr(ppc, ecr_sav); - w_ctr(ppc, ctr_sav); - - return (error); -} - -void -ppc_reset_epp(device_t dev) -{ - struct ppc_data *ppc = DEVTOSOFTC(dev); - - ppc_reset_epp_timeout(ppc); - - return; -} - -int -ppc_setmode(device_t dev, int mode) -{ - struct ppc_data *ppc = DEVTOSOFTC(dev); - - switch (ppc->ppc_type) { - case PPC_TYPE_SMCLIKE: - return (ppc_smclike_setmode(ppc, mode)); - break; - - case PPC_TYPE_GENERIC: - default: - return (ppc_generic_setmode(ppc, mode)); - break; - } - - /* not reached */ - return (ENXIO); -} - -static struct isa_pnp_id lpc_ids[] = { - { 0x0004d041, "Standard parallel printer port" }, /* PNP0400 */ - { 0x0104d041, "ECP parallel printer port" }, /* PNP0401 */ - { 0 } -}; - -static int -ppc_cbus_probe(device_t dev) -{ - device_t parent; - int error; - - parent = device_get_parent(dev); - - error = ISA_PNP_PROBE(parent, dev, lpc_ids); - if (error == ENXIO) - return (ENXIO); - else if (error != 0) /* XXX shall be set after detection */ - device_set_desc(dev, "Parallel port"); - - return(ppc_probe(dev)); -} - -int -ppc_probe(device_t dev) -{ -#ifdef __i386__ - static short next_bios_ppc = 0; -#endif - struct ppc_data *ppc; - int error; - u_long port; -#ifdef PC98 -#define PC98_IEEE_1284_DISABLE 0x100 -#define PC98_IEEE_1284_PORT 0x140 - - unsigned int pc98_ieee_mode = 0x00; - unsigned int tmp; -#endif - - /* - * Allocate the ppc_data structure. - */ - ppc = DEVTOSOFTC(dev); - bzero(ppc, sizeof(struct ppc_data)); - - ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0; - ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0; - - /* retrieve ISA parameters */ - error = bus_get_resource(dev, SYS_RES_IOPORT, 0, &port, NULL); - -#ifdef __i386__ - /* - * If port not specified, use bios list. - */ - if (error) { -#ifndef PC98 - if((next_bios_ppc < BIOS_MAX_PPC) && - (*(BIOS_PORTS+next_bios_ppc) != 0) ) { - port = *(BIOS_PORTS+next_bios_ppc++); - if (bootverbose) - device_printf(dev, "parallel port found at 0x%x\n", - (int) port); - } else { - device_printf(dev, "parallel port not found.\n"); - return ENXIO; - } -#else - if (next_bios_ppc == 0) { - /* Use default IEEE-1284 port of NEC PC-98x1 */ - port = PC98_IEEE_1284_PORT; - next_bios_ppc += 1; - if (bootverbose) - device_printf(dev, - "parallel port found at 0x%x\n", - (int) port); - } -#endif - bus_set_resource(dev, SYS_RES_IOPORT, 0, port, - IO_LPTSIZE_EXTENDED); - } -#endif -#ifdef __alpha__ - /* - * There isn't a bios list on alpha. Put it in the usual place. - */ - if (error) { - bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc, - IO_LPTSIZE_NORMAL); - } -#endif - - /* IO port is mandatory */ - - /* Try "extended" IO port range...*/ - ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, - &ppc->rid_ioport, 0, ~0, - IO_LPTSIZE_EXTENDED, RF_ACTIVE); - - if (ppc->res_ioport != 0) { - if (bootverbose) - device_printf(dev, "using extended I/O port range\n"); - } else { - /* Failed? If so, then try the "normal" IO port range... */ - ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, - &ppc->rid_ioport, 0, ~0, - IO_LPTSIZE_NORMAL, - RF_ACTIVE); - if (ppc->res_ioport != 0) { - if (bootverbose) - device_printf(dev, "using normal I/O port range\n"); - } else { - device_printf(dev, "cannot reserve I/O port range\n"); - goto error; - } - } - - ppc->ppc_base = rman_get_start(ppc->res_ioport); - - ppc->bsh = rman_get_bushandle(ppc->res_ioport); - ppc->bst = rman_get_bustag(ppc->res_ioport); - - ppc->ppc_flags = device_get_flags(dev); - - if (!(ppc->ppc_flags & 0x20)) { - ppc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &ppc->rid_irq, - RF_SHAREABLE); - ppc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &ppc->rid_drq, - RF_ACTIVE); - } - - if (ppc->res_irq) - ppc->ppc_irq = rman_get_start(ppc->res_irq); - if (ppc->res_drq) - ppc->ppc_dmachan = rman_get_start(ppc->res_drq); - - ppc->ppc_unit = device_get_unit(dev); - ppc->ppc_model = GENERIC; - - ppc->ppc_mode = PPB_COMPATIBLE; - ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4; - - ppc->ppc_type = PPC_TYPE_GENERIC; - -#ifdef PC98 - /* - * IEEE STD 1284 Function Check and Enable - * for default IEEE-1284 port of NEC PC-98x1 - */ - if ((ppc->ppc_base == PC98_IEEE_1284_PORT) && - !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) { - tmp = inb(ppc->ppc_base + PPC_1284_ENABLE); - pc98_ieee_mode = tmp; - if ((tmp & 0x10) == 0x10) { - outb(ppc->ppc_base + PPC_1284_ENABLE, tmp & ~0x10); - tmp = inb(ppc->ppc_base + PPC_1284_ENABLE); - if ((tmp & 0x10) == 0x10) - goto error; - } else { - outb(ppc->ppc_base + PPC_1284_ENABLE, tmp | 0x10); - tmp = inb(ppc->ppc_base + PPC_1284_ENABLE); - if ((tmp & 0x10) != 0x10) - goto error; - } - outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode | 0x10); - } -#endif - - /* - * Try to detect the chipset and its mode. - */ - if (ppc_detect(ppc, ppc->ppc_flags & 0xf)) - goto error; - - return (0); - -error: -#ifdef PC98 - if ((ppc->ppc_base == PC98_IEEE_1284_PORT) && - !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) { - outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode); - } -#endif - if (ppc->res_irq != 0) { - bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq, - ppc->res_irq); - } - if (ppc->res_ioport != 0) { - bus_deactivate_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport, - ppc->res_ioport); - bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport, - ppc->res_ioport); - } - if (ppc->res_drq != 0) { - bus_deactivate_resource(dev, SYS_RES_DRQ, ppc->rid_drq, - ppc->res_drq); - bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq, - ppc->res_drq); - } - return (ENXIO); -} - -int -ppc_attach(device_t dev) -{ - struct ppc_data *ppc = DEVTOSOFTC(dev); - - device_t ppbus; - device_t parent = device_get_parent(dev); - - device_printf(dev, "%s chipset (%s) in %s mode%s\n", - ppc_models[ppc->ppc_model], ppc_avms[ppc->ppc_avm], - ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ? - ppc_epp_protocol[ppc->ppc_epp] : ""); - - if (ppc->ppc_fifo) - device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n", - ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr); - - if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) { - /* acquire the DMA channel forever */ /* XXX */ - isa_dma_acquire(ppc->ppc_dmachan); - isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */ - } - - /* add ppbus as a child of this isa to parallel bridge */ - ppbus = device_add_child(dev, "ppbus", -1); - - /* - * Probe the ppbus and attach devices found. - */ - device_probe_and_attach(ppbus); - - /* register the ppc interrupt handler as default */ - if (ppc->res_irq) { - /* default to the tty mask for registration */ /* XXX */ - if (BUS_SETUP_INTR(parent, dev, ppc->res_irq, INTR_TYPE_TTY, - ppcintr, dev, &ppc->intr_cookie) == 0) { - - /* remember the ppcintr is registered */ - ppc->ppc_registered = 1; - } - } - - return (0); -} - -u_char -ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte) -{ - struct ppc_data *ppc = DEVTOSOFTC(ppcdev); - switch (iop) { - case PPB_OUTSB_EPP: - bus_space_write_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt); - break; - case PPB_OUTSW_EPP: - bus_space_write_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt); - break; - case PPB_OUTSL_EPP: - bus_space_write_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt); - break; - case PPB_INSB_EPP: - bus_space_read_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt); - break; - case PPB_INSW_EPP: - bus_space_read_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt); - break; - case PPB_INSL_EPP: - bus_space_read_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt); - break; - case PPB_RDTR: - return (r_dtr(ppc)); - case PPB_RSTR: - return (r_str(ppc)); - case PPB_RCTR: - return (r_ctr(ppc)); - case PPB_REPP_A: - return (r_epp_A(ppc)); - case PPB_REPP_D: - return (r_epp_D(ppc)); - case PPB_RECR: - return (r_ecr(ppc)); - case PPB_RFIFO: - return (r_fifo(ppc)); - case PPB_WDTR: - w_dtr(ppc, byte); - break; - case PPB_WSTR: - w_str(ppc, byte); - break; - case PPB_WCTR: - w_ctr(ppc, byte); - break; - case PPB_WEPP_A: - w_epp_A(ppc, byte); - break; - case PPB_WEPP_D: - w_epp_D(ppc, byte); - break; - case PPB_WECR: - w_ecr(ppc, byte); - break; - case PPB_WFIFO: - w_fifo(ppc, byte); - break; - default: - panic("%s: unknown I/O operation", __func__); - break; - } - - return (0); /* not significative */ -} - -int -ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val) -{ - struct ppc_data *ppc = (struct ppc_data *)device_get_softc(bus); - - switch (index) { - case PPC_IVAR_EPP_PROTO: - *val = (u_long)ppc->ppc_epp; - break; - case PPC_IVAR_IRQ: - *val = (u_long)ppc->ppc_irq; - break; - default: - return (ENOENT); - } - - return (0); -} - -/* - * Resource is useless here since ppbus devices' interrupt handlers are - * multiplexed to the same resource initially allocated by ppc - */ -int -ppc_setup_intr(device_t bus, device_t child, struct resource *r, int flags, - void (*ihand)(void *), void *arg, void **cookiep) -{ - int error; - struct ppc_data *ppc = DEVTOSOFTC(bus); - - if (ppc->ppc_registered) { - /* XXX refuse registration if DMA is in progress */ - - /* first, unregister the default interrupt handler */ - if ((error = BUS_TEARDOWN_INTR(device_get_parent(bus), - bus, ppc->res_irq, ppc->intr_cookie))) - return (error); - -/* bus_deactivate_resource(bus, SYS_RES_IRQ, ppc->rid_irq, */ -/* ppc->res_irq); */ - - /* DMA/FIFO operation won't be possible anymore */ - ppc->ppc_registered = 0; - } - - /* pass registration to the upper layer, ignore the incoming resource */ - return (BUS_SETUP_INTR(device_get_parent(bus), child, - r, flags, ihand, arg, cookiep)); -} - -/* - * When no underlying device has a registered interrupt, register the ppc - * layer one - */ -int -ppc_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih) -{ - int error; - struct ppc_data *ppc = DEVTOSOFTC(bus); - device_t parent = device_get_parent(bus); - - /* pass unregistration to the upper layer */ - if ((error = BUS_TEARDOWN_INTR(parent, child, r, ih))) - return (error); - - /* default to the tty mask for registration */ /* XXX */ - if (ppc->ppc_irq && - !(error = BUS_SETUP_INTR(parent, bus, ppc->res_irq, - INTR_TYPE_TTY, ppcintr, bus, &ppc->intr_cookie))) { - - /* remember the ppcintr is registered */ - ppc->ppc_registered = 1; - } - - return (error); -} - -DRIVER_MODULE(ppc, isa, ppc_driver, ppc_devclass, 0, 0); -#ifndef PC98 -DRIVER_MODULE(ppc, acpi, ppc_driver, ppc_devclass, 0, 0); -#endif diff --git a/sys/pc98/pc98/ppcreg.h b/sys/pc98/pc98/ppcreg.h deleted file mode 100644 index 2aa5ce4..0000000 --- a/sys/pc98/pc98/ppcreg.h +++ /dev/null @@ -1,280 +0,0 @@ -/*- - * Copyright (c) 2001 Alcove - Nicolas Souchu - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - * - */ -#ifndef __PPCREG_H -#define __PPCREG_H - -/* - * Parallel Port Chipset type. - */ -#define SMC_LIKE 0 -#define SMC_37C665GT 1 -#define SMC_37C666GT 2 -#define NS_PC87332 3 -#define NS_PC87306 4 -#define INTEL_820191AA 5 /* XXX not implemented */ -#define GENERIC 6 -#define WINB_W83877F 7 -#define WINB_W83877AF 8 -#define WINB_UNKNOWN 9 -#define NS_PC87334 10 -#define SMC_37C935 11 -#define NS_PC87303 12 - -/* - * Parallel Port Chipset Type. SMC versus GENERIC (others) - */ -#define PPC_TYPE_SMCLIKE 0 -#define PPC_TYPE_GENERIC 1 - -/* - * Generic structure to hold parallel port chipset info. - */ -struct ppc_data { - - int ppc_unit; - int ppc_model; /* chipset model if detected */ - int ppc_type; /* generic or smclike chipset type */ - - int ppc_mode; /* chipset current mode */ - int ppc_avm; /* chipset available modes */ - int ppc_dtm; /* chipset detected modes */ - -#define PPC_IRQ_NONE 0x0 -#define PPC_IRQ_nACK 0x1 -#define PPC_IRQ_DMA 0x2 -#define PPC_IRQ_FIFO 0x4 -#define PPC_IRQ_nFAULT 0x8 - int ppc_irqstat; /* remind irq settings */ - -#define PPC_DMA_INIT 0x01 -#define PPC_DMA_STARTED 0x02 -#define PPC_DMA_COMPLETE 0x03 -#define PPC_DMA_INTERRUPTED 0x04 -#define PPC_DMA_ERROR 0x05 - int ppc_dmastat; /* dma state */ - int ppc_dmachan; /* dma channel */ - int ppc_dmaflags; /* dma transfer flags */ - caddr_t ppc_dmaddr; /* buffer address */ - u_int ppc_dmacnt; /* count of bytes sent with dma */ - -#define PPC_PWORD_MASK 0x30 -#define PPC_PWORD_16 0x00 -#define PPC_PWORD_8 0x10 -#define PPC_PWORD_32 0x20 - char ppc_pword; /* PWord size */ - short ppc_fifo; /* FIFO threshold */ - - short ppc_wthr; /* writeIntrThresold */ - short ppc_rthr; /* readIntrThresold */ - - char *ppc_ptr; /* microseq current pointer */ - int ppc_accum; /* microseq accumulator */ - int ppc_base; /* parallel port base address */ - int ppc_epp; /* EPP mode (1.7 or 1.9) */ - int ppc_irq; - - unsigned char ppc_flags; - - device_t ppbus; /* parallel port chipset corresponding ppbus */ - - int rid_irq, rid_drq, rid_ioport; - struct resource *res_irq, *res_drq, *res_ioport; - - bus_space_handle_t bsh; - bus_space_tag_t bst; - - void *intr_cookie; - - int ppc_registered; /* 1 if ppcintr() is the registered interrupt */ -}; - -/* - * Parallel Port Chipset registers. - */ -#define PPC_SPP_DTR 0 /* SPP data register */ -#define PPC_ECP_A_FIFO 0 /* ECP Address fifo register */ -#define PPC_SPP_STR 1 /* SPP status register */ -#define PPC_SPP_CTR 2 /* SPP control register */ -#define PPC_EPP_ADDR 3 /* EPP address register (8 bit) */ -#define PPC_EPP_DATA 4 /* EPP data register (8, 16 or 32 bit) */ -#ifdef PC98 -#define PPC_1284_ENABLE 0x09 /* IEEE STD 1284 Enable register */ -#define PPC_ECP_D_FIFO 0x0c /* ECP Data fifo register */ -#define PPC_ECP_CNFGA 0x0c /* Configuration register A */ -#define PPC_ECP_CNFGB 0x0d /* Configuration register B */ -#define PPC_ECP_ECR 0x0e /* ECP extended control register */ -#else -#define PPC_ECP_D_FIFO 0x400 /* ECP Data fifo register */ -#define PPC_ECP_CNFGA 0x400 /* Configuration register A */ -#define PPC_ECP_CNFGB 0x401 /* Configuration register B */ -#define PPC_ECP_ECR 0x402 /* ECP extended control register */ -#endif - -#define PPC_FIFO_EMPTY 0x1 /* ecr register - bit 0 */ -#define PPC_FIFO_FULL 0x2 /* ecr register - bit 1 */ -#define PPC_SERVICE_INTR 0x4 /* ecr register - bit 2 */ -#define PPC_ENABLE_DMA 0x8 /* ecr register - bit 3 */ -#define PPC_nFAULT_INTR 0x10 /* ecr register - bit 4 */ -#define PPC_ECR_STD 0x0 -#define PPC_ECR_PS2 0x20 -#define PPC_ECR_FIFO 0x40 -#define PPC_ECR_ECP 0x60 -#define PPC_ECR_EPP 0x80 - -#define PPC_DISABLE_INTR (PPC_SERVICE_INTR | PPC_nFAULT_INTR) -#define PPC_ECR_RESET (PPC_ECR_PS2 | PPC_DISABLE_INTR) - -#define r_dtr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR)) -#define r_str(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR)) -#define r_ctr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR)) - -#define r_epp_A(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR)) -#define r_epp_D(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA)) -#define r_cnfgA(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGA)) -#define r_cnfgB(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGB)) -#define r_ecr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR)) -#define r_fifo(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO)) - -#define w_dtr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR, byte)) -#define w_str(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR, byte)) -#define w_ctr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR, byte)) - -#define w_epp_A(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR, byte)) -#define w_epp_D(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA, byte)) -#define w_ecr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR, byte)) -#define w_fifo(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO, byte)) - -/* - * Register defines for the PC873xx parts - */ - -#define PC873_FER 0x00 -#define PC873_PPENABLE (1<<0) -#define PC873_FAR 0x01 -#define PC873_PTR 0x02 -#define PC873_CFGLOCK (1<<6) -#define PC873_EPPRDIR (1<<7) -#define PC873_EXTENDED (1<<7) -#define PC873_LPTBIRQ7 (1<<3) -#define PC873_FCR 0x03 -#define PC873_ZWS (1<<5) -#define PC873_ZWSPWDN (1<<6) -#define PC873_PCR 0x04 -#define PC873_EPPEN (1<<0) -#define PC873_EPP19 (1<<1) -#define PC873_ECPEN (1<<2) -#define PC873_ECPCLK (1<<3) -#define PC873_PMC 0x06 -#define PC873_TUP 0x07 -#define PC873_SID 0x08 -#define PC873_PNP0 0x1b -#define PC873_PNP1 0x1c -#define PC873_LPTBA 0x19 - -/* - * Register defines for the SMC FDC37C66xGT parts - */ - -/* Init codes */ -#define SMC665_iCODE 0x55 -#define SMC666_iCODE 0x44 - -/* Base configuration ports */ -#define SMC66x_CSR 0x3F0 -#define SMC666_CSR 0x370 /* hard-configured value for 666 */ - -/* Bits */ -#define SMC_CR1_ADDR 0x3 /* bit 0 and 1 */ -#define SMC_CR1_MODE (1<<3) /* bit 3 */ -#define SMC_CR4_EMODE 0x3 /* bits 0 and 1 */ -#define SMC_CR4_EPPTYPE (1<<6) /* bit 6 */ - -/* Extended modes */ -#define SMC_SPP 0x0 /* SPP */ -#define SMC_EPPSPP 0x1 /* EPP and SPP */ -#define SMC_ECP 0x2 /* ECP */ -#define SMC_ECPEPP 0x3 /* ECP and EPP */ - -/* - * Register defines for the SMC FDC37C935 parts - */ - -/* Configuration ports */ -#define SMC935_CFG 0x370 -#define SMC935_IND 0x370 -#define SMC935_DAT 0x371 - -/* Registers */ -#define SMC935_LOGDEV 0x7 -#define SMC935_ID 0x20 -#define SMC935_PORTHI 0x60 -#define SMC935_PORTLO 0x61 -#define SMC935_PPMODE 0xf0 - -/* Parallel port modes */ -#define SMC935_SPP 0x38 + 0 -#define SMC935_EPP19SPP 0x38 + 1 -#define SMC935_ECP 0x38 + 2 -#define SMC935_ECPEPP19 0x38 + 3 -#define SMC935_CENT 0x38 + 4 -#define SMC935_EPP17SPP 0x38 + 5 -#define SMC935_UNUSED 0x38 + 6 -#define SMC935_ECPEPP17 0x38 + 7 - -/* - * Register defines for the Winbond W83877F parts - */ - -#define WINB_W83877F_ID 0xa -#define WINB_W83877AF_ID 0xb - -/* Configuration bits */ -#define WINB_HEFERE (1<<5) /* CROC bit 5 */ -#define WINB_HEFRAS (1<<0) /* CR16 bit 0 */ - -#define WINB_PNPCVS (1<<2) /* CR16 bit 2 */ -#define WINB_CHIPID 0xf /* CR9 bits 0-3 */ - -#define WINB_PRTMODS0 (1<<2) /* CR0 bit 2 */ -#define WINB_PRTMODS1 (1<<3) /* CR0 bit 3 */ -#define WINB_PRTMODS2 (1<<7) /* CR9 bit 7 */ - -/* W83877F modes: CR9/bit7 | CR0/bit3 | CR0/bit2 */ -#define WINB_W83757 0x0 -#define WINB_EXTFDC 0x4 -#define WINB_EXTADP 0x8 -#define WINB_EXT2FDD 0xc -#define WINB_JOYSTICK 0x80 - -#define WINB_PARALLEL 0x80 -#define WINB_EPP_SPP 0x4 -#define WINB_ECP 0x8 -#define WINB_ECP_EPP 0xc - -#endif diff --git a/sys/pc98/pc98/sc_machdep.h b/sys/pc98/pc98/sc_machdep.h deleted file mode 100644 index ea7b3ba..0000000 --- a/sys/pc98/pc98/sc_machdep.h +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD(98) Porting Team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _PC98_PC98_SC_MACHDEP_H_ -#define _PC98_PC98_SC_MACHDEP_H_ - -#undef SC_DFLT_FONT -#undef SC_MOUSE_CHAR -#undef SC_PIXEL_MODE -#undef SC_NO_FONT_LOADING -#define SC_NO_FONT_LOADING 1 -#undef SC_NO_PALETTE_LOADING -#define SC_NO_PALETTE_LOADING 1 - -#ifndef SC_KERNEL_CONS_ATTR -#define SC_KERNEL_CONS_ATTR (FG_LIGHTGREY | BG_BLACK) -#endif - -#define KANJI 1 - -#define BELL_DURATION 5 -#define BELL_PITCH_8M 1339 -#define BELL_PITCH_5M 1678 - -#define UJIS 0 -#define SJIS 1 - -#define PRINTABLE(c) ((c) > 0x1b || ((c) > 0x0f && (c) < 0x1b) \ - || (c) < 0x07) - -#endif /* !_PC98_PC98_SC_MACHDEP_H_ */ diff --git a/sys/pc98/pc98/scgdcrndr.c b/sys/pc98/pc98/scgdcrndr.c deleted file mode 100644 index abebc75..0000000 --- a/sys/pc98/pc98/scgdcrndr.c +++ /dev/null @@ -1,208 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD(98) Porting Team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "opt_syscons.h" -#include "opt_gdc.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/fbio.h> -#include <sys/consio.h> - -#include <dev/fb/fbreg.h> -#include <dev/syscons/syscons.h> - -#ifndef SC_RENDER_DEBUG -#define SC_RENDER_DEBUG 0 -#endif - -static vr_clear_t gdc_txtclear; -static vr_draw_border_t gdc_txtborder; -static vr_draw_t gdc_txtdraw; -static vr_set_cursor_t gdc_txtcursor_shape; -static vr_draw_cursor_t gdc_txtcursor; -#ifndef SC_NO_CUTPASTE -static vr_draw_mouse_t gdc_txtmouse; -#else -#define gdc_txtmouse (vr_draw_mouse_t *)gdc_nop -#endif - -#ifndef SC_NO_MODE_CHANGE -static vr_draw_border_t gdc_grborder; -#endif - -static void gdc_nop(scr_stat *scp, ...); - -static sc_rndr_sw_t txtrndrsw = { - gdc_txtclear, - gdc_txtborder, - gdc_txtdraw, - gdc_txtcursor_shape, - gdc_txtcursor, - (vr_blink_cursor_t *)gdc_nop, - (vr_set_mouse_t *)gdc_nop, - gdc_txtmouse, -}; -RENDERER(gdc, 0, txtrndrsw, gdc_set); - -#ifndef SC_NO_MODE_CHANGE -static sc_rndr_sw_t grrndrsw = { - (vr_clear_t *)gdc_nop, - gdc_grborder, - (vr_draw_t *)gdc_nop, - (vr_set_cursor_t *)gdc_nop, - (vr_draw_cursor_t *)gdc_nop, - (vr_blink_cursor_t *)gdc_nop, - (vr_set_mouse_t *)gdc_nop, - (vr_draw_mouse_t *)gdc_nop, -}; -RENDERER(gdc, GRAPHICS_MODE, grrndrsw, gdc_set); -#endif /* SC_NO_MODE_CHANGE */ - -RENDERER_MODULE(gdc, gdc_set); - -static void -gdc_nop(scr_stat *scp, ...) -{ -} - -/* text mode renderer */ - -static void -gdc_txtclear(scr_stat *scp, int c, int attr) -{ - sc_vtb_clear(&scp->scr, c, attr); -} - -static void -gdc_txtborder(scr_stat *scp, int color) -{ - (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); -} - -static void -gdc_txtdraw(scr_stat *scp, int from, int count, int flip) -{ - vm_offset_t p; - int c; - int a; - - if (from + count > scp->xsize*scp->ysize) - count = scp->xsize*scp->ysize - from; - - if (flip) { - for (p = sc_vtb_pointer(&scp->scr, from); count-- > 0; ++from) { - c = sc_vtb_getc(&scp->vtb, from); - a = sc_vtb_geta(&scp->vtb, from); -#if 0 - a ^= 0x0800; -#else - a = (a & 0x8800) | ((a & 0x7000) >> 4) - | ((a & 0x0700) << 4); -#endif - p = sc_vtb_putchar(&scp->scr, p, c, a); - } - } else { - sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count); - } -} - -static void -gdc_txtcursor_shape(scr_stat *scp, int base, int height, int blink) -{ - if (base < 0 || base >= scp->font_size) - return; - /* the caller may set height <= 0 in order to disable the cursor */ - (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp, - base, height, - scp->font_size, blink); -} - -static void -gdc_txtcursor(scr_stat *scp, int at, int blink, int on, int flip) -{ - if (on) { - scp->status |= VR_CURSOR_ON; - (*vidsw[scp->sc->adapter]->set_hw_cursor)(scp->sc->adp, - at%scp->xsize, at/scp->xsize); - } else { - if (scp->status & VR_CURSOR_ON) - (*vidsw[scp->sc->adapter]->set_hw_cursor)(scp->sc->adp, - -1, -1); - scp->status &= ~VR_CURSOR_ON; - } -} - -#ifndef SC_NO_CUTPASTE - -static void -draw_txtmouse(scr_stat *scp, int x, int y) -{ - int at; - int a; - - at = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff; - a = sc_vtb_geta(&scp->vtb, at); -#if 0 - a ^= 0x0800; -#else - a = (a & 0x8800) | ((a & 0x7000) >> 4) - | ((a & 0x0700) << 4); -#endif - sc_vtb_putc(&scp->scr, at, sc_vtb_getc(&scp->scr, at), a); -} - -static void -remove_txtmouse(scr_stat *scp, int x, int y) -{ -} - -static void -gdc_txtmouse(scr_stat *scp, int x, int y, int on) -{ - if (on) - draw_txtmouse(scp, x, y); - else - remove_txtmouse(scp, x, y); -} - -#endif /* SC_NO_CUTPASTE */ - -#ifndef SC_NO_MODE_CHANGE - -/* graphics mode renderer */ - -static void -gdc_grborder(scr_stat *scp, int color) -{ - (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); -} - -#endif /* SC_NO_MODE_CHANGE */ diff --git a/sys/pc98/pc98/scterm-sck.c b/sys/pc98/pc98/scterm-sck.c deleted file mode 100644 index 7029c07..0000000 --- a/sys/pc98/pc98/scterm-sck.c +++ /dev/null @@ -1,1216 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD(98) Porting Team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "opt_syscons.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/consio.h> - -#include <machine/pc/display.h> - -#include <dev/syscons/syscons.h> -#include <dev/syscons/sctermvar.h> - -#ifndef SC_DUMB_TERMINAL - -#define MAX_ESC_PAR 5 - -#ifdef KANJI -#define IS_KTYPE_ASCII_or_HANKAKU(A) (!((A) & 0xee)) -#define IS_KTYPE_KANA(A) ((A) & 0x11) -#define KTYPE_MASK_CTRL(A) ((A) &= 0xF0) -#endif /* KANJI */ - -/* attribute flags */ -typedef struct { - u_short fg; /* foreground color */ - u_short bg; /* background color */ -} color_t; - -typedef struct { - int flags; -#define SCTERM_BUSY (1 << 0) - int esc; - int num_param; - int last_param; - int param[MAX_ESC_PAR]; - int saved_xpos; - int saved_ypos; - -#ifdef KANJI - u_char kanji_1st_char; - u_char kanji_type; -#define KTYPE_ASCII 0 /* ASCII */ -#define KTYPE_KANA 1 /* HANKAKU */ -#define KTYPE_JKANA 0x10 /* JIS HANKAKU */ -#define KTYPE_7JIS 0x20 /* JIS */ -#define KTYPE_SJIS 2 /* Shift JIS */ -#define KTYPE_UJIS 4 /* UJIS */ -#define KTYPE_SUKANA 3 /* Shift JIS or UJIS HANKAKU */ -#define KTYPE_SUJIS 6 /* SHift JIS or UJIS */ -#define KTYPE_KANIN 0x80 /* Kanji Invoke sequence */ -#define KTYPE_ASCIN 0x40 /* ASCII Invoke sequence */ -#endif /* KANJI */ - - int attr_mask; /* current logical attr mask */ -#define NORMAL_ATTR 0x00 -#define BLINK_ATTR 0x01 -#define BOLD_ATTR 0x02 -#define UNDERLINE_ATTR 0x04 -#define REVERSE_ATTR 0x08 -#define FG_CHANGED 0x10 -#define BG_CHANGED 0x20 - int cur_attr; /* current hardware attr word */ - color_t cur_color; /* current hardware color */ - color_t std_color; /* normal hardware color */ - color_t rev_color; /* reverse hardware color */ - color_t dflt_std_color; /* default normal color */ - color_t dflt_rev_color; /* default reverse color */ -} term_stat; - -static sc_term_init_t scterm_init; -static sc_term_term_t scterm_term; -static sc_term_puts_t scterm_puts; -static sc_term_ioctl_t scterm_ioctl; -static sc_term_reset_t scterm_reset; -static sc_term_default_attr_t scterm_default_attr; -static sc_term_clear_t scterm_clear; -static sc_term_notify_t scterm_notify; -static sc_term_input_t scterm_input; - -static sc_term_sw_t sc_term_sc = { - { NULL, NULL }, - "sck", /* emulator name */ - "syscons kanji terminal", /* description */ - "*", /* matching renderer, any :-) */ - sizeof(term_stat), /* softc size */ - 0, - scterm_init, - scterm_term, - scterm_puts, - scterm_ioctl, - scterm_reset, - scterm_default_attr, - scterm_clear, - scterm_notify, - scterm_input, -}; - -SCTERM_MODULE(sc, sc_term_sc); - -static term_stat reserved_term_stat; -static int default_kanji = UJIS; -static void scterm_scan_esc(scr_stat *scp, term_stat *tcp, - u_char c); -static int mask2attr(term_stat *tcp); - -#ifdef KANJI -__inline static u_char -iskanji1(u_char mode, u_char c) -{ - if (c > 0x80) { - if ((c >= 0xa1) && (c <= 0xdf)) { - if (default_kanji == UJIS) { - /* UJIS */ - return KTYPE_UJIS; - } - if (default_kanji == SJIS) { - /* SJIS HANKAKU */ - return KTYPE_KANA; - } - } - - if (c <= 0x9f) { - if (c == 0x8e) { - /* SJIS or UJIS HANKAKU */ - return KTYPE_SUKANA; - } - - /* SJIS */ - default_kanji = SJIS; - return KTYPE_SJIS; - } - - if ((c >= 0xe0) && (c <= 0xef)) { - /* SJIS or UJIS */ - return KTYPE_SUJIS; - } - - if ((c >= 0xf0) && (c <= 0xfe)) { - /* UJIS */ - default_kanji = UJIS; - return KTYPE_UJIS; - } - } else { - if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) { - /* JIS */ - default_kanji = UJIS; - return KTYPE_7JIS; - } - - if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) { - /* JIS HANKAKU */ - default_kanji = UJIS; - return KTYPE_JKANA; - } - } - - return KTYPE_ASCII; -} - -__inline static u_char -iskanji2(u_char mode, u_char c) -{ - switch (mode) { - case KTYPE_7JIS: - if ((c >= 0x21) && (c <= 0x7e)) { - /* JIS */ - return KTYPE_7JIS; - } - break; - case KTYPE_SJIS: - if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) { - /* SJIS */ - return KTYPE_SJIS; - } - break; - case KTYPE_UJIS: - if ((c >= 0xa1) && (c <= 0xfe)) { - /* UJIS */ - return KTYPE_UJIS; - } - break; - case KTYPE_SUKANA: - if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) { - /* UJIS HANKAKU */ - return KTYPE_KANA; - } - if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) { - /* SJIS */ - default_kanji = SJIS; - return KTYPE_SJIS; - } - break; - case KTYPE_SUJIS: - if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) { - /* SJIS */ - default_kanji = SJIS; - return KTYPE_SJIS; - } - if ((c == 0xfd) || (c == 0xfe)) { - /* UJIS */ - default_kanji = UJIS; - return KTYPE_UJIS; - } - if ((c >= 0xa1) && (c <= 0xfc)) { - if (default_kanji == SJIS) - return KTYPE_SJIS; - if (default_kanji == UJIS) - return KTYPE_UJIS; - } - break; - } - - return KTYPE_ASCII; -} - -/* - * JIS X0208-83 keisen conversion table - */ -static u_short keiConv[32] = { - 0x240c, 0x260c, 0x300c, 0x340c, 0x3c0c, 0x380c, 0x400c, 0x500c, - 0x480c, 0x580c, 0x600c, 0x250c, 0x270c, 0x330c, 0x370c, 0x3f0c, - 0x3b0c, 0x470c, 0x570c, 0x4f0c, 0x5f0c, 0x6f0c, 0x440c, 0x530c, - 0x4c0c, 0x5b0c, 0x630c, 0x410c, 0x540c, 0x490c, 0x5c0c, 0x660c -}; - -static u_short -kanji_convert(u_char mode, u_char h, u_char l) -{ - u_short tmp, high, low, c; - - high = (u_short) h; - low = (u_short) l; - - switch (mode) { - case KTYPE_SJIS: /* SHIFT JIS */ - if (low >= 0xe0) { - low -= 0x40; - } - low = (low - 0x81) * 2 + 0x21; - if (high > 0x7f) { - high--; - } - if (high > 0x9d) { - low++; - high -= 0x9e - 0x21; - } else { - high -= 0x40 - 0x21; - } - high &= 0x7F; - low &= 0x7F; - tmp = ((high << 8) | low) - 0x20; - break; - case KTYPE_7JIS: /* JIS */ - case KTYPE_UJIS: /* UJIS */ - high &= 0x7F; - low &= 0x7F; - tmp = ((high << 8) | low) - 0x20; - break; - default: - tmp = 0; - break; - } - - /* keisen */ - c = ((tmp & 0xff) << 8) | (tmp >> 8); - /* 0x2821 .. 0x2840 */ - if (0x0821 <= c && c <= 0x0840) - tmp = keiConv[c - 0x0821]; - - return (tmp); -} -#endif /* KANJI */ - -static int -scterm_init(scr_stat *scp, void **softc, int code) -{ - term_stat *tcp; - - if (*softc == NULL) { - if (reserved_term_stat.flags & SCTERM_BUSY) - return EINVAL; - *softc = &reserved_term_stat; - } - tcp = *softc; - - switch (code) { - case SC_TE_COLD_INIT: - bzero(tcp, sizeof(*tcp)); - tcp->flags = SCTERM_BUSY; - tcp->esc = 0; - tcp->saved_xpos = -1; - tcp->saved_ypos = -1; -#ifdef KANJI - tcp->kanji_1st_char = 0; - tcp->kanji_type = KTYPE_ASCII; -#endif - tcp->attr_mask = NORMAL_ATTR; - /* XXX */ - tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f; - tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f; - tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f; - tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f; - tcp->std_color = tcp->dflt_std_color; - tcp->rev_color = tcp->dflt_rev_color; - tcp->cur_color = tcp->std_color; - tcp->cur_attr = mask2attr(tcp); - ++sc_term_sc.te_refcount; - break; - - case SC_TE_WARM_INIT: - tcp->esc = 0; - tcp->saved_xpos = -1; - tcp->saved_ypos = -1; -#if 0 - tcp->std_color = tcp->dflt_std_color; - tcp->rev_color = tcp->dflt_rev_color; -#endif - tcp->cur_color = tcp->std_color; - tcp->cur_attr = mask2attr(tcp); - break; - } - - return 0; -} - -static int -scterm_term(scr_stat *scp, void **softc) -{ - if (*softc == &reserved_term_stat) { - *softc = NULL; - bzero(&reserved_term_stat, sizeof(reserved_term_stat)); - } - --sc_term_sc.te_refcount; - return 0; -} - -static void -scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c) -{ - static u_char ansi_col[16] = { - FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, - FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY, - FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW, - FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE - }; - static int cattrs[] = { - 0, /* block */ - CONS_BLINK_CURSOR, /* blinking block */ - CONS_CHAR_CURSOR, /* underline */ - CONS_CHAR_CURSOR | CONS_BLINK_CURSOR, /* blinking underline */ - CONS_RESET_CURSOR, /* reset to default */ - CONS_HIDDEN_CURSOR, /* hide cursor */ - }; - static int tcattrs[] = { - CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, /* normal */ - CONS_HIDDEN_CURSOR | CONS_LOCAL_CURSOR, /* invisible */ - CONS_BLINK_CURSOR | CONS_LOCAL_CURSOR, /* very visible */ - }; - sc_softc_t *sc; - int v0, v1, v2; - int i, n; - - i = n = 0; - sc = scp->sc; - if (tcp->esc == 1) { /* seen ESC */ -#ifdef KANJI - switch (tcp->kanji_type) { - case KTYPE_KANIN: /* Kanji Invoke sequence */ - switch (c) { - case 'B': - case '@': - tcp->kanji_type = KTYPE_7JIS; - tcp->esc = 0; - tcp->kanji_1st_char = 0; - return; - default: - tcp->kanji_type = KTYPE_ASCII; - tcp->esc = 0; - break; - } - break; - case KTYPE_ASCIN: /* Ascii Invoke sequence */ - switch (c) { - case 'J': - case 'B': - case 'H': - tcp->kanji_type = KTYPE_ASCII; - tcp->esc = 0; - tcp->kanji_1st_char = 0; - return; - case 'I': - tcp->kanji_type = KTYPE_JKANA; - tcp->esc = 0; - tcp->kanji_1st_char = 0; - return; - default: - tcp->kanji_type = KTYPE_ASCII; - tcp->esc = 0; - break; - } - break; - default: - break; - } -#endif - switch (c) { - - case '7': /* Save cursor position */ - tcp->saved_xpos = scp->xpos; - tcp->saved_ypos = scp->ypos; - break; - - case '8': /* Restore saved cursor position */ - if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) - sc_move_cursor(scp, tcp->saved_xpos, - tcp->saved_ypos); - break; - - case '[': /* Start ESC [ sequence */ - tcp->esc = 2; - tcp->last_param = -1; - for (i = tcp->num_param; i < MAX_ESC_PAR; i++) - tcp->param[i] = 1; - tcp->num_param = 0; - return; - -#ifdef KANJI - case '$': /* Kanji Invoke sequence */ - tcp->kanji_type = KTYPE_KANIN; - return; -#endif - - case 'M': /* Move cursor up 1 line, scroll if at top */ - sc_term_up_scroll(scp, 1, sc->scr_map[0x20], - tcp->cur_attr, 0, 0); - break; -#if notyet - case 'Q': - tcp->esc = 4; - return; -#endif - case 'c': /* reset */ - tcp->attr_mask = NORMAL_ATTR; - tcp->cur_color = tcp->std_color - = tcp->dflt_std_color; - tcp->rev_color = tcp->dflt_rev_color; - tcp->cur_attr = mask2attr(tcp); - sc_change_cursor_shape(scp, - CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, -1, -1); - sc_clear_screen(scp); - break; - - case '(': /* iso-2022: designate 94 character set to G0 */ -#ifdef KANJI - tcp->kanji_type = KTYPE_ASCIN; -#else - tcp->esc = 5; -#endif - return; - } - } else if (tcp->esc == 2) { /* seen ESC [ */ - if (c >= '0' && c <= '9') { - if (tcp->num_param < MAX_ESC_PAR) { - if (tcp->last_param != tcp->num_param) { - tcp->last_param = tcp->num_param; - tcp->param[tcp->num_param] = 0; - } else { - tcp->param[tcp->num_param] *= 10; - } - tcp->param[tcp->num_param] += c - '0'; - return; - } - } - tcp->num_param = tcp->last_param + 1; - switch (c) { - - case ';': - if (tcp->num_param < MAX_ESC_PAR) - return; - break; - - case '=': - tcp->esc = 3; - tcp->last_param = -1; - for (i = tcp->num_param; i < MAX_ESC_PAR; i++) - tcp->param[i] = 1; - tcp->num_param = 0; - return; - - case 'A': /* up n rows */ - sc_term_up(scp, tcp->param[0], 0); - break; - - case 'B': /* down n rows */ - sc_term_down(scp, tcp->param[0], 0); - break; - - case 'C': /* right n columns */ - sc_term_right(scp, tcp->param[0]); - break; - - case 'D': /* left n columns */ - sc_term_left(scp, tcp->param[0]); - break; - - case 'E': /* cursor to start of line n lines down */ - n = tcp->param[0]; - if (n < 1) - n = 1; - sc_move_cursor(scp, 0, scp->ypos + n); - break; - - case 'F': /* cursor to start of line n lines up */ - n = tcp->param[0]; - if (n < 1) - n = 1; - sc_move_cursor(scp, 0, scp->ypos - n); - break; - - case 'f': /* Cursor move */ - case 'H': - if (tcp->num_param == 0) - sc_move_cursor(scp, 0, 0); - else if (tcp->num_param == 2) - sc_move_cursor(scp, tcp->param[1] - 1, - tcp->param[0] - 1); - break; - - case 'J': /* Clear all or part of display */ - if (tcp->num_param == 0) - n = 0; - else - n = tcp->param[0]; - sc_term_clr_eos(scp, n, sc->scr_map[0x20], - tcp->cur_attr); - break; - - case 'K': /* Clear all or part of line */ - if (tcp->num_param == 0) - n = 0; - else - n = tcp->param[0]; - sc_term_clr_eol(scp, n, sc->scr_map[0x20], - tcp->cur_attr); - break; - - case 'L': /* Insert n lines */ - sc_term_ins_line(scp, scp->ypos, tcp->param[0], - sc->scr_map[0x20], tcp->cur_attr, 0); - break; - - case 'M': /* Delete n lines */ - sc_term_del_line(scp, scp->ypos, tcp->param[0], - sc->scr_map[0x20], tcp->cur_attr, 0); - break; - - case 'P': /* Delete n chars */ - sc_term_del_char(scp, tcp->param[0], - sc->scr_map[0x20], tcp->cur_attr); - break; - - case '@': /* Insert n chars */ - sc_term_ins_char(scp, tcp->param[0], - sc->scr_map[0x20], tcp->cur_attr); - break; - - case 'S': /* scroll up n lines */ - sc_term_del_line(scp, 0, tcp->param[0], - sc->scr_map[0x20], tcp->cur_attr, 0); - break; - - case 'T': /* scroll down n lines */ - sc_term_ins_line(scp, 0, tcp->param[0], - sc->scr_map[0x20], tcp->cur_attr, 0); - break; - - case 'X': /* erase n characters in line */ - n = tcp->param[0]; - if (n < 1) - n = 1; - if (n > scp->xsize - scp->xpos) - n = scp->xsize - scp->xpos; - sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, - sc->scr_map[0x20], tcp->cur_attr); - mark_for_update(scp, scp->cursor_pos); - mark_for_update(scp, scp->cursor_pos + n - 1); - break; - - case 'Z': /* move n tabs backwards */ - sc_term_backtab(scp, tcp->param[0]); - break; - - case '`': /* move cursor to column n */ - sc_term_col(scp, tcp->param[0]); - break; - - case 'a': /* move cursor n columns to the right */ - sc_term_right(scp, tcp->param[0]); - break; - - case 'd': /* move cursor to row n */ - sc_term_row(scp, tcp->param[0]); - break; - - case 'e': /* move cursor n rows down */ - sc_term_down(scp, tcp->param[0], 0); - break; - - case 'm': /* change attribute */ - if (tcp->num_param == 0) { - tcp->attr_mask = NORMAL_ATTR; - tcp->cur_color = tcp->std_color; - tcp->cur_attr = mask2attr(tcp); - break; - } - for (i = 0; i < tcp->num_param; i++) { - switch (n = tcp->param[i]) { - case 0: /* back to normal */ - tcp->attr_mask = NORMAL_ATTR; - tcp->cur_color = tcp->std_color; - tcp->cur_attr = mask2attr(tcp); - break; - case 1: /* bold */ - tcp->attr_mask |= BOLD_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 4: /* underline */ - tcp->attr_mask |= UNDERLINE_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 5: /* blink */ - tcp->attr_mask |= BLINK_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 7: /* reverse */ - tcp->attr_mask |= REVERSE_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 22: /* remove bold (or dim) */ - tcp->attr_mask &= ~BOLD_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 24: /* remove underline */ - tcp->attr_mask &= ~UNDERLINE_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 25: /* remove blink */ - tcp->attr_mask &= ~BLINK_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 27: /* remove reverse */ - tcp->attr_mask &= ~REVERSE_ATTR; - tcp->cur_attr = mask2attr(tcp); - break; - case 30: case 31: /* set ansi fg color */ - case 32: case 33: case 34: - case 35: case 36: case 37: - tcp->attr_mask |= FG_CHANGED; - tcp->cur_color.fg = ansi_col[n - 30]; - tcp->cur_attr = mask2attr(tcp); - break; - case 39: /* restore fg color back to normal */ - tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR); - tcp->cur_color.fg = tcp->std_color.fg; - tcp->cur_attr = mask2attr(tcp); - break; - case 40: case 41: /* set ansi bg color */ - case 42: case 43: case 44: - case 45: case 46: case 47: - tcp->attr_mask |= BG_CHANGED; - tcp->cur_color.bg = ansi_col[n - 40]; - tcp->cur_attr = mask2attr(tcp); - break; - case 49: /* restore bg color back to normal */ - tcp->attr_mask &= ~BG_CHANGED; - tcp->cur_color.bg = tcp->std_color.bg; - tcp->cur_attr = mask2attr(tcp); - break; - } - } - break; - - case 's': /* Save cursor position */ - tcp->saved_xpos = scp->xpos; - tcp->saved_ypos = scp->ypos; - break; - - case 'u': /* Restore saved cursor position */ - if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) - sc_move_cursor(scp, tcp->saved_xpos, - tcp->saved_ypos); - break; - - case 'x': - if (tcp->num_param == 0) - n = 0; - else - n = tcp->param[0]; - switch (n) { - case 0: /* reset colors and attributes back to normal */ - tcp->attr_mask = NORMAL_ATTR; - tcp->cur_color = tcp->std_color - = tcp->dflt_std_color; - tcp->rev_color = tcp->dflt_rev_color; - tcp->cur_attr = mask2attr(tcp); - break; - case 1: /* set ansi background */ - tcp->attr_mask &= ~BG_CHANGED; - tcp->cur_color.bg = tcp->std_color.bg - = ansi_col[tcp->param[1] & 0x0f]; - tcp->cur_attr = mask2attr(tcp); - break; - case 2: /* set ansi foreground */ - tcp->attr_mask &= ~FG_CHANGED; - tcp->cur_color.fg = tcp->std_color.fg - = ansi_col[tcp->param[1] & 0x0f]; - tcp->cur_attr = mask2attr(tcp); - break; - case 3: /* set adapter attribute directly */ - tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED); - tcp->cur_color.fg = tcp->std_color.fg - = tcp->param[1] & 0x0f; - tcp->cur_color.bg = tcp->std_color.bg - = (tcp->param[1] >> 4) & 0x0f; - tcp->cur_attr = mask2attr(tcp); - break; - case 5: /* set ansi reverse background */ - tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f]; - tcp->cur_attr = mask2attr(tcp); - break; - case 6: /* set ansi reverse foreground */ - tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f]; - tcp->cur_attr = mask2attr(tcp); - break; - case 7: /* set adapter reverse attribute directly */ - tcp->rev_color.fg = tcp->param[1] & 0x0f; - tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f; - tcp->cur_attr = mask2attr(tcp); - break; - } - break; - - case 'z': /* switch to (virtual) console n */ - if (tcp->num_param == 1) - sc_switch_scr(sc, tcp->param[0]); - break; - } - } else if (tcp->esc == 3) { /* seen ESC [0-9]+ = */ - if (c >= '0' && c <= '9') { - if (tcp->num_param < MAX_ESC_PAR) { - if (tcp->last_param != tcp->num_param) { - tcp->last_param = tcp->num_param; - tcp->param[tcp->num_param] = 0; - } else { - tcp->param[tcp->num_param] *= 10; - } - tcp->param[tcp->num_param] += c - '0'; - return; - } - } - tcp->num_param = tcp->last_param + 1; - switch (c) { - - case ';': - if (tcp->num_param < MAX_ESC_PAR) - return; - break; - - case 'A': /* set display border color */ - if (tcp->num_param == 1) { - scp->border=tcp->param[0] & 0xff; - if (scp == sc->cur_scp) - sc_set_border(scp, scp->border); - } - break; - - case 'B': /* set bell pitch and duration */ - if (tcp->num_param == 2) { - scp->bell_pitch = tcp->param[0]; - scp->bell_duration = - (tcp->param[1] * hz + 99) / 100; - } - break; - - case 'C': /* set global/parmanent cursor type & shape */ - i = spltty(); - n = tcp->num_param; - v0 = tcp->param[0]; - v1 = tcp->param[1]; - v2 = tcp->param[2]; - switch (n) { - case 1: /* flags only */ - if (v0 < sizeof(cattrs)/sizeof(cattrs[0])) - v0 = cattrs[v0]; - else /* backward compatibility */ - v0 = cattrs[v0 & 0x3]; - sc_change_cursor_shape(scp, v0, -1, -1); - break; - case 2: - v2 = 0; - v0 &= 0x1f; /* backward compatibility */ - v1 &= 0x1f; - /* FALL THROUGH */ - case 3: /* base and height */ - if (v2 == 0) /* count from top */ - sc_change_cursor_shape(scp, -1, - scp->font_size - v1 - 1, - v1 - v0 + 1); - else if (v2 == 1) /* count from bottom */ - sc_change_cursor_shape(scp, -1, - v0, v1 - v0 + 1); - break; - } - splx(i); - break; - - case 'F': /* set adapter foreground */ - if (tcp->num_param == 1) { - tcp->attr_mask &= ~FG_CHANGED; - tcp->cur_color.fg = tcp->std_color.fg - = tcp->param[0] & 0x0f; - tcp->cur_attr = mask2attr(tcp); - } - break; - - case 'G': /* set adapter background */ - if (tcp->num_param == 1) { - tcp->attr_mask &= ~BG_CHANGED; - tcp->cur_color.bg = tcp->std_color.bg - = tcp->param[0] & 0x0f; - tcp->cur_attr = mask2attr(tcp); - } - break; - - case 'H': /* set adapter reverse foreground */ - if (tcp->num_param == 1) { - tcp->rev_color.fg = tcp->param[0] & 0x0f; - tcp->cur_attr = mask2attr(tcp); - } - break; - - case 'I': /* set adapter reverse background */ - if (tcp->num_param == 1) { - tcp->rev_color.bg = tcp->param[0] & 0x0f; - tcp->cur_attr = mask2attr(tcp); - } - break; - - case 'S': /* set local/temporary cursor type & shape */ - i = spltty(); - n = tcp->num_param; - v0 = tcp->param[0]; - switch (n) { - case 0: - v0 = 0; - /* FALL THROUGH */ - case 1: - if (v0 < sizeof(tcattrs)/sizeof(tcattrs[0])) - sc_change_cursor_shape(scp, - tcattrs[v0], -1, -1); - break; - } - splx(i); - break; - } -#if notyet - } else if (tcp->esc == 4) { /* seen ESC Q */ - /* to be filled */ -#endif - } else if (tcp->esc == 5) { /* seen ESC ( */ - switch (c) { - case 'B': /* iso-2022: desginate ASCII into G0 */ - break; - /* other items to be filled */ - default: - break; - } - } - tcp->esc = 0; -} - -static void -scterm_puts(scr_stat *scp, u_char *buf, int len) -{ - term_stat *tcp; - u_char *ptr; -#ifdef KANJI - u_short kanji_code; -#endif - - tcp = scp->ts; - ptr = buf; -outloop: - scp->sc->write_in_progress++; - - if (tcp->esc) { - scterm_scan_esc(scp, tcp, *ptr++); - len--; - } else if (PRINTABLE(*ptr)) { /* Print only printables */ - vm_offset_t p; - u_char *map; - int attr; - int i; - int cnt; -#ifdef KANJI - u_char c; -#endif - - p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos); - map = scp->sc->scr_map; - attr = tcp->cur_attr; - -#ifdef KANJI - c = *ptr; - if (tcp->kanji_1st_char == 0) { - tcp->kanji_type = iskanji1(tcp->kanji_type, c); - if (!IS_KTYPE_ASCII_or_HANKAKU(tcp->kanji_type)) { - /* not Ascii & not HANKAKU */ - tcp->kanji_1st_char = c; - goto kanji_end; - } else if (tcp->kanji_type == KTYPE_ASCII) { - cnt = imin(len, scp->xsize - scp->xpos); - i = cnt; - do { - p = sc_vtb_putchar(&scp->vtb, p, map[c], attr); - c = *++ptr; - --i; - } while (i > 0 && PRINTABLE(c) && - iskanji1(tcp->kanji_type, c) == KTYPE_ASCII); - - len -= cnt - i; - mark_for_update(scp, scp->cursor_pos); - scp->cursor_pos += cnt - i; - mark_for_update(scp, scp->cursor_pos - 1); - scp->xpos += cnt - i; - KTYPE_MASK_CTRL(tcp->kanji_type); - goto ascii_end; - } - } else { - if ((tcp->kanji_type = - iskanji2(tcp->kanji_type, c)) & 0xee) { - /* print kanji on TEXT VRAM */ - kanji_code = kanji_convert(tcp->kanji_type, c, - tcp->kanji_1st_char); - mark_for_update(scp, scp->cursor_pos); - for (i = 0; i < 2; i++) { - /* *cursor_pos = (kanji_code | (i*0x80)); */ - p = sc_vtb_putchar(&scp->vtb, p, - kanji_code | ((i == 0) ? 0x00 : 0x80), attr); - ++scp->cursor_pos; - if (++scp->xpos >= scp->xsize) { - scp->xpos = 0; - scp->ypos++; - } - } - mark_for_update(scp, scp->cursor_pos - 1); - KTYPE_MASK_CTRL(tcp->kanji_type); - tcp->kanji_1st_char = 0; - goto kanji_end; - } else { - tcp->kanji_1st_char = 0; - } - } - if (IS_KTYPE_KANA(tcp->kanji_type)) - c |= 0x80; - KTYPE_MASK_CTRL(tcp->kanji_type); - sc_vtb_putchar(&scp->vtb, p, map[c], attr); - mark_for_update(scp, scp->cursor_pos); - mark_for_update(scp, scp->cursor_pos); - ++scp->cursor_pos; - ++scp->xpos; -kanji_end: - ++ptr; - --len; -ascii_end: -#else /* !KANJI */ - cnt = imin(len, scp->xsize - scp->xpos); - i = cnt; - do { - /* - * gcc-2.6.3 generates poor (un)sign extension code. - * Casting the pointers in the following to volatile should - * have no effect, but in fact speeds up this inner loop - * from 26 to 18 cycles (+ cache misses) on i486's. - */ -#define UCVP(ucp) ((u_char volatile *)(ucp)) - p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)], - attr); - ++ptr; - --i; - } while (i > 0 && PRINTABLE(*ptr)); - - len -= cnt - i; - mark_for_update(scp, scp->cursor_pos); - scp->cursor_pos += cnt - i; - mark_for_update(scp, scp->cursor_pos - 1); - scp->xpos += cnt - i; -#endif /* !KANJI */ - - if (scp->xpos >= scp->xsize) { - scp->xpos = 0; - scp->ypos++; - } - } else { - switch (*ptr) { - case 0x07: - sc_bell(scp, scp->bell_pitch, scp->bell_duration); - break; - - case 0x08: /* non-destructive backspace */ - if (scp->cursor_pos > 0) { - mark_for_update(scp, scp->cursor_pos); - scp->cursor_pos--; - mark_for_update(scp, scp->cursor_pos); - if (scp->xpos > 0) - scp->xpos--; - else { - scp->xpos += scp->xsize - 1; - scp->ypos--; - } - } - break; - - case 0x09: /* non-destructive tab */ - mark_for_update(scp, scp->cursor_pos); - scp->cursor_pos += (8 - scp->xpos % 8u); - scp->xpos += (8 - scp->xpos % 8u); - if (scp->xpos >= scp->xsize) { - scp->xpos = 0; - scp->ypos++; - scp->cursor_pos = scp->xsize * scp->ypos; - } - mark_for_update(scp, scp->cursor_pos); - break; - - case 0x0a: /* newline, same pos */ - mark_for_update(scp, scp->cursor_pos); - scp->cursor_pos += scp->xsize; - mark_for_update(scp, scp->cursor_pos); - scp->ypos++; - break; - - case 0x0c: /* form feed, clears screen */ - sc_clear_screen(scp); - break; - - case 0x0d: /* return, return to pos 0 */ - mark_for_update(scp, scp->cursor_pos); - scp->cursor_pos -= scp->xpos; - mark_for_update(scp, scp->cursor_pos); - scp->xpos = 0; - break; - - case 0x0e: /* ^N */ - tcp->kanji_type = KTYPE_JKANA; - tcp->esc = 0; - tcp->kanji_1st_char = 0; - break; - - case 0x0f: /* ^O */ - tcp->kanji_type = KTYPE_ASCII; - tcp->esc = 0; - tcp->kanji_1st_char = 0; - break; - - case 0x1b: /* start escape sequence */ - tcp->esc = 1; - tcp->num_param = 0; - break; - } - ptr++; - len--; - } - - sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr); - - scp->sc->write_in_progress--; - if (len) - goto outloop; -} - -static int -scterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data, - int flag, struct thread *td) -{ - term_stat *tcp = scp->ts; - vid_info_t *vi; - - switch (cmd) { - case GIO_ATTR: /* get current attributes */ - /* FIXME: */ - *(int*)data = (tcp->cur_attr >> 8) & 0xff; - return 0; - case CONS_GETINFO: /* get current (virtual) console info */ - vi = (vid_info_t *)data; - if (vi->size != sizeof(struct vid_info)) - return EINVAL; - vi->mv_norm.fore = tcp->std_color.fg; - vi->mv_norm.back = tcp->std_color.bg; - vi->mv_rev.fore = tcp->rev_color.fg; - vi->mv_rev.back = tcp->rev_color.bg; - /* - * The other fields are filled by the upper routine. XXX - */ - return ENOIOCTL; - } - return ENOIOCTL; -} - -static int -scterm_reset(scr_stat *scp, int code) -{ - /* FIXME */ - return 0; -} - -static void -scterm_default_attr(scr_stat *scp, int color, int rev_color) -{ - term_stat *tcp = scp->ts; - - tcp->dflt_std_color.fg = color & 0x0f; - tcp->dflt_std_color.bg = (color >> 4) & 0x0f; - tcp->dflt_rev_color.fg = rev_color & 0x0f; - tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f; - tcp->std_color = tcp->dflt_std_color; - tcp->rev_color = tcp->dflt_rev_color; - tcp->cur_color = tcp->std_color; - tcp->cur_attr = mask2attr(tcp); -} - -static void -scterm_clear(scr_stat *scp) -{ - term_stat *tcp = scp->ts; - - sc_move_cursor(scp, 0, 0); - sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr); - mark_all(scp); -} - -static void -scterm_notify(scr_stat *scp, int event) -{ - switch (event) { - case SC_TE_NOTIFY_VTSWITCH_IN: - break; - case SC_TE_NOTIFY_VTSWITCH_OUT: - break; - } -} - -static int -scterm_input(scr_stat *scp, int c, struct tty *tp) -{ - return FALSE; -} - -/* - * Calculate hardware attributes word using logical attributes mask and - * hardware colors - */ - -/* FIXME */ -static int -mask2attr(term_stat *tcp) -{ - int attr, mask = tcp->attr_mask; - - if (mask & REVERSE_ATTR) { - attr = ((mask & FG_CHANGED) ? - tcp->cur_color.bg : tcp->rev_color.fg) | - (((mask & BG_CHANGED) ? - tcp->cur_color.fg : tcp->rev_color.bg) << 4); - } else - attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4); - - /* XXX: underline mapping for Hercules adapter can be better */ - if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) - attr ^= 0x08; - if (mask & BLINK_ATTR) - attr ^= 0x80; - - return (attr << 8); -} - -#endif /* SC_DUMB_TERMINAL */ diff --git a/sys/pc98/pc98/scvtbpc98.c b/sys/pc98/pc98/scvtbpc98.c deleted file mode 100644 index 2d0ea3f..0000000 --- a/sys/pc98/pc98/scvtbpc98.c +++ /dev/null @@ -1,399 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD(98) Porting Team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "opt_syscons.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/consio.h> -#include <sys/fbio.h> - -#include <machine/md_var.h> - -#include <dev/fb/fbreg.h> -#include <dev/syscons/syscons.h> - -#define ATTR_OFFSET_FB 0x2000 -#define attr_offset(vtb) ((vtb)->vtb_size*sizeof(u_int16_t)) - -#define vtb_pointer(vtb, at) \ - ((vtb)->vtb_buffer + sizeof(u_int16_t)*(at)) - -#define vtb_wrap(vtb, at, offset) \ - (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size) - -static u_int8_t ibmpc_to_pc98[256] = { - 0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1, - 0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, - 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, - 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, - 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, - - 0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3, - 0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, - 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, - 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, - 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, -}; -#define at2pc98(attr) ((attr) | ibmpc_to_pc98[(unsigned)(attr) >> 8]) - -void -sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait) -{ - vtb->vtb_flags = 0; - vtb->vtb_type = type; - vtb->vtb_cols = cols; - vtb->vtb_rows = rows; - vtb->vtb_size = cols*rows; - vtb->vtb_buffer = 0; - vtb->vtb_tail = 0; - - switch (type) { - case VTB_MEMORY: - case VTB_RINGBUFFER: - if ((buf == NULL) && (cols*rows != 0)) { - vtb->vtb_buffer = - (vm_offset_t)malloc(cols*rows*sizeof(u_int16_t)*2, - M_DEVBUF, - ((wait) ? M_WAITOK : M_NOWAIT) | M_ZERO); - if (vtb->vtb_buffer != 0) { - vtb->vtb_flags |= VTB_ALLOCED; - } - } else { - vtb->vtb_buffer = (vm_offset_t)buf; - } - vtb->vtb_flags |= VTB_VALID; - break; - case VTB_FRAMEBUFFER: - vtb->vtb_buffer = (vm_offset_t)buf; - vtb->vtb_flags |= VTB_VALID; - break; - default: - break; - } -} - -void -sc_vtb_destroy(sc_vtb_t *vtb) -{ - vm_offset_t p; - - vtb->vtb_cols = 0; - vtb->vtb_rows = 0; - vtb->vtb_size = 0; - vtb->vtb_tail = 0; - - p = vtb->vtb_buffer; - vtb->vtb_buffer = 0; - switch (vtb->vtb_type) { - case VTB_MEMORY: - case VTB_RINGBUFFER: - if ((vtb->vtb_flags & VTB_ALLOCED) && (p != 0)) - free((void *)p, M_DEVBUF); - break; - default: - break; - } - vtb->vtb_flags = 0; - vtb->vtb_type = VTB_INVALID; -} - -size_t -sc_vtb_size(int cols, int rows) -{ - return (size_t)(cols*rows*sizeof(u_int16_t)*2); -} - -int -sc_vtb_getc(sc_vtb_t *vtb, int at) -{ - vm_offset_t p = vtb_pointer(vtb, at); - - if (vtb->vtb_type == VTB_FRAMEBUFFER) - return (readw(p) & 0x00ff); - else - return (*(u_int16_t *)p & 0x00ff); -} - -int -sc_vtb_geta(sc_vtb_t *vtb, int at) -{ - vm_offset_t p = vtb_pointer(vtb, at); - - if (vtb->vtb_type == VTB_FRAMEBUFFER) - return (readw(p + ATTR_OFFSET_FB) & 0xff00); - else - return (*(u_int16_t *)(p + attr_offset(vtb)) & 0xff00); -} - -__inline static void -vtb_putc(sc_vtb_t *vtb, vm_offset_t p, int c, int a) -{ - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - writew(p, c); - writew(p + ATTR_OFFSET_FB, at2pc98(a)); - } else { - *(u_int16_t *)p = c; - *(u_int16_t *)(p + attr_offset(vtb)) = at2pc98(a); - } -} - -void -sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a) -{ - vtb_putc(vtb, vtb_pointer(vtb, at), c, a); -} - -vm_offset_t -sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a) -{ - vtb_putc(vtb, p, c, a); - return (p + sizeof(u_int16_t)); -} - -vm_offset_t -sc_vtb_pointer(sc_vtb_t *vtb, int at) -{ - return (vtb_pointer(vtb, at)); -} - -int -sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset) -{ - return ((pos + offset + vtb->vtb_size)%vtb->vtb_size); -} - -void -sc_vtb_clear(sc_vtb_t *vtb, int c, int attr) -{ - vm_offset_t p = vtb_pointer(vtb, 0); - - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - fillw_io(c, p, vtb->vtb_size); - fillw_io(at2pc98(attr), p + ATTR_OFFSET_FB, vtb->vtb_size); - } else { - fillw(c, (void *)p, vtb->vtb_size); - fillw(at2pc98(attr), (void *)(p + attr_offset(vtb)), - vtb->vtb_size); - } -} - -void -sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count) -{ - vm_offset_t p1, p2; - - p1 = vtb_pointer(vtb1, from); - p2 = vtb_pointer(vtb2, to); - if (vtb2->vtb_type == VTB_FRAMEBUFFER) { - bcopy_toio(p1, p2, count*sizeof(u_int16_t)); - bcopy_toio(p1 + attr_offset(vtb1), - p2 + ATTR_OFFSET_FB, - count*sizeof(u_int16_t)); - } else if (vtb1->vtb_type == VTB_FRAMEBUFFER) { - bcopy_fromio(p1, p2, count*sizeof(u_int16_t)); - bcopy_fromio(p1 + ATTR_OFFSET_FB, - p2 + attr_offset(vtb2), - count*sizeof(u_int16_t)); - } else { - bcopy((void *)p1, (void *)p2, count*sizeof(u_int16_t)); - bcopy((void *)(p1 + attr_offset(vtb1)), - (void *)(p2 + attr_offset(vtb2)), - count*sizeof(u_int16_t)); - } -} - -void -sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count) -{ - int len; - vm_offset_t p1, p2; - - if (vtb2->vtb_type != VTB_RINGBUFFER) - return; - - while (count > 0) { - p1 = vtb_pointer(vtb1, from); - p2 = vtb_pointer(vtb2, vtb2->vtb_tail); - len = imin(count, vtb2->vtb_size - vtb2->vtb_tail); - if (vtb1->vtb_type == VTB_FRAMEBUFFER) { - bcopy_fromio(p1, p2, len*sizeof(u_int16_t)); - bcopy_fromio(p1 + ATTR_OFFSET_FB, - p2 + attr_offset(vtb2), - len*sizeof(u_int16_t)); - } else { - bcopy((void *)p1, (void *)p2, len*sizeof(u_int16_t)); - bcopy((void *)(p1 + attr_offset(vtb1)), - (void *)(p2 + attr_offset(vtb2)), - len*sizeof(u_int16_t)); - } - from += len; - count -= len; - vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len); - } -} - -void -sc_vtb_seek(sc_vtb_t *vtb, int pos) -{ - vtb->vtb_tail = pos%vtb->vtb_size; -} - -void -sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr) -{ - vm_offset_t p; - - if (at + count > vtb->vtb_size) - count = vtb->vtb_size - at; - p = vtb_pointer(vtb, at); - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - fillw_io(c, p, count); - fillw_io(at2pc98(attr), p + ATTR_OFFSET_FB, count); - } else { - fillw(c, (void *)p, count); - fillw(at2pc98(attr), (void *)(p + attr_offset(vtb)), count); - } -} - -void -sc_vtb_move(sc_vtb_t *vtb, int from, int to, int count) -{ - vm_offset_t p1, p2; - - if (from + count > vtb->vtb_size) - count = vtb->vtb_size - from; - if (to + count > vtb->vtb_size) - count = vtb->vtb_size - to; - if (count <= 0) - return; - - p1 = vtb_pointer(vtb, from); - p2 = vtb_pointer(vtb, to); - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - bcopy_io(p1, p2, count*sizeof(u_int16_t)); - bcopy_io(p1 + ATTR_OFFSET_FB, - p2 + ATTR_OFFSET_FB, count*sizeof(u_int16_t)); - } else { - bcopy((void *)p1, (void *)p2, count*sizeof(u_int16_t)); - bcopy((void *)(p1 + attr_offset(vtb)), - (void *)(p2 + attr_offset(vtb)), count*sizeof(u_int16_t)); - } -} - -void -sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr) -{ - int len; - vm_offset_t p1, p2; - - if (at + count > vtb->vtb_size) - count = vtb->vtb_size - at; - len = vtb->vtb_size - at - count; - if (len > 0) { - p1 = vtb_pointer(vtb, at + count); - p2 = vtb_pointer(vtb, at); - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - bcopy_io(p1, p2, len*sizeof(u_int16_t)); - bcopy_io(p1 + ATTR_OFFSET_FB, - p2 + ATTR_OFFSET_FB, - len*sizeof(u_int16_t)); - } else { - bcopy((void *)p1, (void *)p2, len*sizeof(u_int16_t)); - bcopy((void *)(p1 + attr_offset(vtb)), - (void *)(p2 + attr_offset(vtb)), - len*sizeof(u_int16_t)); - } - } - p1 = vtb_pointer(vtb, at + len); - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - fillw_io(c, p1, vtb->vtb_size - at - len); - fillw_io(at2pc98(attr), p1 + ATTR_OFFSET_FB, - vtb->vtb_size - at - len); - } else { - fillw(c, (void *)p1, vtb->vtb_size - at - len); - fillw(at2pc98(attr), (void *)(p1 + attr_offset(vtb)), - vtb->vtb_size - at - len); - } -} - -void -sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr) -{ - vm_offset_t p1, p2; - - p1 = vtb_pointer(vtb, at); - if (at + count > vtb->vtb_size) { - count = vtb->vtb_size - at; - } else { - p2 = vtb_pointer(vtb, at + count); - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - bcopy_io(p1, p2, - (vtb->vtb_size - at - count)*sizeof(u_int16_t)); - bcopy_io(p1 + ATTR_OFFSET_FB, - p2 + ATTR_OFFSET_FB, - (vtb->vtb_size - at - count)*sizeof(u_int16_t)); - } else { - bcopy((void *)p1, (void *)p2, - (vtb->vtb_size - at - count)*sizeof(u_int16_t)); - bcopy((void *)(p1 + attr_offset(vtb)), - (void *)(p2 + attr_offset(vtb)), - (vtb->vtb_size - at - count)*sizeof(u_int16_t)); - } - } - if (vtb->vtb_type == VTB_FRAMEBUFFER) { - fillw_io(c, p1, count); - fillw_io(at2pc98(attr), p1 + ATTR_OFFSET_FB, count); - } else { - fillw(c, (void *)p1, count); - fillw(at2pc98(attr), (void *)(p1 + attr_offset(vtb)), count); - } -} diff --git a/sys/pc98/pc98/sio.c b/sys/pc98/pc98/sio.c deleted file mode 100644 index 297f61d..0000000 --- a/sys/pc98/pc98/sio.c +++ /dev/null @@ -1,4413 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * from: i386/isa sio.c,v 1.234 - */ - -#include "opt_comconsole.h" -#include "opt_compat.h" -#include "opt_gdb.h" -#include "opt_kdb.h" -#include "opt_sio.h" - -/* - * Serial driver, based on 386BSD-0.1 com driver. - * Mostly rewritten to use pseudo-DMA. - * Works for National Semiconductor NS8250-NS16550AF UARTs. - * COM driver, based on HP dca driver. - * - * Changes for PC-Card integration: - * - Added PC-Card driver table and handlers - */ -/*=============================================================== - * 386BSD(98),FreeBSD-1.1x(98) com driver. - * ----- - * modified for PC9801 by M.Ishii - * Kyoto University Microcomputer Club (KMC) - * Chou "TEFUTEFU" Hirotomi - * Kyoto Univ. the faculty of medicine - *=============================================================== - * FreeBSD-2.0.1(98) sio driver. - * ----- - * modified for pc98 Internal i8251 and MICRO CORE MC16550II - * T.Koike(hfc01340@niftyserve.or.jp) - * implement kernel device configuration - * aizu@orient.center.nitech.ac.jp - * - * Notes. - * ----- - * PC98 localization based on 386BSD(98) com driver. Using its PC98 local - * functions. - * This driver is under debugging,has bugs. - */ -/* - * modified for AIWA B98-01 - * by T.Hatanou <hatanou@yasuda.comm.waseda.ac.jp> last update: 15 Sep.1995 - */ -/* - * Modified by Y.Takahashi of Kogakuin University. - */ -/* - * modified for 8251(FIFO) by Seigo TANIMURA <tanimura@FreeBSD.org> - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/interrupt.h> -#include <sys/kdb.h> -#include <sys/kernel.h> -#include <sys/limits.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/reboot.h> -#include <sys/serial.h> -#include <sys/sysctl.h> -#include <sys/syslog.h> -#include <sys/tty.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <sys/timepps.h> -#include <sys/uio.h> -#include <sys/cons.h> - -#include <isa/isavar.h> - -#include <machine/resource.h> - -#include <dev/sio/sioreg.h> -#include <dev/sio/siovar.h> - -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> -#endif - -#ifdef COM_ESP -#include <dev/ic/esp.h> -#endif -#include <dev/ic/ns16550.h> -#ifdef PC98 -#include <dev/ic/i8251.h> -#include <dev/ic/rsa.h> -#endif - -#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ - -/* - * Meaning of flags: - * - * 0x00000001 shared IRQs - * 0x00000002 disable FIFO - * 0x00000008 recover sooner from lost output interrupts - * 0x00000010 device is potential system console - * 0x00000020 device is forced to become system console - * 0x00000040 device is reserved for low-level IO - * 0x00000080 use this port for remote kernel debugging - * 0x0000??00 minor number of master port - * 0x00010000 PPS timestamping on CTS instead of DCD - * 0x00080000 IIR_TXRDY bug - * 0x00400000 If no comconsole found then mark as a comconsole - * 0x1?000000 interface type - */ - -#ifdef COM_MULTIPORT -/* checks in flags for multiport and which is multiport "master chip" - * for a given card - */ -#define COM_ISMULTIPORT(flags) ((flags) & 0x01) -#define COM_MPMASTER(flags) (((flags) >> 8) & 0x0ff) -#ifndef PC98 -#define COM_NOTAST4(flags) ((flags) & 0x04) -#endif -#else -#define COM_ISMULTIPORT(flags) (0) -#endif /* COM_MULTIPORT */ - -#define COM_C_IIR_TXRDYBUG 0x80000 -#define COM_CONSOLE(flags) ((flags) & 0x10) -#define COM_DEBUGGER(flags) ((flags) & 0x80) -#ifndef PC98 -#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24) -#endif -#define COM_FORCECONSOLE(flags) ((flags) & 0x20) -#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG) -#define COM_LLCONSOLE(flags) ((flags) & 0x40) -#define COM_LOSESOUTINTS(flags) ((flags) & 0x08) -#define COM_NOFIFO(flags) ((flags) & 0x02) -#ifndef PC98 -#define COM_NOSCR(flags) ((flags) & 0x100000) -#endif -#define COM_PPSCTS(flags) ((flags) & 0x10000) -#ifndef PC98 -#define COM_ST16650A(flags) ((flags) & 0x20000) -#define COM_TI16754(flags) ((flags) & 0x200000) -#endif - -#define sio_getreg(com, off) \ - (bus_space_read_1((com)->bst, (com)->bsh, (off))) -#define sio_setreg(com, off, value) \ - (bus_space_write_1((com)->bst, (com)->bsh, (off), (value))) - -/* - * com state bits. - * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher - * than the other bits so that they can be tested as a group without masking - * off the low bits. - * - * The following com and tty flags correspond closely: - * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and - * comstop()) - * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) - * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) - * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) - * TS_FLUSH is not used. - * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. - * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). - */ -#define CS_BUSY 0x80 /* output in progress */ -#define CS_TTGO 0x40 /* output not stopped by XOFF */ -#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ -#define CS_CHECKMSR 1 /* check of MSR scheduled */ -#define CS_CTS_OFLOW 2 /* use CTS output flow control */ -#define CS_ODONE 4 /* output completed */ -#define CS_RTS_IFLOW 8 /* use RTS input flow control */ -#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ - -static char const * const error_desc[] = { -#define CE_OVERRUN 0 - "silo overflow", -#define CE_INTERRUPT_BUF_OVERFLOW 1 - "interrupt-level buffer overflow", -#define CE_TTY_BUF_OVERFLOW 2 - "tty-level buffer overflow", -}; - -#define CE_NTYPES 3 -#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) - -/* types. XXX - should be elsewhere */ -typedef u_int Port_t; /* hardware port */ -typedef u_char bool_t; /* boolean */ - -/* queue of linear buffers */ -struct lbq { - u_char *l_head; /* next char to process */ - u_char *l_tail; /* one past the last char to process */ - struct lbq *l_next; /* next in queue */ - bool_t l_queued; /* nonzero if queued */ -}; - -/* com device structure */ -struct com_s { - u_char state; /* miscellaneous flag bits */ - u_char cfcr_image; /* copy of value written to CFCR */ -#ifdef COM_ESP - bool_t esp; /* is this unit a hayes esp board? */ -#endif - u_char extra_state; /* more flag bits, separate for order trick */ - u_char fifo_image; /* copy of value written to FIFO */ - bool_t hasfifo; /* nonzero for 16550 UARTs */ - bool_t loses_outints; /* nonzero if device loses output interrupts */ - u_char mcr_image; /* copy of value written to MCR */ -#ifdef COM_MULTIPORT - bool_t multiport; /* is this unit part of a multiport device? */ -#endif /* COM_MULTIPORT */ - bool_t no_irq; /* nonzero if irq is not attached */ - bool_t gone; /* hardware disappeared */ - bool_t poll; /* nonzero if polling is required */ - bool_t poll_output; /* nonzero if polling for output is required */ - bool_t st16650a; /* nonzero if Startech 16650A compatible */ - int unit; /* unit number */ - u_int flags; /* copy of device flags */ - u_int tx_fifo_size; - - /* - * The high level of the driver never reads status registers directly - * because there would be too many side effects to handle conveniently. - * Instead, it reads copies of the registers stored here by the - * interrupt handler. - */ - u_char last_modem_status; /* last MSR read by intr handler */ - u_char prev_modem_status; /* last MSR handled by high level */ - - u_char *ibuf; /* start of input buffer */ - u_char *ibufend; /* end of input buffer */ - u_char *ibufold; /* old input buffer, to be freed */ - u_char *ihighwater; /* threshold in input buffer */ - u_char *iptr; /* next free spot in input buffer */ - int ibufsize; /* size of ibuf (not include error bytes) */ - int ierroff; /* offset of error bytes in ibuf */ - - struct lbq obufq; /* head of queue of output buffers */ - struct lbq obufs[2]; /* output buffers */ - - bus_space_tag_t bst; - bus_space_handle_t bsh; - -#ifdef PC98 - Port_t cmd_port; - Port_t sts_port; - Port_t in_modem_port; - Port_t intr_ctrl_port; - Port_t rsabase; /* Iobase address of an I/O-DATA RSA board. */ - int intr_enable; - int pc98_prev_modem_status; - int pc98_modem_delta; - int modem_car_chg_timer; - int pc98_prev_siocmd; - int pc98_prev_siomod; - int modem_checking; - int pc98_if_type; - - bool_t pc98_8251fifo; - bool_t pc98_8251fifo_enable; -#endif /* PC98 */ - Port_t data_port; /* i/o ports */ -#ifdef COM_ESP - Port_t esp_port; -#endif - Port_t int_ctl_port; - Port_t int_id_port; - Port_t modem_ctl_port; - Port_t line_status_port; - Port_t modem_status_port; - - struct tty *tp; /* cross reference */ - - struct pps_state pps; - int pps_bit; -#ifdef ALT_BREAK_TO_DEBUGGER - int alt_brk_state; -#endif - - u_long bytes_in; /* statistics */ - u_long bytes_out; - u_int delta_error_counts[CE_NTYPES]; - u_long error_counts[CE_NTYPES]; - - u_long rclk; - - struct resource *irqres; - struct resource *ioportres; - int ioportrid; - void *cookie; - - /* - * Data area for output buffers. Someday we should build the output - * buffer queue without copying data. - */ -#ifdef PC98 - int obufsize; - u_char *obuf1; - u_char *obuf2; -#else - u_char obuf1[256]; - u_char obuf2[256]; -#endif -}; - -#ifdef COM_ESP -static int espattach(struct com_s *com, Port_t esp_port); -#endif - -static void combreak(struct tty *tp, int sig); -static timeout_t siobusycheck; -static u_int siodivisor(u_long rclk, speed_t speed); -static void comclose(struct tty *tp); -static int comopen(struct tty *tp, struct cdev *dev); -static void sioinput(struct com_s *com); -static void siointr1(struct com_s *com); -static void siointr(void *arg); -static int commodem(struct tty *tp, int sigon, int sigoff); -static int comparam(struct tty *tp, struct termios *t); -static void siopoll(void *); -static void siosettimeout(void); -static int siosetwater(struct com_s *com, speed_t speed); -static void comstart(struct tty *tp); -static void comstop(struct tty *tp, int rw); -static timeout_t comwakeup; - -char sio_driver_name[] = "sio"; -static struct mtx sio_lock; -static int sio_inited; - -/* table and macro for fast conversion from a unit number to its com struct */ -devclass_t sio_devclass; -#define com_addr(unit) ((struct com_s *) \ - devclass_get_softc(sio_devclass, unit)) /* XXX */ - -int comconsole = -1; -static volatile speed_t comdefaultrate = CONSPEED; -static u_long comdefaultrclk = DEFAULT_RCLK; -SYSCTL_ULONG(_machdep, OID_AUTO, conrclk, CTLFLAG_RW, &comdefaultrclk, 0, ""); -static speed_t gdbdefaultrate = GDBSPEED; -SYSCTL_UINT(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW, - &gdbdefaultrate, GDBSPEED, ""); -static u_int com_events; /* input chars + weighted output completions */ -static Port_t siocniobase; -static int siocnunit = -1; -static void *sio_slow_ih; -static void *sio_fast_ih; -static int sio_timeout; -static int sio_timeouts_until_log; -static struct callout_handle sio_timeout_handle - = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); -static int sio_numunits; - -#ifdef PC98 -struct siodev { - short if_type; - short irq; - Port_t cmd, sts, ctrl, mod; -}; -static int sysclock; - -#define COM_INT_DISABLE {int previpri; previpri=spltty(); -#define COM_INT_ENABLE splx(previpri);} -#define IEN_TxFLAG IEN_Tx - -#define COM_CARRIER_DETECT_EMULATE 0 -#define PC98_CHECK_MODEM_INTERVAL (hz/10) -#define DCD_OFF_TOLERANCE 2 -#define DCD_ON_RECOGNITION 2 -#define IS_8251(if_type) (!(if_type & 0x10)) -#define COM1_EXT_CLOCK 0x40000 - -static void commint(struct cdev *dev); -static void com_tiocm_bis(struct com_s *com, int msr); -static void com_tiocm_bic(struct com_s *com, int msr); -static int com_tiocm_get(struct com_s *com); -static int com_tiocm_get_delta(struct com_s *com); -static void pc98_msrint_start(struct cdev *dev); -static void com_cflag_and_speed_set(struct com_s *com, int cflag, int speed); -static int pc98_ttspeedtab(struct com_s *com, int speed, u_int *divisor); -static int pc98_get_modem_status(struct com_s *com); -static timeout_t pc98_check_msr; -static void pc98_set_baud_rate(struct com_s *com, u_int count); -static void pc98_i8251_reset(struct com_s *com, int mode, int command); -static void pc98_disable_i8251_interrupt(struct com_s *com, int mod); -static void pc98_enable_i8251_interrupt(struct com_s *com, int mod); -static int pc98_check_i8251_interrupt(struct com_s *com); -static int pc98_i8251_get_cmd(struct com_s *com); -static int pc98_i8251_get_mod(struct com_s *com); -static void pc98_i8251_set_cmd(struct com_s *com, int x); -static void pc98_i8251_or_cmd(struct com_s *com, int x); -static void pc98_i8251_clear_cmd(struct com_s *com, int x); -static void pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x); -static int pc98_check_if_type(device_t dev, struct siodev *iod); -static int pc98_check_8251vfast(void); -static int pc98_check_8251fifo(void); -static void pc98_check_sysclock(void); -static void pc98_set_ioport(struct com_s *com); - -#define com_int_Tx_disable(com) \ - pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP) -#define com_int_Tx_enable(com) \ - pc98_enable_i8251_interrupt(com,IEN_TxFLAG) -#define com_int_Rx_disable(com) \ - pc98_disable_i8251_interrupt(com,IEN_Rx) -#define com_int_Rx_enable(com) \ - pc98_enable_i8251_interrupt(com,IEN_Rx) -#define com_int_TxRx_disable(com) \ - pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx) -#define com_int_TxRx_enable(com) \ - pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx) -#define com_send_break_on(com) \ - (IS_8251((com)->pc98_if_type) ? \ - pc98_i8251_or_cmd((com), CMD8251_SBRK) : \ - sio_setreg((com), com_cfcr, (com)->cfcr_image |= CFCR_SBREAK)) -#define com_send_break_off(com) \ - (IS_8251((com)->pc98_if_type) ? \ - pc98_i8251_clear_cmd((com), CMD8251_SBRK) : \ - sio_setreg((com), com_cfcr, (com)->cfcr_image &= ~CFCR_SBREAK)) - -static struct speedtab pc98speedtab[] = { /* internal RS232C interface */ - { 0, 0, }, - { 50, 50, }, - { 75, 75, }, - { 150, 150, }, - { 200, 200, }, - { 300, 300, }, - { 600, 600, }, - { 1200, 1200, }, - { 2400, 2400, }, - { 4800, 4800, }, - { 9600, 9600, }, - { 19200, 19200, }, - { 38400, 38400, }, - { 51200, 51200, }, - { 76800, 76800, }, - { 20800, 20800, }, - { 31200, 31200, }, - { 41600, 41600, }, - { 62400, 62400, }, - { -1, -1 } -}; -static struct speedtab pc98fast_speedtab[] = { - { 9600, 0x80 | (DEFAULT_RCLK / (16 * (9600))), }, - { 19200, 0x80 | (DEFAULT_RCLK / (16 * (19200))), }, - { 38400, 0x80 | (DEFAULT_RCLK / (16 * (38400))), }, - { 57600, 0x80 | (DEFAULT_RCLK / (16 * (57600))), }, - { 115200, 0x80 | (DEFAULT_RCLK / (16 * (115200))), }, - { -1, -1 } -}; -static struct speedtab comspeedtab_pio9032b[] = { - { 300, 6, }, - { 600, 5, }, - { 1200, 4, }, - { 2400, 3, }, - { 4800, 2, }, - { 9600, 1, }, - { 19200, 0, }, - { 38400, 7, }, - { -1, -1 } -}; -static struct speedtab comspeedtab_b98_01[] = { - { 75, 11, }, - { 150, 10, }, - { 300, 9, }, - { 600, 8, }, - { 1200, 7, }, - { 2400, 6, }, - { 4800, 5, }, - { 9600, 4, }, - { 19200, 3, }, - { 38400, 2, }, - { 76800, 1, }, - { 153600, 0, }, - { -1, -1 } -}; -static struct speedtab comspeedtab_ind[] = { - { 300, 1536, }, - { 600, 768, }, - { 1200, 384, }, - { 2400, 192, }, - { 4800, 96, }, - { 9600, 48, }, - { 19200, 24, }, - { 38400, 12, }, - { 57600, 8, }, - { 115200, 4, }, - { 153600, 3, }, - { 230400, 2, }, - { 460800, 1, }, - { -1, -1 } -}; - -struct { - char *name; - short port_table[7]; - short irr_mask; - struct speedtab *speedtab; - short check_irq; -} if_8251_type[] = { - /* COM_IF_INTERNAL */ - { " (internal)", {0x30, 0x32, 0x32, 0x33, 0x35, -1, -1}, - -1, pc98speedtab, 1 }, - /* COM_IF_PC9861K_1 */ - { " (PC9861K)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, -1, -1}, - 3, NULL, 1 }, - /* COM_IF_PC9861K_2 */ - { " (PC9861K)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, -1, -1}, - 3, NULL, 1 }, - /* COM_IF_IND_SS_1 */ - { " (IND-SS)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb3, -1}, - 3, comspeedtab_ind, 1 }, - /* COM_IF_IND_SS_2 */ - { " (IND-SS)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xbb, -1}, - 3, comspeedtab_ind, 1 }, - /* COM_IF_PIO9032B_1 */ - { " (PIO9032B)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb8, -1}, - 7, comspeedtab_pio9032b, 1 }, - /* COM_IF_PIO9032B_2 */ - { " (PIO9032B)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xba, -1}, - 7, comspeedtab_pio9032b, 1 }, - /* COM_IF_B98_01_1 */ - { " (B98-01)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xd1, 0xd3}, - 7, comspeedtab_b98_01, 0 }, - /* COM_IF_B98_01_2 */ - { " (B98-01)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xd5, 0xd7}, - 7, comspeedtab_b98_01, 0 }, -}; -#define PC98SIO_data_port(type) (if_8251_type[type].port_table[0]) -#define PC98SIO_cmd_port(type) (if_8251_type[type].port_table[1]) -#define PC98SIO_sts_port(type) (if_8251_type[type].port_table[2]) -#define PC98SIO_in_modem_port(type) (if_8251_type[type].port_table[3]) -#define PC98SIO_intr_ctrl_port(type) (if_8251_type[type].port_table[4]) -#define PC98SIO_baud_rate_port(type) (if_8251_type[type].port_table[5]) -#define PC98SIO_func_port(type) (if_8251_type[type].port_table[6]) - -#define I8251F_data 0x130 -#define I8251F_lsr 0x132 -#define I8251F_msr 0x134 -#define I8251F_iir 0x136 -#define I8251F_fcr 0x138 -#define I8251F_div 0x13a - - -static bus_addr_t port_table_0[] = - {0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007}; -static bus_addr_t port_table_1[] = - {0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e}; -static bus_addr_t port_table_8[] = - {0x000, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700}; -static bus_addr_t port_table_rsa[] = { - 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, - 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007 -}; - -struct { - char *name; - short irr_read; - short irr_write; - bus_addr_t *iat; - bus_size_t iatsz; - u_long rclk; -} if_16550a_type[] = { - /* COM_IF_RSA98 */ - {" (RSA-98)", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK}, - /* COM_IF_NS16550 */ - {"", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK}, - /* COM_IF_SECOND_CCU */ - {"", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK}, - /* COM_IF_MC16550II */ - {" (MC16550II)", -1, 0x1000, port_table_8, IO_COMSIZE, - DEFAULT_RCLK * 4}, - /* COM_IF_MCRS98 */ - {" (MC-RS98)", -1, 0x1000, port_table_8, IO_COMSIZE, DEFAULT_RCLK * 4}, - /* COM_IF_RSB3000 */ - {" (RSB-3000)", 0xbf, -1, port_table_1, IO_COMSIZE, DEFAULT_RCLK * 10}, - /* COM_IF_RSB384 */ - {" (RSB-384)", 0xbf, -1, port_table_1, IO_COMSIZE, DEFAULT_RCLK * 10}, - /* COM_IF_MODEM_CARD */ - {"", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK}, - /* COM_IF_RSA98III */ - {" (RSA-98III)", -1, -1, port_table_rsa, 16, DEFAULT_RCLK * 8}, - /* COM_IF_ESP98 */ - {" (ESP98)", -1, -1, port_table_1, IO_COMSIZE, DEFAULT_RCLK * 4}, -}; -#endif /* PC98 */ - -#ifdef GDB -static Port_t siogdbiobase = 0; -#endif - -#ifdef COM_ESP -#ifdef PC98 - -/* XXX configure this properly. */ -/* XXX quite broken for new-bus. */ -static Port_t likely_com_ports[] = { 0, 0xb0, 0xb1, 0 }; -static Port_t likely_esp_ports[] = { 0xc0d0, 0 }; - -#define ESP98_CMD1 (ESP_CMD1 * 0x100) -#define ESP98_CMD2 (ESP_CMD2 * 0x100) -#define ESP98_STATUS1 (ESP_STATUS1 * 0x100) -#define ESP98_STATUS2 (ESP_STATUS2 * 0x100) - -#else /* PC98 */ - -/* XXX configure this properly. */ -static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; -static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; - -#endif /* PC98 */ -#endif - -/* - * handle sysctl read/write requests for console speed - * - * In addition to setting comdefaultrate for I/O through /dev/console, - * also set the initial and lock values for the /dev/ttyXX device - * if there is one associated with the console. Finally, if the /dev/tty - * device has already been open, change the speed on the open running port - * itself. - */ - -static int -sysctl_machdep_comdefaultrate(SYSCTL_HANDLER_ARGS) -{ - int error, s; - speed_t newspeed; - struct com_s *com; - struct tty *tp; - - newspeed = comdefaultrate; - - error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req); - if (error || !req->newptr) - return (error); - - comdefaultrate = newspeed; - - if (comconsole < 0) /* serial console not selected? */ - return (0); - - com = com_addr(comconsole); - if (com == NULL) - return (ENXIO); - - tp = com->tp; - if (tp == NULL) - return (ENXIO); - - /* - * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX - * (note, the lock rates really are boolean -- if non-zero, disallow - * speed changes) - */ - tp->t_init_in.c_ispeed = tp->t_init_in.c_ospeed = - tp->t_lock_in.c_ispeed = tp->t_lock_in.c_ospeed = - tp->t_init_out.c_ispeed = tp->t_init_out.c_ospeed = - tp->t_lock_out.c_ispeed = tp->t_lock_out.c_ospeed = comdefaultrate; - - if (tp->t_state & TS_ISOPEN) { - tp->t_termios.c_ispeed = - tp->t_termios.c_ospeed = comdefaultrate; - s = spltty(); - error = comparam(tp, &tp->t_termios); - splx(s); - } - return error; -} - -SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW, - 0, 0, sysctl_machdep_comdefaultrate, "I", ""); - -/* - * Unload the driver and clear the table. - * XXX this is mostly wrong. - * XXX TODO: - * This is usually called when the card is ejected, but - * can be caused by a kldunload of a controller driver. - * The idea is to reset the driver's view of the device - * and ensure that any driver entry points such as - * read and write do not hang. - */ -int -siodetach(device_t dev) -{ - struct com_s *com; - - com = (struct com_s *) device_get_softc(dev); - if (com == NULL) { - device_printf(dev, "NULL com in siounload\n"); - return (0); - } - com->gone = TRUE; - if (com->tp) - ttyfree(com->tp); - if (com->irqres) { - bus_teardown_intr(dev, com->irqres, com->cookie); - bus_release_resource(dev, SYS_RES_IRQ, 0, com->irqres); - } - if (com->ioportres) - bus_release_resource(dev, SYS_RES_IOPORT, com->ioportrid, - com->ioportres); - if (com->ibuf != NULL) - free(com->ibuf, M_DEVBUF); -#ifdef PC98 - if (com->obuf1 != NULL) - free(com->obuf1, M_DEVBUF); -#endif - - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - return (0); -} - -int -sioprobe(dev, xrid, rclk, noprobe) - device_t dev; - int xrid; - u_long rclk; - int noprobe; -{ -#if 0 - static bool_t already_init; - device_t xdev; -#endif - struct com_s *com; - u_int divisor; - bool_t failures[10]; - int fn; - device_t idev; - Port_t iobase; - intrmask_t irqmap[4]; - intrmask_t irqs; - u_char mcr_image; - int result; - u_long xirq; - u_int flags = device_get_flags(dev); - int rid; - struct resource *port; -#ifdef PC98 - int tmp; - struct siodev iod; -#endif - -#ifdef PC98 - iod.if_type = GET_IFTYPE(flags); - if ((iod.if_type < 0 || iod.if_type > COM_IF_END1) && - (iod.if_type < 0x10 || iod.if_type > COM_IF_END2)) - return ENXIO; -#endif - - rid = xrid; -#ifdef PC98 - if (IS_8251(iod.if_type)) { - port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, - RF_ACTIVE); - } else if (iod.if_type == COM_IF_MODEM_CARD || - iod.if_type == COM_IF_RSA98III || - isa_get_vendorid(dev)) { - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - if_16550a_type[iod.if_type & 0x0f].iatsz, RF_ACTIVE); - } else { - port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - if_16550a_type[iod.if_type & 0x0f].iat, - if_16550a_type[iod.if_type & 0x0f].iatsz, RF_ACTIVE); - } -#else - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, IO_COMSIZE, RF_ACTIVE); -#endif - if (!port) - return (ENXIO); -#ifdef PC98 - if (!IS_8251(iod.if_type)) { - if (isa_load_resourcev(port, - if_16550a_type[iod.if_type & 0x0f].iat, - if_16550a_type[iod.if_type & 0x0f].iatsz) != 0) { - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - return ENXIO; - } - } -#endif - - com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO); - if (com == NULL) { - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - return (ENOMEM); - } - device_set_softc(dev, com); - com->bst = rman_get_bustag(port); - com->bsh = rman_get_bushandle(port); -#ifdef PC98 - if (!IS_8251(iod.if_type) && rclk == 0) - rclk = if_16550a_type[iod.if_type & 0x0f].rclk; -#else - if (rclk == 0) - rclk = DEFAULT_RCLK; -#endif - com->rclk = rclk; - - while (sio_inited != 2) - if (atomic_cmpset_int(&sio_inited, 0, 1)) { - mtx_init(&sio_lock, sio_driver_name, NULL, - (comconsole != -1) ? - MTX_SPIN | MTX_QUIET : MTX_SPIN); - atomic_store_rel_int(&sio_inited, 2); - } - -#if 0 - /* - * XXX this is broken - when we are first called, there are no - * previously configured IO ports. We could hard code - * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse. - * This code has been doing nothing since the conversion since - * "count" is zero the first time around. - */ - if (!already_init) { - /* - * Turn off MCR_IENABLE for all likely serial ports. An unused - * port with its MCR_IENABLE gate open will inhibit interrupts - * from any used port that shares the interrupt vector. - * XXX the gate enable is elsewhere for some multiports. - */ - device_t *devs; - int count, i, xioport; -#ifdef PC98 - int xiftype; -#endif - - devclass_get_devices(sio_devclass, &devs, &count); -#ifdef PC98 - for (i = 0; i < count; i++) { - xdev = devs[i]; - xioport = bus_get_resource_start(xdev, SYS_RES_IOPORT, 0); - xiftype = GET_IFTYPE(device_get_flags(xdev)); - if (device_is_enabled(xdev) && xioport > 0) { - if (IS_8251(xiftype)) - outb((xioport & 0xff00) | PC98SIO_cmd_port(xiftype & 0x0f), 0xf2); - else - outb(xioport + if_16550a_type[xiftype & 0x0f].iat[com_mcr], 0); - } - } -#else - for (i = 0; i < count; i++) { - xdev = devs[i]; - if (device_is_enabled(xdev) && - bus_get_resource(xdev, SYS_RES_IOPORT, 0, &xioport, - NULL) == 0) - outb(xioport + com_mcr, 0); - } -#endif - free(devs, M_TEMP); - already_init = TRUE; - } -#endif - - if (COM_LLCONSOLE(flags)) { - printf("sio%d: reserved for low-level i/o\n", - device_get_unit(dev)); - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - return (ENXIO); - } - -#ifdef PC98 - DELAY(10); - - /* - * If the port is i8251 UART (internal, B98_01) - */ - if (pc98_check_if_type(dev, &iod) == -1) { - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - return (ENXIO); - } - if (iod.irq > 0) - bus_set_resource(dev, SYS_RES_IRQ, 0, iod.irq, 1); - if (IS_8251(iod.if_type)) { - outb(iod.cmd, 0); - DELAY(10); - outb(iod.cmd, 0); - DELAY(10); - outb(iod.cmd, 0); - DELAY(10); - outb(iod.cmd, CMD8251_RESET); - DELAY(1000); /* for a while...*/ - outb(iod.cmd, 0xf2); /* MODE (dummy) */ - DELAY(10); - outb(iod.cmd, 0x01); /* CMD (dummy) */ - DELAY(1000); /* for a while...*/ - if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) { - result = (ENXIO); - } - if (if_8251_type[iod.if_type & 0x0f].check_irq) { - COM_INT_DISABLE - tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx)); - outb( iod.ctrl, tmp|IEN_TxEMP ); - DELAY(10); - result = isa_irq_pending() ? 0 : ENXIO; - outb( iod.ctrl, tmp ); - COM_INT_ENABLE - } else { - /* - * B98_01 doesn't activate TxEMP interrupt line - * when being reset, so we can't check irq pending. - */ - result = 0; - } - if (epson_machine_id==0x20) { /* XXX */ - result = 0; - } - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - if (result) { - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - } - return result; - } -#endif /* PC98 */ - /* - * If the device is on a multiport card and has an AST/4 - * compatible interrupt control register, initialize this - * register and prepare to leave MCR_IENABLE clear in the mcr. - * Otherwise, prepare to set MCR_IENABLE in the mcr. - * Point idev to the device struct giving the correct id_irq. - * This is the struct for the master device if there is one. - */ - idev = dev; - mcr_image = MCR_IENABLE; -#ifdef COM_MULTIPORT - if (COM_ISMULTIPORT(flags)) { -#ifndef PC98 - Port_t xiobase; - u_long io; -#endif - - idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags)); - if (idev == NULL) { - printf("sio%d: master device %d not configured\n", - device_get_unit(dev), COM_MPMASTER(flags)); - idev = dev; - } -#ifndef PC98 - if (!COM_NOTAST4(flags)) { - if (bus_get_resource(idev, SYS_RES_IOPORT, 0, &io, - NULL) == 0) { - xiobase = io; - if (bus_get_resource(idev, SYS_RES_IRQ, 0, - NULL, NULL) == 0) - outb(xiobase + com_scr, 0x80); - else - outb(xiobase + com_scr, 0); - } - mcr_image = 0; - } -#endif - } -#endif /* COM_MULTIPORT */ - if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) != 0) - mcr_image = 0; - - bzero(failures, sizeof failures); - iobase = rman_get_start(port); - -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) { - mcr_image = 0; - - outb(iobase + rsa_msr, 0x04); - outb(iobase + rsa_frr, 0x00); - if ((inb(iobase + rsa_srr) & 0x36) != 0x36) { - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - return (ENXIO); - } - outb(iobase + rsa_ier, 0x00); - outb(iobase + rsa_frr, 0x00); - outb(iobase + rsa_tivsr, 0x00); - outb(iobase + rsa_tcr, 0x00); - } - - tmp = if_16550a_type[iod.if_type & 0x0f].irr_write; - if (tmp != -1) { - /* MC16550II */ - int irqout; - switch (isa_get_irq(idev)) { - case 3: irqout = 4; break; - case 5: irqout = 5; break; - case 6: irqout = 6; break; - case 12: irqout = 7; break; - default: - printf("sio%d: irq configuration error\n", - device_get_unit(dev)); - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - return (ENXIO); - } - outb((iobase & 0x00ff) | tmp, irqout); - } -#endif - - /* - * We don't want to get actual interrupts, just masked ones. - * Interrupts from this line should already be masked in the ICU, - * but mask them in the processor as well in case there are some - * (misconfigured) shared interrupts. - */ - mtx_lock_spin(&sio_lock); -/* EXTRA DELAY? */ - - /* - * Initialize the speed and the word size and wait long enough to - * drain the maximum of 16 bytes of junk in device output queues. - * The speed is undefined after a master reset and must be set - * before relying on anything related to output. There may be - * junk after a (very fast) soft reboot and (apparently) after - * master reset. - * XXX what about the UART bug avoided by waiting in comparam()? - * We don't want to to wait long enough to drain at 2 bps. - */ - if (iobase == siocniobase) - DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); - else { - sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS); - divisor = siodivisor(rclk, SIO_TEST_SPEED); - sio_setreg(com, com_dlbl, divisor & 0xff); - sio_setreg(com, com_dlbh, divisor >> 8); - sio_setreg(com, com_cfcr, CFCR_8BITS); - DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); - } - - /* - * Enable the interrupt gate and disable device interupts. This - * should leave the device driving the interrupt line low and - * guarantee an edge trigger if an interrupt can be generated. - */ -/* EXTRA DELAY? */ - sio_setreg(com, com_mcr, mcr_image); - sio_setreg(com, com_ier, 0); - DELAY(1000); /* XXX */ - irqmap[0] = isa_irq_pending(); - - /* - * Attempt to set loopback mode so that we can send a null byte - * without annoying any external device. - */ -/* EXTRA DELAY? */ - sio_setreg(com, com_mcr, mcr_image | MCR_LOOPBACK); - - /* - * Attempt to generate an output interrupt. On 8250's, setting - * IER_ETXRDY generates an interrupt independent of the current - * setting and independent of whether the THR is empty. On 16450's, - * setting IER_ETXRDY generates an interrupt independent of the - * current setting. On 16550A's, setting IER_ETXRDY only - * generates an interrupt when IER_ETXRDY is not already set. - */ - sio_setreg(com, com_ier, IER_ETXRDY); -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) - outb(iobase + rsa_ier, 0x04); -#endif - - /* - * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate - * an interrupt. They'd better generate one for actually doing - * output. Loopback may be broken on the same incompatibles but - * it's unlikely to do more than allow the null byte out. - */ - sio_setreg(com, com_data, 0); - if (iobase == siocniobase) - DELAY((1 + 2) * 1000000 / (comdefaultrate / 10)); - else - DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); - - /* - * Turn off loopback mode so that the interrupt gate works again - * (MCR_IENABLE was hidden). This should leave the device driving - * an interrupt line high. It doesn't matter if the interrupt - * line oscillates while we are not looking at it, since interrupts - * are disabled. - */ -/* EXTRA DELAY? */ - sio_setreg(com, com_mcr, mcr_image); - - /* - * It seems my Xircom CBEM56G Cardbus modem wants to be reset - * to 8 bits *again*, or else probe test 0 will fail. - * gwk@sgi.com, 4/19/2001 - */ - sio_setreg(com, com_cfcr, CFCR_8BITS); - - /* - * Some PCMCIA cards (Palido 321s, DC-1S, ...) have the "TXRDY bug", - * so we probe for a buggy IIR_TXRDY implementation even in the - * noprobe case. We don't probe for it in the !noprobe case because - * noprobe is always set for PCMCIA cards and the problem is not - * known to affect any other cards. - */ - if (noprobe) { - /* Read IIR a few times. */ - for (fn = 0; fn < 2; fn ++) { - DELAY(10000); - failures[6] = sio_getreg(com, com_iir); - } - - /* IIR_TXRDY should be clear. Is it? */ - result = 0; - if (failures[6] & IIR_TXRDY) { - /* - * No. We seem to have the bug. Does our fix for - * it work? - */ - sio_setreg(com, com_ier, 0); - if (sio_getreg(com, com_iir) & IIR_NOPEND) { - /* Yes. We discovered the TXRDY bug! */ - SET_FLAG(dev, COM_C_IIR_TXRDYBUG); - } else { - /* No. Just fail. XXX */ - result = ENXIO; - sio_setreg(com, com_mcr, 0); - } - } else { - /* Yes. No bug. */ - CLR_FLAG(dev, COM_C_IIR_TXRDYBUG); - } - sio_setreg(com, com_ier, 0); - sio_setreg(com, com_cfcr, CFCR_8BITS); - mtx_unlock_spin(&sio_lock); - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - if (iobase == siocniobase) - result = 0; - if (result != 0) { - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - } - return (result); - } - - /* - * Check that - * o the CFCR, IER and MCR in UART hold the values written to them - * (the values happen to be all distinct - this is good for - * avoiding false positive tests from bus echoes). - * o an output interrupt is generated and its vector is correct. - * o the interrupt goes away when the IIR in the UART is read. - */ -/* EXTRA DELAY? */ - failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS; - failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY; - failures[2] = sio_getreg(com, com_mcr) - mcr_image; - DELAY(10000); /* Some internal modems need this time */ - irqmap[1] = isa_irq_pending(); - failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY; -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) - inb(iobase + rsa_srr); -#endif - DELAY(1000); /* XXX */ - irqmap[2] = isa_irq_pending(); - failures[6] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND; -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) - inb(iobase + rsa_srr); -#endif - - /* - * Turn off all device interrupts and check that they go off properly. - * Leave MCR_IENABLE alone. For ports without a master port, it gates - * the OUT2 output of the UART to - * the ICU input. Closing the gate would give a floating ICU input - * (unless there is another device driving it) and spurious interrupts. - * (On the system that this was first tested on, the input floats high - * and gives a (masked) interrupt as soon as the gate is closed.) - */ - sio_setreg(com, com_ier, 0); - sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ - failures[7] = sio_getreg(com, com_ier); -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) - outb(iobase + rsa_ier, 0x00); -#endif - DELAY(1000); /* XXX */ - irqmap[3] = isa_irq_pending(); - failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND; -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) { - inb(iobase + rsa_srr); - outb(iobase + rsa_frr, 0x00); - } -#endif - - mtx_unlock_spin(&sio_lock); - - irqs = irqmap[1] & ~irqmap[0]; - if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 && - ((1 << xirq) & irqs) == 0) { - printf( - "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n", - device_get_unit(dev), xirq, irqs); - printf( - "sio%d: port may not be enabled\n", - device_get_unit(dev)); - } - if (bootverbose) - printf("sio%d: irq maps: %#x %#x %#x %#x\n", - device_get_unit(dev), - irqmap[0], irqmap[1], irqmap[2], irqmap[3]); - - result = 0; - for (fn = 0; fn < sizeof failures; ++fn) - if (failures[fn]) { - sio_setreg(com, com_mcr, 0); - result = ENXIO; - if (bootverbose) { - printf("sio%d: probe failed test(s):", - device_get_unit(dev)); - for (fn = 0; fn < sizeof failures; ++fn) - if (failures[fn]) - printf(" %d", fn); - printf("\n"); - } - break; - } - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - if (iobase == siocniobase) - result = 0; - if (result != 0) { - device_set_softc(dev, NULL); - free(com, M_DEVBUF); - } - return (result); -} - -#ifdef COM_ESP -static int -espattach(com, esp_port) - struct com_s *com; - Port_t esp_port; -{ - u_char dips; - u_char val; - - /* - * Check the ESP-specific I/O port to see if we're an ESP - * card. If not, return failure immediately. - */ - if ((inb(esp_port) & 0xf3) == 0) { - printf(" port 0x%x is not an ESP board?\n", esp_port); - return (0); - } - - /* - * We've got something that claims to be a Hayes ESP card. - * Let's hope so. - */ - - /* Get the dip-switch configuration */ -#ifdef PC98 - outb(esp_port + ESP98_CMD1, ESP_GETDIPS); - dips = inb(esp_port + ESP98_STATUS1); -#else - outb(esp_port + ESP_CMD1, ESP_GETDIPS); - dips = inb(esp_port + ESP_STATUS1); -#endif - - /* - * Bits 0,1 of dips say which COM port we are. - */ -#ifdef PC98 - if ((rman_get_start(com->ioportres) & 0xff) == - likely_com_ports[dips & 0x03]) -#else - if (rman_get_start(com->ioportres) == likely_com_ports[dips & 0x03]) -#endif - printf(" : ESP"); - else { - printf(" esp_port has com %d\n", dips & 0x03); - return (0); - } - - /* - * Check for ESP version 2.0 or later: bits 4,5,6 = 010. - */ -#ifdef PC98 - outb(esp_port + ESP98_CMD1, ESP_GETTEST); - val = inb(esp_port + ESP98_STATUS1); /* clear reg 1 */ - val = inb(esp_port + ESP98_STATUS2); -#else - outb(esp_port + ESP_CMD1, ESP_GETTEST); - val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */ - val = inb(esp_port + ESP_STATUS2); -#endif - if ((val & 0x70) < 0x20) { - printf("-old (%o)", val & 0x70); - return (0); - } - - /* - * Check for ability to emulate 16550: bit 7 == 1 - */ - if ((dips & 0x80) == 0) { - printf(" slave"); - return (0); - } - - /* - * Okay, we seem to be a Hayes ESP card. Whee. - */ - com->esp = TRUE; - com->esp_port = esp_port; - return (1); -} -#endif /* COM_ESP */ - -int -sioattach(dev, xrid, rclk) - device_t dev; - int xrid; - u_long rclk; -{ - struct com_s *com; -#ifdef COM_ESP - Port_t *espp; -#endif - Port_t iobase; - int unit; - u_int flags; - int rid; - struct resource *port; - int ret; - int error; - struct tty *tp; -#ifdef PC98 - u_char *obuf; - u_long obufsize; - int if_type = GET_IFTYPE(device_get_flags(dev)); -#endif - - rid = xrid; -#ifdef PC98 - if (IS_8251(if_type)) { - port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, - RF_ACTIVE); - } else if (if_type == COM_IF_MODEM_CARD || - if_type == COM_IF_RSA98III || - isa_get_vendorid(dev)) { - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - if_16550a_type[if_type & 0x0f].iatsz, RF_ACTIVE); - } else { - port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, - if_16550a_type[if_type & 0x0f].iat, - if_16550a_type[if_type & 0x0f].iatsz, RF_ACTIVE); - } -#else - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, IO_COMSIZE, RF_ACTIVE); -#endif - if (!port) - return (ENXIO); -#ifdef PC98 - if (!IS_8251(if_type)) { - if (isa_load_resourcev(port, - if_16550a_type[if_type & 0x0f].iat, - if_16550a_type[if_type & 0x0f].iatsz) != 0) { - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - return ENXIO; - } - } -#endif - - iobase = rman_get_start(port); - unit = device_get_unit(dev); - com = device_get_softc(dev); - flags = device_get_flags(dev); - - if (unit >= sio_numunits) - sio_numunits = unit + 1; - -#ifdef PC98 - obufsize = 256; - if (if_type == COM_IF_RSA98III) - obufsize = 2048; - if ((obuf = malloc(obufsize * 2, M_DEVBUF, M_NOWAIT)) == NULL) { - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - return ENXIO; - } - bzero(obuf, obufsize * 2); -#endif - - /* - * sioprobe() has initialized the device registers as follows: - * o cfcr = CFCR_8BITS. - * It is most important that CFCR_DLAB is off, so that the - * data port is not hidden when we enable interrupts. - * o ier = 0. - * Interrupts are only enabled when the line is open. - * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible - * interrupt control register or the config specifies no irq. - * Keeping MCR_DTR and MCR_RTS off might stop the external - * device from sending before we are ready. - */ - bzero(com, sizeof *com); - com->unit = unit; - com->ioportres = port; - com->ioportrid = rid; - com->bst = rman_get_bustag(port); - com->bsh = rman_get_bushandle(port); - com->cfcr_image = CFCR_8BITS; - com->loses_outints = COM_LOSESOUTINTS(flags) != 0; - com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0; - com->tx_fifo_size = 1; -#ifdef PC98 - com->obufsize = obufsize; - com->obuf1 = obuf; - com->obuf2 = obuf + obufsize; -#endif - com->obufs[0].l_head = com->obuf1; - com->obufs[1].l_head = com->obuf2; - -#ifdef PC98 - com->pc98_if_type = if_type; - - if (IS_8251(if_type)) { - pc98_set_ioport(com); - - if (if_type == COM_IF_INTERNAL && pc98_check_8251fifo()) { - com->pc98_8251fifo = 1; - com->pc98_8251fifo_enable = 0; - } - } else { - bus_addr_t *iat = if_16550a_type[if_type & 0x0f].iat; - - com->data_port = iobase + iat[com_data]; - com->int_ctl_port = iobase + iat[com_ier]; - com->int_id_port = iobase + iat[com_iir]; - com->modem_ctl_port = iobase + iat[com_mcr]; - com->mcr_image = inb(com->modem_ctl_port); - com->line_status_port = iobase + iat[com_lsr]; - com->modem_status_port = iobase + iat[com_msr]; - } -#else /* not PC98 */ - com->data_port = iobase + com_data; - com->int_ctl_port = iobase + com_ier; - com->int_id_port = iobase + com_iir; - com->modem_ctl_port = iobase + com_mcr; - com->mcr_image = inb(com->modem_ctl_port); - com->line_status_port = iobase + com_lsr; - com->modem_status_port = iobase + com_msr; -#endif - - tp = com->tp = ttyalloc(); - tp->t_oproc = comstart; - tp->t_param = comparam; - tp->t_stop = comstop; - tp->t_modem = commodem; - tp->t_break = combreak; - tp->t_close = comclose; - tp->t_open = comopen; - tp->t_sc = com; - -#ifdef PC98 - if (!IS_8251(if_type) && rclk == 0) - rclk = if_16550a_type[if_type & 0x0f].rclk; -#else - if (rclk == 0) - rclk = DEFAULT_RCLK; -#endif - com->rclk = rclk; - - if (unit == comconsole) - ttyconsolemode(tp, comdefaultrate); - error = siosetwater(com, tp->t_init_in.c_ispeed); - mtx_unlock_spin(&sio_lock); - if (error) { - /* - * Leave i/o resources allocated if this is a `cn'-level - * console, so that other devices can't snarf them. - */ - if (iobase != siocniobase) - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); - return (ENOMEM); - } - - /* attempt to determine UART type */ - printf("sio%d: type", unit); - -#ifndef PC98 - if (!COM_ISMULTIPORT(flags) && - !COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) { - u_char scr; - u_char scr1; - u_char scr2; - - scr = sio_getreg(com, com_scr); - sio_setreg(com, com_scr, 0xa5); - scr1 = sio_getreg(com, com_scr); - sio_setreg(com, com_scr, 0x5a); - scr2 = sio_getreg(com, com_scr); - sio_setreg(com, com_scr, scr); - if (scr1 != 0xa5 || scr2 != 0x5a) { - printf(" 8250 or not responding"); - goto determined_type; - } - } -#endif /* !PC98 */ -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if (com->pc98_8251fifo && !COM_NOFIFO(flags)) - com->tx_fifo_size = 16; - com_int_TxRx_disable( com ); - com_cflag_and_speed_set( com, tp->t_init_in.c_cflag, comdefaultrate ); - com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); - com_send_break_off( com ); - - if (com->pc98_if_type == COM_IF_INTERNAL) { - printf(" (internal%s%s)", - com->pc98_8251fifo ? " fifo" : "", - PC98SIO_baud_rate_port(com->pc98_if_type) != -1 ? - " v-fast" : ""); - } else { - printf(" 8251%s", if_8251_type[com->pc98_if_type & 0x0f].name); - } - } else { -#endif /* PC98 */ - sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); - DELAY(100); - switch (inb(com->int_id_port) & IIR_FIFO_MASK) { - case FIFO_RX_LOW: - printf(" 16450"); - break; - case FIFO_RX_MEDL: - printf(" 16450?"); - break; - case FIFO_RX_MEDH: - printf(" 16550?"); - break; - case FIFO_RX_HIGH: - if (COM_NOFIFO(flags)) { - printf(" 16550A fifo disabled"); - break; - } - com->hasfifo = TRUE; -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) { - com->tx_fifo_size = 2048; - com->rsabase = iobase; - outb(com->rsabase + rsa_ier, 0x00); - outb(com->rsabase + rsa_frr, 0x00); - } -#else - if (COM_ST16650A(flags)) { - printf(" ST16650A"); - com->st16650a = TRUE; - com->tx_fifo_size = 32; - break; - } - if (COM_TI16754(flags)) { - printf(" TI16754"); - com->tx_fifo_size = 64; - break; - } -#endif - printf(" 16550A"); -#ifdef COM_ESP -#ifdef PC98 - if (com->pc98_if_type == COM_IF_ESP98) -#endif - for (espp = likely_esp_ports; *espp != 0; espp++) - if (espattach(com, *espp)) { - com->tx_fifo_size = 1024; - break; - } - if (com->esp) - break; -#endif -#ifdef PC98 - com->tx_fifo_size = 16; -#else - com->tx_fifo_size = COM_FIFOSIZE(flags); - if (com->tx_fifo_size == 0) - com->tx_fifo_size = 16; - else - printf(" lookalike with %u bytes FIFO", - com->tx_fifo_size); -#endif - break; - } - -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSB3000) { - /* Set RSB-2000/3000 Extended Buffer mode. */ - u_char lcr; - lcr = sio_getreg(com, com_cfcr); - sio_setreg(com, com_cfcr, lcr | CFCR_DLAB); - sio_setreg(com, com_emr, EMR_EXBUFF | EMR_EFMODE); - sio_setreg(com, com_cfcr, lcr); - } -#endif - -#ifdef COM_ESP - if (com->esp) { - /* - * Set 16550 compatibility mode. - * We don't use the ESP_MODE_SCALE bit to increase the - * fifo trigger levels because we can't handle large - * bursts of input. - * XXX flow control should be set in comparam(), not here. - */ -#ifdef PC98 - outb(com->esp_port + ESP98_CMD1, ESP_SETMODE); - outb(com->esp_port + ESP98_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); -#else - outb(com->esp_port + ESP_CMD1, ESP_SETMODE); - outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); -#endif - - /* Set RTS/CTS flow control. */ -#ifdef PC98 - outb(com->esp_port + ESP98_CMD1, ESP_SETFLOWTYPE); - outb(com->esp_port + ESP98_CMD2, ESP_FLOW_RTS); - outb(com->esp_port + ESP98_CMD2, ESP_FLOW_CTS); -#else - outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); - outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS); - outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS); -#endif - - /* Set flow-control levels. */ -#ifdef PC98 - outb(com->esp_port + ESP98_CMD1, ESP_SETRXFLOW); - outb(com->esp_port + ESP98_CMD2, HIBYTE(768)); - outb(com->esp_port + ESP98_CMD2, LOBYTE(768)); - outb(com->esp_port + ESP98_CMD2, HIBYTE(512)); - outb(com->esp_port + ESP98_CMD2, LOBYTE(512)); -#else - outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW); - outb(com->esp_port + ESP_CMD2, HIBYTE(768)); - outb(com->esp_port + ESP_CMD2, LOBYTE(768)); - outb(com->esp_port + ESP_CMD2, HIBYTE(512)); - outb(com->esp_port + ESP_CMD2, LOBYTE(512)); -#endif - -#ifdef PC98 - /* Set UART clock prescaler. */ - outb(com->esp_port + ESP98_CMD1, ESP_SETCLOCK); - outb(com->esp_port + ESP98_CMD2, 2); /* 4 times */ -#endif - } -#endif /* COM_ESP */ - sio_setreg(com, com_fifo, 0); -#ifdef PC98 - printf("%s", if_16550a_type[com->pc98_if_type & 0x0f].name); -#else -determined_type: ; -#endif - -#ifdef COM_MULTIPORT - if (COM_ISMULTIPORT(flags)) { - device_t masterdev; - - com->multiport = TRUE; - printf(" (multiport"); - if (unit == COM_MPMASTER(flags)) - printf(" master"); - printf(")"); - masterdev = devclass_get_device(sio_devclass, - COM_MPMASTER(flags)); - com->no_irq = (masterdev == NULL || bus_get_resource(masterdev, - SYS_RES_IRQ, 0, NULL, NULL) != 0); - } -#endif /* COM_MULTIPORT */ -#ifdef PC98 - } -#endif - if (unit == comconsole) - printf(", console"); - if (COM_IIR_TXRDYBUG(flags)) - printf(" with a buggy IIR_TXRDY implementation"); - printf("\n"); - - if (sio_fast_ih == NULL) { - swi_add(&tty_ithd, "sio", siopoll, NULL, SWI_TTY, 0, - &sio_fast_ih); - swi_add(&clk_ithd, "sio", siopoll, NULL, SWI_CLOCK, 0, - &sio_slow_ih); - } - - com->flags = flags; - com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; - tp->t_pps = &com->pps; - - if (COM_PPSCTS(flags)) - com->pps_bit = MSR_CTS; - else - com->pps_bit = MSR_DCD; - pps_init(&com->pps); - - rid = 0; - com->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); - if (com->irqres) { - ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres, - INTR_TYPE_TTY | INTR_FAST, - siointr, com, &com->cookie); - if (ret) { - ret = BUS_SETUP_INTR(device_get_parent(dev), dev, - com->irqres, INTR_TYPE_TTY, - siointr, com, &com->cookie); - if (ret == 0) - device_printf(dev, "unable to activate interrupt in fast mode - using normal mode\n"); - } - if (ret) - device_printf(dev, "could not activate interrupt\n"); -#if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \ - defined(ALT_BREAK_TO_DEBUGGER)) - /* - * Enable interrupts for early break-to-debugger support - * on the console. - */ - if (ret == 0 && unit == comconsole) - outb(siocniobase + com_ier, IER_ERXRDY | IER_ERLS | - IER_EMSC); -#endif - } - - /* We're ready, open the doors... */ - ttycreate(tp, NULL, unit, MINOR_CALLOUT, "d%r", unit); - - return (0); -} - -static int -comopen(struct tty *tp, struct cdev *dev) -{ - struct com_s *com; - int i; - - com = tp->t_sc; - com->poll = com->no_irq; - com->poll_output = com->loses_outints; -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS); - pc98_msrint_start(dev); - if (com->pc98_8251fifo) { - com->pc98_8251fifo_enable = 1; - outb(I8251F_fcr, CTRL8251F_ENABLE | - CTRL8251F_XMT_RST | CTRL8251F_RCV_RST); - } - } -#endif - if (com->hasfifo) { - /* - * (Re)enable and drain fifos. - * - * Certain SMC chips cause problems if the fifos - * are enabled while input is ready. Turn off the - * fifo if necessary to clear the input. We test - * the input ready bit after enabling the fifos - * since we've already enabled them in comparam() - * and to handle races between enabling and fresh - * input. - */ - for (i = 0; i < 500; i++) { - sio_setreg(com, com_fifo, - FIFO_RCV_RST | FIFO_XMT_RST - | com->fifo_image); -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) - outb(com->rsabase + rsa_frr , 0x00); -#endif - /* - * XXX the delays are for superstitious - * historical reasons. It must be less than - * the character time at the maximum - * supported speed (87 usec at 115200 bps - * 8N1). Otherwise we might loop endlessly - * if data is streaming in. We used to use - * delays of 100. That usually worked - * because DELAY(100) used to usually delay - * for about 85 usec instead of 100. - */ - DELAY(50); -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III ? - !(inb(com->rsabase + rsa_srr) & 0x08) : - !(inb(com->line_status_port) & LSR_RXRDY)) - break; -#else - if (!(inb(com->line_status_port) & LSR_RXRDY)) - break; -#endif - sio_setreg(com, com_fifo, 0); - DELAY(50); - (void) inb(com->data_port); - } - if (i == 500) - return (EIO); - } - - mtx_lock_spin(&sio_lock); -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - com_tiocm_bis(com, TIOCM_LE); - com->pc98_prev_modem_status = pc98_get_modem_status(com); - com_int_Rx_enable(com); - } else { -#endif - (void) inb(com->line_status_port); - (void) inb(com->data_port); - com->prev_modem_status = com->last_modem_status - = inb(com->modem_status_port); - outb(com->int_ctl_port, - IER_ERXRDY | IER_ERLS | IER_EMSC - | (COM_IIR_TXRDYBUG(com->flags) ? 0 : IER_ETXRDY)); -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) { - outb(com->rsabase + rsa_ier, 0x1d); - outb(com->int_ctl_port, IER_ERLS | IER_EMSC); - } -#endif -#ifdef PC98 - } -#endif - mtx_unlock_spin(&sio_lock); - siosettimeout(); - /* XXX: should be generic ? */ -#ifdef PC98 - if ((IS_8251(com->pc98_if_type) && - (pc98_get_modem_status(com) & TIOCM_CAR)) || - (!IS_8251(com->pc98_if_type) && - (com->prev_modem_status & MSR_DCD)) || - ISCALLOUT(dev)) - ttyld_modem(tp, 1); -#else - if (com->prev_modem_status & MSR_DCD || ISCALLOUT(dev)) - ttyld_modem(tp, 1); -#endif - return (0); -} - -static void -comclose(tp) - struct tty *tp; -{ - int s; - struct com_s *com; - - s = spltty(); - com = tp->t_sc; - com->poll = FALSE; - com->poll_output = FALSE; -#ifdef PC98 - com_send_break_off(com); -#else - sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); -#endif - -#if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \ - defined(ALT_BREAK_TO_DEBUGGER)) - /* - * Leave interrupts enabled and don't clear DTR if this is the - * console. This allows us to detect break-to-debugger events - * while the console device is closed. - */ - if (com->unit != comconsole) -#endif - { -#ifdef PC98 - int tmp; - if (IS_8251(com->pc98_if_type)) - com_int_TxRx_disable(com); - else - sio_setreg(com, com_ier, 0); - if (com->pc98_if_type == COM_IF_RSA98III) - outb(com->rsabase + rsa_ier, 0x00); - if (IS_8251(com->pc98_if_type)) - tmp = pc98_get_modem_status(com) & TIOCM_CAR; - else - tmp = com->prev_modem_status & MSR_DCD; -#else - sio_setreg(com, com_ier, 0); -#endif - if (tp->t_cflag & HUPCL - /* - * XXX we will miss any carrier drop between here and the - * next open. Perhaps we should watch DCD even when the - * port is closed; it is not sufficient to check it at - * the next open because it might go up and down while - * we're not watching. - */ - || (!tp->t_actout -#ifdef PC98 - && !(tmp) -#else - && !(com->prev_modem_status & MSR_DCD) -#endif - && !(tp->t_init_in.c_cflag & CLOCAL)) - || !(tp->t_state & TS_ISOPEN)) { -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); - else -#endif - (void)commodem(tp, 0, SER_DTR); - ttydtrwaitstart(tp); - } -#ifdef PC98 - else { - if (IS_8251(com->pc98_if_type)) - com_tiocm_bic(com, TIOCM_LE); - } -#endif - } -#ifdef PC98 - if (com->pc98_8251fifo) { - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, CTRL8251F_XMT_RST | CTRL8251F_RCV_RST); - com->pc98_8251fifo_enable = 0; - } -#endif - if (com->hasfifo) { - /* - * Disable fifos so that they are off after controlled - * reboots. Some BIOSes fail to detect 16550s when the - * fifos are enabled. - */ - sio_setreg(com, com_fifo, 0); - } - tp->t_actout = FALSE; - wakeup(&tp->t_actout); - wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ - siosettimeout(); - splx(s); -} - -static void -siobusycheck(chan) - void *chan; -{ - struct com_s *com; - int s; - - com = (struct com_s *)chan; - - /* - * Clear TS_BUSY if low-level output is complete. - * spl locking is sufficient because siointr1() does not set CS_BUSY. - * If siointr1() clears CS_BUSY after we look at it, then we'll get - * called again. Reading the line status port outside of siointr1() - * is safe because CS_BUSY is clear so there are no output interrupts - * to lose. - */ - s = spltty(); - if (com->state & CS_BUSY) - com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ -#ifdef PC98 - else if ((IS_8251(com->pc98_if_type) && - ((com->pc98_8251fifo_enable && - (inb(I8251F_lsr) & (STS8251F_TxRDY | STS8251F_TxEMP)) - == (STS8251F_TxRDY | STS8251F_TxEMP)) || - (!com->pc98_8251fifo_enable && - (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP)) - == (STS8251_TxRDY | STS8251_TxEMP)))) || - ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) - == (LSR_TSRE | LSR_TXRDY))) { -#else - else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) - == (LSR_TSRE | LSR_TXRDY)) { -#endif - com->tp->t_state &= ~TS_BUSY; - ttwwakeup(com->tp); - com->extra_state &= ~CSE_BUSYCHECK; - } else - timeout(siobusycheck, com, hz / 100); - splx(s); -} - -static u_int -siodivisor(rclk, speed) - u_long rclk; - speed_t speed; -{ - long actual_speed; - u_int divisor; - int error; - - if (speed == 0) - return (0); -#if UINT_MAX > (ULONG_MAX - 1) / 8 - if (speed > (ULONG_MAX - 1) / 8) - return (0); -#endif - divisor = (rclk / (8UL * speed) + 1) / 2; - if (divisor == 0 || divisor >= 65536) - return (0); - actual_speed = rclk / (16UL * divisor); - - /* 10 times error in percent: */ - error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2; - - /* 3.0% maximum error tolerance: */ - if (error < -30 || error > 30) - return (0); - - return (divisor); -} - -/* - * Call this function with the sio_lock mutex held. It will return with the - * lock still held. - */ -static void -sioinput(com) - struct com_s *com; -{ - u_char *buf; - int incc; - u_char line_status; - int recv_data; - struct tty *tp; - - buf = com->ibuf; - tp = com->tp; - if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) { - com_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - return; - } - if (tp->t_state & TS_CAN_BYPASS_L_RINT) { - /* - * Avoid the grotesquely inefficient lineswitch routine - * (ttyinput) in "raw" mode. It usually takes about 450 - * instructions (that's without canonical processing or echo!). - * slinput is reasonably fast (usually 40 instructions plus - * call overhead). - */ - do { - /* - * This may look odd, but it is using save-and-enable - * semantics instead of the save-and-disable semantics - * that are used everywhere else. - */ - mtx_unlock_spin(&sio_lock); - incc = com->iptr - buf; - if (tp->t_rawq.c_cc + incc > tp->t_ihiwat - && (com->state & CS_RTS_IFLOW - || tp->t_iflag & IXOFF) - && !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - com->delta_error_counts[CE_TTY_BUF_OVERFLOW] - += b_to_q((char *)buf, incc, &tp->t_rawq); - buf += incc; - tk_nin += incc; - tk_rawcc += incc; - tp->t_rawcc += incc; - ttwakeup(tp); - if (tp->t_state & TS_TTSTOP - && (tp->t_iflag & IXANY - || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { - tp->t_state &= ~TS_TTSTOP; - tp->t_lflag &= ~FLUSHO; - comstart(tp); - } - mtx_lock_spin(&sio_lock); - } while (buf < com->iptr); - } else { - do { - /* - * This may look odd, but it is using save-and-enable - * semantics instead of the save-and-disable semantics - * that are used everywhere else. - */ - mtx_unlock_spin(&sio_lock); - line_status = buf[com->ierroff]; - recv_data = *buf++; - if (line_status - & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { - if (line_status & LSR_BI) - recv_data |= TTY_BI; - if (line_status & LSR_FE) - recv_data |= TTY_FE; - if (line_status & LSR_OE) - recv_data |= TTY_OE; - if (line_status & LSR_PE) - recv_data |= TTY_PE; - } - ttyld_rint(tp, recv_data); - mtx_lock_spin(&sio_lock); - } while (buf < com->iptr); - } - com_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - - /* - * There is now room for another low-level buffer full of input, - * so enable RTS if it is now disabled and there is room in the - * high-level buffer. - */ -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if ((com->state & CS_RTS_IFLOW) && - !(com_tiocm_get(com) & TIOCM_RTS) && - !(tp->t_state & TS_TBLOCK)) - com_tiocm_bis(com, TIOCM_RTS); - } else { - if ((com->state & CS_RTS_IFLOW) && - !(com->mcr_image & MCR_RTS) && - !(tp->t_state & TS_TBLOCK)) - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); - } -#else - if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) && - !(tp->t_state & TS_TBLOCK)) - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); -#endif -} - -static void -siointr(arg) - void *arg; -{ - struct com_s *com; -#if defined(PC98) && defined(COM_MULTIPORT) - u_char rsa_buf_status; -#endif - -#ifndef COM_MULTIPORT - com = (struct com_s *)arg; - - mtx_lock_spin(&sio_lock); - siointr1(com); - mtx_unlock_spin(&sio_lock); -#else /* COM_MULTIPORT */ - bool_t possibly_more_intrs; - int unit; - - /* - * Loop until there is no activity on any port. This is necessary - * to get an interrupt edge more than to avoid another interrupt. - * If the IRQ signal is just an OR of the IRQ signals from several - * devices, then the edge from one may be lost because another is - * on. - */ - mtx_lock_spin(&sio_lock); - do { - possibly_more_intrs = FALSE; - for (unit = 0; unit < sio_numunits; ++unit) { - com = com_addr(unit); - /* - * XXX COM_LOCK(); - * would it work here, or be counter-productive? - */ -#ifdef PC98 - if (com != NULL - && !com->gone - && IS_8251(com->pc98_if_type)) { - siointr1(com); - } else if (com != NULL - && !com->gone - && com->pc98_if_type == COM_IF_RSA98III) { - rsa_buf_status = - inb(com->rsabase + rsa_srr) & 0xc9; - if ((rsa_buf_status & 0xc8) - || !(rsa_buf_status & 0x01)) { - siointr1(com); - if (rsa_buf_status != - (inb(com->rsabase + rsa_srr) & 0xc9)) - possibly_more_intrs = TRUE; - } - } else -#endif - if (com != NULL - && !com->gone - && (inb(com->int_id_port) & IIR_IMASK) - != IIR_NOPEND) { - siointr1(com); - possibly_more_intrs = TRUE; - } - /* XXX COM_UNLOCK(); */ - } - } while (possibly_more_intrs); - mtx_unlock_spin(&sio_lock); -#endif /* COM_MULTIPORT */ -} - -static struct timespec siots[8]; -static int siotso; -static int volatile siotsunit = -1; - -static int -sysctl_siots(SYSCTL_HANDLER_ARGS) -{ - char buf[128]; - long long delta; - size_t len; - int error, i, tso; - - for (i = 1, tso = siotso; i < tso; i++) { - delta = (long long)(siots[i].tv_sec - siots[i - 1].tv_sec) * - 1000000000 + - (siots[i].tv_nsec - siots[i - 1].tv_nsec); - len = sprintf(buf, "%lld\n", delta); - if (delta >= 110000) - len += sprintf(buf + len - 1, ": *** %ld.%09ld\n", - (long)siots[i].tv_sec, siots[i].tv_nsec) - 1; - if (i == tso - 1) - buf[len - 1] = '\0'; - error = SYSCTL_OUT(req, buf, len); - if (error != 0) - return (error); - uio_yield(); - } - return (0); -} - -SYSCTL_PROC(_machdep, OID_AUTO, siots, CTLTYPE_STRING | CTLFLAG_RD, - 0, 0, sysctl_siots, "A", "sio timestamps"); - -static void -siointr1(com) - struct com_s *com; -{ - u_char int_ctl; - u_char int_ctl_new; - u_char line_status; - u_char modem_status; - u_char *ioptr; - u_char recv_data; - -#ifdef PC98 - u_char tmp = 0; - u_char rsa_buf_status = 0; - int rsa_tx_fifo_size = 0; -#endif /* PC98 */ - - if (COM_IIR_TXRDYBUG(com->flags)) { - int_ctl = inb(com->int_ctl_port); - int_ctl_new = int_ctl; - } else { - int_ctl = 0; - int_ctl_new = 0; - } - - while (!com->gone) { -#ifdef PC98 -status_read:; - if (IS_8251(com->pc98_if_type)) { - if (com->pc98_8251fifo_enable) - tmp = inb(I8251F_lsr); - else - tmp = inb(com->sts_port); -more_intr: - line_status = 0; - if (com->pc98_8251fifo_enable) { - if (tmp & STS8251F_TxRDY) line_status |= LSR_TXRDY; - if (tmp & STS8251F_RxRDY) line_status |= LSR_RXRDY; - if (tmp & STS8251F_TxEMP) line_status |= LSR_TSRE; - if (tmp & STS8251F_PE) line_status |= LSR_PE; - if (tmp & STS8251F_OE) line_status |= LSR_OE; - if (tmp & STS8251F_BD_SD) line_status |= LSR_BI; - } else { - if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; - if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; - if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; - if (tmp & STS8251_PE) line_status |= LSR_PE; - if (tmp & STS8251_OE) line_status |= LSR_OE; - if (tmp & STS8251_FE) line_status |= LSR_FE; - if (tmp & STS8251_BD_SD) line_status |= LSR_BI; - } - } else { -#endif /* PC98 */ - if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) { - modem_status = inb(com->modem_status_port); - if ((modem_status ^ com->last_modem_status) & - com->pps_bit) { - pps_capture(&com->pps); - pps_event(&com->pps, - (modem_status & com->pps_bit) ? - PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); - } - } - line_status = inb(com->line_status_port); -#ifdef PC98 - } - if (com->pc98_if_type == COM_IF_RSA98III) - rsa_buf_status = inb(com->rsabase + rsa_srr); -#endif /* PC98 */ - - /* input event? (check first to help avoid overruns) */ -#ifndef PC98 - while (line_status & LSR_RCV_MASK) { -#else - while ((line_status & LSR_RCV_MASK) - || (com->pc98_if_type == COM_IF_RSA98III - && (rsa_buf_status & 0x08))) { -#endif /* PC98 */ - /* break/unnattached error bits or real input? */ -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if (com->pc98_8251fifo_enable) { - recv_data = inb(I8251F_data); - if (tmp & (STS8251F_PE | STS8251F_OE | - STS8251F_BD_SD)) { - pc98_i8251_or_cmd(com, CMD8251_ER); - recv_data = 0; - } - } else { - recv_data = inb(com->data_port); - if (tmp & (STS8251_PE | STS8251_OE | - STS8251_FE | STS8251_BD_SD)) { - pc98_i8251_or_cmd(com, CMD8251_ER); - recv_data = 0; - } - } - } else if (com->pc98_if_type == COM_IF_RSA98III) { - if (!(rsa_buf_status & 0x08)) - recv_data = 0; - else - recv_data = inb(com->data_port); - } else -#endif - if (!(line_status & LSR_RXRDY)) - recv_data = 0; - else - recv_data = inb(com->data_port); -#ifdef KDB -#ifdef ALT_BREAK_TO_DEBUGGER - if (com->unit == comconsole && - kdb_alt_break(recv_data, &com->alt_brk_state) != 0) - kdb_enter("Break sequence on console"); -#endif /* ALT_BREAK_TO_DEBUGGER */ -#endif /* KDB */ - if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { - /* - * Don't store BI if IGNBRK or FE/PE if IGNPAR. - * Otherwise, push the work to a higher level - * (to handle PARMRK) if we're bypassing. - * Otherwise, convert BI/FE and PE+INPCK to 0. - * - * This makes bypassing work right in the - * usual "raw" case (IGNBRK set, and IGNPAR - * and INPCK clear). - * - * Note: BI together with FE/PE means just BI. - */ - if (line_status & LSR_BI) { -#if defined(KDB) && defined(BREAK_TO_DEBUGGER) - if (com->unit == comconsole) { - kdb_enter("Line break on console"); - goto cont; - } -#endif - if (com->tp == NULL - || com->tp->t_iflag & IGNBRK) - goto cont; - } else { - if (com->tp == NULL - || com->tp->t_iflag & IGNPAR) - goto cont; - } - if (com->tp->t_state & TS_CAN_BYPASS_L_RINT - && (line_status & (LSR_BI | LSR_FE) - || com->tp->t_iflag & INPCK)) - recv_data = 0; - } - ++com->bytes_in; - if (com->tp != NULL && - com->tp->t_hotchar != 0 && recv_data == com->tp->t_hotchar) - swi_sched(sio_fast_ih, 0); - ioptr = com->iptr; - if (ioptr >= com->ibufend) - CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); - else { - if (com->tp != NULL && com->tp->t_do_timestamp) - microtime(&com->tp->t_timestamp); - ++com_events; - swi_sched(sio_slow_ih, SWI_DELAY); -#if 0 /* for testing input latency vs efficiency */ -if (com->iptr - com->ibuf == 8) - swi_sched(sio_fast_ih, 0); -#endif - ioptr[0] = recv_data; - ioptr[com->ierroff] = line_status; - com->iptr = ++ioptr; - if (ioptr == com->ihighwater - && com->state & CS_RTS_IFLOW) -#ifdef PC98 - IS_8251(com->pc98_if_type) ? - com_tiocm_bic(com, TIOCM_RTS) : -#endif - outb(com->modem_ctl_port, - com->mcr_image &= ~MCR_RTS); - if (line_status & LSR_OE) - CE_RECORD(com, CE_OVERRUN); - } -cont: - if (line_status & LSR_TXRDY - && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) - goto txrdy; - - /* - * "& 0x7F" is to avoid the gcc-1.40 generating a slow - * jump from the top of the loop to here - */ -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - goto status_read; - else -#endif - line_status = inb(com->line_status_port) & 0x7F; -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) - rsa_buf_status = inb(com->rsabase + rsa_srr); -#endif /* PC98 */ - } - - /* modem status change? (always check before doing output) */ -#ifdef PC98 - if (!IS_8251(com->pc98_if_type)) { -#endif - modem_status = inb(com->modem_status_port); - if (modem_status != com->last_modem_status) { - /* - * Schedule high level to handle DCD changes. Note - * that we don't use the delta bits anywhere. Some - * UARTs mess them up, and it's easy to remember the - * previous bits and calculate the delta. - */ - com->last_modem_status = modem_status; - if (!(com->state & CS_CHECKMSR)) { - com_events += LOTS_OF_EVENTS; - com->state |= CS_CHECKMSR; - swi_sched(sio_fast_ih, 0); - } - - /* handle CTS change immediately for crisp flow ctl */ - if (com->state & CS_CTS_OFLOW) { - if (modem_status & MSR_CTS) - com->state |= CS_ODEVREADY; - else - com->state &= ~CS_ODEVREADY; - } - } -#ifdef PC98 - } -#endif - -txrdy: - /* output queued and everything ready? */ -#ifndef PC98 - if (line_status & LSR_TXRDY - && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { -#else - if (((com->pc98_if_type == COM_IF_RSA98III) - ? (rsa_buf_status & 0x02) - : (line_status & LSR_TXRDY)) - && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { -#endif -#ifdef PC98 - Port_t tmp_data_port; - - if (IS_8251(com->pc98_if_type) && - com->pc98_8251fifo_enable) - tmp_data_port = I8251F_data; - else - tmp_data_port = com->data_port; -#endif - - ioptr = com->obufq.l_head; - if (com->tx_fifo_size > 1 && com->unit != siotsunit) { - u_int ocount; - - ocount = com->obufq.l_tail - ioptr; -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) { - rsa_buf_status = inb(com->rsabase + rsa_srr); - rsa_tx_fifo_size = 1024; - if (!(rsa_buf_status & 0x01)) - rsa_tx_fifo_size = 2048; - if (ocount > rsa_tx_fifo_size) - ocount = rsa_tx_fifo_size; - } else -#endif - if (ocount > com->tx_fifo_size) - ocount = com->tx_fifo_size; - com->bytes_out += ocount; - do -#ifdef PC98 - outb(tmp_data_port, *ioptr++); -#else - outb(com->data_port, *ioptr++); -#endif - while (--ocount != 0); - } else { -#ifdef PC98 - outb(tmp_data_port, *ioptr++); -#else - outb(com->data_port, *ioptr++); -#endif - ++com->bytes_out; - if (com->unit == siotsunit - && siotso < sizeof siots / sizeof siots[0]) - nanouptime(&siots[siotso++]); - } -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG)) - com_int_Tx_enable(com); -#endif - com->obufq.l_head = ioptr; - if (COM_IIR_TXRDYBUG(com->flags)) - int_ctl_new = int_ctl | IER_ETXRDY; - if (ioptr >= com->obufq.l_tail) { - struct lbq *qp; - - qp = com->obufq.l_next; - qp->l_queued = FALSE; - qp = qp->l_next; - if (qp != NULL) { - com->obufq.l_head = qp->l_head; - com->obufq.l_tail = qp->l_tail; - com->obufq.l_next = qp; - } else { - /* output just completed */ - if (COM_IIR_TXRDYBUG(com->flags)) - int_ctl_new = int_ctl - & ~IER_ETXRDY; - com->state &= ~CS_BUSY; -#if defined(PC98) - if (IS_8251(com->pc98_if_type) && - pc98_check_i8251_interrupt(com) & IEN_TxFLAG) - com_int_Tx_disable(com); -#endif - } - if (!(com->state & CS_ODONE)) { - com_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - /* handle at high level ASAP */ - swi_sched(sio_fast_ih, 0); - } - } -#ifdef PC98 - if (COM_IIR_TXRDYBUG(com->flags) - && int_ctl != int_ctl_new) { - if (com->pc98_if_type == COM_IF_RSA98III) { - int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY); - outb(com->int_ctl_port, int_ctl_new); - outb(com->rsabase + rsa_ier, 0x1d); - } else - outb(com->int_ctl_port, int_ctl_new); - } -#else - if (COM_IIR_TXRDYBUG(com->flags) - && int_ctl != int_ctl_new) - outb(com->int_ctl_port, int_ctl_new); -#endif - } -#ifdef PC98 - else if (line_status & LSR_TXRDY) { - if (IS_8251(com->pc98_if_type)) - if (pc98_check_i8251_interrupt(com) & IEN_TxFLAG) - com_int_Tx_disable(com); - } - if (IS_8251(com->pc98_if_type)) { - if (com->pc98_8251fifo_enable) { - if ((tmp = inb(I8251F_lsr)) & STS8251F_RxRDY) - goto more_intr; - } else { - if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) - goto more_intr; - } - } -#endif - - /* finished? */ -#ifndef COM_MULTIPORT -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - return; -#endif - if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) -#endif /* COM_MULTIPORT */ - return; - } -} - -/* software interrupt handler for SWI_TTY */ -static void -siopoll(void *dummy) -{ - int unit; - - if (com_events == 0) - return; -repeat: - for (unit = 0; unit < sio_numunits; ++unit) { - struct com_s *com; - int incc; - struct tty *tp; - - com = com_addr(unit); - if (com == NULL) - continue; - tp = com->tp; - if (tp == NULL || com->gone) { - /* - * Discard any events related to never-opened or - * going-away devices. - */ - mtx_lock_spin(&sio_lock); - incc = com->iptr - com->ibuf; - com->iptr = com->ibuf; - if (com->state & CS_CHECKMSR) { - incc += LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - } - com_events -= incc; - mtx_unlock_spin(&sio_lock); - continue; - } - if (com->iptr != com->ibuf) { - mtx_lock_spin(&sio_lock); - sioinput(com); - mtx_unlock_spin(&sio_lock); - } - if (com->state & CS_CHECKMSR) { - u_char delta_modem_status; - -#ifdef PC98 - if (!IS_8251(com->pc98_if_type)) { -#endif - mtx_lock_spin(&sio_lock); - delta_modem_status = com->last_modem_status - ^ com->prev_modem_status; - com->prev_modem_status = com->last_modem_status; - com_events -= LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - mtx_unlock_spin(&sio_lock); - if (delta_modem_status & MSR_DCD) - ttyld_modem(tp, - com->prev_modem_status & MSR_DCD); -#ifdef PC98 - } -#endif - } - if (com->state & CS_ODONE) { - mtx_lock_spin(&sio_lock); - com_events -= LOTS_OF_EVENTS; - com->state &= ~CS_ODONE; - mtx_unlock_spin(&sio_lock); - if (!(com->state & CS_BUSY) - && !(com->extra_state & CSE_BUSYCHECK)) { - timeout(siobusycheck, com, hz / 100); - com->extra_state |= CSE_BUSYCHECK; - } - ttyld_start(tp); - } - if (com_events == 0) - break; - } - if (com_events >= LOTS_OF_EVENTS) - goto repeat; -} - -static void -combreak(tp, sig) - struct tty *tp; - int sig; -{ - struct com_s *com; - - com = tp->t_sc; - -#ifdef PC98 - if (sig) - com_send_break_on(com); - else - com_send_break_off(com); -#else - if (sig) - sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK); - else - sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); -#endif -} - -static int -comparam(tp, t) - struct tty *tp; - struct termios *t; -{ - u_int cfcr; - int cflag; - struct com_s *com; - u_int divisor; - u_char dlbh; - u_char dlbl; - u_char efr_flowbits; - int s; -#ifdef PC98 - u_char param = 0; -#endif - - com = tp->t_sc; - if (com == NULL) - return (ENODEV); - -#ifdef PC98 - cfcr = 0; - - if (IS_8251(com->pc98_if_type)) { - if (pc98_ttspeedtab(com, t->c_ospeed, &divisor) != 0) - return (EINVAL); - } else { -#endif - /* check requested parameters */ - if (t->c_ispeed != (t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed)) - return (EINVAL); - divisor = siodivisor(com->rclk, t->c_ispeed); - if (divisor == 0) - return (EINVAL); -#ifdef PC98 - } -#endif - - /* parameters are OK, convert them to the com struct and the device */ - s = spltty(); -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if (t->c_ospeed == 0) - com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); - else - com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); - } else -#endif - if (t->c_ospeed == 0) - (void)commodem(tp, 0, SER_DTR); /* hang up line */ - else - (void)commodem(tp, SER_DTR, 0); - cflag = t->c_cflag; -#ifdef PC98 - if (!IS_8251(com->pc98_if_type)) { -#endif - switch (cflag & CSIZE) { - case CS5: - cfcr = CFCR_5BITS; - break; - case CS6: - cfcr = CFCR_6BITS; - break; - case CS7: - cfcr = CFCR_7BITS; - break; - default: - cfcr = CFCR_8BITS; - break; - } - if (cflag & PARENB) { - cfcr |= CFCR_PENAB; - if (!(cflag & PARODD)) - cfcr |= CFCR_PEVEN; - } - if (cflag & CSTOPB) - cfcr |= CFCR_STOPB; - - if (com->hasfifo) { - /* - * Use a fifo trigger level low enough so that the input - * latency from the fifo is less than about 16 msec and - * the total latency is less than about 30 msec. These - * latencies are reasonable for humans. Serial comms - * protocols shouldn't expect anything better since modem - * latencies are larger. - * - * The fifo trigger level cannot be set at RX_HIGH for high - * speed connections without further work on reducing - * interrupt disablement times in other parts of the system, - * without producing silo overflow errors. - */ - com->fifo_image = com->unit == siotsunit ? 0 - : t->c_ispeed <= 4800 - ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH; -#ifdef COM_ESP - /* - * The Hayes ESP card needs the fifo DMA mode bit set - * in compatibility mode. If not, it will interrupt - * for each character received. - */ - if (com->esp) - com->fifo_image |= FIFO_DMA_MODE; -#endif - sio_setreg(com, com_fifo, com->fifo_image); - } -#ifdef PC98 - } -#endif - - /* - * This returns with interrupts disabled so that we can complete - * the speed change atomically. Keeping interrupts disabled is - * especially important while com_data is hidden. - */ - (void) siosetwater(com, t->c_ispeed); - -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - com_cflag_and_speed_set(com, cflag, t->c_ospeed); - else { -#endif - sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB); - /* - * Only set the divisor registers if they would change, since on - * some 16550 incompatibles (UMC8669F), setting them while input - * is arriving loses sync until data stops arriving. - */ - dlbl = divisor & 0xFF; - if (sio_getreg(com, com_dlbl) != dlbl) - sio_setreg(com, com_dlbl, dlbl); - dlbh = divisor >> 8; - if (sio_getreg(com, com_dlbh) != dlbh) - sio_setreg(com, com_dlbh, dlbh); -#ifdef PC98 - } -#endif - - efr_flowbits = 0; - - if (cflag & CRTS_IFLOW) { - com->state |= CS_RTS_IFLOW; - efr_flowbits |= EFR_AUTORTS; - /* - * If CS_RTS_IFLOW just changed from off to on, the change - * needs to be propagated to MCR_RTS. This isn't urgent, - * so do it later by calling comstart() instead of repeating - * a lot of code from comstart() here. - */ - } else if (com->state & CS_RTS_IFLOW) { - com->state &= ~CS_RTS_IFLOW; - /* - * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS - * on here, since comstart() won't do it later. - */ -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - com_tiocm_bis(com, TIOCM_RTS); - else - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); -#else - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); -#endif - } - - /* - * Set up state to handle output flow control. - * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? - * Now has 10+ msec latency, while CTS flow has 50- usec latency. - */ - com->state |= CS_ODEVREADY; - com->state &= ~CS_CTS_OFLOW; -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) { - param = inb(com->rsabase + rsa_msr); - outb(com->rsabase + rsa_msr, param & 0x14); - } -#endif - if (cflag & CCTS_OFLOW) { - com->state |= CS_CTS_OFLOW; - efr_flowbits |= EFR_AUTOCTS; -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if (!(pc98_get_modem_status(com) & TIOCM_CTS)) - com->state &= ~CS_ODEVREADY; - } else if (com->pc98_if_type == COM_IF_RSA98III) { - /* Set automatic flow control mode */ - outb(com->rsabase + rsa_msr, param | 0x08); - } else -#endif - if (!(com->last_modem_status & MSR_CTS)) - com->state &= ~CS_ODEVREADY; - } - -#ifdef PC98 - if (!IS_8251(com->pc98_if_type)) - sio_setreg(com, com_cfcr, com->cfcr_image = cfcr); -#else - if (com->st16650a) { - sio_setreg(com, com_lcr, LCR_EFR_ENABLE); - sio_setreg(com, com_efr, - (sio_getreg(com, com_efr) - & ~(EFR_AUTOCTS | EFR_AUTORTS)) | efr_flowbits); - } - sio_setreg(com, com_cfcr, com->cfcr_image = cfcr); -#endif - - /* XXX shouldn't call functions while intrs are disabled. */ - ttyldoptim(tp); - - mtx_unlock_spin(&sio_lock); - splx(s); - comstart(tp); - if (com->ibufold != NULL) { - free(com->ibufold, M_DEVBUF); - com->ibufold = NULL; - } - return (0); -} - -/* - * This function must be called with the sio_lock mutex released and will - * return with it obtained. - */ -static int -siosetwater(com, speed) - struct com_s *com; - speed_t speed; -{ - int cp4ticks; - u_char *ibuf; - int ibufsize; - struct tty *tp; - - /* - * Make the buffer size large enough to handle a softtty interrupt - * latency of about 2 ticks without loss of throughput or data - * (about 3 ticks if input flow control is not used or not honoured, - * but a bit less for CS5-CS7 modes). - */ - cp4ticks = speed / 10 / hz * 4; - for (ibufsize = 128; ibufsize < cp4ticks;) - ibufsize <<= 1; -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) - ibufsize = 2048; -#endif - if (ibufsize == com->ibufsize) { - mtx_lock_spin(&sio_lock); - return (0); - } - - /* - * Allocate input buffer. The extra factor of 2 in the size is - * to allow for an error byte for each input byte. - */ - ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); - if (ibuf == NULL) { - mtx_lock_spin(&sio_lock); - return (ENOMEM); - } - - /* Initialize non-critical variables. */ - com->ibufold = com->ibuf; - com->ibufsize = ibufsize; - tp = com->tp; - if (tp != NULL) { - tp->t_ififosize = 2 * ibufsize; - tp->t_ispeedwat = (speed_t)-1; - tp->t_ospeedwat = (speed_t)-1; - } - - /* - * Read current input buffer, if any. Continue with interrupts - * disabled. - */ - mtx_lock_spin(&sio_lock); - if (com->iptr != com->ibuf) - sioinput(com); - - /*- - * Initialize critical variables, including input buffer watermarks. - * The external device is asked to stop sending when the buffer - * exactly reaches high water, or when the high level requests it. - * The high level is notified immediately (rather than at a later - * clock tick) when this watermark is reached. - * The buffer size is chosen so the watermark should almost never - * be reached. - * The low watermark is invisibly 0 since the buffer is always - * emptied all at once. - */ - com->iptr = com->ibuf = ibuf; - com->ibufend = ibuf + ibufsize; - com->ierroff = ibufsize; - com->ihighwater = ibuf + 3 * ibufsize / 4; - return (0); -} - -static void -comstart(tp) - struct tty *tp; -{ - struct com_s *com; - int s; - - com = tp->t_sc; - if (com == NULL) - return; - s = spltty(); - mtx_lock_spin(&sio_lock); - if (tp->t_state & TS_TTSTOP) - com->state &= ~CS_TTGO; - else - com->state |= CS_TTGO; - if (tp->t_state & TS_TBLOCK) { -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if ((com_tiocm_get(com) & TIOCM_RTS) && - (com->state & CS_RTS_IFLOW)) - com_tiocm_bic(com, TIOCM_RTS); - } else { - if ((com->mcr_image & MCR_RTS) && - (com->state & CS_RTS_IFLOW)) - outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); - } -#else - if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) - outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); -#endif - } else { -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if (!(com_tiocm_get(com) & TIOCM_RTS) && - com->iptr < com->ihighwater && - com->state & CS_RTS_IFLOW) - com_tiocm_bis(com, TIOCM_RTS); - } else { - if (!(com->mcr_image & MCR_RTS) && - com->iptr < com->ihighwater && - com->state & CS_RTS_IFLOW) - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); - } -#else - if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater - && com->state & CS_RTS_IFLOW) - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); -#endif - } - mtx_unlock_spin(&sio_lock); - if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - splx(s); - return; - } - if (tp->t_outq.c_cc != 0) { - struct lbq *qp; - struct lbq *next; - - if (!com->obufs[0].l_queued) { - com->obufs[0].l_tail - = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, -#ifdef PC98 - com->obufsize); -#else - sizeof com->obuf1); -#endif - com->obufs[0].l_next = NULL; - com->obufs[0].l_queued = TRUE; - mtx_lock_spin(&sio_lock); - if (com->state & CS_BUSY) { - qp = com->obufq.l_next; - while ((next = qp->l_next) != NULL) - qp = next; - qp->l_next = &com->obufs[0]; - } else { - com->obufq.l_head = com->obufs[0].l_head; - com->obufq.l_tail = com->obufs[0].l_tail; - com->obufq.l_next = &com->obufs[0]; - com->state |= CS_BUSY; - } - mtx_unlock_spin(&sio_lock); - } - if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { - com->obufs[1].l_tail - = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, -#ifdef PC98 - com->obufsize); -#else - sizeof com->obuf2); -#endif - com->obufs[1].l_next = NULL; - com->obufs[1].l_queued = TRUE; - mtx_lock_spin(&sio_lock); - if (com->state & CS_BUSY) { - qp = com->obufq.l_next; - while ((next = qp->l_next) != NULL) - qp = next; - qp->l_next = &com->obufs[1]; - } else { - com->obufq.l_head = com->obufs[1].l_head; - com->obufq.l_tail = com->obufs[1].l_tail; - com->obufq.l_next = &com->obufs[1]; - com->state |= CS_BUSY; - } - mtx_unlock_spin(&sio_lock); - } - tp->t_state |= TS_BUSY; - } - mtx_lock_spin(&sio_lock); - if (com->state >= (CS_BUSY | CS_TTGO)) - siointr1(com); /* fake interrupt to start output */ - mtx_unlock_spin(&sio_lock); - ttwwakeup(tp); - splx(s); -} - -static void -comstop(tp, rw) - struct tty *tp; - int rw; -{ - struct com_s *com; -#ifdef PC98 - int rsa98_tmp = 0; -#endif - - com = tp->t_sc; - if (com == NULL || com->gone) - return; - mtx_lock_spin(&sio_lock); - if (rw & FWRITE) { -#ifdef PC98 - if (!IS_8251(com->pc98_if_type)) { -#endif - if (com->hasfifo) -#ifdef COM_ESP - /* XXX avoid h/w bug. */ - if (!com->esp) -#endif - sio_setreg(com, com_fifo, - FIFO_XMT_RST | com->fifo_image); -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) - for (rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) - sio_setreg(com, com_fifo, - FIFO_XMT_RST | com->fifo_image); - } -#endif - com->obufs[0].l_queued = FALSE; - com->obufs[1].l_queued = FALSE; - if (com->state & CS_ODONE) - com_events -= LOTS_OF_EVENTS; - com->state &= ~(CS_ODONE | CS_BUSY); - com->tp->t_state &= ~TS_BUSY; - } - if (rw & FREAD) { -#ifdef PC98 - if (!IS_8251(com->pc98_if_type)) { - if (com->pc98_if_type == COM_IF_RSA98III) - for (rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) - sio_getreg(com, com_data); -#endif - if (com->hasfifo) -#ifdef COM_ESP - /* XXX avoid h/w bug. */ - if (!com->esp) -#endif - sio_setreg(com, com_fifo, - FIFO_RCV_RST | com->fifo_image); -#ifdef PC98 - } -#endif - com_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - } - mtx_unlock_spin(&sio_lock); - comstart(tp); -} - -static int -commodem(struct tty *tp, int sigon, int sigoff) -{ - struct com_s *com; - int bitand, bitor, msr; -#ifdef PC98 - int clr, set; -#endif - - com = tp->t_sc; - if (com->gone) - return(0); - if (sigon != 0 || sigoff != 0) { -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - bitand = bitor = 0; - clr = set = 0; - if (sigoff & SER_DTR) { - bitand |= TIOCM_DTR; - clr |= CMD8251_DTR; - } - if (sigoff & SER_RTS) { - bitand |= TIOCM_RTS; - clr |= CMD8251_RxEN | CMD8251_RTS; - } - if (sigon & SER_DTR) { - bitor |= TIOCM_DTR; - set |= CMD8251_TxEN | CMD8251_RxEN | - CMD8251_DTR; - } - if (sigon & SER_RTS) { - bitor |= TIOCM_RTS; - set |= CMD8251_TxEN | CMD8251_RxEN | - CMD8251_RTS; - } - bitand = ~bitand; - mtx_lock_spin(&sio_lock); - com->pc98_prev_modem_status &= bitand; - com->pc98_prev_modem_status |= bitor; - pc98_i8251_clear_or_cmd(com, clr, set); - mtx_unlock_spin(&sio_lock); - return (0); - } else { -#endif - bitand = bitor = 0; - if (sigoff & SER_DTR) - bitand |= MCR_DTR; - if (sigoff & SER_RTS) - bitand |= MCR_RTS; - if (sigon & SER_DTR) - bitor |= MCR_DTR; - if (sigon & SER_RTS) - bitor |= MCR_RTS; - bitand = ~bitand; - mtx_lock_spin(&sio_lock); - com->mcr_image &= bitand; - com->mcr_image |= bitor; - outb(com->modem_ctl_port, com->mcr_image); - mtx_unlock_spin(&sio_lock); - return (0); -#ifdef PC98 - } -#endif - } else { -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - return (com_tiocm_get(com)); - else { -#endif - bitor = 0; - if (com->mcr_image & MCR_DTR) - bitor |= SER_DTR; - if (com->mcr_image & MCR_RTS) - bitor |= SER_RTS; - msr = com->prev_modem_status; - if (msr & MSR_CTS) - bitor |= SER_CTS; - if (msr & MSR_DCD) - bitor |= SER_DCD; - if (msr & MSR_DSR) - bitor |= SER_DSR; - if (msr & MSR_DSR) - bitor |= SER_DSR; - if (msr & (MSR_RI | MSR_TERI)) - bitor |= SER_RI; - return (bitor); -#ifdef PC98 - } -#endif - } -} - -static void -siosettimeout() -{ - struct com_s *com; - bool_t someopen; - int unit; - - /* - * Set our timeout period to 1 second if no polled devices are open. - * Otherwise set it to max(1/200, 1/hz). - * Enable timeouts iff some device is open. - */ - untimeout(comwakeup, (void *)NULL, sio_timeout_handle); - sio_timeout = hz; - someopen = FALSE; - for (unit = 0; unit < sio_numunits; ++unit) { - com = com_addr(unit); - if (com != NULL && com->tp != NULL - && com->tp->t_state & TS_ISOPEN && !com->gone) { - someopen = TRUE; - if (com->poll || com->poll_output) { - sio_timeout = hz > 200 ? hz / 200 : 1; - break; - } - } - } - if (someopen) { - sio_timeouts_until_log = hz / sio_timeout; - sio_timeout_handle = timeout(comwakeup, (void *)NULL, - sio_timeout); - } else { - /* Flush error messages, if any. */ - sio_timeouts_until_log = 1; - comwakeup((void *)NULL); - untimeout(comwakeup, (void *)NULL, sio_timeout_handle); - } -} - -static void -comwakeup(chan) - void *chan; -{ - struct com_s *com; - int unit; - - sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); - - /* - * Recover from lost output interrupts. - * Poll any lines that don't use interrupts. - */ - for (unit = 0; unit < sio_numunits; ++unit) { - com = com_addr(unit); - if (com != NULL && !com->gone - && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { - mtx_lock_spin(&sio_lock); - siointr1(com); - mtx_unlock_spin(&sio_lock); - } - } - - /* - * Check for and log errors, but not too often. - */ - if (--sio_timeouts_until_log > 0) - return; - sio_timeouts_until_log = hz / sio_timeout; - for (unit = 0; unit < sio_numunits; ++unit) { - int errnum; - - com = com_addr(unit); - if (com == NULL) - continue; - if (com->gone) - continue; - for (errnum = 0; errnum < CE_NTYPES; ++errnum) { - u_int delta; - u_long total; - - mtx_lock_spin(&sio_lock); - delta = com->delta_error_counts[errnum]; - com->delta_error_counts[errnum] = 0; - mtx_unlock_spin(&sio_lock); - if (delta == 0) - continue; - total = com->error_counts[errnum] += delta; - log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", - unit, delta, error_desc[errnum], - delta == 1 ? "" : "s", total); - } - } -} - -#ifdef PC98 -/* commint is called when modem control line changes */ -static void -commint(struct cdev *dev) -{ - register struct tty *tp; - int stat,delta; - struct com_s *com; - - com = dev->si_drv1; - tp = com->tp; - - stat = com_tiocm_get(com); - delta = com_tiocm_get_delta(com); - - if (com->state & CS_CTS_OFLOW) { - if (stat & TIOCM_CTS) - com->state |= CS_ODEVREADY; - else - com->state &= ~CS_ODEVREADY; - } - if ((delta & TIOCM_CAR) && (ISCALLOUT(dev)) == 0) { - if (stat & TIOCM_CAR ) - (void)ttyld_modem(tp, 1); - else if (ttyld_modem(tp, 0) == 0) { - /* negate DTR, RTS */ - com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? - TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); - /* disable IENABLE */ - com_int_TxRx_disable( com ); - } - } -} -#endif - -/* - * Following are all routines needed for SIO to act as console - */ -struct siocnstate { - u_char dlbl; - u_char dlbh; - u_char ier; - u_char cfcr; - u_char mcr; -}; - -/* - * This is a function in order to not replicate "ttyd%d" more - * places than absolutely necessary. - */ -static void -siocnset(struct consdev *cd, int unit) -{ - - cd->cn_unit = unit; - sprintf(cd->cn_name, "ttyd%d", unit); -} - -static speed_t siocngetspeed(Port_t, u_long rclk); -static void siocnclose(struct siocnstate *sp, Port_t iobase); -static void siocnopen(struct siocnstate *sp, Port_t iobase, int speed); -static void siocntxwait(Port_t iobase); - -static cn_probe_t siocnprobe; -static cn_init_t siocninit; -static cn_term_t siocnterm; -static cn_checkc_t siocncheckc; -static cn_getc_t siocngetc; -static cn_putc_t siocnputc; - -CONS_DRIVER(sio, siocnprobe, siocninit, siocnterm, siocngetc, siocncheckc, - siocnputc, NULL); - -static void -siocntxwait(iobase) - Port_t iobase; -{ - int timo; - - /* - * Wait for any pending transmission to finish. Required to avoid - * the UART lockup bug when the speed is changed, and for normal - * transmits. - */ - timo = 100000; - while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) - != (LSR_TSRE | LSR_TXRDY) && --timo != 0) - ; -} - -/* - * Read the serial port specified and try to figure out what speed - * it's currently running at. We're assuming the serial port has - * been initialized and is basicly idle. This routine is only intended - * to be run at system startup. - * - * If the value read from the serial port doesn't make sense, return 0. - */ - -static speed_t -siocngetspeed(iobase, rclk) - Port_t iobase; - u_long rclk; -{ - u_int divisor; - u_char dlbh; - u_char dlbl; - u_char cfcr; - - cfcr = inb(iobase + com_cfcr); - outb(iobase + com_cfcr, CFCR_DLAB | cfcr); - - dlbl = inb(iobase + com_dlbl); - dlbh = inb(iobase + com_dlbh); - - outb(iobase + com_cfcr, cfcr); - - divisor = dlbh << 8 | dlbl; - - /* XXX there should be more sanity checking. */ - if (divisor == 0) - return (CONSPEED); - return (rclk / (16UL * divisor)); -} - -static void -siocnopen(sp, iobase, speed) - struct siocnstate *sp; - Port_t iobase; - int speed; -{ - u_int divisor; - u_char dlbh; - u_char dlbl; - - /* - * Save all the device control registers except the fifo register - * and set our default ones (cs8 -parenb speed=comdefaultrate). - * We can't save the fifo register since it is read-only. - */ - sp->ier = inb(iobase + com_ier); - outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ - siocntxwait(iobase); - sp->cfcr = inb(iobase + com_cfcr); - outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); - sp->dlbl = inb(iobase + com_dlbl); - sp->dlbh = inb(iobase + com_dlbh); - /* - * Only set the divisor registers if they would change, since on - * some 16550 incompatibles (Startech), setting them clears the - * data input register. This also reduces the effects of the - * UMC8669F bug. - */ - divisor = siodivisor(comdefaultrclk, speed); - dlbl = divisor & 0xFF; - if (sp->dlbl != dlbl) - outb(iobase + com_dlbl, dlbl); - dlbh = divisor >> 8; - if (sp->dlbh != dlbh) - outb(iobase + com_dlbh, dlbh); - outb(iobase + com_cfcr, CFCR_8BITS); - sp->mcr = inb(iobase + com_mcr); - /* - * We don't want interrupts, but must be careful not to "disable" - * them by clearing the MCR_IENABLE bit, since that might cause - * an interrupt by floating the IRQ line. - */ - outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); -} - -static void -siocnclose(sp, iobase) - struct siocnstate *sp; - Port_t iobase; -{ - /* - * Restore the device control registers. - */ - siocntxwait(iobase); - outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); - if (sp->dlbl != inb(iobase + com_dlbl)) - outb(iobase + com_dlbl, sp->dlbl); - if (sp->dlbh != inb(iobase + com_dlbh)) - outb(iobase + com_dlbh, sp->dlbh); - outb(iobase + com_cfcr, sp->cfcr); - /* - * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. - */ - outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); - outb(iobase + com_ier, sp->ier); -} - -static void -siocnprobe(cp) - struct consdev *cp; -{ - speed_t boot_speed; - u_char cfcr; - u_int divisor; - int s, unit; - struct siocnstate sp; - - /* - * Find our first enabled console, if any. If it is a high-level - * console device, then initialize it and return successfully. - * If it is a low-level console device, then initialize it and - * return unsuccessfully. It must be initialized in both cases - * for early use by console drivers and debuggers. Initializing - * the hardware is not necessary in all cases, since the i/o - * routines initialize it on the fly, but it is necessary if - * input might arrive while the hardware is switched back to an - * uninitialized state. We can't handle multiple console devices - * yet because our low-level routines don't take a device arg. - * We trust the user to set the console flags properly so that we - * don't need to probe. - */ - cp->cn_pri = CN_DEAD; - - for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ - int flags; - - if (resource_disabled("sio", unit)) - continue; - if (resource_int_value("sio", unit, "flags", &flags)) - continue; - if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) { - int port; - Port_t iobase; - - if (resource_int_value("sio", unit, "port", &port)) - continue; - iobase = port; - s = spltty(); - if (boothowto & RB_SERIAL) { - boot_speed = - siocngetspeed(iobase, comdefaultrclk); - if (boot_speed) - comdefaultrate = boot_speed; - } - - /* - * Initialize the divisor latch. We can't rely on - * siocnopen() to do this the first time, since it - * avoids writing to the latch if the latch appears - * to have the correct value. Also, if we didn't - * just read the speed from the hardware, then we - * need to set the speed in hardware so that - * switching it later is null. - */ - cfcr = inb(iobase + com_cfcr); - outb(iobase + com_cfcr, CFCR_DLAB | cfcr); - divisor = siodivisor(comdefaultrclk, comdefaultrate); - outb(iobase + com_dlbl, divisor & 0xff); - outb(iobase + com_dlbh, divisor >> 8); - outb(iobase + com_cfcr, cfcr); - - siocnopen(&sp, iobase, comdefaultrate); - - splx(s); - if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) { - siocnset(cp, unit); - cp->cn_pri = COM_FORCECONSOLE(flags) - || boothowto & RB_SERIAL - ? CN_REMOTE : CN_NORMAL; - siocniobase = iobase; - siocnunit = unit; - } -#ifdef GDB - if (COM_DEBUGGER(flags)) - siogdbiobase = iobase; -#endif - } - } -} - -static void -siocninit(cp) - struct consdev *cp; -{ - comconsole = cp->cn_unit; -} - -static void -siocnterm(cp) - struct consdev *cp; -{ - comconsole = -1; -} - -static int -siocncheckc(struct consdev *cd) -{ - int c; - Port_t iobase; - int s; - struct siocnstate sp; - speed_t speed; - - if (cd != NULL && cd->cn_unit == siocnunit) { - iobase = siocniobase; - speed = comdefaultrate; - } else { -#ifdef GDB - iobase = siogdbiobase; - speed = gdbdefaultrate; -#else - return (-1); -#endif - } - s = spltty(); - siocnopen(&sp, iobase, speed); - if (inb(iobase + com_lsr) & LSR_RXRDY) - c = inb(iobase + com_data); - else - c = -1; - siocnclose(&sp, iobase); - splx(s); - return (c); -} - -static int -siocngetc(struct consdev *cd) -{ - int c; - Port_t iobase; - int s; - struct siocnstate sp; - speed_t speed; - - if (cd != NULL && cd->cn_unit == siocnunit) { - iobase = siocniobase; - speed = comdefaultrate; - } else { -#ifdef GDB - iobase = siogdbiobase; - speed = gdbdefaultrate; -#else - return (-1); -#endif - } - s = spltty(); - siocnopen(&sp, iobase, speed); - while (!(inb(iobase + com_lsr) & LSR_RXRDY)) - ; - c = inb(iobase + com_data); - siocnclose(&sp, iobase); - splx(s); - return (c); -} - -static void -siocnputc(struct consdev *cd, int c) -{ - int need_unlock; - int s; - struct siocnstate sp; - Port_t iobase; - speed_t speed; - - if (cd != NULL && cd->cn_unit == siocnunit) { - iobase = siocniobase; - speed = comdefaultrate; - } else { -#ifdef GDB - iobase = siogdbiobase; - speed = gdbdefaultrate; -#else - return; -#endif - } - s = spltty(); - need_unlock = 0; - if (!kdb_active && sio_inited == 2 && !mtx_owned(&sio_lock)) { - mtx_lock_spin(&sio_lock); - need_unlock = 1; - } - siocnopen(&sp, iobase, speed); - siocntxwait(iobase); - outb(iobase + com_data, c); - siocnclose(&sp, iobase); - if (need_unlock) - mtx_unlock_spin(&sio_lock); - splx(s); -} - -/* - * Remote gdb(1) support. - */ - -#if defined(GDB) - -#include <gdb/gdb.h> - -static gdb_probe_f siogdbprobe; -static gdb_init_f siogdbinit; -static gdb_term_f siogdbterm; -static gdb_getc_f siogdbgetc; -static gdb_checkc_f siogdbcheckc; -static gdb_putc_f siogdbputc; - -GDB_DBGPORT(sio, siogdbprobe, siogdbinit, siogdbterm, siogdbcheckc, - siogdbgetc, siogdbputc); - -static int -siogdbprobe(void) -{ - return ((siogdbiobase != 0) ? 0 : -1); -} - -static void -siogdbinit(void) -{ -} - -static void -siogdbterm(void) -{ -} - -static void -siogdbputc(int c) -{ - siocnputc(NULL, c); -} - -static int -siogdbcheckc(void) -{ - return (siocncheckc(NULL)); -} - -static int -siogdbgetc(void) -{ - return (siocngetc(NULL)); -} - -#endif - -#ifdef PC98 -/* - * pc98 local function - */ -static void -com_tiocm_bis(struct com_s *com, int msr) -{ - int s; - int tmp = 0; - - s=spltty(); - com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); - tmp |= CMD8251_TxEN|CMD8251_RxEN; - if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; - if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; - - pc98_i8251_or_cmd( com, tmp ); - splx(s); -} - -static void -com_tiocm_bic(struct com_s *com, int msr) -{ - int s; - int tmp = msr; - - s=spltty(); - com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); - if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; - if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; - - pc98_i8251_clear_cmd( com, tmp ); - splx(s); -} - -static int -com_tiocm_get(struct com_s *com) -{ - return( com->pc98_prev_modem_status ); -} - -static int -com_tiocm_get_delta(struct com_s *com) -{ - int tmp; - - tmp = com->pc98_modem_delta; - com->pc98_modem_delta = 0; - return( tmp ); -} - -/* convert to TIOCM_?? ( ioctl.h ) */ -static int -pc98_get_modem_status(struct com_s *com) -{ - register int msr; - - msr = com->pc98_prev_modem_status - & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); - if (com->pc98_8251fifo_enable) { - int stat2; - - stat2 = inb(I8251F_msr); - if ( stat2 & CICSCDF_CD ) msr |= TIOCM_CAR; - if ( stat2 & CICSCDF_CI ) msr |= TIOCM_RI; - if ( stat2 & CICSCDF_DR ) msr |= TIOCM_DSR; - if ( stat2 & CICSCDF_CS ) msr |= TIOCM_CTS; -#if COM_CARRIER_DETECT_EMULATE - if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { - msr |= TIOCM_CAR; - } -#endif - } else { - int stat, stat2; - - stat = inb(com->sts_port); - stat2 = inb(com->in_modem_port); - if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; - if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; - if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; - if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; -#if COM_CARRIER_DETECT_EMULATE - if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { - msr |= TIOCM_CAR; - } -#endif - } - return(msr); -} - -static void -pc98_check_msr(void* chan) -{ - int msr, delta; - int s; - register struct tty *tp; - struct com_s *com; - struct cdev *dev; - - dev=(struct cdev *)chan; - com = dev->si_drv1; - tp = dev->si_tty; - - s = spltty(); - msr = pc98_get_modem_status(com); - /* make change flag */ - delta = msr ^ com->pc98_prev_modem_status; - if ( delta & TIOCM_CAR ) { - if ( com->modem_car_chg_timer ) { - if ( -- com->modem_car_chg_timer ) - msr ^= TIOCM_CAR; - } else { - if ((com->modem_car_chg_timer = (msr & TIOCM_CAR) ? - DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE) != 0) - msr ^= TIOCM_CAR; - } - } else - com->modem_car_chg_timer = 0; - delta = ( msr ^ com->pc98_prev_modem_status ) & - (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); - com->pc98_prev_modem_status = msr; - delta = ( com->pc98_modem_delta |= delta ); - splx(s); - if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { - if ( delta ) { - commint(dev); - } - timeout(pc98_check_msr, (caddr_t)dev, - PC98_CHECK_MODEM_INTERVAL); - } else { - com->modem_checking = 0; - } -} - -static void -pc98_msrint_start(struct cdev *dev) -{ - struct com_s *com; - int s = spltty(); - - com = dev->si_drv1; - /* modem control line check routine envoke interval is 1/10 sec */ - if ( com->modem_checking == 0 ) { - com->pc98_prev_modem_status = pc98_get_modem_status(com); - com->pc98_modem_delta = 0; - timeout(pc98_check_msr, (caddr_t)dev, - PC98_CHECK_MODEM_INTERVAL); - com->modem_checking = 1; - } - splx(s); -} - -static void -pc98_disable_i8251_interrupt(struct com_s *com, int mod) -{ - /* disable interrupt */ - register int tmp; - - mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); - COM_INT_DISABLE - tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); - outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); - COM_INT_ENABLE -} - -static void -pc98_enable_i8251_interrupt(struct com_s *com, int mod) -{ - register int tmp; - - COM_INT_DISABLE - tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); - outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); - COM_INT_ENABLE -} - -static int -pc98_check_i8251_interrupt(struct com_s *com) -{ - return ( com->intr_enable & 0x07 ); -} - -static void -pc98_i8251_clear_cmd(struct com_s *com, int x) -{ - int tmp; - - COM_INT_DISABLE - tmp = com->pc98_prev_siocmd & ~(x); - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, 0); - outb(com->cmd_port, tmp); - com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, CTRL8251F_ENABLE); - COM_INT_ENABLE -} - -static void -pc98_i8251_or_cmd(struct com_s *com, int x) -{ - int tmp; - - COM_INT_DISABLE - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, 0); - tmp = com->pc98_prev_siocmd | (x); - outb(com->cmd_port, tmp); - com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, CTRL8251F_ENABLE); - COM_INT_ENABLE -} - -static void -pc98_i8251_set_cmd(struct com_s *com, int x) -{ - int tmp; - - COM_INT_DISABLE - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, 0); - tmp = (x); - outb(com->cmd_port, tmp); - com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, CTRL8251F_ENABLE); - COM_INT_ENABLE -} - -static void -pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) -{ - int tmp; - COM_INT_DISABLE - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, 0); - tmp = com->pc98_prev_siocmd & ~(clr); - tmp |= (x); - outb(com->cmd_port, tmp); - com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, CTRL8251F_ENABLE); - COM_INT_ENABLE -} - -static int -pc98_i8251_get_cmd(struct com_s *com) -{ - return com->pc98_prev_siocmd; -} - -static int -pc98_i8251_get_mod(struct com_s *com) -{ - return com->pc98_prev_siomod; -} - -static void -pc98_i8251_reset(struct com_s *com, int mode, int command) -{ - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, 0); - outb(com->cmd_port, 0); /* dummy */ - DELAY(2); - outb(com->cmd_port, 0); /* dummy */ - DELAY(2); - outb(com->cmd_port, 0); /* dummy */ - DELAY(2); - outb(com->cmd_port, CMD8251_RESET); /* internal reset */ - DELAY(2); - outb(com->cmd_port, mode ); /* mode register */ - com->pc98_prev_siomod = mode; - DELAY(2); - pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); - DELAY(10); - if (com->pc98_8251fifo_enable) - outb(I8251F_fcr, CTRL8251F_ENABLE | - CTRL8251F_XMT_RST | CTRL8251F_RCV_RST); -} - -static void -pc98_check_sysclock(void) -{ - /* get system clock from port */ - if ( pc98_machine_type & M_8M ) { - /* 8 MHz system & H98 */ - sysclock = 8; - } else { - /* 5 MHz system */ - sysclock = 5; - } -} - -static void -com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) -{ - int cfcr=0; - int previnterrupt; - u_int count; - - if (pc98_ttspeedtab(com, speed, &count) != 0) - return; - - previnterrupt = pc98_check_i8251_interrupt(com); - pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); - - switch ( cflag&CSIZE ) { - case CS5: - cfcr = MOD8251_5BITS; break; - case CS6: - cfcr = MOD8251_6BITS; break; - case CS7: - cfcr = MOD8251_7BITS; break; - case CS8: - cfcr = MOD8251_8BITS; break; - } - if ( cflag&PARENB ) { - if ( cflag&PARODD ) - cfcr |= MOD8251_PODD; - else - cfcr |= MOD8251_PEVEN; - } else - cfcr |= MOD8251_PDISAB; - - if ( cflag&CSTOPB ) - cfcr |= MOD8251_STOP2; - else - cfcr |= MOD8251_STOP1; - - if ( count & 0x10000 ) - cfcr |= MOD8251_CLKX1; - else - cfcr |= MOD8251_CLKX16; - - if (epson_machine_id != 0x20) { /* XXX */ - int tmp; - while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) - ; - } - /* set baud rate from ospeed */ - pc98_set_baud_rate( com, count ); - - if ( cfcr != pc98_i8251_get_mod(com) ) - pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); - - pc98_enable_i8251_interrupt( com, previnterrupt ); -} - -static int -pc98_ttspeedtab(struct com_s *com, int speed, u_int *divisor) -{ - int if_type, effect_sp, count = -1, mod; - - if_type = com->pc98_if_type & 0x0f; - - switch (com->pc98_if_type) { - case COM_IF_INTERNAL: - if (PC98SIO_baud_rate_port(if_type) != -1) { - count = ttspeedtab(speed, if_8251_type[if_type].speedtab); - if (count > 0) { - count |= COM1_EXT_CLOCK; - break; - } - } - - /* for *1CLK asynchronous! mode, TEFUTEFU */ - mod = (sysclock == 5) ? 2457600 : 1996800; - effect_sp = ttspeedtab( speed, pc98speedtab ); - if ( effect_sp < 0 ) /* XXX */ - effect_sp = ttspeedtab( (speed - 1), pc98speedtab ); - if ( effect_sp <= 0 ) - return effect_sp; - if ( effect_sp == speed ) - mod /= 16; - if ( mod % effect_sp ) - return(-1); - count = mod / effect_sp; - if ( count > 65535 ) - return(-1); - if ( effect_sp != speed ) - count |= 0x10000; - break; - case COM_IF_PC9861K_1: - case COM_IF_PC9861K_2: - count = 1; - break; - case COM_IF_IND_SS_1: - case COM_IF_IND_SS_2: - case COM_IF_PIO9032B_1: - case COM_IF_PIO9032B_2: - count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); - break; - case COM_IF_B98_01_1: - case COM_IF_B98_01_2: - count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); -#ifdef B98_01_OLD - if (count == 0 || count == 1) { - count += 4; - count |= 0x20000; /* x1 mode for 76800 and 153600 */ - } -#endif - break; - } - - if (count < 0) - return count; - - *divisor = (u_int) count; - return 0; -} - -static void -pc98_set_baud_rate( struct com_s *com, u_int count ) -{ - int if_type, io, s; - - if_type = com->pc98_if_type & 0x0f; - io = rman_get_start(com->ioportres) & 0xff00; - - switch (com->pc98_if_type) { - case COM_IF_INTERNAL: - if (PC98SIO_baud_rate_port(if_type) != -1) { - if (count & COM1_EXT_CLOCK) { - outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff); - break; - } else { - outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09); - } - } - - if (count == 0) - return; - - /* set i8253 */ - s = splclock(); - if (count != 3) - outb( 0x77, 0xb6 ); - else - outb( 0x77, 0xb4 ); - outb( 0x5f, 0); - outb( 0x75, count & 0xff ); - outb( 0x5f, 0); - outb( 0x75, (count >> 8) & 0xff ); - splx(s); - break; - case COM_IF_IND_SS_1: - case COM_IF_IND_SS_2: - outb(io | PC98SIO_intr_ctrl_port(if_type), 0); - outb(io | PC98SIO_baud_rate_port(if_type), 0); - outb(io | PC98SIO_baud_rate_port(if_type), 0xc0); - outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80); - outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff); - break; - case COM_IF_PIO9032B_1: - case COM_IF_PIO9032B_2: - outb(io | PC98SIO_baud_rate_port(if_type), count); - break; - case COM_IF_B98_01_1: - case COM_IF_B98_01_2: - outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f); -#ifdef B98_01_OLD - /* - * Some old B98_01 board should be controlled - * in different way, but this hasn't been tested yet. - */ - outb(io | PC98SIO_func_port(if_type), - (count & 0x20000) ? 0xf0 : 0xf2); -#endif - break; - } -} -static int -pc98_check_if_type(device_t dev, struct siodev *iod) -{ - int irr, io, if_type, tmp; - static short irq_tab[2][8] = { - { 3, 5, 6, 9, 10, 12, 13, -1}, - { 3, 10, 12, 13, 5, 6, 9, -1} - }; - - if_type = iod->if_type & 0x0f; - iod->irq = 0; - io = isa_get_port(dev) & 0xff00; - - if (IS_8251(iod->if_type)) { - if (PC98SIO_func_port(if_type) != -1) { - outb(io | PC98SIO_func_port(if_type), 0xf2); - tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab); - if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1) - outb(io | PC98SIO_baud_rate_port(if_type), tmp); - } - - iod->cmd = io | PC98SIO_cmd_port(if_type); - iod->sts = io | PC98SIO_sts_port(if_type); - iod->mod = io | PC98SIO_in_modem_port(if_type); - iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type); - - if (iod->if_type == COM_IF_INTERNAL) { - iod->irq = 4; - - if (pc98_check_8251vfast()) { - PC98SIO_baud_rate_port(if_type) = I8251F_div; - if_8251_type[if_type].speedtab = pc98fast_speedtab; - } - } else { - tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask; - if ((isa_get_port(dev) & 0xff) == IO_COM2) - iod->irq = irq_tab[0][tmp]; - else - iod->irq = irq_tab[1][tmp]; - } - } else { - irr = if_16550a_type[if_type].irr_read; -#ifdef COM_MULTIPORT - if (!COM_ISMULTIPORT(device_get_flags(dev)) || - device_get_unit(dev) == COM_MPMASTER(device_get_flags(dev))) -#endif - if (irr != -1) { - tmp = inb(io | irr); - if (isa_get_port(dev) & 0x01) /* XXX depend on RSB-384 */ - iod->irq = irq_tab[1][tmp >> 3]; - else - iod->irq = irq_tab[0][tmp & 0x07]; - } - } - if ( iod->irq == -1 ) return -1; - - return 0; -} -static void -pc98_set_ioport(struct com_s *com) -{ - int if_type = com->pc98_if_type & 0x0f; - Port_t io = rman_get_start(com->ioportres) & 0xff00; - - pc98_check_sysclock(); - com->data_port = io | PC98SIO_data_port(if_type); - com->cmd_port = io | PC98SIO_cmd_port(if_type); - com->sts_port = io | PC98SIO_sts_port(if_type); - com->in_modem_port = io | PC98SIO_in_modem_port(if_type); - com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(if_type); -} -static int -pc98_check_8251vfast(void) -{ - int i; - - outb(I8251F_div, 0x8c); - DELAY(10); - for (i = 0; i < 100; i++) { - if ((inb(I8251F_div) & 0x80) != 0) { - i = 0; - break; - } - DELAY(1); - } - outb(I8251F_div, 0); - DELAY(10); - for (; i < 100; i++) { - if ((inb(I8251F_div) & 0x80) == 0) - return 1; - DELAY(1); - } - - return 0; -} -static int -pc98_check_8251fifo(void) -{ - u_char tmp1, tmp2; - - tmp1 = inb(I8251F_iir); - DELAY(10); - tmp2 = inb(I8251F_iir); - if (((tmp1 ^ tmp2) & 0x40) != 0 && ((tmp1 | tmp2) & 0x20) == 0) - return 1; - - return 0; -} -#endif /* PC98 defined */ diff --git a/sys/pc98/pc98/sio_cbus.c b/sys/pc98/pc98/sio_cbus.c deleted file mode 100644 index a5c9946..0000000 --- a/sys/pc98/pc98/sio_cbus.c +++ /dev/null @@ -1,118 +0,0 @@ -/*- - * Copyright (c) 2001 Yoshihiro TAKAHASHI. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/module.h> -#include <sys/tty.h> -#include <machine/bus.h> -#include <sys/timepps.h> - -#include <dev/sio/siovar.h> - -#include <isa/isavar.h> - -static int sio_isa_attach(device_t dev); -static int sio_isa_probe(device_t dev); - -static device_method_t sio_isa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, sio_isa_probe), - DEVMETHOD(device_attach, sio_isa_attach), - DEVMETHOD(device_detach, siodetach), - - { 0, 0 } -}; - -static driver_t sio_isa_driver = { - sio_driver_name, - sio_isa_methods, - 0, -}; - -static struct isa_pnp_id sio_ids[] = { - {0x0100e4a5, "RSA-98III"}, - {0x4180a3b8, NULL}, /* NEC8041 - PC-9821CB-B04 */ - {0x0181a3b8, NULL}, /* NEC8101 - PC-9821CB2-B04 */ - {0x5181a3b8, NULL}, /* NEC8151 - Internal FAX/Modem for Cx3, Cb3 */ - {0x9181a3b8, NULL}, /* NEC8191 - NEC PC-9801-120 */ - {0xe181a3b8, NULL}, /* NEC81E1 - Internal FAX/Modem */ - {0x1182a3b8, NULL}, /* NEC8211 - PC-9801-123 */ - {0x3182a3b8, NULL}, /* NEC8231 - Internal FAX/Modem(Voice) */ - {0x4182a3b8, NULL}, /* NEC8241 - NEC PC-9821NR-B05 */ - {0x5182a3b8, NULL}, /* NEC8251 - Internel FAX/Modem */ - {0x7182a3b8, NULL}, /* NEC8271 - NEC PC-9801-125 */ - {0x11802fbf, NULL}, /* OYO8011 - Internal FAX/Modem for ValueStar(Ring) */ - {0} -}; - -static int -sio_isa_probe(dev) - device_t dev; -{ - int logical_id; - - /* Check isapnp ids */ - if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO) - return (ENXIO); - - logical_id = isa_get_logicalid(dev); - switch (logical_id) { - case 0x0100e4a5: /* RSA-98III */ - SET_FLAG(dev, SET_IFTYPE(COM_IF_RSA98III)); - break; - case 0x4180a3b8: /* PC-9821CB-B04 */ - case 0x0181a3b8: /* PC-9821CB2-B04 */ - case 0x5181a3b8: /* for Cx3, Cb3 internal */ - case 0x9181a3b8: /* PC-9801-120 */ - case 0xe181a3b8: /* Internal FAX/Modem */ - case 0x1182a3b8: /* PC-9801-123 */ - case 0x3182a3b8: /* FAX/Voice/Modem internal */ - case 0x4182a3b8: /* PC-9821NR-B05 */ - case 0x5182a3b8: /* FAX/Modem internal */ - case 0x7182a3b8: /* PC-9801-125 */ - case 0x11802fbf: /* for ValueStar internal */ - SET_FLAG(dev, SET_IFTYPE(COM_IF_NS16550)); - break; - } - - return (sioprobe(dev, 0, 0UL, 0)); -} - -static int -sio_isa_attach(dev) - device_t dev; -{ - return (sioattach(dev, 0, 0UL)); -} - -DRIVER_MODULE(sio, isa, sio_isa_driver, sio_devclass, 0, 0); diff --git a/sys/pc98/pc98/syscons_pc98.c b/sys/pc98/pc98/syscons_pc98.c deleted file mode 100644 index df8934e..0000000 --- a/sys/pc98/pc98/syscons_pc98.c +++ /dev/null @@ -1,265 +0,0 @@ -/*- - * Copyright (c) 1999 FreeBSD(98) Porting Team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer as - * the first lines of this file unmodified. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "opt_syscons.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/cons.h> -#include <sys/consio.h> -#include <sys/sysctl.h> - -#include <machine/clock.h> - -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> - -#include <dev/syscons/syscons.h> - -#include <i386/isa/timerreg.h> - -#include <isa/isavar.h> - -static devclass_t sc_devclass; - -static sc_softc_t main_softc; -#ifdef SC_NO_SUSPEND_VTYSWITCH -static int sc_no_suspend_vtswitch = 1; -#else -static int sc_no_suspend_vtswitch = 0; -#endif -static int sc_cur_scr; - -TUNABLE_INT("hw.syscons.sc_no_suspend_vtswitch", (int *)&sc_no_suspend_vtswitch); -SYSCTL_DECL(_hw_syscons); -SYSCTL_INT(_hw_syscons, OID_AUTO, sc_no_suspend_vtswitch, CTLFLAG_RW, - &sc_no_suspend_vtswitch, 0, "Disable VT switch before suspend."); - -static void -scidentify (driver_t *driver, device_t parent) -{ - BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "sc", 0); -} - -static int -scprobe(device_t dev) -{ - /* No pnp support */ - if (isa_get_vendorid(dev)) - return (ENXIO); - - device_set_desc(dev, "System console"); - return sc_probe_unit(device_get_unit(dev), device_get_flags(dev)); -} - -static int -scattach(device_t dev) -{ - return sc_attach_unit(device_get_unit(dev), device_get_flags(dev)); -} - -static int -scsuspend(device_t dev) -{ - int retry = 10; - static int dummy; - sc_softc_t *sc; - - sc = &main_softc; - - if (sc->cur_scp == NULL) - return (0); - - sc_cur_scr = sc->cur_scp->index; - - if (sc_no_suspend_vtswitch) - return (0); - - do { - sc_switch_scr(sc, 0); - if (!sc->switch_in_progress) { - break; - } - tsleep(&dummy, 0, "scsuspend", 100); - } while (retry--); - - return (0); -} - -static int -scresume(device_t dev) -{ - sc_softc_t *sc; - - if (sc_no_suspend_vtswitch) - return (0); - - sc = &main_softc; - sc_switch_scr(sc, sc_cur_scr); - - return (0); -} - -int -sc_max_unit(void) -{ - return devclass_get_maxunit(sc_devclass); -} - -sc_softc_t -*sc_get_softc(int unit, int flags) -{ - sc_softc_t *sc; - - if (unit < 0) - return NULL; - if (flags & SC_KERNEL_CONSOLE) { - /* FIXME: clear if it is wired to another unit! */ - sc = &main_softc; - } else { - sc = (sc_softc_t *)device_get_softc(devclass_get_device(sc_devclass, unit)); - if (sc == NULL) - return NULL; - } - sc->unit = unit; - if (!(sc->flags & SC_INIT_DONE)) { - sc->keyboard = -1; - sc->adapter = -1; - sc->mouse_char = SC_MOUSE_CHAR; - } - return sc; -} - -sc_softc_t -*sc_find_softc(struct video_adapter *adp, struct keyboard *kbd) -{ - sc_softc_t *sc; - int units; - int i; - - sc = &main_softc; - if (((adp == NULL) || (adp == sc->adp)) - && ((kbd == NULL) || (kbd == sc->kbd))) - return sc; - units = devclass_get_maxunit(sc_devclass); - for (i = 0; i < units; ++i) { - sc = (sc_softc_t *)device_get_softc(devclass_get_device(sc_devclass, i)); - if (sc == NULL) - continue; - if (((adp == NULL) || (adp == sc->adp)) - && ((kbd == NULL) || (kbd == sc->kbd))) - return sc; - } - return NULL; -} - -int -sc_get_cons_priority(int *unit, int *flags) -{ - const char *at; - int u, f; - - *unit = -1; - for (u = 0; u < 16; u++) { - if (resource_disabled(SC_DRIVER_NAME, u)) - continue; - if (resource_string_value(SC_DRIVER_NAME, u, "at", &at) != 0) - continue; - if (resource_int_value(SC_DRIVER_NAME, u, "flags", &f) != 0) - f = 0; - if (f & SC_KERNEL_CONSOLE) { - /* the user designates this unit to be the console */ - *unit = u; - *flags = f; - break; - } - if (*unit < 0) { - /* ...otherwise remember the first found unit */ - *unit = u; - *flags = f; - } - } - if (*unit < 0) - return CN_DEAD; - return CN_INTERNAL; -} - -void -sc_get_bios_values(bios_values_t *values) -{ - values->cursor_start = 15; - values->cursor_end = 16; - values->shift_state = 0; - if (pc98_machine_type & M_8M) - values->bell_pitch = BELL_PITCH_8M; - else - values->bell_pitch = BELL_PITCH_5M; -} - -int -sc_tone(int herz) -{ - int pitch; - - if (herz) { - /* enable counter 1 */ - outb(0x35, inb(0x35) & 0xf7); - /* set command for counter 1, 2 byte write */ - if (acquire_timer1(TIMER_16BIT | TIMER_SQWAVE)) - return EBUSY; - /* set pitch */ - pitch = timer_freq/herz; - outb(TIMER_CNTR1, pitch); - outb(TIMER_CNTR1, pitch >> 8); - } else { - /* disable counter 1 */ - outb(0x35, inb(0x35) | 0x08); - release_timer1(); - } - return 0; -} - -static device_method_t sc_methods[] = { - DEVMETHOD(device_identify, scidentify), - DEVMETHOD(device_probe, scprobe), - DEVMETHOD(device_attach, scattach), - DEVMETHOD(device_suspend, scsuspend), - DEVMETHOD(device_resume, scresume), - { 0, 0 } -}; - -static driver_t sc_driver = { - SC_DRIVER_NAME, - sc_methods, - sizeof(sc_softc_t), -}; - -DRIVER_MODULE(sc, isa, sc_driver, sc_devclass, 0, 0); diff --git a/sys/pccard/pccard_nbk.c b/sys/pccard/pccard_nbk.c index 3772ba8..bda9db1 100644 --- a/sys/pccard/pccard_nbk.c +++ b/sys/pccard/pccard_nbk.c @@ -64,7 +64,7 @@ /* XXX Shouldn't reach into the MD code here */ #ifdef PC98 -#include <pc98/pc98/pc98.h> +#include <pc98/cbus/cbus.h> #else #include <i386/isa/isa.h> #endif |