diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-21 00:55:32 +0000 |
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-21 00:55:32 +0000 |
| commit | 76b5366091f76c9bc73570149ef5055648fc2c39 (patch) | |
| tree | 590d020e0f2a5bea6e09d66d951a674443b21d67 /sys/pc98 | |
| parent | 4b4d01da6f07f7754ff6a6e4f5223e9f0984d1a6 (diff) | |
This commit was manufactured by cvs2svn to create tagrelease/3.0.0
'RELENG_3_0_0_RELEASE'.
Diffstat (limited to 'sys/pc98')
39 files changed, 9457 insertions, 6120 deletions
diff --git a/sys/pc98/boot/Makefile.inc b/sys/pc98/boot/Makefile.inc index 88916943ec96..c02d4d7980f0 100644 --- a/sys/pc98/boot/Makefile.inc +++ b/sys/pc98/boot/Makefile.inc @@ -1,7 +1,5 @@ -# $Id: Makefile.inc,v 1.3 1998/03/14 02:33:54 kato Exp $ +# $Id: Makefile.inc,v 1.2 1998/03/14 02:29:24 kato Exp $ -BINDIR?= /usr/mdec -CFLAGS+= -aout .if exists(${.CURDIR}/../../../../include) CFLAGS+= -nostdinc -I${.CURDIR}/../../../../include .endif diff --git a/sys/pc98/boot/biosboot/Makefile b/sys/pc98/boot/biosboot/Makefile index 3a2640c950d3..cef96e0f6c15 100644 --- a/sys/pc98/boot/biosboot/Makefile +++ b/sys/pc98/boot/biosboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.21 1999/01/03 05:03:46 kato Exp $ +# $Id: Makefile,v 1.18 1998/05/28 13:46:04 kato Exp $ # PROG= boot @@ -6,6 +6,7 @@ PROG= boot SRCS= start.S table.c boot2.S boot.c asm.S bios.S serial.S SRCS+= probe_keyboard.c io.c disk.c sys.c +BINDIR= /usr/mdec BINMODE= 444 CFLAGS= -O2 -malign-functions=0 -malign-jumps=0 -malign-loops=0 \ -mno-486 \ @@ -15,8 +16,7 @@ CFLAGS+= ${CWARNFLAGS} # By default, if a serial port is going to be used as console, use COM1 # (aka /dev/ttyd0). -#BOOT_COMCONSOLE_PORT?=0x30 -BOOT_COMCONSOLE_PORT?=0x238 +BOOT_COMCONSOLE_PORT?=0x30 BOOT_COMCONSOLE_CLK?=16 BOOT_COMCONSOLE_MODE=0x0c CFLAGS+= -DCOMCONSOLE=${BOOT_COMCONSOLE_PORT} \ @@ -24,8 +24,8 @@ CFLAGS+= -DCOMCONSOLE=${BOOT_COMCONSOLE_PORT} \ -DCOMCONSOLE_MODE=${BOOT_COMCONSOLE_MODE} # feature not implemented -BOOT_COMCONSOLE_SPEED?=9600 -CFLAGS+= -DCONSPEED=${BOOT_COMCONSOLE_SPEED} +# BOOT_COMCONSOLE_SPEED?=9600 +# CFLAGS+= -DCONSPEED=${BOOT_COMCONSOLE_SPEED} # Enable code to take the default boot string from a fixed location on the # disk. See nextboot(8) and README.386BSD for more info. @@ -64,8 +64,8 @@ BOOTSTACK= 0xFFF0 boot.strip: boot cp -p boot boot.strip - strip -aout boot.strip - size -aout boot.strip + strip boot.strip + size boot.strip boot.nohdr: boot.strip dd if=boot.strip of=boot.nohdr ibs=32 skip=1 obs=1024b @@ -86,11 +86,19 @@ boot2: boot.nohdr all: boot1 boot2 install: - ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ - boot1 boot2 ${DESTDIR}${BINDIR}/ + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ + boot1 ${DESTDIR}${BINDIR}/boot1 + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ + boot2 ${DESTDIR}${BINDIR}/boot2 + for i in da fd wd od vn wfd ; do \ + ( cd ${DESTDIR}${BINDIR} ; \ + rm -f boot$${i} $${i}boot ; \ + ln -s boot1 $${i}boot ; \ + ln -s boot2 boot$${i} ; ) \ + done install-boothelp: - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \ + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ ${.CURDIR}/boot.help ${DESTDIR}/ .include <bsd.kern.mk> diff --git a/sys/pc98/boot/biosboot/README.serial b/sys/pc98/boot/biosboot/README.serial index bf47e6c4a470..5adbfa941233 100644 --- a/sys/pc98/boot/biosboot/README.serial +++ b/sys/pc98/boot/biosboot/README.serial @@ -105,7 +105,7 @@ To boot FreeBSD in serial console mode, you must do the following: higher priority console). This replaces the COMCONSOLE option. Example: - device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 + device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr If the flags were not set, you need to run UserConfig (on a different console) or recompile the kernel. @@ -185,7 +185,7 @@ CAVEATS: `flags' for the serial port you want to use. For example, if you want to make COM2 the console: - device sio1 at isa? port "IO_COM2" tty flags 0x10 irq 3 + device sio1 at isa? port "IO_COM2" tty flags 0x10 irq 3 vector siointr The console flags for the other serial ports should not be set. o Recompile both the boot blocks and the kernel. @@ -193,4 +193,4 @@ CAVEATS: from the new kernel. -$Id: README.serial,v 1.5 1998/04/07 15:33:47 kato Exp $ +$Id: README.serial,v 1.4 1997/06/09 13:44:03 kato Exp $ diff --git a/sys/pc98/boot/biosboot/serial.S b/sys/pc98/boot/biosboot/serial.S index 2cc22465fe79..ebf1c5e9c0c9 100644 --- a/sys/pc98/boot/biosboot/serial.S +++ b/sys/pc98/boot/biosboot/serial.S @@ -24,7 +24,7 @@ * the rights to redistribute these changes. * * from: Mach, Revision 2.2 92/04/04 11:34:26 rpd - * $Id: serial.S,v 1.7 1998/01/02 09:29:15 kato Exp $ + * $Id: serial.S,v 1.6 1997/07/14 12:34:01 kato Exp $ */ /* @@ -65,16 +65,17 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. */ -#if COMCONSOLE == 0x238 -#include "../../../i386/boot/biosboot/serial.S" -#else /* * modified for PC-98 by KATO T. of Nagoya University */ .file "serial.S" +#ifdef PC98 +#include <pc98/pc98/sioreg.h> +#else #include <i386/isa/sioreg.h> +#endif #include "asm.h" .text @@ -198,4 +199,3 @@ ENTRY(init_serial) outb %al, %dx ret -#endif diff --git a/sys/pc98/boot/kzipboot/Makefile b/sys/pc98/boot/kzipboot/Makefile index beb70a5e56cc..f97824c40ed5 100644 --- a/sys/pc98/boot/kzipboot/Makefile +++ b/sys/pc98/boot/kzipboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.6 1998/05/28 13:48:40 kato Exp $ +# $Id: Makefile,v 1.5 1998/03/07 15:48:11 kato Exp $ PROG= kztail.o kzhead.o BINMODE = 444 # target is a relocatable object @@ -22,9 +22,9 @@ CFLAGS+= -DKZIP -DCOMCONSOLE=0x30 CFLAGS+= -DPC98 kztail.o: ${OBJS_KZTAIL} - $(LD) -aout -r -x -o kztail.o $(OBJS_KZTAIL) + $(LD) -r -x -o kztail.o $(OBJS_KZTAIL) kzhead.o: ${OBJS_KZHEAD} - $(LD) -aout -r -x -o kzhead.o $(OBJS_KZHEAD) + $(LD) -r -x -o kzhead.o $(OBJS_KZHEAD) .include <bsd.prog.mk> diff --git a/sys/pc98/boot/kzipboot/malloc.c b/sys/pc98/boot/kzipboot/malloc.c index 052e5e357dbb..cf51be721a51 100644 --- a/sys/pc98/boot/kzipboot/malloc.c +++ b/sys/pc98/boot/kzipboot/malloc.c @@ -36,8 +36,9 @@ extern unsigned char *storage; void * -kzipmalloc(nbytes) +malloc(nbytes, junk1, junk2) /* junk? not used */ size_t nbytes; + int junk1, junk2; { unsigned char *p = storage; storage += nbytes; @@ -50,7 +51,8 @@ kzipmalloc(nbytes) } void -kzipfree(cp) +free(cp, junk) /* junk not used */ void *cp; + int junk; { } diff --git a/sys/pc98/boot/netboot/Makefile b/sys/pc98/boot/netboot/Makefile index dad72fc3b15d..37bfd672afab 100644 --- a/sys/pc98/boot/netboot/Makefile +++ b/sys/pc98/boot/netboot/Makefile @@ -36,6 +36,7 @@ PROG= nb8390.com nb8390.rom # Order is very important on the SRCS line for this prog SRCS= start2.S main.c misc.c bootmenu.c rpc.c +BINDIR= /usr/mdec BINMODE= 555 CFLAGS= -O2 -DNFS -DROMSIZE=${ROMSIZE} -DRELOC=${RELOCADDR} -DASK_BOOT CFLAGS+= -DPC98 @@ -47,12 +48,10 @@ CFLAGS+= -DPC98 NS8390= -DINCLUDE_EGY -DNE_BASE=0xd0 CLEANFILES+= netboot.com CLEANFILES+= makerom start2.ro 3c509.o ns8390.o -ROMLDFLAGS= ${LDFLAGS} -aout -N -T ${RELOCADDR} -e _start -nostdlib +ROMLDFLAGS= ${LDFLAGS} -N -T ${RELOCADDR} -e _start -nostdlib NOSHARED= YES NOMAN= -SIZE= size -aout STRIP= -STRIPCMD= strip -aout ROMSIZE=16384 RELOCADDR=0x90000 @@ -73,27 +72,27 @@ makerom: makerom.c nb8390.rom: makerom start2.ro ${SRCS:N*.h:R:S/$/.o/g} ns8390.o ${LD} ${ROMLDFLAGS} -o ${.TARGET} ${OBJS:S/start2.o/start2.ro/} ns8390.o - ${STRIPCMD} ${.TARGET} - ${SIZE} ${.TARGET} + strip ${.TARGET} + size ${.TARGET} ${.OBJDIR}/makerom ${.TARGET} nb3c509.rom: makerom start2.ro ${SRCS:N*.h:R:S/$/.o/g} 3c509.o ${LD} ${ROMLDFLAGS} -o ${.TARGET} ${OBJS:S/start2.o/start2.ro/} 3c509.o - ${STRIPCMD} ${.TARGET} - ${SIZE} ${.TARGET} + strip ${.TARGET} + size ${.TARGET} ${.OBJDIR}/makerom ${.TARGET} nb8390.com: makerom start2.ro ${SRCS:N*.h:R:S/$/.o/g} ns8390.o ${LD} ${ROMLDFLAGS} -o ${.TARGET}.tmp ${OBJS} ns8390.o - ${STRIPCMD} ${.TARGET}.tmp - ${SIZE} ${.TARGET}.tmp + strip ${.TARGET}.tmp + size ${.TARGET}.tmp dd ibs=32 skip=1 if=${.TARGET}.tmp of=${.TARGET} rm -f ${.TARGET}.tmp nb3c509.com: start2.o ${SRCS:N*.h:R:S/$/.o/g} 3c509.o ${LD} ${ROMLDFLAGS} -o ${.TARGET}.tmp ${OBJS} 3c509.o - ${STRIPCMD} ${.TARGET}.tmp - ${SIZE} ${.TARGET}.tmp + strip ${.TARGET}.tmp + size ${.TARGET}.tmp dd ibs=32 skip=1 if=${.TARGET}.tmp of=${.TARGET} rm -f ${.TARGET}.tmp diff --git a/sys/pc98/boot/rawboot/Makefile b/sys/pc98/boot/rawboot/Makefile index 7aafe0de65fd..b549f42f07d8 100644 --- a/sys/pc98/boot/rawboot/Makefile +++ b/sys/pc98/boot/rawboot/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.11 1998/03/30 12:24:12 kato Exp $ +# $Id: Makefile,v 1.10 1998/03/14 02:30:01 kato Exp $ # PROG= boot @@ -9,6 +9,7 @@ SRCS+= probe_keyboard.c io.c disk.c sys.c .PATH: ${.CURDIR}/../biosboot +BINDIR= /usr/mdec BINMODE= 444 CFLAGS= -O2 -malign-functions=0 -malign-jumps=0 -malign-loops=0 \ -DPC98 \ @@ -68,8 +69,8 @@ BOOTSTACK= 0xFFF0 boot.strip: boot cp -p boot boot.strip - strip -aout boot.strip - size -aout boot.strip + strip boot.strip + size boot.strip boot.nohdr: boot.strip dd if=boot.strip of=boot.nohdr ibs=32 skip=1 obs=1024b diff --git a/sys/pc98/conf/GENERIC98 b/sys/pc98/conf/GENERIC98 index 87d05b6cdad8..90ae50c81a55 100644 --- a/sys/pc98/conf/GENERIC98 +++ b/sys/pc98/conf/GENERIC98 @@ -11,7 +11,7 @@ # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # -# $Id: GENERIC98,v 1.62 1999/01/16 13:20:42 kato Exp $ +# $Id: GENERIC98,v 1.49 1998/10/11 15:00:24 kato Exp $ # GENERIC98 -- Generic PC98 machine with WD/SCSI disks @@ -41,7 +41,7 @@ options SCSI_DELAY=15000 #Be pessimistic about Joe SCSI device options EPSON_BOUNCEDMA #use bounce buufer for 15-16M #options EPSON_MEMWIN #EPSON memory window support options UCONSOLE #Allow users to grab the console -#options "LINE30" +options "LINE30" options FAILSAFE #Be conservative options USERCONFIG #boot -c editor options VISUAL_USERCONFIG #visual boot -c editor @@ -58,26 +58,18 @@ options COM_MULTIPORT config kernel root on wd0 -# To make an SMP kernel, the next two are needed -#options SMP # Symmetric MultiProcessor Kernel -#options APIC_IO # Symmetric (APIC) I/O -# Optionally these may need tweaked, (defaults shown): -#options NCPU=2 # number of CPUs -#options NBUS=4 # number of busses -#options NAPIC=1 # number of IO APICs -#options NINTR=24 # number of INTs - controller isa0 controller pci0 -controller fdc0 at isa? port "IO_FD1" bio irq 11 drq 2 +controller fdc0 at isa? port "IO_FD1" bio irq 11 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 disk fd2 at fdc0 drive 2 disk fd3 at fdc0 drive 3 +tape ft0 at fdc0 drive 4 # options "CMD640" # work around CMD640 chip deficiency -controller wdc0 at isa? port "IO_WD1" bio irq 9 +controller wdc0 at isa? port "IO_WD1" bio irq 9 vector wdintr disk wd0 at wdc0 drive 0 #disk wd1 at wdc0 drive 1 #disk wd2 at wdc0 drive 2 @@ -85,11 +77,12 @@ disk wd0 at wdc0 drive 0 options ATAPI # Enable ATAPI support for IDE bus options ATAPI_STATIC #Don't do it as an LKM -device acd0 #IDE CD-ROM +device wcd0 #IDE CD-ROM -# A single entry for any of these controllers (ncr, ahb, ahc) is +# A single entry for any of these controllers (ncr, ahb, ahc) is sufficient # for any number of installed devices. controller ncr0 +#controller amd0 controller ahc0 controller isp0 @@ -100,19 +93,19 @@ controller isp0 options BS_TARG_SAFEMODE # PC-9801-92 -#controller bs0 at isa? port IO_SCSI bio irq 5 drq 3 flags 0 +controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0 vector bsintr # SC-98 -# controller bs0 at isa? port IO_SCSI bio irq 5 drq 3 flags 0x10000 +# controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x10000 vector bsintr # HA-55BS2 and later -#controller bs0 at isa? port IO_SCSI bio irq 5 drq 3 flags 0x20000 +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x20000 vector bsintr # ELECOM type -#controller bs0 at isa? port IO_SCSI bio irq 5 drq 3 flags 0x30000 +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x30000 vector bsintr # SMIT -#controller bs0 at isa? port IO_SCSI bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 vector bsintr # Logitec LHA-20x -#controller bs0 at isa? port IO_SCSI bio irq 5 drq 3 flags 0x50000 +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x50000 vector bsintr -#controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 +#controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 vector aicintr controller scbus0 @@ -126,17 +119,11 @@ device cd0 #Only need one of these, the code dynamically grows controller matcd0 at isa? port? bio -# keyboard driver -device pckbd0 at isa? port IO_KBD tty irq 1 -#options KBD_INSTALL_CDEV - -device gdc0 at isa? - -#pseudo-device splash +# syscons is the default console driver, resembling an SCO console +device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr +#options XSERVER # support for X server -device sc0 at isa? tty - -device npx0 at isa? port IO_NPX irq 8 +device npx0 at isa? port "IO_NPX" irq 8 vector npxintr # # Laptop support (see LINT for more options) @@ -148,36 +135,12 @@ device apm0 at isa? disable flags 0x31 # Advanced Power Management #device pcic0 at card? #device pcic1 at card? -# -# Serial Interface -# -# COM1 -device sio0 at isa? port "IO_COM1" tty irq 4 -# COM2 (2nd CCU) -device sio1 at isa? port 0x238 tty irq 5 flags 0x12000000 -# PC-9861K, PC-9801-101, MDC-926Rs -#device sio1 at isa? port "IO_COM2" tty irq 5 flags 0x01000000 -#device sio2 at isa? port "IO_COM3" tty irq 6 flags 0x02000000 -# PC-9801-120 (PnP off) -#device sio1 at isa? port 0x8b0 tty irq 5 flags 0x11000000 -# MC-16550II, MC-RS98 -#device sio1 at isa? port 0xd2 tty irq 5 flags 0x14000101 -#device sio2 at isa? port 0x8d2 tty flags 0x14000101 -# RSB-2000, RSB-3000, B98-02 -#device sio1 at isa? port 0xb0 tty flags 0x15000101 -#device sio2 at isa? port 0xb1 tty flags 0x15000101 -# RSB-384 -#device sio1 at isa? port 0xb0 tty flags 0x16000000 -#device sio2 at isa? port 0xb1 tty flags 0x16000000 -# RSA-98III -#device sio1 at isa? port 0x50e0 tty irq 5 flags 0x18000101 -#device sio2 at isa? port 0x51e0 tty flags 0x18000101 -# ESP98 -#options COM_ESP -#device sio1 at isa? port 0x18b0 tty irq 5 flags 0x19000000 +device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr +device sio1 at isa? port 0xd2 tty irq 5 flags 0x101 vector siointr +device sio2 at isa? port 0x8d2 tty flags 0x101 vector siointr -device lpt0 at isa? port IO_LPT tty -device mse0 at isa? port IO_MSE tty irq 13 +device lpt0 at isa? port "IO_LPT" tty +device mse0 at isa? port "IO_MSE" tty irq 13 vector mseintr # Order is important here due to intrusive probes, do *not* alphabetize # this list of network interfaces until the probes have been fixed. @@ -185,14 +148,9 @@ device mse0 at isa? port IO_MSE tty irq 13 # revision 1.20 of this file. device de0 device fxp0 -device mx0 -device pn0 -device rl0 device tl0 device tx0 -device vr0 device vx0 -device wb0 # # DP8390 NIC @@ -210,30 +168,30 @@ device wb0 # fe0: RE1000/1000Plus # fe1: C-NET(98)P2/C-NET(9N)E # -device ed0 at isa? port 0x00d0 net irq 6 -device ed5 at isa? port 0x00d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0x600000 -device ed1 at isa? port 0x00d8 net irq 6 flags 0x200000 -device ed3 at isa? port 0x00d0 net irq 6 flags 0x400000 -device ed4 at isa? port 0x56d0 net irq 5 flags 0x500000 -device ed2 at isa? port 0x00d8 net irq 6 flags 0x300000 -device ed7 at isa? port 0x00d0 net irq 6 flags 0x900000 -device ed6 at isa? port 0x0770 net irq 6 flags 0x800000 -device ed9 at isa? port 0x03d0 net irq 6 flags 0xb00000 -device ed8 at isa? port 0xa3d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0xa00000 +device ed0 at isa? port 0x00d0 net irq 6 vector edintr +device ed1 at isa? port 0x00d8 net irq 6 flags 0x200000 vector edintr +device ed2 at isa? port 0x00d8 net irq 6 flags 0x300000 vector edintr +device ed3 at isa? port 0x00d0 net irq 6 flags 0x400000 vector edintr +device ed4 at isa? port 0x56d0 net irq 5 flags 0x500000 vector edintr +device ed5 at isa? port 0x00d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0x600000 vector edintr +device ed6 at isa? port 0x0770 net irq 6 flags 0x800000 vector edintr +device ed7 at isa? port 0x00d0 net irq 6 flags 0x900000 vector edintr +device ed8 at isa? port 0xa3d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0xa00000 vector edintr +device ed9 at isa? port 0x03d0 net irq 6 flags 0xb00000 vector edintr -device ep0 at isa? port 0x40d0 net irq 3 -device fe0 at isa? port 0x00d0 net irq 3 -device fe1 at isa? port 0x73d0 net irq 5 -device lnc0 at isa? port 0x03d0 net irq 6 -device zp0 at isa? port 0x00d0 net irq 10 iomem 0xe0000 +device ep0 at isa? port 0x40d0 net irq 3 vector epintr +device fe0 at isa? port 0x00d0 net irq 3 vector feintr +device fe1 at isa? port 0x73d0 net irq 5 vector feintr +device lnc0 at isa? port 0x03d0 net irq 6 vector lncintr +device zp0 at isa? port 0x00d0 net irq 10 iomem 0xe0000 vector zpintr #controller snd0 -#device sb0 at isa? port 0x20d2 irq 10 conflicts drq 3 +#device sb0 at isa? port 0x20d2 irq 10 conflicts drq 3 vector sbintr #device sbxvi0 at isa? drq 3 #device sbmidi0 at isa? port 0x80d2 #device opl0 at isa? port 0x28d2 -#device pcm0 at isa? port 0xa460 irq 12 -#device mss0 at isa? port 0xf40 irq 12 drq 1 +#device pcm0 at isa? port 0xa460 irq 12 vector pcmintr +#device mss0 at isa? port 0xf40 irq 12 drq 1 vector adintr pseudo-device loop pseudo-device ether @@ -248,8 +206,3 @@ pseudo-device gzip # Exec gzipped a.out's # the costs of each syscall. options KTRACE #kernel tracing -# The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be -# aware of the legal and administrative consequences of enabling this -# option. The number of devices determines the maximum number of -# simultaneous BPF clients programs runnable. -#pseudo-device bpfilter 4 #Berkeley packet filter diff --git a/sys/pc98/conf/GENERICupgrade b/sys/pc98/conf/GENERICupgrade new file mode 100644 index 000000000000..f07a434b2e7b --- /dev/null +++ b/sys/pc98/conf/GENERICupgrade @@ -0,0 +1,204 @@ +# +# GENERICupgrade (a copy of GENERIC98) +# +# This config file is used by the aout->elf transition build on systems +# not running a 3.0-CURRENT kernel. Unless a kernel is built and installed +# as part of the upgrade, the system will be hosed by the installation +# of the 3.0 binaries and subsequent reboot. If the transition build is +# being perfomed on a machine for which this config file is inappropriate, +# it should be replaced with a suitable one prior to performing the upgrade. +# +# $Id: GENERICupgrade,v 1.3 1998/09/22 16:10:40 kato Exp $ +# + +# GENERIC98 -- Generic PC98 machine with WD/SCSI disks + +machine "pc98" +cpu "I386_CPU" +cpu "I486_CPU" +cpu "I586_CPU" +cpu "I686_CPU" +ident "GENERIC98" +maxusers 32 + +options "PC98" #PC98 +options MATH_EMULATE #Support for x87 emulation +options INET #InterNETworking +options FFS #Berkeley Fast Filesystem +options NFS #Network Filesystem +options MSDOSFS #MSDOS Filesystem +options "CD9660" #ISO 9660 Filesystem +options "CD9660_ROOT" #CD-ROM usable as root device +options FFS_ROOT #FFS usable as root device [keep this!] +options NFS_ROOT #NFS usable as root device +options PROCFS #Process filesystem +options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=15 #Be pessimistic about Joe SCSI device +options EPSON_BOUNCEDMA #use bounce buufer for 15-16M +#options EPSON_MEMWIN #EPSON memory window support +options UCONSOLE #Allow users to grab the console +options "LINE30" +options FAILSAFE #Be conservative +options USERCONFIG #boot -c editor +options VISUAL_USERCONFIG #visual boot -c editor + +options SYSVSHM +options SYSVSEM +options SYSVMSG + +options COM_MULTIPORT + +# +# IBM-PC HDD support +#options COMPAT_ATDISK + +config kernel root on wd0 + +controller isa0 +controller pci0 + +controller fdc0 at isa? port "IO_FD1" bio irq 11 drq 2 vector fdintr +disk fd0 at fdc0 drive 0 +disk fd1 at fdc0 drive 1 +disk fd2 at fdc0 drive 2 +disk fd3 at fdc0 drive 3 +tape ft0 at fdc0 drive 4 + +# options "CMD640" # work around CMD640 chip deficiency +controller wdc0 at isa? port "IO_WD1" bio irq 9 vector wdintr +disk wd0 at wdc0 drive 0 +#disk wd1 at wdc0 drive 1 +#disk wd2 at wdc0 drive 2 +#disk wd3 at wdc0 drive 3 + +options ATAPI # Enable ATAPI support for IDE bus +options ATAPI_STATIC #Don't do it as an LKM +device wcd0 #IDE CD-ROM + +# A single entry for any of these controllers (ncr, ahb, ahc) is sufficient +# for any number of installed devices. +controller ncr0 +#controller amd0 +controller ahc0 +controller isp0 + +# +# WD33C93 SCSI card (55/92 like board) +# + +options BS_TARG_SAFEMODE + +# PC-9801-92 +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0 vector bsintr +# SC-98 +# controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x10000 vector bsintr +# HA-55BS2 and later +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x20000 vector bsintr +# ELECOM type +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x30000 vector bsintr +# SMIT +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 vector bsintr +# Logitec LHA-20x +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x50000 vector bsintr + +#controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 vector aicintr + +controller scbus0 + +device da0 + +device sa0 + +device pass0 + +device cd0 #Only need one of these, the code dynamically grows + +controller matcd0 at isa? port? bio + +# syscons is the default console driver, resembling an SCO console +device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr +#options XSERVER # support for X server + +device npx0 at isa? port "IO_NPX" irq 8 vector npxintr + +# +# Laptop support (see LINT for more options) +# +device apm0 at isa? disable flags 0x31 # Advanced Power Management + +# PCCARD (PCMCIA) support +#controller card0 +#device pcic0 at card? +#device pcic1 at card? + +device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr +device sio1 at isa? port 0xd2 tty irq 5 flags 0x101 vector siointr +device sio2 at isa? port 0x8d2 tty flags 0x101 vector siointr + +device lpt0 at isa? port "IO_LPT" tty +device mse0 at isa? port "IO_MSE" tty irq 13 vector mseintr + +# Order is important here due to intrusive probes, do *not* alphabetize +# this list of network interfaces until the probes have been fixed. +# Right now it appears that the ie0 must be probed before ep0. See +# revision 1.20 of this file. +device de0 +device fxp0 +device tl0 +device tx0 +device vx0 + +# +# DP8390 NIC +# +# ed0: generic driver +# ed1: LANEED LD-BDN +# ed2: EGY-98 +# ed3: LGY-98 +# ed4: ICM-IF-2766/EN-2298-T +# ed5: SIC-98 +# ed6: PC-9801-108 +# ed7: LA-98 +# ed8: C-NET(98) +# ed9: C-NET(98)E/L +# fe0: RE1000/1000Plus +# fe1: C-NET(98)P2/C-NET(9N)E +# +device ed0 at isa? port 0x00d0 net irq 6 vector edintr +device ed1 at isa? port 0x00d8 net irq 6 flags 0x200000 vector edintr +device ed2 at isa? port 0x00d8 net irq 6 flags 0x300000 vector edintr +device ed3 at isa? port 0x00d0 net irq 6 flags 0x400000 vector edintr +device ed4 at isa? port 0x56d0 net irq 5 flags 0x500000 vector edintr +device ed5 at isa? port 0x00d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0x600000 vector edintr +device ed6 at isa? port 0x0770 net irq 6 flags 0x800000 vector edintr +device ed7 at isa? port 0x00d0 net irq 6 flags 0x900000 vector edintr +device ed8 at isa? port 0xa3d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0xa00000 vector edintr +device ed9 at isa? port 0x03d0 net irq 6 flags 0xb00000 vector edintr + +device ep0 at isa? port 0x40d0 net irq 3 vector epintr +device fe0 at isa? port 0x00d0 net irq 3 vector feintr +device fe1 at isa? port 0x73d0 net irq 5 vector feintr +device lnc0 at isa? port 0x03d0 net irq 6 vector lncintr +device zp0 at isa? port 0x00d0 net irq 10 iomem 0xe0000 vector zpintr + +#controller snd0 +#device sb0 at isa? port 0x20d2 irq 10 conflicts drq 3 vector sbintr +#device sbxvi0 at isa? drq 3 +#device sbmidi0 at isa? port 0x80d2 +#device opl0 at isa? port 0x28d2 +#device pcm0 at isa? port 0xa460 irq 12 vector pcmintr +#device mss0 at isa? port 0xf40 irq 12 drq 1 vector adintr + +pseudo-device loop +pseudo-device ether +pseudo-device sl 1 +pseudo-device ppp 1 +pseudo-device tun 1 +pseudo-device pty 16 +pseudo-device gzip # Exec gzipped a.out's + +# KTRACE enables the system-call tracing facility ktrace(2). +# This adds 4 KB bloat to your kernel, and slightly increases +# the costs of each syscall. +options KTRACE #kernel tracing + diff --git a/sys/pc98/conf/Makefile.pc98 b/sys/pc98/conf/Makefile.pc98 index 2af781934392..f6ba1b258a01 100644 --- a/sys/pc98/conf/Makefile.pc98 +++ b/sys/pc98/conf/Makefile.pc98 @@ -3,7 +3,7 @@ # Makefile.i386 -- with config changes. # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.pc98,v 1.51 1999/01/18 11:00:29 kato Exp $ +# $Id: Makefile.pc98,v 1.41 1998/10/05 08:57:17 kato Exp $ # # Makefile for FreeBSD # @@ -19,9 +19,9 @@ # # Which version of config(8) is required. -%VERSREQ= 300009 +%VERSREQ= 300007 -KERNFORMAT?= elf +KERNFORMAT?= aout #STD8X16FONT?= iso @@ -77,8 +77,8 @@ DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} $< DRIVER_S= ${CC} -c -x ${ASM_CFLAGS} $< PROFILE_C= ${CC} -c ${CFLAGS} $< -GEN_CFILES= ${I386}/i386/genassym.c -# setdef0.c and setdef1.c are intentionally +GEN_CFILES= ${I386}/i386/genassym.c ${I386}/i386/gensetdefs.c +# ${I386}/i386/setdef0.c and ${I386}/i386/setdef1.c are intentionally # omitted from SYSTEM_CFILES. They include setdefs.h, a header which # is generated from all of ${OBJS}. We don't want to have to compile # everything just to do a make depend. @@ -89,7 +89,14 @@ SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} SYMORDER_EXCLUDE=-x symbols.exclude .endif SYSTEM_LD_HEAD= @echo loading ${.TARGET}; rm -f ${.TARGET} -.if ${KERNFORMAT} == aout || ${KERNFORMAT} == aoutkld +.if ${KERNFORMAT} == aout +SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o config.o +SYSTEM_LD= @${LD} -aout -Bstatic -Z -T ${LOAD_ADDRESS} -o ${.TARGET} -X ${SYSTEM_OBJS} vers.o +SYSTEM_LD_TAIL= @echo rearranging symbols; \ + symorder -m ${SYMORDER_EXCLUDE} symbols.sort ${.TARGET}; \ + size -aout ${.TARGET} ; chmod 755 ${.TARGET} +.endif +.if ${KERNFORMAT} == aoutkld SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o config.o SYSTEM_LD= @${LD} -aout -Bforcedynamic -Z -T ${LOAD_ADDRESS} -o ${.TARGET} -X ${SYSTEM_OBJS} vers.o SYSTEM_LD_TAIL= @echo rearranging symbols; \ @@ -97,8 +104,9 @@ SYSTEM_LD_TAIL= @echo rearranging symbols; \ size -aout ${.TARGET} ; chmod 755 ${.TARGET} .endif .if ${KERNFORMAT} == elf +# kld compatable export of symbols. SYSTEM_OBJS= locore.o setdef0.o vnode_if.o ${OBJS} ioconf.o param.o config.o \ - setdef1.o hack.So + setdef1.o hack.so SYSTEM_LD= @${LD} -elf -Bdynamic -T $S/i386/conf/kernel.script \ -export-dynamic -dynamic-linker /red/herring \ -o ${.TARGET} -X ${SYSTEM_OBJS} vers.o @@ -120,14 +128,9 @@ SYSTEM_DEP+= $S/i386/conf/kernel.script %CLEAN -.if !exists(.depend) -${SYSTEM_OBJS}: ${BEFORE_DEPEND:M*.h} -.endif - clean: - rm -f *.o *.so *.So *.ko *.s eddep errs genassym gensetdefs \ - kernel linterrs makelinks param.c setdef[01].c setdefs.h \ - symbols.exclude symbols.sort tags \ + rm -f *.o *.so *.ko *.s eddep errs genassym gensetdefs kernel linterrs \ + makelinks param.c setdefs.h symbols.exclude symbols.sort tags \ vers.c vnode_if.c vnode_if.h ${CLEAN} #lint: /tmp param.c @@ -151,21 +154,26 @@ locore.o: ${I386}/i386/locore.s assym.s # This is a hack. BFD "optimizes" away dynamic mode if there are no # dynamic references. We could probably do a '-Bforcedynamic' mode like # in the a.out ld. For now, this works. -hack.So: Makefile +hack.so: Makefile touch hack.c - ${CC} -elf -shared -nostdlib hack.c -o hack.So + ${CC} -elf -shared -nostdlib hack.c -o hack.so rm -f hack.c .endif -setdef0.o: setdef0.c setdefs.h +setdef0.o: ${I386}/i386/setdef0.c setdefs.h ${NORMAL_C} -setdef1.o: setdef1.c setdefs.h +setdef1.o: ${I386}/i386/setdef1.c setdefs.h ${NORMAL_C} -setdef0.c setdef1.c setdefs.h: ${OBJS} - @echo generating linker set emulation glue for ELF - @gensetdefs ${OBJS} +setdefs.h: gensetdefs ${OBJS} + ./gensetdefs ${OBJS} >setdefs.h + +gensetdefs: gensetdefs.o + ${CC} ${GEN_CFLAGS} gensetdefs.o -o ${.TARGET} + +gensetdefs.o: ${I386}/i386/gensetdefs.c + ${CC} -c ${GEN_CFLAGS} ${I386}/i386/gensetdefs.c # this rule stops ./assym.s in .depend from causing problems ./assym.s: assym.s @@ -180,7 +188,7 @@ genassym.o: ${I386}/i386/genassym.c genassym: genassym.o ${CC} ${GEN_CFLAGS} genassym.o -o ${.TARGET} -${SYSTEM_OBJS} genassym.o vers.o: opt_global.h +${SYSTEM_OBJS} genassym.o gensetdefs.o vers.o: opt_global.h # XXX this assumes that the options for NORMAL_C* and DRIVER_C* are identical. depend: assym.s param.c vnode_if.h ${BEFORE_DEPEND} @@ -211,16 +219,6 @@ install: echo "You must first build your kernel before trying to install." ; \ exit 1 ; \ fi -.if ${KERNFORMAT} == "elf" && !defined(FORCE) - @if [ -f /kernel -a "`file /kernel 2>/dev/null | grep ELF`" = "" ]; then \ - echo "WARNING: You are about to install an ELF kernel for the first time!" ; \ - echo "Please be sure you have upgraded your bootblocks and/or /boot/loader so" ; \ - echo "that you can boot it. Old bootblocks WILL NOT WORK! Please read:" ; \ - echo "http://www.freebsd.org/~peter/elfday.html for information." ; \ - echo "If you are satisfied you can boot an ELF kernel, type: make -DFORCE install" ; \ - exit 1 ; \ - fi -.endif .if exists(${DESTDIR}/kernel) chflags noschg ${DESTDIR}/kernel mv ${DESTDIR}/kernel ${DESTDIR}/kernel.old diff --git a/sys/pc98/conf/SMP-GENERIC98 b/sys/pc98/conf/SMP-GENERIC98 new file mode 100644 index 000000000000..6b08d04497a9 --- /dev/null +++ b/sys/pc98/conf/SMP-GENERIC98 @@ -0,0 +1,230 @@ +# +# GENERIC -- Generic machine with WD/AHx/NCR/BTx family disks +# +# For more information read the handbook part System Administration -> +# Configuring the FreeBSD Kernel -> The Configuration File. +# The handbook is available in /usr/share/doc/handbook or online as +# latest version from the FreeBSD World Wide Web server +# <URL:http://www.FreeBSD.ORG/> +# +# An exhaustive list of options and more detailed explanations of the +# device lines is present in the ./LINT configuration file. If you are +# in doubt as to the purpose or necessity of a line, check first in LINT. +# +# $Id: SMP-GENERIC98,v 1.4 1998/09/19 13:36:13 kato Exp $ + +# GENERIC98 -- Generic PC98 machine with WD/SCSI disks + +machine "pc98" +# SMP does NOT support 386/486 CPUs. +#cpu "I386_CPU" +#cpu "I486_CPU" +cpu "I586_CPU" +cpu "I686_CPU" +ident "SMP-GENERIC98" +maxusers 32 + +# Create a SMP capable kernel (mandatory options): +options SMP # Symmetric MultiProcessor Kernel +options APIC_IO # Symmetric (APIC) I/O + +# Optional, these are the defaults: +#options NCPU=2 # number of CPUs +#options NBUS=4 # number of busses +#options NAPIC=1 # number of IO APICs +#options NINTR=24 # number of INTs + +options "PC98" #PC98 +# SMP shouldn't need x87 emulation, disable by default. +#options MATH_EMULATE #Support for x87 emulation +options INET #InterNETworking +options FFS #Berkeley Fast Filesystem +options NFS #Network Filesystem +options MSDOSFS #MSDOS Filesystem +options "CD9660" #ISO 9660 Filesystem +options "CD9660_ROOT" #CD-ROM usable as root device +options FFS_ROOT #FFS usable as root device [keep this!] +options NFS_ROOT #NFS usable as root device +options PROCFS #Process filesystem +options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=15000 #Be pessimistic about Joe SCSI device +options UCONSOLE #Allow users to grab the console +options "LINE30" +options FAILSAFE #Be conservative +options USERCONFIG #boot -c editor +options VISUAL_USERCONFIG #visual boot -c editor + +options SYSVSHM +options SYSVSEM +options SYSVMSG + +options COM_MULTIPORT + +# +# IBM-PC HDD support +#options COMPAT_ATDISK +# +# FreeBSD(98)-current is a *TEST VERSION*. +# It is highly recomended to compile with following options, and to +# record the panic messages and the result of trace command brefore +# reporting a problem. +options DDB +options DIAGNOSTIC + +config kernel root on wd0 + +controller isa0 +controller pci0 + +controller fdc0 at isa? port "IO_FD1" bio irq 11 drq 2 vector fdintr +disk fd0 at fdc0 drive 0 +disk fd1 at fdc0 drive 1 +disk fd2 at fdc0 drive 2 +disk fd3 at fdc0 drive 3 +# Unless you know very well what you're doing, leave ft0 at drive 2, or +# remove the line entirely if you don't need it. Trying to configure +# it on another unit might cause surprises, see PR kern/7176. +tape ft0 at fdc0 drive 4 + +# options "CMD640" # work around CMD640 chip deficiency +controller wdc0 at isa? port "IO_WD1" bio irq 9 vector wdintr +disk wd0 at wdc0 drive 0 +#disk wd1 at wdc0 drive 1 +#disk wd2 at wdc0 drive 2 +#disk wd3 at wdc0 drive 3 + +options ATAPI # Enable ATAPI support for IDE bus +options ATAPI_STATIC #Don't do it as an LKM +device wcd0 #IDE CD-ROM + +# A single entry for any of these controllers (ncr, ahb, ahc) is sufficient +# for any number of installed devices. +controller ncr0 +#controller amd0 +controller ahc0 +controller isp0 + + +# +# SMP does not support bs driver: see /sys/i386/isa/bs/bsif.h +# +# WD33C93 SCSI card (55/92 like board) +# + +options BS_TARG_SAFEMODE + +# PC-9801-92 +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0 vector bsintr +# SC-98 +# controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x10000 vector bsintr +# HA-55BS2 and later +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x20000 vector bsintr +# ELECOM type +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x30000 vector bsintr +# SMIT +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 vector bsintr +# Logitec LHA-20x +#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x50000 vector bsintr + +controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 vector aicintr + +controller scbus0 + +device da0 + +device sa0 + +device pass0 + +device cd0 #Only need one of these, the code dynamically grows + +controller matcd0 at isa? port? bio + +# syscons is the default console driver, resembling an SCO console +device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr +#options XSERVER # support for X server + +device npx0 at isa? port "IO_NPX" irq 8 vector npxintr + +# +# Laptop support (see LINT for more options) +# +device apm0 at isa? disable flags 0x31 # Advanced Power Management + +# PCCARD (PCMCIA) support +#controller card0 +#device pcic0 at card? +#device pcic1 at card? + +device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr +device sio1 at isa? port 0xd2 tty irq 5 flags 0x101 vector siointr +device sio2 at isa? port 0x8d2 tty flags 0x101 vector siointr + +device lpt0 at isa? port "IO_LPT" tty +device mse0 at isa? port "IO_MSE" tty irq 13 vector mseintr + +# Order is important here due to intrusive probes, do *not* alphabetize +# this list of network interfaces until the probes have been fixed. +# Right now it appears that the ie0 must be probed before ep0. See +# revision 1.20 of this file. +device de0 +device fxp0 +device tl0 +device tx0 +device vx0 +device xl0 + +# +# DP8390 NIC +# +# ed0: generic driver +# ed1: LANEED LD-BDN +# ed2: EGY-98 +# ed3: LGY-98 +# ed4: ICM-IF-2766/EN-2298-T +# ed5: SIC-98 +# ed6: PC-9801-108 +# ed7: LA-98 +# ed8: C-NET(98) +# ed9: C-NET(98)E/L +# +device ed0 at isa? port 0x00d0 net irq 6 vector edintr +device ed1 at isa? port 0x00d8 net irq 6 flags 0x200000 vector edintr +device ed2 at isa? port 0x00d8 net irq 6 flags 0x300000 vector edintr +device ed3 at isa? port 0x00d0 net irq 6 flags 0x400000 vector edintr +device ed4 at isa? port 0x56d0 net irq 5 flags 0x500000 vector edintr +device ed5 at isa? port 0x00d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0x600000 vector edintr +device ed6 at isa? port 0x0770 net irq 6 flags 0x800000 vector edintr +device ed7 at isa? port 0x00d0 net irq 6 flags 0x900000 vector edintr +device ed8 at isa? port 0x03d0 net irq 6 iomem 0xd0000 iosiz 16384 flags 0xa00000 vector edintr +device ed9 at isa? port 0x03d0 net irq 6 flags 0xb00000 vector edintr + +device ep0 at isa? port 0x40d0 net irq 3 vector epintr +device fe0 at isa? port 0x00d0 net irq 3 vector feintr +device lnc0 at isa? port 0x03d0 net irq 6 vector lncintr +device zp0 at isa? port 0x00d0 net irq 10 iomem 0xe0000 vector zpintr + +#controller snd0 +#device sb0 at isa? port 0x20d2 irq 10 conflicts drq 3 vector sbintr +#device sbxvi0 at isa? drq 3 +#device sbmidi0 at isa? port 0x80d2 +#device opl0 at isa? port 0x28d2 +#device pcm0 at isa? port 0xa460 irq 12 vector pcmintr +#device mss0 at isa? port 0xf40 irq 12 drq 1 vector adintr + +pseudo-device loop +pseudo-device ether +pseudo-device sl 1 +#pseudo-device ppp 1 +pseudo-device tun 1 +pseudo-device pty 16 +pseudo-device gzip # Exec gzipped a.out's + +# KTRACE enables the system-call tracing facility ktrace(2). +# This adds 4 KB bloat to your kernel, and slightly increases +# the costs of each syscall. +options KTRACE #kernel tracing + +# This provides support for System V shared memory. +# +options SYSVSHM diff --git a/sys/pc98/conf/devices.pc98 b/sys/pc98/conf/devices.pc98 index cc10d30cd991..8b2641f04642 100644 --- a/sys/pc98/conf/devices.pc98 +++ b/sys/pc98/conf/devices.pc98 @@ -1,6 +1,6 @@ # This file tells what major numbers the various possible swap devices have. # -# $Id: devices.pc98,v 1.6 1998/09/15 14:10:55 kato Exp $ +# $Id: devices.pc98,v 1.5 1998/02/18 12:33:34 kato Exp $ # wd 0 wfd 1 @@ -13,5 +13,5 @@ mcd 7 vn 15 scd 16 pcd 17 -acd 19 +wcd 19 wst 24 diff --git a/sys/pc98/conf/files.pc98 b/sys/pc98/conf/files.pc98 index 1a5d72d84f6a..7b2d2a07e48d 100644 --- a/sys/pc98/conf/files.pc98 +++ b/sys/pc98/conf/files.pc98 @@ -3,7 +3,7 @@ # # modified for PC-9801 # -# $Id: files.pc98,v 1.80 1999/01/18 08:38:07 kato Exp $ +# $Id: files.pc98,v 1.71 1998/09/20 10:50:18 kato Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -26,11 +26,6 @@ font8x16.o optional std8x16font \ no-implicit-rule before-depend \ clean "${STD8X16FONT}-8x16 font8x16.c" # -dev/fb/fb.c optional fb device-driver -dev/fb/fb.c optional gdc device-driver -dev/fb/splash.c optional splash -dev/kbd/kbd.c optional kbd device-driver -dev/kbd/kbd.c optional pckbd device-driver i386/apm/apm.c optional apm device-driver i386/apm/apm_setup.s optional apm i386/eisa/dpt_eisa.c optional eisa dpt device-driver @@ -76,7 +71,7 @@ i386/i386/simplelock.s optional smp i386/i386/support.s standard i386/i386/swtch.s standard i386/i386/sys_machdep.c standard -i386/i386/trap.c standard +pc98/i386/trap.c standard pc98/i386/userconfig.c optional userconfig i386/i386/vm_machdep.c standard i386/i386/vm86.c optional vm86 @@ -109,6 +104,8 @@ i386/isa/adv_isa.c optional adv device-driver i386/isa/aha_isa.c optional aha device-driver #i386/isa/aic6360.c optional aic device-driver i386/isa/aic_isa.c optional aic device-driver +i386/isa/alog.c optional alog device-driver +i386/isa/b004.c optional bqu device-driver i386/isa/bt_isa.c optional bt device-driver pc98/pc98/clock.c standard i386/isa/cronyx.c optional cx device-driver @@ -120,6 +117,7 @@ pc98/pc98/atcompat_diskslice.c optional compat_atdisk i386/isa/elink.c optional ep device-driver i386/isa/elink.c optional ie device-driver pc98/pc98/fd.c optional fd device-driver +i386/isa/ft.c optional ft device-driver i386/isa/gpib.c optional gp device-driver i386/isa/asc.c optional asc device-driver i386/isa/gsc.c optional gsc device-driver @@ -127,14 +125,14 @@ i386/isa/if_ar.c optional ar device-driver i386/isa/if_cs.c optional cs device-driver i386/isa/if_cx.c optional cx device-driver pc98/pc98/if_ed.c optional ed device-driver +i386/isa/if_eg.c optional eg device-driver i386/isa/if_el.c optional el device-driver i386/isa/if_ep.c optional ep device-driver i386/isa/if_ex.c optional ex device-driver -i386/isa/if_fe.c optional fe device-driver +pc98/pc98/if_fe.c optional fe device-driver i386/isa/if_ie.c optional ie device-driver i386/isa/if_le.c optional le device-driver i386/isa/if_lnc.c optional lnc device-driver -i386/isa/if_rdp.c optional rdp device-driver i386/isa/if_sr.c optional sr device-driver i386/isa/if_wl.c optional wl device-driver i386/isa/if_ze.c optional ze device-driver @@ -145,25 +143,27 @@ i386/isa/intr_machdep.c standard pc98/pc98/pc98.c optional isa device-driver i386/isa/istallion.c optional stli device-driver i386/isa/joy.c optional joy device-driver -pc98/pc98/pc98kbd.c optional pckbd device-driver +i386/isa/kbdio.c optional psm device-driver +i386/isa/kbdio.c optional sc device-driver +i386/isa/kbdio.c optional vt device-driver i386/isa/loran.c optional loran device-driver pc98/pc98/lpt.c optional lpt device-driver i386/isa/labpc.c optional labpc device-driver i386/isa/mcd.c optional mcd device-driver pc98/pc98/mse.c optional mse device-driver +#i386/isa/ncr5380.c optional nca device-driver pc98/pc98/npx.c mandatory npx device-driver -pc98/pc98/pc98gdc.c optional gdc device-driver pc98/pc98/pcaudio.c optional pca device-driver i386/isa/matcd/matcd.c optional matcd device-driver i386/isa/pcibus.c optional pci device-driver i386/isa/pcicx.c optional ze device-driver i386/isa/pcicx.c optional zp device-driver -#i386/isa/pcvt/pcvt_drv.c optional vt device-driver -#i386/isa/pcvt/pcvt_ext.c optional vt device-driver -#i386/isa/pcvt/pcvt_kbd.c optional vt device-driver -#i386/isa/pcvt/pcvt_out.c optional vt device-driver -#i386/isa/pcvt/pcvt_sup.c optional vt device-driver -#i386/isa/pcvt/pcvt_vtf.c optional vt device-driver +i386/isa/pcvt/pcvt_drv.c optional vt device-driver +i386/isa/pcvt/pcvt_ext.c optional vt device-driver +i386/isa/pcvt/pcvt_kbd.c optional vt device-driver +i386/isa/pcvt/pcvt_out.c optional vt device-driver +i386/isa/pcvt/pcvt_sup.c optional vt device-driver +i386/isa/pcvt/pcvt_vtf.c optional vt device-driver i386/isa/pnp.c optional pnp device-driver i386/isa/prof_machdep.c optional profiling-routine i386/isa/ppc.c optional ppc device-driver @@ -173,15 +173,17 @@ i386/isa/random_machdep.c standard i386/isa/rc.c optional rc device-driver i386/isa/rp.c optional rp device-driver i386/isa/scd.c optional scd device-driver +#i386/isa/seagate.c optional sea device-driver i386/isa/si.c optional si device-driver i386/isa/si2_z280.c optional si device-driver i386/isa/si3_t225.c optional si device-driver pc98/pc98/sio.c optional sio device-driver -i386/isa/snd/sound.c optional pcm device-driver -i386/isa/snd/dmabuf.c optional pcm device-driver -i386/isa/snd/ad1848.c optional pcm device-driver -i386/isa/snd/sb_dsp.c optional pcm device-driver -i386/isa/snd/clones.c optional pcm device-driver +#i386/isa/snd/sound.c optional pcm device-driver +#i386/isa/snd/dmabuf.c optional pcm device-driver +#i386/isa/snd/ad1848.c optional pcm device-driver +#i386/isa/snd/sb_dsp.c optional pcm device-driver +#i386/isa/snd/clones.c optional pcm device-driver +i386/isa/sound/pcm86.c optional pcm device-driver i386/isa/sound/dev_table.c optional snd device-driver i386/isa/sound/soundcard.c optional snd device-driver i386/isa/sound/sound_switch.c optional snd device-driver @@ -247,17 +249,20 @@ i386/isa/spigot.c optional spigot device-driver pc98/pc98/spkr.c optional speaker device-driver i386/isa/stallion.c optional stl device-driver pc98/pc98/syscons.c optional sc device-driver -pc98/pc98/scvidctl.c optional sc device-driver +#i386/isa/scvidctl.c optional sc device-driver #i386/isa/scvesactl.c optional sc device-driver #i386/isa/videoio.c optional sc device-driver #i386/isa/vesa.c optional sc device-driver i386/isa/tw.c optional tw device-driver +#i386/isa/ultra14f.c optional uha device-driver pc98/pc98/wd.c optional wdc device-driver pc98/pc98/wd.c optional wd device-driver i386/isa/atapi.c optional atapi device-driver i386/isa/atapi-cd.c optional acd device-driver +i386/isa/wcd.c optional wcd device-driver i386/isa/wfd.c optional wfd device-driver i386/isa/wst.c optional wst device-driver +i386/isa/wd7000.c optional wds device-driver i386/isa/wt.c optional wt device-driver i386/linux/imgact_linux.c optional compat_linux i386/linux/linux_dummy.c optional compat_linux @@ -273,30 +278,6 @@ i386/linux/linux_stats.c optional compat_linux i386/linux/linux_sysent.c optional compat_linux i386/linux/linux_sysvec.c optional compat_linux i386/linux/linux_util.c optional compat_linux -i4b/layer1/i4b_isic.c optional isic device-driver -i4b/layer1/i4b_isic_isa.c optional isic device-driver -i4b/layer1/i4b_isic_pnp.c optional isic device-driver -i4b/layer1/i4b_isic_pci.c optional isic device-driver -i4b/layer1/i4b_isic_pcmcia.c optional isic device-driver -i4b/layer1/i4b_isac.c optional isic device-driver -i4b/layer1/i4b_hscx.c optional isic device-driver -i4b/layer1/i4b_l1.c optional isic device-driver -i4b/layer1/i4b_l1fsm.c optional isic device-driver -i4b/layer1/i4b_bchan.c optional isic device-driver -i4b/layer1/i4b_tel_s08.c optional isic device-driver -i4b/layer1/i4b_tel_s016.c optional isic device-driver -i4b/layer1/i4b_tel_s0163.c optional isic device-driver -i4b/layer1/i4b_tel_s0P.c optional isic device-driver -i4b/layer1/i4b_ctx_s0P.c optional isic device-driver -i4b/layer1/i4b_avm_a1.c optional isic device-driver -i4b/layer1/i4b_avm_fritz_pcmcia.c optional isic device-driver -i4b/layer1/i4b_usr_sti.c optional isic device-driver -i4b/layer1/i4b_itk_ix1.c optional isic device-driver -i4b/layer1/i4b_drn_ngo.c optional isic device-driver -i4b/layer1/i4b_sws.c optional isic device-driver -i4b/layer1/i4b_dynalink.c optional isic device-driver -i4b/layer1/i4b_elsa_qs1i.c optional isic device-driver -i4b/layer1/i4b_elsa_qs1p.c optional isic device-driver libkern/bcd.c standard libkern/divdi3.c standard libkern/inet_ntoa.c standard @@ -351,5 +332,4 @@ gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate gnu/i386/isa/dgb.c optional dgb device-driver gnu/i386/isa/dgm.c optional dgm device-driver gnu/i386/isa/sound/awe_wave.c optional awe device-driver -pci/es1370.c optional pcm device-driver #pci/ide_pci.c optional wd device-driver diff --git a/sys/pc98/conf/majors.pc98 b/sys/pc98/conf/majors.pc98 index 90ffbefccbce..2dce44c1a47f 100644 --- a/sys/pc98/conf/majors.pc98 +++ b/sys/pc98/conf/majors.pc98 @@ -1,4 +1,4 @@ -$Id: majors.pc98,v 1.48 1999/01/16 11:36:28 kato Exp $ +$Id: majors.pc98,v 1.40 1998/09/15 14:10:56 kato Exp $ Hopefully, this list will one day be obsoleted by DEVFS, but for now this is the current allocation of device major numbers. @@ -32,7 +32,7 @@ blkdev name comments 16 scd Sony CDROM interface 17 matcd Matsushita/Panasonic/Creative(SB) CDROM interface 18 ata "device independent" ATA/IDE driver -19 acdb ATAPI CDROM client of "ata" +19 wcdb ATAPI CDROM client of "ata" 21 ccd concatenated disk 22 gd Geometry disk. 24 wstb ATAPI tape client of "ata" @@ -40,9 +40,6 @@ blkdev name comments 26 sw VM internal swap device 27 myx Mylex RAID (ulf@alameda.net) 28 fla M-Systems DiskOnChip(r) -29 id Intelligent Disk [Array] (md@doc.ic.ac.uk) -100 ?? entries from 100-127 are reserved for local use -127 ?? entries from 100-127 are reserved for local use chrdev name comments 0 cn console @@ -114,7 +111,7 @@ chrdev name comments 66 labpc National Instruments LabPC 67 meteor Matrox Meteor video capture 68 si Specialix SI/XIO (peter@freebsd.org) -69 acd ATAPI CDROM client of "ata" +69 wcd ATAPI CDROM client of "ata" 71 asc AmiScan driver 72 stl Stallion (cd1400 based) (gerg@stallion.oz.au) 73 ?? was qcam @@ -128,9 +125,9 @@ chrdev name comments 81 rp RocketPort/Steve Gericke <steveg@comtrol.com> 82 ppi Generic Parallel I/O <Nicolas.Souchu@prism.uvsq.fr> 83 can CAN16-2 CAN-PC Interface -84 dtfp Datum Time and Frequency processor (louie@UU.NET) +84 ttxt Unitext teletext decoder (arg@arg1.demon.co.uk) 85 vesa VESA support device (j_mini@efn.org) -86 alog Industrial Computer Source AIO8-P driver (deprecated) +86 alog Industrial Computer Source AIO8-P driver 87 wfd ATAPI floppy client of "ata" 88 dpt DPT RAID Controller <shimon@i-connect.net> 89 pps Pulse-Per-Second timing interface @@ -152,12 +149,3 @@ chrdev name comments 105 iic I2C bus generic i/o 106 smb System Management Bus generic i/o 107 3dfx 3Dfx driver (shocking@prth.pgs.com) -108 usb Universal Serial Bus (nick.hibma@jrc.it) -109 id Intelligent Disk [Array] (md@doc.ic.ac.uk) -110 ses SCSI Environmental Services driver (mjacob@feral.com) -111 ums USB Mouse (nick.hibma@jrc.it) -112 kbd keyboard -113 ulpt USB Printer (nick.hibma@jrc.it) -114 ugen USB Generic device (nick.hibma@jrc.it) -200 ?? entries from 200-255 are reserved for local use -255 ?? entries from 200-255 are reserved for local use diff --git a/sys/pc98/conf/options.pc98 b/sys/pc98/conf/options.pc98 index 22c264c07e3a..d18cabcdd4f9 100644 --- a/sys/pc98/conf/options.pc98 +++ b/sys/pc98/conf/options.pc98 @@ -1,7 +1,5 @@ -# $Id: options.pc98,v 1.77 1999/01/04 08:09:15 kato Exp $ - +# $Id: options.pc98,v 1.68 1998/09/28 08:23:26 kato Exp $ DISABLE_PSE -IDE_DELAY USER_LDT MATH_EMULATE opt_math_emulate.h GPL_MATH_EMULATE opt_math_emulate.h @@ -26,13 +24,19 @@ BREAK_TO_DEBUGGER opt_comconsole.h CONSPEED opt_comconsole.h COM_ESP opt_sio.h COM_MULTIPORT opt_sio.h +DSI_SOFT_MODEM opt_sio.h EXTRA_SIO opt_sio.h I586_PMC_GUPROF opt_i586_guprof.h WLCACHE opt_wavelan.h WLDEBUG opt_wavelan.h -# i386 SMP options +# These two SMP options have dramatic implications all over the kernel +SMP opt_global.h APIC_IO opt_global.h + +# Standard SMP options +NCPU opt_smp.h +NBUS opt_smp.h NAPIC opt_smp.h NINTR opt_smp.h @@ -56,7 +60,6 @@ CPU_UPGRADE_HW_CACHE opt_cpu.h CPU_WT_ALLOC opt_cpu.h CYRIX_CACHE_WORKS opt_cpu.h CYRIX_CACHE_REALLY_WORKS opt_cpu.h -NO_MEMORY_HOLE opt_cpu.h # The CPU type affects the endian conversion functions all over the kernel. I386_CPU opt_global.h @@ -64,29 +67,27 @@ I486_CPU opt_global.h I586_CPU opt_global.h I686_CPU opt_global.h +SC_SPLASH_SCREEN opt_syscons.h MAXCONS opt_syscons.h +SLOW_VGA opt_syscons.h STD8X16FONT opt_syscons.h SC_HISTORY_SIZE opt_syscons.h SC_DISABLE_REBOOT opt_syscons.h SC_MOUSE_CHAR opt_syscons.h - -FB_INSTALL_CDEV opt_fb.h +SC_ALT_SEQACCESS opt_syscons.h VESA opt_vesa.h -GDC opt_gdc.h - PSM_HOOKAPM opt_psm.h PSM_RESETAFTERSUSPEND opt_psm.h PSM_DEBUG opt_psm.h PCIC_RESUME_RESET opt_pcic.h -KBD_INSTALL_CDEV opt_kbd.h -KBD_MAXRETRY opt_kbd.h -KBD_MAXWAIT opt_kbd.h -KBD_RESETDELAY opt_kbd.h -KBDIO_DEBUG opt_kbd.h +KBD_RESETDELAY opt_kbdio.h +KBD_MAXRETRY opt_kbdio.h +KBD_MAXWAIT opt_kbdio.h +KBDIO_DEBUG opt_kbdio.h ATAPI opt_atapi.h ATAPI_STATIC opt_atapi.h @@ -95,13 +96,12 @@ CMD640 opt_wd.h USERCONFIG opt_userconfig.h VISUAL_USERCONFIG opt_userconfig.h -INTRO_USERCONFIG opt_userconfig.h +USERCONFIG_BOOT opt_userconfig.h EISA_SLOTS opt_eisa.h FDC_DEBUG opt_fdc.h FDC_PRINT_BOGUS_CHIPTYPE opt_fdc.h -FDC_YE opt_fdc.h # pcvt(4) has a bunch of options FAT_CURSOR opt_pcvt.h @@ -125,42 +125,6 @@ GUS_IRQ opt_sound.h # Video spigot SPIGOT_UNSECURE opt_spigot.h -# ------------------------------- -# isdn4bsd: passive ISA cards -# ------------------------------- -TEL_S0_8 opt_i4b.h -TEL_S0_16 opt_i4b.h -TEL_S0_16_3 opt_i4b.h -AVM_A1 opt_i4b.h -USR_STI opt_i4b.h -ITKIX1 opt_i4b.h -# ------------------------------- -# isdn4bsd: passive ISA PnP cards -# ------------------------------- -CRTX_S0_P opt_i4b.h -DRN_NGO opt_i4b.h -TEL_S0_16_3_P opt_i4b.h -SEDLBAUER opt_i4b.h -DYNALINK opt_i4b.h -ELSA_QS1ISA opt_i4b.h -# ------------------------------- -# isdn4bsd: passive PCI cards -# ------------------------------- -ELSA_QS1PCI opt_i4b.h -# ------------------------------- -# isdn4bsd: passive PCMCIA cards -# ------------------------------- -AVM_A1_PCMCIA opt_i4b.h -# ------------------------------- -# isdn4bsd: misc options -# ------------------------------- -# temporary workaround for SMP machines -I4B_SMP_WORKAROUND opt_i4b.h -# enable VJ compression code for ipr i/f -IPR_VJ opt_i4b.h -# ------------------------------- -# EOF -# ------------------------------- # bs driver options SCSI_BOUNCE_SIZE opt_bs.h diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c index 91095587ab6e..7449379560cf 100644 --- a/sys/pc98/i386/machdep.c +++ b/sys/pc98/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.104 1999/01/08 16:04:20 kato Exp $ + * $Id: machdep.c,v 1.98 1998/10/09 12:36:25 kato Exp $ */ #include "apm.h" @@ -109,6 +109,9 @@ #include <net/netisr.h> #endif +#if NAPM > 0 +#include <machine/apm_bios.h> +#endif #include <machine/cpu.h> #include <machine/reg.h> #include <machine/clock.h> @@ -423,12 +426,6 @@ again: */ { vm_offset_t mb_map_size; - int xclusters; - - /* Allow override of NMBCLUSTERS from the kernel environment */ - if (getenv_int("kern.ipc.nmbclusters", &xclusters) && - xclusters > nmbclusters) - nmbclusters = xclusters; mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES; mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE)); @@ -452,8 +449,14 @@ again: } #if defined(USERCONFIG) - userconfig(); - cninit(); /* the preferred console may have changed */ +#if defined(USERCONFIG_BOOT) + if (1) { +#else + if (boothowto & RB_CONFIG) { +#endif + userconfig(); + cninit(); /* the preferred console may have changed */ + } #endif printf("avail memory = %d (%dK bytes)\n", ptoa(cnt.v_free_count), @@ -545,11 +548,7 @@ sendsig(catcher, sig, mask, code) * and the stack can not be grown. useracc will return FALSE * if access is denied. */ -#ifdef VM_STACK - if ((grow_stack (p, (int)fp) == FALSE) || -#else if ((grow(p, (int)fp) == FALSE) || -#endif (useracc((caddr_t)fp, sizeof(struct sigframe), B_WRITE) == FALSE)) { /* * Process has trashed its stack; give it an illegal @@ -644,7 +643,7 @@ sendsig(catcher, sig, mask, code) } regs->tf_esp = (int)fp; - regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode); + regs->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); regs->tf_cs = _ucodesel; regs->tf_ds = _udatasel; regs->tf_es = _udatasel; @@ -808,6 +807,17 @@ cpu_halt(void) } /* + * Turn the power off. + */ +void +cpu_power_down(void) +{ +#if NAPM > 0 + apm_power_off(); +#endif +} + +/* * Clear registers on exec */ void @@ -1255,7 +1265,11 @@ init386(first) setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); +#ifdef CPU_BUGGY_CYRIX setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); +#else + setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); +#endif setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); @@ -1680,7 +1694,7 @@ f00f_hack(void *unused) { if (!has_f00f_bug) return; - printf("Intel Pentium detected, installing workaround for F00F bug\n"); + printf("Intel Pentium F00F detected, installing workaround\n"); r_idt.rd_limit = sizeof(idt) - 1; diff --git a/sys/pc98/i386/trap.c b/sys/pc98/i386/trap.c new file mode 100644 index 000000000000..9ea5d8051d1f --- /dev/null +++ b/sys/pc98/i386/trap.c @@ -0,0 +1,1159 @@ +/*- + * Copyright (C) 1994, David Greenman + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the University of Utah, and 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: @(#)trap.c 7.4 (Berkeley) 5/13/91 + * $Id: trap.c,v 1.50 1998/04/29 09:45:38 kato Exp $ + */ + +/* + * 386 Trap and System call handling + */ + +#include "opt_cpu.h" +#include "opt_ddb.h" +#include "opt_ktrace.h" +#include "opt_trap.h" +#include "opt_vm86.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/pioctl.h> +#include <sys/kernel.h> +#include <sys/resourcevar.h> +#include <sys/signalvar.h> +#include <sys/syscall.h> +#include <sys/sysent.h> +#include <sys/uio.h> +#include <sys/vmmeter.h> +#ifdef KTRACE +#include <sys/ktrace.h> +#endif + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_prot.h> +#include <sys/lock.h> +#include <vm/pmap.h> +#include <vm/vm_kern.h> +#include <vm/vm_map.h> +#include <vm/vm_page.h> +#include <vm/vm_extern.h> + +#include <machine/cpu.h> +#include <machine/ipl.h> +#include <machine/md_var.h> +#include <machine/pcb.h> +#ifdef SMP +#include <machine/smp.h> +#endif +#include <machine/tss.h> + +#include <i386/isa/intr_machdep.h> + +#ifdef POWERFAIL_NMI +#include <sys/syslog.h> +#include <machine/clock.h> +#endif + +#ifdef VM86 +#include <machine/vm86.h> +#endif + +#include "isa.h" +#include "npx.h" + +extern struct i386tss common_tss; + +int (*pmath_emulate) __P((struct trapframe *)); + +extern void trap __P((struct trapframe frame)); +extern int trapwrite __P((unsigned addr)); +extern void syscall __P((struct trapframe frame)); + +#ifdef CPU_BUGGY_CYRIX +static int trap_pfault __P((struct trapframe *, int, vm_offset_t)); +#else +static int trap_pfault __P((struct trapframe *, int)); +#endif +static void trap_fatal __P((struct trapframe *)); +void dblfault_handler __P((void)); + +extern inthand_t IDTVEC(syscall); + +#define MAX_TRAP_MSG 28 +static char *trap_msg[] = { + "", /* 0 unused */ + "privileged instruction fault", /* 1 T_PRIVINFLT */ + "", /* 2 unused */ + "breakpoint instruction fault", /* 3 T_BPTFLT */ + "", /* 4 unused */ + "", /* 5 unused */ + "arithmetic trap", /* 6 T_ARITHTRAP */ + "system forced exception", /* 7 T_ASTFLT */ + "", /* 8 unused */ + "general protection fault", /* 9 T_PROTFLT */ + "trace trap", /* 10 T_TRCTRAP */ + "", /* 11 unused */ + "page fault", /* 12 T_PAGEFLT */ + "", /* 13 unused */ + "alignment fault", /* 14 T_ALIGNFLT */ + "", /* 15 unused */ + "", /* 16 unused */ + "", /* 17 unused */ + "integer divide fault", /* 18 T_DIVIDE */ + "non-maskable interrupt trap", /* 19 T_NMI */ + "overflow trap", /* 20 T_OFLOW */ + "FPU bounds check fault", /* 21 T_BOUND */ + "FPU device not available", /* 22 T_DNA */ + "double fault", /* 23 T_DOUBLEFLT */ + "FPU operand fetch fault", /* 24 T_FPOPFLT */ + "invalid TSS fault", /* 25 T_TSSFLT */ + "segment not present fault", /* 26 T_SEGNPFLT */ + "stack fault", /* 27 T_STKFLT */ + "machine check trap", /* 28 T_MCHK */ +}; + +static __inline void userret __P((struct proc *p, struct trapframe *frame, + u_quad_t oticks)); + +#if defined(I586_CPU) && !defined(NO_F00F_HACK) +extern struct gate_descriptor *t_idt; +extern int has_f00f_bug; +#endif + +static __inline void +userret(p, frame, oticks) + struct proc *p; + struct trapframe *frame; + u_quad_t oticks; +{ + int sig, s; + + while ((sig = CURSIG(p)) != 0) + postsig(sig); + +#if 0 + if (!want_resched && + (p->p_priority <= p->p_usrpri) && + (p->p_rtprio.type == RTP_PRIO_NORMAL)) { + int newpriority; + p->p_estcpu += 1; + newpriority = PUSER + p->p_estcpu / 4 + 2 * p->p_nice; + newpriority = min(newpriority, MAXPRI); + p->p_usrpri = newpriority; + } +#endif + + p->p_priority = p->p_usrpri; + if (want_resched) { + /* + * Since we are curproc, clock will normally just change + * our priority without moving us from one queue to another + * (since the running process is not on a queue.) + * If that happened after we setrunqueue ourselves but before we + * mi_switch()'ed, we might not be on the queue indicated by + * our priority. + */ + s = splhigh(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + mi_switch(); + splx(s); + while ((sig = CURSIG(p)) != 0) + postsig(sig); + } + /* + * Charge system time if profiling. + */ + if (p->p_flag & P_PROFIL) + addupc_task(p, frame->tf_eip, + (u_int)(p->p_sticks - oticks) * psratio); + + curpriority = p->p_priority; +} + +/* + * Exception, fault, and trap interface to the FreeBSD kernel. + * This common code is called from assembly language IDT gate entry + * routines that prepare a suitable stack frame, and restore this + * frame after the exception has been processed. + */ + +void +trap(frame) + struct trapframe frame; +{ + struct proc *p = curproc; + u_quad_t sticks = 0; + int i = 0, ucode = 0, type, code; +#ifdef DEBUG + u_long eva; +#endif +#ifdef CPU_BUGGY_CYRIX + vm_offset_t va; +#endif + +#if defined(I586_CPU) && !defined(NO_F00F_HACK) +restart: +#endif + type = frame.tf_trapno; + code = frame.tf_err; + +#ifdef CPU_BUGGY_CYRIX + /* XXX: + * CYRIX 486 CPU FIX. + * If you use cyrix cpu, you often encouter strange signal 11's? + * I think this is due to cyrix cpu bugs. + * In any way, the following trick is effective for the problem. + * As soon as possible, we must get the fault page address. + */ + va = (vm_offset_t)(rcr2()); + if( type == T_PAGEFLT && ( frame.tf_eflags & PSL_I ) ) + asm("sti"); +#endif /* CPU_BUGGY_CYRIX */ + +#ifdef VM86 + if (in_vm86call) { + if (frame.tf_eflags & PSL_VM && + (type == T_PROTFLT || type == T_STKFLT)) { + i = vm86_emulate((struct vm86frame *)&frame); + if (i != 0) + /* + * returns to original process + */ + vm86_trap((struct vm86frame *)&frame); + return; + } + switch (type) { + /* + * these traps want either a process context, or + * assume a normal userspace trap. + */ + case T_PROTFLT: + case T_SEGNPFLT: + trap_fatal(&frame); + return; + case T_TRCTRAP: + type = T_BPTFLT; /* kernel breakpoint */ + /* FALL THROUGH */ + } + goto kernel_trap; /* normal kernel trap handling */ + } +#endif + + if ((ISPL(frame.tf_cs) == SEL_UPL) || (frame.tf_eflags & PSL_VM)) { + /* user trap */ + + sticks = p->p_sticks; + p->p_md.md_regs = &frame; + + switch (type) { + case T_PRIVINFLT: /* privileged instruction fault */ + ucode = type; + i = SIGILL; + break; + + case T_BPTFLT: /* bpt instruction fault */ + case T_TRCTRAP: /* trace trap */ + frame.tf_eflags &= ~PSL_T; + i = SIGTRAP; + break; + + case T_ARITHTRAP: /* arithmetic trap */ + ucode = code; + i = SIGFPE; + break; + + case T_ASTFLT: /* Allow process switch */ + astoff(); + cnt.v_soft++; + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + addupc_task(p, p->p_stats->p_prof.pr_addr, + p->p_stats->p_prof.pr_ticks); + } + goto out; + + /* + * The following two traps can happen in + * vm86 mode, and, if so, we want to handle + * them specially. + */ + case T_PROTFLT: /* general protection fault */ + case T_STKFLT: /* stack fault */ +#ifdef VM86 + if (frame.tf_eflags & PSL_VM) { + i = vm86_emulate((struct vm86frame *)&frame); + if (i == 0) + goto out; + break; + } +#endif /* VM86 */ + /* FALL THROUGH */ + + case T_SEGNPFLT: /* segment not present fault */ + case T_TSSFLT: /* invalid TSS fault */ + case T_DOUBLEFLT: /* double fault */ + default: + ucode = code + BUS_SEGM_FAULT ; + i = SIGBUS; + break; + + case T_PAGEFLT: /* page fault */ +#ifdef CPU_BUGGY_CYRIX + i = trap_pfault(&frame, TRUE, va); +#else + i = trap_pfault(&frame, TRUE); +#endif + if (i == -1) + return; +#if defined(I586_CPU) && !defined(NO_F00F_HACK) + if (i == -2) + goto restart; +#endif + if (i == 0) + goto out; + + ucode = T_PAGEFLT; + break; + + case T_DIVIDE: /* integer divide fault */ + ucode = FPE_INTDIV_TRAP; + i = SIGFPE; + break; + +#if NISA > 0 + case T_NMI: +#ifdef POWERFAIL_NMI + goto handle_powerfail; +#else /* !POWERFAIL_NMI */ +#ifdef DDB + /* NMI can be hooked up to a pushbutton for debugging */ + printf ("NMI ... going to debugger\n"); + if (kdb_trap (type, 0, &frame)) + return; +#endif /* DDB */ + /* machine/parity/power fail/"kitchen sink" faults */ + if (isa_nmi(code) == 0) return; + panic("NMI indicates hardware failure"); +#endif /* POWERFAIL_NMI */ +#endif /* NISA > 0 */ + + case T_OFLOW: /* integer overflow fault */ + ucode = FPE_INTOVF_TRAP; + i = SIGFPE; + break; + + case T_BOUND: /* bounds check fault */ + ucode = FPE_SUBRNG_TRAP; + i = SIGFPE; + break; + + case T_DNA: +#if NNPX > 0 + /* if a transparent fault (due to context switch "late") */ + if (npxdna()) + return; +#endif + if (!pmath_emulate) { + i = SIGFPE; + ucode = FPE_FPU_NP_TRAP; + break; + } + i = (*pmath_emulate)(&frame); + if (i == 0) { + if (!(frame.tf_eflags & PSL_T)) + return; + frame.tf_eflags &= ~PSL_T; + i = SIGTRAP; + } + /* else ucode = emulator_only_knows() XXX */ + break; + + case T_FPOPFLT: /* FPU operand fetch fault */ + ucode = T_FPOPFLT; + i = SIGILL; + break; + } + } else { +#ifdef VM86 +kernel_trap: +#endif + /* kernel trap */ + + switch (type) { + case T_PAGEFLT: /* page fault */ +#ifdef CPU_BUGGY_CYRIX + (void) trap_pfault(&frame, FALSE, va); +#else + (void) trap_pfault(&frame, FALSE); +#endif + return; + + case T_DNA: +#if NNPX > 0 + /* + * The kernel is apparently using npx for copying. + * XXX this should be fatal unless the kernel has + * registered such use. + */ + if (npxdna()) + return; +#endif + break; + + case T_PROTFLT: /* general protection fault */ + case T_SEGNPFLT: /* segment not present fault */ + /* + * Invalid segment selectors and out of bounds + * %eip's and %esp's can be set up in user mode. + * This causes a fault in kernel mode when the + * kernel tries to return to user mode. We want + * to get this fault so that we can fix the + * problem here and not have to check all the + * selectors and pointers when the user changes + * them. + */ +#define MAYBE_DORETI_FAULT(where, whereto) \ + do { \ + if (frame.tf_eip == (int)where) { \ + frame.tf_eip = (int)whereto; \ + return; \ + } \ + } while (0) + + if (intr_nesting_level == 0) { + /* + * Invalid %fs's and %gs's can be created using + * procfs or PT_SETREGS or by invalidating the + * underlying LDT entry. This causes a fault + * in kernel mode when the kernel attempts to + * switch contexts. Lose the bad context + * (XXX) so that we can continue, and generate + * a signal. + */ + if (frame.tf_eip == (int)cpu_switch_load_fs) { + curpcb->pcb_fs = 0; + psignal(p, SIGBUS); + return; + } + if (frame.tf_eip == (int)cpu_switch_load_gs) { + curpcb->pcb_gs = 0; + psignal(p, SIGBUS); + return; + } + MAYBE_DORETI_FAULT(doreti_iret, + doreti_iret_fault); + MAYBE_DORETI_FAULT(doreti_popl_ds, + doreti_popl_ds_fault); + MAYBE_DORETI_FAULT(doreti_popl_es, + doreti_popl_es_fault); + if (curpcb && curpcb->pcb_onfault) { + frame.tf_eip = (int)curpcb->pcb_onfault; + return; + } + } + break; + + case T_TSSFLT: + /* + * PSL_NT can be set in user mode and isn't cleared + * automatically when the kernel is entered. This + * causes a TSS fault when the kernel attempts to + * `iret' because the TSS link is uninitialized. We + * want to get this fault so that we can fix the + * problem here and not every time the kernel is + * entered. + */ + if (frame.tf_eflags & PSL_NT) { + frame.tf_eflags &= ~PSL_NT; + return; + } + break; + + case T_TRCTRAP: /* trace trap */ + if (frame.tf_eip == (int)IDTVEC(syscall)) { + /* + * We've just entered system mode via the + * syscall lcall. Continue single stepping + * silently until the syscall handler has + * saved the flags. + */ + return; + } + if (frame.tf_eip == (int)IDTVEC(syscall) + 1) { + /* + * The syscall handler has now saved the + * flags. Stop single stepping it. + */ + frame.tf_eflags &= ~PSL_T; + return; + } + /* + * Fall through. + */ + case T_BPTFLT: + /* + * If DDB is enabled, let it handle the debugger trap. + * Otherwise, debugger traps "can't happen". + */ +#ifdef DDB + if (kdb_trap (type, 0, &frame)) + return; +#endif + break; + +#if NISA > 0 + case T_NMI: +#ifdef POWERFAIL_NMI +#ifndef TIMER_FREQ +# define TIMER_FREQ 1193182 +#endif + handle_powerfail: + { + static unsigned lastalert = 0; + + if(time_second - lastalert > 10) + { + log(LOG_WARNING, "NMI: power fail\n"); + sysbeep(TIMER_FREQ/880, hz); + lastalert = time_second; + } + return; + } +#else /* !POWERFAIL_NMI */ +#ifdef DDB + /* NMI can be hooked up to a pushbutton for debugging */ + printf ("NMI ... going to debugger\n"); + if (kdb_trap (type, 0, &frame)) + return; +#endif /* DDB */ + /* machine/parity/power fail/"kitchen sink" faults */ + if (isa_nmi(code) == 0) return; + /* FALL THROUGH */ +#endif /* POWERFAIL_NMI */ +#endif /* NISA > 0 */ + } + + trap_fatal(&frame); + return; + } + + /* Translate fault for emulators (e.g. Linux) */ + if (*p->p_sysent->sv_transtrap) + i = (*p->p_sysent->sv_transtrap)(i, type); + + trapsignal(p, i, ucode); + +#ifdef DEBUG + eva = rcr2(); + if (type <= MAX_TRAP_MSG) { + uprintf("fatal process exception: %s", + trap_msg[type]); + if ((type == T_PAGEFLT) || (type == T_PROTFLT)) + uprintf(", fault VA = 0x%lx", eva); + uprintf("\n"); + } +#endif + +out: + userret(p, &frame, sticks); +} + +#ifdef notyet +/* + * This version doesn't allow a page fault to user space while + * in the kernel. The rest of the kernel needs to be made "safe" + * before this can be used. I think the only things remaining + * to be made safe are the iBCS2 code and the process tracing/ + * debugging code. + */ +static int +#ifdef CPU_BUGGY_CYRIX +trap_pfault(frame, usermode,faultva) + struct trapframe *frame; + int usermode; + vm_offset_t faultva; +#else +trap_pfault(frame, usermode) + struct trapframe *frame; + int usermode; +#endif +{ + vm_offset_t va; + struct vmspace *vm = NULL; + vm_map_t map = 0; + int rv = 0; + vm_prot_t ftype; + int eva; + struct proc *p = curproc; + + if (frame->tf_err & PGEX_W) + ftype = VM_PROT_READ | VM_PROT_WRITE; + else + ftype = VM_PROT_READ; + +#ifdef CPU_BUGGY_CYRIX + eva = faultva; +#else + eva = rcr2(); +#endif + va = trunc_page((vm_offset_t)eva); + + if (va < VM_MIN_KERNEL_ADDRESS) { + vm_offset_t v; + vm_page_t mpte; + + if (p == NULL || + (!usermode && va < VM_MAXUSER_ADDRESS && + (intr_nesting_level != 0 || curpcb == NULL || + curpcb->pcb_onfault == NULL))) { + trap_fatal(frame); + return (-1); + } + + /* + * This is a fault on non-kernel virtual memory. + * vm is initialized above to NULL. If curproc is NULL + * or curproc->p_vmspace is NULL the fault is fatal. + */ + vm = p->p_vmspace; + if (vm == NULL) + goto nogo; + + map = &vm->vm_map; + + /* + * Keep swapout from messing with us during this + * critical time. + */ + ++p->p_lock; + + /* + * Grow the stack if necessary + */ + if ((caddr_t)va > vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)USRSTACK) { + if (!grow(p, va)) { + rv = KERN_FAILURE; + --p->p_lock; + goto nogo; + } + } + + /* Fault in the user page: */ + rv = vm_fault(map, va, ftype, + (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY : 0); + + --p->p_lock; + } else { + /* + * Don't allow user-mode faults in kernel address space. + */ + if (usermode) + goto nogo; + + /* + * Since we know that kernel virtual address addresses + * always have pte pages mapped, we just have to fault + * the page. + */ + rv = vm_fault(kernel_map, va, ftype, FALSE); + } + + if (rv == KERN_SUCCESS) + return (0); +nogo: + if (!usermode) { + if (intr_nesting_level == 0 && curpcb && curpcb->pcb_onfault) { + frame->tf_eip = (int)curpcb->pcb_onfault; + return (0); + } + trap_fatal(frame); + return (-1); + } + + /* kludge to pass faulting virtual address to sendsig */ + frame->tf_err = eva; + + return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); +} +#endif + +int +#ifdef CPU_BUGGY_CYRIX +trap_pfault(frame, usermode,faultva) + struct trapframe *frame; + int usermode; + vm_offset_t faultva; +#else +trap_pfault(frame, usermode) + struct trapframe *frame; + int usermode; +#endif +{ + vm_offset_t va; + struct vmspace *vm = NULL; + vm_map_t map = 0; + int rv = 0; + vm_prot_t ftype; + int eva; + struct proc *p = curproc; + +#ifdef CPU_BUGGY_CYRIX + eva = faultva; +#else + eva = rcr2(); +#endif + va = trunc_page((vm_offset_t)eva); + + if (va >= KERNBASE) { + /* + * Don't allow user-mode faults in kernel address space. + * An exception: if the faulting address is the invalid + * instruction entry in the IDT, then the Intel Pentium + * F00F bug workaround was triggered, and we need to + * treat it is as an illegal instruction, and not a page + * fault. + */ +#if defined(I586_CPU) && !defined(NO_F00F_HACK) + if ((eva == (unsigned int)&t_idt[6]) && has_f00f_bug) { + frame->tf_trapno = T_PRIVINFLT; + return -2; + } +#endif + if (usermode) + goto nogo; + + map = kernel_map; + } else { + /* + * This is a fault on non-kernel virtual memory. + * vm is initialized above to NULL. If curproc is NULL + * or curproc->p_vmspace is NULL the fault is fatal. + */ + if (p != NULL) + vm = p->p_vmspace; + + if (vm == NULL) + goto nogo; + + map = &vm->vm_map; + } + + if (frame->tf_err & PGEX_W) + ftype = VM_PROT_READ | VM_PROT_WRITE; + else + ftype = VM_PROT_READ; + + if (map != kernel_map) { + /* + * Keep swapout from messing with us during this + * critical time. + */ + ++p->p_lock; + + /* + * Grow the stack if necessary + */ + if ((caddr_t)va > vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)USRSTACK) { + if (!grow(p, va)) { + rv = KERN_FAILURE; + --p->p_lock; + goto nogo; + } + } + + /* Fault in the user page: */ + rv = vm_fault(map, va, ftype, + (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY : 0); + + --p->p_lock; + } else { + /* + * Don't have to worry about process locking or stacks in the kernel. + */ + rv = vm_fault(map, va, ftype, FALSE); + } + + if (rv == KERN_SUCCESS) + return (0); +nogo: + if (!usermode) { + if (intr_nesting_level == 0 && curpcb && curpcb->pcb_onfault) { + frame->tf_eip = (int)curpcb->pcb_onfault; + return (0); + } + trap_fatal(frame); + return (-1); + } + + /* kludge to pass faulting virtual address to sendsig */ + frame->tf_err = eva; + + return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); +} + +static void +trap_fatal(frame) + struct trapframe *frame; +{ + int code, type, eva, ss, esp; + struct soft_segment_descriptor softseg; + + code = frame->tf_err; + type = frame->tf_trapno; + eva = rcr2(); + sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg); + + if (type <= MAX_TRAP_MSG) + printf("\n\nFatal trap %d: %s while in %s mode\n", + type, trap_msg[type], + frame->tf_eflags & PSL_VM ? "vm86" : + ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel"); +#ifdef SMP + /* three seperate prints in case of a trap on an unmapped page */ + printf("mp_lock = %08x; ", mp_lock); + printf("cpuid = %d; ", cpuid); + printf("lapic.id = %08x\n", lapic.id); +#endif + if (type == T_PAGEFLT) { + printf("fault virtual address = 0x%x\n", eva); + printf("fault code = %s %s, %s\n", + code & PGEX_U ? "user" : "supervisor", + code & PGEX_W ? "write" : "read", + code & PGEX_P ? "protection violation" : "page not present"); + } + printf("instruction pointer = 0x%x:0x%x\n", + frame->tf_cs & 0xffff, frame->tf_eip); + if ((ISPL(frame->tf_cs) == SEL_UPL) || (frame->tf_eflags & PSL_VM)) { + ss = frame->tf_ss & 0xffff; + esp = frame->tf_esp; + } else { + ss = GSEL(GDATA_SEL, SEL_KPL); + esp = (int)&frame->tf_esp; + } + printf("stack pointer = 0x%x:0x%x\n", ss, esp); + printf("frame pointer = 0x%x:0x%x\n", ss, frame->tf_ebp); + printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n", + softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type); + printf(" = DPL %d, pres %d, def32 %d, gran %d\n", + softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, + softseg.ssd_gran); + printf("processor eflags = "); + if (frame->tf_eflags & PSL_T) + printf("trace trap, "); + if (frame->tf_eflags & PSL_I) + printf("interrupt enabled, "); + if (frame->tf_eflags & PSL_NT) + printf("nested task, "); + if (frame->tf_eflags & PSL_RF) + printf("resume, "); + if (frame->tf_eflags & PSL_VM) + printf("vm86, "); + printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12); + printf("current process = "); + if (curproc) { + printf("%lu (%s)\n", + (u_long)curproc->p_pid, curproc->p_comm ? + curproc->p_comm : ""); + } else { + printf("Idle\n"); + } + printf("interrupt mask = "); + if ((cpl & net_imask) == net_imask) + printf("net "); + if ((cpl & tty_imask) == tty_imask) + printf("tty "); + if ((cpl & bio_imask) == bio_imask) + printf("bio "); + if ((cpl & cam_imask) == cam_imask) + printf("cam "); + if (cpl == 0) + printf("none"); +#ifdef SMP +/** + * XXX FIXME: + * we probably SHOULD have stopped the other CPUs before now! + * another CPU COULD have been touching cpl at this moment... + */ + printf(" <- SMP: XXX"); +#endif + printf("\n"); + +#ifdef KDB + if (kdb_trap(&psl)) + return; +#endif +#ifdef DDB + if (kdb_trap (type, 0, frame)) + return; +#endif + printf("trap number = %d\n", type); + if (type <= MAX_TRAP_MSG) + panic(trap_msg[type]); + else + panic("unknown/reserved trap"); +} + +/* + * Double fault handler. Called when a fault occurs while writing + * a frame for a trap/exception onto the stack. This usually occurs + * when the stack overflows (such is the case with infinite recursion, + * for example). + * + * XXX Note that the current PTD gets replaced by IdlePTD when the + * task switch occurs. This means that the stack that was active at + * the time of the double fault is not available at <kstack> unless + * the machine was idle when the double fault occurred. The downside + * of this is that "trace <ebp>" in ddb won't work. + */ +void +dblfault_handler() +{ + printf("\nFatal double fault:\n"); + printf("eip = 0x%x\n", common_tss.tss_eip); + printf("esp = 0x%x\n", common_tss.tss_esp); + printf("ebp = 0x%x\n", common_tss.tss_ebp); +#ifdef SMP + /* three seperate prints in case of a trap on an unmapped page */ + printf("mp_lock = %08x; ", mp_lock); + printf("cpuid = %d; ", cpuid); + printf("lapic.id = %08x\n", lapic.id); +#endif + panic("double fault"); +} + +/* + * Compensate for 386 brain damage (missing URKR). + * This is a little simpler than the pagefault handler in trap() because + * it the page tables have already been faulted in and high addresses + * are thrown out early for other reasons. + */ +int trapwrite(addr) + unsigned addr; +{ + struct proc *p; + vm_offset_t va; + struct vmspace *vm; + int rv; + + va = trunc_page((vm_offset_t)addr); + /* + * XXX - MAX is END. Changed > to >= for temp. fix. + */ + if (va >= VM_MAXUSER_ADDRESS) + return (1); + + p = curproc; + vm = p->p_vmspace; + + ++p->p_lock; + + if ((caddr_t)va >= vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)USRSTACK) { + if (!grow(p, va)) { + --p->p_lock; + return (1); + } + } + + /* + * fault the data page + */ + rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, VM_FAULT_DIRTY); + + --p->p_lock; + + if (rv != KERN_SUCCESS) + return 1; + + return (0); +} + +/* + * System call request from POSIX system call gate interface to kernel. + * Like trap(), argument is call by reference. + */ +void +syscall(frame) + struct trapframe frame; +{ + caddr_t params; + int i; + struct sysent *callp; + struct proc *p = curproc; + u_quad_t sticks; + int error; + int args[8]; + u_int code; + +#ifdef DIAGNOSTIC + if (ISPL(frame.tf_cs) != SEL_UPL) + panic("syscall"); +#endif + sticks = p->p_sticks; + p->p_md.md_regs = &frame; + params = (caddr_t)frame.tf_esp + sizeof(int); + code = frame.tf_eax; + if (p->p_sysent->sv_prepsyscall) { + (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, ¶ms); + } else { + /* + * Need to check if this is a 32 bit or 64 bit syscall. + */ + if (code == SYS_syscall) { + /* + * Code is first argument, followed by actual args. + */ + code = fuword(params); + params += sizeof(int); + } else if (code == SYS___syscall) { + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + code = fuword(params); + params += sizeof(quad_t); + } + } + + if (p->p_sysent->sv_mask) + code &= p->p_sysent->sv_mask; + + if (code >= p->p_sysent->sv_size) + callp = &p->p_sysent->sv_table[0]; + else + callp = &p->p_sysent->sv_table[code]; + + if (params && (i = callp->sy_narg * sizeof(int)) && + (error = copyin(params, (caddr_t)args, (u_int)i))) { +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, args); +#endif + goto bad; + } +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, args); +#endif + p->p_retval[0] = 0; + p->p_retval[1] = frame.tf_edx; + + STOPEVENT(p, S_SCE, callp->sy_narg); + + error = (*callp->sy_call)(p, args); + + switch (error) { + + case 0: + /* + * Reinitialize proc pointer `p' as it may be different + * if this is a child returning from fork syscall. + */ + p = curproc; + frame.tf_eax = p->p_retval[0]; + frame.tf_edx = p->p_retval[1]; + frame.tf_eflags &= ~PSL_C; + break; + + case ERESTART: + /* + * Reconstruct pc, assuming lcall $X,y is 7 bytes, + * int 0x80 is 2 bytes. We saved this in tf_err. + */ + frame.tf_eip -= frame.tf_err; + break; + + case EJUSTRETURN: + break; + + default: +bad: + if (p->p_sysent->sv_errsize) + if (error >= p->p_sysent->sv_errsize) + error = -1; /* XXX */ + else + error = p->p_sysent->sv_errtbl[error]; + frame.tf_eax = error; + frame.tf_eflags |= PSL_C; + break; + } + + if ((frame.tf_eflags & PSL_T) && !(frame.tf_eflags & PSL_VM)) { + /* Traced syscall. */ + frame.tf_eflags &= ~PSL_T; + trapsignal(p, SIGTRAP, 0); + } + + userret(p, &frame, sticks); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, p->p_retval[0]); +#endif + + /* + * This works because errno is findable through the + * register set. If we ever support an emulation where this + * is not the case, this code will need to be revisited. + */ + STOPEVENT(p, S_SCX, code); + +} + +/* + * Simplified back end of syscall(), used when returning from fork() + * directly into user mode. + */ +void +fork_return(p, frame) + struct proc *p; + struct trapframe frame; +{ + frame.tf_eax = 0; /* Child returns zero */ + frame.tf_eflags &= ~PSL_C; /* success */ + frame.tf_edx = 1; + + userret(p, &frame, 0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, SYS_fork, 0, 0); +#endif +} diff --git a/sys/pc98/i386/userconfig.c b/sys/pc98/i386/userconfig.c index 30fccbc4da75..d291653b8419 100644 --- a/sys/pc98/i386/userconfig.c +++ b/sys/pc98/i386/userconfig.c @@ -46,7 +46,7 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** - ** $Id: userconfig.c,v 1.64 1999/01/16 11:39:08 kato Exp $ + ** $Id: userconfig.c,v 1.56 1998/10/08 12:09:38 kato Exp $ **/ /** @@ -117,8 +117,6 @@ #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/reboot.h> -#include <sys/linker.h> -#include <sys/sysctl.h> #include <machine/cons.h> #include <machine/md_var.h> @@ -137,156 +135,36 @@ static MALLOC_DEFINE(M_DEVL, "isa_devlist", "isa_device lists in userconfig()"); static struct isa_device *isa_devlist; /* list read by dset to extract changes */ +#ifdef USERCONFIG_BOOT +char userconfig_from_boot[512] = ""; static int userconfig_boot_parsing; /* set if we are reading from the boot instructions */ -#define putchar(x) cnputc(x) - static int -sysctl_machdep_uc_devlist SYSCTL_HANDLER_ARGS +getchar(void) { - struct isa_device *id; - int error=0; - char name[8]; + static char *next = userconfig_from_boot; - if(!req->oldptr) { - /* Only sizing */ - id=isa_devlist; - while(id) { - error+=sizeof(struct isa_device)+8; - id=id->id_next; - } - return(SYSCTL_OUT(req,0,error)); + if (next == userconfig_from_boot) { + if (strncmp(next, "USERCONFIG\n", 11)) { + next++; + strcpy(next, "intro\n"); } else { - /* Output the data. The buffer is filled with consecutive - * struct isa_device and char buf[8], containing the name - * (not guaranteed to end with '\0'). - */ - id=isa_devlist; - while(id) { - error=sysctl_handle_opaque(oidp,id, - sizeof(struct isa_device),req); - if(error) return(error); - strncpy(name,id->id_driver->name,8); - error=sysctl_handle_opaque(oidp,name, - 8,req); - if(error) return(error); - id=id->id_next; - } - return(0); - } -} - -SYSCTL_PROC( _machdep, OID_AUTO, uc_devlist, CTLFLAG_RD, - 0, 0, sysctl_machdep_uc_devlist, "A", - "List of ISA devices changed in UserConfig"); - -/* -** Obtain command input. -** -** Initially, input is read from a possibly-loaded script. -** At the end of the script, or if no script is supplied, -** behaviour is determined by the RB_CONFIG (-c) flag. If -** the flag is set, user input is read from the console; if -** unset, the 'quit' command is invoked and userconfig -** will exit. -** -** Note that quit commands encountered in the script will be -** ignored if the RB_CONFIG flag is supplied. -*/ -static int -getchar(void) -{ - static const char *asp; - static int assize; /* use of int for -ve magic value */ - static int autocheck = 0; - caddr_t autoentry, autoattr; - int c = 0; - static int intro = 0; - - /* Look for loaded userconfig script */ - if (autocheck == 0) - { - autocheck = 1; - autoentry = preload_search_by_type("userconfig_script"); - if (autoentry != NULL) - { - /* We have one, get size and data */ - assize = 0; - if ((autoattr = preload_search_info(autoentry, MODINFO_SIZE)) != NULL) - assize = (size_t)*(u_int32_t *)autoattr; - asp = NULL; - if ((autoattr = preload_search_info(autoentry, MODINFO_ADDR)) != NULL) - asp = *(const char **)autoattr; - /* sanity check */ - if ((assize == 0) || (asp == NULL)) { - assize = 0; - asp = NULL; - } + next += 11; } - } - - if (assize > 0) - { - /* Consume character from loaded userconfig script, display */ + } + if (*next) { userconfig_boot_parsing = 1; - c = *asp; - asp++; - assize--; - - } else if (assize == 0) { - -#ifdef INTRO_USERCONFIG - if (intro == 0) - { - /* - * We don't want intro if we just executed a - * script (userconfig_boot_parsing==1), otherwise - * we would always block here waiting for user input. - */ - intro = 1; - if (userconfig_boot_parsing == 0) - { - /* userconfig_boot_parsing will be set to 1 on next pass, - * which will allow using 'intro' in the middle of other - * userconfig_script commands. - */ - c = 'i'; - asp = "ntro\n"; - assize = strlen(asp); - } else { - userconfig_boot_parsing = 0; - assize=-1; - } -#else + return (*next++); + } else { userconfig_boot_parsing = 0; - if (!(boothowto & RB_CONFIG)) - { - /* don't want to drop to interpreter */ - c = 'q'; - asp = "uit\n"; - assize = strlen(asp); -#endif - userconfig_boot_parsing = 0; - } else { - /* Only display signon banner if we are about to go interactive */ - if (!intro) - printf("\nFreeBSD Kernel Configuration Utility - Version 1.2\n" - " Type \"help\" for help" -#ifdef VISUAL_USERCONFIG - " or \"visual\" to go to the visual\n" - " configuration interface (requires MGA/VGA display or\n" - " serial terminal capable of displaying ANSI graphics)" -#endif - ".\n"); - assize = -1; - } + return cngetc(); } - if (assize < 0) { - /* No script, read from the keyboard */ - c = cngetc(); - } - return(c); } +#else /* !USERCONFIG_BOOT */ +#define getchar() cngetc() +#endif /* USERCONFIG_BOOT */ + +#define putchar(x) cnputc(x) #ifndef FALSE #define FALSE (0) @@ -403,16 +281,10 @@ static DEV_INFO device_info[] = { {"vx", "3COM 3C590/3C595 Ethernet adapters", 0, CLS_NETWORK}, {"ze", "IBM/National Semiconductor PCMCIA Ethernet adapter",0, CLS_NETWORK}, {"zp", "3COM PCMCIA Etherlink III Ethernet adapter", 0, CLS_NETWORK}, -{"ax", "ASIC AX88140A ethernet adapter", FLG_FIXED, CLS_NETWORK}, {"de", "DEC DC21040 Ethernet adapter", FLG_FIXED, CLS_NETWORK}, {"fpa", "DEC DEFPA PCI FDDI adapter", FLG_FIXED, CLS_NETWORK}, -{"rl", "RealTek 8129/8139 ethernet adapter", FLG_FIXED, CLS_NETWORK}, -{"mx", "Macronix PMAC ethernet adapter", FLG_FIXED, CLS_NETWORK}, -{"pn", "Lite-On 82c168/82c169 PNIC adapter", FLG_FIXED, CLS_NETWORK}, -{"tl", "Texas Instruments ThunderLAN ethernet adapter", FLG_FIXED, CLS_NETWORK}, -{"vr", "VIA Rhine/Rhine II ethernet adapter", FLG_FIXED, CLS_NETWORK}, -{"wb", "Winbond W89C840F ethernet adapter", FLG_FIXED, CLS_NETWORK}, -{"xl", "3COM 3C90x PCI ethernet adapter", FLG_FIXED, CLS_NETWORK}, +{"tlc", "Texas Instruments ThunderLAN ethernet adapter", FLG_FIXED, CLS_NETWORK}, +{"xl", "3COM 3C90x PCI FDDI adapter", FLG_FIXED, CLS_NETWORK}, {"sio", "8250/16450/16550 Serial port", 0, CLS_COMMS}, {"cx", "Cronyx/Sigma multiport sync/async adapter",0, CLS_COMMS}, @@ -2081,17 +1953,15 @@ static void helpscreen(void) { int topline = 0; /* where we are in the text */ - int c, delta = 1; + int line, c, delta = 1; char prompt[80]; for (;;) /* loop until user quits */ { - int line = 0; - /* display help text */ if (delta) { - clear(); /* remove everything else */ + clear(); /* remove everything else */ for (line = topline; (line < (topline + 24)) && (helptext[line]); line++) @@ -2531,7 +2401,7 @@ visuserconfig(void) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: userconfig.c,v 1.64 1999/01/16 11:39:08 kato Exp $ + * $Id: userconfig.c,v 1.56 1998/10/08 12:09:38 kato Exp $ */ #include "scbus.h" @@ -2584,7 +2454,7 @@ static int set_device_enable(CmdParm *); static int set_device_disable(CmdParm *); static int quitfunc(CmdParm *); static int helpfunc(CmdParm *); -#if defined(INTRO_USERCONFIG) +#if defined(USERCONFIG_BOOT) static int introfunc(CmdParm *); #endif @@ -2622,12 +2492,10 @@ static CmdParm dev_parms[] = { { -1, {} }, }; -#if NPNP > 0 static CmdParm string_arg[] = { { PARM_STRING, {} }, { -1, {} }, }; -#endif #if NEISA > 0 static CmdParm int_arg[] = { @@ -2647,7 +2515,7 @@ static Cmd CmdList[] = { { "ex", quitfunc, NULL }, /* exit (quit) */ { "f", set_device_flags, int_parms }, /* flags dev mask */ { "h", helpfunc, NULL }, /* help */ -#if defined(INTRO_USERCONFIG) +#if defined(USERCONFIG_BOOT) { "intro", introfunc, NULL }, /* intro screen */ #endif { "iom", set_device_mem, addr_parms }, /* iomem dev addr */ @@ -2676,6 +2544,16 @@ userconfig(void) int rval; Cmd *cmd; + printf("\nFreeBSD Kernel Configuration Utility - Version 1.1\n" + " Type \"help\" for help" +#ifdef VISUAL_USERCONFIG + " or \"visual\" to go to the visual\n" + " configuration interface (requires MGA/VGA display or\n" + " serial terminal capable of displaying ANSI graphics)" +#endif + ".\n"); + + while (1) { printf("config> "); cngets(input, 80); @@ -2989,6 +2867,7 @@ set_num_eisa_slots(CmdParm *parms) static int quitfunc(CmdParm *parms) { +#ifdef USERCONFIG_BOOT /* * If kernel config supplied, and we are parsing it, and -c also supplied, * ignore a quit command, This provides a safety mechanism to allow @@ -2996,6 +2875,7 @@ quitfunc(CmdParm *parms) */ if ((boothowto & RB_CONFIG) && userconfig_boot_parsing) return 0; +#endif return 1; } @@ -3038,7 +2918,7 @@ helpfunc(CmdParm *parms) return 0; } -#if defined(INTRO_USERCONFIG) +#if defined(USERCONFIG_BOOT) #if defined (VISUAL_USERCONFIG) static void @@ -3172,10 +3052,7 @@ introfunc(CmdParm *parms) return visuserconfig(); else { putxy(0, 1, "Type \"help\" for help or \"quit\" to exit."); - /* enable quitfunc */ - userconfig_boot_parsing=0; move (0, 3); - boothowto |= RB_CONFIG; /* force -c */ return 0; } break; @@ -3204,14 +3081,12 @@ lspnp () "mem 0x%x 0x%x 0x%x 0x%x"; char buf[256]; if (lineno >= 23) { - if (!userconfig_boot_parsing) { - printf("<More> "); - if (getchar() == 'q') { - printf("quit\n"); - return (1); - } - printf("\n"); + printf("<More> "); + if (getchar() == 'q') { + printf("quit\n"); + return (1); } + printf("\n"); lineno = 0; } if (lineno == 0 || first) @@ -3257,13 +3132,11 @@ lsdevtab(struct isa_device *dt) if (lineno >= 23) { printf("<More> "); - if (!userconfig_boot_parsing) { - if (getchar() == 'q') { - printf("quit\n"); - return (1); - } - printf("\n"); + if (getchar() == 'q') { + printf("quit\n"); + return (1); } + printf("\n"); lineno = 0; } if (lineno == 0) { diff --git a/sys/pc98/pc98/atcompat_diskslice.c b/sys/pc98/pc98/atcompat_diskslice.c index ad51bc05e3f6..c25afaf36e56 100644 --- a/sys/pc98/pc98/atcompat_diskslice.c +++ b/sys/pc98/pc98/atcompat_diskslice.c @@ -35,7 +35,7 @@ * * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $ - * $Id: atcompat_diskslice.c,v 1.12 1998/08/10 16:55:54 kato Exp $ + * $Id: atcompat_diskslice.c,v 1.11 1998/07/27 09:49:22 kato Exp $ */ /* @@ -423,7 +423,7 @@ atcompat_extended(dname, dev, strat, lp, ssp, ext_offset, ext_size, sname = dsname(dname, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname); - snprintf(buf, sizeof(buf), "%s", sname); + strcpy(buf, sname); if (strlen(buf) < sizeof buf - 11) strcat(buf, "<extended>"); check_part(buf, dp, base_ext_offset, nsectors, diff --git a/sys/pc98/pc98/clock.c b/sys/pc98/pc98/clock.c index 1225f3157d4c..20744f80f8c0 100644 --- a/sys/pc98/pc98/clock.c +++ b/sys/pc98/pc98/clock.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.64 1998/10/23 13:13:43 kato Exp $ + * $Id: clock.c,v 1.62 1998/10/13 02:33:21 kato Exp $ */ /* @@ -136,7 +136,7 @@ static void setup_8254_mixed_mode __P((void)); */ #define TIMER0_MAX_FREQ 20000 -int adjkerntz; /* local offset from GMT in seconds */ +int adjkerntz; /* local offset from GMT in seconds */ int disable_rtc_set; /* disable resettodr() if != 0 */ u_int idelayed; int statclock_disable; @@ -151,7 +151,7 @@ u_int stat_imask = SWI_CLOCK_MASK; u_int timer_freq = TIMER_FREQ; int timer0_max_count; u_int tsc_freq; -int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ static int beeping = 0; static u_int clk_imask = HWI_MASK | SWI_MASK; @@ -198,7 +198,7 @@ static unsigned i8254_get_timecount __P((struct timecounter *tc)); static unsigned tsc_get_timecount __P((struct timecounter *tc)); static void set_timer_freq(u_int freq, int intr_freq); -static struct timecounter tsc_timecounter = { +static struct timecounter tsc_timecounter[3] = { tsc_get_timecount, /* get_timecount */ 0, /* no poll_pps */ ~0u, /* counter_mask */ @@ -207,9 +207,9 @@ static struct timecounter tsc_timecounter = { }; SYSCTL_OPAQUE(_debug, OID_AUTO, tsc_timecounter, CTLFLAG_RD, - &tsc_timecounter, sizeof(tsc_timecounter), "S,timecounter", ""); + tsc_timecounter, sizeof(tsc_timecounter), "S,timecounter", ""); -static struct timecounter i8254_timecounter = { +static struct timecounter i8254_timecounter[3] = { i8254_get_timecount, /* get_timecount */ 0, /* no poll_pps */ ~0u, /* counter_mask */ @@ -218,7 +218,7 @@ static struct timecounter i8254_timecounter = { }; SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, - &i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", ""); + i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", ""); static void clkintr(struct clockframe frame) @@ -952,8 +952,8 @@ startrtclock() } set_timer_freq(timer_freq, hz); - i8254_timecounter.tc_frequency = timer_freq; - init_timecounter(&i8254_timecounter); + i8254_timecounter[0].tc_frequency = timer_freq; + init_timecounter(i8254_timecounter); #ifndef CLK_USE_TSC_CALIBRATION if (tsc_freq != 0) { @@ -1002,8 +1002,8 @@ startrtclock() #endif /* NAPM > 0 */ if (tsc_present && tsc_freq != 0) { - tsc_timecounter.tc_frequency = tsc_freq; - init_timecounter(&tsc_timecounter); + tsc_timecounter[0].tc_frequency = tsc_freq; + init_timecounter(tsc_timecounter); } #endif /* !defined(SMP) */ @@ -1070,8 +1070,8 @@ rtc_inb(void) #endif /* PC-98 */ /* - * Initialize the time of day register, based on the time base which is, e.g. - * from a filesystem. + * Initialize the time of day register, based on the time base which is, e.g. + * from a filesystem. */ void inittodr(time_t base) @@ -1123,17 +1123,17 @@ inittodr(time_t base) /* sec now contains the number of seconds, since Jan 1 1970, in the local time zone */ #else /* IBM-PC */ - /* Look if we have a RTC present and the time is valid */ + /* Look if we have a RTC present and the time is valid */ if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) goto wrong_time; - /* wait for time update to complete */ - /* If RTCSA_TUP is zero, we have at least 244us before next update */ + /* wait for time update to complete */ + /* If RTCSA_TUP is zero, we have at least 244us before next update */ while (rtcin(RTC_STATUSA) & RTCSA_TUP); days = 0; #ifdef USE_RTC_CENTURY - year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; + year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; #else year = readrtc(RTC_YEAR) + 1900; if (year < 1970) @@ -1141,21 +1141,21 @@ inittodr(time_t base) #endif if (year < 1970) goto wrong_time; - month = readrtc(RTC_MONTH); - for (m = 1; m < month; m++) - days += daysinmonth[m-1]; - if ((month > 2) && LEAPYEAR(year)) + month = readrtc(RTC_MONTH); + for (m = 1; m < month; m++) + days += daysinmonth[m-1]; + if ((month > 2) && LEAPYEAR(year)) days ++; - days += readrtc(RTC_DAY) - 1; + days += readrtc(RTC_DAY) - 1; yd = days; for (y = 1970; y < year; y++) - days += DAYSPERYEAR + LEAPYEAR(y); + days += DAYSPERYEAR + LEAPYEAR(y); sec = ((( days * 24 + readrtc(RTC_HRS)) * 60 + readrtc(RTC_MIN)) * 60 + readrtc(RTC_SEC)); - /* sec now contains the number of seconds, since Jan 1 1970, - in the local time zone */ + /* sec now contains the number of seconds, since Jan 1 1970, + in the local time zone */ #endif sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); @@ -1172,12 +1172,12 @@ inittodr(time_t base) return; wrong_time: - printf("Invalid time in real time clock.\n"); - printf("Check and reset the date immediately!\n"); + printf("Invalid time in real time clock.\n"); + printf("Check and reset the date immediately!\n"); } /* - * Write system time back to RTC + * Write system time back to RTC */ void resettodr() @@ -1236,7 +1236,7 @@ resettodr() /* Disable RTC updates and interrupts. */ writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); - /* Calculate local time to put in RTC */ + /* Calculate local time to put in RTC */ tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); @@ -1244,7 +1244,7 @@ resettodr() writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ - /* We have now the days since 01-01-1970 in tm */ + /* We have now the days since 01-01-1970 in tm */ writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); tm >= m; @@ -1467,7 +1467,7 @@ sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS if (timer0_state != RELEASED) return (EBUSY); /* too much trouble to handle */ set_timer_freq(freq, hz); - i8254_timecounter.tc_frequency = freq; + i8254_timecounter[0].tc_frequency = freq; } return (error); } @@ -1487,7 +1487,7 @@ sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); if (error == 0 && req->newptr != NULL) { tsc_freq = freq; - tsc_timecounter.tc_frequency = tsc_freq; + tsc_timecounter[0].tc_frequency = tsc_freq; } return (error); } diff --git a/sys/pc98/pc98/diskslice_machdep.c b/sys/pc98/pc98/diskslice_machdep.c index 5370462dcd06..e2688ffde2f6 100644 --- a/sys/pc98/pc98/diskslice_machdep.c +++ b/sys/pc98/pc98/diskslice_machdep.c @@ -35,7 +35,7 @@ * * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $ - * $Id: diskslice_machdep.c,v 1.16 1998/08/10 16:55:54 kato Exp $ + * $Id: diskslice_machdep.c,v 1.15 1998/07/27 09:49:23 kato Exp $ */ /* @@ -470,7 +470,7 @@ reread_mbr: sp->ds_size = pc98_size; sp->ds_type = dp->dp_mid; sp->ds_subtype = dp->dp_sid; - strncpy(sp->ds_name, dp->dp_name, sizeof(sp->ds_name)); + strncpy(sp->ds_name, dp->dp_name, 16); #else sp->ds_offset = mbr_offset + dp->dp_start; sp->ds_size = dp->dp_size; @@ -580,7 +580,7 @@ extended(dname, dev, strat, lp, ssp, ext_offset, ext_size, base_ext_offset, sname = dsname(dname, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname); - snprintf(buf, sizeof(buf), "%s", sname); + strcpy(buf, sname); if (strlen(buf) < sizeof buf - 11) strcat(buf, "<extended>"); check_part(buf, dp, base_ext_offset, nsectors, @@ -611,7 +611,7 @@ extended(dname, dev, strat, lp, ssp, ext_offset, ext_size, base_ext_offset, sp->ds_size = pc98_size; sp->ds_type = dp->dp_mid; sp->ds_subtype = dp->dp_sid; - strncpy(sp->ds_name, dp->dp_name, sizeof(sp->ds_name)); + strncpy(sp->ds_name, dp->dp_name, 16); #else sp->ds_offset = ext_offset + dp->dp_start; sp->ds_size = dp->dp_size; diff --git a/sys/pc98/pc98/fd.c b/sys/pc98/pc98/fd.c index 90f230f5e871..889c066e6e25 100644 --- a/sys/pc98/pc98/fd.c +++ b/sys/pc98/pc98/fd.c @@ -5,10 +5,6 @@ * 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) @@ -47,10 +43,14 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.49 1999/01/16 11:40:02 kato Exp $ + * $Id: fd.c,v 1.40 1998/09/15 14:07:08 kato Exp $ * */ +#include "ft.h" +#if NFT < 1 +#undef NFDC +#endif #include "fd.h" #include "opt_devfs.h" #include "opt_fdc.h" @@ -84,6 +84,10 @@ #endif #include <i386/isa/fdc.h> #include <machine/stdarg.h> +#if NFT > 0 +#include <sys/ftape.h> +#include <i386/isa/ftreg.h> +#endif #ifdef DEVFS #include <sys/devfsext.h> #endif /* DEVFS */ @@ -93,10 +97,6 @@ /* configuration flags */ #define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */ -#ifdef FDC_YE -#define FDC_IS_PCMCIA (1 << 1) /* if successful probe, then it's - a PCMCIA device */ -#endif /* internally used only, not really from CMOS: */ #define RTCFDT_144M_PRETENDED 0x1000 @@ -285,9 +285,15 @@ nrd_info(addr) * fdsu is the floppy drive unit number on that controller. (sub-unit) * \***********************************************************************/ -#ifdef FDC_YE -#include "card.h" -static int yeattach(struct isa_device *); +#if NFT > 0 +int ftopen(dev_t, int); +int ftintr(ftu_t ftu); +int ftclose(dev_t, int); +void ftstrategy(struct buf *); +int ftioctl(dev_t, unsigned long, caddr_t, int, struct proc *); +int ftdump(dev_t); +int ftsize(dev_t); +int ftattach(struct isa_device *, struct isa_device *, int); #endif /* autoconfig functions */ @@ -310,7 +316,6 @@ static int fd_in(fdcu_t, int *); static void fdstart(fdcu_t); static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; -static ointhand2_t fdintr; static int fdstate(fdcu_t, fdc_p); static int retrier(fdcu_t); static int fdformat(dev_t, struct fd_formb *, struct proc *); @@ -333,9 +338,6 @@ static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */ #define MOTORWAIT 10 #define IOTIMEDOUT 11 #define RESETCOMPLETE 12 -#ifdef FDC_YE -#define PIOREAD 13 -#endif #ifdef FDC_DEBUG static char const * const fdstates[] = @@ -353,9 +355,6 @@ static char const * const fdstates[] = "MOTORWAIT", "IOTIMEDOUT", "RESETCOMPLETE", -#ifdef FDC_YE -"PIOREAD", -#endif }; /* CAUTION: fd_debug causes huge amounts of logging output */ @@ -367,91 +366,6 @@ static int volatile fd_debug = 0; #define TRACE1(arg1, arg2) #endif /* FDC_DEBUG */ -#ifdef FDC_YE -#if NCARD > 0 -#include <sys/select.h> -#include <sys/module.h> -#include <pccard/cardinfo.h> -#include <pccard/driver.h> -#include <pccard/slot.h> - -/* - * PC-Card (PCMCIA) specific code. - */ -static int yeinit(struct pccard_devinfo *); /* init device */ -static void yeunload(struct pccard_devinfo *); /* Disable driver */ -static int yeintr(struct pccard_devinfo *); /* Interrupt handler */ - -PCCARD_MODULE(fdc, yeinit, yeunload, yeintr, 0, bio_imask); - -/* - * this is the secret PIO data port (offset from base) - */ -#define FDC_YE_DATAPORT 6 - -/* - * Initialize the device - called from Slot manager. - */ -static int yeinit(struct pccard_devinfo *devi) -{ - fdc_p fdc = &fdc_data[devi->isahd.id_unit]; - - /* validate unit number. */ - if (devi->isahd.id_unit >= NFDC) - return(ENODEV); - fdc->baseport = devi->isahd.id_iobase; - /* - * reset controller - */ - outb(fdc->baseport+FDOUT, 0); - DELAY(100); - outb(fdc->baseport+FDOUT, FDO_FRST); - - /* - * wire into system - */ - if (yeattach(&devi->isahd) == 0) - return(ENXIO); - - return(0); -} - -/* - * yeunload - unload the driver and clear the table. - * XXX TODO: - * This is usually called when the card is ejected, but - * can be caused by a modunload 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. - */ -static void yeunload(struct pccard_devinfo *devi) -{ - if (fd_data[devi->isahd.id_unit].type == NO_TYPE) - return; - - /* - * this prevents Fdopen() and fdstrategy() from attempting - * to access unloaded controller - */ - fd_data[devi->isahd.id_unit].type = NO_TYPE; - - printf("fdc%d: unload\n", devi->isahd.id_unit); -} - -/* - * yeintr - Shared interrupt called from - * front end of PC-Card handler. - */ -static int yeintr(struct pccard_devinfo *devi) -{ - fdintr((fdcu_t)devi->isahd.id_unit); - return(1); -} -#endif /* NCARD > 0 */ -#endif /* FDC_YE */ - - /* autoconfig structure */ struct isa_driver fdcdriver = { @@ -490,7 +404,7 @@ fdc_err(fdcu_t fdcu, const char *s) printf("fdc%d: %s", fdcu, s); else if(fdc_data[fdcu].fdc_errs == FDC_ERRMAX) printf("fdc%d: too many errors, not logging any more\n", - fdcu); + fdcu); } return FD_FAILED; @@ -520,7 +434,7 @@ fd_cmd(fdcu_t fdcu, int n_out, ...) if (out_fdc(fdcu, va_arg(ap, int)) < 0) { char msg[50]; - snprintf(msg, sizeof(msg), + sprintf(msg, "cmd %x failed at out byte %d of %d\n", cmd, n + 1, n_out); return fdc_err(fdcu, msg); @@ -533,7 +447,7 @@ fd_cmd(fdcu_t fdcu, int n_out, ...) if (fd_in(fdcu, ptr) < 0) { char msg[50]; - snprintf(msg, sizeof(msg), + sprintf(msg, "cmd %02x failed at in byte %d of %d\n", cmd, n + 1, n_in); return fdc_err(fdcu, msg); @@ -783,14 +697,6 @@ fdprobe(struct isa_device *dev) { return(0); } -#ifdef FDC_YE - /* - * don't succeed on probe; wait - * for PCCARD subsystem to do it - */ - if (dev->id_flags & FDC_IS_PCMCIA) - return(0); -#endif return (IO_FDCSIZE); } @@ -806,6 +712,9 @@ fdattach(struct isa_device *dev) fdc_p fdc = fdc_data + fdcu; fd_p fd; int fdsu, st0, st3, i; +#if NFT > 0 + int unithasfd; +#endif struct isa_device *fdup; int ic_type = 0; #ifdef DEVFS @@ -814,7 +723,6 @@ fdattach(struct isa_device *dev) int typesize; #endif - dev->id_ointr = fdintr; fdc->fdcu = fdcu; fdc->flags |= FDC_ATTACHED; #ifdef PC98 @@ -845,7 +753,7 @@ fdattach(struct isa_device *dev) continue; fdu = fdup->id_unit; fd = &fd_data[fdu]; - if (fdu >= (NFD)) + if (fdu >= (NFD+NFT)) continue; fdsu = fdup->id_physid; /* look up what bios thinks we have */ @@ -901,11 +809,29 @@ fdattach(struct isa_device *dev) #else if ((fdt == RTCFDT_NONE) #endif +#if NFT > 0 + || (fdsu >= DRVS_PER_CTLR)) { +#else ) { #ifdef PC98 fd->fdc = fdc; #endif fd->type = NO_TYPE; +#endif +#if NFT > 0 + /* If BIOS says no floppy, or > 2nd device */ + /* Probe for and attach a floppy tape. */ + /* Tell FT if there was already a disk */ + /* with this unit number found. */ + + unithasfd = 0; + if (fdu < NFD && fd->type != NO_TYPE) + unithasfd = 1; + if (ftattach(dev, fdup, unithasfd)) + continue; + if (fdsu < DRVS_PER_CTLR) + fd->type = NO_TYPE; +#endif continue; } @@ -952,7 +878,7 @@ fdattach(struct isa_device *dev) enable_fifo(fdc) == 0) { printf("fdc%d: FIFO enabled", fdcu); printf(", %d bytes threshold\n", - fifo_threshold); + fifo_threshold); } } if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && @@ -1141,10 +1067,10 @@ fdattach(struct isa_device *dev) } for (i = 0; i < MAXPARTITIONS; i++) { - fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], + fd->bdevs[1 + NUMDENS + i] = devfs_link(fd->bdevs[0], "fd%d%c", fdu, 'a' + i); fd->cdevs[1 + NUMDENS + i] = - devfs_makelink(fd->cdevs[0], + devfs_link(fd->cdevs[0], "rfd%d%c", fdu, 'a' + i); } #endif /* DEVFS */ @@ -1163,138 +1089,6 @@ fdattach(struct isa_device *dev) -#ifdef FDC_YE -/* - * this is a subset of fdattach() optimized for the Y-E Data - * PCMCIA floppy drive. - */ -static int yeattach(struct isa_device *dev) -{ - fdcu_t fdcu = dev->id_unit; - fdc_p fdc = fdc_data + fdcu; - fdsu_t fdsu = 0; /* assume 1 drive per YE controller */ - fdu_t fdu; - fd_p fd; - int st0, st3, i; -#ifdef DEVFS - int mynor; - int typemynor; - int typesize; -#endif - fdc->fdcu = fdcu; - /* - * the FDC_PCMCIA flag is used to to indicate special PIO is used - * instead of DMA - */ - fdc->flags = FDC_ATTACHED|FDC_PCMCIA; - fdc->state = DEVIDLE; - /* reset controller, turn motor off, clear fdout mirror reg */ - outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); - bufq_init(&fdc->head); - /* - * assume 2 drives/ "normal" controller - */ - fdu = fdcu * 2; - if (fdu >= NFD) { - printf("fdu %d >= NFD\n",fdu); - return(0); - }; - fd = &fd_data[fdu]; - - set_motor(fdcu, fdsu, TURNON); - DELAY(1000000); /* 1 sec */ - fdc->fdct = FDC_NE765; - - if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* if at track 0, first seek inwards */ - /* seek some steps: */ - (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); - DELAY(300000); /* ...wait a moment... */ - (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ - } - - /* 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(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { - /* ...wait a moment... */ - DELAY(300000); - /* make ctrlr happy: */ - (void)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(fdcu, 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(fdcu, fdsu, TURNOFF); - - if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ - return(0); - - fd->track = FD_NO_TRACK; - fd->fdc = fdc; - fd->fdsu = fdsu; - fd->options = 0; - printf("fdc%d: 1.44MB 3.5in PCMCIA\n", fdcu); - fd->type = FD_1440; - -#ifdef DEVFS - mynor = fdcu << 6; - fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, - "fd%d", fdu); - fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, - "rfd%d", fdu); - /* - * XXX this and the lookup in Fdopen() should be - * data driven. - */ - typemynor = mynor | FD_1440; - typesize = fd_types[FD_1440 - 1].size / 2; - /* - * XXX all these conversions give bloated code and - * confusing names. - */ - if (typesize == 1476) - typesize = 1480; - if (typesize == 1722) - typesize = 1720; - fd->bdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor, - DV_BLK, UID_ROOT, GID_OPERATOR, - 0640, "fd%d.%d", fdu, typesize); - fd->cdevs[FD_1440] = devfs_add_devswf(&fd_cdevsw, typemynor, - DV_CHR, UID_ROOT, GID_OPERATOR, - 0640,"rfd%d.%d", fdu, typesize); - for (i = 0; i < MAXPARTITIONS; i++) { - fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], - "fd%d%c", fdu, 'a' + i); - fd->cdevs[1 + NUMDENS + i] = devfs_makelink(fd->cdevs[0], - "rfd%d%c", fdu, 'a' + i); - } -#endif /* DEVFS */ - return (1); -} -#endif - /****************************************************************************/ /* motor control stuff */ /* remember to not deselect the drive we're working on */ @@ -1532,6 +1326,11 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) int type = FDTYPE(minor(dev)); fdc_p fdc; +#if NFT > 0 + /* check for a tape open */ + if (type & F_TAPE_TYPE) + return(ftopen(dev, flags)); +#endif /* check bounds */ if (fdu >= NFD) return(ENXIO); @@ -1611,6 +1410,12 @@ fdclose(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); +#if NFT > 0 + int type = FDTYPE(minor(dev)); + + if (type & F_TAPE_TYPE) + return ftclose(dev, flags); +#endif fd_data[fdu].flags &= ~FD_OPEN; fd_data[fdu].options &= ~FDOPT_NORETRY; @@ -1648,18 +1453,21 @@ fdstrategy(struct buf *bp) fd = &fd_data[fdu]; fdc = fd->fdc; fdcu = fdc->fdcu; -#ifdef FDC_YE - if (fd->type == NO_TYPE) { - bp->b_error = ENXIO; + +#if NFT > 0 + if (FDTYPE(minor(bp->b_dev)) & F_TAPE_TYPE) { + /* ft tapes do not (yet) support strategy i/o */ + bp->b_error = ENODEV; bp->b_flags |= B_ERROR; - /* - * I _refuse_ to use a goto - */ - biodone(bp); - return; - }; + goto bad; + } + /* check for controller already busy with tape */ + if (fdc->flags & FDC_TAPE_BUSY) { + bp->b_error = EBUSY; + bp->b_flags |= B_ERROR; + goto bad; + } #endif - fdblk = 128 << (fd->ft->secsize); if (!(bp->b_flags & B_FORMAT)) { if ((fdu >= NFD) || (bp->b_blkno < 0)) { @@ -1797,46 +1605,21 @@ fd_pseudointr(void *arg1) * keep calling the state machine until it returns a 0 * * ALWAYS called at SPLBIO * \***********************************************************************/ -static void +void fdintr(fdcu_t fdcu) { fdc_p fdc = fdc_data + fdcu; +#if NFT > 0 + fdu_t fdu = fdc->fdu; + + if (fdc->flags & FDC_TAPE_BUSY) + (ftintr(fdu)); + else +#endif while(fdstate(fdcu, fdc)) ; } -#ifdef FDC_YE -/* - * magic pseudo-DMA initialization for YE FDC. Sets count and - * direction - */ -#define SET_BCDR(wr,cnt,port) outb(port,(((cnt)-1) & 0xff)); \ - outb(port+1,((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f))) - -/* - * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy - */ -static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) -{ - u_char *cptr = (u_char *)addr; - fdc_p fdc = &fdc_data[fdcu]; - int io = fdc->baseport; - - if (flags & B_READ) { - if (fdc->state != PIOREAD) { - fdc->state = PIOREAD; - return(0); - }; - SET_BCDR(0,count,io); - insb(io+FDC_YE_DATAPORT,cptr,count); - } else { - outsb(io+FDC_YE_DATAPORT,cptr,count); - SET_BCDR(0,count,io); - }; - return(1); -} -#endif /* FDC_YE */ - /***********************************************************************\ * The controller state machine. * * if it returns a non zero value, it should be called again immediatly * @@ -1844,6 +1627,7 @@ static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) static int fdstate(fdcu_t fdcu, fdc_p fdc) { + struct subdev *sd; int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; unsigned blknum = 0, b_cylinder = 0; fdu_t fdu = fdc->fdu; @@ -1852,15 +1636,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) struct fd_formb *finfo = NULL; size_t fdblk; - bp = fdc->bp; - if (bp == NULL) { - bp = bufq_first(&fdc->head); - if (bp != NULL) { - bufq_remove(&fdc->head, bp); - fdc->bp = bp; - } - } - if (bp == NULL) { + bp = bufq_first(&fdc->head); + if(!bp) { /***********************************************\ * nothing left for this controller to do * * Force into the IDLE state, * @@ -2083,11 +1860,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) #ifdef EPSON_NRDISK if (fdu != nrdu) { #endif /* EPSON_NRDISK */ -#ifdef FDC_YE - if (!(fdc->flags & FDC_PCMCIA)) -#endif - isa_dmastart(bp->b_flags, bp->b_data+fd->skip, - format ? bp->b_bcount : fdblk, fdc->dmachan); + isa_dmastart(bp->b_flags, bp->b_data+fd->skip, + format ? bp->b_bcount : fdblk, fdc->dmachan); sectrac = fd->ft->sectrac; sec = blknum % (sectrac * fd->ft->heads); head = sec / sectrac; @@ -2128,12 +1902,6 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if(format) { -#ifdef FDC_YE - if (fdc->flags & FDC_PCMCIA) - (void)fdcpio(fdcu,bp->b_flags, - bp->b_data+fd->skip, - bp->b_bcount); -#endif /* formatting */ if(fd_cmd(fdcu, 6, NE7CMD_FORMAT, @@ -2154,24 +1922,6 @@ fdstate(fdcu_t fdcu, fdc_p fdc) } else { -#ifdef FDC_YE - if (fdc->flags & FDC_PCMCIA) { - /* - * this seems to be necessary even when - * reading data - */ - SET_BCDR(1,fdblk,fdc->baseport); - - /* - * perform the write pseudo-DMA before - * the WRITE command is sent - */ - if (!read) - (void)fdcpio(fdcu,bp->b_flags, - bp->b_data+fd->skip, - fdblk); - } -#endif if (fd_cmd(fdcu, 9, (read ? NE7CMD_READ : NE7CMD_WRITE), head << 2 | fdu, /* head & unit */ @@ -2192,24 +1942,6 @@ fdstate(fdcu_t fdcu, fdc_p fdc) return(retrier(fdcu)); } } -#ifdef FDC_YE - if (fdc->flags & FDC_PCMCIA) - /* - * if this is a read, then simply await interrupt - * before performing PIO - */ - if (read && !fdcpio(fdcu,bp->b_flags, - bp->b_data+fd->skip,fdblk)) { - fd->tohandle = timeout(fd_iotimeout, - (caddr_t)fdcu, hz); - return(0); /* will return later */ - }; - - /* - * write (or format) operation will fall through and - * await completion interrupt - */ -#endif fdc->state = IOCOMPLETE; fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz); return(0); /* will return later */ @@ -2243,16 +1975,6 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->state = IOCOMPLETE; } #endif -#ifdef FDC_YE - case PIOREAD: - /* - * actually perform the PIO read. The IOCOMPLETE case - * removes the timeout for us. - */ - (void)fdcpio(fdcu,bp->b_flags,bp->b_data+fd->skip,fdblk); - fdc->state = IOCOMPLETE; - /* FALLTHROUGH */ -#endif case IOCOMPLETE: /* IO DONE, post-analyze */ #ifdef EPSON_NRDISK if (fdu != nrdu) @@ -2279,11 +2001,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) #ifdef EPSON_NRDISK if (fdu != nrdu) { #endif /* EPSON_NRDISK */ -#ifdef FDC_YE - if (!(fdc->flags & FDC_PCMCIA)) -#endif - isa_dmadone(bp->b_flags, bp->b_data + fd->skip, - format ? bp->b_bcount : fdblk, fdc->dmachan); + isa_dmadone(bp->b_flags, bp->b_data + fd->skip, + format ? bp->b_bcount : fdblk, fdc->dmachan); #ifdef EPSON_NRDISK } else nrd_LED_off(); @@ -2322,7 +2041,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) { /* ALL DONE */ fd->skip = 0; - fdc->bp = NULL; + bufq_remove(&fdc->head, bp); /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fd->device_stats, bp->b_bcount - bp->b_resid, @@ -2451,10 +2170,12 @@ static int retrier(fdcu) fdcu_t fdcu; { + struct subdev *sd; fdc_p fdc = fdc_data + fdcu; register struct buf *bp; + int fdu; - bp = fdc->bp; + bp = bufq_first(&fdc->head); if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) goto fail; @@ -2498,7 +2219,7 @@ retrier(fdcu) bp->b_flags |= B_ERROR; bp->b_error = EIO; bp->b_resid += bp->b_bcount - fdc->fd->skip; - fdc->bp = NULL; + bufq_remove(&fdc->head, bp); /* Tell devstat we have finished with the transaction */ devstat_end_transaction(&fdc->fd->device_stats, @@ -2607,6 +2328,14 @@ fdioctl(dev, cmd, addr, flag, p) char buffer[DEV_BSIZE]; int error = 0; +#if NFT > 0 + int type = FDTYPE(minor(dev)); + + /* check for a tape ioctl */ + if (type & F_TAPE_TYPE) + return ftioctl(dev, cmd, addr, flag, p); +#endif + fdblk = 128 << fd->ft->secsize; #ifdef PC98 diff --git a/sys/pc98/pc98/if_ed.c b/sys/pc98/pc98/if_ed.c index b34898e3e80e..9b7f815e1d28 100644 --- a/sys/pc98/pc98/if_ed.c +++ b/sys/pc98/pc98/if_ed.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ed.c,v 1.57 1998/12/31 03:23:39 kato Exp $ + * $Id: if_ed.c,v 1.53 1998/10/08 17:04:58 kato Exp $ */ /* @@ -49,7 +49,6 @@ * MELCO LPC-TJ, LPC-TS, LGY-98, LGH-98, IND-SP, IND-SS, EGY-98 * PLANET SMART COM CREDITCARD/2000 PCMCIA, EN-2298 * Contec C-NET(98), C-NET(98)E, C-NET(98)L, C-NET(98)E-A, C-NET(98)L-A - * SMC EtherEZ98 * * Modified for FreeBSD(98) 2.2 by KATO T. of Nagoya University. * @@ -180,7 +179,6 @@ static int ed_attach __P((struct ed_softc *, int, int)); static int ed_attach_isa __P((struct isa_device *)); static void ed_init __P((void *)); -static ointhand2_t edintr; static int ed_ioctl __P((struct ifnet *, u_long, caddr_t)); static int ed_probe __P((struct isa_device *)); static void ed_start __P((struct ifnet *)); @@ -241,7 +239,6 @@ static u_long ds_crc __P((u_char *ep)); #endif #if NCARD > 0 #include <sys/select.h> -#include <sys/module.h> #include <pccard/cardinfo.h> #include <pccard/slot.h> @@ -252,7 +249,17 @@ static int edinit __P((struct pccard_devinfo *)); static void edunload __P((struct pccard_devinfo *)); static int card_intr __P((struct pccard_devinfo *)); -PCCARD_MODULE(ed, edinit, edunload, card_intr, 0, net_imask); +static struct pccard_device ed_info = { + "ed", + edinit, + edunload, + card_intr, + 0, /* Attributes - presently unused */ + &net_imask /* Interrupt mask for device */ + /* XXX - Should this also include net_imask? */ +}; + +DATA_SET(pccarddrv_set, ed_info); /* * Initialize the device - called from Slot manager. @@ -349,16 +356,6 @@ static unsigned short ed_intr_mask[] = { * Interrupt conversion table for 83C790 */ static unsigned short ed_790_intr_mask[] = { -#ifdef PC98 - 0, - IRQ3, - IRQ5, - IRQ6, - 0, - IRQ9, - IRQ12, - IRQ13 -#else 0, IRQ9, IRQ3, @@ -367,7 +364,6 @@ static unsigned short ed_790_intr_mask[] = { IRQ10, IRQ11, IRQ15 -#endif }; /* @@ -2485,7 +2481,6 @@ ed_attach_isa(isa_dev) struct ed_softc *sc = &ed_softc[unit]; int flags = isa_dev->id_flags; - isa_dev->id_ointr = edintr; return ed_attach(sc, unit, flags); } @@ -3322,7 +3317,7 @@ edintr_sc(sc) } } -static void +void edintr(unit) int unit; { @@ -4283,7 +4278,7 @@ edpnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) dev->id_iobase = d.port[0]; dev->id_irq = (1 << d.irq[0]); - dev->id_ointr = edintr; + dev->id_intr = edintr; dev->id_drq = -1; if (dev->id_driver == NULL) { diff --git a/sys/pc98/pc98/if_ed98.h b/sys/pc98/pc98/if_ed98.h index 19d07d08dd07..632006437273 100644 --- a/sys/pc98/pc98/if_ed98.h +++ b/sys/pc98/pc98/if_ed98.h @@ -26,7 +26,7 @@ */ /* - * PC-9801 specific definitions for DP8390/SMC8216 NICs. + * PC-9801 specific definitions for National Semiconductor DP8390 NIC. */ #ifndef __PC98_PC98_IF_ED98_H__ #define __PC98_PC98_IF_ED98_H__ @@ -47,22 +47,30 @@ static int pc98_set_register_unit __P((struct ed_softc *sc, int type, int iobase /* * Register offsets/total */ +#ifdef ED_NOVELL_NIC_OFFSET #undef ED_NOVELL_NIC_OFFSET +#endif #define ED_NOVELL_NIC_OFFSET sc->edreg.nic_offset +#ifdef ED_NOVELL_ASIC_OFFSET #undef ED_NOVELL_ASIC_OFFSET +#endif #define ED_NOVELL_ASIC_OFFSET sc->edreg.asic_offset /* * Remote DMA data register; for reading or writing to the NIC mem * via programmed I/O (offset from ASIC base). */ +#ifdef ED_NOVELL_DATA #undef ED_NOVELL_DATA +#endif #define ED_NOVELL_DATA sc->edreg.data /* * Reset register; reading from this register causes a board reset. */ +#ifdef ED_NOVELL_RESET #undef ED_NOVELL_RESET +#endif #define ED_NOVELL_RESET sc->edreg.reset /* @@ -82,20 +90,20 @@ static int pc98_set_register_unit __P((struct ed_softc *sc, int type, int iobase * 0xa0 Contec C-NET(98). * 0xb0 Contec C-NET(98)E/L. */ -#define ED_TYPE98_BASE 0x80 +#define ED_TYPE98_BASE 0x10 -#define ED_TYPE98_GENERIC 0x80 -#define ED_TYPE98_LPC 0x81 -#define ED_TYPE98_BDN 0x82 -#define ED_TYPE98_EGY 0x83 -#define ED_TYPE98_LGY 0x84 -#define ED_TYPE98_ICM 0x85 -#define ED_TYPE98_SIC 0x86 -#define ED_TYPE98_108 0x88 -#define ED_TYPE98_LA98 0x89 -#define ED_TYPE98_CNET98 0x8a -#define ED_TYPE98_CNET98EL 0x8b -#define ED_TYPE98_UE2212 0x8c +#define ED_TYPE98_GENERIC 0x10 +#define ED_TYPE98_LPC 0x11 +#define ED_TYPE98_BDN 0x12 +#define ED_TYPE98_EGY 0x13 +#define ED_TYPE98_LGY 0x14 +#define ED_TYPE98_ICM 0x15 +#define ED_TYPE98_SIC 0x16 +#define ED_TYPE98_108 0x18 +#define ED_TYPE98_LA98 0x19 +#define ED_TYPE98_CNET98 0x1a +#define ED_TYPE98_CNET98EL 0x1b +#define ED_TYPE98_UE2212 0x1c #define ED_TYPE98(x) (((x & 0xffff0000) >> 20) | ED_TYPE98_BASE) #define ED_TYPE98SUB(x) ((x & 0xf0000) >> 16) @@ -247,10 +255,14 @@ static int pc98_set_register_unit __P((struct ed_softc *sc, int type, int iobase #define ED_P2_IMR sc->edreg.port[0x0f] /* PCCARD */ +#ifdef ED_PC_MISC #undef ED_PC_MISC +#endif #define ED_PC_MISC sc->edreg.pc_misc +#ifdef ED_PC_RESET #undef ED_PC_RESET -#define ED_PC_RESET sc->edreg.pc_reset +#endif +#define ED_PC_RESET sc->edreg.pc_reset /* LPC-T support */ #define LPCT_1d0_ON() \ @@ -385,9 +397,6 @@ pc98_set_register_unit(struct ed_softc *sc, int type, int iobase) int nports; sc->type = type; - ED_PC_MISC = 0x18; /* dummy for NON-PCCard */ - ED_PC_RESET = 0x1f; /* same above */ - switch (type) { case ED_TYPE98_GENERIC: sc->edreg.port = edp_generic; @@ -395,6 +404,8 @@ pc98_set_register_unit(struct ed_softc *sc, int type, int iobase) ED_NOVELL_ASIC_OFFSET = 0x0010; ED_NOVELL_DATA = 0x0000; ED_NOVELL_RESET = 0x000f; + ED_PC_MISC = 0x18; + ED_PC_RESET = 0x1f; nports = 32; break; @@ -404,24 +415,30 @@ pc98_set_register_unit(struct ed_softc *sc, int type, int iobase) ED_NOVELL_ASIC_OFFSET = 0x0200; ED_NOVELL_DATA = 0x0000; ED_NOVELL_RESET = 0x0100; + ED_PC_MISC = 0x18; + ED_PC_RESET = 0x1f; nports = 16; break; case ED_TYPE98_EGY: sc->edreg.port = edp_egy98; - ED_NOVELL_NIC_OFFSET = 0x0000; + ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0200; ED_NOVELL_DATA = 0x0000; ED_NOVELL_RESET = 0x0100; + ED_PC_MISC = 0x18; + ED_PC_RESET = 0x1f; nports = 16; break; case ED_TYPE98_ICM: sc->edreg.port = edp_generic; - ED_NOVELL_NIC_OFFSET = 0x0000; + ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0100; ED_NOVELL_DATA = 0x0000; ED_NOVELL_RESET = 0x000f; + ED_PC_MISC = 0x18; + ED_PC_RESET = 0x1f; nports = 16; break; @@ -429,8 +446,10 @@ pc98_set_register_unit(struct ed_softc *sc, int type, int iobase) sc->edreg.port = edp_la98; ED_NOVELL_NIC_OFFSET = 0x0000; ED_NOVELL_ASIC_OFFSET = 0x0100; - ED_NOVELL_DATA = 0x0000; + ED_NOVELL_DATA = 0; ED_NOVELL_RESET = 0xc100; + ED_PC_MISC = 0x18; + ED_PC_RESET = 0x1f; nports = 1; break; @@ -438,8 +457,10 @@ pc98_set_register_unit(struct ed_softc *sc, int type, int iobase) sc->edreg.port = edp_sic98; ED_NOVELL_NIC_OFFSET = 0x0000; ED_NOVELL_ASIC_OFFSET = 0x2000; - ED_NOVELL_DATA = 0; /* dummy */ - ED_NOVELL_RESET = 0; /* dummy */ + ED_NOVELL_DATA = 0x00; /* dummy */ + ED_NOVELL_RESET = 0x00; + ED_PC_MISC = 0x18; /* dummy */ + ED_PC_RESET = 0x1f; /* dummy */ nports = 1; break; @@ -457,58 +478,47 @@ pc98_set_register_unit(struct ed_softc *sc, int type, int iobase) case ED_TYPE98_108: sc->edreg.port = edp_nec108; adj = (iobase & 0xf000) / 2; - ED_NOVELL_NIC_OFFSET = 0x0000; - ED_NOVELL_ASIC_OFFSET = (0x0888 | adj) - iobase; - ED_NOVELL_DATA = 0x0000; - ED_NOVELL_RESET = 0x0002; + ED_NOVELL_NIC_OFFSET = 0; + ED_NOVELL_ASIC_OFFSET = (0x888 | adj) - iobase; + ED_NOVELL_DATA = 0; + ED_NOVELL_RESET = 2; + ED_PC_MISC = 0x18; + ED_PC_RESET = 0x1f; nports = 16; break; case ED_TYPE98_LA98: sc->edreg.port = edp_la98; - ED_NOVELL_NIC_OFFSET = 0x0000; - ED_NOVELL_ASIC_OFFSET = 0x0100; + ED_NOVELL_NIC_OFFSET = 0; + ED_NOVELL_ASIC_OFFSET = 0x100; ED_NOVELL_DATA = 0x0000; ED_NOVELL_RESET = 0xf000; + ED_PC_MISC = 0x18; + ED_PC_RESET = 0x1f; nports = 1; break; case ED_TYPE98_CNET98EL: sc->edreg.port = edp_generic; - ED_NOVELL_NIC_OFFSET = 0x0000; + ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0400; ED_NOVELL_DATA = 0x000e; - ED_NOVELL_RESET = 0; /* dummy */ + ED_NOVELL_RESET = 0x0000; /* dummy */ + ED_PC_RESET = 0x1f; nports = 16; break; case ED_TYPE98_CNET98: sc->edreg.port = edp_cnet98; - ED_NOVELL_NIC_OFFSET = 0x0000; + ED_NOVELL_NIC_OFFSET = 0; ED_NOVELL_ASIC_OFFSET = 0x0400; - ED_NOVELL_DATA = 0; /* dummy */ - ED_NOVELL_RESET = 0; /* dummy */ + ED_NOVELL_DATA = 0x0000; + ED_NOVELL_RESET = 0x0000; /* dummy */ + ED_PC_RESET = 0x1f; nports = 16; break; } return nports; } -/* - * SMC EtherEZ98(SMC8498BTA) - * - * A sample of kernel conf is as follows. - * #device ed0 at isa? port 0x10d0 net irq 6 iomem 0xc8000 vector edintr - */ -#undef ED_WD_NIC_OFFSET -#define ED_WD_NIC_OFFSET 0x100 /* I/O base offset to NIC */ -#undef ED_WD_ASIC_OFFSET -#define ED_WD_ASIC_OFFSET 0 /* I/O base offset to ASIC */ -/* - * XXX - The I/O address range is fragmented in the EtherEZ98; - * it occupies 16*2 I/O addresses, by the way. - */ -#undef ED_WD_IO_PORTS -#define ED_WD_IO_PORTS 16 /* # of i/o addresses used */ - #endif /* __PC98_PC98_IF_ED98_H__ */ diff --git a/sys/pc98/pc98/if_fe.c b/sys/pc98/pc98/if_fe.c new file mode 100644 index 000000000000..64b3091572cb --- /dev/null +++ b/sys/pc98/pc98/if_fe.c @@ -0,0 +1,3824 @@ +/* + * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 + * + * This software may be used, modified, copied, distributed, and sold, in + * both source and binary form provided that the above copyright, these + * terms and the following disclaimer are retained. The name of the author + * and/or the contributor 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 THE CONTRIBUTOR ``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 THE CONTRIBUTOR 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. + */ + +/* + * $Id: if_fe.c,v 1.33 1998/10/08 17:06:32 kato Exp $ + * + * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. + * To be used with FreeBSD 2.x + * Contributed by M. Sekiguchi. <seki@sysrap.cs.fujitsu.co.jp> + * + * This version is intended to be a generic template for various + * MB86960A/MB86965A based Ethernet cards. It currently supports + * Fujitsu FMV-180 series for ISA and Allied-Telesis AT1700/RE2000 + * series for ISA, as well as Fujitsu MBH10302 PC card. + * There are some currently- + * unused hooks embedded, which are primarily intended to support + * other types of Ethernet cards, but the author is not sure whether + * they are useful. + * + * This version also includes some alignments for + * RE1000/RE1000+/ME1500 support. It is incomplete, however, since the + * cards are not for AT-compatibles. (They are for PC98 bus -- a + * proprietary bus architecture available only in Japan.) Further + * work for PC98 version will be available as a part of FreeBSD(98) + * project. + * + * This software is a derivative work of if_ed.c version 1.56 by David + * Greenman available as a part of FreeBSD 2.0 RELEASE source distribution. + * + * The following lines are retained from the original if_ed.c: + * + * Copyright (C) 1993, David Greenman. This software may be used, modified, + * copied, distributed, and sold, in both source and binary form provided + * that the above copyright and these terms are retained. Under no + * circumstances is the author responsible for the proper functioning + * of this software, nor does the author assume any responsibility + * for damages incurred with its use. + */ + +/* + * Modified for Allied-Telesis RE1000 series. + */ + + +/* + * TODO: + * o To support MBH10304 PC card. It is another MB8696x based + * PCMCIA Ethernet card by Fujitsu, which is not compatible with + * MBH10302. + * o To merge FreeBSD(98) efforts into a single source file. + * o To support ISA PnP auto configuration for FMV-183/184. + * o To reconsider mbuf usage. + * o To reconsider transmission buffer usage, including + * transmission buffer size (currently 4KB x 2) and pros-and- + * cons of multiple frame transmission. + * o To test IPX codes. + */ + +#include "fe.h" +#include "bpfilter.h" +#include "opt_inet.h" +#include "opt_ipx.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sockio.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/syslog.h> + +#include <net/if.h> +#include <net/if_dl.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#endif + +/* IPX code is not tested. FIXME. */ +#ifdef IPX +#include <netipx/ipx.h> +#include <netipx/ipx_if.h> +#endif + +/* To be used with IPv6 package of INRIA. */ +#ifdef INET6 +/* IPv6 added by shin 96.2.6 */ +#include <netinet/if_ether6.h> +#endif + +/* XNS code is not tested. FIXME. */ +#ifdef NS +#include <netns/ns.h> +#include <netns/ns_if.h> +#endif + +#if NBPFILTER > 0 +#include <net/bpf.h> +#endif + +#include <machine/clock.h> + +#include <i386/isa/isa_device.h> +#include <i386/isa/icu.h> + +/* PCCARD suport */ +#include "card.h" +#if NCARD > 0 +#include <sys/kernel.h> +#include <sys/select.h> +#include <pccard/cardinfo.h> +#include <pccard/slot.h> +#endif + +#include <i386/isa/ic/mb86960.h> +#include <i386/isa/if_fereg.h> + +/* + * This version of fe is an ISA device driver. + * Override the following macro to adapt it to another bus. + * (E.g., PC98.) + */ +#define DEVICE struct isa_device + +/* + * Default settings for fe driver specific options. + * They can be set in config file by "options" statements. + */ + +/* + * Debug control. + * 0: No debug at all. All debug specific codes are stripped off. + * 1: Silent. No debug messages are logged except emergent ones. + * 2: Brief. Lair events and/or important information are logged. + * 3: Detailed. Logs all information which *may* be useful for debugging. + * 4: Trace. All actions in the driver is logged. Super verbose. + */ +#ifndef FE_DEBUG +#define FE_DEBUG 1 +#endif + +/* + * Transmit just one packet per a "send" command to 86960. + * This option is intended for performance test. An EXPERIMENTAL option. + */ +#ifndef FE_SINGLE_TRANSMISSION +#define FE_SINGLE_TRANSMISSION 0 +#endif + +/* + * Device configuration flags. + */ + +/* DLCR6 settings. */ +#define FE_FLAGS_DLCR6_VALUE 0x007F + +/* Force DLCR6 override. */ +#define FE_FLAGS_OVERRIDE_DLCR6 0x0080 + +/* Shouldn't these be defined somewhere else such as isa_device.h? */ +#define NO_IOADDR (-1) +#define NO_IRQ 0 + +/* + * Data type for a multicast address filter on 8696x. + */ +struct fe_filter { u_char data [ FE_FILTER_LEN ]; }; + +/* + * Special filter values. + */ +static struct fe_filter const fe_filter_nothing = { FE_FILTER_NOTHING }; +static struct fe_filter const fe_filter_all = { FE_FILTER_ALL }; + +/* How many registers does an fe-supported adapter have at maximum? */ +#define MAXREGISTERS 32 + +/* + * fe_softc: per line info and status + */ +static struct fe_softc { + + /* Used by "common" codes. */ + struct arpcom arpcom; /* Ethernet common */ + + /* Used by config codes. */ + + /* Set by probe() and not modified in later phases. */ + char * typestr; /* printable name of the interface. */ + u_short iobase; /* base I/O address of the adapter. */ + u_short ioaddr [ MAXREGISTERS ]; /* I/O addresses of register. */ + u_short txb_size; /* size of TX buffer, in bytes */ + u_char proto_dlcr4; /* DLCR4 prototype. */ + u_char proto_dlcr5; /* DLCR5 prototype. */ + u_char proto_dlcr6; /* DLCR6 prototype. */ + u_char proto_dlcr7; /* DLCR7 prototype. */ + u_char proto_bmpr13; /* BMPR13 prototype. */ + u_char proto_bmpr14; /* BMPR14 prototype. */ + + /* Vendor specific hooks. */ + void ( * init )( struct fe_softc * ); /* Just before fe_init(). */ + void ( * stop )( struct fe_softc * ); /* Just after fe_stop(). */ + + /* Transmission buffer management. */ + u_short txb_free; /* free bytes in TX buffer */ + u_char txb_count; /* number of packets in TX buffer */ + u_char txb_sched; /* number of scheduled packets */ + + /* Excessive collision counter (see fe_tint() for details. */ + u_char tx_excolls; /* # of excessive collisions. */ + + /* Multicast address filter management. */ + u_char filter_change; /* MARs must be changed ASAP. */ + struct fe_filter filter;/* new filter value. */ + +} fe_softc[NFE]; + +#define sc_if arpcom.ac_if +#define sc_unit arpcom.ac_if.if_unit +#define sc_enaddr arpcom.ac_enaddr + +/* Standard driver entry points. These can be static. */ +static int fe_probe ( struct isa_device * ); +static int fe_attach ( struct isa_device * ); +static void fe_init ( int ); +static int fe_ioctl ( struct ifnet *, u_long, caddr_t ); +static void fe_start ( struct ifnet * ); +static void fe_reset ( int ); +static void fe_watchdog ( struct ifnet * ); + +/* Local functions. Order of declaration is confused. FIXME. */ +#ifdef PC98 +static int fe_probe_re1000 ( DEVICE *, struct fe_softc * ); +static int fe_probe_re1000p( DEVICE *, struct fe_softc * ); +static int fe_probe_cnet9ne ( DEVICE *, struct fe_softc * ); +static int fe_probe_cnet98p2( DEVICE *, struct fe_softc * ); +#else +static int fe_probe_fmv ( DEVICE *, struct fe_softc * ); +static int fe_probe_ati ( DEVICE *, struct fe_softc * ); +static void fe_init_ati ( struct fe_softc * ); +#endif /* PC98 */ +static int fe_probe_gwy ( DEVICE *, struct fe_softc * ); +#if NCARD > 0 +static int fe_probe_mbh ( DEVICE *, struct fe_softc * ); +static void fe_init_mbh ( struct fe_softc * ); +static int fe_probe_tdk ( DEVICE *, struct fe_softc * ); +#endif +static int fe_get_packet ( struct fe_softc *, u_short ); +static void fe_stop ( int ); +static void fe_tint ( struct fe_softc *, u_char ); +static void fe_rint ( struct fe_softc *, u_char ); +static void fe_xmit ( struct fe_softc * ); +static void fe_emptybuffer ( struct fe_softc * ); +static void fe_write_mbufs ( struct fe_softc *, struct mbuf * ); +static struct fe_filter + fe_mcaf ( struct fe_softc * ); +static int fe_hash ( u_char * ); +static void fe_setmode ( struct fe_softc * ); +static void fe_loadmar ( struct fe_softc * ); +#if FE_DEBUG >= 1 +static void fe_dump ( int, struct fe_softc *, char * ); +#endif + +/* Driver struct used in the config code. This must be public (external.) */ +struct isa_driver fedriver = +{ + fe_probe, + fe_attach, + "fe", + 1 /* It's safe to mark as "sensitive" */ +}; + +/* + * Fe driver specific constants which relate to 86960/86965. + */ + +/* Interrupt masks */ +#define FE_TMASK ( FE_D2_COLL16 | FE_D2_TXDONE ) +#define FE_RMASK ( FE_D3_OVRFLO | FE_D3_CRCERR \ + | FE_D3_ALGERR | FE_D3_SRTPKT | FE_D3_PKTRDY ) + +/* Maximum number of iterations for a receive interrupt. */ +#define FE_MAX_RECV_COUNT ( ( 65536 - 2048 * 2 ) / 64 ) + /* + * Maximum size of SRAM is 65536, + * minimum size of transmission buffer in fe is 2x2KB, + * and minimum amount of received packet including headers + * added by the chip is 64 bytes. + * Hence FE_MAX_RECV_COUNT is the upper limit for number + * of packets in the receive buffer. + */ + +/* + * Routines to access contiguous I/O ports. + */ + +static void +inblk ( struct fe_softc * sc, int offs, u_char * mem, int len ) +{ + while ( --len >= 0 ) { + *mem++ = inb( sc->ioaddr[ offs++ ] ); + } +} + +static void +outblk ( struct fe_softc * sc, int offs, u_char const * mem, int len ) +{ + while ( --len >= 0 ) { + outb( sc->ioaddr[ offs++ ], *mem++ ); + } +} + +/* PCCARD Support */ +#if NCARD > 0 +/* + * PC-Card (PCMCIA) specific code. + */ +static int feinit ( struct pccard_devinfo * ); +static void feunload ( struct pccard_devinfo * ); +static int fe_card_intr ( struct pccard_devinfo * ); + +static struct pccard_device fe_info = { + "fe", + feinit, + feunload, + fe_card_intr, + 0, /* Attributes - presently unused */ + &net_imask /* XXX - Should this also include tty_imask? */ +}; + +DATA_SET(pccarddrv_set, fe_info); + +/* + * Initialize the device - called from Slot manager. + */ +static int +feinit(struct pccard_devinfo *devi) +{ + struct fe_softc *sc; + + /* validate unit number. */ + if (devi->isahd.id_unit >= NFE) + return (ENODEV); + /* + * Probe the device. If a value is returned, + * the device was found at the location. + */ +#if FE_DEBUG >= 2 + printf("Start Probe\n"); +#endif + /* Initialize "minimum" parts of our softc. */ + sc = &fe_softc[devi->isahd.id_unit]; + sc->sc_unit = devi->isahd.id_unit; + sc->iobase = devi->isahd.id_iobase; + + /* Use Ethernet address got from CIS, if one is available. */ + if ((devi->misc[0] & 0x03) == 0x00 + && (devi->misc[0] | devi->misc[1] | devi->misc[2]) != 0) { + /* Yes, it looks like a valid Ether address. */ + bcopy(devi->misc, sc->sc_enaddr, ETHER_ADDR_LEN); + } else { + /* Indicate we have no Ether address in CIS. */ + bzero(sc->sc_enaddr, ETHER_ADDR_LEN); + } + + /* Probe supported PC card models. */ + if (fe_probe_tdk(&devi->isahd, sc) == 0 && + fe_probe_mbh(&devi->isahd, sc) == 0) + return (ENXIO); +#if FE_DEBUG >= 2 + printf("Start attach\n"); +#endif + if (fe_attach(&devi->isahd) == 0) + return (ENXIO); + + return (0); +} + +/* + * feunload - unload the driver and clear the table. + * XXX TODO: + * This is usually called when the card is ejected, but + * can be caused by a modunload 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. + */ +static void +feunload(struct pccard_devinfo *devi) +{ + struct fe_softc *sc = &fe_softc[devi->isahd.id_unit]; + printf("fe%d: unload\n", devi->isahd.id_unit); + fe_stop(devi->isahd.id_unit); +} + +/* + * fe_card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ +static int +fe_card_intr(struct pccard_devinfo *devi) +{ + feintr(devi->isahd.id_unit); + return (1); +} +#endif /* NCARD > 0 */ + + +/* + * Hardware probe routines. + */ + +/* How and where to probe; to support automatic I/O address detection. */ +struct fe_probe_list +{ + int ( * probe ) ( DEVICE *, struct fe_softc * ); + u_short const * addresses; +}; + +/* Lists of possible addresses. */ +#ifdef PC98 +static u_short const fe_re1000_addr [] = + { 0x0D0, 0x0D2, 0x0D4, 0x0D6, 0x0D8, 0x0DA, 0x0DC, 0x0DE, + 0x1D0, 0x1D2, 0x1D4, 0x1D6, 0x1D8, 0x1DA, 0x1DC, 0x1DE, 0 }; +static u_short const fe_re1000p_addr [] = + { 0x0D0, 0x0D2, 0x0D4, 0x0D8, 0x1D4, 0x1D6, 0x1D8, 0x1DA, 0 }; +static u_short const fe_cnet9ne_addr [] = + { 0x73D0, 0 }; +static u_short const fe_cnet98p2_addr [] = + { 0x03D0, 0x13D0, 0x23D0, 0x33D0, 0x43D0, 0x53D0, 0x63D0, + 0x73D0, 0x83D0, 0x93D0, 0xA3D0, 0xB3D0, 0xC3D0, 0xD3D0, 0 }; +#else +static u_short const fe_fmv_addr [] = + { 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x300, 0x340, 0 }; +static u_short const fe_ati_addr [] = + { 0x240, 0x260, 0x280, 0x2A0, 0x300, 0x320, 0x340, 0x380, 0 }; +#endif + +static struct fe_probe_list const fe_probe_list [] = +{ +#ifdef PC98 + { fe_probe_re1000, fe_re1000_addr }, + { fe_probe_re1000p, fe_re1000p_addr }, + /* XXX: We must probe C-NET(98)P2 after C-NET(9N)E. */ + { fe_probe_cnet9ne, fe_cnet9ne_addr }, + { fe_probe_cnet98p2, fe_cnet98p2_addr }, +#else + { fe_probe_fmv, fe_fmv_addr }, + { fe_probe_ati, fe_ati_addr }, +#endif + { fe_probe_gwy, NULL }, /* GWYs cannot be auto detected. */ + { NULL, NULL } +}; + + +/* + * Determine if the device is present + * + * on entry: + * a pointer to an isa_device struct + * on exit: + * zero if device not found + * or number of i/o addresses used (if found) + */ + +static int +fe_probe ( DEVICE * dev ) +{ + struct fe_softc * sc; + int u; + int nports; + struct fe_probe_list const * list; + u_short const * addr; + u_short single [ 2 ]; + + /* Initialize "minimum" parts of our softc. */ + sc = &fe_softc[ dev->id_unit ]; + sc->sc_unit = dev->id_unit; + + /* TODO: Should be in each probe routines */ + sc->proto_bmpr14 = 0; + + /* Probe each possibility, one at a time. */ + for ( list = fe_probe_list; list->probe != NULL; list++ ) { + + if ( dev->id_iobase != NO_IOADDR ) { + /* Probe one specific address. */ + single[ 0 ] = dev->id_iobase; + single[ 1 ] = 0; + addr = single; + } else if ( list->addresses != NULL ) { + /* Auto detect. */ + addr = list->addresses; + } else { + /* We need a list of addresses to do auto detect. */ + continue; + } + + /* Probe all possible addresses for the board. */ + while ( *addr != 0 ) { + + /* See if the address is already in use. */ + for ( u = 0; u < NFE; u++ ) { + if ( fe_softc[u].iobase == *addr ) break; + } + +#if FE_DEBUG >= 3 + if ( u == NFE ) { + log( LOG_INFO, "fe%d: probing %d at 0x%x\n", + sc->sc_unit, list - fe_probe_list, *addr ); + } else if ( u == sc->sc_unit ) { + log( LOG_INFO, "fe%d: re-probing %d at 0x%x?\n", + sc->sc_unit, list - fe_probe_list, *addr ); + } else { + log( LOG_INFO, "fe%d: skipping %d at 0x%x\n", + sc->sc_unit, list - fe_probe_list, *addr ); + } +#endif + + /* Probe the address if it is free. */ + if ( u == NFE || u == sc->sc_unit ) { + + /* Probe an address. */ + sc->iobase = *addr; + nports = list->probe( dev, sc ); + if ( nports > 0 ) { + /* Found. */ + dev->id_iobase = *addr; + return ( nports ); + } + sc->iobase = 0; + } + + /* Try next. */ + addr++; + } + } + + /* Probe failed. */ + return ( 0 ); +} + +/* + * Check for specific bits in specific registers have specific values. + */ +struct fe_simple_probe_struct +{ + u_char port; /* Offset from the base I/O address. */ + u_char mask; /* Bits to be checked. */ + u_char bits; /* Values to be compared against. */ +}; + +static int +fe_simple_probe ( struct fe_softc const * sc, + struct fe_simple_probe_struct const * sp ) +{ + struct fe_simple_probe_struct const * p; + + for ( p = sp; p->mask != 0; p++ ) { +#if FE_DEBUG >=2 + printf("Probe Port:%x,Value:%x,Mask:%x.Bits:%x\n", + p->port,inb(sc->ioaddr[ p->port]),p->mask,p->bits); +#endif + if ( ( inb( sc->ioaddr[ p->port ] ) & p->mask ) != p->bits ) + { + return ( 0 ); + } + } + return ( 1 ); +} + +/* + * Routines to read all bytes from the config EEPROM through MB86965A. + * I'm not sure what exactly I'm doing here... I was told just to follow + * the steps, and it worked. Could someone tell me why the following + * code works? (Or, why all similar codes I tried previously doesn't + * work.) FIXME. + */ + +static void +fe_strobe_eeprom ( u_short bmpr16 ) +{ + /* + * We must guarantee 800ns (or more) interval to access slow + * EEPROMs. The following redundant code provides enough + * delay with ISA timing. (Even if the bus clock is "tuned.") + * Some modification will be needed on faster busses. + */ + outb( bmpr16, FE_B16_SELECT ); + outb( bmpr16, FE_B16_SELECT ); + outb( bmpr16, FE_B16_SELECT | FE_B16_CLOCK ); + outb( bmpr16, FE_B16_SELECT | FE_B16_CLOCK ); + outb( bmpr16, FE_B16_SELECT ); + outb( bmpr16, FE_B16_SELECT ); +} + +static void +fe_read_eeprom ( struct fe_softc * sc, u_char * data ) +{ + u_short bmpr16 = sc->ioaddr[ FE_BMPR16 ]; + u_short bmpr17 = sc->ioaddr[ FE_BMPR17 ]; + u_char n, val, bit; + + /* Read bytes from EEPROM; two bytes per an iteration. */ + for ( n = 0; n < FE_EEPROM_SIZE / 2; n++ ) { + + /* Reset the EEPROM interface. */ + outb( bmpr16, 0x00 ); + outb( bmpr17, 0x00 ); + + /* Start EEPROM access. */ + outb( bmpr16, FE_B16_SELECT ); + outb( bmpr17, FE_B17_DATA ); + fe_strobe_eeprom( bmpr16 ); + + /* Pass the iteration count to the chip. */ + val = 0x80 | n; + for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { + outb( bmpr17, ( val & bit ) ? FE_B17_DATA : 0 ); + fe_strobe_eeprom( bmpr16 ); + } + outb( bmpr17, 0x00 ); + + /* Read a byte. */ + val = 0; + for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { + fe_strobe_eeprom( bmpr16 ); + if ( inb( bmpr17 ) & FE_B17_DATA ) { + val |= bit; + } + } + *data++ = val; + + /* Read one more byte. */ + val = 0; + for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { + fe_strobe_eeprom( bmpr16 ); + if ( inb( bmpr17 ) & FE_B17_DATA ) { + val |= bit; + } + } + *data++ = val; + } + + /* Reset the EEPROM interface, again. */ + outb( bmpr16, 0x00 ); + outb( bmpr17, 0x00 ); + +#if FE_DEBUG >= 3 + /* Report what we got. */ + data -= FE_EEPROM_SIZE; + log( LOG_INFO, "fe%d: EEPROM:" + " %02x%02x%02x%02x %02x%02x%02x%02x -" + " %02x%02x%02x%02x %02x%02x%02x%02x -" + " %02x%02x%02x%02x %02x%02x%02x%02x -" + " %02x%02x%02x%02x %02x%02x%02x%02x\n", + sc->sc_unit, + data[ 0], data[ 1], data[ 2], data[ 3], + data[ 4], data[ 5], data[ 6], data[ 7], + data[ 8], data[ 9], data[10], data[11], + data[12], data[13], data[14], data[15], + data[16], data[17], data[18], data[19], + data[20], data[21], data[22], data[23], + data[24], data[25], data[26], data[27], + data[28], data[29], data[30], data[31] ); +#endif +} + +/* + * Hardware (vendor) specific probe routines. + */ + +#ifdef PC98 +/* + * Probe and initialization for Allied-Telesis RE1000 series. + */ +static int +fe_probe_re1000 ( DEVICE * isa_dev, struct fe_softc * sc ) +{ + int i, n; + int dlcr6, dlcr7; + u_char c = 0; + + static u_short const irqmap [ 4 ] = + { IRQ3, IRQ5, IRQ6, IRQ12 }; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: probe (0x%x) for RE1000\n", sc->sc_unit, sc->iobase ); + fe_dump( LOG_INFO, sc, NULL ); +#endif + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + (i/2)*0x200 + (i%2); + } + + /* + * RE1000 does not use 86965 EEPROM interface. + */ + c ^= sc->sc_enaddr[0] = inb(sc->ioaddr[FE_RE1000_MAC0]); + c ^= sc->sc_enaddr[1] = inb(sc->ioaddr[FE_RE1000_MAC1]); + c ^= sc->sc_enaddr[2] = inb(sc->ioaddr[FE_RE1000_MAC2]); + c ^= sc->sc_enaddr[3] = inb(sc->ioaddr[FE_RE1000_MAC3]); + c ^= sc->sc_enaddr[4] = inb(sc->ioaddr[FE_RE1000_MAC4]); + c ^= sc->sc_enaddr[5] = inb(sc->ioaddr[FE_RE1000_MAC5]); + c ^= inb(sc->ioaddr[FE_RE1000_MACCHK]); + if (c != 0) return 0; + + if ( sc->sc_enaddr[ 0 ] != 0x00 + || sc->sc_enaddr[ 1 ] != 0x00 + || sc->sc_enaddr[ 2 ] != 0xF4 ) return 0; + + /* + * check interrupt configure + */ + for (n=0; n<4; n++) { + if (isa_dev->id_irq == irqmap[n]) break; + } + if (n == 4) return 0; + + /* + * set irq + */ + c = inb(sc->ioaddr[FE_RE1000_IRQCONF]); + c &= (~ FE_RE1000_IRQCONF_IRQ); + c |= (1 << (n + FE_RE1000_IRQCONF_IRQSHIFT)); + outb(sc->ioaddr[FE_RE1000_IRQCONF], c); + + sc->typestr = "RE1000"; + + /* + * Program the 86965 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; /* FIXME */ + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC; + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "RE1000 found" ); +#endif + + /* Initialize 86965. */ + outb( sc->ioaddr[FE_DLCR6], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY(200); + + /* Disable all interrupts. */ + outb( sc->ioaddr[FE_DLCR2], 0 ); + outb( sc->ioaddr[FE_DLCR3], 0 ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "end of fe_probe_re1000()" ); +#endif + + /* + * That's all. RE1000 occupies 2*16 I/O addresses, by the way. + */ + return 2; /* ??? */ +} + +/* + * Probe and initialization for Allied-Telesis RE1000Plus/ME1500 series. + */ +static int +fe_probe_re1000p ( DEVICE * isa_dev, struct fe_softc * sc ) +{ + int i, n, signature; + int dlcr6, dlcr7; + u_char eeprom [ FE_EEPROM_SIZE ]; + + static u_short const irqmap [ 4 ] = + { IRQ3, IRQ5, IRQ6, IRQ12 }; + static struct fe_simple_probe_struct const probe_signature1 [] = { + { FE_DLCR0, 0xBF, 0x00 }, + { FE_DLCR2, 0xFF, 0x00 }, + { FE_DLCR4, 0x0F, 0x06 }, + { FE_DLCR6, 0x0F, 0x06 }, + { 0 } + }; + static struct fe_simple_probe_struct const probe_signature2 [] = { + { FE_DLCR1, 0xFF, 0x00 }, + { FE_DLCR3, 0xFF, 0x00 }, + { FE_DLCR5, 0xFF, 0x41 }, + { 0 } + }; + static struct fe_simple_probe_struct const probe_table [] = { + { FE_DLCR2, 0x71, 0x00 }, + { FE_DLCR4, 0x08, 0x00 }, + { FE_DLCR5, 0x80, 0x00 }, + { 0 } + }; + static struct fe_simple_probe_struct const vendor_code [] = { + { FE_DLCR8, 0xFF, 0x00 }, + { FE_DLCR9, 0xFF, 0x00 }, + { FE_DLCR10, 0xFF, 0xF4 }, + { 0 } + }; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: probe (0x%x) for RE1000Plus/ME1500\n", sc->sc_unit, sc->iobase ); + fe_dump( LOG_INFO, sc, NULL ); +#endif + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < 16; i++ ) { + sc->ioaddr[ i ] = sc->iobase + (i/2)*0x200 + (i%2); + } + for ( i = 16; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i*0x200 - 0x1000; + } + + /* First, check the "signature" */ + signature = 0; + if (fe_simple_probe(sc, probe_signature1)) { + outb(sc->ioaddr[FE_DLCR6], (inb(sc->ioaddr[FE_DLCR6]) & 0xCF) | 0x16); + if (fe_simple_probe(sc, probe_signature2)) + signature = 1; + } + + /* + * If the "signature" not detected, 86965 *might* be previously + * initialized. So, check the Ethernet address here. + * + * Allied-Telesis uses 00 00 F4 ?? ?? ??. + */ + if (signature == 0) { + /* Simple check */ + if (!fe_simple_probe(sc, probe_table)) return 0; + + /* Disable DLC */ + dlcr6 = inb(sc->ioaddr[FE_DLCR6]); + outb(sc->ioaddr[FE_DLCR6], dlcr6 | FE_D6_DLC_DISABLE); + /* Select register bank for DLCR */ + dlcr7 = inb(sc->ioaddr[FE_DLCR7]); + outb(sc->ioaddr[FE_DLCR7], dlcr7 & 0xF3 | FE_D7_RBS_DLCR); + + /* Check the Ethernet address */ + if (!fe_simple_probe(sc, vendor_code)) return 0; + + /* Restore configuration registers */ + DELAY(200); + outb(sc->ioaddr[FE_DLCR6], dlcr6); + outb(sc->ioaddr[FE_DLCR7], dlcr7); + } + + /* + * We are now almost sure we have an 86965 at the given + * address. So, read EEPROM through 86965. We have to write + * into LSI registers to read from EEPROM. I want to avoid it + * at this stage, but I cannot test the presense of the chip + * any further without reading EEPROM. FIXME. + */ + fe_read_eeprom( sc, eeprom ); + + /* Make sure that config info in EEPROM and 86965 agree. */ + if ( eeprom[ FE_EEPROM_CONF ] != inb( sc->ioaddr[FE_BMPR19] ) ) { + return 0; + } + + /* + * Initialize constants in the per-line structure. + */ + + /* Get our station address from EEPROM. */ + bcopy( eeprom + FE_ATI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN ); + + sc->typestr = "RE1000Plus/ME1500"; + + /* + * Read IRQ configuration. + */ + n = (inb(sc->ioaddr[FE_BMPR19]) & FE_B19_IRQ ) >> FE_B19_IRQ_SHIFT; + isa_dev->id_irq = irqmap[n]; + + /* + * Program the 86965 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; /* FIXME */ + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC; + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "RE1000Plus/ME1500 found" ); +#endif + + /* Initialize 86965. */ + outb( sc->ioaddr[FE_DLCR6], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY(200); + + /* Disable all interrupts. */ + outb( sc->ioaddr[FE_DLCR2], 0 ); + outb( sc->ioaddr[FE_DLCR3], 0 ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "end of fe_probe_re1000p()" ); +#endif + + /* + * That's all. RE1000Plus/ME1500 occupies 2*16 I/O addresses, by the way. + */ + return 2; /* ??? */ +} + +/* + * Probe and initialization for Contec C-NET(9N)E series. + */ + +/* TODO: Should be in "if_fereg.h" */ +#define FE_CNET9NE_INTR 0x10 /* Interrupt Mask? */ +#define FE_CNET9NE_MAC0 0x11 /* Station(MAC) address */ +#define FE_CNET9NE_MAC1 0x13 +#define FE_CNET9NE_MAC2 0x15 +#define FE_CNET9NE_MAC3 0x17 +#define FE_CNET9NE_MAC4 0x19 +#define FE_CNET9NE_MAC5 0x1B + +/* TODO: Should be in "ic/mb86960.h" */ +#define FE_D7_ENDEC 0xC0 /* Encoder/Decoder mode(86960 only) */ +#define FE_D7_ENDEC_NORMAL_NICE 0x00 /* Normal NICE */ +#define FE_D7_ENDEC_NICE_MONITOR 0x40 /* NICE + Monitor */ +#define FE_D7_ENDEC_BYPASS 0x80 /* Encoder/Decoder Bypass */ +#define FE_D7_ENDEC_TEST 0xC0 /* Encoder/Decoder Test */ + +static int +fe_probe_cnet9ne ( DEVICE * isa_dev, struct fe_softc * sc ) +{ + int i; + u_char c; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: probe (0x%x) for C-NET(9N)E\n", sc->sc_unit, sc->iobase ); +#endif + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < 16; i++ ) { + sc->ioaddr[i] = sc->iobase + i; + } + for ( ; i < MAXREGISTERS; i++ ) { + sc->ioaddr[i] = sc->iobase + 0x400 - 16 + i; + } + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, NULL ); +#endif + + /* Get our station address from EEPROM. */ + sc->sc_enaddr[0] = inb( sc->ioaddr[FE_CNET9NE_MAC0] ); + sc->sc_enaddr[1] = inb( sc->ioaddr[FE_CNET9NE_MAC1] ); + sc->sc_enaddr[2] = inb( sc->ioaddr[FE_CNET9NE_MAC2] ); + sc->sc_enaddr[3] = inb( sc->ioaddr[FE_CNET9NE_MAC3] ); + sc->sc_enaddr[4] = inb( sc->ioaddr[FE_CNET9NE_MAC4] ); + sc->sc_enaddr[5] = inb( sc->ioaddr[FE_CNET9NE_MAC5] ); + +#if 1 + /* + * Check the Ethernet address here. + * + * Contec uses 00 80 4C ?? ?? ??. + */ + if ( sc->sc_enaddr[0] != (u_char)0x00 + || sc->sc_enaddr[1] != (u_char)0x80 + || sc->sc_enaddr[2] != (u_char)0x4C ) { +#else + /* + * Make sure we got a valid Ethernet address. + */ + if ( ( sc->sc_enaddr[0] & 0x03 ) != 0x00 /* Multicast or Local address. */ + || ( sc->sc_enaddr[0] | sc->sc_enaddr[1] | sc->sc_enaddr[2] ) == 0x00 ) { +#endif +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: invalid MAC adrs(%x:%x:%x:%x:%x:%x)\n" + , sc->sc_unit + , (u_char)sc->sc_enaddr[0], (u_char)sc->sc_enaddr[1] + , (u_char)sc->sc_enaddr[2], (u_char)sc->sc_enaddr[3] + , (u_char)sc->sc_enaddr[4], (u_char)sc->sc_enaddr[5] ); +#endif + return 0; + } + + /* See if C-NET(9N)E is on its address. */ + if ( inb( sc->ioaddr[FE_DLCR6] ) == (u_char)0xff ) { +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: inb(%x) returns 0xff\n" + , sc->sc_unit, sc->ioaddr[FE_DLCR6] ); +#endif + return 0; + } + + sc->typestr = "C-NET9NE"; + + /* + * Program the 86960 as follows: + * SRAM: 64KB, word-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + * Encoder/Decoder mode: Normal NICE. + * + * 86960 manual says that SRAM access-time can't be configured. + * (must be 1) + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; + sc->proto_dlcr5 = FE_D5_RMTRST; /* reserved bit(must be 1) */ + sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM; +#ifndef CNET9NC + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_ENDEC_NORMAL_NICE; +#else + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_ENDEC_BYPASS; +#endif + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; + sc->proto_bmpr14 = 0; + + sc->stop = sc->init = NULL; + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "C-NET(9N)E found" ); +#endif + + /* Initialize 86960. */ + outb( sc->ioaddr[FE_DLCR6], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + +#if 1 /* XXX: Is this really necessary? FIXME. */ + c = inb( sc->ioaddr[FE_DLCR1] ); + if ( c == (u_char)0xff ) { +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: inb(%x) returns 0xff\n" + , sc->sc_unit, sc->ioaddr[FE_DLCR1] ); +#endif + return 0; + } + if ( ( c & FE_D1_PKTRDY ) == 0 ) { + outb( sc->ioaddr[FE_DLCR1], FE_D1_PKTRDY ); + } +#endif + + /* Disable all interrupts. */ + outb( sc->ioaddr[FE_DLCR2], 0 ); + outb( sc->ioaddr[FE_DLCR3], 0 ); + +#ifndef CNET9NC + /* Enable interrupt? FIXME. */ + outb( sc->ioaddr[FE_CNET9NE_INTR], 0x10 ); +#endif + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "end of fe_probe_cnet9ne()" ); +#endif + + /* + * XXX: The I/O address range is fragmented in the CNET(9N)E. + * "16" is the number of regs at iobase. + */ + return 16; +} + +/* + * Probe and initialization for Contec C-NET(98)P2 series. + */ + +/* + * Routines to read all bytes from the config EEPROM through TDK 78Q8377A. + * I'm not sure what exactly I'm doing here... I was told just to follow + * the steps, and it worked. Could someone tell me why the following + * code works? FIXME. + */ + +static void +fe_strobe_eeprom_tdk ( u_short bmpr12 ) +{ + outb( bmpr12, 0x10 ); + outb( bmpr12, 0x12 ); + outb( bmpr12, 0x12 ); + outb( bmpr12, 0x16 ); + outb( bmpr12, 0x12 | 0x01 ); + outb( bmpr12, 0x16 | 0x01 ); + outb( bmpr12, 0x12 | 0x01 ); + outb( bmpr12, 0x16 | 0x01 ); + outb( bmpr12, 0x12 ); + outb( bmpr12, 0x16 ); +} + +static void +fe_read_eeprom_tdk ( struct fe_softc * sc, u_char * data ) +{ + u_short bmpr12 = sc->ioaddr[FE_DLCR12]; + u_char n, val, bit; + + outb( sc->ioaddr[FE_DLCR6], FE_D6_BBW_WORD | FE_D6_SBW_WORD + | FE_D6_DLC_DISABLE ); + outb( sc->ioaddr[FE_DLCR7], FE_D7_BYTSWP_LH | FE_D7_RBS_BMPR + | FE_D7_RDYPNS | FE_D7_POWER_UP ); + + /* Read bytes from EEPROM; two bytes per an iteration. */ + for ( n = 0; n < FE_EEPROM_SIZE / 2; n++ ) { + + /* Start EEPROM access. */ + fe_strobe_eeprom_tdk( bmpr12 ); + + /* Pass the iteration count to the chip. */ + for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { + val = ( n & bit ) ? 0x01 : 0x00; + outb( bmpr12, 0x12 | val ); + outb( bmpr12, 0x16 | val ); + } + + /* Read a byte. */ + val = 0; + for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { + outb( bmpr12, 0x12 ); + outb( bmpr12, 0x16 ); + if ( inb( bmpr12 ) & 0x01 ) { + val |= bit; + } + } + *data++ = val; + + /* Read one more byte. */ + val = 0; + for ( bit = 0x80; bit != 0x00; bit >>= 1 ) { + outb( bmpr12, 0x12 ); + outb( bmpr12, 0x16 ); + if ( inb( bmpr12 ) & 0x01 ) { + val |= bit; + } + } + *data++ = val; + + outb( bmpr12, 0x10 ); + } + + /* Reset the EEPROM interface. */ + outb( bmpr12, 0x00 ); + +#if FE_DEBUG >= 3 + /* Report what we got. */ + data -= FE_EEPROM_SIZE; + log( LOG_INFO, "fe%d: EEPROM:" + " %02x%02x%02x%02x %02x%02x%02x%02x -" + " %02x%02x%02x%02x %02x%02x%02x%02x -" + " %02x%02x%02x%02x %02x%02x%02x%02x -" + " %02x%02x%02x%02x %02x%02x%02x%02x\n", + sc->sc_unit, + data[ 0], data[ 1], data[ 2], data[ 3], + data[ 4], data[ 5], data[ 6], data[ 7], + data[ 8], data[ 9], data[10], data[11], + data[12], data[13], data[14], data[15], + data[16], data[17], data[18], data[19], + data[20], data[21], data[22], data[23], + data[24], data[25], data[26], data[27], + data[28], data[29], data[30], data[31] ); +#endif +} + +/* TODO: Should be in "if_fereg.h" */ +#define FE_CNET98P2_EEP_IRQ (0x04 * 2 + 1) /* Irq */ +#define FE_CNET98P2_EEP_ADDR (0x08 * 2) /* Station(MAC) address */ +#define FE_CNET98P2_EEP_DUPLEX (0x0c * 2 + 1) /* Duplex mode */ + +static int +fe_probe_cnet98p2 ( DEVICE * isa_dev, struct fe_softc * sc ) +{ + int i; + u_char duplex; + u_char eeprom[FE_EEPROM_SIZE]; + static u_short const irqmap [] = + /* INT0 INT1 INT2 */ + { NO_IRQ, NO_IRQ, NO_IRQ, IRQ3, NO_IRQ, IRQ5, IRQ6, NO_IRQ, + NO_IRQ, IRQ9, IRQ10, NO_IRQ, IRQ12, IRQ13, NO_IRQ, NO_IRQ }; + /* INT3 INT4 INT5 INT6 */ + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: probe (0x%x) for C-NET(98)P2\n", sc->sc_unit, sc->iobase ); +#endif + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < 16; i++ ) { + sc->ioaddr[i] = sc->iobase + i; + } + /* Full unused slots with a safe address. */ + for ( ; i < MAXREGISTERS; i++ ) { + sc->ioaddr[i] = sc->iobase; + } + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, NULL ); +#endif + + /* See if C-NET(98)P2 is on its address. */ + if ( inb( sc->ioaddr[FE_DLCR0] ) == (u_char)0xff ) { +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: inb(%x) returns 0xff\n" + , sc->sc_unit, sc->ioaddr[FE_DLCR0] ); +#endif + return 0; + } + if ( inb( sc->ioaddr[FE_DLCR6] ) == (u_char)0xff ) { +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: inb(%x) returns 0xff\n" + , sc->sc_unit, sc->ioaddr[FE_DLCR6] ); +#endif + return 0; + } + + /* + * We are now almost sure we have a 78Q8377 at the given + * address. So, read EEPROM through 78Q8377. We have to write + * into LSI registers to read from EEPROM. FIXME. + */ + fe_read_eeprom_tdk( sc, eeprom ); + + /* + * Initialize constants in the per-line structure. + */ + + /* Get our station address from EEPROM. */ + bcopy( eeprom + FE_CNET98P2_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN ); + +#if 1 + /* + * Check the Ethernet address here. + * + * Contec uses 00 80 4C ?? ?? ??. + */ + if ( sc->sc_enaddr[0] != (u_char)0x00 + || sc->sc_enaddr[1] != (u_char)0x80 + || sc->sc_enaddr[2] != (u_char)0x4C ) { +#else + /* + * Make sure we got a valid Ethernet address. + */ + if ( ( sc->sc_enaddr[0] & 0x03 ) != 0x00 /* Multicast or Local address. */ + || ( sc->sc_enaddr[0] | sc->sc_enaddr[1] | sc->sc_enaddr[2] ) == 0x00 ) { +#endif +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: invalid MAC adrs(%x:%x:%x:%x:%x:%x)\n" + , sc->sc_unit + , (u_char)sc->sc_enaddr[0], (u_char)sc->sc_enaddr[1] + , (u_char)sc->sc_enaddr[2], (u_char)sc->sc_enaddr[3] + , (u_char)sc->sc_enaddr[4], (u_char)sc->sc_enaddr[5] ); +#endif + return 0; + } + + /* + * Get IRQ configuration from EEPROM. + */ + isa_dev->id_irq = irqmap[ eeprom[FE_CNET98P2_EEP_IRQ] ]; + if ( isa_dev->id_irq == NO_IRQ ) { +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: invalid irq configuration(%d)\n" + , sc->sc_unit, eeprom[FE_CNET98P2_EEP_IRQ] ); +#endif + return 0; + } + + /* + * Get Duplex-mode configuration from EEPROM. + */ + duplex = eeprom[FE_CNET98P2_EEP_DUPLEX] & FE_D4_DSC; + sc->typestr = ( duplex ? "CNET98P2(Full duplex)" + : "CNET98P2(Half duplex)" ); + + /* + * Program the 78Q8377 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + * XXX: Should we add IDENT_NICE or IDENT_EC to DLCR7? FIXME. + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL | duplex; + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH; + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; + sc->proto_bmpr14 = FE_B14_FILTER; + + sc->stop = sc->init = NULL; + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "C-NET(98)P2 found" ); +#endif + + /* Initialize 78Q8377. */ + outb( sc->ioaddr[FE_DLCR6], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Disable all interrupts. */ + outb( sc->ioaddr[FE_DLCR2], 0 ); + outb( sc->ioaddr[FE_DLCR3], 0 ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "end of fe_probe_cnet98p2()" ); +#endif + + /* + * That's all. C-NET(98)P2 occupies 16 I/O addresses, as always. + */ + return 16; +} +#else +/* + * Probe and initialization for Fujitsu FMV-180 series boards + */ +static int +fe_probe_fmv ( DEVICE * dev, struct fe_softc * sc ) +{ + int i, n; + + static u_short const baseaddr [ 8 ] = + { 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x300, 0x340 }; + static u_short const irqmap [ 4 ] = + { IRQ3, IRQ7, IRQ10, IRQ15 }; + + static struct fe_simple_probe_struct const probe_table [] = { + { FE_DLCR2, 0x70, 0x00 }, + { FE_DLCR4, 0x08, 0x00 }, + /* { FE_DLCR5, 0x80, 0x00 }, Doesn't work. */ + + { FE_FMV0, 0x78, 0x50 }, /* ERRDY+PRRDY */ + { FE_FMV1, 0xB0, 0x00 }, /* FMV-183/184 has 0x48 bits. */ + { FE_FMV3, 0x7F, 0x00 }, +#if 1 + /* + * Test *vendor* part of the station address for Fujitsu. + * The test will gain reliability of probe process, but + * it rejects FMV-180 clone boards manufactured by other vendors. + * We have to turn the test off when such cards are made available. + */ + { FE_FMV4, 0xFF, 0x00 }, + { FE_FMV5, 0xFF, 0x00 }, + { FE_FMV6, 0xFF, 0x0E }, +#else + /* + * We can always verify the *first* 2 bits (in Ethernet + * bit order) are "no multicast" and "no local" even for + * unknown vendors. + */ + { FE_FMV4, 0x03, 0x00 }, +#endif + { 0 } + }; + + /* "Hardware revision ID" */ + int revision; + + /* + * See if the specified address is possible for FMV-180 series. + */ + for ( i = 0; i < 8; i++ ) { + if ( baseaddr[ i ] == sc->iobase ) break; + } + if ( i == 8 ) return 0; + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i; + } + + /* Simple probe. */ + if ( !fe_simple_probe( sc, probe_table ) ) return 0; + + /* Check if our I/O address matches config info. on EEPROM. */ + n = ( inb( sc->ioaddr[ FE_FMV2 ] ) & FE_FMV2_IOS ) + >> FE_FMV2_IOS_SHIFT; + if ( baseaddr[ n ] != sc->iobase ) { +#if 0 + /* May not work on some revisions of the cards... FIXME. */ + return 0; +#else + /* Just log the fact and see what happens... FIXME. */ + log( LOG_WARNING, "fe%d: strange I/O config?\n", sc->sc_unit ); +#endif + } + + /* Find the "hardware revision." */ + revision = inb( sc->ioaddr[ FE_FMV1 ] ) & FE_FMV1_REV; + + /* Determine the card type. */ + sc->typestr = NULL; + switch ( inb( sc->ioaddr[ FE_FMV0 ] ) & FE_FMV0_MEDIA ) { + case 0: + /* No interface? This doesn't seem to be an FMV-180... */ + return 0; + case FE_FMV0_MEDIUM_T: + switch ( revision ) { + case 8: + sc->typestr = "FMV-183"; + break; + case 12: + sc->typestr = "FMV-183 (on-board)"; + break; + } + break; + case FE_FMV0_MEDIUM_T | FE_FMV0_MEDIUM_5: + switch ( revision ) { + case 0: + sc->typestr = "FMV-181"; + break; + case 1: + sc->typestr = "FMV-181A"; + break; + } + break; + case FE_FMV0_MEDIUM_2: + switch ( revision ) { + case 8: + sc->typestr = "FMV-184 (CSR = 2)"; + break; + } + break; + case FE_FMV0_MEDIUM_5: + switch ( revision ) { + case 8: + sc->typestr = "FMV-184 (CSR = 1)"; + break; + } + break; + case FE_FMV0_MEDIUM_2 | FE_FMV0_MEDIUM_5: + switch ( revision ) { + case 0: + sc->typestr = "FMV-182"; + break; + case 1: + sc->typestr = "FMV-182A"; + break; + case 8: + sc->typestr = "FMV-184 (CSR = 3)"; + break; + } + break; + } + if ( sc->typestr == NULL ) { + /* Unknown card type... Hope the driver works. */ + sc->typestr = "unknown FMV-180 version"; + log( LOG_WARNING, "fe%d: %s: %x-%x-%x-%x\n", + sc->sc_unit, sc->typestr, + inb( sc->ioaddr[ FE_FMV0 ] ), + inb( sc->ioaddr[ FE_FMV1 ] ), + inb( sc->ioaddr[ FE_FMV2 ] ), + inb( sc->ioaddr[ FE_FMV3 ] ) ); + } + + /* + * An FMV-180 has been proved. + * Determine which IRQ to be used. + * + * In this version, we give a priority to the kernel config file. + * If the EEPROM and config don't match, say it to the user for + * an attention. + */ + n = ( inb( sc->ioaddr[ FE_FMV2 ] ) & FE_FMV2_IRS ) + >> FE_FMV2_IRS_SHIFT; + if ( dev->id_irq == NO_IRQ ) { + /* Just use the probed value. */ + dev->id_irq = irqmap[ n ]; + } else if ( dev->id_irq != irqmap[ n ] ) { + /* Don't match. */ + log( LOG_WARNING, + "fe%d: check IRQ in config; it may be incorrect\n", + sc->sc_unit ); + } + + /* + * Initialize constants in the per-line structure. + */ + + /* Get our station address from EEPROM. */ + inblk( sc, FE_FMV4, sc->sc_enaddr, ETHER_ADDR_LEN ); + + /* Make sure we got a valid station address. */ + if ( ( sc->sc_enaddr[ 0 ] & 0x03 ) != 0x00 + || ( sc->sc_enaddr[ 0 ] == 0x00 + && sc->sc_enaddr[ 1 ] == 0x00 + && sc->sc_enaddr[ 2 ] == 0x00 ) ) return 0; + + /* + * Register values which (may) depend on board design. + * + * Program the 86960 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC; + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; + + /* + * Minimum initialization of the hardware. + * We write into registers; hope I/O ports have no + * overlap with other boards. + */ + + /* Initialize ASIC. */ + outb( sc->ioaddr[ FE_FMV3 ], 0 ); + outb( sc->ioaddr[ FE_FMV10 ], 0 ); + + /* Initialize 86960. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Disable all interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0 ); + + /* "Refresh" hardware configuration. FIXME. */ + outb( sc->ioaddr[ FE_FMV2 ], inb( sc->ioaddr[ FE_FMV2 ] ) ); + + /* Turn the "master interrupt control" flag of ASIC on. */ + outb( sc->ioaddr[ FE_FMV3 ], FE_FMV3_IRQENB ); + + /* + * That's all. FMV-180 occupies 32 I/O addresses, by the way. + */ + return 32; +} + +/* + * Probe and initialization for Allied-Telesis AT1700/RE2000 series. + */ +static int +fe_probe_ati ( DEVICE * dev, struct fe_softc * sc ) +{ + int i, n; + u_char eeprom [ FE_EEPROM_SIZE ]; + u_char save16, save17; + + static u_short const baseaddr [ 8 ] = + { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300 }; + static u_short const irqmaps [ 4 ][ 4 ] = + { + { IRQ3, IRQ4, IRQ5, IRQ9 }, + { IRQ10, IRQ11, IRQ12, IRQ15 }, + { IRQ3, IRQ11, IRQ5, IRQ15 }, + { IRQ10, IRQ11, IRQ14, IRQ15 }, + }; + static struct fe_simple_probe_struct const probe_table [] = { + { FE_DLCR2, 0x70, 0x00 }, + { FE_DLCR4, 0x08, 0x00 }, + { FE_DLCR5, 0x80, 0x00 }, +#if 0 + { FE_BMPR16, 0x1B, 0x00 }, + { FE_BMPR17, 0x7F, 0x00 }, +#endif + { 0 } + }; + + /* Assume we have 86965 and no need to restore these. */ + save16 = 0; + save17 = 0; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: probe (0x%x) for ATI\n", + sc->sc_unit, sc->iobase ); + fe_dump( LOG_INFO, sc, NULL ); +#endif + + /* + * See if the specified address is possible for MB86965A JLI mode. + */ + for ( i = 0; i < 8; i++ ) { + if ( baseaddr[ i ] == sc->iobase ) break; + } + if ( i == 8 ) goto NOTFOUND; + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i; + } + + /* + * We should test if MB86965A is on the base address now. + * Unfortunately, it is very hard to probe it reliably, since + * we have no way to reset the chip under software control. + * On cold boot, we could check the "signature" bit patterns + * described in the Fujitsu document. On warm boot, however, + * we can predict almost nothing about register values. + */ + if ( !fe_simple_probe( sc, probe_table ) ) goto NOTFOUND; + + /* Check if our I/O address matches config info on 86965. */ + n = ( inb( sc->ioaddr[ FE_BMPR19 ] ) & FE_B19_ADDR ) + >> FE_B19_ADDR_SHIFT; + if ( baseaddr[ n ] != sc->iobase ) goto NOTFOUND; + + /* + * We are now almost sure we have an AT1700 at the given + * address. So, read EEPROM through 86965. We have to write + * into LSI registers to read from EEPROM. I want to avoid it + * at this stage, but I cannot test the presence of the chip + * any further without reading EEPROM. FIXME. + */ + save16 = inb( sc->ioaddr[ FE_BMPR16 ] ); + save17 = inb( sc->ioaddr[ FE_BMPR17 ] ); + fe_read_eeprom( sc, eeprom ); + + /* Make sure the EEPROM is turned off. */ + outb( sc->ioaddr[ FE_BMPR16 ], 0 ); + outb( sc->ioaddr[ FE_BMPR17 ], 0 ); + + /* Make sure that config info in EEPROM and 86965 agree. */ + if ( eeprom[ FE_EEPROM_CONF ] != inb( sc->ioaddr[ FE_BMPR19 ] ) ) { + goto NOTFOUND; + } + + /* + * The following model identification codes are stolen from + * from the NetBSD port of the fe driver. My reviewers + * suggested minor revision. + */ + + /* Determine the card type. */ + switch (eeprom[FE_ATI_EEP_MODEL]) { + case FE_ATI_MODEL_AT1700T: + sc->typestr = "AT-1700T/RE2001"; + break; + case FE_ATI_MODEL_AT1700BT: + sc->typestr = "AT-1700BT/RE2003"; + break; + case FE_ATI_MODEL_AT1700FT: + sc->typestr = "AT-1700FT/RE2009"; + break; + case FE_ATI_MODEL_AT1700AT: + sc->typestr = "AT-1700AT/RE2005"; + break; + default: + sc->typestr = "unknown AT-1700/RE2000 ?"; + break; + } + + /* + * Try to determine IRQ settings. + * Different models use different ranges of IRQs. + */ + if ( dev->id_irq == NO_IRQ ) { + n = ( inb( sc->ioaddr[ FE_BMPR19 ] ) & FE_B19_IRQ ) + >> FE_B19_IRQ_SHIFT; + switch ( eeprom[ FE_ATI_EEP_REVISION ] & 0xf0 ) { + case 0x30: + dev->id_irq = irqmaps[ 3 ][ n ]; + break; + case 0x10: + case 0x50: + dev->id_irq = irqmaps[ 2 ][ n ]; + break; + case 0x40: + case 0x60: + if ( eeprom[ FE_ATI_EEP_MAGIC ] & 0x04 ) { + dev->id_irq = irqmaps[ 1 ][ n ]; + } else { + dev->id_irq = irqmaps[ 0 ][ n ]; + } + break; + default: + dev->id_irq = irqmaps[ 0 ][ n ]; + break; + } + } + + + /* + * Initialize constants in the per-line structure. + */ + + /* Get our station address from EEPROM. */ + bcopy( eeprom + FE_ATI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN ); + +#if 1 + /* + * This test doesn't work well for AT1700 look-alike by + * other vendors. + */ + /* Make sure the vendor part is for Allied-Telesis. */ + if ( sc->sc_enaddr[ 0 ] != 0x00 + || sc->sc_enaddr[ 1 ] != 0x00 + || sc->sc_enaddr[ 2 ] != 0xF4 ) return 0; + +#else + /* Make sure we got a valid station address. */ + if ( ( sc->sc_enaddr[ 0 ] & 0x03 ) != 0x00 + || ( sc->sc_enaddr[ 0 ] == 0x00 + && sc->sc_enaddr[ 1 ] == 0x00 + && sc->sc_enaddr[ 2 ] == 0x00 ) ) return 0; +#endif + + /* + * Program the 86960 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; /* FIXME */ + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC; +#if 0 /* XXXX Should we use this? FIXME. */ + sc->proto_bmpr13 = eeprom[ FE_ATI_EEP_MEDIA ]; +#else + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; +#endif + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "ATI found" ); +#endif + + /* Setup hooks. This may solves a nasty bug. FIXME. */ + sc->init = fe_init_ati; + + /* Initialize 86965. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Disable all interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0 ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "end of fe_probe_ati()" ); +#endif + + /* + * That's all. AT1700 occupies 32 I/O addresses, by the way. + */ + return 32; + + NOTFOUND: + /* + * We have no AT1700 at a given address. + * Restore BMPR16 and BMPR17 if we have destroyed them, + * hoping that the hardware on the address didn't get + * bad side effect. + */ + if ( save16 != 0 | save17 != 0 ) { + outb( sc->ioaddr[ FE_BMPR16 ], save16 ); + outb( sc->ioaddr[ FE_BMPR17 ], save17 ); + } + return ( 0 ); +} + +/* ATI specific initialization routine. */ +static void +fe_init_ati ( struct fe_softc * sc ) +{ +/* + * I've told that the following operation "Resets" the chip. + * Hope this solve a bug which hangs up the driver under + * heavy load... FIXME. + */ + + /* Minimal initialization of 86965. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* "Reset" by wrting into an undocument register location. */ + outb( sc->ioaddr[ 0x1F ], 0 ); + + /* How long do we have to wait after the reset? FIXME. */ + DELAY( 300 ); +} +#endif /* PC98 */ + +/* + * Probe and initialization for Gateway Communications' old cards. + */ +static int +fe_probe_gwy ( DEVICE * dev, struct fe_softc * sc ) +{ + int i; + + static struct fe_simple_probe_struct probe_table [] = { + { FE_DLCR2, 0x70, 0x00 }, + { FE_DLCR4, 0x08, 0x00 }, + { FE_DLCR7, 0xC0, 0x00 }, + /* + * Test *vendor* part of the address for Gateway. + * This test is essential to identify Gateway's cards. + * We shuld define some symbolic names for the + * following offsets. FIXME. + */ + { 0x18, 0xFF, 0x00 }, + { 0x19, 0xFF, 0x00 }, + { 0x1A, 0xFF, 0x61 }, + { 0 } + }; + + /* + * We need explicit IRQ and supported address. + * I'm not sure which address and IRQ is possible for Gateway + * Ethernet family. The following accepts everything. FIXME. + */ + if ( dev->id_irq == NO_IRQ || ( sc->iobase & ~0x3E0 ) != 0 ) { + return ( 0 ); + } + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "top of probe" ); +#endif + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i; + } + + /* See if the card is on its address. */ + if ( !fe_simple_probe( sc, probe_table ) ) { + return 0; + } + + /* Determine the card type. */ + sc->typestr = "Gateway Ethernet w/ Fujitsu chipset"; + + /* Get our station address from EEPROM. */ + inblk( sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN ); + + /* + * Program the 86960 as follows: + * SRAM: 16KB, 100ns, byte-wide access. + * Transmission buffer: 2KB x 2. + * System bus interface: 16 bits. + * Make sure to clear out ID bits in DLCR7 + * (They actually are Encoder/Decoder control in NICE.) + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_16KB | FE_D6_TXBSIZ_2x2KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH; + sc->proto_bmpr13 = 0; + + /* Minimal initialization of 86960. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Disable all interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0 ); + + /* That's all. The card occupies 32 I/O addresses, as always. */ + return 32; +} + +#if NCARD > 0 +/* + * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface. + * Note that this is for 10302 only; MBH10304 is handled by fe_probe_tdk(). + */ +static int +fe_probe_mbh ( DEVICE * dev, struct fe_softc * sc ) +{ + int i,type; + + static struct fe_simple_probe_struct probe_table [] = { + { FE_DLCR0, 0x09, 0x00 }, + { FE_DLCR2, 0x79, 0x00 }, + { FE_DLCR4, 0x08, 0x00 }, + { FE_DLCR6, 0xFF, 0xB6 }, + /* + * The following location has the first byte of the card's + * Ethernet (MAC) address. + * We can always verify the *first* 2 bits (in Ethernet + * bit order) are "global" and "unicast" for any vendors'. + */ + { FE_MBH10, 0x03, 0x00 }, + + /* Just a gap? Seems reliable, anyway. */ + { 0x12, 0xFF, 0x00 }, + { 0x13, 0xFF, 0x00 }, + { 0x14, 0xFF, 0x00 }, + { 0x15, 0xFF, 0x00 }, + { 0x16, 0xFF, 0x00 }, + { 0x17, 0xFF, 0x00 }, +#if 0 + { 0x18, 0xFF, 0xFF }, + { 0x19, 0xFF, 0xFF }, +#endif + + { 0 } + }; + + /* + * We need explicit IRQ and supported address. + */ + if ( dev->id_irq == NO_IRQ || ( sc->iobase & ~0x3E0 ) != 0 ) { + return ( 0 ); + } + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "top of probe" ); +#endif + + /* Setup an I/O address mapping table. */ + for ( i = 0; i < MAXREGISTERS; i++ ) { + sc->ioaddr[ i ] = sc->iobase + i; + } + + /* + * See if MBH10302 is on its address. + * I'm not sure the following probe code works. FIXME. + */ + if ( !fe_simple_probe( sc, probe_table ) ) return 0; + + /* Determine the card type. */ + sc->typestr = "MBH10302 (PCMCIA)"; + + /* + * Initialize constants in the per-line structure. + */ + + /* Get our station address from EEPROM. */ + inblk( sc, FE_MBH10, sc->sc_enaddr, ETHER_ADDR_LEN ); + + /* Make sure we got a valid station address. */ + if ( sc->sc_enaddr[ 0 ] == 0x00 + && sc->sc_enaddr[ 1 ] == 0x00 + && sc->sc_enaddr[ 2 ] == 0x00 ) return 0; + + /* + * Program the 86960 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE; + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; + + /* Setup hooks. We need a special initialization procedure. */ + sc->init = fe_init_mbh; + + /* + * Minimum initialization. + */ + + /* Minimal initialization of 86960. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Disable all interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0 ); + +#if 1 /* FIXME. */ + /* Initialize system bus interface and encoder/decoder operation. */ + outb( sc->ioaddr[ FE_MBH0 ], FE_MBH0_MAGIC | FE_MBH0_INTR_DISABLE ); +#endif + + /* + * That's all. MBH10302 occupies 32 I/O addresses, by the way. + */ + return 32; +} + +/* MBH specific initialization routine. */ +static void +fe_init_mbh ( struct fe_softc * sc ) +{ + /* Minimal initialization of 86960. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Disable all interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0 ); + + /* Enable master interrupt flag. */ + outb( sc->ioaddr[ FE_MBH0 ], FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE ); +} + +/* + * Probe and initialization for TDK/CONTEC PCMCIA Ethernet interface. + * by MASUI Kenji <masui@cs.titech.ac.jp> + * + * (Contec uses TDK Ethenet chip -- hosokawa) + * + * This version of fe_probe_tdk has been rewrote to handle + * *generic* PC card implementation of Fujitsu MB8696x and compatibles. + * The name _tdk is just for a historical reason. <seki> :-) + */ +static int +fe_probe_tdk ( DEVICE * dev, struct fe_softc * sc ) +{ + int i; + + static struct fe_simple_probe_struct probe_table [] = { + { FE_DLCR2, 0x70, 0x00 }, + { FE_DLCR4, 0x08, 0x00 }, + /* { FE_DLCR5, 0x80, 0x00 }, Does not work well. */ + { 0 } + }; + + /* We need an IRQ. */ + if ( dev->id_irq == NO_IRQ ) { + return ( 0 ); + } + + /* Generic driver needs Ethernet address taken from CIS. */ + if (sc->arpcom.ac_enaddr[0] == 0 + && sc->arpcom.ac_enaddr[1] == 0 + && sc->arpcom.ac_enaddr[2] == 0) { + return 0; + } + + /* Setup an I/O address mapping table; we need only 16 ports. */ + for (i = 0; i < 16; i++) { + sc->ioaddr[i] = sc->iobase + i; + } + /* Fill unused slots with a safe address. */ + for (i = 16; i < MAXREGISTERS; i++) { + sc->ioaddr[i] = sc->iobase; + } + + /* + * See if C-NET(PC)C is on its address. + */ + + if ( !fe_simple_probe( sc, probe_table ) ) return 0; + + /* Determine the card type. */ + sc->typestr = "Generic MB8696x Ethernet (PCMCIA)"; + + /* + * Initialize constants in the per-line structure. + */ + + /* The station address *must*be* already in sc_enaddr; + Make sure we got a valid station address. */ + if ( ( sc->sc_enaddr[ 0 ] & 0x03 ) != 0x00 + || ( sc->sc_enaddr[ 0 ] == 0x00 + && sc->sc_enaddr[ 1 ] == 0x00 + && sc->sc_enaddr[ 2 ] == 0x00 ) ) return 0; + + /* + * Program the 86965 as follows: + * SRAM: 32KB, 100ns, byte-wide access. + * Transmission buffer: 4KB x 2. + * System bus interface: 16 bits. + * XXX: Should we remove IDENT_NICE from DLCR7? Or, + * even add IDENT_EC instead? FIXME. + */ + sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; + sc->proto_dlcr5 = 0; + sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB + | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; + sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE; + sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; + + /* Minimul initialization of 86960. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Disable all interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0 ); + + /* + * That's all. C-NET(PC)C occupies 16 I/O addresses. + * + * Some PC cards (e.g., TDK and Contec) have 16 I/O addresses, + * while some others (e.g., Fujitsu) have 32. Fortunately, + * this generic driver never accesses latter 16 ports in 32 + * ports cards. So, we can assume the *generic* PC cards + * always have 16 ports. + * + * Moreover, PC card probe is isolated from ISA probe, and PC + * card probe routine doesn't use "# of ports" returned by this + * function. 16 v.s. 32 is not important now. + */ + return 16; +} +#endif /* NCARD > 0 */ + +/* + * Install interface into kernel networking data structures + */ +static int +fe_attach ( DEVICE * dev ) +{ +#if NCARD > 0 + static int already_ifattach[NFE]; +#endif + struct fe_softc *sc = &fe_softc[dev->id_unit]; + + /* + * Initialize ifnet structure + */ + sc->sc_if.if_softc = sc; + sc->sc_if.if_unit = sc->sc_unit; + sc->sc_if.if_name = "fe"; + sc->sc_if.if_output = ether_output; + sc->sc_if.if_start = fe_start; + sc->sc_if.if_ioctl = fe_ioctl; + sc->sc_if.if_watchdog = fe_watchdog; + + /* + * Set default interface flags. + */ + sc->sc_if.if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + + /* + * Set maximum size of output queue, if it has not been set. + * It is done here as this driver may be started after the + * system initialization (i.e., the interface is PCMCIA.) + * + * I'm not sure this is really necessary, but, even if it is, + * it should be done somewhere else, e.g., in if_attach(), + * since it must be a common workaround for all network drivers. + * FIXME. + */ + if ( sc->sc_if.if_snd.ifq_maxlen == 0 ) { + sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen; + } + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "attach()" ); +#endif + +#if FE_SINGLE_TRANSMISSION + /* Override txb config to allocate minimum. */ + sc->proto_dlcr6 &= ~FE_D6_TXBSIZ + sc->proto_dlcr6 |= FE_D6_TXBSIZ_2x2KB; +#endif + + /* Modify hardware config if it is requested. */ + if ( dev->id_flags & FE_FLAGS_OVERRIDE_DLCR6 ) { + sc->proto_dlcr6 = dev->id_flags & FE_FLAGS_DLCR6_VALUE; + } + + /* Find TX buffer size, based on the hardware dependent proto. */ + switch ( sc->proto_dlcr6 & FE_D6_TXBSIZ ) { + case FE_D6_TXBSIZ_2x2KB: sc->txb_size = 2048; break; + case FE_D6_TXBSIZ_2x4KB: sc->txb_size = 4096; break; + case FE_D6_TXBSIZ_2x8KB: sc->txb_size = 8192; break; + default: + /* Oops, we can't work with single buffer configuration. */ +#if FE_DEBUG >= 2 + log( LOG_WARNING, "fe%d: strange TXBSIZ config; fixing\n", + sc->sc_unit ); +#endif + sc->proto_dlcr6 &= ~FE_D6_TXBSIZ; + sc->proto_dlcr6 |= FE_D6_TXBSIZ_2x2KB; + sc->txb_size = 2048; + break; + } + + /* Attach and stop the interface. */ +#if NCARD > 0 + if (already_ifattach[dev->id_unit] != 1) { + if_attach(&sc->sc_if); + already_ifattach[dev->id_unit] = 1; + } +#else + if_attach(&sc->sc_if); +#endif + fe_stop(sc->sc_unit); /* This changes the state to IDLE. */ + ether_ifattach(&sc->sc_if); + + /* Print additional info when attached. */ + printf( "fe%d: address %6D, type %s\n", sc->sc_unit, + sc->sc_enaddr, ":" , sc->typestr ); +#if FE_DEBUG >= 3 + { + int buf, txb, bbw, sbw, ram; + + buf = txb = bbw = sbw = ram = -1; + switch ( sc->proto_dlcr6 & FE_D6_BUFSIZ ) { + case FE_D6_BUFSIZ_8KB: buf = 8; break; + case FE_D6_BUFSIZ_16KB: buf = 16; break; + case FE_D6_BUFSIZ_32KB: buf = 32; break; + case FE_D6_BUFSIZ_64KB: buf = 64; break; + } + switch ( sc->proto_dlcr6 & FE_D6_TXBSIZ ) { + case FE_D6_TXBSIZ_2x2KB: txb = 2; break; + case FE_D6_TXBSIZ_2x4KB: txb = 4; break; + case FE_D6_TXBSIZ_2x8KB: txb = 8; break; + } + switch ( sc->proto_dlcr6 & FE_D6_BBW ) { + case FE_D6_BBW_BYTE: bbw = 8; break; + case FE_D6_BBW_WORD: bbw = 16; break; + } + switch ( sc->proto_dlcr6 & FE_D6_SBW ) { + case FE_D6_SBW_BYTE: sbw = 8; break; + case FE_D6_SBW_WORD: sbw = 16; break; + } + switch ( sc->proto_dlcr6 & FE_D6_SRAM ) { + case FE_D6_SRAM_100ns: ram = 100; break; + case FE_D6_SRAM_150ns: ram = 150; break; + } + printf( "fe%d: SRAM %dKB %dbit %dns, TXB %dKBx2, %dbit I/O\n", + sc->sc_unit, buf, bbw, ram, txb, sbw ); + } +#endif + +#if NBPFILTER > 0 + /* If BPF is in the kernel, call the attach for it. */ + bpfattach( &sc->sc_if, DLT_EN10MB, sizeof(struct ether_header)); +#endif + return 1; +} + +/* + * Reset interface. + */ +static void +fe_reset ( int unit ) +{ + /* + * Stop interface and re-initialize. + */ + fe_stop(unit); + fe_init(unit); +} + +/* + * Stop everything on the interface. + * + * All buffered packets, both transmitting and receiving, + * if any, will be lost by stopping the interface. + */ +static void +fe_stop ( int unit ) +{ + struct fe_softc *sc = &fe_softc[unit]; + int s; + + s = splimp(); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "stop()" ); +#endif + + /* Disable interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0x00 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0x00 ); + + /* Stop interface hardware. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Clear all interrupt status. */ + outb( sc->ioaddr[ FE_DLCR0 ], 0xFF ); + outb( sc->ioaddr[ FE_DLCR1 ], 0xFF ); + + /* Put the chip in stand-by mode. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR7 ], sc->proto_dlcr7 | FE_D7_POWER_DOWN ); + DELAY( 200 ); + + /* Reset transmitter variables and interface flags. */ + sc->sc_if.if_flags &= ~( IFF_OACTIVE | IFF_RUNNING ); + sc->sc_if.if_timer = 0; + sc->txb_free = sc->txb_size; + sc->txb_count = 0; + sc->txb_sched = 0; + + /* MAR loading can be delayed. */ + sc->filter_change = 0; + + /* Update config status also. */ + + /* Call a hook. */ + if ( sc->stop ) sc->stop( sc ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "end of stop()" ); +#endif + + (void) splx(s); +} + +/* + * Device timeout/watchdog routine. Entered if the device neglects to + * generate an interrupt after a transmit has been started on it. + */ +static void +fe_watchdog ( struct ifnet *ifp ) +{ + struct fe_softc *sc = (struct fe_softc *)ifp; + +#if FE_DEBUG >= 1 + /* A "debug" message. */ + log( LOG_ERR, "fe%d: transmission timeout (%d+%d)%s\n", + ifp->if_unit, sc->txb_sched, sc->txb_count, + ( ifp->if_flags & IFF_UP ) ? "" : " when down" ); + if ( sc->sc_if.if_opackets == 0 && sc->sc_if.if_ipackets == 0 ) { + log( LOG_WARNING, "fe%d: wrong IRQ setting in config?\n", + ifp->if_unit ); + } +#endif + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, NULL ); +#endif + + /* Record how many packets are lost by this accident. */ + ifp->if_oerrors += sc->txb_sched + sc->txb_count; + + /* Put the interface into known initial state. */ + if ( ifp->if_flags & IFF_UP ) { + fe_reset( ifp->if_unit ); + } else { + fe_stop( ifp->if_unit ); + } +} + +/* + * Initialize device. + */ +static void +fe_init ( int unit ) +{ + struct fe_softc *sc = &fe_softc[unit]; + int s; + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "init()" ); +#endif + + /* We need an address. */ + if (TAILQ_EMPTY(&sc->sc_if.if_addrhead)) { /* XXX unlikely */ +#if FE_DEBUG >= 1 + log( LOG_ERR, "fe%d: init() without any address\n", + sc->sc_unit ); +#endif + return; + } + +#if FE_DEBUG >= 1 + /* + * Make sure we have a valid station address. + * The following test is applicable for any Ethernet interfaces. + * It can be done in somewhere common to all of them. FIXME. + */ + if ( ( sc->sc_enaddr[ 0 ] & 0x01 ) != 0 + || ( sc->sc_enaddr[ 0 ] == 0x00 + && sc->sc_enaddr[ 1 ] == 0x00 + && sc->sc_enaddr[ 2 ] == 0x00 ) ) { + log( LOG_ERR, "fe%d: invalid station address (%6D)\n", + sc->sc_unit, sc->sc_enaddr, ":" ); + return; + } +#endif + + /* Start initializing 86960. */ + s = splimp(); + + /* Call a hook. */ + if ( sc->init ) sc->init( sc ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "after init hook" ); +#endif + + /* + * Make sure to disable the chip, also. + * This may also help re-programming the chip after + * hot insertion of PCMCIAs. + */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Power up the chip and select register bank for DLCRs. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR7 ], + sc->proto_dlcr7 | FE_D7_RBS_DLCR | FE_D7_POWER_UP ); + DELAY( 200 ); + + /* Feed the station address. */ + outblk( sc, FE_DLCR8, sc->sc_enaddr, ETHER_ADDR_LEN ); + + /* Clear multicast address filter to receive nothing. */ + outb( sc->ioaddr[ FE_DLCR7 ], + sc->proto_dlcr7 | FE_D7_RBS_MAR | FE_D7_POWER_UP ); + outblk( sc, FE_MAR8, fe_filter_nothing.data, FE_FILTER_LEN ); + + /* Select the BMPR bank for runtime register access. */ + outb( sc->ioaddr[ FE_DLCR7 ], + sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP ); + + /* Initialize registers. */ + outb( sc->ioaddr[ FE_DLCR0 ], 0xFF ); /* Clear all bits. */ + outb( sc->ioaddr[ FE_DLCR1 ], 0xFF ); /* ditto. */ + outb( sc->ioaddr[ FE_DLCR2 ], 0x00 ); + outb( sc->ioaddr[ FE_DLCR3 ], 0x00 ); + outb( sc->ioaddr[ FE_DLCR4 ], sc->proto_dlcr4 ); + outb( sc->ioaddr[ FE_DLCR5 ], sc->proto_dlcr5 ); + outb( sc->ioaddr[ FE_BMPR10 ], 0x00 ); + outb( sc->ioaddr[ FE_BMPR11 ], FE_B11_CTRL_SKIP | FE_B11_MODE1 ); + outb( sc->ioaddr[ FE_BMPR12 ], 0x00 ); + outb( sc->ioaddr[ FE_BMPR13 ], sc->proto_bmpr13 ); + outb( sc->ioaddr[ FE_BMPR14 ], 0x00 ); + outb( sc->ioaddr[ FE_BMPR15 ], 0x00 ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "just before enabling DLC" ); +#endif + + /* Enable interrupts. */ + outb( sc->ioaddr[ FE_DLCR2 ], FE_TMASK ); + outb( sc->ioaddr[ FE_DLCR3 ], FE_RMASK ); + + /* Enable transmitter and receiver. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_ENABLE ); + DELAY( 200 ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "just after enabling DLC" ); +#endif + + /* + * Make sure to empty the receive buffer. + * + * This may be redundant, but *if* the receive buffer were full + * at this point, then the driver would hang. I have experienced + * some strange hang-up just after UP. I hope the following + * code solve the problem. + * + * I have changed the order of hardware initialization. + * I think the receive buffer cannot have any packets at this + * point in this version. The following code *must* be + * redundant now. FIXME. + * + * I've heard a rumore that on some PC card implementation of + * 8696x, the receive buffer can have some data at this point. + * The following message helps discovering the fact. FIXME. + */ + if ( !( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) ) { + log( LOG_WARNING, + "fe%d: receive buffer has some data after reset\n", + sc->sc_unit ); + + fe_emptybuffer( sc ); + } + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "after ERB loop" ); +#endif + + /* Do we need this here? Actually, no. I must be paranoia. */ + outb( sc->ioaddr[ FE_DLCR0 ], 0xFF ); /* Clear all bits. */ + outb( sc->ioaddr[ FE_DLCR1 ], 0xFF ); /* ditto. */ + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "after FIXME" ); +#endif + /* Set 'running' flag, because we are now running. */ + sc->sc_if.if_flags |= IFF_RUNNING; + + /* + * At this point, the interface is running properly, + * except that it receives *no* packets. we then call + * fe_setmode() to tell the chip what packets to be + * received, based on the if_flags and multicast group + * list. It completes the initialization process. + */ + fe_setmode( sc ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "after setmode" ); +#endif + + /* ...and attempt to start output queued packets. */ + fe_start( &sc->sc_if ); + +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, "init() done" ); +#endif + + (void) splx(s); +} + +/* + * This routine actually starts the transmission on the interface + */ +static void +fe_xmit ( struct fe_softc * sc ) +{ + /* + * Set a timer just in case we never hear from the board again. + * We use longer timeout for multiple packet transmission. + * I'm not sure this timer value is appropriate. FIXME. + */ + sc->sc_if.if_timer = 1 + sc->txb_count; + + /* Update txb variables. */ + sc->txb_sched = sc->txb_count; + sc->txb_count = 0; + sc->txb_free = sc->txb_size; + sc->tx_excolls = 0; + + /* Start transmitter, passing packets in TX buffer. */ + outb( sc->ioaddr[ FE_BMPR10 ], sc->txb_sched | FE_B10_START ); +} + +/* + * Start output on interface. + * We make two assumptions here: + * 1) that the current priority is set to splimp _before_ this code + * is called *and* is returned to the appropriate priority after + * return + * 2) that the IFF_OACTIVE flag is checked before this code is called + * (i.e. that the output part of the interface is idle) + */ +void +fe_start ( struct ifnet *ifp ) +{ + struct fe_softc *sc = ifp->if_softc; + struct mbuf *m; + +#if FE_DEBUG >= 1 + /* Just a sanity check. */ + if ( ( sc->txb_count == 0 ) != ( sc->txb_free == sc->txb_size ) ) { + /* + * Txb_count and txb_free co-works to manage the + * transmission buffer. Txb_count keeps track of the + * used potion of the buffer, while txb_free does unused + * potion. So, as long as the driver runs properly, + * txb_count is zero if and only if txb_free is same + * as txb_size (which represents whole buffer.) + */ + log( LOG_ERR, "fe%d: inconsistent txb variables (%d, %d)\n", + sc->sc_unit, sc->txb_count, sc->txb_free ); + /* + * So, what should I do, then? + * + * We now know txb_count and txb_free contradicts. We + * cannot, however, tell which is wrong. More + * over, we cannot peek 86960 transmission buffer or + * reset the transmission buffer. (In fact, we can + * reset the entire interface. I don't want to do it.) + * + * If txb_count is incorrect, leaving it as-is will cause + * sending of garbage after next interrupt. We have to + * avoid it. Hence, we reset the txb_count here. If + * txb_free was incorrect, resetting txb_count just loose + * some packets. We can live with it. + */ + sc->txb_count = 0; + } +#endif + +#if FE_DEBUG >= 1 + /* + * First, see if there are buffered packets and an idle + * transmitter - should never happen at this point. + */ + if ( ( sc->txb_count > 0 ) && ( sc->txb_sched == 0 ) ) { + log( LOG_ERR, + "fe%d: transmitter idle with %d buffered packets\n", + sc->sc_unit, sc->txb_count ); + fe_xmit( sc ); + } +#endif + + /* + * Stop accepting more transmission packets temporarily, when + * a filter change request is delayed. Updating the MARs on + * 86960 flushes the transmission buffer, so it is delayed + * until all buffered transmission packets have been sent + * out. + */ + if ( sc->filter_change ) { + /* + * Filter change request is delayed only when the DLC is + * working. DLC soon raise an interrupt after finishing + * the work. + */ + goto indicate_active; + } + + for (;;) { + + /* + * See if there is room to put another packet in the buffer. + * We *could* do better job by peeking the send queue to + * know the length of the next packet. Current version just + * tests against the worst case (i.e., longest packet). FIXME. + * + * When adding the packet-peek feature, don't forget adding a + * test on txb_count against QUEUEING_MAX. + * There is a little chance the packet count exceeds + * the limit. Assume transmission buffer is 8KB (2x8KB + * configuration) and an application sends a bunch of small + * (i.e., minimum packet sized) packets rapidly. An 8KB + * buffer can hold 130 blocks of 62 bytes long... + */ + if ( sc->txb_free + < ETHER_MAX_LEN - ETHER_CRC_LEN + FE_DATA_LEN_LEN ) { + /* No room. */ + goto indicate_active; + } + +#if FE_SINGLE_TRANSMISSION + if ( sc->txb_count > 0 ) { + /* Just one packet per a transmission buffer. */ + goto indicate_active; + } +#endif + + /* + * Get the next mbuf chain for a packet to send. + */ + IF_DEQUEUE( &sc->sc_if.if_snd, m ); + if ( m == NULL ) { + /* No more packets to send. */ + goto indicate_inactive; + } + + /* + * Copy the mbuf chain into the transmission buffer. + * txb_* variables are updated as necessary. + */ + fe_write_mbufs( sc, m ); + + /* Start transmitter if it's idle. */ + if ( ( sc->txb_count > 0 ) && ( sc->txb_sched == 0 ) ) { + fe_xmit( sc ); + } + + /* + * Tap off here if there is a bpf listener, + * and the device is *not* in promiscuous mode. + * (86960 receives self-generated packets if + * and only if it is in "receive everything" + * mode.) + */ +#if NBPFILTER > 0 + if ( sc->sc_if.if_bpf + && !( sc->sc_if.if_flags & IFF_PROMISC ) ) { + bpf_mtap( &sc->sc_if, m ); + } +#endif + + m_freem( m ); + } + + indicate_inactive: + /* + * We are using the !OACTIVE flag to indicate to + * the outside world that we can accept an + * additional packet rather than that the + * transmitter is _actually_ active. Indeed, the + * transmitter may be active, but if we haven't + * filled all the buffers with data then we still + * want to accept more. + */ + sc->sc_if.if_flags &= ~IFF_OACTIVE; + return; + + indicate_active: + /* + * The transmitter is active, and there are no room for + * more outgoing packets in the transmission buffer. + */ + sc->sc_if.if_flags |= IFF_OACTIVE; + return; +} + +/* + * Drop (skip) a packet from receive buffer in 86960 memory. + */ +static void +fe_droppacket ( struct fe_softc * sc, int len ) +{ + int i; + + /* + * 86960 manual says that we have to read 8 bytes from the buffer + * before skip the packets and that there must be more than 8 bytes + * remaining in the buffer when issue a skip command. + * Remember, we have already read 4 bytes before come here. + */ + if ( len > 12 ) { + /* Read 4 more bytes, and skip the rest of the packet. */ + ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); + ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); + outb( sc->ioaddr[ FE_BMPR14 ], sc->proto_bmpr14 | FE_B14_SKIP ); + } else { + /* We should not come here unless receiving RUNTs. */ + for ( i = 0; i < len; i += 2 ) { + ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); + } + } +} + +/* + * Empty receiving buffer. + */ +static void +fe_emptybuffer ( struct fe_softc * sc ) +{ + int i; + u_char saved_dlcr5; + +#if FE_DEBUG >= 2 + log( LOG_WARNING, "fe%d: emptying receive buffer\n", sc->sc_unit ); +#endif + /* + * Stop receiving packets, temporarily. + */ + saved_dlcr5 = inb( sc->ioaddr[ FE_DLCR5 ] ); + outb( sc->ioaddr[ FE_DLCR5 ], sc->proto_dlcr5 ); + DELAY(1300); + + /* + * When we come here, the receive buffer management should + * have been broken. So, we cannot use skip operation. + * Just discard everything in the buffer. + */ + for (i = 0; i < 32768; i++) { + if ( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) break; + ( void )inw( sc->ioaddr[ FE_BMPR8 ] ); + } + + /* + * Double check. + */ + if ( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) { + log( LOG_ERR, "fe%d: could not empty receive buffer\n", + sc->sc_unit ); + /* Hmm. What should I do if this happens? FIXME. */ + } + + /* + * Restart receiving packets. + */ + outb( sc->ioaddr[ FE_DLCR5 ], saved_dlcr5 ); +} + +/* + * Transmission interrupt handler + * The control flow of this function looks silly. FIXME. + */ +static void +fe_tint ( struct fe_softc * sc, u_char tstat ) +{ + int left; + int col; + + /* + * Handle "excessive collision" interrupt. + */ + if ( tstat & FE_D0_COLL16 ) { + + /* + * Find how many packets (including this collided one) + * are left unsent in transmission buffer. + */ + left = inb( sc->ioaddr[ FE_BMPR10 ] ); + +#if FE_DEBUG >= 2 + log( LOG_WARNING, "fe%d: excessive collision (%d/%d)\n", + sc->sc_unit, left, sc->txb_sched ); +#endif +#if FE_DEBUG >= 3 + fe_dump( LOG_INFO, sc, NULL ); +#endif + + /* + * Clear the collision flag (in 86960) here + * to avoid confusing statistics. + */ + outb( sc->ioaddr[ FE_DLCR0 ], FE_D0_COLLID ); + + /* + * Restart transmitter, skipping the + * collided packet. + * + * We *must* skip the packet to keep network running + * properly. Excessive collision error is an + * indication of the network overload. If we + * tried sending the same packet after excessive + * collision, the network would be filled with + * out-of-time packets. Packets belonging + * to reliable transport (such as TCP) are resent + * by some upper layer. + */ + outb( sc->ioaddr[ FE_BMPR11 ], + FE_B11_CTRL_SKIP | FE_B11_MODE1 ); + + /* Update statistics. */ + sc->tx_excolls++; + } + + /* + * Handle "transmission complete" interrupt. + */ + if ( tstat & FE_D0_TXDONE ) { + + /* + * Add in total number of collisions on last + * transmission. We also clear "collision occurred" flag + * here. + * + * 86960 has a design flaw on collision count on multiple + * packet transmission. When we send two or more packets + * with one start command (that's what we do when the + * transmission queue is crowded), 86960 informs us number + * of collisions occurred on the last packet on the + * transmission only. Number of collisions on previous + * packets are lost. I have told that the fact is clearly + * stated in the Fujitsu document. + * + * I considered not to mind it seriously. Collision + * count is not so important, anyway. Any comments? FIXME. + */ + + if ( inb( sc->ioaddr[ FE_DLCR0 ] ) & FE_D0_COLLID ) { + + /* Clear collision flag. */ + outb( sc->ioaddr[ FE_DLCR0 ], FE_D0_COLLID ); + + /* Extract collision count from 86960. */ + col = inb( sc->ioaddr[ FE_DLCR4 ] ); + col = ( col & FE_D4_COL ) >> FE_D4_COL_SHIFT; + if ( col == 0 ) { + /* + * Status register indicates collisions, + * while the collision count is zero. + * This can happen after multiple packet + * transmission, indicating that one or more + * previous packet(s) had been collided. + * + * Since the accurate number of collisions + * has been lost, we just guess it as 1; + * Am I too optimistic? FIXME. + */ + col = 1; + } + sc->sc_if.if_collisions += col; +#if FE_DEBUG >= 3 + log( LOG_WARNING, "fe%d: %d collision(s) (%d)\n", + sc->sc_unit, col, sc->txb_sched ); +#endif + } + + /* + * Update transmission statistics. + * Be sure to reflect number of excessive collisions. + */ + sc->sc_if.if_opackets += sc->txb_sched - sc->tx_excolls; + sc->sc_if.if_oerrors += sc->tx_excolls; + sc->sc_if.if_collisions += sc->tx_excolls * 16; + sc->txb_sched = 0; + + /* + * The transmitter is no more active. + * Reset output active flag and watchdog timer. + */ + sc->sc_if.if_flags &= ~IFF_OACTIVE; + sc->sc_if.if_timer = 0; + + /* + * If more data is ready to transmit in the buffer, start + * transmitting them. Otherwise keep transmitter idle, + * even if more data is queued. This gives receive + * process a slight priority. + */ + if ( sc->txb_count > 0 ) fe_xmit( sc ); + } +} + +/* + * Ethernet interface receiver interrupt. + */ +static void +fe_rint ( struct fe_softc * sc, u_char rstat ) +{ + u_short len; + u_char status; + int i; + + /* + * Update statistics if this interrupt is caused by an error. + */ + if ( rstat & ( FE_D1_OVRFLO | FE_D1_CRCERR + | FE_D1_ALGERR | FE_D1_SRTPKT ) ) { +#if FE_DEBUG >= 2 + log( LOG_WARNING, + "fe%d: receive error: %s%s%s%s(%02x)\n", + sc->sc_unit, + rstat & FE_D1_OVRFLO ? "OVR " : "", + rstat & FE_D1_CRCERR ? "CRC " : "", + rstat & FE_D1_ALGERR ? "ALG " : "", + rstat & FE_D1_SRTPKT ? "LEN " : "", + rstat ); +#endif + sc->sc_if.if_ierrors++; + } + + /* + * MB86960 has a flag indicating "receive queue empty." + * We just loop, checking the flag, to pull out all received + * packets. + * + * We limit the number of iterations to avoid infinite-loop. + * The upper bound is set to unrealistic high value. + */ + for (i = 0; i < FE_MAX_RECV_COUNT * 2; i++) { + + /* Stop the iteration if 86960 indicates no packets. */ + if ( inb( sc->ioaddr[ FE_DLCR5 ] ) & FE_D5_BUFEMP ) break; + + /* + * Extract A receive status byte. + * As our 86960 is in 16 bit bus access mode, we have to + * use inw() to get the status byte. The significant + * value is returned in lower 8 bits. + */ + status = ( u_char )inw( sc->ioaddr[ FE_BMPR8 ] ); +#if FE_DEBUG >= 4 + log( LOG_INFO, "fe%d: receive status = %04x\n", + sc->sc_unit, status ); +#endif + + /* + * Extract the packet length. + * It is a sum of a header (14 bytes) and a payload. + * CRC has been stripped off by the 86960. + */ + len = inw( sc->ioaddr[ FE_BMPR8 ] ); + +#if FE_DEBUG >= 1 + /* + * If there was an error with the received packet, it + * must be an indication of out-of-sync on receive + * buffer, because we have programmed the 8696x to + * to discard errored packets, even when the interface + * is in promiscuous mode. We have to re-synchronize. + */ + if (!(status & FE_RPH_GOOD)) { + log(LOG_ERR, + "fe%d: corrupted receive status byte (%02x)\n", + sc->arpcom.ac_if.if_unit, status); + sc->arpcom.ac_if.if_ierrors++; + fe_emptybuffer( sc ); + break; + } +#endif + +#if FE_DEBUG >= 1 + /* + * MB86960 checks the packet length and drop big packet + * before passing it to us. There are no chance we can + * get big packets through it, even if they are actually + * sent over a line. Hence, if the length exceeds + * the specified limit, it means some serious failure, + * such as out-of-sync on receive buffer management. + * + * Same for short packets, since we have programmed + * 86960 to drop short packets. + */ + if ( len > ETHER_MAX_LEN - ETHER_CRC_LEN + || len < ETHER_MIN_LEN - ETHER_CRC_LEN ) { + log( LOG_WARNING, + "fe%d: received a %s packet? (%u bytes)\n", + sc->sc_unit, + len < ETHER_MIN_LEN - ETHER_CRC_LEN + ? "partial" : "big", + len ); + sc->sc_if.if_ierrors++; + fe_emptybuffer( sc ); + break; + } +#endif + + /* + * Go get a packet. + */ + if ( fe_get_packet( sc, len ) < 0 ) { + +#if FE_DEBUG >= 2 + log( LOG_WARNING, "%s%d: out of mbuf;" + " dropping a packet (%u bytes)\n", + sc->sc_unit, len ); +#endif + + /* Skip a packet, updating statistics. */ + sc->sc_if.if_ierrors++; + fe_droppacket( sc, len ); + + /* + * Try extracting other packets, although they will + * cause out-of-mbuf error again. This is required + * to keep receiver interrupt comming. + * (Earlier versions had a bug on this point.) + */ + continue; + } + + /* Successfully received a packet. Update stat. */ + sc->sc_if.if_ipackets++; + } +} + +/* + * Ethernet interface interrupt processor + */ +void +feintr ( int unit ) +{ + struct fe_softc *sc = &fe_softc[unit]; + u_char tstat, rstat; + + /* + * Loop until there are no more new interrupt conditions. + */ + for (;;) { + +#if FE_DEBUG >= 4 + fe_dump( LOG_INFO, sc, "intr()" ); +#endif + + /* + * Get interrupt conditions, masking unneeded flags. + */ + tstat = inb( sc->ioaddr[ FE_DLCR0 ] ) & FE_TMASK; + rstat = inb( sc->ioaddr[ FE_DLCR1 ] ) & FE_RMASK; + +#if FE_DEBUG >= 1 + /* Test for a "dead-lock" condition. */ + if ((rstat & FE_D1_PKTRDY) == 0 + && (inb(sc->ioaddr[FE_DLCR5]) & FE_D5_BUFEMP) == 0 + && (inb(sc->ioaddr[FE_DLCR1]) & FE_D1_PKTRDY) == 0) { + /* + * PKTRDY is off, while receive buffer is not empty. + * We did a double check to avoid a race condition... + * So, we should have missed an interrupt. + */ + log(LOG_WARNING, + "fe%d: missed a receiver interrupt?\n", + sc->arpcom.ac_if.if_unit); + /* Simulate the missed interrupt condition. */ + rstat |= FE_D1_PKTRDY; + } +#endif + + /* Stop processing if there are no interrupts to handle. */ + if ( tstat == 0 && rstat == 0 ) break; + + /* + * Reset the conditions we are acknowledging. + */ + outb( sc->ioaddr[ FE_DLCR0 ], tstat ); + outb( sc->ioaddr[ FE_DLCR1 ], rstat ); + + /* + * Handle transmitter interrupts. Handle these first because + * the receiver will reset the board under some conditions. + */ + if ( tstat ) { + fe_tint( sc, tstat ); + } + + /* + * Handle receiver interrupts + */ + if ( rstat ) { + fe_rint( sc, rstat ); + } + + /* + * Update the multicast address filter if it is + * needed and possible. We do it now, because + * we can make sure the transmission buffer is empty, + * and there is a good chance that the receive queue + * is empty. It will minimize the possibility of + * packet loss. + */ + if ( sc->filter_change + && sc->txb_count == 0 && sc->txb_sched == 0 ) { + fe_loadmar(sc); + sc->sc_if.if_flags &= ~IFF_OACTIVE; + } + + /* + * If it looks like the transmitter can take more data, + * attempt to start output on the interface. This is done + * after handling the receiver interrupt to give the + * receive operation priority. + * + * BTW, I'm not sure in what case the OACTIVE is on at + * this point. Is the following test redundant? + * + * No. This routine polls for both transmitter and + * receiver interrupts. 86960 can raise a receiver + * interrupt when the transmission buffer is full. + */ + if ( ( sc->sc_if.if_flags & IFF_OACTIVE ) == 0 ) { + fe_start( &sc->sc_if ); + } + + } +} + +/* + * Process an ioctl request. This code needs some work - it looks + * pretty ugly. + */ +static int +fe_ioctl ( struct ifnet * ifp, u_long command, caddr_t data ) +{ + struct fe_softc *sc = ifp->if_softc; + int s, error = 0; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: ioctl(%x)\n", sc->sc_unit, command ); +#endif + + s = splimp(); + + switch (command) { + + case SIOCSIFADDR: + { + struct ifaddr * ifa = ( struct ifaddr * )data; + + sc->sc_if.if_flags |= IFF_UP; + + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + fe_init( sc->sc_unit ); /* before arp_ifinit */ + arp_ifinit( &sc->arpcom, ifa ); + break; +#endif +#ifdef IPX + /* + * XXX - This code is probably wrong + */ + case AF_IPX: + { + register struct ipx_addr *ina + = &(IA_SIPX(ifa)->sipx_addr); + + if (ipx_nullhost(*ina)) + ina->x_host = + *(union ipx_host *) (sc->sc_enaddr); else { + bcopy((caddr_t) ina->x_host.c_host, + (caddr_t) sc->sc_enaddr, + sizeof(sc->sc_enaddr)); + } + + /* + * Set new address + */ + fe_init(sc->sc_unit); + break; + } +#endif +#ifdef INET6 + case AF_INET6: + /* IPV6 added by shin 96.2.6 */ + fe_init(sc->sc_unit); + ndp6_ifinit(&sc->arpcom, ifa); + break; +#endif +#ifdef NS + + /* + * XXX - This code is probably wrong + */ + case AF_NS: + { + register struct ns_addr *ina + = &(IA_SNS(ifa)->sns_addr); + + if (ns_nullhost(*ina)) + ina->x_host = + *(union ns_host *) (sc->sc_enaddr); + else { + bcopy((caddr_t) ina->x_host.c_host, + (caddr_t) sc->sc_enaddr, + sizeof(sc->sc_enaddr)); + } + + /* + * Set new address + */ + fe_init(sc->sc_unit); + break; + } +#endif + default: + fe_init( sc->sc_unit ); + break; + } + break; + } + +#ifdef SIOCGIFADDR + case SIOCGIFADDR: + { + struct ifreq * ifr = ( struct ifreq * )data; + struct sockaddr * sa = ( struct sockaddr * )&ifr->ifr_data; + + bcopy((caddr_t)sc->sc_enaddr, + (caddr_t)sa->sa_data, ETHER_ADDR_LEN); + break; + } +#endif + +#ifdef SIOCGIFPHYSADDR + case SIOCGIFPHYSADDR: + { + struct ifreq * ifr = ( struct ifreq * )data; + + bcopy((caddr_t)sc->sc_enaddr, + (caddr_t)&ifr->ifr_data, ETHER_ADDR_LEN); + break; + } +#endif + +#ifdef notdef +#ifdef SIOCSIFPHYSADDR + case SIOCSIFPHYSADDR: + { + /* + * Set the physical (Ethernet) address of the interface. + * When and by whom is this command used? FIXME. + */ + struct ifreq * ifr = ( struct ifreq * )data; + + bcopy((caddr_t)&ifr->ifr_data, + (caddr_t)sc->sc_enaddr, ETHER_ADDR_LEN); + fe_setlinkaddr( sc ); + break; + } +#endif +#endif /* notdef */ + +#ifdef SIOCSIFFLAGS + case SIOCSIFFLAGS: + { + /* + * Switch interface state between "running" and + * "stopped", reflecting the UP flag. + */ + if ( sc->sc_if.if_flags & IFF_UP ) { + if ( ( sc->sc_if.if_flags & IFF_RUNNING ) == 0 ) { + fe_init( sc->sc_unit ); + } + } else { + if ( ( sc->sc_if.if_flags & IFF_RUNNING ) != 0 ) { + fe_stop( sc->sc_unit ); + } + } + + /* + * Promiscuous and/or multicast flags may have changed, + * so reprogram the multicast filter and/or receive mode. + */ + fe_setmode( sc ); + +#if FE_DEBUG >= 1 + /* "ifconfig fe0 debug" to print register dump. */ + if ( sc->sc_if.if_flags & IFF_DEBUG ) { + fe_dump( LOG_DEBUG, sc, "SIOCSIFFLAGS(DEBUG)" ); + } +#endif + break; + } +#endif + +#ifdef SIOCADDMULTI + case SIOCADDMULTI: + case SIOCDELMULTI: + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + fe_setmode( sc ); + error = 0; + break; +#endif + +#ifdef SIOCSIFMTU + case SIOCSIFMTU: + { + /* + * Set the interface MTU. + */ + struct ifreq * ifr = ( struct ifreq * )data; + + if ( ifr->ifr_mtu > ETHERMTU ) { + error = EINVAL; + } else { + sc->sc_if.if_mtu = ifr->ifr_mtu; + } + break; + } +#endif + + default: + error = EINVAL; + } + + (void) splx(s); + return (error); +} + +/* + * Retrieve packet from receive buffer and send to the next level up via + * ether_input(). If there is a BPF listener, give a copy to BPF, too. + * Returns 0 if success, -1 if error (i.e., mbuf allocation failure). + */ +static int +fe_get_packet ( struct fe_softc * sc, u_short len ) +{ + struct ether_header *eh; + struct mbuf *m; + + /* + * NFS wants the data be aligned to the word (4 byte) + * boundary. Ethernet header has 14 bytes. There is a + * 2-byte gap. + */ +#define NFS_MAGIC_OFFSET 2 + + /* + * This function assumes that an Ethernet packet fits in an + * mbuf (with a cluster attached when necessary.) On FreeBSD + * 2.0 for x86, which is the primary target of this driver, an + * mbuf cluster has 4096 bytes, and we are happy. On ancient + * BSDs, such as vanilla 4.3 for 386, a cluster size was 1024, + * however. If the following #error message were printed upon + * compile, you need to rewrite this function. + */ +#if ( MCLBYTES < ETHER_MAX_LEN - ETHER_CRC_LEN + NFS_MAGIC_OFFSET ) +#error "Too small MCLBYTES to use fe driver." +#endif + + /* + * Our strategy has one more problem. There is a policy on + * mbuf cluster allocation. It says that we must have at + * least MINCLSIZE (208 bytes on FreeBSD 2.0 for x86) to + * allocate a cluster. For a packet of a size between + * (MHLEN - 2) to (MINCLSIZE - 2), our code violates the rule... + * On the other hand, the current code is short, simple, + * and fast, however. It does no harmful thing, just waists + * some memory. Any comments? FIXME. + */ + + /* Allocate an mbuf with packet header info. */ + MGETHDR(m, M_DONTWAIT, MT_DATA); + if ( m == NULL ) return -1; + + /* Attach a cluster if this packet doesn't fit in a normal mbuf. */ + if ( len > MHLEN - NFS_MAGIC_OFFSET ) { + MCLGET( m, M_DONTWAIT ); + if ( !( m->m_flags & M_EXT ) ) { + m_freem( m ); + return -1; + } + } + + /* Initialize packet header info. */ + m->m_pkthdr.rcvif = &sc->sc_if; + m->m_pkthdr.len = len; + + /* Set the length of this packet. */ + m->m_len = len; + + /* The following silliness is to make NFS happy */ + m->m_data += NFS_MAGIC_OFFSET; + + /* Get a packet. */ + insw( sc->ioaddr[ FE_BMPR8 ], m->m_data, ( len + 1 ) >> 1 ); + + /* Get (actually just point to) the header part. */ + eh = mtod( m, struct ether_header *); + +#define ETHER_ADDR_IS_MULTICAST(A) (*(char *)(A) & 1) + +#if NBPFILTER > 0 + /* + * Check if there's a BPF listener on this interface. + * If it is, hand off the raw packet to bpf. + */ + if ( sc->sc_if.if_bpf ) { + bpf_mtap( &sc->sc_if, m ); + } +#endif + + /* + * Make sure this packet is (or may be) directed to us. + * That is, the packet is either unicasted to our address, + * or broad/multi-casted. If any other packets are + * received, it is an indication of an error -- probably + * 86960 is in a wrong operation mode. + * Promiscuous mode is an exception. Under the mode, all + * packets on the media must be received. (We must have + * programmed the 86960 so.) + */ + + if ( ( sc->sc_if.if_flags & IFF_PROMISC ) + && !ETHER_ADDR_IS_MULTICAST( eh->ether_dhost ) + && bcmp( eh->ether_dhost, sc->sc_enaddr, ETHER_ADDR_LEN ) != 0 ) { + /* + * The packet was not for us. This is normal since + * we are now in promiscuous mode. Just drop the packet. + */ + m_freem( m ); + return 0; + } + +#if FE_DEBUG >= 3 + if ( !ETHER_ADDR_IS_MULTICAST( eh->ether_dhost ) + && bcmp( eh->ether_dhost, sc->sc_enaddr, ETHER_ADDR_LEN ) != 0 ) { + /* + * This packet was not for us. We can't be in promiscuous + * mode since the case was handled by above test. + * We found an error (of this driver.) + */ + log( LOG_WARNING, + "fe%d: got an unwanted packet, dst = %6D\n", + sc->sc_unit, eh->ether_dhost , ":" ); + m_freem( m ); + return 0; + } +#endif + + /* Strip off the Ethernet header. */ + m->m_pkthdr.len -= sizeof ( struct ether_header ); + m->m_len -= sizeof ( struct ether_header ); + m->m_data += sizeof ( struct ether_header ); + + /* Feed the packet to upper layer. */ + ether_input( &sc->sc_if, eh, m ); + return 0; +} + +/* + * Write an mbuf chain to the transmission buffer memory using 16 bit PIO. + * Returns number of bytes actually written, including length word. + * + * If an mbuf chain is too long for an Ethernet frame, it is not sent. + * Packets shorter than Ethernet minimum are legal, and we pad them + * before sending out. An exception is "partial" packets which are + * shorter than mandatory Ethernet header. + */ +static void +fe_write_mbufs ( struct fe_softc *sc, struct mbuf *m ) +{ + u_short addr_bmpr8 = sc->ioaddr[ FE_BMPR8 ]; + u_short length, len; + struct mbuf *mp; + u_char *data; + u_short savebyte; /* WARNING: Architecture dependent! */ +#define NO_PENDING_BYTE 0xFFFF + + static u_char padding [ ETHER_MIN_LEN - ETHER_CRC_LEN - ETHER_HDR_LEN ]; + +#if FE_DEBUG >= 1 + /* First, count up the total number of bytes to copy */ + length = 0; + for ( mp = m; mp != NULL; mp = mp->m_next ) { + length += mp->m_len; + } +#else + /* Just use the length value in the packet header. */ + length = m->m_pkthdr.len; +#endif + +#if FE_DEBUG >= 2 + /* Check if this matches the one in the packet header. */ + if ( length != m->m_pkthdr.len ) { + log( LOG_WARNING, "fe%d: packet length mismatch? (%d/%d)\n", + sc->sc_unit, length, m->m_pkthdr.len ); + } +#endif + +#if FE_DEBUG >= 1 + /* + * Should never send big packets. If such a packet is passed, + * it should be a bug of upper layer. We just ignore it. + * ... Partial (too short) packets, neither. + */ + if ( length < ETHER_HDR_LEN + || length > ETHER_MAX_LEN - ETHER_CRC_LEN ) { + log( LOG_ERR, + "fe%d: got an out-of-spec packet (%u bytes) to send\n", + sc->sc_unit, length ); + sc->sc_if.if_oerrors++; + return; + } +#endif + + /* + * Put the length word for this frame. + * Does 86960 accept odd length? -- Yes. + * Do we need to pad the length to minimum size by ourselves? + * -- Generally yes. But for (or will be) the last + * packet in the transmission buffer, we can skip the + * padding process. It may gain performance slightly. FIXME. + */ + outw( addr_bmpr8, max( length, ETHER_MIN_LEN - ETHER_CRC_LEN ) ); + + /* + * Update buffer status now. + * Truncate the length up to an even number, since we use outw(). + */ + length = ( length + 1 ) & ~1; + sc->txb_free -= FE_DATA_LEN_LEN + max( length, ETHER_MIN_LEN - ETHER_CRC_LEN); + sc->txb_count++; + + /* + * Transfer the data from mbuf chain to the transmission buffer. + * MB86960 seems to require that data be transferred as words, and + * only words. So that we require some extra code to patch + * over odd-length mbufs. + */ + savebyte = NO_PENDING_BYTE; + for ( mp = m; mp != 0; mp = mp->m_next ) { + + /* Ignore empty mbuf. */ + len = mp->m_len; + if ( len == 0 ) continue; + + /* Find the actual data to send. */ + data = mtod(mp, caddr_t); + + /* Finish the last byte. */ + if ( savebyte != NO_PENDING_BYTE ) { + outw( addr_bmpr8, savebyte | ( *data << 8 ) ); + data++; + len--; + savebyte = NO_PENDING_BYTE; + } + + /* output contiguous words */ + if (len > 1) { + outsw( addr_bmpr8, data, len >> 1); + data += len & ~1; + len &= 1; + } + + /* Save a remaining byte, if there is one. */ + if ( len > 0 ) { + savebyte = *data; + } + } + + /* Spit the last byte, if the length is odd. */ + if ( savebyte != NO_PENDING_BYTE ) { + outw( addr_bmpr8, savebyte ); + } + + /* Pad to the Ethernet minimum length, if the packet is too short. */ + if ( length < ETHER_MIN_LEN - ETHER_CRC_LEN ) { + outsw( addr_bmpr8, padding, ( ETHER_MIN_LEN - ETHER_CRC_LEN - length ) >> 1); + } +} + +/* + * Compute hash value for an Ethernet address + */ +static int +fe_hash ( u_char * ep ) +{ +#define FE_HASH_MAGIC_NUMBER 0xEDB88320L + + u_long hash = 0xFFFFFFFFL; + int i, j; + u_char b; + u_long m; + + for ( i = ETHER_ADDR_LEN; --i >= 0; ) { + b = *ep++; + for ( j = 8; --j >= 0; ) { + m = hash; + hash >>= 1; + if ( ( m ^ b ) & 1 ) hash ^= FE_HASH_MAGIC_NUMBER; + b >>= 1; + } + } + return ( ( int )( hash >> 26 ) ); +} + +/* + * Compute the multicast address filter from the + * list of multicast addresses we need to listen to. + */ +static struct fe_filter +fe_mcaf ( struct fe_softc *sc ) +{ + int index; + struct fe_filter filter; + struct ifmultiaddr *ifma; + + filter = fe_filter_nothing; + for (ifma = sc->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + index = fe_hash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); +#if FE_DEBUG >= 4 + log( LOG_INFO, "fe%d: hash(%6D) == %d\n", + sc->sc_unit, enm->enm_addrlo , ":", index ); +#endif + + filter.data[index >> 3] |= 1 << (index & 7); + } + return ( filter ); +} + +/* + * Calculate a new "multicast packet filter" and put the 86960 + * receiver in appropriate mode. + */ +static void +fe_setmode ( struct fe_softc *sc ) +{ + int flags = sc->sc_if.if_flags; + + /* + * If the interface is not running, we postpone the update + * process for receive modes and multicast address filter + * until the interface is restarted. It reduces some + * complicated job on maintaining chip states. (Earlier versions + * of this driver had a bug on that point...) + * + * To complete the trick, fe_init() calls fe_setmode() after + * restarting the interface. + */ + if ( !( flags & IFF_RUNNING ) ) return; + + /* + * Promiscuous mode is handled separately. + */ + if ( flags & IFF_PROMISC ) { + /* + * Program 86960 to receive all packets on the segment + * including those directed to other stations. + * Multicast filter stored in MARs are ignored + * under this setting, so we don't need to update it. + * + * Promiscuous mode in FreeBSD 2 is used solely by + * BPF, and BPF only listens to valid (no error) packets. + * So, we ignore erroneous ones even in this mode. + * (Older versions of fe driver mistook the point.) + */ + outb( sc->ioaddr[ FE_DLCR5 ], + sc->proto_dlcr5 | FE_D5_AFM0 | FE_D5_AFM1 ); + sc->filter_change = 0; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: promiscuous mode\n", sc->sc_unit ); +#endif + return; + } + + /* + * Turn the chip to the normal (non-promiscuous) mode. + */ + outb( sc->ioaddr[ FE_DLCR5 ], sc->proto_dlcr5 | FE_D5_AFM1 ); + + /* + * Find the new multicast filter value. + * I'm not sure we have to handle modes other than MULTICAST. + * Who sets ALLMULTI? Who turns MULTICAST off? FIXME. + */ + if ( flags & IFF_ALLMULTI ) { + sc->filter = fe_filter_all; + } else if ( flags & IFF_MULTICAST ) { + sc->filter = fe_mcaf( sc ); + } else { + sc->filter = fe_filter_nothing; + } + sc->filter_change = 1; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: address filter: [%8D]\n", + sc->sc_unit, sc->filter.data, " " ); +#endif + + /* + * We have to update the multicast filter in the 86960, A.S.A.P. + * + * Note that the DLC (Data Link Control unit, i.e. transmitter + * and receiver) must be stopped when feeding the filter, and + * DLC trashes all packets in both transmission and receive + * buffers when stopped. + * + * ... Are the above sentences correct? I have to check the + * manual of the MB86960A. FIXME. + * + * To reduce the packet loss, we delay the filter update + * process until buffers are empty. + */ + if ( sc->txb_sched == 0 && sc->txb_count == 0 + && !( inb( sc->ioaddr[ FE_DLCR1 ] ) & FE_D1_PKTRDY ) ) { + /* + * Buffers are (apparently) empty. Load + * the new filter value into MARs now. + */ + fe_loadmar(sc); + } else { + /* + * Buffers are not empty. Mark that we have to update + * the MARs. The new filter will be loaded by feintr() + * later. + */ +#if FE_DEBUG >= 4 + log( LOG_INFO, "fe%d: filter change delayed\n", sc->sc_unit ); +#endif + } +} + +/* + * Load a new multicast address filter into MARs. + * + * The caller must have splimp'ed before fe_loadmar. + * This function starts the DLC upon return. So it can be called only + * when the chip is working, i.e., from the driver's point of view, when + * a device is RUNNING. (I mistook the point in previous versions.) + */ +static void +fe_loadmar ( struct fe_softc * sc ) +{ + /* Stop the DLC (transmitter and receiver). */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_DISABLE ); + DELAY( 200 ); + + /* Select register bank 1 for MARs. */ + outb( sc->ioaddr[ FE_DLCR7 ], + sc->proto_dlcr7 | FE_D7_RBS_MAR | FE_D7_POWER_UP ); + + /* Copy filter value into the registers. */ + outblk( sc, FE_MAR8, sc->filter.data, FE_FILTER_LEN ); + + /* Restore the bank selection for BMPRs (i.e., runtime registers). */ + outb( sc->ioaddr[ FE_DLCR7 ], + sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP ); + + /* Restart the DLC. */ + DELAY( 200 ); + outb( sc->ioaddr[ FE_DLCR6 ], sc->proto_dlcr6 | FE_D6_DLC_ENABLE ); + DELAY( 200 ); + + /* We have just updated the filter. */ + sc->filter_change = 0; + +#if FE_DEBUG >= 3 + log( LOG_INFO, "fe%d: address filter changed\n", sc->sc_unit ); +#endif +} + +#if FE_DEBUG >= 1 +static void +fe_dump ( int level, struct fe_softc * sc, char * message ) +{ + log( level, "fe%d: %s," + " DLCR = %02x %02x %02x %02x %02x %02x %02x %02x," + " BMPR = xx xx %02x %02x %02x %02x %02x %02x," + " asic = %02x %02x %02x %02x %02x %02x %02x %02x" + " + %02x %02x %02x %02x %02x %02x %02x %02x\n", + sc->sc_unit, message ? message : "registers", + inb( sc->ioaddr[ FE_DLCR0 ] ), inb( sc->ioaddr[ FE_DLCR1 ] ), + inb( sc->ioaddr[ FE_DLCR2 ] ), inb( sc->ioaddr[ FE_DLCR3 ] ), + inb( sc->ioaddr[ FE_DLCR4 ] ), inb( sc->ioaddr[ FE_DLCR5 ] ), + inb( sc->ioaddr[ FE_DLCR6 ] ), inb( sc->ioaddr[ FE_DLCR7 ] ), + inb( sc->ioaddr[ FE_BMPR10 ] ), inb( sc->ioaddr[ FE_BMPR11 ] ), + inb( sc->ioaddr[ FE_BMPR12 ] ), inb( sc->ioaddr[ FE_BMPR13 ] ), + inb( sc->ioaddr[ FE_BMPR14 ] ), inb( sc->ioaddr[ FE_BMPR15 ] ), + inb( sc->ioaddr[ 0x10 ] ), inb( sc->ioaddr[ 0x11 ] ), + inb( sc->ioaddr[ 0x12 ] ), inb( sc->ioaddr[ 0x13 ] ), + inb( sc->ioaddr[ 0x14 ] ), inb( sc->ioaddr[ 0x15 ] ), + inb( sc->ioaddr[ 0x16 ] ), inb( sc->ioaddr[ 0x17 ] ), + inb( sc->ioaddr[ 0x18 ] ), inb( sc->ioaddr[ 0x19 ] ), + inb( sc->ioaddr[ 0x1A ] ), inb( sc->ioaddr[ 0x1B ] ), + inb( sc->ioaddr[ 0x1C ] ), inb( sc->ioaddr[ 0x1D ] ), + inb( sc->ioaddr[ 0x1E ] ), inb( sc->ioaddr[ 0x1F ] ) ); +} +#endif diff --git a/sys/pc98/pc98/lpt.c b/sys/pc98/pc98/lpt.c index 856974f65f84..1fac3d86e58c 100644 --- a/sys/pc98/pc98/lpt.c +++ b/sys/pc98/pc98/lpt.c @@ -46,7 +46,7 @@ * SUCH DAMAGE. * * from: unknown origin, 386BSD 0.1 - * $Id: lpt.c,v 1.23 1998/10/22 05:58:45 bde Exp $ + * $Id: lpt.c,v 1.21 1998/06/17 16:33:14 kato Exp $ */ /* @@ -195,12 +195,9 @@ #ifndef DEBUG -#define lprintf(args) +#define lprintf (void) #else -#define lprintf(args) do { \ - if (lptflag) \ - printf args; \ - } while (0) +#define lprintf if (lptflag) printf static int volatile lptflag = 1; #endif @@ -272,7 +269,6 @@ static struct lpt_softc { static timeout_t lptout; static int lptprobe (struct isa_device *dvp); static int lptattach (struct isa_device *isdp); -static ointhand2_t lptintr; #ifdef INET @@ -328,8 +324,8 @@ lpt_port_test (int port, u_char data, u_char mask) temp = inb(port) & mask; } while (temp != data && --timeout); - lprintf(("Port 0x%x\tout=%x\tin=%x\ttout=%d\n", - port, data, temp, timeout)); + lprintf("Port 0x%x\tout=%x\tin=%x\ttout=%d\n", + port, data, temp, timeout); return (temp == data); } @@ -441,7 +437,6 @@ lptattach(struct isa_device *isdp) struct lpt_softc *sc; int unit; - isdp->id_ointr = lptintr; unit = isdp->id_unit; sc = lpt_sc + unit; sc->sc_port = isdp->id_iobase; @@ -457,7 +452,7 @@ lptattach(struct isa_device *isdp) #endif /* check if we can use interrupt */ - lprintf(("oldirq %x\n", sc->sc_irq)); + lprintf("oldirq %x\n", sc->sc_irq); if (isdp->id_irq) { sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ; printf("lpt%d: Interrupt-driven port\n", unit); @@ -466,9 +461,9 @@ lptattach(struct isa_device *isdp) #endif } else { sc->sc_irq = 0; - lprintf(("lpt%d: Polled port\n", unit)); + lprintf("lpt%d: Polled port\n", unit); } - lprintf(("irq %x\n", sc->sc_irq)); + lprintf("irq %x\n", sc->sc_irq); #ifdef DEVFS /* XXX what to do about the flags in the minor number? */ @@ -506,7 +501,7 @@ lptopen (dev_t dev, int flags, int fmt, struct proc *p) #endif if (sc->sc_state) { - lprintf(("lp: still open %x\n", sc->sc_state)); + lprintf("lp: still open %x\n", sc->sc_state); return(EBUSY); } else sc->sc_state |= INIT; @@ -520,7 +515,7 @@ lptopen (dev_t dev, int flags, int fmt, struct proc *p) } s = spltty(); - lprintf(("lp flags 0x%x\n", sc->sc_flags)); + lprintf("lp flags 0x%x\n", sc->sc_flags); port = sc->sc_port; /* set IRQ status according to ENABLE_IRQ flag */ @@ -548,7 +543,7 @@ lptopen (dev_t dev, int flags, int fmt, struct proc *p) if (trys++ >= LPINITRDY*4) { splx(s); sc->sc_state = 0; - lprintf(("status %x\n", inb(port+lpt_status))); + lprintf ("status %x\n", inb(port+lpt_status) ); return (EBUSY); } @@ -581,14 +576,14 @@ lptopen (dev_t dev, int flags, int fmt, struct proc *p) splx(s); /* only use timeout if using interrupt */ - lprintf(("irq %x\n", sc->sc_irq)); + 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")); + lprintf("opened.\n"); return(0); } @@ -598,7 +593,7 @@ lptout (void *arg) struct lpt_softc *sc = arg; int pl; - lprintf(("T %x ", inb(sc->sc_port+lpt_status))); + lprintf ("T %x ", inb(sc->sc_port+lpt_status)); if (sc->sc_state & OPEN) { sc->sc_backoff++; if (sc->sc_backoff > hz/LPTOUTMAX) @@ -657,7 +652,7 @@ lptclose(dev_t dev, int flags, int fmt, struct proc *p) end_close: sc->sc_state = 0; sc->sc_xfercnt = 0; - lprintf(("closed.\n")); + lprintf("closed.\n"); return(0); } @@ -676,7 +671,7 @@ pushbytes(struct lpt_softc * sc) char ch; int port = sc->sc_port; - lprintf(("p")); + lprintf("p"); /* loop for every character .. */ while (sc->sc_xfercnt > 0) { /* printer data */ @@ -754,16 +749,16 @@ lptwrite(dev_t dev, struct uio * uio, int ioflag) uiomove(sc->sc_cp, n, uio); sc->sc_xfercnt = n ; while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) { - lprintf(("i")); + 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)); + lprintf("\nC %d. ", sc->sc_xfercnt); pl = spltty(); lptintr(sc - lpt_sc); (void) splx(pl); } - lprintf(("W ")); + lprintf("W "); if (sc->sc_state & OBUSY) if ((err = tsleep ((caddr_t)sc, LPPRI|PCATCH, "lpwrite", 0))) { @@ -773,7 +768,7 @@ lptwrite(dev_t dev, struct uio * uio, int ioflag) } /* check to see if we must do a polled write */ if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) { - lprintf(("p")); + lprintf("p"); if((err = pushbytes(sc))) return(err); } @@ -788,7 +783,7 @@ lptwrite(dev_t dev, struct uio * uio, int ioflag) * do checking for interrupted write call. */ -static void +void lptintr(int unit) { struct lpt_softc *sc = lpt_sc + unit; @@ -819,7 +814,7 @@ lptintr(int unit) if (sc->sc_xfercnt) { /* send char */ - /*lprintf(("%x ", *sc->sc_cp)); */ + /*lprintf("%x ", *sc->sc_cp); */ outb(port+lpt_data, *sc->sc_cp++) ; outb(port+lpt_control, sc->sc_control|LPC_STB); /* DELAY(X) */ @@ -836,7 +831,7 @@ lptintr(int unit) sc->sc_state &= ~OBUSY; if(!(sc->sc_state & INTERRUPTED)) wakeup((caddr_t)sc); - lprintf(("w ")); + lprintf("w "); return; } else { /* check for error */ if(((sts & (LPS_NERR | LPS_OUT) ) != LPS_NERR) && @@ -845,7 +840,7 @@ lptintr(int unit) /* lptout() will jump in and try to restart. */ } #endif - lprintf(("sts %x ", sts)); + lprintf("sts %x ", sts); } static int @@ -1032,7 +1027,7 @@ lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data) break; default: - lprintf(("LP:ioctl(0x%lx)\n", cmd)); + lprintf("LP:ioctl(0x%lx)\n", cmd); return EINVAL; } return 0; @@ -1129,7 +1124,7 @@ lpintr (int unit) sc->sc_iferrs = 0; if (IF_QFULL(&ipintrq)) { - lprintf(("DROP")); + lprintf("DROP"); IF_DROP(&ipintrq); goto done; } @@ -1178,7 +1173,7 @@ lpintr (int unit) sc->sc_iferrs = 0; if (IF_QFULL(&ipintrq)) { - lprintf(("DROP")); + lprintf("DROP"); IF_DROP(&ipintrq); goto done; } @@ -1200,7 +1195,7 @@ lpintr (int unit) err: outb(lpt_data_port, 0); - lprintf(("R")); + lprintf("R"); sc->sc_if.if_ierrors++; sc->sc_iferrs++; @@ -1266,7 +1261,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m, if (ifp->if_flags & IFF_LINK0) { if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) { - lprintf(("&")); + lprintf("&"); lptintr(ifp->if_unit); } @@ -1326,7 +1321,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m, nend: if (err) { /* if we didn't timeout... */ ifp->if_oerrors++; - lprintf(("X")); + lprintf("X"); } else { ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; @@ -1335,7 +1330,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m, m_freem(m); if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) { - lprintf(("^")); + lprintf("^"); lptintr(ifp->if_unit); } (void) splx(s); @@ -1343,7 +1338,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m, } if (inb(lpt_stat_port) & LPIP_SHAKE) { - lprintf(("&")); + lprintf("&"); lptintr(ifp->if_unit); } @@ -1368,7 +1363,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m, if (err) { /* if we didn't timeout... */ ifp->if_oerrors++; - lprintf(("X")); + lprintf("X"); } else { ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; @@ -1396,7 +1391,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m, m_freem(m); if (inb(lpt_stat_port) & LPIP_SHAKE) { - lprintf(("^")); + lprintf("^"); lptintr(ifp->if_unit); } diff --git a/sys/pc98/pc98/mse.c b/sys/pc98/pc98/mse.c index e5bcc4439bf8..65a8aa5bc858 100644 --- a/sys/pc98/pc98/mse.c +++ b/sys/pc98/pc98/mse.c @@ -11,7 +11,7 @@ * this software for any purpose. It is provided "as is" * without express or implied warranty. * - * $Id: mse.c,v 1.17 1998/06/08 08:55:44 kato Exp $ + * $Id: mse.c,v 1.16 1998/01/24 02:54:38 eivind Exp $ */ /* * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and @@ -88,7 +88,6 @@ static struct cdevsw mse_cdevsw = mseioctl, nostop, nullreset, nodevtotty,/* mse */ msepoll, nommap, NULL, "mse", NULL, -1 }; -static ointhand2_t mseintr; /* * Software control structure for mouse. The sc_enablemouse(), @@ -322,7 +321,6 @@ mseattach(idp) } #endif - idp->id_ointr = mseintr; sc->sc_port = idp->id_iobase; sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4; #ifdef DEVFS @@ -612,7 +610,7 @@ msepoll(dev, events, p) /* * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative. */ -static void +void mseintr(unit) int unit; { diff --git a/sys/pc98/pc98/npx.c b/sys/pc98/pc98/npx.c index 03077ddfb565..504fd3cf506e 100644 --- a/sys/pc98/pc98/npx.c +++ b/sys/pc98/pc98/npx.c @@ -32,7 +32,7 @@ * SUCH DAMAGE. * * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 - * $Id: npx.c,v 1.41 1998/12/17 08:41:34 kato Exp $ + * $Id: npx.c,v 1.37 1998/05/04 07:33:32 kato Exp $ */ #include "npx.h" @@ -59,7 +59,9 @@ #include <machine/cputypes.h> #include <machine/frame.h> #include <machine/ipl.h> +#ifndef SMP #include <machine/md_var.h> +#endif #include <machine/pcb.h> #include <machine/psl.h> #ifndef SMP @@ -89,7 +91,15 @@ #define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2) /* XXX - should be in header file. */ -ointhand2_t npxintr; +extern void (*bcopy_vector) __P((const void *from, void *to, size_t len)); +extern void (*ovbcopy_vector) __P((const void *from, void *to, size_t len)); +extern int (*copyin_vector) __P((const void *udaddr, void *kaddr, size_t len)); +extern int (*copyout_vector) __P((const void *kaddr, void *udaddr, size_t len)); + +void i586_bcopy __P((const void *from, void *to, size_t len)); +void i586_bzero __P((void *buf, size_t len)); +int i586_copyin __P((const void *udaddr, void *kaddr, size_t len)); +int i586_copyout __P((const void *kaddr, void *udaddr, size_t len)); #ifdef __GNUC__ @@ -140,17 +150,15 @@ SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, CTLFLAG_RD, &hw_float, 0, "Floatingpoint instructions executed in hardware"); -#ifndef SMP -static u_int npx0_imask = SWI_CLOCK_MASK; -static struct gate_descriptor npx_idt_probeintr; -static int npx_intrno; -static volatile u_int npx_intrs_while_probing; -static volatile u_int npx_traps_while_probing; -#endif +static u_int npx0_imask = SWI_CLOCK_MASK; static bool_t npx_ex16; static bool_t npx_exists; +static struct gate_descriptor npx_idt_probeintr; +static int npx_intrno; +static volatile u_int npx_intrs_while_probing; static bool_t npx_irq13; +static volatile u_int npx_traps_while_probing; #ifndef SMP /* @@ -270,10 +278,8 @@ static int npxprobe1(dvp) struct isa_device *dvp; { -#ifndef SMP u_short control; u_short status; -#endif /* * Partially reset the coprocessor, if any. Some BIOS's don't reset @@ -421,8 +427,6 @@ int npxattach(dvp) struct isa_device *dvp; { - dvp->id_ointr = npxintr; - /* The caller has printed "irq 13" for the npx_irq13 case. */ if (!npx_irq13) { printf("npx%d: ", dvp->id_unit); diff --git a/sys/pc98/pc98/pc98.c b/sys/pc98/pc98/pc98.c index a3c9bc36c214..185c34906674 100644 --- a/sys/pc98/pc98/pc98.c +++ b/sys/pc98/pc98/pc98.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: pc98.c,v 1.54 1998/10/22 05:58:45 bde Exp $ + * $Id: pc98.c,v 1.52 1998/10/12 15:06:02 kato Exp $ */ /* @@ -535,7 +535,7 @@ config_isadev_c(isdp, mp, reconfig) printf("%s%d", dp->name, isdp->id_unit); if (id_alive != -1) { if (isdp->id_iobase == -1) - printf(" at"); + printf(" at ?"); else { printf(" at 0x%x", isdp->id_iobase); if (isdp->id_iobase + id_alive - 1 != @@ -583,10 +583,7 @@ config_isadev_c(isdp, mp, reconfig) isdp->id_alive = id_alive; } (*dp->attach)(isdp); - if (isdp->id_irq != 0 && isdp->id_intr == NULL) - printf("%s%d: irq with no handler\n", - dp->name, isdp->id_unit); - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { + if (isdp->id_irq) { #ifdef APIC_IO /* * Some motherboards use upper IRQs for traditional @@ -623,7 +620,7 @@ config_isadev_c(isdp, mp, reconfig) } else { #if 0 /* This code has not been tested.... */ - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { + if (isdp->id_irq) { icu_unset(ffs(isdp->id_irq) - 1, isdp->id_intr); if (mp) diff --git a/sys/pc98/pc98/pc98gdc.c b/sys/pc98/pc98/pc98gdc.c deleted file mode 100644 index 076f9e774882..000000000000 --- a/sys/pc98/pc98/pc98gdc.c +++ /dev/null @@ -1,887 +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. - * - * $Id$ - */ - -#include "gdc.h" -#include "opt_gdc.h" -#include "opt_fb.h" -#include "opt_syscons.h" - -#if NGDC > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/bus.h> -#include <sys/malloc.h> - -#include <vm/vm.h> -#include <vm/pmap.h> - -#include <machine/console.h> -#include <machine/md_var.h> -#include <machine/pc/bios.h> - -#include <dev/fb/fbreg.h> - -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> - -#include <i386/isa/isa_device.h> - -#define TEXT_GDC IO_GDC1 /* 0x60 */ -#define ROW 25 -#define COL 80 - -#define DRIVER_NAME "gdc" - -/* cdev driver declaration */ - -#define GDC_UNIT(dev) minor(dev) -#define GDC_MKMINOR(unit) (unit) - -static int gdcprobe(struct isa_device *dev); -static int gdc_attach(struct isa_device *dev); -static void gdc_drvinit(void *unused); - -struct isa_driver gdcdriver = { - gdcprobe, - gdc_attach, - DRIVER_NAME, - 0, -}; - -typedef struct gdc_softc { - video_adapter_t *adp; -} gdc_softc_t; - -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); - -#define GDC_SOFTC(unit) (gdc_softc[unit]) - -static gdc_softc_t *gdc_softc[NGDC]; - -#if FB_INSTALL_CDEV - -static d_open_t gdcopen; -static d_close_t gdcclose; -static d_read_t gdcread; -static d_ioctl_t gdcioctl; - -static struct cdevsw vga_cdevsw = { - gdcopen, gdcclose, noread, nowrite, /* ?? */ - gdcioctl, nostop, nullreset, nodevtotty, - seltrue, nommap, NULL, DRIVER_NAME, - NULL, -1, nodump, nopsize, -}; - -#endif /* FB_INSTALL_CDEV */ - -static int -gdcprobe(struct isa_device *dev) -{ - gdc_softc_t *sc; - int error; - - if (dev->id_unit >= sizeof(gdc_softc)/sizeof(gdc_softc[0])) - return 0; - sc = gdc_softc[dev->id_unit] - = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) - return 0; - - error = gdc_probe_unit(dev->id_unit, sc, dev->id_flags); - if (error) { - gdc_softc[dev->id_unit] = NULL; - free(sc, M_DEVBUF); - return 0; - } - - dev->id_iobase = sc->adp->va_io_base; - dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base); - dev->id_msize = sc->adp->va_mem_size; - - return sc->adp->va_io_size; -} - -static int -gdc_attach(struct isa_device *dev) -{ - gdc_softc_t *sc; - - if (dev->id_unit >= sizeof(gdc_softc)/sizeof(gdc_softc[0])) - return 0; - sc = gdc_softc[dev->id_unit]; - if (sc == NULL) - return 0; - - return ((gdc_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1); -} - -static int -gdc_probe_unit(int unit, gdc_softc_t *sc, int flags) -{ - video_switch_t *sw; - - bzero(sc, sizeof(*sc)); - sw = vid_get_switch(DRIVER_NAME); - if (sw == NULL) - return 0; - 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; - int error; - - sw = vid_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - - error = (*sw->init)(unit, sc->adp, flags); - if (error) - return ENXIO; - -#ifdef FB_INSTALL_CDEV - /* attach a virtual frame buffer device */ - error = fb_attach(makedev(0, GDC_MKMINOR(unit)), scp->adp, - &vga_cdevsw); - if (error) - return error; -#endif /* FB_INSTALL_CDEV */ - - if (bootverbose) - (*sw->diag)(sc->adp, bootverbose); - - return 0; -} - -/* LOW-LEVEL */ - -#include <machine/clock.h> - -#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, - IO_GDC1, 16, TEXT_GDC, /* va_io*, XXX */ - VIDEO_BUF_BASE, VIDEO_BUF_SIZE, /* va_mem* */ - TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, /* va_window* */ - 0, 0, /* va_buffer, va_buffer_size */ - 0, M_PC98_80x25, 0, 0, /* va_*mode* */ - NULL }, -}; - -static video_adapter_t biosadapter[1]; - -/* video driver declarations */ -static int gdc_configure(int flags); -static int gdc_nop(void); -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_mmap_t gdc_mmap; -static vi_diag_t gdc_diag; - -static int gdc_err(video_adapter_t *adp, ...); - -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, - (vi_save_palette_t *)gdc_err, - (vi_load_palette_t *)gdc_err, - gdc_set_border, - gdc_save_state, - gdc_load_state, - (vi_set_win_org_t *)gdc_err, - gdc_read_hw_cursor, - gdc_set_hw_cursor, - gdc_set_hw_cursor_shape, - (vi_blank_display_t *)gdc_nop, - gdc_mmap, - 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 }, -#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 }, -#endif - { EOT }, -}; - -static int init_done = FALSE; - -/* local functions */ -static int map_gen_mode_num(int type, int color, int mode); -static int probe_adapters(void); -static void dump_buffer(u_char *buf, size_t len); - -#define prologue(adp, flag, err) \ - if (!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; -} - -/* 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 (init_done) - return 1; - 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; - - master_gdc_wait_vsync(); - master_gdc_cmd(_GDC_START); /* text ON */ - gdc_wait_vsync(); - gdc_cmd(_GDC_STOP); /* graphics OFF */ - - gdc_get_info(&biosadapter[0], biosadapter[0].va_initial_mode, &info); - biosadapter[0].va_mode_flags = info.vi_flags; - 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; - - return 1; -} - -static void master_gdc_cmd(unsigned int cmd) -{ - while ( (inb(IO_GDC1) & 2) != 0); - outb(IO_GDC1+2, cmd); -} - -static void master_gdc_prm(unsigned int pmtr) -{ - while ( (inb(IO_GDC1) & 2) != 0); - outb(IO_GDC1, pmtr); -} - -static void master_gdc_word_prm(unsigned int wpmtr) -{ - master_gdc_prm(wpmtr & 0x00ff); - master_gdc_prm((wpmtr >> 8) & 0x00ff); -} - -static void master_gdc_fifo_empty(void) -{ - while ( (inb(IO_GDC1) & 4) == 0); -} - -static void master_gdc_wait_vsync(void) -{ - while ( (inb(IO_GDC1) & 0x20) != 0); - while ( (inb(IO_GDC1) & 0x20) == 0); -} - -static void gdc_cmd(unsigned int cmd) -{ - while ( (inb(IO_GDC2) & 2) != 0); - outb( IO_GDC2+2, cmd); -} - -static void gdc_prm(unsigned int pmtr) -{ - while ( (inb(IO_GDC2) & 2) != 0); - outb( IO_GDC2, 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(IO_GDC2) & 0x04) == 0); -} - -static void gdc_wait_vsync(void) -{ - while ( (inb(IO_GDC2) & 0x20) != 0); - while ( (inb(IO_GDC2) & 0x20) == 0); -} - -static int check_gdc_clock(void) -{ - if ((inb(IO_SYSPORT) & 0x80) == 0){ - return _5MHZ; - } else { - return _2_5MHZ; - } -} - -static void initialize_gdc(unsigned int mode) -{ - /* start 30line initialize */ - int m_mode,s_mode,gdc_clock; - gdc_clock = check_gdc_clock(); - - if (mode == T25_G400){ - m_mode = _25L; - }else{ - m_mode = _30L; - } - - s_mode = 2*mode+gdc_clock; - - gdc_INFO = m_mode; - - 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[m_mode][GDC_CR]); - master_gdc_word_prm(((master_param[m_mode][GDC_HFP] << 10) - + (master_param[m_mode][GDC_VS] << 5) - + master_param[m_mode][GDC_HS])); - master_gdc_prm(master_param[m_mode][GDC_HBP]); - master_gdc_prm(master_param[m_mode][GDC_VFP]); - master_gdc_word_prm(((master_param[m_mode][GDC_VBP] << 10) - + (master_param[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[s_mode][GDC_CR]); - gdc_word_prm((slave_param[s_mode][GDC_HFP] << 10) - + (slave_param[s_mode][GDC_VS] << 5) - + (slave_param[s_mode][GDC_HS])); - gdc_prm(slave_param[s_mode][GDC_HBP]); - gdc_prm(slave_param[s_mode][GDC_VFP]); - gdc_word_prm((slave_param[s_mode][GDC_VBP] << 10) - + (slave_param[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[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(_GDC_STOP); - - gdc_wait_vsync(); - gdc_wait_vsync(); - gdc_wait_vsync(); - - master_gdc_cmd(_GDC_START); -} - -/* entry points */ - -static int -gdc_nop(void) -{ - return 0; -} - -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 (!init_done) - return 1; - - 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]; - return 0; - } - } - return 1; -} - -/* - * 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) -{ - video_info_t buf; - int i; - - if (!init_done) - return -1; - - 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, &buf)) - continue; - return bios_vmode[i].vi_mode; - } - return -1; -} - -/* - * 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, 1); - - mode = map_gen_mode_num(adp->va_type, - adp->va_flags & V_ADP_COLOR, mode); - if (gdc_get_info(adp, mode, &info)) - return 1; - -#ifdef LINE30 - switch (scp->mode) { - case M_PC98_80x25: /* VGA TEXT MODES */ - initialize_gdc(T25_G400); - break; - case M_PC98_80x30: - initialize_gdc(T30_G400); - break; - default: - break; - } -#endif - - adp->va_mode = mode; - adp->va_mode_flags = info.vi_flags; - 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; - } - - /* 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 1; -} - -/* - * load_state(): - * Set video card registers at once. - */ -static int -gdc_load_state(video_adapter_t *adp, void *p) -{ - return 1; -} - -/* - * 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) -{ - video_info_t info; - u_int16_t off; - int s; - - if (!init_done) - return 1; - - (*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info); - if (info.vi_flags & V_INFO_GRAPHICS) - return 1; - - 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 / info.vi_width; - *col = off % 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) -{ - video_info_t info; - u_int16_t off; - int s; - - if (!init_done) - return 1; - - if ((col == -1) && (row == -1)) { - off = -1; - } else { - (*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info); - if (info.vi_flags & V_INFO_GRAPHICS) - return 1; - off = row*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; - - start = celsize - (base + height); - end = celsize - base - 1; - /* - * 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)) - --end; - - 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 ? 0x20 : 0) /* blink on/off */ - | (start & 0x1f)); /* start line */ - splx(s); - - return 1; -} - -static void -dump_buffer(u_char *buf, size_t len) -{ - int i; - - for(i = 0; i < len;) { - printf("%02x ", buf[i]); - if ((++i % 16) == 0) - printf("\n"); - } -} - -/* - * mmap(): - * Mmap frame buffer. - */ -static int -gdc_mmap(video_adapter_t *adp, vm_offset_t offset) -{ - if (offset > 0x48000 - PAGE_SIZE) - return -1; - return i386_btop((VIDEO_BUF_BASE + offset)); -} - -/* - * 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) -{ - video_info_t info; - int i; - - if (!init_done) - return 1; - - 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; -} - -static int -gdc_err(video_adapter_t *adp, ...) -{ - return 0; -} - -#endif /* NGDC > 0 */ diff --git a/sys/pc98/pc98/pc98kbd.c b/sys/pc98/pc98/pc98kbd.c deleted file mode 100644 index 668ae9d8ae43..000000000000 --- a/sys/pc98/pc98/pc98kbd.c +++ /dev/null @@ -1,1009 +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. - * - * $Id: pc98kbd.c,v 1.3 1999/01/19 12:41:26 kato Exp $ - */ - -#include "pckbd.h" -#include "opt_kbd.h" -#include "opt_devfs.h" - -#if NPCKBD > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/proc.h> -#include <sys/tty.h> -#include <sys/fcntl.h> -#include <sys/bus.h> -#include <sys/malloc.h> - -#include <machine/resource.h> - -#include <dev/kbd/kbdreg.h> - -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> - -#ifdef __i386__ -#include <i386/isa/isa_device.h> -#endif - -#define DRIVER_NAME "pckbd" - -/* device configuration flags */ -#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */ - -/* some macros */ -#define PC98KBD_UNIT(dev) minor(dev) -#define PC98KBD_MKMINOR(unit) (unit) - -/* cdev driver declaration */ - -typedef struct pckbd_softc { - short flags; -#define PC98KBD_ATTACHED (1 << 0) - keyboard_t *kbd; -#ifdef KBD_INSTALL_CDEV - genkbd_softc_t gensc; -#endif -} pckbd_softc_t; - -#define PC98KBD_SOFTC(unit) pckbd_softc[(unit)] - -static pckbd_softc_t *pckbd_softc[NPCKBD]; - -static int pckbdprobe(struct isa_device *dev); -static int pckbdattach(struct isa_device *dev); - -static ointhand2_t pckbd_isa_intr; - -/* driver declaration for isa_devtab_tty[] */ -struct isa_driver pckbddriver = { - pckbdprobe, - pckbdattach, - DRIVER_NAME, - 0, -}; - -static int pckbd_probe_unit(int unit, pckbd_softc_t *sc, - int port, int irq, int flags); -static int pckbd_attach_unit(int unit, pckbd_softc_t *sc); -static timeout_t pckbd_timeout; - -#ifdef KBD_INSTALL_CDEV - -static d_open_t pckbdopen; -static d_close_t pckbdclose; -static d_read_t pckbdread; -static d_ioctl_t pckbdioctl; -static d_poll_t pckbdpoll; - -static struct cdevsw pckbd_cdevsw = { - pckbdopen, pckbdclose, pckbdread, nowrite, - pckbdioctl, nostop, nullreset, nodevtotty, - pckbdpoll, nommap, NULL, DRIVER_NAME, - NULL, -1, -}; - -#endif /* KBD_INSTALL_CDEV */ - -static int -pckbdprobe(struct isa_device *dev) -{ - pckbd_softc_t *sc; - int error; - - if (dev->id_unit >= sizeof(pckbd_softc)/sizeof(pckbd_softc[0])) - return 0; - sc = pckbd_softc[dev->id_unit]; - if (sc == NULL) { - sc = pckbd_softc[dev->id_unit] - = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) - return 0; - bzero(sc, sizeof(*sc)); - } - - /* try to find a keyboard */ - error = pckbd_probe_unit(dev->id_unit, sc, dev->id_iobase, - dev->id_irq, dev->id_flags); - if (error) - return 0; - - /* declare our interrupt handler */ - dev->id_ointr = pckbd_isa_intr; - - return IO_KBDSIZE; -} - -static int -pckbdattach(struct isa_device *dev) -{ - pckbd_softc_t *sc; - - if (dev->id_unit >= sizeof(pckbd_softc)/sizeof(pckbd_softc[0])) - return 0; - sc = pckbd_softc[dev->id_unit]; - if (sc == NULL) - return 0; - - return ((pckbd_attach_unit(dev->id_unit, sc)) ? 0 : 1); -} - -static void -pckbd_isa_intr(int unit) -{ - keyboard_t *kbd; - - kbd = pckbd_softc[unit]->kbd; - (*kbdsw[kbd->kb_index]->intr)(kbd); -} - -static int -pckbd_probe_unit(int unit, pckbd_softc_t *sc, int port, int irq, int flags) -{ - keyboard_switch_t *sw; - int args[2]; - - if (sc->flags & PC98KBD_ATTACHED) - return 0; - - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - - args[0] = port; - args[1] = irq; - return (*sw->probe)(unit, &sc->kbd, args, flags); -} - -static int -pckbd_attach_unit(int unit, pckbd_softc_t *sc) -{ - keyboard_switch_t *sw; - int error; - - if (sc->flags & PC98KBD_ATTACHED) - return 0; - - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - - /* reset, initialize and enable the device */ - error = (*sw->init)(sc->kbd); - if (error) - return ENXIO; - (*sw->enable)(sc->kbd); - -#ifdef KBD_INSTALL_CDEV - /* attach a virtual keyboard cdev */ - error = kbd_attach(makedev(0, PC98KBD_MKMINOR(unit)), sc->kbd, - &pckbd_cdevsw); - 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(sc->kbd); - - if (bootverbose) - (*sw->diag)(sc->kbd, bootverbose); - - sc->flags |= PC98KBD_ATTACHED; - 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); - } - splx(s); - timeout(pckbd_timeout, arg, hz/10); -} - -/* cdev driver functions */ - -#ifdef KBD_INSTALL_CDEV - -static int -pckbdopen(dev_t dev, int flag, int mode, struct proc *p) -{ - pckbd_softc_t *sc; - int unit; - - unit = PC98KBD_UNIT(dev); - if ((unit >= NPCKBD) || ((sc = PC98KBD_SOFTC(unit)) == NULL)) - return ENXIO; - if (mode & (FWRITE | O_CREAT | O_APPEND | O_TRUNC)) - return ENODEV; - - /* FIXME: set the initial input mode (K_XLATE?) and lock state? */ - return genkbdopen(&sc->gensc, sc->kbd, flag, mode, p); -} - -static int -pckbdclose(dev_t dev, int flag, int mode, struct proc *p) -{ - pckbd_softc_t *sc; - - sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev)); - return genkbdclose(&sc->gensc, sc->kbd, flag, mode, p); -} - -static int -pckbdread(dev_t dev, struct uio *uio, int flag) -{ - pckbd_softc_t *sc; - - sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev)); - return genkbdread(&sc->gensc, sc->kbd, uio, flag); -} - -static int -pckbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) -{ - pckbd_softc_t *sc; - - sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev)); - return genkbdioctl(&sc->gensc, sc->kbd, cmd, arg, flag, p); -} - -static int -pckbdpoll(dev_t dev, int event, struct proc *p) -{ - pckbd_softc_t *sc; - - sc = PC98KBD_SOFTC(PC98KBD_UNIT(dev)); - return genkbdpoll(&sc->gensc, sc->kbd, event, p); -} - -#endif /* KBD_INSTALL_CDEV */ - -/* LOW-LEVEL */ - -#include <machine/limits.h> -#include <machine/console.h> -#include <machine/clock.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; - -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, - 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; - KBDC kbdc; - int arg[2]; - struct isa_device *dev; - - /* XXX: a kludge to obtain the device configuration flags */ - dev = find_isadev(isa_devtab_tty, &pckbddriver, 0); - if (dev != NULL) - flags |= dev->id_flags; - - /* probe the default keyboard */ - arg[0] = -1; - arg[1] = -1; - if (pckbd_probe(PC98KBD_DEFAULT, &kbd, arg, flags)) - return 0; - - /* initialize it */ - kbdc = ((pckbd_state_t *)kbd->kb_data)->kbdc; - if (!(flags & KB_CONF_PROBE_ONLY) && !KBD_IS_PROBED(kbd)) { - if (KBD_HAS_DEVICE(kbd) - && init_keyboard(kbdc, &kbd->kb_type, flags) - && (flags & KB_CONF_FAIL_IF_NO_KBD)) - return 0; - KBD_INIT_DONE(kbd); - } - - /* and register */ - if (!KBD_IS_CONFIGURED(kbd)) { - if (kbd_register(kbd) < 0) - return 0; - KBD_CONFIG_DONE(kbd); - } - - return 1; /* return the number of found keyboards */ -} - -/* low-level functions */ - -/* initialize the keyboard_t structure and try to detect a keyboard */ -static int -pckbd_probe(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; - KBDC kbdc; - int *data = (int *)arg; - - if (unit != PC98KBD_DEFAULT) - return ENXIO; - - *kbdp = kbd = &default_kbd; - if (KBD_IS_PROBED(kbd)) - return 0; - state = &default_kbd_state; - keymap = &default_keymap; - accmap = &default_accentmap; - fkeymap = default_fkeytab; - fkeymap_size = sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); - - state->kbdc = kbdc = kbdc_open(data[0]); - if (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(kbdc, flags)) { - 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); - return 0; -} - -/* reset and initialize the device */ -static int -pckbd_init(keyboard_t *kbd) -{ - KBDC kbdc; - - if ((kbd == NULL) || !KBD_IS_PROBED(kbd)) - return ENXIO; /* shouldn't happen */ - kbdc = ((pckbd_state_t *)kbd->kb_data)->kbdc; - if (kbdc == NULL) - return ENXIO; /* shouldn't happen */ - - if (!KBD_IS_INITIALIZED(kbd)) { - if (KBD_HAS_DEVICE(kbd) - && init_keyboard(kbdc, &kbd->kb_type, kbd->kb_config) - && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) - return ENXIO; - pckbd_ioctl(kbd, KDSETLED, - (caddr_t)&((pckbd_state_t *)(kbd->kb_data))->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) -{ - 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); - 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; - } - - /* 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); - } - /* FALL THROUGH */ - 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 */ - 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; - /* FALL THROUGH */ - 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; -} - -/* 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[NPCKBD] = { { 0 }, }; - -/* associate a port number with a KBDC */ - -static KBDC -kbdc_open(int port) -{ - if (port <= 0) - port = IO_KBD; - - if (NPCKBD) { - /* PC-98 has only one keyboard I/F */ - kbdc_softc[0].port = port; - kbdc_softc[0].lock = FALSE; - return (KBDC)&kbdc_softc[0]; - } - return NULL; /* You didn't include sc driver in your config file */ -} - -/* 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 */ -} - -#endif /* NPCKBD > 0 */ diff --git a/sys/pc98/pc98/pcaudio.c b/sys/pc98/pc98/pcaudio.c index 05ba0161b6aa..abffc8c418ef 100644 --- a/sys/pc98/pc98/pcaudio.c +++ b/sys/pc98/pc98/pcaudio.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcaudio.c,v 1.19 1998/12/14 08:58:56 kato Exp $ + * $Id: pcaudio.c,v 1.43 1998/09/15 18:16:37 sos Exp $ */ #include "pca.h" @@ -52,6 +52,11 @@ #include <i386/isa/isa_device.h> #include <i386/isa/timerreg.h> +#define DSP_ULAW_NOT_WANTED +#include <i386/isa/sound/ulaw.h> +#define LINEAR_ALAW_NOT_WANTED +#include <i386/isa/sound/alaw.h> + #ifdef DEVFS #include <sys/devfsext.h> #endif /* DEVFS */ @@ -84,44 +89,6 @@ static char buffer2[BUF_SIZE]; static char buffer3[BUF_SIZE]; static char volume_table[256]; -#define DSP_ULAW_NOT_WANTED -#include <i386/isa/snd/ulaw.h> - -static unsigned char alaw_linear[] = { - 45, 214, 122, 133, 0, 255, 107, 149, - 86, 171, 126, 129, 0, 255, 117, 138, - 13, 246, 120, 135, 0, 255, 99, 157, - 70, 187, 124, 131, 0, 255, 113, 142, - 61, 198, 123, 132, 0, 255, 111, 145, - 94, 163, 127, 128, 0, 255, 119, 136, - 29, 230, 121, 134, 0, 255, 103, 153, - 78, 179, 125, 130, 0, 255, 115, 140, - 37, 222, 122, 133, 0, 255, 105, 151, - 82, 175, 126, 129, 0, 255, 116, 139, - 5, 254, 120, 135, 0, 255, 97, 159, - 66, 191, 124, 131, 0, 255, 112, 143, - 53, 206, 123, 132, 0, 255, 109, 147, - 90, 167, 127, 128, 0, 255, 118, 137, - 21, 238, 121, 134, 0, 255, 101, 155, - 74, 183, 125, 130, 0, 255, 114, 141, - 49, 210, 123, 133, 0, 255, 108, 148, - 88, 169, 127, 129, 0, 255, 118, 138, - 17, 242, 121, 135, 0, 255, 100, 156, - 72, 185, 125, 131, 0, 255, 114, 142, - 64, 194, 124, 132, 0, 255, 112, 144, - 96, 161, 128, 128, 1, 255, 120, 136, - 33, 226, 122, 134, 0, 255, 104, 152, - 80, 177, 126, 130, 0, 255, 116, 140, - 41, 218, 122, 133, 0, 255, 106, 150, - 84, 173, 126, 129, 0, 255, 117, 139, - 9, 250, 120, 135, 0, 255, 98, 158, - 68, 189, 124, 131, 0, 255, 113, 143, - 57, 202, 123, 132, 0, 255, 110, 146, - 92, 165, 127, 128, 0, 255, 119, 137, - 25, 234, 121, 134, 0, 255, 102, 154, - 76, 181, 125, 130, 0, 255, 115, 141, -}; - #ifdef DEVFS static void *pca_devfs_token; static void *pcac_devfs_token; @@ -198,7 +165,7 @@ pca_init(void) pca_status.buf[1] = (unsigned char *)&buffer2[0]; pca_status.buf[2] = (unsigned char *)&buffer3[0]; pca_status.buffer = pca_status.buf[0]; - pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[2] = 0; + pca_status.in_use[0] = pca_status.in_use[1] = pca_status.in_use[3] = 0; pca_status.current = 0; pca_status.sample_rate = SAMPLE_RATE; pca_status.scale = (pca_status.sample_rate << 8) / INTERRUPT_RATE; @@ -602,4 +569,5 @@ static void pca_drvinit(void *unused) SYSINIT(pcadev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,pca_drvinit,NULL) + #endif diff --git a/sys/pc98/pc98/scvidctl.c b/sys/pc98/pc98/scvidctl.c deleted file mode 100644 index 77eba9811ce8..000000000000 --- a/sys/pc98/pc98/scvidctl.c +++ /dev/null @@ -1,582 +0,0 @@ -/*- - * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> - * 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 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. - * - * $Id: scvidctl.c,v 1.1 1998/12/16 14:57:37 kato Exp $ - */ - -#include "sc.h" -#include "opt_syscons.h" - -#if NSC > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/signalvar.h> -#include <sys/tty.h> -#include <sys/kernel.h> - -#include <machine/apm_bios.h> -#include <machine/console.h> - -#include <dev/fb/fbreg.h> - -#include <pc98/pc98/syscons.h> - -/* for compatibility with previous versions */ -typedef struct old_video_adapter { - int va_index; - int va_type; - int va_flags; -#define V_ADP_COLOR (1<<0) -#define V_ADP_MODECHANGE (1<<1) -#define V_ADP_STATESAVE (1<<2) -#define V_ADP_STATELOAD (1<<3) -#define V_ADP_FONT (1<<4) -#define V_ADP_PALETTE (1<<5) -#define V_ADP_BORDER (1<<6) -#define V_ADP_VESA (1<<7) - int va_crtc_addr; - u_int va_window; /* virtual address */ - size_t va_window_size; - size_t va_window_gran; - u_int va_buffer; /* virtual address */ - size_t va_buffer_size; - int va_initial_mode; - int va_initial_bios_mode; - int va_mode; -} old_video_adapter_t; - -#define OLD_CONS_ADPINFO _IOWR('c', 101, old_video_adapter_t) - -/* variables */ -extern scr_stat *cur_console; -extern int fonts_loaded; -extern int sc_history_size; -extern u_char palette[]; - -int -sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize, - int fontsize) -{ - video_info_t info; - int error; - int s; - int i; - - if ((*vidsw[scp->ad]->get_info)(scp->adp, mode, &info)) - return ENODEV; - - /* adjust argument values */ - if (fontsize <= 0) - fontsize = info.vi_cheight; - if (fontsize < 14) { - fontsize = 8; - if (!(fonts_loaded & FONT_8)) - return EINVAL; - } else if (fontsize >= 16) { - fontsize = 16; - if (!(fonts_loaded & FONT_16)) - return EINVAL; - } else { - fontsize = 14; - if (!(fonts_loaded & FONT_14)) - return EINVAL; - } - if ((xsize <= 0) || (xsize > info.vi_width)) - xsize = info.vi_width; - if ((ysize <= 0) || (ysize > info.vi_height)) - ysize = info.vi_height; - - /* stop screen saver, etc */ - s = spltty(); - if ((error = sc_clean_up(scp))) { - splx(s); - return error; - } - - /* set up scp */ - if (scp->history != NULL) - i = imax(scp->history_size / scp->xsize - - imax(sc_history_size, scp->ysize), 0); - else - i = 0; - /* - * This is a kludge to fend off scrn_update() while we - * muck around with scp. XXX - */ - scp->status |= UNKNOWN_MODE; - scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE); - scp->mode = mode; - scp->font_size = fontsize; - scp->xsize = xsize; - scp->ysize = ysize; - scp->xoff = 0; - scp->yoff = 0; - scp->xpixel = scp->xsize*8; - scp->ypixel = scp->ysize*fontsize; - - /* allocate buffers */ - sc_alloc_scr_buffer(scp, TRUE, TRUE); - if (ISMOUSEAVAIL(scp->adp->va_flags)) - sc_alloc_cut_buffer(scp, FALSE); - sc_alloc_history_buffer(scp, sc_history_size, i, FALSE); - splx(s); - - if (scp == cur_console) - set_mode(scp); - scp->status &= ~UNKNOWN_MODE; - - if (tp == NULL) - return 0; - if (tp->t_winsize.ws_col != scp->xsize - || tp->t_winsize.ws_row != scp->ysize) { - tp->t_winsize.ws_col = scp->xsize; - tp->t_winsize.ws_row = scp->ysize; - pgsignal(tp->t_pgrp, SIGWINCH, 1); - } - - return 0; -} - -int -sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) -{ - video_info_t info; - int error; - int s; - - if ((*vidsw[scp->ad]->get_info)(scp->adp, mode, &info)) - return ENODEV; - - /* stop screen saver, etc */ - s = spltty(); - if ((error = sc_clean_up(scp))) { - splx(s); - return error; - } - - /* set up scp */ - scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE); - scp->status &= ~PIXEL_MODE; - scp->mode = mode; - scp->xoff = 0; - scp->yoff = 0; - scp->xpixel = info.vi_width; - scp->ypixel = info.vi_height; - scp->xsize = info.vi_width/8; - scp->ysize = info.vi_height/info.vi_cheight; - scp->font_size = FONT_NONE; - /* move the mouse cursor at the center of the screen */ - sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); - splx(s); - - if (scp == cur_console) - set_mode(scp); - /* clear_graphics();*/ - scp->status &= ~UNKNOWN_MODE; - - if (tp == NULL) - return 0; - if (tp->t_winsize.ws_xpixel != scp->xpixel - || tp->t_winsize.ws_ypixel != scp->ypixel) { - tp->t_winsize.ws_xpixel = scp->xpixel; - tp->t_winsize.ws_ypixel = scp->ypixel; - pgsignal(tp->t_pgrp, SIGWINCH, 1); - } - - return 0; -} - -int -sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, - int fontsize) -{ - video_info_t info; - int error; - int s; - int i; - - if ((*vidsw[scp->ad]->get_info)(scp->adp, scp->mode, &info)) - return ENODEV; /* this shouldn't happen */ - -#ifdef SC_VIDEO_DEBUG - if (scp->scr_buf != NULL) { - printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n", - scp->mode, xsize, ysize, fontsize); - } -#endif - - /* adjust argument values */ - if ((fontsize <= 0) || (fontsize == FONT_NONE)) - fontsize = info.vi_cheight; - if (fontsize < 14) { - fontsize = 8; - if (!(fonts_loaded & FONT_8)) - return EINVAL; - } else if (fontsize >= 16) { - fontsize = 16; - if (!(fonts_loaded & FONT_16)) - return EINVAL; - } else { - fontsize = 14; - if (!(fonts_loaded & FONT_14)) - return EINVAL; - } - if (xsize <= 0) - xsize = info.vi_width/8; - if (ysize <= 0) - ysize = info.vi_height/fontsize; - -#ifdef SC_VIDEO_DEBUG - if (scp->scr_buf != NULL) { - printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n", - scp->mode, xsize, ysize, fontsize); - printf("set_pixel_mode(): window:%x, %dx%d, xoff:%d, yoff:%d\n", - scp->adp->va_window, info.vi_width, info.vi_height, - (info.vi_width/8 - xsize)/2, - (info.vi_height/fontsize - ysize)/2); - } -#endif - - if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize)) - return EINVAL; - - /* only 16 color, 4 plane modes are supported XXX */ - if ((info.vi_depth != 4) || (info.vi_planes != 4)) - return ENODEV; - - /* - * set_pixel_mode() currently does not support video modes whose - * memory size is larger than 64K. Because such modes require - * bank switching to access the entire screen. XXX - */ - if (info.vi_width*info.vi_height/8 > info.vi_window_size) - return ENODEV; - - /* stop screen saver, etc */ - s = spltty(); - if ((error = sc_clean_up(scp))) { - splx(s); - return error; - } - - /* set up scp */ - if (scp->history != NULL) - i = imax(scp->history_size / scp->xsize - - imax(sc_history_size, scp->ysize), 0); - else - i = 0; - scp->status |= (UNKNOWN_MODE | PIXEL_MODE); - scp->status &= ~(GRAPHICS_MODE | MOUSE_ENABLED); - scp->xsize = xsize; - scp->ysize = ysize; - scp->font_size = fontsize; - scp->xoff = (scp->xpixel/8 - xsize)/2; - scp->yoff = (scp->ypixel/fontsize - ysize)/2; - - /* allocate buffers */ - sc_alloc_scr_buffer(scp, TRUE, TRUE); - if (ISMOUSEAVAIL(scp->adp->va_flags)) - sc_alloc_cut_buffer(scp, FALSE); - sc_alloc_history_buffer(scp, sc_history_size, i, FALSE); - splx(s); - - if (scp == cur_console) - set_border(scp, scp->border); - - scp->status &= ~UNKNOWN_MODE; - -#ifdef SC_VIDEO_DEBUG - printf("set_pixel_mode(): status:%x\n", scp->status); -#endif - - if (tp == NULL) - return 0; - if (tp->t_winsize.ws_col != scp->xsize - || tp->t_winsize.ws_row != scp->ysize) { - tp->t_winsize.ws_col = scp->xsize; - tp->t_winsize.ws_row = scp->ysize; - pgsignal(tp->t_pgrp, SIGWINCH, 1); - } - - return 0; -} - -int -sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) -{ - scr_stat *scp; - int error; - int s; - - scp = sc_get_scr_stat(tp->t_dev); - - switch (cmd) { - - case CONS_CURRENT: /* get current adapter type */ - if (scp->adp == NULL) - return ENODEV; - *(int *)data = scp->adp->va_type; - return 0; - - case CONS_CURRENTADP: /* get current adapter index */ - *(int *)data = scp->ad; - return 0; - - case OLD_CONS_ADPINFO: /* adapter information */ - if (scp->adp == NULL) - return ENODEV; - ((old_video_adapter_t *)data)->va_index = scp->adp->va_index; - ((old_video_adapter_t *)data)->va_type = scp->adp->va_type; - ((old_video_adapter_t *)data)->va_flags = scp->adp->va_flags; - ((old_video_adapter_t *)data)->va_crtc_addr = scp->adp->va_crtc_addr; - ((old_video_adapter_t *)data)->va_window = scp->adp->va_window; - ((old_video_adapter_t *)data)->va_window_size - = scp->adp->va_window_size; - ((old_video_adapter_t *)data)->va_window_gran - = scp->adp->va_window_gran; - ((old_video_adapter_t *)data)->va_buffer = scp->adp->va_buffer; - ((old_video_adapter_t *)data)->va_buffer_size - = scp->adp->va_buffer_size; - ((old_video_adapter_t *)data)->va_mode = scp->adp->va_mode; - ((old_video_adapter_t *)data)->va_initial_mode - = scp->adp->va_initial_mode; - ((old_video_adapter_t *)data)->va_initial_bios_mode - = scp->adp->va_initial_bios_mode; - return 0; - - case CONS_ADPINFO: /* adapter information */ - if (scp->adp == NULL) - return ENODEV; - ((video_adapter_info_t *)data)->va_index = scp->adp->va_index; - ((video_adapter_info_t *)data)->va_type = scp->adp->va_type; - bcopy(scp->adp->va_name, ((video_adapter_info_t *)data)->va_name, - imin(strlen(scp->adp->va_name) + 1, - sizeof(((video_adapter_info_t *)data)->va_name))); - ((video_adapter_info_t *)data)->va_unit = scp->adp->va_unit; - ((video_adapter_info_t *)data)->va_flags = scp->adp->va_flags; - ((video_adapter_info_t *)data)->va_io_base = scp->adp->va_io_base; - ((video_adapter_info_t *)data)->va_io_size = scp->adp->va_io_size; - ((video_adapter_info_t *)data)->va_crtc_addr = scp->adp->va_crtc_addr; - ((video_adapter_info_t *)data)->va_mem_base = scp->adp->va_mem_base; - ((video_adapter_info_t *)data)->va_mem_size = scp->adp->va_mem_size; - ((video_adapter_info_t *)data)->va_window = scp->adp->va_window; - ((video_adapter_info_t *)data)->va_window_size - = scp->adp->va_window_size; - ((video_adapter_info_t *)data)->va_window_gran - = scp->adp->va_window_gran; - ((video_adapter_info_t *)data)->va_buffer = scp->adp->va_buffer; - ((video_adapter_info_t *)data)->va_buffer_size - = scp->adp->va_buffer_size; - ((video_adapter_info_t *)data)->va_mode = scp->adp->va_mode; - ((video_adapter_info_t *)data)->va_mode_flags = scp->adp->va_mode_flags; - ((video_adapter_info_t *)data)->va_initial_mode - = scp->adp->va_initial_mode; - ((video_adapter_info_t *)data)->va_initial_bios_mode - = scp->adp->va_initial_bios_mode; - return 0; - - case CONS_GET: /* get current video mode */ - *(int *)data = scp->mode; - return 0; - - case CONS_MODEINFO: /* get mode information */ - return ((*vidsw[scp->ad]->get_info)(scp->adp, - ((video_info_t *)data)->vi_mode, (video_info_t *)data) - ? ENODEV : 0); - - case CONS_FINDMODE: /* find a matching video mode */ - return ((*vidsw[scp->ad]->query_mode)(scp->adp, (video_info_t *)data) - ? ENODEV : 0); - - case CONS_SETWINORG: - return ((*vidsw[scp->ad]->set_win_org)(scp->adp, *(u_int *)data) - ? ENODEV : 0); - - /* generic text modes */ - case SW_TEXT_80x25: case SW_TEXT_80x30: - case SW_TEXT_80x43: case SW_TEXT_80x50: - case SW_TEXT_80x60: - /* FALL THROUGH */ - - /* VGA TEXT MODES */ - case SW_VGA_C40x25: - case SW_VGA_C80x25: case SW_VGA_M80x25: - case SW_VGA_C80x30: case SW_VGA_M80x30: - case SW_VGA_C80x50: case SW_VGA_M80x50: - case SW_VGA_C80x60: case SW_VGA_M80x60: - case SW_B40x25: case SW_C40x25: - case SW_B80x25: case SW_C80x25: - case SW_ENH_B40x25: case SW_ENH_C40x25: - case SW_ENH_B80x25: case SW_ENH_C80x25: - case SW_ENH_B80x43: case SW_ENH_C80x43: - case SW_EGAMONO80x25: - -#ifdef PC98 - /* PC98 TEXT MODES */ - case SW_PC98_80x25: - case SW_PC98_80x30: -#endif - if (!(scp->adp->va_flags & V_ADP_MODECHANGE)) - return ENODEV; - return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0); - - /* GRAPHICS MODES */ - case SW_BG320: case SW_BG640: - case SW_CG320: case SW_CG320_D: case SW_CG640_E: - case SW_CG640x350: case SW_ENH_CG640: - case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: - case SW_VGA_MODEX: - if (!(scp->adp->va_flags & V_ADP_MODECHANGE)) - return ENODEV; - return sc_set_graphics_mode(scp, tp, cmd & 0xff); - - case KDSETMODE: /* set current mode of this (virtual) console */ - switch (*(int *)data) { - case KD_TEXT: /* switch to TEXT (known) mode */ - /* - * If scp->mode is of graphics modes, we don't know which - * text mode to switch back to... - */ - if (scp->status & GRAPHICS_MODE) - return EINVAL; - /* restore fonts & palette ! */ -#if 0 - if (ISFONTAVAIL(scp->adp->va_flags) - && !(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) - /* - * FONT KLUDGE - * Don't load fonts for now... XXX - */ - if (fonts_loaded & FONT_8) - copy_font(scp, LOAD, 8, font_8); - if (fonts_loaded & FONT_14) - copy_font(scp, LOAD, 14, font_14); - if (fonts_loaded & FONT_16) - copy_font(scp, LOAD, 16, font_16); - } -#endif - load_palette(scp->adp, palette); - - /* move hardware cursor out of the way */ - (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, -1, -1); - - /* FALL THROUGH */ - - case KD_TEXT1: /* switch to TEXT (known) mode */ - /* - * If scp->mode is of graphics modes, we don't know which - * text/pixel mode to switch back to... - */ - if (scp->status & GRAPHICS_MODE) - return EINVAL; - s = spltty(); - if ((error = sc_clean_up(scp))) { - splx(s); - return error; - } -#ifndef PC98 - scp->status |= UNKNOWN_MODE; - splx(s); - /* no restore fonts & palette */ - if (scp == cur_console) - set_mode(scp); - sc_clear_screen(scp); - scp->status &= ~UNKNOWN_MODE; -#else /* PC98 */ - scp->status &= ~UNKNOWN_MODE; - /* no restore fonts & palette */ - if (scp == cur_console) - set_mode(scp); - sc_clear_screen(scp); - splx(s); -#endif /* PC98 */ - return 0; - - case KD_PIXEL: /* pixel (raster) display */ - if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) - return EINVAL; - if (scp->status & GRAPHICS_MODE) - return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, - scp->font_size); - s = spltty(); - if ((error = sc_clean_up(scp))) { - splx(s); - return error; - } - scp->status |= (UNKNOWN_MODE | PIXEL_MODE); - splx(s); - if (scp == cur_console) { - set_mode(scp); - load_palette(scp->adp, palette); - } - sc_clear_screen(scp); - scp->status &= ~UNKNOWN_MODE; - return 0; - - case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ - s = spltty(); - if ((error = sc_clean_up(scp))) { - splx(s); - return error; - } - scp->status |= UNKNOWN_MODE; - splx(s); -#ifdef PC98 - if (scp == cur_console) - set_mode(scp); -#endif - return 0; - - default: - return EINVAL; - } - /* NOT REACHED */ - - case KDRASTER: /* set pixel (raster) display mode */ - if (ISUNKNOWNSC(scp) || ISTEXTSC(scp)) - return ENODEV; - return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], - ((int *)data)[2]); - - case KDGETMODE: /* get current mode of this (virtual) console */ - /* - * From the user program's point of view, KD_PIXEL is the same - * as KD_TEXT... - */ - *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT; - return 0; - - case KDSBORDER: /* set border color of this (virtual) console */ - scp->border = *data; - if (scp == cur_console) - set_border(scp, scp->border); - return 0; - } - - return ENOIOCTL; -} - -#endif /* NSC > 0 */ diff --git a/sys/pc98/pc98/sio.c b/sys/pc98/pc98/sio.c index 97ac3ad3b384..abce135c8193 100644 --- a/sys/pc98/pc98/sio.c +++ b/sys/pc98/pc98/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.75 1999/01/16 11:42:16 kato Exp $ + * $Id: sio.c,v 1.66 1998/08/28 12:44:49 kato Exp $ */ #include "opt_comconsole.h" @@ -74,9 +74,9 @@ * * 1) config * options COM_MULTIPORT #if using MC16550II - * device sio0 at nec? port 0x30 tty irq 4 #internal - * device sio1 at nec? port 0xd2 tty irq 5 flags 0x101 #mc1 - * device sio2 at nec? port 0x8d2 tty flags 0x101 #mc2 + * device sio0 at nec? port 0x30 tty irq 4 vector siointr #internal + * device sio1 at nec? port 0xd2 tty irq 5 flags 0x101 vector siointr #mc1 + * device sio2 at nec? port 0x8d2 tty flags 0x101 vector siointr #mc2 * # ~~~~~iobase ~~multi port flag * # ~ master device is sio1 * 2) device @@ -103,36 +103,21 @@ * # options COM_MULTIPORT # support for MICROCORE MC16550II * ... comment-out this line, which will conflict with B98_01. * options "B98_01" # support for AIWA B98-01 - * device sio1 at nec? port 0x00d1 tty irq ? - * device sio2 at nec? port 0x00d5 tty irq ? + * device sio1 at nec? port 0x00d1 tty irq ? vector siointr + * device sio2 at nec? port 0x00d5 tty irq ? vector siointr * ... you can leave these lines `irq ?', irq will be autodetected. */ -/* - * Modified by Y.Takahashi of Kogakuin University. - */ - #ifdef PC98 -#define COM_IF_INTERNAL 0x00 -#define COM_IF_PC9861K_1 0x01 -#define COM_IF_PC9861K_2 0x02 -#define COM_IF_IND_SS_1 0x03 -#define COM_IF_IND_SS_2 0x04 -#define COM_IF_PIO9032B_1 0x05 -#define COM_IF_PIO9032B_2 0x06 -#define COM_IF_B98_01_1 0x07 -#define COM_IF_B98_01_2 0x08 -#define COM_IF_END1 COM_IF_B98_01_2 -#define COM_IF_RSA98 0x10 /* same as COM_IF_NS16550 */ -#define COM_IF_NS16550 0x11 -#define COM_IF_SECOND_CCU 0x12 /* same as COM_IF_NS16550 */ -#define COM_IF_MC16550II 0x13 -#define COM_IF_MCRS98 0x14 /* same as COM_IF_MC16550II */ -#define COM_IF_RSB3000 0x15 -#define COM_IF_RSB384 0x16 -#define COM_IF_MODEM_CARD 0x17 /* same as COM_IF_NS16550 */ -#define COM_IF_RSA98III 0x18 -#define COM_IF_ESP98 0x19 -#define COM_IF_END2 COM_IF_ESP98 +#define MC16550 0 +#define COM_IF_INTERNAL 1 +#if 0 +#define COM_IF_PC9861K 2 +#define COM_IF_PIO9032B 3 +#endif +#ifdef B98_01 +#undef COM_MULTIPORT /* COM_MULTIPORT will conflict with B98_01 */ +#define COM_IF_B98_01 4 +#endif /* B98_01 */ #endif /* PC98 */ #include <sys/param.h> @@ -154,33 +139,28 @@ #include <machine/clock.h> #include <machine/ipl.h> -#ifndef SMP -#include <machine/lock.h> -#endif #ifdef PC98 #include <pc98/pc98/pc98.h> #include <pc98/pc98/pc98_machdep.h> #include <i386/isa/icu.h> +#include <i386/isa/isa_device.h> +#include <pc98/pc98/sioreg.h> #include <i386/isa/ic/i8251.h> #else #include <i386/isa/isa.h> -#endif #include <i386/isa/isa_device.h> #include <i386/isa/sioreg.h> +#endif #include <i386/isa/intr_machdep.h> #ifdef COM_ESP #include <i386/isa/ic/esp.h> #endif #include <i386/isa/ic/ns16550.h> -#ifdef PC98 -#include <i386/isa/ic/rsa.h> -#endif #include "card.h" #if NCARD > 0 -#include <sys/module.h> #include <pccard/cardinfo.h> #include <pccard/slot.h> #endif @@ -236,11 +216,9 @@ #define COM_IIR_TXRDYBUG(dev) ((dev)->id_flags & COM_C_IIR_TXRDYBUG) #define COM_FIFOSIZE(dev) (((dev)->id_flags & 0xff000000) >> 24) -#ifdef PC98 -#define com_emr com_msr /* Extension mode register for RSB-2000/3000 */ -#else +#ifndef PC98 #define com_scr 7 /* scratch register for 16450-16550 (R/W) */ -#endif +#endif /* !PC98 */ /* * Input buffer watermarks. @@ -369,9 +347,6 @@ struct com_s { #endif Port_t int_id_port; Port_t iobase; -#ifdef PC98 - Port_t rsabase; /* iobase address of a I/O-DATA RSA board */ -#endif Port_t modem_ctl_port; Port_t line_status_port; Port_t modem_status_port; @@ -401,18 +376,6 @@ struct com_s { * Ping-pong input buffers. The extra factor of 2 in the sizes is * to allow for an error byte for each input byte. */ -#ifdef PC98 - u_long CE_INPUT_OFFSET; - u_char *ibuf1; - u_char *ibuf2; - - /* - * Data area for output buffers. Someday we should build the output - * buffer queue without copying data. - */ - u_char *obuf1; - u_char *obuf2; -#else #define CE_INPUT_OFFSET RS_IBUFSIZE u_char ibuf1[2 * RS_IBUFSIZE]; u_char ibuf2[2 * RS_IBUFSIZE]; @@ -423,7 +386,6 @@ struct com_s { */ u_char obuf1[256]; u_char obuf2[256]; -#endif #ifdef DEVFS void *devfs_token_ttyd; void *devfs_token_ttyl; @@ -442,7 +404,6 @@ static int sioattach __P((struct isa_device *dev)); static timeout_t siobusycheck; static timeout_t siodtrwakeup; static void comhardclose __P((struct com_s *com)); -static ointhand2_t siointr; static void siointr1 __P((struct com_s *com)); static int commctl __P((struct com_s *com, int bits, int how)); static int comparam __P((struct tty *tp, struct termios *t)); @@ -454,6 +415,9 @@ static timeout_t comwakeup; static void disc_optim __P((struct tty *tp, struct termios *t, struct com_s *com)); +#ifdef DSI_SOFT_MODEM +static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr)); +#endif /* DSI_SOFT_MODEM */ static char driver_name[] = "sio"; @@ -503,9 +467,28 @@ struct siodev { short if_type; short irq; Port_t cmd, sts, ctrl, mod; -}; + }; static int sysclock; - +static short port_table[5][3] = { + {0x30, 0xb1, 0xb9}, + {0x32, 0xb3, 0xbb}, + {0x32, 0xb3, 0xbb}, + {0x33, 0xb0, 0xb2}, + {0x35, 0xb0, 0xb2} + }; +#define PC98SIO_data_port(ch) port_table[0][ch] +#define PC98SIO_cmd_port(ch) port_table[1][ch] +#define PC98SIO_sts_port(ch) port_table[2][ch] +#define PC98SIO_in_modem_port(ch) port_table[3][ch] +#define PC98SIO_intr_ctrl_port(ch) port_table[4][ch] +#ifdef COM_IF_PIO9032B +#define IO_COM_PIO9032B_2 0x0b8 +#define IO_COM_PIO9032B_3 0x0ba +#endif /* COM_IF_PIO9032B */ +#ifdef COM_IF_B98_01 +#define IO_COM_B98_01_2 0x0d1 +#define IO_COM_B98_01_3 0x0d5 +#endif /* COM_IF_B98_01 */ #define COM_INT_DISABLE {int previpri; previpri=spltty(); #define COM_INT_ENABLE splx(previpri);} #define IEN_TxFLAG IEN_Tx @@ -514,8 +497,8 @@ static int sysclock; #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 +#define IS_8251(type) (type != MC16550) +#define IS_PC98IN(adr) (adr == 0x30) static void commint __P((dev_t dev)); static void com_tiocm_set __P((struct com_s *com, int msr)); @@ -539,9 +522,9 @@ static void pc98_i8251_set_cmd __P((struct com_s *com, int x)); static void pc98_i8251_or_cmd __P((struct com_s *com, int x)); static void pc98_i8251_clear_cmd __P((struct com_s *com, int x)); static void pc98_i8251_clear_or_cmd __P((struct com_s *com, int clr, int x)); -static int pc98_check_if_type __P((struct isa_device *dev, struct siodev *iod)); +static int pc98_check_if_type __P((int iobase, struct siodev *iod)); static void pc98_check_sysclock __P((void)); -static int pc98_set_ioport __P((struct com_s *com, int id_flags)); +static int pc98_set_ioport __P((struct com_s *com, int io_base)); #define com_int_Tx_disable(com) \ pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP) @@ -560,7 +543,7 @@ static int pc98_set_ioport __P((struct com_s *com, int id_flags)); #define com_send_break_off(com) \ pc98_i8251_clear_cmd(com,CMD8251_SBRK) -static struct speedtab pc98speedtab[] = { /* internal RS232C interface */ +struct speedtab pc98speedtab[] = { /* internal RS232C interface */ 0, 0, 50, 50, 75, 75, @@ -574,23 +557,16 @@ static struct speedtab pc98speedtab[] = { /* internal RS232C interface */ 9600, 9600, 19200, 19200, 38400, 38400, - 51200, 51200, 76800, 76800, 20800, 20800, - 31200, 31200, 41600, 41600, + 15600, 15600, + 31200, 31200, 62400, 62400, -1, -1 }; -static struct speedtab pc98fast_speedtab[] = { - 9600, 0x80 | COMBRD(9600), - 19200, 0x80 | COMBRD(19200), - 38400, 0x80 | COMBRD(38400), - 57600, 0x80 | COMBRD(57600), - 115200, 0x80 | COMBRD(115200), - -1, -1 -}; -static struct speedtab comspeedtab_pio9032b[] = { +#ifdef COM_IF_PIO9032B +struct speedtab comspeedtab_pio9032b[] = { 300, 6, 600, 5, 1200, 4, @@ -601,82 +577,26 @@ static struct speedtab comspeedtab_pio9032b[] = { 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_mc16550[] = { - 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, +#endif + +#ifdef COM_IF_B98_01 +struct speedtab comspeedtab_b98_01[] = { + 0, 0, + 75, 15, + 150, 14, + 300, 13, + 600, 12, + 1200, 11, + 2400, 10, + 4800, 9, + 9600, 8, + 19200, 7, + 38400, 6, + 76800, 5, + 153600, 4, -1, -1 }; -static struct speedtab comspeedtab_rsb384[] = { - 300, 3840, - 600, 1920, - 1200, 960, - 2400, 480, - 4800, 240, - 9600, 120, - 19200, 60, - 38400, 30, - 57600, 20, - 115200, 10, - 128000, 9, - 144000, 8, - 192000, 6, - 230400, 5, - 288000, 4, - 384000, 3, - 576000, 2, - 1152000, 1, - -1, -1 -}; -static struct speedtab comspeedtab_rsa[] = { - { 0, 0 }, - { 50, COMBRD_RSA(50) }, - { 75, COMBRD_RSA(75) }, - { 110, COMBRD_RSA(110) }, - { 134, COMBRD_RSA(134) }, - { 150, COMBRD_RSA(150) }, - { 200, COMBRD_RSA(200) }, - { 300, COMBRD_RSA(300) }, - { 600, COMBRD_RSA(600) }, - { 1200, COMBRD_RSA(1200) }, - { 1800, COMBRD_RSA(1800) }, - { 2400, COMBRD_RSA(2400) }, - { 4800, COMBRD_RSA(4800) }, - { 9600, COMBRD_RSA(9600) }, - { 19200, COMBRD_RSA(19200) }, - { 38400, COMBRD_RSA(38400) }, - { 57600, COMBRD_RSA(57600) }, - { 115200, COMBRD_RSA(115200) }, - { 230400, COMBRD_RSA(230400) }, - { 460800, COMBRD_RSA(460800) }, - { 921600, COMBRD_RSA(921600) }, - { -1, -1 } -}; +#endif #endif /* PC98 */ static struct speedtab comspeedtab[] = { @@ -701,100 +621,10 @@ static struct speedtab comspeedtab[] = { { -1, -1 } }; -#ifdef PC98 -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_mc16550, 1 }, - /* COM_IF_IND_SS_2 */ - { " (IND-SS)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xbb, -1}, - 3, comspeedtab_mc16550, 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]) - -struct { - char *name; - short irr_read; - short irr_write; - short port_shift; - short io_size; - struct speedtab *speedtab; -} if_16550a_type[] = { - /* COM_IF_RSA98 */ - { " (RSA-98)", -1, -1, 0, IO_COMSIZE, comspeedtab }, - /* COM_IF_NS16550 */ - { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, - /* COM_IF_SECOND_CCU */ - { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, - /* COM_IF_MC16550II */ - { " (MC16550II)", -1, 0x1000, 8, 1, comspeedtab_mc16550 }, - /* COM_IF_MCRS98 */ - { " (MC-RS98)", -1, 0x1000, 8, 1, comspeedtab_mc16550 }, - /* COM_IF_RSB3000 */ - { " (RSB-3000)", 0xbf, -1, 1, 1, comspeedtab_rsb384 }, - /* COM_IF_RSB384 */ - { " (RSB-384)", 0xbf, -1, 1, 1, comspeedtab_rsb384 }, - /* COM_IF_MODEM_CARD */ - { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, - /* COM_IF_RSA98III */ - { " (RSA-98III)", -1, -1, 0, 16, comspeedtab_rsa }, - /* COM_IF_ESP98 */ - { " (ESP98)", -1, -1, 1, 1, comspeedtab_mc16550 }, -}; -#endif /* PC98 */ - #ifdef COM_ESP -#ifdef PC98 - -/* XXX configure this properly. */ -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 /* @@ -865,7 +695,17 @@ static int sioinit __P((struct pccard_devinfo *)); static void siounload __P((struct pccard_devinfo *)); static int card_intr __P((struct pccard_devinfo *)); -PCCARD_MODULE(sio, sioinit, siounload, card_intr, 0, tty_imask); +static struct pccard_device sio_info = { + driver_name, + sioinit, + siounload, + card_intr, + 0, /* Attributes - presently unused */ + &tty_imask /* Interrupt mask for device */ + /* XXX - Should this also include net_imask? */ +}; + +DATA_SET(pccarddrv_set, sio_info); /* * Initialize the device - called from Slot manager. @@ -932,9 +772,6 @@ siounload(struct pccard_devinfo *devi) ttwwakeup(com->tp); } else { com_addr(com->unit) = NULL; -#ifdef PC98 - bzero(com->ibuf1, com->CE_INPUT_OFFSET * 6); -#endif bzero(com, sizeof *com); free(com,M_TTYS); printf("sio%d: unload,gone\n", devi->isahd.id_unit); @@ -977,9 +814,7 @@ sioprobe(dev) int irqout=0; int ret = 0; int tmp; - int port_shift = 0; - struct siodev iod; - Port_t rsabase = NULL; + struct siodev iod; #endif if (!already_init) { @@ -990,26 +825,13 @@ sioprobe(dev) * XXX the gate enable is elsewhere for some multiports. */ for (xdev = isa_devtab_tty; xdev->id_driver != NULL; xdev++) + if (xdev->id_driver == &siodriver && xdev->id_enabled) #ifdef PC98 - if (xdev->id_driver == &siodriver && xdev->id_enabled) { - tmp = (xdev->id_flags >> 24) & 0xff; - if (IS_8251(tmp)) - outb((xdev->id_iobase & 0xff00) | PC98SIO_cmd_port(tmp & 0x0f), 0xf2); - else - if (tmp == COM_IF_RSA98III) { - rsabase = xdev->id_iobase & 0xfff0; -#if 0 - if (rsabase != xdev->id_iobase) - return(0); + if (IS_PC98IN(xdev->id_iobase)) + outb(xdev->id_iobase + 2, 0xf2); + else #endif - outb(xdev->id_iobase + 8 + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0); - } else - outb(xdev->id_iobase + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0); - } -#else - if (xdev->id_driver == &siodriver && xdev->id_enabled) outb(xdev->id_iobase + com_mcr, 0); -#endif already_init = TRUE; } @@ -1020,15 +842,14 @@ sioprobe(dev) #ifdef PC98 DELAY(10); - /* * If the port is i8251 UART (internal, B98_01) */ - if (pc98_check_if_type(dev, &iod) == -1) - return 0; - if (iod.irq > 0) - dev->id_irq = 1 << iod.irq; - if (IS_8251(iod.if_type)) { + if(pc98_check_if_type(dev->id_iobase, &iod) == -1) + return 0; + if(IS_8251(iod.if_type)){ + if ( iod.irq > 0 ) + dev->id_irq = (1 << iod.irq); outb(iod.cmd, 0); DELAY(10); outb(iod.cmd, 0); @@ -1044,20 +865,23 @@ sioprobe(dev) if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) { ret = 0; } - 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); - ret = isa_irq_pending() ? 4 : 0; - 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. - */ - ret = 4; + switch (iod.if_type) { + case COM_IF_INTERNAL: + COM_INT_DISABLE + tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx)); + outb( iod.ctrl, tmp|IEN_TxEMP ); + DELAY(10); + ret = isa_irq_pending() ? 4 : 0; + outb( iod.ctrl, tmp ); + COM_INT_ENABLE + break; +#ifdef COM_IF_B98_01 + case COM_IF_B98_01: + /* B98_01 doesn't activate TxEMP interrupt line + when being reset, so we can't check irq pending.*/ + ret = 4; + break; +#endif } if (epson_machine_id==0x20) { /* XXX */ ret = 4; @@ -1075,22 +899,6 @@ sioprobe(dev) */ idev = dev; mcr_image = MCR_IENABLE; -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) { - mcr_image = 0; - rsabase = idev->id_iobase & 0xfff0; - if (rsabase != idev->id_iobase) - return(0); - outb(rsabase + rsa_msr, 0x04); - outb(rsabase + rsa_frr, 0x00); - if ((inb(rsabase + rsa_srr) & 0x36) != 0x36) - return (0); - outb(rsabase + rsa_ier, 0x00); - outb(rsabase + rsa_frr, 0x00); - outb(rsabase + rsa_tivsr, 0x00); - outb(rsabase + rsa_tcr, 0x00); - } -#endif /* PC98 */ #ifdef COM_MULTIPORT if (COM_ISMULTIPORT(dev)) { idev = find_isadev(isa_devtab_tty, &siodriver, @@ -1114,28 +922,18 @@ sioprobe(dev) mcr_image = 0; #ifdef PC98 - tmp = if_16550a_type[iod.if_type & 0x0f].irr_write; - if (tmp != -1) { - /* MC16550II */ - switch (idev->id_irq) { - case IRQ3: irqout = 4; break; - case IRQ5: irqout = 5; break; - case IRQ6: irqout = 6; break; - case IRQ12: irqout = 7; break; - default: - printf("sio%d: irq configuration error\n", dev->id_unit); - return (0); - } - outb((dev->id_iobase & 0x00ff) | tmp, irqout); + switch(idev->id_irq){ + case IRQ3: irqout = 4; break; + case IRQ5: irqout = 5; break; + case IRQ6: irqout = 6; break; + case IRQ12: irqout = 7; break; + default: + printf("sio%d: irq configuration error\n",dev->id_unit); + return (0); } - port_shift = if_16550a_type[iod.if_type & 0x0f].port_shift; + outb(dev->id_iobase+0x1000, irqout); #endif bzero(failures, sizeof failures); -#ifdef PC98 - if (iod.if_type == COM_IF_RSA98III) - iobase = dev->id_iobase + 8; - else -#endif iobase = dev->id_iobase; /* @@ -1160,19 +958,10 @@ sioprobe(dev) if (iobase == siocniobase) DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); else { -#ifdef PC98 - tmp = ttspeedtab(SIO_TEST_SPEED, - if_16550a_type[iod.if_type & 0x0f].speedtab); - outb(iobase + (com_cfcr << port_shift), CFCR_DLAB|CFCR_8BITS); - outb(iobase + (com_dlbl << port_shift), tmp & 0xff); - outb(iobase + (com_dlbh << port_shift), (tmp >> 8) & 0xff); - outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); -#else outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff); outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8); outb(iobase + com_cfcr, CFCR_8BITS); -#endif DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); } @@ -1182,13 +971,8 @@ sioprobe(dev) * guarantee an edge trigger if an interrupt can be generated. */ /* EXTRA DELAY? */ -#ifdef PC98 - outb(iobase + (com_mcr << port_shift), mcr_image); - outb(iobase + (com_ier << port_shift), 0); -#else outb(iobase + com_mcr, mcr_image); outb(iobase + com_ier, 0); -#endif DELAY(1000); /* XXX */ irqmap[0] = isa_irq_pending(); @@ -1197,11 +981,7 @@ sioprobe(dev) * without annoying any external device. */ /* EXTRA DELAY? */ -#ifdef PC98 - outb(iobase + (com_mcr << port_shift), mcr_image | MCR_LOOPBACK); -#else outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK); -#endif /* * Attempt to generate an output interrupt. On 8250's, setting @@ -1211,14 +991,7 @@ sioprobe(dev) * current setting. On 16550A's, setting IER_ETXRDY only * generates an interrupt when IER_ETXRDY is not already set. */ -#ifdef PC98 - outb(iobase + (com_ier << port_shift), IER_ETXRDY); - if (iod.if_type == COM_IF_RSA98III) { - outb(rsabase + rsa_ier, 0x04); - } -#else outb(iobase + com_ier, IER_ETXRDY); -#endif /* PC98 */ /* * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate @@ -1226,11 +999,7 @@ sioprobe(dev) * output. Loopback may be broken on the same incompatibles but * it's unlikely to do more than allow the null byte out. */ -#ifdef PC98 - outb(iobase + (com_data << port_shift), 0); -#else outb(iobase + com_data, 0); -#endif DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); /* @@ -1241,11 +1010,7 @@ sioprobe(dev) * are disabled. */ /* EXTRA DELAY? */ -#ifdef PC98 - outb(iobase + (com_mcr << port_shift), mcr_image); -#else outb(iobase + com_mcr, mcr_image); -#endif /* PC98 */ /* * It's a definitly Serial PCMCIA(16550A), but still be required @@ -1255,28 +1020,14 @@ sioprobe(dev) /* Reading IIR register twice */ for ( fn = 0; fn < 2; fn ++ ) { DELAY(10000); -#ifdef PC98 - failures[6] = inb(iobase + (com_iir << port_shift)); -#else failures[6] = inb(iobase + com_iir); -#endif } /* Check IIR_TXRDY clear ? */ -#ifdef PC98 - result = if_16550a_type[iod.if_type & 0x0f].io_size; -#else result = IO_COMSIZE; -#endif if ( failures[6] & IIR_TXRDY ) { /* Nop, Double check with clearing IER */ -#ifdef PC98 - outb(iobase + (com_ier << port_shift), 0); - if (inb(iobase + - (com_iir << port_shift)) & IIR_NOPEND) { -#else outb(iobase + com_ier, 0); if ( inb(iobase + com_iir) & IIR_NOPEND ) { -#endif /* Ok. we're familia this gang */ dev->id_flags |= COM_C_IIR_TXRDYBUG; /* Set IIR_TXRDYBUG */ } else { @@ -1287,11 +1038,7 @@ sioprobe(dev) /* OK. this is well-known guys */ dev->id_flags &= ~COM_C_IIR_TXRDYBUG; /*Clear IIR_TXRDYBUG*/ } -#ifdef PC98 - outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); -#else outb(iobase + com_cfcr, CFCR_8BITS); -#endif enable_intr(); return (iobase == siocniobase ? IO_COMSIZE : result); } @@ -1305,37 +1052,15 @@ sioprobe(dev) * o the interrupt goes away when the IIR in the UART is read. */ /* EXTRA DELAY? */ -#ifdef PC98 - failures[0] = inb(iobase + (com_cfcr << port_shift)) - CFCR_8BITS; - failures[1] = inb(iobase + (com_ier << port_shift)) - IER_ETXRDY; - failures[2] = inb(iobase + (com_mcr << port_shift)) - mcr_image; -#else failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS; failures[1] = inb(iobase + com_ier) - IER_ETXRDY; failures[2] = inb(iobase + com_mcr) - mcr_image; -#endif DELAY(10000); /* Some internal modems need this time */ irqmap[1] = isa_irq_pending(); -#ifdef PC98 - failures[4] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) - - IIR_TXRDY; - if (iod.if_type == COM_IF_RSA98III) { - inb(rsabase + rsa_srr); - } -#else failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY; -#endif DELAY(1000); /* XXX */ irqmap[2] = isa_irq_pending(); -#ifdef PC98 - failures[6] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) - - IIR_NOPEND; - if (iod.if_type == COM_IF_RSA98III) { - inb(rsabase + rsa_srr); - } -#else failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; -#endif /* * Turn off all device interrupts and check that they go off properly. @@ -1346,30 +1071,12 @@ sioprobe(dev) * (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.) */ -#ifdef PC98 - outb(iobase + (com_ier << port_shift), 0); - outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); - failures[7] = inb(iobase + (com_ier << port_shift)); - if (iod.if_type == COM_IF_RSA98III) { - outb(rsabase + rsa_ier, 0x00); - } -#else outb(iobase + com_ier, 0); outb(iobase + com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ failures[7] = inb(iobase + com_ier); -#endif DELAY(1000); /* XXX */ irqmap[3] = isa_irq_pending(); -#ifdef PC98 - failures[9] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) - - IIR_NOPEND; - if (iod.if_type == COM_IF_RSA98III) { - inb(rsabase + rsa_srr); - outb(rsabase + rsa_frr, 0x00); - } -#else failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; -#endif enable_intr(); @@ -1382,18 +1089,10 @@ sioprobe(dev) printf("sio%d: irq maps: %#x %#x %#x %#x\n", dev->id_unit, irqmap[0], irqmap[1], irqmap[2], irqmap[3]); -#ifdef PC98 - result = if_16550a_type[iod.if_type & 0x0f].io_size; -#else result = IO_COMSIZE; -#endif for (fn = 0; fn < sizeof failures; ++fn) if (failures[fn]) { -#ifdef PC98 - outb(iobase + (com_mcr << port_shift), 0); -#else outb(iobase + com_mcr, 0); -#endif result = 0; if (bootverbose) { printf("sio%d: probe failed test(s):", @@ -1433,22 +1132,13 @@ espattach(isdp, com, esp_port) */ /* 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 ((com->iobase & 0xff) == likely_com_ports[dips & 0x03]) -#else if (com->iobase == likely_com_ports[dips & 0x03]) -#endif printf(" : ESP"); else { printf(" esp_port has com %d\n", dips & 0x03); @@ -1458,15 +1148,9 @@ espattach(isdp, com, esp_port) /* * 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); @@ -1501,28 +1185,11 @@ sioattach(isdp) Port_t iobase; int s; int unit; -#ifdef PC98 - int port_shift = 0; - u_long ibufsize; -#endif - isdp->id_ointr = siointr; isdp->id_ri_flags |= RI_FAST; -#ifdef PC98 - if (((isdp->id_flags >> 24) & 0xff) == COM_IF_RSA98III) - iobase = isdp->id_iobase + 8; - else -#endif iobase = isdp->id_iobase; unit = isdp->id_unit; -#ifndef PC98 com = malloc(sizeof *com, M_TTYS, M_NOWAIT); -#else - ibufsize = RS_IBUFSIZE; - if (((isdp->id_flags >> 24) & 0xff) == COM_IF_RSA98III) - ibufsize = 2048; - com = malloc((sizeof *com) + ibufsize * 6, M_TTYS, M_NOWAIT); -#endif if (com == NULL) return (0); @@ -1539,14 +1206,6 @@ sioattach(isdp) * device from sending before we are ready. */ bzero(com, sizeof *com); -#ifdef PC98 - com->CE_INPUT_OFFSET = ibufsize; - com->ibuf1 = (u_char *)com + (sizeof *com); - com->ibuf2 = com->ibuf1 + (ibufsize * 2); - com->obuf1 = com->ibuf2 + (ibufsize * 2); - com->obuf2 = com->obuf1 + ibufsize; - bzero(com->ibuf1, ibufsize * 6); -#endif com->unit = unit; com->cfcr_image = CFCR_8BITS; com->dtr_wait = 3 * hz; @@ -1554,29 +1213,24 @@ sioattach(isdp) com->no_irq = isdp->id_irq == 0; com->tx_fifo_size = 1; com->iptr = com->ibuf = com->ibuf1; -#ifndef PC98 com->ibufend = com->ibuf1 + RS_IBUFSIZE; com->ihighwater = com->ibuf1 + RS_IHIGHWATER; -#else - com->ibufend = com->ibuf1 + com->CE_INPUT_OFFSET; - com->ihighwater = com->ibuf1 + (3 * com->CE_INPUT_OFFSET / 4); -#endif com->obufs[0].l_head = com->obuf1; com->obufs[1].l_head = com->obuf2; com->iobase = iobase; #ifdef PC98 - if (pc98_set_ioport(com, isdp->id_flags) == -1) { - com->pc98_if_type = (isdp->id_flags >> 24) & 0xff; - port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; - com->data_port = iobase + (com_data << port_shift); - com->int_id_port = iobase + (com_iir << port_shift); - com->modem_ctl_port = iobase + (com_mcr << port_shift); - com->mcr_image = inb(com->modem_ctl_port); - com->line_status_port = iobase + (com_lsr << port_shift); - com->modem_status_port = iobase + (com_msr << port_shift); - com->intr_ctl_port = iobase + (com_ier << port_shift); - } + if(pc98_set_ioport(com, iobase) == -1) + if((iobase & 0x0f0) == 0xd0) { + com->pc98_if_type = MC16550; + com->data_port = iobase + com_data; + 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; + com->intr_ctl_port = iobase + com_ier; + } #else /* not PC98 */ com->data_port = iobase + com_data; com->int_id_port = iobase + com_iir; @@ -1599,7 +1253,7 @@ sioattach(isdp) com->it_in.c_lflag = 0; if (unit == comconsole) { #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) DELAY(100000); #endif com->it_in.c_iflag = TTYDEF_IFLAG; @@ -1618,6 +1272,12 @@ sioattach(isdp) /* attempt to determine UART type */ printf("sio%d: type", unit); +#ifdef DSI_SOFT_MODEM + if((inb(iobase+7) ^ inb(iobase+7)) & 0x80) { + printf(" Digicom Systems, Inc. SoftModem"); + goto determined_type; + } +#endif /* DSI_SOFT_MODEM */ #ifndef PC98 #ifdef COM_MULTIPORT @@ -1643,17 +1303,35 @@ sioattach(isdp) } #endif /* !PC98 */ #ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - com_int_TxRx_disable( com ); - com_cflag_and_speed_set( com, com->it_in.c_cflag, comdefaultrate ); - com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); - com_send_break_off( com ); - printf(" 8251%s", if_8251_type[com->pc98_if_type & 0x0f].name); + if(IS_8251(com->pc98_if_type)){ + com_int_TxRx_disable( com ); + com_cflag_and_speed_set( com, com->it_in.c_cflag, + comdefaultrate ); + com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); + com_send_break_off( com ); + switch(com->pc98_if_type){ + case COM_IF_INTERNAL: + printf(" 8251 (internal)"); + break; +#ifdef COM_IF_PC9861K + case COM_IF_PC9861K: + printf(" 8251 (PC9861K)"); + break; +#endif +#ifdef COM_IF_PIO9032B + case COM_IF_PIO9032B: + printf(" 8251 (PIO9032B)"); + break; +#endif +#ifdef COM_IF_B98_01 + case COM_IF_B98_01: + printf(" 8251 (B98_01)"); + break; +#endif + } } else { - outb(iobase + (com_fifo << port_shift), FIFO_ENABLE | FIFO_RX_HIGH); -#else - outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); #endif /* PC98 */ + outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); DELAY(100); com->st16650a = 0; switch (inb(com->int_id_port) & IIR_FIFO_MASK) { @@ -1671,10 +1349,6 @@ sioattach(isdp) printf(" 16550A fifo disabled"); } else { com->hasfifo = TRUE; -#ifdef PC98 - com->tx_fifo_size = 0; /* XXX flag conflicts. */ - printf(" 16550A"); -#else if (COM_ST16650A(isdp)) { com->st16650a = 1; com->tx_fifo_size = 32; @@ -1683,21 +1357,8 @@ sioattach(isdp) com->tx_fifo_size = COM_FIFOSIZE(isdp); printf(" 16550A"); } -#endif - } -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) { - com->tx_fifo_size = 2048; - com->rsabase = isdp->id_iobase; - outb(com->rsabase + rsa_ier, 0x00); - outb(com->rsabase + rsa_frr, 0x00); } -#endif - #ifdef COM_ESP -#ifdef PC98 - if (com->pc98_if_type == COM_IF_ESP98) -#endif for (espp = likely_esp_ports; *espp != 0; espp++) if (espattach(isdp, com, *espp)) { com->tx_fifo_size = 1024; @@ -1715,17 +1376,6 @@ sioattach(isdp) break; } -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSB3000) { - /* Set RSB-2000/3000 Extended Buffer mode. */ - u_char lcr; - lcr = inb(iobase + (com_cfcr << port_shift)); - outb(iobase + (com_cfcr << port_shift), lcr | CFCR_DLAB); - outb(iobase + (com_emr << port_shift), EMR_EXBUFF | EMR_EFMODE); - outb(iobase + (com_cfcr << port_shift), lcr); - } -#endif - #ifdef COM_ESP if (com->esp) { /* @@ -1735,53 +1385,23 @@ sioattach(isdp) * 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 */ -#ifdef PC98 - printf("%s", if_16550a_type[com->pc98_if_type & 0x0f].name); - outb(iobase + (com_fifo << port_shift), 0); -#else outb(iobase + com_fifo, 0); -#endif determined_type: ; #ifdef COM_MULTIPORT @@ -1793,7 +1413,7 @@ determined_type: ; printf(")"); com->no_irq = find_isadev(isa_devtab_tty, &siodriver, COM_MPMASTER(isdp))->id_irq == 0; - } + } #endif /* COM_MULTIPORT */ #ifdef PC98 } @@ -1852,9 +1472,6 @@ sioopen(dev, flag, mode, p) int s; struct tty *tp; int unit; -#ifdef PC98 - int port_shift = 0; -#endif mynor = minor(dev); unit = MINOR_TO_UNIT(mynor); @@ -1870,11 +1487,6 @@ sioopen(dev, flag, mode, p) tp = com->tp = &sio_tty[unit]; #endif s = spltty(); - -#ifdef PC98 - if (!IS_8251(com->pc98_if_type)) - port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; -#endif /* * We jump to this label after all non-interrupted sleeps to pick * up any changes of the device state. @@ -1928,15 +1540,11 @@ open_top: tp->t_dev = dev; tp->t_termios = mynor & CALLOUT_MASK ? com->it_out : com->it_in; -#ifndef PC98 tp->t_ififosize = 2 * RS_IBUFSIZE; -#else - tp->t_ififosize = 2 * com->CE_INPUT_OFFSET; -#endif tp->t_ispeedwat = (speed_t)-1; tp->t_ospeedwat = (speed_t)-1; #ifdef PC98 - if (!IS_8251(com->pc98_if_type)) + if(!IS_8251(com->pc98_if_type)) #endif (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); com->poll = com->no_irq; @@ -1947,7 +1555,7 @@ open_top: if (error != 0) goto out; #ifdef PC98 - if (IS_8251(com->pc98_if_type)) { + if(IS_8251(com->pc98_if_type)){ com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS); pc98_msrint_start(dev); } @@ -1969,17 +1577,9 @@ open_top: * input. */ while (TRUE) { -#ifdef PC98 - outb(iobase + (com_fifo << port_shift), - FIFO_RCV_RST | FIFO_XMT_RST - | com->fifo_image); - if (com->pc98_if_type == COM_IF_RSA98III) - outb(com->rsabase + rsa_frr , 0x00); -#else outb(iobase + com_fifo, FIFO_RCV_RST | FIFO_XMT_RST | com->fifo_image); -#endif /* * XXX the delays are for superstitious * historical reasons. It must be less than @@ -1992,19 +1592,9 @@ open_top: * for about 85 usec instead of 100. */ DELAY(50); -#ifndef PC98 if (!(inb(com->line_status_port) & LSR_RXRDY)) -#else - if (com->pc98_if_type == COM_IF_RSA98III - ? !(inb(com->rsabase + rsa_srr) & 0x08) - : !(inb(com->line_status_port) & LSR_RXRDY)) -#endif break; -#ifdef PC98 - outb(iobase + (com_fifo << port_shift), 0); -#else outb(iobase + com_fifo, 0); -#endif DELAY(50); (void) inb(com->data_port); } @@ -2012,10 +1602,11 @@ open_top: disable_intr(); #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); + 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); @@ -2030,12 +1621,6 @@ open_top: | IER_ERLS | IER_EMSC); } #ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) { - outb(com->rsabase + rsa_ier, 0x1d); - outb(com->intr_ctl_port, IER_ERLS | IER_EMSC); - } -#endif -#ifdef PC98 } #endif enable_intr(); @@ -2137,9 +1722,6 @@ comhardclose(com) int s; struct tty *tp; int unit; -#ifdef PC98 - int port_shift = 0; -#endif unit = com->unit; iobase = com->iobase; @@ -2149,32 +1731,22 @@ comhardclose(com) com->do_timestamp = FALSE; com->do_dcd_timestamp = FALSE; #ifdef PC98 - if (IS_8251(com->pc98_if_type)) - com_send_break_off(com); - else { - port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; - outb(iobase + (com_cfcr << port_shift), - com->cfcr_image &= ~CFCR_SBREAK); - } -#else - outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); + if(IS_8251(com->pc98_if_type)) + com_send_break_off(com); + else #endif + outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); { #ifdef PC98 int tmp; - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) com_int_TxRx_disable(com); else - outb(iobase + (com_ier << port_shift), 0); - if (com->pc98_if_type == COM_IF_RSA98III) { - outb(com->rsabase + rsa_ier, 0x00); - } -#else - outb(iobase + com_ier, 0); #endif + outb(iobase + com_ier, 0); tp = com->tp; #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) tmp = pc98_get_modem_status(com) & TIOCM_CAR; else tmp = com->prev_modem_status & MSR_DCD; @@ -2196,8 +1768,8 @@ comhardclose(com) && !(com->it_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); + if(IS_8251(com->pc98_if_type)) + com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); else #endif (void)commctl(com, TIOCM_DTR, DMBIC); @@ -2208,7 +1780,7 @@ comhardclose(com) } #ifdef PC98 else { - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) com_tiocm_bic(com, TIOCM_LE ); } #endif @@ -2219,11 +1791,7 @@ comhardclose(com) * reboots. Some BIOSes fail to detect 16550s when the * fifos are enabled. */ -#ifdef PC98 - outb(iobase + (com_fifo << port_shift), 0); -#else outb(iobase + com_fifo, 0); -#endif } com->active_out = FALSE; wakeup(&com->active_out); @@ -2329,7 +1897,7 @@ siodtrwakeup(chan) wakeup(&com->dtr_wait); } -static void +void siointr(unit) int unit; { @@ -2340,9 +1908,6 @@ siointr(unit) #else /* COM_MULTIPORT */ struct com_s *com; bool_t possibly_more_intrs; -#ifdef PC98 - u_char rsa_buf_status; -#endif /* * Loop until there is no activity on any port. This is necessary @@ -2367,20 +1932,6 @@ siointr(unit) siointr1(com); } else #endif /* PC98 */ -#ifdef PC98 - 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) @@ -2403,14 +1954,13 @@ siointr1(com) u_char modem_status; u_char *ioptr; u_char recv_data; + u_char int_ident; u_char int_ctl; u_char int_ctl_new; #ifdef PC98 u_char tmp=0; - u_char rsa_buf_status = 0; - int rsa_tx_fifo_size=0; - recv_data=0; +recv_data=0; #endif /* PC98 */ int_ctl = inb(com->intr_ctl_port); @@ -2433,38 +1983,19 @@ more_intr: } else #endif /* PC98 */ 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(IS_8251(com->pc98_if_type)){ recv_data = inb(com->data_port); - if (tmp & 0x78) { + if(tmp & 0x78){ pc98_i8251_or_cmd(com,CMD8251_ER); recv_data = 0; } } else { #endif /* PC98 */ -#ifdef PC98 - 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 @@ -2521,16 +2052,12 @@ if (com->iptr - com->ibuf == 8) setsofttty(); #endif ioptr[0] = recv_data; -#ifdef PC98 - ioptr[com->CE_INPUT_OFFSET] = line_status; -#else ioptr[CE_INPUT_OFFSET] = line_status; -#endif com->iptr = ++ioptr; if (ioptr == com->ihighwater && com->state & CS_RTS_IFLOW) #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) com_tiocm_bic(com, TIOCM_RTS); else #endif @@ -2545,20 +2072,16 @@ cont: * jump from the top of the loop to here */ #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + 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)) { + if(!IS_8251(com->pc98_if_type)){ #endif modem_status = inb(com->modem_status_port); if (modem_status != com->last_modem_status) { @@ -2593,30 +2116,13 @@ cont: #endif /* 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 ioptr = com->obufq.l_head; if (com->tx_fifo_size > 1) { 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; @@ -2628,8 +2134,8 @@ cont: ++com->bytes_out; } #ifdef PC98 - if (IS_8251(com->pc98_if_type)) - if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG)) + 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; @@ -2653,9 +2159,9 @@ cont: } com->state &= ~CS_BUSY; #if defined(PC98) - 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 ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) + com_int_Tx_disable(com); #endif } if (!(com->state & CS_ODONE)) { @@ -2665,29 +2171,24 @@ cont: } } if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { - if (com->pc98_if_type == COM_IF_RSA98III) { - int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY); - outb(com->intr_ctl_port, int_ctl_new); - outb(com->rsabase + rsa_ier, 0x1d); - } else outb(com->intr_ctl_port, int_ctl_new); } } #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 ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) + com_int_Tx_disable(com); } - if (IS_8251(com->pc98_if_type)) - if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) - goto more_intr; + if(IS_8251(com->pc98_if_type)) + 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)) + if(IS_8251(com->pc98_if_type)) return; #endif if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) @@ -2749,6 +2250,34 @@ sioioctl(dev, cmd, data, flag, p) case TIOCGWINSZ: bzero(data, sizeof(struct winsize)); return (0); +#ifdef DSI_SOFT_MODEM + /* + * Download micro-code to Digicom modem. + */ + case TIOCDSIMICROCODE: + { + u_long l; + u_char *p,*pi; + + pi = (u_char*)(*(caddr_t*)data); + error = copyin(pi,&l,sizeof l); + if(error) + {return error;}; + pi += sizeof l; + + p = malloc(l,M_TEMP,M_NOWAIT); + if(!p) + {return ENOBUFS;} + error = copyin(pi,p,l); + if(error) + {free(p,M_TEMP); return error;}; + if(error = LoadSoftModem( + MINOR_TO_UNIT(mynor),iobase,l,p)) + {free(p,M_TEMP); return error;} + free(p,M_TEMP); + return(0); + } +#endif /* DSI_SOFT_MODEM */ default: return (ENOTTY); } @@ -2796,7 +2325,7 @@ sioioctl(dev, cmd, data, flag, p) return (error); } #ifdef PC98 - if (IS_8251(com->pc98_if_type)) { + if(IS_8251(com->pc98_if_type)){ switch (cmd) { case TIOCSBRK: com_send_break_on( com ); @@ -2851,25 +2380,13 @@ sioioctl(dev, cmd, data, flag, p) return (ENOTTY); } } else { - int port_shift; - port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; #endif switch (cmd) { case TIOCSBRK: -#ifdef PC98 - outb(iobase + (com_cfcr << port_shift), - com->cfcr_image |= CFCR_SBREAK); -#else outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); -#endif break; case TIOCCBRK: -#ifdef PC98 - outb(iobase + (com_cfcr << port_shift), - com->cfcr_image &= ~CFCR_SBREAK); -#else outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); -#endif break; case TIOCSDTR: (void)commctl(com, TIOCM_DTR, DMBIS); @@ -2976,13 +2493,8 @@ repeat: ibuf = com->ibuf2; else ibuf = com->ibuf1; -#ifndef PC98 com->ibufend = ibuf + RS_IBUFSIZE; com->ihighwater = ibuf + RS_IHIGHWATER; -#else - com->ibufend = ibuf + com->CE_INPUT_OFFSET; - com->ihighwater = ibuf + (3 * com->CE_INPUT_OFFSET / 4); -#endif com->iptr = ibuf; /* @@ -2991,7 +2503,7 @@ repeat: * there is room in the high-level buffer. */ #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) tmp = com_tiocm_get(com) & TIOCM_RTS; else tmp = com->mcr_image & MCR_RTS; @@ -3004,7 +2516,7 @@ repeat: #endif && !(tp->t_state & TS_TBLOCK)) #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) com_tiocm_bis(com, TIOCM_RTS); else #endif @@ -3018,7 +2530,7 @@ repeat: u_char delta_modem_status; #ifdef PC98 - if (!IS_8251(com->pc98_if_type)) { + if(!IS_8251(com->pc98_if_type)){ #endif disable_intr(); delta_modem_status = com->last_modem_status @@ -3080,11 +2592,7 @@ repeat: u_char line_status; int recv_data; -#ifndef PC98 line_status = (u_char) buf[CE_INPUT_OFFSET]; -#else - line_status = (u_char) buf[com->CE_INPUT_OFFSET]; -#endif recv_data = (u_char) *buf++; if (line_status & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { @@ -3118,14 +2626,14 @@ comparam(tp, t) int divisor; u_char dlbh; u_char dlbl; + int error; Port_t iobase; int s; int unit; + int txtimeout; #ifdef PC98 Port_t tmp_port; int tmp_flg; - int port_shift = 0; - u_char param = 0; #endif #ifdef PC98 @@ -3133,27 +2641,16 @@ comparam(tp, t) unit = DEV_TO_UNIT(tp->t_dev); com = com_addr(unit); iobase = com->iobase; - if (IS_8251(com->pc98_if_type)) { - divisor = pc98_ttspeedtab(com, t->c_ospeed); - } else { - port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; - - /* do historical conversions */ - if (t->c_ispeed == 0) - t->c_ispeed = t->c_ospeed; - - /* check requested parameters */ - divisor = ttspeedtab(t->c_ospeed, - if_16550a_type[com->pc98_if_type & 0x0f].speedtab); - } -#else + if(IS_8251(com->pc98_if_type)) { + divisor = pc98_ttspeedtab(com, t->c_ospeed); + } else +#endif /* do historical conversions */ if (t->c_ispeed == 0) t->c_ispeed = t->c_ospeed; /* check requested parameters */ divisor = ttspeedtab(t->c_ospeed, comspeedtab); -#endif if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed) return (EINVAL); @@ -3165,8 +2662,8 @@ comparam(tp, t) #endif s = spltty(); #ifdef PC98 - if (IS_8251(com->pc98_if_type)) { - if (divisor == 0) + if(IS_8251(com->pc98_if_type)){ + if(divisor == 0) com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); else com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); @@ -3181,7 +2678,7 @@ comparam(tp, t) #endif cflag = t->c_cflag; #ifdef PC98 - if (!IS_8251(com->pc98_if_type)) { + if(!IS_8251(com->pc98_if_type)){ #endif switch (cflag & CSIZE) { case CS5: @@ -3225,29 +2722,80 @@ comparam(tp, t) if (com->esp) com->fifo_image |= FIFO_DMA_MODE; #endif -#ifdef PC98 - outb(iobase + (com_fifo << port_shift), com->fifo_image); -#else outb(iobase + com_fifo, com->fifo_image); -#endif } + + /* + * Some UARTs lock up if the divisor latch registers are selected + * while the UART is doing output (they refuse to transmit anything + * more until given a hard reset). Fix this by stopping filling + * the device buffers and waiting for them to drain. Reading the + * line status port outside of siointr1() might lose some receiver + * error bits, but that is acceptable here. + */ #ifdef PC98 } #endif + disable_intr(); +retry: + com->state &= ~CS_TTGO; + txtimeout = tp->t_timeout; + enable_intr(); +#ifdef PC98 + if(IS_8251(com->pc98_if_type)){ + tmp_port = com->sts_port; + tmp_flg = (STS8251_TxRDY|STS8251_TxEMP); + } else { + tmp_port = com->line_status_port; + tmp_flg = (LSR_TSRE|LSR_TXRDY); + } + while ((inb(tmp_port) & tmp_flg) != tmp_flg) { +#else + while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) + != (LSR_TSRE | LSR_TXRDY)) { +#endif + tp->t_state |= TS_SO_OCOMPLETE; + error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH, + "siotx", hz / 100); + if ( txtimeout != 0 + && (!error || error == EAGAIN) + && (txtimeout -= hz / 100) <= 0 + ) + error = EIO; + if (com->gone) + error = ENODEV; + if (error != 0 && error != EAGAIN) { + if (!(tp->t_state & TS_TTSTOP)) { + disable_intr(); + com->state |= CS_TTGO; + enable_intr(); + } + splx(s); + return (error); + } + } - disable_intr(); /* very important while com_data is hidden */ + disable_intr(); /* very important while com_data is hidden */ + /* + * XXX - clearing CS_TTGO is not sufficient to stop further output, + * because siopoll() calls comstart() which usually sets it again + * because TS_TTSTOP is clear. Setting TS_TTSTOP would not be + * sufficient, for similar reasons. + */ #ifdef PC98 - if (IS_8251(com->pc98_if_type)) - com_cflag_and_speed_set(com, cflag, t->c_ospeed); - else { + if ((inb(tmp_port) & tmp_flg) != tmp_flg) +#else + if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) + != (LSR_TSRE | LSR_TXRDY)) #endif - if (divisor != 0) { + goto retry; + #ifdef PC98 - outb(iobase + (com_cfcr << port_shift), cfcr | CFCR_DLAB); -#else - outb(iobase + com_cfcr, cfcr | CFCR_DLAB); + if(!IS_8251(com->pc98_if_type)){ #endif + if (divisor != 0) { + outb(iobase + com_cfcr, cfcr | CFCR_DLAB); /* * Only set the divisor registers if they would change, * since on some 16550 incompatibles (UMC8669F), setting @@ -3255,29 +2803,20 @@ comparam(tp, t) * data stops arriving. */ dlbl = divisor & 0xFF; -#ifdef PC98 - if (inb(iobase + (com_dlbl << port_shift)) != dlbl) - outb(iobase + (com_dlbl << port_shift), dlbl); - dlbh = (u_int) divisor >> 8; - if (inb(iobase + (com_dlbh << port_shift)) != dlbh) - outb(iobase + (com_dlbh << port_shift), dlbh); -#else if (inb(iobase + com_dlbl) != dlbl) outb(iobase + com_dlbl, dlbl); dlbh = (u_int) divisor >> 8; if (inb(iobase + com_dlbh) != dlbh) outb(iobase + com_dlbh, dlbh); -#endif } -#ifdef PC98 - } - outb(iobase + (com_cfcr << port_shift), com->cfcr_image = cfcr); -#else outb(iobase + com_cfcr, com->cfcr_image = cfcr); -#endif +#ifdef PC98 + } else + com_cflag_and_speed_set(com, cflag, t->c_ospeed); +#endif if (!(tp->t_state & TS_TTSTOP)) com->state |= CS_TTGO; @@ -3300,7 +2839,7 @@ comparam(tp, t) * on here, since comstart() won't do it later. */ #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) com_tiocm_bis(com, TIOCM_RTS); else #endif @@ -3319,26 +2858,14 @@ comparam(tp, t) */ 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; #ifdef PC98 - if (IS_8251(com->pc98_if_type)) { + if(IS_8251(com->pc98_if_type)){ if (!(pc98_get_modem_status(com) & TIOCM_CTS)) com->state &= ~CS_ODEVREADY; } else { #endif -#ifdef PC98 - 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; if (com->st16650a) { @@ -3356,11 +2883,7 @@ comparam(tp, t) } -#ifdef PC98 - outb(iobase + (com_cfcr << port_shift), com->cfcr_image); -#else outb(iobase + com_cfcr, com->cfcr_image); -#endif /* XXX shouldn't call functions while intrs are disabled. */ @@ -3400,7 +2923,7 @@ comstart(tp) com->state |= CS_TTGO; if (tp->t_state & TS_TBLOCK) { #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) tmp = com_tiocm_get(com) & TIOCM_RTS; else tmp = com->mcr_image & MCR_RTS; @@ -3409,14 +2932,14 @@ comstart(tp) if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) #endif #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) com_tiocm_bic(com, TIOCM_RTS); else #endif outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); } else { #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) tmp = com_tiocm_get(com) & TIOCM_RTS; else tmp = com->mcr_image & MCR_RTS; @@ -3427,7 +2950,7 @@ comstart(tp) && com->state & CS_RTS_IFLOW) #endif #ifdef PC98 - if (IS_8251(com->pc98_if_type)) + if(IS_8251(com->pc98_if_type)) com_tiocm_bis(com, TIOCM_RTS); else #endif @@ -3450,11 +2973,7 @@ comstart(tp) if (!com->obufs[0].l_queued) { com->obufs[0].l_tail = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, -#ifndef PC98 sizeof com->obuf1); -#else - com->CE_INPUT_OFFSET); -#endif com->obufs[0].l_next = NULL; com->obufs[0].l_queued = TRUE; disable_intr(); @@ -3474,11 +2993,7 @@ comstart(tp) 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, -#ifndef PC98 sizeof com->obuf2); -#else - com->CE_INPUT_OFFSET); -#endif com->obufs[1].l_next = NULL; com->obufs[1].l_queued = TRUE; disable_intr(); @@ -3515,18 +3030,10 @@ siostop(tp, rw) int rw; { struct com_s *com; -#ifdef PC98 - int port_shift = 0; - int rsa98_tmp = 0; -#endif com = com_addr(DEV_TO_UNIT(tp->t_dev)); if (com->gone) return; -#ifdef PC98 - if (IS_8251(com->pc98_if_type)) - port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; -#endif disable_intr(); if (rw & FWRITE) { if (com->hasfifo) @@ -3534,17 +3041,9 @@ siostop(tp, rw) /* XXX avoid h/w bug. */ if (!com->esp) #endif -#ifdef PC98 - outb(com->iobase + (com_fifo << port_shift), - FIFO_XMT_RST | com->fifo_image); - if (com->pc98_if_type == COM_IF_RSA98III) - for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) - outb(com->iobase + (com_fifo << port_shift), - FIFO_XMT_RST | com->fifo_image); -#else + /* XXX does this flush everything? */ outb(com->iobase + 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) @@ -3558,17 +3057,9 @@ siostop(tp, rw) /* XXX avoid h/w bug. */ if (!com->esp) #endif -#ifdef PC98 - if (com->pc98_if_type == COM_IF_RSA98III) { - for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) - inb(com->data_port); - } - outb(com->iobase + (com_fifo << port_shift), - FIFO_RCV_RST | com->fifo_image); -#else + /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_RCV_RST | com->fifo_image); -#endif com_events -= (com->iptr - com->ibuf); com->iptr = com->ibuf; } @@ -3815,18 +3306,6 @@ static void siocnclose __P((struct siocnstate *sp)); static void siocnopen __P((struct siocnstate *sp)); static void siocntxwait __P((void)); -/* - * XXX: sciocnget() and sciocnputc() are not declared static, as they are - * referred to from i386/i386/i386-gdbstub.c. - */ -static cn_probe_t siocnprobe; -static cn_init_t siocninit; -static cn_checkc_t siocncheckc; - cn_getc_t siocngetc; - cn_putc_t siocnputc; - -CONS_DRIVER(sio, siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc); - static void siocntxwait() { @@ -3948,7 +3427,7 @@ siocnclose(sp) outb(iobase + com_ier, sp->ier); } -static void +void siocnprobe(cp) struct consdev *cp; { @@ -4014,14 +3493,14 @@ siocnprobe(cp) } } -static void +void siocninit(cp) struct consdev *cp; { comconsole = DEV_TO_UNIT(cp->cn_dev); } -static int +int siocncheckc(dev) dev_t dev; { @@ -4079,6 +3558,126 @@ siocnputc(dev, c) splx(s); } +#ifdef DSI_SOFT_MODEM +/* + * The magic code to download microcode to a "Connection 14.4+Fax" + * modem from Digicom Systems Inc. Very magic. + */ + +#define DSI_ERROR(str) { ptr = str; goto error; } +static int +LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr) +{ + int int_c,int_k; + int data_0188, data_0187; + + /* + * First see if it is a DSI SoftModem + */ + if(!((inb(base_io+7) ^ inb(base_io+7)) & 0x80)) + return ENODEV; + + data_0188 = inb(base_io+4); + data_0187 = inb(base_io+3); + outb(base_io+3,0x80); + outb(base_io+4,0x0C); + outb(base_io+0,0x31); + outb(base_io+1,0x8C); + outb(base_io+7,0x10); + outb(base_io+7,0x19); + + if(0x18 != (inb(base_io+7) & 0x1A)) + DSI_ERROR("dsp bus not granted"); + + if(0x01 != (inb(base_io+7) & 0x01)) { + outb(base_io+7,0x18); + outb(base_io+7,0x19); + if(0x01 != (inb(base_io+7) & 0x01)) + DSI_ERROR("program mem not granted"); + } + + int_c = 0; + + while(1) { + if(int_c >= 7 || size <= 0x1800) + break; + + for(int_k = 0 ; int_k < 0x800; int_k++) { + outb(base_io+0,*ptr++); + outb(base_io+1,*ptr++); + outb(base_io+2,*ptr++); + } + + size -= 0x1800; + int_c++; + } + + if(size > 0x1800) { + outb(base_io+7,0x18); + outb(base_io+7,0x19); + if(0x00 != (inb(base_io+7) & 0x01)) + DSI_ERROR("program data not granted"); + + for(int_k = 0 ; int_k < 0x800; int_k++) { + outb(base_io+1,*ptr++); + outb(base_io+2,0); + outb(base_io+1,*ptr++); + outb(base_io+2,*ptr++); + } + + size -= 0x1800; + + while(size > 0x1800) { + for(int_k = 0 ; int_k < 0xC00; int_k++) { + outb(base_io+1,*ptr++); + outb(base_io+2,*ptr++); + } + size -= 0x1800; + } + + if(size < 0x1800) { + for(int_k=0;int_k<size/2;int_k++) { + outb(base_io+1,*ptr++); + outb(base_io+2,*ptr++); + } + } + + } else if (size > 0) { + if(int_c == 7) { + outb(base_io+7,0x18); + outb(base_io+7,0x19); + if(0x00 != (inb(base_io+7) & 0x01)) + DSI_ERROR("program data not granted"); + for(int_k = 0 ; int_k < size/3; int_k++) { + outb(base_io+1,*ptr++); + outb(base_io+2,0); + outb(base_io+1,*ptr++); + outb(base_io+2,*ptr++); + } + } else { + for(int_k = 0 ; int_k < size/3; int_k++) { + outb(base_io+0,*ptr++); + outb(base_io+1,*ptr++); + outb(base_io+2,*ptr++); + } + } + } + outb(base_io+7,0x11); + outb(base_io+7,3); + + outb(base_io+4,data_0188 & 0xfb); + + outb(base_io+3,data_0187); + + return 0; +error: + printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr); + outb(base_io+7,0x00); \ + outb(base_io+3,data_0187); \ + outb(base_io+4,data_0188); \ + return EIO; +} +#endif /* DSI_SOFT_MODEM */ /* * support PnP cards if we are using 'em @@ -4156,7 +3755,7 @@ siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) dev->id_iobase = d.port[0]; dev->id_irq = (1 << d.irq[0]); - dev->id_ointr = siointr; + dev->id_intr = siointr; dev->id_ri_flags = RI_FAST; dev->id_drq = -1; @@ -4173,7 +3772,6 @@ siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) printf("sio%d: probe failed\n", dev->id_unit); } #endif - #ifdef PC98 /* * pc98 local function @@ -4497,10 +4095,12 @@ com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 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 ); @@ -4513,214 +4113,206 @@ com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) static int pc98_ttspeedtab(struct com_s *com, int speed) { - int if_type, effect_sp, count = -1, mod; + int 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: - if ( speed == 0 ) return 0; - count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); - break; - case COM_IF_B98_01_1: - case COM_IF_B98_01_2: - if ( speed == 0 ) return 0; - 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 */ - } + switch ( com->pc98_if_type ) { + case COM_IF_INTERNAL: + /* for *1CLK asynchronous! mode , TEFUTEFU */ + effect_sp = ttspeedtab( speed, pc98speedtab ); + if ( effect_sp < 0 ) + effect_sp = ttspeedtab( (speed-1), pc98speedtab ); + if ( effect_sp <= 0 ) + return effect_sp; + mod = (sysclock == 5 ? 2457600 : 1996800); + if ( effect_sp == speed ) + mod /= 16; + count = mod / effect_sp; + if ( count > 65535 ) + return(-1); + if ( effect_sp >= 2400 ) + if ( !(sysclock != 5 && + (effect_sp == 19200 || effect_sp == 38400)) ) + if ( ( mod % effect_sp ) != 0 ) + return(-1); + if ( effect_sp != speed ) + count |= 0x10000; + break; +#ifdef COM_IF_PC9861K + case COM_IF_PC9861K: + effect_sp = speed; + count = 1; + break; +#endif +#ifdef COM_IF_PIO9032B + case COM_IF_PIO9032B: + if ( speed == 0 ) return 0; + count = ttspeedtab( speed, comspeedtab_pio9032b ); + if ( count < 0 ) return count; + effect_sp = speed; + break; +#endif +#ifdef COM_IF_B98_01 + case COM_IF_B98_01: + effect_sp=speed; + count = ttspeedtab( speed, comspeedtab_b98_01 ); + if ( count <= 3 ) + return -1; /* invalid speed/count */ + if ( count <= 5 ) + count |= 0x10000; /* x1 mode for 76800 and 153600 */ + else + count -= 4; /* x16 mode for slower */ + break; #endif - break; } - return count; } static void -pc98_set_baud_rate( struct com_s *com, int count ) +pc98_set_baud_rate( struct com_s *com, int count) { - int if_type, io, s; - - if_type = com->pc98_if_type & 0x0f; - io = com->iobase & 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); - } - } + int s; - if ( count < 0 ) { - printf( "[ Illegal count : %d ]", count ); - return; - } else if ( count == 0 ) - return; - /* set i8253 */ - s = splclock(); - if (count != 3) + switch ( com->pc98_if_type ) { + case COM_IF_INTERNAL: + if ( count < 0 ) { + printf( "[ Illegal count : %d ]", count ); + return; + } else if ( count == 0) + return; + /* set i8253 */ + s = splclock(); 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); + outb( 0x5f, 0); + outb( 0x75, count & 0xff ); + outb( 0x5f, 0); + outb( 0x75, (count >> 8) & 0xff ); + splx(s); + break; +#if 0 +#ifdef COM_IF_PC9861K + case COM_IF_PC9861K: + break; + /* ext. RS232C board: speed is determined by DIP switch */ +#endif +#endif /* 0 */ +#ifdef COM_IF_PIO9032B + case COM_IF_PIO9032B: + outb( com_addr[unit], count & 0x07 ); + break; +#endif +#ifdef COM_IF_B98_01 + case COM_IF_B98_01: + outb( com->iobase, 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); + /* some old board should be controlled in different way, + but this hasn't been tested yet.*/ + outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 ); +#endif + break; #endif - break; } } static int -pc98_check_if_type(struct isa_device *dev, struct siodev *iod) +pc98_check_if_type( int iobase, struct siodev *iod) { - int irr, io, if_type, tmp; + int irr = 0, tmp = 0; + int ret = 0; static short irq_tab[2][8] = { { 3, 5, 6, 9, 10, 12, 13, -1}, { 3, 10, 12, 13, 5, 6, 9, -1} }; - - iod->if_type = if_type = (dev->id_flags >> 24) & 0xff; - if ((if_type < 0 || if_type > COM_IF_END1) && - (if_type < 0x10 || if_type > COM_IF_END2)) - return(-1); - if_type &= 0x0f; iod->irq = 0; - io = dev->id_iobase & 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; - - /* XXX check new internal port. */ - outb(0x138, 0); - DELAY(10); - for (tmp = 0; tmp < 100; tmp++) { - if ((inb(0x138) & 1) == 0) { - PC98SIO_baud_rate_port(if_type) = 0x13a; - if_8251_type[if_type].name = " (internal fast)"; - if_8251_type[if_type].speedtab = pc98fast_speedtab; + switch ( iobase & 0xff ) { + case IO_COM1: + iod->if_type = COM_IF_INTERNAL; + ret = 0; iod->irq = 4; break; +#ifdef COM_IF_PC9861K + case IO_COM2: + iod->if_type = COM_IF_PC9861K; + ret = 1; irr = 0; tmp = 3; break; + case IO_COM3: + iod->if_type = COM_IF_PC9861K; + ret = 2; irr = 1; tmp = 3; break; +#endif +#ifdef COM_IF_PIO9032B + case IO_COM_PIO9032B_2: + iod->if_type = COM_IF_PIO9032B; + ret = 1; irr = 0; tmp = 7; break; + case IO_COM_PIO9032B_3: + iod->if_type = COM_IF_PIO9032B; + ret = 2; irr = 1; tmp = 7; break; +#endif +#ifdef COM_IF_B98_01 + case IO_COM_B98_01_2: + iod->if_type = COM_IF_B98_01; + ret = 1; irr = 0; tmp = 7; + outb(iobase + 2, 0xf2); + outb(iobase, 4); + break; + case IO_COM_B98_01_3: + iod->if_type = COM_IF_B98_01; + ret = 2; irr = 1; tmp = 7; + outb(iobase + 2, 0xf2); + outb(iobase , 4); break; - } - DELAY(1); - } - } else { - tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask; - if ((dev->id_iobase & 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(dev) || dev->id_unit == COM_MPMASTER(dev)) #endif - if (irr != -1) { - tmp = inb(io | irr); - if (dev->id_iobase & 0x01) /* XXX depend on RSB-384 */ - iod->irq = irq_tab[1][tmp >> 3]; - else - iod->irq = irq_tab[0][tmp & 0x07]; - } + default: + if((iobase & 0x0f0) == 0xd0){ + iod->if_type = MC16550; + return 0; + } + return -1; } - if ( iod->irq == -1 ) return -1; + iod->cmd = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret); + iod->sts = ( iobase & 0xff00 )|PC98SIO_sts_port(ret); + iod->mod = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret); + iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret); + + if ( iod->irq == 0 ) { + tmp &= inb( iod->mod ); + iod->irq = irq_tab[irr][tmp]; + if ( iod->irq == -1 ) return -1; + } return 0; } static int -pc98_set_ioport( struct com_s *com, int id_flags ) +pc98_set_ioport( struct com_s *com, int io_base ) { - int io, if_type; + int a, io, type; - if_type = (id_flags >> 24) & 0xff; - if (IS_8251(if_type)) { - pc98_check_sysclock(); - io = com->iobase & 0xff00; - com->pc98_if_type = if_type; - if_type &= 0x0f; - 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); - return 0; + switch ( io_base & 0xff ) { + case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL; + pc98_check_sysclock(); break; +#ifdef COM_IF_PC9861K + case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break; + case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break; +#endif /* COM_IF_PC9861K */ +#ifdef COM_IF_PIO9032B + /* PIO9032B : I/O address is changeable */ + case IO_COM_PIO9032B_2: + a = 1; io = io_base & 0xff00; + type = COM_IF_PIO9032B; break; + case IO_COM_PIO9032B_3: + a = 2; io = io_base & 0xff00; + type = COM_IF_PIO9032B; break; +#endif /* COM_IF_PIO9032B */ +#ifdef COM_IF_B98_01 + case IO_COM_B98_01_2: + a = 1; io = 0; type = COM_IF_B98_01; break; + case IO_COM_B98_01_3: + a = 2; io = 0; type = COM_IF_B98_01; break; +#endif /* COM_IF_B98_01*/ + default: /* i/o address not match */ + return -1; } - return -1; + com->pc98_if_type = type; + com->data_port = io | PC98SIO_data_port(a); + com->cmd_port = io | PC98SIO_cmd_port(a); + com->sts_port = io | PC98SIO_sts_port(a); + com->in_modem_port = io | PC98SIO_in_modem_port(a); + com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(a); + return 0; } #endif /* PC98 defined */ diff --git a/sys/pc98/pc98/sioreg.h b/sys/pc98/pc98/sioreg.h new file mode 100644 index 000000000000..840df10841be --- /dev/null +++ b/sys/pc98/pc98/sioreg.h @@ -0,0 +1,119 @@ +/*- + * 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. + * 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: @(#)comreg.h 7.2 (Berkeley) 5/9/91 + * $Id: sioreg.h,v 1.6 1997/06/04 10:27:53 kato Exp $ + */ + + +/* 16 bit baud rate divisor (lower byte in dca_data, upper in dca_ier) */ +#if defined(PC98) +#define COMBRD(x) (7372800 / (16*(x))) +#else +#define COMBRD(x) (1843200 / (16*(x))) +#endif + +/* interrupt enable register */ +#define IER_ERXRDY 0x1 +#define IER_ETXRDY 0x2 +#define IER_ERLS 0x4 +#define IER_EMSC 0x8 + +/* interrupt identification register */ +#define IIR_IMASK 0xf +#define IIR_RXTOUT 0xc +#define IIR_RLS 0x6 +#define IIR_RXRDY 0x4 +#define IIR_TXRDY 0x2 +#define IIR_NOPEND 0x1 +#define IIR_MLSC 0x0 +#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ + +/* fifo control register */ +#define FIFO_ENABLE 0x01 +#define FIFO_RCV_RST 0x02 +#define FIFO_XMT_RST 0x04 +#define FIFO_DMA_MODE 0x08 +#define FIFO_RX_LOW 0x00 +#define FIFO_RX_MEDL 0x40 +#define FIFO_RX_MEDH 0x80 +#define FIFO_RX_HIGH 0xc0 + +/* character format control register */ +#define CFCR_DLAB 0x80 +#define CFCR_SBREAK 0x40 +#define CFCR_PZERO 0x30 +#define CFCR_PONE 0x20 +#define CFCR_PEVEN 0x10 +#define CFCR_PODD 0x00 +#define CFCR_PENAB 0x08 +#define CFCR_STOPB 0x04 +#define CFCR_8BITS 0x03 +#define CFCR_7BITS 0x02 +#define CFCR_6BITS 0x01 +#define CFCR_5BITS 0x00 + +/* modem control register */ +#define MCR_LOOPBACK 0x10 +#define MCR_IENABLE 0x08 +#define MCR_DRS 0x04 +#define MCR_RTS 0x02 +#define MCR_DTR 0x01 + +/* line status register */ +#define LSR_RCV_FIFO 0x80 +#define LSR_TSRE 0x40 +#define LSR_TXRDY 0x20 +#define LSR_BI 0x10 +#define LSR_FE 0x08 +#define LSR_PE 0x04 +#define LSR_OE 0x02 +#define LSR_RXRDY 0x01 +#define LSR_RCV_MASK 0x1f + +/* modem status register */ +#define MSR_DCD 0x80 +#define MSR_RI 0x40 +#define MSR_DSR 0x20 +#define MSR_CTS 0x10 +#define MSR_DDCD 0x08 +#define MSR_TERI 0x04 +#define MSR_DDSR 0x02 +#define MSR_DCTS 0x01 + +/* speed to initialize to during chip tests */ +#define SIO_TEST_SPEED 9600 + +/* default serial console speed if not set with sysctl or probed from boot */ +#ifndef CONSPEED +#define CONSPEED 9600 +#endif diff --git a/sys/pc98/pc98/syscons.c b/sys/pc98/pc98/syscons.c index bfce06877b62..e85a1b317454 100644 --- a/sys/pc98/pc98/syscons.c +++ b/sys/pc98/pc98/syscons.c @@ -1,18 +1,18 @@ /*- - * Copyright (c) 1992-1998 Sen Schmidt + * Copyright (c) 1992-1995 Sen Schmidt * 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. + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. * 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. + * derived from this software withough 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 @@ -25,16 +25,13 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.108 1999/01/18 14:48:34 kato Exp $ + * $Id: syscons.c,v 1.100 1998/08/28 12:45:43 kato Exp $ */ #include "sc.h" -#include "splash.h" #include "apm.h" #include "opt_ddb.h" #include "opt_devfs.h" -#include "opt_vesa.h" -#include "opt_vm86.h" #include "opt_syscons.h" #if NSC > 0 @@ -60,33 +57,36 @@ #include <machine/psl.h> #include <machine/frame.h> #include <machine/pc/display.h> -#include <machine/pc/vesa.h> #include <machine/apm_bios.h> #include <machine/random.h> +#include <machine/bootinfo.h> #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> -#include <dev/kbd/kbdreg.h> -#include <dev/fb/fbreg.h> -#include <dev/fb/splashreg.h> - #ifdef PC98 #define KANJI #include <pc98/pc98/pc98.h> #include <pc98/pc98/pc98_machdep.h> #include <i386/isa/isa_device.h> #include <i386/isa/timerreg.h> +#include <i386/isa/kbdtables.h> +#include <i386/isa/kbdio.h> #include <pc98/pc98/syscons.h> #else -#include <dev/fb/vgareg.h> -#include <dev/syscons/syscons.h> #include <i386/isa/isa.h> #include <i386/isa/isa_device.h> #include <i386/isa/timerreg.h> +#include <i386/isa/kbdtables.h> +#include <i386/isa/kbdio.h> +#include <i386/isa/syscons.h> #endif /* PC98 */ +#if defined(PC98) && defined(LINE30) +#include <pc98/pc98/30line.h> +#endif + #if !defined(MAXCONS) #define MAXCONS 16 #endif @@ -111,6 +111,11 @@ #define COLD 0 #define WARM 1 +#define VESA_MODE(x) ((x) >= M_VESA_BASE) + +#define MODE_MAP_SIZE (M_VGA_CG320 + 1) +#define MODE_PARAM_SIZE 64 + #define DEFAULT_BLANKTIME (5*60) /* 5 minutes */ #define MAX_BLANKTIME (7*24*60*60) /* 7 days!? */ @@ -131,6 +136,9 @@ typedef struct old_mouse_info { } u; } old_mouse_info_t; +/* XXX use sc_bcopy where video memory is concerned */ +extern void generic_bcopy(const void *, void *, size_t); + static default_attr user_default = { (FG_LIGHTGREY | BG_BLACK) << 8, (FG_BLACK | BG_LIGHTGREY) << 8 @@ -159,7 +167,9 @@ static void *sc_console_devfs_token; static scr_stat *new_scp, *old_scp; static term_stat kernel_console; static default_attr *current_default; -static int sc_flags; +static int flags = 0; +static int sc_port = IO_KBD; +static KBDC sc_kbdc = NULL; static char init_done = COLD; static u_short sc_buffer[ROW*COL]; static char shutdown_in_progress = FALSE; @@ -168,38 +178,51 @@ static char switch_in_progress = FALSE; static char write_in_progress = FALSE; static char blink_in_progress = FALSE; static int blinkrate = 0; -static int adapter = -1; -static int keyboard = -1; -static keyboard_t *kbd; +#ifndef PC98 + u_int crtc_addr = MONO_BASE; +#endif + char crtc_type = KD_MONO; + char crtc_vga = FALSE; +static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; +static u_char accents = 0; +#ifdef PC98 +static u_char nlkcnt = 0, slkcnt = 0, alkcnt = 0; +#else +static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; +#endif +static const u_int n_fkey_tab = sizeof(fkey_tab) / sizeof(*fkey_tab); static int delayed_next_scr = FALSE; static long scrn_blank_time = 0; /* screen saver timeout value */ -static int scrn_blanked = FALSE; /* screen saver active flag */ + int scrn_blanked = 0; /* screen saver active flag */ static long scrn_time_stamp; static int saver_mode = CONS_LKM_SAVER; /* LKM/user saver */ static int run_scrn_saver = FALSE; /* should run the saver? */ static int scrn_idle = FALSE; /* about to run the saver */ -static int scrn_saver_failed; u_char scr_map[256]; u_char scr_rmap[256]; -static int initial_video_mode; /* initial video mode # */ + char *video_mode_ptr = NULL; +static int bios_video_mode; /* video mode # set by BIOS */ int fonts_loaded = 0 #ifdef STD8X16FONT | FONT_16 #endif ; - u_char font_8[256*8]; - u_char font_14[256*14]; + char font_8[256*8]; + char font_14[256*14]; #ifdef STD8X16FONT extern #endif - u_char font_16[256*16]; - u_char palette[256*3]; -static u_char *cut_buffer; + unsigned char font_16[256*16]; + char palette[256*3]; +static char *mode_map[MODE_MAP_SIZE]; +static char vgaregs[MODE_PARAM_SIZE]; +static char vgaregs2[MODE_PARAM_SIZE]; +static int rows_offset = 1; +static char *cut_buffer; static int cut_buffer_size; -static int mouse_level; /* sysmouse protocol level */ +static int mouse_level = 0; /* sysmouse protocol level */ static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; -#ifndef PC98 static u_short mouse_and_mask[16] = { 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, @@ -212,22 +235,17 @@ static u_short mouse_or_mask[16] = { 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000 }; -#endif - int sc_history_size = SC_HISTORY_SIZE; -static int extra_history_size = +static int extra_history_size = SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS; static void none_saver(int blank) { } static void (*current_saver)(int blank) = none_saver; - d_ioctl_t *sc_user_ioctl; +static void (*default_saver)(int blank) = none_saver; +int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data, + int flag, struct proc *p) = NULL; static int sticky_splash = FALSE; -static struct { - u_int8_t cursor_start; - u_int8_t cursor_end; - u_int8_t shift_state; - } bios_value; /* OS specific stuff */ #ifdef not_yet_done @@ -243,92 +261,81 @@ static struct tty sccons[MAXCONS+2]; #endif #define SC_MOUSE 128 #define SC_CONSOLE 255 -u_short *Crtat; #ifdef PC98 -u_short *Atrat; static u_char default_kanji = UJIS; +u_short *Crtat; +u_short *Atrat; +#else +#define MONO_BUF pa_to_va(0xB0000) +#define CGA_BUF pa_to_va(0xB8000) +u_short *Crtat; #endif static const int nsccons = MAXCONS+2; #define WRAPHIST(scp, pointer, offset)\ - ((scp)->history + ((((pointer) - (scp)->history) + (scp)->history_size \ - + (offset)) % (scp)->history_size)) + ((scp->history) + ((((pointer) - (scp->history)) + (scp->history_size)\ + + (offset)) % (scp->history_size))) #ifdef PC98 #define WRAPHIST_A(scp, pointer, offset)\ - ((scp->his_atr) + ((((pointer) - (scp->his_atr)) + (scp)->history_size \ - + (offset)) % (scp)->history_size)) + ((scp->his_atr) + ((((pointer) - (scp->his_atr)) + (scp->history_size)\ + + (offset)) % (scp->history_size))) #endif #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) -/* some useful macros */ -#define kbd_read_char(kbd, wait) \ - (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait)) -#define kbd_check_char(kbd) \ - (*kbdsw[(kbd)->kb_index]->check_char)((kbd)) -#define kbd_enable(kbd) \ - (*kbdsw[(kbd)->kb_index]->enable)((kbd)) -#define kbd_disable(kbd) \ - (*kbdsw[(kbd)->kb_index]->disable)((kbd)) -#define kbd_lock(kbd, lockf) \ - (*kbdsw[(kbd)->kb_index]->lock)((kbd), (lockf)) -#define kbd_ioctl(kbd, cmd, arg) \ - (((kbd) == NULL) ? \ - ENODEV : (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (arg))) -#define kbd_clear_state(kbd) \ - (*kbdsw[(kbd)->kb_index]->clear_state)((kbd)) -#define kbd_get_fkeystr(kbd, fkey, len) \ - (*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len)) +/* this should really be in `rtc.h' */ +#define RTC_EQUIPMENT 0x14 /* prototypes */ static int scattach(struct isa_device *dev); -static kbd_callback_func_t sckbdevent; static int scparam(struct tty *tp, struct termios *t); static int scprobe(struct isa_device *dev); -static int scvidprobe(int unit, int flags, int cons); -static int sckbdprobe(int unit, int flags, int cons); +static int scvidprobe(int unit, int flags); +static int sckbdprobe(int unit, int flags); static void scstart(struct tty *tp); static void scmousestart(struct tty *tp); static void scinit(void); static void scshutdown(int howto, void *arg); -static u_int scgetc(keyboard_t *kbd, u_int flags); +static void map_mode_table(char *map[], char *table, int max); +static int map_mode_num(int mode); +static char *get_mode_param(scr_stat *scp, int mode); +static u_int scgetc(u_int flags); #define SCGETC_CN 1 #define SCGETC_NONBLOCK 2 -static int sccngetch(int flags); static void sccnupdate(scr_stat *scp); +static scr_stat *get_scr_stat(dev_t dev); static scr_stat *alloc_scp(void); static void init_scp(scr_stat *scp); -static void get_bios_values(void); static void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark); static int get_scr_num(void); static timeout_t scrn_timer; static void scrn_update(scr_stat *scp, int show_cursor); -#if NSPLASH > 0 -static int scsplash_callback(int); -static void scsplash_saver(int show); -static int add_scrn_saver(void (*this_saver)(int)); -static int remove_scrn_saver(void (*this_saver)(int)); -static int set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border); -static int restore_scrn_saver_mode(scr_stat *scp, int changemode); static void stop_scrn_saver(void (*saver)(int)); static int wait_scrn_saver_stop(void); -#define scsplash_stick(stick) (sticky_splash = (stick)) -#else -#define scsplash_stick(stick) -#endif /* NSPLASH */ +static void clear_screen(scr_stat *scp); static int switch_scr(scr_stat *scp, u_int next_scr); static void exchange_scr(void); +static void move_crsr(scr_stat *scp, int x, int y); static void scan_esc(scr_stat *scp, u_char c); -static void ansi_put(scr_stat *scp, u_char *buf, int len); static void draw_cursor_image(scr_stat *scp); static void remove_cursor_image(scr_stat *scp); -static void move_crsr(scr_stat *scp, int x, int y); +static void ansi_put(scr_stat *scp, u_char *buf, int len); +static u_char *get_fstr(u_int c, u_int *len); static void history_to_screen(scr_stat *scp); static int history_up_line(scr_stat *scp); static int history_down_line(scr_stat *scp); static int mask2attr(struct term_stat *term); -static int save_kbd_state(scr_stat *scp); -static int update_kbd_state(int state, int mask); -static int update_kbd_leds(int which); +static void set_keyboard(int command, int data); +static void update_leds(int which); +static void set_vgaregs(char *modetable); +static void read_vgaregs(char *buf); +#define COMP_IDENTICAL 0 +#define COMP_SIMILAR 1 +#define COMP_DIFFERENT 2 +static int comp_vgaregs(u_char *buf1, u_char *buf2); +static void dump_vgaregs(u_char *buf); +#define PARAM_BUFSIZE 6 +static void set_font_mode(u_char *buf); +static void set_normal_mode(u_char *buf); static void set_destructive_cursor(scr_stat *scp); static void set_mouse_pos(scr_stat *scp); static int skip_spc_right(scr_stat *scp, u_short *p); @@ -344,16 +351,16 @@ static void draw_mouse_image(scr_stat *scp); static void remove_mouse_image(scr_stat *scp); static void draw_cutmarking(scr_stat *scp); static void remove_cutmarking(scr_stat *scp); +static void save_palette(void); static void do_bell(scr_stat *scp, int pitch, int duration); static timeout_t blink_screen; - -static cn_probe_t sccnprobe; -static cn_init_t sccninit; -static cn_getc_t sccngetc; -static cn_checkc_t sccncheckc; -static cn_putc_t sccnputc; - -CONS_DRIVER(sc, sccnprobe, sccninit, sccngetc, sccncheckc, sccnputc); +#ifdef SC_SPLASH_SCREEN +static void scsplash_init(void); +static void scsplash(int show); +#define scsplash_stick(stick) (sticky_splash = (stick)) +#else +#define scsplash_stick(stick) +#endif struct isa_driver scdriver = { scprobe, scattach, "sc", 1 @@ -364,6 +371,7 @@ static d_close_t scclose; static d_read_t scread; static d_write_t scwrite; static d_ioctl_t scioctl; +static d_devtotty_t scdevtotty; static d_mmap_t scmmap; #define CDEV_MAJOR 12 @@ -412,27 +420,31 @@ at2pc98(unsigned int attr) } #endif +/* + * These functions need to be before calls to them so they can be inlined. + */ static void draw_cursor_image(scr_stat *scp) { + u_short cursor_image, *ptr; + u_short prev_image; #ifdef PC98 - (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, scp->xpos, scp->ypos); + int pos = scp->cursor_pos - scp->scr_buf; + while((inb(TEXT_GDC + 0) & 0x04) == 0) {} + outb(TEXT_GDC + 2, 0x49); /* CSRW */ + outb(TEXT_GDC + 0, pos & 0xff); /* EADl */ + outb(TEXT_GDC + 0, pos >> 8); /* EADh */ #else - u_short cursor_image; - u_short *ptr; - u_short prev_image; + ptr = Crtat + (scp->cursor_pos - scp->scr_buf); - if (ISPIXELSC(scp)) { + if (VESA_MODE(scp->mode)) { sc_bcopy(scp, scp->scr_buf, scp->cursor_pos - scp->scr_buf, scp->cursor_pos - scp->scr_buf, 1); return; } - ptr = (u_short *)(scp->adp->va_window) - + (scp->cursor_pos - scp->scr_buf); - /* do we have a destructive cursor ? */ - if (sc_flags & CHAR_CURSOR) { + if (flags & CHAR_CURSOR) { prev_image = scp->cursor_saveunder; cursor_image = *ptr & 0x00ff; if (cursor_image == DEAD_CHAR) @@ -443,7 +455,7 @@ draw_cursor_image(scr_stat *scp) if (prev_image != cursor_image) set_destructive_cursor(scp); /* modify cursor_image */ - if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ + if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ /* * When the mouse pointer is at the same position as the cursor, * the cursor bitmap needs to be updated even if the char under @@ -459,7 +471,7 @@ draw_cursor_image(scr_stat *scp) } else { cursor_image = (*(ptr) & 0x00ff) | *(scp->cursor_pos) & 0xff00; scp->cursor_saveunder = cursor_image; - if (!(sc_flags & BLINK_CURSOR)||((sc_flags & BLINK_CURSOR)&&(blinkrate & 4))){ + if (!(flags & BLINK_CURSOR)||((flags & BLINK_CURSOR)&&(blinkrate & 4))){ if ((cursor_image & 0x7000) == 0x7000) { cursor_image &= 0x8fff; if(!(cursor_image & 0x0700)) @@ -479,13 +491,11 @@ static void remove_cursor_image(scr_stat *scp) { #ifndef PC98 - if (ISPIXELSC(scp)) + if (VESA_MODE(scp->mode)) sc_bcopy(scp, scp->scr_buf, scp->cursor_oldpos - scp->scr_buf, - scp->cursor_oldpos - scp->scr_buf, 0); + scp->cursor_oldpos - scp->scr_buf, 0); else - *((u_short *)(scp->adp->va_window) - + (scp->cursor_oldpos - scp->scr_buf)) - = scp->cursor_saveunder; + *(Crtat + (scp->cursor_oldpos - scp->scr_buf)) = scp->cursor_saveunder; #endif } @@ -511,72 +521,303 @@ move_crsr(scr_stat *scp, int x, int y) static int scprobe(struct isa_device *dev) { - if (!scvidprobe(dev->id_unit, dev->id_flags, FALSE)) { + if (!scvidprobe(dev->id_unit, dev->id_flags)) { if (bootverbose) printf("sc%d: no video adapter is found.\n", dev->id_unit); return (0); } - return ((sckbdprobe(dev->id_unit, dev->id_flags, FALSE)) ? -1 : 0); + sc_port = dev->id_iobase; + if (sckbdprobe(dev->id_unit, dev->id_flags)) + return (IO_KBDSIZE); + else + return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); } /* probe video adapters, return TRUE if found */ static int -scvidprobe(int unit, int flags, int cons) +scvidprobe(int unit, int flags) { - video_adapter_t *adp; + /* + * XXX don't try to `printf' anything here, the console may not have + * been configured yet. + */ + u_short volatile *cp; + u_short was; + u_int pa; + u_int segoff; + + /* do this test only once */ + if (init_done != COLD) + return (Crtat != 0); /* - * Access the video adapter driver through the back door! - * Video adapter drivers need to be configured before syscons. - * However, when syscons is being probed as the low-level console, - * they have not been initialized yet. We force them to initialize - * themselves here. XXX + * Finish defaulting crtc variables for a mono screen. Crtat is a + * bogus common variable so that it can be shared with pcvt, so it + * can't be statically initialized. XXX. */ - vid_configure(cons ? VIO_PROBE_ONLY : 0); - - /* allocate a frame buffer */ - if (adapter < 0) { - adapter = vid_allocate("*", -1, (void *)&adapter); - if (adapter < 0) +#ifdef PC98 + Crtat = (u_short *)TEXT_VRAM; + Atrat = (u_short *)TEXT_VRAM + ATTR_OFFSET; + crtc_type = KD_PC98; +#else + Crtat = (u_short *)MONO_BUF; + crtc_type = KD_MONO; + /* If CGA memory seems to work, switch to color. */ + cp = (u_short *)CGA_BUF; + was = *cp; + *cp = (u_short) 0xA55A; + bios_video_mode = *(u_char *)pa_to_va(0x449); + if (bootinfo.bi_vesa == 0x102) { + bios_video_mode = bootinfo.bi_vesa; + Crtat = (u_short *)pa_to_va(0xA0000); + crtc_addr = COLOR_BASE; + crtc_type = KD_VGA; + bzero(Crtat, 800*600/8); + } else if (*cp == 0xA55A) { + Crtat = (u_short *)CGA_BUF; + crtc_addr = COLOR_BASE; + crtc_type = KD_CGA; + } else { + cp = Crtat; + was = *cp; + *cp = (u_short) 0xA55A; + if (*cp != 0xA55A) { + /* no screen at all, bail out */ + Crtat = 0; return FALSE; + } } - adp = vid_get_adapter(adapter); /* shouldn't fail */ + *cp = was; - Crtat = (u_short *)adp->va_window; -#ifdef PC98 - Atrat = Crtat + ATTR_OFFSET; -#endif - initial_video_mode = adp->va_initial_mode; + if (!VESA_MODE(bios_video_mode)) { + /* + * Check rtc and BIOS date area. + * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy + * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are + * zeros for EGA and VGA. However, the EGA/VGA BIOS will set + * these bits in BIOSDATA_EQUIPMENT according to the monitor + * type detected. + */ + switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ + case 0: /* EGA/VGA, or nothing */ + crtc_type = KD_EGA; + /* the color adapter may be in the 40x25 mode... XXX */ + break; + case 1: /* CGA 40x25 */ + /* switch to the 80x25 mode? XXX */ + /* FALL THROUGH */ + case 2: /* CGA 80x25 */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_CGA; */ + break; + case 3: /* MDA */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_MONO; */ + break; + } + + /* is this a VGA or higher ? */ + outb(crtc_addr, 7); + if (inb(crtc_addr) == 7) { + crtc_type = KD_VGA; + crtc_vga = TRUE; + read_vgaregs(vgaregs); + + /* Get the BIOS video mode pointer */ + segoff = *(u_int *)pa_to_va(0x4a8); + pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff); + if (ISMAPPED(pa, sizeof(u_int))) { + segoff = *(u_int *)pa_to_va(pa); + pa = ((segoff & 0xffff0000) >> 12) + (segoff & 0xffff); + if (ISMAPPED(pa, MODE_PARAM_SIZE)) + video_mode_ptr = (char *)pa_to_va(pa); + } + } + } +#endif /* PC98 */ return TRUE; } /* probe the keyboard, return TRUE if found */ static int -sckbdprobe(int unit, int flags, int cons) +sckbdprobe(int unit, int flags) { - /* access the keyboard driver through the backdoor! */ - kbd_configure(cons ? KB_CONF_PROBE_ONLY : 0); + int codeset; + int c = -1; + int m; + int res, id; - /* allocate a keyboard and register the keyboard event handler */ - if (keyboard < 0) { - keyboard = kbd_allocate("*", -1, (void *)&keyboard, sckbdevent, NULL); - if (keyboard < 0) - return FALSE; + sc_kbdc = kbdc_open(sc_port); +#ifndef PC98 + if (!kbdc_lock(sc_kbdc, TRUE)) { + /* driver error? */ + printf("sc%d: unable to lock the controller.\n", unit); + return ((flags & DETECT_KBD) ? FALSE : TRUE); + } + + /* discard anything left after UserConfig */ + empty_both_buffers(sc_kbdc, 10); + + /* save the current keyboard controller command byte */ + m = kbdc_get_device_mask(sc_kbdc) & ~KBD_KBD_CONTROL_BITS; + c = get_controller_command_byte(sc_kbdc); + if (c == -1) { + /* CONTROLLER ERROR */ + printf("sc%d: unable to get the current command byte value.\n", unit); + goto fail; + } + if (bootverbose) + printf("sc%d: the current keyboard controller command byte %04x\n", + unit, c); +#if 0 + /* override the keyboard lock switch */ + c |= KBD_OVERRIDE_KBD_LOCK; +#endif + + /* + * The keyboard may have been screwed up by the boot block. + * We may just be able to recover from error by testing the controller + * and the keyboard port. The controller command byte needs to be saved + * before this recovery operation, as some controllers seem to set + * the command byte to particular values. + */ + test_controller(sc_kbdc); + test_kbd_port(sc_kbdc); + + /* enable the keyboard port, but disable the keyboard intr. */ + if (!set_controller_command_byte(sc_kbdc, + KBD_KBD_CONTROL_BITS, + KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { + /* CONTROLLER ERROR + * there is very little we can do... + */ + printf("sc%d: unable to set the command byte.\n", unit); + goto fail; + } + + /* + * Check if we have an XT keyboard before we attempt to reset it. + * The procedure assumes that the keyboard and the controller have + * been set up properly by BIOS and have not been messed up + * during the boot process. + */ + codeset = -1; + if (flags & XT_KEYBD) + /* the user says there is a XT keyboard */ + codeset = 1; +#ifdef DETECT_XT_KEYBOARD + else if ((c & KBD_TRANSLATION) == 0) { + /* SET_SCANCODE_SET is not always supported; ignore error */ + if (send_kbd_command_and_data(sc_kbdc, KBDC_SET_SCANCODE_SET, 0) + == KBD_ACK) + codeset = read_kbd_data(sc_kbdc); + } + if (bootverbose) + printf("sc%d: keyboard scancode set %d\n", unit, codeset); +#endif /* DETECT_XT_KEYBOARD */ + + if (flags & KBD_NORESET) { + write_kbd_command(sc_kbdc, KBDC_ECHO); + if (read_kbd_data(sc_kbdc) != KBD_ECHO) { + empty_both_buffers(sc_kbdc, 10); + test_controller(sc_kbdc); + test_kbd_port(sc_kbdc); + if (bootverbose) + printf("sc%d: failed to get response from the keyboard.\n", + unit); + goto fail; + } + } else { + /* reset keyboard hardware */ + if (!reset_kbd(sc_kbdc)) { + /* KEYBOARD ERROR + * Keyboard reset may fail either because the keyboard doen't + * exist, or because the keyboard doesn't pass the self-test, + * or the keyboard controller on the motherboard and the keyboard + * somehow fail to shake hands. It is just possible, particularly + * in the last case, that the keyoard controller may be left + * in a hung state. test_controller() and test_kbd_port() appear + * to bring the keyboard controller back (I don't know why and + * how, though.) + */ + empty_both_buffers(sc_kbdc, 10); + test_controller(sc_kbdc); + test_kbd_port(sc_kbdc); + /* We could disable the keyboard port and interrupt... but, + * the keyboard may still exist (see above). + */ + if (bootverbose) + printf("sc%d: failed to reset the keyboard.\n", unit); + goto fail; + } + } + + /* + * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards + * such as those on the IBM ThinkPad laptop computers can be used + * with the standard console driver. + */ + if (codeset == 1) { + if (send_kbd_command_and_data( + sc_kbdc, KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) { + /* XT kbd doesn't need scan code translation */ + c &= ~KBD_TRANSLATION; + } else { + /* KEYBOARD ERROR + * The XT kbd isn't usable unless the proper scan code set + * is selected. + */ + printf("sc%d: unable to set the XT keyboard mode.\n", unit); + goto fail; + } + } + /* enable the keyboard port and intr. */ + if (!set_controller_command_byte(sc_kbdc, + KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, + (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK)) + | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { + /* CONTROLLER ERROR + * This is serious; we are left with the disabled keyboard intr. + */ + printf("sc%d: unable to enable the keyboard port and intr.\n", unit); + goto fail; + } + + /* Get the ID of the keyboard, if any */ + empty_kbd_buffer(sc_kbdc, 5); + res = send_kbd_command(sc_kbdc, KBDC_SEND_DEV_ID); + if (res == KBD_ACK) { + /* 10ms delay */ + DELAY(10000); + id = (read_kbd_data(sc_kbdc) << 8) | read_kbd_data(sc_kbdc); + if (bootverbose) + printf("sc%d: keyboard device ID: %04x\n", unit, id); } - kbd = kbd_get_keyboard(keyboard); /* shouldn't fail */ + kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), + kbdc_lock(sc_kbdc, FALSE); +#endif /* !PC98 */ return TRUE; +#ifndef PC98 +fail: + if (c != -1) + /* try to restore the command byte as before, if possible */ + set_controller_command_byte(sc_kbdc, 0xff, c); + kbdc_set_device_mask(sc_kbdc, + (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); + kbdc_lock(sc_kbdc, FALSE); + return FALSE; +#endif /* !PC98 */ } #if NAPM > 0 static int scresume(void *dummy) { - if (kbd != NULL) - kbd_clear_state(kbd); - return 0; + shfts = ctls = alts = agrs = metas = accents = 0; + return 0; } #endif @@ -584,85 +825,117 @@ static int scattach(struct isa_device *dev) { scr_stat *scp; -#if defined(VESA) && defined(VM86) - video_info_t info; -#endif dev_t cdev = makedev(CDEV_MAJOR, 0); + char *p; #ifdef DEVFS int vc; #endif scinit(); + flags = dev->id_flags; + if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode)) + flags &= ~CHAR_CURSOR; + scp = console[0]; - sc_flags = dev->id_flags; - if (!ISFONTAVAIL(scp->adp->va_flags)) - sc_flags &= ~CHAR_CURSOR; + + if (crtc_type == KD_VGA) { + cut_buffer_size = scp->xsize * scp->ysize + 1; + cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT); + if (cut_buffer != NULL) + cut_buffer[0] = '\0'; + } + + scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), + M_DEVBUF, M_NOWAIT); +#ifdef PC98 + scp->atr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), + M_DEVBUF, M_NOWAIT); +#endif /* copy temporary buffer to final buffer */ - scp->scr_buf = NULL; + bcopy(sc_buffer, scp->scr_buf, scp->xsize * scp->ysize * sizeof(u_short)); + #ifdef PC98 - scp->atr_buf = NULL; + bcopy(Atrat, scp->atr_buf, scp->xsize * scp->ysize * sizeof(u_short)); #endif - sc_alloc_scr_buffer(scp, FALSE, FALSE); - bcopy(sc_buffer, scp->scr_buf, scp->xsize*scp->ysize*sizeof(u_short)); + scp->cursor_pos = scp->cursor_oldpos = + scp->scr_buf + scp->xpos + scp->ypos * scp->xsize; #ifdef PC98 - bcopy(Atrat, scp->atr_buf, scp->xsize*scp->ysize*sizeof(u_short)); + scp->cursor_atr = + scp->atr_buf + scp->xpos + scp->ypos * scp->xsize; #endif - - /* cut buffer is available only when the mouse pointer is used */ - if (ISMOUSEAVAIL(scp->adp->va_flags)) - sc_alloc_cut_buffer(scp, FALSE); + scp->mouse_pos = scp->mouse_oldpos = + scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + + scp->mouse_xpos/8); /* initialize history buffer & pointers */ - sc_alloc_history_buffer(scp, sc_history_size, 0, FALSE); - -#if defined(VESA) && defined(VM86) - if ((sc_flags & VESA800X600) - && ((*vidsw[scp->ad]->get_info)(scp->adp, M_VESA_800x600, &info) == 0)) { -#if NSPLASH > 0 - splash_term(scp->adp); -#endif - sc_set_graphics_mode(scp, NULL, M_VESA_800x600); - sc_set_pixel_mode(scp, NULL, COL, ROW, 16); - initial_video_mode = M_VESA_800x600; -#if NSPLASH > 0 - /* put up the splash again! */ - splash_init(scp->adp, scsplash_callback); + scp->history_head = scp->history_pos = + (u_short *)malloc(scp->history_size*sizeof(u_short), + M_DEVBUF, M_NOWAIT); + if (scp->history_head != NULL) + bzero(scp->history_head, scp->history_size*sizeof(u_short)); + scp->history = scp->history_head; +#ifdef PC98 + scp->his_atr_head = scp->his_atr_pos = + (u_short *)malloc(scp->history_size*sizeof(u_short), + M_DEVBUF, M_NOWAIT); + if (scp->his_atr_head != NULL) + bzero(scp->his_atr_head, scp->history_size*sizeof(u_short)); + scp->his_atr = scp->his_atr_pos; #endif - } -#endif /* VESA && VM86 */ /* initialize cursor stuff */ - if (!ISGRAPHSC(scp)) + if (!(scp->status & UNKNOWN_MODE)) draw_cursor_image(scp); /* get screen update going */ scrn_timer((void *)TRUE); - /* set up the keyboard */ - kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); - update_kbd_state(scp->status, LOCK_MASK); + update_leds(scp->status); - if (bootverbose) { - printf("sc%d:", dev->id_unit); - if (adapter >= 0) - printf(" fb%d", adapter); - if (keyboard >= 0) - printf(" kbd%d", keyboard); - printf("\n"); +#ifndef PC98 + if ((crtc_type == KD_VGA) && bootverbose) { + printf("sc%d: BIOS video mode:%d\n", dev->id_unit, bios_video_mode); + printf("sc%d: VGA registers upon power-up\n", dev->id_unit); + dump_vgaregs(vgaregs); + printf("sc%d: video mode:%d\n", dev->id_unit, scp->mode); + printf("sc%d: VGA registers in BIOS for mode:%d\n", + dev->id_unit, scp->mode); + dump_vgaregs(vgaregs2); + p = get_mode_param(scp, scp->mode); + if (p != NULL) { + printf("sc%d: VGA registers to be used for mode:%d\n", + dev->id_unit, scp->mode); + dump_vgaregs(p); + } + printf("sc%d: rows_offset:%d\n", dev->id_unit, rows_offset); } + if ((crtc_type == KD_VGA) && !VESA_MODE(bios_video_mode) + && (video_mode_ptr == NULL)) + printf("sc%d: WARNING: video mode switching is only partially supported\n", + dev->id_unit); +#endif + printf("sc%d: ", dev->id_unit); - switch(scp->adp->va_type) { + switch(crtc_type) { #ifdef PC98 case KD_PC98: printf(" <text mode>"); break; #else case KD_VGA: - printf("VGA %s", (scp->adp->va_flags & V_ADP_COLOR) ? "color" : "mono"); + if (VESA_MODE(bios_video_mode)) + printf("Graphics display (VESA mode = 0x%x)", bios_video_mode); + else if (crtc_addr == MONO_BASE) + printf("VGA mono"); + else + printf("VGA color"); break; case KD_EGA: - printf("EGA %s", (scp->adp->va_flags & V_ADP_COLOR) ? "color" : "mono"); + if (crtc_addr == MONO_BASE) + printf("EGA mono"); + else + printf("EGA color"); break; case KD_CGA: printf("CGA"); @@ -670,11 +943,11 @@ scattach(struct isa_device *dev) case KD_MONO: case KD_HERCULES: default: - printf("MDA/Hercules"); + printf("MDA/hercules"); break; #endif /* PC98 */ } - printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, sc_flags); + printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); #if NAPM > 0 scp->r_hook.ah_fun = scresume; @@ -720,8 +993,6 @@ int scopen(dev_t dev, int flag, int mode, struct proc *p) { struct tty *tp = scdevtotty(dev); - keyarg_t key; - int s; if (!tp) return(ENXIO); @@ -733,9 +1004,7 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) ttychars(tp); /* Use the current setting of the <-- key as default VERASE. */ /* If the Delete key is preferable, an stty is necessary */ - key.keynum = 0x0e; /* how do we know this magic number... XXX */ - kbd_ioctl(kbd, GIO_KEYMAPENT, (caddr_t)&key); - tp->t_cc[VERASE] = key.key.map[0]; + tp->t_cc[VERASE] = key_map.key[0x0e].map[0]; tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; @@ -745,20 +1014,12 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) (*linesw[tp->t_line].l_modem)(tp, 1); if (minor(dev) == SC_MOUSE) mouse_level = 0; /* XXX */ - if (minor(dev) < MAXCONS && console[minor(dev)] && scrn_blanked) { - s = spltty(); - sc_touch_scrn_saver(); - sc_clean_up(console[minor(dev)]); - splx(s); - } } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) return(EBUSY); if (minor(dev) < MAXCONS && !console[minor(dev)]) { console[minor(dev)] = alloc_scp(); - if (ISGRAPHSC(console[minor(dev)])) - sc_set_pixel_mode(console[minor(dev)], NULL, COL, ROW, 16); } if (minor(dev)<MAXCONS && !tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { tp->t_winsize.ws_col = console[minor(dev)]->xsize; @@ -776,7 +1037,7 @@ scclose(dev_t dev, int flag, int mode, struct proc *p) if (!tp) return(ENXIO); if (minor(dev) < MAXCONS) { - scp = sc_get_scr_stat(tp->t_dev); + scp = get_scr_stat(tp->t_dev); if (scp->status & SWITCH_WAIT_ACQ) wakeup((caddr_t)&scp->smode); #if not_yet_done @@ -795,9 +1056,9 @@ scclose(dev_t dev, int flag, int mode, struct proc *p) if (scp->history != NULL) { free(scp->history, M_DEVBUF); if (scp->history_size / scp->xsize - > imax(sc_history_size, scp->ysize)) + > imax(SC_HISTORY_SIZE, scp->ysize)) extra_history_size += scp->history_size / scp->xsize - - imax(sc_history_size, scp->ysize); + - imax(SC_HISTORY_SIZE, scp->ysize); } free(scp, M_DEVBUF); console[minor(dev)] = NULL; @@ -835,53 +1096,38 @@ scwrite(dev_t dev, struct uio *uio, int flag) return((*linesw[tp->t_line].l_write)(tp, uio, flag)); } -static int -sckbdevent(keyboard_t *thiskbd, int event, void *arg) +void +scintr(int unit) { static struct tty *cur_tty; - int c; - size_t len; + int c, len; u_char *cp; - /* assert(thiskbd == kbd) */ - - switch (event) { - case KBDIO_KEYINPUT: - break; - case KBDIO_UNLOADING: - kbd = NULL; - kbd_release(thiskbd, (void *)&keyboard); - return 0; - default: - return EINVAL; - } - /* * Loop while there is still input to get from the keyboard. * I don't think this is nessesary, and it doesn't fix * the Xaccel-2.1 keyboard hang, but it can't hurt. XXX */ - while ((c = scgetc(thiskbd, SCGETC_NONBLOCK)) != NOKEY) { + while ((c = scgetc(SCGETC_NONBLOCK)) != NOKEY) { cur_tty = VIRTUAL_TTY(get_scr_num()); if (!(cur_tty->t_state & TS_ISOPEN)) if (!((cur_tty = CONSOLE_TTY)->t_state & TS_ISOPEN)) continue; - switch (KEYFLAGS(c)) { + switch (c & 0xff00) { case 0x0000: /* normal key */ - (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty); + (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); break; case FKEY: /* function key, return string */ - cp = kbd_get_fkeystr(thiskbd, KEYCHAR(c), &len); - if (cp != NULL) { + if (cp = get_fstr((u_int)c, (u_int *)&len)) { while (len-- > 0) - (*linesw[cur_tty->t_line].l_rint)(*cp++, cur_tty); + (*linesw[cur_tty->t_line].l_rint)(*cp++ & 0xFF, cur_tty); } break; case MKEY: /* meta is active, prepend ESC */ (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); - (*linesw[cur_tty->t_line].l_rint)(KEYCHAR(c), cur_tty); + (*linesw[cur_tty->t_line].l_rint)(c & 0xFF, cur_tty); break; case BKEY: /* backtab fixed sequence (esc [ Z) */ (*linesw[cur_tty->t_line].l_rint)(0x1b, cur_tty); @@ -891,11 +1137,10 @@ sckbdevent(keyboard_t *thiskbd, int event, void *arg) } } - if (cur_console->status & MOUSE_VISIBLE) { - remove_mouse_image(cur_console); + if (cur_console->status & MOUSE_ENABLED) { cur_console->status &= ~MOUSE_VISIBLE; + remove_mouse_image(cur_console); } - return 0; } static int @@ -910,29 +1155,28 @@ scparam(struct tty *tp, struct termios *t) int scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { - u_int delta_ehs; int error; - int i; + u_int i; struct tty *tp; scr_stat *scp; + u_short *usp; +#ifdef PC98 + u_short *atr_usp; +#endif + char *mp; int s; tp = scdevtotty(dev); if (!tp) return ENXIO; - scp = sc_get_scr_stat(tp->t_dev); + scp = get_scr_stat(tp->t_dev); /* If there is a user_ioctl function call that first */ if (sc_user_ioctl) { - error = (*sc_user_ioctl)(dev, cmd, data, flag, p); - if (error != ENOIOCTL) + if (error = (*sc_user_ioctl)(dev, cmd, data, flag, p)) return error; } - error = sc_vid_ioctl(tp, cmd, data, flag, p); - if (error != ENOIOCTL) - return error; - switch (cmd) { /* process console hardware related ioctl's */ case GIO_ATTR: /* get current attributes */ @@ -940,7 +1184,22 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case GIO_COLOR: /* is this a color console ? */ - *(int *)data = (scp->adp->va_flags & V_ADP_COLOR) ? 1 : 0; +#ifdef PC98 + *(int*)data = 0; +#else + if (crtc_addr == COLOR_BASE) + *(int*)data = 1; + else + *(int*)data = 0; +#endif + return 0; + + case CONS_CURRENT: /* get current adapter type */ + *(int *)data = crtc_type; + return 0; + + case CONS_GET: /* get current video mode */ + *(int*)data = scp->mode; return 0; case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */ @@ -954,38 +1213,36 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case CONS_CURSORTYPE: /* set cursor type blink/noblink */ if ((*(int*)data) & 0x01) - sc_flags |= BLINK_CURSOR; + flags |= BLINK_CURSOR; else - sc_flags &= ~BLINK_CURSOR; + flags &= ~BLINK_CURSOR; if ((*(int*)data) & 0x02) { - if (!ISFONTAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode)) return ENXIO; - sc_flags |= CHAR_CURSOR; + flags |= CHAR_CURSOR; } else - sc_flags &= ~CHAR_CURSOR; + flags &= ~CHAR_CURSOR; /* * The cursor shape is global property; all virtual consoles * are affected. Update the cursor in the current console... */ - if (!ISGRAPHSC(cur_console)) { - s = spltty(); + if (!(cur_console->status & UNKNOWN_MODE)) { remove_cursor_image(cur_console); - if (sc_flags & CHAR_CURSOR) + if (flags & CHAR_CURSOR) set_destructive_cursor(cur_console); draw_cursor_image(cur_console); - splx(s); } return 0; case CONS_BELLTYPE: /* set bell type sound/visual */ if ((*(int *)data) & 0x01) - sc_flags |= VISUAL_BELL; + flags |= VISUAL_BELL; else - sc_flags &= ~VISUAL_BELL; + flags &= ~VISUAL_BELL; if ((*(int *)data) & 0x02) - sc_flags |= QUIET_BELL; + flags |= QUIET_BELL; else - sc_flags &= ~QUIET_BELL; + flags &= ~QUIET_BELL; return 0; case CONS_HISTORY: /* set history size */ @@ -996,22 +1253,50 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) lines = imax(*(int *)data, scp->ysize); lines0 = (scp->history != NULL) ? scp->history_size / scp->xsize : scp->ysize; - if (lines0 > imax(sc_history_size, scp->ysize)) - delta_ehs = lines0 - imax(sc_history_size, scp->ysize); - else - delta_ehs = 0; /* * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE * lines or scp->ysize lines, whichever is larger. A value * greater than that is allowed, subject to extra_history_size. */ - if (lines > imax(sc_history_size, scp->ysize)) - if (lines - imax(sc_history_size, scp->ysize) > - extra_history_size + delta_ehs) - return EINVAL; + if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size) + return EINVAL; if (cur_console->status & BUFFER_SAVED) return EBUSY; - sc_alloc_history_buffer(scp, lines, delta_ehs, TRUE); + usp = scp->history; + scp->history = NULL; + if (usp != NULL) + free(usp, M_DEVBUF); +#ifdef PC98 + atr_usp = scp->his_atr; + scp->his_atr = NULL; + if (atr_usp != NULL) + free(atr_usp, M_DEVBUF); +#endif + scp->history_size = lines * scp->xsize; + /* + * extra_history_size += + * (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ? + * lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; + * extra_history_size -= + * (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ? + * lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0; + * lines0 >= ysize && lines >= ysize... Hey, the above can be + * reduced to the following... + */ + extra_history_size += + imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE); + usp = (u_short *)malloc(scp->history_size * sizeof(u_short), + M_DEVBUF, M_WAITOK); + bzero(usp, scp->history_size * sizeof(u_short)); + scp->history_head = scp->history_pos = usp; + scp->history = usp; +#ifdef PC98 + atr_usp = (u_short *)malloc(scp->history_size * sizeof(u_short), + M_DEVBUF, M_WAITOK); + bzero(atr_usp, scp->history_size * sizeof(u_short)); + scp->his_atr_head = scp->his_atr_pos = atr_usp; + scp->his_atr = atr_usp; +#endif return 0; } else @@ -1021,8 +1306,9 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case OLD_CONS_MOUSECTL: { /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ - static int butmap[8] = { - MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, + static butmap[8] = { + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP + | MOUSE_MSC_BUTTON3UP, MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, MOUSE_MSC_BUTTON3UP, @@ -1034,12 +1320,11 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) mouse_info_t *mouse = (mouse_info_t*)data; mouse_info_t buf; - /* FIXME: */ - if (!ISMOUSEAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA || VESA_MODE(bios_video_mode)) return ENODEV; if (cmd == OLD_CONS_MOUSECTL) { - static u_char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + static unsigned char swapb[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; old_mouse_info_t *old_mouse = (old_mouse_info_t *)data; mouse = &buf; @@ -1084,7 +1369,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case MOUSE_SHOW: - if (ISTEXTSC(scp) && !(scp->status & MOUSE_ENABLED)) { + if (!(scp->status & MOUSE_ENABLED)) { scp->status |= (MOUSE_ENABLED | MOUSE_VISIBLE); scp->mouse_oldpos = scp->mouse_pos; mark_all(scp); @@ -1095,7 +1380,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) break; case MOUSE_HIDE: - if (ISTEXTSC(scp) && (scp->status & MOUSE_ENABLED)) { + if (scp->status & MOUSE_ENABLED) { scp->status &= ~(MOUSE_ENABLED | MOUSE_VISIBLE); mark_all(scp); return 0; @@ -1140,7 +1425,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) if (mouse_status.flags == 0) return 0; - if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) + if (cur_console->status & MOUSE_ENABLED) cur_console->status |= MOUSE_VISIBLE; if ((MOUSE_TTY)->t_state & TS_ISOPEN) { @@ -1185,7 +1470,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) else if (mouse->operation == MOUSE_ACTION && cut_buffer != NULL) { /* process button presses */ if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && - ISTEXTSC(cur_console)) { + !(cur_console->status & UNKNOWN_MODE)) { cur_console->mouse_buttons = mouse->u.data.buttons; if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) mouse_cut_start(cur_console); @@ -1222,7 +1507,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) if (mouse_status.flags == 0) return 0; - if (ISTEXTSC(cur_console) && (cur_console->status & MOUSE_ENABLED)) + if (cur_console->status & MOUSE_ENABLED) cur_console->status |= MOUSE_VISIBLE; if ((MOUSE_TTY)->t_state & TS_ISOPEN) { @@ -1251,7 +1536,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) break; } - if (!ISTEXTSC(cur_console) || (cut_buffer == NULL)) + if ((cur_console->status & UNKNOWN_MODE) || (cut_buffer == NULL)) break; switch (mouse->u.event.id) { @@ -1298,7 +1583,8 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return EINVAL; } /* make screensaver happy */ - sc_touch_scrn_saver(); + scsplash_stick(FALSE); + run_scrn_saver = FALSE; return 0; } @@ -1419,9 +1705,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) ptr->mv_grfc.fore = 0; /* not supported */ ptr->mv_grfc.back = 0; /* not supported */ ptr->mv_ovscan = scp->border; - if (scp == cur_console) - save_kbd_state(scp); - ptr->mk_keylock = scp->status & LOCK_MASK; + ptr->mk_keylock = scp->status & LOCK_KEY_MASK; return 0; } return EINVAL; @@ -1432,43 +1716,18 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case CONS_IDLE: /* see if the screen has been idle */ - /* - * When the screen is in the GRAPHICS_MODE or UNKNOWN_MODE, - * the user process may have been writing something on the - * screen and syscons is not aware of it. Declare the screen - * is NOT idle if it is in one of these modes. But there is - * an exception to it; if a screen saver is running in the - * graphics mode in the current screen, we should say that the - * screen has been idle. - */ - *(int *)data = scrn_idle - && (!ISGRAPHSC(cur_console) - || (cur_console->status & SAVER_RUNNING)); + *(int *)data = (scrn_idle && !(cur_console->status & UNKNOWN_MODE)); return 0; case CONS_SAVERMODE: /* set saver mode */ switch(*(int *)data) { case CONS_USR_SAVER: - /* if a LKM screen saver is running, stop it first. */ - scsplash_stick(FALSE); + /* if a LKM screen saver is running, it will eventually stop... */ saver_mode = *(int *)data; - s = spltty(); -#if NSPLASH > 0 - if ((error = wait_scrn_saver_stop())) { - splx(s); - return error; - } -#endif /* NSPLASH */ - scp->status |= SAVER_RUNNING; scsplash_stick(TRUE); - splx(s); break; case CONS_LKM_SAVER: - s = spltty(); - if ((saver_mode == CONS_USR_SAVER) && (scp->status & SAVER_RUNNING)) - scp->status &= ~SAVER_RUNNING; saver_mode = *(int *)data; - splx(s); break; default: return EINVAL; @@ -1487,6 +1746,279 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) splx(s); return 0; +#ifdef PC98 + case SW_PC98_80x25: + case SW_PC98_80x30: /* PC98 TEXT MODES */ + if (!crtc_vga) + return ENXIO; + scp->xsize = 80; + + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + if (scp->history != NULL) + i = imax(scp->history_size / scp->xsize + - imax(SC_HISTORY_SIZE, scp->ysize), 0); + else + i = 0; + switch (cmd & 0xff) { + case M_PC98_80x25: + scp->ysize = 25; + break; +#ifdef LINE30 + case M_PC98_80x30: + scp->ysize = LINE30_ROW; + break; +#endif + default: + return EINVAL; + } +#else /* IBM-PC */ + /* VGA TEXT MODES */ + case SW_VGA_C40x25: + case SW_VGA_C80x25: case SW_VGA_M80x25: + case SW_VGA_C80x30: case SW_VGA_M80x30: + case SW_VGA_C80x50: case SW_VGA_M80x50: + case SW_VGA_C80x60: case SW_VGA_M80x60: + case SW_B40x25: case SW_C40x25: + case SW_B80x25: case SW_C80x25: + case SW_ENH_B40x25: case SW_ENH_C40x25: + case SW_ENH_B80x25: case SW_ENH_C80x25: + case SW_ENH_B80x43: case SW_ENH_C80x43: + case SW_EGAMONO80x25: + + if (crtc_type != KD_VGA) + return ENODEV; + mp = get_mode_param(scp, cmd & 0xff); + if (mp == NULL) + return ENODEV; + + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + if (scp->history != NULL) + i = imax(scp->history_size / scp->xsize + - imax(SC_HISTORY_SIZE, scp->ysize), 0); + else + i = 0; + switch (cmd & 0xff) { + case M_VGA_C80x60: case M_VGA_M80x60: + if (!(fonts_loaded & FONT_8)) { + splx(s); + return EINVAL; + } + /* + * This is a kludge to fend off scrn_update() while we + * muck around with scp. XXX + */ + scp->status |= UNKNOWN_MODE; + scp->xsize = 80; + scp->ysize = 60; + scp->font_size = 8; + break; + case M_VGA_C80x50: case M_VGA_M80x50: + if (!(fonts_loaded & FONT_8)) { + splx(s); + return EINVAL; + } + scp->status |= UNKNOWN_MODE; + scp->xsize = 80; + scp->ysize = 50; + scp->font_size = 8; + break; + case M_ENH_B80x43: case M_ENH_C80x43: + if (!(fonts_loaded & FONT_8)) { + splx(s); + return EINVAL; + } + scp->status |= UNKNOWN_MODE; + scp->xsize = 80; + scp->ysize = 43; + scp->font_size = 8; + break; + case M_VGA_C80x30: case M_VGA_M80x30: + scp->status |= UNKNOWN_MODE; + scp->xsize = 80; + scp->ysize = 30; + scp->font_size = mp[2]; + break; + case M_ENH_C40x25: case M_ENH_B40x25: + case M_ENH_C80x25: case M_ENH_B80x25: + case M_EGAMONO80x25: + if (!(fonts_loaded & FONT_14)) { + splx(s); + return EINVAL; + } + /* FALL THROUGH */ + default: + if ((cmd & 0xff) > M_VGA_CG320) { + splx(s); + return EINVAL; + } + scp->status |= UNKNOWN_MODE; + scp->xsize = mp[0]; + scp->ysize = mp[1] + rows_offset; + scp->font_size = mp[2]; + break; + } +#endif + + scp->mode = cmd & 0xff; + scp->xpixel = scp->xsize * 8; + scp->ypixel = scp->ysize * scp->font_size; + free(scp->scr_buf, M_DEVBUF); + scp->scr_buf = (u_short *) + malloc(scp->xsize*scp->ysize*sizeof(u_short), M_DEVBUF, M_WAITOK); +#ifdef PC98 + free(scp->atr_buf, M_DEVBUF); + scp->atr_buf = (u_short *) + malloc(scp->xsize*scp->ysize*sizeof(u_short),M_DEVBUF, M_WAITOK); +#endif + /* move the text cursor to the home position */ + move_crsr(scp, 0, 0); + /* move the mouse cursor at the center of the screen */ + scp->mouse_xpos = scp->xpixel / 2; + scp->mouse_ypos = scp->ypixel / 2; + scp->mouse_pos = scp->mouse_oldpos = + scp->scr_buf + (scp->mouse_ypos / scp->font_size) * scp->xsize + + scp->mouse_xpos / 8; + /* allocate a larger cut buffer if necessary */ + if ((cut_buffer == NULL) + || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { + if (cut_buffer != NULL) + free(cut_buffer, M_DEVBUF); + cut_buffer_size = scp->xsize * scp->ysize + 1; + cut_buffer = (char *)malloc(cut_buffer_size, M_DEVBUF, M_NOWAIT); + if (cut_buffer != NULL) + cut_buffer[0] = '\0'; + } + splx(s); + + usp = scp->history; + scp->history = NULL; + if (usp != NULL) { + free(usp, M_DEVBUF); + extra_history_size += i; + } +#ifdef PC98 + atr_usp = scp->his_atr; + scp->his_atr = NULL; + if (atr_usp != NULL) + free(atr_usp, M_DEVBUF); +#endif + scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; + usp = (u_short *)malloc(scp->history_size * sizeof(u_short), + M_DEVBUF, M_NOWAIT); + if (usp != NULL) + bzero(usp, scp->history_size * sizeof(u_short)); + scp->history_head = scp->history_pos = usp; + scp->history = usp; +#ifdef PC98 + atr_usp = (u_short *)malloc(scp->history_size * sizeof(u_short), + M_DEVBUF, M_NOWAIT); + if (atr_usp != NULL) + bzero(atr_usp, scp->history_size * sizeof(u_short)); + scp->his_atr_head = scp->his_atr_pos = atr_usp; + scp->his_atr = atr_usp; +#endif + if (scp == cur_console) + set_mode(scp); + clear_screen(scp); + scp->status &= ~UNKNOWN_MODE; + + if (tp->t_winsize.ws_col != scp->xsize + || tp->t_winsize.ws_row != scp->ysize) { + tp->t_winsize.ws_col = scp->xsize; + tp->t_winsize.ws_row = scp->ysize; + pgsignal(tp->t_pgrp, SIGWINCH, 1); + } + return 0; +#ifndef PC98 + /* GRAPHICS MODES */ + case SW_BG320: case SW_BG640: + case SW_CG320: case SW_CG320_D: case SW_CG640_E: + case SW_CG640x350: case SW_ENH_CG640: + case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: + + if (crtc_type != KD_VGA) + return ENODEV; + mp = get_mode_param(scp, cmd & 0xff); + if (mp == NULL) + return ENODEV; + + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + scp->status |= UNKNOWN_MODE; /* graphics mode */ + scp->mode = cmd & 0xFF; + scp->xpixel = mp[0] * 8; + scp->ypixel = (mp[1] + rows_offset) * mp[2]; + scp->font_size = FONT_NONE; + /* move the mouse cursor at the center of the screen */ + scp->mouse_xpos = scp->xpixel / 2; + scp->mouse_ypos = scp->ypixel / 2; + splx(s); + + if (scp == cur_console) + set_mode(scp); + /* clear_graphics();*/ + + if (tp->t_winsize.ws_xpixel != scp->xpixel + || tp->t_winsize.ws_ypixel != scp->ypixel) { + tp->t_winsize.ws_xpixel = scp->xpixel; + tp->t_winsize.ws_ypixel = scp->ypixel; + pgsignal(tp->t_pgrp, SIGWINCH, 1); + } + return 0; + + case SW_VGA_MODEX: + if (crtc_type != KD_VGA) + return ENODEV; + mp = get_mode_param(scp, cmd & 0xff); + if (mp == NULL) + return ENODEV; + + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + scp->status |= UNKNOWN_MODE; /* graphics mode */ + scp->mode = cmd & 0xFF; + scp->xpixel = 320; + scp->ypixel = 240; + scp->font_size = FONT_NONE; + splx(s); + + if (scp == cur_console) + set_mode(scp); + /* clear_graphics();*/ + if (tp->t_winsize.ws_xpixel != scp->xpixel + || tp->t_winsize.ws_ypixel != scp->ypixel) { + tp->t_winsize.ws_xpixel = scp->xpixel; + tp->t_winsize.ws_ypixel = scp->ypixel; + pgsignal(tp->t_pgrp, SIGWINCH, 1); + } + return 0; +#endif /* PC98 */ + case VT_SETMODE: /* set screen switcher mode */ { struct vt_mode *mode; @@ -1509,7 +2041,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case VT_RELDISP: /* screen switcher ioctl */ - switch(*(int *)data) { + switch(*data) { case VT_FALSE: /* user refuses to release screen, abort */ if (scp == old_scp && (scp->status & SWITCH_WAIT_REL)) { old_scp->status &= ~SWITCH_WAIT_REL; @@ -1549,40 +2081,32 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) for (i = 0; i < MAXCONS; i++) { tp = VIRTUAL_TTY(i); if (!(tp->t_state & TS_ISOPEN)) { - *(int *)data = i + 1; + *data = i + 1; return 0; } } return EINVAL; case VT_ACTIVATE: /* switch to screen *data */ - s = spltty(); - sc_clean_up(cur_console); - splx(s); - return switch_scr(scp, *(int *)data - 1); + return switch_scr(scp, (*data) - 1); case VT_WAITACTIVE: /* wait for switch to occur */ - if (*(int *)data > MAXCONS || *(int *)data < 0) + if (*data > MAXCONS || *data < 0) return EINVAL; - s = spltty(); - error = sc_clean_up(cur_console); - splx(s); - if (error) - return error; - if (minor(dev) == *(int *)data - 1) + if (minor(dev) == (*data) - 1) return 0; - if (*(int *)data == 0) { + if (*data == 0) { if (scp == cur_console) return 0; } else - scp = console[*(int *)data - 1]; + scp = console[(*data) - 1]; while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH, "waitvt", 0)) == ERESTART) ; return error; case VT_GETACTIVE: - *(int *)data = get_scr_num()+1; + *data = get_scr_num()+1; return 0; case KDENABIO: /* allow io operations */ @@ -1598,37 +2122,126 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; return 0; - case KDSKBSTATE: /* set keyboard state (locks) */ - if (*(int *)data & ~LOCK_MASK) + case KDSETMODE: /* set current mode of this (virtual) console */ + switch (*data) { + case KD_TEXT: /* switch to TEXT (known) mode */ +#ifndef PC98 + /* restore fonts & palette ! */ + if (crtc_type == KD_VGA) { + if (!VESA_MODE(scp->mode)) { +#if 0 + /* + * FONT KLUDGE + * Don't load fonts for now... XXX + */ + if (fonts_loaded & FONT_8) + copy_font(LOAD, FONT_8, font_8); + if (fonts_loaded & FONT_14) + copy_font(LOAD, FONT_14, font_14); + if (fonts_loaded & FONT_16) + copy_font(LOAD, FONT_16, font_16); +#endif + } + load_palette(palette); + } + + /* move hardware cursor out of the way */ + outb(crtc_addr, 14); + outb(crtc_addr + 1, 0xff); + outb(crtc_addr, 15); + outb(crtc_addr + 1, 0xff); + + /* FALL THROUGH */ +#endif + case KD_TEXT1: /* switch to TEXT (known) mode */ + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + scp->status |= UNKNOWN_MODE; + splx(s); + /* no restore fonts & palette */ +#ifdef PC98 + scp->status &= ~UNKNOWN_MODE; +#else + if (crtc_type == KD_VGA) +#endif + set_mode(scp); + scp->status &= ~UNKNOWN_MODE; + clear_screen(scp); + return 0; + + case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ + s = spltty(); + if ((error = wait_scrn_saver_stop())) { + splx(s); + return error; + } + scp->status &= ~MOUSE_VISIBLE; + remove_cutmarking(scp); + scp->status |= UNKNOWN_MODE; +#ifdef PC98 + set_mode(scp); +#endif + splx(s); + return 0; + default: return EINVAL; - scp->status &= ~LOCK_MASK; - scp->status |= *(int *)data; + } + /* NOT REACHED */ + + case KDGETMODE: /* get current mode of this (virtual) console */ + *data = (scp->status & UNKNOWN_MODE) ? KD_GRAPHICS : KD_TEXT; + return 0; + + case KDSBORDER: /* set border color of this (virtual) console */ + scp->border = *data; if (scp == cur_console) - update_kbd_state(scp->status, LOCK_MASK); + set_border(scp->border); return 0; + case KDSKBSTATE: /* set keyboard state (locks) */ + if (*data >= 0 && *data <= LOCK_KEY_MASK) { + scp->status &= ~LOCK_KEY_MASK; + scp->status |= *data; + if (scp == cur_console) + update_leds(scp->status); + return 0; + } + return EINVAL; + case KDGKBSTATE: /* get keyboard state (locks) */ - if (scp == cur_console) - save_kbd_state(scp); - *(int *)data = scp->status & LOCK_MASK; + *data = scp->status & LOCK_KEY_MASK; return 0; case KDSETRAD: /* set keyboard repeat & delay rates */ - if (*(int *)data & ~0x7f) +#ifndef PC98 + if (*data & 0x80) return EINVAL; - error = kbd_ioctl(kbd, KDSETRAD, data); - if (error == ENOIOCTL) - error = ENODEV; - return error; + if (sc_kbdc != NULL) + set_keyboard(KBDC_SET_TYPEMATIC, *data); +#endif + return 0; case KDSKBMODE: /* set keyboard mode */ - switch (*(int *)data) { - case K_XLATE: /* switch to XLT ascii mode */ + switch (*data) { case K_RAW: /* switch to RAW scancode mode */ + scp->status &= ~KBD_CODE_MODE; + scp->status |= KBD_RAW_MODE; + return 0; + case K_CODE: /* switch to CODE mode */ - scp->kbd_mode = *(int *)data; - if (scp == cur_console) - kbd_ioctl(kbd, cmd, data); + scp->status &= ~KBD_RAW_MODE; + scp->status |= KBD_CODE_MODE; + return 0; + + case K_XLATE: /* switch to XLT ascii mode */ + if (scp == cur_console && scp->status & KBD_RAW_MODE) + shfts = ctls = alts = agrs = metas = accents = 0; + scp->status &= ~(KBD_RAW_MODE | KBD_CODE_MODE); return 0; default: return EINVAL; @@ -1636,15 +2249,10 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) /* NOT REACHED */ case KDGKBMODE: /* get keyboard mode */ - *(int *)data = scp->kbd_mode; + *data = (scp->status & KBD_RAW_MODE) ? K_RAW : + ((scp->status & KBD_CODE_MODE) ? K_CODE : K_XLATE); return 0; - case KDGKBINFO: - error = kbd_ioctl(kbd, cmd, data); - if (error == ENOIOCTL) - error = ENODEV; - return error; - case KDMKTONE: /* sound the bell */ if (*(int*)data) do_bell(scp, (*(int*)data)&0xffff, @@ -1696,74 +2304,45 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return 0; case KDGKBTYPE: /* get keyboard type */ - error = kbd_ioctl(kbd, cmd, data); - if (error == ENOIOCTL) { - /* always return something? XXX */ - *(int *)data = 0; - } + *data = 0; /* type not known (yet) */ return 0; case KDSETLED: /* set keyboard LED status */ - if (*(int *)data & ~LED_MASK) /* FIXME: LOCK_MASK? */ - return EINVAL; - scp->status &= ~LED_MASK; - scp->status |= *(int *)data; - if (scp == cur_console) - update_kbd_leds(scp->status); - return 0; + if (*data >= 0 && *data <= LED_MASK) { + scp->status &= ~LED_MASK; + scp->status |= *data; + if (scp == cur_console) + update_leds(scp->status); + return 0; + } + return EINVAL; case KDGETLED: /* get keyboard LED status */ - if (scp == cur_console) - save_kbd_state(scp); - *(int *)data = scp->status & LED_MASK; + *data = scp->status & LED_MASK; return 0; - case CONS_SETKBD: /* set the new keyboard */ - { - keyboard_t *newkbd; - - s = spltty(); - newkbd = kbd_get_keyboard(*(int *)data); - if (newkbd == NULL) { - splx(s); - return EINVAL; - } - error = 0; - if (kbd != newkbd) { - i = kbd_allocate(newkbd->kb_name, newkbd->kb_unit, - (void *)&keyboard, sckbdevent, NULL); - /* i == newkbd->kb_index */ - if (i >= 0) { - if (kbd != NULL) { - save_kbd_state(cur_console); - kbd_release(kbd, (void *)&keyboard); - } - kbd = kbd_get_keyboard(i); /* kbd == newkbd */ - keyboard = i; - kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); - update_kbd_state(cur_console->status, LOCK_MASK); - } else { - error = EPERM; /* XXX */ - } - } - splx(s); - return error; + case GETFKEY: /* get functionkey string */ + if (*(u_short*)data < n_fkey_tab) { + fkeyarg_t *ptr = (fkeyarg_t*)data; + bcopy(&fkey_tab[ptr->keynum].str, ptr->keydef, + fkey_tab[ptr->keynum].len); + ptr->flen = fkey_tab[ptr->keynum].len; + return 0; } + else + return EINVAL; - case CONS_RELKBD: /* release the current keyboard */ - s = spltty(); - error = 0; - if (kbd != NULL) { - save_kbd_state(cur_console); - error = kbd_release(kbd, (void *)&keyboard); - if (error == 0) { - kbd = NULL; - keyboard = -1; - } + case SETFKEY: /* set functionkey string */ + if (*(u_short*)data < n_fkey_tab) { + fkeyarg_t *ptr = (fkeyarg_t*)data; + bcopy(ptr->keydef, &fkey_tab[ptr->keynum].str, + min(ptr->flen, MAXFK)); + fkey_tab[ptr->keynum].len = min(ptr->flen, MAXFK); + return 0; } - splx(s); - return error; - + else + return EINVAL; + case GIO_SCRNMAP: /* get output translation table */ bcopy(&scr_map, data, sizeof(scr_map)); return 0; @@ -1774,19 +2353,36 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) scr_rmap[scr_map[i]] = i; return 0; - case GIO_KEYMAP: /* get keyboard translation table */ - case PIO_KEYMAP: /* set keyboard translation table */ - case GIO_DEADKEYMAP: /* get accent key translation table */ - case PIO_DEADKEYMAP: /* set accent key translation table */ - case GETFKEY: /* get function key string */ - case SETFKEY: /* set function key string */ - error = kbd_ioctl(kbd, cmd, data); - if (error == ENOIOCTL) - error = ENODEV; - return error; + case GIO_KEYMAP: /* get keyboard translation table */ + bcopy(&key_map, data, sizeof(key_map)); + return 0; + + case PIO_KEYMAP: /* set keyboard translation table */ + accents = 0; + bzero(&accent_map, sizeof(accent_map)); + bcopy(data, &key_map, sizeof(key_map)); + return 0; + + case GIO_DEADKEYMAP: /* get accent key translation table */ + bcopy(&accent_map, data, sizeof(accent_map)); + return 0; + + case PIO_DEADKEYMAP: /* set accent key translation table */ + accents = 0; + bcopy(data, &accent_map, sizeof(accent_map)); + return 0; +#ifdef PC98 + case PIO_FONT8x8: /* set 8x8 dot font */ + case GIO_FONT8x8: /* get 8x8 dot font */ + case PIO_FONT8x14: /* set 8x14 dot font */ + case GIO_FONT8x14: /* get 8x14 dot font */ + case PIO_FONT8x16: /* set 8x16 dot font */ + case GIO_FONT8x16: /* get 8x16 dot font */ + return ENXIO; +#else case PIO_FONT8x8: /* set 8x8 dot font */ - if (!ISFONTAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA) return ENXIO; bcopy(data, font_8, 8*256); fonts_loaded |= FONT_8; @@ -1795,12 +2391,17 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * Always use the font page #0. XXX * Don't load if the current font size is not 8x8. */ - if (ISTEXTSC(cur_console) && (cur_console->font_size < 14)) - copy_font(cur_console, LOAD, 8, font_8); + if (!VESA_MODE(cur_console->mode) + && !(cur_console->status & UNKNOWN_MODE) + && (cur_console->font_size < 14)) { + copy_font(LOAD, FONT_8, font_8); + if (flags & CHAR_CURSOR) + set_destructive_cursor(cur_console); + } return 0; case GIO_FONT8x8: /* get 8x8 dot font */ - if (!ISFONTAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA) return ENXIO; if (fonts_loaded & FONT_8) { bcopy(font_8, data, 8*256); @@ -1810,7 +2411,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return ENXIO; case PIO_FONT8x14: /* set 8x14 dot font */ - if (!ISFONTAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA) return ENXIO; bcopy(data, font_14, 14*256); fonts_loaded |= FONT_14; @@ -1819,13 +2420,17 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * Always use the font page #0. XXX * Don't load if the current font size is not 8x14. */ - if (ISTEXTSC(cur_console) - && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) - copy_font(cur_console, LOAD, 14, font_14); + if (!VESA_MODE(cur_console->mode) + && !(cur_console->status & UNKNOWN_MODE) + && (cur_console->font_size >= 14) && (cur_console->font_size < 16)) { + copy_font(LOAD, FONT_14, font_14); + if (flags & CHAR_CURSOR) + set_destructive_cursor(cur_console); + } return 0; case GIO_FONT8x14: /* get 8x14 dot font */ - if (!ISFONTAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA) return ENXIO; if (fonts_loaded & FONT_14) { bcopy(font_14, data, 14*256); @@ -1835,7 +2440,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) return ENXIO; case PIO_FONT8x16: /* set 8x16 dot font */ - if (!ISFONTAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA) return ENXIO; bcopy(data, font_16, 16*256); fonts_loaded |= FONT_16; @@ -1844,12 +2449,17 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) * Always use the font page #0. XXX * Don't load if the current font size is not 8x16. */ - if (ISTEXTSC(cur_console) && (cur_console->font_size >= 16)) - copy_font(cur_console, LOAD, 16, font_16); + if (!VESA_MODE(cur_console->mode) + && !(cur_console->status & UNKNOWN_MODE) + && (cur_console->font_size >= 16)) { + copy_font(LOAD, FONT_16, font_16); + if (flags & CHAR_CURSOR) + set_destructive_cursor(cur_console); + } return 0; case GIO_FONT8x16: /* get 8x16 dot font */ - if (!ISFONTAVAIL(scp->adp->va_flags)) + if (crtc_type != KD_VGA) return ENXIO; if (fonts_loaded & FONT_16) { bcopy(font_16, data, 16*256); @@ -1857,6 +2467,7 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) } else return ENXIO; +#endif /* PC98 */ #ifdef PC98 case ADJUST_CLOCK: /* /dev/rtc for 98note resume */ @@ -1882,7 +2493,7 @@ scstart(struct tty *tp) struct clist *rbp; int s, len; u_char buf[PCBURST]; - scr_stat *scp = sc_get_scr_stat(tp->t_dev); + scr_stat *scp = get_scr_stat(tp->t_dev); if (scp->status & SLKED || blink_in_progress) return; /* XXX who repeats the call when the above flags are cleared? */ @@ -1922,7 +2533,7 @@ scmousestart(struct tty *tp) splx(s); } -static void +void sccnprobe(struct consdev *cp) { struct isa_device *dvp; @@ -1936,59 +2547,35 @@ sccnprobe(struct consdev *cp) return; } - if (!scvidprobe(dvp->id_unit, dvp->id_flags, TRUE)) { + if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { cp->cn_pri = CN_DEAD; return; } - sckbdprobe(dvp->id_unit, dvp->id_flags, TRUE); /* initialize required fields */ cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); cp->cn_pri = CN_INTERNAL; + + sc_kbdc = kbdc_open(sc_port); } -static void +void sccninit(struct consdev *cp) { scinit(); } -static void +void sccnputc(dev_t dev, int c) { u_char buf[1]; + int s; scr_stat *scp = console[0]; term_stat save = scp->term; - u_short *p; - int s; - int i; - - if (scp == cur_console && scp->status & SLKED) { - scp->status &= ~SLKED; - update_kbd_state(scp->status, SLKED); - if (cur_console->status & BUFFER_SAVED) { - p = cur_console->history_save; - for (i = 0; i < cur_console->ysize; ++i) { - bcopy(p, cur_console->scr_buf + (cur_console->xsize*i), - cur_console->xsize*sizeof(u_short)); - p += cur_console->xsize; - if (p + cur_console->xsize - > cur_console->history + cur_console->history_size) - p = cur_console->history; - } - cur_console->status &= ~BUFFER_SAVED; - cur_console->history_head = cur_console->history_save; - cur_console->status |= CURSOR_ENABLED; - mark_all(cur_console); - } -#if 1 /* XXX */ - scstart(VIRTUAL_TTY(get_scr_num())); -#endif - } scp->term = kernel_console; current_default = &kernel_default; - if (scp == cur_console && !ISGRAPHSC(scp)) + if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) remove_cursor_image(scp); buf[0] = c; ansi_put(scp, buf, 1); @@ -1996,71 +2583,43 @@ sccnputc(dev_t dev, int c) current_default = &user_default; scp->term = save; - s = spltty(); /* block sckbdevent and scrn_timer */ + s = spltty(); /* block scintr and scrn_timer */ sccnupdate(scp); splx(s); } -static int +int sccngetc(dev_t dev) { - return sccngetch(0); -} - -static int -sccncheckc(dev_t dev) -{ - return sccngetch(SCGETC_NONBLOCK); -} - -static int -sccngetch(int flags) -{ - int cur_mode; - int s = spltty(); /* block sckbdevent and scrn_timer while we poll */ + int s = spltty(); /* block scintr and scrn_timer while we poll */ int c; /* * Stop the screen saver and update the screen if necessary. * What if we have been running in the screen saver code... XXX */ - sc_touch_scrn_saver(); + scsplash_stick(FALSE); + run_scrn_saver = FALSE; sccnupdate(cur_console); - if (kbd == NULL) { - splx(s); - return -1; - } - - /* - * Make sure the keyboard is accessible even when the kbd device - * driver is disabled. - */ - kbd_enable(kbd); + c = scgetc(SCGETC_CN); + splx(s); + return(c); +} - /* we shall always use the keyboard in the XLATE mode here */ - cur_mode = cur_console->kbd_mode; - cur_console->kbd_mode = K_XLATE; - kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); +int +sccncheckc(dev_t dev) +{ + int s = spltty(); /* block scintr and scrn_timer while we poll */ + int c; - c = scgetc(kbd, SCGETC_CN | flags); + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + sccnupdate(cur_console); - cur_console->kbd_mode = cur_mode; - kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&cur_console->kbd_mode); - kbd_disable(kbd); + c = scgetc(SCGETC_CN | SCGETC_NONBLOCK); splx(s); - - switch (KEYFLAGS(c)) { - case 0: /* normal char */ - return KEYCHAR(c); - case FKEY: /* function key */ - return c; /* XXX */ - case NOKEY: - case ERRKEY: - default: - return -1; - } - /* NOT REACHED */ + return(c == NOKEY ? -1 : c); /* c == -1 can't happen */ } static void @@ -2071,28 +2630,25 @@ sccnupdate(scr_stat *scp) if (font_loading_in_progress) return; - if (panicstr || shutdown_in_progress) { - sc_touch_scrn_saver(); - } else if (scp != cur_console) { - return; + if (panicstr) { + scsplash_stick(FALSE); + run_scrn_saver = FALSE; } - if (!run_scrn_saver) scrn_idle = FALSE; -#if NSPLASH > 0 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) - if (scrn_blanked) + if (scrn_blanked > 0) stop_scrn_saver(current_saver); -#endif /* NSPLASH */ + if (scp != cur_console || blink_in_progress || switch_in_progress) return; - if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) + if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0) scrn_update(scp, TRUE); } -scr_stat -*sc_get_scr_stat(dev_t dev) +static scr_stat +*get_scr_stat(dev_t dev) { int unit = minor(dev); @@ -2128,10 +2684,35 @@ scrn_timer(void *arg) } s = spltty(); + /* + * 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. + */ + if (kbdc_lock(sc_kbdc, TRUE)) { + /* + * We have seen the lock flag is not set. Let's reset the flag early; + * otherwise `update_led()' failes which may want the lock + * during `scintr()'. + */ + kbdc_lock(sc_kbdc, FALSE); + if (kbdc_data_ready(sc_kbdc)) + scintr(0); + } + /* should we stop the screen saver? */ getmicrouptime(&tv); - if (panicstr || shutdown_in_progress) - sc_touch_scrn_saver(); + if (panicstr || shutdown_in_progress) { + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + } if (run_scrn_saver) { scrn_idle = (tv.tv_sec > scrn_time_stamp + scrn_blank_time); } else { @@ -2140,11 +2721,10 @@ scrn_timer(void *arg) if (scrn_blank_time > 0) run_scrn_saver = TRUE; } -#if NSPLASH > 0 if ((saver_mode != CONS_LKM_SAVER) || !scrn_idle) - if (scrn_blanked) + if (scrn_blanked > 0) stop_scrn_saver(current_saver); -#endif /* NSPLASH */ + /* should we just return ? */ if (blink_in_progress || switch_in_progress) { if (arg) @@ -2155,12 +2735,12 @@ scrn_timer(void *arg) /* Update the screen */ scp = cur_console; - if (!ISGRAPHSC(scp) && !(scp->status & SAVER_RUNNING)) + if ((scp->status & UNKNOWN_MODE) == 0 && scrn_blanked <= 0) scrn_update(scp, TRUE); /* should we activate the screen saver? */ if ((saver_mode == CONS_LKM_SAVER) && scrn_idle) - if (!ISGRAPHSC(scp) || scrn_blanked) + if ((scp->status & UNKNOWN_MODE) == 0 || scrn_blanked > 0) (*current_saver)(TRUE); if (arg) @@ -2228,7 +2808,7 @@ scrn_update(scr_stat *scp, int show_cursor) draw_cursor_image(scp); } else { /* if its a blinking cursor, we may have to update it */ - if (sc_flags & BLINK_CURSOR) + if (flags & BLINK_CURSOR) draw_cursor_image(scp); } } @@ -2242,96 +2822,25 @@ scrn_update(scr_stat *scp, int show_cursor) scp->start = scp->xsize*scp->ysize - 1; } -#if NSPLASH > 0 - -static int -scsplash_callback(int event) -{ - int error; - - switch (event) { - case SPLASH_INIT: - scrn_saver_failed = FALSE; - if (add_scrn_saver(scsplash_saver) == 0) { - run_scrn_saver = TRUE; - if (cold && !(boothowto & (RB_VERBOSE | RB_CONFIG))) { - scsplash_stick(TRUE); - (*current_saver)(TRUE); - } - } - return 0; - - case SPLASH_TERM: - if (current_saver == scsplash_saver) { - scsplash_stick(FALSE); - error = remove_scrn_saver(scsplash_saver); - if (error) - return error; - } - return 0; - - default: - return EINVAL; - } -} - -static void -scsplash_saver(int show) -{ - static int busy = FALSE; - scr_stat *scp; - - if (busy) - return; - busy = TRUE; - - scp = cur_console; - if (show) { - if (!scrn_saver_failed) { - if (!scrn_blanked) - set_scrn_saver_mode(scp, -1, NULL, 0); - switch (splash(scp->adp, TRUE)) { - case 0: /* succeeded */ - scrn_blanked = TRUE; - break; - case EAGAIN: /* try later */ - restore_scrn_saver_mode(scp, FALSE); - break; - default: - scrn_saver_failed = TRUE; - scsplash_stick(FALSE); - printf("scsplash_saver(): failed to put up the image\n"); - restore_scrn_saver_mode(scp, TRUE); - break; - } - } - } else if (!sticky_splash) { - if (scrn_blanked && (splash(scp->adp, FALSE) == 0)) { - restore_scrn_saver_mode(scp, TRUE); - scrn_blanked = FALSE; - } - } - busy = FALSE; -} - -static int +int add_scrn_saver(void (*this_saver)(int)) { - int error; - - if (current_saver != none_saver) { - error = remove_scrn_saver(current_saver); - if (error) - return error; +#ifdef SC_SPLASH_SCREEN + if (current_saver == scsplash) { + scsplash_stick(FALSE); + stop_scrn_saver(scsplash); } +#endif - run_scrn_saver = FALSE; - saver_mode = CONS_LKM_SAVER; + if (current_saver != default_saver) + return EBUSY; current_saver = this_saver; + saver_mode = CONS_LKM_SAVER; + run_scrn_saver = (scrn_blank_time > 0); return 0; } -static int +int remove_scrn_saver(void (*this_saver)(int)) { if (current_saver != this_saver) @@ -2344,72 +2853,14 @@ remove_scrn_saver(void (*this_saver)(int)) * before stopping the current saver, rather than blocking by `splXX()'. */ current_saver = none_saver; - if (scrn_blanked) + if (scrn_blanked > 0) stop_scrn_saver(this_saver); - return (scrn_blanked ? EBUSY : 0); -} - -static int -set_scrn_saver_mode(scr_stat *scp, int mode, u_char *pal, int border) -{ - int s; - - /* assert(scp == cur_console) */ - s = spltty(); - scp->splash_save_mode = scp->mode; - scp->splash_save_status = scp->status & (GRAPHICS_MODE | PIXEL_MODE); - scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE); - scp->status |= (UNKNOWN_MODE | SAVER_RUNNING); - splx(s); - if (mode < 0) - return 0; - scp->mode = mode; - if (set_mode(scp) == 0) { - if (scp->adp->va_mode_flags & V_INFO_GRAPHICS) - scp->status |= GRAPHICS_MODE; - if (pal != NULL) - load_palette(scp->adp, pal); - set_border(scp, border); - return 0; - } else { - s = spltty(); - scp->mode = scp->splash_save_mode; - scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING); - scp->status |= scp->splash_save_status; - splx(s); - return 1; - } -} - -static int -restore_scrn_saver_mode(scr_stat *scp, int changemode) -{ - int mode; - int status; - int s; + if (scrn_blanked > 0) + return EBUSY; /* XXX */ - /* assert(scp == cur_console) */ - s = spltty(); - mode = scp->mode; - status = scp->status; - scp->mode = scp->splash_save_mode; - scp->status &= ~(UNKNOWN_MODE | SAVER_RUNNING); - scp->status |= scp->splash_save_status; - if (!changemode) { - splx(s); - return 0; - } - if (set_mode(scp) == 0) { - load_palette(scp->adp, palette); - splx(s); - return 0; - } else { - scp->mode = mode; - scp->status = status; - splx(s); - return 1; - } + current_saver = default_saver; + return 0; } static void @@ -2418,7 +2869,7 @@ stop_scrn_saver(void (*saver)(int)) (*saver)(FALSE); run_scrn_saver = FALSE; /* the screen saver may have chosen not to stop after all... */ - if (scrn_blanked) + if (scrn_blanked > 0) return; mark_all(cur_console); @@ -2432,8 +2883,8 @@ wait_scrn_saver_stop(void) { int error = 0; - while (scrn_blanked) { - run_scrn_saver = FALSE; + run_scrn_saver = FALSE; + while (scrn_blanked > 0) { error = tsleep((caddr_t)&scrn_blanked, PZERO | PCATCH, "scrsav", 0); run_scrn_saver = FALSE; if (error != ERESTART) @@ -2442,17 +2893,8 @@ wait_scrn_saver_stop(void) return error; } -#endif /* NSPLASH */ - -void -sc_touch_scrn_saver(void) -{ - scsplash_stick(FALSE); - run_scrn_saver = FALSE; -} - -void -sc_clear_screen(scr_stat *scp) +static void +clear_screen(scr_stat *scp) { move_crsr(scp, 0, 0); scp->cursor_oldpos = scp->cursor_pos; @@ -2473,9 +2915,10 @@ static int switch_scr(scr_stat *scp, u_int next_scr) { /* delay switch if actively updating screen */ - if (scrn_blanked || write_in_progress || blink_in_progress) { + if (scrn_blanked > 0 || write_in_progress || blink_in_progress) { + scsplash_stick(FALSE); + run_scrn_saver = FALSE; delayed_next_scr = next_scr+1; - sc_touch_scrn_saver(); return 0; } @@ -2483,7 +2926,8 @@ switch_scr(scr_stat *scp, u_int next_scr) switch_in_progress = FALSE; if (next_scr >= MAXCONS || switch_in_progress || - (cur_console->smode.mode == VT_AUTO && ISGRAPHSC(cur_console))) { + (cur_console->smode.mode == VT_AUTO + && cur_console->status & UNKNOWN_MODE)) { do_bell(scp, BELL_PITCH, BELL_DURATION); return EINVAL; } @@ -2533,35 +2977,33 @@ switch_scr(scr_stat *scp, u_int next_scr) static void exchange_scr(void) { - /* save the current state of video and keyboard */ move_crsr(old_scp, old_scp->xpos, old_scp->ypos); - if (old_scp->kbd_mode == K_XLATE) - save_kbd_state(old_scp); - - /* set up the video for the new screen */ cur_console = new_scp; #ifdef PC98 - if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp) || ISUNKNOWNSC(new_scp)) + if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE) || (new_scp->status & UNKNOWN_MODE)){ #else - if (old_scp->mode != new_scp->mode || ISUNKNOWNSC(old_scp)) + if (old_scp->mode != new_scp->mode || (old_scp->status & UNKNOWN_MODE)){ + if (crtc_type == KD_VGA) #endif - set_mode(new_scp); + set_mode(new_scp); + } move_crsr(new_scp, new_scp->xpos, new_scp->ypos); #ifndef PC98 - if (ISTEXTSC(new_scp) && (sc_flags & CHAR_CURSOR)) + if (!(new_scp->status & UNKNOWN_MODE) && (flags & CHAR_CURSOR)) set_destructive_cursor(new_scp); - if (ISGRAPHSC(old_scp)) - load_palette(new_scp->adp, palette); + if ((old_scp->status & UNKNOWN_MODE) && crtc_type == KD_VGA) + load_palette(palette); #endif - set_border(new_scp, new_scp->border); - - /* set up the keyboard for the new screen */ - if (old_scp->kbd_mode != new_scp->kbd_mode) - kbd_ioctl(kbd, KDSKBMODE, (caddr_t)&new_scp->kbd_mode); - update_kbd_state(new_scp->status, LOCK_MASK); - + if (old_scp->status & KBD_RAW_MODE || new_scp->status & KBD_RAW_MODE || + old_scp->status & KBD_CODE_MODE || new_scp->status & KBD_CODE_MODE) + shfts = ctls = alts = agrs = metas = accents = 0; + set_border(new_scp->border); + update_leds(new_scp->status); delayed_next_scr = FALSE; mark_all(new_scp); + if (new_scp->mode == 0x102) { + bzero(Crtat, 800*600/8); + } } static void @@ -2578,36 +3020,36 @@ scan_esc(scr_stat *scp, u_char c) if (scp->term.esc == 1) { /* seen ESC */ #ifdef KANJI switch (scp->kanji_type) { - case KTYPE_KANIN: /* Kanji Invoke sequence */ + case 0x80: switch (c) { case 'B': case '@': - scp->kanji_type = KTYPE_7JIS; + scp->kanji_type = 0x20; scp->term.esc = 0; scp->kanji_1st_char = 0; return; default: - scp->kanji_type = KTYPE_ASCII; + scp->kanji_type = 0; scp->term.esc = 0; break; } break; - case KTYPE_ASCIN: /* Ascii Invoke sequence */ + case 0x40: switch (c) { case 'J': case 'B': case 'H': - scp->kanji_type = KTYPE_ASCII; + scp->kanji_type = 0; scp->term.esc = 0; scp->kanji_1st_char = 0; return; case 'I': - scp->kanji_type = KTYPE_JKANA; + scp->kanji_type = 0x10; scp->term.esc = 0; scp->kanji_1st_char = 0; return; default: - scp->kanji_type = KTYPE_ASCII; + scp->kanji_type = 0; scp->term.esc = 0; break; } @@ -2637,8 +3079,8 @@ scan_esc(scr_stat *scp, u_char c) return; #ifdef KANJI - case '$': /* Kanji Invoke sequence */ - scp->kanji_type = KTYPE_KANIN; + case '$': /* Kanji IN sequence */ + scp->kanji_type = 0x80; return; #endif @@ -2670,12 +3112,12 @@ scan_esc(scr_stat *scp, u_char c) return; #endif case 'c': /* Clear screen & home */ - sc_clear_screen(scp); + clear_screen(scp); break; case '(': /* iso-2022: designate 94 character set to G0 */ #ifdef KANJI - scp->kanji_type = KTYPE_ASCIN; + scp->kanji_type = 0x40; #else scp->term.esc = 5; #endif @@ -2772,7 +3214,7 @@ scan_esc(scr_stat *scp, u_char c) #ifdef PC98 mark_for_update(scp, scp->cursor_atr - scp->atr_buf); #endif - mark_for_update(scp, scp->xsize * scp->ysize - 1); + mark_for_update(scp, scp->xsize * scp->ysize); remove_cutmarking(scp); break; case 1: /* clear from beginning of display to cursor */ @@ -2835,10 +3277,10 @@ scan_esc(scr_stat *scp, u_char c) mark_for_update(scp, scp->cursor_atr - scp->atr_buf); #endif mark_for_update(scp, scp->cursor_pos - scp->scr_buf + - scp->xsize - 1 - scp->xpos); + scp->xsize - scp->xpos); #ifdef PC98 mark_for_update(scp, scp->cursor_atr - scp->atr_buf + - scp->xsize - 1 - scp->xpos); + scp->xsize - scp->xpos); #endif break; case 1: /* clear from beginning of line to cursor */ @@ -2874,7 +3316,7 @@ scan_esc(scr_stat *scp, u_char c) scp->xsize); #endif mark_for_update(scp, scp->ypos * scp->xsize); - mark_for_update(scp, (scp->ypos + 1) * scp->xsize - 1); + mark_for_update(scp, (scp->ypos + 1) * scp->xsize); break; } break; @@ -2900,7 +3342,7 @@ scan_esc(scr_stat *scp, u_char c) n * scp->xsize); #endif mark_for_update(scp, scp->ypos * scp->xsize); - mark_for_update(scp, scp->xsize * scp->ysize - 1); + mark_for_update(scp, scp->xsize * scp->ysize); break; case 'M': /* Delete n lines */ @@ -2926,7 +3368,7 @@ scan_esc(scr_stat *scp, u_char c) n * scp->xsize); #endif mark_for_update(scp, scp->ypos * scp->xsize); - mark_for_update(scp, scp->xsize * scp->ysize - 1); + mark_for_update(scp, scp->xsize * scp->ysize); break; case 'P': /* Delete n chars */ @@ -2952,9 +3394,9 @@ scan_esc(scr_stat *scp, u_char c) #ifdef PC98 mark_for_update(scp, scp->cursor_atr - scp->atr_buf); #endif - mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); #ifdef PC98 - mark_for_update(scp, scp->cursor_atr - scp->atr_buf + n + count - 1); + mark_for_update(scp, scp->cursor_atr - scp->atr_buf + n + count); #endif break; @@ -2979,9 +3421,9 @@ scan_esc(scr_stat *scp, u_char c) #ifdef PC98 mark_for_update(scp, scp->cursor_atr - scp->atr_buf); #endif - mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count - 1); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n + count); #ifdef PC98 - mark_for_update(scp, scp->cursor_atr - scp->atr_buf + n + count - 1); + mark_for_update(scp, scp->cursor_atr - scp->atr_buf + n + count); #endif break; @@ -3051,9 +3493,9 @@ scan_esc(scr_stat *scp, u_char c) #ifdef PC98 mark_for_update(scp, scp->cursor_atr - scp->atr_buf); #endif - mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n - 1); + mark_for_update(scp, scp->cursor_pos - scp->scr_buf + n); #ifdef PC98 - mark_for_update(scp, scp->cursor_atr - scp->atr_buf + n - 1); + mark_for_update(scp, scp->cursor_atr - scp->atr_buf + n); #endif break; @@ -3125,7 +3567,7 @@ scan_esc(scr_stat *scp, u_char c) scp->term.cur_color = (scp->term.cur_color&0xF000) | (ansi_col[(n-30)&7]<<8); scp->term.cur_attr = mask2attr(&scp->term); - break; + break; case 40: case 41: /* set bg color */ case 42: case 43: case 44: case 45: case 46: case 47: @@ -3232,7 +3674,7 @@ scan_esc(scr_stat *scp, u_char c) if (scp->term.num_param == 1) { scp->border=scp->term.param[0] & 0xff; if (scp == cur_console) - set_border(cur_console, scp->border); + set_border(scp->border); } break; @@ -3246,21 +3688,14 @@ scan_esc(scr_stat *scp, u_char c) case 'C': /* set cursor type & shape */ if (scp->term.num_param == 1) { if (scp->term.param[0] & 0x01) - sc_flags |= BLINK_CURSOR; - else - sc_flags &= ~BLINK_CURSOR; -#ifdef PC98 - if (scp->term.param[0] & 0x02) - sc_flags |= CHAR_CURSOR; + flags |= BLINK_CURSOR; else - sc_flags &= ~CHAR_CURSOR; -#else /* PC98 */ - if ((scp->term.param[0] & 0x02) - && ISFONTAVAIL(scp->adp->va_flags)) - sc_flags |= CHAR_CURSOR; + flags &= ~BLINK_CURSOR; + if ((scp->term.param[0] & 0x02) && + crtc_type == KD_VGA && !VESA_MODE(bios_video_mode)) + flags |= CHAR_CURSOR; else - sc_flags &= ~CHAR_CURSOR; -#endif /* PC98 */ + flags &= ~CHAR_CURSOR; } else if (scp->term.num_param == 2) { scp->cursor_start = scp->term.param[0] & 0x1F; @@ -3270,13 +3705,11 @@ scan_esc(scr_stat *scp, u_char c) * The cursor shape is global property; all virtual consoles * are affected. Update the cursor in the current console... */ - if (!ISGRAPHSC(cur_console)) { - i = spltty(); + if (!(cur_console->status & UNKNOWN_MODE)) { remove_cursor_image(cur_console); - if (sc_flags & CHAR_CURSOR) + if (crtc_type == KD_VGA && (flags & CHAR_CURSOR)) set_destructive_cursor(cur_console); draw_cursor_image(cur_console); - splx(i); } break; @@ -3339,114 +3772,103 @@ scan_esc(scr_stat *scp, u_char c) #ifdef KANJI static u_char iskanji1(u_char mode, u_char c) { - if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) { + if ((mode == 0x20) && (c >= 0x21) && (c <= 0x7e)) { /* JIS */ - default_kanji = UJIS; - return KTYPE_7JIS; + return 0x20; } - if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) { + if ((mode == 0x10) && (c >= 0x21) && (c <= 0x5f)) { /* JIS HANKAKU */ - default_kanji = UJIS; - return KTYPE_JKANA; - } - -#if 1 - if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) { - /* UJIS */ - return KTYPE_UJIS; + return 0x10; } -#endif if ((c >= 0x81) && (c <= 0x9f) && (c != 0x8e)) { /* SJIS */ default_kanji = SJIS; - return KTYPE_SJIS; + return 2; } if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == SJIS)) { - /* SJIS HANKAKU */ - return KTYPE_KANA; + /* Sjis HANKAKU */ + return 1; } -#if 0 if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) { /* UJIS */ - return KTYPE_UJIS; + return 4; } -#endif if ((c >= 0xf0) && (c <= 0xfe)) { /* UJIS */ default_kanji = UJIS; - return KTYPE_UJIS; + return 4; } if ((c >= 0xe0) && (c <= 0xef)) { /* SJIS or UJIS */ - return KTYPE_SUJIS; + return 6; } if (c == 0x8e) { /* SJIS or UJIS HANKAKU */ - return KTYPE_SUKANA; + return 3; } - return KTYPE_ASCII; + return 0; } static u_char iskanji2(u_char mode, u_char c) { switch (mode) { - case KTYPE_7JIS: + case 0x20: if ((c >= 0x21) && (c <= 0x7e)) { /* JIS */ - return KTYPE_7JIS; + return 0x20; } break; - case KTYPE_SJIS: + case 2: if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) { /* SJIS */ - return KTYPE_SJIS; + return 2; } break; - case KTYPE_UJIS: + case 4: if ((c >= 0xa1) && (c <= 0xfe)) { /* UJIS */ - return KTYPE_UJIS; + return 4; } break; - case KTYPE_SUKANA: + case 3: if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) { /* UJIS HANKAKU */ - return KTYPE_KANA; + return 1; } if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) { /* SJIS */ default_kanji = SJIS; - return KTYPE_SJIS; + return 2; } break; - case KTYPE_SUJIS: + case 6: if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) { /* SJIS */ default_kanji = SJIS; - return KTYPE_SJIS; + return 2; } if ((c == 0xfd) || (c == 0xfe)) { /* UJIS */ default_kanji = UJIS; - return KTYPE_UJIS; + return 4; } if ((c >= 0xa1) && (c <= 0xfc)) { if (default_kanji == SJIS) - return KTYPE_SJIS; + return 2; if (default_kanji == UJIS) - return KTYPE_UJIS; + return 4; } break; } - return KTYPE_ASCII; + return 0; } /* @@ -3467,7 +3889,7 @@ static u_short kanji_convert(u_char mode, u_char h, u_char l) low = (u_short) l; switch (mode) { - case KTYPE_SJIS: /* SHIFT JIS */ + case 2: /* SHIFT JIS */ if (low >= 0xe0) { low -= 0x40; } @@ -3475,7 +3897,7 @@ static u_short kanji_convert(u_char mode, u_char h, u_char l) if (high > 0x7f) { high--; } - if (high > 0x9d) { + if (high >0x9d) { low++; high -= 0x9e - 0x21; } else { @@ -3485,8 +3907,8 @@ static u_short kanji_convert(u_char mode, u_char h, u_char l) low &= 0x7F; tmp = ((high << 8) | low) - 0x20; break; - case KTYPE_7JIS: /* JIS */ - case KTYPE_UJIS: /* UJIS */ + case 0x20: /* JIS */ + case 4: /* HANKAKU? */ high &= 0x7F; low &= 0x7F; tmp = ((high << 8) | low) - 0x20; @@ -3498,7 +3920,6 @@ static u_short kanji_convert(u_char mode, u_char h, u_char l) /* keisen */ c = ((tmp & 0xff) << 8) | (tmp >> 8); - /* 0x2821 .. 0x2840 */ if (0x0821 <= c && c <= 0x0840) tmp = keiConv[c - 0x0821]; @@ -3525,9 +3946,7 @@ outloop: len--; } else if (PRINTABLE(*ptr)) { /* Print only printables */ -#ifndef PC98 int cnt = len <= (scp->xsize-scp->xpos) ? len : (scp->xsize-scp->xpos); -#endif u_short cur_attr = scp->term.cur_attr; u_short *cursor_pos = scp->cursor_pos; #ifdef PC98 @@ -3536,7 +3955,7 @@ outloop: #ifdef KANJI if (scp->kanji_1st_char == 0) { scp->kanji_type = iskanji1(scp->kanji_type, c); - if (!IS_KTYPE_ASCII_or_HANKAKU(scp->kanji_type)) { + if (scp->kanji_type & 0xee) { /* not Ascii & not HANKAKU */ scp->kanji_1st_char = c; ptr++; len--; @@ -3549,8 +3968,7 @@ outloop: /* print kanji on TEXT VRAM */ kanji_code = kanji_convert(scp->kanji_type, c, scp->kanji_1st_char); for (i=0; i<2; i++){ - /* *cursor_pos = (kanji_code | (i*0x80)); */ - *cursor_pos = kanji_code | ((i==0) ? 0x00 : 0x80); + *cursor_pos = (kanji_code | (i*0x80)); *cursor_atr = (at2pc98(cur_attr)); cursor_pos++; cursor_atr++; @@ -3559,7 +3977,7 @@ outloop: scp->ypos++; } } - KTYPE_MASK_CTRL(scp->kanji_type); + scp->kanji_type &= 0xF0; scp->kanji_1st_char = 0; ptr++; len--; goto kanji_end; @@ -3567,9 +3985,8 @@ outloop: scp->kanji_1st_char = 0; } } - if (IS_KTYPE_KANA(scp->kanji_type)) - c |= 0x80; - KTYPE_MASK_CTRL(scp->kanji_type); + if ((scp->kanji_type & 0x11)) c |= 0x80; + scp->kanji_type &= 0xf0; #endif /* KANJI */ *cursor_pos++ = (scr_map[c]); *cursor_atr++ = at2pc98(cur_attr); @@ -3675,7 +4092,7 @@ kanji_end: break; case 0x0c: /* form feed, clears screen */ - sc_clear_screen(scp); + clear_screen(scp); break; case 0x0d: /* return, return to pos 0 */ @@ -3694,20 +4111,6 @@ kanji_end: scp->xpos = 0; break; -#ifdef PC98 - case 0x0e: /* ^N */ - scp->kanji_type = KTYPE_JKANA; - scp->term.esc = 0; - scp->kanji_1st_char = 0; - break; - - case 0x0f: /* ^O */ - scp->kanji_type = KTYPE_ASCII; - scp->term.esc = 0; - scp->kanji_1st_char = 0; - break; -#endif - case 0x1b: /* start escape sequence */ scp->term.esc = 1; scp->term.num_param = 0; @@ -3718,7 +4121,7 @@ kanji_end: /* do we have to scroll ?? */ if (scp->cursor_pos >= scp->scr_buf + scp->ysize * scp->xsize) { remove_cutmarking(scp); - if (scp->history != NULL) { + if (scp->history) { bcopy(scp->scr_buf, scp->history_head, scp->xsize * sizeof(u_short)); scp->history_head += scp->xsize; @@ -3734,8 +4137,7 @@ kanji_end: #endif scp->history_head = scp->history; #ifdef PC98 - scp->his_atr_head = scp->his_atr; - } + scp->his_atr_head = scp->his_atr; } #endif } bcopy(scp->scr_buf + scp->xsize, scp->scr_buf, @@ -3772,30 +4174,66 @@ kanji_end: static void scinit(void) { - video_adapter_t *adp; - int col; - int row; + u_int hw_cursor; u_int i; if (init_done != COLD) return; init_done = WARM; - get_bios_values(); - #ifdef PC98 - if (pc98_machine_type & M_8M) - BELL_PITCH = 1339; - else - BELL_PITCH = 1678; -#endif + if (pc98_machine_type & M_8M) { + BELL_PITCH = 1339; + } else { + BELL_PITCH = 1678; + } + outb(0x62, 0xd); + outb(0xA2, 0xd); + /* Extract cursor location */ + while((inb(TEXT_GDC + 0) & 0x04) == 0) {} /* GDC wait */ + outb(TEXT_GDC + 2, 0xe0); /* CSRR */ + while((inb(TEXT_GDC + 0) & 0x1) == 0) {} /* GDC wait */ + hw_cursor = inb(TEXT_GDC + 2); /* EADl */ + hw_cursor |= (inb(TEXT_GDC + 2) << 8); /* EADh */ + inb(TEXT_GDC + 2); /* dummy */ + inb(TEXT_GDC + 2); /* dummy */ + inb(TEXT_GDC + 2); /* dummy */ - /* extract the hardware cursor location and hide the cursor for now */ - adp = vid_get_adapter(adapter); - (*vidsw[adapter]->read_hw_cursor)(adp, &col, &row); -#ifndef PC98 - (*vidsw[adapter]->set_hw_cursor)(adp, -1, -1); -#endif + if (hw_cursor >= ROW*COL) { + hw_cursor = 0; + } + crtc_vga = TRUE; +#else /* IBM-PC */ + /* + * Ensure a zero start address. This is mainly to recover after + * switching from pcvt using userconfig(). The registers are w/o + * for old hardware so it's too hard to relocate the active screen + * memory. + */ + outb(crtc_addr, 12); + outb(crtc_addr + 1, 0); + outb(crtc_addr, 13); + outb(crtc_addr + 1, 0); + + /* extract cursor location */ + outb(crtc_addr, 14); + hw_cursor = inb(crtc_addr + 1) << 8; + outb(crtc_addr, 15); + hw_cursor |= inb(crtc_addr + 1); + + /* + * Validate cursor location. It may be off the screen. Then we must + * not use it for the initial buffer offset. + */ + if (hw_cursor >= ROW * COL) + hw_cursor = (ROW - 1) * COL; + + /* move hardware cursor out of the way */ + outb(crtc_addr, 14); + outb(crtc_addr + 1, 0xff); + outb(crtc_addr, 15); + outb(crtc_addr + 1, 0xff); +#endif /* PC98 */ /* set up the first console */ current_default = &user_default; @@ -3803,27 +4241,57 @@ scinit(void) init_scp(console[0]); cur_console = console[0]; +#ifndef PC98 + /* discard the video mode table if we are not familiar with it... */ + if (video_mode_ptr) { + bzero(mode_map, sizeof(mode_map)); + bcopy(video_mode_ptr + MODE_PARAM_SIZE*console[0]->mode, + vgaregs2, sizeof(vgaregs2)); + switch (comp_vgaregs(vgaregs, video_mode_ptr + + MODE_PARAM_SIZE*console[0]->mode)) { + case COMP_IDENTICAL: + map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); + /* + * This is a kludge for Toshiba DynaBook SS433 whose BIOS video + * mode table entry has the actual # of rows at the offset 1; + * BIOSes from other manufacturers store the # of rows - 1 there. + * XXX + */ + rows_offset = vgaregs[1] + 1 + - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; + break; + case COMP_SIMILAR: + map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); + mode_map[console[0]->mode] = vgaregs; + rows_offset = vgaregs[1] + 1 + - video_mode_ptr[MODE_PARAM_SIZE*console[0]->mode + 1]; + vgaregs[1] -= rows_offset - 1; + break; + case COMP_DIFFERENT: + default: + video_mode_ptr = NULL; + mode_map[console[0]->mode] = vgaregs; + rows_offset = 1; + break; + } + } +#endif /* copy screen to temporary buffer */ - if (ISTEXTSC(console[0])) - generic_bcopy((ushort *)(console[0]->adp->va_window), sc_buffer, - console[0]->xsize * console[0]->ysize * sizeof(u_short)); + if (!VESA_MODE(console[0]->mode)) + generic_bcopy(Crtat, sc_buffer, + console[0]->xsize * console[0]->ysize * sizeof(u_short)); console[0]->scr_buf = console[0]->mouse_pos = console[0]->mouse_oldpos = sc_buffer; - if (col >= console[0]->xsize) - col = 0; - if (row >= console[0]->ysize) - row = console[0]->ysize - 1; - console[0]->xpos = col; - console[0]->ypos = row; - console[0]->cursor_pos = console[0]->cursor_oldpos = - sc_buffer + row*console[0]->xsize + col; -#ifndef PC98 - console[0]->cursor_saveunder = *console[0]->cursor_pos; -#else + console[0]->cursor_pos = console[0]->cursor_oldpos = sc_buffer + hw_cursor; +#ifdef PC98 console[0]->atr_buf = Atrat; - console[0]->cursor_atr = Atrat + row*console[0]->xsize + col; + console[0]->cursor_atr = Atrat + hw_cursor; +#else + console[0]->cursor_saveunder = *console[0]->cursor_pos; #endif + console[0]->xpos = hw_cursor % COL; + console[0]->ypos = hw_cursor / COL; for (i=1; i<MAXCONS; i++) console[i] = NULL; kernel_console.esc = 0; @@ -3838,141 +4306,93 @@ scinit(void) scr_map[i] = scr_rmap[i] = i; } #ifdef PC98 - scr_map[0x5c] = (u_char)0xfc; /* for backslash */ + scr_map[0x5c] = (u_char)0xfc; /* for backslash */ #endif - /* Save font and palette */ - if (ISFONTAVAIL(cur_console->adp->va_flags)) { - if (fonts_loaded & FONT_16) { - copy_font(cur_console, LOAD, 16, font_16); - } else { - copy_font(cur_console, SAVE, 16, font_16); - fonts_loaded = FONT_16; - set_destructive_cursor(cur_console); +#ifndef PC98 + /* Save font and palette if VGA */ + if (crtc_type == KD_VGA) { + if (!VESA_MODE(bios_video_mode)) { + if (fonts_loaded & FONT_16) { + copy_font(LOAD, FONT_16, font_16); + } else { + copy_font(SAVE, FONT_16, font_16); + fonts_loaded = FONT_16; + } + set_destructive_cursor(console[0]); } - /* - * FONT KLUDGE - * Always use the font page #0. XXX - */ - (*vidsw[cur_console->ad]->show_font)(cur_console->adp, 0); + save_palette(); } - save_palette(cur_console->adp, palette); -#if NSPLASH > 0 - /* we are ready to put up the splash image! */ - splash_init(cur_console->adp, scsplash_callback); +#ifdef SC_SPLASH_SCREEN + /* + * If not booting verbosely, put up the splash. + * Note that the splash screen is not currently supported in + * the VESA mode. + */ + if (!(boothowto & RB_VERBOSE) && !VESA_MODE(bios_video_mode)) + scsplash_init(); +#endif #endif } static void scshutdown(int howto, void *arg) { - sc_touch_scrn_saver(); + scsplash_stick(FALSE); + run_scrn_saver = FALSE; if (!cold && cur_console->smode.mode == VT_AUTO && console[0]->smode.mode == VT_AUTO) switch_scr(cur_console, 0); shutdown_in_progress = TRUE; } -int -sc_clean_up(scr_stat *scp) +static void +map_mode_table(char *map[], char *table, int max) { - int error; + int i; - sc_touch_scrn_saver(); -#if NSPLASH > 0 - if ((error = wait_scrn_saver_stop())) - return error; -#endif /* NSPLASH */ - scp->status &= ~MOUSE_VISIBLE; - remove_cutmarking(scp); - return 0; + for(i = 0; i < max; ++i) + map[i] = table + i*MODE_PARAM_SIZE; + for(; i < MODE_MAP_SIZE; ++i) + map[i] = NULL; } -void -sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear) +static int +map_mode_num(int mode) { - if (scp->scr_buf) - free(scp->scr_buf, M_DEVBUF); - scp->scr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), - M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); -#ifdef PC98 - if (scp->atr_buf) - free(scp->atr_buf, M_DEVBUF); - scp->atr_buf = (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), - M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); -#endif - - if (clear) { - /* clear the screen and move the text cursor to the top-left position */ - sc_clear_screen(scp); - } else { - /* retain the current cursor position, but adjust pointers */ - move_crsr(scp, scp->xpos, scp->ypos); - scp->cursor_oldpos = scp->cursor_pos; - } - - /* move the mouse cursor at the center of the screen */ - sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); -} + static struct { + int from; + int to; + } mode_map[] = { + { M_ENH_B80x43, M_ENH_B80x25 }, + { M_ENH_C80x43, M_ENH_C80x25 }, + { M_VGA_M80x30, M_VGA_M80x25 }, + { M_VGA_C80x30, M_VGA_C80x25 }, + { M_VGA_M80x50, M_VGA_M80x25 }, + { M_VGA_C80x50, M_VGA_C80x25 }, + { M_VGA_M80x60, M_VGA_M80x25 }, + { M_VGA_C80x60, M_VGA_C80x25 }, + { M_VGA_MODEX, M_VGA_CG320 }, + }; + int i; -void -sc_alloc_cut_buffer(scr_stat *scp, int wait) -{ - if ((cut_buffer == NULL) - || (cut_buffer_size < scp->xsize * scp->ysize + 1)) { - if (cut_buffer != NULL) - free(cut_buffer, M_DEVBUF); - cut_buffer_size = scp->xsize * scp->ysize + 1; - cut_buffer = (u_char *)malloc(cut_buffer_size, - M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); - if (cut_buffer != NULL) - cut_buffer[0] = '\0'; + 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; } -void -sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait) +static char +*get_mode_param(scr_stat *scp, int mode) { - u_short *usp; -#ifdef PC98 - u_short *atr_usp; -#endif - - if (lines < scp->ysize) - lines = scp->ysize; - - usp = scp->history; - scp->history = NULL; - if (usp != NULL) { - free(usp, M_DEVBUF); - if (extra > 0) - extra_history_size += extra; - } -#ifdef PC98 - atr_usp = scp->his_atr; - scp->his_atr = NULL; - if (atr_usp != NULL) - free(atr_usp, M_DEVBUF); -#endif - - scp->history_size = lines * scp->xsize; - if (lines > imax(sc_history_size, scp->ysize)) - extra_history_size -= lines - imax(sc_history_size, scp->ysize); - usp = (u_short *)malloc(scp->history_size * sizeof(u_short), - M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); - if (usp != NULL) - bzero(usp, scp->history_size * sizeof(u_short)); - scp->history_head = scp->history_pos = usp; - scp->history = usp; -#ifdef PC98 - atr_usp = (u_short *)malloc(scp->history_size * sizeof(u_short), - M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT); - if (atr_usp != NULL) - bzero(atr_usp, scp->history_size * sizeof(u_short)); - scp->his_atr_head = scp->his_atr_pos = atr_usp; - scp->his_atr = atr_usp; -#endif + if (mode >= MODE_MAP_SIZE) + mode = map_mode_num(mode); + if (mode < MODE_MAP_SIZE) + return mode_map[mode]; + else + return NULL; } static scr_stat @@ -3982,21 +4402,34 @@ static scr_stat scp = (scr_stat *)malloc(sizeof(scr_stat), M_DEVBUF, M_WAITOK); init_scp(scp); - sc_alloc_scr_buffer(scp, TRUE, TRUE); + scp->scr_buf = scp->cursor_pos = scp->cursor_oldpos = + (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), + M_DEVBUF, M_WAITOK); + scp->mouse_pos = scp->mouse_oldpos = + scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + + scp->mouse_xpos/8); + scp->history_head = scp->history_pos = + (u_short *)malloc(scp->history_size*sizeof(u_short), + M_DEVBUF, M_WAITOK); + bzero(scp->history_head, scp->history_size*sizeof(u_short)); + scp->history = scp->history_head; #ifdef PC98 - sc_alloc_cut_buffer(scp, TRUE); -#else /* PC98 */ - if (ISMOUSEAVAIL(scp->adp->va_flags)) - sc_alloc_cut_buffer(scp, TRUE); -#endif /* PC98 */ - sc_alloc_history_buffer(scp, sc_history_size, 0, TRUE); + scp->atr_buf = scp->cursor_atr = scp->atr_buf = + (u_short *)malloc(scp->xsize*scp->ysize*sizeof(u_short), + M_DEVBUF, M_WAITOK); + scp->his_atr_head = scp->his_atr_pos = + (u_short *)malloc(scp->history_size*sizeof(u_short), + M_DEVBUF, M_WAITOK); + bzero(scp->his_atr_head, scp->history_size*sizeof(u_short)); + scp->his_atr = scp->his_atr_head; +#endif /* SOS #ifndef PC98 - if (scp->adp->va_flags & V_ADP_MODECHANGE) + if (crtc_type == KD_VGA && video_mode_ptr) #endif set_mode(scp); */ - sc_clear_screen(scp); + clear_screen(scp); #ifndef PC98 scp->cursor_saveunder = *scp->cursor_pos; #endif @@ -4006,30 +4439,47 @@ static scr_stat static void init_scp(scr_stat *scp) { - video_info_t info; - - scp->ad = adapter; - scp->adp = vid_get_adapter(scp->ad); - (*vidsw[scp->ad]->get_info)(scp->adp, initial_video_mode, &info); - - scp->status = 0; - scp->mode = initial_video_mode; - scp->scr_buf = NULL; - if (info.vi_flags & V_INFO_GRAPHICS) { - scp->status |= GRAPHICS_MODE; - scp->xpixel = info.vi_width; - scp->ypixel = info.vi_height; - scp->xsize = info.vi_width/8; - scp->ysize = info.vi_height/info.vi_cheight; - scp->font_size = FONT_NONE; - } else { - scp->xsize = info.vi_width; - scp->ysize = info.vi_height; - scp->xpixel = scp->xsize*8; - scp->ypixel = scp->ysize*info.vi_cheight; - scp->font_size = info.vi_cheight; +#ifdef PC98 + scp->mode = M_PC98_80x25; + scp->font_size = 16; +#else + switch(crtc_type) { + case KD_VGA: + if (VESA_MODE(bios_video_mode)) + scp->mode = bios_video_mode; + else if (crtc_addr == MONO_BASE) + scp->mode = M_VGA_M80x25; + else + scp->mode = M_VGA_C80x25; + else + scp->font_size = 16; + break; + case KD_CGA: + if (crtc_addr == MONO_BASE) + scp->mode = M_B80x25; + else + scp->mode = M_C80x25; + scp->font_size = 8; + break; + case KD_EGA: + scp->mode = M_B80x25; + else + scp->mode = M_C80x25; + scp->font_size = 14; + break; + case KD_MONO: + case KD_HERCULES: + default: + scp->mode = M_EGAMONO80x25; + scp->font_size = 14; + break; } - scp->xoff = scp->yoff = 0; + scp->initial_mode = scp->mode; +#endif + scp->xsize = COL; + scp->ysize = ROW; + scp->xpixel = scp->xsize * 8; + scp->ypixel = scp->ysize * scp->font_size; scp->xpos = scp->ypos = 0; scp->saved_xpos = scp->saved_ypos = -1; scp->start = scp->xsize * scp->ysize; @@ -4041,21 +4491,28 @@ init_scp(scr_stat *scp) current_default->std_color; scp->term.rev_color = current_default->rev_color; scp->border = BG_BLACK; - scp->cursor_start = bios_value.cursor_start; - scp->cursor_end = bios_value.cursor_end; +#ifdef PC98 + scp->cursor_start = 0; + scp->cursor_end = 0; +#else + scp->cursor_start = *(char *)pa_to_va(0x461); + scp->cursor_end = *(char *)pa_to_va(0x460); +#endif scp->mouse_xpos = scp->xsize*8/2; scp->mouse_ypos = scp->ysize*scp->font_size/2; scp->mouse_cut_start = scp->mouse_cut_end = NULL; scp->mouse_signal = 0; scp->mouse_pid = 0; scp->mouse_proc = NULL; - scp->kbd_mode = K_XLATE; scp->bell_pitch = BELL_PITCH; scp->bell_duration = BELL_DURATION; -#ifndef PC98 - scp->status |= (bios_value.shift_state & 0x20) ? NLKED : 0; -#endif +#ifdef PC98 + scp->status = 0; scp->status |= CURSOR_ENABLED; +#else + scp->status = (*(char *)pa_to_va(0x417) & 0x20) ? NLKED : 0; + scp->status |= CURSOR_ENABLED; +#endif scp->pid = 0; scp->proc = NULL; scp->smode.mode = VT_AUTO; @@ -4063,25 +4520,25 @@ init_scp(scr_stat *scp) #ifdef PC98 scp->his_atr_head = scp->his_atr_pos = scp->his_atr = NULL; #endif - scp->history_size = imax(sc_history_size, scp->ysize) * scp->xsize; + scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize; #ifdef KANJI scp->kanji_1st_char = 0; - scp->kanji_type = KTYPE_ASCII; + scp->kanji_type = 0; #endif } -static void -get_bios_values(void) +static u_char +*get_fstr(u_int c, u_int *len) { -#ifdef PC98 - bios_value.cursor_start = 0; - bios_value.cursor_end = 0; - bios_value.shift_state = 0; -#else /* !PC98 */ - bios_value.cursor_start = *(u_int8_t *)pa_to_va(0x461); - bios_value.cursor_end = *(u_int8_t *)pa_to_va(0x460); - bios_value.shift_state = *(u_int8_t *)pa_to_va(0x417); -#endif + u_int i; + + if (!(c & FKEY)) + return(NULL); + i = (c & 0xFF) - F_FN; + if (i > n_fkey_tab) + return(NULL); + *len = fkey_tab[i].len; + return(fkey_tab[i].str); } static void @@ -4144,46 +4601,151 @@ history_down_line(scr_stat *scp) * return NOKEY if there is nothing there. */ static u_int -scgetc(keyboard_t *kbd, u_int flags) +scgetc(u_int flags) { - u_int c; - int this_scr; - int f; - int i; - - if (kbd == NULL) - return NOKEY; + struct key_t *key; + u_char scancode, keycode; + u_int state, action; + int c; + static u_char esc_flag = 0, compose = 0; + static u_int chr = 0; next_code: - /* I don't like this, but... XXX */ - if (flags & SCGETC_CN) - sccnupdate(cur_console); /* first see if there is something in the keyboard port */ - for (;;) { - c = kbd_read_char(kbd, !(flags & SCGETC_NONBLOCK)); - if (c == ERRKEY) { - if (!(flags & SCGETC_CN)) - do_bell(cur_console, BELL_PITCH, BELL_DURATION); - } else if (c == NOKEY) - return c; - else - break; + if (flags & SCGETC_NONBLOCK) { + c = read_kbd_data_no_wait(sc_kbdc); + if (c == -1) + return(NOKEY); + } else { + do { + c = read_kbd_data(sc_kbdc); + } while(c == -1); } + scancode = (u_char)c; /* make screensaver happy */ - if (!(c & RELKEY)) - sc_touch_scrn_saver(); + if (!(scancode & 0x80)) { + scsplash_stick(FALSE); + run_scrn_saver = FALSE; + } - if (!(flags & SCGETC_CN)) + if (!(flags & SCGETC_CN)) { /* do the /dev/random device a favour */ - add_keyboard_randomness(c); + add_keyboard_randomness(scancode); + + if (cur_console->status & KBD_RAW_MODE) + return scancode; + } + + keycode = scancode & 0x7F; + switch (esc_flag) { + case 0x00: /* normal scancode */ + switch(scancode) { + case 0xB8: /* left alt (compose key) */ + if (compose) { + compose = 0; + if (chr > 255) { + do_bell(cur_console, + BELL_PITCH, BELL_DURATION); + chr = 0; + } + } + break; + case 0x38: + if (!compose) { + compose = 1; + chr = 0; + } + break; + case 0xE0: + case 0xE1: + esc_flag = scancode; + goto next_code; + } + break; + case 0xE0: /* 0xE0 prefix */ + esc_flag = 0; + switch (keycode) { + case 0x1C: /* right enter key */ + keycode = 0x59; + break; + case 0x1D: /* right ctrl key */ + keycode = 0x5A; + break; + case 0x35: /* keypad divide key */ + keycode = 0x5B; + break; + case 0x37: /* print scrn key */ + keycode = 0x5C; + break; + case 0x38: /* right alt key (alt gr) */ + keycode = 0x5D; + break; + case 0x47: /* grey home key */ + keycode = 0x5E; + break; + case 0x48: /* grey up arrow key */ + keycode = 0x5F; + break; + case 0x49: /* grey page up key */ + keycode = 0x60; + break; + case 0x4B: /* grey left arrow key */ + keycode = 0x61; + break; + case 0x4D: /* grey right arrow key */ + keycode = 0x62; + break; + case 0x4F: /* grey end key */ + keycode = 0x63; + break; + case 0x50: /* grey down arrow key */ + keycode = 0x64; + break; + case 0x51: /* grey page down key */ + keycode = 0x65; + break; + case 0x52: /* grey insert key */ + keycode = 0x66; + break; + case 0x53: /* grey delete key */ + keycode = 0x67; + break; - if (cur_console->kbd_mode != K_XLATE) - return KEYCHAR(c); + /* the following 3 are only used on the MS "Natural" keyboard */ + case 0x5b: /* left Window key */ + keycode = 0x69; + break; + case 0x5c: /* right Window key */ + keycode = 0x6a; + break; + case 0x5d: /* menu key */ + keycode = 0x6b; + break; + default: /* ignore everything else */ + goto next_code; + } + break; + case 0xE1: /* 0xE1 prefix */ + esc_flag = 0; + if (keycode == 0x1D) + esc_flag = 0x1D; + goto next_code; + /* NOT REACHED */ + case 0x1D: /* pause / break */ + esc_flag = 0; + if (keycode != 0x45) + goto next_code; + keycode = 0x68; + break; + } + + if (!(flags & SCGETC_CN) && (cur_console->status & KBD_CODE_MODE)) + return (keycode | (scancode & 0x80)); /* if scroll-lock pressed allow history browsing */ - if (!ISGRAPHSC(cur_console) && cur_console->history - && cur_console->status & SLKED) { + if (cur_console->history && cur_console->status & SLKED) { + int i; cur_console->status &= ~CURSOR_ENABLED; if (!(cur_console->status & BUFFER_SAVED)) { @@ -4209,11 +4771,10 @@ next_code: cur_console->history + cur_console->history_size) #ifdef PC98 { +#endif cur_console->history_head=cur_console->history; - cur_console->his_atr_head=cur_console->his_atr; - } -#else - cur_console->history_head=cur_console->history; +#ifdef PC98 + cur_console->his_atr_head=cur_console->his_atr; } #endif } cur_console->history_pos = cur_console->history_head; @@ -4222,10 +4783,12 @@ next_code: #endif history_to_screen(cur_console); } - switch (c) { - /* FIXME: key codes */ - case SPCLKEY | FKEY | F(49): /* home key */ - remove_cutmarking(cur_console); + switch (scancode) { +#ifdef PC98 + case 0x3E: /* home key */ +#else + case 0x47: /* home key */ +#endif cur_console->history_pos = cur_console->history_head; #ifdef PC98 cur_console->his_atr_pos = cur_console->his_atr_head; @@ -4233,8 +4796,11 @@ next_code: history_to_screen(cur_console); goto next_code; - case SPCLKEY | FKEY | F(57): /* end key */ - remove_cutmarking(cur_console); +#ifdef PC98 + case 0x3F: /* help key */ +#else + case 0x4F: /* end key */ +#endif cur_console->history_pos = WRAPHIST(cur_console, cur_console->history_head, cur_console->xsize*cur_console->ysize); @@ -4246,65 +4812,183 @@ next_code: history_to_screen(cur_console); goto next_code; - case SPCLKEY | FKEY | F(50): /* up arrow key */ - remove_cutmarking(cur_console); +#ifdef PC98 + case 0x3A: /* up arrow key */ +#else + case 0x48: /* up arrow key */ +#endif if (history_up_line(cur_console)) - if (!(flags & SCGETC_CN)) - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + do_bell(cur_console, BELL_PITCH, BELL_DURATION); goto next_code; - case SPCLKEY | FKEY | F(58): /* down arrow key */ - remove_cutmarking(cur_console); +#ifdef PC98 + case 0x3D: /* down arrow key */ +#else + case 0x50: /* down arrow key */ +#endif if (history_down_line(cur_console)) - if (!(flags & SCGETC_CN)) - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + do_bell(cur_console, BELL_PITCH, BELL_DURATION); goto next_code; - case SPCLKEY | FKEY | F(51): /* page up key */ - remove_cutmarking(cur_console); +#ifdef PC98 + case 0x36: /* roll up key */ +#else + case 0x49: /* page up key */ +#endif for (i=0; i<cur_console->ysize; i++) if (history_up_line(cur_console)) { - if (!(flags & SCGETC_CN)) - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + do_bell(cur_console, BELL_PITCH, BELL_DURATION); break; } goto next_code; - case SPCLKEY | FKEY | F(59): /* page down key */ - remove_cutmarking(cur_console); +#ifdef PC98 + case 0x37: /* roll down key */ +#else + case 0x51: /* page down key */ +#endif for (i=0; i<cur_console->ysize; i++) if (history_down_line(cur_console)) { - if (!(flags & SCGETC_CN)) - do_bell(cur_console, BELL_PITCH, BELL_DURATION); + do_bell(cur_console, BELL_PITCH, BELL_DURATION); break; } goto next_code; } } - /* - * Process and consume special keys here. Return a plain char code - * or a char code with the META flag or a function key code. - */ - if (c & RELKEY) { - /* key released */ - /* goto next_code */ + if (compose) { + switch (scancode) { + /* key pressed process it */ + case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ + chr = (scancode - 0x40) + chr*10; + goto next_code; + case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ + chr = (scancode - 0x47) + chr*10; + goto next_code; + case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ + chr = (scancode - 0x4E) + chr*10; + goto next_code; + case 0x52: /* keypad 0 */ + chr *= 10; + goto next_code; + + /* key release, no interest here */ + case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ + case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ + case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ + case 0xD2: /* keypad 0 */ + goto next_code; + + case 0x38: /* left alt key */ + break; + default: + if (chr) { + compose = chr = 0; + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + goto next_code; + } + break; + } + } + + state = (shfts ? 1 : 0 ) | (2 * (ctls ? 1 : 0)) | (4 * (alts ? 1 : 0)); + if ((!agrs && (cur_console->status & ALKED)) + || (agrs && !(cur_console->status & ALKED))) + keycode += ALTGR_OFFSET; + key = &key_map.key[keycode]; + if ( ((key->flgs & FLAG_LOCK_C) && (cur_console->status & CLKED)) + || ((key->flgs & FLAG_LOCK_N) && (cur_console->status & NLKED)) ) + state ^= 1; + + /* Check for make/break */ + action = key->map[state]; + if (scancode & 0x80) { /* key released */ + if (key->spcl & (0x80>>state)) { + switch (action) { + case LSH: + shfts &= ~1; + break; + case RSH: + shfts &= ~2; + break; + case LCTR: + ctls &= ~1; + break; + case RCTR: + ctls &= ~2; + break; + case LALT: + alts &= ~1; + break; + case RALT: + alts &= ~2; + break; + case NLK: + nlkcnt = 0; + break; + case CLK: +#ifdef PC98 + cur_console->status &= ~CLKED; + update_leds(cur_console->status); +#else + clkcnt = 0; +#endif + break; + case SLK: + slkcnt = 0; + break; + case ASH: + agrs = 0; + break; + case ALK: + alkcnt = 0; + break; + case META: + metas = 0; + break; + } + } + if (chr && !compose) { + action = chr; + chr = 0; + return(action); + } } else { /* key pressed */ - if (c & SPCLKEY) { - c &= ~SPCLKEY; - switch (KEYCHAR(c)) { + if (key->spcl & (0x80>>state)) { + switch (action) { /* LOCKING KEYS */ - case NLK: case CLK: case ALK: + case NLK: + if (!nlkcnt) { + nlkcnt++; + if (cur_console->status & NLKED) + cur_console->status &= ~NLKED; + else + cur_console->status |= NLKED; + update_leds(cur_console->status); + } + break; + case CLK: +#ifdef PC98 + cur_console->status |= CLKED; + update_leds(cur_console->status); +#else + if (!clkcnt) { + clkcnt++; + if (cur_console->status & CLKED) + cur_console->status &= ~CLKED; + else + cur_console->status |= CLKED; + update_leds(cur_console->status); + } +#endif break; case SLK: - kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&f); - if (f & SLKED) { - cur_console->status |= SLKED; - } else { + if (!slkcnt) { + slkcnt++; if (cur_console->status & SLKED) { cur_console->status &= ~SLKED; - if (cur_console->status & BUFFER_SAVED) { + if (cur_console->status & BUFFER_SAVED){ int i; u_short *ptr = cur_console->history_save; #ifdef PC98 @@ -4328,12 +5012,11 @@ next_code: cur_console->history + cur_console->history_size) #ifdef PC98 - { - ptr = cur_console->history; - ptr_a = cur_console->his_atr; - } -#else + { +#endif ptr = cur_console->history; +#ifdef PC98 + ptr_a = cur_console->his_atr; } #endif } cur_console->status &= ~BUFFER_SAVED; @@ -4346,64 +5029,73 @@ next_code: } scstart(VIRTUAL_TTY(get_scr_num())); } + else + cur_console->status |= SLKED; + update_leds(cur_console->status); + } + break; + case ALK: + if (!alkcnt) { + alkcnt++; + if (cur_console->status & ALKED) + cur_console->status &= ~ALKED; + else + cur_console->status |= ALKED; + update_leds(cur_console->status); } break; /* NON-LOCKING KEYS */ case NOP: - case LSH: case RSH: case LCTR: case RCTR: - case LALT: case RALT: case ASH: case META: break; - - case BTAB: - return c; - case SPSC: /* force activatation/deactivation of the screen saver */ - if (!scrn_blanked) { + accents = 0; + if (scrn_blanked <= 0) { run_scrn_saver = TRUE; scrn_time_stamp -= scrn_blank_time; } -#if NSPLASH > 0 +#ifdef SC_SPLASH_SCREEN if (cold) { /* * While devices are being probed, the screen saver need * to be invoked explictly. XXX */ - if (scrn_blanked) { + if (scrn_blanked > 0) { scsplash_stick(FALSE); stop_scrn_saver(current_saver); } else { - if (!ISGRAPHSC(cur_console)) { + if ((cur_console->status & UNKNOWN_MODE) == 0) { scsplash_stick(TRUE); (*current_saver)(TRUE); } } } -#endif /* NSPLASH */ +#endif break; - case RBT: #ifndef SC_DISABLE_REBOOT + accents = 0; shutdown_nice(); #endif break; - -#if NAPM > 0 case SUSP: +#if NAPM > 0 + accents = 0; apm_suspend(PMST_SUSPEND); +#endif break; + case STBY: +#if NAPM > 0 + accents = 0; apm_suspend(PMST_STANDBY); - break; -#else - case SUSP: - case STBY: - break; #endif + break; case DBG: #ifdef DDB /* try to switch to console 0 */ + accents = 0; /* * TRY to make sure the screen saver is stopped, * and the screen is updated before switching to @@ -4418,47 +5110,135 @@ next_code: printf("No debugger in kernel\n"); #endif break; - + case LSH: + shfts |= 1; + break; + case RSH: + shfts |= 2; + break; + case LCTR: + ctls |= 1; + break; + case RCTR: + ctls |= 2; + break; + case LALT: + alts |= 1; + break; + case RALT: + alts |= 2; + break; + case ASH: + agrs = 1; + break; + case META: + metas = 1; + break; case NEXT: - this_scr = get_scr_num(); - for (i = this_scr + 1; i != this_scr; i = (i + 1)%MAXCONS) { - struct tty *tp = VIRTUAL_TTY(i); + { + int next, this = get_scr_num(); + accents = 0; + for (next = this+1; next != this; next = (next+1)%MAXCONS) { + struct tty *tp = VIRTUAL_TTY(next); if (tp->t_state & TS_ISOPEN) { - switch_scr(cur_console, i); + switch_scr(cur_console, next); break; } } + } break; - + case BTAB: + accents = 0; + return(BKEY); default: - if (KEYCHAR(c) >= F_SCR && KEYCHAR(c) <= L_SCR) { - switch_scr(cur_console, KEYCHAR(c) - F_SCR); + if (action >= F_ACC && action <= L_ACC) { + /* turn it into an index */ + action -= F_ACC - 1; + if ((action > accent_map.n_accs) + || (accent_map.acc[action - 1].accchar == 0)) { + /* + * The index is out of range or pointing to an + * empty entry. + */ + accents = 0; + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + } + /* + * If the same accent key has been hit twice, + * produce the accent char itself. + */ + if (action == accents) { + action = accent_map.acc[accents - 1].accchar; + accents = 0; + if (metas) + action |= MKEY; + return (action); + } + /* remember the index and wait for the next key stroke */ + accents = action; + break; + } + if (accents > 0) { + accents = 0; + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + } + if (action >= F_SCR && action <= L_SCR) { + switch_scr(cur_console, action - F_SCR); break; } - /* assert(c & FKEY) */ - return c; + if (action >= F_FN && action <= L_FN) + action |= FKEY; + return(action); } - /* goto next_code */ - } else { - /* regular keys (maybe MKEY is set) */ - return c; } - } + else { + if (accents) { + struct acc_t *acc; + int i; + acc = &accent_map.acc[accents - 1]; + accents = 0; + /* + * If the accent key is followed by the space key, + * produce the accent char itself. + */ + if (action == ' ') { + action = acc->accchar; + if (metas) + action |= MKEY; + return (action); + } + for (i = 0; i < NUM_ACCENTCHARS; ++i) { + if (acc->map[i][0] == 0) /* end of the map entry */ + break; + if (acc->map[i][0] == action) { + action = acc->map[i][1]; + if (metas) + action |= MKEY; + return (action); + } + } + do_bell(cur_console, BELL_PITCH, BELL_DURATION); + goto next_code; + } + if (metas) + action |= MKEY; + return(action); + } + } goto next_code; } int -scmmap(dev_t dev, vm_offset_t offset, int nprot) +scmmap(dev_t dev, int offset, int nprot) { - struct tty *tp; - struct scr_stat *scp; - - tp = scdevtotty(dev); - if (!tp) - return ENXIO; - scp = sc_get_scr_stat(tp->t_dev); - return (*vidsw[scp->ad]->mmap)(scp->adp, offset); +#ifdef PC98 + if (offset > 0x48000 - PAGE_SIZE) +#else + if (offset > 0x20000 - PAGE_SIZE) +#endif + return -1; + return i386_btop((VIDEOMEM + offset)); } /* @@ -4490,213 +5270,585 @@ mask2attr(struct term_stat *term) return attr; } -static int -save_kbd_state(scr_stat *scp) +static void +set_keyboard(int command, int data) { - int state; - int error; +#ifndef PC98 + int s; + + if (sc_kbdc == NULL) + return; + + /* prevent the timeout routine from polling the keyboard */ + if (!kbdc_lock(sc_kbdc, TRUE)) + return; - error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state); - if (error == ENOIOCTL) - error = ENODEV; - if (error == 0) { - scp->status &= ~LOCK_MASK; - scp->status |= state; + /* disable the keyboard and mouse interrupt */ + s = spltty(); +#if 0 + c = get_controller_command_byte(sc_kbdc); + if ((c == -1) + || !set_controller_command_byte(sc_kbdc, + kbdc_get_device_mask(sc_kbdc), + KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { + /* CONTROLLER ERROR */ + kbdc_lock(sc_kbdc, FALSE); + splx(s); + return; } - return error; -} + /* + * Now that the keyboard controller is told not to generate + * the keyboard and mouse interrupts, call `splx()' to allow + * the other tty interrupts. The clock interrupt may also occur, + * but the timeout routine (`scrn_timer()') will be blocked + * by the lock flag set via `kbdc_lock()' + */ + splx(s); +#endif -static int -update_kbd_state(int new_bits, int mask) -{ - int state; - int error; + if (send_kbd_command_and_data(sc_kbdc, command, data) != KBD_ACK) + send_kbd_command(sc_kbdc, KBDC_ENABLE_KBD); - if (mask != LOCK_MASK) { - error = kbd_ioctl(kbd, KDGKBSTATE, (caddr_t)&state); - if (error == ENOIOCTL) - error = ENODEV; - if (error) - return error; - state &= ~mask; - state |= new_bits & mask; - } else { - state = new_bits & LOCK_MASK; +#if 0 + /* restore the interrupts */ + if (!set_controller_command_byte(sc_kbdc, + kbdc_get_device_mask(sc_kbdc), + c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { + /* CONTROLLER ERROR */ } - error = kbd_ioctl(kbd, KDSKBSTATE, (caddr_t)&state); - if (error == ENOIOCTL) - error = ENODEV; - return error; +#else + splx(s); +#endif + kbdc_lock(sc_kbdc, FALSE); +#endif } -static int -update_kbd_leds(int which) +static void +update_leds(int which) { - int error; +#ifndef PC98 + int s; + static u_char xlate_leds[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - which &= LOCK_MASK; - error = kbd_ioctl(kbd, KDSETLED, (caddr_t)&which); - if (error == ENOIOCTL) - error = ENODEV; - return error; + /* replace CAPS led with ALTGR led for ALTGR keyboards */ + if (key_map.n_keys > ALTGR_OFFSET) { + if (which & ALKED) + which |= CLKED; + else + which &= ~CLKED; + } + + set_keyboard(KBDC_SET_LEDS, xlate_leds[which & LED_MASK]); +#endif } -int +void set_mode(scr_stat *scp) { - video_info_t info; - - /* reject unsupported mode */ - if ((*vidsw[scp->ad]->get_info)(scp->adp, scp->mode, &info)) - return 1; + char special_modetable[MODE_PARAM_SIZE]; + char *mp; + int s; + int i; - /* if this vty is not currently showing, do nothing */ if (scp != cur_console) - return 0; + return; - /* setup video hardware for the given mode */ - (*vidsw[scp->ad]->set_mode)(scp->adp, scp->mode); - Crtat = (u_short *)scp->adp->va_window; +#ifndef PC98 + /* + * even if mode switching is disabled, we can change back + * to the initial mode or the custom mode based on the initial + * mode if we have saved register values upon start-up. + */ + mp = get_mode_param(scp, scp->mode); + if (mp == NULL) + return; + bcopy(mp, &special_modetable, sizeof(special_modetable)); +#endif + /* setup video hardware for the given mode */ #ifdef PC98 - if (scp->status & UNKNOWN_MODE) { - while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ - outb(0x62, 0xc); /* text off */ - outb(0xA2, 0xd); /* graphics on */ - } else { - while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ - outb(0x62, 0xd); /* text off */ - outb(0xA2, 0xc); /* graphics on */ - } +#ifdef LINE30 + switch (scp->mode) { + case M_PC98_80x25: /* VGA TEXT MODES */ + initialize_gdc(T25_G400); + break; + case M_PC98_80x30: + initialize_gdc(T30_G400); + break; + default: + break; + } #endif + if (scp->status & UNKNOWN_MODE) { + while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ + outb(0x62, 0xc); /* text off */ + outb(0xA2, 0xd); /* graphics on */ + } else { + while (!(inb(0x60) & 0x20)) {} /* V-SYNC wait */ + outb(0x62, 0xd); /* text on */ + outb(0xA2, 0xc); /* graphics off */ + } +#else /* IBM-PC */ + switch (scp->mode) { + case M_VGA_C80x60: case M_VGA_M80x60: + special_modetable[2] = 0x08; + special_modetable[19] = 0x47; + goto special_480l; - if (!(scp->status & GRAPHICS_MODE)) { - /* load appropriate font */ - if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->adp->va_flags)) { - if (scp->font_size < 14) { - if (fonts_loaded & FONT_8) - copy_font(scp, LOAD, 8, font_8); - } else if (scp->font_size >= 16) { - if (fonts_loaded & FONT_16) - copy_font(scp, LOAD, 16, font_16); - } else { - if (fonts_loaded & FONT_14) - copy_font(scp, LOAD, 14, font_14); - } - /* - * FONT KLUDGE: - * This is an interim kludge to display correct font. - * Always use the font page #0 on the video plane 2. - * Somehow we cannot show the font in other font pages on - * some video cards... XXX - */ - (*vidsw[scp->ad]->show_font)(scp->adp, 0); + case M_VGA_C80x30: case M_VGA_M80x30: + special_modetable[19] = 0x4f; +special_480l: + special_modetable[9] |= 0xc0; + special_modetable[16] = 0x08; + special_modetable[17] = 0x3e; + special_modetable[26] = 0xea; + special_modetable[28] = 0xdf; + special_modetable[31] = 0xe7; + special_modetable[32] = 0x04; + goto setup_mode; + + case M_ENH_C80x43: case M_ENH_B80x43: + special_modetable[28] = 87; + goto special_80x50; + + case M_VGA_C80x50: case M_VGA_M80x50: +special_80x50: + special_modetable[2] = 8; + special_modetable[19] = 7; + goto setup_mode; + + case M_VGA_C40x25: case M_VGA_C80x25: + case M_VGA_M80x25: + case M_B40x25: case M_C40x25: + case M_B80x25: case M_C80x25: + case M_ENH_B40x25: case M_ENH_C40x25: + case M_ENH_B80x25: case M_ENH_C80x25: + case M_EGAMONO80x25: + +setup_mode: + set_vgaregs(special_modetable); + scp->font_size = special_modetable[2]; + + /* set font type (size) */ + if (scp->font_size < 14) { + if (fonts_loaded & FONT_8) + copy_font(LOAD, FONT_8, font_8); + i = 0x0a; /* font 2 */ + } else if (scp->font_size >= 16) { + if (fonts_loaded & FONT_16) + copy_font(LOAD, FONT_16, font_16); + i = 0x00; /* font 0 */ + } else { + if (fonts_loaded & FONT_14) + copy_font(LOAD, FONT_14, font_14); + i = 0x05; /* font 1 */ } + /* + * FONT KLUDGE: + * This is an interim kludge to display correct font. + * Always use the font page #0 on the video plane 2. + * Somehow we cannot show the font in other font pages on + * some video cards... XXX + */ + i = 0x00; + s = splhigh(); + outb(TSIDX, 0x00); outb(TSREG, 0x01); + outb(TSIDX, 0x03); outb(TSREG, i); + outb(TSIDX, 0x00); outb(TSREG, 0x03); + splx(s); + if (flags & CHAR_CURSOR) + set_destructive_cursor(scp); mark_all(scp); - } + break; - if (scp->status & PIXEL_MODE) - generic_bzero((u_char *)(scp->adp->va_window), - scp->xpixel*scp->ypixel/8); - set_border(scp, scp->border); + case M_VGA_MODEX: + /* "unchain" the VGA mode */ + special_modetable[5-1+0x04] &= 0xf7; + special_modetable[5-1+0x04] |= 0x04; + /* turn off doubleword mode */ + special_modetable[10+0x14] &= 0xbf; + /* turn off word adressing */ + special_modetable[10+0x17] |= 0x40; + /* set logical screen width */ + special_modetable[10+0x13] = 80; + /* set 240 lines */ + special_modetable[10+0x11] = 0x2c; + special_modetable[10+0x06] = 0x0d; + special_modetable[10+0x07] = 0x3e; + special_modetable[10+0x10] = 0xea; + special_modetable[10+0x11] = 0xac; + special_modetable[10+0x12] = 0xdf; + special_modetable[10+0x15] = 0xe7; + special_modetable[10+0x16] = 0x06; + /* set vertical sync polarity to reflect aspect ratio */ + special_modetable[9] = 0xe3; + goto setup_grmode; -#ifndef PC98 - /* move hardware cursor out of the way */ - (*vidsw[scp->ad]->set_hw_cursor)(scp->adp, -1, -1); -#endif + case M_BG320: case M_CG320: case M_BG640: + case M_CG320_D: case M_CG640_E: + case M_CG640x350: case M_ENH_CG640: + case M_BG640x480: case M_CG640x480: case M_VGA_CG320: - return 0; +setup_grmode: + set_vgaregs(special_modetable); + scp->font_size = FONT_NONE; + break; + + default: + /* call user defined function XXX */ + break; + } +#endif /* PC98 */ + + /* set border color for this (virtual) console */ + set_border(scp->border); + return; } void -set_border(scr_stat *scp, int color) +set_border(u_char color) { + switch (crtc_type) { +#ifdef PC98 + case KD_PC98: + outb(0x6c, color << 4); + break; +#else + case KD_EGA: + case KD_VGA: + inb(crtc_addr + 6); /* reset flip-flop */ + outb(ATC, 0x31); outb(ATC, color); + break; + case KD_CGA: + outb(crtc_addr + 5, color & 0x0f); /* color select register */ + break; + case KD_MONO: + case KD_HERCULES: +#endif + default: + break; + } +} + #ifndef PC98 - u_char *p; - int xoff; - int yoff; - int xlen; - int ylen; +static void +set_vgaregs(char *modetable) +{ + int i, s = splhigh(); + + outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ + for (i=0; i<4; i++) { /* program sequencer */ + outb(TSIDX, i+1); + outb(TSREG, modetable[i+5]); + } + outb(MISC, modetable[9]); /* set dot-clock */ + outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ + outb(crtc_addr, 0x11); + outb(crtc_addr+1, inb(crtc_addr+1) & 0x7F); + for (i=0; i<25; i++) { /* program crtc */ + outb(crtc_addr, i); + if (i == 14 || i == 15) /* no hardware cursor */ + outb(crtc_addr+1, 0xff); + else + outb(crtc_addr+1, modetable[i+10]); + } + inb(crtc_addr+6); /* reset flip-flop */ + for (i=0; i<20; i++) { /* program attribute ctrl */ + outb(ATC, i); + outb(ATC, modetable[i+35]); + } + for (i=0; i<9; i++) { /* program graph data ctrl */ + outb(GDCIDX, i); + outb(GDCREG, modetable[i+55]); + } + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + splx(s); +} + +static void +read_vgaregs(char *buf) +{ + int i, j; + int s; + + bzero(buf, MODE_PARAM_SIZE); + + s = splhigh(); + + outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ + for (i=0, j=5; i<4; i++) { + outb(TSIDX, i+1); + buf[j++] = inb(TSREG); + } + buf[9] = inb(MISC + 10); /* dot-clock */ + outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ + + for (i=0, j=10; i<25; i++) { /* crtc */ + outb(crtc_addr, i); + buf[j++] = inb(crtc_addr+1); + } + for (i=0, j=35; i<20; i++) { /* attribute ctrl */ + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, i); + buf[j++] = inb(ATC + 1); + } + for (i=0, j=55; i<9; i++) { /* graph data ctrl */ + outb(GDCIDX, i); + buf[j++] = inb(GDCREG); + } + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + + buf[0] = *(char *)pa_to_va(0x44a); /* COLS */ + buf[1] = *(char *)pa_to_va(0x484); /* ROWS */ + buf[2] = *(char *)pa_to_va(0x485); /* POINTS */ + buf[3] = *(char *)pa_to_va(0x44c); + buf[4] = *(char *)pa_to_va(0x44d); + + splx(s); +} + +static int +comp_vgaregs(u_char *buf1, u_char *buf2) +{ + static struct { + u_char mask; + } params[MODE_PARAM_SIZE] = { + 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */ + 0xff, 0xff, /* page length */ + 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */ + 0xf3, /* misc register */ + 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */ + 0xff, 0xff, 0xff, 0x7f, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x7f, 0xff, 0xff, + 0x7f, 0xff, 0xff, 0xef, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */ + 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */ + 0xff, 0xff, 0xff, 0xff, + }; + int identical = TRUE; int i; - (*vidsw[scp->ad]->set_border)(scp->adp, color); + for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { + if (params[i].mask == 0) /* don't care */ + continue; + if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) + return COMP_DIFFERENT; + if (buf1[i] != buf2[i]) + identical = FALSE; + } + return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; - if (scp->status & PIXEL_MODE) { - outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ - outw(GDCIDX, 0x0003); /* data rotate/function select */ - outw(GDCIDX, 0x0f01); /* set/reset enable */ - outw(GDCIDX, 0xff08); /* bit mask */ - outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ - p = (u_char *)(scp->adp->va_window); - xoff = scp->xoff; - yoff = scp->yoff*scp->font_size; - xlen = scp->xpixel/8; - ylen = scp->ysize*scp->font_size; - if (yoff > 0) { - generic_bzero(p, xlen*yoff); - generic_bzero(p + xlen*(yoff + ylen), - xlen*scp->ypixel - xlen*(yoff + ylen)); - } - if (xoff > 0) { - for (i = 0; i < ylen; ++i) { - generic_bzero(p + xlen*(yoff + i), xoff); - generic_bzero(p + xlen*(yoff + i) + xoff + scp->xsize, - xlen - xoff - scp->xsize); - } - } - outw(GDCIDX, 0x0000); /* set/reset */ - outw(GDCIDX, 0x0001); /* set/reset enable */ +#if 0 + for(i = 0; i < 20; ++i) { + if (*buf1++ != *buf2++) + return COMP_DIFFERENT; } -#else /* PC98 */ - (*vidsw[scp->ad]->set_border)(scp->adp, color); -#endif /* PC98 */ + buf1 += 2; /* skip the cursor shape */ + buf2 += 2; + for(i = 22; i < 24; ++i) { + if (*buf1++ != *buf2++) + return COMP_DIFFERENT; + } + buf1 += 2; /* skip the cursor position */ + buf2 += 2; + for(i = 26; i < MODE_PARAM_SIZE; ++i) { + if (*buf1++ != *buf2++) + return COMP_DIFFERENT; + } + return COMP_IDENTICAL; +#endif } -void -copy_font(scr_stat *scp, int operation, int font_size, u_char *buf) +static void +dump_vgaregs(u_char *buf) { - /* - * FONT KLUDGE: - * This is an interim kludge to display correct font. - * Always use the font page #0 on the video plane 2. - * Somehow we cannot show the font in other font pages on - * some video cards... XXX - */ + int i; + + for(i = 0; i < MODE_PARAM_SIZE;) { + printf("%02x ", buf[i]); + if ((++i % 16) == 0) + printf("\n"); + } +} + +static void +set_font_mode(u_char *buf) +{ + int s = splhigh(); + font_loading_in_progress = TRUE; - if (operation == LOAD) { - (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, buf, 0, 256); - if (sc_flags & CHAR_CURSOR) - set_destructive_cursor(scp); - } else if (operation == SAVE) { - (*vidsw[scp->ad]->save_font)(scp->adp, 0, font_size, buf, 0, 256); + + /* save register values */ + outb(TSIDX, 0x02); buf[0] = inb(TSREG); + outb(TSIDX, 0x04); buf[1] = inb(TSREG); + outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); + outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); + outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); + inb(crtc_addr + 6); + outb(ATC, 0x10); buf[5] = inb(ATC + 1); + + /* setup vga for loading fonts */ + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01); + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + +#if SLOW_VGA +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x01); +#endif + outb(TSIDX, 0x02); outb(TSREG, 0x04); + outb(TSIDX, 0x04); outb(TSREG, 0x07); +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x03); +#endif + outb(GDCIDX, 0x04); outb(GDCREG, 0x02); + outb(GDCIDX, 0x05); outb(GDCREG, 0x00); + outb(GDCIDX, 0x06); outb(GDCREG, 0x04); +#else +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0100); +#endif + outw(TSIDX, 0x0402); + outw(TSIDX, 0x0704); +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0300); +#endif + outw(GDCIDX, 0x0204); + outw(GDCIDX, 0x0005); + outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */ +#endif + splx(s); +} + +static void +set_normal_mode(u_char *buf) +{ + char *modetable; + int s = splhigh(); + + /* setup vga for normal operation mode again */ + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, 0x10); outb(ATC, buf[5]); + inb(crtc_addr+6); /* reset flip-flop */ + outb(ATC, 0x20); /* enable palette */ + +#if SLOW_VGA +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x01); +#endif + outb(TSIDX, 0x02); outb(TSREG, buf[0]); + outb(TSIDX, 0x04); outb(TSREG, buf[1]); +#ifndef SC_BAD_FLICKER + outb(TSIDX, 0x00); outb(TSREG, 0x03); +#endif + outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); + outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); + if (crtc_addr == MONO_BASE) { + outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); + } else { + outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); } +#else +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0100); +#endif + outw(TSIDX, 0x0002 | (buf[0] << 8)); + outw(TSIDX, 0x0004 | (buf[1] << 8)); +#ifndef SC_BAD_FLICKER + outw(TSIDX, 0x0300); +#endif + outw(GDCIDX, 0x0004 | (buf[2] << 8)); + outw(GDCIDX, 0x0005 | (buf[3] << 8)); + if (crtc_addr == MONO_BASE) + outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); + else + outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); +#endif + font_loading_in_progress = FALSE; + splx(s); +} +#endif + +void +copy_font(int operation, int font_type, char* font_image) +{ +#ifndef PC98 + int ch, line, segment, fontsize; + u_char buf[PARAM_BUFSIZE]; + u_char val; + + switch (font_type) { + default: + case FONT_8: + segment = 0x8000; + fontsize = 8; + break; + case FONT_14: + segment = 0x4000; + fontsize = 14; + break; + case FONT_16: + segment = 0x0000; + fontsize = 16; + break; + } + /* + * FONT KLUDGE + * Always use the font page #0. XXX + */ + segment = 0x0000; + outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ + outb(TSIDX, 0x01); outb(TSREG, val | 0x20); + set_font_mode(buf); + for (ch=0; ch < 256; ch++) + for (line=0; line < fontsize; line++) + if (operation) + *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line) = + font_image[(ch*fontsize)+line]; + else + font_image[(ch*fontsize)+line] = + *(char *)pa_to_va(VIDEOMEM+(segment)+(ch*32)+line); + set_normal_mode(buf); + outb(TSIDX, 0x01); outb(TSREG, val & 0xDF); /* enable screen */ +#endif } static void set_destructive_cursor(scr_stat *scp) { #ifndef PC98 + u_char buf[PARAM_BUFSIZE]; u_char cursor[32]; - u_char *font_buffer; - int font_size; - int crtc_addr; + caddr_t address; int i; - - if (!ISFONTAVAIL(scp->adp->va_flags) - || (scp->status & (GRAPHICS_MODE | PIXEL_MODE))) - return; + char *font_buffer; if (scp->font_size < 14) { font_buffer = font_8; - font_size = 8; - } else if (scp->font_size >= 16) { + address = (caddr_t)VIDEOMEM + 0x8000; + } + else if (scp->font_size >= 16) { font_buffer = font_16; - font_size = 16; - } else { + address = (caddr_t)VIDEOMEM; + } + else { font_buffer = font_14; - font_size = 14; + address = (caddr_t)VIDEOMEM + 0x4000; } + /* + * FONT KLUDGE + * Always use the font page #0. XXX + */ + address = (caddr_t)VIDEOMEM; if (scp->status & MOUSE_VISIBLE) { if ((scp->cursor_saveunder & 0xff) == SC_MOUSE_CHAR) @@ -4719,24 +5871,14 @@ set_destructive_cursor(scr_stat *scp) (scp->cursor_start >= scp->font_size && i == scp->font_size - 1)) cursor[i] |= 0xff; #if 1 - crtc_addr = scp->adp->va_crtc_addr; while (!(inb(crtc_addr+6) & 0x08)) /* wait for vertical retrace */ ; #endif - font_loading_in_progress = TRUE; - (*vidsw[scp->ad]->load_font)(scp->adp, 0, font_size, cursor, DEAD_CHAR, 1); - font_loading_in_progress = FALSE; + set_font_mode(buf); + generic_bcopy(cursor, (char *)pa_to_va(address) + DEAD_CHAR * 32, 32); + set_normal_mode(buf); #endif } -void -sc_move_mouse(scr_stat *scp, int x, int y) -{ - scp->mouse_xpos = x; - scp->mouse_ypos = y; - scp->mouse_pos = scp->mouse_oldpos = - scp->scr_buf + (y / scp->font_size) * scp->xsize + x / 8; -} - static void set_mouse_pos(scr_stat *scp) { @@ -4746,7 +5888,7 @@ set_mouse_pos(scr_stat *scp) scp->mouse_xpos = 0; if (scp->mouse_ypos < 0) scp->mouse_ypos = 0; - if (!ISTEXTSC(scp)) { + if (scp->status & UNKNOWN_MODE) { if (scp->mouse_xpos > scp->xpixel-1) scp->mouse_xpos = scp->xpixel-1; if (scp->mouse_ypos > scp->ypixel-1) @@ -4979,28 +6121,35 @@ draw_mouse_image(scr_stat *scp) #ifdef PC98 *(Atrat + (scp->mouse_pos - scp->scr_buf)) ^= 0x4; /* reverse bit */ #else + caddr_t address; + int i; + char *font_buffer; + u_char buf[PARAM_BUFSIZE]; u_short buffer[32]; u_short xoffset, yoffset; - u_short *crt_pos = (u_short *)(scp->adp->va_window) - + (scp->mouse_pos - scp->scr_buf); - u_char *font_buffer; - int font_size; - int crtc_addr; - int i; + u_short *crt_pos = Crtat + (scp->mouse_pos - scp->scr_buf); + int font_size = scp->font_size; - if (scp->font_size < 14) { + if (font_size < 14) { font_buffer = font_8; - font_size = 8; - } else if (scp->font_size >= 16) { + address = (caddr_t)VIDEOMEM + 0x8000; + } + else if (font_size >= 16) { font_buffer = font_16; - font_size = 16; - } else { + address = (caddr_t)VIDEOMEM; + } + else { font_buffer = font_14; - font_size = 14; + address = (caddr_t)VIDEOMEM + 0x4000; } + /* + * FONT KLUDGE + * Always use the font page #0. XXX + */ + address = (caddr_t)VIDEOMEM; xoffset = scp->mouse_xpos % 8; - yoffset = scp->mouse_ypos % scp->font_size; + yoffset = scp->mouse_ypos % font_size; /* prepare mousepointer char's bitmaps */ bcopy(font_buffer + ((*(scp->mouse_pos) & 0xff) * font_size), @@ -5029,19 +6178,15 @@ draw_mouse_image(scr_stat *scp) scp->mouse_cursor[i+96] = buffer[i+font_size] & 0xff; } #endif - scp->mouse_oldpos = scp->mouse_pos; #ifndef PC98 #if 1 /* wait for vertical retrace to avoid jitter on some videocards */ - crtc_addr = scp->adp->va_crtc_addr; while (!(inb(crtc_addr+6) & 0x08)) /* idle */ ; #endif - font_loading_in_progress = TRUE; - (*vidsw[scp->ad]->load_font)(scp->adp, 0, 32, scp->mouse_cursor, - SC_MOUSE_CHAR, 4); - font_loading_in_progress = FALSE; - + set_font_mode(buf); + generic_bcopy(scp->mouse_cursor, (char *)pa_to_va(address) + SC_MOUSE_CHAR * 32, 128); + set_normal_mode(buf); *(crt_pos) = (*(scp->mouse_pos) & 0xff00) | SC_MOUSE_CHAR; *(crt_pos+scp->xsize) = (*(scp->mouse_pos + scp->xsize) & 0xff00) | (SC_MOUSE_CHAR + 2); @@ -5060,16 +6205,10 @@ draw_mouse_image(scr_stat *scp) static void remove_mouse_image(scr_stat *scp) { - u_short *crt_pos; - - if (!ISTEXTSC(scp)) - return; - #ifdef PC98 - crt_pos = Atrat + (scp->mouse_oldpos - scp->scr_buf); + u_short *crt_pos = Atrat + (scp->mouse_oldpos - scp->scr_buf); #else - crt_pos = (u_short *)(scp->adp->va_window) - + (scp->mouse_oldpos - scp->scr_buf); + u_short *crt_pos = Crtat + (scp->mouse_oldpos - scp->scr_buf); #endif #ifdef PC98 @@ -5089,17 +6228,15 @@ remove_mouse_image(scr_stat *scp) static void draw_cutmarking(scr_stat *scp) { - u_short *crt_pos; u_short *ptr; u_short och, nch; + for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { #ifdef PC98 - crt_pos = Atrat; + nch = och = *(Atrat + (ptr - scp->scr_buf)); #else - crt_pos = (u_short *)(scp->adp->va_window); + nch = och = *(Crtat + (ptr - scp->scr_buf)); #endif - for (ptr=scp->scr_buf; ptr<=(scp->scr_buf+(scp->xsize*scp->ysize)); ptr++) { - nch = och = *(crt_pos + (ptr - scp->scr_buf)); /* are we outside the selected area ? */ if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? scp->mouse_cut_end : scp->mouse_cut_start) || @@ -5124,16 +6261,20 @@ draw_cutmarking(scr_stat *scp) if (ptr != scp->cursor_pos) nch = (och & 0x88ff) | (*ptr & 0x7000)>>4 | (*ptr & 0x0700)<<4; else { - if (sc_flags & CHAR_CURSOR) + if (flags & CHAR_CURSOR) nch = (och & 0x88ff)|(*ptr & 0x7000)>>4|(*ptr & 0x0700)<<4; else - if (!(sc_flags & BLINK_CURSOR)) + if (!(flags & BLINK_CURSOR)) nch = (och & 0xff) | (*ptr & 0xff00); } #endif } if (nch != och) - *(crt_pos + (ptr - scp->scr_buf)) = nch; +#ifdef PC98 + *(Atrat + (ptr - scp->scr_buf)) = nch; +#else + *(Crtat + (ptr - scp->scr_buf)) = nch; +#endif } } @@ -5146,15 +6287,43 @@ remove_cutmarking(scr_stat *scp) } static void +save_palette(void) +{ +#ifndef PC98 + int i; + + outb(PALRADR, 0x00); + for (i=0x00; i<0x300; i++) + palette[i] = inb(PALDATA); + inb(crtc_addr+6); /* reset flip/flop */ +#endif +} + +void +load_palette(char *palette) +{ +#ifndef PC98 + int i; + + outb(PIXMASK, 0xFF); /* no pixelmask */ + outb(PALWADR, 0x00); + for (i=0x00; i<0x300; i++) + outb(PALDATA, palette[i]); + inb(crtc_addr+6); /* reset flip/flop */ + outb(ATC, 0x20); /* enable palette */ +#endif +} + +static void do_bell(scr_stat *scp, int pitch, int duration) { if (cold || shutdown_in_progress) return; - if (scp != cur_console && (sc_flags & QUIET_BELL)) + if (scp != cur_console && (flags & QUIET_BELL)) return; - if (sc_flags & VISUAL_BELL) { + if (flags & VISUAL_BELL) { if (blink_in_progress) return; blink_in_progress = 4; @@ -5173,7 +6342,7 @@ blink_screen(void *arg) { scr_stat *scp = arg; - if (!ISTEXTSC(scp) || (blink_in_progress <= 1)) { + if ((scp->status & UNKNOWN_MODE) || (blink_in_progress <= 1)) { blink_in_progress = FALSE; mark_all(scp); if (delayed_next_scr) @@ -5183,26 +6352,22 @@ blink_screen(void *arg) #ifdef PC98 if (blink_in_progress & 1){ fillw(scr_map[0x20], - (u_short *)(scp->adp->va_window), - scp->xsize * scp->ysize); + Crtat, scp->xsize * scp->ysize); fillw(at2pc98(kernel_default.std_color), Atrat, scp->xsize * scp->ysize); } else { fillw(scr_map[0x20], - (u_short *)(scp->adp->va_window), - scp->xsize * scp->ysize); + Crtat, scp->xsize * scp->ysize); fillw(at2pc98(kernel_default.rev_color), Atrat, scp->xsize * scp->ysize); } #else if (blink_in_progress & 1) fillw(kernel_default.std_color | scr_map[0x20], - (u_short *)(scp->adp->va_window), - scp->xsize * scp->ysize); + Crtat, scp->xsize * scp->ysize); else fillw(kernel_default.rev_color | scr_map[0x20], - (u_short *)(scp->adp->va_window), - scp->xsize * scp->ysize); + Crtat, scp->xsize * scp->ysize); #endif blink_in_progress--; timeout(blink_screen, scp, hz / 10); @@ -5212,105 +6377,225 @@ blink_screen(void *arg) void sc_bcopy(scr_stat *scp, u_short *p, int from, int to, int mark) { -#ifdef PC98 - if (ISTEXTSC(scp)) - generic_bcopy(p + from, (u_short *)(scp->adp->va_window) + from, - (to - from + 1)*sizeof(u_short)); -#else /* PC98 */ - u_char *font; - u_char volatile *d; - u_char *e; - u_char *f; - int font_size; - int line_length; - int xsize; - u_short bg; - int i, j; - u_char c; + if (!VESA_MODE(scp->mode)) { + generic_bcopy(p+from, Crtat+from, (to-from+1)*sizeof (u_short)); + } else if (scp->mode == 0x102) { + u_char *d, *e; + int i,j; - if (ISTEXTSC(scp)) { - generic_bcopy(p + from, (u_short *)(scp->adp->va_window) + from, - (to - from + 1)*sizeof(u_short)); - } else /* if ISPIXELSC(scp) */ { if (mark) - mark = 255; - font_size = scp->font_size; - if (font_size < 14) - font = font_8; - else if (font_size >= 16) - font = font_16; - else - font = font_14; - line_length = scp->xpixel/8; - xsize = scp->xsize; - d = (u_char *)(scp->adp->va_window) - + scp->xoff + scp->yoff*font_size*line_length - + (from%xsize) + font_size*line_length*(from/xsize); - - outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ - outw(GDCIDX, 0x0003); /* data rotate/function select */ - outw(GDCIDX, 0x0f01); /* set/reset enable */ - bg = -1; + mark = 255; + d = (u_char *)Crtat; + d += 10 + 6*16*100 + (from%80) + 16*100*(from/80); for (i = from ; i <= to ; i++) { - /* set background color in EGA/VGA latch */ - if (bg != (p[i] & 0xf000)) { - bg = (p[i] & 0xf000); - outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ - outw(GDCIDX, 0xff08); /* bit mask */ - *d = 0; - c = *d; /* set the background color in the latch */ - } - /* foreground color */ - outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ - e = (u_char *)d; - f = &font[(p[i] & 0x00ff)*font_size]; - for (j = 0 ; j < font_size; j++, f++) { - outw(GDCIDX, ((*f^mark) << 8) | 0x08); /* bit mask */ - *e = 0; - e += line_length; + e = d; + for (j = 0 ; j < 16; j++) { + *e = mark^font_16[(p[i]&0xff)*16+j]; + e+=100; } d++; - if ((i % xsize) == xsize - 1) - d += scp->xoff*2 + (font_size - 1)*line_length; + if ((i % 80) == 79) + d += 20 + 15*100; } - outw(GDCIDX, 0x0000); /* set/reset */ - outw(GDCIDX, 0x0001); /* set/reset enable */ - outw(GDCIDX, 0xff08); /* bit mask */ + } +} -#if 0 /* VGA only */ - outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ - outw(GDCIDX, 0x0003); /* data rotate/function select */ - outw(GDCIDX, 0x0f01); /* set/reset enable */ - outw(GDCIDX, 0xff08); /* bit mask */ - bg = -1; - for (i = from ; i <= to ; i++) { - /* set background color in EGA/VGA latch */ - if (bg != (p[i] & 0xf000)) { - bg = (p[i] & 0xf000); - outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ - outw(GDCIDX, (bg >> 4) | 0x00); /* set/reset */ - *d = 0; - c = *d; /* set the background color in the latch */ - outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ - } - /* foreground color */ - outw(GDCIDX, (p[i] & 0x0f00) | 0x00); /* set/reset */ - e = (u_char *)d; - f = &font[(p[i] & 0x00ff)*font_size]; - for (j = 0 ; j < font_size; j++, f++) { - *e = *f^mark; - e += line_length; - } - d++; - if ((i % xsize) == xsize - 1) - d += scp->xoff*2 + (font_size - 1)*line_length; +#ifdef SC_SPLASH_SCREEN + +static void +scsplash_init(void) +{ +#ifndef PC98 + /* + * We currently assume the splash screen always use + * VGA_CG320 mode and abort installation if this mode is not + * supported with this video card. XXX + */ + if (crtc_type != KD_VGA || get_mode_param(cur_console, M_VGA_CG320) == NULL) + return; +#endif + + if (splash_load() == 0 && add_scrn_saver(scsplash) == 0) { + default_saver = scsplash; + scrn_blank_time = DEFAULT_BLANKTIME; + run_scrn_saver = TRUE; + if (!(boothowto & RB_CONFIG)) { + scsplash_stick(TRUE); + scsplash(TRUE); } - outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ - outw(GDCIDX, 0x0000); /* set/reset */ - outw(GDCIDX, 0x0001); /* set/reset enable */ -#endif /* 0 */ } -#endif /* PC98 */ } +static void +scsplash(int show) +{ + if (show) + splash(TRUE); + else if (!sticky_splash) + splash(FALSE); +} + +#endif /* SC_SPLASH_SCREEN */ + +#if defined(PC98) && defined(LINE30) /* 30line */ + +static void master_gdc_cmd(unsigned int cmd) +{ + while ( (inb(0x60) & 2) != 0); + outb(0x62, cmd); +} + +static void master_gdc_prm(unsigned int pmtr) +{ + while ( (inb(0x60) & 2) != 0); + outb(0x60, pmtr); +} + +static void master_gdc_word_prm(unsigned int wpmtr) +{ + master_gdc_prm(wpmtr & 0x00ff); + master_gdc_prm((wpmtr >> 8) & 0x00ff); +} + +static void master_gdc_fifo_empty(void) +{ + while ( (inb(0x60) & 4) == 0); +} + +static void master_gdc_wait_vsync(void) +{ + while ( (inb(0x60) & 0x20) != 0); + while ( (inb(0x60) & 0x20) == 0); +} + +static void gdc_cmd(unsigned int cmd) +{ + while ( (inb(0xa0) & 2) != 0); + outb( 0xa2, cmd); +} + +static void gdc_prm(unsigned int pmtr) +{ + while ( (inb(0xa0) & 2) != 0); + outb( 0xa0, 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(0xa0) & 0x04) == 0); +} + +static void gdc_wait_vsync(void) +{ + while ( (inb(0xa0) & 0x20) != 0); + while ( (inb(0xa0) & 0x20) == 0); +} + +static int check_gdc_clock(void) +{ + if ((inb(0x31) & 0x80) == 0){ + return _5MHZ; + } else { + return _2_5MHZ; + } +} + +static void initialize_gdc(unsigned int mode) +{ + /* start 30line initialize */ + int m_mode,s_mode,gdc_clock; + gdc_clock = check_gdc_clock(); + + if (mode == T25_G400){ + m_mode = _25L; + }else{ + m_mode = _30L; + } + + s_mode = 2*mode+gdc_clock; + + gdc_INFO = m_mode; + + 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[m_mode][GDC_CR]); + master_gdc_word_prm(((master_param[m_mode][GDC_HFP] << 10) + + (master_param[m_mode][GDC_VS] << 5) + + master_param[m_mode][GDC_HS])); + master_gdc_prm(master_param[m_mode][GDC_HBP]); + master_gdc_prm(master_param[m_mode][GDC_VFP]); + master_gdc_word_prm(((master_param[m_mode][GDC_VBP] << 10) + + (master_param[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[s_mode][GDC_CR]); + gdc_word_prm((slave_param[s_mode][GDC_HFP] << 10) + + (slave_param[s_mode][GDC_VS] << 5) + + (slave_param[s_mode][GDC_HS])); + gdc_prm(slave_param[s_mode][GDC_HBP]); + gdc_prm(slave_param[s_mode][GDC_VFP]); + gdc_word_prm((slave_param[s_mode][GDC_VBP] << 10) + + (slave_param[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[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(_GDC_STOP); + + gdc_wait_vsync(); + gdc_wait_vsync(); + gdc_wait_vsync(); + + master_gdc_cmd(_GDC_START); +} +#endif /* 30 line */ + #endif /* NSC */ diff --git a/sys/pc98/pc98/syscons.h b/sys/pc98/pc98/syscons.h index a265d15277ae..3d4b8d3ed00b 100644 --- a/sys/pc98/pc98/syscons.h +++ b/sys/pc98/pc98/syscons.h @@ -1,18 +1,18 @@ /*- - * Copyright (c) 1992-1998 Sen Schmidt + * Copyright (c) 1995 Sen Schmidt * 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. + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. * 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. + * 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 @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.h,v 1.27 1999/01/17 15:42:27 kato Exp $ + * $Id: syscons.h,v 1.24 1998/08/03 10:50:57 kato Exp $ */ #ifndef _PC98_PC98_SYSCONS_H_ @@ -38,13 +38,8 @@ #define pa_to_va(pa) (KERNBASE + (pa)) /* works if ISMAPPED(pa...) */ /* printable chars */ -#ifdef PC98 -#define PRINTABLE(ch) ((ch) > 0x1b || ((ch) > 0x0f && (ch) < 0x1b) \ - || (ch) < 0x07) -#else #define PRINTABLE(ch) ((ch) > 0x1b || ((ch) > 0x0d && (ch) < 0x1b) \ || (ch) < 0x07) -#endif /* macros for "intelligent" screen update */ #define mark_for_update(scp, x) {\ @@ -57,7 +52,11 @@ } /* status flags */ +#define LOCK_KEY_MASK 0x0000F +#define LED_MASK 0x00007 #define UNKNOWN_MODE 0x00010 +#define KBD_RAW_MODE 0x00020 +#define KBD_CODE_MODE 0x00040 #define SWITCH_WAIT_REL 0x00080 #define SWITCH_WAIT_ACQ 0x00100 #define BUFFER_SAVED 0x00200 @@ -66,22 +65,15 @@ #define MOUSE_MOVED 0x01000 #define MOUSE_CUTTING 0x02000 #define MOUSE_VISIBLE 0x04000 -#define GRAPHICS_MODE 0x08000 -#define PIXEL_MODE 0x10000 -#define SAVER_RUNNING 0x20000 /* configuration flags */ #define VISUAL_BELL 0x00001 #define BLINK_CURSOR 0x00002 #define CHAR_CURSOR 0x00004 -/* these options are now obsolete; use corresponding options for kbd driver */ -#if 0 #define DETECT_KBD 0x00008 #define XT_KEYBD 0x00010 #define KBD_NORESET 0x00020 -#endif #define QUIET_BELL 0x00040 -#define VESA800X600 0x00080 /* attribute flags */ #define NORMAL_ATTR 0x00 @@ -92,6 +84,9 @@ #define FOREGROUND_CHANGED 0x10 #define BACKGROUND_CHANGED 0x20 +/* video hardware memory addresses */ +#define VIDEOMEM 0x000A0000 + /* misc defines */ #define FALSE 0 #define TRUE 1 @@ -116,11 +111,24 @@ static unsigned int BELL_PITCH = 1678; #define FONT_14 4 #define FONT_16 8 -#ifdef PC98 /* defines related to hardware addresses */ +#ifdef PC98 #define TEXT_GDC IO_GDC1 /* 0x60 */ #define TEXT_VRAM (KERNBASE+0xA0000) #define ATTR_OFFSET 0x1000 +#else /* IBM */ +#define MONO_BASE 0x3B4 /* crt controller base mono */ +#define COLOR_BASE 0x3D4 /* crt controller base color */ +#define MISC 0x3C2 /* misc output register */ +#define ATC IO_VGA+0x00 /* attribute controller */ +#define TSIDX IO_VGA+0x04 /* timing sequencer idx */ +#define TSREG IO_VGA+0x05 /* timing sequencer data */ +#define PIXMASK IO_VGA+0x06 /* pixel write mask */ +#define PALRADR IO_VGA+0x07 /* palette read address */ +#define PALWADR IO_VGA+0x08 /* palette write address */ +#define PALDATA IO_VGA+0x09 /* palette data register */ +#define GDCIDX IO_VGA+0x0E /* graph data controller idx */ +#define GDCREG IO_VGA+0x0F /* graph data controller data */ #endif /* special characters */ @@ -146,8 +154,6 @@ typedef struct term_stat { } term_stat; typedef struct scr_stat { - int ad; /* video adapter index */ - video_adapter_t *adp; /* video adapter structure */ u_short *scr_buf; /* buffer when off screen */ #ifdef PC98 u_short *atr_buf; /* buffer when off screen */ @@ -161,14 +167,11 @@ typedef struct scr_stat { int ysize; /* Y text size */ int xpixel; /* X graphics size */ int ypixel; /* Y graphics size */ - int xoff; /* X offset in pixel mode */ - int yoff; /* Y offset in pixel mode */ int font_size; /* fontsize in Y direction */ int start; /* modified area start */ int end; /* modified area end */ term_stat term; /* terminal emulation stuff */ int status; /* status (bitfield) */ - int kbd_mode; /* keyboard I/O mode */ u_short *cursor_pos; /* cursor buffer position */ u_short *cursor_oldpos; /* cursor old buffer position */ #ifndef PC98 @@ -192,6 +195,7 @@ typedef struct scr_stat { u_short bell_duration; u_short bell_pitch; u_char border; /* border color */ + int initial_mode; /* initial mode */ int mode; /* mode */ pid_t pid; /* pid of controlling proc */ struct proc *proc; /* proc* of controlling proc */ @@ -208,30 +212,14 @@ typedef struct scr_stat { #endif int history_size; /* size of history buffer */ struct apmhook r_hook; /* reconfiguration support */ - int splash_save_mode; /* saved mode for splash screen */ - int splash_save_status; /* saved status for splash screen */ +#ifdef SC_SPLASH_SCREEN + u_char splash_save_mode; /* saved mode for splash screen */ +#endif #ifdef KANJI u_char kanji_1st_char; -#define KTYPE_ASCII 0 -#define KTYPE_KANA 1 -#define KTYPE_JKANA 0x10 -#define KTYPE_7JIS 0x20 -#define KTYPE_SJIS 2 -#define KTYPE_UJIS 4 -#define KTYPE_SUKANA 3 -#define KTYPE_SUJIS 6 -#define KTYPE_KANIN 0x80 -#define KTYPE_ASCIN 0x40 - u_char kanji_type; /* 0: Ascii code 1: HANKAKU */ - /* 2: Shift JIS 4: UJIS */ - /* 3: Shift JIS or UJIS HANKAKU */ - /* 6: Shift JIS or UJIS */ + u_char kanji_type; /* 0: ASCII CODE 1: HANKAKU ? */ + /* 2: SHIFT JIS 4: EUC */ /* 0x10: JIS HANKAKU 0x20: JIS */ - /* 0x80: Kanji Invoke sequence */ - /* 0x40: Ascii Invoke sequence */ -#define IS_KTYPE_ASCII_or_HANKAKU(A) (!((A) & 0xee)) -#define IS_KTYPE_KANA(A) ((A) & 0x11) -#define KTYPE_MASK_CTRL(A) ((A) &= 0xF0) #endif } scr_stat; @@ -240,56 +228,22 @@ typedef struct default_attr { int rev_color; /* reverse hardware color */ } default_attr; - -#define ISTEXTSC(scp) (!((scp)->status \ - & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE))) -#define ISGRAPHSC(scp) (((scp)->status \ - & (UNKNOWN_MODE | GRAPHICS_MODE))) -#define ISPIXELSC(scp) (((scp)->status \ - & (UNKNOWN_MODE | GRAPHICS_MODE | PIXEL_MODE))\ - == PIXEL_MODE) -#define ISUNKNOWNSC(scp) ((scp)->status & UNKNOWN_MODE) - -#define ISFONTAVAIL(af) ((af) & V_ADP_FONT) -#define ISMOUSEAVAIL(af) ((af) & V_ADP_FONT) -#define ISPALAVAIL(af) ((af) & V_ADP_PALETTE) - /* misc prototypes used by different syscons related LKM's */ +void set_border(u_char color); +void set_mode(scr_stat *scp); +void copy_font(int operation, int font_type, char* font_image); +void load_palette(char *palette); +int add_scrn_saver(void (*this)(int)); +int remove_scrn_saver(void (*this)(int)); -/* syscons.c */ -extern int (*sc_user_ioctl)(dev_t dev, u_long cmd, caddr_t data, int flag, - struct proc *p); - -int set_mode(scr_stat *scp); -scr_stat *sc_get_scr_stat(dev_t dev); - -void copy_font(scr_stat *scp, int operation, int font_size, u_char *font_image); -void set_border(scr_stat *scp, int color); -#define save_palette(adp, pal) \ - (*vidsw[(adp)->va_index]->save_palette)((adp), (pal)) -#define load_palette(adp, pal) \ - (*vidsw[(adp)->va_index]->load_palette)((adp), (pal)) - -void sc_touch_scrn_saver(void); -void sc_clear_screen(scr_stat *scp); -void sc_move_mouse(scr_stat *scp, int x, int y); -int sc_clean_up(scr_stat *scp); -void sc_alloc_scr_buffer(scr_stat *scp, int wait, int clear); -void sc_alloc_cut_buffer(scr_stat *scp, int wait); -void sc_alloc_history_buffer(scr_stat *scp, int lines, int extra, int wait); -struct tty *scdevtotty(dev_t dev); - -/* scvidctl.c */ -int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, - int xsize, int ysize, int fontsize); -int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode); -int sc_set_pixel_mode(scr_stat *scp, struct tty *tp, - int xsize, int ysize, int fontsize); -int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, - struct proc *p); +#ifdef SC_SPLASH_SCREEN +void splash(int); +int splash_load(void); +int splash_unload(void); +#endif #ifdef PC98 unsigned int at2pc98(unsigned int attr); #endif -#endif /* !_PC98_PC98_SYSCONS_H_ */ +#endif /* !_I386_ISA_SYSCONS_H_ */ diff --git a/sys/pc98/pc98/wd.c b/sys/pc98/pc98/wd.c index eb6522bf8fb9..90fc584ca221 100644 --- a/sys/pc98/pc98/wd.c +++ b/sys/pc98/pc98/wd.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.70 1999/01/16 11:43:12 kato Exp $ + * $Id: wd.c,v 1.63 1998/09/15 14:07:08 kato Exp $ */ /* TODO: @@ -67,8 +67,8 @@ #include "opt_atapi.h" #include "opt_devfs.h" #include "opt_hw_wdog.h" -#include "opt_ide_delay.h" #include "opt_wd.h" +#include "pci.h" #include <sys/param.h> #include <sys/dkbad.h> @@ -112,11 +112,7 @@ extern void wdstart(int ctrlr); -#ifdef IDE_DELAY -#define TIMEOUT IDE_DELAY -#else #define TIMEOUT 10000 -#endif #define RETRIES 5 /* number of retries before giving up */ #define RECOVERYTIME 500000 /* usec for controller to recover after err */ #define MAXTRANSFER 255 /* max size of transfer in sectors */ @@ -337,16 +333,19 @@ wdprobe(struct isa_device *dvp) du->dk_ctrlr = dvp->id_unit; interface = du->dk_ctrlr / 2; du->dk_interface = interface; - du->dk_port = dvp->id_iobase; - if (wddma[interface].wdd_candma != NULL) { - du->dk_dmacookie = - wddma[interface].wdd_candma(dvp->id_iobase, du->dk_ctrlr, - du->dk_unit); - du->dk_altport = - wddma[interface].wdd_altiobase(du->dk_dmacookie); - } - if (du->dk_altport == 0) +#if !defined(DISABLE_PCI_IDE) && (NPCI > 0) + if (wddma[interface].wdd_candma) { + du->dk_dmacookie = wddma[interface].wdd_candma(dvp->id_iobase, du->dk_ctrlr); + du->dk_port = dvp->id_iobase; + du->dk_altport = wddma[interface].wdd_altiobase(du->dk_dmacookie); + } else { + du->dk_port = dvp->id_iobase; du->dk_altport = du->dk_port + wd_ctlr; + } +#else + du->dk_port = dvp->id_iobase; + du->dk_altport = du->dk_port + wd_ctlr; +#endif /* check if we have registers that work */ #ifdef PC98 @@ -367,11 +366,9 @@ wdprobe(struct isa_device *dvp) } } du->dk_altport = du->dk_port + wd_ctlr; -#if 0 if ((PC98_SYSTEM_PARAMETER(0x55d) & 3) == 0) { goto nodevice; } -#endif outb(0x432,(du->dk_unit)%2); #else /* IBM-PC */ outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */ @@ -395,31 +392,11 @@ wdprobe(struct isa_device *dvp) if (inb(du->dk_port + wd_cyl_lo) == 0x14 && inb(du->dk_port + wd_cyl_hi) == 0xeb) goto reset_ok; -#ifdef PC98 - du->dk_unit = 2; -#else du->dk_unit = 1; -#endif outb(du->dk_port + wd_sdh, WDSD_IBM | 0x10); /* slave */ if (inb(du->dk_port + wd_cyl_lo) == 0x14 && inb(du->dk_port + wd_cyl_hi) == 0xeb) goto reset_ok; -#ifdef PC98 - du->dk_unit = 1; - outb(0x432,(du->dk_unit)%2); - if (wdreset(du) == 0) - goto reset_ok; - /* test for ATAPI signature */ - outb(du->dk_port + wd_sdh, WDSD_IBM); /* master */ - if (inb(du->dk_port + wd_cyl_lo) == 0x14 && - inb(du->dk_port + wd_cyl_hi) == 0xeb) - goto reset_ok; - du->dk_unit = 3; - outb(du->dk_port + wd_sdh, WDSD_IBM | 0x10); /* slave */ - if (inb(du->dk_port + wd_cyl_lo) == 0x14 && - inb(du->dk_port + wd_cyl_hi) == 0xeb) - goto reset_ok; -#endif #endif DELAY(RECOVERYTIME); if (wdreset(du) != 0) { @@ -509,8 +486,6 @@ wdattach(struct isa_device *dvp) struct disk *du; struct wdparams *wp; - dvp->id_intr = wdintr; - if (dvp->id_unit >= NWDC) return (0); @@ -773,17 +748,17 @@ wdstrategy(register struct buf *bp) /* queue transfer on drive, activate drive and controller if idle */ s = splbio(); + bufqdisksort(&drive_queue[lunit], bp); + + if (wdutab[lunit].b_active == 0) + wdustart(du); /* start drive */ + /* Pick up changes made by readdisklabel(). */ if (du->dk_flags & DKFL_LABELLING && du->dk_state > RECAL) { wdsleep(du->dk_ctrlr, "wdlab"); du->dk_state = WANTOPEN; } - bufqdisksort(&drive_queue[lunit], bp); - - if (wdutab[lunit].b_active == 0) - wdustart(du); /* start drive */ - #ifdef CMD640 if (wdtab[du->dk_ctrlr_cmd640].b_active == 0) #else @@ -1166,12 +1141,11 @@ wdstart(int ctrlr) */ void -wdintr(void *unitnum) +wdintr(int unit) { register struct disk *du; register struct buf *bp; int dmastat = 0; /* Shut up GCC */ - int unit = (int)unitnum; #ifdef CMD640 int ctrlr_atapi; @@ -1223,7 +1197,8 @@ wdintr(void *unitnum) if (du->dk_flags & (DKFL_DMA|DKFL_USEDMA)) { /* XXX SMP boxes sometimes generate an early intr. Why? */ if ((wddma[du->dk_interface].wdd_dmastatus(du->dk_dmacookie) & WDDS_INTERRUPT) - != 0) + == 0) + return; dmastat = wddma[du->dk_interface].wdd_dmadone(du->dk_dmacookie); } @@ -2097,8 +2072,7 @@ failed: * check drive's DMA capability */ if (wddma[du->dk_interface].wdd_candma) { - du->dk_dmacookie = wddma[du->dk_interface].wdd_candma( - du->dk_port, du->dk_ctrlr, du->dk_unit); + du->dk_dmacookie = wddma[du->dk_interface].wdd_candma(du->dk_port, du->dk_ctrlr); /* does user want this? */ if ((du->cfg_flags & WDOPT_DMA) && /* have we got a DMA controller? */ @@ -2502,11 +2476,11 @@ static void wderror(struct buf *bp, struct disk *du, char *mesg) { if (bp == NULL) - printf("wd%d: %s", du->dk_lunit, mesg); + printf("wd%d: %s:\n", du->dk_lunit, mesg); else diskerr(bp, "wd", mesg, LOG_PRINTF, du->dk_skip, dsgetlabel(bp->b_dev, du->dk_slices)); - printf(" (status %b error %b)\n", + printf("wd%d: status %b error %b\n", du->dk_lunit, du->dk_status, WDCS_BITS, du->dk_error, WDERR_BITS); } |
